Skip to content

Commit ded9b5d

Browse files
committed
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf fixes from Ingo Molnar: "Six fixes for bugs that were found via fuzzing, and a trivial hw-enablement patch for AMD Family-17h CPU PMUs" * 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: perf/x86/intel/uncore: Allow only a single PMU/box within an events group perf/x86/intel: Cure bogus unwind from PEBS entries perf/x86: Restore TASK_SIZE check on frame pointer perf/core: Fix address filter parser perf/x86: Add perf support for AMD family-17h processors perf/x86/uncore: Fix crash by removing bogus event_list[] handling for SNB client uncore IMC perf/core: Do not set cpuctx->cgrp for unscheduled cgroups
2 parents 23aabe7 + 033ac60 commit ded9b5d

7 files changed

Lines changed: 50 additions & 38 deletions

File tree

arch/x86/events/amd/core.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -662,7 +662,13 @@ static int __init amd_core_pmu_init(void)
662662
pr_cont("Fam15h ");
663663
x86_pmu.get_event_constraints = amd_get_event_constraints_f15h;
664664
break;
665-
665+
case 0x17:
666+
pr_cont("Fam17h ");
667+
/*
668+
* In family 17h, there are no event constraints in the PMC hardware.
669+
* We fallback to using default amd_get_event_constraints.
670+
*/
671+
break;
666672
default:
667673
pr_err("core perfctr but no constraints; unknown hardware!\n");
668674
return -ENODEV;

arch/x86/events/core.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2352,7 +2352,7 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry_ctx *ent
23522352
frame.next_frame = 0;
23532353
frame.return_address = 0;
23542354

2355-
if (!access_ok(VERIFY_READ, fp, 8))
2355+
if (!valid_user_frame(fp, sizeof(frame)))
23562356
break;
23572357

23582358
bytes = __copy_from_user_nmi(&frame.next_frame, fp, 4);
@@ -2362,9 +2362,6 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry_ctx *ent
23622362
if (bytes != 0)
23632363
break;
23642364

2365-
if (!valid_user_frame(fp, sizeof(frame)))
2366-
break;
2367-
23682365
perf_callchain_store(entry, cs_base + frame.return_address);
23692366
fp = compat_ptr(ss_base + frame.next_frame);
23702367
}
@@ -2413,7 +2410,7 @@ perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs
24132410
frame.next_frame = NULL;
24142411
frame.return_address = 0;
24152412

2416-
if (!access_ok(VERIFY_READ, fp, sizeof(*fp) * 2))
2413+
if (!valid_user_frame(fp, sizeof(frame)))
24172414
break;
24182415

24192416
bytes = __copy_from_user_nmi(&frame.next_frame, fp, sizeof(*fp));
@@ -2423,9 +2420,6 @@ perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs
24232420
if (bytes != 0)
24242421
break;
24252422

2426-
if (!valid_user_frame(fp, sizeof(frame)))
2427-
break;
2428-
24292423
perf_callchain_store(entry, frame.return_address);
24302424
fp = (void __user *)frame.next_frame;
24312425
}

arch/x86/events/intel/ds.c

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1108,20 +1108,20 @@ static void setup_pebs_sample_data(struct perf_event *event,
11081108
}
11091109

11101110
/*
1111-
* We use the interrupt regs as a base because the PEBS record
1112-
* does not contain a full regs set, specifically it seems to
1113-
* lack segment descriptors, which get used by things like
1114-
* user_mode().
1111+
* We use the interrupt regs as a base because the PEBS record does not
1112+
* contain a full regs set, specifically it seems to lack segment
1113+
* descriptors, which get used by things like user_mode().
11151114
*
1116-
* In the simple case fix up only the IP and BP,SP regs, for
1117-
* PERF_SAMPLE_IP and PERF_SAMPLE_CALLCHAIN to function properly.
1118-
* A possible PERF_SAMPLE_REGS will have to transfer all regs.
1115+
* In the simple case fix up only the IP for PERF_SAMPLE_IP.
1116+
*
1117+
* We must however always use BP,SP from iregs for the unwinder to stay
1118+
* sane; the record BP,SP can point into thin air when the record is
1119+
* from a previous PMI context or an (I)RET happend between the record
1120+
* and PMI.
11191121
*/
11201122
*regs = *iregs;
11211123
regs->flags = pebs->flags;
11221124
set_linear_ip(regs, pebs->ip);
1123-
regs->bp = pebs->bp;
1124-
regs->sp = pebs->sp;
11251125

11261126
if (sample_type & PERF_SAMPLE_REGS_INTR) {
11271127
regs->ax = pebs->ax;
@@ -1130,10 +1130,21 @@ static void setup_pebs_sample_data(struct perf_event *event,
11301130
regs->dx = pebs->dx;
11311131
regs->si = pebs->si;
11321132
regs->di = pebs->di;
1133-
regs->bp = pebs->bp;
1134-
regs->sp = pebs->sp;
11351133

1136-
regs->flags = pebs->flags;
1134+
/*
1135+
* Per the above; only set BP,SP if we don't need callchains.
1136+
*
1137+
* XXX: does this make sense?
1138+
*/
1139+
if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) {
1140+
regs->bp = pebs->bp;
1141+
regs->sp = pebs->sp;
1142+
}
1143+
1144+
/*
1145+
* Preserve PERF_EFLAGS_VM from set_linear_ip().
1146+
*/
1147+
regs->flags = pebs->flags | (regs->flags & PERF_EFLAGS_VM);
11371148
#ifndef CONFIG_X86_32
11381149
regs->r8 = pebs->r8;
11391150
regs->r9 = pebs->r9;

arch/x86/events/intel/uncore.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -319,9 +319,9 @@ static struct intel_uncore_box *uncore_alloc_box(struct intel_uncore_type *type,
319319
*/
320320
static int uncore_pmu_event_init(struct perf_event *event);
321321

322-
static bool is_uncore_event(struct perf_event *event)
322+
static bool is_box_event(struct intel_uncore_box *box, struct perf_event *event)
323323
{
324-
return event->pmu->event_init == uncore_pmu_event_init;
324+
return &box->pmu->pmu == event->pmu;
325325
}
326326

327327
static int
@@ -340,7 +340,7 @@ uncore_collect_events(struct intel_uncore_box *box, struct perf_event *leader,
340340

341341
n = box->n_events;
342342

343-
if (is_uncore_event(leader)) {
343+
if (is_box_event(box, leader)) {
344344
box->event_list[n] = leader;
345345
n++;
346346
}
@@ -349,7 +349,7 @@ uncore_collect_events(struct intel_uncore_box *box, struct perf_event *leader,
349349
return n;
350350

351351
list_for_each_entry(event, &leader->sibling_list, group_entry) {
352-
if (!is_uncore_event(event) ||
352+
if (!is_box_event(box, event) ||
353353
event->state <= PERF_EVENT_STATE_OFF)
354354
continue;
355355

arch/x86/events/intel/uncore_snb.c

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -490,24 +490,12 @@ static int snb_uncore_imc_event_add(struct perf_event *event, int flags)
490490

491491
snb_uncore_imc_event_start(event, 0);
492492

493-
box->n_events++;
494-
495493
return 0;
496494
}
497495

498496
static void snb_uncore_imc_event_del(struct perf_event *event, int flags)
499497
{
500-
struct intel_uncore_box *box = uncore_event_to_box(event);
501-
int i;
502-
503498
snb_uncore_imc_event_stop(event, PERF_EF_UPDATE);
504-
505-
for (i = 0; i < box->n_events; i++) {
506-
if (event == box->event_list[i]) {
507-
--box->n_events;
508-
break;
509-
}
510-
}
511499
}
512500

513501
int snb_pci2phy_map_init(int devid)

arch/x86/events/perf_event.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ struct debug_store {
113113
* Per register state.
114114
*/
115115
struct er_account {
116-
raw_spinlock_t lock; /* per-core: protect structure */
116+
raw_spinlock_t lock; /* per-core: protect structure */
117117
u64 config; /* extra MSR config */
118118
u64 reg; /* extra MSR number */
119119
atomic_t ref; /* reference count */

kernel/events/core.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -902,6 +902,17 @@ list_update_cgroup_event(struct perf_event *event,
902902
* this will always be called from the right CPU.
903903
*/
904904
cpuctx = __get_cpu_context(ctx);
905+
906+
/* Only set/clear cpuctx->cgrp if current task uses event->cgrp. */
907+
if (perf_cgroup_from_task(current, ctx) != event->cgrp) {
908+
/*
909+
* We are removing the last cpu event in this context.
910+
* If that event is not active in this cpu, cpuctx->cgrp
911+
* should've been cleared by perf_cgroup_switch.
912+
*/
913+
WARN_ON_ONCE(!add && cpuctx->cgrp);
914+
return;
915+
}
905916
cpuctx->cgrp = add ? event->cgrp : NULL;
906917
}
907918

@@ -8018,6 +8029,7 @@ static void perf_event_addr_filters_apply(struct perf_event *event)
80188029
* if <size> is not specified, the range is treated as a single address.
80198030
*/
80208031
enum {
8032+
IF_ACT_NONE = -1,
80218033
IF_ACT_FILTER,
80228034
IF_ACT_START,
80238035
IF_ACT_STOP,
@@ -8041,6 +8053,7 @@ static const match_table_t if_tokens = {
80418053
{ IF_SRC_KERNEL, "%u/%u" },
80428054
{ IF_SRC_FILEADDR, "%u@%s" },
80438055
{ IF_SRC_KERNELADDR, "%u" },
8056+
{ IF_ACT_NONE, NULL },
80448057
};
80458058

80468059
/*

0 commit comments

Comments
 (0)