Lew*_*sey 4 x86 pipeline intel interrupt-handling
读完这篇文章后:
关于软件中断会发生什么情况的信息并不多,但我们确实了解到以下内容:
相反,异常(例如页面错误)会标记受影响的指令。当该指令即将提交时,异常之后的所有后续指令都将被刷新,并且指令获取将被重定向。
我想知道管道中的软件中断(INT 0xX)会发生什么,首先,它们何时被检测到?它们是否可能在预解码阶段被检测到?在指令队列中?在解码阶段?或者他们到达后端并立即完成(不进入保留站),依次退休,退休阶段发现这是一条 INT 指令(看起来很浪费)。
假设它在预解码时被拾取,必须有一种方法向 IFU 发出信号以停止获取指令,或者确实对其进行时钟/电源门控,或者如果它在指令队列中被拾取,则必须有一种在队列中之前刷新指令的方法。然后必须有一种方法向某种逻辑(“控制单元”)发出信号,例如为软件中断生成微指令(索引到 IDT、检查 DPL >=CPL >=段 RPL 等),天真的建议,但如果有人更好地了解这个过程,那就太好了。
我还想知道当这个过程受到干扰时它如何处理它,即发生硬件中断(记住陷阱不会清除 EFLAGS 中的 IF),现在必须开始一个全新的中断处理和 uop 生成过程,它将如何处理之后回到处理软件中断的状态。
我同意彼得在回答中所说的一切。虽然可以通过多种方式来实现INTn指令,但最有可能针对 CPU 设计的简单性而不是性能来调整实现。可以非推测性地确定这样的指令存在的最早点是在流水线的解码阶段的末尾。也许可以预测所获取的字节是否可能包含可能或确实引发异常的指令,但我找不到一篇研究这个想法的研究论文,所以它似乎不值得。
的执行INTn涉及从IDT中获取指定条目,执行许多检查,计算异常处理程序的地址,然后告诉获取单元从那里开始预取。这个过程取决于处理器的操作模式(实模式、64位模式等)。CR0该模式由、CR4和寄存器中的多个标志来描述Eflags。因此,实际调用异常处理程序将需要许多微指令。在Skylake中,有4个简单解码器和1个复杂解码器。简单的解码器只能发出单个融合的微指令。复杂的解码器最多可以发出 4 个融合的微指令。它们都无法处理INTn,因此需要使用 MSROM 才能执行软件中断。请注意,INTn指令本身可能会导致异常。此时,尚不清楚INTn其自身是否会将控制权更改为指定的异常处理程序(无论其地址是什么)或其他异常处理程序。可以肯定的是,指令流肯定会INTn在其他地方结束并开始。
激活微码定序器有两种可能的方式。第一个是解码需要4个以上uop的宏指令时,类似于rdtsc. 第二个是当退出指令并且至少其微指令在其 ROB 条目中具有有效事件代码时。根据该专利,有一个专门用于软件中断的事件代码。所以我认为INTn被解码成一个携带中断向量的单个微指令(或最多 4 个微指令)。ROB 已经需要有一个字段来保存描述相应指令是否引发异常以及异常类型的信息。同一字段可用于保存中断向量。uop 只是简单地通过分配阶段,并且可能不需要被调度到执行单元之一,因为不需要进行计算。当 uop 即将退休时,ROB 确定它已经退休INTn并且应该引发一个事件(参见专利中的图 10)。此时,有两种可能的方式进行:
在执行assist的过程中,可能会出现异常。这将像任何其他导致异常的指令一样进行处理。ROB 单元从 ROB 中提取异常描述并调用辅助来处理它。
无效的操作码可以用类似的方式处理。在预编码阶段,唯一重要的是正确确定无效操作码之前指令的长度。在这些有效指令之后,边界就变得无关紧要了。当简单解码器收到无效操作码时,它会发出一个特殊的微指令,其唯一目的只是引发无效操作码异常。负责最后一个有效指令之后的指令的其他解码器都可以发出特殊的微指令。由于指令按顺序退出,因此可以保证第一个特殊微操作会引发异常。当然,除非前一个 uop 引发异常或发生分支错误预测或内存排序清除事件。
当任何解码器发出该特殊微指令时,获取和解码阶段可能会停止,直到确定宏指令异常处理程序的地址为止。这可能是针对 uop 指定的异常,也可能是针对某些其他异常。对于处理该特殊 uop 的每个阶段,该阶段都可以自行停止(断电/时钟门控)。这可以节省电力,而且我认为这很容易实现。
或者,如果另一个逻辑核心处于活动状态,则像该逻辑线程将其前端周期放弃给另一个超线程的任何其他原因一样对待它。分配周期通常在超线程之间交替,但当一个线程停止时(例如 ROB 已满或前端为空),另一个线程可以在连续周期中进行分配。这也可能发生在解码器中,但是也许可以使用足够大的代码块进行测试以阻止它从 uop 缓存运行。(或者太密集而无法进入微指令缓存)。