Setting Up Paging With PAE: Difference between revisions

m
Bot: Replace deprecated source tag with syntaxhighlight
[unchecked revision][unchecked revision]
m (Mark as in progress)
m (Bot: Replace deprecated source tag with syntaxhighlight)
 
(6 intermediate revisions by 4 users not shown)
Line 11:
===Setting Up The Data Structures===
As mentioned above the 'Page-Directory-Pointer-Table' is added, which contains 4 Page-Directory-Entries
<sourcesyntaxhighlight lang="c">
uint64_t page_dir_ptr_tab[4] __attribute__((aligned(0x20))); // must be aligned to (at least)0x20, ...
// ... turning out that you can put more of them into one page, saving memory
</syntaxhighlight>
</source>
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)
<sourcesyntaxhighlight lang="c">
// 512 entries
uint64_t page_dir[512] __attribute__((aligned(0x1000))); // must be aligned to page boundary
</syntaxhighlight>
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.
<sourcesyntaxhighlight 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
</syntaxhighlight>
</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.
<sourcesyntaxhighlight lang="c">
asm volatile ("movl %%cr4, %%eax; bts $5, %%eax; movl %%eax, %%cr4" ::: "eax"); // set bit5 in CR4 to enable PAE
unsigned int i, address = 0;
asm volatile ("movl %%eax0, %%cr3" :: "ar" (&page_dir_ptr_tab)); // load PDPT into CR3
for(i = 0; i < 512; i++)
</syntaxhighlight>
{
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"); // set bit5 in CR4 to enable PAE
asm volatile ("movl %%eax, %%cr3" :: "a" (&page_dir_ptr_tab)); // load PDPT into CR3
</source>
 
The last thingFinally, we'll need to do is activatingenable paging.
Simply done:
<sourcesyntaxhighlight lang="c">
asm volatile ("movl %%cr0, %%eax; orl $0x80000000, %%eax; movl %%eax, %%cr0;" ::: "eax");
</syntaxhighlight>
</source>
 
PAE-Paging paging should now be enabled.
 
==FAQ==
===Mapping the PD to itself===
Q: Why is it causing triple fault/page fault?
In Legacy-Paging this is quite easy. Just map the PD to the last entry of itself.
 
A: You're kernel is probably not inside the first 2 MiB of the memory. You'll need to identity map your kernel.
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.
 
Q: How do I map pages?
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.
A: Firstly, align your desired virtual memory address to 1 GiB, and divide it by 1 GiB to obtain the PDPT index. Then, find the index of the page directory by aligning your desired virtual address to 2 MiB and divide it by 2 MiB. Finally, lookup the page directory entry by the index obtained in the previous step, and set the entry's address to your desired physical address that's aligned to 2 MiB.
 
[[Category:Paging]]
[[Category:Virtual Memory]]
[[Category:X86 CPU]]
[[Category:Tutorials]]