Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S941035AbcKWRsD (ORCPT ); Wed, 23 Nov 2016 12:48:03 -0500 Received: from mga14.intel.com ([192.55.52.115]:15925 "EHLO mga14.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933957AbcKWRo6 (ORCPT ); Wed, 23 Nov 2016 12:44:58 -0500 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.31,539,1473145200"; d="scan'208";a="1072652933" From: kan.liang@intel.com To: peterz@infradead.org, mingo@redhat.com, acme@kernel.org, linux-kernel@vger.kernel.org Cc: alexander.shishkin@linux.intel.com, tglx@linutronix.de, namhyung@kernel.org, jolsa@kernel.org, adrian.hunter@intel.com, wangnan0@huawei.com, mark.rutland@arm.com, andi@firstfloor.org, Kan Liang Subject: [PATCH 01/14] perf/x86: Introduce PERF_RECORD_OVERHEAD Date: Wed, 23 Nov 2016 04:44:39 -0500 Message-Id: <1479894292-16277-2-git-send-email-kan.liang@intel.com> X-Mailer: git-send-email 2.5.5 In-Reply-To: <1479894292-16277-1-git-send-email-kan.liang@intel.com> References: <1479894292-16277-1-git-send-email-kan.liang@intel.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3597 Lines: 132 From: Kan Liang A new perf record is introduced to export perf overhead information to userspace. So we can measure the overhead of sampling directly. To output the overhead information, it takes advantage of the existing event log mechanism. But the overhead information is the system overhead, not per-event overhead. Signed-off-by: Kan Liang --- include/linux/perf_event.h | 4 ++++ include/uapi/linux/perf_event.h | 29 +++++++++++++++++++++++++++ kernel/events/core.c | 43 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+) diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 4741ecd..3a530a7 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -998,6 +998,10 @@ perf_event__output_id_sample(struct perf_event *event, extern void perf_log_lost_samples(struct perf_event *event, u64 lost); +extern void +perf_log_overhead(struct perf_event *event, u32 type, + struct perf_overhead_entry *entry); + static inline bool is_sampling_event(struct perf_event *event) { return event->attr.sample_period != 0; diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h index c66a485..ae571be 100644 --- a/include/uapi/linux/perf_event.h +++ b/include/uapi/linux/perf_event.h @@ -862,6 +862,17 @@ enum perf_event_type { */ PERF_RECORD_SWITCH_CPU_WIDE = 15, + /* + * Records perf overhead + * struct { + * struct perf_event_header header; + * u32 type; + * struct perf_overhead_entry entry; + * struct sample_id sample_id; + * }; + */ + PERF_RECORD_OVERHEAD = 16, + PERF_RECORD_MAX, /* non-ABI */ }; @@ -980,4 +991,22 @@ struct perf_branch_entry { reserved:44; }; +enum perf_record_overhead_type { + PERF_OVERHEAD_MAX, +}; + +/* + * single overhead record layout: + * + * cpu: The cpu which overhead occues + * nr: Times of overhead happens. + * E.g. for NMI, nr == times of NMI handler are called. + * time: Total overhead cost(ns) + */ +struct perf_overhead_entry { + __u32 cpu; + __u64 nr; + __u64 time; +}; + #endif /* _UAPI_LINUX_PERF_EVENT_H */ diff --git a/kernel/events/core.c b/kernel/events/core.c index ff230bb..590c399 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -7037,6 +7037,49 @@ static void perf_log_itrace_start(struct perf_event *event) perf_output_end(&handle); } + +/* + * Record overhead logging + * + * The overhead logged here is the system overhead, not per-event overhead. + * This function only take advantage of the existing event log mechanism + * to log the overhead record. + * + */ +void perf_log_overhead(struct perf_event *event, u32 type, + struct perf_overhead_entry *entry) +{ + struct perf_output_handle handle; + struct perf_sample_data sample; + int ret; + + struct { + struct perf_event_header header; + u32 type; + struct perf_overhead_entry overhead; + } overhead_event = { + .header = { + .type = PERF_RECORD_OVERHEAD, + .misc = 0, + .size = sizeof(overhead_event), + }, + }; + overhead_event.type = type; + memcpy(&overhead_event.overhead, entry, sizeof(overhead_event.overhead)); + + perf_event_header__init_id(&overhead_event.header, &sample, event); + ret = perf_output_begin(&handle, event, overhead_event.header.size); + + if (ret) + return; + + perf_output_put(&handle, overhead_event); + perf_event__output_id_sample(event, &handle, &sample); + + perf_output_end(&handle); + memset(entry, 0, sizeof(*entry)); +} + /* * Generic event overflow handling, sampling. */ -- 2.5.5