I've been creeping on these forums since last summer. I've been reading all the tutorials I could find, mainly Bran's and JamesM's. I've gotten to the point where I'm looking to enable paging. I completely understand the very high level theory, but I'm not 100% on the nitty gritty implementation details. I'm a little hung up on some of the locations JamesM, out of the blue, decides to use for storing certain things with no explanation. I've read that his code on his personal website isn't maintained and might be buggy, so I've also been following the code he has on code.google.com. I've spent the past few days reading every thread that even mentions the word "paging" on this forum. I've been pouring over the wiki to no avail.
Now to the problem.
I successfully set up a GDT (with 3 values, null, a code, and a data segment; 0- 4GB limit, 4KB granularity), and IDT with working interrupt service routines and IRQs, the timer is set up.
I'm reading the multiboot memory map, but I'm not using it yet. I've been printing out all the addresses floating around and you may find them of use.
My kernel ends at address 0x00106CC8, so I allocate the first page directory at 0x00108000. The first page table follows at 0x00109000. The read/write and present flags are correctly set on those pages.
This is the paging enable code:
Code: Select all
int i;
unsigned int cr0;
install_interrupt_handler(14, &page_fault);
// Allocate a new frame for the page directory to sit in
unsigned int *pd = (unsigned int*)AllocateFrame(); // AllocateFrame() returns the next page aligned address that is free
// Clear it
memset_dw(pd, 0, 0x1000);
// Create the first page table entry to go in the new page directory
unsigned int *pt = (unsigned int*)AllocateFrame();
// Assign it to the page directory and set its flags
pd[0] = (unsigned int)pt | PAGE_PRESENT | PAGE_WRITE;
// Identity map the first 4MB of physical memory to it
for (i = 0; i < 1024; i++)
pt[i] = (i*0x1000) | PAGE_PRESENT | PAGE_WRITE;
SwitchPageDirectory(pd); // simply does - asm volatile("mov %0, %%cr3" : : "r" (pd));
// Enable paging
asm volatile ("mov %%cr0, %0" : "=r" (cr0));
cr0 |= 0x80000000;
asm volatile ("mov %0, %%cr0" : : "r" (cr0));
pagingActive = 1;
Code: Select all
// quick test of page fault handler
unsigned int *ptr = (unsigned int*)0xC0000000;
*ptr = 500;
Shouldn't it be throwing a page fault?
Furthermore even if I do this
Code: Select all
// quick test of page fault handler
unsigned int *ptr = (unsigned int*)0xC0000000;
unsigned int doPageFault = *ptr;
doPageFault++;
I am out of my league on this problem so far. I could imagine that maybe the page_fault handler is somehow not paged in, so when it tries to execute that code it throws the GPF, but my IDT is identity mapped in, and also if I simply change the int from 14 to 13 in the install_interrupt_handler routine, it runs my page_fault handler just fine for the GPF.
Please, someone just tell me I'm doing something obviously retarded so I can facepalm and keep going.
Thanks.