notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs) { unsigned int sum, touched = 0; int cpu = smp_processor_id(); clear_softint(1 << irq); pcr_ops->write(PCR_PIC_PRIV); local_cpu_data().__nmi_count++; if (notify_die(DIE_NMI, "nmi", regs, 0, pt_regs_trap_type(regs), SIGINT) == NOTIFY_STOP) touched = 1; sum = kstat_irqs_cpu(0, cpu); if (__get_cpu_var(nmi_touch)) { __get_cpu_var(nmi_touch) = 0; touched = 1; } if (!touched && __get_cpu_var(last_irq_sum) == sum) { local_inc(&__get_cpu_var(alert_counter)); if (local_read(&__get_cpu_var(alert_counter)) == 5 * nmi_hz) die_nmi("BUG: NMI Watchdog detected LOCKUP", regs, panic_on_timeout); } else { __get_cpu_var(last_irq_sum) = sum; local_set(&__get_cpu_var(alert_counter), 0); } if (nmi_usable) { write_pic(picl_value(nmi_hz)); pcr_ops->write(pcr_enable); } }
/* Performance counter interrupts run unmasked at PIL level 15. * Therefore we can't do things like wakeups and other work * that expects IRQ disabling to be adhered to in locking etc. * * Therefore in such situations we defer the work by signalling * a lower level cpu IRQ. */ void __irq_entry deferred_pcr_work_irq(int irq, struct pt_regs *regs) { struct pt_regs *old_regs; clear_softint(1 << PIL_DEFERRED_PCR_WORK); old_regs = set_irq_regs(regs); irq_enter(); #ifdef CONFIG_IRQ_WORK irq_work_run(); #endif irq_exit(); set_irq_regs(old_regs); }
/* Performance counter interrupts run unmasked at PIL level 15. * Therefore we can't do things like wakeups and other work * that expects IRQ disabling to be adhered to in locking etc. * * Therefore in such situations we defer the work by signalling * a lower level cpu IRQ. */ void deferred_pcr_work_irq(int irq, struct pt_regs *regs) { struct pt_regs *old_regs; clear_softint(1 << PIL_DEFERRED_PCR_WORK); old_regs = set_irq_regs(regs); irq_enter(); #ifdef CONFIG_PERF_EVENTS perf_event_do_pending(); #endif irq_exit(); set_irq_regs(old_regs); }