x86 32位保护模式下TSS使用及中断运行相关技术问题咨询
问题1解答
你当前的中断是同特权级触发的:中断处理程序和内核都运行在0环,CPU处理这类中断时不需要切换特权级,自然不需要访问TSS。
同特权级中断的执行逻辑和你猜测的完全一致:CPU会自动把EIP、CS、EFLAGS、(如果有错误码则压错误码)压入当前栈,执行iret时再按顺序弹出恢复,全程用当前的SS和ESP操作,完全不涉及TSS。只有当中断需要从低特权级(比如3环用户态)切换到高特权级(0环内核态)时,CPU才会从TSS中读取高特权级对应的栈指针完成栈切换。
补充:你提到的EPS应该是笔误,正确的寄存器是ESP。
问题2解答
是的,关联逻辑完全如你所说:
首先你需要在GDT中定义合法的TSS段描述符,之后执行ltr指令传入该TSS段的选择子,CPU会将该TSS段的基址、限长等信息加载到TR(任务寄存器)中。后续只要发生需要特权级切换的中断/异常,CPU会自动从TR指向的TSS中读取对应特权级的栈参数,完成栈切换。如果你的系统只运行在内核态没有用户态,即使加载了TSS,同特权级中断也不会触发TSS访问。
问题3解答
使用硬件上下文切换时是支持自动切回前一个TSS的,核心依赖TSS结构中的PrevTSS字段,而非你以为的不存在的next字段:
当你通过call/jmp指令跳转到一个TSS段描述符触发硬件上下文切换时,CPU会先把当前所有寄存器状态存入当前TR指向的旧TSS,再把目标TSS的寄存器加载到CPU,同时会把旧TSS的选择子写入新TSS的PrevTSS字段,完成上下文链路的拼接。当你在新任务中执行iret指令返回时,CPU会自动读取当前TSS的PrevTSS字段,切回对应的旧TSS执行。
不过要注意,现在主流操作系统基本都放弃了硬件上下文切换方案,改用软件手动保存/恢复寄存器上下文,灵活性更高,也更易维护。
内容的提问来源于stack exchange,提问作者Leosa99_

