Code: Select all
memset((void*)idtr.offset, 0, 256 * sizeof(struct idtdescentry));
was correct, it shouldn't matter that the page has trash somewhere else. As every entry is
initialiced by the default handler, I'm not sure why this "fixed" the problem.
I migrate my original question to: This is weird, do you see anything wrong here?
Original question:
Hello everyone.
I'm facing trouble with interrupts on my kernel. I'm forcing a general protection fault to
test interrupt handling works.
Code: Select all
void * target = request_page(); //Request a physical page with page frame allocator
memset(target, 0, 4096);
map_memory((void*)0xffffffffdeadb000, target); //Map it to the address
uint64_t* ptr1 = (uint64_t*)0xffffffffdeadb000;
PAGE_RESTRICT_WRITE((void*)ptr1); //Clear writable bit in page table
*ptr1 = 0xdeadbeef;
Code: Select all
qemu-system-x86_64 -cpu qemu64 -d cpu_reset -machine q35 -m 512 -boot d -cdrom ./image.iso
But if I create a limine compatible .img and run it like:
Code: Select all
qemu-system-x86_64 -cpu qemu64 -d cpu_reset -machine q35 -m 512 -boot d -cdrom ./test/useless.iso -drive if=pflash,format=raw,unit=0,file=./OVMFbin/OVMF_CODE-pure-efi.fd,readonly=on -drive if=pflash,format=raw,unit=1,file=./OVMFbin/OVMF_VARS-pure-efi.fd -net none -drive file=./image.img
It is mandatory to point out that some interrupts work fine, i can handle keyboard input, pit, mouse, divbyzero, etc just fine. But the PageFault and general protection fault handlers
don't seem to work.
My initialization code:
Code: Select all
struct idtr idtr;
void set_idt_gate(uint64_t handler, uint8_t entry_offset, uint8_t type_attr, uint8_t selector) {
struct idtdescentry* interrupt = (struct idtdescentry*)(idtr.offset + entry_offset * sizeof(struct idtdescentry));
set_offset(interrupt, handler);
interrupt->type_attr = type_attr;
interrupt->selector = selector;
}
void init_interrupts(uint8_t pit_disable) {
__asm__("cli");
idtr.limit = 0x0FFF;
idtr.offset = (uint64_t)request_page(); //Request physical page
for (int i = 0; i < 256; i++) {
set_idt_gate((uint64_t)UncaughtInt_Handler, i, IDT_TA_InterruptGate, 0x28);
}
set_idt_gate((uint64_t)PageFault_Handler, 0xE, IDT_TA_InterruptGate, 0x28);
set_idt_gate((uint64_t)DoubleFault_Handler, 0x8, IDT_TA_InterruptGate, 0x28);
set_idt_gate((uint64_t)GPFault_Handler, 0xD, IDT_TA_InterruptGate, 0x28);
set_idt_gate((uint64_t)KeyboardInt_Handler, 0x21, IDT_TA_InterruptGate, 0x28);
set_idt_gate((uint64_t)MouseInt_Handler, 0x2C, IDT_TA_InterruptGate, 0x28);
set_idt_gate((uint64_t)PitInt_Handler, 0x20, IDT_TA_InterruptGate, 0x28);
set_idt_gate((uint64_t)DivByZero_Handler, 0x0, IDT_TA_InterruptGate, 0x28);
__asm__("lidt %0" : : "m"(idtr));
remap_pic();
init_keyboard();
outb(PIC1_DATA, 0xf8 + pit_disable); //PIT IS DISABLED
outb(PIC2_DATA, 0xef);
__asm__("sti");
}
Code: Select all
__attribute__((interrupt)) void UncaughtInt_Handler(struct interrupt_frame* frame) {
dbg_print("UncaughtInt_Handler\n");
(void)frame;
while(1);
}
P.S. The entire code is available here: https://github.com/TretornESP/bloodmoon
P.S.v2. I can't log interrupts with qemu's
Code: Select all
-d int
to the point where it will never boot. cpu_reset just tells me what I was already expecting (A triple fault on the write operation).
Code: Select all
Triple fault
CPU Reset (CPU 0)
RAX=00000000deadbeef RBX=0000000000000000 RCX=0000000000a78000 RDX=0000000000a77001
RSI=0000000000000000 RDI=ffffffff8000c93b RBP=0000000000a77000 RSP=ffff80001d98aff0
R8 =00000000000000f5 R9 =ffffffffdeadb000 R10=000000001fe13200 R11=0000000000000009
R12=0000000000000000 R13=0000000000000000 R14=0000000000000000 R15=0000000000000000
RIP=ffffffff8000bb33 RFL=00000202 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0030 0000000000000000 00000000 00009300 DPL=0 DS [-WA]
CS =0028 0000000000000000 00000000 00209a00 DPL=0 CS64 [-R-]
SS =0030 0000000000000000 00000000 00009300 DPL=0 DS [-WA]
DS =0030 0000000000000000 00000000 00009300 DPL=0 DS [-WA]
FS =0030 0000000000000000 00000000 00009300 DPL=0 DS [-WA]
GS =0030 0000000000000000 00000000 00009300 DPL=0 DS [-WA]
LDT=0000 0000000000000000 00000000 00008200 DPL=0 LDT
TR =0000 0000000000000000 0000ffff 00008b00 DPL=0 TSS64-busy
GDT= ffff80001fee7000 00000037
IDT= 0000000000a09000 00000fff
CR0=80010011 CR2=0000000000000044 CR3=000000001d97a000 CR4=00000020
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=0000000000000018 CCD=0000000000a77001 CCO=LOGICQ
EFER=0000000000000d00
FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80
FPR0=0000000000000000 0000 FPR1=0000000000000000 0000
FPR2=0000000000000000 0000 FPR3=0000000000000000 0000
FPR4=0000000000000000 0000 FPR5=0000000000000000 0000
FPR6=0000000000000000 0000 FPR7=0000000000000000 0000
XMM00=0000000000000000 0000000000000000 XMM01=0000000000000000 0000000000000000
XMM02=0000000000000000 0000000000000000 XMM03=0000000000000000 0000000000000000
XMM04=0000000000000000 0000000000000000 XMM05=0000000000000000 0000000000000000
XMM06=0000000000000000 0000000000000000 XMM07=0000000000000000 0000000000000000
XMM08=0000000000000000 0000000000000000 XMM09=0000000000000000 0000000000000000
XMM10=0000000000000000 0000000000000000 XMM11=0000000000000000 0000000000000000
XMM12=0000000000000000 0000000000000000 XMM13=0000000000000000 0000000000000000
XMM14=0000000000000000 0000000000000000 XMM15=0000000000000000 0000000000000000