Where to place page tables, directories, etc

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
samoz
Member
Member
Posts: 59
Joined: Sun Jun 01, 2008 1:16 pm

Where to place page tables, directories, etc

Post 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!
Hexciting: An open source hex editor for the command line.
https://sourceforge.net/projects/hexciting/
User avatar
gzaloprgm
Member
Member
Posts: 141
Joined: Sun Sep 23, 2007 4:53 pm
Location: Buenos Aires, Argentina
Contact:

Re: Where to place page tables, directories, etc

Post 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
Last edited by gzaloprgm on Mon Jan 05, 2009 5:50 pm, edited 1 time in total.
Visit https://gzalo.com : my web site with electronic circuits, articles, schematics, pcb, calculators, and other things related to electronics.
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: Where to place page tables, directories, etc

Post 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.
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
User avatar
samoz
Member
Member
Posts: 59
Joined: Sun Jun 01, 2008 1:16 pm

Re: Where to place page tables, directories, etc

Post 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?
Hexciting: An open source hex editor for the command line.
https://sourceforge.net/projects/hexciting/
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: Where to place page tables, directories, etc

Post 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 ;)
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Re: Where to place page tables, directories, etc

Post 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
User avatar
samoz
Member
Member
Posts: 59
Joined: Sun Jun 01, 2008 1:16 pm

Re: Where to place page tables, directories, etc

Post 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);
}
Hexciting: An open source hex editor for the command line.
https://sourceforge.net/projects/hexciting/
User avatar
carbonBased
Member
Member
Posts: 382
Joined: Sat Nov 20, 2004 12:00 am
Location: Wellesley, Ontario, Canada
Contact:

Re: Where to place page tables, directories, etc

Post 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
Post Reply