diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/events/core.c | 60 |
1 files changed, 51 insertions, 9 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c index 1cd5eef1fcdd..3e19d3ebc29c 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c | |||
| @@ -4460,7 +4460,7 @@ perf_output_sample_regs(struct perf_output_handle *handle, | |||
| 4460 | } | 4460 | } |
| 4461 | } | 4461 | } |
| 4462 | 4462 | ||
| 4463 | static void perf_sample_regs_user(struct perf_regs_user *regs_user, | 4463 | static void perf_sample_regs_user(struct perf_regs *regs_user, |
| 4464 | struct pt_regs *regs) | 4464 | struct pt_regs *regs) |
| 4465 | { | 4465 | { |
| 4466 | if (!user_mode(regs)) { | 4466 | if (!user_mode(regs)) { |
| @@ -4471,11 +4471,22 @@ static void perf_sample_regs_user(struct perf_regs_user *regs_user, | |||
| 4471 | } | 4471 | } |
| 4472 | 4472 | ||
| 4473 | if (regs) { | 4473 | if (regs) { |
| 4474 | regs_user->regs = regs; | ||
| 4475 | regs_user->abi = perf_reg_abi(current); | 4474 | regs_user->abi = perf_reg_abi(current); |
| 4475 | regs_user->regs = regs; | ||
| 4476 | } else { | ||
| 4477 | regs_user->abi = PERF_SAMPLE_REGS_ABI_NONE; | ||
| 4478 | regs_user->regs = NULL; | ||
| 4476 | } | 4479 | } |
| 4477 | } | 4480 | } |
| 4478 | 4481 | ||
| 4482 | static void perf_sample_regs_intr(struct perf_regs *regs_intr, | ||
| 4483 | struct pt_regs *regs) | ||
| 4484 | { | ||
| 4485 | regs_intr->regs = regs; | ||
| 4486 | regs_intr->abi = perf_reg_abi(current); | ||
| 4487 | } | ||
| 4488 | |||
| 4489 | |||
| 4479 | /* | 4490 | /* |
| 4480 | * Get remaining task size from user stack pointer. | 4491 | * Get remaining task size from user stack pointer. |
| 4481 | * | 4492 | * |
| @@ -4857,6 +4868,23 @@ void perf_output_sample(struct perf_output_handle *handle, | |||
| 4857 | if (sample_type & PERF_SAMPLE_TRANSACTION) | 4868 | if (sample_type & PERF_SAMPLE_TRANSACTION) |
| 4858 | perf_output_put(handle, data->txn); | 4869 | perf_output_put(handle, data->txn); |
| 4859 | 4870 | ||
| 4871 | if (sample_type & PERF_SAMPLE_REGS_INTR) { | ||
| 4872 | u64 abi = data->regs_intr.abi; | ||
| 4873 | /* | ||
| 4874 | * If there are no regs to dump, notice it through | ||
| 4875 | * first u64 being zero (PERF_SAMPLE_REGS_ABI_NONE). | ||
| 4876 | */ | ||
| 4877 | perf_output_put(handle, abi); | ||
| 4878 | |||
| 4879 | if (abi) { | ||
| 4880 | u64 mask = event->attr.sample_regs_intr; | ||
| 4881 | |||
| 4882 | perf_output_sample_regs(handle, | ||
| 4883 | data->regs_intr.regs, | ||
| 4884 | mask); | ||
| 4885 | } | ||
| 4886 | } | ||
| 4887 | |||
| 4860 | if (!event->attr.watermark) { | 4888 | if (!event->attr.watermark) { |
| 4861 | int wakeup_events = event->attr.wakeup_events; | 4889 | int wakeup_events = event->attr.wakeup_events; |
| 4862 | 4890 | ||
| @@ -4922,12 +4950,13 @@ void perf_prepare_sample(struct perf_event_header *header, | |||
| 4922 | header->size += size; | 4950 | header->size += size; |
| 4923 | } | 4951 | } |
| 4924 | 4952 | ||
| 4953 | if (sample_type & (PERF_SAMPLE_REGS_USER | PERF_SAMPLE_STACK_USER)) | ||
| 4954 | perf_sample_regs_user(&data->regs_user, regs); | ||
| 4955 | |||
| 4925 | if (sample_type & PERF_SAMPLE_REGS_USER) { | 4956 | if (sample_type & PERF_SAMPLE_REGS_USER) { |
| 4926 | /* regs dump ABI info */ | 4957 | /* regs dump ABI info */ |
| 4927 | int size = sizeof(u64); | 4958 | int size = sizeof(u64); |
| 4928 | 4959 | ||
| 4929 | perf_sample_regs_user(&data->regs_user, regs); | ||
| 4930 | |||
| 4931 | if (data->regs_user.regs) { | 4960 | if (data->regs_user.regs) { |
| 4932 | u64 mask = event->attr.sample_regs_user; | 4961 | u64 mask = event->attr.sample_regs_user; |
| 4933 | size += hweight64(mask) * sizeof(u64); | 4962 | size += hweight64(mask) * sizeof(u64); |
| @@ -4943,15 +4972,11 @@ void perf_prepare_sample(struct perf_event_header *header, | |||
| 4943 | * in case new sample type is added, because we could eat | 4972 | * in case new sample type is added, because we could eat |
| 4944 | * up the rest of the sample size. | 4973 | * up the rest of the sample size. |
| 4945 | */ | 4974 | */ |
| 4946 | struct perf_regs_user *uregs = &data->regs_user; | ||
| 4947 | u16 stack_size = event->attr.sample_stack_user; | 4975 | u16 stack_size = event->attr.sample_stack_user; |
| 4948 | u16 size = sizeof(u64); | 4976 | u16 size = sizeof(u64); |
| 4949 | 4977 | ||
| 4950 | if (!uregs->abi) | ||
| 4951 | perf_sample_regs_user(uregs, regs); | ||
| 4952 | |||
| 4953 | stack_size = perf_sample_ustack_size(stack_size, header->size, | 4978 | stack_size = perf_sample_ustack_size(stack_size, header->size, |
| 4954 | uregs->regs); | 4979 | data->regs_user.regs); |
| 4955 | 4980 | ||
| 4956 | /* | 4981 | /* |
| 4957 | * If there is something to dump, add space for the dump | 4982 | * If there is something to dump, add space for the dump |
| @@ -4964,6 +4989,21 @@ void perf_prepare_sample(struct perf_event_header *header, | |||
| 4964 | data->stack_user_size = stack_size; | 4989 | data->stack_user_size = stack_size; |
| 4965 | header->size += size; | 4990 | header->size += size; |
| 4966 | } | 4991 | } |
| 4992 | |||
| 4993 | if (sample_type & PERF_SAMPLE_REGS_INTR) { | ||
| 4994 | /* regs dump ABI info */ | ||
| 4995 | int size = sizeof(u64); | ||
| 4996 | |||
| 4997 | perf_sample_regs_intr(&data->regs_intr, regs); | ||
| 4998 | |||
| 4999 | if (data->regs_intr.regs) { | ||
| 5000 | u64 mask = event->attr.sample_regs_intr; | ||
| 5001 | |||
| 5002 | size += hweight64(mask) * sizeof(u64); | ||
| 5003 | } | ||
| 5004 | |||
| 5005 | header->size += size; | ||
| 5006 | } | ||
| 4967 | } | 5007 | } |
| 4968 | 5008 | ||
| 4969 | static void perf_event_output(struct perf_event *event, | 5009 | static void perf_event_output(struct perf_event *event, |
| @@ -7151,6 +7191,8 @@ static int perf_copy_attr(struct perf_event_attr __user *uattr, | |||
| 7151 | ret = -EINVAL; | 7191 | ret = -EINVAL; |
| 7152 | } | 7192 | } |
| 7153 | 7193 | ||
| 7194 | if (attr->sample_type & PERF_SAMPLE_REGS_INTR) | ||
| 7195 | ret = perf_reg_validate(attr->sample_regs_intr); | ||
| 7154 | out: | 7196 | out: |
| 7155 | return ret; | 7197 | return ret; |
| 7156 | 7198 | ||
