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.