Page 1 of 1

[Solved] #PF in sheduler

Posted: Tue Oct 30, 2012 6:18 am
by Sin
Hello

First, sorry for my bad english, I'm french '^^
I'm working on a simple multi-tasks try.
I think I have miss something, but what ...
The kernel said me "Page Fault" on an existing virtual address (0xE0000FEC).
0xE0000000 is the esp register of the current task.
What's my mistake ?

I include the source code in zip file, so, thx in advance for your help (the load task file is processes.cpp).

Re: #PF in sheduler

Posted: Tue Oct 30, 2012 7:34 am
by Combuster
If you have a proper pagefault handler, you will have the EIP of the fault, and with that you can get the specific line of code causing it.

Which line is that?

Re: #PF in sheduler

Posted: Tue Oct 30, 2012 7:53 am
by Sin
eip is 0x40000000, which correspond theorically at the first line of the function copied in memory (I decided to copy the function at this virtual address).
This is the test function:

Code: Select all

void task1()
{
	char *msg = (char *) 0x40001000;

	msg[0] = 'T';
	msg[1] = 'a';
	msg[2] = 's';
	msg[3] = 'k';
	msg[4] = '1';
	msg[5] = '\n';
	msg[6] = 0x00;

	while (true)
 	{
		asm("mov %0, %%ebx; mov $0x01, %%eax; int $0x30":: "m"(msg));
		for (int i = 0; i < 1000000; i++);  //  Wait a while
	}

	return;			/* Never go there */
}
Edit: I checked the error code returned by the Page Fault, it is 0x07. So, the fault occurs when the page is present but has a protection violation. What I miss in my code ?

Edit2: I think the problem is in that piece of code, which load a user task, but where ?

Code: Select all

namespace Processes
{
  struct Process List[128];
  struct Process* Current = 0;
  s32 Count = 0;

  s32 LoadTask(s8* function, u32 size)
  {
    int PID = 1;

    while(List[PID].State != 0 && PID < 128)
      PID++;

    if (List[PID].State != 0)
    {
      BootProcess::Screen::Print((s8*)"\r\nPANIC: Not enough slot for process.\r\n");
      return 0;
    }

    VirtualMemoryManager::PageDirectory* pageDirectory = VirtualMemoryManager::NewPageDirectory(1);
    VirtualMemoryManager::InitUserPageDirectory(pageDirectory);

    VirtualMemoryManager::PageTable* pageTable = VirtualMemoryManager::NewPageTable(1);
    VirtualMemoryManager::AddPageTable(pageDirectory, pageTable, 0x40000000);

    u32 i = 0;
    u32 indexPageTable = 0;
    while(i < size)
    {
      u32 virtualAddress = 0x40000000 + i;
      u32 physicalAddress = PhysicalMemoryManager::GetFirstPageFrameAvailable();
      PhysicalMemoryManager::SetPageFrameUsed(physicalAddress);
      VirtualMemoryManager::AddPhysicalAddress(pageTable, virtualAddress, physicalAddress);

      Lib::MemoryCopy(function, (s8*)physicalAddress, i, 4096);

      indexPageTable++;      
      i += 4096;
    }

    //  User stack
    VirtualMemoryManager::PageTable* userStackPageTable = VirtualMemoryManager::NewPageTable(1);
    VirtualMemoryManager::AddPageTable(pageDirectory, pageTable, 0xE0000000);
    u32 physicalAddress2 = PhysicalMemoryManager::GetFirstPageFrameAvailable();
    PhysicalMemoryManager::SetPageFrameUsed(physicalAddress2);
    VirtualMemoryManager::AddPhysicalAddress(userStackPageTable, 0xE0000000, physicalAddress2);

    //  Kernel stack
    u32 physicalAddressKernelStack = PhysicalMemoryManager::GetFirstPageFrameAvailable();
    PhysicalMemoryManager::SetPageFrameUsed(physicalAddressKernelStack);

    Count++;

    List[PID].ID = PID;

    List[PID].Registers.ss = 0x33;
    List[PID].Registers.esp = 0xE0000000 + 4096 - 16;
    List[PID].Registers.eflags = 0x00;
    List[PID].Registers.cs = 0x23;
    List[PID].Registers.eip = 0x40000000;
    List[PID].Registers.ds = 0x2B;
    List[PID].Registers.es = 0x2B;
    List[PID].Registers.fs = 0x2B;
    List[PID].Registers.gs = 0x2B;

    List[PID].Registers.cr3 = (u32)pageDirectory;

    List[PID].KernelStack.ss0 = 0x18;
    List[PID].KernelStack.esp0 = physicalAddressKernelStack + 4096 - 16;  //  Current

    List[PID].Registers.eax = 0;
    List[PID].Registers.ecx = 0;
    List[PID].Registers.edx = 0;
    List[PID].Registers.ebx = 0;

    List[PID].Registers.ebp = 0;
    List[PID].Registers.esi = 0;
    List[PID].Registers.edi = 0;

    List[PID].PageDirectory = pageDirectory;

    List[PID].State = 1;

    return PID;
  }
}

Re: #PF in sheduler

Posted: Mon Nov 05, 2012 1:24 am
by Sin
Does anyone there's a little help please?

Re: #PF in sheduler

Posted: Mon Nov 05, 2012 1:34 am
by bluemoon
Check if the page directory entry has writable bit set (and all level of entries, not just PTE)

And what's the fault address CR2? is it on data you attempt to write ( 0x40001000 ) or on the stack ?
Edit2: I think the problem is in that piece of code, which load a user task, but where ?
Not likely, and error code 7 indicate the exception occur in user mode.

Re: #PF in sheduler

Posted: Mon Nov 05, 2012 2:17 am
by Sin
Thanks you Bluemoon, it was the ReadWrite bit set to 0 (stupid me).
I change this to 1, and rocks now!