<html><head></head><body dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="ApplePlainTextBody"><div class="ApplePlainTextBody"><br><br><blockquote type="cite">On 28-Nov-2020, at 8:10 PM, Nicholas Piggin <npiggin@gmail.com> wrote:<br><br>This is required in order to allow more significant differences between<br>NMI type interrupt handlers and regular asynchronous handlers.<br><br>Signed-off-by: Nicholas Piggin <npiggin@gmail.com><br></blockquote><br>Reviewed this patch and the changes looks good to me.<br><br>Reviewed-by: Athira Rajeev <atrajeev@linux.vnet.ibm.com><br><br>Thanks<br>Athira<br><blockquote type="cite">---<br>arch/powerpc/kernel/traps.c      | 31 +++++++++++++++++++++++++++-<br>arch/powerpc/perf/core-book3s.c  | 35 ++------------------------------<br>arch/powerpc/perf/core-fsl-emb.c | 25 -----------------------<br>3 files changed, 32 insertions(+), 59 deletions(-)<br><br>diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c<br>index 902fcbd1a778..7dda72eb97cc 100644<br>--- a/arch/powerpc/kernel/traps.c<br>+++ b/arch/powerpc/kernel/traps.c<br>@@ -1919,11 +1919,40 @@ void vsx_unavailable_tm(struct pt_regs *regs)<br>}<br>#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */<br><br>-void performance_monitor_exception(struct pt_regs *regs)<br>+static void performance_monitor_exception_nmi(struct pt_regs *regs)<br>+{<br>+<span class="Apple-tab-span" style="white-space:pre">   </span>nmi_enter();<br>+<br>+<span class="Apple-tab-span" style="white-space:pre">  </span>__this_cpu_inc(irq_stat.pmu_irqs);<br>+<br>+<span class="Apple-tab-span" style="white-space:pre">    </span>perf_irq(regs);<br>+<br>+<span class="Apple-tab-span" style="white-space:pre">       </span>nmi_exit();<br>+}<br>+<br>+static void performance_monitor_exception_async(struct pt_regs *regs)<br>{<br>+<span class="Apple-tab-span" style="white-space:pre">    </span>irq_enter();<br>+<br><span class="Apple-tab-span" style="white-space:pre">   </span>__this_cpu_inc(irq_stat.pmu_irqs);<br><br><span class="Apple-tab-span" style="white-space:pre">      </span>perf_irq(regs);<br>+<br>+<span class="Apple-tab-span" style="white-space:pre">       </span>irq_exit();<br>+}<br>+<br>+void performance_monitor_exception(struct pt_regs *regs)<br>+{<br>+<span class="Apple-tab-span" style="white-space:pre">        </span>/*<br>+<span class="Apple-tab-span" style="white-space:pre">       </span> * On 64-bit, if perf interrupts hit in a local_irq_disable<br>+<span class="Apple-tab-span" style="white-space:pre">      </span> * (soft-masked) region, we consider them as NMIs. This is required to<br>+<span class="Apple-tab-span" style="white-space:pre">   </span> * prevent hash faults on user addresses when reading callchains (and<br>+<span class="Apple-tab-span" style="white-space:pre">    </span> * looks better from an irq tracing perspective).<br>+<span class="Apple-tab-span" style="white-space:pre">        </span> */<br>+<span class="Apple-tab-span" style="white-space:pre">      </span>if (IS_ENABLED(CONFIG_PPC64) && unlikely(arch_irq_disabled_regs(regs)))<br>+<span class="Apple-tab-span" style="white-space:pre">  </span><span class="Apple-tab-span" style="white-space:pre">    </span>performance_monitor_exception_nmi(regs);<br>+<span class="Apple-tab-span" style="white-space:pre"> </span>else<br>+<span class="Apple-tab-span" style="white-space:pre">     </span><span class="Apple-tab-span" style="white-space:pre">    </span>performance_monitor_exception_async(regs);<br>}<br><br>#ifdef CONFIG_PPC_ADV_DEBUG_REGS<br>diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c<br>index 08643cba1494..9fd8cae09218 100644<br>--- a/arch/powerpc/perf/core-book3s.c<br>+++ b/arch/powerpc/perf/core-book3s.c<br>@@ -109,10 +109,6 @@ static inline void perf_read_regs(struct pt_regs *regs)<br>{<br><span class="Apple-tab-span" style="white-space:pre"> </span>regs->result = 0;<br>}<br>-static inline int perf_intr_is_nmi(struct pt_regs *regs)<br>-{<br>-<span class="Apple-tab-span" style="white-space:pre">   </span>return 0;<br>-}<br><br>static inline int siar_valid(struct pt_regs *regs)<br>{<br>@@ -328,15 +324,6 @@ static inline void perf_read_regs(struct pt_regs *regs)<br><span class="Apple-tab-span" style="white-space:pre">      </span>regs->result = use_siar;<br>}<br><br>-/*<br>- * If interrupts were soft-disabled when a PMU interrupt occurs, treat<br>- * it as an NMI.<br>- */<br>-static inline int perf_intr_is_nmi(struct pt_regs *regs)<br>-{<br>-<span class="Apple-tab-span" style="white-space:pre">   </span>return (regs->softe & IRQS_DISABLED);<br>-}<br>-<br>/*<br> * On processors like P7+ that have the SIAR-Valid bit, marked instructions<br> * must be sampled only if the SIAR-valid bit is set.<br>@@ -2224,7 +2211,6 @@ static void __perf_event_interrupt(struct pt_regs *regs)<br><span class="Apple-tab-span" style="white-space:pre">       </span>struct perf_event *event;<br><span class="Apple-tab-span" style="white-space:pre"> </span>unsigned long val[8];<br><span class="Apple-tab-span" style="white-space:pre">     </span>int found, active;<br>-<span class="Apple-tab-span" style="white-space:pre">       </span>int nmi;<br><br><span class="Apple-tab-span" style="white-space:pre">        </span>if (cpuhw->n_limited)<br><span class="Apple-tab-span" style="white-space:pre">  </span><span class="Apple-tab-span" style="white-space:pre">    </span>freeze_limited_counters(cpuhw, mfspr(SPRN_PMC5),<br>@@ -2232,18 +2218,6 @@ static void __perf_event_interrupt(struct pt_regs *regs)<br><br><span class="Apple-tab-span" style="white-space:pre">       </span>perf_read_regs(regs);<br><br>-<span class="Apple-tab-span" style="white-space:pre">  </span>/*<br>-<span class="Apple-tab-span" style="white-space:pre">       </span> * If perf interrupts hit in a local_irq_disable (soft-masked) region,<br>-<span class="Apple-tab-span" style="white-space:pre">   </span> * we consider them as NMIs. This is required to prevent hash faults on<br>-<span class="Apple-tab-span" style="white-space:pre">  </span> * user addresses when reading callchains. See the NMI test in<br>-<span class="Apple-tab-span" style="white-space:pre">   </span> * do_hash_page.<br>-<span class="Apple-tab-span" style="white-space:pre"> </span> */<br>-<span class="Apple-tab-span" style="white-space:pre">      </span>nmi = perf_intr_is_nmi(regs);<br>-<span class="Apple-tab-span" style="white-space:pre">    </span>if (nmi)<br>-<span class="Apple-tab-span" style="white-space:pre"> </span><span class="Apple-tab-span" style="white-space:pre">    </span>nmi_enter();<br>-<span class="Apple-tab-span" style="white-space:pre">     </span>else<br>-<span class="Apple-tab-span" style="white-space:pre">     </span><span class="Apple-tab-span" style="white-space:pre">    </span>irq_enter();<br>-<br><span class="Apple-tab-span" style="white-space:pre">   </span>/* Read all the PMCs since we'll need them a bunch of times */<br><span class="Apple-tab-span" style="white-space:pre">    </span>for (i = 0; i < ppmu->n_counter; ++i)<br><span class="Apple-tab-span" style="white-space:pre">       </span><span class="Apple-tab-span" style="white-space:pre">    </span>val[i] = read_pmc(i + 1);<br>@@ -2289,8 +2263,8 @@ static void __perf_event_interrupt(struct pt_regs *regs)<br><span class="Apple-tab-span" style="white-space:pre"> </span><span class="Apple-tab-span" style="white-space:pre">    </span><span class="Apple-tab-span" style="white-space:pre">    </span>}<br><span class="Apple-tab-span" style="white-space:pre"> </span><span class="Apple-tab-span" style="white-space:pre">    </span>}<br><span class="Apple-tab-span" style="white-space:pre"> </span>}<br>-<span class="Apple-tab-span" style="white-space:pre">        </span>if (!found && !nmi && printk_ratelimit())<br>-<span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">    </span>printk(KERN_WARNING "Can't find PMC that caused IRQ\n");<br>+<span class="Apple-tab-span" style="white-space:pre">       </span>if (unlikely(!found) && !arch_irq_disabled_regs(regs))<br>+<span class="Apple-tab-span" style="white-space:pre">   </span><span class="Apple-tab-span" style="white-space:pre">    </span>printk_ratelimited(KERN_WARNING "Can't find PMC that caused IRQ\n");<br><br><span class="Apple-tab-span" style="white-space:pre">  </span>/*<br><span class="Apple-tab-span" style="white-space:pre">        </span> * Reset MMCR0 to its normal value.  This will set PMXE and<br>@@ -2300,11 +2274,6 @@ static void __perf_event_interrupt(struct pt_regs *regs)<br><span class="Apple-tab-span" style="white-space:pre"> </span> * we get back out of this interrupt.<br><span class="Apple-tab-span" style="white-space:pre">     </span> */<br><span class="Apple-tab-span" style="white-space:pre">       </span>write_mmcr0(cpuhw, cpuhw->mmcr.mmcr0);<br>-<br>-<span class="Apple-tab-span" style="white-space:pre">     </span>if (nmi)<br>-<span class="Apple-tab-span" style="white-space:pre"> </span><span class="Apple-tab-span" style="white-space:pre">    </span>nmi_exit();<br>-<span class="Apple-tab-span" style="white-space:pre">      </span>else<br>-<span class="Apple-tab-span" style="white-space:pre">     </span><span class="Apple-tab-span" style="white-space:pre">    </span>irq_exit();<br>}<br><br>static void perf_event_interrupt(struct pt_regs *regs)<br>diff --git a/arch/powerpc/perf/core-fsl-emb.c b/arch/powerpc/perf/core-fsl-emb.c<br>index e0e7e276bfd2..ee721f420a7b 100644<br>--- a/arch/powerpc/perf/core-fsl-emb.c<br>+++ b/arch/powerpc/perf/core-fsl-emb.c<br>@@ -31,19 +31,6 @@ static atomic_t num_events;<br>/* Used to avoid races in calling reserve/release_pmc_hardware */<br>static DEFINE_MUTEX(pmc_reserve_mutex);<br><br>-/*<br>- * If interrupts were soft-disabled when a PMU interrupt occurs, treat<br>- * it as an NMI.<br>- */<br>-static inline int perf_intr_is_nmi(struct pt_regs *regs)<br>-{<br>-#ifdef __powerpc64__<br>-<span class="Apple-tab-span" style="white-space:pre">   </span>return (regs->softe & IRQS_DISABLED);<br>-#else<br>-<span class="Apple-tab-span" style="white-space:pre">     </span>return 0;<br>-#endif<br>-}<br>-<br>static void perf_event_interrupt(struct pt_regs *regs);<br><br>/*<br>@@ -659,13 +646,6 @@ static void perf_event_interrupt(struct pt_regs *regs)<br><span class="Apple-tab-span" style="white-space:pre">     </span>struct perf_event *event;<br><span class="Apple-tab-span" style="white-space:pre"> </span>unsigned long val;<br><span class="Apple-tab-span" style="white-space:pre">        </span>int found = 0;<br>-<span class="Apple-tab-span" style="white-space:pre">   </span>int nmi;<br>-<br>-<span class="Apple-tab-span" style="white-space:pre">      </span>nmi = perf_intr_is_nmi(regs);<br>-<span class="Apple-tab-span" style="white-space:pre">    </span>if (nmi)<br>-<span class="Apple-tab-span" style="white-space:pre"> </span><span class="Apple-tab-span" style="white-space:pre">    </span>nmi_enter();<br>-<span class="Apple-tab-span" style="white-space:pre">     </span>else<br>-<span class="Apple-tab-span" style="white-space:pre">     </span><span class="Apple-tab-span" style="white-space:pre">    </span>irq_enter();<br><br><span class="Apple-tab-span" style="white-space:pre">    </span>for (i = 0; i < ppmu->n_counter; ++i) {<br><span class="Apple-tab-span" style="white-space:pre">     </span><span class="Apple-tab-span" style="white-space:pre">    </span>event = cpuhw->event[i];<br>@@ -690,11 +670,6 @@ static void perf_event_interrupt(struct pt_regs *regs)<br><span class="Apple-tab-span" style="white-space:pre">  </span>mtmsr(mfmsr() | MSR_PMM);<br><span class="Apple-tab-span" style="white-space:pre"> </span>mtpmr(PMRN_PMGC0, PMGC0_PMIE | PMGC0_FCECE);<br><span class="Apple-tab-span" style="white-space:pre">      </span>isync();<br>-<br>-<span class="Apple-tab-span" style="white-space:pre">      </span>if (nmi)<br>-<span class="Apple-tab-span" style="white-space:pre"> </span><span class="Apple-tab-span" style="white-space:pre">    </span>nmi_exit();<br>-<span class="Apple-tab-span" style="white-space:pre">      </span>else<br>-<span class="Apple-tab-span" style="white-space:pre">     </span><span class="Apple-tab-span" style="white-space:pre">    </span>irq_exit();<br>}<br><br>void hw_perf_event_setup(int cpu)<br>-- <br>2.23.0<br><br></blockquote><br></div></body></html>