R/O huge page overlapping 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
carbonBased
Member
Member
Posts: 389
Joined: Sat Nov 20, 2004 12:00 am
Location: Wellesley, Ontario, Canada
Contact:

R/O huge page overlapping page table

Post by carbonBased »

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:

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
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
User avatar
bellezzasolo
Member
Member
Posts: 163
Joined: Sun Feb 20, 2011 2:01 pm

Re: R/O huge page overlapping page table

Post by bellezzasolo »

carbonBased wrote: 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:

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
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
Firstly, you illustrate a slight misunderstanding on what the higher page tables are saying. RW there isn't saying that the page directory is writeable, it's saying that the region of virtual memory that they cover might be writeable.

For a page table, that's 4KB. For a page directory, that's 2MB. For a PDPT, that's a 1GB region, and for the PML4T, 512GB. In the PML5T, 256TB. If the RW bit isn't set, the processor page faults and goes home. But it's perfectly valid for different pages to be set differently.

With that out of the way, the UEFI spec says that regions in the memory map must be identity mapped. It does not specify the attributes required.

Since the page tables UEFI uses are going to be in UEFI reclaimable memory, you will eventually want to replace them anyway. So, how do you write physical memory? Well, remember it's identity mapped! If you reserve a few KB of writeable BSS in your application, you can create page tables. or just AllocatePages() before exiting boot services.
Whoever said you can't do OS development on Windows?
https://github.com/ChaiSoft/ChaiOS
Post Reply