diff --git a/VKernel/Kernel/sched/process.vp b/VKernel/Kernel/sched/process.vp index aec76e5..a215532 100644 --- a/VKernel/Kernel/sched/process.vp +++ b/VKernel/Kernel/sched/process.vp @@ -242,6 +242,21 @@ def drop_to_user_mode(entry: rawptr, user_rsp: uint64, kern_rsp: uint64): # GS state is restored in isrCommonhandler before _yield() if needed. __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 + or rax, rdx + test rax, rax + jz 1f + swapgs + 1: mov rdx, {asminp(user_rsp, ASM_DESCR.REG_ANY)} mov rcx, {asminp(entry, ASM_DESCR.REG_ANY)} mov r11, 0x202