Skip to content

Commit e66d001

Browse files
committed
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
2 parents bab5c80 + ca2b497 commit e66d001

File tree

4 files changed

+42
-30
lines changed

4 files changed

+42
-30
lines changed

arch/arm64/kernel/perf_event.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -966,6 +966,12 @@ static int armv8pmu_set_event_filter(struct hw_perf_event *event,
966966
return 0;
967967
}
968968

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+
969975
static void armv8pmu_reset(void *info)
970976
{
971977
struct arm_pmu *cpu_pmu = (struct arm_pmu *)info;
@@ -1114,6 +1120,7 @@ static int armv8_pmu_init(struct arm_pmu *cpu_pmu)
11141120
cpu_pmu->stop = armv8pmu_stop,
11151121
cpu_pmu->reset = armv8pmu_reset,
11161122
cpu_pmu->set_event_filter = armv8pmu_set_event_filter;
1123+
cpu_pmu->filter_match = armv8pmu_filter_match;
11171124

11181125
return 0;
11191126
}

arch/arm64/kernel/setup.c

Lines changed: 27 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@
6464
#include <asm/xen/hypervisor.h>
6565
#include <asm/mmu_context.h>
6666

67+
static int num_standard_resources;
68+
static struct resource *standard_resources;
69+
6770
phys_addr_t __fdt_pointer __initdata;
6871

6972
/*
@@ -206,14 +209,19 @@ static void __init request_standard_resources(void)
206209
{
207210
struct memblock_region *region;
208211
struct resource *res;
212+
unsigned long i = 0;
209213

210214
kernel_code.start = __pa_symbol(_text);
211215
kernel_code.end = __pa_symbol(__init_begin - 1);
212216
kernel_data.start = __pa_symbol(_sdata);
213217
kernel_data.end = __pa_symbol(_end - 1);
214218

219+
num_standard_resources = memblock.memory.cnt;
220+
standard_resources = alloc_bootmem_low(num_standard_resources *
221+
sizeof(*standard_resources));
222+
215223
for_each_memblock(memory, region) {
216-
res = alloc_bootmem_low(sizeof(*res));
224+
res = &standard_resources[i++];
217225
if (memblock_is_nomap(region)) {
218226
res->name = "reserved";
219227
res->flags = IORESOURCE_MEM;
@@ -243,36 +251,26 @@ static void __init request_standard_resources(void)
243251

244252
static int __init reserve_memblock_reserved_regions(void)
245253
{
246-
phys_addr_t start, end, roundup_end = 0;
247-
struct resource *mem, *res;
248-
u64 i;
249-
250-
for_each_reserved_mem_region(i, &start, &end) {
251-
if (end <= roundup_end)
252-
continue; /* done already */
253-
254-
start = __pfn_to_phys(PFN_DOWN(start));
255-
end = __pfn_to_phys(PFN_UP(end)) - 1;
256-
roundup_end = end;
257-
258-
res = kzalloc(sizeof(*res), GFP_ATOMIC);
259-
if (WARN_ON(!res))
260-
return -ENOMEM;
261-
res->start = start;
262-
res->end = end;
263-
res->name = "reserved";
264-
res->flags = IORESOURCE_MEM;
265-
266-
mem = request_resource_conflict(&iomem_resource, res);
267-
/*
268-
* We expected memblock_reserve() regions to conflict with
269-
* memory created by request_standard_resources().
270-
*/
271-
if (WARN_ON_ONCE(!mem))
254+
u64 i, j;
255+
256+
for (i = 0; i < num_standard_resources; ++i) {
257+
struct resource *mem = &standard_resources[i];
258+
phys_addr_t r_start, r_end, mem_size = resource_size(mem);
259+
260+
if (!memblock_is_region_reserved(mem->start, mem_size))
272261
continue;
273-
kfree(res);
274262

275-
reserve_region_with_split(mem, start, end, "reserved");
263+
for_each_reserved_mem_region(j, &r_start, &r_end) {
264+
resource_size_t start, end;
265+
266+
start = max(PFN_PHYS(PFN_DOWN(r_start)), mem->start);
267+
end = min(PFN_PHYS(PFN_UP(r_end)) - 1, mem->end);
268+
269+
if (start > mem->end || end < mem->start)
270+
continue;
271+
272+
reserve_region_with_split(mem, start, end, "reserved");
273+
}
276274
}
277275

278276
return 0;

drivers/perf/arm_pmu.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,13 @@ static int armpmu_filter_match(struct perf_event *event)
485485
{
486486
struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
487487
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;
489495
}
490496

491497
static ssize_t armpmu_cpumask_show(struct device *dev,

include/linux/perf/arm_pmu.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ struct arm_pmu {
9999
void (*stop)(struct arm_pmu *);
100100
void (*reset)(void *);
101101
int (*map_event)(struct perf_event *event);
102+
int (*filter_match)(struct perf_event *event);
102103
int num_events;
103104
bool secure_access; /* 32-bit ARM only */
104105
#define ARMV8_PMUV3_MAX_COMMON_EVENTS 0x40

0 commit comments

Comments
 (0)