Paging: Difference between revisions

176 bytes added ,  13 years ago
m
Syntax highlighting and minor correction
[unchecked revision][unchecked revision]
m (Typos)
m (Syntax highlighting and minor correction)
Line 52:
INVLPG is an instruction available since the 486 that invalidates a single page table entry in the TLB. Intel warns that this instruction may be implemented differently on future processors. INVLPG modifies no flags.
 
NASM example:
<source lang="C">
invlpg [0]
</source>
 
Inline asm in CGCC:
<source lang="C">
__asm__ volatile("invlpg %0"::"m" (*(char *)addr));
</source>
 
===Example===
Line 62 ⟶ 66:
Say I loaded my kernel to 0x100000. However, I want it mapped to 0xc0000000. After loading my kernel, I initiate paging, and set up the appropriate tables. (See [[Higher Half Kernel]]) After [[Identity Paging]] the first megabyte, I start to create my second table (ie. at entry #768 in my directory.) to map 0x100000 to 0xc0000000. My code could be like: <br /><br />
 
<source lang="asm">
mov eax, 0x0
mov ebx, 0x100000
Line 74 ⟶ 79:
jmp .fill_table
.end:
</source>
 
==Enabling==
Enabling paging is actually very simple. All that is needed is to load CR3 with the address of the page directory and to set the paging bit of CR0.
 
<source lang="asm">
mov eax, [page_directory]
mov cr3, eax
Line 84 ⟶ 91:
or eax, 0x80000000
mov cr0, eax
</source>
 
To enable PSE (4 MiB pages) the following code is required.
 
<source lang="asm">
mov eax, cr4
or eax, 0x00000010
mov cr4, eax
</source>
 
==Physical Address Extension==
Line 111 ⟶ 121:
 
Many prefer to map the last PDE to itself. The page directory will look like a page table to the system. To get the physical address of any virtual address in the range 0x00000000-0xFFFFF000 is then just a matter of:
<source lang="C">
<pre>
void * get_physaddr(void * virtualaddr)
{
Line 125 ⟶ 135:
return (void *)((pt[ptindex] & ~0xFFF) + ((unsigned long)virtualaddr & 0xFFF));
}
</presource>
 
To map a virtual address to a physical address can be done as follows:
<source lang="C">
<pre>
void map_page(void * physaddr, void * virtualaddr, unsigned int flags)
{
Line 150 ⟶ 160:
// or you might not notice the change.
}
</presource>
Unmapping an entry is essentially the same as above, but instead of assigning the <code>pt[ptindex]</code> a value, you set it to 0x00000000 (i.e. not present). When the entire page table is empty, you may want to remove it and mark the page directory entry 'not present'. Of course you don't need the 'flags' or 'physaddr' for unmapping.
 
Anonymous user