aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2017-06-06 06:57:06 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2017-09-27 07:45:42 -0400
commit31afb2ea2b10a7d17ce3db4cdb0a12b63b2fe08a (patch)
tree6b95d75fe5afe16e396968ba6d99f34e0868af37
parent8b306e2f3c41939ea528e6174c88cfbfff893ce1 (diff)
KVM: VMX: simplify and fix vmx_vcpu_pi_load
The simplify part: do not touch pi_desc.nv, we can set it when the VCPU is first created. Likewise, pi_desc.sn is only handled by vmx_vcpu_pi_load, do not touch it in __pi_post_block. The fix part: do not check kvm_arch_has_assigned_device, instead check the SN bit to figure out whether vmx_vcpu_pi_put ran before. This matches what the previous patch did in pi_post_block. Cc: Huangweidong <weidong.huang@huawei.com> Cc: Gonglei <arei.gonglei@huawei.com> Cc: wangxin <wangxinxin.wang@huawei.com> Cc: Radim Krčmář <rkrcmar@redhat.com> Tested-by: Longpeng (Mike) <longpeng2@huawei.com> Cc: stable@vger.kernel.org Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--arch/x86/kvm/vmx.c68
1 files changed, 35 insertions, 33 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 0bfe97e50a40..b9d2140eb212 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -2202,43 +2202,41 @@ static void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu)
2202 struct pi_desc old, new; 2202 struct pi_desc old, new;
2203 unsigned int dest; 2203 unsigned int dest;
2204 2204
2205 if (!kvm_arch_has_assigned_device(vcpu->kvm) || 2205 /*
2206 !irq_remapping_cap(IRQ_POSTING_CAP) || 2206 * In case of hot-plug or hot-unplug, we may have to undo
2207 !kvm_vcpu_apicv_active(vcpu)) 2207 * vmx_vcpu_pi_put even if there is no assigned device. And we
2208 * always keep PI.NDST up to date for simplicity: it makes the
2209 * code easier, and CPU migration is not a fast path.
2210 */
2211 if (!pi_test_sn(pi_desc) && vcpu->cpu == cpu)
2212 return;
2213
2214 /*
2215 * First handle the simple case where no cmpxchg is necessary; just
2216 * allow posting non-urgent interrupts.
2217 *
2218 * If the 'nv' field is POSTED_INTR_WAKEUP_VECTOR, do not change
2219 * PI.NDST: pi_post_block will do it for us and the wakeup_handler
2220 * expects the VCPU to be on the blocked_vcpu_list that matches
2221 * PI.NDST.
2222 */
2223 if (pi_desc->nv == POSTED_INTR_WAKEUP_VECTOR ||
2224 vcpu->cpu == cpu) {
2225 pi_clear_sn(pi_desc);
2208 return; 2226 return;
2227 }
2209 2228
2229 /* The full case. */
2210 do { 2230 do {
2211 old.control = new.control = pi_desc->control; 2231 old.control = new.control = pi_desc->control;
2212 2232
2213 /* 2233 dest = cpu_physical_id(cpu);
2214 * If 'nv' field is POSTED_INTR_WAKEUP_VECTOR, there
2215 * are two possible cases:
2216 * 1. After running 'pre_block', context switch
2217 * happened. For this case, 'sn' was set in
2218 * vmx_vcpu_put(), so we need to clear it here.
2219 * 2. After running 'pre_block', we were blocked,
2220 * and woken up by some other guy. For this case,
2221 * we don't need to do anything, 'pi_post_block'
2222 * will do everything for us. However, we cannot
2223 * check whether it is case #1 or case #2 here
2224 * (maybe, not needed), so we also clear sn here,
2225 * I think it is not a big deal.
2226 */
2227 if (pi_desc->nv != POSTED_INTR_WAKEUP_VECTOR) {
2228 if (vcpu->cpu != cpu) {
2229 dest = cpu_physical_id(cpu);
2230
2231 if (x2apic_enabled())
2232 new.ndst = dest;
2233 else
2234 new.ndst = (dest << 8) & 0xFF00;
2235 }
2236 2234
2237 /* set 'NV' to 'notification vector' */ 2235 if (x2apic_enabled())
2238 new.nv = POSTED_INTR_VECTOR; 2236 new.ndst = dest;
2239 } 2237 else
2238 new.ndst = (dest << 8) & 0xFF00;
2240 2239
2241 /* Allow posting non-urgent interrupts */
2242 new.sn = 0; 2240 new.sn = 0;
2243 } while (cmpxchg(&pi_desc->control, old.control, 2241 } while (cmpxchg(&pi_desc->control, old.control,
2244 new.control) != old.control); 2242 new.control) != old.control);
@@ -9592,6 +9590,13 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
9592 9590
9593 vmx->msr_ia32_feature_control_valid_bits = FEATURE_CONTROL_LOCKED; 9591 vmx->msr_ia32_feature_control_valid_bits = FEATURE_CONTROL_LOCKED;
9594 9592
9593 /*
9594 * Enforce invariant: pi_desc.nv is always either POSTED_INTR_VECTOR
9595 * or POSTED_INTR_WAKEUP_VECTOR.
9596 */
9597 vmx->pi_desc.nv = POSTED_INTR_VECTOR;
9598 vmx->pi_desc.sn = 1;
9599
9595 return &vmx->vcpu; 9600 return &vmx->vcpu;
9596 9601
9597free_vmcs: 9602free_vmcs:
@@ -11723,9 +11728,6 @@ static void __pi_post_block(struct kvm_vcpu *vcpu)
11723 else 11728 else
11724 new.ndst = (dest << 8) & 0xFF00; 11729 new.ndst = (dest << 8) & 0xFF00;
11725 11730
11726 /* Allow posting non-urgent interrupts */
11727 new.sn = 0;
11728
11729 /* set 'NV' to 'notification vector' */ 11731 /* set 'NV' to 'notification vector' */
11730 new.nv = POSTED_INTR_VECTOR; 11732 new.nv = POSTED_INTR_VECTOR;
11731 } while (cmpxchg(&pi_desc->control, old.control, 11733 } while (cmpxchg(&pi_desc->control, old.control,