Page 1 of 1

[Paging] How to figure out where to place pages in memory

Posted: Thu Dec 30, 2010 9:05 am
by padmalcom
Hi, I'm struggeling with paging atm and run into a GP fault when I try to enable it.
I figured out that the physical address of my pages is responsible for this fault (from my point of view).

So my question is: How do I find out where to place my pages in memory?

My solution would be:
- Get the address of the end section from the linker script! (As done in JamesM's tutorial)

This would be for me: 0x1068a0 hex -> 1075360 byte -> 1.02554 mega byte

So with 32mb of physical memory set in my VM there should be no problem mapping 4mb by my paging routine.

Funny thing: When I start creating my pages at 0b it works (works = I can set the cr3 to my page_directory address)
but when I start putting my pages 1075360b (behind the "end" from the linker script) I get a GP fault
when setting the paging bit to 1.

Any ideas why this happens or any hints I might not have considered?

Thanks in advance :)

My paging code so far:

Code: Select all

#include "system.h"

unsigned long *page_directory = (unsigned long *) 0x9C000;
unsigned long *page_table = (unsigned long *) 0x9D000; // the page table comes right after the page directory

extern u32int end;

unsigned long address=(u32int)&end; // holds the physical address of where a page is <- This address does not work
unsigned int i;

void startPaging() {

	putfs("Addresses will be placed at: %p\n",address);
	// map the first 4MB of memory
	for(i=0; i<1024; i++)
	{
	page_table[i] = address | 3; // attribute set to: supervisor level, read/write, present(011 in binary)
	address = address + 4096; // 4096 = 4kb
	};

	// fill the first entry of the page directory
	page_directory[0] = page_table; // attribute set to: supervisor level, read/write, present(011 in binary)
	page_directory[0] = page_directory[0] | 3;

	for(i=1; i<1024; i++)
	{
	page_directory[i] = 0 | 2; // attribute set to: supervisor level, read/write, not present(010 in binary)
	};

	irq_install_handler(14, page_fault);
	
	asm volatile("mov %0, %%cr3":: "r"(page_directory));
    unsigned long cr0;
    asm volatile("mov %%cr0, %0": "=r"(cr0));
    cr0 |= 0x80000000;
    //asm volatile("mov %0, %%cr0":: "r"(cr0));
}

Re: [Paging] How to figure out where to place pages in memor

Posted: Thu Dec 30, 2010 2:24 pm
by gerryg400
You need to round 'end' up to the nearest page boundary.

Re: [Paging] How to figure out where to place pages in memor

Posted: Thu Dec 30, 2010 2:25 pm
by azblue
My solution would be:
- Get the address of the end section from the linker script! (As done in JamesM's tutorial)

This would be for me: 0x1068a0 hex -> 1075360 byte -> 1.02554 mega byte
You pages need to be on 4KB or 4 MB boundaries.

Re: [Paging] How to figure out where to place pages in memor

Posted: Fri Dec 31, 2010 5:34 am
by padmalcom
Okay, I put the following code at the beginning of startPaging:

Code: Select all

void startPaging() {

	// Align start address
	if (address & 0xFFFFF000)
    {
        address &= 0xFFFFF000;
        address += 0x1000;
    }
    ...
}
I got it from JamesM's tutorial but it results in a GP fault, as well. Is this piece of code
sufficient to align my adress to 4 KB boundaries?

Re: [Paging] How to figure out where to place pages in memor

Posted: Fri Dec 31, 2010 9:47 am
by padmalcom
Hey guys, thanks for the reply.

This code should aling my adress to 4kb:

Code: Select all

if ((address % 4096) != 0) {	
    address += 4096 - (address % 4096);
}
As berkus pointed out correctly this is - sadly - not the solution to my GP fault.

Re: [Paging] How to figure out where to place pages in memor

Posted: Fri Dec 31, 2010 11:37 am
by Brendan
Hi,
padmalcom wrote:This code should aling my adress to 4kb:
It's probably easier/better to do it without a conditional branch:

Code: Select all

    address = (address + 0x00000FFF) & 0xFFFFF000;
Cheers,

Brendan

Re: [Paging] How to figure out where to place pages in memor

Posted: Sat Jan 01, 2011 11:08 am
by padmalcom
Hi Brendan, thanks, this is really nice code.

Unfortunately, I did not find a solution to my problem ("which memory can I use to put my pages on").

Re: [Paging] How to figure out where to place pages in memor

Posted: Fri Jan 07, 2011 10:56 am
by Jezze
I'm writing this from a phone so bare with me. If your ptables and pdirs are not dynamically allocated you can always use the aligned directive to automatically place your ptables and pdirectories on a correctly aligned address. Something like: struct page_directory {...} __attribute__ __aligned__((4096))); I'm not sure if that was correct but I hope the point came across.

Re: [Paging] How to figure out where to place pages in memor

Posted: Fri Jan 07, 2011 12:36 pm
by Tosi
You can place your page structures wherever you want, since it's your operating system.
Just make sure the address range you choose is usable RAM and is aligned on a page directory.
Whatever is causing a GPF might be somewhere else in the code.

Re: [Paging] How to figure out where to place pages in memor

Posted: Fri Jan 07, 2011 5:16 pm
by Dario
It would be nice to see your page structure. Also make sure that page directory/tables addresses are properly inserted into your page_dir/table structure(shift them right by 12 bits if necessary).
If you used bit fields to define your page structure, make sure that order of assignment are right.
Dump memory where these structures are located and check for their correctness.
I also have a short jump(jmp 1f) right after the enabling paging, although I don't think thats necessary.

EDIT: now I have actually red your code so you can ignore my post.

Re: [Paging] How to figure out where to place pages in memor

Posted: Sat Jan 29, 2011 5:08 am
by padmalcom
Hi, my page structure looks like:

Code: Select all

typedef struct page
{
    u32int present    : 1;   // Page present in memory
    u32int rw         : 1;   // Read-only if clear, readwrite if set
    u32int user       : 1;   // Supervisor level only if clear
    u32int accessed   : 1;   // Has the page been accessed since last refresh?
    u32int dirty      : 1;   // Has the page been written to since last refresh?
    u32int unused     : 7;   // Amalgamation of unused and reserved bits
    u32int frame      : 20;  // Frame address (shifted right 12 bits)
} page_t;
I did not make any progress with the chapter of JamesM about paging (I got my own paging
algorithm running but I cannot adopt it to the memory management of the following chapters
of JamesMs tutorial...).

So any help is still welcome!