Triple fault on loading CR3 with new page table

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
h3tR
Posts: 9
Joined: Fri Mar 21, 2025 10:23 am
GitHub: https://github.com/h3tR

Triple fault on loading CR3 with new page table

Post by h3tR »

Hi all,
I've been trying to write an x86_64 kernel in rust using the Limine boot protocol. Initially I based a lot of what I had on the tutorials on https://os.phil-opp.com/ but I found that I had to figure most things out myself as I decided to restart and use Limine as the bootloader.

Recently I've been trying to implement paging using a custom recursive page table that allows me to modify it without it being loaded (makes it a lot easier to set everything up up until that point), instead of relying on one from the x86_64 crate.
Whenever I load the page table however, I get a triple fault. I've been trying to debug this for a couple days now and I feel like I'm not making any progress whatsoever.
Using info mem and info tlb doesn't seem to show anything wrong, I am mapping the kernel and the kernel stack as well as the page table itself and those appear to be correct in there.

I've also tried logging all interrupts and in the first page fault it does show CR2 to have a strange value ending in 0x9, which I think means there might be some stack corruption, although I wouldn't really know how or why that could be happening.

The code for this project is hosted at https://github.com/h3tR/kermol and the page table is loaded in https://github.com/h3tR/kermol/blob/mas ... le.rs#L211

I might be forgetting some details so feel free to ask for anything I might have left out of this post. I also hope the code is readable enough, I try to add comments as much as I can but I doubt that is enough. :?
Any help is greatly appreciated. :mrgreen:
Octocontrabass
Member
Member
Posts: 6248
Joined: Mon Mar 25, 2013 7:01 pm

Re: Triple fault on loading CR3 with new page table

Post by Octocontrabass »

h3tR wrote: Mon May 04, 2026 8:59 amI've also tried logging all interrupts and in the first page fault it does show CR2 to have a strange value ending in 0x9, which I think means there might be some stack corruption, although I wouldn't really know how or why that could be happening.
Can we see the log? Why do you think the CR2 value is strange?
h3tR wrote: Mon May 04, 2026 8:59 amThe code for this project is hosted at https://github.com/h3tR/kermol and the page table is loaded in https://github.com/h3tR/kermol/blob/mas ... le.rs#L211
What's up with that MFENCE instruction? It doesn't look like it's doing anything useful.
User avatar
h3tR
Posts: 9
Joined: Fri Mar 21, 2025 10:23 am
GitHub: https://github.com/h3tR

Re: Triple fault on loading CR3 with new page table

Post by h3tR »

Octocontrabass wrote: Mon May 04, 2026 11:22 am What's up with that MFENCE instruction? It doesn't look like it's doing anything useful.
Honestly I was just throwing things at the wall to see what stuck, same for the infinite loop. So yeah its not really useful, forgot to take it out the commit before I pushed it.

Octocontrabass wrote: Mon May 04, 2026 11:22 am Can we see the log? Why do you think the CR2 value is strange?
So iirc the CR2 points to the address that caused the page fault, I would expect this to be aligned by at least 4 bytes for things like instructions assuming it came from a bad jmp instruction or something similar, since RIP has the same value as CR2.

Here's the first page fault in the log (after this it goes on for a really long time until it runs off the stack). Most things do look fine I think, the stack pointer, the GDT & the IDT have the correct values from what I've cross-referenced with info mem

Code: Select all

check_exception old: 0xffffffff new 0xe
   762: v=0e e=0011 i=0 cpl=0 IP=0008:ffffffff800f4e69 pc=ffffffff800f4e69 SP=0030:ffff80001fe538e0 CR2=ffffffff800f4e69
RAX=0000000001b80000 RBX=0000000000000000 RCX=0000000000000000 RDX=0000000001b80000
RSI=0000000001b80000 RDI=0000000001b80000 RBP=0000000000000000 RSP=ffff80001fe538e0
R8 =ffffffff80162f10 R9 =ffffffff80165f48 R10=0000000000aaaaaa R11=0000000000000020
R12=0000000000000000 R13=0000000000000000 R14=0000000000000000 R15=0000000000000000
RIP=ffffffff800f4e69 RFL=00000006 [-----P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0030 0000000000000000 00000000 00009300 DPL=0 DS   [-WA]
CS =0008 0000000000000000 ffffffff 00af9b00 DPL=0 CS64 [-RA]
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 =0010 ffffffff801781c0 00000067 00008900 DPL=0 TSS64-avl
GDT=     ffffffff80178230 0000001f
IDT=     ffffffff80177020 00000fff
CR0=80010011 CR2=ffffffff800f4e69 CR3=0000000001b80000 CR4=00000020
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=0000000000000000 CCD=0000000001b80000 CCO=LOGICQ
EFER=0000000000000d00
Octocontrabass
Member
Member
Posts: 6248
Joined: Mon Mar 25, 2013 7:01 pm

Re: Triple fault on loading CR3 with new page table

Post by Octocontrabass »

h3tR wrote: Mon May 04, 2026 11:53 amSo iirc the CR2 points to the address that caused the page fault, I would expect this to be aligned by at least 4 bytes for things like instructions assuming it came from a bad jmp instruction or something similar, since RIP has the same value as CR2.
Assuming it came from a bad jump instruction and your compiler always aligns jump destinations, sure, but those may not be safe assumptions. Did you check to see if RIP points to a reasonable address? If so, which instruction in which function?
h3tR wrote: Mon May 04, 2026 11:53 am

Code: Select all

   762: v=0e e=0011
Did you set the NX bit somewhere you shouldn't have?
User avatar
h3tR
Posts: 9
Joined: Fri Mar 21, 2025 10:23 am
GitHub: https://github.com/h3tR

Re: Triple fault on loading CR3 with new page table

Post by h3tR »

Octocontrabass wrote: Mon May 04, 2026 12:33 pm Assuming it came from a bad jump instruction and your compiler always aligns jump destinations, sure, but those may not be safe assumptions. Did you check to see if RIP points to a reasonable address? If so, which instruction in which function?
I just did a disassembly of the kernel elf and I found that it points to the instruction right after loading cr3 so I suppose it is a valid address after all. I guess that would mean that it already faults at the next fetch.
Octocontrabass wrote: Mon May 04, 2026 12:33 pm Did you set the NX bit somewhere you shouldn't have?
I don't think I have, I temporarily set every flag to rwx (writable and present) so I don't have to worry about that being flagged but even when I set everything to the correct flags the same happens. I just double checked and the TLB dump states the following (with the correct flags instead of rwx) so I doubt that could be the issue.

Code: Select all

ffffffff800f4000: 0000000019e04000 -G-------
Octocontrabass
Member
Member
Posts: 6248
Joined: Mon Mar 25, 2013 7:01 pm

Re: Triple fault on loading CR3 with new page table

Post by Octocontrabass »

h3tR wrote: Mon May 04, 2026 4:24 pmI just double checked and the TLB dump states the following (with the correct flags instead of rwx) so I doubt that could be the issue.
QEMU's "info tlb" shows the bits set in the last-level page table entry, not the actual page permissions. You could still have mistakenly set the NX bit somewhere in your page tables.
User avatar
h3tR
Posts: 9
Joined: Fri Mar 21, 2025 10:23 am
GitHub: https://github.com/h3tR

Re: Triple fault on loading CR3 with new page table

Post by h3tR »

Octocontrabass wrote: Mon May 04, 2026 5:16 pm QEMU's "info tlb" shows the bits set in the last-level page table entry, not the actual page permissions. You could still have mistakenly set the NX bit somewhere in your page tables.
I did not at all realize that the flags cascaded #-o. Thank you so much, I would've never figured this out by myself!
Post Reply