History

Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull perf fixes from Ingo Molnar: "Two fixes on the kernel side: fix an over-eager condition that failed larger perf ring-buffer sizes, plus fix crashes in the Intel BTS code for a corner case, found by fuzzing" * 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: perf/core: Fix impossible ring-buffer sizes warning perf/x86: Add check_period PMU callback

Linus Torvalds committed 7 years ago

Commit dd6f29d2 parents c5f1ac5 528871b6 files · +59 −3Browse files

Unified · Split

6 files
  1. arch/x86/events/core.c +14 −0
  2. arch/x86/events/intel/core.c +9 −0
  3. arch/x86/events/perf_event.h +14 −2
  4. include/linux/perf_event.h +5 −0
  5. kernel/events/core.c +16 −0
  6. kernel/events/ring_buffer.c +1 −1
arch/x86/events/core.c+14−0
@@ -2278,6 +2278,19 @@ void perf_check_microcode(void) · 2277 unmodified lines
22782278 x86_pmu.check_microcode();
22792279 }
22802280
2281+static int x86_pmu_check_period(struct perf_event *event, u64 value)
2282+{
2283+ if (x86_pmu.check_period && x86_pmu.check_period(event, value))
2284+ return -EINVAL;
2285+
2286+ if (value && x86_pmu.limit_period) {
2287+ if (x86_pmu.limit_period(event, value) > value)
2288+ return -EINVAL;
2289+ }
2290+
2291+ return 0;
2292+}
2293+
22812294 static struct pmu pmu = {
22822295 .pmu_enable = x86_pmu_enable,
22832296 .pmu_disable = x86_pmu_disable,
@@ -2302,6 +2315,7 @@ static struct pmu pmu = { · 18 unmodified lines
23022315 .event_idx = x86_pmu_event_idx,
23032316 .sched_task = x86_pmu_sched_task,
23042317 .task_ctx_size = sizeof(struct x86_perf_task_context),
2318+ .check_period = x86_pmu_check_period,
23052319 };
23062320
23072321 void arch_perf_update_userpage(struct perf_event *event,
arch/x86/events/intel/core.c+9−0
@@ -3587,6 +3587,11 @@ static void intel_pmu_sched_task(struct perf_event_context *ctx, · 3586 unmodified lines
35873587 intel_pmu_lbr_sched_task(ctx, sched_in);
35883588 }
35893589
3590+static int intel_pmu_check_period(struct perf_event *event, u64 value)
3591+{
3592+ return intel_pmu_has_bts_period(event, value) ? -EINVAL : 0;
3593+}
3594+
35903595 PMU_FORMAT_ATTR(offcore_rsp, "config1:0-63");
35913596
35923597 PMU_FORMAT_ATTR(ldlat, "config1:0-15");
@@ -3667,6 +3672,8 @@ static __initconst const struct x86_pmu core_pmu = { · 74 unmodified lines
36673672 .cpu_starting = intel_pmu_cpu_starting,
36683673 .cpu_dying = intel_pmu_cpu_dying,
36693674 .cpu_dead = intel_pmu_cpu_dead,
3675+
3676+ .check_period = intel_pmu_check_period,
36703677 };
36713678
36723679 static struct attribute *intel_pmu_attrs[];
@@ -3711,6 +3718,8 @@ static __initconst const struct x86_pmu intel_pmu = { · 38 unmodified lines
37113718
37123719 .guest_get_msrs = intel_guest_get_msrs,
37133720 .sched_task = intel_pmu_sched_task,
3721+
3722+ .check_period = intel_pmu_check_period,
37143723 };
37153724
37163725 static __init void intel_clovertown_quirk(void)
arch/x86/events/perf_event.h+14−2
@@ -646,6 +646,11 @@ struct x86_pmu { · 645 unmodified lines
646646 * Intel host/guest support (KVM)
647647 */
648648 struct perf_guest_switch_msr *(*guest_get_msrs)(int *nr);
649+
650+ /*
651+ * Check period value for PERF_EVENT_IOC_PERIOD ioctl.
652+ */
653+ int (*check_period) (struct perf_event *event, u64 period);
649654 };
650655
651656 struct x86_perf_task_context {
@@ -857,7 +862,7 @@ static inline int amd_pmu_init(void) · 205 unmodified lines
857862
858863 #ifdef CONFIG_CPU_SUP_INTEL
859864
860−static inline bool intel_pmu_has_bts(struct perf_event *event)
865+static inline bool intel_pmu_has_bts_period(struct perf_event *event, u64 period)
861866 {
862867 struct hw_perf_event *hwc = &event->hw;
863868 unsigned int hw_event, bts_event;
@@ -868,7 +873,14 @@ static inline bool intel_pmu_has_bts(struct perf_event *event) · 4 unmodified lines
868873 hw_event = hwc->config & INTEL_ARCH_EVENT_MASK;
869874 bts_event = x86_pmu.event_map(PERF_COUNT_HW_BRANCH_INSTRUCTIONS);
870875
871− return hw_event == bts_event && hwc->sample_period == 1;
876+ return hw_event == bts_event && period == 1;
877+}
878+
879+static inline bool intel_pmu_has_bts(struct perf_event *event)
880+{
881+ struct hw_perf_event *hwc = &event->hw;
882+
883+ return intel_pmu_has_bts_period(event, hwc->sample_period);
872884 }
873885
874886 int intel_pmu_save_and_restart(struct perf_event *event);
include/linux/perf_event.h+5−0
@@ -447,6 +447,11 @@ struct pmu { · 446 unmodified lines
447447 * Filter events for PMU-specific reasons.
448448 */
449449 int (*filter_match) (struct perf_event *event); /* optional */
450+
451+ /*
452+ * Check period value for PERF_EVENT_IOC_PERIOD ioctl.
453+ */
454+ int (*check_period) (struct perf_event *event, u64 value); /* optional */
450455 };
451456
452457 enum perf_addr_filter_action_t {
kernel/events/core.c+16−0
@@ -4963,6 +4963,11 @@ static void __perf_event_period(struct perf_event *event, · 4962 unmodified lines
49634963 }
49644964 }
49654965
4966+static int perf_event_check_period(struct perf_event *event, u64 value)
4967+{
4968+ return event->pmu->check_period(event, value);
4969+}
4970+
49664971 static int perf_event_period(struct perf_event *event, u64 __user *arg)
49674972 {
49684973 u64 value;
@@ -4979,6 +4984,9 @@ static int perf_event_period(struct perf_event *event, u64 __user *arg) · 10 unmodified lines
49794984 if (event->attr.freq && value > sysctl_perf_event_sample_rate)
49804985 return -EINVAL;
49814986
4987+ if (perf_event_check_period(event, value))
4988+ return -EINVAL;
4989+
49824990 event_function_call(event, __perf_event_period, &value);
49834991
49844992 return 0;
@@ -9391,6 +9399,11 @@ static int perf_pmu_nop_int(struct pmu *pmu) · 4406 unmodified lines
93919399 return 0;
93929400 }
93939401
9402+static int perf_event_nop_int(struct perf_event *event, u64 value)
9403+{
9404+ return 0;
9405+}
9406+
93949407 static DEFINE_PER_CPU(unsigned int, nop_txn_flags);
93959408
93969409 static void perf_pmu_start_txn(struct pmu *pmu, unsigned int flags)
@@ -9691,6 +9704,9 @@ got_cpu_context: · 294 unmodified lines
96919704 pmu->pmu_disable = perf_pmu_nop_void;
96929705 }
96939706
9707+ if (!pmu->check_period)
9708+ pmu->check_period = perf_event_nop_int;
9709+
96949710 if (!pmu->event_idx)
96959711 pmu->event_idx = perf_event_idx_default;
96969712
kernel/events/ring_buffer.c+1−1
@@ -734,7 +734,7 @@ struct ring_buffer *rb_alloc(int nr_pages, long watermark, int cpu, int flags) · 733 unmodified lines
734734 size = sizeof(struct ring_buffer);
735735 size += nr_pages * sizeof(void *);
736736
737− if (order_base_2(size) >= MAX_ORDER)
737+ if (order_base_2(size) >= PAGE_SHIFT+MAX_ORDER)
738738 goto fail;
739739
740740 rb = kzalloc(size, GFP_KERNEL);