arm64/perf: Add ACPI support
Subsystems (3)
v3 cover arm64/perf: Add ACPI support
This patch set expands upon the patches published by Mark Salter to clean up a few of the previous review comments, as well as add support for A72's, and big/little configurations.
I've been testing this patch in concert with the ACPI/PCIe and ACPI/GICv3 patches. It works well on seattle/juno, but there appears to be a problem with at least one platform using PPIs (which is questionable as ACPI defines the pmu interrupt as a GSI). I said a couple weeks ago I would post it, so here it is.
Jeremy Linton (1):
arm64: pmu: add A72 cpu type, support multiple PMU types
Mark Salter (3):
arm: pmu: Fix non-devicetree probing
arm64: pmu: add fallback probe table
arm64: pmu: Add support for probing with ACPI
arch/arm64/include/asm/cputype.h | 1 + arch/arm64/kernel/perf_event.c | 11 +- arch/arm64/kernel/smp.c | 5 + drivers/perf/Kconfig | 4 + drivers/perf/Makefile | 1 + drivers/perf/arm_pmu.c | 54 ++++++++-- drivers/perf/arm_pmu_acpi.c | 212 +++++++++++++++++++++++++++++++++++++++ include/linux/perf/arm_pmu.h | 10 ++ 8 files changed, 287 insertions(+), 11 deletions(-) create mode 100644 drivers/perf/arm_pmu_acpi.c
Signature · 1 line
2.4.3
PATCH v3 1/4 arm: pmu: Fix non-devicetree probing
From: Mark Salter <[email protected]>
There is a problem in the non-devicetree PMU probing where some probe functions may get the number of supported events through smp_call_function_any() using the arm_pmu supported_cpus mask. But at the time the probe function is called, the supported_cpus mask is empty so the call fails. This patch makes sure the mask is set before calling the init function rather than after.
--- drivers/perf/arm_pmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/perf/arm_pmu.c +1 -1
@@ -997,8 +997,8 @@ int arm_pmu_device_probe(struct platform_device *pdev,if (!ret) ret =init_fn (pmu); }else { - ret =probe_current_pmu (pmu, probe_table);cpumask_setall (&pmu->supported_cpus); + ret =probe_current_pmu (pmu, probe_table); }if (ret) {
Signature · 1 line
2.4.3
PATCH v3 2/4 arm64: pmu: add fallback probe table
In reply to Jeremy LintonFrom: Mark Salter <[email protected]>
In preparation for ACPI support, add a pmu_probe_info table to the arm_pmu_device_probe() call. This table gets used when probing in the absence of a devicetree node for PMU.
--- arch/arm64/kernel/perf_event.c | 10 +++++++++- include/linux/perf/arm_pmu.h | 3 +++ 2 files changed, 12 insertions(+), 1 deletion(-)
arch/arm64/kernel/perf_event.c +9 -1
@@ -901,9 +901,17 @@ static const struct of_device_id armv8_pmu_of_device_ids[] = { {}, }; +static const struct pmu_probe_info armv8_pmu_probe_table[] = { +ARMV8_PMU_PART_PROBE (ARM_CPU_PART_CORTEX_A53 , armv8_a53_pmu_init), +ARMV8_PMU_PART_PROBE (ARM_CPU_PART_CORTEX_A57 , armv8_a57_pmu_init), +PMU_PROBE (0 ,0 , armv8_pmuv3_init),/* if all else fails... */ + {/* sentinel value */ } +}; +static int armv8_pmu_device_probe (struct platform_device *pdev) { -return arm_pmu_device_probe (pdev, armv8_pmu_of_device_ids,NULL ); +return arm_pmu_device_probe (pdev, armv8_pmu_of_device_ids, + armv8_pmu_probe_table); }static struct platform_driver armv8_pmu_driver = {
include/linux/perf/arm_pmu.h +3 -0
@@ -145,6 +145,9 @@ struct pmu_probe_info {#define XSCALE_PMU_PROBE (_version, _fn) \ PMU_PROBE(ARM_CPU_IMP_INTEL << 24 | _version, ARM_PMU_XSCALE_MASK, _fn) +#define ARMV8_PMU_PART_PROBE (_part, _fn) \ + PMU_PROBE((_part) << MIDR_PARTNUM_SHIFT, MIDR_PARTNUM_MASK, _fn) +int arm_pmu_device_probe (struct platform_device *pdev,const struct of_device_id *of_table,const struct pmu_probe_info *probe_table);
Signature · 1 line
2.4.3
PATCH 2/4 arm64: pmu: add fallback probe table
Quoted 52 lines · Jeremy Linton
From: Mark Salter <[email protected]>
In preparation for ACPI support, add a
pmu_probe_infotable to thearm_pmu_device_probe()call. This table gets used when probing in the absence of a devicetree node for PMU.Signed-off-by Mark Salter <[email protected]>--- arch/arm64/kernel/perf_event.c | 10 +++++++++- include/linux/perf/arm_pmu.h | 3 +++ 2 files changed, 12 insertions(+), 1 deletion(-)arch/arm64/kernel/perf_event.c +9
-1@@ -901,9 +901,17 @@ static const struct of_device_id armv8_pmu_of_device_ids[] = { {}, }; +static const struct pmu_probe_info armv8_pmu_probe_table[] = { +ARMV8_PMU_PART_PROBE (ARM_CPU_PART_CORTEX_A53 , armv8_a53_pmu_init), +ARMV8_PMU_PART_PROBE (ARM_CPU_PART_CORTEX_A57 , armv8_a57_pmu_init), +PMU_PROBE (0 ,0 , armv8_pmuv3_init),/* if all else fails... */ + {/* sentinel value */ } +}; +static int armv8_pmu_device_probe (struct platform_device *pdev) { -return arm_pmu_device_probe (pdev, armv8_pmu_of_device_ids,NULL ); +return arm_pmu_device_probe (pdev, armv8_pmu_of_device_ids, + armv8_pmu_probe_table); }static struct
platform_driverarmv8_pmu_driver= {include/linux/perf/arm_pmu.h +3
-0@@ -145,6 +145,9 @@ struct pmu_probe_info {#define XSCALE_PMU_PROBE (_version, _fn) \ PMU_PROBE(ARM_CPU_IMP_INTEL << 24 | _version, ARM_PMU_XSCALE_MASK, _fn) +#define ARMV8_PMU_PART_PROBE (_part, _fn) \ + PMU_PROBE((_part) << MIDR_PARTNUM_SHIFT, MIDR_PARTNUM_MASK, _fn) + int arm_pmu_device_probe(struct platform_device *pdev, const struct of_device_id *of_table,
Quoted 1 line
const struct
pmu_probe_info*probe_table);
Hi Jeremy,
Thanks for pulling these patches together.
Just one comment: MIDR part numbers are not guaranteed unique across implementors, so I'd suggest that ARMV8_PMU_PART_PROBE include the MIDR_IMPLEMENTOR in the cpuid and mask.
Otherwise everything looks good - I successfully used this patchset as a base for getting my pmu driver running with ACPI.
-- Neil
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
PATCH v3 3/4 arm64: pmu: Add support for probing with ACPI
In reply to Jeremy LintonFrom: Mark Salter <[email protected]>
In the case of ACPI, the PMU IRQ information is contained in the MADT table. Also, since the PMU does not exist as a device in the ACPI DSDT table, it is necessary to create a platform device so that the appropriate driver probing is triggered.
--- arch/arm64/kernel/smp.c | 5 ++ drivers/perf/Kconfig | 4 ++ drivers/perf/Makefile | 1 + drivers/perf/arm_pmu_acpi.c | 125 +++++++++++++++++++++++++++++++++++++++++++ include/linux/perf/arm_pmu.h | 7 +++ 5 files changed, 142 insertions(+) create mode 100644 drivers/perf/arm_pmu_acpi.c
arch/arm64/kernel/smp.c +5 -0
@@ -37,6 +37,7 @@#include <linux/completion.h> #include <linux/of.h> #include <linux/irq_work.h> +#include <linux/perf/arm_pmu.h> #include <asm/alternative.h> #include <asm/atomic.h>
@@ -502,6 +503,7 @@ acpi_map_gic_cpu_interface(struct acpi_madt_generic_interrupt *processor)return ; } bootcpu_valid = true; +arm_pmu_parse_acpi (0 , processor);return ; }
@@ -522,6 +524,9 @@ acpi_map_gic_cpu_interface(struct acpi_madt_generic_interrupt *processor)*/ acpi_set_mailbox_entry (cpu_count, processor); +/* get PMU irq info */ +arm_pmu_parse_acpi (cpu_count, processor); + cpu_count++; }
drivers/perf/Kconfig +4 -0
@@ -12,4 +12,8 @@ config ARM_PMU Say y if you want to use CPU performance monitors on ARM-based systems. +config ARM_PMU_ACPI + def_bool y + depends on ARM_PMU && ACPI + endmenu
drivers/perf/Makefile +1 -0
@@ -1 +1,2 @@ obj-$(CONFIG_ARM_PMU) += arm_pmu.o +obj-$(CONFIG_ARM_PMU_ACPI) += arm_pmu_acpi.o
drivers/perf/arm_pmu_acpi.c new file +125 -0
125 lines not on this page · raw message
include/linux/perf/arm_pmu.h +7 -0
@@ -154,4 +154,11 @@ int arm_pmu_device_probe(struct platform_device *pdev,#endif /* CONFIG_ARM_PMU */ +#ifdef CONFIG_ARM_PMU_ACPI +struct acpi_madt_generic_interrupt ; +void arm_pmu_parse_acpi (int cpu,struct acpi_madt_generic_interrupt *gic); +#else +#define arm_pmu_parse_acpi (a, b) do { } while (0) +#endif /* CONFIG_ARM_PMU_ACPI */ +#endif /* __ARM_PMU_H__ */
Signature · 1 line
2.4.3
PATCH 3/4 arm64: pmu: Add support for probing with ACPI
Quoted 10 lines · Jeremy Linton
drivers/perf/arm_pmu_acpi.c new file +10
-0+int i, count, irq; + +if (acpi_disabled) +return 0 ; + +acpi_parse_boot_cpu (); + +/* Must have irq for boot boot cpu, at least */ +if (pirq->gsi ==0 ) +return -EINVAL ;
drivers/perf/arm_pmu_acpi.c line 87
Quoted 10 lines
drivers/perf/arm_pmu_acpi.c new file +10
-0+ + irq =acpi_register_gsi (NULL , pirq->gsi, pirq->trigger, +ACPI_ACTIVE_HIGH ); + +if (irq_is_percpu (irq)) + count =1 ; +else +for (i =1 , count =1 ; i <NR_CPUS ; i++) +if (pmu_irqs[i].gsi) + ++count;
You could more simply with:
int count = 1 ... if (!irq_is_percpu(irq)) for (i = 1; i < NR_CPUS; i++) if (pmu_irqs[i].gsi) ++count;
Signature · 3 lines
Sent by an employee of the Qualcomm Innovation Center, Inc. The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation.
PATCH v3 3/4 arm64: pmu: Add support for probing with ACPI
Quoted 24 lines · Timur Tabi
Quoted 10 lines · Jeremy Linton
drivers/perf/arm_pmu_acpi.c new file +10
-0+int i, count, irq; + +if (acpi_disabled) +return 0 ; + +acpi_parse_boot_cpu (); + +/* Must have irq for boot boot cpu, at least */ +if (pirq->gsi ==0 ) +return -EINVAL ;drivers/perf/arm_pmu_acpi.c line 87
Quoted 10 lines
drivers/perf/arm_pmu_acpi.c new file +10
-0+ + irq =acpi_register_gsi (NULL , pirq->gsi, pirq->trigger, +ACPI_ACTIVE_HIGH ); + +if (irq_is_percpu (irq)) + count =1 ; +else +for (i =1 , count =1 ; i <NR_CPUS ; i++) +if (pmu_irqs[i].gsi) + ++count;You could more simply with:
Quoted 6 lines
int count = 1
...
if (!irq_is_percpu(irq))
for (i = 1; i < NR_CPUS; i++)
if (pmu_irqs[i].gsi)
++count;I think you will notice that the following patch rewrites a lot of this function.
I kept the original patches from Mark to identify/segment his contribution because they run/bisect by themselves. They should probably be squashed together for review purposes.
PATCH v3 4/4 arm64: pmu: add A72 cpu type, support multiple PMU types
In reply to Jeremy LintonARM big/little machines can have PMU's with differing PMU counters. ACPI systems should be able to support this as well. Also add support for A72 PMU counters.
--- arch/arm64/include/asm/cputype.h | 1 + arch/arm64/kernel/perf_event.c | 1 + drivers/perf/arm_pmu.c | 54 +++++++-- drivers/perf/arm_pmu_acpi.c | 229 +++++++++++++++++++++++++++------------ 4 files changed, 204 insertions(+), 81 deletions(-)
arch/arm64/include/asm/cputype.h +1 -0
@@ -74,6 +74,7 @@#define ARM_CPU_PART_AEM_V8 0xD0F#define ARM_CPU_PART_FOUNDATION 0xD00 +#define ARM_CPU_PART_CORTEX_A72 0xD08#define ARM_CPU_PART_CORTEX_A57 0xD07#define ARM_CPU_PART_CORTEX_A53 0xD03
arch/arm64/kernel/perf_event.c +1 -0
@@ -904,6 +904,7 @@ static const struct of_device_id armv8_pmu_of_device_ids[] = {static const struct pmu_probe_info armv8_pmu_probe_table[] = {ARMV8_PMU_PART_PROBE (ARM_CPU_PART_CORTEX_A53 , armv8_a53_pmu_init),ARMV8_PMU_PART_PROBE (ARM_CPU_PART_CORTEX_A57 , armv8_a57_pmu_init), +ARMV8_PMU_PART_PROBE (ARM_CPU_PART_CORTEX_A72 , armv8_a72_pmu_init),PMU_PROBE (0 ,0 , armv8_pmuv3_init),/* if all else fails... */ {/* sentinel value */ } };
drivers/perf/arm_pmu.c +44 -10
89 lines not on this page · raw message
drivers/perf/arm_pmu_acpi.c +158 -71
280 lines not on this page · raw message
Signature · 1 line
2.4.3