So you can see that this happened:
Code: Select all
0: v=80 e=0000 i=1 cpl=0 IP=0028:ffffffff800001e5 pc=ffffffff800001e5 SP=0030:ffff80007ff6cff0 env->regs[R_EAX]=000000000000000b
v=80 (hex) is the interrupt number. I assume 0x80 is your system call. At the point of the exception call in the dump `CS =0028`. That is to be expected if you never reloaded CS after you did `lgdt`. The `gdt` address in the dump suggests a memory address in your own kernel so I assume that you are still using your own `gdt` here. Okay so `v=80` occurred and then you get:
Code: Select all
1: v=0d e=0028 i=0 cpl=0 IP=0008:ffffffff80000841 pc=ffffffff80000841 SP=0030:ffff80007ff6cfc8 env->regs[R_EAX]=000000000000000b
This is the GPF exception. (v=0d). The error code e=0028 tells us that there was an exception trying to use selector index 5 (0x28) in the GDT. See
https://wiki.osdev.org/Exceptions#Selector_Error_Code on decoding GPF error codes. This is what I'd expect to happen the moment IRETQ executes and tries to reload the Limine CS of 0x28. Your own GDT is only 0x18 bytes long so it is faulting there. You will also see that when this GPF happened CS=0008. This was because your ISR entry in the IDT has a selector of 0x0008 for the code segment (which is correct for your GDT). You could verify the instruction at pc(RIP)=0xffffffff800001e5 is an IRETQ instruction.
So for your question, should you use your own GDT or Limine? That is up to you, but if you ever want to get into ring 3 (user mode) you will need your own TSS so I do recommend you have your own GDT. I use my own GDT. But if you use your own then after LGDT you are going to have to do a FAR JMP to set CS to 0x0008 and then reload the data segment registers with 0x0010. Until you load CS with 0x0008 you will get this GPF If you use your own GDT.
If you modify your code to reload CS with 0x08 and it faults with a page fault (v=0e) then you are going to have to see my previous comment about the GDT being in a read only page. You can either move it to the `.data` section (read/write page) instead of `.rodata` (read only) OR set the ACCESSED bit in your GDT entries (0x08, and 0x10) to 1.
Edit: In 64-bit mode the error code pushed on the stack is a 64-bit value. I noticed some of your ISR's treat it as 2 2-byte words (4 bytes). If you make your entries in the IDT interrupt gates then interrupts/exceptions will be turned off by the CPU when your ISR handler is called. There is no need for a CLI at the top. The IRETQ will restore the RFLAGS register (including the interrupt flag) to what it was before the interrupt/exception occurred.