Reputation: 225
this is part of code which demonstrates basic functions of os kernel.
After flushing GTD and setting up IDT I want to switch to ring 3 run some int and context switch.
However I cannot jump to user mode. I want to use trick with iret
instruction. As far I know iret
will pop
from stack following values: SS ESP EFLAGS CS EIP
so the idea is push proper values to the stack(with new segment selectors),
and let iret
set values in registers. Here is the code I am using:
.equ NULL_DESCRIPTOR, 0x0000000000000000
.equ CODE_P3, 0x40C3FA000000D090
.equ DATA_P3, 0x40C3F2000000D090
.equ CODE_KERNEL, 0x00CF9A000000FFFF
.equ DATA_KERNEL, 0x00CF92000000FFFF
GDT:
.quad NULL_DESCRIPTOR
.quad CODE_P3 #0x08
.quad DATA_P3 #0x10
.quad CODE_KERNEL #0x18
.quad DATA_KERNEL #0x20
_GDT:
.word 39
.long GDT
.global flushGDT
.type flushGDT, @function
flushGDT:
cli
lgdt _GDT
xor %eax, %eax
#Data segment setup
mov $0x10, %ax
mov %ax, %ds
mov %ax, %gs
mov %ax, %fs
mov %ax, %es
#Stack save
mov %esp, %eax
#stack setup for iret and user space return
pushl $0x10
pushl %eax
pushf
#enable ints after switch to ring 3
pop %eax
or $0x200, %eax
push %eax
#CS selector
pushl $0x08
pushl $0x60 #Address of .leave (I have written proper ld script and checked with objdump)
iret
.section .upper_code, "ax", @progbits
.leave:
hlt
call upperKernelCode
The problem is with iret
after starting to execute this instruction check on privilege level of selector and a code is perforem, so in result CPU faults and reset.
Here is log form BOCHS: check_cs(0x0008): non-conforming code seg descriptor dpl != cpl, dpl=3, cpl=0
. I will much appreciate any help with this issue
Upvotes: 0
Views: 907
Reputation: 58762
As bochs told you, your selector 0x08
has CPL=0
but the descriptor entry has DPL=3
. Remember that the two least significant bits of the selector are the CPL
. Thus, to switch to ring3, you should use 0x0b
.
Upvotes: 2