Page fault problem?

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
Whatever5k

Page fault problem?

Post by Whatever5k »

I'm about enabling paging in my Operating System...when enabling paging, I get the error "3rd (14) exception with no resolution" in Bochs. I have set up a page fault handler, that's why I cannot understand this error message. What does it mean?
I have set up a page directory, mapped the whole kernel virtual -> physical and loaded CR3 with the address of the page directory
any idea what might be wrong?
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Page fault problem?

Post by Pype.Clicker »

This is known as "triple fault".
this means you're having nested exception. At the 3rd exception, the CPU resets (or bochs complains).

Note that it is a problem only when 2nd (and 3rd) exceptions occur before the first instructio of the first handler can be executed (otherwise, you just have nested exceptions, not triple fault ...)

Your first exception is probably a page fault, and most likely either your IDT entry for that handler is not valid, or the page that holds that code is not valid either ...

you should check your page table entries again ... and remember CR3 will hold some *physical* address, therefore it is not affected by CS.base or whatever ...

- try to get BOCHS giving you CR2 and CR3 content
- try to see what dword is in memory at physical CR3|(CR2>>22) -- this is your PDE
- try to see what dword is in memory at (PDE&0xFFFFF000)|((CR2&0x003FF000)>>12) : this is your PTE
- check your PTE's frame is correct.

Note the mapping for your kernel before and after paging enable should either remain constant or you should relocate the code your kernel can call after paging is enabled (usually too tricky unless you enable paging in 2nd stage loader.)
Whatever5k

Re:Page fault problem?

Post by Whatever5k »

Hm, the PDE entry is correct, but PTE is not the same...

Code: Select all

void map_kregion(void)
{
int *pt;
...
pt = phys_alloc();
printf("pt = %i\n", pt);
...
for (...)
  pt[i] = addr;
  addr += PAGE_SIZE;
...
}
And after that, I print the dword at (PDE&0xFFFFF000)|((CR2&0x003FF000)>>12)

And it isn't the same...
any idea what might be not okay?
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Page fault problem?

Post by Pype.Clicker »

i don't see where you set the "present" bit to 1 in your code ...
Whatever5k

Re:Page fault problem?

Post by Whatever5k »

Oups...I wanted to say:

Code: Select all

...
for (...)
 pt[i] = addr | 3;
 addr += PAGE_SIZE;
...
Whatever5k

Re:Page fault problem?

Post by Whatever5k »

Are you sure that the memory address at
(PDE&0xFFFFF000)|((CR2&0x003FF000)>>12)
is the PTE? What is this supposed to mean? I don't have a common PTE, it depends on the address to be accessed? Or do you mean that's the PTE when a page fault occurs?
DarylD

Re:Page fault problem?

Post by DarylD »

No, Pype looks correct on that. Remember the PDE contains 1024 PT entries.

This little function will index the PDE to get the address of the relevant PTE.

Daryl.
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Page fault problem?

Post by Pype.Clicker »

oops... seems there is something wrong with my PDE address computation.

Code: Select all

    dword* pde = ((dword*) cr3)+(cr2>>22);
but don't forget that as CR3 is a dword* pointer, the effective value of PDE will be value_of_CR3 + (value_of_cr2 >>2)*4 ...


the physical address of the page table #i is stored in the #i th page directory entry (PDE).

Therefore, once you have the value of PDE, you just get the frame out of it (*pde & 0xFFFFF000), add the page table index from CR2 ((value_of_CR2 &0x003FF000) >>12) * 4 and you have the pointer for your Page Table Entry ...
Whatever5k

Re:Page fault problem?

Post by Whatever5k »

Alright, so now I have the PDE and PTE...but in how far does that help me...? I cannot see any bugs in my code as I just map 4MB of physical memory to virtual addresses, load CR3 with the page directory and enable paging...
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Page fault problem?

Post by Pype.Clicker »

abless wrote: Are you sure that the memory address at
(PDE&0xFFFFF000)|((CR2&0x003FF000)>>12)
is the PTE? What is this supposed to mean? I don't have a common PTE, it depends on the address to be accessed? Or do you mean that's the PTE when a page fault occurs?
yes. the CR2 register has the virtual address of the latest page fault that occured. You should check the entries you set up in your page table are correct and that the first entry of your page directory points towards it.

Your "mapregion" code seems correctly filling the page table, but i can't see any page-directory setup code ...

All in all, it could be easier if you posted your paging code ...
Whatever5k

Re:Page fault problem?

Post by Whatever5k »

All in all, it could be easier if you posted your paging code ...
Alright, here it is:

paging.c:

Code: Select all

#define PDIR_SELFMAPPING_ENTRY 1023

extern addr_t kernel_end; /* defined in linker script */
addr_t *pdir;

void init_paging(void)
{
???int i;
???
???pdir = (addr_t*) &kernel_end + 1; 
???
???/* set up the page directory entries */
???for (i = 0; i < 1024; i++) 
??????pdir[i] = PRIV_KERNEL | PRIV_RW;???/* since we set this to non-present, the address does not matter */

???/* use selfmapping: pdir can be handled as a seperate ptable */
???pdir[PDIR_SELFMAPPING_ENTRY] = (addr_t) pdir | PRIV_KERNEL | PRIV_RW | PRIV_PRES;???/* flags: present, supervisor level, read/write */ 

???/* only a page directory is set up
??? * next, phys_alloc will be initialized and then the
??? * kernel will be mapped
??? */
}
vmm.c

Code: Select all

void __map_kregion(void)
{
???addr_t *pt;
???unsigned int num_ptables;
???unsigned long addr = 0;
???int n = 0, i = 0;

???/* map kernel region to ensure that EIP will be mapped
??? * when paging is enabled
??? */
???num_ptables = (unsigned int) (PAGE_ALIGN((addr_t) &kernel_end) / 0x400000) + 1;
???while(num_ptables-- > 0) {
??????pt = phys_alloc();
??????if (pt == NULL)
?????????panic("Fatal: out of memory\n");
??????for (i = 0; i < 1024; i++) {
?????????pt[i] = addr | PRIV_KERNEL | PRIV_RW | PRIV_PRES;
?????????addr += PAGE_SIZE;
??????}
??????if (n != 1023)???/* don't overwrite selfmapping entry */
?????????pdir[n++] =  (addr_t) pt | 3;
???}
}
That's it...init_paging() is called before __map_kregion().
After that, I write pdir into CR3 and enable paging.
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Page fault problem?

Post by Pype.Clicker »

pdir = (addr_t*) &kernel_end + 1;

you should check that kernel_end + 1 is page-aligned ... and i doubt it is ...
Whatever5k

Re:Page fault problem?

Post by Whatever5k »

Ahh, that's right...I forgot to page-align pdir...well, now it seems to work quite nice...
Thanks very much, Pype...
Post Reply