Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux

Pull arm64 regression fix from Will Deacon:
"Apologies for the _extremely_ late pull request here, but we had a
'perf' (i.e. CPU PMU) regression on the Apple M1 reported on Wednesday
[1] which was introduced by bd2756811766 ("perf: Rewrite core context
handling") during the merge window.

Mark and I looked into this and noticed an additional problem caused
by the same patch, where the 'CHAIN' event (used to combine two
adjacent 32-bit counters into a single 64-bit counter) was not being
filtered correctly. Mark posted a series on Thursday [2] which
addresses both of these regressions and I queued it the same day.

The changes are small, self-contained and have been confirmed to fix
the original regression.

Summary:

- Fix 'perf' regression for non-standard CPU PMU hardware (i.e. Apple
M1)"

* tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux:
arm64: perf: reject CHAIN events at creation time
arm_pmu: fix event CPU filtering

+9 -15
+8 -7
arch/arm64/kernel/perf_event.c
··· 1023 1023 return 0; 1024 1024 } 1025 1025 1026 - static bool armv8pmu_filter(struct pmu *pmu, int cpu) 1027 - { 1028 - struct arm_pmu *armpmu = to_arm_pmu(pmu); 1029 - return !cpumask_test_cpu(smp_processor_id(), &armpmu->supported_cpus); 1030 - } 1031 - 1032 1026 static void armv8pmu_reset(void *info) 1033 1027 { 1034 1028 struct arm_pmu *cpu_pmu = (struct arm_pmu *)info; ··· 1062 1068 hw_event_id = armpmu_map_event(event, &armv8_pmuv3_perf_map, 1063 1069 &armv8_pmuv3_perf_cache_map, 1064 1070 ARMV8_PMU_EVTYPE_EVENT); 1071 + 1072 + /* 1073 + * CHAIN events only work when paired with an adjacent counter, and it 1074 + * never makes sense for a user to open one in isolation, as they'll be 1075 + * rotated arbitrarily. 1076 + */ 1077 + if (hw_event_id == ARMV8_PMUV3_PERFCTR_CHAIN) 1078 + return -EINVAL; 1065 1079 1066 1080 if (armv8pmu_event_is_64bit(event)) 1067 1081 event->hw.flags |= ARMPMU_EVT_64BIT; ··· 1260 1258 cpu_pmu->stop = armv8pmu_stop; 1261 1259 cpu_pmu->reset = armv8pmu_reset; 1262 1260 cpu_pmu->set_event_filter = armv8pmu_set_event_filter; 1263 - cpu_pmu->filter = armv8pmu_filter; 1264 1261 1265 1262 cpu_pmu->pmu.event_idx = armv8pmu_user_event_idx; 1266 1263
+1 -7
drivers/perf/arm_pmu.c
··· 550 550 static bool armpmu_filter(struct pmu *pmu, int cpu) 551 551 { 552 552 struct arm_pmu *armpmu = to_arm_pmu(pmu); 553 - bool ret; 554 - 555 - ret = cpumask_test_cpu(cpu, &armpmu->supported_cpus); 556 - if (ret && armpmu->filter) 557 - return armpmu->filter(pmu, cpu); 558 - 559 - return ret; 553 + return !cpumask_test_cpu(cpu, &armpmu->supported_cpus); 560 554 } 561 555 562 556 static ssize_t cpus_show(struct device *dev,
-1
include/linux/perf/arm_pmu.h
··· 100 100 void (*stop)(struct arm_pmu *); 101 101 void (*reset)(void *); 102 102 int (*map_event)(struct perf_event *event); 103 - bool (*filter)(struct pmu *pmu, int cpu); 104 103 int num_events; 105 104 bool secure_access; /* 32-bit ARM only */ 106 105 #define ARMV8_PMUV3_MAX_COMMON_EVENTS 0x40