Re: [RFC PATCH 17/23] watchdog/hardlockup/hpet: Convert the timer's interrupt to NMI
From: Peter Zijlstra <peterz@infradead.org>
Date: 2018-06-13 09:07:47
Also in:
linux-iommu, lkml, sparclinux
From: Peter Zijlstra <peterz@infradead.org>
Date: 2018-06-13 09:07:47
Also in:
linux-iommu, lkml, sparclinux
On Tue, Jun 12, 2018 at 05:57:37PM -0700, Ricardo Neri wrote:
+static bool is_hpet_wdt_interrupt(struct hpet_hld_data *hdata)
+{
+ unsigned long this_isr;
+ unsigned int lvl_trig;
+
+ this_isr = hpet_readl(HPET_STATUS) & BIT(hdata->num);
+
+ lvl_trig = hpet_readl(HPET_Tn_CFG(hdata->num)) & HPET_TN_LEVEL;
+
+ if (lvl_trig && this_isr)
+ return true;
+
+ return false;
+}
+static int hardlockup_detector_nmi_handler(unsigned int val,
+ struct pt_regs *regs)
+{
+ struct hpet_hld_data *hdata = hld_data;
+ unsigned int use_fsb;
+
+ /*
+ * If FSB delivery mode is used, the timer interrupt is programmed as
+ * edge-triggered and there is no need to check the ISR register.
+ */
+ use_fsb = hdata->flags & HPET_DEV_FSB_CAP;Please do explain.. That FSB thing basically means MSI. But there's only a single NMI vector. How do we know this NMI came from the HPET?
+ + if (!use_fsb && !is_hpet_wdt_interrupt(hdata))
So you add _2_ HPET reads for every single NMI that gets triggered... and IIRC HPET reads are _sllooooowwwwww_.
+ return NMI_DONE; + + inspect_for_hardlockups(regs); + + if (!(hdata->flags & HPET_DEV_PERI_CAP)) + kick_timer(hdata); + + /* Acknowledge interrupt if in level-triggered mode */ + if (!use_fsb) + hpet_writel(BIT(hdata->num), HPET_STATUS); + + return NMI_HANDLED;
So if I read this right, when in FSB/MSI mode, we'll basically _always_ claim every single NMI as handled? That's broken.
+}