• J
    KVM: VMX: Do not change PID.NDST when loading a blocked vCPU · 132194ff
    Joao Martins 提交于
    When vCPU enters block phase, pi_pre_block() inserts vCPU to a per pCPU
    linked list of all vCPUs that are blocked on this pCPU. Afterwards, it
    changes PID.NV to POSTED_INTR_WAKEUP_VECTOR which its handler
    (wakeup_handler()) is responsible to kick (unblock) any vCPU on that
    linked list that now has pending posted interrupts.
    
    While vCPU is blocked (in kvm_vcpu_block()), it may be preempted which
    will cause vmx_vcpu_pi_put() to set PID.SN.  If later the vCPU will be
    scheduled to run on a different pCPU, vmx_vcpu_pi_load() will clear
    PID.SN but will also *overwrite PID.NDST to this different pCPU*.
    Instead of keeping it with original pCPU which vCPU had entered block
    phase on.
    
    This results in an issue because when a posted interrupt is delivered, as
    the wakeup_handler() will be executed and fail to find blocked vCPU on
    its per pCPU linked list of all vCPUs that are blocked on this pCPU.
    Which is due to the vCPU being placed on a *different* per pCPU
    linked list i.e. the original pCPU in which it entered block phase.
    
    The regression is introduced by commit c112b5f5 ("KVM: x86:
    Recompute PID.ON when clearing PID.SN"). Therefore, partially revert
    it and reintroduce the condition in vmx_vcpu_pi_load() responsible for
    avoiding changing PID.NDST when loading a blocked vCPU.
    
    Fixes: c112b5f5 ("KVM: x86: Recompute PID.ON when clearing PID.SN")
    Tested-by: NNathan Ni <nathan.ni@oracle.com>
    Co-developed-by: NLiran Alon <liran.alon@oracle.com>
    Signed-off-by: NLiran Alon <liran.alon@oracle.com>
    Signed-off-by: NJoao Martins <joao.m.martins@oracle.com>
    Signed-off-by: NPaolo Bonzini <pbonzini@redhat.com>
    132194ff
vmx.c 219.2 KB