|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v1 5/6] nestedsvm: Fix deferred event injection
If an event for L1 occurs while L2 is running, Xen should inject
VMEXIT_INTR and the event into L1.
nestedsvm_vcpu_interrupt() and nestedsvm_vmexit_defer() set this up to
be handled later by nsvm_vcpu_vmexit_inject() after the switch back to
L1. However, the code there appears to be bogus and completely ignores
the source/vector set up in the first place. Fix this by using the
values to properly inject the event.
Fixes: 9a779e4fc161 ("Implement SVM specific part for Nested Virtualization")
Signed-off-by: Ross Lagerwall <ross.lagerwall@xxxxxxxxxx>
---
xen/arch/x86/hvm/svm/intr.c | 4 ++--
xen/arch/x86/hvm/svm/nestedsvm.c | 22 ++++++++++++++++++----
xen/arch/x86/hvm/svm/svm.h | 3 +++
3 files changed, 23 insertions(+), 6 deletions(-)
diff --git a/xen/arch/x86/hvm/svm/intr.c b/xen/arch/x86/hvm/svm/intr.c
index cf0621d2f628..8914375b6c21 100644
--- a/xen/arch/x86/hvm/svm/intr.c
+++ b/xen/arch/x86/hvm/svm/intr.c
@@ -55,7 +55,7 @@ static void svm_inject_nmi(struct vcpu *v)
vmcb, general1_intercepts | GENERAL1_INTERCEPT_IRET);
}
-static void svm_inject_extint(struct vcpu *v, int vector)
+void svm_inject_extint(struct vcpu *v, int vector)
{
struct vmcb_struct *vmcb = v->arch.hvm.svm.vmcb;
intinfo_t event;
@@ -69,7 +69,7 @@ static void svm_inject_extint(struct vcpu *v, int vector)
vmcb->event_inj = event;
}
-static void svm_enable_intr_window(struct vcpu *v, struct hvm_intack intack)
+void svm_enable_intr_window(struct vcpu *v, struct hvm_intack intack)
{
struct vmcb_struct *vmcb = v->arch.hvm.svm.vmcb;
uint32_t general1_intercepts = vmcb_get_general1_intercepts(vmcb);
diff --git a/xen/arch/x86/hvm/svm/nestedsvm.c b/xen/arch/x86/hvm/svm/nestedsvm.c
index 9b0bd0358ce4..d4fd838ca0b6 100644
--- a/xen/arch/x86/hvm/svm/nestedsvm.c
+++ b/xen/arch/x86/hvm/svm/nestedsvm.c
@@ -733,11 +733,25 @@ nsvm_vcpu_vmexit_inject(struct vcpu *v, struct
cpu_user_regs *regs,
switch ( exitcode )
{
case VMEXIT_INTR:
- if ( unlikely(ns_vmcb->event_inj.v) && nv->nv_vmentry_pending &&
- hvm_event_needs_reinjection(ns_vmcb->event_inj.type,
- ns_vmcb->event_inj.vector) )
- ns_vmcb->exit_int_info = ns_vmcb->event_inj;
+ {
+ struct hvm_intack intack = {
+ .source = svm->ns_vmexit.exitinfo1,
+ .vector = svm->ns_vmexit.exitinfo2
+ };
+
+ /* See the comment in svm_intr_assist() for why this is necessary
*/
+ if ( unlikely(vmcb->event_inj.v) ||
+ hvm_interrupt_blocked(v, intack) )
+ {
+ svm_enable_intr_window(v, intack);
+ break;
+ }
+
+ svm_inject_extint(v, intack.vector);
+ pt_intr_post(v, intack);
break;
+ }
+
case VMEXIT_EXCEPTION_PF:
ns_vmcb->_cr2 = ns_vmcb->ei.exc.cr2;
fallthrough;
diff --git a/xen/arch/x86/hvm/svm/svm.h b/xen/arch/x86/hvm/svm/svm.h
index cfa411ad5ae1..186e0905967c 100644
--- a/xen/arch/x86/hvm/svm/svm.h
+++ b/xen/arch/x86/hvm/svm/svm.h
@@ -95,6 +95,9 @@ enum vmcb_sync_state {
void svm_sync_vmcb(struct vcpu *v, enum vmcb_sync_state new_state);
+void svm_inject_extint(struct vcpu *v, int vector);
+void svm_enable_intr_window(struct vcpu *v, struct hvm_intack intack);
+
#endif /* __X86_HVM_SVM_SVM_PRIV_H__ */
/*
--
2.53.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |