Skip to content

Commit a2b00f8

Browse files
Fred Griffoulsean-jc
authored andcommitted
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. Signed-off-by: Fred Griffoul <fgriffo@amazon.co.uk> Reviewed-by: Paul Durrant <paul@xen.org> Reviewed-by: David Woodhouse <dwmw@amazon.co.uk> Link: https://lore.kernel.org/r/20250124150539.69975-1-fgriffo@amazon.co.uk Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent 26e228e commit a2b00f8

File tree

5 files changed

+29
-27
lines changed

5 files changed

+29
-27
lines changed

arch/x86/kvm/cpuid.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2006,6 +2006,22 @@ bool kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx,
20062006
} else if (function == 0x80000007) {
20072007
if (kvm_hv_invtsc_suppressed(vcpu))
20082008
*edx &= ~feature_bit(CONSTANT_TSC);
2009+
} else if (IS_ENABLED(CONFIG_KVM_XEN) &&
2010+
kvm_xen_is_tsc_leaf(vcpu, function)) {
2011+
/*
2012+
* Update guest TSC frequency information if necessary.
2013+
* Ignore failures, there is no sane value that can be
2014+
* provided if KVM can't get the TSC frequency.
2015+
*/
2016+
if (kvm_check_request(KVM_REQ_CLOCK_UPDATE, vcpu))
2017+
kvm_guest_time_update(vcpu);
2018+
2019+
if (index == 1) {
2020+
*ecx = vcpu->arch.hv_clock.tsc_to_system_mul;
2021+
*edx = vcpu->arch.hv_clock.tsc_shift;
2022+
} else if (index == 2) {
2023+
*eax = vcpu->arch.hw_tsc_khz;
2024+
}
20092025
}
20102026
} else {
20112027
*eax = *ebx = *ecx = *edx = 0;

arch/x86/kvm/x86.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3170,7 +3170,7 @@ static void kvm_setup_guest_pvclock(struct kvm_vcpu *v,
31703170
trace_kvm_pvclock_update(v->vcpu_id, &vcpu->hv_clock);
31713171
}
31723172

3173-
static int kvm_guest_time_update(struct kvm_vcpu *v)
3173+
int kvm_guest_time_update(struct kvm_vcpu *v)
31743174
{
31753175
unsigned long flags, tgt_tsc_khz;
31763176
unsigned seq;
@@ -3253,7 +3253,6 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
32533253
&vcpu->hv_clock.tsc_shift,
32543254
&vcpu->hv_clock.tsc_to_system_mul);
32553255
vcpu->hw_tsc_khz = tgt_tsc_khz;
3256-
kvm_xen_update_tsc_info(v);
32573256
}
32583257

32593258
vcpu->hv_clock.tsc_timestamp = tsc_timestamp;

arch/x86/kvm/x86.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,7 @@ void kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq, int inc_eip);
362362
u64 get_kvmclock_ns(struct kvm *kvm);
363363
uint64_t kvm_get_wall_clock_epoch(struct kvm *kvm);
364364
bool kvm_get_monotonic_and_clockread(s64 *kernel_ns, u64 *tsc_timestamp);
365+
int kvm_guest_time_update(struct kvm_vcpu *v);
365366

366367
int kvm_read_guest_virt(struct kvm_vcpu *vcpu,
367368
gva_t addr, void *val, unsigned int bytes,

arch/x86/kvm/xen.c

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2256,29 +2256,6 @@ void kvm_xen_destroy_vcpu(struct kvm_vcpu *vcpu)
22562256
del_timer_sync(&vcpu->arch.xen.poll_timer);
22572257
}
22582258

2259-
void kvm_xen_update_tsc_info(struct kvm_vcpu *vcpu)
2260-
{
2261-
struct kvm_cpuid_entry2 *entry;
2262-
u32 function;
2263-
2264-
if (!vcpu->arch.xen.cpuid.base)
2265-
return;
2266-
2267-
function = vcpu->arch.xen.cpuid.base | XEN_CPUID_LEAF(3);
2268-
if (function > vcpu->arch.xen.cpuid.limit)
2269-
return;
2270-
2271-
entry = kvm_find_cpuid_entry_index(vcpu, function, 1);
2272-
if (entry) {
2273-
entry->ecx = vcpu->arch.hv_clock.tsc_to_system_mul;
2274-
entry->edx = vcpu->arch.hv_clock.tsc_shift;
2275-
}
2276-
2277-
entry = kvm_find_cpuid_entry_index(vcpu, function, 2);
2278-
if (entry)
2279-
entry->eax = vcpu->arch.hw_tsc_khz;
2280-
}
2281-
22822259
void kvm_xen_init_vm(struct kvm *kvm)
22832260
{
22842261
mutex_init(&kvm->arch.xen.xen_lock);

arch/x86/kvm/xen.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#ifndef __ARCH_X86_KVM_XEN_H__
1010
#define __ARCH_X86_KVM_XEN_H__
1111

12+
#include <asm/xen/cpuid.h>
1213
#include <asm/xen/hypervisor.h>
1314

1415
#ifdef CONFIG_KVM_XEN
@@ -35,7 +36,6 @@ int kvm_xen_set_evtchn_fast(struct kvm_xen_evtchn *xe,
3536
int kvm_xen_setup_evtchn(struct kvm *kvm,
3637
struct kvm_kernel_irq_routing_entry *e,
3738
const struct kvm_irq_routing_entry *ue);
38-
void kvm_xen_update_tsc_info(struct kvm_vcpu *vcpu);
3939

4040
static inline void kvm_xen_sw_enable_lapic(struct kvm_vcpu *vcpu)
4141
{
@@ -50,6 +50,14 @@ static inline void kvm_xen_sw_enable_lapic(struct kvm_vcpu *vcpu)
5050
kvm_xen_inject_vcpu_vector(vcpu);
5151
}
5252

53+
static inline bool kvm_xen_is_tsc_leaf(struct kvm_vcpu *vcpu, u32 function)
54+
{
55+
return static_branch_unlikely(&kvm_xen_enabled.key) &&
56+
vcpu->arch.xen.cpuid.base &&
57+
function <= vcpu->arch.xen.cpuid.limit &&
58+
function == (vcpu->arch.xen.cpuid.base | XEN_CPUID_LEAF(3));
59+
}
60+
5361
static inline bool kvm_xen_msr_enabled(struct kvm *kvm)
5462
{
5563
return static_branch_unlikely(&kvm_xen_enabled.key) &&
@@ -170,8 +178,9 @@ static inline bool kvm_xen_timer_enabled(struct kvm_vcpu *vcpu)
170178
return false;
171179
}
172180

173-
static inline void kvm_xen_update_tsc_info(struct kvm_vcpu *vcpu)
181+
static inline bool kvm_xen_is_tsc_leaf(struct kvm_vcpu *vcpu, u32 function)
174182
{
183+
return false;
175184
}
176185
#endif
177186

0 commit comments

Comments
 (0)