在“sti”之后执行“ret”不会启动中断

Executing "ret" after "sti" doesn't start interrupts

提问人:Akib Azmain Turja 提问时间:6/26/2021 最后编辑:Akib Azmain Turja 更新时间:6/28/2021 访问量:226

问:

我正在开发一个微内核。在我的内核中,有一个启用外部中断的函数。但它不起作用。然后我意识到导致问题的指令是后跟的。英特尔软件开发人员手册 说:stiret

如果 IF = 0,则在执行 STI 后,指令边界上的可屏蔽硬件中断仍处于抑制状态。(提供此指令的延迟效果是为了允许在从过程或子例程返回之前启用中断。例如,如果 STI 指令后跟 RET 指令,则允许 RET 指令在识别外部中断之前执行。如果 CLI 的执行紧随 STI 的执行,则无法识别中断。抑制在传递另一个事件(例如,异常)或执行下一个指令后结束。

因此,应该在指令之后启用中断,但这不会发生。IF in eflags 在集合中,但没有外部中断。如果我在 和 之间放置一条指令,一切正常。retnopstiret

最小可重复示例:

        asm volatile ("call 1f;"
                      "jmp 2f;"
                      "1:"
                      "sti;"
//                      "nop;"
                      "ret;"
                      "2:");

取消注释,中断将被启用。此外,如果我在上面的后面放置以下行之一,则会中断工作:nop

        asm volatile ("jecxz 1f; 1:");
        asm volatile ("pushf; popf");

注意:我正在使用 QEMU 来运行我的内核。

汇编 x86 中断 qemu

评论

1赞 CherryDT 6/26/2021
你如何确定它不会发生?如果在返回后执行并输出推送的标志(或在调试器中查看标志),是否设置了 IF?pushf
3赞 Nate Eldredge 6/26/2021
你确定它是一个而不是一个?retiret
2赞 Peter Cordes 6/26/2021
是不是你造成了故障?(例如,返回到未映射的地址?甚至是非规范地址?还是带有错误片段选择器的远距离?但是,您是否希望在故障发生之前进行外部中断?如果你能做一个足够小的、有用的例子,那么一个最小的可重现的例子会很好,但肯定需要对你的测试用例进行更详细的描述。retret
2赞 Peter Cordes 6/26/2021
如果在 EFLAGS 中设置了 IF,则启用中断。你确定你没有以某种方式阻止大多数中断吗?比如 APIC/LAPIC 的可能中断优先级过滤器?如何使用 CR8 寄存器对 x86-64 CPU 中的中断进行优先级排序?讨论了 x86-64 如何通过 CR8 访问它,但它也可以通过 MMIO 或 APIC 上的 IO 端口或类似的东西访问。您是否尝试过在 BOCHS 的内置调试器中单步执行,以查看是否处理了挂起的中断?
2赞 Peter Cordes 6/26/2021
那么,听起来像是一个可能的 QEMU 错误。我不认为真正的硬件设置IF是合理的(如果你用popf阅读它),但表现得好像不是。除非内核的其余部分某处存在错误。

答: 暂无答案