Setting Up Paging With PAE: Difference between revisions

no edit summary
[unchecked revision][unchecked revision]
No edit summary
Line 17:
Keep in mind that the size of the CR3 register remains at 4byte, meaning that a PDPT must be located below 4GiB in physical memory.
 
Now we need our Page-Directory/-Table. For the sake of easiness, we'll use PSE. (2 MIB pages mapped in page directory)
<source lang="c">
// 512 entries
uint64_t page_dir[512] __attribute__((aligned(0x1000))); // must be aligned to page boundary
uint64_t page_tab[512] __attribute__((aligned(0x1000)));
</source>
 
===Making it run===
Ok, now we have our structures. NowLet's wemap havethe tofirst make2 it runMIB.
<source lang="c">
page_dir_ptr_tab[0] = (uint64_t)&page_dir | 1; // set the page directory into the PDPT and mark it present
page_dir[0] = (uint64_t)&p_tab | 30b10000011; //setAddress=0, the2MIB, page table into the PDRW and mark it present/writable
</source>
 
Ok, pagesPages are mapped. Now we have to set the PAE-bit in CR4 and load the PDPT into CR3
Ok, let's map the first 2MiB.
<source lang="c">
unsigned int i, address = 0;
for(i = 0; i < 512; i++)
{
page_tab[i] = address | 3; // map address and mark it present/writable
address = address + 0x1000;
}
</source>
Ok, pages are mapped. Now we have to set the PAE-bit and load the PDPT into CR3
<source lang="c">
asm volatile ("movl %%cr4, %%eax; bts $5, %%eax; movl %%eax, %%cr4" ::: "eax"); // set bit5 in CR4 to enable PAE
Line 46 ⟶ 36:
</source>
 
The last thingFinally, we'll need to do is activatingenable paging.
Simply done:
<source lang="c">
Line 52 ⟶ 42:
</source>
 
PAE-Paging paging should now be enabled.
 
===Mapping the PD to itself===
In Legacy-Paging this is quite easy. Just map the PD to the last entry of itself.
 
In PAE-Paging we have 4 entries and the PDPT, so how does it work?
Depending on where you want to set it you just map all 4 directories into one of those!
Example (PD's at end of virtual memory)
<source lang="c">
uint64_t * page_dir = (uint64_t*)page_dir_ptr_tab[3]; // get the page directory (you should 'and' the flags away)
page_dir[511] = (uint64_t)page_dir; // map pd to itself
page_dir[510] = page_dir_ptr_tab[2]; // map pd3 to it
page_dir[509] = page_dir_ptr_tab[1]; // map pd2 to it
page_dir[508] = page_dir_ptr_tab[0]; // map pd1 to it
page_dir[507] = (uint64_t)&page_dir_ptr_tab; /* map the PDPT to the directory
</source>
Now you can access all structures in virtual memory. Mapping the PDPT into the directory wastes quite much virtual memory as only 32 bytes are used, but if you allocate most/all PDPT's into one page then you can access ALL of them, which can be quite useful.
 
You can also statically allocate the PDPT at boot time, put the 4 page directory addresses in your process struct, and then just write the same PDPT address to CR3 on a context switch after you've
patched the PDPT.
[[Category:X86 CPU]]
[[Category:Tutorials]]