XD/NX reserved bit on pages in the PML4 from the APs
Posted: Fri Sep 22, 2023 4:01 pm
Hey folks, my kernel is slowly coming together and I've been lurking on OSDev for a few months and the site and forums have been an invaluable resource. I've just spent the last few weeks struggling to get my APs to initialize into long mode, and I think my last hurdle may be worth signposting for others that follow. I don't have wiki write access so I'll document it here for now.
If like me you went for a UEFI only kernel, I didn't go through the real -> protected -> long sequence initially. Instead I started in long mode already and just needed to set my own PML4.
While doing this, I started off by utilizing the NX/XD bit on all my pages except those I tag as executable. UEFI must enable the XD bit in the EFER for you because I didn't.
The fun comes when you attempt to bring up the APs, go through all the dance, then set the PML4 you know works only to discover your code is executing fine, but your stack is not!
My clue came from the error code on the page fault only to discover that the value was 0xB. One of the bits indicates that a reserved bit is set. After checking against the reserved bits, it wasn't set and I was thoroughly confused.
After much head scratching and rubber duck programming with ChatGPT, it kept telling me that bit 63 was reserved, and I told it back that this is where the NX/XD flag is set. It replied that this bit is only valid when NX/XD is enabled in the EFER.
I think it's worth signposting this in a few places:
If like me you went for a UEFI only kernel, I didn't go through the real -> protected -> long sequence initially. Instead I started in long mode already and just needed to set my own PML4.
While doing this, I started off by utilizing the NX/XD bit on all my pages except those I tag as executable. UEFI must enable the XD bit in the EFER for you because I didn't.
The fun comes when you attempt to bring up the APs, go through all the dance, then set the PML4 you know works only to discover your code is executing fine, but your stack is not!
My clue came from the error code on the page fault only to discover that the value was 0xB. One of the bits indicates that a reserved bit is set. After checking against the reserved bits, it wasn't set and I was thoroughly confused.
After much head scratching and rubber duck programming with ChatGPT, it kept telling me that bit 63 was reserved, and I told it back that this is where the NX/XD flag is set. It replied that this bit is only valid when NX/XD is enabled in the EFER.
I think it's worth signposting this in a few places:
- In the section on Page Fault error codes I would include a note in both the row for Reserved write, and the the list of conditions under which a page fault occurs.
- On the SMP page I would link to the page fault error codes section saying there is more info here if you are struggling with page faults.
- Finally a note on the Setting Up Long Mode about how the NX/XD bit may set by UEFI but it won't be set on the APs, with a link to the above, and perhaps a bit where you manipulate the EFER in the section on switching from protected mode.