lkml.org 
[lkml]   [2011]   [Dec]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
Subject[RFC] Latched NMI handler
Hi!

Given the recent interest for latched NMI handler providing the ability
to fault and take exception within NMI handlers, I thought it would be
good if I wrote down the pseudo-code I got stucked in my brain since
this last discussion with Linus on the topic about a year ago. Feedback
is welcome, and hopefully it will be useful to Steven who is starting to
work a solution.

variables used:

stack-local int nmi_nest_count;
stack-local int nmi_latch;
__nmi_epilogue_begin (pointer to text)
__nmi_epilogue_end (pointer to text)
REAL_NMI_STACK: beginning of the stack used for real nmi handler
LATCHED_NMI_STACK: beginning of the stack used for latched nmi handler

int in_nmi_epilogue(void)
{
return (instruction_pointer() >= __nmi_epilogue_begin
&& instruction_pointer() < __nmi_epilogue_end);
}

int in_nmi(void)
{
return nmi_nest_count > 0;
}

/* Use REAL_NMI_STACK */
real_nmi_handler: /* always running with nmis disabled */
/*
* We disable interrupts to ensure we don't have to deal with IRQs
* when NMIs get re-enabled due to an iret from a fault/exception.
*/
local_irq_disable();
if (in_nmi_epilogue()) {
nmi_latch = 0;
/* set stack pointer to start of LATCHED_NMI_STACK */
goto latched_nmi_handler;
}
if (in_nmi()) {
nmi_latch = 1;
iret
}
nmi_nest_count++;
/* set stack pointer to start of LATCHED_NMI_STACK */
goto latched_nmi_handler;


/* Use LATCHED_NMI_STACK */
latched_nmi_handler: /* Can fault and reenable NMIs. */

[ execute actual system NMI handler, including faults, int3, ... ]

/*
* note: test nmi_latch and iret instruction are within the
* epilogue range to deal with latch test vs iret non-atomicity. If a
* real nmi nests over this range, it clears the nmi_latch flag and
* just restarts the latched nmi handler. No
* faults/exceptions/interrupts are permitted in this region, except
* for the real NMI and MCEs (TODO).
*/
__nmi_epilogue_begin:
/*
* here we are restarting the latched nmi handler if an nmi happened
* while nested within the nmi nest count.
*/
if (nmi_latch) {
nmi_latch = 0;
goto latched_nmi_handler;
}
nmi_nest_count--;
iret /* restores interrupts */
__nmi_epilogue_end:

--
Mathieu Desnoyers
Operating System Efficiency R&D Consultant
EfficiOS Inc.
http://www.efficios.com


\
 
 \ /
  Last update: 2011-12-08 02:55    [W:0.072 / U:0.324 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site