Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP1:GA
xen.8005
57238bb9-x86-vMSI-X-also-snoop-REP-MOVS.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 57238bb9-x86-vMSI-X-also-snoop-REP-MOVS.patch of Package xen.8005
References: bsc#963161 # Commit 854c6aab46dec23573ca7dc1a4a03674d2ec63d5 # Date 2016-04-29 18:28:41 +0200 # Author Jan Beulich <jbeulich@suse.com> # Committer Jan Beulich <jbeulich@suse.com> x86/vMSI-X: also snoop REP MOVS ... as at least certain versions of Windows use such to update the MSI-X table. However, to not overly complicate the logic for now - only EFLAGS.DF=0 is being handled, - only updates not crossing MSI-X table entry boundaries are handled. Signed-off-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Paul Durrant <paul.durrant@citrix.com> --- a/xen/arch/x86/hvm/emulate.c +++ b/xen/arch/x86/hvm/emulate.c @@ -110,7 +110,6 @@ static int hvmemul_do_io( if ( (p_data != NULL) && (dir == IOREQ_WRITE) ) { memcpy(&value, p_data, size); - vio->io_data = value; p_data = NULL; } @@ -186,8 +185,10 @@ static int hvmemul_do_io( vio->io_state = (p_data == NULL) ? HVMIO_dispatched : HVMIO_awaiting_completion; vio->io_addr = addr; + vio->io_data = value; vio->io_dir = dir; vio->io_data_is_ptr = value_is_ptr; + vio->io_df = df; vio->io_size = size; /* @@ -202,7 +203,7 @@ static int hvmemul_do_io( p->type = is_mmio ? IOREQ_TYPE_COPY : IOREQ_TYPE_PIO; p->size = size; p->addr = addr; - p->count = *reps; + p->count = vio->io_count = *reps; p->df = df; p->data = value; @@ -222,10 +223,11 @@ static int hvmemul_do_io( /* * p->count may have got reduced (see hvm_mmio_access() and - * process_portio_intercept()) - inform our callers. + * process_portio_intercept()) - inform our callers and mirror this into + * latched state. */ if ( p->count <= *reps ) - *reps = p->count; + *reps = vio->io_count = p->count; switch ( rc ) { --- a/xen/arch/x86/hvm/vmsi.c +++ b/xen/arch/x86/hvm/vmsi.c @@ -386,9 +386,10 @@ static int msixtbl_range(struct vcpu *v, return 0; if ( vio->io_dir == IOREQ_WRITE ) { + unsigned int size = vio->io_size; + if ( !vio->io_data_is_ptr ) { - unsigned int size = vio->io_size; unsigned long data = vio->io_data; if ( size == 8 ) @@ -401,7 +402,30 @@ static int msixtbl_range(struct vcpu *v, ((addr & (PCI_MSIX_ENTRY_SIZE - 1)) == PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET) && !(data & PCI_MSIX_VECTOR_BITMASK) ) + { v->arch.hvm_vcpu.hvm_io.msix_snoop_address = addr; + v->arch.hvm_vcpu.hvm_io.msix_snoop_gpa = 0; + } + } + else if ( (size == 4 || size == 8) && + /* Only support forward REP MOVS for now. */ + !vio->io_df && + /* + * Only fully support accesses to a single table entry for + * now (if multiple ones get written to in one go, only the + * final one gets dealt with). + */ + vio->io_count && + vio->io_count <= PCI_MSIX_ENTRY_SIZE / size && + !((addr + (size * vio->io_count)) & (PCI_MSIX_ENTRY_SIZE - 1)) ) + { + BUILD_BUG_ON((PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET + 4) & + (PCI_MSIX_ENTRY_SIZE - 1)); + + v->arch.hvm_vcpu.hvm_io.msix_snoop_address = + addr + size * vio->io_count - 4; + v->arch.hvm_vcpu.hvm_io.msix_snoop_gpa = + vio->io_data + size * vio->io_count - 4; } } @@ -508,6 +532,7 @@ out: for_each_vcpu ( d, v ) { if ( (v->pause_flags & VPF_blocked_in_xen) && + !v->arch.hvm_vcpu.hvm_io.msix_snoop_gpa && v->arch.hvm_vcpu.hvm_io.msix_snoop_address == (gtable + msi_desc->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + @@ -581,9 +606,29 @@ void msixtbl_pt_cleanup(struct domain *d void msix_write_completion(struct vcpu *v) { unsigned long ctrl_address = v->arch.hvm_vcpu.hvm_io.msix_unmask_address; + unsigned long snoop_addr = v->arch.hvm_vcpu.hvm_io.msix_snoop_address; v->arch.hvm_vcpu.hvm_io.msix_snoop_address = 0; + if ( !ctrl_address && snoop_addr && + v->arch.hvm_vcpu.hvm_io.msix_snoop_gpa ) + { + const void *virt; + uint32_t data; + + rcu_read_lock(&msixtbl_rcu_lock); + virt = msixtbl_addr_to_virt(msixtbl_find_entry(v, snoop_addr), + snoop_addr); + rcu_read_unlock(&msixtbl_rcu_lock); + + if ( virt && + hvm_copy_from_guest_phys(&data, + v->arch.hvm_vcpu.hvm_io.msix_snoop_gpa, + sizeof(data)) == HVMCOPY_okay && + !(data & PCI_MSIX_VECTOR_BITMASK) ) + ctrl_address = snoop_addr; + } + if ( !ctrl_address ) return; --- a/xen/include/asm-x86/hvm/vcpu.h +++ b/xen/include/asm-x86/hvm/vcpu.h @@ -50,8 +50,10 @@ struct hvm_vcpu_io { unsigned long io_addr; unsigned long io_data; uint8_t io_dir; + uint8_t io_df; bool_t io_data_is_ptr; int io_size; + unsigned long io_count; /* * HVM emulation: @@ -81,6 +83,7 @@ struct hvm_vcpu_io { unsigned long msix_unmask_address; unsigned long msix_snoop_address; + unsigned long msix_snoop_gpa; }; #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