[PATCH 2/8] KVM: x86/pmu: Add PMU ops for vendor state sync

Sandipan Das <[email protected]>
Newsgroups org.kernel.vger.kvm
Message-ID <97458b49f1ba443345e13868db0115fd0249b5aa.1786345201.git.sandipan.das@amd.com>
When hardware-switched mediated PMU is enabled, the guest PMU state
resides in a vendor save area. Because of this, after every VMEXIT,
the state inside struct kvm_pmu can go out of sync with the vendor
save area. Since KVM expects struct kvm_pmu to have the correct guest
PMU state during event filtering and instruction emulation, introduce
new PMU ops to opportunistically synchronize the state of PMU MSRs
between the two backing stores.

The new ops are directional. get_vendor_state() copies data from the
vendor save area to the corresponding member of struct kvm_pmu while
set_vendor_state() does the opposite.

Signed-off-by: Sandipan Das <[email protected]>
---
 arch/x86/include/asm/kvm-x86-pmu-ops.h | 3 +++
 arch/x86/kvm/pmu.c                     | 5 ++++-
 arch/x86/kvm/pmu.h                     | 2 ++
 3 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/kvm-x86-pmu-ops.h b/arch/x86/include/asm/kvm-x86-pmu-ops.h
index 4a223c2793e3..4a617162d4c0 100644
--- a/arch/x86/include/asm/kvm-x86-pmu-ops.h
+++ b/arch/x86/include/asm/kvm-x86-pmu-ops.h
@@ -29,6 +29,9 @@ KVM_X86_PMU_OP_OPTIONAL_RET0(pmc_is_disabled_in_current_mode)
 KVM_X86_PMU_OP_OPTIONAL(write_global_ctrl)
 KVM_X86_PMU_OP(mediated_load)
 KVM_X86_PMU_OP(mediated_put)
+
+KVM_X86_PMU_OP_OPTIONAL_RET0(get_vendor_state)
+KVM_X86_PMU_OP_OPTIONAL_RET0(set_vendor_state)
 #endif
 
 #undef KVM_X86_PMU_OP
diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
index a7d60c8785cd..5ede3ee968e3 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
@@ -166,8 +166,11 @@ void kvm_init_pmu_capability(struct kvm_pmu_ops *pmu_ops)
 	    !pmu_ops->is_mediated_pmu_supported(&kvm_host_pmu))
 		enable_mediated_pmu = false;
 
-	if (!enable_mediated_pmu)
+	if (!enable_mediated_pmu) {
 		pmu_ops->write_global_ctrl = NULL;
+		pmu_ops->get_vendor_state = NULL;
+		pmu_ops->set_vendor_state = NULL;
+	}
 
 	if (!enable_pmu) {
 		memset(&kvm_pmu_cap, 0, sizeof(kvm_pmu_cap));
diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h
index 1aa46d3e2339..5d6f6863ad40 100644
--- a/arch/x86/kvm/pmu.h
+++ b/arch/x86/kvm/pmu.h
@@ -42,6 +42,8 @@ struct kvm_pmu_ops {
 	void (*mediated_load)(struct kvm_vcpu *vcpu);
 	void (*mediated_put)(struct kvm_vcpu *vcpu);
 	void (*write_global_ctrl)(u64 global_ctrl);
+	int (*get_vendor_state)(struct kvm_vcpu *vcpu, u32 msr);
+	int (*set_vendor_state)(struct kvm_vcpu *vcpu, u32 msr);
 
 	const u64 EVENTSEL_EVENT;
 	const int MAX_NR_GP_COUNTERS;
-- 
2.53.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.