Page 1 of 1
paging fault problem
Posted: Tue Jan 08, 2008 2:18 pm
by kiwipresse
Hi,
after setting up paging correctly I now wan't to get ride of 1:1 paging and only want to use virtual addresses (Except someone can persuade me not to do it for various reasons).
My problem: I want to disable identity paging explicitly by using pd[0] = 0. This actually works and qemu reports that the specific memory region isn't mapped anymore. However, when I disable 1:1 paging page faults occur.
cr2 has an address of an unmapped location (0x001041b3) but I don't know exactly where this come from. I suppose that my interrupt system is to blame for this since:
my interrupt handler has an argument which holds a pointer to the current stackframe. When I don't disable 1:1 paging I saw that this pointer points to an unmapped memory location (always) near the location which is saved in cr2. adding 0xC0000000 to the pointer doesn't help...
Any hints?
Posted: Tue Jan 08, 2008 5:17 pm
by Combuster
did you change the location of your stack after entering the higher half?
Posted: Tue Jan 08, 2008 11:04 pm
by deadmutex
Maybe your GDTR or IDTR are still pointing to unmapped addresses? If so, then you would need to do a new "lgdt" or "lidt".
Posted: Wed Jan 09, 2008 1:58 am
by xyzzy
Is your kernel actually linked to run at the virtual location you want it to run at? See this page:
http://www.osdev.org/wiki/Higher_Half_bare_bones
Posted: Thu Jan 10, 2008 9:49 am
by kiwipresse
@combuster: No I didn't! Can I do this simply by adding 0xC0000000 to %esp or do I have to take care of some x86 specific thing? I ask because if I just add this value to %esp the paging fault still occur.
@deadmutex: hmm I printed out the addresses of my idt and gdt arrays and saw that their address is much beyond the 0xC0000000 base. Too much if you ask me (it's actually in the 0xD******* region). nm said that they are here:
Thus I'm somewhat confused whether it points to the right position since interrupts do occure rightly...
@AlexExtreme: Yes the kernel which should run in the higher half is linked as an higher half kernel
Posted: Thu Jan 10, 2008 11:43 am
by Combuster
I think that you forgot to flush the TLBs after changing the paging structures. The "random" address you encounter is the first one to be flushed and then accessed.
You should at least do the following things:
- reload CR3 with its current value to force a complete flush. This will probably make the page fault happen sooner, but you will at least know for sure that this address is the first one to be accessed.
- make indeed sure the stack is located in the higher half. Adding 0xC0000000 should do the trick. It will fix at least one potential source of page faults. The reason why this isn't currently causing pagefaults is mentioned above.
- add 0xC0000000 to the page fault address, then use objdump to find what's actually located at that address. If you know what's being accessed you might get a clue about what would be accessing it.
Posted: Sat Jan 12, 2008 6:41 am
by kiwipresse
Hmm I have reloaded CR3 with the old value of CR3 but nothing changed.
The virtual addresses of idt and gdt are still strange:
Code: Select all
gdt[0] is at 0xd1218000
idt[0] is at 0xd1219140
but in objdump/nm they are at
Why they are about 10000000 bytes beyond the addresses objdump/nm showed?
Posted: Sat Jan 12, 2008 6:57 pm
by fontknocker
kiwipresse wrote:Why they are about 10000000 bytes beyond the addresses objdump/nm showed?
Do those addresses change depending on when you print them? What's your code for printing those addresses? Also, I realise it's probably a dumb question, but are you certain your printf() function works correctly?
Posted: Mon Jan 14, 2008 1:38 pm
by kiwipresse
Hmm it seems that there are some bugs in my vsnprintf code - I'll try to fix them soon. Hence, to be sure fire that printk isn't responsible for any paging faults I removed all printk instructions, however, paging fault still occure so I suppose that there is something else to blame for this
BTW I also saved the addresses of gdt and idt in registers and saw that they are actually pointing to the higher half.
Re: paging fault problem
Posted: Sun Mar 16, 2008 9:20 pm
by thomasloven
kiwipresse wrote:
my interrupt handler has an argument which holds a pointer to the current stackframe. When I don't disable 1:1 paging I saw that this pointer points to an unmapped memory location (always) near the location which is saved in cr2. adding 0xC0000000 to the pointer doesn't help...
I have the same problem.
Pointers doesn't realy work as I believe they should after enabling paging.
I am using the code from the Higher Half Barebones tutorial from the wiki and the problems apear when I'm trying to remove the identity maped paging.
For example: I have a page directory set up at say 0x10000 in physical address space. When the paging is setup, I can access this from 0xC0010000, but my old pointer (pointing to 0x10000) is now useless.
The natural thing here would be to do page_directoy_pointer += 0xC0000000; , right?
The thing is, this doesn't work. It still points to 0x10000. Adding any other number works (except multiples of 0xC0000000).
I.E. if I do page_directory_pointer += 0xB0000000; it will point to 0xB0010000. But if I then do page_directory_pointer += 0x10000000, it goes back to pointing to 0x10000.
How would I go to redirect my pointers? Or is there a way this could be automated? Some kind of reverse GDT-trick (all my bases are 0)?
I'd be the first one to admit I know nothing about linkers, so I pretty much have no idea what's going on here, and why.
Thanks in advance.
Oh, and sorry about the pretty long bump, but I didn't realy think it necessary to start a new topic about this.
/Thomas
Posted: Mon Mar 17, 2008 2:52 am
by Combuster
If you'd know your pointer math, you'd know adding to a pointer would increment that pointer by a multiple thereof.
Code: Select all
int* p = (int*) 0x100000;
// p -> 1MB
p += 0xC0000000;
// p -> p + sizeof(int) * 0xC0000000 = 0x3 0010 0000
// p -> 1MB (due to 32-bit overflow)
p = (int*) (((int)p) + 0xC0000000);
// p -> 0xC0100000
Posted: Mon Mar 17, 2008 9:16 am
by thomasloven
I actualy realized that in the shower this morning...
I guess studying multiple variable mathematical analysis for a year make you forget the simple things..
Thanks a lot.