From 1f2faf0db8fa33b4ae216bd5f39116236d5aff6e Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Wed, 14 Oct 2026 22:11:19 +0800 Subject: [PATCH] =?UTF-8?q?fix(vkernel):=20=E8=BF=9B=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E6=80=81=E5=89=8D=E5=BD=92=E4=B8=80=E5=8C=96=20GS=5FBASE?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=E7=BA=BF=E7=A8=8B=E4=BB=8E=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E6=80=81=E5=AE=9A=E6=97=B6=E5=99=A8=20ISR=20=E5=88=87=E5=87=BA?= =?UTF-8?q?=E5=90=8E=20GS=20=E7=8A=B6=E6=80=81=E9=94=99=E4=B9=B1=E5=AF=BC?= =?UTF-8?q?=E8=87=B4=E7=9A=84=E4=B8=89=E9=87=8D=E6=95=85=E9=9A=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根因:线程可能是在**别人的用户态定时器 ISR 里**被 _yield 切过来的(timer 路径不经 isrCommonhandler 的 GS 恢复,且切换后 ISR 出口的 swapgs 永不执行),此时 GS_BASE 仍 = _per_cpu。带着这个状态跑用户代码 ⇒ app 第一条 syscall 再 swapgs 就反了 ⇒ mov rsp,gs:[0x8] 读到地址 0x8 的垃圾 ⇒ rsp 变垃圾 ⇒ push 触发 #PF 时异常帧也压不进去 ⇒ 三重故障(QEMU 消失、零输出、ISR 入口探针都照不到)。现场:pid=1(Terminal) 正常、pid=2 起静默三崩。修复:drop_to_user_mode 在 iretq 前按 GS_BASE 是否为 0 决定是否 swapgs(幂等),保证用户代码一律以 GS_BASE=0 运行。 --- VKernel/Kernel/sched/process.vp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) 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