Page 1 of 1

Paging Enabled... Where's the Page Fault?

Posted: Sun May 18, 2008 8:48 pm
by dega512
I've been trying to get paging to work for weeks now with no luck (triple fault after triple fault); after getting incredibly frustrated I finally decided to write some "simple" code to enable paging and identity map the first 4MB of memory to practice the theory and process behind enabling paging. After completing my little practice assignment I didn't get any triple faults, but my code to invoke a page fault well, just doesn't invoke a page fault. Here is my code:

Code: Select all

printf("Setting up paging.\n");

// typedef unsigned int u32;
// void *kpmalloc(u32 size, bool pageAligned);  // (placement malloc)
u32 **dir = (u32 **)kpmalloc(4096, TRUE);
u32 *table = (u32 *)kpmalloc(4096, TRUE);

memset(dir, 0, 4096);
memset(table, 0, 4096);

/* identity map the first 4MB of memory */

u32 i = 0;  // current page descriptor within the table
u32 addr = 0;  // current address
while (i < 1024)
{
    table[i] = addr | 3;  // RW + Supervisor + Present
    addr += 4096;
    i++;
}

// the first entry in the descriptor describes the virtual address for 0MB-4MB,
// so this is where our table must go
dir[0] = (u32 *)((u32)table | 3); // RW + Supervisor + Present

// put the page directory in cr3
asm volatile("mov %0, %%cr3":: "r"(dir));

// enable the paging bit in cr0
u32 cr0;
asm volatile("mov %%cr0, %0": "=r"(cr0));
cr0 |= 0x80000000; // Enable paging!
asm volatile("mov %0, %%cr0":: "r"(cr0));

// since we identity mapped the first 4 MB of memory,
// dereferencing a pointer pointing to the end of the first
// 5MB should invoke a page fault...
u32 fault = *(u32 *)(5 * 1024 * 1024);

printf("Test done...\n");
My output is simply:
Setting up paging.
Test done...
Something must be wrong with my theory and/or process, because my IDT #14 handler just isn't being called. I know the problem that I'm experiencing can't be that a page fault is occurring and my IDT handler isn't setup properly to handle it because the following code invokes my handler no problem.

Code: Select all

// test the page fault handler
asm volatile("int $14");
Any ideas as to where I screwed up or suggestions on more places to search would be greatly appreciated!

Thanks!

P.S. I'm using QEMU for emulation, but I highly doubt QEMU is behind my problem.

Posted: Mon May 19, 2008 1:34 am
by JamesM
Hi,

Code: Select all

// since we identity mapped the first 4 MB of memory,
// dereferencing a pointer pointing to the end of the first
// 5MB should invoke a page fault...
u32 fault = *(u32 *)(5 * 1024 * 1024); 
Your compiler will remove this statement. The return value is not used anywhere, so it is not needed, technically.

To stop it getting removed, either mark your 'fault' variable as volatile, or (better), do a write to memory instead of a read. The compiler can't optimise out a write.

Cheers,

James

Posted: Mon May 19, 2008 7:56 am
by dega512
Hey it worked! I forgot I had the optimize option turned on :shock: .

Thanks a ton!