Page 1 of 1

Page allocation not quite working

Posted: Sun Mar 07, 2004 4:42 pm
by Andrew275
I have a page fault handler set up that sets the necessary page directory and page table entry to an allocated physical page. It also invalidates the TLB. The problem I've having though, is if I set a pointer to a memory location, set the value, and then try to print the value, I get garbage. But if I set it twice, and then print the value, it works. I can't figure it out. Here's the code for the page fault handler:

Code: Select all

void Kernel::Memory::PageFault(unsigned int error)
{
   unsigned long* address = read_cr2();
   PageDirectory pageDir(read_cr3());
   if (!pageDir.GetPageTable(address))
   {
      PageTable pageTable;
      pageTable.SetEntry(address, (unsigned long*)Physical::AllocatePage());
      pageDir.SetPageTable(address, pageTable.GetAddress());
   }
   else
   {
      PageTable pageTable((unsigned long*)pageDir.GetPageTable(address));
      pageTable.SetEntry(address, (unsigned long*)Physical::AllocatePage());
   }
}
In my main function, if I try to do something like this, it works:

Code: Select all

unsigned long* p = (unsigned long*)0x700000;
   *p = 4;
   *p = 4;
   Integer x(*p);
   console.WriteLine(x); //prints 4
but if I do this, I get garbage:

Code: Select all

unsigned long* p = (unsigned long*)0x700000;
   *p = 4;
   Integer x(*p);
   console.WriteLine(x); //prints 41951232
Any help would be greatly appreciated.

Re:Page allocation not quite working

Posted: Sun Mar 07, 2004 11:38 pm
by kytf
unsigned long* p = (unsigned long*)0x700000;
*p = 5;
*p = 7;
Integer x(*p);
console.WriteLine(x); //prints ?

Re:Page allocation not quite working

Posted: Mon Mar 08, 2004 3:26 pm
by Andrew275
kytf wrote: unsigned long* p = (unsigned long*)0x700000;
*p = 5;
*p = 7;
Integer x(*p);
console.WriteLine(x); //prints ?
That prints 7. Also, doing something like this works fine:

Code: Select all

unsigned long* p = (unsigned long*)0x700000;
   *p = 5;
    p = (unsigned long*)0x700010;
   *p = 7;
   Integer x(*p);
   console.WriteLine(x); //prints 7
It seems that once the page is allocated, any future operation to that page works. But it's like the first write instruction isn't retried after the page fault.

Re:Page allocation not quite working

Posted: Mon Mar 08, 2004 6:07 pm
by rsy6j
if (!pageDir.GetPageTable(address))
{
PageTable pageTable;
pageTable.SetEntry(address, (unsigned long*)Physical::AllocatePage());
pageDir.SetPageTable(address, pageTable.GetAddress());
PageFault(error); //muahaha..
}

Re:Page allocation not quite working

Posted: Mon Mar 08, 2004 7:15 pm
by fdyj
hm...
perhaps the following command does not try to access the page, thus invoking the handler

unsigned long* p = (unsigned long*)0x700000;

you could have a look at the assembly, *.o i believe

what kind of handler is it anyway ? does it transfer pages between disks and ram, or from ram to caches ?

*p = 5;
*p = 7;

it would be strange if the last command invoked the handler, the page has already been transfered
when is the handler called ? to see whether there is a page fault, or to fix one ?

pageTable.SetEntry(address, (unsigned long*)Physical::AllocatePage());

if the above command suggests page transfer, why does it apear on both cases ?

who calls the handler ? (when ..)


for the time being, we can assume that
- the handler is only called in case of page fault
- assigning a value to a pointer does not attempt to access the corresponding page
- the error lies in the routine invoking the handler (after finding a page fault), that it returns immediately, without finishing the write operation

Re:Page allocation not quite working

Posted: Mon Mar 08, 2004 7:26 pm
by xfsyn
confused :(

why is there an if clause inside the handler ?
i hate tlbs .. (bet 2 cents SetPageTable() overwrites staff)

Re:Page allocation not quite working

Posted: Mon Mar 08, 2004 9:52 pm
by Andrew275
The PageFault function is only called when there is a page fault interrupt. By having the handler print a character to the console, I've seen that it is called for the first assignment (*p = 5), but not the second (*p = 7). This is, of course, what should be happening.

All the page fault handler does right now is allocate a physical memory page for a virtual address that is marked as not present.

The reason there is an if statement, is because I'm checking to see if there's a valid page directory entry for that 4 MB block. If not, I have to set that up, and also set up a page table entry for the 4 KB page. Otherwise, I can just set up a page table entry.

Here is the code for SetPageTable:

Code: Select all

void PageDirectory::SetPageTable(unsigned long* address, unsigned long* table, PermissionLevel perm, ReadWrite rw, IsPresent present)
{
   int p = (unsigned long)address / 4194304;
   pageDirectory[p] = (unsigned long)table;
   pageDirectory[p] |= perm | rw | present;
   write_cr3(read_cr3());
}
Also, I wonder if there is a problem with the assembly method that calls PageFault. Here is the code for that:

Code: Select all

isr14:
 pop eax
 pusha
 push gs
 push fs
 push ds
 push es
 push eax

 call isr_page_fault
 
 mov    eax, 0x20
 out    0x20, al
 
 pop eax
 pop es
 pop ds
 pop fs
 pop gs
 popa
 iret
That assembly method calls this:

Code: Select all

extern "C" void isr_page_fault(unsigned int error)
{
   Memory::PageFault(error);
}

Re:Page allocation not quite working

Posted: Tue Mar 09, 2004 1:14 am
by Pype.Clicker
Hmm ... I know there are faults and trap descriptors for the IDT. Faults will return to the faulty instruction while traps will return to the next one. Clearly, the PageFault should be handled by a Fault.

I don't know if this actually has an impact or if it's hardwired in the CPU nowadays, but the behaviour you explain suggests me the problems comes from the fact your PF handler is not a Fault Gate, but rather an Interrupt or Trap gate ...

Re:Page allocation not quite working

Posted: Tue Mar 09, 2004 7:50 am
by kuyf
so, who calls isr14 ?
can you trace the system calls an assignment like *p=5 provokes ?
is there a debugger available ?)

Re:Page allocation not quite working

Posted: Tue Mar 09, 2004 8:06 am
by Candy
Pype.Clicker wrote: Hmm ... I know there are faults and trap descriptors for the IDT. Faults will return to the faulty instruction while traps will return to the next one. Clearly, the PageFault should be handled by a Fault.
There are no fault descriptors. The EIP that's pushed depends on the exception, not on the IDT. It should return there and re-execute it. Might I suggest a bochs disassembly?

Re:Page allocation not quite working

Posted: Tue Mar 09, 2004 12:32 pm
by Pype.Clicker
oops. sorry ... seems i was confused by the Trap/Interrupt gate stuff about IF handling ...

Re:Page allocation not quite working

Posted: Tue Mar 09, 2004 3:35 pm
by Andrew275
Thanks guys, I'll see what I can find out from Bochs.