当内核堆栈的 esp 存储到 TSS 用于中断 return iret?

When kernel stack's esp is stored to TSS for interrupt return iret?

当我阅读 Intel 的 X86 程序员手册时,请参阅以下中断和中断 return 堆栈切换:

中断:

如果确实发生堆栈切换,处理器将执行以下操作:

  1. 临时保存(内部)SS、ESP、EFLAGS、CS 和 EIP 寄存器的当前内容。
  2. 从 TSS 将新堆栈(即被调用特权级别的堆栈)的段选择器和堆栈指针加载到 SS 和 ESP 寄存器和开关中到新堆栈。
  3. 将临时保存的中断过程堆栈的 SS、ESP、EFLAGS、CS 和 EIP 值压入新堆栈。
  4. 将错误代码压入新堆栈(如果适用)。
  5. 将新代码段的段选择器和新指令指针(从中断门或陷阱门)分别加载到 CS 和 EIP 寄存器中。
  6. 如果调用是通过中断门进行的,则清除 EFLAGS 寄存器中的 IF 标志。
  7. 开始在新的特权级别执行处理程序。

在 return:

  1. 执行权限检查。
  2. 将 CS 和 EIP 寄存器恢复到它们在中断或异常之前的值。
  3. 恢复 EFLAGS 寄存器。
  4. 将 SS 和 ESP 寄存器恢复到中断或异常之前的值,导致堆栈切换回中断过程的堆栈。
  5. 恢复执行中断的程序。

例如,一个linux进程P:

  1. 它最初处于内核模式
  2. 它 return 由 iret 进入用户模式。但是从手册上看,TSS没有变化
  3. 它被 int 困在内核中。这里需要从TSS中的ESP & SS找到内核栈。这个内核堆栈值是如何设置的,因为它们没有在步骤 2 中存储到 TSS?

一旦内核returns为用户space指定任务,它就完成了该任务的内核堆栈,直到下一个中​​断/异常。它上面没有有用的数据,因此 TSS 可以保存一个固定的 SS:[ER]SP 值,该值指向分配为 current 任务的内核堆栈的虚拟页面 [s] 的顶部。

内核状态并不存在于内核条目之间的内核堆栈中;它保存在进程控制块的其他地方。 (请求之间的上下文切换实际上发生在内核中,将内核堆栈切换到以前休眠任务的内核堆栈,因此最终返回到 user-space 意味着返回该任务在内核中执行的任何调用链第一个)。

顺便说一句,除非内核为 iret 推送新的 CS:EIP / EFLAGS / SS:ESP 弹出,否则它弹出的内容将是硬件在指定地址推送的内容在 TSS 中。因此,即使有些人希望在您离开时使用堆栈重新进入内核,但通常无论如何都会在 TSS 位置。但这无关紧要,因为 Linux 不会 在任务的内核堆栈上保留内容,而 user-space 是 运行,除了指向的指针区域底部的每个任务的东西,内核可以用 [ER]SP & -16384.

找到它

(我认为这是对的;我看过一些 Linux 内核代码,但还没有真正动手试验过。我 认为 这就是 Linux 的工作方式,也是一个一致的可行设计。)