aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2010-05-10 09:55:54 +0100
committerKeir Fraser <keir.fraser@citrix.com>2010-05-10 09:55:54 +0100
commit304097c7cff270b6cce57c17a4135f547c6070c6 (patch)
tree06b2c831f0c8951f573f5999282b43c74cb41b21
parentd11b4a6bd23c951dc6e7e2e9345938c5e6f8538b (diff)
downloadxen-304097c7cff270b6cce57c17a4135f547c6070c6.tar.gz
xen-304097c7cff270b6cce57c17a4135f547c6070c6.tar.bz2
xen-304097c7cff270b6cce57c17a4135f547c6070c6.zip
svm: Avoid VINTR injection during NMI shadow
It is invalid because we get vmexit via IRET interception in this case. VINTR is unaware of NMI shadows and may vmexit early, leaving us in an endless loop of VINTR injections and interceptions. Signed-off-by: Wei Wang <wei.wang2@amd.com> Signed-off-by: Keir Fraser <keir.fraser@citrix.com> xen-unstable changeset: 21331:bbf009817ffb xen-unstable date: Fri May 07 19:22:28 2010 +0100
-rw-r--r--xen/arch/x86/hvm/svm/intr.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/xen/arch/x86/hvm/svm/intr.c b/xen/arch/x86/hvm/svm/intr.c
index 369423612b..dc881aaa8c 100644
--- a/xen/arch/x86/hvm/svm/intr.c
+++ b/xen/arch/x86/hvm/svm/intr.c
@@ -88,10 +88,21 @@ static void enable_intr_window(struct vcpu *v, struct hvm_intack intack)
* guest can accept the real interrupt.
*
* TODO: Better NMI handling. We need a way to skip a MOV SS interrupt
- * shadow. This is hard to do without hardware support. We should also
- * track 'NMI blocking' from NMI injection until IRET. This can be done
- * quite easily in software by intercepting the unblocking IRET.
+ * shadow. This is hard to do without hardware support. Also we should
+ * not be waiting for EFLAGS.IF to become 1.
*/
+
+ /*
+ * NMI-blocking window is handled by IRET interception. We should not
+ * inject a VINTR in this case as VINTR is unaware of NMI-blocking and
+ * hence we can enter an endless loop (VINTR intercept fires, yet
+ * hvm_interrupt_blocked() still indicates NMI-blocking is active, so
+ * we inject a VINTR, ...).
+ */
+ if ( (intack.source == hvm_intsrc_nmi) &&
+ (vmcb->general1_intercepts & GENERAL1_INTERCEPT_IRET) )
+ return;
+
intr = vmcb->vintr;
intr.fields.irq = 1;
intr.fields.vector = 0;