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:
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:
| 63 .... 48 Sgn Ext | 47 ... 39 P4 | 38 ... 32 31 30 P3 | 29 .. 21 P2 | 20 ... 0 Offset |
So i created this macro:
Code:
#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:
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:
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:
| 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:
#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)