Setting Up Paging With PAE: Difference between revisions
[unchecked revision] | [unchecked revision] |
(New page: This is a guide to setting up paging with PAE enabled. You should read Setting Up Paging first. ==Differences between PAE-Paging and Legacy-Paging== *PAE allows you to access more phy...) |
m (Bot: Replace deprecated source tag with syntaxhighlight) |
||
(19 intermediate revisions by 11 users not shown) | |||
Line 1: | Line 1: | ||
{{Rating|1}} |
|||
⚫ | |||
{{In_Progress}} |
|||
⚫ | |||
==Differences between PAE-Paging and Legacy-Paging== |
===Differences between PAE-Paging and Legacy-Paging=== |
||
*PAE allows you to access more physical memory, which is usually 64GiB (in fact, this is implementation specific). |
*PAE allows you to access more physical memory, which is usually 64GiB (in fact, this is implementation specific). |
||
*A new data structure is added, the so called 'Page-Directory-Pointer-Table' |
*A new data structure is added, the so called 'Page-Directory-Pointer-Table' |
||
* |
*An entry is now 8-byte-wide (Legacy: 4-byte), so the number of entries is halved to 512 (Legacy: 1024) |
||
*If the CPU supports it you can use the NoExecute-bit |
|||
===Setting Up The Data Structures=== |
===Setting Up The Data Structures=== |
||
As mentioned above the 'Page-Directory-Pointer-Table' is added, which contains 4 Page-Directory-Entries |
As mentioned above the 'Page-Directory-Pointer-Table' is added, which contains 4 Page-Directory-Entries |
||
<syntaxhighlight lang="c"> |
|||
<pre> |
|||
uint64_t page_dir_ptr_tab[4] __attribute__((aligned( |
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 |
|||
</pre> |
|||
</syntaxhighlight> |
|||
Now we need our Page-Directory/-Table |
|||
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. |
|||
<pre> |
|||
Now we need our Page-Directory. For the sake of easiness, we'll use PSE. (2 MIB pages mapped in page directory) |
|||
<syntaxhighlight lang="c"> |
|||
// 512 entries |
// 512 entries |
||
uint64_t page_dir[512] __attribute__((aligned(0x1000))); |
uint64_t page_dir[512] __attribute__((aligned(0x1000))); // must be aligned to page boundary |
||
</syntaxhighlight> |
|||
uint64_t page_tab[512] __attribute__((aligned(0x1000))); |
|||
</pre> |
|||
===Making it run=== |
===Making it run=== |
||
Ok, now we have our structures. |
Ok, now we have our structures. Let's map the first 2 MIB. |
||
<syntaxhighlight lang="c"> |
|||
<pre> |
|||
page_dir_ptr_tab[0] = (uint64_t)&page_dir | 1; // set the page directory into the PDPT and mark it present |
page_dir_ptr_tab[0] = (uint64_t)&page_dir | 1; // set the page directory into the PDPT and mark it present |
||
page_dir[0] = |
page_dir[0] = 0b10000011; //Address=0, 2MIB, RW and present |
||
</syntaxhighlight> |
|||
</pre> |
|||
⚫ | |||
Ok, let's map the first 2MiB. |
|||
<syntaxhighlight lang="c"> |
|||
<pre> |
|||
⚫ | |||
unsigned int i, address = 0; |
|||
⚫ | |||
for(i = 0; i < 512; i++) |
|||
</syntaxhighlight> |
|||
{ |
|||
page_tab[i] = address | 3; // map address and mark it present/writable |
|||
address = address + 0x1000; |
|||
} |
|||
</pre> |
|||
⚫ | |||
<pre> |
|||
⚫ | |||
⚫ | |||
</pre> |
|||
Finally, we'll enable paging. |
|||
Simply done: |
Simply done: |
||
<syntaxhighlight lang="c"> |
|||
<pre> |
|||
asm volatile ("movl %cr0, %eax; orl $0x80000000, %eax; movl %eax, %cr0;"); |
asm volatile ("movl %%cr0, %%eax; orl $0x80000000, %%eax; movl %%eax, %%cr0;" ::: "eax"); |
||
</syntaxhighlight> |
|||
</pre> |
|||
⚫ | |||
==FAQ== |
|||
Q: Why is it causing triple fault/page fault? |
|||
A: You're kernel is probably not inside the first 2 MiB of the memory. You'll need to identity map your kernel. |
|||
Q: How do I map pages? |
|||
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]] |
Latest revision as of 04:48, 9 June 2024
Difficulty level |
---|
![]() Beginner |
This is a guide to setting up paging with PAE enabled. You should read Setting Up Paging first.
Differences between PAE-Paging and Legacy-Paging
- PAE allows you to access more physical memory, which is usually 64GiB (in fact, this is implementation specific).
- A new data structure is added, the so called 'Page-Directory-Pointer-Table'
- An entry is now 8-byte-wide (Legacy: 4-byte), so the number of entries is halved to 512 (Legacy: 1024)
- If the CPU supports it you can use the NoExecute-bit
Setting Up The Data Structures
As mentioned above the 'Page-Directory-Pointer-Table' is added, which contains 4 Page-Directory-Entries
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
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. For the sake of easiness, we'll use PSE. (2 MIB pages mapped in page directory)
// 512 entries
uint64_t page_dir[512] __attribute__((aligned(0x1000))); // must be aligned to page boundary
Making it run
Ok, now we have our structures. Let's map the first 2 MIB.
page_dir_ptr_tab[0] = (uint64_t)&page_dir | 1; // set the page directory into the PDPT and mark it present
page_dir[0] = 0b10000011; //Address=0, 2MIB, RW and present
Pages are mapped. Now we have to set the PAE-bit in CR4 and load the PDPT into CR3
asm volatile ("movl %%cr4, %%eax; bts $5, %%eax; movl %%eax, %%cr4" ::: "eax"); // set bit5 in CR4 to enable PAE
asm volatile ("movl %0, %%cr3" :: "r" (&page_dir_ptr_tab)); // load PDPT into CR3
Finally, we'll enable paging. Simply done:
asm volatile ("movl %%cr0, %%eax; orl $0x80000000, %%eax; movl %%eax, %%cr0;" ::: "eax");
PAE paging should now be enabled.
FAQ
Q: Why is it causing triple fault/page fault?
A: You're kernel is probably not inside the first 2 MiB of the memory. You'll need to identity map your kernel.
Q: How do I map pages?
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.