From b4a7a1ea1adde6f25cee9e648eb0de6ca818eb47 Mon Sep 17 00:00:00 2001 From: Minggui Cao Date: Tue, 9 Oct 2018 18:48:16 +0800 Subject: [PATCH] HV: allow no IRR when pending bit set if no APIC-V An issue reported on KBL NUC (No APIC-V), when runing GVT test case, it is easily to cause SOS/UOS hung. This patch is to root cause it and how to avoid it. On some platforms with no APIC-V support, this modidication can avoid SOS hung when no IRR but event pending bit set. If no APIC-V, interrupt injection will use IRR in vLAPIC and event pending bitmap; work logic as following (set ABC for notes): 1. in ISR or when UOS send an interrupt to SOS/VHM (like IO request), step A: set IRR --> step B: set event pending bit; 2. in SOS event handing, step C: check/clear event pending bit --> step D: probe/get IRR --> step E: clear/handle IRR. 3. after that, it will probe IRR again to check if other IRR left: step F: probe IRR --> step G: set event pending bit --> step H: enable IRQ window in VMX. Before, from step C to D, if pending bit checked, but no IRR, it will return -1, then the CPU will goto ZOMBIE status. It can cause SOS hung. It can happen occasionally under following case : 4. between UOS step A and step B, SOS can goto step F, so it gets IRR, and step G --> step H, then SOS enter non-root mode, for IRQ window enabled, it will cause vmexit to continue step C/D/E. 5. then UOS does step B, to set pending bit, but no IRR now. When next vmexit, SOS does step C and D, it can't get IRR, failure happens. In summary, a failed case steps: A-->F-->G-->H-->C-->D-->E-->B-->C-->D So we allow that when event pending bit checked, IRR could be cleared already.It just wastes one probe time occasionally. Tracked-On: #1363 Signed-off-by: Minggui Cao Acked-by: Eddie Dong --- hypervisor/arch/x86/virq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hypervisor/arch/x86/virq.c b/hypervisor/arch/x86/virq.c index d1a1fabc8..a6014d553 100644 --- a/hypervisor/arch/x86/virq.c +++ b/hypervisor/arch/x86/virq.c @@ -132,7 +132,7 @@ static int vcpu_inject_vlapic_int(struct vcpu *vcpu) * through the local APIC. */ if (ret == 0) { - return -1; + return 0; } if (!(vector >= 16U && vector <= 255U)) {