After some more debugging, I still can't seem to solve the problem.
I've changed the flags (that includes Present, Type, DPL etc) to 0xEE from 0x8E, setting DPL=3. Probably not supposed to do that, but I'm just trying everything at this stage.
Bochs still reports CS=0xB, not 0x8 as expected, when in the ISR handler.
(Note how the IDT dump above says the target=0x08)...
I can get to Ring3 just fine: CS=0x1B.
The code runs and all.
Next I deliberately cause an interrupt (any interrupt, although a #PF is what I usually use) to see if I can at least get back into Ring0.
Problem is, when I try to modify %DS or %CR2, I get a #GPF because presumably I'm still in Ring3... (CS=0xB now)... And because the ISR handler gets CR2 and changes DS=0x10... I interrupt loop forever.
So I think the problem is, the CPU isn't going back to Ring0...
Code: Select all
struct __attribute__((packed)) IDTEntry
{
uint16_t base_lo;
uint16_t sel;
uint8_t always0_ist;
uint8_t flags;
uint16_t base_mid;
uint32_t base_hi;
uint32_t always0_1;
};
struct __attribute__((packed)) IDTPointer
{
uint16_t limit;
uint64_t base;
};
static IDTEntry idt[256];
static IDTPointer idtp;
// Use this function to set an entry in the IDT. Alot simpler
// than twiddling with the GDT ;)
void SetGate(uint8_t num, uint64_t base, uint16_t sel, uint8_t flags)
{
// The interrupt routine's base address
idt[num].base_lo = (base & 0xFFFF);
idt[num].base_mid = (base >> 16) & 0xFFFF;
idt[num].base_hi = (base >> 32) & 0xFFFFFFFF;
// The segment or 'selector' that this IDT entry will use
// is set here, along with any access flags
idt[num].sel = sel;
// if(num < 32)
// idt[num].always0_ist = 0x1;
// else
idt[num].always0_ist = 0x0;
idt[num].always0_1 = 0;
idt[num].flags = flags;
}
// Installs the IDT
void Initialise()
{
// Sets the special IDT pointer up, just like in 'gdt.c'
idtp.limit = (sizeof(IDTEntry) * 256) - 1;
idtp.base = (uintptr_t)&idt;
// Clear out the entire IDT, initializing it to zeros
Memory::Set(&idt, 0, sizeof(IDTEntry) * 256);
// Add any new ISRs to the IDT here using idt_set_gate
InstallDefaultHandlers();
// Points the processor's internal register to the new IDT
HAL_AsmLoadIDT((uint64_t)&idtp);
}
void InstallDefaultHandlers()
{
SetGate(0, (uint64_t)isr0, 0x08, 0xEE);
SetGate(1, (uint64_t)isr1, 0x08, 0xEE);
SetGate(2, (uint64_t)isr2, 0x08, 0xEE);
SetGate(3, (uint64_t)isr3, 0x08, 0xEE);
SetGate(4, (uint64_t)isr4, 0x08, 0xEE);
SetGate(5, (uint64_t)isr5, 0x08, 0xEE);
SetGate(6, (uint64_t)isr6, 0x08, 0xEE);
SetGate(7, (uint64_t)isr7, 0x08, 0xEE);
SetGate(8, (uint64_t)isr8, 0x08, 0x8E);
SetGate(9, (uint64_t)isr9, 0x08, 0xEE);
SetGate(10, (uint64_t)isr10, 0x08, 0xEE);
SetGate(11, (uint64_t)isr11, 0x08, 0xEE);
SetGate(12, (uint64_t)isr12, 0x08, 0xEE);
SetGate(13, (uint64_t)isr13, 0x08, 0xEE);
SetGate(14, (uint64_t)isr14, 0x08, 0xEE);
SetGate(15, (uint64_t)isr15, 0x08, 0xEE);
SetGate(16, (uint64_t)isr16, 0x08, 0x8E);
SetGate(17, (uint64_t)isr17, 0x08, 0x8E);
SetGate(18, (uint64_t)isr18, 0x08, 0x8E);
SetGate(19, (uint64_t)isr19, 0x08, 0x8E);
SetGate(20, (uint64_t)isr20, 0x08, 0x8E);
SetGate(21, (uint64_t)isr21, 0x08, 0x8E);
SetGate(22, (uint64_t)isr22, 0x08, 0x8E);
SetGate(23, (uint64_t)isr23, 0x08, 0x8E);
SetGate(24, (uint64_t)isr24, 0x08, 0x8E);
SetGate(25, (uint64_t)isr25, 0x08, 0x8E);
SetGate(26, (uint64_t)isr26, 0x08, 0x8E);
SetGate(27, (uint64_t)isr27, 0x08, 0x8E);
SetGate(28, (uint64_t)isr28, 0x08, 0x8E);
SetGate(29, (uint64_t)isr29, 0x08, 0x8E);
SetGate(30, (uint64_t)isr30, 0x08, 0x8E);
SetGate(31, (uint64_t)isr31, 0x08, 0x8E);
// Remap the IRQs from 0 - 7 -> 8 - 15 to 32-47
outb(0x20, 0x11);
outb(0xA0, 0x11);
outb(0x21, 0x20);
outb(0xA1, 0x28);
outb(0x21, 0x04);
outb(0xA1, 0x02);
outb(0x21, 0x01);
outb(0xA1, 0x01);
outb(0x21, 0x0);
outb(0xA1, 0x0);
SetGate(32, (uint64_t)irq0, 0x08, 0x8E);
SetGate(33, (uint64_t)irq1, 0x08, 0x8E);
SetGate(34, (uint64_t)irq2, 0x08, 0x8E);
SetGate(35, (uint64_t)irq3, 0x08, 0x8E);
SetGate(36, (uint64_t)irq4, 0x08, 0x8E);
SetGate(37, (uint64_t)irq5, 0x08, 0x8E);
SetGate(38, (uint64_t)irq6, 0x08, 0x8E);
SetGate(39, (uint64_t)irq7, 0x08, 0x8E);
SetGate(40, (uint64_t)irq8, 0x08, 0x8E);
SetGate(41, (uint64_t)irq9, 0x08, 0x8E);
SetGate(42, (uint64_t)irq10, 0x08, 0x8E);
SetGate(43, (uint64_t)irq11, 0x08, 0x8E);
SetGate(44, (uint64_t)irq12, 0x08, 0x8E);
SetGate(45, (uint64_t)irq13, 0x08, 0x8E);
SetGate(46, (uint64_t)irq14, 0x08, 0x8E);
SetGate(47, (uint64_t)irq15, 0x08, 0x8E);
}
Sorry for the code dump... but I'm kinda desperate here.