Re: [RFC PATCH 17/23] watchdog/hardlockup/hpet: Convert the timer's interrupt to NMI

From: Ricardo Neri
Date: Thu Jun 14 2018 - 22:11:23 EST


On Wed, Jun 13, 2018 at 11:07:20AM +0200, Peter Zijlstra wrote:
> 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?

Indeed, I see now that this is wrong. There is no way to know. The only way
is to use an IO APIC interrupt and read the HPET status register.

>
> > +
> > + 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_.


Since the trigger mode of the HPET timer is not expected to change,
perhaps is_hpet_wdt_interrupt() can only need the interrupt status
register. This would reduce the reads to one. Furthermore, the hardlockup
detector can skip an X number of NMIs and reduce further the frequency
of reads. Does this make sense?

>
> > + 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.

Yes, this is not correct. I will drop the functionality to use
FSB/MSI mode.

Thanks and BR,
Ricardo