kvm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/5] KVM: x86/pmu: Add support to enable guest PEBS via PT
@ 2021-05-12  8:44 Like Xu
  2021-05-12  8:44 ` [PATCH v3 1/5] KVM: x86/pmu: Add pebs_vmx support for ATOM_TREMONT Like Xu
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Like Xu @ 2021-05-12  8:44 UTC (permalink / raw)
  To: Paolo Bonzini, peterz
  Cc: Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li, Jim Mattson,
	Joerg Roedel, weijiang.yang, eranian, wei.w.wang, kvm, x86,
	linux-kernel, Like Xu

I recently noticed that some developers particularly like the PT feature.
So please help review this version since a new kernel cycle has begun .

Intel new hardware (Atom processors based on the Tremont microarchitecture)
introduces some Processor Event-Based Sampling (PEBS) extensions that output
the PEBS record to Intel PT stream instead of DS area. The PEBS record will
be packaged in a specific format when outputting to Intel PT buffer.

To use PEBS-via-PT, the guest driver will firstly check the basic support
for PEBS-via-DS, so this patch set is based on the PEBS-via-DS enabling
patch set [1].

We can use PEBS-via-PT feature on the Linux guest like native:
(you may need modprobe kvm-intel.ko with pt_mode=1)

Recording is selected by using the aux-output config term e.g.
$ perf record -c 10000 -e '{intel_pt/branch=0/,cycles/aux-output/ppp}' uname
Warning:
Intel Processor Trace: TSC not available
Linux
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.028 MB perf.data ]

To display PEBS events from the Intel PT trace, use the itrace 'o' option e.g.
$ perf script --itrace=oe
uname   853   113.230292:      10000 cycles/aux-output/ppp:  ffffffff8125dcd9 perf_output_begin+0x29 ([kernel.kallsyms])
uname   853   113.230443:      10000 cycles/aux-output/ppp:  ffffffff8106de86 native_write_msr+0x6 ([kernel.kallsyms])
uname   853   113.230444:      10000 cycles/aux-output/ppp:  ffffffff81bd035b exc_nmi+0x10b ([kernel.kallsyms])
uname   853   113.230567:      10000 cycles/aux-output/ppp:  ffffffff8106de86 native_write_msr+0x6 ([kernel.kallsyms])
uname   853   113.230567:      10000 cycles/aux-output/ppp:  ffffffff8125dce0 perf_output_begin+0x30 ([kernel.kallsyms])
uname   853   113.230688:      10000 cycles/aux-output/ppp:  ffffffff8106de86 native_write_msr+0x6 ([kernel.kallsyms])
uname   853   113.230689:      10000 cycles/aux-output/ppp:  ffffffff81005da7 perf_event_nmi_handler+0x7 ([kernel.kallsyms])
uname   853   113.230816:      10000 cycles/aux-output/ppp:  ffffffff8106de86 native_write_msr+0x6 ([kernel.kallsyms])

Please check more details in each commit and feel free to comment.

V2 -> V3 Changelog:
- Add x86_pmu.pebs_vmx to ATOM_TREMONT and support PDIR counter;
- Rewrite get_gp_pmc() and get_fixed_pmc() based on PERF_CAP_PEBS_OUTPUT_PT;
- Check and add counter reload registers in the intel_guest_get_msrs();
- Expose this capability in the vmx_get_perf_capabilities();
 
Previous:
https://lore.kernel.org/kvm/1584628430-23220-1-git-send-email-luwei.kang@intel.com/
[1] https://lore.kernel.org/kvm/20210511024214.280733-1-like.xu@linux.intel.com/

Like Xu (4):
  KVM: x86/pmu: Add pebs_vmx support for ATOM_TREMONT
  KVM: x86/pmu: Add counter reload MSR emulation for all counters
  KVM: x86/pmu: Add counter reload registers to the MSR-load list
  KVM: x86/pmu: Expose PEBS-via-PT in the KVM supported capabilities

Luwei Kang (1):
  KVM: x86/pmu: Add the base address parameter for get_fixed_pmc()

 arch/x86/events/intel/core.c     | 28 +++++++++++++++++++++++++
 arch/x86/events/perf_event.h     |  5 -----
 arch/x86/include/asm/kvm_host.h  |  1 +
 arch/x86/include/asm/msr-index.h |  6 ++++++
 arch/x86/kvm/pmu.c               |  5 ++---
 arch/x86/kvm/pmu.h               | 11 ++++++++--
 arch/x86/kvm/vmx/capabilities.h  |  5 ++++-
 arch/x86/kvm/vmx/pmu_intel.c     | 35 ++++++++++++++++++++++++++------
 arch/x86/kvm/vmx/vmx.h           |  2 +-
 9 files changed, 80 insertions(+), 18 deletions(-)

-- 
2.31.1


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v3 1/5] KVM: x86/pmu: Add pebs_vmx support for ATOM_TREMONT
  2021-05-12  8:44 [PATCH v3 0/5] KVM: x86/pmu: Add support to enable guest PEBS via PT Like Xu
@ 2021-05-12  8:44 ` Like Xu
  2021-05-12  8:44 ` [PATCH v3 2/5] KVM: x86/pmu: Add the base address parameter for get_fixed_pmc() Like Xu
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Like Xu @ 2021-05-12  8:44 UTC (permalink / raw)
  To: Paolo Bonzini, peterz
  Cc: Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li, Jim Mattson,
	Joerg Roedel, weijiang.yang, eranian, wei.w.wang, kvm, x86,
	linux-kernel, Like Xu, Andi Kleen, Alexander Shishkin

The ATOM_TREMONT platform also supports the EPT-Friendly PEBS capability
and we can also safely enable guest PEBS. Per Intel SDM, the PDIR counter
on non-Ice Lake platforms is always GP counter 1;

Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Andi Kleen <andi.kleen@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Signed-off-by: Like Xu <like.xu@linux.intel.com>
---
 arch/x86/events/intel/core.c | 1 +
 arch/x86/kvm/pmu.c           | 5 ++---
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index e7bbd9aab175..4404987bbc57 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -5826,6 +5826,7 @@ __init int intel_pmu_init(void)
 	case INTEL_FAM6_ATOM_TREMONT_D:
 	case INTEL_FAM6_ATOM_TREMONT:
 	case INTEL_FAM6_ATOM_TREMONT_L:
+		x86_pmu.pebs_vmx = 1;
 		x86_pmu.late_ack = true;
 		memcpy(hw_cache_event_ids, glp_hw_cache_event_ids,
 		       sizeof(hw_cache_event_ids));
diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
index 4798bf991b60..8c700a7930c4 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
@@ -151,9 +151,8 @@ static void pmc_reprogram_counter(struct kvm_pmc *pmc, u32 type,
 		 * the accuracy of the PEBS profiling result, because the "event IP"
 		 * in the PEBS record is calibrated on the guest side.
 		 */
-		attr.precise_ip = 1;
-		if (x86_match_cpu(vmx_icl_pebs_cpu) && pmc->idx == 32)
-			attr.precise_ip = 3;
+		attr.precise_ip = x86_match_cpu(vmx_icl_pebs_cpu) ?
+			((pmc->idx == 32) ? 3 : 1) : ((pmc->idx == 1) ? 3 : 1);
 	}
 
 	event = perf_event_create_kernel_counter(&attr, -1, current,
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v3 2/5] KVM: x86/pmu: Add the base address parameter for get_fixed_pmc()
  2021-05-12  8:44 [PATCH v3 0/5] KVM: x86/pmu: Add support to enable guest PEBS via PT Like Xu
  2021-05-12  8:44 ` [PATCH v3 1/5] KVM: x86/pmu: Add pebs_vmx support for ATOM_TREMONT Like Xu
@ 2021-05-12  8:44 ` Like Xu
  2021-05-12  8:44 ` [PATCH v3 3/5] KVM: x86/pmu: Add counter reload MSR emulation for all counters Like Xu
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Like Xu @ 2021-05-12  8:44 UTC (permalink / raw)
  To: Paolo Bonzini, peterz
  Cc: Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li, Jim Mattson,
	Joerg Roedel, weijiang.yang, eranian, wei.w.wang, kvm, x86,
	linux-kernel, Luwei Kang

From: Luwei Kang <luwei.kang@intel.com>

Introduce a new base MSR address pass-in parameter for get_fixed_pmc()
so that the caller can define its base for fixed counters (such as
MSR_RELOAD_FIXED_CTRx that can be used in the PBES-via-PT feature).

Refactor the code using the current value MSR_CORE_PERF_FIXED_CTR0.

Signed-off-by: Luwei Kang <luwei.kang@intel.com>
---
The checkpatch.pl yell "ERROR: do not use assignment in if condition",
should I fix the orignal coding style ?

 arch/x86/kvm/pmu.h           |  5 ++---
 arch/x86/kvm/vmx/pmu_intel.c | 17 +++++++++++------
 2 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h
index 832cf56e6924..6720881b8370 100644
--- a/arch/x86/kvm/pmu.h
+++ b/arch/x86/kvm/pmu.h
@@ -126,10 +126,9 @@ static inline struct kvm_pmc *get_gp_pmc(struct kvm_pmu *pmu, u32 msr,
 }
 
 /* returns fixed PMC with the specified MSR */
-static inline struct kvm_pmc *get_fixed_pmc(struct kvm_pmu *pmu, u32 msr)
+static inline struct kvm_pmc *get_fixed_pmc(struct kvm_pmu *pmu,
+					    u32 msr, u32 base)
 {
-	int base = MSR_CORE_PERF_FIXED_CTR0;
-
 	if (msr >= base && msr < base + pmu->nr_arch_fixed_counters) {
 		u32 index = array_index_nospec(msr - base,
 					       pmu->nr_arch_fixed_counters);
diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
index a706d3597720..c10cb3008bf1 100644
--- a/arch/x86/kvm/vmx/pmu_intel.c
+++ b/arch/x86/kvm/vmx/pmu_intel.c
@@ -44,7 +44,8 @@ static void reprogram_fixed_counters(struct kvm_pmu *pmu, u64 data)
 		u8 old_ctrl = fixed_ctrl_field(pmu->fixed_ctr_ctrl, i);
 		struct kvm_pmc *pmc;
 
-		pmc = get_fixed_pmc(pmu, MSR_CORE_PERF_FIXED_CTR0 + i);
+		pmc = get_fixed_pmc(pmu, MSR_CORE_PERF_FIXED_CTR0 + i,
+				    MSR_CORE_PERF_FIXED_CTR0);
 
 		if (old_ctrl == new_ctrl)
 			continue;
@@ -114,7 +115,8 @@ static struct kvm_pmc *intel_pmc_idx_to_pmc(struct kvm_pmu *pmu, int pmc_idx)
 	else {
 		u32 idx = pmc_idx - INTEL_PMC_IDX_FIXED;
 
-		return get_fixed_pmc(pmu, idx + MSR_CORE_PERF_FIXED_CTR0);
+		return get_fixed_pmc(pmu, idx + MSR_CORE_PERF_FIXED_CTR0,
+				     MSR_CORE_PERF_FIXED_CTR0);
 	}
 }
 
@@ -222,7 +224,8 @@ static bool intel_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr)
 	default:
 		ret = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0) ||
 			get_gp_pmc(pmu, msr, MSR_P6_EVNTSEL0) ||
-			get_fixed_pmc(pmu, msr) || get_fw_gp_pmc(pmu, msr) ||
+			get_fixed_pmc(pmu, msr, MSR_CORE_PERF_FIXED_CTR0) ||
+			get_fw_gp_pmc(pmu, msr) ||
 			intel_pmu_is_valid_lbr_msr(vcpu, msr);
 		break;
 	}
@@ -235,7 +238,7 @@ static struct kvm_pmc *intel_msr_idx_to_pmc(struct kvm_vcpu *vcpu, u32 msr)
 	struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
 	struct kvm_pmc *pmc;
 
-	pmc = get_fixed_pmc(pmu, msr);
+	pmc = get_fixed_pmc(pmu, msr, MSR_CORE_PERF_FIXED_CTR0);
 	pmc = pmc ? pmc : get_gp_pmc(pmu, msr, MSR_P6_EVNTSEL0);
 	pmc = pmc ? pmc : get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0);
 
@@ -382,7 +385,8 @@ static int intel_pmu_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 			msr_info->data =
 				val & pmu->counter_bitmask[KVM_PMC_GP];
 			return 0;
-		} else if ((pmc = get_fixed_pmc(pmu, msr))) {
+		} else if ((pmc = get_fixed_pmc(pmu, msr,
+						MSR_CORE_PERF_FIXED_CTR0))) {
 			u64 val = pmc_read_counter(pmc);
 			msr_info->data =
 				val & pmu->counter_bitmask[KVM_PMC_FIXED];
@@ -470,7 +474,8 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 				perf_event_period(pmc->perf_event,
 						  get_sample_period(pmc, data));
 			return 0;
-		} else if ((pmc = get_fixed_pmc(pmu, msr))) {
+		} else if ((pmc = get_fixed_pmc(pmu, msr,
+						MSR_CORE_PERF_FIXED_CTR0))) {
 			pmc->counter += data - pmc_read_counter(pmc);
 			if (pmc->perf_event)
 				perf_event_period(pmc->perf_event,
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v3 3/5] KVM: x86/pmu: Add counter reload MSR emulation for all counters
  2021-05-12  8:44 [PATCH v3 0/5] KVM: x86/pmu: Add support to enable guest PEBS via PT Like Xu
  2021-05-12  8:44 ` [PATCH v3 1/5] KVM: x86/pmu: Add pebs_vmx support for ATOM_TREMONT Like Xu
  2021-05-12  8:44 ` [PATCH v3 2/5] KVM: x86/pmu: Add the base address parameter for get_fixed_pmc() Like Xu
@ 2021-05-12  8:44 ` Like Xu
  2021-05-12  8:44 ` [PATCH v3 4/5] KVM: x86/pmu: Add counter reload registers to the MSR-load list Like Xu
  2021-05-12  8:44 ` [PATCH v3 5/5] KVM: x86/pmu: Expose PEBS-via-PT in the KVM supported capabilities Like Xu
  4 siblings, 0 replies; 6+ messages in thread
From: Like Xu @ 2021-05-12  8:44 UTC (permalink / raw)
  To: Paolo Bonzini, peterz
  Cc: Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li, Jim Mattson,
	Joerg Roedel, weijiang.yang, eranian, wei.w.wang, kvm, x86,
	linux-kernel, Like Xu, Luwei Kang

The Intel PEBS-via-PT feature introduces a new output mechanism that
directs PEBS records to the PT buffer, and after each PEBS record is
generated, it automatically reloads the counter values from a new set
of "reload values" MSRs (based on  MSR_RELOAD_FIXED_CTRx and
MSR_RELOAD_PMCx), instead of the counter reload values stored in
the DS management area.

If perf_capabilities supports this capability, PEBS records will be
directed to the PT buffer when the relevant bit in pebs_enable is set.

Co-developed-by: Luwei Kang <luwei.kang@intel.com>
Signed-off-by: Luwei Kang <luwei.kang@intel.com>
Signed-off-by: Like Xu <like.xu@linux.intel.com>
---
 arch/x86/events/perf_event.h     |  5 -----
 arch/x86/include/asm/kvm_host.h  |  1 +
 arch/x86/include/asm/msr-index.h |  6 ++++++
 arch/x86/kvm/pmu.h               |  8 ++++++++
 arch/x86/kvm/vmx/pmu_intel.c     | 18 ++++++++++++++++++
 5 files changed, 33 insertions(+), 5 deletions(-)

diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h
index 685a1a4e9438..4171f1328732 100644
--- a/arch/x86/events/perf_event.h
+++ b/arch/x86/events/perf_event.h
@@ -115,11 +115,6 @@ struct amd_nb {
 };
 
 #define PEBS_COUNTER_MASK	((1ULL << MAX_PEBS_EVENTS) - 1)
-#define PEBS_PMI_AFTER_EACH_RECORD BIT_ULL(60)
-#define PEBS_OUTPUT_OFFSET	61
-#define PEBS_OUTPUT_MASK	(3ull << PEBS_OUTPUT_OFFSET)
-#define PEBS_OUTPUT_PT		(1ull << PEBS_OUTPUT_OFFSET)
-#define PEBS_VIA_PT_MASK	(PEBS_OUTPUT_PT | PEBS_PMI_AFTER_EACH_RECORD)
 
 /*
  * Flags PEBS can handle without an PMI.
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 15bff609fd57..29d2d8027014 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -443,6 +443,7 @@ struct kvm_pmc {
 	u8 idx;
 	u64 counter;
 	u64 eventsel;
+	u64 reload_counter;
 	struct perf_event *perf_event;
 	struct kvm_vcpu *vcpu;
 	/*
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 1ab3f280f3a9..364c40ecd963 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -187,12 +187,18 @@
 #define MSR_IA32_PERF_CAPABILITIES	0x00000345
 #define PERF_CAP_METRICS_IDX		15
 #define PERF_CAP_PT_IDX			16
+#define PEBS_PMI_AFTER_EACH_RECORD	BIT_ULL(60)
+#define PEBS_OUTPUT_OFFSET		61
+#define PEBS_OUTPUT_MASK		(3ull << PEBS_OUTPUT_OFFSET)
+#define PEBS_OUTPUT_PT			(1ull << PEBS_OUTPUT_OFFSET)
+#define PEBS_VIA_PT_MASK		(PEBS_OUTPUT_PT | PEBS_PMI_AFTER_EACH_RECORD)
 
 #define MSR_PEBS_LD_LAT_THRESHOLD	0x000003f6
 #define PERF_CAP_PEBS_TRAP             BIT_ULL(6)
 #define PERF_CAP_ARCH_REG              BIT_ULL(7)
 #define PERF_CAP_PEBS_FORMAT           0xf00
 #define PERF_CAP_PEBS_BASELINE         BIT_ULL(14)
+#define PERF_CAP_PEBS_OUTPUT_PT        BIT_ULL(16)
 #define PERF_CAP_PEBS_MASK	(PERF_CAP_PEBS_TRAP | PERF_CAP_ARCH_REG | \
 				 PERF_CAP_PEBS_FORMAT | PERF_CAP_PEBS_BASELINE)
 
diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h
index 6720881b8370..f9895a7a59bc 100644
--- a/arch/x86/kvm/pmu.h
+++ b/arch/x86/kvm/pmu.h
@@ -115,6 +115,10 @@ static inline bool kvm_valid_perf_global_ctrl(struct kvm_pmu *pmu,
 static inline struct kvm_pmc *get_gp_pmc(struct kvm_pmu *pmu, u32 msr,
 					 u32 base)
 {
+	if ((msr == MSR_RELOAD_PMC0 || msr == MSR_RELOAD_FIXED_CTR0) &&
+	    !(pmu_to_vcpu(pmu)->arch.perf_capabilities & PERF_CAP_PEBS_OUTPUT_PT))
+		return NULL;
+
 	if (msr >= base && msr < base + pmu->nr_arch_gp_counters) {
 		u32 index = array_index_nospec(msr - base,
 					       pmu->nr_arch_gp_counters);
@@ -129,6 +133,10 @@ static inline struct kvm_pmc *get_gp_pmc(struct kvm_pmu *pmu, u32 msr,
 static inline struct kvm_pmc *get_fixed_pmc(struct kvm_pmu *pmu,
 					    u32 msr, u32 base)
 {
+	if ((msr == MSR_RELOAD_PMC0 || msr == MSR_RELOAD_FIXED_CTR0) &&
+	    !(pmu_to_vcpu(pmu)->arch.perf_capabilities & PERF_CAP_PEBS_OUTPUT_PT))
+		return NULL;
+
 	if (msr >= base && msr < base + pmu->nr_arch_fixed_counters) {
 		u32 index = array_index_nospec(msr - base,
 					       pmu->nr_arch_fixed_counters);
diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
index c10cb3008bf1..e5c12c958cdb 100644
--- a/arch/x86/kvm/vmx/pmu_intel.c
+++ b/arch/x86/kvm/vmx/pmu_intel.c
@@ -226,6 +226,8 @@ static bool intel_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr)
 			get_gp_pmc(pmu, msr, MSR_P6_EVNTSEL0) ||
 			get_fixed_pmc(pmu, msr, MSR_CORE_PERF_FIXED_CTR0) ||
 			get_fw_gp_pmc(pmu, msr) ||
+			get_gp_pmc(pmu, msr, MSR_RELOAD_PMC0) ||
+			get_fixed_pmc(pmu, msr, MSR_RELOAD_FIXED_CTR0) ||
 			intel_pmu_is_valid_lbr_msr(vcpu, msr);
 		break;
 	}
@@ -241,6 +243,8 @@ static struct kvm_pmc *intel_msr_idx_to_pmc(struct kvm_vcpu *vcpu, u32 msr)
 	pmc = get_fixed_pmc(pmu, msr, MSR_CORE_PERF_FIXED_CTR0);
 	pmc = pmc ? pmc : get_gp_pmc(pmu, msr, MSR_P6_EVNTSEL0);
 	pmc = pmc ? pmc : get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0);
+	pmc = pmc ? pmc : get_gp_pmc(pmu, msr, MSR_RELOAD_PMC0);
+	pmc = pmc ? pmc : get_fixed_pmc(pmu, msr, MSR_RELOAD_FIXED_CTR0);
 
 	return pmc;
 }
@@ -394,6 +398,10 @@ static int intel_pmu_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 		} else if ((pmc = get_gp_pmc(pmu, msr, MSR_P6_EVNTSEL0))) {
 			msr_info->data = pmc->eventsel;
 			return 0;
+		} else if ((pmc = get_gp_pmc(pmu, msr, MSR_RELOAD_PMC0)) ||
+			   (pmc = get_fixed_pmc(pmu, msr, MSR_RELOAD_FIXED_CTR0))) {
+			msr_info->data = pmc->reload_counter;
+			return 0;
 		} else if (intel_pmu_handle_lbr_msrs_access(vcpu, msr_info, true))
 			return 0;
 	}
@@ -488,6 +496,12 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 				reprogram_gp_counter(pmc, data);
 				return 0;
 			}
+		} else if ((pmc = get_gp_pmc(pmu, msr, MSR_RELOAD_PMC0)) ||
+			   (pmc = get_fixed_pmc(pmu, msr, MSR_RELOAD_FIXED_CTR0))) {
+			if (!(data & ~pmc_bitmask(pmc))) {
+				pmc->reload_counter = data;
+				return 0;
+			}
 		} else if (intel_pmu_handle_lbr_msrs_access(vcpu, msr_info, false))
 			return 0;
 	}
@@ -595,6 +609,8 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
 			pmu->pebs_enable_mask =
 				~((1ull << pmu->nr_arch_gp_counters) - 1);
 		}
+		if (vcpu->arch.perf_capabilities & PERF_CAP_PEBS_OUTPUT_PT)
+			pmu->pebs_enable_mask &= ~PEBS_VIA_PT_MASK;
 	} else {
 		vcpu->arch.ia32_misc_enable_msr |= MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL;
 		vcpu->arch.perf_capabilities &= ~PERF_CAP_PEBS_MASK;
@@ -612,6 +628,7 @@ static void intel_pmu_init(struct kvm_vcpu *vcpu)
 		pmu->gp_counters[i].vcpu = vcpu;
 		pmu->gp_counters[i].idx = i;
 		pmu->gp_counters[i].current_config = 0;
+		pmu->gp_counters[i].reload_counter = 0;
 	}
 
 	for (i = 0; i < INTEL_PMC_MAX_FIXED; i++) {
@@ -619,6 +636,7 @@ static void intel_pmu_init(struct kvm_vcpu *vcpu)
 		pmu->fixed_counters[i].vcpu = vcpu;
 		pmu->fixed_counters[i].idx = i + INTEL_PMC_IDX_FIXED;
 		pmu->fixed_counters[i].current_config = 0;
+		pmu->fixed_counters[i].reload_counter = 0;
 	}
 
 	vcpu->arch.perf_capabilities = vmx_get_perf_capabilities();
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v3 4/5] KVM: x86/pmu: Add counter reload registers to the MSR-load list
  2021-05-12  8:44 [PATCH v3 0/5] KVM: x86/pmu: Add support to enable guest PEBS via PT Like Xu
                   ` (2 preceding siblings ...)
  2021-05-12  8:44 ` [PATCH v3 3/5] KVM: x86/pmu: Add counter reload MSR emulation for all counters Like Xu
@ 2021-05-12  8:44 ` Like Xu
  2021-05-12  8:44 ` [PATCH v3 5/5] KVM: x86/pmu: Expose PEBS-via-PT in the KVM supported capabilities Like Xu
  4 siblings, 0 replies; 6+ messages in thread
From: Like Xu @ 2021-05-12  8:44 UTC (permalink / raw)
  To: Paolo Bonzini, peterz
  Cc: Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li, Jim Mattson,
	Joerg Roedel, weijiang.yang, eranian, wei.w.wang, kvm, x86,
	linux-kernel, Like Xu

The guest counter reload registers need to be loaded to real HW
before VM-entry. Taking into account the existing guest PT
implementation, we add those counter reload registers to MSR-load list
when the corresponding PEBS counters are enabled and the optimization
from clear_atomic_switch_msr() can be reused.

To support that, it needs to expand the value of NR_LOADSTORE_MSRS
from 8 to 16 because when all counters are enabled, up to 7 or 8
counter reload registers need to be added into the MSR-load list.

Cc: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Like Xu <like.xu@linux.intel.com>
---
 arch/x86/events/intel/core.c | 27 +++++++++++++++++++++++++++
 arch/x86/kvm/vmx/vmx.h       |  2 +-
 2 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index 4404987bbc57..bd6d9e2a64d9 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -3903,6 +3903,8 @@ static struct perf_guest_switch_msr *intel_guest_get_msrs(int *nr, void *data)
 	u64 intel_ctrl = hybrid(cpuc->pmu, intel_ctrl);
 	u64 pebs_mask = (x86_pmu.flags & PMU_FL_PEBS_ALL) ?
 		cpuc->pebs_enabled : (cpuc->pebs_enabled & PEBS_COUNTER_MASK);
+	u64 guest_pebs_enable, base, idx, host_reload_ctr;
+	unsigned long bit;
 
 	*nr = 0;
 	arr[(*nr)++] = (struct perf_guest_switch_msr){
@@ -3964,7 +3966,32 @@ static struct perf_guest_switch_msr *intel_guest_get_msrs(int *nr, void *data)
 		arr[0].guest |= arr[*nr].guest;
 	}
 
+	guest_pebs_enable = arr[*nr].guest;
 	++(*nr);
+
+	if (!x86_pmu.intel_cap.pebs_output_pt_available ||
+	    !(guest_pebs_enable & PEBS_OUTPUT_PT))
+		return arr;
+
+	for_each_set_bit(bit, (unsigned long *)&guest_pebs_enable,
+			 X86_PMC_IDX_MAX) {
+		base = (bit < INTEL_PMC_IDX_FIXED) ?
+			MSR_RELOAD_PMC0 : MSR_RELOAD_FIXED_CTR0;
+		idx = (bit < INTEL_PMC_IDX_FIXED) ?
+			bit : (bit - INTEL_PMC_IDX_FIXED);
+
+		/* It's good when the pebs counters are not cross-mapped. */
+		rdmsrl(base, host_reload_ctr);
+
+		arr[(*nr)++] = (struct perf_guest_switch_msr){
+			.msr = base,
+			.host = host_reload_ctr,
+			.guest = (bit < INTEL_PMC_IDX_FIXED) ?
+				pmu->gp_counters[bit].reload_counter :
+				pmu->fixed_counters[bit].reload_counter,
+		};
+	}
+
 	return arr;
 }
 
diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h
index 3afdcebb0a11..25aa1cc3cc6a 100644
--- a/arch/x86/kvm/vmx/vmx.h
+++ b/arch/x86/kvm/vmx/vmx.h
@@ -28,7 +28,7 @@ extern const u32 vmx_msr_index[];
 #define MAX_NR_USER_RETURN_MSRS	4
 #endif
 
-#define MAX_NR_LOADSTORE_MSRS	8
+#define MAX_NR_LOADSTORE_MSRS	16
 
 struct vmx_msrs {
 	unsigned int		nr;
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v3 5/5] KVM: x86/pmu: Expose PEBS-via-PT in the KVM supported capabilities
  2021-05-12  8:44 [PATCH v3 0/5] KVM: x86/pmu: Add support to enable guest PEBS via PT Like Xu
                   ` (3 preceding siblings ...)
  2021-05-12  8:44 ` [PATCH v3 4/5] KVM: x86/pmu: Add counter reload registers to the MSR-load list Like Xu
@ 2021-05-12  8:44 ` Like Xu
  4 siblings, 0 replies; 6+ messages in thread
From: Like Xu @ 2021-05-12  8:44 UTC (permalink / raw)
  To: Paolo Bonzini, peterz
  Cc: Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li, Jim Mattson,
	Joerg Roedel, weijiang.yang, eranian, wei.w.wang, kvm, x86,
	linux-kernel, Like Xu, Alexander Shishkin, Andi Kleen

The hypervisor userspace can dis/enable it via the MSR-based feature
"MSR_IA32_PERF_CAPABILITIES [bit 16]". If guest also has basic PT support,
it can output the PEBS records to the PT buffer.

Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi.kleen@intel.com>
Signed-off-by: Like Xu <like.xu@linux.intel.com>
---
 arch/x86/kvm/vmx/capabilities.h | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kvm/vmx/capabilities.h b/arch/x86/kvm/vmx/capabilities.h
index fd8c9822db9e..e04b50174dd5 100644
--- a/arch/x86/kvm/vmx/capabilities.h
+++ b/arch/x86/kvm/vmx/capabilities.h
@@ -398,8 +398,11 @@ static inline u64 vmx_get_perf_capabilities(void)
 
 	perf_cap |= host_perf_cap & PMU_CAP_LBR_FMT;
 
-	if (vmx_pebs_supported())
+	if (vmx_pebs_supported()) {
 		perf_cap |= host_perf_cap & PERF_CAP_PEBS_MASK;
+		if (vmx_pt_mode_is_host_guest())
+			perf_cap |= host_perf_cap & PERF_CAP_PEBS_OUTPUT_PT;
+	}
 
 	return perf_cap;
 }
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2021-05-12  8:46 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-12  8:44 [PATCH v3 0/5] KVM: x86/pmu: Add support to enable guest PEBS via PT Like Xu
2021-05-12  8:44 ` [PATCH v3 1/5] KVM: x86/pmu: Add pebs_vmx support for ATOM_TREMONT Like Xu
2021-05-12  8:44 ` [PATCH v3 2/5] KVM: x86/pmu: Add the base address parameter for get_fixed_pmc() Like Xu
2021-05-12  8:44 ` [PATCH v3 3/5] KVM: x86/pmu: Add counter reload MSR emulation for all counters Like Xu
2021-05-12  8:44 ` [PATCH v3 4/5] KVM: x86/pmu: Add counter reload registers to the MSR-load list Like Xu
2021-05-12  8:44 ` [PATCH v3 5/5] KVM: x86/pmu: Expose PEBS-via-PT in the KVM supported capabilities Like Xu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).