Re: [PATCH 3/3] KVM: nVMX: Migrate the VMX-preemption timer

Paolo Bonzini
2020-05-09T13:17:26Z

On 08/05/20 22:36, Jim Mattson wrote:
> 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>
> ---
> arch/x86/include/asm/kvm_host.h | 2 ++
> arch/x86/kvm/irq.c | 2 ++
> arch/x86/kvm/vmx/vmx.c | 11 +++++++++++
> 3 files changed, 15 insertions(+)
>
> diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
> index 42a2d0d3984a..a47c71d13039 100644
> --- a/arch/x86/include/asm/kvm_host.h
> +++ b/arch/x86/include/asm/kvm_host.h
> @@ -1254,6 +1254,8 @@ struct kvm_x86_ops {
>
> bool (*apic_init_signal_blocked)(struct kvm_vcpu *vcpu);
> int (*enable_direct_tlbflush)(struct kvm_vcpu *vcpu);
> +
> + void (*migrate_timers)(struct kvm_vcpu *vcpu);
> };
>
> struct kvm_x86_init_ops {
> diff --git a/arch/x86/kvm/irq.c b/arch/x86/kvm/irq.c
> index e330e7d125f7..54f7ea68083b 100644
> --- a/arch/x86/kvm/irq.c
> +++ b/arch/x86/kvm/irq.c
> @@ -159,6 +159,8 @@ void __kvm_migrate_timers(struct kvm_vcpu *vcpu)
> {
> __kvm_migrate_apic_timer(vcpu);
> __kvm_migrate_pit_timer(vcpu);
> + if (kvm_x86_ops.migrate_timers)
> + kvm_x86_ops.migrate_timers(vcpu);
> }
>
> bool kvm_arch_irqfd_allowed(struct kvm *kvm, struct kvm_irqfd *args)
> diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
> index c2c6335a998c..3896dea72082 100644
> --- a/arch/x86/kvm/vmx/vmx.c
> +++ b/arch/x86/kvm/vmx/vmx.c
> @@ -7687,6 +7687,16 @@ static bool vmx_apic_init_signal_blocked(struct kvm_vcpu *vcpu)
> return to_vmx(vcpu)->nested.vmxon;
> }
>
> +static void vmx_migrate_timers(struct kvm_vcpu *vcpu)
> +{
> + if (is_guest_mode(vcpu)) {
> + struct hrtimer *timer = &to_vmx(vcpu)->nested.preemption_timer;
> +
> + if (hrtimer_try_to_cancel(timer) == 1)
> + hrtimer_start_expires(timer, HRTIMER_MODE_ABS_PINNED);
> + }
> +}
> +
> static void hardware_unsetup(void)
> {
> if (nested)
> @@ -7838,6 +7848,7 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = {
> .nested_get_evmcs_version = NULL,
> .need_emulation_on_page_fault = vmx_need_emulation_on_page_fault,
> .apic_init_signal_blocked = vmx_apic_init_signal_blocked,
> + .migrate_timers = vmx_migrate_timers,
> };
>
> static __init int hardware_setup(void)
>

Queued all, thanks.

Paolo