[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH v2] x86: properly handle MSI-X unmask operation from guests



There are some issues in this version, please ignore this one, I will send out 
a new version soon!

> -----Original Message-----
> From: xen-devel-bounces@xxxxxxxxxxxxx
> [mailto:xen-devel-bounces@xxxxxxxxxxxxx] On Behalf Of Wu, Feng
> Sent: Thursday, November 21, 2013 9:29 AM
> To: Jan Beulich (JBeulich@xxxxxxxx); xen-devel@xxxxxxxxxxxxx
> Cc: Auld, Will; Zhang, Xiantao; Nakajima, Jun
> Subject: [Xen-devel] [PATCH v2] x86: properly handle MSI-X unmask operation
> from guests
> 
> patch revision history
> ----------------------
> v1: Initial patch to handle this issue involving changing the hypercall 
> interface
> v2: Totally handled inside hypervisor, need to add a MSI-X specific handler 
> in the
> general I/O emulation path.
> 
> From fb9b39754da87c895a8d00efebd5aa557cfc1216 Mon Sep 17 00:00:00
> 2001
> From: Feng Wu <feng.wu@xxxxxxxxx>
> Date: Wed, 13 Nov 2013 21:43:48 -0500
> Subject: [PATCH] x86: properly handle MSI-X unmask operation from guests
> 
> For a pass-through device with MSI-x capability, when guest tries
> to unmask the MSI-x interrupt for the passed through device, xen
> doesn't clear the mask bit for MSI-x in hardware in the following
> scenario, which will cause network disconnection:
> 
> 1. Guest masks the MSI-x interrupt
> 2. Guest updates the address and data for it
> 3. Guest unmasks the MSI-x interrupt (This is the problematic step)
> 
> In the step #3 above, Xen doesn't handle it well. When guest tries
> to unmask MSI-X interrupt, it traps to Xen, Xen just returns to Qemu
> if it notices that address or data has been modified by guest before,
> then Qemu will update Xen with the latest value of address/data by
> hypercall. However, in this whole process, the MSI-X interrupt unmask
> operation is missing, which means Xen doesn't clear the mask bit in
> hardware for the MSI-X interrupt, so it remains disabled, that is why
> it loses the network connection.
> 
> This patch fixes this issue.
> 
> Signed-off-by: Feng Wu <feng.wu@xxxxxxxxx>
> ---
>  xen/arch/x86/domain.c        |    2 ++
>  xen/arch/x86/hvm/io.c        |    3 +++
>  xen/arch/x86/hvm/vmsi.c      |   40
> +++++++++++++++++++++++++++++++++++++++-
>  xen/include/asm-x86/domain.h |    8 ++++++++
>  xen/include/xen/pci.h        |    1 +
>  5 files changed, 53 insertions(+), 1 deletions(-)
> 
> diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
> index b67fcb8..eb3de90 100644
> --- a/xen/arch/x86/domain.c
> +++ b/xen/arch/x86/domain.c
> @@ -374,6 +374,8 @@ int vcpu_initialise(struct vcpu *v)
> 
>      v->arch.flags = TF_kernel_mode;
> 
> +    spin_lock_init(&v->arch.pending_msix_unmask.lock);
> +
>      rc = mapcache_vcpu_init(v);
>      if ( rc )
>      if ( rc )
>          return rc;
> diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c
> index 6e344e4..06fcd43 100644
> --- a/xen/arch/x86/hvm/io.c
> +++ b/xen/arch/x86/hvm/io.c
> @@ -288,6 +288,9 @@ void hvm_io_assist(void)
>          break;
>      }
> 
> +    if (msix_post_handler(curr->domain))
> +        gdprintk(XENLOG_ERR, ": msix_post_handler error\n");
> +
>      if ( p->state == STATE_IOREQ_NONE )
>          vcpu_end_shutdown_deferral(curr);
>  }
> diff --git a/xen/arch/x86/hvm/vmsi.c b/xen/arch/x86/hvm/vmsi.c
> index 4826b4a..36f27fc 100644
> --- a/xen/arch/x86/hvm/vmsi.c
> +++ b/xen/arch/x86/hvm/vmsi.c
> @@ -292,8 +292,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 ( test_and_clear_bit(nr_entry, &entry->table_flags) ) {
> +        v->arch.pending_msix_unmask.valid = 1;
> +        v->arch.pending_msix_unmask.ctrl_address = address;
>          goto out;
> +    }
> 
>      virt = msixtbl_addr_to_virt(entry, address);
>      if ( !virt )
> @@ -528,3 +531,38 @@ void msixtbl_pt_cleanup(struct domain *d)
>      spin_unlock(&d->arch.hvm_domain.msixtbl_list_lock);
>      local_irq_restore(flags);
>  }
> +
> +int msix_post_handler(struct domain *d)
> +{
> +    int rc;
> +    unsigned long flags;
> +    struct vcpu *v;
> +
> +    for_each_vcpu(d, v) {
> +
> +        /*
> +         * v->arch.pending_msix_unmask.valid may be checked on other
> cpus
> +         * at the same time, we need to add spinlock to protect it
> +         */
> +
> +        spin_lock_irqsave(&v->arch.pending_msix_unmask.lock, flags);
> +
> +        if (v->arch.pending_msix_unmask.valid == 0) {
> +            spin_unlock_irqrestore(&v->arch.pending_msix_unmask.lock,
> flags);
> +            return 0;
> +        }
> +
> +        v->arch.pending_msix_unmask.valid = 0;
> +
> +        spin_unlock_irqrestore(&v->arch.pending_msix_unmask.lock,
> flags);
> +
> +        rc = msixtbl_write(v, v->arch.pending_msix_unmask.ctrl_address, 4,
> 0);
> +        if (rc != X86EMUL_OKAY)
> +            return -1;
> +        else
> +            return 0;
> +    }
> +
> +    return 0;
> +}
> +
> diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h
> index e42651e..844aadc 100644
> --- a/xen/include/asm-x86/domain.h
> +++ b/xen/include/asm-x86/domain.h
> @@ -376,6 +376,12 @@ struct pv_vcpu
>      spinlock_t shadow_ldt_lock;
>  };
> 
> +struct pending_msix_unmask_info {
> +    int valid;
> +    unsigned long ctrl_address;
> +    spinlock_t lock;
> +};
> +
>  struct arch_vcpu
>  {
>      /*
> @@ -440,6 +446,8 @@ struct arch_vcpu
> 
>      /* A secondary copy of the vcpu time info. */
>      XEN_GUEST_HANDLE(vcpu_time_info_t) time_info_guest;
> +
> +    struct pending_msix_unmask_info pending_msix_unmask;
>  } __cacheline_aligned;
> 
>  /* Shorthands to improve code legibility. */
> diff --git a/xen/include/xen/pci.h b/xen/include/xen/pci.h
> index cadb525..649b869 100644
> --- a/xen/include/xen/pci.h
> +++ b/xen/include/xen/pci.h
> @@ -147,5 +147,6 @@ struct pirq;
>  int msixtbl_pt_register(struct domain *, struct pirq *, uint64_t gtable);
>  void msixtbl_pt_unregister(struct domain *, struct pirq *);
>  void msixtbl_pt_cleanup(struct domain *d);
> +int msix_post_handler(struct domain *d);
> 
>  #endif /* __XEN_PCI_H__ */
> --
> 1.7.1
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@xxxxxxxxxxxxx
> http://lists.xen.org/xen-devel

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.