fix(vkernel): GS 归一化的说明改为 asm 外的英文注释(本编译器 asm 模板不接受注释/符号名)
上一版把说明写进 __asm__ 模板里:① 编译器会扫描 asm 模板中的符号名(注释里的 _per_cpu 也被判为需导出而报 TypeError);② 本编译器的 __asm__ 模板本身不接受注释。现把注释全部移出 asm,并改用英文;汇编指令本体不变(cli → mov rsp,ksp → 按 GS_BASE 是否为 0 决定 swapgs → 压 iretq 帧)。
This commit is contained in:
1 parent
1f2faf0db8
commit
f8eed7f300
1 file changed
+8
-7
@@ -240,15 +240,16 @@ def drop_to_user_mode(entry: rawptr, user_rsp: uint64, kern_rsp: uint64):
|
||||
# syscall/ISR entry does swapgs to get GS_BASE = &_per_cpu
|
||||
# syscall/ISR return does swapgs to restore GS_BASE = 0
|
||||
# GS state is restored in isrCommonhandler before _yield() if needed.
|
||||
# [FIX] Normalize GS to the user convention (GS_BASE = 0) before returning to ring 3.
|
||||
# This thread may have been switched in from ANOTHER thread's user-mode timer interrupt:
|
||||
# that path never runs the ISR exit swapgs, so GS_BASE is still the kernel view (pointing
|
||||
# at the per-cpu struct). Running user code in that state makes the app's first syscall
|
||||
# swapgs the wrong way; the kernel-stack lookup then reads garbage from linear address 8,
|
||||
# the stack pointer becomes garbage, and even the page-fault frame cannot be pushed
|
||||
# => triple fault with zero output (not even the ISR entry probe can fire).
|
||||
# Swapgs only when GS_BASE != 0 (idempotent; same idiom as the handler's GS restore).
|
||||
__asm__(f"""cli
|
||||
mov rsp, {asminp(kern_rsp, ASM_DESCR.REG_ANY)}
|
||||
# 【FIX】进用户态前必须把 GS 归一化到用户约定(GS_BASE=0):
|
||||
# 本线程可能是**从别人的用户态定时器 ISR 里被切换过来的**(timer 路径不走
|
||||
# isrCommonhandler 的 GS 恢复,且线程切换后 ISR 出口的 swapgs 永远不会执行),
|
||||
# 此时 GS_BASE 仍 = _per_cpu(内核视角)。带着这个状态跑用户代码 ⇒ app 第一条
|
||||
# syscall 再 swapgs 就反了 ⇒ mov rsp, gs:[0x8] 读到地址 0x8 的垃圾 ⇒ rsp 变
|
||||
# 垃圾 ⇒ push 时 #PF 连异常帧都压不进去 ⇒ 三重故障(QEMU 直接消失、零输出,
|
||||
# 连 ISR 入口探针都照不到)。这里按 GS_BASE 是否为 0 决定是否 swapgs(幂等)。
|
||||
mov ecx, 0xC0000101
|
||||
rdmsr
|
||||
shl rdx, 32
|
||||
|
||||
Reference in new issue
Block a user