Page 1 of 1

Error enabling paging?

Posted: Wed Nov 07, 2007 12:02 am
by shiz98
Hi guys,

I've been trying to get paging working, but I haven't had much success. I've got a working physical page (de)allocator, and everything seems to be fine up to setting CR0. I haven't been able to figure out what I've been doing wrong from the tutorials I've read. I'd be much obliged if someone could point me in the right direction. Here's the pertinent code:

This assembly code is pretty straight forward - SetPageDirectory works fine, but EnablePaging fails at mov cr0, eax. I haven't tested DisablePaging.

Code: Select all

global _SetPageDirectory
_SetPageDirectory:
    push ebp ;stack stuff
    mov ebp, esp
    mov eax, [ebp + 8] ;"pop" the directory
    and eax, 0xFFFFF000
    mov cr3, eax
    pop ebp
    ret
global _EnablePaging
_EnablePaging:
    mov eax, cr0
    or eax, 0x80000000
    mov cr0, eax
    ret
global _DisablePaging
_DisablePaging:
    mov eax, cr0
    and eax, 0x7FFFFFFF
    mov cr0, eax
    ret
Here's the code that calls enable paging:

Code: Select all

    KernelPageDirectoryAddress = AllocatePage();
    memset(KernelPageDirectoryAddress, 0, 4096); //clear the page directory
    KernelPageDirectoryAddress[1023] = ((unsigned int)KernelPageDirectoryAddress & 0xFFFFF000) | 0x3; //maps the page directory's last entries into itself
    //map the pages we've claimed
    PrintString("\nMapping Pages");
    MapPages(0xC0000000, 0x100000, kernelPages); //map our kernel to its virtual location
    MapPages(0xD0000000, 0x100000 + kernelPages * 4096, kernelHeapPages); //map the currently used heap pages
    
    SetPageDirectory(KernelPageDirectoryAddress);
    EnablePaging(); //problem here
There's not much to this either - MapPages maps continuous sets of pages, but isn't implemented yet. In fact, the only mapping that gets done is to map the page directory into itself. I don't think that would prevent me from enabling paging.

I haven't yet written an interrupt handler - I want to get some memory management done first - so I can't get details on the failure. Any help would be greatly appreciated!

Posted: Wed Nov 07, 2007 5:31 am
by JamesM
Unfortunately I would have to say that being unable to get information on the failure (GPF? Page fault?) really limits your (and our) debugging ability. I would hack up a quick IDT and use that.

Posted: Wed Nov 07, 2007 11:56 am
by shiz98
Yeah, I thought I might have to. Just wanted to make sure I wasn't making an obvious mistake.

I'll throw an IDT together and post the results.

Posted: Wed Nov 07, 2007 2:51 pm
by shiz98
Alright, I've written up a simple IDT that deals with interrupts 0-31. I tested it with a division by zero, and it seems to work. Unfortunately, it doesn't do me any good in debugging this problem: virtual pc just tells me that an unrecoverable processor error has occurred and shuts itself down.

So what do I do now? I'm going to download bochs and see if it gives me any more information, but I doubt it'll help much.

Here's how my kernel initializes itself, in case it helps:
Sets up basic GDT (code, data covering entire address range)
Clears the screen
Initializes the physical memory manager
Sets up interrupts
Initializes virtual memory (problem is here)

Posted: Wed Nov 07, 2007 3:34 pm
by JoeKayzA
Just a wild guess, but where is your stack located? Are you sure it is mapped after you enable paging? When the stack is unreachable, you won't even receive a pagefault (immediate triple fault instead).

cheers
Joe

Posted: Wed Nov 07, 2007 3:55 pm
by frank
You have to map in the pages where the kernel is located at. I see that you are mapping the kernel to 0xC0000000 but you also say in your post that MapPages isn't implemented yet. Without mapping in the kernel how is the processor supposed to find the it to run it?

Posted: Wed Nov 07, 2007 3:55 pm
by shiz98
Hmm. Right now I haven't mapped anything to virtual memory(haven't yet implemented the needed functions). I didn't think this would cause a problem yet, because I just have an endless loop after enabling paging.

I had also completely forgotten about the stack (not a good idea, it seems). Do ebp and esp point to physical or virtual addresses?

Looking at the bochs output, the code that deals with CR0 and CR3 works correctly, so the problem lies with my understanding :). I'm getting a page not present, then triple fault. I wonder why my IDT isn't picking that up. Maybe it's related to the stack...

Posted: Wed Nov 07, 2007 4:01 pm
by shiz98
Thanks frank, that didn't even occur to me until you pointed it out. Looks like mapping some pages would be a really good idea. I guess while I was debugging I found that disabling that mov cr0, eax call made everything work, and naturally concluded that the problem lies there. Didn't even occur to me that not enabling paging might avoid the problem... I should stop debugging so late at night.

Thanks for the help guys - I'm going to write my mapping functions and see if I can get things working. I'll let you know if I do.

On final question though. Once I start using virtual memory, are ALL addresses mapped, save the one in CR3? The addresses of the IDT and GDT, for example.

Posted: Tue Nov 20, 2007 12:54 am
by shiz98
*Bump*

Alright, so a couple of weeks later, I've finally gotten around to implementing those paging functions... Still not working though.

I've managed to hone my bochs skills now, and here's what I've found:

My page directory and entries are all set up fine. CR3 points to the right location.

The exact instruction that the EnablePaging function fails on is mov cr0, eax - I'm sure of it this time :P

As soon as I attempt to execute that line, bochs gives me a ??? (Physical Address Not Available) error. At the time of this error, the paging bit in CR0 is actually set; I can even look at my stack, which is now mapped into virtual memory, through bochs' memory viewer.

Any ideas on this?

Posted: Tue Nov 20, 2007 1:44 am
by Combuster
you probably forgot to identity map the currently executing code.