From: Andrew Cooper <andrew.cooper3@citrix.com>
To: Jan Beulich <JBeulich@suse.com>
Cc: "xen-devel@lists.xen.org" <xen-devel@lists.xen.org>
Subject: Re: [PATCH 3 of 4 RFC] x86/nmi: Prevent reentrant execution of the C nmi handler
Date: Wed, 5 Dec 2012 10:47:41 +0000 [thread overview]
Message-ID: <50BF264D.9040804@citrix.com> (raw)
In-Reply-To: <50BF202502000078000AE0E8@nat28.tlf.novell.com>
On 05/12/12 09:21, Jan Beulich wrote:
>>>> On 04.12.12 at 19:16, Andrew Cooper <andrew.cooper3@citrix.com> wrote:
>> The (old) function do_nmi() is not reentrantly-safe. Rename it to
>> _do_nmi() and present a new do_nmi() which reentrancy guards.
>>
>> If a reentrant NMI has been detected, then it is highly likely that the
>> outer NMI exception frame has been corrupted, meaning we cannot return
>> to the original context. In this case, we panic() obviously rather than
>> falling into an infinite loop.
>>
>> panic() however is not safe to reenter from an NMI context, as an NMI
>> (or MCE) can interrupt it inside its critical section, at which point a
>> new call to panic() will deadlock. As a result, we bail early if a
>> panic() is already in progress, as Xen is about to die anyway.
>>
>> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
>>
>> --
>> I am fairly sure this is safe with the current kexec_crash functionality
>> which involves holding all non-crashing pcpus in an NMI loop. In the
>> case of reentrant NMIs and panic_in_progress, we will repeatedly bail
>> early in an infinite loop of NMIs, which has the same intended effect of
>> simply causing all non-crashing CPUs to stay out of the way while the
>> main crash occurs.
>>
>> diff -r 48a60a407e15 -r f6ad86b61d5a xen/arch/x86/traps.c
>> --- a/xen/arch/x86/traps.c
>> +++ b/xen/arch/x86/traps.c
>> @@ -88,6 +88,7 @@ static char __read_mostly opt_nmi[10] =
>> string_param("nmi", opt_nmi);
>>
>> DEFINE_PER_CPU(u64, efer);
>> +static DEFINE_PER_CPU(bool_t, nmi_in_progress) = 0;
>>
>> DEFINE_PER_CPU_READ_MOSTLY(u32, ler_msr);
>>
>> @@ -3182,7 +3183,8 @@ static int dummy_nmi_callback(struct cpu
>>
>> static nmi_callback_t nmi_callback = dummy_nmi_callback;
>>
>> -void do_nmi(struct cpu_user_regs *regs)
>> +/* This function should never be called directly. Use do_nmi() instead. */
>> +static void _do_nmi(struct cpu_user_regs *regs)
>> {
>> unsigned int cpu = smp_processor_id();
>> unsigned char reason;
>> @@ -3208,6 +3210,44 @@ void do_nmi(struct cpu_user_regs *regs)
>> }
>> }
>>
>> +/* This function is NOT SAFE to call from C code in general.
>> + * Use with extreme care! */
>> +void do_nmi(struct cpu_user_regs *regs)
>> +{
>> + bool_t * in_progress = &this_cpu(nmi_in_progress);
>> +
>> + if ( is_panic_in_progress() )
>> + {
>> + /* A panic is already in progress. It may have reenabled NMIs,
>> + * or we are simply unluckly to receive one right now. Either
>> + * way, bail early, as Xen is about to die.
>> + *
>> + * TODO: Ideally we should exit without executing an iret, to
>> + * leave NMIs disabled, but that option is not currently
>> + * available to us.
> You could easily provide the ground work for this here by having
> the function return a bool_t (even if not immediately consumed by
> the caller in this same patch).
>
> Jan
Will do. I had considered a bool_t and was planning to integrate it
later in development.
~Andrew
>
>> + */
>> + return;
>> + }
>> +
>> + if ( test_and_set_bool(*in_progress) )
>> + {
>> + /* Crash in an obvious mannor, as opposed to falling into
>> + * infinite loop because our exception frame corrupted the
>> + * exception frame of the previous NMI.
>> + *
>> + * TODO: This check does not cover all possible cases of corrupt
>> + * exception frames, but it is substantially better than
>> + * nothing.
>> + */
>> + console_force_unlock();
>> + show_execution_state(regs);
>> + panic("Reentrant NMI detected\n");
>> + }
>> +
>> + _do_nmi(regs);
>> + *in_progress = 0;
>> +}
>> +
>> void set_nmi_callback(nmi_callback_t callback)
>> {
>> nmi_callback = callback;
>>
>> _______________________________________________
>> Xen-devel mailing list
>> Xen-devel@lists.xen.org
>> http://lists.xen.org/xen-devel
>
>
--
Andrew Cooper - Dom0 Kernel Engineer, Citrix XenServer
T: +44 (0)1223 225 900, http://www.citrix.com
next prev parent reply other threads:[~2012-12-05 10:47 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-12-04 18:16 [PATCH 0 of 4 RFC] Kexec path alteration Andrew Cooper
2012-12-04 18:16 ` [PATCH 1 of 4 RFC] x86/kexec: Change NMI and MCE handling on kexec path Andrew Cooper
2012-12-04 18:25 ` Andrew Cooper
2012-12-05 9:17 ` Jan Beulich
2012-12-05 10:05 ` Andrew Cooper
2012-12-06 11:36 ` Tim Deegan
2012-12-06 11:58 ` Andrew Cooper
2012-12-04 18:16 ` [PATCH 2 of 4 RFC] xen/panic: Introduce panic_in_progress Andrew Cooper
2012-12-04 18:16 ` [PATCH 3 of 4 RFC] x86/nmi: Prevent reentrant execution of the C nmi handler Andrew Cooper
2012-12-05 9:21 ` Jan Beulich
2012-12-05 10:47 ` Andrew Cooper [this message]
2012-12-06 11:39 ` Tim Deegan
2012-12-04 18:16 ` [PATCH 4 of 4 RFC] xen/nmi: DO NOT APPLY: debugkey to deliberatly invoke a reentrant NMI Andrew Cooper
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=50BF264D.9040804@citrix.com \
--to=andrew.cooper3@citrix.com \
--cc=JBeulich@suse.com \
--cc=xen-devel@lists.xen.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.