All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Mushahid Hussain" <hmushi@amazon.co.uk>
Cc: kvm@vger.kernel.org, linux-hyperv@vger.kernel.org
Subject: Re: [PATCH 3/3] KVM: x86: hyper-v: Implement HvCallRestorePartitionTime
Date: Mon, 05 Oct 2026 19:38:53 +0000	[thread overview]
Message-ID: <20261005193853.A50251F000FF@smtp.kernel.org> (raw)
In-Reply-To: <20261005192431.87317-4-hmushi@amazon.co.uk>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] x86/kvm: Race condition in kvm_vcpu_apply_tsc_generation() causes state corruption
- [High] x86/kvm: Pre-mature matched TSC count increment permits double-counting
- [Medium] x86/kvm: VM-wide cur_tsc_offset overwritten in per-vCPU loop
--

commit 3619ce01761243ff0d6db55e73b6eefb9f3cc10b
Author: Mushahid Hussain <hmushi@amazon.co.uk>
Subject: KVM: x86: hyper-v: Implement HvCallRestorePartitionTime

A nested Hyper-V guest can resume from hibernation and use
HvCallRestorePartitionTime to sync its TSC and reference counter. This commit
implements handling for the hypercall in KVM, stepping both clocks in a
single update. It updates kvm_set_clock_and_tsc() and issues requests to
write the TSC offset for each vCPU.

> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 19666a80240a5..c0865468b02e7 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c

[ ... ]

> @@ -4354,13 +4354,85 @@ static int kvm_vm_ioctl_get_clock(struct kvm *kvm, void __user *argp)
>  	return 0;
>  }
>  
> -static void __kvm_set_clock(struct kvm *kvm, struct kvm_clock_data *data)
> +/* Must precede pvclock_update_vm_gtod_copy(), which reads the matched count. */
> +static void kvm_open_tsc_generation(struct kvm *kvm, u64 guest_tsc)
> +{
> +	struct kvm_arch *ka = &kvm->arch;
> +	struct kvm_vcpu *vcpu;
> +	unsigned long i;
> +
> +	lockdep_assert_held(&ka->tsc_write_lock);
> +
> +	ka->cur_tsc_generation++;
> +	ka->cur_tsc_write = guest_tsc;
> +	ka->last_tsc_write = guest_tsc;
> +	ka->nr_vcpus_matched_tsc = atomic_read(&kvm->online_vcpus) - 1;

[Severity: High]
Is it safe to pre-increment the matched count globally before the per-vCPU
updates complete?

If a vCPU executes kvm_synchronize_tsc() before processing the asynchronous
KVM_REQ_WRITE_TSC_OFFSET, it might see a stale generation, match it, and
increment ka->nr_vcpus_matched_tsc.

Since the count is pre-incremented here, double-counting could cause
the total to reach or exceed online_vcpus, permanently breaking the KVM
masterclock validation (which checks if matched_tsc + 1 == online_vcpus).

> +
> +	kvm_for_each_vcpu(i, vcpu, kvm) {
> +		if (vcpu->arch.guest_tsc_protected)
> +			continue;
> +		ka->last_tsc_khz = vcpu->arch.virtual_tsc_khz;
> +		ka->last_tsc_scaling_ratio = vcpu->arch.l1_tsc_scaling_ratio;
> +		break;
> +	}
> +}
> +
> +/* Every vCPU reads @guest_tsc at host TSC @host_tsc. */
> +static void kvm_set_tsc_generation(struct kvm *kvm, u64 host_tsc,
> +				   u64 guest_tsc, u64 ns)
> +{
> +	struct kvm_arch *ka = &kvm->arch;
> +	struct kvm_vcpu *vcpu;
> +	unsigned long i;
> +
> +	lockdep_assert_held(&ka->tsc_write_lock);
> +
> +	ka->cur_tsc_nsec = ns;
> +	ka->last_tsc_nsec = ns;
> +	ka->restore_host_tsc = host_tsc;
> +	ka->restore_guest_tsc = guest_tsc;
> +	ka->restore_tsc_nsec = ns;
> +
> +	kvm_for_each_vcpu(i, vcpu, kvm) {
> +		if (vcpu->arch.guest_tsc_protected)
> +			continue;
> +
> +		ka->cur_tsc_offset = kvm_compute_l1_tsc_offset(vcpu, host_tsc,
> +							       guest_tsc);
> +		ka->last_tsc_offset = ka->cur_tsc_offset;

[Severity: Medium]
Could this loop repeatedly overwrite the VM-wide offset, leaving it configured
for the last vCPU?

If vCPUs have different TSC scaling ratios (which can be set via
KVM_SET_TSC_KHZ), the reference frequency is bound to the first valid vCPU in
kvm_open_tsc_generation() above, while the offset here ends up bound to the
last vCPU, breaking consistency.

> +		kvm_make_request(KVM_REQ_WRITE_TSC_OFFSET, vcpu);
> +	}
> +}
> +
> +/* Runs on the vCPU; only the owner writes its TSC offset. */
> +static void kvm_vcpu_apply_tsc_generation(struct kvm_vcpu *vcpu)
> +{
> +	struct kvm_arch *ka = &vcpu->kvm->arch;
> +	unsigned long flags;
> +	u64 offset;
> +
> +	raw_spin_lock_irqsave(&ka->tsc_write_lock, flags);
> +	offset = kvm_compute_l1_tsc_offset(vcpu, ka->restore_host_tsc,
> +					   ka->restore_guest_tsc);
> +	vcpu->arch.last_guest_tsc = ka->restore_guest_tsc;
> +	vcpu->arch.this_tsc_generation = ka->cur_tsc_generation;

[Severity: High]
Could a race condition corrupt state tracking here?

If a concurrent write to MSR_IA32_TSC bumps ka->cur_tsc_generation while
KVM_REQ_WRITE_TSC_OFFSET is queued, the vCPU processing the request will copy
the newer generation counter here while applying the stale ka->restore_*
offset data.

This would leave the vCPU claiming synchronization with the new generation
while actually holding old data, breaking KVM masterclock and TSC
synchronization.

> +	vcpu->arch.this_tsc_nsec = ka->restore_tsc_nsec;
> +	vcpu->arch.this_tsc_write = ka->restore_guest_tsc;
> +	raw_spin_unlock_irqrestore(&ka->tsc_write_lock, flags);
> +
> +	kvm_vcpu_write_tsc_offset(vcpu, offset);
> +}

[ ... ]

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261005192431.87317-1-hmushi@amazon.co.uk?part=3

  reply	other threads:[~2026-10-05 19:38 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-05 19:24 [PATCH 0/3] KVM: x86: Support hibernation of a nested Hyper-V Mushahid Hussain
2026-10-05 19:24 ` [PATCH 1/3] KVM: nVMX: Clear stale vmcs02 sync flag in free_nested() Mushahid Hussain
2026-10-12 19:29   ` Jim Mattson
2026-10-05 19:24 ` [PATCH 2/3] KVM: x86: Extract __kvm_set_clock() from kvm_vm_ioctl_set_clock() Mushahid Hussain
2026-10-12 19:35   ` Jim Mattson
2026-10-05 19:24 ` [PATCH 3/3] KVM: x86: hyper-v: Implement HvCallRestorePartitionTime Mushahid Hussain
2026-10-05 19:38   ` sashiko-bot [this message]
2026-10-05 22:30   ` David Woodhouse
2026-10-12 21:23   ` Jim Mattson
2026-10-13 11:32     ` Woodhouse, David
2026-10-06  5:08 ` [PATCH 0/3] KVM: x86: Support hibernation of a nested Hyper-V David Woodhouse

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261005193853.A50251F000FF@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=hmushi@amazon.co.uk \
    --cc=kvm@vger.kernel.org \
    --cc=linux-hyperv@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.