Skip to content

Commit 24c1663

Browse files
committed
KVM: x86: Don't bleed PVCLOCK_GUEST_STOPPED across PV clocks
When updating a specific PV clock, make a full copy of KVM's reference copy/cache so that PVCLOCK_GUEST_STOPPED doesn't bleed across clocks. E.g. in the unlikely scenario the guest has enabled both kvmclock and Xen PV clock, a dangling GUEST_STOPPED in kvmclock would bleed into Xen PV clock. Using a local copy of the pvclock structure also sets the stage for eliminating the per-vCPU copy/cache (only the TSC frequency information actually "needs" to be cached/persisted). Fixes: aa096aa ("KVM: x86/xen: setup pvclock updates") Reviewed-by: Paul Durrant <paul@xen.org> Link: https://lore.kernel.org/r/20250201013827.680235-7-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent ca28aa6 commit 24c1663

File tree

1 file changed

+8
-5
lines changed

1 file changed

+8
-5
lines changed

arch/x86/kvm/x86.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3123,8 +3123,11 @@ static void kvm_setup_guest_pvclock(struct kvm_vcpu *v,
31233123
{
31243124
struct kvm_vcpu_arch *vcpu = &v->arch;
31253125
struct pvclock_vcpu_time_info *guest_hv_clock;
3126+
struct pvclock_vcpu_time_info hv_clock;
31263127
unsigned long flags;
31273128

3129+
memcpy(&hv_clock, &vcpu->hv_clock, sizeof(hv_clock));
3130+
31283131
read_lock_irqsave(&gpc->lock, flags);
31293132
while (!kvm_gpc_check(gpc, offset + sizeof(*guest_hv_clock))) {
31303133
read_unlock_irqrestore(&gpc->lock, flags);
@@ -3144,25 +3147,25 @@ static void kvm_setup_guest_pvclock(struct kvm_vcpu *v,
31443147
* it is consistent.
31453148
*/
31463149

3147-
guest_hv_clock->version = vcpu->hv_clock.version = (guest_hv_clock->version + 1) | 1;
3150+
guest_hv_clock->version = hv_clock.version = (guest_hv_clock->version + 1) | 1;
31483151
smp_wmb();
31493152

31503153
/* retain PVCLOCK_GUEST_STOPPED if set in guest copy */
3151-
vcpu->hv_clock.flags |= (guest_hv_clock->flags & PVCLOCK_GUEST_STOPPED);
3154+
hv_clock.flags |= (guest_hv_clock->flags & PVCLOCK_GUEST_STOPPED);
31523155

3153-
memcpy(guest_hv_clock, &vcpu->hv_clock, sizeof(*guest_hv_clock));
3156+
memcpy(guest_hv_clock, &hv_clock, sizeof(*guest_hv_clock));
31543157

31553158
if (force_tsc_unstable)
31563159
guest_hv_clock->flags &= ~PVCLOCK_TSC_STABLE_BIT;
31573160

31583161
smp_wmb();
31593162

3160-
guest_hv_clock->version = ++vcpu->hv_clock.version;
3163+
guest_hv_clock->version = ++hv_clock.version;
31613164

31623165
kvm_gpc_mark_dirty_in_slot(gpc);
31633166
read_unlock_irqrestore(&gpc->lock, flags);
31643167

3165-
trace_kvm_pvclock_update(v->vcpu_id, &vcpu->hv_clock);
3168+
trace_kvm_pvclock_update(v->vcpu_id, &hv_clock);
31663169
}
31673170

31683171
static int kvm_guest_time_update(struct kvm_vcpu *v)

0 commit comments

Comments
 (0)