paging fault problem
-
- Member
- Posts: 25
- Joined: Sun Nov 04, 2007 7:41 am
paging fault problem
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?
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?
-
- Member
- Posts: 391
- Joined: Wed Jul 25, 2007 8:45 am
- Libera.chat IRC: aejsmith
- Location: London, UK
- Contact:
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
-
- Member
- Posts: 25
- Joined: Sun Nov 04, 2007 7:41 am
@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
@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:
Code: Select all
c0108000 B gdt
c0108040 B idt
@AlexExtreme: Yes the kernel which should run in the higher half is linked as an higher half kernel
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
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.
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.
-
- Member
- Posts: 25
- Joined: Sun Nov 04, 2007 7:41 am
Hmm I have reloaded CR3 with the old value of CR3 but nothing changed.
The virtual addresses of idt and gdt are still strange:
but in objdump/nm they are at
Why they are about 10000000 bytes beyond the addresses objdump/nm showed?
The virtual addresses of idt and gdt are still strange:
Code: Select all
gdt[0] is at 0xd1218000
idt[0] is at 0xd1219140
Code: Select all
c0108000 B gdt
c0108040 B idt
- fontknocker
- Posts: 16
- Joined: Mon Dec 11, 2006 1:49 am
- Location: Canberra, Australia
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?kiwipresse wrote:Why they are about 10000000 bytes beyond the addresses objdump/nm showed?
-
- Member
- Posts: 25
- Joined: Sun Nov 04, 2007 7:41 am
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.
BTW I also saved the addresses of gdt and idt in registers and saw that they are actually pointing to the higher half.
-
- Member
- Posts: 89
- Joined: Tue Feb 26, 2008 10:47 am
- Location: Sweden
Re: paging fault problem
I have the same problem.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...
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
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
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
-
- Member
- Posts: 89
- Joined: Tue Feb 26, 2008 10:47 am
- Location: Sweden