Page becomes not present when switching to ring 3

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.
SlayterDev
Member
Member
Posts: 25
Joined: Wed Aug 13, 2014 4:22 pm

Page becomes not present when switching to ring 3

Post by SlayterDev »

Ok so i'm writing an ELF Loader for my kernel that reads in the binary and executes it in ring 3. I allocate memory for the executable image and set those pages as present, writable, and user. I then verify that the page is present right before dropping to user space. However when the code gets to ring 3, it causes a page fault stating that the page is not present. I'm using the same page directory for both kernel and user space. How could it be present in kernel space but not user space?

Here is the code to run in user space:

Code: Select all

asm volatile(" \
		mov $0x23, %%ax; \
		mov %%ax, %%ds; \
		mov %%ax, %%es; \
		mov %%ax, %%fs; \
		mov %%ax, %%gs; \
		pushl $0x23; \
		push %0; \
		pushl $0x200; \
		pushl $0x1B; \
		push %1; \
		iret; \
		":: "r" (mainThread->frame.esp), "m" (mainThread->frame.eip));
Let me know if you'd like me to post any other relevant parts of code.
User avatar
b.zaar
Member
Member
Posts: 294
Joined: Wed May 21, 2008 4:33 am
Location: Mars MTC +6:00
Contact:

Re: Page becomes not present when switching to ring 3

Post by b.zaar »

Is the page mapped to user space at the right address? Is the user space app loaded and running at the right address?
"God! Not Unix" - Richard Stallman

Website: venom Dev
OS project: venom OS
Hexadecimal Editor: hexed
SlayterDev
Member
Member
Posts: 25
Joined: Wed Aug 13, 2014 4:22 pm

Re: Page becomes not present when switching to ring 3

Post by SlayterDev »

Yes, I get the entry point from the ELF header. I allocate enough memory for the size of the executable and map that block of memory to the address of the entry point and set it for user,writable, and present. Then I copy the executable into that space in memory.
User avatar
b.zaar
Member
Member
Posts: 294
Joined: Wed May 21, 2008 4:33 am
Location: Mars MTC +6:00
Contact:

Re: Page becomes not present when switching to ring 3

Post by b.zaar »

Try running your kernel in bochs with the debugger and maybe paste the log after the page fault. You'll have a better idea of what is going wrong.
"God! Not Unix" - Richard Stallman

Website: venom Dev
OS project: venom OS
Hexadecimal Editor: hexed
alexfru
Member
Member
Posts: 1112
Joined: Tue Mar 04, 2014 5:27 am

Re: Page becomes not present when switching to ring 3

Post by alexfru »

SlayterDev wrote:Ok so i'm writing an ELF Loader for my kernel that reads in the binary and executes it in ring 3. I allocate memory for the executable image and set those pages as present, writable, and user. I then verify that the page is present right before dropping to user space. However when the code gets to ring 3, it causes a page fault stating that the page is not present. I'm using the same page directory for both kernel and user space. How could it be present in kernel space but not user space?
You need to verify that it's indeed a "page not present" fault and not a "protection violation" one.

My guess is that your PDEs/PTEs aren't set up properly to allow ring 3/user accesses. There are Supervisor/User bits at both levels and you may have some (or all) set incorrectly. Look up the documentation to see what these bits should be at each level to allow user access.
User avatar
iocoder
Member
Member
Posts: 208
Joined: Sun Oct 18, 2009 5:47 pm
Libera.chat IRC: iocoder
Location: Alexandria, Egypt | Ottawa, Canada
Contact:

Re: Page becomes not present when switching to ring 3

Post by iocoder »

SlayterDev wrote:Ok so i'm writing an ELF Loader for my kernel that reads in the binary and executes it in ring 3. I allocate memory for the executable image and set those pages as present, writable, and user. I then verify that the page is present right before dropping to user space. However when the code gets to ring 3, it causes a page fault stating that the page is not present. I'm using the same page directory for both kernel and user space. How could it be present in kernel space but not user space?
Did you check the type of page fault and the contents of cr2, cs, and eip after the exception signal? This might show us what actually causes the fault.
SlayterDev wrote:Yes, I get the entry point from the ELF header. I allocate enough memory for the size of the executable and map that block of memory to the address of the entry point
Could you explain this please? You should read the program headers of type LOAD and map a block of memory to each vaddr, not the address of the entry point.
User avatar
iansjack
Member
Member
Posts: 4707
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Page becomes not present when switching to ring 3

Post by iansjack »

How do you know you are getting a page not present error? It seems unlikely. The only possibility that I can think of is that the faulting page is not the one you think it is - probably due to stack corruption.

Are you running this in Bochs? If so, relevant parts of the log would be useful. And have you checked the address that the fault is being reported? The error code of the Page Fault and the value of CR2 should be inspected.
SlayterDev
Member
Member
Posts: 25
Joined: Wed Aug 13, 2014 4:22 pm

Re: Page becomes not present when switching to ring 3

Post by SlayterDev »

Well I finally got bochs installed but now when I run my OS it comes up with "port 0x3f5: no results to read" when installing the floppy driver. Specifically when sending the CHECK INT command. What gives?

EDIT: More info on the real problem. I dumped some more info from what I can get with the page fault. It faults at address 0x300000 (the virtual address I mapped. The one I want). The page is marked as user mode but not present (so says the page fault error code). The eip is at 0x300000 (where we wanted the program to start). cs is 0x1B (this is what I set it too right before the jump). esp is 0x1FE4 <- this is the only thing I'm wary about. That doesn't seem right to me but I don't understand why or what to do about it especially since I push the new user stack right before the jump.
User avatar
b.zaar
Member
Member
Posts: 294
Joined: Wed May 21, 2008 4:33 am
Location: Mars MTC +6:00
Contact:

Re: Page becomes not present when switching to ring 3

Post by b.zaar »

SlayterDev wrote:It faults at address 0x300000 (the virtual address I mapped. The one I want). The page is marked as user mode but not present (so says the page fault error code). The eip is at 0x300000 (where we wanted the program to start)
Doesn't elf's entry address default to something higher than 0x300000? Why are you using this address?
SlayterDev wrote:esp is 0x1FE4 <- this is the only thing I'm wary about. That doesn't seem right to me but I don't understand why or what to do about it especially since I push the new user stack right before the jump.
Is this the kernel esp after the pagefault? Is the SS base set to 0x00000000?

Maybe paste the Bochs log in a code block so we can see too.

SlayterDev wrote:since I push the new user stack right before the jump.


How are you trying to enter user space, through a jump or an iret?


Nevermind I looked back at the code in your original post.

P.S. is there a strike through code for editing?
Last edited by b.zaar on Tue Oct 07, 2014 4:36 pm, edited 2 times in total.
"God! Not Unix" - Richard Stallman

Website: venom Dev
OS project: venom OS
Hexadecimal Editor: hexed
SlayterDev
Member
Member
Posts: 25
Joined: Wed Aug 13, 2014 4:22 pm

Re: Page becomes not present when switching to ring 3

Post by SlayterDev »

I'd like to post the bochs log but the issue I posted above with the floppy controller prevents me from getting to this problem.
Doesn't elf's entry address default to something higher than 0x300000? Why are you using this address?
I'm not sure. I modeled my executable build process from something I saw on github. Basically I'm using this linker script:

Code: Select all

ENTRY(_start)
phys = 0x00300000;
SECTIONS
{
	.text phys : AT(phys) {
		code = .;
		*(.text)
		*(.rodata)
		. = ALIGN(4096);
	}
	.data : AT(phys + (data - code))
	{
		data = .;
		*(.data)
		. = ALIGN(4096);
	}
	.bss : AT(phys + (bss - code))
	{
		bss = .;
		*(.bss)
		. = ALIGN(4096);
	}
	/DISCARD/ :
	{
		*(.comment)
		*(.eh_frame)
		*(.note.gnu.build-id)
	}
}
_start refers to this assembly file which is supposed to start the program:

Code: Select all

[BITS 32]
[GLOBAL _start]
_start:
	pop eax ; I dont know if this is needed
	extern main
	call main 
I compile that file plus the C file using my i686-elf cross compiler built from the instructions on the wiki.

The ss that comes in the page fault is 0x23. I push that value when going to user mode. And I do use iret using this code:

Code: Select all

asm volatile(" \
		mov $0x23, %%ax; \
		mov %%ax, %%ds; \
		mov %%ax, %%es; \
		mov %%ax, %%fs; \
		mov %%ax, %%gs; \
		pushl $0x23; \
		push %0; \
		pushl $0x200; \
		pushl $0x1B; \
		push %1; \
		iret; \
		":: "r" (mainThread->frame.esp), "m" (mainThread->frame.eip));
User avatar
b.zaar
Member
Member
Posts: 294
Joined: Wed May 21, 2008 4:33 am
Location: Mars MTC +6:00
Contact:

Re: Page becomes not present when switching to ring 3

Post by b.zaar »

SlayterDev wrote: _start refers to this assembly file which is supposed to start the program:

Code: Select all

[BITS 32]
[GLOBAL _start]
_start:
	pop eax ; I dont know if this is needed
	extern main
	call main 
What is eax popping? You're not putting any extra data onto the stack.

Change the first instruction to a jmp $ and see if it loops happily.
"God! Not Unix" - Richard Stallman

Website: venom Dev
OS project: venom OS
Hexadecimal Editor: hexed
SlayterDev
Member
Member
Posts: 25
Joined: Wed Aug 13, 2014 4:22 pm

Re: Page becomes not present when switching to ring 3

Post by SlayterDev »

That causes the same page fault
User avatar
b.zaar
Member
Member
Posts: 294
Joined: Wed May 21, 2008 4:33 am
Location: Mars MTC +6:00
Contact:

Re: Page becomes not present when switching to ring 3

Post by b.zaar »

Do the push for esp and eip before you change the ds register.
"God! Not Unix" - Richard Stallman

Website: venom Dev
OS project: venom OS
Hexadecimal Editor: hexed
SlayterDev
Member
Member
Posts: 25
Joined: Wed Aug 13, 2014 4:22 pm

Re: Page becomes not present when switching to ring 3

Post by SlayterDev »

Changed to this (I think thats what you meant):

Code: Select all

asm volatile(" \
		mov $0x23, %%ax; \
		mov %%ax, %%ds; \
		mov %%ax, %%es; \
		mov %%ax, %%fs; \
		mov %%ax, %%gs; \
		push %0; \
		pushl $0x200; \
		pushl $0x1B; \
		push %1; \
		pushl $0x23; \
		iret; \
		":: "r" (mainThread->frame.esp), "m" (mainThread->frame.eip));
Now I get a general protection fault.
User avatar
b.zaar
Member
Member
Posts: 294
Joined: Wed May 21, 2008 4:33 am
Location: Mars MTC +6:00
Contact:

Re: Page becomes not present when switching to ring 3

Post by b.zaar »

Code: Select all

asm volatile(" \
		pushl $0x23; \
		push %0; \
		pushl $0x200; \
		pushl $0x1B; \
		push %1; \
		mov $0x23, %%ax; \
		mov %%ax, %%ds; \
		mov %%ax, %%es; \
		mov %%ax, %%fs; \
		mov %%ax, %%gs; \
		iret; \
		":: "r" (mainThread->frame.esp), "m" (mainThread->frame.eip));
You are using the user data selector to acces mainThread in your push operations. If you do your stack work first then adjust the other segments you will be using the kernel data segment.
"God! Not Unix" - Richard Stallman

Website: venom Dev
OS project: venom OS
Hexadecimal Editor: hexed
Post Reply