cr2 shows wrong addr with page fault

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
goku420
Member
Member
Posts: 51
Joined: Wed Jul 10, 2013 9:11 am

cr2 shows wrong addr with page fault

Post by goku420 »

I've begun implementing paging and have the following characteristics:

- PMM uses bitmap allocator
- I have a higher half kernel; first four MB is identity mapped for kernel

Further I have the following algorithm for mapping a page:

- Get address to page directory
- Get free physical page for page table
- Create a new page directory entry with the physical page (index vaddr >> 22)
- Get address to page table (by OR'ing 0xFFC00000 with ((vaddr >> 22) << 12))
- Get free physical page for page table entry
- Create new page table entry (index vaddr >> 12) with the physical page
- Flush TLB wherever appropriate

This seems to work pretty well. Trying to modify a random address like 0x1234 page faults unless I map it first. However, I've run into a strange bug. Unless I add printf statements, my cr2 value shows ffc00004 (everytime); otherwise it shows the correct value. Example:

Code: Select all

    pmm.map(0x1234);
    *((int*) 0x1234) = 4;
    printf("test\n");
   
    pmm.map(0x2234);
    *((int*) 0x2234) = 6;
        
    pmm.map(0x12234);
    *((int*) 0x12234) = 8;

    *((int*) 0x11234) = 9; 
If I keep the printf, cr2 correctly shows 0x11234, otherwise it shows ffc00004.

The printf is from a third party library and it calls putc on my terminal object which is global, so it is strange that it "resolves" the problem. Any ideas?
LtG
Member
Member
Posts: 384
Joined: Thu Aug 13, 2015 4:57 pm

Re: cr2 shows wrong addr with page fault

Post by LtG »

What does pmm.map() do? Usually PMM (Physical MM) only provides physical frames (pages) and nothing more, the VMM (Virtual MM) does virtual memory management like modifying the page directory and tables.

In your code it seems you are first mapping the page and then using it, why is it causing a #PF at all? I guess pmm.map() does something else..

The code doesn't seem to refer to CR2 at all, so how do you know what the value of CR2 is? Given that you have a higher-half kernel, what's at 0xffc00004?

Finally, GDB is your friend, single stepping will likely show you the reason.
goku420
Member
Member
Posts: 51
Joined: Wed Jul 10, 2013 9:11 am

Re: cr2 shows wrong addr with page fault

Post by goku420 »

LtG wrote:What does pmm.map() do? Usually PMM (Physical MM) only provides physical frames (pages) and nothing more, the VMM (Virtual MM) does virtual memory management like modifying the page directory and tables.
In theory, yes. However I haven't factored it out yet so temporarily the code belongs to the PMM class.
In your code it seems you are first mapping the page and then using it, why is it causing a #PF at all? I guess pmm.map() does something else..
The page fault happens when I deliberately write to an address I haven't called map on.
The code doesn't seem to refer to CR2 at all, so how do you know what the value of CR2 is? Given that you have a higher-half kernel, what's at 0xffc00004?
I read CR2 in the page fault handler.
Finally, GDB is your friend, single stepping will likely show you the reason.
After some testing it seems the issue is that part of my code is being optimized out unless I have a visible side effect (like printf). Though I'm not 100%
certain.

EDIT: That was indeed the issue. An objdump shows that this block of code is missing with optimizations turned on.

Code: Select all

c0100935:	68 00 20 00 00       	push   0x2000
c010093a:	8d 85 5c b7 ff ff    	lea    eax,[ebp-0x48a4]
c0100940:	50                   	push   eax
c0100941:	e8 a0 22 00 00       	call   c0102be6 <_ZN3Pmm3mapEm>
Thanks for the help.
LtG
Member
Member
Posts: 384
Joined: Thu Aug 13, 2015 4:57 pm

Re: cr2 shows wrong addr with page fault

Post by LtG »

The code you quoted has no comments so I can only guess what happens with it, and there's no info on your #PF handler, etc.. so there's not much we can comment on..

As for optimizing compilation, yes, so long as there's no side effect (impact) the compiler can do what ever it wants. It doesn't even have to be "visible". You can generally use volatile to override that, for example:

Code: Select all

volatile int* foo = (int*) 0x1234;
(*foo) = 0xf001234;
Also you could disable optimizations and see how that impacts things.
Post Reply