切换到用户 space
Switch to user space
这是演示os内核基本功能的部分代码。
刷新 GTD 并设置 IDT 后,我想切换到环 3 运行 一些 int 和上下文切换。
但是我不能跳转到用户模式。我想在 iret
指令中使用技巧。据我所知 iret
会弹出
来自堆栈的以下值:SS ESP EFLAGS CS EIP
所以想法是将正确的值推送到堆栈(使用新的段选择器),
并让 iret
在寄存器中设置值。这是我使用的代码:
.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 [=11=]x10, %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 [=11=]x10
pushl %eax
pushf
#enable ints after switch to ring 3
pop %eax
or [=11=]x200, %eax
push %eax
#CS selector
pushl [=11=]x08
pushl [=11=]x60 #Address of .leave (I have written proper ld script and checked with objdump)
iret
.section .upper_code, "ax", @progbits
.leave:
hlt
call upperKernelCode
问题出在 iret
开始执行此指令后,检查选择器的特权级别并且执行代码,因此导致 CPU 故障并重置。
这是 BOCHS 的日志形式:check_cs(0x0008): non-conforming code seg descriptor dpl != cpl, dpl=3, cpl=0
。我将非常感谢对此问题的任何帮助
正如 bochs 告诉您的那样,您的选择器 0x08
具有 CPL=0
,但描述符条目具有 DPL=3
。请记住,选择器的两个最低有效位是 CPL
。因此,要切换到 ring3,您应该使用 0x0b
.
这是演示os内核基本功能的部分代码。
刷新 GTD 并设置 IDT 后,我想切换到环 3 运行 一些 int 和上下文切换。
但是我不能跳转到用户模式。我想在 iret
指令中使用技巧。据我所知 iret
会弹出
来自堆栈的以下值:SS ESP EFLAGS CS EIP
所以想法是将正确的值推送到堆栈(使用新的段选择器),
并让 iret
在寄存器中设置值。这是我使用的代码:
.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 [=11=]x10, %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 [=11=]x10
pushl %eax
pushf
#enable ints after switch to ring 3
pop %eax
or [=11=]x200, %eax
push %eax
#CS selector
pushl [=11=]x08
pushl [=11=]x60 #Address of .leave (I have written proper ld script and checked with objdump)
iret
.section .upper_code, "ax", @progbits
.leave:
hlt
call upperKernelCode
问题出在 iret
开始执行此指令后,检查选择器的特权级别并且执行代码,因此导致 CPU 故障并重置。
这是 BOCHS 的日志形式:check_cs(0x0008): non-conforming code seg descriptor dpl != cpl, dpl=3, cpl=0
。我将非常感谢对此问题的任何帮助
正如 bochs 告诉您的那样,您的选择器 0x08
具有 CPL=0
,但描述符条目具有 DPL=3
。请记住,选择器的两个最低有效位是 CPL
。因此,要切换到 ring3,您应该使用 0x0b
.