Patch "KVM: nVMX: Fix races when sending nested PI while dest enters/leaves L2" has been added to the 4.14-stable tree
Subsystems (3)
This is a note to let you know that I've just added the patch titled
KVM: nVMX: Fix races when sending nested PI while dest enters/leaves L2
to the 4.14-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
kvm-nvmx-fix-races-when-sending-nested-pi-while-dest-enters-leaves-l2.patch
and it can be found in the queue-4.14 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
6b6977117f50d60455ace86b2d256f6fb4f3de05Mon Sep 17 00:00:00 2001
From: Liran Alon <[email protected]>
Date: Thu, 9 Nov 2017 20:27:20 +0200
Subject: KVM: nVMX: Fix races when sending nested PI while dest enters/leaves L2
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
From: Liran Alon <[email protected]>
commit 6b6977117f50d60455ace86b2d256f6fb4f3de05 upstream.
Consider the following scenario:
1. CPU A calls vmx_deliver_nested_posted_interrupt() to send an IPI to CPU B via virtual posted-interrupt mechanism.
2. CPU B is currently executing L2 guest.
3. vmx_deliver_nested_posted_interrupt() calls kvm_vcpu_trigger_posted_interrupt() which will note that vcpu->mode == IN_GUEST_MODE.
4. Assume that before CPU A sends the physical POSTED_INTR_NESTED_VECTOR IPI, CPU B exits from L2 to L0 during event-delivery
(valid IDT-vectoring-info).
5. CPU A now sends the physical IPI. The IPI is received in host and it's handler (smp_kvm_posted_intr_nested_ipi()) does nothing.
6. Assume that before CPU A sets pi_pending=true and KVM_REQ_EVENT, CPU B continues to run in L0 and reach vcpu_enter_guest(). As KVM_REQ_EVENT is not set yet, vcpu_enter_guest() will continue and resume L2 guest.
7. At this point, CPU A sets pi_pending=true and KVM_REQ_EVENT but it's too late! CPU B already entered L2 and KVM_REQ_EVENT will only be consumed at next L2 entry!
Another scenario to consider:
1. CPU A calls vmx_deliver_nested_posted_interrupt() to send an IPI to CPU B via virtual posted-interrupt mechanism.
2. Assume that before CPU A calls kvm_vcpu_trigger_posted_interrupt(), CPU B is at L0 and is about to resume into L2. Further assume that it is in vcpu_enter_guest() after check for KVM_REQ_EVENT.
3. At this point, CPU A calls kvm_vcpu_trigger_posted_interrupt() which will note that vcpu->mode != IN_GUEST_MODE. Therefore, do nothing and return false. Then, will set pi_pending=true and KVM_REQ_EVENT.
4. Now CPU B continue and resumes into L2 guest without processing the posted-interrupt until next L2 entry!
To fix both issues, we just need to change vmx_deliver_nested_posted_interrupt() to set pi_pending=true and KVM_REQ_EVENT before calling kvm_vcpu_trigger_posted_interrupt().
It will fix the first scenario by chaging step (6) to note that KVM_REQ_EVENT and pi_pending=true and therefore process nested posted-interrupt.
It will fix the second scenario by two possible ways:
1. If kvm_vcpu_trigger_posted_interrupt() is called while CPU B has changed vcpu->mode to IN_GUEST_MODE, physical IPI will be sent and will be received when CPU resumes into L2.
2. If kvm_vcpu_trigger_posted_interrupt() is called while CPU B hasn't yet changed vcpu->mode to IN_GUEST_MODE, then after CPU B will change vcpu->mode it will call kvm_request_pending() which will return true and therefore force another round of vcpu_enter_guest() which will note that KVM_REQ_EVENT and pi_pending=true and therefore process nested posted-interrupt.
[Add kvm_vcpu_kick to also handle the case where L1 doesn't intercept L2 HLT
and L2 executes HLT instruction. - Paolo]
--- arch/x86/kvm/vmx.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
arch/x86/kvm/vmx.c +3 -2
@@ -5322,14 +5322,15 @@ static int vmx_deliver_nested_posted_intif (is_guest_mode (vcpu) && vector == vmx->nested.posted_intr_nv) { -/* the PIR and ON have been set by L1. */ -kvm_vcpu_trigger_posted_interrupt (vcpu, true);/* * If a posted intr is not recognized by hardware, * we will accomplish it in the next vmentry. */ vmx->nested.pi_pending = true;kvm_make_request (KVM_REQ_EVENT , vcpu); +/* the PIR and ON have been set by L1. */ +if (!kvm_vcpu_trigger_posted_interrupt (vcpu, true)) +kvm_vcpu_kick (vcpu);return 0 ; }return -1 ;
Patches currently in stable-queue which might be from [email protected] are
queue-4.14/kvm-nvmx-fix-bug-of-injecting-l2-exception-into-l1.patch queue-4.14/kvm-nvmx-fix-races-when-sending-nested-pi-while-dest-enters-leaves-l2.patch