Hi all. New to this forum and to OS Development, so please be gentle with me…
I had a few spare days over Christmas so I started playing around with a tutorial I saw a few months ago on OS development. The spare days were rapidly used up and I ended up spending quite a few more that I should really have put to more productive use, but I’ve now achieved the following with more than a little help from your wiki:
My own bootloader which loads a flat binary kernel from the root of a FAT 32 file system, sets up a temporary GDT and switches into 32 bit protected mode.
A function that sets up a proper GDT and enables paging. The first 1MB of memory is identity mapped and this is where everything is loaded and/or set up at the moment.
Interrupt handling routines which set up the IDT and direct interrupts to the right handler.
A basic PS2 keyboard driver which is able to print characters to the screen.
A function which transfers execution to ‘user mode’ and loads a function called console_main(), which is effectively just an event loop, although it doesn’t know how to respond to any events yet. At the moment it just causes an X to blink at the top left of the screen.
I tested all of this quite thoroughly. I was able to get into user mode quite happily (checked by trying to execute a privileged instruction and getting a GP exception), receive interrupts from the keyboard, handle them in ring 0 and then return to ring 3 without issue. I extended this further by implementing a basic system call – sending interrupt 0x80 causes the kernel to print a string to the screen from the address in eax. All of this was working perfectly well.
I decided to tidy the code up a little by moving the system call from an inline assembly statement in the console_main() function to its own syscall() function, which is when I came unstuck. Basically, trying to call syscall() from console_main() in user mode caused a page fault. The error code was all zeros and the address of the offending instruction (from CR2) was in the order of 0x80000000, well out of the range of the paging structure I’d set up and also well out of the range of my kernel, which is loaded at 0x10000 and extends to about 0x14000. Syscall() exists in memory in this range, so there’s no issue with e.g. it not being loaded from the disk.
In the main kernel function, I commented it out the call to the function which makes the switch to user mode and called console_main() directly – in kernel mode it then made the call to syscall() without error.
So, in desperation, I re-implemented syscall() in assembly rather than C. Exactly the same function. Now, from user mode, from the C function console_main(), I can make a call to the asm syscall() quite happily. After several hours of trying everything I can think of, I just can’t understand why. The asm function that I have written appears to be identical to the C function compiled by gcc. I also can’t understand why the C function works in kernel mode but not user mode. I’ve pinned the problem down to the call statement. Somehow, when syscall() is implemented in C and called from console_main(), the outcome is that the processor attempts to execute an instruction at 0x8000000-something and not where it should be, i.e. &syscall, causing, quite correctly, a page fault.
Has anyone come across a problem like this before? I appreciate that it isn’t normal to be compiling kernel and user mode code together, but I don’t see how this could affect how gcc compiles the code. Have I failed to understand something? Is there something in the way that a call is executed by an x86 that is different in ring 3 from ring 0?
User-mode function call causes page fault in C (but not asm)
Re: User-mode function call causes page fault in C (but not
We can't help you if you don't post any code. Useful things would be the C version of your syscall() function, its disassembly, (turn off optimisations) as well as your handwritten function.
OTOH I can't really think of anything that might be causing this.
OTOH I can't really think of anything that might be causing this.
[nx] kernel: http://github.com/zhiayang/nx
- eryjus
- Member
- Posts: 286
- Joined: Fri Oct 21, 2011 9:47 pm
- Libera.chat IRC: eryjus
- Location: Tustin, CA USA
Re: User-mode function call causes page fault in C (but not
I would compile the C function and pass the flag to generate asm code ("-S" I believe). Then compare the output of your C-code-translated-to-asm to that of your own assembly.capson wrote:The asm function that I have written appears to be identical to the C function compiled by gcc.
Also, be sure you are using a GCC_Cross-Compiler.
Adam
The name is fitting: Century Hobby OS -- At this rate, it's gonna take me that long!
Read about my mistakes and missteps with this iteration: Journal
"Sometimes things just don't make sense until you figure them out." -- Phil Stahlheber
The name is fitting: Century Hobby OS -- At this rate, it's gonna take me that long!
Read about my mistakes and missteps with this iteration: Journal
"Sometimes things just don't make sense until you figure them out." -- Phil Stahlheber