Skip to content

Commit 39d61b4

Browse files
committed
KVM: x86: Remove per-vCPU "cache" of its reference pvclock
Remove the per-vCPU "cache" of the reference pvclock and instead cache only the TSC shift+multiplier. All other fields in pvclock are fully recomputed by kvm_guest_time_update(), i.e. aren't actually persisted. In addition to shaving a few bytes, explicitly tracking the TSC shift/mul fields makes it easier to see that those fields are tied to hw_tsc_khz (they exist to avoid having to do expensive math in the common case). And conversely, not tracking the other fields makes it easier to see that things like the version number are pulled from the guest's copy, not from KVM's reference. Reviewed-by: Paul Durrant <paul@xen.org> Link: https://lore.kernel.org/r/20250201013827.680235-10-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent 46aed4d commit 39d61b4

File tree

3 files changed

+21
-17
lines changed

3 files changed

+21
-17
lines changed

arch/x86/include/asm/kvm_host.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -908,7 +908,8 @@ struct kvm_vcpu_arch {
908908
int (*complete_userspace_io)(struct kvm_vcpu *vcpu);
909909

910910
gpa_t time;
911-
struct pvclock_vcpu_time_info hv_clock;
911+
s8 pvclock_tsc_shift;
912+
u32 pvclock_tsc_mul;
912913
unsigned int hw_tsc_khz;
913914
struct gfn_to_pfn_cache pv_time;
914915
/* set guest stopped flag in pvclock flags field */

arch/x86/kvm/x86.c

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3170,6 +3170,7 @@ static void kvm_setup_guest_pvclock(struct pvclock_vcpu_time_info *ref_hv_clock,
31703170

31713171
static int kvm_guest_time_update(struct kvm_vcpu *v)
31723172
{
3173+
struct pvclock_vcpu_time_info hv_clock = {};
31733174
unsigned long flags, tgt_tsc_khz;
31743175
unsigned seq;
31753176
struct kvm_vcpu_arch *vcpu = &v->arch;
@@ -3247,20 +3248,22 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
32473248

32483249
if (unlikely(vcpu->hw_tsc_khz != tgt_tsc_khz)) {
32493250
kvm_get_time_scale(NSEC_PER_SEC, tgt_tsc_khz * 1000LL,
3250-
&vcpu->hv_clock.tsc_shift,
3251-
&vcpu->hv_clock.tsc_to_system_mul);
3251+
&vcpu->pvclock_tsc_shift,
3252+
&vcpu->pvclock_tsc_mul);
32523253
vcpu->hw_tsc_khz = tgt_tsc_khz;
32533254
kvm_xen_update_tsc_info(v);
32543255
}
32553256

3256-
vcpu->hv_clock.tsc_timestamp = tsc_timestamp;
3257-
vcpu->hv_clock.system_time = kernel_ns + v->kvm->arch.kvmclock_offset;
3257+
hv_clock.tsc_shift = vcpu->pvclock_tsc_shift;
3258+
hv_clock.tsc_to_system_mul = vcpu->pvclock_tsc_mul;
3259+
hv_clock.tsc_timestamp = tsc_timestamp;
3260+
hv_clock.system_time = kernel_ns + v->kvm->arch.kvmclock_offset;
32583261
vcpu->last_guest_tsc = tsc_timestamp;
32593262

32603263
/* If the host uses TSC clocksource, then it is stable */
3261-
vcpu->hv_clock.flags = 0;
3264+
hv_clock.flags = 0;
32623265
if (use_master_clock)
3263-
vcpu->hv_clock.flags |= PVCLOCK_TSC_STABLE_BIT;
3266+
hv_clock.flags |= PVCLOCK_TSC_STABLE_BIT;
32643267

32653268
if (vcpu->pv_time.active) {
32663269
/*
@@ -3269,24 +3272,24 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
32693272
* is active/enabled.
32703273
*/
32713274
if (vcpu->pvclock_set_guest_stopped_request) {
3272-
vcpu->hv_clock.flags |= PVCLOCK_GUEST_STOPPED;
3275+
hv_clock.flags |= PVCLOCK_GUEST_STOPPED;
32733276
vcpu->pvclock_set_guest_stopped_request = false;
32743277
}
3275-
kvm_setup_guest_pvclock(&vcpu->hv_clock, v, &vcpu->pv_time, 0, false);
3278+
kvm_setup_guest_pvclock(&hv_clock, v, &vcpu->pv_time, 0, false);
32763279

3277-
vcpu->hv_clock.flags &= ~PVCLOCK_GUEST_STOPPED;
3280+
hv_clock.flags &= ~PVCLOCK_GUEST_STOPPED;
32783281
}
32793282

32803283
#ifdef CONFIG_KVM_XEN
32813284
if (vcpu->xen.vcpu_info_cache.active)
3282-
kvm_setup_guest_pvclock(&vcpu->hv_clock, v, &vcpu->xen.vcpu_info_cache,
3285+
kvm_setup_guest_pvclock(&hv_clock, v, &vcpu->xen.vcpu_info_cache,
32833286
offsetof(struct compat_vcpu_info, time),
32843287
xen_pvclock_tsc_unstable);
32853288
if (vcpu->xen.vcpu_time_info_cache.active)
3286-
kvm_setup_guest_pvclock(&vcpu->hv_clock, v, &vcpu->xen.vcpu_time_info_cache, 0,
3289+
kvm_setup_guest_pvclock(&hv_clock, v, &vcpu->xen.vcpu_time_info_cache, 0,
32873290
xen_pvclock_tsc_unstable);
32883291
#endif
3289-
kvm_hv_setup_tsc_page(v->kvm, &vcpu->hv_clock);
3292+
kvm_hv_setup_tsc_page(v->kvm, &hv_clock);
32903293
return 0;
32913294
}
32923295

arch/x86/kvm/xen.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,8 @@ static int xen_get_guest_pvclock(struct kvm_vcpu *vcpu,
176176
* Sanity check TSC shift+multiplier to verify the guest's view of time
177177
* is more or less consistent.
178178
*/
179-
if (hv_clock->tsc_shift != vcpu->arch.hv_clock.tsc_shift ||
180-
hv_clock->tsc_to_system_mul != vcpu->arch.hv_clock.tsc_to_system_mul)
179+
if (hv_clock->tsc_shift != vcpu->arch.pvclock_tsc_shift ||
180+
hv_clock->tsc_to_system_mul != vcpu->arch.pvclock_tsc_mul)
181181
return -EINVAL;
182182

183183
return 0;
@@ -2316,8 +2316,8 @@ void kvm_xen_update_tsc_info(struct kvm_vcpu *vcpu)
23162316

23172317
entry = kvm_find_cpuid_entry_index(vcpu, function, 1);
23182318
if (entry) {
2319-
entry->ecx = vcpu->arch.hv_clock.tsc_to_system_mul;
2320-
entry->edx = vcpu->arch.hv_clock.tsc_shift;
2319+
entry->ecx = vcpu->arch.pvclock_tsc_mul;
2320+
entry->edx = vcpu->arch.pvclock_tsc_shift;
23212321
}
23222322

23232323
entry = kvm_find_cpuid_entry_index(vcpu, function, 2);

0 commit comments

Comments
 (0)