From: Jacob Pan <jacob.jun.pan@linux.intel.com>
To: "H. Peter Anvin" <hpa@zytor.com>
Cc: X86 Kernel <x86@kernel.org>, LKML <linux-kernel@vger.kernel.org>,
Thomas Gleixner <tglx@linutronix.de>,
Dave Hansen <dave.hansen@intel.com>,
Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
linux-perf-users@vger.kernel.org,
Peter Zijlstra <peterz@infradead.org>,
Andi Kleen <andi.kleen@intel.com>, Xin Li <xin3.li@intel.com>,
jacob.jun.pan@linux.intel.com
Subject: Re: [PATCH v2 4/6] x86/irq: Process nmi sources in NMI handler
Date: Wed, 12 Jun 2024 14:54:24 -0700 [thread overview]
Message-ID: <20240612145424.61890aa3@jacob-builder> (raw)
In-Reply-To: <b2a230b0-3f00-49b3-87fb-63622f697395@zytor.com>
Hi H.,
On Tue, 11 Jun 2024 11:41:07 -0700, "H. Peter Anvin" <hpa@zytor.com> wrote:
> On 6/11/24 09:54, Jacob Pan wrote:
> > +
> > + source_bitmask = fred_event_data(regs);
> > + if (!source_bitmask) {
> > + pr_warn_ratelimited("NMI without source information!
> > Disable source reporting.\n");
> > + setup_clear_cpu_cap(X86_FEATURE_NMI_SOURCE);
> > + return 0;
> > + }
>
> Is setup_clear_cpu_cap() even meaningful here?
Right, alternative patching doesn't work here. Let me use a separate flag.
>
> > +
> > + /*
> > + * Per NMI source specification, there is no guarantee that a
> > valid
> > + * NMI vector is always delivered, even when the source
> > specified
> > + * one. It is software's responsibility to check all available
> > NMI
> > + * sources when bit 0 is set in the NMI source bitmap. i.e. we
> > have
> > + * to call every handler as if we have no NMI source.
> > + * On the other hand, if we do get non-zero vectors, we know
> > exactly
> > + * what the sources are. So we only call the handlers with the
> > bit set.
> > + */
> > + if (source_bitmask & BIT(NMI_SOURCE_VEC_UNKNOWN)) {
> > + pr_warn_ratelimited("NMI received with unknown
> > source\n");
> > + return 0;
> > + }
> > +
>
> You can still dispatch the known NMI handlers early before doing the
> polling.
True, my thinking was based on two conditions:
1. unknown NMI source is a rare/unlikely case
2. when unknown source does get set, it is due to deep CPU idle where
performance optimization is not productive.
So I think any optimization to the unlikely case should not add cost to the
common case. Tracking early/direct dispatched handler adds cost to the
common case. Below is my attempt, there must be a better way.
static int nmi_handle_src(unsigned int type, struct pt_regs *regs, unsigned long *handled_mask)
{
static bool nmi_source_disabled = false;
bool has_unknown_src = false;
unsigned long source_bitmask;
struct nmiaction *a;
int handled = 0;
int vec = 1;
if (!cpu_feature_enabled(X86_FEATURE_NMI_SOURCE) ||
type != NMI_LOCAL || nmi_source_disabled)
return 0;
source_bitmask = fred_event_data(regs);
if (!source_bitmask) {
pr_warn("NMI received without source information! Disable source reporting.\n");
nmi_source_disabled = true;
return 0;
}
/*
* Per NMI source specification, there is no guarantee that a valid
* NMI vector is always delivered, even when the source specified
* one. It is software's responsibility to check all available NMI
* sources when bit 0 is set in the NMI source bitmap. i.e. we have
* to call every handler as if we have no NMI source.
* On the other hand, if we do get non-zero vectors, we know exactly
* what the sources are. So we only call the handlers with the bit set.
*/
if (source_bitmask & BIT(NMI_SOURCE_VEC_UNKNOWN)) {
pr_warn_ratelimited("NMI received with unknown source\n");
has_unknown_src = true;
}
rcu_read_lock();
/* Bit 0 is for unknown NMI sources, skip it. */
for_each_set_bit_from(vec, &source_bitmask, NR_NMI_SOURCE_VECTORS) {
a = rcu_dereference(nmiaction_src_table[vec]);
if (!a) {
pr_warn_ratelimited("NMI received %d no handler", vec);
continue;
}
handled += do_handle_nmi(a, regs, type);
/*
* Needs polling if unknown source bit is set, handled_mask is
* used to tell the polling code which NMIs can be skipped.
*/
if (has_unknown_src)
*handled_mask |= BIT(vec);
}
rcu_read_unlock();
return handled;
}
static int nmi_handle(unsigned int type, struct pt_regs *regs)
{
struct nmi_desc *desc = nmi_to_desc(type);
unsigned long handled_mask = 0;
struct nmiaction *a;
int handled=0;
/*
* Check if the NMI source handling is complete, otherwise polling is
* still required. handled_mask is non-zero if NMI source handling is
* partial due to unknown NMI sources.
*/
handled = nmi_handle_src(type, regs, &handled_mask);
if (handled && !handled_mask)
return handled;
rcu_read_lock();
/*
* NMIs are edge-triggered, which means if you have enough
* of them concurrently, you can lose some because only one
* can be latched at any given time. Walk the whole list
* to handle those situations.
*/
list_for_each_entry_rcu(a, &desc->head, list) {
/* Skip NMIs handled earlier with source info */
if (BIT(a->source_vec) & handled_mask)
continue;
handled += do_handle_nmi(a, regs, type);
}
rcu_read_unlock();
/* return total number of NMI events handled */
return handled;
}
NOKPROBE_SYMBOL(nmi_handle);
> > + rcu_read_lock();
> > + /* Bit 0 is for unknown NMI sources, skip it. */
> > + for_each_set_bit_from(vec, &source_bitmask,
> > NR_NMI_SOURCE_VECTORS) {
> > + a = rcu_dereference(nmiaction_src_table[vec]);
> > + if (!a) {
> > + pr_warn_ratelimited("NMI received %d no
> > handler", vec);
> > + continue;
> > + }
> > + handled += do_handle_nmi(a, regs, type);
> > + }
> > + rcu_read_unlock();
> > + return handled;
> > +}
> > +
>
> That would mean that you would also need to return a bitmask of which
> source vectors need to be handled with polling.
Should it be the bitmask to be skipped by polling? see handled_mask in
the code above.
Thanks,
Jacob
next prev parent reply other threads:[~2024-06-12 21:49 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-06-11 16:54 Jacob Pan
2024-06-11 16:54 ` [PATCH v2 1/6] x86/irq: Add enumeration of NMI source reporting CPU feature Jacob Pan
2024-06-12 2:32 ` Xin Li
2024-06-12 2:50 ` H. Peter Anvin
2024-06-12 3:04 ` Xin Li
2024-06-21 23:00 ` Sohil Mehta
2024-06-28 5:00 ` Jacob Pan
2024-06-21 22:23 ` Sohil Mehta
2024-06-21 23:46 ` Jacob Pan
2024-06-22 1:08 ` Sohil Mehta
2024-06-27 22:23 ` Jacob Pan
2024-06-27 23:20 ` Sohil Mehta
2024-06-11 16:54 ` [PATCH v2 2/6] x86/irq: Extend NMI handler registration interface to include source Jacob Pan
2024-06-24 23:16 ` Sohil Mehta
2024-06-28 4:56 ` Jacob Pan
2024-06-11 16:54 ` [PATCH v2 3/6] x86/irq: Factor out common NMI handling code Jacob Pan
2024-06-11 16:54 ` [PATCH v2 4/6] x86/irq: Process nmi sources in NMI handler Jacob Pan
2024-06-11 18:41 ` H. Peter Anvin
2024-06-12 21:54 ` Jacob Pan [this message]
2024-06-24 23:38 ` Sohil Mehta
2024-06-24 23:53 ` Sohil Mehta
2024-06-11 16:54 ` [PATCH v2 5/6] perf/x86: Enable NMI source reporting for perfmon Jacob Pan
2024-06-11 19:10 ` H. Peter Anvin
2024-06-12 20:27 ` Jacob Pan
2024-06-11 16:54 ` [PATCH v2 6/6] x86/irq: Enable NMI source on IPIs delivered as NMI Jacob Pan
2024-06-12 2:04 ` Sean Christopherson
2024-06-12 2:55 ` Re: Xin Li
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=20240612145424.61890aa3@jacob-builder \
--to=jacob.jun.pan@linux.intel.com \
--cc=andi.kleen@intel.com \
--cc=bp@alien8.de \
--cc=dave.hansen@intel.com \
--cc=hpa@zytor.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=peterz@infradead.org \
--cc=tglx@linutronix.de \
--cc=x86@kernel.org \
--cc=xin3.li@intel.com \
/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.