[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH V2] xen: vmx: Use an INT 2 call to process real NMI's instead of self_nmi() in VMEXIT handler


At 10:06 +0000 on 14 Nov (1352887560), Jan Beulich wrote:
> > +            asm volatile("int $2"); /* Real NMI, vector 2: normal 
> > processing */
> And I still don't like this use of "int $2" here: An aspect we didn't
> consider so far is that a nested MCE would break things again

OK, I think I understand the problem[s], but I'm going to spell it out
slowly so you can correct me. :)

[ tl;dr I agree that do_nmi() is better, and we should do that in this
  patch, but maybe we need to solve the general problem too. ]

On a PV guest, we have to use dedicated stacks for NMI and MCE in case
either of those things happens just before SYSRET when we're on the user
stack (no other interrupt or exception can happen at that point).

On an AMD CPU we _don't_ have dedicated stacks for NMI or MCE when we're
running a HVM guest, so the stack issue doesn't apply (but nested NMIs
are still bad).

On an Intel CPU, we _do_ use dedicated stacks for NMI and MCE in HVM
guests.  We don't really have to but it saves time in the context switch
not to update the IDT.  Using do_nmi() here means that the first NMI is
handled on the normal stack instead.  It's also consistent with the way
we call do_machine_check() for the MCE case.  But it needs an explicit
IRET after the call to do_nmi() to make sure that NMIs get re-enabled.

These dedicated stacks make the general problem of re-entrant MCE/NMI
worse.  In the general case those handlers don't expect to be called in
a reentrant way, but blatting the stack turns a possible problem into a
definite one.


All of this would be moot except for the risk that we might take an MCE
while in the NMI handler.  The IRET from the MCE handler re-enables NMIs
while we're still in the NMI handler, and a second NMI arriving could
break the NMI handler.  In the PV case, it will also clobber the NMI
handler's stack.  In the VMX case we would need to see something like
(NMI (MCE) (NMI (MCE) (NMI))) for that to happen, but it could.

The inverse case, taking an NMI while in the MCE handler, is not very
interesting.  There's no masking of MCEs so that handler already has to
deal with nested entry, and the IRET from the NMI handler has no effect.

We could potentially solve the problem by having the MCE handler check
whether it's returning to the NMI stack, and do a normal return in that
case.  It's a bit of extra code but only in the MCE handler, which is
not performance-critical. 

If we do that, then the choice of 'int $2' vs 'do_nmi(); fake_iret()'
is mostly one of taste.  do_nmi() saves an IDT indirection but
unbalances the call/return stack.  I slightly prefer 'int $2' just
because it makes the PV and non-PV cases more similar.

But first, we should take the current fix, with do_nmi() and iret() 
instead of 'int $2'.  The nested-MCE issue can be handled separately.

Does that make sense?


Xen-devel mailing list



Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.