Page 1 of 1

GP on context switch

Posted: Tue Oct 21, 2003 5:11 am
by user mode
Hello,

I'm getting general protection exception whenever I try to switch to user mode. Here is what I use:

Code: Select all

global userMode

userMode:
        mov    eax, esp     ; Save Current Stack Offset
        push    0x18        ; Push user data selector
        push    eax         ; Push Stack Offset
        pushfd                ; Push EFLAGS
        push    0x20        ; Push user code selector
        push    here        ; Push EIP
        iretd               ; Cause Switch
here:
        mov    ax, 0x18   ; user data selector
        mov    ds, ax
        mov    es, ax
        mov    fs, ax
        mov    gs, ax
and my gdt's user & code selectors:

Code: Select all


userData        equ     $-gdt      
        dw 0FFFFh
        dw 0
        db 0
        db 0F2h         ; ring 3
        db 0CFh        
        db 0

userCode        equ     $-gdt      
        dw 0FFFFh
        dw 0
        db 0
        db 0FAh        ; ring 3 
        db 0CFh         
        db 0
Can anyone please help me out? :)

Re:GP on context switch

Posted: Tue Oct 21, 2003 7:39 am
by Pype.Clicker
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 ...

Re:GP on context switch

Posted: Tue Oct 21, 2003 8:45 am
by userMode
knowing which instruction raises the GPF and what the error code was could help
The IRETD seems to be the culprit causing GPF.

Re:GP on context switch

Posted: Tue Oct 21, 2003 9:23 am
by Pype.Clicker
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 ...

Re:GP on context switch

Posted: Tue Oct 21, 2003 2:24 pm
by userMode
Is this not correct method of context switching to ring 3:

push userSS
push userESP
push userEFLAGS
push userCS
push userEIP
iretd

If anyone has better psuedo code please let me know :)

Re:GP on context switch

Posted: Tue Oct 21, 2003 2:49 pm
by Therx
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

Pete

Re: GP on context switch

Posted: Mon Jul 04, 2011 3:58 pm
by shadowH3
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:

Re: GP on context switch

Posted: Mon Jul 04, 2011 7:40 pm
by Owen
I'm so sure user mode is has been waiting ever so patiently these 8 yearsfor an answer to his question.

(Also: A font size cap of 200%? Aww, what? I can't help but feel that sometimes you need 1000% or similar to really hammer home the point)

Re: GP on context switch

Posted: Mon Jul 04, 2011 8:08 pm
by gerryg400

Code: Select all

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.

Re: GP on context switch

Posted: Tue Jul 05, 2011 1:30 am
by xenos
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.)

Re: GP on context switch

Posted: Tue Jul 05, 2011 4:50 am
by digo_rp
Man have you set up the tss.ss0 and tss.esp0 ? to use ring3 in context switch you need one TSS.

Re: GP on context switch

Posted: Tue Jul 05, 2011 7:18 am
by xenos
digo_rp wrote:Man have you set up the tss.ss0 and tss.esp0 ? to use ring3 in context switch you need one TSS.
AFAIK, you always need a TSS if you want to get back from PL3 to PL0.

Re: GP on context switch

Posted: Tue Jul 05, 2011 7:48 am
by Combuster
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.)

Re: GP on context switch

Posted: Tue Jul 05, 2011 8:28 am
by xenos
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.