[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250123190253.25891-1-fgriffo@amazon.co.uk>
Date: Thu, 23 Jan 2025 19:02:53 +0000
From: Fred Griffoul <fgriffo@...zon.co.uk>
To: <kvm@...r.kernel.org>
CC: <griffoul@...il.com>, <vkuznets@...hat.com>, Fred Griffoul
<fgriffo@...zon.co.uk>, Sean Christopherson <seanjc@...gle.com>, "Paolo
Bonzini" <pbonzini@...hat.com>, Thomas Gleixner <tglx@...utronix.de>, "Ingo
Molnar" <mingo@...hat.com>, Borislav Petkov <bp@...en8.de>, Dave Hansen
<dave.hansen@...ux.intel.com>, <x86@...nel.org>, "H. Peter Anvin"
<hpa@...or.com>, David Woodhouse <dwmw2@...radead.org>, Paul Durrant
<paul@....org>, <linux-kernel@...r.kernel.org>
Subject: [PATCH] KVM: x86: Update Xen TSC leaves during CPUID emulation
The Xen emulation in KVM modifies certain CPUID leaves to expose
TSC information to the guest.
Previously, these CPUID leaves were updated whenever guest time changed,
but this conflicts with KVM_SET_CPUID/KVM_SET_CPUID2 ioctls which reject
changes to CPUID entries on running vCPUs.
Fix this by updating the TSC information directly in the CPUID emulation
handler instead of modifying the vCPU's CPUID entries.
Suggested-by: Sean Christopherson <seanjc@...gle.com>
Signed-off-by: Fred Griffoul <fgriffo@...zon.co.uk>
---
arch/x86/kvm/cpuid.c | 3 ++-
arch/x86/kvm/x86.c | 1 -
arch/x86/kvm/xen.c | 24 ------------------------
arch/x86/kvm/xen.h | 21 +++++++++++++++++++--
4 files changed, 21 insertions(+), 28 deletions(-)
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index edef30359c19..77f50273d902 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -2005,7 +2005,8 @@ bool kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx,
} else if (function == 0x80000007) {
if (kvm_hv_invtsc_suppressed(vcpu))
*edx &= ~feature_bit(CONSTANT_TSC);
- }
+ } else
+ kvm_xen_may_update_tsc_info(vcpu, function, index, eax, ecx, edx);
} else {
*eax = *ebx = *ecx = *edx = 0;
/*
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index b2d9a16fd4d3..2e4aaa028238 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3253,7 +3253,6 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
&vcpu->hv_clock.tsc_shift,
&vcpu->hv_clock.tsc_to_system_mul);
vcpu->hw_tsc_khz = tgt_tsc_khz;
- kvm_xen_update_tsc_info(v);
}
vcpu->hv_clock.tsc_timestamp = tsc_timestamp;
diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
index a909b817b9c0..f5d1c8132bec 100644
--- a/arch/x86/kvm/xen.c
+++ b/arch/x86/kvm/xen.c
@@ -23,7 +23,6 @@
#include <xen/interface/event_channel.h>
#include <xen/interface/sched.h>
-#include <asm/xen/cpuid.h>
#include <asm/pvclock.h>
#include "cpuid.h"
@@ -2247,29 +2246,6 @@ void kvm_xen_destroy_vcpu(struct kvm_vcpu *vcpu)
del_timer_sync(&vcpu->arch.xen.poll_timer);
}
-void kvm_xen_update_tsc_info(struct kvm_vcpu *vcpu)
-{
- struct kvm_cpuid_entry2 *entry;
- u32 function;
-
- if (!vcpu->arch.xen.cpuid.base)
- return;
-
- function = vcpu->arch.xen.cpuid.base | XEN_CPUID_LEAF(3);
- if (function > vcpu->arch.xen.cpuid.limit)
- return;
-
- entry = kvm_find_cpuid_entry_index(vcpu, function, 1);
- if (entry) {
- entry->ecx = vcpu->arch.hv_clock.tsc_to_system_mul;
- entry->edx = vcpu->arch.hv_clock.tsc_shift;
- }
-
- entry = kvm_find_cpuid_entry_index(vcpu, function, 2);
- if (entry)
- entry->eax = vcpu->arch.hw_tsc_khz;
-}
-
void kvm_xen_init_vm(struct kvm *kvm)
{
mutex_init(&kvm->arch.xen.xen_lock);
diff --git a/arch/x86/kvm/xen.h b/arch/x86/kvm/xen.h
index f5841d9000ae..03ee7d28519a 100644
--- a/arch/x86/kvm/xen.h
+++ b/arch/x86/kvm/xen.h
@@ -10,6 +10,7 @@
#define __ARCH_X86_KVM_XEN_H__
#include <asm/xen/hypervisor.h>
+#include <asm/xen/cpuid.h>
#ifdef CONFIG_KVM_XEN
#include <linux/jump_label_ratelimit.h>
@@ -35,7 +36,6 @@ int kvm_xen_set_evtchn_fast(struct kvm_xen_evtchn *xe,
int kvm_xen_setup_evtchn(struct kvm *kvm,
struct kvm_kernel_irq_routing_entry *e,
const struct kvm_irq_routing_entry *ue);
-void kvm_xen_update_tsc_info(struct kvm_vcpu *vcpu);
static inline void kvm_xen_sw_enable_lapic(struct kvm_vcpu *vcpu)
{
@@ -92,6 +92,21 @@ static inline int kvm_xen_has_pending_timer(struct kvm_vcpu *vcpu)
return 0;
}
+static inline void kvm_xen_may_update_tsc_info(struct kvm_vcpu *vcpu,
+ u32 function, u32 index,
+ u32 *eax, u32 *ecx, u32 *edx)
+{
+ u32 base = vcpu->arch.xen.cpuid.base;
+
+ if (base && (function == (base | XEN_CPUID_LEAF(3)))) {
+ if (index == 1) {
+ *ecx = vcpu->arch.hv_clock.tsc_to_system_mul;
+ *edx = vcpu->arch.hv_clock.tsc_shift;
+ } else if (index == 2)
+ *eax = vcpu->arch.hw_tsc_khz;
+ }
+}
+
void kvm_xen_inject_timer_irqs(struct kvm_vcpu *vcpu);
#else
static inline int kvm_xen_write_hypercall_page(struct kvm_vcpu *vcpu, u64 data)
@@ -157,7 +172,9 @@ static inline bool kvm_xen_timer_enabled(struct kvm_vcpu *vcpu)
return false;
}
-static inline void kvm_xen_update_tsc_info(struct kvm_vcpu *vcpu)
+static inline void kvm_xen_may_update_tsc_info(struct kvm_vcpu *vcpu,
+ u32 function, u32 index,
+ u32 *eax, u32 *ecx, u32 *edx)
{
}
#endif
--
2.40.1
Powered by blists - more mailing lists