Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP1:GA
xen.10697
571f3a56-x86-vMSI-X-avoid-missing-first-unmask-...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 571f3a56-x86-vMSI-X-avoid-missing-first-unmask-of-vectors.patch of Package xen.10697
References: bsc#963161 # Commit 3a6222bd57209d4c2f098d61ace042370a9b0a96 # Date 2016-04-26 11:52:22 +0200 # Author Jan Beulich <jbeulich@suse.com> # Committer Jan Beulich <jbeulich@suse.com> x86/vMSI-X: avoid missing first unmask of vectors Recent changes to Linux result in there just being a single unmask operation prior to expecting the first interrupts to arrive. However, we've had a chicken-and-egg problem here: Qemu invokes xc_domain_update_msi_irq(), ultimately leading to msixtbl_pt_register(), upon seeing that first unmask operation. Yet for msixtbl_range() to return true (in order to msixtbl_write() to get invoked at all) msixtbl_pt_register() must have completed. Deal with this by snooping suitable writes in msixtbl_range() and triggering the invocation of msix_write_completion() from msixtbl_pt_register() when that happens in the context of a still in progress vector control field write. Note that the seemingly unrelated deletion of the redundant irq_desc->msi_desc check in msixtbl_pt_register() is to make clear to any compiler version used that the "msi_desc" local variable isn't being used uninitialized. (Doing the same in msixtbl_pt_unregister() is just for consistency reasons.) Signed-off-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Paul Durrant <paul.durrant@citrix.com> # Commit 9772c480a71ad38cc2c342e4c2e78c2475de7268 # Date 2016-04-26 16:53:36 +0200 # Author Jan Beulich <jbeulich@suse.com> # Committer Jan Beulich <jbeulich@suse.com> x86/vMSI-X: write snoops should ignore hvm_mmio_internal() requests Those aren't actual I/O requests (and hence are of no interest here anyway). Since they don't get copied into struct vcpu, looking at that copy reads whatever was left there. Use the state of the request to determine its validity. Signed-off-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Paul Durrant <paul.durrant@citrix.com> # Commit de8627767968d84385648b399317b1b55323bc15 # Date 2016-04-28 15:10:22 +0200 # Author Jan Beulich <jbeulich@suse.com> # Committer Jan Beulich <jbeulich@suse.com> x86/vMSI-X: add further checks to snoop logic msixtbl_range(), as any other MMIO ->check() handlers, may get called with other than the base address of an access - avoid the snoop logic considering those. Also avoid considering vCPU-s not blocked in the hypervisor in msixtbl_pt_register(), just to be on the safe side. Signed-off-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com> Reviewed-by: Paul Durrant <paul.durrant@citrix.com> --- a/xen/arch/x86/hvm/emulate.c +++ b/xen/arch/x86/hvm/emulate.c @@ -110,6 +110,7 @@ static int hvmemul_do_io( if ( (p_data != NULL) && (dir == IOREQ_WRITE) ) { memcpy(&value, p_data, size); + vio->io_data = value; p_data = NULL; } @@ -184,6 +185,9 @@ static int hvmemul_do_io( vio->io_state = (p_data == NULL) ? HVMIO_dispatched : HVMIO_awaiting_completion; + vio->io_addr = addr; + vio->io_dir = dir; + vio->io_data_is_ptr = value_is_ptr; vio->io_size = size; /* --- a/xen/arch/x86/hvm/vmsi.c +++ b/xen/arch/x86/hvm/vmsi.c @@ -377,7 +377,23 @@ static int msixtbl_range(struct vcpu *v, rcu_read_unlock(&msixtbl_rcu_lock); - return !!virt; + if ( virt ) + return 1; + + if ( (addr & (PCI_MSIX_ENTRY_SIZE - 1)) == + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET ) + { + const struct hvm_vcpu_io *vio = &v->arch.hvm_vcpu.hvm_io; + + if ( vio->io_state != HVMIO_dispatched || vio->io_addr != addr ) + return 0; + if ( vio->io_dir == IOREQ_WRITE && vio->io_size == 4 && + !vio->io_data_is_ptr && + !(vio->io_data & PCI_MSIX_VECTOR_BITMASK) ) + v->arch.hvm_vcpu.hvm_io.msix_snoop_address = addr; + } + + return 0; } const struct hvm_mmio_handler msixtbl_mmio_handler = { @@ -448,9 +464,6 @@ int msixtbl_pt_register(struct domain *d return r; } - if ( !irq_desc->msi_desc ) - goto out; - msi_desc = irq_desc->msi_desc; if ( !msi_desc ) goto out; @@ -475,6 +488,23 @@ found: out: spin_unlock_irq(&irq_desc->lock); xfree(new_entry); + + if ( !r ) + { + struct vcpu *v; + + for_each_vcpu ( d, v ) + { + if ( (v->pause_flags & VPF_blocked_in_xen) && + v->arch.hvm_vcpu.hvm_io.msix_snoop_address == + (gtable + msi_desc->msi_attrib.entry_nr * + PCI_MSIX_ENTRY_SIZE + + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET) ) + v->arch.hvm_vcpu.hvm_io.msix_unmask_address = + v->arch.hvm_vcpu.hvm_io.msix_snoop_address; + } + } + return r; } @@ -492,9 +522,6 @@ void msixtbl_pt_unregister(struct domain if ( !irq_desc ) return; - if ( !irq_desc->msi_desc ) - goto out; - msi_desc = irq_desc->msi_desc; if ( !msi_desc ) goto out; @@ -543,6 +570,8 @@ void msix_write_completion(struct vcpu * { unsigned long ctrl_address = v->arch.hvm_vcpu.hvm_io.msix_unmask_address; + v->arch.hvm_vcpu.hvm_io.msix_snoop_address = 0; + if ( !ctrl_address ) return; --- a/xen/include/asm-x86/hvm/vcpu.h +++ b/xen/include/asm-x86/hvm/vcpu.h @@ -47,7 +47,10 @@ struct hvm_vcpu_asid { struct hvm_vcpu_io { /* I/O request in flight to device model. */ enum hvm_io_state io_state; + unsigned long io_addr; unsigned long io_data; + uint8_t io_dir; + bool_t io_data_is_ptr; int io_size; /* @@ -77,6 +80,7 @@ struct hvm_vcpu_io { bool_t mmio_retry, mmio_retrying; unsigned long msix_unmask_address; + unsigned long msix_snoop_address; }; #define VMCX_EADDR (~0ULL)
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor