Hey, apologies for the delay. Not sure if you've figured this out already, but in case you haven't:
so, your code is correct, insofar as it handles 4KB pages.
however, (unless you removed experimental code) you don't support some of the flags -- notably, the "size" flag of the page table. I personally don't use bitfields to do this but rather bitmasks, and so inspecting the raw value in the page directory entry, i saw "0xE3" -- which is Present (0x1), Read/Write (0x2), Accessed (0x20), and also
Dirty (0x40) and
Large(0x80). (in your structs you marked them as "padding1").
From the AMD manual:
Quote:
Dirty (D) Bit. Bit 6. This bit is only present in the lowest level of the page-translation hierarchy
...
Page Size (PS) Bit. Bit 7. This bit is present in page-directory entries and long-mode page-directory-pointer entries. When the PS bit is set in the page-directory-pointer entry (PDPE) or page-directory entry (PDE), that entry is the lowest level of the page-translation hierarchy.
So, to conclude, the firmware has used 2MB pages to map some of the address space, which might line up with why you're getting "strange" results. If you continued to try and read a page table entry (as you do), you'd read memory from page 0, which explains why seemingly none of the bit flags are set.
It kinda makes sense that UEFI would use large pages (who knows, you might find 1GB pages possibly?), because they require identity mapping the entirety of physical memory -- that'd be done a lot more efficiently with large or even huge pages.