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.
knowing which instruction raises the GPF and what the error code was could help ... i can't remember whether ds..gs are also automatically pushed when a user/supervisor stack switch occur, but i would say it's only in case of a virtual/protected mode switch ... so everything should be fine ...
i'm not sure, but you might need to push home-made flags rather than using "pushfd". iirc, some of the bits in eflags carry things like the IO Priviledge Level, and the processor might not like you to run user-level code segment with a supervisor IOPL ...
It also seems a bad idea to reuse the supervisor stack pointer in the user code. You should better allocate a memory region and fill the user pointer with it ...
Somewhere in this thread is loads of disscusion on the order of pushing/poping on entering leaving ISRs/irets etc. I was really confused and after that even I understood it. ;D
MAKE SURE you are coding straight assembler within the OS defs header file, not C or pascal..they add headers that will drive you BONKERS!
just tried a 'what if' in prt0 and VIOLA!!! Finally, after months of hell...USER MODE and proper register settings..this is close..all you need is a call to this routine(as external assembler).
I know the code is off, use the C example. This is for NASM, not GAS or AS(S).
I use FPC, but this is within the prt0 OS assembler header.
Try $23 and $1b...(have to add ring3 [+03]) and you need a TSS to get back to ring0.
----
extern UserESP ; this MUST be a seperate stack.
global switch_to_user_mode
switch_to_user_mode:
cli ;there is especial way to turn interrupts on for user mode, sti will NOT do it.
mov dword eax,$23
mov word ds,ax
mov word es,ax
mov word fs,ax
mov word gs,ax
mov eax,UserESP
push dword $23
pushf
push dword $1b
push dword eax
push dword $23 ; think this is the culprit, I GPF in usermode on switch..
iret
jmp 0x1b:user
user:
extern UserESP ; this MUST be a seperate stack.
global switch_to_user_mode
switch_to_user_mode:
cli ;there is especial way to turn interrupts on for user mode, sti will NOT do it.
mov dword eax,$23
mov word ds,ax
mov word es,ax
mov word fs,ax
mov word gs,ax
mov eax,UserESP
push dword $23
pushf
push dword $1b
push dword eax
push dword $23 ; think this is the culprit, I GPF in usermode on switch..
iret
jmp 0x1b:user
user:
Strictly speaking I don't think it's 100% correct anyway. Loading DS with the ring3 data selector and then accessing a kernel-private variable (UserESP) won't work for all designs.
If a trainstation is where trains stop, what is a workstation ?
IMHO it is easier to switch to user mode only in the scheduler, since you need the kernel -> user transition there anyway. In my kernel there is no "switch to user mode" in the way described here, having a sequence of instructions where some of them are executed in kernel mode, the segment registers are reloaded and the following ones are executed in user mode. Instead, when a new user thread is created, the task manager creates a PL0 stack image for the new thread, which looks exactly as if had been generated by the timer interrupt handler. This handler pushes all registers to the stack, calls the scheduler, switches to a different PL0 stack, pops the register contents and IRETs. It does not matter whether the scheduled thread was running at PL3 before or whether it was just created by the task manager. The task manager simply needs to create the new PL0 stack, put the initial register values at the right position, set the return EIP and ESP to the entry point and PL3 stack of the new thread - that's it.
(Of course one can modify this a bit. For example, instead of pushing the registers to the stack, one could save them in a "struct ThreadState" or whatever.)
Why are we still replying to an OP from 2003? (you don't need a TSS to get back to ring 0, but a lack of TSS in usermode is just stupid design.)
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
Well, my post was not meant for the OP, but simply for the readers of this thread which has been awakened from the dead...
Just out of curiosity, let me see if I get this right: If I have no TSS, i cannot have interrupts while running in PL3 (so I need to clear the IF) and the only way to get back to PL0 is using SYSENTER (or SYSCALL in long mode) or call gates? But anyway, I agree with you, it's a stupid design.