KVM: lapic: Track lapic timer advance per vCPU
Automatically adjusting the globally-shared timer advancement could
corrupt the timer, e.g. if multiple vCPUs are concurrently adjusting
the advancement value. That could be partially fixed by using a local
variable for the arithmetic, but it would still be susceptible to a
race when setting timer_advance_adjust_done.
And because virtual_tsc_khz and tsc_scaling_ratio are per-vCPU, the
correct calibration for a given vCPU may not apply to all vCPUs.
Furthermore, lapic_timer_advance_ns is marked __read_mostly, which is
effectively violated when finding a stable advancement takes an extended
amount of timer.
Opportunistically change the definition of lapic_timer_advance_ns to
a u32 so that it matches the style of struct kvm_timer. Explicitly
pass the param to kvm_create_lapic() so that it doesn't have to be
exposed to lapic.c, thus reducing the probability of unintentionally
using the global value instead of the per-vCPU value.
Cc: Liran Alon <liran.alon@oracle.com>
Cc: Wanpeng Li <wanpengli@tencent.com>
Reviewed-by: Liran Alon <liran.alon@oracle.com>
Cc: stable@vger.kernel.org
Fixes: 3b8a5df6c4
("KVM: LAPIC: Tune lapic_timer_advance_ns automatically")
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:

zatwierdzone przez
Paolo Bonzini

rodzic
57bf67e73c
commit
39497d7660
@@ -7032,6 +7032,7 @@ static int vmx_set_hv_timer(struct kvm_vcpu *vcpu, u64 guest_deadline_tsc)
|
||||
{
|
||||
struct vcpu_vmx *vmx;
|
||||
u64 tscl, guest_tscl, delta_tsc, lapic_timer_advance_cycles;
|
||||
struct kvm_timer *ktimer = &vcpu->arch.apic->lapic_timer;
|
||||
|
||||
if (kvm_mwait_in_guest(vcpu->kvm))
|
||||
return -EOPNOTSUPP;
|
||||
@@ -7040,7 +7041,8 @@ static int vmx_set_hv_timer(struct kvm_vcpu *vcpu, u64 guest_deadline_tsc)
|
||||
tscl = rdtsc();
|
||||
guest_tscl = kvm_read_l1_tsc(vcpu, tscl);
|
||||
delta_tsc = max(guest_deadline_tsc, guest_tscl) - guest_tscl;
|
||||
lapic_timer_advance_cycles = nsec_to_cycles(vcpu, lapic_timer_advance_ns);
|
||||
lapic_timer_advance_cycles = nsec_to_cycles(vcpu,
|
||||
ktimer->timer_advance_ns);
|
||||
|
||||
if (delta_tsc > lapic_timer_advance_cycles)
|
||||
delta_tsc -= lapic_timer_advance_cycles;
|
||||
|
Reference in New Issue
Block a user