Page 1 of 1

Can't fix a GPF in my switch to usermode function.

Posted: Thu Mar 03, 2011 2:56 am
by Peterbjornx
I am not very experienced in assembler so i ported JamesM's switch_to_usermode() to MSVC inline assembler's syntax, but it doesnt work, it gives a GPF and according to bochs it tries to access segment 0xC007 (which is not a address used in the function), my code pushing the values is
(usermode is a lablel located somewhere near 0xc0004e50)

Code: Select all

void switch_to_usermode(){ 
//I replaced vars by constants hoping it might fix it
         int data_segment = (4 * GDT_SELECTOR_MULTIPLIER) | RPL_USERMODE_MASK;//0x23
          short data_seg16 = (short) data_segment;
          int code_segment = (3 * GDT_SELECTOR_MULTIPLIER) | RPL_USERMODE_MASK;//0x1B
          __asm{
                  cli 
                 mov ax, data_seg16 
                 mov ds, ax
                 mov es, ax
                 mov fs, ax 
                 mov gs, ax 
                 mov eax, esp
                 mov ebx, 0x23
                 push ebx                  
                 push eax
                 pushf
                 pop eax 
                 or eax, 0x200  
                 push eax
                 mov ebx, 0x1B 
                 push ebx  
                 push usermode  
                 iret 
         }  usermode:
          return;
  }  
As you can see it seems to get that value out of thin air.

My theorys are:
- It corrupting my stack pointer and that makes it pop a invalid value

- I have the push/pops in the wrong order

I have used the bochs debugger to check the registers but it is lacking a good way of examining the stack, but i do now EBX is being set correctly, FLAGS is being loaded into EAX and ES,DS,FS,GS are all being set correctly

Re: Can't fix a GPF in my switch to usermode function.

Posted: Thu Mar 03, 2011 3:40 am
by a5498828
mov ds,ebx

only 16 bit registers

pushf
pop eax
or eax,0x200
push eax

why not use sti?


push ebx
push usermode
iret

what are you trying to do... iret also takes flags.
My theorys are:
my theory is you should not start from portnig c code, but trying basics. Have you even tried entering pmode in asm?

Re: Can't fix a GPF in my switch to usermode function.

Posted: Thu Mar 03, 2011 4:13 am
by Peterbjornx
I understand the memory manager/protection of the x86 architecture quite well, its just that im not very experienced with assembler and x86 opcodes internal workings, so i decided to use JamesM's and that EBX should've been BX, i forgot to edit that but it still works like its supposed to, DS,ES,GS and FS get loaded properly so that is not the problem.

The flags are in EAX and got pushed even before the segment and IP were pushed, and its intended to switch to usermode and reenable interrupts, but as you cannot enable interrupts in usermode you have to set it manually on the FLAGS pushed onto the stack.

Re: Can't fix a GPF in my switch to usermode function.

Posted: Thu Mar 03, 2011 5:17 am
by Combuster
It seems you forgot to push the SS/ESP image onto the stack.

Re: Can't fix a GPF in my switch to usermode function.

Posted: Thu Mar 03, 2011 5:28 am
by Peterbjornx
Oops, i forgot to write them down here, i simply wrote down what i remembered cause im not at home right now (stupid because i could have got my source from SVN), fixed, the version from SVN is on there now

Re: Can't fix a GPF in my switch to usermode function.

Posted: Thu Mar 03, 2011 6:24 am
by Peterbjornx
Btw i have set up a TSS for the syscalls and im 100% sure it crashes on the IRET instruction

Re: Can't fix a GPF in my switch to usermode function.

Posted: Thu Mar 03, 2011 9:25 am
by Peterbjornx
Fixed it, it was a the MSVC assembler acting weird, in 32bit pmode pushf should do the same as pushfd, but it didnt, it wrote a pushf which only pushed the low word of EFLAGS