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?

- 959
- 5
- 15
-
1No, there is not. There is hidden state indicating being in an NMI handler, but it isn’t accessible by software. – prl Apr 21 '21 at 02:44
-
1If you wanted such an indication for a system you’re designing, you could use a distinct code segment descriptor for all of the entries in the IDT. – prl Apr 21 '21 at 02:45
-
@prl: for external interrupts (not exceptions), is `outb(0x20, 0x20)` to keep the PIC happy still relevant (https://wiki.osdev.org/IDT_problems#I_can_only_receive_one_IRQ), or is that only for old legacy ways of doing things? Or only for some kinds of interrupts? I wondered about that in my answer, feel free to edit or comment if you can simplify it to something accurate. – Peter Cordes Apr 21 '21 at 05:07
1 Answers
Not, there's no bit in the CPU itself (e.g. a control register) that means "we're in an exception or interrupt handler".
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.
For normal interrupts, you can disable interrupts (cli
) if you don't want another interrupt to be delivered while this one is being handled.
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.
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.
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.
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?).
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).
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.

- 328,167
- 45
- 605
- 847
-
1Thank you, a very comprehensive answer. Actually, I didn't have in mind POSIX/Linux signals but a typical microcontroller interrupt handlers, which are very similar to signal nadlers in some sense. And the fact that this model does not apply to system calls was something I actually wanted to have confirmed. – mrn Apr 21 '21 at 15:09