From: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
To: Tony Luck <tony.luck@intel.com>,
Dave Hansen <dave.hansen@intel.com>,
"Rafael J. Wysocki" <rafael.j.wysocki@intel.com>,
Reinette Chatre <reinette.chatre@intel.com>,
Dan Williams <dan.j.williams@intel.com>,
Len Brown <len.brown@intel.com>
Cc: "Ravi V. Shankar" <ravi.v.shankar@intel.com>,
Andi Kleen <ak@linux.intel.com>,
Ricardo Neri <ricardo.neri-calderon@linux.intel.com>,
Ricardo Neri <ricardo.neri@intel.com>,
Stephane Eranian <eranian@google.com>,
linux-kernel@vger.kernel.org, iommu@lists.linux-foundation.org,
linuxppc-dev@lists.ozlabs.org
Subject: [PATCH v7 04/24] x86/apic/vector: Implement a local APIC NMI controller
Date: Wed, 1 Mar 2023 15:47:33 -0800 [thread overview]
Message-ID: <20230301234753.28582-5-ricardo.neri-calderon@linux.intel.com> (raw)
In-Reply-To: <20230301234753.28582-1-ricardo.neri-calderon@linux.intel.com>
Add a separate local APIC NMI controller to handle NMIs apart from the
regular APIC management.
This controller will be used to handle the NMI vector of the HPET NMI
watchdog.
Cc: Andi Kleen <ak@linux.intel.com>
Cc: "Ravi V. Shankar" <ravi.v.shankar@intel.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: iommu@lists.linux-foundation.org
Cc: linuxppc-dev@lists.ozlabs.org
Suggested-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
---
Changes since v6:
* Reworked patch "x86/apic/vector: Implement support for NMI delivery
mode" into a separate local APIC NMI controller. (Thomas)
Changes since v5:
* Introduced this patch.
Changes since v4:
* N/A
Changes since v3:
* N/A
Changes since v2:
* N/A
Changes since v1:
* N/A
---
arch/x86/kernel/apic/vector.c | 57 +++++++++++++++++++++++++++++++++++
include/linux/irq.h | 5 +++
2 files changed, 62 insertions(+)
diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c
index 633b442c8f84..a4cf041427cb 100644
--- a/arch/x86/kernel/apic/vector.c
+++ b/arch/x86/kernel/apic/vector.c
@@ -42,6 +42,7 @@ EXPORT_SYMBOL_GPL(x86_vector_domain);
static DEFINE_RAW_SPINLOCK(vector_lock);
static cpumask_var_t vector_searchmask;
static struct irq_chip lapic_controller;
+static struct irq_chip lapic_nmi_controller;
static struct irq_matrix *vector_matrix;
#ifdef CONFIG_SMP
static DEFINE_PER_CPU(struct hlist_head, cleanup_list);
@@ -451,6 +452,10 @@ static int x86_vector_activate(struct irq_domain *dom, struct irq_data *irqd,
trace_vector_activate(irqd->irq, apicd->is_managed,
apicd->can_reserve, reserve);
+ /* NMI has a fixed vector. No vector management required */
+ if (apicd->hw_irq_cfg.delivery_mode == APIC_DELIVERY_MODE_NMI)
+ return 0;
+
raw_spin_lock_irqsave(&vector_lock, flags);
if (!apicd->can_reserve && !apicd->is_managed)
assign_irq_vector_any_locked(irqd);
@@ -472,6 +477,10 @@ static void vector_free_reserved_and_managed(struct irq_data *irqd)
trace_vector_teardown(irqd->irq, apicd->is_managed,
apicd->has_reserved);
+ /* NMI has a fixed vector. No vector management required */
+ if (apicd->hw_irq_cfg.delivery_mode == APIC_DELIVERY_MODE_NMI)
+ return;
+
if (apicd->has_reserved)
irq_matrix_remove_reserved(vector_matrix);
if (apicd->is_managed)
@@ -539,6 +548,10 @@ static int x86_vector_alloc_irqs(struct irq_domain *domain, unsigned int virq,
if (disable_apic)
return -ENXIO;
+ /* Only one IRQ per NMI */
+ if ((info->flags & X86_IRQ_ALLOC_AS_NMI) && nr_irqs != 1)
+ return -EINVAL;
+
/*
* Catch any attempt to touch the cascade interrupt on a PIC
* equipped system.
@@ -573,6 +586,25 @@ static int x86_vector_alloc_irqs(struct irq_domain *domain, unsigned int virq,
/* Don't invoke affinity setter on deactivated interrupts */
irqd_set_affinity_on_activate(irqd);
+ if (info->flags & X86_IRQ_ALLOC_AS_NMI) {
+ /*
+ * NMIs have a fixed vector and need their own
+ * interrupt chip so nothing can end up in the
+ * regular local APIC management code except the
+ * MSI message composing callback.
+ */
+ apicd->hw_irq_cfg.delivery_mode = APIC_DELIVERY_MODE_NMI;
+ irqd->chip = &lapic_nmi_controller;
+ /*
+ * Exclude NMIs from balancing. This cannot work with
+ * the regular affinity mechanisms. The local APIC NMI
+ * controller provides a set_affinity() callback for the
+ * intended HPET NMI watchdog use case.
+ */
+ irqd_set_no_balance(irqd);
+ return 0;
+ }
+
/*
* A delivery mode may be specified in the interrupt allocation
* info. If not, use the delivery mode of the APIC.
@@ -872,8 +904,27 @@ static int apic_set_affinity(struct irq_data *irqd,
return err ? err : IRQ_SET_MASK_OK;
}
+static int apic_nmi_set_affinity(struct irq_data *irqd,
+ const struct cpumask *dest, bool force)
+{
+ struct apic_chip_data *apicd = apic_chip_data(irqd);
+ static struct cpumask tmp_mask;
+ int cpu;
+
+ cpumask_and(&tmp_mask, dest, cpu_online_mask);
+ if (cpumask_empty(&tmp_mask))
+ return -ENODEV;
+
+ cpu = cpumask_first(&tmp_mask);
+ apicd->hw_irq_cfg.dest_apicid = apic->calc_dest_apicid(cpu);
+ irq_data_update_effective_affinity(irqd, cpumask_of(cpu));
+
+ return IRQ_SET_MASK_OK;
+}
+
#else
# define apic_set_affinity NULL
+# define apic_nmi_set_affinity NULL
#endif
static int apic_retrigger_irq(struct irq_data *irqd)
@@ -914,6 +965,12 @@ static struct irq_chip lapic_controller = {
.irq_retrigger = apic_retrigger_irq,
};
+static struct irq_chip lapic_nmi_controller = {
+ .name = "APIC-NMI",
+ .irq_set_affinity = apic_nmi_set_affinity,
+ .irq_compose_msi_msg = x86_vector_msi_compose_msg,
+};
+
#ifdef CONFIG_SMP
static void free_moved_vector(struct apic_chip_data *apicd)
diff --git a/include/linux/irq.h b/include/linux/irq.h
index b1b28affb32a..c8738b36e316 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -263,6 +263,11 @@ static inline bool irqd_is_per_cpu(struct irq_data *d)
return __irqd_to_state(d) & IRQD_PER_CPU;
}
+static inline void irqd_set_no_balance(struct irq_data *d)
+{
+ __irqd_to_state(d) |= IRQD_NO_BALANCING;
+}
+
static inline bool irqd_can_balance(struct irq_data *d)
{
return !(__irqd_to_state(d) & (IRQD_PER_CPU | IRQD_NO_BALANCING));
--
2.25.1
next prev parent reply other threads:[~2023-03-01 23:43 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-03-01 23:47 [PATCH v7 00/24] x86: Implement an HPET-based hardlockup detector Ricardo Neri
2023-03-01 23:47 ` [PATCH v7 01/24] x86/apic: Add irq_cfg::delivery_mode Ricardo Neri
2023-03-01 23:47 ` [PATCH v7 02/24] x86/apic/msi: Use the delivery mode from irq_cfg for message composition Ricardo Neri
2023-03-01 23:47 ` [PATCH v7 03/24] x86/apic: Add the X86_IRQ_ALLOC_AS_NMI interrupt allocation flag Ricardo Neri
2023-03-01 23:47 ` Ricardo Neri [this message]
2023-03-01 23:47 ` [PATCH v7 05/24] x86/apic/vector: Skip cleanup for the NMI vector Ricardo Neri
2023-03-01 23:47 ` [PATCH v7 06/24] iommu/vt-d: Clear the redirection hint when the destination mode is physical Ricardo Neri
2023-03-01 23:47 ` [PATCH v7 07/24] iommu/vt-d: Rework prepare_irte() to support per-interrupt delivery mode Ricardo Neri
2023-03-01 23:47 ` [PATCH v7 08/24] iommu/vt-d: Set the IRTE delivery mode individually for each interrupt Ricardo Neri
2023-03-01 23:47 ` [PATCH v7 09/24] iommu/amd: Expose [set|get]_dev_entry_bit() Ricardo Neri
2023-03-01 23:47 ` [PATCH v7 10/24] iommu/amd: Enable NMIPass when allocating an NMI Ricardo Neri
2023-03-01 23:47 ` [PATCH v7 11/24] iommu/amd: Compose MSI messages for NMIs in non-IR format Ricardo Neri
2023-03-01 23:47 ` [PATCH v7 12/24] x86/hpet: Expose hpet_writel() in header Ricardo Neri
2023-03-01 23:47 ` [PATCH v7 13/24] x86/hpet: Add helper function hpet_set_comparator_periodic() Ricardo Neri
2023-03-01 23:47 ` [PATCH v7 14/24] x86/hpet: Prepare IRQ assignments to use the X86_ALLOC_AS_NMI flag Ricardo Neri
2023-03-01 23:47 ` [PATCH v7 15/24] x86/hpet: Reserve an HPET channel for the hardlockup detector Ricardo Neri
2023-03-01 23:47 ` [PATCH v7 16/24] watchdog/hardlockup: Define a generic function to detect hardlockups Ricardo Neri
2023-03-01 23:47 ` [PATCH v7 17/24] watchdog/hardlockup: Decouple the hardlockup detector from perf Ricardo Neri
2023-03-01 23:47 ` [PATCH v7 18/24] init/main: Delay initialization of the lockup detector after smp_init() Ricardo Neri
2023-03-01 23:47 ` [PATCH v7 19/24] x86/watchdog/hardlockup: Add an HPET-based hardlockup detector Ricardo Neri
2026-02-03 17:02 ` Thomas Gleixner
2023-03-01 23:47 ` [PATCH v7 20/24] x86/watchdog/hardlockup/hpet: Determine if HPET timer caused NMI Ricardo Neri
2023-03-01 23:47 ` [PATCH v7 21/24] watchdog/hardlockup/hpet: Only enable the HPET watchdog via a boot parameter Ricardo Neri
2023-03-01 23:47 ` [PATCH v7 22/24] x86/watchdog: Add a shim hardlockup detector Ricardo Neri
2023-03-01 23:47 ` [PATCH v7 23/24] watchdog: Introduce hardlockup_detector_mark_unavailable() Ricardo Neri
2023-03-01 23:47 ` [PATCH v7 24/24] x86/tsc: Stop the HPET hardlockup detector if TSC become unstable Ricardo Neri
2023-04-13 3:58 ` [PATCH v7 00/24] x86: Implement an HPET-based hardlockup detector Ricardo Neri
2026-02-03 15:58 ` Thomas Gleixner
2026-02-04 5:02 ` Ricardo Neri
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=20230301234753.28582-5-ricardo.neri-calderon@linux.intel.com \
--to=ricardo.neri-calderon@linux.intel.com \
--cc=ak@linux.intel.com \
--cc=dan.j.williams@intel.com \
--cc=dave.hansen@intel.com \
--cc=eranian@google.com \
--cc=iommu@lists.linux-foundation.org \
--cc=len.brown@intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linuxppc-dev@lists.ozlabs.org \
--cc=rafael.j.wysocki@intel.com \
--cc=ravi.v.shankar@intel.com \
--cc=reinette.chatre@intel.com \
--cc=ricardo.neri@intel.com \
--cc=tony.luck@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox