Page 1 of 1

Page fault on entering user mode

Posted: Sun Jun 16, 2013 2:54 am
by BMW
I am trying to enter user mode, but I get an unexpected page fault.

This is how I'm doing it:

Code: Select all

//setup TSS
	void* stack = kmalloc(1024);
	void* tss = kmalloc(104);
	*(uint32_t*)(tss+4) = (uint32_t)stack;
	*(uint32_t*)(tss+8) = 0x10; //kernel data descriptor
	
	gdt_set_entry(5, create_gdt_entry(104, (uint32_t)tss, 0x89, 0x4));
	load_gdt(6);
	__asm__ __volatile__("ltr %%ax" : : "a" (0x28));
	
	void* program = (void*)0x00000000;
	void* userstack = (void*)0xBFFFF000;
	
	if(!vmmngr_alloc_page((virtual_addr)program))
		PrintString("Fail\n");
	else
	{
		pt_entry_add_attrib(vmmngr_ptable_lookup_entry(get_ptable_address((virtual_addr)program), (virtual_addr)program), PTE_USER); //make it a user page
		
		if(!vmmngr_alloc_page((virtual_addr)userstack))
			PrintString("Failed to allocate stack.\n");
		else
		{
			pt_entry_add_attrib(vmmngr_ptable_lookup_entry(get_ptable_address((virtual_addr)userstack), (virtual_addr)userstack), PTE_USER); //make it a user page
		   vmmngr_flush_tlb_entry((virtual_addr)program);
	      vmmngr_flush_tlb_entry((virtual_addr)userstack);

			struct FileInfo fi;
		
			if(!GetFileInfo("test.bin", &fi, 0))
				PrintString("Failed to load file.");
			else
			{
				LoadFile("test.bin", program, 0);
            _enter_usermode();
			}
		}
	}
	

	
	
(I know the code's a bit messy but its just for testing purposes atm)

And this is the _enter_usermode() function (NASM)

Code: Select all

bits 32

global _enter_usermode

%define UserModeESP 0xC0000000

_enter_usermode:
	cli
	mov ax, 0x23 ;user mode data selector
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	
	push 0x23 ;for SS
	push UserModeESP ;ESP
	pushfd ;eflags
	push 0x1B ;user mode code selector
	push 0x00 ;EIP of usermode program - prog is loaded at 0
	iret
	
	cli
	hlt
	
At the time of page fault, CR2 = 0x00000000. I load the user mode program to 0x00000000, so I assume I have done some user mode setup incorrectly...

This is the usermode program I am trying to execute:

Code: Select all

void main(void)
{
for(;;);
}
User mode program is flat binary format.

Re: Page fault on entering user mode

Posted: Sun Jun 16, 2013 4:12 am
by iansjack
What's the error code from the page fault exception?

Re: Page fault on entering user mode

Posted: Sun Jun 16, 2013 9:23 pm
by BMW
Error code is 0x5. In binary this is 101. So it was a page protection violation from ring 3.

Hmmm... maybe I have set the stack up incorrectly...

Re: Page fault on entering user mode

Posted: Mon Jun 17, 2013 12:27 am
by iansjack
It's a privilege violation so I don't see how it can be anything to do with the stack. You haven't touched the user stack at this point. Taken in conjunction with your other recent posts, it appears that you haven't managed to construct your descriptor correctly.

Re: Page fault on entering user mode

Posted: Mon Jun 17, 2013 1:05 am
by BMW
iansjack wrote:Taken in conjunction with your other recent posts, it appears that you haven't managed to construct your descriptor correctly.
You mean my GDT? How could an incorrect GDT cause a page fault? I think that would generate a GPF.

Re: Page fault on entering user mode

Posted: Mon Jun 17, 2013 1:42 am
by iansjack
No, I mean a descriptor in the GDT (specifically - probably - your user code descriptor). Get that wrong and you can end up with a page fault because of insufficient privilege.

Edit - Or your page table entries for address 0 are wrong. Check both the descriptor and the page table to see if they contain what you expect them to.

Re: Page fault on entering user mode

Posted: Mon Jun 17, 2013 6:33 am
by sortie
BMW wrote:(I know the code's a bit messy but its just for testing purposes atm)
Note that is is much easier to help you if you clean up your code so other people can understand it as well, additionally this clean up task may occasionally make the bug much more obvious and help you fix it.

Re: Page fault on entering user mode

Posted: Tue Jun 18, 2013 12:38 am
by BMW
iansjack wrote:Check both the descriptor and the page table to see if they contain what you expect them to.
I have checked them, and they both contain expected data.

What do the user flags on page directory entries do? Do they allow user mode code to modify the page table?

Re: Page fault on entering user mode

Posted: Tue Jun 18, 2013 1:33 am
by iansjack
They control access to all pages that they reference. If you have that wrong that would explain the page fault.

Re: Page fault on entering user mode

Posted: Tue Jun 18, 2013 2:10 am
by halofreak1990
iansjack wrote:They control access to all pages that they reference. If you have that wrong that would explain the page fault.
Indeed.

If you have your page directory set up as Kernel Mode with user mode pages inside it, user mode won't be able to access the pages, even though they are marked as User Mode.
Set the containing page directory as User Mode, and restrict access to the individual pages as necessary.

Re: Page fault on entering user mode

Posted: Tue Jun 18, 2013 2:49 am
by BMW
AHHHH!!! Thank you thank you!!!

Working now :D

I have added this to the explanation of the user bit in the wiki:
For a page directory entry, the user bit controls access to all the pages referenced by the page directory entry. Therefore if you wish to make a page a user page, you must set the user bit in the relevant page directory entry as well as the page table entry.