diff options
-rw-r--r-- | sys/i386/i386/exception.s | 29 |
1 files changed, 27 insertions, 2 deletions
diff --git a/sys/i386/i386/exception.s b/sys/i386/i386/exception.s index 2e69ab8..6a45179 100644 --- a/sys/i386/i386/exception.s +++ b/sys/i386/i386/exception.s @@ -78,8 +78,6 @@ IDTVEC(div) pushl $0; TRAP(T_DIVIDE) IDTVEC(dbg) pushl $0; TRAP(T_TRCTRAP) -IDTVEC(nmi) - pushl $0; TRAP(T_NMI) IDTVEC(bpt) pushl $0; TRAP(T_BPTFLT) IDTVEC(ofl) @@ -215,6 +213,33 @@ ENTRY(fork_trampoline) MEXITCOUNT jmp doreti +/* + * NMI handling is somewhat special: NMI interrupts may be taken at + * any time, including when the processor has turned off external + * interrupts by clearing EFLAGS.IF. This means that the kernel's + * internal state could be inconsistent at the time of the interrupt, + * and it is not safe to call "ast()" as is done in the exit path + * for normal interrupts. + * + * The NMI handler therefore invokes the C language routine "trap()" + * and directly jumps to 'doreti_exit'. + */ +IDTVEC(nmi) + /* create a trap frame */ + pushl $0 + pushl $T_NMI + pushal + pushl %ds + pushl %es + pushl %fs + movl $KDSEL,%eax + movl %eax,%ds + movl %eax,%es + movl $KPSEL,%eax + movl %eax,%fs + FAKE_MCOUNT(TF_EIP(%esp)) + call trap + jmp doreti_exit /* * To efficiently implement classification of trap and interrupt handlers |