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.
Unified · Split
| @@ -1247,6 +1247,8 @@ struct kvm_x86_ops { · 1246 unmodified lines | |||
| 1247 | 1247 | ||
| 1248 | bool (*apic_init_signal_blocked)(struct kvm_vcpu *vcpu); | 1248 | bool (*apic_init_signal_blocked)(struct kvm_vcpu *vcpu); |
| 1249 | int (*enable_direct_tlbflush)(struct kvm_vcpu *vcpu); | 1249 | int (*enable_direct_tlbflush)(struct kvm_vcpu *vcpu); |
| 1250 | |||
| 1251 | void (*migrate_timers)(struct kvm_vcpu *vcpu); | ||
| 1250 | }; | 1252 | }; |
| 1251 | 1253 | ||
| 1252 | struct kvm_x86_nested_ops { | 1254 | struct kvm_x86_nested_ops { |
| @@ -159,6 +159,8 @@ void __kvm_migrate_timers(struct kvm_vcpu *vcpu) · 158 unmodified lines | |||
| 159 | { | 159 | { |
| 160 | __kvm_migrate_apic_timer(vcpu); | 160 | __kvm_migrate_apic_timer(vcpu); |
| 161 | __kvm_migrate_pit_timer(vcpu); | 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 | bool kvm_arch_irqfd_allowed(struct kvm *kvm, struct kvm_irqfd *args) | 166 | bool kvm_arch_irqfd_allowed(struct kvm *kvm, struct kvm_irqfd *args) |
| @@ -7814,6 +7814,16 @@ static bool vmx_apic_init_signal_blocked(struct kvm_vcpu *vcpu) · 7813 unmodified lines | |||
| 7814 | return to_vmx(vcpu)->nested.vmxon; | 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 | static void hardware_unsetup(void) | 7827 | static void hardware_unsetup(void) |
| 7818 | { | 7828 | { |
| 7819 | if (nested) | 7829 | if (nested) |
| @@ -7957,6 +7967,7 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = { · 137 unmodified lines | |||
| 7957 | 7967 | ||
| 7958 | .need_emulation_on_page_fault = vmx_need_emulation_on_page_fault, | 7968 | .need_emulation_on_page_fault = vmx_need_emulation_on_page_fault, |
| 7959 | .apic_init_signal_blocked = vmx_apic_init_signal_blocked, | 7969 | .apic_init_signal_blocked = vmx_apic_init_signal_blocked, |
| 7970 | .migrate_timers = vmx_migrate_timers, | ||
| 7960 | }; | 7971 | }; |
| 7961 | 7972 | ||
| 7962 | static __init int hardware_setup(void) | 7973 | static __init int hardware_setup(void) |