R/O huge page overlapping page table
Posted: Wed Apr 22, 2026 6:23 am
Hi everyone!
It's been a long time since I've been back in the osdev community... I'm starting work on a 64-bit rust-based OS (previous OSes were all 32-bit and C/C++ based, so both are new to me)
I'm curious if anyone has any suggestions for handling the following scenario:
This is how some of the memory is setup by the UEFI firmware. It's identity mapped, which is great -- I'd like to preserve that, as writable, at a specific offset, in order to have writable access to physical pages in order to manipulate page tables.
My plan was to copy the identity mapped entry in pl4_table[0] to pl4_table[510] (effectively mirroring the first 512GB of physical memory to be starting at the virtual address 0xFFFFFF0000000000) and then iterate through the page tables and mark them all as writable.
Of course, In order to modify a specific entry in a page table, the page containing the page table must be parked as writable... which it is, in this case... the pl2_table is at 0x7fc04000 and is marked as writable... so I just need to modify index 510 of that table as writable... but that's impossible, because the pl2_table_entry says that that address is actually part of a 2mb R/O huge page which starts before the pl2_table, and overlaps it.. effectively making it read-only, even though it's marked as writable.
So while the pl3_table_entry says that 4kb region is writable... the pl2_table_entry says that whole 2mb region is actually read only.
It seems like I'm in a bit of a chicken and egg scenario, and very-much at the whim of the UEFI firmware's memory map... it feels like I probably have to drop all the UEFI page tables, and create my own... but I need to be able to write to physical memory in order to do that.
Mostly wondering how others have handled this situation.
Thanks,
Jeff
It's been a long time since I've been back in the osdev community... I'm starting work on a 64-bit rust-based OS (previous OSes were all 32-bit and C/C++ based, so both are new to me)
I'm curious if anyone has any suggestions for handling the following scenario:
Code: Select all
(gdb) print_address_indices 0x000000007fc04000
0x7fc04000 -> 0, 1, 510, 4 <-- indices into pl4, pl3, pl2 and pl1 tables for the given address
entry = 0x7fc02023 addr = 0x7fc02000 flags = 0x23 ( P RW A ) <-- pl3 table entry
entry = 0x7fc04023 addr = 0x7fc04000 flags = 0x23 ( P RW A ) <-- pl3 table entry
entry = 0x7fc000e1 addr = 0x7fc00000 flags = 0xe1 ( P A D PS ) <-- pl2 table entry
My plan was to copy the identity mapped entry in pl4_table[0] to pl4_table[510] (effectively mirroring the first 512GB of physical memory to be starting at the virtual address 0xFFFFFF0000000000) and then iterate through the page tables and mark them all as writable.
Of course, In order to modify a specific entry in a page table, the page containing the page table must be parked as writable... which it is, in this case... the pl2_table is at 0x7fc04000 and is marked as writable... so I just need to modify index 510 of that table as writable... but that's impossible, because the pl2_table_entry says that that address is actually part of a 2mb R/O huge page which starts before the pl2_table, and overlaps it.. effectively making it read-only, even though it's marked as writable.
So while the pl3_table_entry says that 4kb region is writable... the pl2_table_entry says that whole 2mb region is actually read only.
It seems like I'm in a bit of a chicken and egg scenario, and very-much at the whim of the UEFI firmware's memory map... it feels like I probably have to drop all the UEFI page tables, and create my own... but I need to be able to write to physical memory in order to do that.
Mostly wondering how others have handled this situation.
Thanks,
Jeff