Page 1 of 1
Page fault problem?
Posted: Wed Feb 05, 2003 8:25 am
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?
Re:Page fault problem?
Posted: Wed Feb 05, 2003 8:38 am
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.)
Re:Page fault problem?
Posted: Wed Feb 05, 2003 10:50 am
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?
Re:Page fault problem?
Posted: Thu Feb 06, 2003 3:11 am
by Pype.Clicker
i don't see where you set the "present" bit to 1 in your code ...
Re:Page fault problem?
Posted: Thu Feb 06, 2003 7:31 am
by Whatever5k
Oups...I wanted to say:
Code: Select all
...
for (...)
pt[i] = addr | 3;
addr += PAGE_SIZE;
...
Re:Page fault problem?
Posted: Fri Feb 07, 2003 9:01 am
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?
Re:Page fault problem?
Posted: Fri Feb 07, 2003 9:48 am
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.
Re:Page fault problem?
Posted: Fri Feb 07, 2003 10:01 am
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 ...
Re:Page fault problem?
Posted: Fri Feb 07, 2003 10:51 am
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...
Re:Page fault problem?
Posted: Sat Feb 08, 2003 6:46 am
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 ...
Re:Page fault problem?
Posted: Sat Feb 08, 2003 7:29 am
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.
Re:Page fault problem?
Posted: Sat Feb 08, 2003 5:58 pm
by Pype.Clicker
pdir = (addr_t*) &kernel_end + 1;
you should check that kernel_end + 1 is page-aligned ... and i doubt it is ...
Re:Page fault problem?
Posted: Sun Feb 09, 2003 6:49 am
by Whatever5k
Ahh, that's right...I forgot to page-align pdir...well, now it seems to work quite nice...
Thanks very much, Pype...