diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c index 15e0b4c0ae..bf6309de26 100644 --- a/xen/arch/x86/hvm/io.c +++ b/xen/arch/x86/hvm/io.c @@ -300,7 +300,10 @@ void hvm_io_assist(ioreq_t *p) } if ( p->state == STATE_IOREQ_NONE ) + { + msix_write_completion(curr); vcpu_end_shutdown_deferral(curr); + } } static int dpci_ioport_read(uint32_t mport, ioreq_t *p) diff --git a/xen/arch/x86/hvm/vmsi.c b/xen/arch/x86/hvm/vmsi.c index 4826b4ad77..10e5f34954 100644 --- a/xen/arch/x86/hvm/vmsi.c +++ b/xen/arch/x86/hvm/vmsi.c @@ -293,7 +293,11 @@ static int msixtbl_write(struct vcpu *v, unsigned long address, /* exit to device model if address/data has been modified */ if ( test_and_clear_bit(nr_entry, &entry->table_flags) ) + { + if ( !(val & PCI_MSIX_VECTOR_BITMASK) ) + v->arch.hvm_vcpu.hvm_io.msix_unmask_address = address; goto out; + } virt = msixtbl_addr_to_virt(entry, address); if ( !virt ) @@ -528,3 +532,15 @@ void msixtbl_pt_cleanup(struct domain *d) spin_unlock(&d->arch.hvm_domain.msixtbl_list_lock); local_irq_restore(flags); } + +void msix_write_completion(struct vcpu *v) +{ + unsigned long ctrl_address = v->arch.hvm_vcpu.hvm_io.msix_unmask_address; + + if ( !ctrl_address ) + return; + + v->arch.hvm_vcpu.hvm_io.msix_unmask_address = 0; + if ( msixtbl_write(v, ctrl_address, 4, 0) != X86EMUL_OKAY ) + gdprintk(XENLOG_WARNING, "MSI-X write completion failure\n"); +} diff --git a/xen/include/asm-x86/hvm/io.h b/xen/include/asm-x86/hvm/io.h index 6f4cb96408..86db58de0a 100644 --- a/xen/include/asm-x86/hvm/io.h +++ b/xen/include/asm-x86/hvm/io.h @@ -124,6 +124,7 @@ void hvm_interrupt_post(struct vcpu *v, int vector, int type); void hvm_io_assist(ioreq_t *p); void hvm_dpci_eoi(struct domain *d, unsigned int guest_irq, union vioapic_redir_entry *ent); +void msix_write_completion(struct vcpu *); struct hvm_hw_stdvga { uint8_t sr_index; diff --git a/xen/include/asm-x86/hvm/vcpu.h b/xen/include/asm-x86/hvm/vcpu.h index a309389187..4f45060e7f 100644 --- a/xen/include/asm-x86/hvm/vcpu.h +++ b/xen/include/asm-x86/hvm/vcpu.h @@ -74,6 +74,8 @@ struct hvm_vcpu_io { * necessary retry through other than function return codes. */ bool_t mmio_retry, mmio_retrying; + + unsigned long msix_unmask_address; }; #define VMCX_EADDR (~0ULL)