All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v10 00/16] Introduce Architectural LBR for vPMU
@ 2022-04-22  7:54 Yang Weijiang
  2022-04-22  7:54 ` [PATCH v10 01/16] KVM: x86: Report XSS as an MSR to be saved if there are supported features Yang Weijiang
                   ` (15 more replies)
  0 siblings, 16 replies; 24+ messages in thread
From: Yang Weijiang @ 2022-04-22  7:54 UTC (permalink / raw)
  To: pbonzini, jmattson, seanjc, like.xu.linux, vkuznets, wei.w.wang,
	kvm, linux-kernel
  Cc: Yang Weijiang

Intel CPU model-specific LBR(Legacy LBR) evolved into Architectural
LBR(Arch LBR[0]), it's the replacement of legacy LBR on new platforms.
The native support patches were merged into 5.9 kernel tree, and this
patch series is to enable Arch LBR in vPMU so that guest can benefit
from the merits of the feature.

The main advantages of Arch LBR are [1]:
- Faster context switching due to XSAVES support and faster reset of
  LBR MSRs via the new DEPTH MSR
- Faster LBR read for a non-PEBS event due to XSAVES support, which
  lowers the overhead of the NMI handler.
- Linux kernel can support the LBR features without knowing the model
  number of the current CPU.

From end user's point of view, the usage of Arch LBR is the same as
the Legacy LBR that has been merged in the mainline.

Note, in this series, we impose one restriction for guest Arch LBR:
Guest can only set the same LBR record depth as host, this is due to
the special behavior of MSR_ARCH_LBR_DEPTH: 1) On write to the MSR,
it'll reset all Arch LBR recording MSRs to 0s. 2) XRSTORS resets all
record MSRs to 0s if the saved depth mismatches MSR_ARCH_LBR_DEPTH.
Enforcing the restriction keeps the KVM enabling patch simple and
straightforward.

[0] https://software.intel.com/sites/default/files/managed/c5/15/architecture-instruction-set-extensions-programming-reference.pdf
[1] https://lore.kernel.org/lkml/1593780569-62993-1-git-send-email-kan.liang@linux.intel.com/

Qemu patch:
https://patchwork.ozlabs.org/project/qemu-devel/cover/20220215195258.29149-1-weijiang.yang@intel.com/

Previous version:
v9: https://lore.kernel.org/all/20220215212544.51666-1-weijiang.yang@intel.com/

Changes in v10:
1. Refactored XSS related patch due to mainline evolvement.
2. Removed unnecessary guest fpu load/put helpers when accessing guest LBR MSRs.
3. Rebase the patch series to 5.18-rc2.


Like Xu (6):
  perf/x86/intel: Fix the comment about guest LBR support on KVM
  perf/x86/lbr: Simplify the exposure check for the LBR_INFO registers
  KVM: vmx/pmu: Emulate MSR_ARCH_LBR_DEPTH for guest Arch LBR
  KVM: vmx/pmu: Emulate MSR_ARCH_LBR_CTL for guest Arch LBR
  KVM: x86: Refine the matching and clearing logic for supported_xss
  KVM: x86: Add XSAVE Support for Architectural LBR

Sean Christopherson (1):
  KVM: x86: Report XSS as an MSR to be saved if there are supported
    features

Yang Weijiang (9):
  KVM: x86: Refresh CPUID on writes to MSR_IA32_XSS
  KVM: x86: Add Arch LBR MSRs to msrs_to_save_all list
  KVM: x86/pmu: Refactor code to support guest Arch LBR
  KVM: x86/vmx: Check Arch LBR config when return perf capabilities
  KVM: nVMX: Add necessary Arch LBR settings for nested VM
  KVM: x86/vmx: Clear Arch LBREn bit before inject #DB to guest
  KVM: x86/vmx: Flip Arch LBREn bit on guest state change
  KVM: x86: Add Arch LBR data MSR access interface
  KVM: x86/cpuid: Advertise Arch LBR feature in CPUID

 arch/x86/events/intel/core.c     |   3 +-
 arch/x86/events/intel/lbr.c      |   6 +-
 arch/x86/include/asm/kvm_host.h  |   3 +
 arch/x86/include/asm/msr-index.h |   1 +
 arch/x86/include/asm/vmx.h       |   4 +
 arch/x86/kvm/cpuid.c             |  49 +++++++++-
 arch/x86/kvm/vmx/capabilities.h  |   8 ++
 arch/x86/kvm/vmx/nested.c        |   7 +-
 arch/x86/kvm/vmx/pmu_intel.c     | 155 ++++++++++++++++++++++++++++---
 arch/x86/kvm/vmx/vmcs12.c        |   1 +
 arch/x86/kvm/vmx/vmcs12.h        |   3 +-
 arch/x86/kvm/vmx/vmx.c           |  65 ++++++++++++-
 arch/x86/kvm/x86.c               |  23 ++++-
 13 files changed, 294 insertions(+), 34 deletions(-)


base-commit: ce522ba9ef7e2d9fb22a39eb3371c0c64e2a433e
-- 
2.27.0


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

* [PATCH v10 01/16] KVM: x86: Report XSS as an MSR to be saved if there are supported features
  2022-04-22  7:54 [PATCH v10 00/16] Introduce Architectural LBR for vPMU Yang Weijiang
@ 2022-04-22  7:54 ` Yang Weijiang
  2022-04-22  7:54 ` [PATCH v10 02/16] KVM: x86: Refresh CPUID on writes to MSR_IA32_XSS Yang Weijiang
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 24+ messages in thread
From: Yang Weijiang @ 2022-04-22  7:54 UTC (permalink / raw)
  To: pbonzini, jmattson, seanjc, like.xu.linux, vkuznets, wei.w.wang,
	kvm, linux-kernel
  Cc: Sean Christopherson, Yang Weijiang

From: Sean Christopherson <sean.j.christopherson@intel.com>

Add MSR_IA32_XSS to the list of MSRs reported to userspace if
supported_xss is non-zero, i.e. KVM supports at least one XSS based
feature.

Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
---
 arch/x86/kvm/x86.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 0c0ca599a353..20d94e7dbbfe 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1428,6 +1428,7 @@ static const u32 msrs_to_save_all[] = {
 	MSR_F15H_PERF_CTR0, MSR_F15H_PERF_CTR1, MSR_F15H_PERF_CTR2,
 	MSR_F15H_PERF_CTR3, MSR_F15H_PERF_CTR4, MSR_F15H_PERF_CTR5,
 	MSR_IA32_XFD, MSR_IA32_XFD_ERR,
+	MSR_IA32_XSS,
 };
 
 static u32 msrs_to_save[ARRAY_SIZE(msrs_to_save_all)];
@@ -6654,6 +6655,10 @@ static void kvm_init_msr_list(void)
 			if (!kvm_cpu_cap_has(X86_FEATURE_XFD))
 				continue;
 			break;
+		case MSR_IA32_XSS:
+			if (!supported_xss)
+				continue;
+			break;
 		default:
 			break;
 		}
-- 
2.27.0


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

* [PATCH v10 02/16] KVM: x86: Refresh CPUID on writes to MSR_IA32_XSS
  2022-04-22  7:54 [PATCH v10 00/16] Introduce Architectural LBR for vPMU Yang Weijiang
  2022-04-22  7:54 ` [PATCH v10 01/16] KVM: x86: Report XSS as an MSR to be saved if there are supported features Yang Weijiang
@ 2022-04-22  7:54 ` Yang Weijiang
  2022-04-22  7:54 ` [PATCH v10 03/16] perf/x86/intel: Fix the comment about guest LBR support on KVM Yang Weijiang
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 24+ messages in thread
From: Yang Weijiang @ 2022-04-22  7:54 UTC (permalink / raw)
  To: pbonzini, jmattson, seanjc, like.xu.linux, vkuznets, wei.w.wang,
	kvm, linux-kernel
  Cc: Yang Weijiang, Zhang Yi Z

Updated CPUID.0xD.0x1, which reports the current required storage size
of all features enabled via XCR0 | XSS, when the guest's XSS is modified.

Note, KVM does not yet support any XSS based features, i.e. supported_xss
is guaranteed to be zero at this time.

Co-developed-by: Zhang Yi Z <yi.z.zhang@linux.intel.com>
Signed-off-by: Zhang Yi Z <yi.z.zhang@linux.intel.com>
Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
---
 arch/x86/kvm/cpuid.c | 16 +++++++++++++---
 arch/x86/kvm/x86.c   |  6 ++++--
 2 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index b24ca7f4ed7c..3f3ec42c27d5 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -239,9 +239,19 @@ static void __kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu, struct kvm_cpuid_e
 		best->ebx = xstate_required_size(vcpu->arch.xcr0, false);
 
 	best = cpuid_entry2_find(entries, nent, 0xD, 1);
-	if (best && (cpuid_entry_has(best, X86_FEATURE_XSAVES) ||
-		     cpuid_entry_has(best, X86_FEATURE_XSAVEC)))
-		best->ebx = xstate_required_size(vcpu->arch.xcr0, true);
+	if (best) {
+		if (cpuid_entry_has(best, X86_FEATURE_XSAVES) ||
+		    cpuid_entry_has(best, X86_FEATURE_XSAVEC))  {
+			u64 xstate = vcpu->arch.xcr0 | vcpu->arch.ia32_xss;
+
+			best->ebx = xstate_required_size(xstate, true);
+		}
+
+		if (!cpuid_entry_has(best, X86_FEATURE_XSAVES)) {
+			best->ecx = 0;
+			best->edx = 0;
+		}
+	}
 
 	best = __kvm_find_kvm_cpuid_features(vcpu, entries, nent);
 	if (kvm_hlt_in_guest(vcpu->kvm) && best &&
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 20d94e7dbbfe..f42f250884f1 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3577,8 +3577,10 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 		 */
 		if (data & ~supported_xss)
 			return 1;
-		vcpu->arch.ia32_xss = data;
-		kvm_update_cpuid_runtime(vcpu);
+		if (vcpu->arch.ia32_xss != data) {
+			vcpu->arch.ia32_xss = data;
+			kvm_update_cpuid_runtime(vcpu);
+		}
 		break;
 	case MSR_SMI_COUNT:
 		if (!msr_info->host_initiated)
-- 
2.27.0


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

* [PATCH v10 03/16] perf/x86/intel: Fix the comment about guest LBR support on KVM
  2022-04-22  7:54 [PATCH v10 00/16] Introduce Architectural LBR for vPMU Yang Weijiang
  2022-04-22  7:54 ` [PATCH v10 01/16] KVM: x86: Report XSS as an MSR to be saved if there are supported features Yang Weijiang
  2022-04-22  7:54 ` [PATCH v10 02/16] KVM: x86: Refresh CPUID on writes to MSR_IA32_XSS Yang Weijiang
@ 2022-04-22  7:54 ` Yang Weijiang
  2022-04-22  7:54 ` [PATCH v10 04/16] perf/x86/lbr: Simplify the exposure check for the LBR_INFO registers Yang Weijiang
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 24+ messages in thread
From: Yang Weijiang @ 2022-04-22  7:54 UTC (permalink / raw)
  To: pbonzini, jmattson, seanjc, like.xu.linux, vkuznets, wei.w.wang,
	kvm, linux-kernel
  Cc: Like Xu, Peter Zijlstra, Kan Liang, Andi Kleen, Yang Weijiang

From: Like Xu <like.xu@linux.intel.com>

Starting from v5.12, KVM reports guest LBR and extra_regs support
when the host has relevant support. Just delete this part of the
comment and fix a typo incidentally.

Cc: Peter Zijlstra <peterz@infradead.org>
Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
Reviewed-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Like Xu <like.xu@linux.intel.com>
Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
---
 arch/x86/events/intel/core.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index fc7f458eb3de..b4a0ae3eea27 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -6396,8 +6396,7 @@ __init int intel_pmu_init(void)
 					  x86_pmu.intel_ctrl);
 	/*
 	 * Access LBR MSR may cause #GP under certain circumstances.
-	 * E.g. KVM doesn't support LBR MSR
-	 * Check all LBT MSR here.
+	 * Check all LBR MSR here.
 	 * Disable LBR access if any LBR MSRs can not be accessed.
 	 */
 	if (x86_pmu.lbr_tos && !check_msr(x86_pmu.lbr_tos, 0x3UL))
-- 
2.27.0


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

* [PATCH v10 04/16] perf/x86/lbr: Simplify the exposure check for the LBR_INFO registers
  2022-04-22  7:54 [PATCH v10 00/16] Introduce Architectural LBR for vPMU Yang Weijiang
                   ` (2 preceding siblings ...)
  2022-04-22  7:54 ` [PATCH v10 03/16] perf/x86/intel: Fix the comment about guest LBR support on KVM Yang Weijiang
@ 2022-04-22  7:54 ` Yang Weijiang
  2022-04-22  7:54 ` [PATCH v10 05/16] KVM: x86: Add Arch LBR MSRs to msrs_to_save_all list Yang Weijiang
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 24+ messages in thread
From: Yang Weijiang @ 2022-04-22  7:54 UTC (permalink / raw)
  To: pbonzini, jmattson, seanjc, like.xu.linux, vkuznets, wei.w.wang,
	kvm, linux-kernel
  Cc: Like Xu, Peter Zijlstra, Kan Liang, Andi Kleen, Yang Weijiang

From: Like Xu <like.xu@linux.intel.com>

The x86_pmu.lbr_info is 0 unless explicitly initialized, so there's
no point checking x86_pmu.intel_cap.lbr_format.

Cc: Peter Zijlstra <peterz@infradead.org>
Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
Reviewed-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Like Xu <like.xu@linux.intel.com>
Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
---
 arch/x86/events/intel/lbr.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c
index fe1742c4ca49..4529ce448b2e 100644
--- a/arch/x86/events/intel/lbr.c
+++ b/arch/x86/events/intel/lbr.c
@@ -1874,12 +1874,10 @@ void __init intel_pmu_arch_lbr_init(void)
  */
 int x86_perf_get_lbr(struct x86_pmu_lbr *lbr)
 {
-	int lbr_fmt = x86_pmu.intel_cap.lbr_format;
-
 	lbr->nr = x86_pmu.lbr_nr;
 	lbr->from = x86_pmu.lbr_from;
 	lbr->to = x86_pmu.lbr_to;
-	lbr->info = (lbr_fmt == LBR_FORMAT_INFO) ? x86_pmu.lbr_info : 0;
+	lbr->info = x86_pmu.lbr_info;
 
 	return 0;
 }
-- 
2.27.0


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

* [PATCH v10 05/16] KVM: x86: Add Arch LBR MSRs to msrs_to_save_all list
  2022-04-22  7:54 [PATCH v10 00/16] Introduce Architectural LBR for vPMU Yang Weijiang
                   ` (3 preceding siblings ...)
  2022-04-22  7:54 ` [PATCH v10 04/16] perf/x86/lbr: Simplify the exposure check for the LBR_INFO registers Yang Weijiang
@ 2022-04-22  7:54 ` Yang Weijiang
  2022-04-22  7:54 ` [PATCH v10 06/16] KVM: vmx/pmu: Emulate MSR_ARCH_LBR_DEPTH for guest Arch LBR Yang Weijiang
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 24+ messages in thread
From: Yang Weijiang @ 2022-04-22  7:54 UTC (permalink / raw)
  To: pbonzini, jmattson, seanjc, like.xu.linux, vkuznets, wei.w.wang,
	kvm, linux-kernel
  Cc: Yang Weijiang

Arch LBR MSR_ARCH_LBR_DEPTH and MSR_ARCH_LBR_CTL are queried by
userspace application before it wants to {save|restore} the Arch LBR
data. Other LBR related data MSRs are omitted here intentionally due
to lengthy list(32*3). Userspace can still use KVM_{GET|SET}_MSRS to
access them if necessary.

Suggested-by: Jim Mattson <jmattson@google.com>
Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
Reviewed-by: Jim Mattson <jmattson@google.com>
---
 arch/x86/kvm/x86.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index f42f250884f1..c81014f618ca 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1429,6 +1429,7 @@ static const u32 msrs_to_save_all[] = {
 	MSR_F15H_PERF_CTR3, MSR_F15H_PERF_CTR4, MSR_F15H_PERF_CTR5,
 	MSR_IA32_XFD, MSR_IA32_XFD_ERR,
 	MSR_IA32_XSS,
+	MSR_ARCH_LBR_CTL, MSR_ARCH_LBR_DEPTH,
 };
 
 static u32 msrs_to_save[ARRAY_SIZE(msrs_to_save_all)];
@@ -6661,6 +6662,11 @@ static void kvm_init_msr_list(void)
 			if (!supported_xss)
 				continue;
 			break;
+		case MSR_ARCH_LBR_DEPTH:
+		case MSR_ARCH_LBR_CTL:
+			if (!kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR))
+				continue;
+			break;
 		default:
 			break;
 		}
-- 
2.27.0


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

* [PATCH v10 06/16] KVM: vmx/pmu: Emulate MSR_ARCH_LBR_DEPTH for guest Arch LBR
  2022-04-22  7:54 [PATCH v10 00/16] Introduce Architectural LBR for vPMU Yang Weijiang
                   ` (4 preceding siblings ...)
  2022-04-22  7:54 ` [PATCH v10 05/16] KVM: x86: Add Arch LBR MSRs to msrs_to_save_all list Yang Weijiang
@ 2022-04-22  7:54 ` Yang Weijiang
  2022-04-22  7:55 ` [PATCH v10 07/16] KVM: vmx/pmu: Emulate MSR_ARCH_LBR_CTL " Yang Weijiang
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 24+ messages in thread
From: Yang Weijiang @ 2022-04-22  7:54 UTC (permalink / raw)
  To: pbonzini, jmattson, seanjc, like.xu.linux, vkuznets, wei.w.wang,
	kvm, linux-kernel
  Cc: Like Xu, Yang Weijiang

From: Like Xu <like.xu@linux.intel.com>

The number of Arch LBR entries available is determined by the value
in host MSR_ARCH_LBR_DEPTH.DEPTH. The supported LBR depth values are
enumerated in CPUID.(EAX=01CH, ECX=0):EAX[7:0]. For each bit "n" set
in this field, the MSR_ARCH_LBR_DEPTH.DEPTH value of "8*(n+1)" is
supported. In the first generation of Arch LBR, max entry size is 32,
host configures the max size and guest always honors the setting.

Write to MSR_ARCH_LBR_DEPTH has side-effect, all LBR entries are reset
to 0. Kernel PMU driver can leverage this effect to do fask reset to
LBR record MSRs. KVM allows guest to achieve it when Arch LBR records
MSRs are passed through to the guest.

Signed-off-by: Like Xu <like.xu@linux.intel.com>
Co-developed-by: Yang Weijiang <weijiang.yang@intel.com>
Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
---
 arch/x86/include/asm/kvm_host.h |  3 +++
 arch/x86/kvm/vmx/pmu_intel.c    | 48 ++++++++++++++++++++++++++++++++-
 2 files changed, 50 insertions(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index d23e80a56eb8..d067a382e914 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -534,6 +534,9 @@ struct kvm_pmu {
 	 * redundant check before cleanup if guest don't use vPMU at all.
 	 */
 	u8 event_count;
+
+	/* Guest arch lbr depth supported by KVM. */
+	u64 kvm_arch_lbr_depth;
 };
 
 struct kvm_pmu_ops;
diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
index bc3f8512bb64..c8e6c1e1e00c 100644
--- a/arch/x86/kvm/vmx/pmu_intel.c
+++ b/arch/x86/kvm/vmx/pmu_intel.c
@@ -205,7 +205,7 @@ static bool intel_pmu_is_valid_lbr_msr(struct kvm_vcpu *vcpu, u32 index)
 static bool intel_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr)
 {
 	struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
-	int ret;
+	int ret = 0;
 
 	switch (msr) {
 	case MSR_CORE_PERF_FIXED_CTR_CTRL:
@@ -214,6 +214,10 @@ static bool intel_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr)
 	case MSR_CORE_PERF_GLOBAL_OVF_CTRL:
 		ret = pmu->version > 1;
 		break;
+	case MSR_ARCH_LBR_DEPTH:
+		if (kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR))
+			ret = guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR);
+		break;
 	default:
 		ret = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0) ||
 			get_gp_pmc(pmu, msr, MSR_P6_EVNTSEL0) ||
@@ -342,10 +346,26 @@ static bool intel_pmu_handle_lbr_msrs_access(struct kvm_vcpu *vcpu,
 	return true;
 }
 
+/*
+ * Check if the requested depth value the same as that of host.
+ * When guest/host depth are different, the handling would be tricky,
+ * so now only max depth is supported for both host and guest.
+ */
+static bool arch_lbr_depth_is_valid(struct kvm_vcpu *vcpu, u64 depth)
+{
+	struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
+
+	if (!kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR))
+		return false;
+
+	return (depth == pmu->kvm_arch_lbr_depth);
+}
+
 static int intel_pmu_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 {
 	struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
 	struct kvm_pmc *pmc;
+	struct lbr_desc *lbr_desc = vcpu_to_lbr_desc(vcpu);
 	u32 msr = msr_info->index;
 
 	switch (msr) {
@@ -361,6 +381,9 @@ static int intel_pmu_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 	case MSR_CORE_PERF_GLOBAL_OVF_CTRL:
 		msr_info->data = 0;
 		return 0;
+	case MSR_ARCH_LBR_DEPTH:
+		msr_info->data = lbr_desc->records.nr;
+		return 0;
 	default:
 		if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)) ||
 		    (pmc = get_gp_pmc(pmu, msr, MSR_IA32_PMC0))) {
@@ -387,6 +410,7 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 {
 	struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
 	struct kvm_pmc *pmc;
+	struct lbr_desc *lbr_desc = vcpu_to_lbr_desc(vcpu);
 	u32 msr = msr_info->index;
 	u64 data = msr_info->data;
 	u64 reserved_bits;
@@ -421,6 +445,16 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 			return 0;
 		}
 		break;
+	case MSR_ARCH_LBR_DEPTH:
+		if (!arch_lbr_depth_is_valid(vcpu, data))
+			return 1;
+		lbr_desc->records.nr = data;
+		/*
+		 * Writing depth MSR from guest could either setting the
+		 * MSR or resetting the LBR records with the side-effect.
+		 */
+		wrmsrl(MSR_ARCH_LBR_DEPTH, lbr_desc->records.nr);
+		return 0;
 	default:
 		if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)) ||
 		    (pmc = get_gp_pmc(pmu, msr, MSR_IA32_PMC0))) {
@@ -559,6 +593,18 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
 
 	if (lbr_desc->records.nr)
 		bitmap_set(pmu->all_valid_pmc_idx, INTEL_PMC_IDX_FIXED_VLBR, 1);
+
+	if (!kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR))
+		return;
+
+	entry = kvm_find_cpuid_entry(vcpu, 28, 0);
+	if (entry) {
+		/*
+		 * The depth mask in CPUID is fixed to host supported
+		 * value when userspace sets guest CPUID.
+		 */
+		pmu->kvm_arch_lbr_depth = fls(entry->eax & 0xff) * 8;
+	}
 }
 
 static void intel_pmu_init(struct kvm_vcpu *vcpu)
-- 
2.27.0


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

* [PATCH v10 07/16] KVM: vmx/pmu: Emulate MSR_ARCH_LBR_CTL for guest Arch LBR
  2022-04-22  7:54 [PATCH v10 00/16] Introduce Architectural LBR for vPMU Yang Weijiang
                   ` (5 preceding siblings ...)
  2022-04-22  7:54 ` [PATCH v10 06/16] KVM: vmx/pmu: Emulate MSR_ARCH_LBR_DEPTH for guest Arch LBR Yang Weijiang
@ 2022-04-22  7:55 ` Yang Weijiang
  2022-04-28 14:16   ` Liang, Kan
  2022-04-22  7:55 ` [PATCH v10 08/16] KVM: x86/pmu: Refactor code to support " Yang Weijiang
                   ` (8 subsequent siblings)
  15 siblings, 1 reply; 24+ messages in thread
From: Yang Weijiang @ 2022-04-22  7:55 UTC (permalink / raw)
  To: pbonzini, jmattson, seanjc, like.xu.linux, vkuznets, wei.w.wang,
	kvm, linux-kernel
  Cc: Like Xu, Yang Weijiang

From: Like Xu <like.xu@linux.intel.com>

Arch LBR is enabled by setting MSR_ARCH_LBR_CTL.LBREn to 1. A new guest
state field named "Guest IA32_LBR_CTL" is added to enhance guest LBR usage.
When guest Arch LBR is enabled, a guest LBR event will be created like the
model-specific LBR does. Clear guest LBR enable bit on host PMI handling so
guest can see expected config.

On processors that support Arch LBR, MSR_IA32_DEBUGCTLMSR[bit 0] has no
meaning. It can be written to 0 or 1, but reads will always return 0.
Like IA32_DEBUGCTL, IA32_ARCH_LBR_CTL msr is also preserved on INIT.

Regardless of the Arch LBR or legacy LBR, when the LBR_EN bit 0 of the
corresponding control MSR is set to 1, LBR recording will be enabled.

Signed-off-by: Like Xu <like.xu@linux.intel.com>
Co-developed-by: Yang Weijiang <weijiang.yang@intel.com>
Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
---
 arch/x86/events/intel/lbr.c      |  2 --
 arch/x86/include/asm/msr-index.h |  1 +
 arch/x86/include/asm/vmx.h       |  2 ++
 arch/x86/kvm/vmx/pmu_intel.c     | 58 +++++++++++++++++++++++++++++---
 arch/x86/kvm/vmx/vmx.c           | 12 +++++++
 5 files changed, 68 insertions(+), 7 deletions(-)

diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c
index 4529ce448b2e..4fe6c3b50fc3 100644
--- a/arch/x86/events/intel/lbr.c
+++ b/arch/x86/events/intel/lbr.c
@@ -160,8 +160,6 @@ enum {
 	 ARCH_LBR_RETURN		|\
 	 ARCH_LBR_OTHER_BRANCH)
 
-#define ARCH_LBR_CTL_MASK			0x7f000e
-
 static void intel_pmu_lbr_filter(struct cpu_hw_events *cpuc);
 
 static __always_inline bool is_lbr_call_stack_bit_set(u64 config)
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 0eb90d21049e..60e0ab108dc0 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -169,6 +169,7 @@
 #define LBR_INFO_BR_TYPE		(0xfull << LBR_INFO_BR_TYPE_OFFSET)
 
 #define MSR_ARCH_LBR_CTL		0x000014ce
+#define ARCH_LBR_CTL_MASK		0x7f000e
 #define ARCH_LBR_CTL_LBREN		BIT(0)
 #define ARCH_LBR_CTL_CPL_OFFSET		1
 #define ARCH_LBR_CTL_CPL		(0x3ull << ARCH_LBR_CTL_CPL_OFFSET)
diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h
index 0ffaa3156a4e..ea3be961cc8e 100644
--- a/arch/x86/include/asm/vmx.h
+++ b/arch/x86/include/asm/vmx.h
@@ -245,6 +245,8 @@ enum vmcs_field {
 	GUEST_BNDCFGS_HIGH              = 0x00002813,
 	GUEST_IA32_RTIT_CTL		= 0x00002814,
 	GUEST_IA32_RTIT_CTL_HIGH	= 0x00002815,
+	GUEST_IA32_LBR_CTL		= 0x00002816,
+	GUEST_IA32_LBR_CTL_HIGH		= 0x00002817,
 	HOST_IA32_PAT			= 0x00002c00,
 	HOST_IA32_PAT_HIGH		= 0x00002c01,
 	HOST_IA32_EFER			= 0x00002c02,
diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
index c8e6c1e1e00c..7dc8a5783df7 100644
--- a/arch/x86/kvm/vmx/pmu_intel.c
+++ b/arch/x86/kvm/vmx/pmu_intel.c
@@ -19,6 +19,7 @@
 #include "pmu.h"
 
 #define MSR_PMC_FULL_WIDTH_BIT      (MSR_IA32_PMC0 - MSR_IA32_PERFCTR0)
+#define KVM_ARCH_LBR_CTL_MASK  (ARCH_LBR_CTL_MASK | ARCH_LBR_CTL_LBREN)
 
 static struct kvm_event_hw_type_mapping intel_arch_events[] = {
 	[0] = { 0x3c, 0x00, PERF_COUNT_HW_CPU_CYCLES },
@@ -215,6 +216,7 @@ static bool intel_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr)
 		ret = pmu->version > 1;
 		break;
 	case MSR_ARCH_LBR_DEPTH:
+	case MSR_ARCH_LBR_CTL:
 		if (kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR))
 			ret = guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR);
 		break;
@@ -361,6 +363,35 @@ static bool arch_lbr_depth_is_valid(struct kvm_vcpu *vcpu, u64 depth)
 	return (depth == pmu->kvm_arch_lbr_depth);
 }
 
+#define ARCH_LBR_CTL_BRN_MASK   GENMASK_ULL(22, 16)
+
+static bool arch_lbr_ctl_is_valid(struct kvm_vcpu *vcpu, u64 ctl)
+{
+	struct kvm_cpuid_entry2 *entry;
+
+	if (!kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR))
+		return false;
+
+	if (ctl & ~KVM_ARCH_LBR_CTL_MASK)
+		goto warn;
+
+	entry = kvm_find_cpuid_entry(vcpu, 0x1c, 0);
+	if (!entry)
+		return false;
+
+	if (!(entry->ebx & BIT(0)) && (ctl & ARCH_LBR_CTL_CPL))
+		return false;
+	if (!(entry->ebx & BIT(2)) && (ctl & ARCH_LBR_CTL_STACK))
+		return false;
+	if (!(entry->ebx & BIT(1)) && (ctl & ARCH_LBR_CTL_BRN_MASK))
+		return false;
+	return true;
+warn:
+	pr_warn_ratelimited("kvm: vcpu-%d: invalid arch lbr ctl.\n",
+			    vcpu->vcpu_id);
+	return false;
+}
+
 static int intel_pmu_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 {
 	struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
@@ -384,6 +415,9 @@ static int intel_pmu_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 	case MSR_ARCH_LBR_DEPTH:
 		msr_info->data = lbr_desc->records.nr;
 		return 0;
+	case MSR_ARCH_LBR_CTL:
+		msr_info->data = vmcs_read64(GUEST_IA32_LBR_CTL);
+		return 0;
 	default:
 		if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)) ||
 		    (pmc = get_gp_pmc(pmu, msr, MSR_IA32_PMC0))) {
@@ -455,6 +489,16 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 		 */
 		wrmsrl(MSR_ARCH_LBR_DEPTH, lbr_desc->records.nr);
 		return 0;
+	case MSR_ARCH_LBR_CTL:
+		if (!arch_lbr_ctl_is_valid(vcpu, data))
+			break;
+
+		vmcs_write64(GUEST_IA32_LBR_CTL, data);
+
+		if (intel_pmu_lbr_is_enabled(vcpu) && !lbr_desc->event &&
+		    (data & ARCH_LBR_CTL_LBREN))
+			intel_pmu_create_guest_lbr_event(vcpu);
+		return 0;
 	default:
 		if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)) ||
 		    (pmc = get_gp_pmc(pmu, msr, MSR_IA32_PMC0))) {
@@ -668,12 +712,16 @@ static void intel_pmu_reset(struct kvm_vcpu *vcpu)
  */
 static void intel_pmu_legacy_freezing_lbrs_on_pmi(struct kvm_vcpu *vcpu)
 {
-	u64 data = vmcs_read64(GUEST_IA32_DEBUGCTL);
+	u32 lbr_ctl_field = GUEST_IA32_DEBUGCTL;
 
-	if (data & DEBUGCTLMSR_FREEZE_LBRS_ON_PMI) {
-		data &= ~DEBUGCTLMSR_LBR;
-		vmcs_write64(GUEST_IA32_DEBUGCTL, data);
-	}
+	if (!(vmcs_read64(GUEST_IA32_DEBUGCTL) & DEBUGCTLMSR_FREEZE_LBRS_ON_PMI))
+		return;
+
+	if (kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR) &&
+	    guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR))
+		lbr_ctl_field = GUEST_IA32_LBR_CTL;
+
+	vmcs_write64(lbr_ctl_field, vmcs_read64(lbr_ctl_field) & ~0x1ULL);
 }
 
 static void intel_pmu_deliver_pmi(struct kvm_vcpu *vcpu)
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 04d170c4b61e..73961fcfb62d 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -2022,6 +2022,13 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 						VM_EXIT_SAVE_DEBUG_CONTROLS)
 			get_vmcs12(vcpu)->guest_ia32_debugctl = data;
 
+		/*
+		 * For Arch LBR, IA32_DEBUGCTL[bit 0] has no meaning.
+		 * It can be written to 0 or 1, but reads will always return 0.
+		 */
+		if (guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR))
+			data &= ~DEBUGCTLMSR_LBR;
+
 		vmcs_write64(GUEST_IA32_DEBUGCTL, data);
 		if (intel_pmu_lbr_is_enabled(vcpu) && !to_vmx(vcpu)->lbr_desc.event &&
 		    (data & DEBUGCTLMSR_LBR))
@@ -4548,6 +4555,11 @@ static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
 	kvm_make_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu);
 
 	vpid_sync_context(vmx->vpid);
+
+	if (!init_event) {
+		if (static_cpu_has(X86_FEATURE_ARCH_LBR))
+			vmcs_write64(GUEST_IA32_LBR_CTL, 0);
+	}
 }
 
 static void vmx_enable_irq_window(struct kvm_vcpu *vcpu)
-- 
2.27.0


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

* [PATCH v10 08/16] KVM: x86/pmu: Refactor code to support guest Arch LBR
  2022-04-22  7:54 [PATCH v10 00/16] Introduce Architectural LBR for vPMU Yang Weijiang
                   ` (6 preceding siblings ...)
  2022-04-22  7:55 ` [PATCH v10 07/16] KVM: vmx/pmu: Emulate MSR_ARCH_LBR_CTL " Yang Weijiang
@ 2022-04-22  7:55 ` Yang Weijiang
  2022-04-28 14:18   ` Liang, Kan
  2022-04-22  7:55 ` [PATCH v10 09/16] KVM: x86: Refine the matching and clearing logic for supported_xss Yang Weijiang
                   ` (7 subsequent siblings)
  15 siblings, 1 reply; 24+ messages in thread
From: Yang Weijiang @ 2022-04-22  7:55 UTC (permalink / raw)
  To: pbonzini, jmattson, seanjc, like.xu.linux, vkuznets, wei.w.wang,
	kvm, linux-kernel
  Cc: Yang Weijiang, Like Xu

Take account of Arch LBR when do sanity checks before program
vPMU for guest. Pass through Arch LBR recording MSRs to guest
to gain better performance. Note, Arch LBR and Legacy LBR support
are mutually exclusive, i.e., they're not both available on one
platform.

Co-developed-by: Like Xu <like.xu@linux.intel.com>
Signed-off-by: Like Xu <like.xu@linux.intel.com>
Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
---
 arch/x86/kvm/vmx/pmu_intel.c | 37 +++++++++++++++++++++++++++++-------
 arch/x86/kvm/vmx/vmx.c       |  3 +++
 2 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
index 7dc8a5783df7..cb28888e9f4f 100644
--- a/arch/x86/kvm/vmx/pmu_intel.c
+++ b/arch/x86/kvm/vmx/pmu_intel.c
@@ -170,12 +170,16 @@ static inline struct kvm_pmc *get_fw_gp_pmc(struct kvm_pmu *pmu, u32 msr)
 
 bool intel_pmu_lbr_is_compatible(struct kvm_vcpu *vcpu)
 {
+	if (kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR))
+		return guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR);
+
 	/*
 	 * As a first step, a guest could only enable LBR feature if its
 	 * cpu model is the same as the host because the LBR registers
 	 * would be pass-through to the guest and they're model specific.
 	 */
-	return boot_cpu_data.x86_model == guest_cpuid_model(vcpu);
+	return !boot_cpu_has(X86_FEATURE_ARCH_LBR) &&
+		boot_cpu_data.x86_model == guest_cpuid_model(vcpu);
 }
 
 bool intel_pmu_lbr_is_enabled(struct kvm_vcpu *vcpu)
@@ -193,12 +197,19 @@ static bool intel_pmu_is_valid_lbr_msr(struct kvm_vcpu *vcpu, u32 index)
 	if (!intel_pmu_lbr_is_enabled(vcpu))
 		return ret;
 
-	ret = (index == MSR_LBR_SELECT) || (index == MSR_LBR_TOS) ||
-		(index >= records->from && index < records->from + records->nr) ||
-		(index >= records->to && index < records->to + records->nr);
+	if (!guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR))
+		ret = (index == MSR_LBR_SELECT) || (index == MSR_LBR_TOS);
+
+	if (!ret) {
+		ret = (index >= records->from &&
+		       index < records->from + records->nr) ||
+		      (index >= records->to &&
+		       index < records->to + records->nr);
+	}
 
 	if (!ret && records->info)
-		ret = (index >= records->info && index < records->info + records->nr);
+		ret = (index >= records->info &&
+		       index < records->info + records->nr);
 
 	return ret;
 }
@@ -747,6 +758,9 @@ static void vmx_update_intercept_for_lbr_msrs(struct kvm_vcpu *vcpu, bool set)
 			vmx_set_intercept_for_msr(vcpu, lbr->info + i, MSR_TYPE_RW, set);
 	}
 
+	if (guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR))
+		return;
+
 	vmx_set_intercept_for_msr(vcpu, MSR_LBR_SELECT, MSR_TYPE_RW, set);
 	vmx_set_intercept_for_msr(vcpu, MSR_LBR_TOS, MSR_TYPE_RW, set);
 }
@@ -787,10 +801,13 @@ void vmx_passthrough_lbr_msrs(struct kvm_vcpu *vcpu)
 {
 	struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
 	struct lbr_desc *lbr_desc = vcpu_to_lbr_desc(vcpu);
+	bool lbr_enable = guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR) ?
+		(vmcs_read64(GUEST_IA32_LBR_CTL) & ARCH_LBR_CTL_LBREN) :
+		(vmcs_read64(GUEST_IA32_DEBUGCTL) & DEBUGCTLMSR_LBR);
 
 	if (!lbr_desc->event) {
 		vmx_disable_lbr_msrs_passthrough(vcpu);
-		if (vmcs_read64(GUEST_IA32_DEBUGCTL) & DEBUGCTLMSR_LBR)
+		if (lbr_enable)
 			goto warn;
 		if (test_bit(INTEL_PMC_IDX_FIXED_VLBR, pmu->pmc_in_use))
 			goto warn;
@@ -807,13 +824,19 @@ void vmx_passthrough_lbr_msrs(struct kvm_vcpu *vcpu)
 	return;
 
 warn:
+	if (kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR))
+		wrmsrl(MSR_ARCH_LBR_DEPTH, lbr_desc->records.nr);
 	pr_warn_ratelimited("kvm: vcpu-%d: fail to passthrough LBR.\n",
 		vcpu->vcpu_id);
 }
 
 static void intel_pmu_cleanup(struct kvm_vcpu *vcpu)
 {
-	if (!(vmcs_read64(GUEST_IA32_DEBUGCTL) & DEBUGCTLMSR_LBR))
+	bool lbr_enable = guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR) ?
+		(vmcs_read64(GUEST_IA32_LBR_CTL) & ARCH_LBR_CTL_LBREN) :
+		(vmcs_read64(GUEST_IA32_DEBUGCTL) & DEBUGCTLMSR_LBR);
+
+	if (!lbr_enable)
 		intel_pmu_release_guest_lbr_event(vcpu);
 }
 
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 73961fcfb62d..a1816c6597f5 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -573,6 +573,9 @@ static bool is_valid_passthrough_msr(u32 msr)
 	case MSR_LBR_NHM_TO ... MSR_LBR_NHM_TO + 31:
 	case MSR_LBR_CORE_FROM ... MSR_LBR_CORE_FROM + 8:
 	case MSR_LBR_CORE_TO ... MSR_LBR_CORE_TO + 8:
+	case MSR_ARCH_LBR_FROM_0 ... MSR_ARCH_LBR_FROM_0 + 31:
+	case MSR_ARCH_LBR_TO_0 ... MSR_ARCH_LBR_TO_0 + 31:
+	case MSR_ARCH_LBR_INFO_0 ... MSR_ARCH_LBR_INFO_0 + 31:
 		/* LBR MSRs. These are handled in vmx_update_intercept_for_lbr_msrs() */
 		return true;
 	}
-- 
2.27.0


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

* [PATCH v10 09/16] KVM: x86: Refine the matching and clearing logic for supported_xss
  2022-04-22  7:54 [PATCH v10 00/16] Introduce Architectural LBR for vPMU Yang Weijiang
                   ` (7 preceding siblings ...)
  2022-04-22  7:55 ` [PATCH v10 08/16] KVM: x86/pmu: Refactor code to support " Yang Weijiang
@ 2022-04-22  7:55 ` Yang Weijiang
  2022-04-22  7:55 ` [PATCH v10 10/16] KVM: x86: Add XSAVE Support for Architectural LBR Yang Weijiang
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 24+ messages in thread
From: Yang Weijiang @ 2022-04-22  7:55 UTC (permalink / raw)
  To: pbonzini, jmattson, seanjc, like.xu.linux, vkuznets, wei.w.wang,
	kvm, linux-kernel
  Cc: Like Xu, Yang Weijiang

From: Like Xu <like.xu@linux.intel.com>

Refine the code path of the existing clearing of supported_xss in this way:
initialize the supported_xss with the filter of KVM_SUPPORTED_XSS mask and
update its value in a bit clear manner (rather than bit setting).

Suggested-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: Like Xu <like.xu@linux.intel.com>
Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
---
 arch/x86/kvm/vmx/vmx.c | 5 +++--
 arch/x86/kvm/x86.c     | 6 +++++-
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index a1816c6597f5..b29c8e75f902 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -7439,9 +7439,10 @@ static __init void vmx_set_cpu_caps(void)
 		kvm_cpu_cap_set(X86_FEATURE_UMIP);
 
 	/* CPUID 0xD.1 */
-	supported_xss = 0;
-	if (!cpu_has_vmx_xsaves())
+	if (!cpu_has_vmx_xsaves()) {
 		kvm_cpu_cap_clear(X86_FEATURE_XSAVES);
+		supported_xss = 0;
+	}
 
 	/* CPUID 0x80000001 and 0x7 (RDPID) */
 	if (!cpu_has_vmx_rdtscp()) {
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index c81014f618ca..13475563c3f6 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -224,6 +224,8 @@ static struct kvm_user_return_msrs __percpu *user_return_msrs;
 				| XFEATURE_MASK_BNDCSR | XFEATURE_MASK_AVX512 \
 				| XFEATURE_MASK_PKRU | XFEATURE_MASK_XTILE)
 
+#define KVM_SUPPORTED_XSS     0
+
 u64 __read_mostly host_efer;
 EXPORT_SYMBOL_GPL(host_efer);
 
@@ -11586,8 +11588,10 @@ int kvm_arch_hardware_setup(void *opaque)
 
 	rdmsrl_safe(MSR_EFER, &host_efer);
 
-	if (boot_cpu_has(X86_FEATURE_XSAVES))
+	if (boot_cpu_has(X86_FEATURE_XSAVES)) {
 		rdmsrl(MSR_IA32_XSS, host_xss);
+		supported_xss = host_xss & KVM_SUPPORTED_XSS;
+	}
 
 	r = ops->hardware_setup();
 	if (r != 0)
-- 
2.27.0


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

* [PATCH v10 10/16] KVM: x86: Add XSAVE Support for Architectural LBR
  2022-04-22  7:54 [PATCH v10 00/16] Introduce Architectural LBR for vPMU Yang Weijiang
                   ` (8 preceding siblings ...)
  2022-04-22  7:55 ` [PATCH v10 09/16] KVM: x86: Refine the matching and clearing logic for supported_xss Yang Weijiang
@ 2022-04-22  7:55 ` Yang Weijiang
  2022-04-22  7:55 ` [PATCH v10 11/16] KVM: x86/vmx: Check Arch LBR config when return perf capabilities Yang Weijiang
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 24+ messages in thread
From: Yang Weijiang @ 2022-04-22  7:55 UTC (permalink / raw)
  To: pbonzini, jmattson, seanjc, like.xu.linux, vkuznets, wei.w.wang,
	kvm, linux-kernel
  Cc: Like Xu, Yang Weijiang

From: Like Xu <like.xu@linux.intel.com>

On processors supporting XSAVES and XRSTORS, Architectural LBR XSAVE
support is enumerated from CPUID.(EAX=0DH, ECX=1):ECX[bit 15].
The detailed sub-leaf for Arch LBR is enumerated in CPUID.(0DH, 0FH).

XSAVES provides a faster means than RDMSR for guest to read all LBRs.
When guest IA32_XSS[bit 15] is set, the Arch LBR state can be saved using
XSAVES and restored by XRSTORS with the appropriate RFBM.

Signed-off-by: Like Xu <like.xu@linux.intel.com>
Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
---
 arch/x86/kvm/vmx/vmx.c | 4 ++++
 arch/x86/kvm/x86.c     | 2 +-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index b29c8e75f902..60d92a459f4c 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -7427,6 +7427,10 @@ static __init void vmx_set_cpu_caps(void)
 		kvm_cpu_cap_clear(X86_FEATURE_INVPCID);
 	if (vmx_pt_mode_is_host_guest())
 		kvm_cpu_cap_check_and_set(X86_FEATURE_INTEL_PT);
+	if (!cpu_has_vmx_arch_lbr()) {
+		kvm_cpu_cap_clear(X86_FEATURE_ARCH_LBR);
+		supported_xss &= ~XFEATURE_MASK_LBR;
+	}
 
 	if (!enable_sgx) {
 		kvm_cpu_cap_clear(X86_FEATURE_SGX);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 13475563c3f6..e33315662db9 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -224,7 +224,7 @@ static struct kvm_user_return_msrs __percpu *user_return_msrs;
 				| XFEATURE_MASK_BNDCSR | XFEATURE_MASK_AVX512 \
 				| XFEATURE_MASK_PKRU | XFEATURE_MASK_XTILE)
 
-#define KVM_SUPPORTED_XSS     0
+#define KVM_SUPPORTED_XSS     XFEATURE_MASK_LBR
 
 u64 __read_mostly host_efer;
 EXPORT_SYMBOL_GPL(host_efer);
-- 
2.27.0


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

* [PATCH v10 11/16] KVM: x86/vmx: Check Arch LBR config when return perf capabilities
  2022-04-22  7:54 [PATCH v10 00/16] Introduce Architectural LBR for vPMU Yang Weijiang
                   ` (9 preceding siblings ...)
  2022-04-22  7:55 ` [PATCH v10 10/16] KVM: x86: Add XSAVE Support for Architectural LBR Yang Weijiang
@ 2022-04-22  7:55 ` Yang Weijiang
  2022-04-22  7:55 ` [PATCH v10 12/16] KVM: nVMX: Add necessary Arch LBR settings for nested VM Yang Weijiang
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 24+ messages in thread
From: Yang Weijiang @ 2022-04-22  7:55 UTC (permalink / raw)
  To: pbonzini, jmattson, seanjc, like.xu.linux, vkuznets, wei.w.wang,
	kvm, linux-kernel
  Cc: Yang Weijiang, Like Xu

Two new bit fields(VM_EXIT_CLEAR_IA32_LBR_CTL, VM_ENTRY_LOAD_IA32_LBR_CTL)
are added to support guest Arch LBR. These two bits should be set in order
to make Arch LBR workable in both guest and host.

Co-developed-by: Like Xu <like.xu@linux.intel.com>
Signed-off-by: Like Xu <like.xu@linux.intel.com>
Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
---
 arch/x86/include/asm/vmx.h      |  2 ++
 arch/x86/kvm/vmx/capabilities.h |  8 ++++++++
 arch/x86/kvm/vmx/vmx.c          | 10 ++++++++--
 3 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h
index ea3be961cc8e..d9b1dffc4638 100644
--- a/arch/x86/include/asm/vmx.h
+++ b/arch/x86/include/asm/vmx.h
@@ -95,6 +95,7 @@
 #define VM_EXIT_CLEAR_BNDCFGS                   0x00800000
 #define VM_EXIT_PT_CONCEAL_PIP			0x01000000
 #define VM_EXIT_CLEAR_IA32_RTIT_CTL		0x02000000
+#define VM_EXIT_CLEAR_IA32_LBR_CTL		0x04000000
 
 #define VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR	0x00036dff
 
@@ -108,6 +109,7 @@
 #define VM_ENTRY_LOAD_BNDCFGS                   0x00010000
 #define VM_ENTRY_PT_CONCEAL_PIP			0x00020000
 #define VM_ENTRY_LOAD_IA32_RTIT_CTL		0x00040000
+#define VM_ENTRY_LOAD_IA32_LBR_CTL		0x00200000
 
 #define VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR	0x000011ff
 
diff --git a/arch/x86/kvm/vmx/capabilities.h b/arch/x86/kvm/vmx/capabilities.h
index 3f430e218375..68fbb76ba439 100644
--- a/arch/x86/kvm/vmx/capabilities.h
+++ b/arch/x86/kvm/vmx/capabilities.h
@@ -385,6 +385,12 @@ static inline bool vmx_pt_mode_is_host_guest(void)
 	return pt_mode == PT_MODE_HOST_GUEST;
 }
 
+static inline bool cpu_has_vmx_arch_lbr(void)
+{
+	return (vmcs_config.vmexit_ctrl & VM_EXIT_CLEAR_IA32_LBR_CTL) &&
+		(vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_LBR_CTL);
+}
+
 static inline u64 vmx_get_perf_capabilities(void)
 {
 	u64 perf_cap = 0;
@@ -396,6 +402,8 @@ static inline u64 vmx_get_perf_capabilities(void)
 		rdmsrl(MSR_IA32_PERF_CAPABILITIES, perf_cap);
 
 	perf_cap &= PMU_CAP_LBR_FMT;
+	if (boot_cpu_has(X86_FEATURE_ARCH_LBR) && !cpu_has_vmx_arch_lbr())
+		perf_cap &= ~PMU_CAP_LBR_FMT;
 
 	/*
 	 * Since counters are virtualized, KVM would support full
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 60d92a459f4c..8962a8bab5eb 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -2532,7 +2532,8 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf,
 	      VM_EXIT_LOAD_IA32_EFER |
 	      VM_EXIT_CLEAR_BNDCFGS |
 	      VM_EXIT_PT_CONCEAL_PIP |
-	      VM_EXIT_CLEAR_IA32_RTIT_CTL;
+	      VM_EXIT_CLEAR_IA32_RTIT_CTL |
+	      VM_EXIT_CLEAR_IA32_LBR_CTL;
 	if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_EXIT_CTLS,
 				&_vmexit_control) < 0)
 		return -EIO;
@@ -2556,7 +2557,8 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf,
 	      VM_ENTRY_LOAD_IA32_EFER |
 	      VM_ENTRY_LOAD_BNDCFGS |
 	      VM_ENTRY_PT_CONCEAL_PIP |
-	      VM_ENTRY_LOAD_IA32_RTIT_CTL;
+	      VM_ENTRY_LOAD_IA32_RTIT_CTL |
+	      VM_ENTRY_LOAD_IA32_LBR_CTL;
 	if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_ENTRY_CTLS,
 				&_vmentry_control) < 0)
 		return -EIO;
@@ -5925,6 +5927,10 @@ void dump_vmcs(struct kvm_vcpu *vcpu)
 	    vmentry_ctl & VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL)
 		pr_err("PerfGlobCtl = 0x%016llx\n",
 		       vmcs_read64(GUEST_IA32_PERF_GLOBAL_CTRL));
+	if (kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR) &&
+	    vmentry_ctl & VM_ENTRY_LOAD_IA32_LBR_CTL)
+		pr_err("ArchLBRCtl = 0x%016llx\n",
+		       vmcs_read64(GUEST_IA32_LBR_CTL));
 	if (vmentry_ctl & VM_ENTRY_LOAD_BNDCFGS)
 		pr_err("BndCfgS = 0x%016llx\n", vmcs_read64(GUEST_BNDCFGS));
 	pr_err("Interruptibility = %08x  ActivityState = %08x\n",
-- 
2.27.0


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

* [PATCH v10 12/16] KVM: nVMX: Add necessary Arch LBR settings for nested VM
  2022-04-22  7:54 [PATCH v10 00/16] Introduce Architectural LBR for vPMU Yang Weijiang
                   ` (10 preceding siblings ...)
  2022-04-22  7:55 ` [PATCH v10 11/16] KVM: x86/vmx: Check Arch LBR config when return perf capabilities Yang Weijiang
@ 2022-04-22  7:55 ` Yang Weijiang
  2022-04-22  7:55 ` [PATCH v10 13/16] KVM: x86/vmx: Clear Arch LBREn bit before inject #DB to guest Yang Weijiang
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 24+ messages in thread
From: Yang Weijiang @ 2022-04-22  7:55 UTC (permalink / raw)
  To: pbonzini, jmattson, seanjc, like.xu.linux, vkuznets, wei.w.wang,
	kvm, linux-kernel
  Cc: Yang Weijiang

Arch LBR is not supported in nested VM now. This patch is to add
necessary settings to make it pass host KVM checks before L2 VM is
launched and also to avoid some warnings reported from L1.

Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
---
 arch/x86/kvm/vmx/nested.c    | 7 +++++--
 arch/x86/kvm/vmx/pmu_intel.c | 2 ++
 arch/x86/kvm/vmx/vmcs12.c    | 1 +
 arch/x86/kvm/vmx/vmcs12.h    | 3 ++-
 4 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
index f18744f7ff82..97a4da07a0ec 100644
--- a/arch/x86/kvm/vmx/nested.c
+++ b/arch/x86/kvm/vmx/nested.c
@@ -6558,7 +6558,9 @@ void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps)
 		VM_EXIT_HOST_ADDR_SPACE_SIZE |
 #endif
 		VM_EXIT_LOAD_IA32_PAT | VM_EXIT_SAVE_IA32_PAT |
-		VM_EXIT_CLEAR_BNDCFGS | VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL;
+		VM_EXIT_CLEAR_BNDCFGS | VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL |
+		VM_EXIT_CLEAR_IA32_LBR_CTL;
+
 	msrs->exit_ctls_high |=
 		VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR |
 		VM_EXIT_LOAD_IA32_EFER | VM_EXIT_SAVE_IA32_EFER |
@@ -6578,7 +6580,8 @@ void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps)
 		VM_ENTRY_IA32E_MODE |
 #endif
 		VM_ENTRY_LOAD_IA32_PAT | VM_ENTRY_LOAD_BNDCFGS |
-		VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL;
+		VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VM_ENTRY_LOAD_IA32_LBR_CTL;
+
 	msrs->entry_ctls_high |=
 		(VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR | VM_ENTRY_LOAD_IA32_EFER);
 
diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
index cb28888e9f4f..79eecbffa07b 100644
--- a/arch/x86/kvm/vmx/pmu_intel.c
+++ b/arch/x86/kvm/vmx/pmu_intel.c
@@ -228,6 +228,8 @@ static bool intel_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr)
 		break;
 	case MSR_ARCH_LBR_DEPTH:
 	case MSR_ARCH_LBR_CTL:
+		if (is_guest_mode(vcpu))
+			break;
 		if (kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR))
 			ret = guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR);
 		break;
diff --git a/arch/x86/kvm/vmx/vmcs12.c b/arch/x86/kvm/vmx/vmcs12.c
index 2251b60920f8..bcda664e4d26 100644
--- a/arch/x86/kvm/vmx/vmcs12.c
+++ b/arch/x86/kvm/vmx/vmcs12.c
@@ -65,6 +65,7 @@ const unsigned short vmcs12_field_offsets[] = {
 	FIELD64(HOST_IA32_PAT, host_ia32_pat),
 	FIELD64(HOST_IA32_EFER, host_ia32_efer),
 	FIELD64(HOST_IA32_PERF_GLOBAL_CTRL, host_ia32_perf_global_ctrl),
+	FIELD64(GUEST_IA32_LBR_CTL, guest_lbr_ctl),
 	FIELD(PIN_BASED_VM_EXEC_CONTROL, pin_based_vm_exec_control),
 	FIELD(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control),
 	FIELD(EXCEPTION_BITMAP, exception_bitmap),
diff --git a/arch/x86/kvm/vmx/vmcs12.h b/arch/x86/kvm/vmx/vmcs12.h
index 746129ddd5ae..bf50227fe401 100644
--- a/arch/x86/kvm/vmx/vmcs12.h
+++ b/arch/x86/kvm/vmx/vmcs12.h
@@ -71,7 +71,7 @@ struct __packed vmcs12 {
 	u64 pml_address;
 	u64 encls_exiting_bitmap;
 	u64 tsc_multiplier;
-	u64 padding64[1]; /* room for future expansion */
+	u64 guest_lbr_ctl;
 	/*
 	 * To allow migration of L1 (complete with its L2 guests) between
 	 * machines of different natural widths (32 or 64 bit), we cannot have
@@ -254,6 +254,7 @@ static inline void vmx_check_vmcs12_offsets(void)
 	CHECK_OFFSET(pml_address, 312);
 	CHECK_OFFSET(encls_exiting_bitmap, 320);
 	CHECK_OFFSET(tsc_multiplier, 328);
+	CHECK_OFFSET(guest_lbr_ctl, 336);
 	CHECK_OFFSET(cr0_guest_host_mask, 344);
 	CHECK_OFFSET(cr4_guest_host_mask, 352);
 	CHECK_OFFSET(cr0_read_shadow, 360);
-- 
2.27.0


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

* [PATCH v10 13/16] KVM: x86/vmx: Clear Arch LBREn bit before inject #DB to guest
  2022-04-22  7:54 [PATCH v10 00/16] Introduce Architectural LBR for vPMU Yang Weijiang
                   ` (11 preceding siblings ...)
  2022-04-22  7:55 ` [PATCH v10 12/16] KVM: nVMX: Add necessary Arch LBR settings for nested VM Yang Weijiang
@ 2022-04-22  7:55 ` Yang Weijiang
  2022-04-22  7:55 ` [PATCH v10 14/16] KVM: x86/vmx: Flip Arch LBREn bit on guest state change Yang Weijiang
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 24+ messages in thread
From: Yang Weijiang @ 2022-04-22  7:55 UTC (permalink / raw)
  To: pbonzini, jmattson, seanjc, like.xu.linux, vkuznets, wei.w.wang,
	kvm, linux-kernel
  Cc: Yang Weijiang

On a debug breakpoint event (#DB), IA32_LBR_CTL.LBREn is cleared.
So need to clear the bit manually before inject #DB.

Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
---
 arch/x86/kvm/vmx/vmx.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 8962a8bab5eb..8c2a4c6923a2 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -1605,6 +1605,27 @@ static void vmx_clear_hlt(struct kvm_vcpu *vcpu)
 		vmcs_write32(GUEST_ACTIVITY_STATE, GUEST_ACTIVITY_ACTIVE);
 }
 
+static void flip_arch_lbr_ctl(struct kvm_vcpu *vcpu, bool on)
+{
+	struct lbr_desc *lbr_desc = vcpu_to_lbr_desc(vcpu);
+	struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
+
+	if (kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR) &&
+	    test_bit(INTEL_PMC_IDX_FIXED_VLBR, pmu->pmc_in_use) &&
+	    lbr_desc->event) {
+		u64 old = vmcs_read64(GUEST_IA32_LBR_CTL);
+		u64 new;
+
+		if (on)
+			new = old | ARCH_LBR_CTL_LBREN;
+		else
+			new = old & ~ARCH_LBR_CTL_LBREN;
+
+		if (old != new)
+			vmcs_write64(GUEST_IA32_LBR_CTL, new);
+	}
+}
+
 static void vmx_queue_exception(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -1640,6 +1661,9 @@ static void vmx_queue_exception(struct kvm_vcpu *vcpu)
 	vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, intr_info);
 
 	vmx_clear_hlt(vcpu);
+
+	if (nr == DB_VECTOR)
+		flip_arch_lbr_ctl(vcpu, false);
 }
 
 static void vmx_setup_uret_msr(struct vcpu_vmx *vmx, unsigned int msr,
@@ -4640,6 +4664,9 @@ static void vmx_inject_nmi(struct kvm_vcpu *vcpu)
 			INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK | NMI_VECTOR);
 
 	vmx_clear_hlt(vcpu);
+
+	if (vcpu->arch.exception.nr == DB_VECTOR)
+		flip_arch_lbr_ctl(vcpu, false);
 }
 
 bool vmx_get_nmi_mask(struct kvm_vcpu *vcpu)
-- 
2.27.0


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

* [PATCH v10 14/16] KVM: x86/vmx: Flip Arch LBREn bit on guest state change
  2022-04-22  7:54 [PATCH v10 00/16] Introduce Architectural LBR for vPMU Yang Weijiang
                   ` (12 preceding siblings ...)
  2022-04-22  7:55 ` [PATCH v10 13/16] KVM: x86/vmx: Clear Arch LBREn bit before inject #DB to guest Yang Weijiang
@ 2022-04-22  7:55 ` Yang Weijiang
  2022-04-22  7:55 ` [PATCH v10 15/16] KVM: x86: Add Arch LBR data MSR access interface Yang Weijiang
  2022-04-22  7:55 ` [PATCH v10 16/16] KVM: x86/cpuid: Advertise Arch LBR feature in CPUID Yang Weijiang
  15 siblings, 0 replies; 24+ messages in thread
From: Yang Weijiang @ 2022-04-22  7:55 UTC (permalink / raw)
  To: pbonzini, jmattson, seanjc, like.xu.linux, vkuznets, wei.w.wang,
	kvm, linux-kernel
  Cc: Yang Weijiang

Per spec:"IA32_LBR_CTL.LBREn is saved and cleared on #SMI, and restored
on RSM. On a warm reset, all LBR MSRs, including IA32_LBR_DEPTH, have their
values preserved. However, IA32_LBR_CTL.LBREn is cleared to 0, disabling
LBRs." So clear Arch LBREn bit on #SMI and restore it on RSM manully, also
clear the bit when guest does warm reset.

Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
---
 arch/x86/kvm/vmx/vmx.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 8c2a4c6923a2..d58d50730efa 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -4588,6 +4588,8 @@ static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
 	if (!init_event) {
 		if (static_cpu_has(X86_FEATURE_ARCH_LBR))
 			vmcs_write64(GUEST_IA32_LBR_CTL, 0);
+	} else {
+		flip_arch_lbr_ctl(vcpu, false);
 	}
 }
 
@@ -7699,6 +7701,7 @@ static int vmx_enter_smm(struct kvm_vcpu *vcpu, char *smstate)
 	vmx->nested.smm.vmxon = vmx->nested.vmxon;
 	vmx->nested.vmxon = false;
 	vmx_clear_hlt(vcpu);
+	flip_arch_lbr_ctl(vcpu, false);
 	return 0;
 }
 
@@ -7720,6 +7723,7 @@ static int vmx_leave_smm(struct kvm_vcpu *vcpu, const char *smstate)
 		vmx->nested.nested_run_pending = 1;
 		vmx->nested.smm.guest_mode = false;
 	}
+	flip_arch_lbr_ctl(vcpu, true);
 	return 0;
 }
 
-- 
2.27.0


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

* [PATCH v10 15/16] KVM: x86: Add Arch LBR data MSR access interface
  2022-04-22  7:54 [PATCH v10 00/16] Introduce Architectural LBR for vPMU Yang Weijiang
                   ` (13 preceding siblings ...)
  2022-04-22  7:55 ` [PATCH v10 14/16] KVM: x86/vmx: Flip Arch LBREn bit on guest state change Yang Weijiang
@ 2022-04-22  7:55 ` Yang Weijiang
  2022-04-28 15:05   ` Liang, Kan
  2022-04-22  7:55 ` [PATCH v10 16/16] KVM: x86/cpuid: Advertise Arch LBR feature in CPUID Yang Weijiang
  15 siblings, 1 reply; 24+ messages in thread
From: Yang Weijiang @ 2022-04-22  7:55 UTC (permalink / raw)
  To: pbonzini, jmattson, seanjc, like.xu.linux, vkuznets, wei.w.wang,
	kvm, linux-kernel
  Cc: Yang Weijiang

Arch LBR MSRs are xsave-supported, but they're operated as "independent"
xsave feature by PMU code, i.e., during thread/process context switch,
the MSRs are saved/restored with PMU specific code instead of generic
kernel fpu XSAVES/XRSTORS operation. When vcpu guest/host fpu state swap
happens, Arch LBR MSRs won't be touched so access them directly.

Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
---
 arch/x86/kvm/vmx/pmu_intel.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
index 79eecbffa07b..5f81644c4612 100644
--- a/arch/x86/kvm/vmx/pmu_intel.c
+++ b/arch/x86/kvm/vmx/pmu_intel.c
@@ -431,6 +431,11 @@ static int intel_pmu_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 	case MSR_ARCH_LBR_CTL:
 		msr_info->data = vmcs_read64(GUEST_IA32_LBR_CTL);
 		return 0;
+	case MSR_ARCH_LBR_FROM_0 ... MSR_ARCH_LBR_FROM_0 + 31:
+	case MSR_ARCH_LBR_TO_0 ... MSR_ARCH_LBR_TO_0 + 31:
+	case MSR_ARCH_LBR_INFO_0 ... MSR_ARCH_LBR_INFO_0 + 31:
+		rdmsrl(msr_info->index, msr_info->data);
+		return 0;
 	default:
 		if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)) ||
 		    (pmc = get_gp_pmc(pmu, msr, MSR_IA32_PMC0))) {
@@ -512,6 +517,11 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 		    (data & ARCH_LBR_CTL_LBREN))
 			intel_pmu_create_guest_lbr_event(vcpu);
 		return 0;
+	case MSR_ARCH_LBR_FROM_0 ... MSR_ARCH_LBR_FROM_0 + 31:
+	case MSR_ARCH_LBR_TO_0 ... MSR_ARCH_LBR_TO_0 + 31:
+	case MSR_ARCH_LBR_INFO_0 ... MSR_ARCH_LBR_INFO_0 + 31:
+		wrmsrl(msr_info->index, msr_info->data);
+		return 0;
 	default:
 		if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)) ||
 		    (pmc = get_gp_pmc(pmu, msr, MSR_IA32_PMC0))) {
-- 
2.27.0


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

* [PATCH v10 16/16] KVM: x86/cpuid: Advertise Arch LBR feature in CPUID
  2022-04-22  7:54 [PATCH v10 00/16] Introduce Architectural LBR for vPMU Yang Weijiang
                   ` (14 preceding siblings ...)
  2022-04-22  7:55 ` [PATCH v10 15/16] KVM: x86: Add Arch LBR data MSR access interface Yang Weijiang
@ 2022-04-22  7:55 ` Yang Weijiang
  15 siblings, 0 replies; 24+ messages in thread
From: Yang Weijiang @ 2022-04-22  7:55 UTC (permalink / raw)
  To: pbonzini, jmattson, seanjc, like.xu.linux, vkuznets, wei.w.wang,
	kvm, linux-kernel
  Cc: Yang Weijiang, Like Xu

Add Arch LBR feature bit in CPU cap-mask to expose the feature.
Only max LBR depth is supported for guest, and it's consistent
with host Arch LBR settings.

Co-developed-by: Like Xu <like.xu@linux.intel.com>
Signed-off-by: Like Xu <like.xu@linux.intel.com>
Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
---
 arch/x86/kvm/cpuid.c | 33 ++++++++++++++++++++++++++++++++-
 1 file changed, 32 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index 3f3ec42c27d5..0f4afedf787e 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -102,6 +102,16 @@ static int kvm_check_cpuid(struct kvm_vcpu *vcpu,
 		if (vaddr_bits != 48 && vaddr_bits != 57 && vaddr_bits != 0)
 			return -EINVAL;
 	}
+	best = cpuid_entry2_find(entries, nent, 0x1c, 0);
+	if (best) {
+		unsigned int eax, ebx, ecx, edx;
+
+		/* Reject user-space CPUID if depth is different from host's.*/
+		cpuid_count(0x1c, 0, &eax, &ebx, &ecx, &edx);
+
+		if ((best->eax & 0xff) != BIT(fls(eax & 0xff) - 1))
+			return -EINVAL;
+	}
 
 	/*
 	 * Exposing dynamic xfeatures to the guest requires additional
@@ -598,7 +608,7 @@ void kvm_set_cpu_caps(void)
 		F(SPEC_CTRL_SSBD) | F(ARCH_CAPABILITIES) | F(INTEL_STIBP) |
 		F(MD_CLEAR) | F(AVX512_VP2INTERSECT) | F(FSRM) |
 		F(SERIALIZE) | F(TSXLDTRK) | F(AVX512_FP16) |
-		F(AMX_TILE) | F(AMX_INT8) | F(AMX_BF16)
+		F(AMX_TILE) | F(AMX_INT8) | F(AMX_BF16) | F(ARCH_LBR)
 	);
 
 	/* TSC_ADJUST and ARCH_CAPABILITIES are emulated in software. */
@@ -1044,6 +1054,27 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
 				goto out;
 		}
 		break;
+	/* Architectural LBR */
+	case 0x1c: {
+		u32 lbr_depth_mask = entry->eax & 0xff;
+
+		if (!lbr_depth_mask ||
+		    !kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR)) {
+			entry->eax = entry->ebx = entry->ecx = entry->edx = 0;
+			break;
+		}
+		/*
+		 * KVM only exposes the maximum supported depth, which is the
+		 * fixed value used on the host side.
+		 * KVM doesn't allow VMM userspace to adjust LBR depth because
+		 * guest LBR emulation depends on the configuration of host LBR
+		 * driver.
+		 */
+		lbr_depth_mask = BIT((fls(lbr_depth_mask) - 1));
+		entry->eax &= ~0xff;
+		entry->eax |= lbr_depth_mask;
+		break;
+	}
 	/* Intel AMX TILE */
 	case 0x1d:
 		if (!kvm_cpu_cap_has(X86_FEATURE_AMX_TILE)) {
-- 
2.27.0


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

* Re: [PATCH v10 07/16] KVM: vmx/pmu: Emulate MSR_ARCH_LBR_CTL for guest Arch LBR
  2022-04-22  7:55 ` [PATCH v10 07/16] KVM: vmx/pmu: Emulate MSR_ARCH_LBR_CTL " Yang Weijiang
@ 2022-04-28 14:16   ` Liang, Kan
  2022-04-29  3:20     ` Yang, Weijiang
  0 siblings, 1 reply; 24+ messages in thread
From: Liang, Kan @ 2022-04-28 14:16 UTC (permalink / raw)
  To: Yang Weijiang, pbonzini, jmattson, seanjc, like.xu.linux,
	vkuznets, wei.w.wang, kvm, linux-kernel



On 4/22/2022 3:55 AM, Yang Weijiang wrote:
> From: Like Xu <like.xu@linux.intel.com>
> 
> Arch LBR is enabled by setting MSR_ARCH_LBR_CTL.LBREn to 1. A new guest
> state field named "Guest IA32_LBR_CTL" is added to enhance guest LBR usage.
> When guest Arch LBR is enabled, a guest LBR event will be created like the
> model-specific LBR does. Clear guest LBR enable bit on host PMI handling so
> guest can see expected config.
> 
> On processors that support Arch LBR, MSR_IA32_DEBUGCTLMSR[bit 0] has no
> meaning. It can be written to 0 or 1, but reads will always return 0.
> Like IA32_DEBUGCTL, IA32_ARCH_LBR_CTL msr is also preserved on INIT.
> 
> Regardless of the Arch LBR or legacy LBR, when the LBR_EN bit 0 of the
> corresponding control MSR is set to 1, LBR recording will be enabled.
> 
> Signed-off-by: Like Xu <like.xu@linux.intel.com>
> Co-developed-by: Yang Weijiang <weijiang.yang@intel.com>
> Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
> ---
>   arch/x86/events/intel/lbr.c      |  2 --
>   arch/x86/include/asm/msr-index.h |  1 +
>   arch/x86/include/asm/vmx.h       |  2 ++
>   arch/x86/kvm/vmx/pmu_intel.c     | 58 +++++++++++++++++++++++++++++---
>   arch/x86/kvm/vmx/vmx.c           | 12 +++++++
>   5 files changed, 68 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c
> index 4529ce448b2e..4fe6c3b50fc3 100644
> --- a/arch/x86/events/intel/lbr.c
> +++ b/arch/x86/events/intel/lbr.c
> @@ -160,8 +160,6 @@ enum {
>   	 ARCH_LBR_RETURN		|\
>   	 ARCH_LBR_OTHER_BRANCH)
>   
> -#define ARCH_LBR_CTL_MASK			0x7f000e
> -
>   static void intel_pmu_lbr_filter(struct cpu_hw_events *cpuc);
>   
>   static __always_inline bool is_lbr_call_stack_bit_set(u64 config)
> diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
> index 0eb90d21049e..60e0ab108dc0 100644
> --- a/arch/x86/include/asm/msr-index.h
> +++ b/arch/x86/include/asm/msr-index.h
> @@ -169,6 +169,7 @@
>   #define LBR_INFO_BR_TYPE		(0xfull << LBR_INFO_BR_TYPE_OFFSET)
>   
>   #define MSR_ARCH_LBR_CTL		0x000014ce
> +#define ARCH_LBR_CTL_MASK		0x7f000e
>   #define ARCH_LBR_CTL_LBREN		BIT(0)
>   #define ARCH_LBR_CTL_CPL_OFFSET		1
>   #define ARCH_LBR_CTL_CPL		(0x3ull << ARCH_LBR_CTL_CPL_OFFSET)
> diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h
> index 0ffaa3156a4e..ea3be961cc8e 100644
> --- a/arch/x86/include/asm/vmx.h
> +++ b/arch/x86/include/asm/vmx.h
> @@ -245,6 +245,8 @@ enum vmcs_field {
>   	GUEST_BNDCFGS_HIGH              = 0x00002813,
>   	GUEST_IA32_RTIT_CTL		= 0x00002814,
>   	GUEST_IA32_RTIT_CTL_HIGH	= 0x00002815,
> +	GUEST_IA32_LBR_CTL		= 0x00002816,
> +	GUEST_IA32_LBR_CTL_HIGH		= 0x00002817,
>   	HOST_IA32_PAT			= 0x00002c00,
>   	HOST_IA32_PAT_HIGH		= 0x00002c01,
>   	HOST_IA32_EFER			= 0x00002c02,
> diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
> index c8e6c1e1e00c..7dc8a5783df7 100644
> --- a/arch/x86/kvm/vmx/pmu_intel.c
> +++ b/arch/x86/kvm/vmx/pmu_intel.c
> @@ -19,6 +19,7 @@
>   #include "pmu.h"
>   
>   #define MSR_PMC_FULL_WIDTH_BIT      (MSR_IA32_PMC0 - MSR_IA32_PERFCTR0)
> +#define KVM_ARCH_LBR_CTL_MASK  (ARCH_LBR_CTL_MASK | ARCH_LBR_CTL_LBREN)
>   
>   static struct kvm_event_hw_type_mapping intel_arch_events[] = {
>   	[0] = { 0x3c, 0x00, PERF_COUNT_HW_CPU_CYCLES },
> @@ -215,6 +216,7 @@ static bool intel_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr)
>   		ret = pmu->version > 1;
>   		break;
>   	case MSR_ARCH_LBR_DEPTH:
> +	case MSR_ARCH_LBR_CTL:
>   		if (kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR))
>   			ret = guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR);
>   		break;
> @@ -361,6 +363,35 @@ static bool arch_lbr_depth_is_valid(struct kvm_vcpu *vcpu, u64 depth)
>   	return (depth == pmu->kvm_arch_lbr_depth);
>   }
>   
> +#define ARCH_LBR_CTL_BRN_MASK   GENMASK_ULL(22, 16)
> +
> +static bool arch_lbr_ctl_is_valid(struct kvm_vcpu *vcpu, u64 ctl)
> +{
> +	struct kvm_cpuid_entry2 *entry;
> +
> +	if (!kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR))
> +		return false;
> +
> +	if (ctl & ~KVM_ARCH_LBR_CTL_MASK)
> +		goto warn;
> +
> +	entry = kvm_find_cpuid_entry(vcpu, 0x1c, 0);
> +	if (!entry)
> +		return false;
> +
> +	if (!(entry->ebx & BIT(0)) && (ctl & ARCH_LBR_CTL_CPL))
> +		return false;
> +	if (!(entry->ebx & BIT(2)) && (ctl & ARCH_LBR_CTL_STACK))
> +		return false;
> +	if (!(entry->ebx & BIT(1)) && (ctl & ARCH_LBR_CTL_BRN_MASK))

Why KVM wants to define this mask by itself? Cannot we use the 
ARCH_LBR_CTL_FILTER?

Thanks,
Kan

> +		return false;
> +	return true;
> +warn:
> +	pr_warn_ratelimited("kvm: vcpu-%d: invalid arch lbr ctl.\n",
> +			    vcpu->vcpu_id);
> +	return false;
> +}
> +
>   static int intel_pmu_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
>   {
>   	struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
> @@ -384,6 +415,9 @@ static int intel_pmu_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
>   	case MSR_ARCH_LBR_DEPTH:
>   		msr_info->data = lbr_desc->records.nr;
>   		return 0;
> +	case MSR_ARCH_LBR_CTL:
> +		msr_info->data = vmcs_read64(GUEST_IA32_LBR_CTL);
> +		return 0;
>   	default:
>   		if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)) ||
>   		    (pmc = get_gp_pmc(pmu, msr, MSR_IA32_PMC0))) {
> @@ -455,6 +489,16 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
>   		 */
>   		wrmsrl(MSR_ARCH_LBR_DEPTH, lbr_desc->records.nr);
>   		return 0;
> +	case MSR_ARCH_LBR_CTL:
> +		if (!arch_lbr_ctl_is_valid(vcpu, data))
> +			break;
> +
> +		vmcs_write64(GUEST_IA32_LBR_CTL, data);
> +
> +		if (intel_pmu_lbr_is_enabled(vcpu) && !lbr_desc->event &&
> +		    (data & ARCH_LBR_CTL_LBREN))
> +			intel_pmu_create_guest_lbr_event(vcpu);
> +		return 0;
>   	default:
>   		if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)) ||
>   		    (pmc = get_gp_pmc(pmu, msr, MSR_IA32_PMC0))) {
> @@ -668,12 +712,16 @@ static void intel_pmu_reset(struct kvm_vcpu *vcpu)
>    */
>   static void intel_pmu_legacy_freezing_lbrs_on_pmi(struct kvm_vcpu *vcpu)
>   {
> -	u64 data = vmcs_read64(GUEST_IA32_DEBUGCTL);
> +	u32 lbr_ctl_field = GUEST_IA32_DEBUGCTL;
>   
> -	if (data & DEBUGCTLMSR_FREEZE_LBRS_ON_PMI) {
> -		data &= ~DEBUGCTLMSR_LBR;
> -		vmcs_write64(GUEST_IA32_DEBUGCTL, data);
> -	}
> +	if (!(vmcs_read64(GUEST_IA32_DEBUGCTL) & DEBUGCTLMSR_FREEZE_LBRS_ON_PMI))
> +		return;
> +
> +	if (kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR) &&
> +	    guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR))
> +		lbr_ctl_field = GUEST_IA32_LBR_CTL;
> +
> +	vmcs_write64(lbr_ctl_field, vmcs_read64(lbr_ctl_field) & ~0x1ULL);
>   }
>   
>   static void intel_pmu_deliver_pmi(struct kvm_vcpu *vcpu)
> diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
> index 04d170c4b61e..73961fcfb62d 100644
> --- a/arch/x86/kvm/vmx/vmx.c
> +++ b/arch/x86/kvm/vmx/vmx.c
> @@ -2022,6 +2022,13 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
>   						VM_EXIT_SAVE_DEBUG_CONTROLS)
>   			get_vmcs12(vcpu)->guest_ia32_debugctl = data;
>   
> +		/*
> +		 * For Arch LBR, IA32_DEBUGCTL[bit 0] has no meaning.
> +		 * It can be written to 0 or 1, but reads will always return 0.
> +		 */
> +		if (guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR))
> +			data &= ~DEBUGCTLMSR_LBR;
> +
>   		vmcs_write64(GUEST_IA32_DEBUGCTL, data);
>   		if (intel_pmu_lbr_is_enabled(vcpu) && !to_vmx(vcpu)->lbr_desc.event &&
>   		    (data & DEBUGCTLMSR_LBR))
> @@ -4548,6 +4555,11 @@ static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
>   	kvm_make_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu);
>   
>   	vpid_sync_context(vmx->vpid);
> +
> +	if (!init_event) {
> +		if (static_cpu_has(X86_FEATURE_ARCH_LBR))
> +			vmcs_write64(GUEST_IA32_LBR_CTL, 0);
> +	}
>   }
>   
>   static void vmx_enable_irq_window(struct kvm_vcpu *vcpu)

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

* Re: [PATCH v10 08/16] KVM: x86/pmu: Refactor code to support guest Arch LBR
  2022-04-22  7:55 ` [PATCH v10 08/16] KVM: x86/pmu: Refactor code to support " Yang Weijiang
@ 2022-04-28 14:18   ` Liang, Kan
  2022-04-29  5:45     ` Yang, Weijiang
  0 siblings, 1 reply; 24+ messages in thread
From: Liang, Kan @ 2022-04-28 14:18 UTC (permalink / raw)
  To: Yang Weijiang, pbonzini, jmattson, seanjc, like.xu.linux,
	vkuznets, wei.w.wang, kvm, linux-kernel



On 4/22/2022 3:55 AM, Yang Weijiang wrote:
> Take account of Arch LBR when do sanity checks before program
> vPMU for guest. Pass through Arch LBR recording MSRs to guest
> to gain better performance. Note, Arch LBR and Legacy LBR support
> are mutually exclusive, i.e., they're not both available on one
> platform.
> 
> Co-developed-by: Like Xu <like.xu@linux.intel.com>
> Signed-off-by: Like Xu <like.xu@linux.intel.com>
> Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
> ---
>   arch/x86/kvm/vmx/pmu_intel.c | 37 +++++++++++++++++++++++++++++-------
>   arch/x86/kvm/vmx/vmx.c       |  3 +++
>   2 files changed, 33 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
> index 7dc8a5783df7..cb28888e9f4f 100644
> --- a/arch/x86/kvm/vmx/pmu_intel.c
> +++ b/arch/x86/kvm/vmx/pmu_intel.c
> @@ -170,12 +170,16 @@ static inline struct kvm_pmc *get_fw_gp_pmc(struct kvm_pmu *pmu, u32 msr)
>   
>   bool intel_pmu_lbr_is_compatible(struct kvm_vcpu *vcpu)
>   {
> +	if (kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR))
> +		return guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR);
> +
>   	/*
>   	 * As a first step, a guest could only enable LBR feature if its
>   	 * cpu model is the same as the host because the LBR registers
>   	 * would be pass-through to the guest and they're model specific.
>   	 */
> -	return boot_cpu_data.x86_model == guest_cpuid_model(vcpu);
> +	return !boot_cpu_has(X86_FEATURE_ARCH_LBR) &&
> +		boot_cpu_data.x86_model == guest_cpuid_model(vcpu);
>   }
>   
>   bool intel_pmu_lbr_is_enabled(struct kvm_vcpu *vcpu)
> @@ -193,12 +197,19 @@ static bool intel_pmu_is_valid_lbr_msr(struct kvm_vcpu *vcpu, u32 index)

I think we should move MSR_ARCH_LBR_DEPTH and MSR_ARCH_LBR_CTL to this 
function as well, since they are LBR related MSRs.

>   	if (!intel_pmu_lbr_is_enabled(vcpu))
>   		return ret;
>   
> -	ret = (index == MSR_LBR_SELECT) || (index == MSR_LBR_TOS) ||
> -		(index >= records->from && index < records->from + records->nr) ||
> -		(index >= records->to && index < records->to + records->nr);
> +	if (!guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR))
> +		ret = (index == MSR_LBR_SELECT) || (index == MSR_LBR_TOS);
> +
> +	if (!ret) {
> +		ret = (index >= records->from &&
> +		       index < records->from + records->nr) ||
> +		      (index >= records->to &&
> +		       index < records->to + records->nr);
> +	}
>   
>   	if (!ret && records->info)
> -		ret = (index >= records->info && index < records->info + records->nr);
> +		ret = (index >= records->info &&
> +		       index < records->info + records->nr);

Please use "{}" since you split it to two lines.

Thanks,
Kan
>   
>   	return ret;
>   }
> @@ -747,6 +758,9 @@ static void vmx_update_intercept_for_lbr_msrs(struct kvm_vcpu *vcpu, bool set)
>   			vmx_set_intercept_for_msr(vcpu, lbr->info + i, MSR_TYPE_RW, set);
>   	}
>   
> +	if (guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR))
> +		return;
> +
>   	vmx_set_intercept_for_msr(vcpu, MSR_LBR_SELECT, MSR_TYPE_RW, set);
>   	vmx_set_intercept_for_msr(vcpu, MSR_LBR_TOS, MSR_TYPE_RW, set);
>   }
> @@ -787,10 +801,13 @@ void vmx_passthrough_lbr_msrs(struct kvm_vcpu *vcpu)
>   {
>   	struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
>   	struct lbr_desc *lbr_desc = vcpu_to_lbr_desc(vcpu);
> +	bool lbr_enable = guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR) ?
> +		(vmcs_read64(GUEST_IA32_LBR_CTL) & ARCH_LBR_CTL_LBREN) :
> +		(vmcs_read64(GUEST_IA32_DEBUGCTL) & DEBUGCTLMSR_LBR);
>   
>   	if (!lbr_desc->event) {
>   		vmx_disable_lbr_msrs_passthrough(vcpu);
> -		if (vmcs_read64(GUEST_IA32_DEBUGCTL) & DEBUGCTLMSR_LBR)
> +		if (lbr_enable)
>   			goto warn;
>   		if (test_bit(INTEL_PMC_IDX_FIXED_VLBR, pmu->pmc_in_use))
>   			goto warn;
> @@ -807,13 +824,19 @@ void vmx_passthrough_lbr_msrs(struct kvm_vcpu *vcpu)
>   	return;
>   
>   warn:
> +	if (kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR))
> +		wrmsrl(MSR_ARCH_LBR_DEPTH, lbr_desc->records.nr);
>   	pr_warn_ratelimited("kvm: vcpu-%d: fail to passthrough LBR.\n",
>   		vcpu->vcpu_id);
>   }
>   
>   static void intel_pmu_cleanup(struct kvm_vcpu *vcpu)
>   {
> -	if (!(vmcs_read64(GUEST_IA32_DEBUGCTL) & DEBUGCTLMSR_LBR))
> +	bool lbr_enable = guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR) ?
> +		(vmcs_read64(GUEST_IA32_LBR_CTL) & ARCH_LBR_CTL_LBREN) :
> +		(vmcs_read64(GUEST_IA32_DEBUGCTL) & DEBUGCTLMSR_LBR);
> +
> +	if (!lbr_enable)
>   		intel_pmu_release_guest_lbr_event(vcpu);
>   }
>   
> diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
> index 73961fcfb62d..a1816c6597f5 100644
> --- a/arch/x86/kvm/vmx/vmx.c
> +++ b/arch/x86/kvm/vmx/vmx.c
> @@ -573,6 +573,9 @@ static bool is_valid_passthrough_msr(u32 msr)
>   	case MSR_LBR_NHM_TO ... MSR_LBR_NHM_TO + 31:
>   	case MSR_LBR_CORE_FROM ... MSR_LBR_CORE_FROM + 8:
>   	case MSR_LBR_CORE_TO ... MSR_LBR_CORE_TO + 8:
> +	case MSR_ARCH_LBR_FROM_0 ... MSR_ARCH_LBR_FROM_0 + 31:
> +	case MSR_ARCH_LBR_TO_0 ... MSR_ARCH_LBR_TO_0 + 31:
> +	case MSR_ARCH_LBR_INFO_0 ... MSR_ARCH_LBR_INFO_0 + 31:
>   		/* LBR MSRs. These are handled in vmx_update_intercept_for_lbr_msrs() */
>   		return true;
>   	}

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

* Re: [PATCH v10 15/16] KVM: x86: Add Arch LBR data MSR access interface
  2022-04-22  7:55 ` [PATCH v10 15/16] KVM: x86: Add Arch LBR data MSR access interface Yang Weijiang
@ 2022-04-28 15:05   ` Liang, Kan
  2022-04-29  6:34     ` Yang, Weijiang
  0 siblings, 1 reply; 24+ messages in thread
From: Liang, Kan @ 2022-04-28 15:05 UTC (permalink / raw)
  To: Yang Weijiang, pbonzini, jmattson, seanjc, like.xu.linux,
	vkuznets, wei.w.wang, kvm, linux-kernel



On 4/22/2022 3:55 AM, Yang Weijiang wrote:
> Arch LBR MSRs are xsave-supported, but they're operated as "independent"
> xsave feature by PMU code, i.e., during thread/process context switch,
> the MSRs are saved/restored with PMU specific code instead of generic
> kernel fpu XSAVES/XRSTORS operation. 

During thread/process context switch, Linux perf still uses the 
XSAVES/XRSTORS operation to save/restore the LBR MSRs.

Linux perf only manipulates these MSRs only when the xsave feature is 
not supported.

Thanks,
Kan

> When vcpu guest/host fpu state swap
> happens, Arch LBR MSRs won't be touched so access them directly.
> 
> Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
> ---
>   arch/x86/kvm/vmx/pmu_intel.c | 10 ++++++++++
>   1 file changed, 10 insertions(+)
> 
> diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
> index 79eecbffa07b..5f81644c4612 100644
> --- a/arch/x86/kvm/vmx/pmu_intel.c
> +++ b/arch/x86/kvm/vmx/pmu_intel.c
> @@ -431,6 +431,11 @@ static int intel_pmu_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
>   	case MSR_ARCH_LBR_CTL:
>   		msr_info->data = vmcs_read64(GUEST_IA32_LBR_CTL);
>   		return 0;
> +	case MSR_ARCH_LBR_FROM_0 ... MSR_ARCH_LBR_FROM_0 + 31:
> +	case MSR_ARCH_LBR_TO_0 ... MSR_ARCH_LBR_TO_0 + 31:
> +	case MSR_ARCH_LBR_INFO_0 ... MSR_ARCH_LBR_INFO_0 + 31:
> +		rdmsrl(msr_info->index, msr_info->data);
> +		return 0;
>   	default:
>   		if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)) ||
>   		    (pmc = get_gp_pmc(pmu, msr, MSR_IA32_PMC0))) {
> @@ -512,6 +517,11 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
>   		    (data & ARCH_LBR_CTL_LBREN))
>   			intel_pmu_create_guest_lbr_event(vcpu);
>   		return 0;
> +	case MSR_ARCH_LBR_FROM_0 ... MSR_ARCH_LBR_FROM_0 + 31:
> +	case MSR_ARCH_LBR_TO_0 ... MSR_ARCH_LBR_TO_0 + 31:
> +	case MSR_ARCH_LBR_INFO_0 ... MSR_ARCH_LBR_INFO_0 + 31:
> +		wrmsrl(msr_info->index, msr_info->data);
> +		return 0;
>   	default:
>   		if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)) ||
>   		    (pmc = get_gp_pmc(pmu, msr, MSR_IA32_PMC0))) {

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

* Re: [PATCH v10 07/16] KVM: vmx/pmu: Emulate MSR_ARCH_LBR_CTL for guest Arch LBR
  2022-04-28 14:16   ` Liang, Kan
@ 2022-04-29  3:20     ` Yang, Weijiang
  2022-04-29  8:19       ` Yang, Weijiang
  0 siblings, 1 reply; 24+ messages in thread
From: Yang, Weijiang @ 2022-04-29  3:20 UTC (permalink / raw)
  To: Liang, Kan, pbonzini, jmattson, seanjc, like.xu.linux, vkuznets,
	Wang, Wei W, kvm, linux-kernel


On 4/28/2022 10:16 PM, Liang, Kan wrote:
>
> On 4/22/2022 3:55 AM, Yang Weijiang wrote:
>> From: Like Xu <like.xu@linux.intel.com>
>>
>> Arch LBR is enabled by setting MSR_ARCH_LBR_CTL.LBREn to 1. A new guest
>> state field named "Guest IA32_LBR_CTL" is added to enhance guest LBR usage.
>> When guest Arch LBR is enabled, a guest LBR event will be created like the
>> model-specific LBR does. Clear guest LBR enable bit on host PMI handling so
>> guest can see expected config.
>>
>> On processors that support Arch LBR, MSR_IA32_DEBUGCTLMSR[bit 0] has no
>> meaning. It can be written to 0 or 1, but reads will always return 0.
>> Like IA32_DEBUGCTL, IA32_ARCH_LBR_CTL msr is also preserved on INIT.
>>
>> Regardless of the Arch LBR or legacy LBR, when the LBR_EN bit 0 of the
>> corresponding control MSR is set to 1, LBR recording will be enabled.
>>
>> Signed-off-by: Like Xu <like.xu@linux.intel.com>
>> Co-developed-by: Yang Weijiang <weijiang.yang@intel.com>
>> Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
>> ---
>>    arch/x86/events/intel/lbr.c      |  2 --
>>    arch/x86/include/asm/msr-index.h |  1 +
>>    arch/x86/include/asm/vmx.h       |  2 ++
>>    arch/x86/kvm/vmx/pmu_intel.c     | 58 +++++++++++++++++++++++++++++---
>>    arch/x86/kvm/vmx/vmx.c           | 12 +++++++
>>    5 files changed, 68 insertions(+), 7 deletions(-)
>>
>> diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c
>> index 4529ce448b2e..4fe6c3b50fc3 100644
>> --- a/arch/x86/events/intel/lbr.c
>> +++ b/arch/x86/events/intel/lbr.c
>> @@ -160,8 +160,6 @@ enum {
>>    	 ARCH_LBR_RETURN		|\
>>    	 ARCH_LBR_OTHER_BRANCH)
>>    
>> -#define ARCH_LBR_CTL_MASK			0x7f000e
>> -
>>    static void intel_pmu_lbr_filter(struct cpu_hw_events *cpuc);
>>    
>>    static __always_inline bool is_lbr_call_stack_bit_set(u64 config)
>> diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
>> index 0eb90d21049e..60e0ab108dc0 100644
>> --- a/arch/x86/include/asm/msr-index.h
>> +++ b/arch/x86/include/asm/msr-index.h
>> @@ -169,6 +169,7 @@
>>    #define LBR_INFO_BR_TYPE		(0xfull << LBR_INFO_BR_TYPE_OFFSET)
>>    
>>    #define MSR_ARCH_LBR_CTL		0x000014ce
>> +#define ARCH_LBR_CTL_MASK		0x7f000e
>>    #define ARCH_LBR_CTL_LBREN		BIT(0)
>>    #define ARCH_LBR_CTL_CPL_OFFSET		1
>>    #define ARCH_LBR_CTL_CPL		(0x3ull << ARCH_LBR_CTL_CPL_OFFSET)
>> diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h
>> index 0ffaa3156a4e..ea3be961cc8e 100644
>> --- a/arch/x86/include/asm/vmx.h
>> +++ b/arch/x86/include/asm/vmx.h
>> @@ -245,6 +245,8 @@ enum vmcs_field {
>>    	GUEST_BNDCFGS_HIGH              = 0x00002813,
>>    	GUEST_IA32_RTIT_CTL		= 0x00002814,
>>    	GUEST_IA32_RTIT_CTL_HIGH	= 0x00002815,
>> +	GUEST_IA32_LBR_CTL		= 0x00002816,
>> +	GUEST_IA32_LBR_CTL_HIGH		= 0x00002817,
>>    	HOST_IA32_PAT			= 0x00002c00,
>>    	HOST_IA32_PAT_HIGH		= 0x00002c01,
>>    	HOST_IA32_EFER			= 0x00002c02,
>> diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
>> index c8e6c1e1e00c..7dc8a5783df7 100644
>> --- a/arch/x86/kvm/vmx/pmu_intel.c
>> +++ b/arch/x86/kvm/vmx/pmu_intel.c
>> @@ -19,6 +19,7 @@
>>    #include "pmu.h"
>>    
>>    #define MSR_PMC_FULL_WIDTH_BIT      (MSR_IA32_PMC0 - MSR_IA32_PERFCTR0)
>> +#define KVM_ARCH_LBR_CTL_MASK  (ARCH_LBR_CTL_MASK | ARCH_LBR_CTL_LBREN)
>>    
>>    static struct kvm_event_hw_type_mapping intel_arch_events[] = {
>>    	[0] = { 0x3c, 0x00, PERF_COUNT_HW_CPU_CYCLES },
>> @@ -215,6 +216,7 @@ static bool intel_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr)
>>    		ret = pmu->version > 1;
>>    		break;
>>    	case MSR_ARCH_LBR_DEPTH:
>> +	case MSR_ARCH_LBR_CTL:
>>    		if (kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR))
>>    			ret = guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR);
>>    		break;
>> @@ -361,6 +363,35 @@ static bool arch_lbr_depth_is_valid(struct kvm_vcpu *vcpu, u64 depth)
>>    	return (depth == pmu->kvm_arch_lbr_depth);
>>    }
>>    
>> +#define ARCH_LBR_CTL_BRN_MASK   GENMASK_ULL(22, 16)
>> +
>> +static bool arch_lbr_ctl_is_valid(struct kvm_vcpu *vcpu, u64 ctl)
>> +{
>> +	struct kvm_cpuid_entry2 *entry;
>> +
>> +	if (!kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR))
>> +		return false;
>> +
>> +	if (ctl & ~KVM_ARCH_LBR_CTL_MASK)
>> +		goto warn;
>> +
>> +	entry = kvm_find_cpuid_entry(vcpu, 0x1c, 0);
>> +	if (!entry)
>> +		return false;
>> +
>> +	if (!(entry->ebx & BIT(0)) && (ctl & ARCH_LBR_CTL_CPL))
>> +		return false;
>> +	if (!(entry->ebx & BIT(2)) && (ctl & ARCH_LBR_CTL_STACK))
>> +		return false;
>> +	if (!(entry->ebx & BIT(1)) && (ctl & ARCH_LBR_CTL_BRN_MASK))
> Why KVM wants to define this mask by itself? Cannot we use the
> ARCH_LBR_CTL_FILTER?

Thanks Ken for review!

Sounds like the ISE has been updated, per section "CPUID for Ach LBRs":

EBX 1 Branch Filtering Supported If set, the processor supports setting 
IA32_LBR_CTL[22:16] to non-zero value.

but the FILTER definition looks like:

#define ARCH_LBR_CTL_FILTER_OFFSET      16

#define ARCH_LBR_CTL_FILTER             (0x7full << 
ARCH_LBR_CTL_FILTER_OFFSET)

Maybe I need to update the FILTER and re-use it.

>
> Thanks,
> Kan
>
>> +		return false;
>> +	return true;
>> +warn:
>> +	pr_warn_ratelimited("kvm: vcpu-%d: invalid arch lbr ctl.\n",
>> +			    vcpu->vcpu_id);
>> +	return false;
>> +}
>> +
>>    static int intel_pmu_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
>>    {
>>    	struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
>> @@ -384,6 +415,9 @@ static int intel_pmu_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
>>    	case MSR_ARCH_LBR_DEPTH:
>>    		msr_info->data = lbr_desc->records.nr;
>>    		return 0;
>> +	case MSR_ARCH_LBR_CTL:
>> +		msr_info->data = vmcs_read64(GUEST_IA32_LBR_CTL);
>> +		return 0;
>>    	default:
>>    		if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)) ||
>>    		    (pmc = get_gp_pmc(pmu, msr, MSR_IA32_PMC0))) {
>> @@ -455,6 +489,16 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
>>    		 */
>>    		wrmsrl(MSR_ARCH_LBR_DEPTH, lbr_desc->records.nr);
>>    		return 0;
>> +	case MSR_ARCH_LBR_CTL:
>> +		if (!arch_lbr_ctl_is_valid(vcpu, data))
>> +			break;
>> +
>> +		vmcs_write64(GUEST_IA32_LBR_CTL, data);
>> +
>> +		if (intel_pmu_lbr_is_enabled(vcpu) && !lbr_desc->event &&
>> +		    (data & ARCH_LBR_CTL_LBREN))
>> +			intel_pmu_create_guest_lbr_event(vcpu);
>> +		return 0;
>>    	default:
>>    		if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)) ||
>>    		    (pmc = get_gp_pmc(pmu, msr, MSR_IA32_PMC0))) {
>> @@ -668,12 +712,16 @@ static void intel_pmu_reset(struct kvm_vcpu *vcpu)
>>     */
>>    static void intel_pmu_legacy_freezing_lbrs_on_pmi(struct kvm_vcpu *vcpu)
>>    {
>> -	u64 data = vmcs_read64(GUEST_IA32_DEBUGCTL);
>> +	u32 lbr_ctl_field = GUEST_IA32_DEBUGCTL;
>>    
>> -	if (data & DEBUGCTLMSR_FREEZE_LBRS_ON_PMI) {
>> -		data &= ~DEBUGCTLMSR_LBR;
>> -		vmcs_write64(GUEST_IA32_DEBUGCTL, data);
>> -	}
>> +	if (!(vmcs_read64(GUEST_IA32_DEBUGCTL) & DEBUGCTLMSR_FREEZE_LBRS_ON_PMI))
>> +		return;
>> +
>> +	if (kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR) &&
>> +	    guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR))
>> +		lbr_ctl_field = GUEST_IA32_LBR_CTL;
>> +
>> +	vmcs_write64(lbr_ctl_field, vmcs_read64(lbr_ctl_field) & ~0x1ULL);
>>    }
>>    
>>    static void intel_pmu_deliver_pmi(struct kvm_vcpu *vcpu)
>> diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
>> index 04d170c4b61e..73961fcfb62d 100644
>> --- a/arch/x86/kvm/vmx/vmx.c
>> +++ b/arch/x86/kvm/vmx/vmx.c
>> @@ -2022,6 +2022,13 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
>>    						VM_EXIT_SAVE_DEBUG_CONTROLS)
>>    			get_vmcs12(vcpu)->guest_ia32_debugctl = data;
>>    
>> +		/*
>> +		 * For Arch LBR, IA32_DEBUGCTL[bit 0] has no meaning.
>> +		 * It can be written to 0 or 1, but reads will always return 0.
>> +		 */
>> +		if (guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR))
>> +			data &= ~DEBUGCTLMSR_LBR;
>> +
>>    		vmcs_write64(GUEST_IA32_DEBUGCTL, data);
>>    		if (intel_pmu_lbr_is_enabled(vcpu) && !to_vmx(vcpu)->lbr_desc.event &&
>>    		    (data & DEBUGCTLMSR_LBR))
>> @@ -4548,6 +4555,11 @@ static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
>>    	kvm_make_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu);
>>    
>>    	vpid_sync_context(vmx->vpid);
>> +
>> +	if (!init_event) {
>> +		if (static_cpu_has(X86_FEATURE_ARCH_LBR))
>> +			vmcs_write64(GUEST_IA32_LBR_CTL, 0);
>> +	}
>>    }
>>    
>>    static void vmx_enable_irq_window(struct kvm_vcpu *vcpu)

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

* Re: [PATCH v10 08/16] KVM: x86/pmu: Refactor code to support guest Arch LBR
  2022-04-28 14:18   ` Liang, Kan
@ 2022-04-29  5:45     ` Yang, Weijiang
  0 siblings, 0 replies; 24+ messages in thread
From: Yang, Weijiang @ 2022-04-29  5:45 UTC (permalink / raw)
  To: Liang, Kan, pbonzini, jmattson, seanjc, like.xu.linux, vkuznets,
	Wang, Wei W, kvm, linux-kernel


On 4/28/2022 10:18 PM, Liang, Kan wrote:
>
> On 4/22/2022 3:55 AM, Yang Weijiang wrote:
>> Take account of Arch LBR when do sanity checks before program
>> vPMU for guest. Pass through Arch LBR recording MSRs to guest
>> to gain better performance. Note, Arch LBR and Legacy LBR support
>> are mutually exclusive, i.e., they're not both available on one
>> platform.
>>
>> Co-developed-by: Like Xu <like.xu@linux.intel.com>
>> Signed-off-by: Like Xu <like.xu@linux.intel.com>
>> Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
>> ---
>>    arch/x86/kvm/vmx/pmu_intel.c | 37 +++++++++++++++++++++++++++++-------
>>    arch/x86/kvm/vmx/vmx.c       |  3 +++
>>    2 files changed, 33 insertions(+), 7 deletions(-)
>>
>> diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
>> index 7dc8a5783df7..cb28888e9f4f 100644
>> --- a/arch/x86/kvm/vmx/pmu_intel.c
>> +++ b/arch/x86/kvm/vmx/pmu_intel.c
>> @@ -170,12 +170,16 @@ static inline struct kvm_pmc *get_fw_gp_pmc(struct kvm_pmu *pmu, u32 msr)
>>    
>>    bool intel_pmu_lbr_is_compatible(struct kvm_vcpu *vcpu)
>>    {
>> +	if (kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR))
>> +		return guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR);
>> +
>>    	/*
>>    	 * As a first step, a guest could only enable LBR feature if its
>>    	 * cpu model is the same as the host because the LBR registers
>>    	 * would be pass-through to the guest and they're model specific.
>>    	 */
>> -	return boot_cpu_data.x86_model == guest_cpuid_model(vcpu);
>> +	return !boot_cpu_has(X86_FEATURE_ARCH_LBR) &&
>> +		boot_cpu_data.x86_model == guest_cpuid_model(vcpu);
>>    }
>>    
>>    bool intel_pmu_lbr_is_enabled(struct kvm_vcpu *vcpu)
>> @@ -193,12 +197,19 @@ static bool intel_pmu_is_valid_lbr_msr(struct kvm_vcpu *vcpu, u32 index)
> I think we should move MSR_ARCH_LBR_DEPTH and MSR_ARCH_LBR_CTL to this
> function as well, since they are LBR related MSRs.
Makes sense, will change it in next version.
>
>>    	if (!intel_pmu_lbr_is_enabled(vcpu))
>>    		return ret;
>>    
>> -	ret = (index == MSR_LBR_SELECT) || (index == MSR_LBR_TOS) ||
>> -		(index >= records->from && index < records->from + records->nr) ||
>> -		(index >= records->to && index < records->to + records->nr);
>> +	if (!guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR))
>> +		ret = (index == MSR_LBR_SELECT) || (index == MSR_LBR_TOS);
>> +
>> +	if (!ret) {
>> +		ret = (index >= records->from &&
>> +		       index < records->from + records->nr) ||
>> +		      (index >= records->to &&
>> +		       index < records->to + records->nr);
>> +	}
>>    
>>    	if (!ret && records->info)
>> -		ret = (index >= records->info && index < records->info + records->nr);
>> +		ret = (index >= records->info &&
>> +		       index < records->info + records->nr);
> Please use "{}" since you split it to two lines.
OK.
>
> Thanks,
> Kan
>>    
>>    	return ret;
>>    }
>> @@ -747,6 +758,9 @@ static void vmx_update_intercept_for_lbr_msrs(struct kvm_vcpu *vcpu, bool set)
>>    			vmx_set_intercept_for_msr(vcpu, lbr->info + i, MSR_TYPE_RW, set);
>>    	}
>>    
>> +	if (guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR))
>> +		return;
>> +
>>    	vmx_set_intercept_for_msr(vcpu, MSR_LBR_SELECT, MSR_TYPE_RW, set);
>>    	vmx_set_intercept_for_msr(vcpu, MSR_LBR_TOS, MSR_TYPE_RW, set);
>>    }
>> @@ -787,10 +801,13 @@ void vmx_passthrough_lbr_msrs(struct kvm_vcpu *vcpu)
>>    {
>>    	struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
>>    	struct lbr_desc *lbr_desc = vcpu_to_lbr_desc(vcpu);
>> +	bool lbr_enable = guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR) ?
>> +		(vmcs_read64(GUEST_IA32_LBR_CTL) & ARCH_LBR_CTL_LBREN) :
>> +		(vmcs_read64(GUEST_IA32_DEBUGCTL) & DEBUGCTLMSR_LBR);
>>    
>>    	if (!lbr_desc->event) {
>>    		vmx_disable_lbr_msrs_passthrough(vcpu);
>> -		if (vmcs_read64(GUEST_IA32_DEBUGCTL) & DEBUGCTLMSR_LBR)
>> +		if (lbr_enable)
>>    			goto warn;
>>    		if (test_bit(INTEL_PMC_IDX_FIXED_VLBR, pmu->pmc_in_use))
>>    			goto warn;
>> @@ -807,13 +824,19 @@ void vmx_passthrough_lbr_msrs(struct kvm_vcpu *vcpu)
>>    	return;
>>    
>>    warn:
>> +	if (kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR))
>> +		wrmsrl(MSR_ARCH_LBR_DEPTH, lbr_desc->records.nr);
>>    	pr_warn_ratelimited("kvm: vcpu-%d: fail to passthrough LBR.\n",
>>    		vcpu->vcpu_id);
>>    }
>>    
>>    static void intel_pmu_cleanup(struct kvm_vcpu *vcpu)
>>    {
>> -	if (!(vmcs_read64(GUEST_IA32_DEBUGCTL) & DEBUGCTLMSR_LBR))
>> +	bool lbr_enable = guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR) ?
>> +		(vmcs_read64(GUEST_IA32_LBR_CTL) & ARCH_LBR_CTL_LBREN) :
>> +		(vmcs_read64(GUEST_IA32_DEBUGCTL) & DEBUGCTLMSR_LBR);
>> +
>> +	if (!lbr_enable)
>>    		intel_pmu_release_guest_lbr_event(vcpu);
>>    }
>>    
>> diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
>> index 73961fcfb62d..a1816c6597f5 100644
>> --- a/arch/x86/kvm/vmx/vmx.c
>> +++ b/arch/x86/kvm/vmx/vmx.c
>> @@ -573,6 +573,9 @@ static bool is_valid_passthrough_msr(u32 msr)
>>    	case MSR_LBR_NHM_TO ... MSR_LBR_NHM_TO + 31:
>>    	case MSR_LBR_CORE_FROM ... MSR_LBR_CORE_FROM + 8:
>>    	case MSR_LBR_CORE_TO ... MSR_LBR_CORE_TO + 8:
>> +	case MSR_ARCH_LBR_FROM_0 ... MSR_ARCH_LBR_FROM_0 + 31:
>> +	case MSR_ARCH_LBR_TO_0 ... MSR_ARCH_LBR_TO_0 + 31:
>> +	case MSR_ARCH_LBR_INFO_0 ... MSR_ARCH_LBR_INFO_0 + 31:
>>    		/* LBR MSRs. These are handled in vmx_update_intercept_for_lbr_msrs() */
>>    		return true;
>>    	}

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

* Re: [PATCH v10 15/16] KVM: x86: Add Arch LBR data MSR access interface
  2022-04-28 15:05   ` Liang, Kan
@ 2022-04-29  6:34     ` Yang, Weijiang
  0 siblings, 0 replies; 24+ messages in thread
From: Yang, Weijiang @ 2022-04-29  6:34 UTC (permalink / raw)
  To: Liang, Kan, pbonzini, jmattson, seanjc, like.xu.linux, vkuznets,
	Wang, Wei W, kvm, linux-kernel


On 4/28/2022 11:05 PM, Liang, Kan wrote:
>
> On 4/22/2022 3:55 AM, Yang Weijiang wrote:
>> Arch LBR MSRs are xsave-supported, but they're operated as "independent"
>> xsave feature by PMU code, i.e., during thread/process context switch,
>> the MSRs are saved/restored with PMU specific code instead of generic
>> kernel fpu XSAVES/XRSTORS operation.
> During thread/process context switch, Linux perf still uses the
> XSAVES/XRSTORS operation to save/restore the LBR MSRs.

I meant Arch LBR MSRs are switched with perf_event_task_sched_out()/

perf_event_task_sched_in() instead of save_fpregs_to_fpstate()/ 
restore_fpregs_from_fpstate().

sorry for the confusion, will modify it a bit.

>
> Linux perf only manipulates these MSRs only when the xsave feature is
> not supported.
Exactly.
>
> Thanks,
> Kan
>
>> When vcpu guest/host fpu state swap
>> happens, Arch LBR MSRs won't be touched so access them directly.
>>
>> Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
>> ---
>>    arch/x86/kvm/vmx/pmu_intel.c | 10 ++++++++++
>>    1 file changed, 10 insertions(+)
>>
>> diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
>> index 79eecbffa07b..5f81644c4612 100644
>> --- a/arch/x86/kvm/vmx/pmu_intel.c
>> +++ b/arch/x86/kvm/vmx/pmu_intel.c
>> @@ -431,6 +431,11 @@ static int intel_pmu_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
>>    	case MSR_ARCH_LBR_CTL:
>>    		msr_info->data = vmcs_read64(GUEST_IA32_LBR_CTL);
>>    		return 0;
>> +	case MSR_ARCH_LBR_FROM_0 ... MSR_ARCH_LBR_FROM_0 + 31:
>> +	case MSR_ARCH_LBR_TO_0 ... MSR_ARCH_LBR_TO_0 + 31:
>> +	case MSR_ARCH_LBR_INFO_0 ... MSR_ARCH_LBR_INFO_0 + 31:
>> +		rdmsrl(msr_info->index, msr_info->data);
>> +		return 0;
>>    	default:
>>    		if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)) ||
>>    		    (pmc = get_gp_pmc(pmu, msr, MSR_IA32_PMC0))) {
>> @@ -512,6 +517,11 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
>>    		    (data & ARCH_LBR_CTL_LBREN))
>>    			intel_pmu_create_guest_lbr_event(vcpu);
>>    		return 0;
>> +	case MSR_ARCH_LBR_FROM_0 ... MSR_ARCH_LBR_FROM_0 + 31:
>> +	case MSR_ARCH_LBR_TO_0 ... MSR_ARCH_LBR_TO_0 + 31:
>> +	case MSR_ARCH_LBR_INFO_0 ... MSR_ARCH_LBR_INFO_0 + 31:
>> +		wrmsrl(msr_info->index, msr_info->data);
>> +		return 0;
>>    	default:
>>    		if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)) ||
>>    		    (pmc = get_gp_pmc(pmu, msr, MSR_IA32_PMC0))) {

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

* Re: [PATCH v10 07/16] KVM: vmx/pmu: Emulate MSR_ARCH_LBR_CTL for guest Arch LBR
  2022-04-29  3:20     ` Yang, Weijiang
@ 2022-04-29  8:19       ` Yang, Weijiang
  0 siblings, 0 replies; 24+ messages in thread
From: Yang, Weijiang @ 2022-04-29  8:19 UTC (permalink / raw)
  To: Liang, Kan, pbonzini, jmattson, seanjc, like.xu.linux, vkuznets,
	Wang, Wei W, kvm, linux-kernel


On 4/29/2022 11:20 AM, Yang, Weijiang wrote:
>
> On 4/28/2022 10:16 PM, Liang, Kan wrote:
>>
>> On 4/22/2022 3:55 AM, Yang Weijiang wrote:
>>> From: Like Xu <like.xu@linux.intel.com>
>>>
>>> Arch LBR is enabled by setting MSR_ARCH_LBR_CTL.LBREn to 1. A new guest
>>> state field named "Guest IA32_LBR_CTL" is added to enhance guest LBR 
>>> usage.
>>> When guest Arch LBR is enabled, a guest LBR event will be created 
>>> like the
>>> model-specific LBR does. Clear guest LBR enable bit on host PMI 
>>> handling so
>>> guest can see expected config.
>>>
>>> On processors that support Arch LBR, MSR_IA32_DEBUGCTLMSR[bit 0] has no
>>> meaning. It can be written to 0 or 1, but reads will always return 0.
>>> Like IA32_DEBUGCTL, IA32_ARCH_LBR_CTL msr is also preserved on INIT.
>>>
>>> Regardless of the Arch LBR or legacy LBR, when the LBR_EN bit 0 of the
>>> corresponding control MSR is set to 1, LBR recording will be enabled.
>>>
>>> Signed-off-by: Like Xu <like.xu@linux.intel.com>
>>> Co-developed-by: Yang Weijiang <weijiang.yang@intel.com>
>>> Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
>>> ---
>>>    arch/x86/events/intel/lbr.c      |  2 --
>>>    arch/x86/include/asm/msr-index.h |  1 +
>>>    arch/x86/include/asm/vmx.h       |  2 ++
>>>    arch/x86/kvm/vmx/pmu_intel.c     | 58 
>>> +++++++++++++++++++++++++++++---
>>>    arch/x86/kvm/vmx/vmx.c           | 12 +++++++
>>>    5 files changed, 68 insertions(+), 7 deletions(-)
>>>
>>> diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c
>>> index 4529ce448b2e..4fe6c3b50fc3 100644
>>> --- a/arch/x86/events/intel/lbr.c
>>> +++ b/arch/x86/events/intel/lbr.c
>>> @@ -160,8 +160,6 @@ enum {
>>>         ARCH_LBR_RETURN        |\
>>>         ARCH_LBR_OTHER_BRANCH)
>>>    -#define ARCH_LBR_CTL_MASK            0x7f000e
>>> -
>>>    static void intel_pmu_lbr_filter(struct cpu_hw_events *cpuc);
>>>       static __always_inline bool is_lbr_call_stack_bit_set(u64 config)
>>> diff --git a/arch/x86/include/asm/msr-index.h 
>>> b/arch/x86/include/asm/msr-index.h
>>> index 0eb90d21049e..60e0ab108dc0 100644
>>> --- a/arch/x86/include/asm/msr-index.h
>>> +++ b/arch/x86/include/asm/msr-index.h
>>> @@ -169,6 +169,7 @@
>>>    #define LBR_INFO_BR_TYPE        (0xfull << LBR_INFO_BR_TYPE_OFFSET)
>>>       #define MSR_ARCH_LBR_CTL        0x000014ce
>>> +#define ARCH_LBR_CTL_MASK        0x7f000e
>>>    #define ARCH_LBR_CTL_LBREN        BIT(0)
>>>    #define ARCH_LBR_CTL_CPL_OFFSET        1
>>>    #define ARCH_LBR_CTL_CPL        (0x3ull << ARCH_LBR_CTL_CPL_OFFSET)
>>> diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h
>>> index 0ffaa3156a4e..ea3be961cc8e 100644
>>> --- a/arch/x86/include/asm/vmx.h
>>> +++ b/arch/x86/include/asm/vmx.h
>>> @@ -245,6 +245,8 @@ enum vmcs_field {
>>>        GUEST_BNDCFGS_HIGH              = 0x00002813,
>>>        GUEST_IA32_RTIT_CTL        = 0x00002814,
>>>        GUEST_IA32_RTIT_CTL_HIGH    = 0x00002815,
>>> +    GUEST_IA32_LBR_CTL        = 0x00002816,
>>> +    GUEST_IA32_LBR_CTL_HIGH        = 0x00002817,
>>>        HOST_IA32_PAT            = 0x00002c00,
>>>        HOST_IA32_PAT_HIGH        = 0x00002c01,
>>>        HOST_IA32_EFER            = 0x00002c02,
>>> diff --git a/arch/x86/kvm/vmx/pmu_intel.c 
>>> b/arch/x86/kvm/vmx/pmu_intel.c
>>> index c8e6c1e1e00c..7dc8a5783df7 100644
>>> --- a/arch/x86/kvm/vmx/pmu_intel.c
>>> +++ b/arch/x86/kvm/vmx/pmu_intel.c
>>> @@ -19,6 +19,7 @@
>>>    #include "pmu.h"
>>>       #define MSR_PMC_FULL_WIDTH_BIT      (MSR_IA32_PMC0 - 
>>> MSR_IA32_PERFCTR0)
>>> +#define KVM_ARCH_LBR_CTL_MASK  (ARCH_LBR_CTL_MASK | 
>>> ARCH_LBR_CTL_LBREN)
>>>       static struct kvm_event_hw_type_mapping intel_arch_events[] = {
>>>        [0] = { 0x3c, 0x00, PERF_COUNT_HW_CPU_CYCLES },
>>> @@ -215,6 +216,7 @@ static bool intel_is_valid_msr(struct kvm_vcpu 
>>> *vcpu, u32 msr)
>>>            ret = pmu->version > 1;
>>>            break;
>>>        case MSR_ARCH_LBR_DEPTH:
>>> +    case MSR_ARCH_LBR_CTL:
>>>            if (kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR))
>>>                ret = guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR);
>>>            break;
>>> @@ -361,6 +363,35 @@ static bool arch_lbr_depth_is_valid(struct 
>>> kvm_vcpu *vcpu, u64 depth)
>>>        return (depth == pmu->kvm_arch_lbr_depth);
>>>    }
>>>    +#define ARCH_LBR_CTL_BRN_MASK   GENMASK_ULL(22, 16)
>>> +
>>> +static bool arch_lbr_ctl_is_valid(struct kvm_vcpu *vcpu, u64 ctl)
>>> +{
>>> +    struct kvm_cpuid_entry2 *entry;
>>> +
>>> +    if (!kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR))
>>> +        return false;
>>> +
>>> +    if (ctl & ~KVM_ARCH_LBR_CTL_MASK)
>>> +        goto warn;
>>> +
>>> +    entry = kvm_find_cpuid_entry(vcpu, 0x1c, 0);
>>> +    if (!entry)
>>> +        return false;
>>> +
>>> +    if (!(entry->ebx & BIT(0)) && (ctl & ARCH_LBR_CTL_CPL))
>>> +        return false;
>>> +    if (!(entry->ebx & BIT(2)) && (ctl & ARCH_LBR_CTL_STACK))
>>> +        return false;
>>> +    if (!(entry->ebx & BIT(1)) && (ctl & ARCH_LBR_CTL_BRN_MASK))
>> Why KVM wants to define this mask by itself? Cannot we use the
>> ARCH_LBR_CTL_FILTER?
>
> Thanks Ken for review!
Please ignore below reply, I must be blind at the moment :-), will use 
the existing mask.
>
> Sounds like the ISE has been updated, per section "CPUID for Ach LBRs":
>
> EBX 1 Branch Filtering Supported If set, the processor supports 
> setting IA32_LBR_CTL[22:16] to non-zero value.
>
> but the FILTER definition looks like:
>
> #define ARCH_LBR_CTL_FILTER_OFFSET      16
>
> #define ARCH_LBR_CTL_FILTER             (0x7full << 
> ARCH_LBR_CTL_FILTER_OFFSET)
>
> Maybe I need to update the FILTER and re-use it.
>
>>
>> Thanks,
>> Kan
>>
>>> +        return false;
>>> +    return true;
>>> +warn:
>>> +    pr_warn_ratelimited("kvm: vcpu-%d: invalid arch lbr ctl.\n",
>>> +                vcpu->vcpu_id);
>>> +    return false;
>>> +}
>>> +
>>>    static int intel_pmu_get_msr(struct kvm_vcpu *vcpu, struct 
>>> msr_data *msr_info)
>>>    {
>>>        struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
>>> @@ -384,6 +415,9 @@ static int intel_pmu_get_msr(struct kvm_vcpu 
>>> *vcpu, struct msr_data *msr_info)
>>>        case MSR_ARCH_LBR_DEPTH:
>>>            msr_info->data = lbr_desc->records.nr;
>>>            return 0;
>>> +    case MSR_ARCH_LBR_CTL:
>>> +        msr_info->data = vmcs_read64(GUEST_IA32_LBR_CTL);
>>> +        return 0;
>>>        default:
>>>            if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)) ||
>>>                (pmc = get_gp_pmc(pmu, msr, MSR_IA32_PMC0))) {
>>> @@ -455,6 +489,16 @@ static int intel_pmu_set_msr(struct kvm_vcpu 
>>> *vcpu, struct msr_data *msr_info)
>>>             */
>>>            wrmsrl(MSR_ARCH_LBR_DEPTH, lbr_desc->records.nr);
>>>            return 0;
>>> +    case MSR_ARCH_LBR_CTL:
>>> +        if (!arch_lbr_ctl_is_valid(vcpu, data))
>>> +            break;
>>> +
>>> +        vmcs_write64(GUEST_IA32_LBR_CTL, data);
>>> +
>>> +        if (intel_pmu_lbr_is_enabled(vcpu) && !lbr_desc->event &&
>>> +            (data & ARCH_LBR_CTL_LBREN))
>>> +            intel_pmu_create_guest_lbr_event(vcpu);
>>> +        return 0;
>>>        default:
>>>            if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)) ||
>>>                (pmc = get_gp_pmc(pmu, msr, MSR_IA32_PMC0))) {
>>> @@ -668,12 +712,16 @@ static void intel_pmu_reset(struct kvm_vcpu 
>>> *vcpu)
>>>     */
>>>    static void intel_pmu_legacy_freezing_lbrs_on_pmi(struct kvm_vcpu 
>>> *vcpu)
>>>    {
>>> -    u64 data = vmcs_read64(GUEST_IA32_DEBUGCTL);
>>> +    u32 lbr_ctl_field = GUEST_IA32_DEBUGCTL;
>>>    -    if (data & DEBUGCTLMSR_FREEZE_LBRS_ON_PMI) {
>>> -        data &= ~DEBUGCTLMSR_LBR;
>>> -        vmcs_write64(GUEST_IA32_DEBUGCTL, data);
>>> -    }
>>> +    if (!(vmcs_read64(GUEST_IA32_DEBUGCTL) & 
>>> DEBUGCTLMSR_FREEZE_LBRS_ON_PMI))
>>> +        return;
>>> +
>>> +    if (kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR) &&
>>> +        guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR))
>>> +        lbr_ctl_field = GUEST_IA32_LBR_CTL;
>>> +
>>> +    vmcs_write64(lbr_ctl_field, vmcs_read64(lbr_ctl_field) & ~0x1ULL);
>>>    }
>>>       static void intel_pmu_deliver_pmi(struct kvm_vcpu *vcpu)
>>> diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
>>> index 04d170c4b61e..73961fcfb62d 100644
>>> --- a/arch/x86/kvm/vmx/vmx.c
>>> +++ b/arch/x86/kvm/vmx/vmx.c
>>> @@ -2022,6 +2022,13 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, 
>>> struct msr_data *msr_info)
>>>                            VM_EXIT_SAVE_DEBUG_CONTROLS)
>>>                get_vmcs12(vcpu)->guest_ia32_debugctl = data;
>>>    +        /*
>>> +         * For Arch LBR, IA32_DEBUGCTL[bit 0] has no meaning.
>>> +         * It can be written to 0 or 1, but reads will always 
>>> return 0.
>>> +         */
>>> +        if (guest_cpuid_has(vcpu, X86_FEATURE_ARCH_LBR))
>>> +            data &= ~DEBUGCTLMSR_LBR;
>>> +
>>>            vmcs_write64(GUEST_IA32_DEBUGCTL, data);
>>>            if (intel_pmu_lbr_is_enabled(vcpu) && 
>>> !to_vmx(vcpu)->lbr_desc.event &&
>>>                (data & DEBUGCTLMSR_LBR))
>>> @@ -4548,6 +4555,11 @@ static void vmx_vcpu_reset(struct kvm_vcpu 
>>> *vcpu, bool init_event)
>>>        kvm_make_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu);
>>>           vpid_sync_context(vmx->vpid);
>>> +
>>> +    if (!init_event) {
>>> +        if (static_cpu_has(X86_FEATURE_ARCH_LBR))
>>> +            vmcs_write64(GUEST_IA32_LBR_CTL, 0);
>>> +    }
>>>    }
>>>       static void vmx_enable_irq_window(struct kvm_vcpu *vcpu)

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

end of thread, other threads:[~2022-04-29  8:20 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-22  7:54 [PATCH v10 00/16] Introduce Architectural LBR for vPMU Yang Weijiang
2022-04-22  7:54 ` [PATCH v10 01/16] KVM: x86: Report XSS as an MSR to be saved if there are supported features Yang Weijiang
2022-04-22  7:54 ` [PATCH v10 02/16] KVM: x86: Refresh CPUID on writes to MSR_IA32_XSS Yang Weijiang
2022-04-22  7:54 ` [PATCH v10 03/16] perf/x86/intel: Fix the comment about guest LBR support on KVM Yang Weijiang
2022-04-22  7:54 ` [PATCH v10 04/16] perf/x86/lbr: Simplify the exposure check for the LBR_INFO registers Yang Weijiang
2022-04-22  7:54 ` [PATCH v10 05/16] KVM: x86: Add Arch LBR MSRs to msrs_to_save_all list Yang Weijiang
2022-04-22  7:54 ` [PATCH v10 06/16] KVM: vmx/pmu: Emulate MSR_ARCH_LBR_DEPTH for guest Arch LBR Yang Weijiang
2022-04-22  7:55 ` [PATCH v10 07/16] KVM: vmx/pmu: Emulate MSR_ARCH_LBR_CTL " Yang Weijiang
2022-04-28 14:16   ` Liang, Kan
2022-04-29  3:20     ` Yang, Weijiang
2022-04-29  8:19       ` Yang, Weijiang
2022-04-22  7:55 ` [PATCH v10 08/16] KVM: x86/pmu: Refactor code to support " Yang Weijiang
2022-04-28 14:18   ` Liang, Kan
2022-04-29  5:45     ` Yang, Weijiang
2022-04-22  7:55 ` [PATCH v10 09/16] KVM: x86: Refine the matching and clearing logic for supported_xss Yang Weijiang
2022-04-22  7:55 ` [PATCH v10 10/16] KVM: x86: Add XSAVE Support for Architectural LBR Yang Weijiang
2022-04-22  7:55 ` [PATCH v10 11/16] KVM: x86/vmx: Check Arch LBR config when return perf capabilities Yang Weijiang
2022-04-22  7:55 ` [PATCH v10 12/16] KVM: nVMX: Add necessary Arch LBR settings for nested VM Yang Weijiang
2022-04-22  7:55 ` [PATCH v10 13/16] KVM: x86/vmx: Clear Arch LBREn bit before inject #DB to guest Yang Weijiang
2022-04-22  7:55 ` [PATCH v10 14/16] KVM: x86/vmx: Flip Arch LBREn bit on guest state change Yang Weijiang
2022-04-22  7:55 ` [PATCH v10 15/16] KVM: x86: Add Arch LBR data MSR access interface Yang Weijiang
2022-04-28 15:05   ` Liang, Kan
2022-04-29  6:34     ` Yang, Weijiang
2022-04-22  7:55 ` [PATCH v10 16/16] KVM: x86/cpuid: Advertise Arch LBR feature in CPUID Yang Weijiang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.