fix(kernel): 用户异常终止不再提前 swapgs,避免拖垮整机
用户态 #PF 的终止路径直接从 ISR 调用 _yield,不经过 ISR 出口。 原实现在 _yield 前把 GS_BASE swap 回 0;但下一个被调度的线程如果是 从用户态 timer IRQ 或 syscall 挂起的,它的恢复路径会自己 swapgs 回 0。 提前 swap 会让它 swap 反,下一次系统调用用 gs:[8] 取内核栈时读到 线性地址 8,进而三重故障/整机卡死。 - 删除终止路径的 swapgs 块,保持 ISR 入口后的 GS 视图,与其他 timer/syscall 让出路径一致 - 先置 THREAD_DONE 再 free_user_thread,与 Scheduler.exit_current_thread 的次序一致,避免“资源已释放但 state 仍是 RUNNING”的再调度窗口
This commit is contained in:
1 parent
f9e91a9d6e
commit
b6ea47277c
1 file changed
+9
-16
@@ -302,23 +302,16 @@ def isrCommonhandler(interrupt: int):
|
||||
buf2: [64]char
|
||||
viperlib.snprintf(&buf2, 64, " exc in tid=%d, terminating\n", tid)
|
||||
serial.puts(buf2)
|
||||
# 用户线程被异常终止时回收其用户栈等资源(主线程/内核线程没有对应槽位,自动跳过)。
|
||||
proc.free_user_thread(proc.find_user_slot_by_tid(tid))
|
||||
# 用户线程被异常终止:**先**标 DONE,**再**回收资源(与
|
||||
# Scheduler.exit_current_thread 的次序一致)。反过来的话,在
|
||||
# “用户栈已释放、state 仍为 RUNNING”的窗口里若发生一次再调度,
|
||||
# 本线程会被再次选中并带着失效上下文回用户态。
|
||||
s.threads[tid].state = 3
|
||||
# Restore GS to kernel-normal state before _yield().
|
||||
# ISR entry does swapgs for user-mode exceptions (GS_BASE=&_per_cpu).
|
||||
# Since _yield() switches to another thread and never returns via ISR exit,
|
||||
# the swapgs at ISR exit is never executed. We must swap back here.
|
||||
# Check IA32_GS_BASE (MSR 0xC0000101): if non-zero, swapgs was done at entry.
|
||||
__asm__(f"""mov ecx, 0xC0000101
|
||||
rdmsr
|
||||
shl rdx, 32
|
||||
or rax, rdx
|
||||
test rax, rax
|
||||
jz 1f
|
||||
swapgs
|
||||
1:""",
|
||||
op=[ASM_DESCR.CLOBBER_RAX, ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX])
|
||||
proc.free_user_thread(proc.find_user_slot_by_tid(tid))
|
||||
# 本路径直接 _yield,不经过 ISR 出口。**不要**在这里 swapgs 回 GS_BASE=0:
|
||||
# 被切到的线程如果是从用户态 timer ISR / syscall 挂起的,它的恢复路径会
|
||||
# 自己 swapgs 回用户态 GS;这里提前 swap 会让它 swap 反,下一次系统调用
|
||||
# 用 gs:[8] 取内核栈时读到线性地址 8,直接三重故障。
|
||||
# 【修复】本路径是从**异常上下文**进来(用户态异常时 CPU 已把 IF 清 0),而且这里
|
||||
# **永不 iretq 返回**(直接 _yield 换线程)⇒ 若不在这里开中断,被切到的线程就会带着
|
||||
# "中断关着"继续跑 ⇒ 定时器再也进不来 ⇒ 整机卡死;后续再出异常就是三重故障。
|
||||
|
||||
Reference in new issue
Block a user