Code: Select all
__asm__ volatile("int $0x0");
The current setup looks like this:
Code: Select all
// interrupt.h:
struct idt_entry {
uint16_t offset_low;
uint16_t selector;
uint8_t __r0;
uint8_t type;
uint16_t offset_middle;
uint32_t offset_high;
uint32_t __r1;
} __attribute((packed));
// isr.c:
void isr_init(void)
{
idt_set_gate(0, (uint64_t)__isr0, __KERNEL_CS, 0x8e);
idt_set_gate(1, (uint64_t)__isr1, __KERNEL_CS, 0x8e);
idt_set_gate(2, (uint64_t)__isr2, __KERNEL_CS, 0x8e);
idt_set_gate(3, (uint64_t)__isr3, __KERNEL_CS, 0x8e);
idt_set_gate(4, (uint64_t)__isr4, __KERNEL_CS, 0x8e);
idt_set_gate(5, (uint64_t)__isr5, __KERNEL_CS, 0x8e);
idt_set_gate(6, (uint64_t)__isr6, __KERNEL_CS, 0x8e);
idt_set_gate(7, (uint64_t)__isr7, __KERNEL_CS, 0x8e);
idt_set_gate(8, (uint64_t)__isr8, __KERNEL_CS, 0x8e);
idt_set_gate(9, (uint64_t)__isr9, __KERNEL_CS, 0x8e);
idt_set_gate(10, (uint64_t)__isr10, __KERNEL_CS, 0x8e);
idt_set_gate(11, (uint64_t)__isr11, __KERNEL_CS, 0x8e);
idt_set_gate(12, (uint64_t)__isr12, __KERNEL_CS, 0x8e);
idt_set_gate(13, (uint64_t)__isr13, __KERNEL_CS, 0x8e);
idt_set_gate(14, (uint64_t)__isr14, __KERNEL_CS, 0x8e);
idt_set_gate(15, (uint64_t)__isr15, __KERNEL_CS, 0x8e);
idt_set_gate(16, (uint64_t)__isr16, __KERNEL_CS, 0x8e);
idt_set_gate(17, (uint64_t)__isr17, __KERNEL_CS, 0x8e);
idt_set_gate(18, (uint64_t)__isr18, __KERNEL_CS, 0x8e);
idt_set_gate(19, (uint64_t)__isr19, __KERNEL_CS, 0x8e);
idt_set_gate(20, (uint64_t)__isr20, __KERNEL_CS, 0x8e);
}
- - When int 0x0 is triggered, the instruction pointer moves to the function located at the first entry (index 0) of the IDT. No problems so far.
- When stepping to the next instruction, the instruction pointer however moves to the next interrupt service routine, which is the page fault handler. In there, the instruction triggers itself multiple consecutive page fault, as the instruction pointer seems to only complete the cli instruction at the beginning of the isr stub. This goes on until I seemed to enter real mode again.
Code: Select all
Dump gate:
08894662103e[CPU0 ] Type : f
08894662103e[CPU0 ] Valid: 1
08894662103e[CPU0 ] Segm : 1
08894662103e[CPU0 ] interrupt(long mode): gate descriptor is not valid sys seg
08894662105e[CPU0 ] Dump gate:
08894662105e[CPU0 ] Type : f
08894662105e[CPU0 ] Valid: 1
08894662105e[CPU0 ] Segm : 1
08894662105e[CPU0 ] interrupt(long mode): gate descriptor is not valid sys seg
08894662107e[CPU0 ] Dump gate:
08894662107e[CPU0 ] Type : f
08894662107e[CPU0 ] Valid: 1
08894662107e[CPU0 ] Segm : 1
08894662107e[CPU0 ] interrupt(long mode): gate descriptor is not valid sys seg
08894662107e[CPU0 ] Dump gate:
08894662107e[CPU0 ] Type : f
08894662107e[CPU0 ] Valid: 1
08894662107e[CPU0 ] Segm : 1
08894662107e[CPU0 ] interrupt(long mode): gate descriptor is not valid sys seg
Code: Select all
// bochs/cpu/exception.cc:64
if ((gate_descriptor.valid==0) || gate_descriptor.segment)
{
BX_ERROR(("Dump gate:"));
BX_ERROR(("Type : %x", gate_descriptor.type));
BX_ERROR(("Valid: %x", gate_descriptor.valid ? 1 : 0));
BX_ERROR(("Segm : %x", gate_descriptor.segment ? 1 : 0));
BX_ERROR(("interrupt(long mode): gate descriptor is not valid sys seg"));
exception(BX_GP_EXCEPTION, vector*8 + 2);
}
Code: Select all
// bochs/cpu/descriptor.h:typedef struct bx_descriptor_t
// ...
bx_bool segment; /* 0 = system/gate, 1 = data/code segment */
// ...
Code: Select all
// From https://wiki.osdev.org/Interrupt_Descriptor_Table#Structure_IA-32
7 0
+---+---+---+---+---+---+---+---+
| P | DPL | S | GateType |
+---+---+---+---+---+---+---+---+
1 0 0 0 1 1 1 0 --> 0x8E
I am at loss of ideas how to move on here, because I'm very sure I checked the values in the type_attr member of my struct idt_entry above (0x8E).