Commit ada68a66 authored by Mahesh Salgaonkar's avatar Mahesh Salgaonkar Committed by Michael Ellerman

powerpc/64s: Move HMI IRQ stat from percpu variable to paca.

With the proposed change in percpu bootmem allocator to use page
mapping [1], the percpu first chunk memory area can come from vmalloc
ranges. This makes the HMI (Hypervisor Maintenance Interrupt) handler
crash the kernel whenever percpu variable is accessed in real mode.
This patch fixes this issue by moving the HMI IRQ stat inside paca for
safe access in realmode.

[1] https://lore.kernel.org/linuxppc-dev/20200608070904.387440-1-aneesh.kumar@linux.ibm.com/Suggested-by: default avatarAneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
Signed-off-by: default avatarMahesh Salgaonkar <mahesh@linux.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/159290806973.3642154.5244613424529764050.stgit@jupiter
parent d3c61954
...@@ -13,7 +13,6 @@ typedef struct { ...@@ -13,7 +13,6 @@ typedef struct {
unsigned int pmu_irqs; unsigned int pmu_irqs;
unsigned int mce_exceptions; unsigned int mce_exceptions;
unsigned int spurious_irqs; unsigned int spurious_irqs;
unsigned int hmi_exceptions;
unsigned int sreset_irqs; unsigned int sreset_irqs;
#ifdef CONFIG_PPC_WATCHDOG #ifdef CONFIG_PPC_WATCHDOG
unsigned int soft_nmi_irqs; unsigned int soft_nmi_irqs;
......
...@@ -225,6 +225,7 @@ struct paca_struct { ...@@ -225,6 +225,7 @@ struct paca_struct {
u16 in_mce; u16 in_mce;
u8 hmi_event_available; /* HMI event is available */ u8 hmi_event_available; /* HMI event is available */
u8 hmi_p9_special_emu; /* HMI P9 special emulation */ u8 hmi_p9_special_emu; /* HMI P9 special emulation */
u32 hmi_irqs; /* HMI irq stat */
#endif #endif
u8 ftrace_enabled; /* Hard disable ftrace */ u8 ftrace_enabled; /* Hard disable ftrace */
......
...@@ -621,13 +621,14 @@ int arch_show_interrupts(struct seq_file *p, int prec) ...@@ -621,13 +621,14 @@ int arch_show_interrupts(struct seq_file *p, int prec)
seq_printf(p, "%10u ", per_cpu(irq_stat, j).mce_exceptions); seq_printf(p, "%10u ", per_cpu(irq_stat, j).mce_exceptions);
seq_printf(p, " Machine check exceptions\n"); seq_printf(p, " Machine check exceptions\n");
#ifdef CONFIG_PPC_BOOK3S_64
if (cpu_has_feature(CPU_FTR_HVMODE)) { if (cpu_has_feature(CPU_FTR_HVMODE)) {
seq_printf(p, "%*s: ", prec, "HMI"); seq_printf(p, "%*s: ", prec, "HMI");
for_each_online_cpu(j) for_each_online_cpu(j)
seq_printf(p, "%10u ", seq_printf(p, "%10u ", paca_ptrs[j]->hmi_irqs);
per_cpu(irq_stat, j).hmi_exceptions);
seq_printf(p, " Hypervisor Maintenance Interrupts\n"); seq_printf(p, " Hypervisor Maintenance Interrupts\n");
} }
#endif
seq_printf(p, "%*s: ", prec, "NMI"); seq_printf(p, "%*s: ", prec, "NMI");
for_each_online_cpu(j) for_each_online_cpu(j)
...@@ -665,7 +666,9 @@ u64 arch_irq_stat_cpu(unsigned int cpu) ...@@ -665,7 +666,9 @@ u64 arch_irq_stat_cpu(unsigned int cpu)
sum += per_cpu(irq_stat, cpu).mce_exceptions; sum += per_cpu(irq_stat, cpu).mce_exceptions;
sum += per_cpu(irq_stat, cpu).spurious_irqs; sum += per_cpu(irq_stat, cpu).spurious_irqs;
sum += per_cpu(irq_stat, cpu).timer_irqs_others; sum += per_cpu(irq_stat, cpu).timer_irqs_others;
sum += per_cpu(irq_stat, cpu).hmi_exceptions; #ifdef CONFIG_PPC_BOOK3S_64
sum += paca_ptrs[cpu]->hmi_irqs;
#endif
sum += per_cpu(irq_stat, cpu).sreset_irqs; sum += per_cpu(irq_stat, cpu).sreset_irqs;
#ifdef CONFIG_PPC_WATCHDOG #ifdef CONFIG_PPC_WATCHDOG
sum += per_cpu(irq_stat, cpu).soft_nmi_irqs; sum += per_cpu(irq_stat, cpu).soft_nmi_irqs;
......
...@@ -727,7 +727,7 @@ long hmi_exception_realmode(struct pt_regs *regs) ...@@ -727,7 +727,7 @@ long hmi_exception_realmode(struct pt_regs *regs)
{ {
int ret; int ret;
__this_cpu_inc(irq_stat.hmi_exceptions); local_paca->hmi_irqs++;
ret = hmi_handle_debugtrig(regs); ret = hmi_handle_debugtrig(regs);
if (ret >= 0) if (ret >= 0)
......
...@@ -244,7 +244,7 @@ long kvmppc_realmode_hmi_handler(void) ...@@ -244,7 +244,7 @@ long kvmppc_realmode_hmi_handler(void)
{ {
bool resync_req; bool resync_req;
__this_cpu_inc(irq_stat.hmi_exceptions); local_paca->hmi_irqs++;
if (hmi_handle_debugtrig(NULL) >= 0) if (hmi_handle_debugtrig(NULL) >= 0)
return 1; return 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment