forked from Bananymous/banan-os
Add GDT and IDT
This commit is contained in:
parent
b500a8a7ed
commit
f2b45ba212
|
@ -29,6 +29,8 @@ LIBS:=$(LIBS) $(KERNEL_ARCH_LIBS)
|
|||
|
||||
KERNEL_OBJS=\
|
||||
$(KERNEL_ARCH_OBJS) \
|
||||
kernel/GDT.o \
|
||||
kernel/IDT.o \
|
||||
kernel/kernel.o \
|
||||
kernel/kmalloc.o \
|
||||
kernel/SSP.o \
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
union SegmentDesriptor
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint16_t limit_lo;
|
||||
uint16_t base_lo;
|
||||
uint8_t base_hi1;
|
||||
|
||||
uint8_t type : 4;
|
||||
uint8_t system : 1;
|
||||
uint8_t DPL : 2;
|
||||
uint8_t present : 1;
|
||||
|
||||
uint8_t limit_hi : 4;
|
||||
uint8_t flags : 4;
|
||||
|
||||
uint8_t base_hi2;
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t low;
|
||||
uint32_t high;
|
||||
};
|
||||
|
||||
SegmentDesriptor() : low(0), high(0) {}
|
||||
SegmentDesriptor(uint32_t base, uint32_t limit, uint8_t access, uint8_t _flags)
|
||||
: low(0), high(0)
|
||||
{
|
||||
set_base(base);
|
||||
set_limit(limit);
|
||||
|
||||
high |= ((uint16_t)access) << 8;
|
||||
flags = _flags;
|
||||
}
|
||||
|
||||
void set_base(uint32_t base)
|
||||
{
|
||||
base_lo = base & 0xFFFF;
|
||||
base_hi1 = (base >> 16) & 0x00FF;
|
||||
base_hi2 = (base >> 24) & 0x00FF;
|
||||
}
|
||||
|
||||
void set_limit(uint32_t limit)
|
||||
{
|
||||
limit_lo = limit & 0xFFFF;
|
||||
limit_hi = (limit >> 16) & 0x00FF;
|
||||
}
|
||||
|
||||
} __attribute__((packed));
|
||||
|
||||
void gdt_initialize();
|
|
@ -0,0 +1,27 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
union GateDescriptor
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint16_t offset_lo;
|
||||
uint16_t selector;
|
||||
uint8_t reserved;
|
||||
uint8_t type : 4;
|
||||
uint8_t zero : 1;
|
||||
uint8_t dpl : 2;
|
||||
uint8_t present : 1;
|
||||
uint16_t offset_hi;
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t low;
|
||||
uint32_t high;
|
||||
};
|
||||
|
||||
} __attribute__((packed));
|
||||
|
||||
void idt_initialize();
|
|
@ -0,0 +1,46 @@
|
|||
#include <kernel/GDT.h>
|
||||
#include <kernel/kmalloc.h>
|
||||
|
||||
struct GDTR
|
||||
{
|
||||
uint16_t size;
|
||||
void* address;
|
||||
} __attribute__((packed));
|
||||
|
||||
static GDTR s_gdtr;
|
||||
static SegmentDesriptor* s_gdt;
|
||||
|
||||
void write_gdt_entry_raw(uint8_t index, uint32_t low, uint32_t high)
|
||||
{
|
||||
s_gdt[index].low = low;
|
||||
s_gdt[index].high = high;
|
||||
}
|
||||
|
||||
void write_gdt_entry(uint8_t index, SegmentDesriptor descriptor)
|
||||
{
|
||||
write_gdt_entry_raw(index, descriptor.low, descriptor.high);
|
||||
}
|
||||
|
||||
static void flush_gdt()
|
||||
{
|
||||
asm volatile("lgdt %0"::"m"(s_gdtr));
|
||||
}
|
||||
|
||||
void gdt_initialize()
|
||||
{
|
||||
constexpr size_t gdt_size = 256;
|
||||
|
||||
s_gdt = new SegmentDesriptor[gdt_size];
|
||||
|
||||
s_gdtr.address = s_gdt;
|
||||
s_gdtr.size = gdt_size * 8 - 1;
|
||||
|
||||
uint8_t index = 0;
|
||||
write_gdt_entry(index++, { 0, 0x0000, 0x00, 0x0 }); // null
|
||||
write_gdt_entry(index++, { 0, 0xFFFF, 0x9A, 0xC }); // kernel code
|
||||
write_gdt_entry(index++, { 0, 0xFFFF, 0x92, 0xC }); // kernel data
|
||||
write_gdt_entry(index++, { 0, 0xFFFF, 0xFA, 0xC }); // user code
|
||||
write_gdt_entry(index++, { 0, 0xFFFF, 0xF2, 0xC }); // user data
|
||||
|
||||
flush_gdt();
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
#include <kernel/IDT.h>
|
||||
#include <kernel/kmalloc.h>
|
||||
#include <kernel/panic.h>
|
||||
#include <kernel/kprint.h>
|
||||
|
||||
struct IDTR
|
||||
{
|
||||
uint16_t size;
|
||||
void* offset;
|
||||
} __attribute((packed));
|
||||
|
||||
static IDTR s_idtr;
|
||||
static GateDescriptor* s_idt;
|
||||
|
||||
|
||||
#define INTERRUPT_HANDLER(i, msg) \
|
||||
static void interrupt ## i () \
|
||||
{ \
|
||||
uint32_t cr0, cr2, cr3, cr4; \
|
||||
asm volatile("movl %%cr0, %%eax":"=a"(cr0)); \
|
||||
asm volatile("movl %%cr2, %%eax":"=a"(cr2)); \
|
||||
asm volatile("movl %%cr3, %%eax":"=a"(cr3)); \
|
||||
asm volatile("movl %%cr4, %%eax":"=a"(cr4)); \
|
||||
Kernel::panic(msg ", CR0={} CR2={} CR3={} CR4={}\n", cr0, cr2, cr3, cr4); \
|
||||
}
|
||||
|
||||
INTERRUPT_HANDLER(0x00, "Divide error")
|
||||
INTERRUPT_HANDLER(0x01, "Debug exception")
|
||||
INTERRUPT_HANDLER(0x02, "Unknown error")
|
||||
INTERRUPT_HANDLER(0x03, "Breakpoint")
|
||||
INTERRUPT_HANDLER(0x04, "Overflow")
|
||||
INTERRUPT_HANDLER(0x05, "Bounds check")
|
||||
INTERRUPT_HANDLER(0x06, "Invalid opcode")
|
||||
INTERRUPT_HANDLER(0x07, "Coprocessor not available")
|
||||
INTERRUPT_HANDLER(0x08, "Double fault")
|
||||
INTERRUPT_HANDLER(0x09, "Coprocessor segment overrun")
|
||||
INTERRUPT_HANDLER(0x0a, "Invalid TSS")
|
||||
INTERRUPT_HANDLER(0x0b, "Segment not present")
|
||||
INTERRUPT_HANDLER(0x0c, "Stack exception")
|
||||
INTERRUPT_HANDLER(0x0d, "General protection fault")
|
||||
INTERRUPT_HANDLER(0x0e, "Page fault")
|
||||
INTERRUPT_HANDLER(0x0f, "Unknown error")
|
||||
INTERRUPT_HANDLER(0x10, "Coprocessor error")
|
||||
|
||||
#define REGISTER_HANDLER(i) register_interrupt_handeler(i, interrupt ## i)
|
||||
|
||||
static void flush_idt()
|
||||
{
|
||||
asm volatile("lidt %0"::"m"(s_idtr));
|
||||
}
|
||||
|
||||
static void unimplemented_trap()
|
||||
{
|
||||
Kernel::panic("Unhandeled IRQ");
|
||||
}
|
||||
|
||||
static void register_interrupt_handeler(uint8_t index, void (*f)())
|
||||
{
|
||||
s_idt[index].low = 0x00080000 | ((uint32_t)(f) & 0x0000ffff);
|
||||
s_idt[index].high = ((uint32_t)(f) & 0xffff0000) | 0x8e00;
|
||||
flush_idt();
|
||||
}
|
||||
|
||||
void idt_initialize()
|
||||
{
|
||||
constexpr size_t idt_size = 256;
|
||||
|
||||
s_idt = new GateDescriptor[idt_size];
|
||||
|
||||
s_idtr.offset = s_idt;
|
||||
s_idtr.size = idt_size * 8;
|
||||
|
||||
REGISTER_HANDLER(0x00);
|
||||
REGISTER_HANDLER(0x01);
|
||||
REGISTER_HANDLER(0x02);
|
||||
REGISTER_HANDLER(0x03);
|
||||
REGISTER_HANDLER(0x04);
|
||||
REGISTER_HANDLER(0x05);
|
||||
REGISTER_HANDLER(0x06);
|
||||
REGISTER_HANDLER(0x07);
|
||||
REGISTER_HANDLER(0x08);
|
||||
REGISTER_HANDLER(0x09);
|
||||
REGISTER_HANDLER(0x0a);
|
||||
REGISTER_HANDLER(0x0b);
|
||||
REGISTER_HANDLER(0x0c);
|
||||
REGISTER_HANDLER(0x0d);
|
||||
REGISTER_HANDLER(0x0e);
|
||||
REGISTER_HANDLER(0x0f);
|
||||
REGISTER_HANDLER(0x10);
|
||||
|
||||
for (uint16_t i = 0x11; i < idt_size; i++)
|
||||
register_interrupt_handeler(i, unimplemented_trap);
|
||||
|
||||
flush_idt();
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
#include <kernel/GDT.h>
|
||||
#include <kernel/IDT.h>
|
||||
#include <kernel/kmalloc.h>
|
||||
#include <kernel/multiboot.h>
|
||||
#include <kernel/panic.h>
|
||||
|
@ -17,27 +18,21 @@ extern "C"
|
|||
void kernel_main(multiboot_info_t* mbi, uint32_t magic)
|
||||
{
|
||||
DISABLE_INTERRUPTS();
|
||||
|
||||
if (magic != 0x2BADB002)
|
||||
asm volatile("hlt");
|
||||
|
||||
s_multiboot_info = mbi;
|
||||
|
||||
terminal_initialize();
|
||||
|
||||
if (magic != 0x2BADB002)
|
||||
Kernel::panic("Invalid magic in multiboot");
|
||||
kmalloc_initialize();
|
||||
|
||||
if (!(mbi->flags & (1 << 6)))
|
||||
Kernel::panic("Bootloader did not provide memory map");
|
||||
|
||||
for (uint32_t i = 0; i < mbi->mmap_length;)
|
||||
{
|
||||
multiboot_memory_map_t* mmmt = (multiboot_memory_map_t*)(mbi->mmap_addr + i);
|
||||
if (mmmt->type == 1)
|
||||
kprint("Size: {}, Addr: {}, Length: {}, Type: {}\n", mmmt->size, (void*)mmmt->base_addr, (void*)mmmt->length, mmmt->type);
|
||||
|
||||
i += mmmt->size + sizeof(uint32_t);
|
||||
}
|
||||
|
||||
printf("Hello from the kernel!\n");
|
||||
gdt_initialize();
|
||||
idt_initialize();
|
||||
|
||||
kprint("Hello from the kernel!\n");
|
||||
|
||||
asm volatile("int $14");
|
||||
|
||||
}
|
Loading…
Reference in New Issue