flat assembler
Message board for the users of flat assembler.

Index > OS Construction > [SOLVED] Switching from ring 0 to ring 3

Author
Thread Post new topic Reply to topic
calpol2004



Joined: 16 Dec 2004
Posts: 110
calpol2004 21 Dec 2008, 03:16
EDIT: Solved, simply had to set the lowest 2 bits of cs and ss to 11b to indicate a ring level of 3. Thanks to manofsteel and japheth.

I've been trying for a little while now to successfuly switch from ring 0 to ring 3. From what i can tell there are only 2 ways to do this, either use the TSS or set up a stack frame and iret.

Heres what im doing:

Code:
;code to jump
pushd 0x20           ;ss
pushd 0x9FFFF      ;esp
pushd 0                ;flags
pushd 0x18           ;cs
pushd @F              ;ip
iret
@@:
jmp $    

;GDT
;kernel code selector
dw 0xFFFF
dw 0
db 0                          ;0x8
db 10011010b
db 11001111b
db 0
;kernel data selector
dw 0xFFFF
dw 0
db 0
db 10010010b                  ;0x10
db 11001111b
db 0
;User Space code
dw 0xFFFF
dw 0
db 0
db 11111010b                  ;0x18
db 11001111b
db 0
;User Space data
dw 0xFFFF
dw 0
db 0                          ;0x20
db 11110010b
db 11001111b
db 0                                                
    


But i get GPF everytime. Anyone got any examples or info on ring switch from 0 to 3 using iret?


Last edited by calpol2004 on 22 Dec 2008, 03:43; edited 2 times in total
Post 21 Dec 2008, 03:16
View user's profile Send private message MSN Messenger Reply with quote
ManOfSteel



Joined: 02 Feb 2005
Posts: 1154
ManOfSteel 21 Dec 2008, 10:31
PM is very strict. It could be anything anywhere in your code.

First, try ORing your stack and code selectors with 11b for ring 3 RPL (pushd 0xXX or 3).
Post 21 Dec 2008, 10:31
View user's profile Send private message Reply with quote
calpol2004



Joined: 16 Dec 2004
Posts: 110
calpol2004 21 Dec 2008, 16:19
It could quite possibly be a wrongly flipped bit in my GDT, but is what im doing the right method?

is setting up a TSS required to switch from 0 to 3? is using iret with the stack frame im using a valid way of switching?

From what i can tell i need to set up a TSS. Because when you ring switch, the cpu will try and use one if you have one or not for some things. For example when switching from ring 3 to ring 0 (not sure if this is the case for sysenter) the cpu will look into the selector stored in TR and then load esp and ss from the structure the selector points to. I'm curious to whether i need a valid Task selector and TSS struct setup before i can switch from ring 0 to ring 3?

All help appreciated (now checking my selectors bit bit...).

Cheers, Cal.


Last edited by calpol2004 on 21 Dec 2008, 17:11; edited 5 times in total
Post 21 Dec 2008, 16:19
View user's profile Send private message MSN Messenger Reply with quote
calpol2004



Joined: 16 Dec 2004
Posts: 110
calpol2004 21 Dec 2008, 16:37
Okay i setup from what i can tell is a valid TSS:

TSS Selector:

Code:
;0x0067 is Size of TSS structure - 1
;im using using lower 16 bits of base address but *for now* the the TSSData is being stored under the first 64kb of memory.
TSS        dw 0x0067,TSSData,0x8900,0x0040 ;0x28
    


TSS structure (only iomap, esp0 and ss0 are set):

Code:
;Only used to switch stack pointer when switching ring 3 -> 0
TSSData:
dw 0   ;link
dw 0   ;link_h
dd STACK_LOCATION+STACK_SIZE        ;SET - esp to load on ring switch to 0
dw 0x10,0                           ;SET - ss to load on ring switch to 0
dd 0   ;esp1
dw 0,0 ;ss1,ss1_h
dd 0   ;esp2
dw 0,0 ;ss2,ss2_h
dd 0   ;cr3
dd 0   ;eip
dd 0   ;eflags
dd 0   ;eax
dd 0   ;ecx
dd 0   ;edx
dd 0   ;ebx
dd 0   ;esp
dd 0   ;ebp
dd 0   ;esi
dd 0   ;edi
dw 0,0 ;es,es_h
dw 0,0 ;cs,cs_h
dw 0,0 ;ss,ss_h
dw 0,0 ;ds,ds_h
dw 0,0 ;fs,fs_h
dw 0,0 ;gs,gs_h
dw 0,0 ;ldt,ldt_h
dw 0   ;trap
dw 104  ;iomap      ;SET - An offset from start of tss to a iomap - i set io map outside of tss so if you try and use I/O the cpu will check this and cause the GPF because it points outside.                                
    


Load TR register:

Code:
mov   eax,0x28          ;load task register with task selector (only used for stack-switch)
ltr   ax       
    


Still can't switch. Is there something im missing here?
Post 21 Dec 2008, 16:37
View user's profile Send private message MSN Messenger Reply with quote
Japheth



Joined: 26 Oct 2004
Posts: 151
Japheth 21 Dec 2008, 16:53
calpol2004 wrote:

is setting up a TSS required to switch from 0 to 3?

IIRC no. However, without a TSS and TR loaded with a valid descriptor you won't be able to switch back to ring 0. So interrupts must remain disabled in ring 3. Best is to make a TSS and load TR. Just the values for SS:ESP for ring 0 must be set in the TSS.
calpol2004 wrote:

is using iret with the stack frame im using a valid way of switching?

Yes. You can use IRET or RETF (with RETF, there is no value for the EFLAGS register expected onto the stack).

Did you try ManOfSteels hint? It's important that CS (and IIRC also SS) is loaded with a selector with RPL=3.
Post 21 Dec 2008, 16:53
View user's profile Send private message Reply with quote
calpol2004



Joined: 16 Dec 2004
Posts: 110
calpol2004 22 Dec 2008, 03:08
Checked my GDT Entries, nothing wrong with them. My ring 3 selectors are simply my ring 0 selectors but with bits 45 and 46 set (RPL bits). The ring 0 selectors work, im able to enter protected mode with them.

Code:
KernelCode dq 0000000011001111100110100000000000000000000000001111111111111111b
KernelData dq 0000000011001111100100100000000000000000000000001111111111111111b
UserCode   dq 0000000011001111111110100000000000000000000000001111111111111111b
UserData   dq 0000000011001111111100100000000000000000000000001111111111111111b
    


Ive made a little "demo" (below) with the minimun code needed to do the ring switch. Im totally stumped. If all thats required is to change the RPL bits to 3 then my GDT entries are definetly correct, in which case switching into PMODE successfuly and doing the ring switch almost directly after should work.

I just know its got to be something stupidly obvious that perhaps you assumed id done or a really hard to find small error thats doing this. Driving me insane, i can't make any progress at all until i can switch to ring 3, someone must have a snippet of code from their OS which switches to ring 3 or a user level GDT entry i could test. Really need your help.

Cal.

Code:
;##########################################################;
;                       Initialize                                   ;
;##########################################################;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;      16bit Segments       ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
use16
org   0x7E00
cli
xor   eax,eax                      ;setup segments
mov   ds,ax
mov   es,ax
mov   ax,0x90000/16        ;what sp counts down too, divide by 16 as segments are always *16 when absolute
mov   ss,ax
mov   sp,0xFFFF               ;sp is offset from ss, gets closer to ss as you push more stuff
sti
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;      Enable A20 Gate      ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov   al,0xD0    ;send read output port command
out   0x64,al
@@:              ;wait for keyboard
in    al,0x64
test  eax,2
jnz   @B
in    al,0x60    ;read input buffer and store on stack. This is the data read from the output port
push  eax
@@:              ;wait for keyboard
in    al,0x64
test  eax,2
jnz   @B
mov   eax,0xD1    ;send write output port command
out   0x64,al
@@:              ;wait for keyboard
in    al,0x64
test  eax,2
jnz   @B
pop   eax        ;pop the output port data from stack and set bit 1 (A20) to enable
or    eax,2
out   0x60,al
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;PMODE & Disable Interrupts ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
cli
lgdt  [GDTR]                 ;load Global Descriptor Table
mov   eax,cr0
or    eax,1
mov   cr0,eax               ;set protected mode bit
jmp   0x8:@F                ;far jump to set cs
@@:
use32
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;   Set Kernel Selectors    ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov   eax,0x10               ;kernel data selector
mov   ds,ax
mov   ss,ax
mov   es,ax
mov   esp,0x9FFFF ;start counting down from top of stack, no limits
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Jump to ring 3             ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pushd 0x20
pushd 0x9FFFF
pushd 0                  ;interrupts are off
pushd 0x18
pushd @F
iret
@@:
mov ah,7
mov al,'a'
mov [0xB8000],ax
jmp $
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;GDT             ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GDTR:
dw         GDT_End-GDT-1
dd         GDT
GDT:
Null       dq 0000000000000000000000000000000000000000000000000000000000000000b
KernelCode dq 0000000011001111100110100000000000000000000000001111111111111111b
KernelData dq 0000000011001111100100100000000000000000000000001111111111111111b
UserCode   dq 0000000011001111111110100000000000000000000000001111111111111111b
UserData   dq 0000000011001111111100100000000000000000000000001111111111111111b
GDT_End:                                                                                              
    


Last edited by calpol2004 on 22 Dec 2008, 03:27; edited 1 time in total
Post 22 Dec 2008, 03:08
View user's profile Send private message MSN Messenger Reply with quote
Japheth



Joined: 26 Oct 2004
Posts: 151
Japheth 22 Dec 2008, 03:24
calpol2004 wrote:
Checked my GDT Entries, nothing wrong with them. My ring 3 selectors are simply my ring 0 selectors but with bits 45 and 46 set (RPL bits). The ring 0 selectors work, im able to enter protected mode with them.


RPL are bits 0-1 of the value loaded into CS/SS, not the bits in the descriptor (IIRC those bits are called DPL).
Post 22 Dec 2008, 03:24
View user's profile Send private message Reply with quote
calpol2004



Joined: 16 Dec 2004
Posts: 110
calpol2004 22 Dec 2008, 03:35
I totally misunderstood (i thought you meant the DPL in the descriptor, never even knew about this), thankyou!

I simply changed ss to 0x23 and cs to 0x1B (add 3) and it worked. What a perculiar way to set the privelege level, you'd think that setting it in the descriptor would be enough d'ya think? i suppose it's so iret/retf can know about it before it checks the descriptor.

Learn something new everyday.

Thankyou very much japheth and manofsteel. You only had to tell me 3 times XD.

Cal.
Post 22 Dec 2008, 03:35
View user's profile Send private message MSN Messenger Reply with quote
asmmsa



Joined: 06 Feb 2010
Posts: 45
asmmsa 10 Feb 2010, 23:17
bullshit, doesnt work.
you missed something.
Post 10 Feb 2010, 23:17
View user's profile Send private message Reply with quote
Coddy41



Joined: 18 Jan 2009
Posts: 384
Location: Ohio, USA
Coddy41 10 Feb 2010, 23:29
@asmmsa: You bumped up a topic this old just to say that? What is wrong with it?

_________________
Want hosting for free for your asm project? You can PM me. (*.fasm4u.net)
Post 10 Feb 2010, 23:29
View user's profile Send private message Visit poster's website Reply with quote
asmmsa



Joined: 06 Feb 2010
Posts: 45
asmmsa 11 Feb 2010, 10:28
its exactly same issue i had.
everything is fine, GPF isnt switch related, but access to screenbuffer is made using null selector.
Post 11 Feb 2010, 10:28
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.