[Solved] #PF in sheduler

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
Sin
Posts: 4
Joined: Tue Oct 30, 2012 6:09 am

[Solved] #PF in sheduler

Post 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).
Attachments
HCAOS_Reboot_Clean.zip
Code source of the OS
(45.02 KiB) Downloaded 85 times
Last edited by Sin on Mon Nov 05, 2012 2:17 am, edited 1 time in total.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: #PF in sheduler

Post 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?
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
Sin
Posts: 4
Joined: Tue Oct 30, 2012 6:09 am

Re: #PF in sheduler

Post 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;
  }
}
Sin
Posts: 4
Joined: Tue Oct 30, 2012 6:09 am

Re: #PF in sheduler

Post by Sin »

Does anyone there's a little help please?
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: #PF in sheduler

Post 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.
Sin
Posts: 4
Joined: Tue Oct 30, 2012 6:09 am

Re: #PF in sheduler

Post by Sin »

Thanks you Bluemoon, it was the ReadWrite bit set to 0 (stupid me).
I change this to 1, and rocks now!
Post Reply