[<prev] [next>] [day] [month] [year] [list]
Message-ID: <20111208015152.GA8337@Krystal>
Date: Wed, 7 Dec 2011 20:51:52 -0500
From: Mathieu Desnoyers <mathieu.desnoyers@...icios.com>
To: Linus Torvalds <torvalds@...ux-foundation.org>,
Steven Rostedt <rostedt@...dmis.org>
Cc: LKML <linux-kernel@...r.kernel.org>,
Ingo Molnar <mingo@...hat.com>,
Peter Zijlstra <peterz@...radead.org>,
"H. Peter Anvin" <hpa@...ux.intel.com>,
Frederic Weisbecker <fweisbec@...il.com>,
Thomas Gleixner <tglx@...utronix.de>,
Paul Turner <pjt@...gle.com>
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
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists