Paging 64bit: Recursive address calculation for 4k/2Mb pages

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
finarfin
Member
Member
Posts: 106
Joined: Fri Feb 23, 2007 1:41 am
Location: Italy & Ireland
Contact:

Paging 64bit: Recursive address calculation for 4k/2Mb pages

Post by finarfin »

Hi all,

i started to implement the recursive access to Page dirs in my OS, i created some macros etc.

And my understanding was that i have to build a special address to access recursively paging data structures.

That is fine, so first thing that i did was map pml4 entry into itself:

Code: Select all

    mov eax, p4_table - KERNEL_VIRTUAL_ADDR ; Mapping the PML4 into itself
    or eax, PRESENT_BIT | WRITE_BIT
    mov dword [(p4_table - KERNEL_VIRTUAL_ADDR) + 510 * 8], eax
I used entry 510 because 511 is used for kernel in higher half.

And then from here depending on how i build the address i can access p4, p3, p2 p1.

But what i thought: ok if i'm using 2mb pages i need to build a 2mb type of virtual address that is:

Code: Select all

| 63 .... 48  Sgn Ext | 47 ... 39 P4 | 38   ... 32  31  30 P3 | 29  ..  21 P2 | 20 ...  0 Offset |
So i created this macro:

Code: Select all

#define ENTRIES_TO_ADDRESS(pml4, pdpr, pd)((pml4 << 39) | (pdpr << 30) | (pd << 21))
But when using this address i see wrong information, for example if i build the address:

Code: Select all

table = SIGN_EXTENSION | ENTRIES_TO_ADDRESS(510l,510l,510l)
And try to print the content i see the value of first entry of p3 table not p4, and if i try to use this address:

Code: Select all

table = SIGN_EXTENSION | ENTRIES_TO_ADDRESS(510l,510l,0l)
The entry is from table p2, it honestly took me a while to figure out why, i had to read couple of times documentation on intel manuals to start to think what could have been the problem, and looks like it is that:

The address translation mechanism in ia32e is still:

Code: Select all

| 63 .... 48  Sgn Ext | 47 ... 39 P4 | 38   ... 32  31  30 P3 | 29  ..  21 P2 | 20  12 Pt | 11...  0 Offset |
Like when using 4kb pages, but when it reaches a 2mb page if the huge bit is set, it stops there, instead of resolving the pagetable, and while using the recursion the address to access data structures has to be built still like i'm accessing a 4kb page not a 2mb one, because there is no way that the pml4 entry has the hugepage bit set.

When i changed the function to use also the ptable:

Code: Select all

#define ENTRIES_TO_ADDRESS(pml4, pdpr, pd, pt)((pml4 << 39) | (pdpr << 30) | (pd << 21)) | (pt << 12)
I got the expected values.

I just wanted to know with this post few things:

1. If my reasoning is correct, and this is the expeceted behaviour, or it works in a different way, and i got expected values just by chance.
2. This means that i can have 4kb and 2mb pages coexisting at the same time?
3. But if this is the behaviour: if need to access a p2 entry in theory that can be a 4kb or 2mb page so in theory trhe OS should check the huege page bit before trying to access the page table from there (i say in theory because if the OS is stick only to one size, it should be safe in this case to make an assumption on the value of this bit)
Elen síla lúmenn' omentielvo
- DreamOS64 - My latest attempt with osdev: https://github.com/dreamos82/Dreamos64
- Osdev Notes - My notes about osdeving! https://github.com/dreamos82/Osdev-Notes
- My old Os Project: https://github.com/dreamos82/DreamOs
Octocontrabass
Member
Member
Posts: 5568
Joined: Mon Mar 25, 2013 7:01 pm

Re: Paging 64bit: Recursive address calculation for 4k/2Mb p

Post by Octocontrabass »

finarfin wrote:1. If my reasoning is correct, and this is the expeceted behaviour, or it works in a different way, and i got expected values just by chance.
As far as I can tell, you're correct. The huge page bit won't be set in the higher levels of your page structures, so when you use recursive mapping to reinterpret them, they'll be mapped as 4kB pages.
finarfin wrote:2. This means that i can have 4kb and 2mb pages coexisting at the same time?
Yes. You can also have 1GB pages, if the CPU supports them.
finarfin wrote:3. But if this is the behaviour: if need to access a p2 entry in theory that can be a 4kb or 2mb page so in theory trhe OS should check the huege page bit before trying to access the page table from there (i say in theory because if the OS is stick only to one size, it should be safe in this case to make an assumption on the value of this bit)
Correct.
Post Reply