# HG changeset patch # User cegger # Date 1281004719 -7200 Implement SVM specific interrupt handling diff -r c6a5143c1c33 -r 092d43f1ba2a xen/arch/x86/hvm/svm/entry.S --- a/xen/arch/x86/hvm/svm/entry.S +++ b/xen/arch/x86/hvm/svm/entry.S @@ -56,6 +56,11 @@ ENTRY(svm_asm_do_resume) call svm_intr_assist get_current(bx) + + movl NESTEDHVM_hostflags(r(bx)),%eax + and $NESTEDHVM_forcevmexit,%eax + jnz svm_stgi_label + CLGI mov VCPU_processor(r(bx)),%eax diff -r c6a5143c1c33 -r 092d43f1ba2a xen/arch/x86/hvm/svm/intr.c --- a/xen/arch/x86/hvm/svm/intr.c +++ b/xen/arch/x86/hvm/svm/intr.c @@ -33,6 +33,7 @@ #include #include #include +#include /* for nestedhvm_vcpu_in_guestmode */ #include #include #include @@ -58,7 +59,7 @@ static void svm_inject_nmi(struct vcpu * */ vmcb->general1_intercepts |= GENERAL1_INTERCEPT_IRET; } - + static void svm_inject_extint(struct vcpu *v, int vector) { struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; @@ -72,7 +73,7 @@ static void svm_inject_extint(struct vcp ASSERT(vmcb->eventinj.fields.v == 0); vmcb->eventinj = event; } - + static void enable_intr_window(struct vcpu *v, struct hvm_intack intack) { struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; @@ -117,15 +118,46 @@ asmlinkage void svm_intr_assist(void) struct vcpu *v = current; struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; struct hvm_intack intack; + enum hvm_intblk intblk; /* Crank the handle on interrupt state. */ pt_update_irq(v); do { + int rc; + intack = hvm_vcpu_has_pending_irq(v); if ( likely(intack.source == hvm_intsrc_none) ) return; + intblk = hvm_interrupt_blocked(v, intack); + if ( intblk == hvm_intblk_gif ) { + ASSERT(nestedhvm_enabled(v->domain)); + return; + } + + /* Interrupts for the nested guest are already + * in the vmcb. + */ + if ( nestedhvm_enabled(v->domain) && nestedhvm_vcpu_in_guestmode(v) ) + { + rc = nestedhvm_vcpu_interrupt(v, intack); + switch (rc) { + case NESTEDHVM_INTR_NOTINTERCEPTED: + /* Inject interrupt into 2nd level guest directly. */ + break; + case NESTEDHVM_INTR_NOTHANDLED: + case NESTEDHVM_INTR_FORCEVMEXIT: + return; + case NESTEDHVM_INTR_MASKED: + /* Guest already enabled an interrupt window. */ + return; + default: + panic("%s: nestedhvm_vcpu_interrupt can't handle value 0x%x\n", + __func__, rc); + } + } + /* * Pending IRQs must be delayed if: * 1. An event is already pending. This is despite the fact that SVM @@ -140,8 +172,7 @@ asmlinkage void svm_intr_assist(void) * have cleared the interrupt out of the IRR. * 2. The IRQ is masked. */ - if ( unlikely(vmcb->eventinj.fields.v) || - hvm_interrupt_blocked(v, intack) ) + if ( unlikely(vmcb->eventinj.fields.v) || intblk ) { enable_intr_window(v, intack); return;