[RFC PATCH v5 2/7] x86/hpet: Introduce function to identify HPET hardlockup detector irq

From: Ricardo Neri
Date: Tue May 04 2021 - 15:11:47 EST


The HPET hardlockup detector needs to deliver its interrupt as NMI.
In x86 there is not an IRQF_NMI flag that can be used in the irq plumbing
code to tell interrupt remapping drivers to set the interrupt delivery
mode accordingly. Hence, they must fixup the delivery mode internally.

Implement a method to determine if the interrupt being allocated belongs
to the HPET hardlockup detector.

Cc: Andi Kleen <andi.kleen@xxxxxxxxx>
Cc: Borislav Petkov <bp@xxxxxxx>
Cc: David Woodhouse <dwmw2@xxxxxxxxxxxxx> (supporter:INTEL IOMMU (VT-d))
Cc: "Ravi V. Shankar" <ravi.v.shankar@xxxxxxxxx>
Cc: Ingo Molnar <mingo@xxxxxxxxxx>
Cc: Jacob Pan <jacob.jun.pan@xxxxxxxxx>
Cc: Lu Baolu <baolu.lu@xxxxxxxxxxxxxxx> (supporter:INTEL IOMMU (VT-d))
Cc: Stephane Eranian <eranian@xxxxxxxxxx>
Cc: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
Cc: iommu@xxxxxxxxxxxxxxxxxxxxxxxxxx (open list:INTEL IOMMU (VT-d))
Cc: x86@xxxxxxxxxx
Reviewed-by: Ashok Raj <ashok.raj@xxxxxxxxx>
Signed-off-by: Ricardo Neri <ricardo.neri-calderon@xxxxxxxxxxxxxxx>
---
Changes since v4:
* Introduced this patch. Previous versions had special functions to
allocate and set the affinity of a remapped NMI interrupt.

Changes since v3:
* N/A

Changes since v2:
* N/A

Changes since v1:
* N/A
---
arch/x86/include/asm/hpet.h | 3 +++
arch/x86/kernel/hpet.c | 33 +++++++++++++++++++++++++++++++++
2 files changed, 36 insertions(+)

diff --git a/arch/x86/include/asm/hpet.h b/arch/x86/include/asm/hpet.h
index df11c7d4af44..5bf675970d4b 100644
--- a/arch/x86/include/asm/hpet.h
+++ b/arch/x86/include/asm/hpet.h
@@ -149,6 +149,7 @@ extern void hardlockup_detector_hpet_stop(void);
extern void hardlockup_detector_hpet_enable(unsigned int cpu);
extern void hardlockup_detector_hpet_disable(unsigned int cpu);
extern void hardlockup_detector_switch_to_perf(void);
+extern bool is_hpet_irq_hardlockup_detector(struct irq_alloc_info *info);
#else
static inline int hardlockup_detector_hpet_init(void)
{ return -ENODEV; }
@@ -156,6 +157,8 @@ static inline void hardlockup_detector_hpet_stop(void) {}
static inline void hardlockup_detector_hpet_enable(unsigned int cpu) {}
static inline void hardlockup_detector_hpet_disable(unsigned int cpu) {}
static inline void hardlockup_detector_switch_to_perf(void) {}
+static inline bool is_hpet_irq_hardlockup_detector(struct irq_alloc_info *info)
+{ return false; }
#endif /* CONFIG_X86_HARDLOCKUP_DETECTOR_HPET */

#else /* CONFIG_HPET_TIMER */
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 5012590dc1b8..3e43e0f348b8 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -1479,6 +1479,39 @@ struct hpet_hld_data *hpet_hld_get_timer(void)
hld_data = NULL;
return NULL;
}
+
+/**
+ * is_hpet_irq_hardlockup_detector() - Identify the HPET hld interrupt info
+ * @info: Interrupt allocation info, with private HPET channel data
+ *
+ * The HPET hardlockup detector is special as it needs its interrupts delivered
+ * as NMI. However, for interrupt remapping we use the existing irq subsystem
+ * to configure and route the HPET interrupt. Unfortunately, there is not a
+ * IRQF_NMI flag for x86. Instead, identify whether the interrupt being
+ * allocated for the HPET channel belongs to the hardlockup detector.
+ *
+ * Returns: True if @info indicates that it belongs to the HPET hardlockup
+ * detector. False otherwise.
+ */
+bool is_hpet_irq_hardlockup_detector(struct irq_alloc_info *info)
+{
+ struct hpet_channel *hc;
+
+ if (!info)
+ return false;
+
+ if (info->type != X86_IRQ_ALLOC_TYPE_HPET)
+ return false;
+
+ hc = info->data;
+ if (!hc)
+ return false;
+
+ if (hc->mode == HPET_MODE_NMI_WATCHDOG)
+ return true;
+
+ return false;
+}
#endif /* CONFIG_X86_HARDLOCKUP_DETECTOR_HPET */

#endif
--
2.17.1