Page 1 of 1
Where to place page tables, directories, etc
Posted: Mon Jan 05, 2009 4:34 pm
by samoz
Hey guys, I'm working on implementing paging and had a question. Where do I actually place the page tables and directories?
I've seen some tutorials that place it in the lower memory, but I can't really figure out why (other than random choice). Should it be in lower as opposed to higher memory? I looked at the x86 memory map on the wiki and saw that there is space in lower memory, but only if the ram is available. How do I check this if I'm using GRUB as my boot loader? I've tried reading data out of the multiboot header, but it gives me garbage.
Also, when first starting paging, does some virtual space HAVE to be mapped to identical physical space so that the computer can still keep running it self properly? i.e Do I have to be under 1 MB?
Thanks guys!
Re: Where to place page tables, directories, etc
Posted: Mon Jan 05, 2009 5:25 pm
by gzaloprgm
To know the memory map using grub (to avoid placing something in a unavailable address), I suggest you to read
http://wiki.osdev.org/How_Do_I_Determin ... p_Via_GRUB
Yes, the GDT must be present if you are working in protected mode and the IDT and ISRs if you wanna use interrupts. And of course, the code after setting paging must be mapped correctly.
Cheers,
Gonzalo
Re: Where to place page tables, directories, etc
Posted: Mon Jan 05, 2009 5:43 pm
by neon
Hey guys, I'm working on implementing paging and had a question. Where do I actually place the page tables and directories?
They can be placed anywhere in physical memory (However page tables must be aligned at 4K addresses. This does not apply to page directories though but may be a small performance hit if it is not.) I recommend storing it above 1MB though in physical memory and mapping the physical location to a virtual address somewhere in the high memory area in kernel land.
Also, when first starting paging, does some virtual space HAVE to be mapped to identical physical space so that the computer can still keep running it self properly? i.e Do I have to be under 1 MB?
Yes. The reason is because the format of your physical addresses are treated very different when paging is enabled. More specifically, as soon as paging is enabled, all addresses become virtual and are treated as such. This is guaranteed to #GPF as none of the page tables refer to valid physical addresses yet.
Re: Where to place page tables, directories, etc
Posted: Mon Jan 05, 2009 6:20 pm
by samoz
Thanks neon, that helped!
However, I'm still a little confused. In the first part you recommend putting everything above 1MB, yet in the 2nd part you recommend putting stuff under 1 MB. I'm probably not reading it right, can you clarify some?
Also, I don't understand this part:
I recommend storing it above 1MB though in physical memory and mapping the physical location to a virtual address somewhere in the high memory area in kernel land
Is this referring to storing the directories or the tables or both above the 1 MB part?
Re: Where to place page tables, directories, etc
Posted: Mon Jan 05, 2009 6:26 pm
by neon
However, I'm still a little confused. In the first part you recommend putting everything above 1MB, yet in the 2nd part you recommend putting stuff under 1 MB. I'm probably not reading it right, can you clarify some?
Perhaps I didnt word it right. I recommend storing it above 1MB physical memory.
Is this referring to storing the directories or the tables or both above the 1 MB part?
Both.
I try not putting anything below 1MB as that can be used for real mode programs and data. I personally map my kernel to 2GB virtual address and store my memory management tables above 2GB in kernel land so no user mode app can touch them in any way. The physical address that this virtual address refers to can be anything, but do recommend above the kernel over the 1MB physical address mark.
Keep in mind that this is only opinion
Re: Where to place page tables, directories, etc
Posted: Tue Jan 06, 2009 2:43 am
by AJ
Here's another opinion
When I go to PMode, my page frame allocator is one of the first things that goes online. I do not plan to use any real mode code at all and have a 32/64 bit kernel.
Page directories and page tables are allocated just as any other memory - there is no special case. Because I do not use legacy ISA DMA, I do not need to keep any memory under 1MiB especially for this. I use a stack page frame allocator and build the stack from the base of memory upwards. For this reason, chances are that pages used for the initial page directory and page tables will come from high memory somewhere.
As for identity mapping - the code you are currently running needs to be identity mapped (and stack, and the data), but remember that CR3, PDE's and PTE's always refer to physical addresses. I generally map the PD and PT's (and in 64 bit mode PDPT and PML4) in to a contiguous range in the high virtual address range (above my kernel). If you have a lower-half kernel, you may want to consider something different!
Cheers,
Adam
Re: Where to place page tables, directories, etc
Posted: Wed Jan 07, 2009 12:10 pm
by samoz
Hey guys, so I've been working on my paging implementation and I'm having some trouble again.
So far, I've allocated 512 page tables, 1024 4kb pages each inside of 1 page directory. As such, shouldn't I be able to be able to access any address up to 2gb? However, the way things are now, my OS page faults when I access an address past 0x1FFFF000 (512mb-4kb).
Additionally, my code is very slow, due to the massive for loop in the code. Can anyone suggest ways to improve this?
Below is my code, can someone give me some pointers as to what I'm doing wrong? Thanks!
Code: Select all
// give kmalloc a starting point
placementAddress = (unsigned int)&end; // defined in linker script
placementAddress &= 0xFFFFF000; // align it on 4kb
placementAddress += 0x1000;
unsigned long* kernelDirectory = (unsigned long*)kmalloc_a(sizeof(unsigned long) * 1024); // array of tables - 1024 tables, 4 kb
memset((unsigned char*)kernelDirectory, 0, sizeof(unsigned long)*1024);
unsigned long* kernelTables = (unsigned long*)kmalloc_a(sizeof(unsigned long) * 1024 * 512); // 0x8000; // array of pages - 512 pages per table, 512kb
memset((unsigned char*)kernelTables, 0, sizeof(unsigned long)*1024*1024);
unsigned long physicalAddress = 0x0;
unsigned int i;
for(i=0; i<1024*512-1; i++) // 512b * 1kb = 512 kb
{
kernelTables[i] = (physicalAddress) | 3;
physicalAddress = physicalAddress + 4096;
if(physicalAddress <= 0)
{
monitorWriteUDec(i);
PANIC("OVERFLOW!");
}
}
monitorWriteUHex(physicalAddress);
// for the kernel directory, we have 512 tables * 1024 pages each = 2G available space
// this means we need 512KB to store the directory
// we need to put 2G into low space for the kernel
for(i=0; i<512; i++)
{
kernelDirectory[i] = (unsigned long)(kernelTables + i * 1024 * sizeof(unsigned long));
kernelDirectory[i] = kernelDirectory[i] | 3;
}
for(i=512; i<1024; i++)
{
kernelDirectory[i] = 0 | 2; // not present, rw, supervisor
}
// now actually enable the paging code
write_cr3((unsigned long)kernelDirectory); // put that page directory address into CR3
write_cr0(read_cr0() | 0x80000000); // set the paging bit in CR0 to 1
// set up page fault interrupts
register_interrupt_handler(14, page_fault);
}
Re: Where to place page tables, directories, etc
Posted: Wed Jan 07, 2009 3:38 pm
by carbonBased
This may, or may not, be useful to you, but I always found it useful to hex dump my page directory, and all defined page tables inside my core exception handlers (at least the ones which can't be handled, and kill the system).
From there, you have a good set of info to debug paging problems. It's tedious, but you get better at it, the more you do it.
Your performance can be improved by only mapping pages as required. Don't map everything at once; map what you need, and incrementally map as requested.
--Jeff