aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/perf_event.h12
-rw-r--r--kernel/perf_event.c108
2 files changed, 102 insertions, 18 deletions
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index b9950b1620d8..2814ead4adb8 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -215,8 +215,9 @@ struct perf_event_attr {
215 */ 215 */
216 precise_ip : 2, /* skid constraint */ 216 precise_ip : 2, /* skid constraint */
217 mmap_data : 1, /* non-exec mmap data */ 217 mmap_data : 1, /* non-exec mmap data */
218 sample_id_all : 1, /* sample_type all events */
218 219
219 __reserved_1 : 46; 220 __reserved_1 : 45;
220 221
221 union { 222 union {
222 __u32 wakeup_events; /* wakeup every n events */ 223 __u32 wakeup_events; /* wakeup every n events */
@@ -327,6 +328,15 @@ struct perf_event_header {
327enum perf_event_type { 328enum perf_event_type {
328 329
329 /* 330 /*
331 * If perf_event_attr.sample_id_all is set then all event types will
332 * have the sample_type selected fields related to where/when
333 * (identity) an event took place (TID, TIME, ID, CPU, STREAM_ID)
334 * described in PERF_RECORD_SAMPLE below, it will be stashed just after
335 * the perf_event_header and the fields already present for the existing
336 * fields, i.e. at the end of the payload. That way a newer perf.data
337 * file will be supported by older perf tools, with these new optional
338 * fields being ignored.
339 *
330 * The MMAP events record the PROT_EXEC mappings so that we can 340 * The MMAP events record the PROT_EXEC mappings so that we can
331 * correlate userspace IPs to code. They have the following structure: 341 * correlate userspace IPs to code. They have the following structure:
332 * 342 *
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index a04799769566..77ad22c00b9d 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -3388,9 +3388,9 @@ __always_inline void perf_output_copy(struct perf_output_handle *handle,
3388 } while (len); 3388 } while (len);
3389} 3389}
3390 3390
3391static void perf_event_header__init_id(struct perf_event_header *header, 3391static void __perf_event_header__init_id(struct perf_event_header *header,
3392 struct perf_sample_data *data, 3392 struct perf_sample_data *data,
3393 struct perf_event *event) 3393 struct perf_event *event)
3394{ 3394{
3395 u64 sample_type = event->attr.sample_type; 3395 u64 sample_type = event->attr.sample_type;
3396 3396
@@ -3418,6 +3418,43 @@ static void perf_event_header__init_id(struct perf_event_header *header,
3418 } 3418 }
3419} 3419}
3420 3420
3421static void perf_event_header__init_id(struct perf_event_header *header,
3422 struct perf_sample_data *data,
3423 struct perf_event *event)
3424{
3425 if (event->attr.sample_id_all)
3426 __perf_event_header__init_id(header, data, event);
3427}
3428
3429static void __perf_event__output_id_sample(struct perf_output_handle *handle,
3430 struct perf_sample_data *data)
3431{
3432 u64 sample_type = data->type;
3433
3434 if (sample_type & PERF_SAMPLE_TID)
3435 perf_output_put(handle, data->tid_entry);
3436
3437 if (sample_type & PERF_SAMPLE_TIME)
3438 perf_output_put(handle, data->time);
3439
3440 if (sample_type & PERF_SAMPLE_ID)
3441 perf_output_put(handle, data->id);
3442
3443 if (sample_type & PERF_SAMPLE_STREAM_ID)
3444 perf_output_put(handle, data->stream_id);
3445
3446 if (sample_type & PERF_SAMPLE_CPU)
3447 perf_output_put(handle, data->cpu_entry);
3448}
3449
3450static void perf_event__output_id_sample(struct perf_event *event,
3451 struct perf_output_handle *handle,
3452 struct perf_sample_data *sample)
3453{
3454 if (event->attr.sample_id_all)
3455 __perf_event__output_id_sample(handle, sample);
3456}
3457
3421int perf_output_begin(struct perf_output_handle *handle, 3458int perf_output_begin(struct perf_output_handle *handle,
3422 struct perf_event *event, unsigned int size, 3459 struct perf_event *event, unsigned int size,
3423 int nmi, int sample) 3460 int nmi, int sample)
@@ -3425,6 +3462,7 @@ int perf_output_begin(struct perf_output_handle *handle,
3425 struct perf_buffer *buffer; 3462 struct perf_buffer *buffer;
3426 unsigned long tail, offset, head; 3463 unsigned long tail, offset, head;
3427 int have_lost; 3464 int have_lost;
3465 struct perf_sample_data sample_data;
3428 struct { 3466 struct {
3429 struct perf_event_header header; 3467 struct perf_event_header header;
3430 u64 id; 3468 u64 id;
@@ -3451,8 +3489,12 @@ int perf_output_begin(struct perf_output_handle *handle,
3451 goto out; 3489 goto out;
3452 3490
3453 have_lost = local_read(&buffer->lost); 3491 have_lost = local_read(&buffer->lost);
3454 if (have_lost) 3492 if (have_lost) {
3455 size += sizeof(lost_event); 3493 lost_event.header.size = sizeof(lost_event);
3494 perf_event_header__init_id(&lost_event.header, &sample_data,
3495 event);
3496 size += lost_event.header.size;
3497 }
3456 3498
3457 perf_output_get_handle(handle); 3499 perf_output_get_handle(handle);
3458 3500
@@ -3483,11 +3525,11 @@ int perf_output_begin(struct perf_output_handle *handle,
3483 if (have_lost) { 3525 if (have_lost) {
3484 lost_event.header.type = PERF_RECORD_LOST; 3526 lost_event.header.type = PERF_RECORD_LOST;
3485 lost_event.header.misc = 0; 3527 lost_event.header.misc = 0;
3486 lost_event.header.size = sizeof(lost_event);
3487 lost_event.id = event->id; 3528 lost_event.id = event->id;
3488 lost_event.lost = local_xchg(&buffer->lost, 0); 3529 lost_event.lost = local_xchg(&buffer->lost, 0);
3489 3530
3490 perf_output_put(handle, lost_event); 3531 perf_output_put(handle, lost_event);
3532 perf_event__output_id_sample(event, handle, &sample_data);
3491 } 3533 }
3492 3534
3493 return 0; 3535 return 0;
@@ -3700,7 +3742,7 @@ void perf_prepare_sample(struct perf_event_header *header,
3700 header->misc = 0; 3742 header->misc = 0;
3701 header->misc |= perf_misc_flags(regs); 3743 header->misc |= perf_misc_flags(regs);
3702 3744
3703 perf_event_header__init_id(header, data, event); 3745 __perf_event_header__init_id(header, data, event);
3704 3746
3705 if (sample_type & PERF_SAMPLE_IP) 3747 if (sample_type & PERF_SAMPLE_IP)
3706 data->ip = perf_instruction_pointer(regs); 3748 data->ip = perf_instruction_pointer(regs);
@@ -3768,6 +3810,7 @@ perf_event_read_event(struct perf_event *event,
3768 struct task_struct *task) 3810 struct task_struct *task)
3769{ 3811{
3770 struct perf_output_handle handle; 3812 struct perf_output_handle handle;
3813 struct perf_sample_data sample;
3771 struct perf_read_event read_event = { 3814 struct perf_read_event read_event = {
3772 .header = { 3815 .header = {
3773 .type = PERF_RECORD_READ, 3816 .type = PERF_RECORD_READ,
@@ -3779,12 +3822,14 @@ perf_event_read_event(struct perf_event *event,
3779 }; 3822 };
3780 int ret; 3823 int ret;
3781 3824
3825 perf_event_header__init_id(&read_event.header, &sample, event);
3782 ret = perf_output_begin(&handle, event, read_event.header.size, 0, 0); 3826 ret = perf_output_begin(&handle, event, read_event.header.size, 0, 0);
3783 if (ret) 3827 if (ret)
3784 return; 3828 return;
3785 3829
3786 perf_output_put(&handle, read_event); 3830 perf_output_put(&handle, read_event);
3787 perf_output_read(&handle, event); 3831 perf_output_read(&handle, event);
3832 perf_event__output_id_sample(event, &handle, &sample);
3788 3833
3789 perf_output_end(&handle); 3834 perf_output_end(&handle);
3790} 3835}
@@ -3814,14 +3859,16 @@ static void perf_event_task_output(struct perf_event *event,
3814 struct perf_task_event *task_event) 3859 struct perf_task_event *task_event)
3815{ 3860{
3816 struct perf_output_handle handle; 3861 struct perf_output_handle handle;
3862 struct perf_sample_data sample;
3817 struct task_struct *task = task_event->task; 3863 struct task_struct *task = task_event->task;
3818 int size, ret; 3864 int ret, size = task_event->event_id.header.size;
3819 3865
3820 size = task_event->event_id.header.size; 3866 perf_event_header__init_id(&task_event->event_id.header, &sample, event);
3821 ret = perf_output_begin(&handle, event, size, 0, 0);
3822 3867
3868 ret = perf_output_begin(&handle, event,
3869 task_event->event_id.header.size, 0, 0);
3823 if (ret) 3870 if (ret)
3824 return; 3871 goto out;
3825 3872
3826 task_event->event_id.pid = perf_event_pid(event, task); 3873 task_event->event_id.pid = perf_event_pid(event, task);
3827 task_event->event_id.ppid = perf_event_pid(event, current); 3874 task_event->event_id.ppid = perf_event_pid(event, current);
@@ -3831,7 +3878,11 @@ static void perf_event_task_output(struct perf_event *event,
3831 3878
3832 perf_output_put(&handle, task_event->event_id); 3879 perf_output_put(&handle, task_event->event_id);
3833 3880
3881 perf_event__output_id_sample(event, &handle, &sample);
3882
3834 perf_output_end(&handle); 3883 perf_output_end(&handle);
3884out:
3885 task_event->event_id.header.size = size;
3835} 3886}
3836 3887
3837static int perf_event_task_match(struct perf_event *event) 3888static int perf_event_task_match(struct perf_event *event)
@@ -3944,11 +3995,16 @@ static void perf_event_comm_output(struct perf_event *event,
3944 struct perf_comm_event *comm_event) 3995 struct perf_comm_event *comm_event)
3945{ 3996{
3946 struct perf_output_handle handle; 3997 struct perf_output_handle handle;
3998 struct perf_sample_data sample;
3947 int size = comm_event->event_id.header.size; 3999 int size = comm_event->event_id.header.size;
3948 int ret = perf_output_begin(&handle, event, size, 0, 0); 4000 int ret;
4001
4002 perf_event_header__init_id(&comm_event->event_id.header, &sample, event);
4003 ret = perf_output_begin(&handle, event,
4004 comm_event->event_id.header.size, 0, 0);
3949 4005
3950 if (ret) 4006 if (ret)
3951 return; 4007 goto out;
3952 4008
3953 comm_event->event_id.pid = perf_event_pid(event, comm_event->task); 4009 comm_event->event_id.pid = perf_event_pid(event, comm_event->task);
3954 comm_event->event_id.tid = perf_event_tid(event, comm_event->task); 4010 comm_event->event_id.tid = perf_event_tid(event, comm_event->task);
@@ -3956,7 +4012,12 @@ static void perf_event_comm_output(struct perf_event *event,
3956 perf_output_put(&handle, comm_event->event_id); 4012 perf_output_put(&handle, comm_event->event_id);
3957 perf_output_copy(&handle, comm_event->comm, 4013 perf_output_copy(&handle, comm_event->comm,
3958 comm_event->comm_size); 4014 comm_event->comm_size);
4015
4016 perf_event__output_id_sample(event, &handle, &sample);
4017
3959 perf_output_end(&handle); 4018 perf_output_end(&handle);
4019out:
4020 comm_event->event_id.header.size = size;
3960} 4021}
3961 4022
3962static int perf_event_comm_match(struct perf_event *event) 4023static int perf_event_comm_match(struct perf_event *event)
@@ -4001,7 +4062,6 @@ static void perf_event_comm_event(struct perf_comm_event *comm_event)
4001 comm_event->comm_size = size; 4062 comm_event->comm_size = size;
4002 4063
4003 comm_event->event_id.header.size = sizeof(comm_event->event_id) + size; 4064 comm_event->event_id.header.size = sizeof(comm_event->event_id) + size;
4004
4005 rcu_read_lock(); 4065 rcu_read_lock();
4006 list_for_each_entry_rcu(pmu, &pmus, entry) { 4066 list_for_each_entry_rcu(pmu, &pmus, entry) {
4007 cpuctx = get_cpu_ptr(pmu->pmu_cpu_context); 4067 cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
@@ -4080,11 +4140,15 @@ static void perf_event_mmap_output(struct perf_event *event,
4080 struct perf_mmap_event *mmap_event) 4140 struct perf_mmap_event *mmap_event)
4081{ 4141{
4082 struct perf_output_handle handle; 4142 struct perf_output_handle handle;
4143 struct perf_sample_data sample;
4083 int size = mmap_event->event_id.header.size; 4144 int size = mmap_event->event_id.header.size;
4084 int ret = perf_output_begin(&handle, event, size, 0, 0); 4145 int ret;
4085 4146
4147 perf_event_header__init_id(&mmap_event->event_id.header, &sample, event);
4148 ret = perf_output_begin(&handle, event,
4149 mmap_event->event_id.header.size, 0, 0);
4086 if (ret) 4150 if (ret)
4087 return; 4151 goto out;
4088 4152
4089 mmap_event->event_id.pid = perf_event_pid(event, current); 4153 mmap_event->event_id.pid = perf_event_pid(event, current);
4090 mmap_event->event_id.tid = perf_event_tid(event, current); 4154 mmap_event->event_id.tid = perf_event_tid(event, current);
@@ -4092,7 +4156,12 @@ static void perf_event_mmap_output(struct perf_event *event,
4092 perf_output_put(&handle, mmap_event->event_id); 4156 perf_output_put(&handle, mmap_event->event_id);
4093 perf_output_copy(&handle, mmap_event->file_name, 4157 perf_output_copy(&handle, mmap_event->file_name,
4094 mmap_event->file_size); 4158 mmap_event->file_size);
4159
4160 perf_event__output_id_sample(event, &handle, &sample);
4161
4095 perf_output_end(&handle); 4162 perf_output_end(&handle);
4163out:
4164 mmap_event->event_id.header.size = size;
4096} 4165}
4097 4166
4098static int perf_event_mmap_match(struct perf_event *event, 4167static int perf_event_mmap_match(struct perf_event *event,
@@ -4245,6 +4314,7 @@ void perf_event_mmap(struct vm_area_struct *vma)
4245static void perf_log_throttle(struct perf_event *event, int enable) 4314static void perf_log_throttle(struct perf_event *event, int enable)
4246{ 4315{
4247 struct perf_output_handle handle; 4316 struct perf_output_handle handle;
4317 struct perf_sample_data sample;
4248 int ret; 4318 int ret;
4249 4319
4250 struct { 4320 struct {
@@ -4266,11 +4336,15 @@ static void perf_log_throttle(struct perf_event *event, int enable)
4266 if (enable) 4336 if (enable)
4267 throttle_event.header.type = PERF_RECORD_UNTHROTTLE; 4337 throttle_event.header.type = PERF_RECORD_UNTHROTTLE;
4268 4338
4269 ret = perf_output_begin(&handle, event, sizeof(throttle_event), 1, 0); 4339 perf_event_header__init_id(&throttle_event.header, &sample, event);
4340
4341 ret = perf_output_begin(&handle, event,
4342 throttle_event.header.size, 1, 0);
4270 if (ret) 4343 if (ret)
4271 return; 4344 return;
4272 4345
4273 perf_output_put(&handle, throttle_event); 4346 perf_output_put(&handle, throttle_event);
4347 perf_event__output_id_sample(event, &handle, &sample);
4274 perf_output_end(&handle); 4348 perf_output_end(&handle);
4275} 4349}
4276 4350