Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: nVMX: Migrate the VMX-preemption timer

The hrtimer used to emulate the VMX-preemption timer must be pinned to
the same logical processor as the vCPU thread to be interrupted if we
want to have any hope of adhering to the architectural specification
of the VMX-preemption timer. Even with this change, the emulated
VMX-preemption timer VM-exit occasionally arrives too late.

Signed-off-by: Jim Mattson <jmattson@google.com>
Reviewed-by: Peter Shier <pshier@google.com>
Reviewed-by: Oliver Upton <oupton@google.com>
Message-Id: <20200508203643.85477-4-jmattson@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

authored by

Jim Mattson and committed by
Paolo Bonzini
93dff2fe ada0098d

+15
+2
arch/x86/include/asm/kvm_host.h
··· 1247 1247 1248 1248 bool (*apic_init_signal_blocked)(struct kvm_vcpu *vcpu); 1249 1249 int (*enable_direct_tlbflush)(struct kvm_vcpu *vcpu); 1250 + 1251 + void (*migrate_timers)(struct kvm_vcpu *vcpu); 1250 1252 }; 1251 1253 1252 1254 struct kvm_x86_nested_ops {
+2
arch/x86/kvm/irq.c
··· 159 159 { 160 160 __kvm_migrate_apic_timer(vcpu); 161 161 __kvm_migrate_pit_timer(vcpu); 162 + if (kvm_x86_ops.migrate_timers) 163 + kvm_x86_ops.migrate_timers(vcpu); 162 164 } 163 165 164 166 bool kvm_arch_irqfd_allowed(struct kvm *kvm, struct kvm_irqfd *args)
+11
arch/x86/kvm/vmx/vmx.c
··· 7814 7814 return to_vmx(vcpu)->nested.vmxon; 7815 7815 } 7816 7816 7817 + static void vmx_migrate_timers(struct kvm_vcpu *vcpu) 7818 + { 7819 + if (is_guest_mode(vcpu)) { 7820 + struct hrtimer *timer = &to_vmx(vcpu)->nested.preemption_timer; 7821 + 7822 + if (hrtimer_try_to_cancel(timer) == 1) 7823 + hrtimer_start_expires(timer, HRTIMER_MODE_ABS_PINNED); 7824 + } 7825 + } 7826 + 7817 7827 static void hardware_unsetup(void) 7818 7828 { 7819 7829 if (nested) ··· 7967 7957 7968 7958 .need_emulation_on_page_fault = vmx_need_emulation_on_page_fault, 7969 7959 .apic_init_signal_blocked = vmx_apic_init_signal_blocked, 7960 + .migrate_timers = vmx_migrate_timers, 7970 7961 }; 7971 7962 7972 7963 static __init int hardware_setup(void)