Merge tag 'cris-for-4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/jesper...
[cascardo/linux.git] / arch / arm64 / kernel / perf_event.c
index 838ccf1..a9310a6 100644 (file)
@@ -24,6 +24,7 @@
 #include <asm/sysreg.h>
 #include <asm/virt.h>
 
+#include <linux/acpi.h>
 #include <linux/of.h>
 #include <linux/perf/arm_pmu.h>
 #include <linux/platform_device.h>
 #define ARMV8_THUNDER_PERFCTR_L1I_CACHE_PREF_MISS              0xED
 
 /* PMUv3 HW events mapping. */
+
+/*
+ * ARMv8 Architectural defined events, not all of these may
+ * be supported on any given implementation. Undefined events will
+ * be disabled at run-time.
+ */
 static const unsigned armv8_pmuv3_perf_map[PERF_COUNT_HW_MAX] = {
        PERF_MAP_ALL_UNSUPPORTED,
        [PERF_COUNT_HW_CPU_CYCLES]              = ARMV8_PMUV3_PERFCTR_CPU_CYCLES,
        [PERF_COUNT_HW_INSTRUCTIONS]            = ARMV8_PMUV3_PERFCTR_INST_RETIRED,
        [PERF_COUNT_HW_CACHE_REFERENCES]        = ARMV8_PMUV3_PERFCTR_L1D_CACHE,
        [PERF_COUNT_HW_CACHE_MISSES]            = ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL,
+       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]     = ARMV8_PMUV3_PERFCTR_PC_WRITE_RETIRED,
        [PERF_COUNT_HW_BRANCH_MISSES]           = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
+       [PERF_COUNT_HW_BUS_CYCLES]              = ARMV8_PMUV3_PERFCTR_BUS_CYCLES,
+       [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = ARMV8_PMUV3_PERFCTR_STALL_FRONTEND,
+       [PERF_COUNT_HW_STALLED_CYCLES_BACKEND]  = ARMV8_PMUV3_PERFCTR_STALL_BACKEND,
 };
 
 /* ARM Cortex-A53 HW events mapping. */
@@ -258,6 +269,15 @@ static const unsigned armv8_pmuv3_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
        [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1D_CACHE,
        [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)]   = ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL,
 
+       [C(L1I)][C(OP_READ)][C(RESULT_ACCESS)]  = ARMV8_PMUV3_PERFCTR_L1I_CACHE,
+       [C(L1I)][C(OP_READ)][C(RESULT_MISS)]    = ARMV8_PMUV3_PERFCTR_L1I_CACHE_REFILL,
+
+       [C(DTLB)][C(OP_READ)][C(RESULT_MISS)]   = ARMV8_PMUV3_PERFCTR_L1D_TLB_REFILL,
+       [C(DTLB)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1D_TLB,
+
+       [C(ITLB)][C(OP_READ)][C(RESULT_MISS)]   = ARMV8_PMUV3_PERFCTR_L1I_TLB_REFILL,
+       [C(ITLB)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1I_TLB,
+
        [C(BPU)][C(OP_READ)][C(RESULT_ACCESS)]  = ARMV8_PMUV3_PERFCTR_BR_PRED,
        [C(BPU)][C(OP_READ)][C(RESULT_MISS)]    = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
        [C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_BR_PRED,
@@ -523,12 +543,6 @@ static struct attribute_group armv8_pmuv3_format_attr_group = {
        .attrs = armv8_pmuv3_format_attrs,
 };
 
-static const struct attribute_group *armv8_pmuv3_attr_groups[] = {
-       &armv8_pmuv3_events_attr_group,
-       &armv8_pmuv3_format_attr_group,
-       NULL,
-};
-
 /*
  * Perf Events' indices
  */
@@ -905,9 +919,22 @@ static void armv8pmu_reset(void *info)
 
 static int armv8_pmuv3_map_event(struct perf_event *event)
 {
-       return armpmu_map_event(event, &armv8_pmuv3_perf_map,
-                               &armv8_pmuv3_perf_cache_map,
-                               ARMV8_PMU_EVTYPE_EVENT);
+       int hw_event_id;
+       struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
+
+       hw_event_id = armpmu_map_event(event, &armv8_pmuv3_perf_map,
+                                      &armv8_pmuv3_perf_cache_map,
+                                      ARMV8_PMU_EVTYPE_EVENT);
+       if (hw_event_id < 0)
+               return hw_event_id;
+
+       /* disable micro/arch events not supported by this PMU */
+       if ((hw_event_id < ARMV8_PMUV3_MAX_COMMON_EVENTS) &&
+               !test_bit(hw_event_id, armpmu->pmceid_bitmap)) {
+                       return -EOPNOTSUPP;
+       }
+
+       return hw_event_id;
 }
 
 static int armv8_a53_map_event(struct perf_event *event)
@@ -985,7 +1012,10 @@ static int armv8_pmuv3_init(struct arm_pmu *cpu_pmu)
        armv8_pmu_init(cpu_pmu);
        cpu_pmu->name                   = "armv8_pmuv3";
        cpu_pmu->map_event              = armv8_pmuv3_map_event;
-       cpu_pmu->pmu.attr_groups        = armv8_pmuv3_attr_groups;
+       cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] =
+               &armv8_pmuv3_events_attr_group;
+       cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] =
+               &armv8_pmuv3_format_attr_group;
        return armv8pmu_probe_pmu(cpu_pmu);
 }
 
@@ -994,7 +1024,10 @@ static int armv8_a53_pmu_init(struct arm_pmu *cpu_pmu)
        armv8_pmu_init(cpu_pmu);
        cpu_pmu->name                   = "armv8_cortex_a53";
        cpu_pmu->map_event              = armv8_a53_map_event;
-       cpu_pmu->pmu.attr_groups        = armv8_pmuv3_attr_groups;
+       cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] =
+               &armv8_pmuv3_events_attr_group;
+       cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] =
+               &armv8_pmuv3_format_attr_group;
        return armv8pmu_probe_pmu(cpu_pmu);
 }
 
@@ -1003,7 +1036,10 @@ static int armv8_a57_pmu_init(struct arm_pmu *cpu_pmu)
        armv8_pmu_init(cpu_pmu);
        cpu_pmu->name                   = "armv8_cortex_a57";
        cpu_pmu->map_event              = armv8_a57_map_event;
-       cpu_pmu->pmu.attr_groups        = armv8_pmuv3_attr_groups;
+       cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] =
+               &armv8_pmuv3_events_attr_group;
+       cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] =
+               &armv8_pmuv3_format_attr_group;
        return armv8pmu_probe_pmu(cpu_pmu);
 }
 
@@ -1012,7 +1048,10 @@ static int armv8_a72_pmu_init(struct arm_pmu *cpu_pmu)
        armv8_pmu_init(cpu_pmu);
        cpu_pmu->name                   = "armv8_cortex_a72";
        cpu_pmu->map_event              = armv8_a57_map_event;
-       cpu_pmu->pmu.attr_groups        = armv8_pmuv3_attr_groups;
+       cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] =
+               &armv8_pmuv3_events_attr_group;
+       cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] =
+               &armv8_pmuv3_format_attr_group;
        return armv8pmu_probe_pmu(cpu_pmu);
 }
 
@@ -1021,7 +1060,10 @@ static int armv8_thunder_pmu_init(struct arm_pmu *cpu_pmu)
        armv8_pmu_init(cpu_pmu);
        cpu_pmu->name                   = "armv8_cavium_thunder";
        cpu_pmu->map_event              = armv8_thunder_map_event;
-       cpu_pmu->pmu.attr_groups        = armv8_pmuv3_attr_groups;
+       cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] =
+               &armv8_pmuv3_events_attr_group;
+       cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] =
+               &armv8_pmuv3_format_attr_group;
        return armv8pmu_probe_pmu(cpu_pmu);
 }
 
@@ -1030,7 +1072,10 @@ static int armv8_vulcan_pmu_init(struct arm_pmu *cpu_pmu)
        armv8_pmu_init(cpu_pmu);
        cpu_pmu->name                   = "armv8_brcm_vulcan";
        cpu_pmu->map_event              = armv8_vulcan_map_event;
-       cpu_pmu->pmu.attr_groups        = armv8_pmuv3_attr_groups;
+       cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] =
+               &armv8_pmuv3_events_attr_group;
+       cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] =
+               &armv8_pmuv3_format_attr_group;
        return armv8pmu_probe_pmu(cpu_pmu);
 }
 
@@ -1044,21 +1089,32 @@ static const struct of_device_id armv8_pmu_of_device_ids[] = {
        {},
 };
 
+/*
+ * Non DT systems have their micro/arch events probed at run-time.
+ * A fairly complete list of generic events are provided and ones that
+ * aren't supported by the current PMU are disabled.
+ */
+static const struct pmu_probe_info armv8_pmu_probe_table[] = {
+       PMU_PROBE(0, 0, armv8_pmuv3_init), /* enable all defined counters */
+       { /* sentinel value */ }
+};
+
 static int armv8_pmu_device_probe(struct platform_device *pdev)
 {
-       return arm_pmu_device_probe(pdev, armv8_pmu_of_device_ids, NULL);
+       if (acpi_disabled)
+               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 = {
        .driver         = {
-               .name   = "armv8-pmu",
+               .name   = ARMV8_PMU_PDEV_NAME,
                .of_match_table = armv8_pmu_of_device_ids,
        },
        .probe          = armv8_pmu_device_probe,
 };
 
-static int __init register_armv8_pmu_driver(void)
-{
-       return platform_driver_register(&armv8_pmu_driver);
-}
-device_initcall(register_armv8_pmu_driver);
+builtin_platform_driver(armv8_pmu_driver);