Loading arch/arm64/Kconfig +11 −0 Original line number Diff line number Diff line Loading @@ -1311,6 +1311,17 @@ config BUILD_ARM64_UNCOMPRESSED_KERNEL concatenated dtb. endchoice config KRYO_PMU_WORKAROUND bool "Workaround for PMU IRQ burst" default n depends on ARM_PMU help Disable Performance Monitor overflow interrupts when handling an monitor IRQ, to avoid simultaneous overflow interrupts from multiple monitors. Enable this flag for effect SoCs. config BUILD_ARM64_DT_OVERLAY bool "enable DT overlay compilation support" depends on OF Loading arch/arm64/kernel/perf_event.c +55 −1 Original line number Diff line number Diff line Loading @@ -677,6 +677,41 @@ static void armv8pmu_disable_event(struct perf_event *event) raw_spin_unlock_irqrestore(&events->pmu_lock, flags); } #ifdef CONFIG_KRYO_PMU_WORKAROUND static inline u32 armv8pmu_get_enabled_ints(void) { u32 int_enset; int_enset = read_sysreg(pmintenset_el1); write_sysreg(0xffffffff, pmintenclr_el1); isb(); return int_enset; } static inline u32 armv8pmu_update_enabled_ints(u32 value, int idx, int set) { if (set) value |= BIT(ARMV8_IDX_TO_COUNTER(idx)); else value &= ~(BIT(ARMV8_IDX_TO_COUNTER(idx))); return value; } static inline void armv8pmu_set_enabled_ints(u32 mask) { write_sysreg(mask, pmintenset_el1); isb(); } #else static inline u32 armv8pmu_get_enabled_ints(void) { return 0; } static inline u32 armv8pmu_update_enabled_ints(u32 value, int idx, int set) { return value; } static inline void armv8pmu_set_enabled_ints(u32 mask) { } #endif static irqreturn_t armv8pmu_handle_irq(int irq_num, void *dev) { Loading @@ -686,6 +721,12 @@ static irqreturn_t armv8pmu_handle_irq(int irq_num, void *dev) struct pmu_hw_events *cpuc = this_cpu_ptr(cpu_pmu->hw_events); struct pt_regs *regs; int idx; u32 enabled_ints; /* * Get enabled the PMU interrupts and mask all PMU interrupts. */ enabled_ints = armv8pmu_get_enabled_ints(); /* * Get and reset the IRQ flags Loading Loading @@ -724,8 +765,16 @@ static irqreturn_t armv8pmu_handle_irq(int irq_num, void *dev) if (!armpmu_event_set_period(event)) continue; if (perf_event_overflow(event, &data, regs)) if (perf_event_overflow(event, &data, regs)) { cpu_pmu->disable(event); /* * Update the list of interrupts * that should be reenabled. */ enabled_ints = armv8pmu_update_enabled_ints( enabled_ints, idx, 0); } } /* Loading @@ -737,6 +786,11 @@ static irqreturn_t armv8pmu_handle_irq(int irq_num, void *dev) */ irq_work_run(); /* * Re-enable the PMU interrupts */ armv8pmu_set_enabled_ints(enabled_ints); return IRQ_HANDLED; } Loading Loading
arch/arm64/Kconfig +11 −0 Original line number Diff line number Diff line Loading @@ -1311,6 +1311,17 @@ config BUILD_ARM64_UNCOMPRESSED_KERNEL concatenated dtb. endchoice config KRYO_PMU_WORKAROUND bool "Workaround for PMU IRQ burst" default n depends on ARM_PMU help Disable Performance Monitor overflow interrupts when handling an monitor IRQ, to avoid simultaneous overflow interrupts from multiple monitors. Enable this flag for effect SoCs. config BUILD_ARM64_DT_OVERLAY bool "enable DT overlay compilation support" depends on OF Loading
arch/arm64/kernel/perf_event.c +55 −1 Original line number Diff line number Diff line Loading @@ -677,6 +677,41 @@ static void armv8pmu_disable_event(struct perf_event *event) raw_spin_unlock_irqrestore(&events->pmu_lock, flags); } #ifdef CONFIG_KRYO_PMU_WORKAROUND static inline u32 armv8pmu_get_enabled_ints(void) { u32 int_enset; int_enset = read_sysreg(pmintenset_el1); write_sysreg(0xffffffff, pmintenclr_el1); isb(); return int_enset; } static inline u32 armv8pmu_update_enabled_ints(u32 value, int idx, int set) { if (set) value |= BIT(ARMV8_IDX_TO_COUNTER(idx)); else value &= ~(BIT(ARMV8_IDX_TO_COUNTER(idx))); return value; } static inline void armv8pmu_set_enabled_ints(u32 mask) { write_sysreg(mask, pmintenset_el1); isb(); } #else static inline u32 armv8pmu_get_enabled_ints(void) { return 0; } static inline u32 armv8pmu_update_enabled_ints(u32 value, int idx, int set) { return value; } static inline void armv8pmu_set_enabled_ints(u32 mask) { } #endif static irqreturn_t armv8pmu_handle_irq(int irq_num, void *dev) { Loading @@ -686,6 +721,12 @@ static irqreturn_t armv8pmu_handle_irq(int irq_num, void *dev) struct pmu_hw_events *cpuc = this_cpu_ptr(cpu_pmu->hw_events); struct pt_regs *regs; int idx; u32 enabled_ints; /* * Get enabled the PMU interrupts and mask all PMU interrupts. */ enabled_ints = armv8pmu_get_enabled_ints(); /* * Get and reset the IRQ flags Loading Loading @@ -724,8 +765,16 @@ static irqreturn_t armv8pmu_handle_irq(int irq_num, void *dev) if (!armpmu_event_set_period(event)) continue; if (perf_event_overflow(event, &data, regs)) if (perf_event_overflow(event, &data, regs)) { cpu_pmu->disable(event); /* * Update the list of interrupts * that should be reenabled. */ enabled_ints = armv8pmu_update_enabled_ints( enabled_ints, idx, 0); } } /* Loading @@ -737,6 +786,11 @@ static irqreturn_t armv8pmu_handle_irq(int irq_num, void *dev) */ irq_work_run(); /* * Re-enable the PMU interrupts */ armv8pmu_set_enabled_ints(enabled_ints); return IRQ_HANDLED; } Loading