Messages in this thread Patch in this message | | | From | kan.liang@linux ... | Subject | [PATCH V5 01/14] perf/core: Add PERF_SAMPLE_DATA_PAGE_SIZE | Date | Fri, 8 Feb 2019 09:54:56 -0800 |
| |
From: Kan Liang <kan.liang@linux.intel.com>
Current perf can report both virtual address and physical address, but it doesn't report page size. Users have no idea how large the utilized page is. They cannot promote/demote large pages to optimize memory use.
Add a new sample type for data page size.
Current perf already has a facility to collect data virtual address. A __weak function, aim to retrieve page size via a given virtual address, is introduced in the generic code. Now it always returns 0. All architectures can implement their own functions later separately. The real page size must be returned. The function must be IRQ-safe.
A u64 type is claimed for page_size. Because struct perf_sample_data requires cacheline_aligned.
Signed-off-by: Kan Liang <kan.liang@linux.intel.com> ---
Changes since V4 - Split patch 1 of V4 into two patches. This patch add the core stuff including the weak function
include/linux/perf_event.h | 1 + include/uapi/linux/perf_event.h | 4 +++- kernel/events/core.c | 15 +++++++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 6cb5d48..46908cf 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -938,6 +938,7 @@ struct perf_sample_data { u64 stack_user_size; u64 phys_addr; + u64 data_page_size; } ____cacheline_aligned; /* default value for data source */ diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h index 7198ddd..0e8d222 100644 --- a/include/uapi/linux/perf_event.h +++ b/include/uapi/linux/perf_event.h @@ -141,8 +141,9 @@ enum perf_event_sample_format { PERF_SAMPLE_TRANSACTION = 1U << 17, PERF_SAMPLE_REGS_INTR = 1U << 18, PERF_SAMPLE_PHYS_ADDR = 1U << 19, + PERF_SAMPLE_DATA_PAGE_SIZE = 1U << 20, - PERF_SAMPLE_MAX = 1U << 20, /* non-ABI */ + PERF_SAMPLE_MAX = 1U << 21, /* non-ABI */ __PERF_SAMPLE_CALLCHAIN_EARLY = 1ULL << 63, /* non-ABI; internal use */ }; @@ -863,6 +864,7 @@ enum perf_event_type { * { u64 abi; # enum perf_sample_regs_abi * u64 regs[weight(mask)]; } && PERF_SAMPLE_REGS_INTR * { u64 phys_addr;} && PERF_SAMPLE_PHYS_ADDR + * { u64 data_page_size;} && PERF_SAMPLE_DATA_PAGE_SIZE * }; */ PERF_RECORD_SAMPLE = 9, diff --git a/kernel/events/core.c b/kernel/events/core.c index 5aeb4c7..fe6f601 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -1752,6 +1752,9 @@ static void __perf_event_header_size(struct perf_event *event, u64 sample_type) if (sample_type & PERF_SAMPLE_PHYS_ADDR) size += sizeof(data->phys_addr); + if (sample_type & PERF_SAMPLE_DATA_PAGE_SIZE) + size += sizeof(data->data_page_size); + event->header_size = size; } @@ -6304,6 +6307,9 @@ void perf_output_sample(struct perf_output_handle *handle, if (sample_type & PERF_SAMPLE_PHYS_ADDR) perf_output_put(handle, data->phys_addr); + if (sample_type & PERF_SAMPLE_DATA_PAGE_SIZE) + perf_output_put(handle, data->data_page_size); + if (!event->attr.watermark) { int wakeup_events = event->attr.wakeup_events; @@ -6351,6 +6357,12 @@ static u64 perf_virt_to_phys(u64 virt) return phys_addr; } +/* Return page size of given virtual address. IRQ-safe required. */ +u64 __weak perf_get_page_size(u64 virt) +{ + return 0; +} + static struct perf_callchain_entry __empty_callchain = { .nr = 0, }; struct perf_callchain_entry * @@ -6492,6 +6504,9 @@ void perf_prepare_sample(struct perf_event_header *header, if (sample_type & PERF_SAMPLE_PHYS_ADDR) data->phys_addr = perf_virt_to_phys(data->addr); + + if (sample_type & PERF_SAMPLE_DATA_PAGE_SIZE) + data->data_page_size = perf_get_page_size(data->addr); } static __always_inline int -- 2.7.4
| |