Page allocation not quite working

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
Andrew275

Page allocation not quite working

Post 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.
kytf

Re:Page allocation not quite working

Post by kytf »

unsigned long* p = (unsigned long*)0x700000;
*p = 5;
*p = 7;
Integer x(*p);
console.WriteLine(x); //prints ?
Andrew275

Re:Page allocation not quite working

Post 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.
rsy6j

Re:Page allocation not quite working

Post by rsy6j »

if (!pageDir.GetPageTable(address))
{
PageTable pageTable;
pageTable.SetEntry(address, (unsigned long*)Physical::AllocatePage());
pageDir.SetPageTable(address, pageTable.GetAddress());
PageFault(error); //muahaha..
}
fdyj

Re:Page allocation not quite working

Post 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
xfsyn

Re:Page allocation not quite working

Post by xfsyn »

confused :(

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

Re:Page allocation not quite working

Post 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);
}
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 allocation not quite working

Post 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 ...
kuyf

Re:Page allocation not quite working

Post by kuyf »

so, who calls isr14 ?
can you trace the system calls an assignment like *p=5 provokes ?
is there a debugger available ?)
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:Page allocation not quite working

Post 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?
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 allocation not quite working

Post by Pype.Clicker »

oops. sorry ... seems i was confused by the Trap/Interrupt gate stuff about IF handling ...
Andrew275

Re:Page allocation not quite working

Post by Andrew275 »

Thanks guys, I'll see what I can find out from Bochs.
Post Reply