Kernel: Move GDT and IDT files to architecture specific folder
This commit is contained in:
43
kernel/arch/i386/GDT.cpp
Normal file
43
kernel/arch/i386/GDT.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
#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;
|
||||
|
||||
extern "C" void load_gdt(void* gdt_ptr);
|
||||
|
||||
void write_gdt_entry_raw(uint8_t segment, uint32_t low, uint32_t high)
|
||||
{
|
||||
uint8_t index = segment >> 3;
|
||||
s_gdt[index].low = low;
|
||||
s_gdt[index].high = high;
|
||||
}
|
||||
|
||||
void write_gdt_entry(uint8_t segment, SegmentDesriptor descriptor)
|
||||
{
|
||||
write_gdt_entry_raw(segment, descriptor.low, descriptor.high);
|
||||
}
|
||||
|
||||
void gdt_initialize()
|
||||
{
|
||||
constexpr uint8_t GDT_SIZE = 5;
|
||||
|
||||
s_gdt = new SegmentDesriptor[GDT_SIZE];
|
||||
|
||||
s_gdtr.address = s_gdt;
|
||||
s_gdtr.size = GDT_SIZE * 8 - 1;
|
||||
|
||||
write_gdt_entry(0x00, { 0, 0x00000, 0x00, 0x0 }); // null
|
||||
write_gdt_entry(0x08, { 0, 0xFFFFF, 0x9A, 0xC }); // kernel code
|
||||
write_gdt_entry(0x10, { 0, 0xFFFFF, 0x92, 0xC }); // kernel data
|
||||
write_gdt_entry(0x18, { 0, 0xFFFFF, 0xFA, 0xC }); // user code
|
||||
write_gdt_entry(0x20, { 0, 0xFFFFF, 0xF2, 0xC }); // user data
|
||||
|
||||
load_gdt(&s_gdtr);
|
||||
}
|
||||
16
kernel/arch/i386/GDT_asm.S
Normal file
16
kernel/arch/i386/GDT_asm.S
Normal file
@@ -0,0 +1,16 @@
|
||||
.global load_gdt
|
||||
|
||||
load_gdt:
|
||||
movl 4(%esp),%eax
|
||||
lgdt (%eax)
|
||||
|
||||
movw $0x10, %ax
|
||||
movw %ax, %ds
|
||||
movw %ax, %es
|
||||
movw %ax, %fs
|
||||
movw %ax, %gs
|
||||
movw %ax, %ss
|
||||
jmp $0x08,$flush
|
||||
|
||||
flush:
|
||||
ret
|
||||
162
kernel/arch/i386/IDT.cpp
Normal file
162
kernel/arch/i386/IDT.cpp
Normal file
@@ -0,0 +1,162 @@
|
||||
#include <kernel/IDT.h>
|
||||
#include <kernel/kmalloc.h>
|
||||
#include <kernel/panic.h>
|
||||
#include <kernel/PIC.h>
|
||||
#include <kernel/kprint.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));
|
||||
|
||||
struct IDTR
|
||||
{
|
||||
uint16_t size;
|
||||
void* offset;
|
||||
} __attribute((packed));
|
||||
|
||||
static IDTR s_idtr;
|
||||
static GateDescriptor* s_idt;
|
||||
|
||||
static void (*s_irq_handlers[16])();
|
||||
|
||||
extern "C" void handle_irq();
|
||||
extern "C" void handle_irq_common();
|
||||
|
||||
#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={}", 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_handler(i, interrupt ## i)
|
||||
|
||||
void handle_irq()
|
||||
{
|
||||
uint16_t isr = PIC::get_isr();
|
||||
if (!isr) {
|
||||
kprint("Spurious IRQ\n");
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t irq = 0;
|
||||
for (uint8_t i = 0; i < 16; ++i) {
|
||||
if (i == 2)
|
||||
continue;
|
||||
if (isr & (1 << i)) {
|
||||
irq = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (s_irq_handlers[irq])
|
||||
s_irq_handlers[irq]();
|
||||
else
|
||||
kprint("no handler for irq {}\n", irq);
|
||||
|
||||
PIC::eoi(irq);
|
||||
}
|
||||
|
||||
namespace IDT
|
||||
{
|
||||
|
||||
static void flush_idt()
|
||||
{
|
||||
asm volatile("lidt %0"::"m"(s_idtr));
|
||||
}
|
||||
|
||||
static void unimplemented_trap()
|
||||
{
|
||||
Kernel::panic("Unhandeled IRQ");
|
||||
}
|
||||
|
||||
static void register_interrupt_handler(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 register_irq_handler(uint8_t irq, void (*f)())
|
||||
{
|
||||
s_irq_handlers[irq] = f;
|
||||
register_interrupt_handler(IRQ_VECTOR_BASE + irq, handle_irq_common);
|
||||
}
|
||||
|
||||
void initialize()
|
||||
{
|
||||
constexpr size_t idt_size = 256;
|
||||
|
||||
s_idt = new GateDescriptor[idt_size];
|
||||
|
||||
s_idtr.offset = s_idt;
|
||||
s_idtr.size = idt_size * 8;
|
||||
|
||||
for (uint8_t i = 0xff; i > 0x10; i--)
|
||||
register_interrupt_handler(i, unimplemented_trap);
|
||||
|
||||
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 (uint8_t i = 0; i < sizeof(s_irq_handlers) / sizeof(*s_irq_handlers); i++)
|
||||
s_irq_handlers[i] = nullptr;
|
||||
|
||||
flush_idt();
|
||||
}
|
||||
|
||||
}
|
||||
15
kernel/arch/i386/IDT_asm.S
Normal file
15
kernel/arch/i386/IDT_asm.S
Normal file
@@ -0,0 +1,15 @@
|
||||
.globl handle_irq_common
|
||||
|
||||
handle_irq_common:
|
||||
pusha
|
||||
pushw %ds
|
||||
pushw %es
|
||||
pushw %ss
|
||||
pushw %ss
|
||||
popw %ds
|
||||
popw %es
|
||||
call handle_irq
|
||||
popw %es
|
||||
popw %ds
|
||||
popa
|
||||
iret
|
||||
@@ -6,3 +6,7 @@ KERNEL_ARCH_LIBS=
|
||||
KERNEL_ARCH_OBJS=\
|
||||
$(ARCHDIR)/boot.o \
|
||||
$(ARCHDIR)/tty.o \
|
||||
$(ARCHDIR)/GDT.o \
|
||||
$(ARCHDIR)/GDT_asm.o \
|
||||
$(ARCHDIR)/IDT.o \
|
||||
$(ARCHDIR)/IDT_asm.o \
|
||||
|
||||
Reference in New Issue
Block a user