是否有任何CPU状态位指示处于x86和x86-64中的异常/中断处理程序中? [英] Are there any CPU-state bits indicating being in an exception/interrupt handler in x86 and x86-64?

查看:75
本文介绍了是否有任何CPU状态位指示处于x86和x86-64中的异常/中断处理程序中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

x86 x86-64 中是否有任何 CPU状态位指示处于异常/中断处理程序中?换句话说,我们能否仅基于 CPU 寄存器的状态来判断当前是否正在执行主线程或异常处理程序?

Are there any CPU-state bits indicating being in an exception/interrupt handler in x86 and x86-64? In other words, can we tell whether the main thread or exception handler is currently executed based only on the CPU registers' state?

推荐答案

不,CPU本身(例如控制寄存器)中没有位表示我们在异常或中断处理程序中".

Not, there's no bit in the CPU itself (e.g. a control register) that means "we're in an exception or interrupt handler".

但是存在隐藏状态,表明您正在使用NMI(不可屏蔽中断)处理程序.由于无法通过禁用中断来阻止它们,并且NMI的不可嵌套的任意嵌套会带来不便,因此除非运行 iret ,否则其他NMI不会交付.即使在NMI处理程序中发生异常(如 #DE div乘以0),该异常处理程序本身也会以 iret 返回,即使您没有完成NMI的处理.请参阅LWN上的 x86 NMI iret问题.

But there is hidden state indicating that you're in an NMI (Non-Maskable Interrupt) handler. Since you can't block them by disabling interrupts, and unblockable arbitrary nesting of NMIs would be inconvenient, another NMI won't get delivered until you run an iret. Even if an exception (like #DE div by 0) happens during an NMI handler, and that exception handler itself returns with iret even if you're not done handling the NMI. See The x86 NMI iret problem on LWN.

对于普通中断,如果您不希望在处理该中断时传递另一个中断,则可以禁用中断( cli ).

For normal interrupts, you can disable interrupts (cli) if you don't want another interrupt to be delivered while this one is being handled.

但是,当您处理完外部中断后,可能需要告知中断控制器(逻辑上在CPU内核之外,但实际上是现代CPU的一部分).(不是软件中断或异常). https://wiki.osdev.org/IDT_problems#I_can_only_receive_one_IRQ 显示 outb 说明,以使旧版PIC保持满意状态.(我不知道这是否适用于更现代的中断方式,例如MSI-X消息信号中断.OSdev Wiki页面的该部分可能特定于玩具OS,这些玩具OS使BIOS可以模仿旧的IBM-PC东西.)但这两种方式都仅用于外部中断,例如PS/2键盘控制器,硬盘驱动器DMA已完成,或发生了什么(不是异常),因此它与您的是否在异常处理程序内执行Linux系统调用?问题.

However, the interrupt controller (logically outside the CPU core, but actually part of modern CPUs) may need to be told when you're done handling an external interrupt. (Not a software-interrupt or exception). https://wiki.osdev.org/IDT_problems#I_can_only_receive_one_IRQ shows the outb instructions needed to keep the legacy PIC happy. (I don't know if this applies to more modern ways of doing interrupts, like MSI-X message-signalled interrupts. That part of the OSdev wiki page might be specific to toy OSes that let the BIOS emulate legacy IBM-PC stuff.) But either way, that's only for external interrupts like PS/2 keyboard controller, hard drive DMA complete, or whatever (not exceptions), so it's unrelated to your Are Linux system calls executed inside an exception handler? question.

缺少异常状态意味着您无需运行任何特殊指令即可确认"消息.从中断处理程序调用 schedule()之前的异常.您要做的就是确保在应该或不应该使用中断时启用或不启用中断.( sti / cli pushf / popf 可以保存/恢复旧的中断状态.)当然您的软件数据结构保持一致并适合您的工作.但是,您无需做任何特别的事情即可使CPU保持快乐状态.

The lack of exception-state means there's no special instruction you have to run to "acknowledge" an exception before calling schedule() from what was an interrupt handler. All you have to do is make sure interrupts are enabled or not when they should or shouldn't be. (sti / cli, or pushf / popf to save/restore the old interrupt state.) And of course that your software data structures remain consistent and appropriate for what you're doing. But there isn't anything you have to do specifically to keep the CPU happy.

这与用户空间不同,在信号处理程序中,信号处理程序应该告诉操作系统它已经完成,而不是仅仅跳到某个地方并无限期地运行.(在Linux中,信号处理程序可以修改主线程程序计数器,因此 sigreturn(2)可以从交付时的其他位置恢复执行.)如果POSIX或Linux发出信号是您想知道的用于中断/异常的(心理)模型,不是,不是那样的.

It's not like with user-space where a signal handler should tell the OS it's done instead of just jumping somewhere and running indefinitely. (In Linux, a signal handler can modify the main-thread program-counter so sigreturn(2) resumes execution somewhere other than where you were when it was delivered.) If POSIX or Linux signals were the (mental) model you were wondering about for interrupts/exceptions, no, it's not like that.

有一个中断优先级机制(x86-64中的CR8或LAPIC TPR(任务优先级寄存器)),但是当CPU发出中断时,它不会自动被置位.您可以设置一次(例如,如果您要在此内核上处理许多高优先级的中断),并且该中断会在各个中断之间持续存在.(如何使用CR8寄存器优先处理x86-64 CPU中的中断?).

There is an interrupt-priority mechanism (CR8 in x86-64, or the LAPIC TPR (Task Priority Register)), but it does not automatically get set when the CPU delivers an interrupt. You can set it once (e.g. if you have a lot of high-priority interrupts to process on this core) and it persists across interrupts. (How is CR8 register used to prioritize interrupts in an x86-64 CPU?).

这只是一个过滤器,用于确定在启用中断( sti ,RFLAGS中的IF = 1位)时可以将哪些中断号传递给该内核.Windows显然使用了它,或早在2007年,但Linux没有(或没有).

It's just a filter on what interrupt-numbers can get delivered to this core when interrupts are enabled (sti, IF=1 bit in RFLAGS). Apparently Windows makes some use of it, or did back in 2007, but Linux doesn't (or didn't).

这不像您必须告诉CPU/LAPIC该中断已完成,因此可以传递另一个具有此优先级或更低优先级的中断是可以的.

It's not like you have to tell the CPU / LAPIC that you're done with this interrupt so it's ok for it to deliver another interrupt of this or lower priority.

这篇关于是否有任何CPU状态位指示处于x86和x86-64中的异常/中断处理程序中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆