Higher half kernels and a few paging questions
Posted: Fri Feb 17, 2006 6:50 am
I have been looking at the two different Higher half with grub example kernels in the FAQ
HigherHalfBareBones
HigherHalfWithGdt
I have tested HigherHalfWithGdt.
Her is how it setup paging.
it says it maps the first 4mb in the loop well that I undrestand 1024 * 4kb pages would be 4mb. But how does the mapping really work? I have commented a bit of the paging C code above to what I have understand each part of the code does.
At the beginning of the file this two is decleared, this is the real storage place for the pagedir and pagetable (or have I missed something?) this two would then have a vaddr (virtual address) I gess in the higher half where the kernel is mapped
Then this two pointers will be pointing to the paddr (physical address) where it actually are stored in memory.
This is from the loop, so what I have understand it will put the value (k * 4096) | 0x3; into each "slot" of the page table, well that is self explaining though. so the (k * 4096) will be the paddr and 0x3 is a the flags for the page ( 0x3 is RW and Present bit )
Self explaining pice of code, will clear the entire page dir.
Then after the loop this two are set into the page dir, this I don't understand yet. but the lowpagetablePtr is the paddr for the above pagetable and then 0x3 is the same flags as above. so this will actually map an entire 4mb page that has 4kb subpages mapped above.
but why 0 and 768? the code comments says it is 0-4mb and 3072-3076MB, and why put the same info in both of them?
Then there is the ASM code that actually do the magic.
So now paging is enabled, and if I use any address after this that address would be a virtual address and the MMU will look into the pagedir/pagetables to find the physical address and then read/write to that address even though the application thinks it writing to another place.. valid virtual addresses would be addresses below 4mb and between 3072 and 3076mb altough they actually are the same place in the physical memory.
if I have understand everything ok why can't I remove the line where I map the first 4mb and leave that part unmapped?
edit: or if I can what can't I do if I remove that line?
edit 2: I can access videomem at both 0xB8000 and 0xC00B8000 isn't that a result of the mapping above that these two vaddr points to the same paddr.
HigherHalfBareBones
HigherHalfWithGdt
I have tested HigherHalfWithGdt.
Her is how it setup paging.
Code: Select all
// Declare the page directory and a page table, both 4kb-aligned
unsigned long kernelpagedir[1024] __attribute__ ((aligned (4096)));
unsigned long lowpagetable[1024] __attribute__ ((aligned (4096)));
// This function fills the page directory and the page table,
// then enables paging by putting the address of the page directory
// into the CR3 register and setting the 31st bit into the CR0 one
void init_paging()
{
// Pointers to the page directory and the page table
void *kernelpagedirPtr = 0;
void *lowpagetablePtr = 0;
int k = 0;
kernelpagedirPtr = (char *)kernelpagedir + 0x40000000; // Translate the page directory from
// virtual address to physical address
lowpagetablePtr = (char *)lowpagetable + 0x40000000; // Same for the page table
// Counts from 0 to 1023 to...
for (k = 0; k < 1024; k++)
{
lowpagetable[k] = (k * 4096) | 0x3; // ...map the first 4MB of memory into the page table...
kernelpagedir[k] = 0; // ...and clear the page directory entries
}
// Fills the addresses 0...4MB and 3072MB...3076MB of the page directory
// with the same page table
kernelpagedir[0] = (unsigned long)lowpagetablePtr | 0x3;
kernelpagedir[768] = (unsigned long)lowpagetablePtr | 0x3;
// Copies the address of the page directory into the CR3 register and, finally, enables paging!
asm volatile ( "mov %0, %%eax\n"
"mov %%eax, %%cr3\n"
"mov %%cr0, %%eax\n"
"orl $0x80000000, %%eax\n"
"mov %%eax, %%cr0\n" :: "m" (kernelpagedirPtr));
}
At the beginning of the file this two is decleared, this is the real storage place for the pagedir and pagetable (or have I missed something?) this two would then have a vaddr (virtual address) I gess in the higher half where the kernel is mapped
Code: Select all
unsigned long kernelpagedir[1024] __attribute__ ((aligned (4096)));
unsigned long lowpagetable[1024] __attribute__ ((aligned (4096)));
Code: Select all
kernelpagedirPtr = (char *)kernelpagedir + 0x40000000;
lowpagetablePtr = (char *)lowpagetable + 0x40000000;
Code: Select all
lowpagetable[k] = (k * 4096) | 0x3;
Code: Select all
kernelpagedir[k] = 0;
Code: Select all
kernelpagedir[0] = (unsigned long)lowpagetablePtr | 0x3;
kernelpagedir[768] = (unsigned long)lowpagetablePtr | 0x3;
Then there is the ASM code that actually do the magic.
So now paging is enabled, and if I use any address after this that address would be a virtual address and the MMU will look into the pagedir/pagetables to find the physical address and then read/write to that address even though the application thinks it writing to another place.. valid virtual addresses would be addresses below 4mb and between 3072 and 3076mb altough they actually are the same place in the physical memory.
if I have understand everything ok why can't I remove the line where I map the first 4mb and leave that part unmapped?
edit: or if I can what can't I do if I remove that line?
edit 2: I can access videomem at both 0xB8000 and 0xC00B8000 isn't that a result of the mapping above that these two vaddr points to the same paddr.