This commit adds GDT initialization with proper code/data segments and reloads CS. It also adds the initial IDT structure and loads an empty IDT. Build configuration updated to disable SSE/MMX to prevent compiler generation of unsupported instructions in early boot.
47 lines
1.2 KiB
C
47 lines
1.2 KiB
C
#include "idt.h"
|
|
#include <stdint.h>
|
|
#include <stddef.h> /* for memset */
|
|
|
|
idt_entry_t idt_entries[256];
|
|
idt_ptr_t idt_ptr;
|
|
|
|
extern void idt_load();
|
|
|
|
static void idt_set_gate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags)
|
|
{
|
|
idt_entries[num].base_lo = base & 0xFFFF;
|
|
idt_entries[num].base_hi = (base >> 16) & 0xFFFF;
|
|
|
|
idt_entries[num].sel = sel;
|
|
idt_entries[num].always0 = 0;
|
|
// We must uncomment the OR below when we get to using user-mode.
|
|
// It sets the interrupt gate's privilege level to 3.
|
|
idt_entries[num].flags = flags /* | 0x60 */;
|
|
}
|
|
|
|
/* Note: memset implementation because we don't link with libc */
|
|
static void *memset(void *s, int c, size_t n)
|
|
{
|
|
unsigned char *p = s;
|
|
while(n--)
|
|
*p++ = (unsigned char)c;
|
|
return s;
|
|
}
|
|
|
|
void init_idt()
|
|
{
|
|
idt_ptr.limit = sizeof(idt_entry_t) * 256 - 1;
|
|
idt_ptr.base = (uint32_t)&idt_entries;
|
|
|
|
memset(&idt_entries, 0, sizeof(idt_entry_t) * 256);
|
|
|
|
/* Determine valid flags:
|
|
* 0x8E = 1000 1110
|
|
* P=1, DPL=00, S=0 (System), Type=1110 (32-bit Interrupt Gate) */
|
|
|
|
/* For now, just load the IDT without any entries to verify loading works without crashing.
|
|
Later we will set up ISRs. */
|
|
|
|
idt_load((uint32_t)&idt_ptr);
|
|
}
|