public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [RFC] Latched NMI handler
@ 2011-12-08  1:51 Mathieu Desnoyers
  0 siblings, 0 replies; only message in thread
From: Mathieu Desnoyers @ 2011-12-08  1:51 UTC (permalink / raw)
  To: Linus Torvalds, Steven Rostedt
  Cc: LKML, Ingo Molnar, Peter Zijlstra, H. Peter Anvin,
	Frederic Weisbecker, Thomas Gleixner, Paul Turner

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

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2011-12-08  1:51 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-12-08  1:51 [RFC] Latched NMI handler Mathieu Desnoyers

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox