From: Adrian Hunter <adrian.hunter@intel.com>
To: Peter Zijlstra <peterz@infradead.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>,
Arnaldo Carvalho de Melo <acme@kernel.org>,
Jiri Olsa <jolsa@redhat.com>,
linux-kernel@vger.kernel.org,
Thomas Gleixner <tglx@linutronix.de>,
Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
Dave Hansen <dave.hansen@linux.intel.com>,
x86@kernel.org, kvm@vger.kernel.org,
H Peter Anvin <hpa@zytor.com>,
Mathieu Poirier <mathieu.poirier@linaro.org>,
Suzuki K Poulose <suzuki.poulose@arm.com>,
Leo Yan <leo.yan@linaro.org>
Subject: [PATCH V3 03/10] perf/x86: Add support for TSC in nanoseconds as a perf event clock
Date: Mon, 7 Mar 2022 10:53:05 +0200 [thread overview]
Message-ID: <20220307085312.1814506-4-adrian.hunter@intel.com> (raw)
In-Reply-To: <20220307085312.1814506-1-adrian.hunter@intel.com>
Currently, when Intel PT is used within a VM guest, it is not possible to
make use of TSC because perf clock is subject to paravirtualization.
If the hypervisor leaves rdtsc alone, the TSC value will be subject only to
the VMCS TSC Offset and Scaling, the same as the TSC packet from Intel PT.
The new clock is based on rdtsc and not subject to paravirtualization.
Hence it would be possible to use this new clock for Intel PT decoding
within a VM guest.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
arch/x86/events/core.c | 39 ++++++++++++++++++++-----------
arch/x86/include/asm/perf_event.h | 2 ++
include/uapi/linux/time.h | 6 +++++
kernel/events/core.c | 6 +++++
4 files changed, 40 insertions(+), 13 deletions(-)
diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
index e2ad3f9cca93..bd3781fe5faa 100644
--- a/arch/x86/events/core.c
+++ b/arch/x86/events/core.c
@@ -41,6 +41,7 @@
#include <asm/desc.h>
#include <asm/ldt.h>
#include <asm/unwind.h>
+#include <asm/tsc.h>
#include "perf_event.h"
@@ -2728,16 +2729,26 @@ void arch_perf_update_userpage(struct perf_event *event,
!!(event->hw.flags & PERF_EVENT_FLAG_USER_READ_CNT);
userpg->pmc_width = x86_pmu.cntval_bits;
- if (event->attr.use_clockid && event->attr.clockid == CLOCK_PERF_HW_CLOCK) {
- userpg->cap_user_time_zero = 1;
- userpg->time_mult = 1;
- userpg->time_shift = 0;
- userpg->time_offset = 0;
- userpg->time_zero = 0;
- return;
+ if (event->attr.use_clockid) {
+ if (event->attr.clockid == CLOCK_PERF_HW_CLOCK) {
+ userpg->cap_user_time_zero = 1;
+ userpg->time_mult = 1;
+ userpg->time_shift = 0;
+ userpg->time_offset = 0;
+ userpg->time_zero = 0;
+ return;
+ }
+ if (event->attr.clockid == CLOCK_PERF_HW_CLOCK_NS)
+ userpg->cap_user_time_zero = 1;
+ }
+
+ if (using_native_sched_clock() && sched_clock_stable()) {
+ userpg->cap_user_time = 1;
+ if (!event->attr.use_clockid)
+ userpg->cap_user_time_zero = 1;
}
- if (!using_native_sched_clock() || !sched_clock_stable())
+ if (!userpg->cap_user_time && !userpg->cap_user_time_zero)
return;
cyc2ns_read_begin(&data);
@@ -2748,19 +2759,16 @@ void arch_perf_update_userpage(struct perf_event *event,
* Internal timekeeping for enabled/running/stopped times
* is always in the local_clock domain.
*/
- userpg->cap_user_time = 1;
userpg->time_mult = data.cyc2ns_mul;
userpg->time_shift = data.cyc2ns_shift;
userpg->time_offset = offset - now;
/*
* cap_user_time_zero doesn't make sense when we're using a different
- * time base for the records.
+ * time base for the records, except for CLOCK_PERF_HW_CLOCK_NS.
*/
- if (!event->attr.use_clockid) {
- userpg->cap_user_time_zero = 1;
+ if (userpg->cap_user_time_zero)
userpg->time_zero = offset;
- }
cyc2ns_read_end();
}
@@ -2994,6 +3002,11 @@ u64 perf_hw_clock(void)
return rdtsc_ordered();
}
+u64 perf_hw_clock_ns(void)
+{
+ return native_sched_clock_from_tsc(perf_hw_clock());
+}
+
void perf_get_x86_pmu_capability(struct x86_pmu_capability *cap)
{
cap->version = x86_pmu.version;
diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h
index 3c75459bdeaf..b429b473401e 100644
--- a/arch/x86/include/asm/perf_event.h
+++ b/arch/x86/include/asm/perf_event.h
@@ -453,6 +453,8 @@ extern unsigned long perf_misc_flags(struct pt_regs *regs);
extern u64 perf_hw_clock(void);
#define perf_hw_clock perf_hw_clock
+extern u64 perf_hw_clock_ns(void);
+#define perf_hw_clock_ns perf_hw_clock_ns
#include <asm/stacktrace.h>
diff --git a/include/uapi/linux/time.h b/include/uapi/linux/time.h
index 95602420122e..d527c42719f7 100644
--- a/include/uapi/linux/time.h
+++ b/include/uapi/linux/time.h
@@ -77,6 +77,12 @@ struct timezone {
* paravirtualized. Note the warning above can also apply to TSC.
*/
#define CLOCK_PERF_HW_CLOCK 0x10000000
+/*
+ * Same as CLOCK_PERF_HW_CLOCK but in nanoseconds. Note support of
+ * CLOCK_PERF_HW_CLOCK_NS does not necesssarily imply support of
+ * CLOCK_PERF_HW_CLOCK or vice versa.
+ */
+#define CLOCK_PERF_HW_CLOCK_NS 0x10000001
/*
* The various flags for setting POSIX.1b interval timers:
diff --git a/kernel/events/core.c b/kernel/events/core.c
index e2f06384de50..284a44b385cf 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -12040,6 +12040,12 @@ static int perf_event_set_clock(struct perf_event *event, clockid_t clk_id)
nmi_safe = true;
break;
#endif
+#ifdef perf_hw_clock_ns
+ case CLOCK_PERF_HW_CLOCK_NS:
+ event->clock = &perf_hw_clock_ns;
+ nmi_safe = true;
+ break;
+#endif
default:
return -EINVAL;
--
2.25.1
next prev parent reply other threads:[~2022-03-07 8:53 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-03-07 8:53 [PATCH V3 00/10] perf intel-pt: Add perf event clocks to better support VM tracing Adrian Hunter
2022-03-07 8:53 ` [PATCH V3 01/10] perf/x86: Fix native_perf_sched_clock_from_tsc() with __sched_clock_offset Adrian Hunter
2022-03-07 8:53 ` [PATCH V3 02/10] perf/x86: Add support for TSC as a perf event clock Adrian Hunter
2022-03-07 8:53 ` Adrian Hunter [this message]
2022-03-07 8:53 ` [PATCH V3 04/10] perf tools: Add new perf clock IDs Adrian Hunter
2022-03-07 8:53 ` [PATCH V3 05/10] perf tools: Add API probes for new " Adrian Hunter
2022-03-07 8:53 ` [PATCH V3 06/10] perf tools: Add new clock IDs to "perf time to TSC" test Adrian Hunter
2022-03-07 8:53 ` [PATCH V3 07/10] perf tools: Add perf_read_tsc_conv_for_clockid() Adrian Hunter
2022-03-07 8:53 ` [PATCH V3 08/10] perf intel-pt: Add support for new clock IDs Adrian Hunter
2022-03-07 8:53 ` [PATCH V3 09/10] perf intel-pt: Add config variables for timing parameters Adrian Hunter
2022-03-07 8:53 ` [PATCH V3 10/10] perf intel-pt: Add documentation for new clock IDs Adrian Hunter
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220307085312.1814506-4-adrian.hunter@intel.com \
--to=adrian.hunter@intel.com \
--cc=acme@kernel.org \
--cc=alexander.shishkin@linux.intel.com \
--cc=bp@alien8.de \
--cc=dave.hansen@linux.intel.com \
--cc=hpa@zytor.com \
--cc=jolsa@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=leo.yan@linaro.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mathieu.poirier@linaro.org \
--cc=mingo@redhat.com \
--cc=peterz@infradead.org \
--cc=suzuki.poulose@arm.com \
--cc=tglx@linutronix.de \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox