I have a GDT and IDT setup.
It usually faults in a while loop
Code: Select all
while (true) {}
Code: Select all
#define ALIGN(a) __attribute__((aligned(a)))
GDT::GDT_Ptr GDT_Ptr ALIGN(16);
GDT::GDT_Entry GDT_Entries[4] ALIGN(16);
IDT::IDT_Ptr IDT_Ptr ALIGN(16);
IDT::IDT_Entry IDT_Entries[0x40] ALIGN(16);
// Setup GDT
GDT::set_gdt_entry(GDT_Entries, 1, 0, -1, true);
GDT::set_gdt_entry(GDT_Entries, 2, 0, -1, false);
GDT::set_gdt(&GDT_Ptr, GDT_Entries, sizeof(GDT_Entries));
enable_gdt(&GDT_Ptr, 0x08, 0x10);
// Setup interrupts
for (size_t i = 0; i < 0x40; i++) {
IDT::set_idt_entry(IDT_Entries, i, 0x08, (uint32_t)test, true);
}
IDT::set_idt_entry(IDT_Entries, 8, 0x08, (uint32_t)test2, true);
IDT::set_idt_entry(IDT_Entries, 10, 0x08, (uint32_t)test2, true);
IDT::set_idt_entry(IDT_Entries, 11, 0x08, (uint32_t)test2, true);
IDT::set_idt_entry(IDT_Entries, 12, 0x08, (uint32_t)test2, true);
IDT::set_idt_entry(IDT_Entries, 13, 0x08, (uint32_t)test2, true);
IDT::set_idt_entry(IDT_Entries, 14, 0x08, (uint32_t)test2, true);
IDT::set_idt_entry(IDT_Entries, 17, 0x08, (uint32_t)test2, true);
IDT::set_idt_entry(IDT_Entries, 30, 0x08, (uint32_t)test2, true);
IDT::set_idt(&IDT_Ptr, IDT_Entries, sizeof(IDT_Entries));
PIC::reload_pic(0x30, 0x38);
enable_idt(&IDT_Ptr);
Code: Select all
typedef struct __attribute__((packed)){
uint16_t size;
uint32_t addr;
} GDT_Ptr;
typedef struct __attribute__((packed)){
uint16_t limit;
uint16_t base0;
uint8_t base1;
uint8_t access;
uint8_t limit_flags;
uint8_t base2;
} GDT_Entry;
typedef struct __attribute__((packed)) {
uint16_t size;
uint32_t addr;
} IDT_Ptr;
typedef struct __attribute__((packed)) {
uint16_t base0;
uint16_t selector;
uint8_t zero;
uint8_t type;
uint16_t base1;
} IDT_Entry;
Code: Select all
void set_gdt(GDT_Ptr *ptr, GDT_Entry *gdt, size_t size) {
ptr->size = size - 1;
ptr->addr = (uint32_t)gdt;
}
void set_gdt_entry(GDT_Entry *gdt, size_t index, uint32_t base, uint32_t limit, bool code) {
gdt[index].base0 = (uint16_t)base;
gdt[index].base1 = (uint8_t)(base >> 16);
gdt[index].base2 = (uint8_t)(base >> 24);
gdt[index].limit = (uint16_t)limit;
gdt[index].limit_flags = (uint8_t)((limit >> 16) & 0xf) | 0b11000000;
if (limit != 0)
gdt[index].access = 0b10010010;
else
gdt[index].access = 0b00010010;
if (code)
gdt[index].access |= 0b1000;
}
void set_idt(IDT_Ptr *ptr, IDT_Entry *idt, size_t size) {
ptr->size = size - 1;
ptr->addr = (uint32_t)idt;
}
void set_idt_entry(IDT_Entry *idt, size_t index, uint16_t selector, uint32_t base, bool present) {
idt[index].base0 = (uint16_t)base;
idt[index].base1 = (uint16_t)(base >> 16);
idt[index].selector = selector;
if (present)
idt[index].type = 0b10001111;
else
idt[index].type = 0;
idt[index].zero = 0;
}
Code: Select all
global enable_gdt
enable_gdt:
mov eax, [esp+4]
mov ecx, [esp+8]
mov edx, [esp+12]
lgdt [eax]
mov ax, dx
mov ds, ax
mov es, ax
mov ss, ax
mov fs, ax
mov gs, ax
; For some reason, retf mangles the esp
mov eax, esp
push cx
push _reload_code
retf
_reload_code:
mov esp, eax
ret
global enable_idt
enable_idt:
mov eax, [esp+4]
lidt [eax]
sti
ret
Code: Select all
global test
test:
xchg bx, bx
iret
global test2
test2:
xchg bx, bx
add esp, 4
iret