fix(vkernel/intr): ISR 用户返回同时接受 CS=0x2B(sysretq 选择子),修“用户态一被中断就 cli;hlt 假死”
- 现象:日志尾部只有 "B 2B 23",随后整机假死(QEMU 窗口消失、没有 dump) - 根因:isr\num\()_ret_user 硬编码校验 CS==0x1B;但 app 只要发过一次 syscall,返回走 sysretq 后 CS 就是 STAR[63:48]=0x1B 算出的 0x2B(SS=0x23)→ 之后任何用户态中断/异常(例如定时器抢占)都被判“坏 CS/SS” → 走 cli;hlt 死循环,既假死又掩盖真实异常现场 - 现在同时接受 0x1B 与 0x2B(SS 仍须 0x23);注释里记录 GDT/STAR 隐患:0x2B 当前指向 GDT 第 5 项,而那里是 TSS(QEMU 不校验 SYSRET 目标描述符类型才没暴露),根治需把用户代码段挪到第 5 项
This commit is contained in:
1 parent
c232c0c0d5
commit
79e9dfd5a4
1 file changed
+12
-2
@@ -189,10 +189,20 @@ isr\num\()_ret_user:
|
||||
mov al, 0x4E # 'N' marker = NT was set (now cleared)
|
||||
out dx, al
|
||||
1:
|
||||
cmp r9, 0x1B
|
||||
jne 8f
|
||||
# 用户态 CS 必须同时接受两个值(本内核两条入口路径给的不一样):
|
||||
# 0x1B — drop_to_user_mode 首次 iretq 进用户态时压的 CS(= USER_CODE_SEG 0x18 | RPL3)
|
||||
# 0x2B — syscall 返回走 sysretq:STAR[63:48]=0x1B ⇒ 硬件算 CS=+16=0x2B、SS=+8=0x23
|
||||
# 原来只认 0x1B:app 只要发过一次 syscall,之后任何用户态**中断/异常**(例如定时器抢占)
|
||||
# 都被判“坏 CS/SS”,打印 "B 2B 23" 后 cli;hlt 死机 —— 既假死,又掩盖真正的用户态异常现场。
|
||||
# (另注:0x2B 指向 GDT 第 5 项,见 gdt.vp —— 那里目前放的是 TSS,属于 GDT/STAR 布局的
|
||||
# 隐患,QEMU 不校验 SYSRET 的目标描述符类型才没暴露;要根治需把用户代码段挪到第 5 项。)
|
||||
cmp r11, 0x23
|
||||
jne 8f
|
||||
cmp r9, 0x1B
|
||||
je 6f
|
||||
cmp r9, 0x2B
|
||||
jne 8f
|
||||
6:
|
||||
push r11 # SS
|
||||
push rax # RSP
|
||||
push r10 # RFLAGS
|
||||
|
||||
Reference in new issue
Block a user