Page 1 of 2
Page becomes not present when switching to ring 3
Posted: Mon Oct 06, 2014 6:31 pm
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.
Re: Page becomes not present when switching to ring 3
Posted: Mon Oct 06, 2014 6:59 pm
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?
Re: Page becomes not present when switching to ring 3
Posted: Mon Oct 06, 2014 7:14 pm
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.
Re: Page becomes not present when switching to ring 3
Posted: Mon Oct 06, 2014 7:50 pm
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.
Re: Page becomes not present when switching to ring 3
Posted: Mon Oct 06, 2014 10:36 pm
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.
Re: Page becomes not present when switching to ring 3
Posted: Mon Oct 06, 2014 11:24 pm
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.
Re: Page becomes not present when switching to ring 3
Posted: Tue Oct 07, 2014 1:47 am
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.
Re: Page becomes not present when switching to ring 3
Posted: Tue Oct 07, 2014 3:16 pm
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.
Re: Page becomes not present when switching to ring 3
Posted: Tue Oct 07, 2014 4:20 pm
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?
Re: Page becomes not present when switching to ring 3
Posted: Tue Oct 07, 2014 4:32 pm
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));
Re: Page becomes not present when switching to ring 3
Posted: Tue Oct 07, 2014 4:45 pm
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.
Re: Page becomes not present when switching to ring 3
Posted: Tue Oct 07, 2014 4:53 pm
by SlayterDev
That causes the same page fault
Re: Page becomes not present when switching to ring 3
Posted: Tue Oct 07, 2014 6:52 pm
by b.zaar
Do the push for esp and eip before you change the ds register.
Re: Page becomes not present when switching to ring 3
Posted: Tue Oct 07, 2014 8:00 pm
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.
Re: Page becomes not present when switching to ring 3
Posted: Tue Oct 07, 2014 8:10 pm
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.