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

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

Will writes:
"More arm64 fixes

- Reject CHAIN PMU events when they are not part of a 64-bit counter

- Fix WARN_ON_ONCE() that triggers for reserved regions that don't
correspond to mapped memory"

* tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux:
arm64: perf: Reject stand-alone CHAIN events for PMUv3
arm64: Fix /proc/iomem for reserved but not memory regions

+40 -28
+7
arch/arm64/kernel/perf_event.c
··· 966 966 return 0; 967 967 } 968 968 969 + static int armv8pmu_filter_match(struct perf_event *event) 970 + { 971 + unsigned long evtype = event->hw.config_base & ARMV8_PMU_EVTYPE_EVENT; 972 + return evtype != ARMV8_PMUV3_PERFCTR_CHAIN; 973 + } 974 + 969 975 static void armv8pmu_reset(void *info) 970 976 { 971 977 struct arm_pmu *cpu_pmu = (struct arm_pmu *)info; ··· 1120 1114 cpu_pmu->stop = armv8pmu_stop, 1121 1115 cpu_pmu->reset = armv8pmu_reset, 1122 1116 cpu_pmu->set_event_filter = armv8pmu_set_event_filter; 1117 + cpu_pmu->filter_match = armv8pmu_filter_match; 1123 1118 1124 1119 return 0; 1125 1120 }
+25 -27
arch/arm64/kernel/setup.c
··· 64 64 #include <asm/xen/hypervisor.h> 65 65 #include <asm/mmu_context.h> 66 66 67 + static int num_standard_resources; 68 + static struct resource *standard_resources; 69 + 67 70 phys_addr_t __fdt_pointer __initdata; 68 71 69 72 /* ··· 209 206 { 210 207 struct memblock_region *region; 211 208 struct resource *res; 209 + unsigned long i = 0; 212 210 213 211 kernel_code.start = __pa_symbol(_text); 214 212 kernel_code.end = __pa_symbol(__init_begin - 1); 215 213 kernel_data.start = __pa_symbol(_sdata); 216 214 kernel_data.end = __pa_symbol(_end - 1); 217 215 216 + num_standard_resources = memblock.memory.cnt; 217 + standard_resources = alloc_bootmem_low(num_standard_resources * 218 + sizeof(*standard_resources)); 219 + 218 220 for_each_memblock(memory, region) { 219 - res = alloc_bootmem_low(sizeof(*res)); 221 + res = &standard_resources[i++]; 220 222 if (memblock_is_nomap(region)) { 221 223 res->name = "reserved"; 222 224 res->flags = IORESOURCE_MEM; ··· 251 243 252 244 static int __init reserve_memblock_reserved_regions(void) 253 245 { 254 - phys_addr_t start, end, roundup_end = 0; 255 - struct resource *mem, *res; 256 - u64 i; 246 + u64 i, j; 257 247 258 - for_each_reserved_mem_region(i, &start, &end) { 259 - if (end <= roundup_end) 260 - continue; /* done already */ 248 + for (i = 0; i < num_standard_resources; ++i) { 249 + struct resource *mem = &standard_resources[i]; 250 + phys_addr_t r_start, r_end, mem_size = resource_size(mem); 261 251 262 - start = __pfn_to_phys(PFN_DOWN(start)); 263 - end = __pfn_to_phys(PFN_UP(end)) - 1; 264 - roundup_end = end; 265 - 266 - res = kzalloc(sizeof(*res), GFP_ATOMIC); 267 - if (WARN_ON(!res)) 268 - return -ENOMEM; 269 - res->start = start; 270 - res->end = end; 271 - res->name = "reserved"; 272 - res->flags = IORESOURCE_MEM; 273 - 274 - mem = request_resource_conflict(&iomem_resource, res); 275 - /* 276 - * We expected memblock_reserve() regions to conflict with 277 - * memory created by request_standard_resources(). 278 - */ 279 - if (WARN_ON_ONCE(!mem)) 252 + if (!memblock_is_region_reserved(mem->start, mem_size)) 280 253 continue; 281 - kfree(res); 282 254 283 - reserve_region_with_split(mem, start, end, "reserved"); 255 + for_each_reserved_mem_region(j, &r_start, &r_end) { 256 + resource_size_t start, end; 257 + 258 + start = max(PFN_PHYS(PFN_DOWN(r_start)), mem->start); 259 + end = min(PFN_PHYS(PFN_UP(r_end)) - 1, mem->end); 260 + 261 + if (start > mem->end || end < mem->start) 262 + continue; 263 + 264 + reserve_region_with_split(mem, start, end, "reserved"); 265 + } 284 266 } 285 267 286 268 return 0;
+7 -1
drivers/perf/arm_pmu.c
··· 485 485 { 486 486 struct arm_pmu *armpmu = to_arm_pmu(event->pmu); 487 487 unsigned int cpu = smp_processor_id(); 488 - return cpumask_test_cpu(cpu, &armpmu->supported_cpus); 488 + int ret; 489 + 490 + ret = cpumask_test_cpu(cpu, &armpmu->supported_cpus); 491 + if (ret && armpmu->filter_match) 492 + return armpmu->filter_match(event); 493 + 494 + return ret; 489 495 } 490 496 491 497 static ssize_t armpmu_cpumask_show(struct device *dev,
+1
include/linux/perf/arm_pmu.h
··· 99 99 void (*stop)(struct arm_pmu *); 100 100 void (*reset)(void *); 101 101 int (*map_event)(struct perf_event *event); 102 + int (*filter_match)(struct perf_event *event); 102 103 int num_events; 103 104 bool secure_access; /* 32-bit ARM only */ 104 105 #define ARMV8_PMUV3_MAX_COMMON_EVENTS 0x40