|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v2 2/2] x86/nestedsvm: honour L2's EFLAGS.IF when L1 clears V_INTR_MASKING
From: Chunjie Zhu <chunjie.zhu@xxxxxxxxxx>
L0 always runs L2 with V_INTR_MASKING set, so a physical interrupt exits to
L0 regardless of L2's EFLAGS.IF. nsvm_intr_blocked() only blocks when L1
requested V_INTR_MASKING=1 and L1's IF was clear. With V_INTR_MASKING=0
and L2's IF clear, nestedsvm_vcpu_interrupt() would still inject
VMEXIT(INTR) into L1.
Per the APM (vol.2 rev 3.44 "Physical Interrupt Masking in EFLAGS"), with
V_INTR_MASKING=0 L2's IF masks physical interrupts, and a masked interrupt
must stay pending. Return NSVM_INTR_MASKED for external interrupts in
that case.
Signed-off-by: Chunjie Zhu <chunjie.zhu@xxxxxxxxxx>
---
v2:
* Move the check into nsvm_intr_blocked(), as suggested by Ross.
xen/arch/x86/hvm/svm/nestedsvm.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/xen/arch/x86/hvm/svm/nestedsvm.c b/xen/arch/x86/hvm/svm/nestedsvm.c
index a93681e9bbcd..e3b2d20ffce2 100644
--- a/xen/arch/x86/hvm/svm/nestedsvm.c
+++ b/xen/arch/x86/hvm/svm/nestedsvm.c
@@ -1222,8 +1222,16 @@ enum hvm_intblk cf_check nsvm_intr_blocked(struct vcpu
*v)
{
struct vmcb_struct *n2vmcb = nv->nv_n2vmcx;
- if ( svm->ns_hostflags.fields.vintrmask &&
- !svm->ns_hostflags.fields.rflagsif )
+ /*
+ * With V_INTR_MASKING, L1's EFLAGS.IF masks physical interrupts.
+ * Without it, L2's EFLAGS.IF does (APM vol.2 rev 3.44 "Physical
+ * Interrupt Masking in EFLAGS"); L0 always runs L2 with
+ * V_INTR_MASKING set, so the interrupt would otherwise exit to L0
+ * and be forwarded to L1 even with L2's IF clear.
+ */
+ if ( svm->ns_hostflags.fields.vintrmask
+ ? !svm->ns_hostflags.fields.rflagsif
+ : !(guest_cpu_user_regs()->eflags & X86_EFLAGS_IF) )
return hvm_intblk_rflags_ie;
/* when l1 guest passes its devices through to the l2 guest
--
2.34.1
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |