Recursive paging trick on non-last PML4 entry

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
CRoemheld
Member
Member
Posts: 55
Joined: Wed May 02, 2018 1:26 pm
Libera.chat IRC: CRoemheld

Recursive paging trick on non-last PML4 entry

Post by CRoemheld »

I'm trying to figure out the recursive paging trick I read about from here and here.
Although I think I understand the idea behind this, when trying to apply this trick on my own system, I cannot seem to use the last PML4 entry because the OS seems to be using the last PML4 entry for the kernel.

The first question would be: Should I set the recursive entry in the PML4 table first, before mapping any addresses?

If I use the 510th entry, rather than the last (511th) entry in the PML4 table for my recursive mapping trick, that would mean, the recursion would happen at

Code: Select all

0xFFFFFF0...
0xFFFFFF7F8...
0xFFFFFF7FBFC...
0xFFFFFF7FBFDFE...
Meaning, if I were to map a, let's say, an entry which loops the PML4 table 3 times (PML4 -> PDPT -> PD), I would need to map the virtual address 0xFFFFFF7FBFC... to a specific physical address?

Isn't this too "complicated" an address to use for recursive mapping? What is the idea behind sometimes using the 510th rather than the 511th entry in the PML4 table for this purpose?
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Recursive paging trick on non-last PML4 entry

Post by Brendan »

Hi,
CRoemheld wrote:What is the idea behind sometimes using the 510th rather than the 511th entry in the PML4 table for this purpose?
Lots of instructions have "immediate data" - data that is built into the instruction itself, like the number 0x12345678 in the instruction "mov eax,[0x12345678 + ebx]". For 64-bit code, almost all immediate data is limited to 32 bits, because having 64 bits of immediate data in instructions makes the instructions huge (and makes it harder/slower for CPU to decode instructions).

Because of this, for "addresses known at compile time" it's more efficient to use 32-bit addresses. For example, something like "mov rax,[0x12345678 + rbx]" is fine because the immediate data fits in 32 bits, but "mov rax,[0x123456789ABCDEF + rbx]" is not supported and would have to be split into a 2 instructions (e.g. maybe "mov rax,0x123456789ABCDEF" and then "mov rax,[rax + rbx]").

This means that it's best to have your code in the first 2 GiB or the first 4 GiB of the virtual address space (where it can use "unsigned 32-bit" immediate data for addresses known at compile time); or in the last 2 GiB of the virtual address space (where it can use "signed 32-bit" immediate data). For this reason; typically user-space processes use the first 2 GiB or 4 GiB of the virtual address space and the kernel uses the last 2 GiB of the virtual address space. To cope with this most compilers are designed to support different memory models for 64-bit code - e.g. a normal memory model (where everything is in the first 2 GiB of the virtual address space), a large memory model (where the code is too large to use 32-bit addresses for addresses known at compile time), and a kernel memory model (where everything is in the last 2 GiB of the virtual address space).

If the kernel's code and data uses the last 2 GiB of the virtual address space (for better efficiency); then you can't use 511th entry in the PML4 table for the recursive mapping trick because it'd effect the area used for kernel's code and data.


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: Recursive paging trick on non-last PML4 entry

Post by xenos »

CRoemheld wrote:Isn't this too "complicated" an address to use for recursive mapping?
No, not at all. Your page tables are still contiguous in memory - you just have to keep in mind where the page tables, page directories etc., i.e., the different levels of the paging hierarchy, start in memory:
https://github.com/xenos1984/NOS/blob/m ... able.h#L34
And then you can use these addresses as base addresses and find every page table by indexing into an array:
https://github.com/xenos1984/NOS/blob/m ... ble.h#L139
(This example code might not have the most simple structure - but it should demonstrate the principle, that the only difference between using entry 510 or 511 is the offset addresses you need to use for accessing the page tables.)
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
Post Reply