Page fault on entering user mode

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
User avatar
BMW
Member
Member
Posts: 286
Joined: Mon Nov 05, 2012 8:31 pm
Location: New Zealand

Page fault on entering user mode

Post 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.
Currently developing Lithium OS (LiOS).

Recursive paging saves lives.
"I want to change the world, but they won't give me the source code."
User avatar
iansjack
Member
Member
Posts: 4711
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Page fault on entering user mode

Post by iansjack »

What's the error code from the page fault exception?
User avatar
BMW
Member
Member
Posts: 286
Joined: Mon Nov 05, 2012 8:31 pm
Location: New Zealand

Re: Page fault on entering user mode

Post 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...
Currently developing Lithium OS (LiOS).

Recursive paging saves lives.
"I want to change the world, but they won't give me the source code."
User avatar
iansjack
Member
Member
Posts: 4711
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Page fault on entering user mode

Post 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.
User avatar
BMW
Member
Member
Posts: 286
Joined: Mon Nov 05, 2012 8:31 pm
Location: New Zealand

Re: Page fault on entering user mode

Post 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.
Currently developing Lithium OS (LiOS).

Recursive paging saves lives.
"I want to change the world, but they won't give me the source code."
User avatar
iansjack
Member
Member
Posts: 4711
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Page fault on entering user mode

Post 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.
User avatar
sortie
Member
Member
Posts: 931
Joined: Wed Mar 21, 2012 3:01 pm
Libera.chat IRC: sortie

Re: Page fault on entering user mode

Post 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.
User avatar
BMW
Member
Member
Posts: 286
Joined: Mon Nov 05, 2012 8:31 pm
Location: New Zealand

Re: Page fault on entering user mode

Post 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?
Currently developing Lithium OS (LiOS).

Recursive paging saves lives.
"I want to change the world, but they won't give me the source code."
User avatar
iansjack
Member
Member
Posts: 4711
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Page fault on entering user mode

Post by iansjack »

They control access to all pages that they reference. If you have that wrong that would explain the page fault.
halofreak1990
Member
Member
Posts: 41
Joined: Thu Aug 09, 2012 5:10 am

Re: Page fault on entering user mode

Post 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.
<PixelToast> but i cant mouse

Porting is good if you want to port, not if you want maximum quality. -- sortie
User avatar
BMW
Member
Member
Posts: 286
Joined: Mon Nov 05, 2012 8:31 pm
Location: New Zealand

Re: Page fault on entering user mode

Post 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.
Currently developing Lithium OS (LiOS).

Recursive paging saves lives.
"I want to change the world, but they won't give me the source code."
Post Reply