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 'perf_urgent_for_v5.17_rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull perf fixes from Borislav Petkov:

- Intel/PT: filters could crash the kernel

- Intel: default disable the PMU for SMM, some new-ish EFI firmware has
started using CPL3 and the PMU CPL filters don't discriminate against
SMM, meaning that CPL3 (userspace only) events now also count EFI/SMM
cycles.

- Fixup for perf_event_attr::sig_data

* tag 'perf_urgent_for_v5.17_rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
perf/x86/intel/pt: Fix crash with stop filters in single-range mode
perf: uapi: Document perf_event_attr::sig_data truncation on 32 bit architectures
selftests/perf_events: Test modification of perf_event_attr::sig_data
perf: Copy perf_event_attr::sig_data on modification
x86/perf: Default set FREEZE_ON_SMI for all

+43 -10
+13
arch/x86/events/intel/core.c
··· 4703 4703 .lbr_read = intel_pmu_lbr_read_64, 4704 4704 .lbr_save = intel_pmu_lbr_save, 4705 4705 .lbr_restore = intel_pmu_lbr_restore, 4706 + 4707 + /* 4708 + * SMM has access to all 4 rings and while traditionally SMM code only 4709 + * ran in CPL0, 2021-era firmware is starting to make use of CPL3 in SMM. 4710 + * 4711 + * Since the EVENTSEL.{USR,OS} CPL filtering makes no distinction 4712 + * between SMM or not, this results in what should be pure userspace 4713 + * counters including SMM data. 4714 + * 4715 + * This is a clear privilege issue, therefore globally disable 4716 + * counting SMM by default. 4717 + */ 4718 + .attr_freeze_on_smi = 1, 4706 4719 }; 4707 4720 4708 4721 static __init void intel_clovertown_quirk(void)
+3 -2
arch/x86/events/intel/pt.c
··· 897 897 * means we are already losing data; need to let the decoder 898 898 * know. 899 899 */ 900 - if (!intel_pt_validate_hw_cap(PT_CAP_topa_multiple_entries) || 901 - buf->output_off == pt_buffer_region_size(buf)) { 900 + if (!buf->single && 901 + (!intel_pt_validate_hw_cap(PT_CAP_topa_multiple_entries) || 902 + buf->output_off == pt_buffer_region_size(buf))) { 902 903 perf_aux_output_flag(&pt->handle, 903 904 PERF_AUX_FLAG_TRUNCATED); 904 905 advance++;
+2
include/uapi/linux/perf_event.h
··· 465 465 /* 466 466 * User provided data if sigtrap=1, passed back to user via 467 467 * siginfo_t::si_perf_data, e.g. to permit user to identify the event. 468 + * Note, siginfo_t::si_perf_data is long-sized, and sig_data will be 469 + * truncated accordingly on 32 bit architectures. 468 470 */ 469 471 __u64 sig_data; 470 472 };
+16
kernel/events/core.c
··· 3238 3238 return err; 3239 3239 } 3240 3240 3241 + /* 3242 + * Copy event-type-independent attributes that may be modified. 3243 + */ 3244 + static void perf_event_modify_copy_attr(struct perf_event_attr *to, 3245 + const struct perf_event_attr *from) 3246 + { 3247 + to->sig_data = from->sig_data; 3248 + } 3249 + 3241 3250 static int perf_event_modify_attr(struct perf_event *event, 3242 3251 struct perf_event_attr *attr) 3243 3252 { ··· 3269 3260 WARN_ON_ONCE(event->ctx->parent_ctx); 3270 3261 3271 3262 mutex_lock(&event->child_mutex); 3263 + /* 3264 + * Event-type-independent attributes must be copied before event-type 3265 + * modification, which will validate that final attributes match the 3266 + * source attributes after all relevant attributes have been copied. 3267 + */ 3268 + perf_event_modify_copy_attr(&event->attr, attr); 3272 3269 err = func(event, attr); 3273 3270 if (err) 3274 3271 goto out; 3275 3272 list_for_each_entry(child, &event->child_list, child_list) { 3273 + perf_event_modify_copy_attr(&child->attr, attr); 3276 3274 err = func(child, attr); 3277 3275 if (err) 3278 3276 goto out;
+9 -8
tools/testing/selftests/perf_events/sigtrap_threads.c
··· 44 44 } ctx; 45 45 46 46 /* Unique value to check si_perf_data is correctly set from perf_event_attr::sig_data. */ 47 - #define TEST_SIG_DATA(addr) (~(unsigned long)(addr)) 47 + #define TEST_SIG_DATA(addr, id) (~(unsigned long)(addr) + id) 48 48 49 - static struct perf_event_attr make_event_attr(bool enabled, volatile void *addr) 49 + static struct perf_event_attr make_event_attr(bool enabled, volatile void *addr, 50 + unsigned long id) 50 51 { 51 52 struct perf_event_attr attr = { 52 53 .type = PERF_TYPE_BREAKPOINT, ··· 61 60 .inherit_thread = 1, /* ... but only cloned with CLONE_THREAD. */ 62 61 .remove_on_exec = 1, /* Required by sigtrap. */ 63 62 .sigtrap = 1, /* Request synchronous SIGTRAP on event. */ 64 - .sig_data = TEST_SIG_DATA(addr), 63 + .sig_data = TEST_SIG_DATA(addr, id), 65 64 }; 66 65 return attr; 67 66 } ··· 111 110 112 111 FIXTURE_SETUP(sigtrap_threads) 113 112 { 114 - struct perf_event_attr attr = make_event_attr(false, &ctx.iterate_on); 113 + struct perf_event_attr attr = make_event_attr(false, &ctx.iterate_on, 0); 115 114 struct sigaction action = {}; 116 115 int i; 117 116 ··· 166 165 EXPECT_EQ(ctx.tids_want_signal, 0); 167 166 EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on); 168 167 EXPECT_EQ(ctx.first_siginfo.si_perf_type, PERF_TYPE_BREAKPOINT); 169 - EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on)); 168 + EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on, 0)); 170 169 171 170 /* Check enabled for parent. */ 172 171 ctx.iterate_on = 0; ··· 176 175 /* Test that modification propagates to all inherited events. */ 177 176 TEST_F(sigtrap_threads, modify_and_enable_event) 178 177 { 179 - struct perf_event_attr new_attr = make_event_attr(true, &ctx.iterate_on); 178 + struct perf_event_attr new_attr = make_event_attr(true, &ctx.iterate_on, 42); 180 179 181 180 EXPECT_EQ(ioctl(self->fd, PERF_EVENT_IOC_MODIFY_ATTRIBUTES, &new_attr), 0); 182 181 run_test_threads(_metadata, self); ··· 185 184 EXPECT_EQ(ctx.tids_want_signal, 0); 186 185 EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on); 187 186 EXPECT_EQ(ctx.first_siginfo.si_perf_type, PERF_TYPE_BREAKPOINT); 188 - EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on)); 187 + EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on, 42)); 189 188 190 189 /* Check enabled for parent. */ 191 190 ctx.iterate_on = 0; ··· 205 204 EXPECT_EQ(ctx.tids_want_signal, 0); 206 205 EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on); 207 206 EXPECT_EQ(ctx.first_siginfo.si_perf_type, PERF_TYPE_BREAKPOINT); 208 - EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on)); 207 + EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on, 0)); 209 208 } 210 209 211 210 TEST_HARNESS_MAIN