diff options
| -rw-r--r-- | include/linux/perf_event.h | 3 | ||||
| -rw-r--r-- | kernel/perf_event.c | 54 |
2 files changed, 29 insertions, 28 deletions
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 7098ebbb3b3a..7bd17f0488f8 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h | |||
| @@ -806,6 +806,9 @@ struct perf_output_handle { | |||
| 806 | unsigned long head; | 806 | unsigned long head; |
| 807 | unsigned long offset; | 807 | unsigned long offset; |
| 808 | unsigned long wakeup; | 808 | unsigned long wakeup; |
| 809 | unsigned long size; | ||
| 810 | void *addr; | ||
| 811 | int page; | ||
| 809 | int nmi; | 812 | int nmi; |
| 810 | int sample; | 813 | int sample; |
| 811 | }; | 814 | }; |
diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 1531e0b409a5..b67549a08626 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c | |||
| @@ -2961,39 +2961,30 @@ again: | |||
| 2961 | void perf_output_copy(struct perf_output_handle *handle, | 2961 | void perf_output_copy(struct perf_output_handle *handle, |
| 2962 | const void *buf, unsigned int len) | 2962 | const void *buf, unsigned int len) |
| 2963 | { | 2963 | { |
| 2964 | unsigned int pages_mask; | 2964 | handle->offset += len; |
| 2965 | unsigned long offset; | ||
| 2966 | unsigned int size; | ||
| 2967 | void **pages; | ||
| 2968 | |||
| 2969 | offset = handle->offset; | ||
| 2970 | pages_mask = handle->data->nr_pages - 1; | ||
| 2971 | pages = handle->data->data_pages; | ||
| 2972 | |||
| 2973 | do { | ||
| 2974 | unsigned long page_offset; | ||
| 2975 | unsigned long page_size; | ||
| 2976 | int nr; | ||
| 2977 | |||
| 2978 | nr = (offset >> PAGE_SHIFT) & pages_mask; | ||
| 2979 | page_size = 1UL << (handle->data->data_order + PAGE_SHIFT); | ||
| 2980 | page_offset = offset & (page_size - 1); | ||
| 2981 | size = min_t(unsigned int, page_size - page_offset, len); | ||
| 2982 | |||
| 2983 | memcpy(pages[nr] + page_offset, buf, size); | ||
| 2984 | |||
| 2985 | len -= size; | ||
| 2986 | buf += size; | ||
| 2987 | offset += size; | ||
| 2988 | } while (len); | ||
| 2989 | |||
| 2990 | handle->offset = offset; | ||
| 2991 | 2965 | ||
| 2992 | /* | 2966 | /* |
| 2993 | * Check we didn't copy past our reservation window, taking the | 2967 | * Check we didn't copy past our reservation window, taking the |
| 2994 | * possible unsigned int wrap into account. | 2968 | * possible unsigned int wrap into account. |
| 2995 | */ | 2969 | */ |
| 2996 | WARN_ON_ONCE(((long)(handle->head - handle->offset)) < 0); | 2970 | if (WARN_ON_ONCE(((long)(handle->head - handle->offset)) < 0)) |
| 2971 | return; | ||
| 2972 | |||
| 2973 | do { | ||
| 2974 | unsigned long size = min(handle->size, len); | ||
| 2975 | |||
| 2976 | memcpy(handle->addr, buf, size); | ||
| 2977 | |||
| 2978 | len -= size; | ||
| 2979 | handle->addr += size; | ||
| 2980 | handle->size -= size; | ||
| 2981 | if (!handle->size) { | ||
| 2982 | handle->page++; | ||
| 2983 | handle->page &= handle->data->nr_pages - 1; | ||
| 2984 | handle->addr = handle->data->data_pages[handle->page]; | ||
| 2985 | handle->size = PAGE_SIZE << handle->data->data_order; | ||
| 2986 | } | ||
| 2987 | } while (len); | ||
| 2997 | } | 2988 | } |
| 2998 | 2989 | ||
| 2999 | int perf_output_begin(struct perf_output_handle *handle, | 2990 | int perf_output_begin(struct perf_output_handle *handle, |
| @@ -3059,6 +3050,13 @@ int perf_output_begin(struct perf_output_handle *handle, | |||
| 3059 | if (head - local_read(&data->wakeup) > data->watermark) | 3050 | if (head - local_read(&data->wakeup) > data->watermark) |
| 3060 | local_add(data->watermark, &data->wakeup); | 3051 | local_add(data->watermark, &data->wakeup); |
| 3061 | 3052 | ||
| 3053 | handle->page = handle->offset >> (PAGE_SHIFT + data->data_order); | ||
| 3054 | handle->page &= data->nr_pages - 1; | ||
| 3055 | handle->size = handle->offset & ((PAGE_SIZE << data->data_order) - 1); | ||
| 3056 | handle->addr = data->data_pages[handle->page]; | ||
| 3057 | handle->addr += handle->size; | ||
| 3058 | handle->size = (PAGE_SIZE << data->data_order) - handle->size; | ||
| 3059 | |||
| 3062 | if (have_lost) { | 3060 | if (have_lost) { |
| 3063 | lost_event.header.type = PERF_RECORD_LOST; | 3061 | lost_event.header.type = PERF_RECORD_LOST; |
| 3064 | lost_event.header.misc = 0; | 3062 | lost_event.header.misc = 0; |
