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

Re: [Xen-devel] [PATCH v3 08/13] xen/passthrough: iommu: Basic support of device tree assignment



>>> On 11.03.14 at 16:49, Julien Grall <julien.grall@xxxxxxxxxx> wrote:
> Add IOMMU helpers to support device tree assignment/deassignment. This patch
> introduces 2 new fields in the dt_device_node:
>     - is_protected: Does the device is protected by an IOMMU
>     - next_assigned: Pointer to the next device assigned to the same
>     domain
> 
> Signed-off-by: Julien Grall <julien.grall@xxxxxxxxxx>
> Cc: Xiantao Zhang <xiantao.zhang@xxxxxxxxx>

For the modifications to existing files:
Acked-by: Jan Beulich <jbeulich@xxxxxxxx>

> 
> ---
>     Changes in v3:
>         - Remove iommu_dt_domain_{init,destroy} call in common code. Let
>         architecture code to call them
>         - Fix indentation in xen/include/xen/hvm/iommu.h
>     Changes in v2:
>         - Patch added
> ---
>  xen/common/device_tree.c              |    4 ++
>  xen/drivers/passthrough/Makefile      |    1 +
>  xen/drivers/passthrough/device_tree.c |  106 
> +++++++++++++++++++++++++++++++++
>  xen/include/xen/device_tree.h         |   14 +++++
>  xen/include/xen/hvm/iommu.h           |    6 ++
>  xen/include/xen/iommu.h               |   16 +++++
>  6 files changed, 147 insertions(+)
>  create mode 100644 xen/drivers/passthrough/device_tree.c
> 
> diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
> index 564f2bb..7c6b683 100644
> --- a/xen/common/device_tree.c
> +++ b/xen/common/device_tree.c
> @@ -1695,6 +1695,10 @@ static unsigned long __init unflatten_dt_node(const 
> void *fdt,
>          np->full_name = ((char *)np) + sizeof(struct dt_device_node);
>          /* By default dom0 owns the device */
>          np->used_by = 0;
> +        /* By default the device is not protected */
> +        np->is_protected = false;
> +        INIT_LIST_HEAD(&np->next_assigned);
> +
>          if ( new_format )
>          {
>              char *fn = np->full_name;
> diff --git a/xen/drivers/passthrough/Makefile 
> b/xen/drivers/passthrough/Makefile
> index 6e08f89..5a0a35e 100644
> --- a/xen/drivers/passthrough/Makefile
> +++ b/xen/drivers/passthrough/Makefile
> @@ -5,3 +5,4 @@ subdir-$(x86_64) += x86
>  obj-y += iommu.o
>  obj-$(x86) += io.o
>  obj-$(HAS_PCI) += pci.o
> +obj-$(HAS_DEVICE_TREE) += device_tree.o
> diff --git a/xen/drivers/passthrough/device_tree.c 
> b/xen/drivers/passthrough/device_tree.c
> new file mode 100644
> index 0000000..7384e73
> --- /dev/null
> +++ b/xen/drivers/passthrough/device_tree.c
> @@ -0,0 +1,106 @@
> +/*
> + * xen/drivers/passthrough/arm/device_tree.c
> + *
> + * Code to passthrough device tree node to a guest
> + *
> + * Julien Grall <julien.grall@xxxxxxxxxx>
> + * Copyright (c) 2014 Linaro Limited.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <xen/lib.h>
> +#include <xen/sched.h>
> +#include <xen/iommu.h>
> +#include <xen/device_tree.h>
> +
> +static spinlock_t dtdevs_lock = SPIN_LOCK_UNLOCKED;
> +
> +int iommu_assign_dt_device(struct domain *d, struct dt_device_node *dev)
> +{
> +    int rc = -EBUSY;
> +    struct hvm_iommu *hd = domain_hvm_iommu(d);
> +
> +    if ( !iommu_enabled || !hd->platform_ops )
> +        return -EINVAL;
> +
> +    if ( !dt_device_is_protected(dev) )
> +        return -EINVAL;
> +
> +    spin_lock(&dtdevs_lock);
> +
> +    if ( !list_empty(&dev->next_assigned) )
> +        goto fail;
> +
> +    rc = hd->platform_ops->assign_dt_device(d, dev);
> +
> +    if ( rc )
> +        goto fail;
> +
> +    list_add(&dev->next_assigned, &hd->dt_devices);
> +    dt_device_set_used_by(dev, d->domain_id);
> +
> +fail:
> +    spin_unlock(&dtdevs_lock);
> +
> +    return rc;
> +}
> +
> +int iommu_deassign_dt_device(struct domain *d, struct dt_device_node *dev)
> +{
> +    struct hvm_iommu *hd = domain_hvm_iommu(d);
> +    int rc;
> +
> +    if ( !iommu_enabled || !hd->platform_ops )
> +        return -EINVAL;
> +
> +    if ( !dt_device_is_protected(dev) )
> +        return -EINVAL;
> +
> +    spin_lock(&dtdevs_lock);
> +
> +    rc = hd->platform_ops->reassign_dt_device(d, dom0, dev);
> +    if ( rc )
> +        goto fail;
> +
> +    dt_device_set_used_by(dev, dom0->domain_id);
> +
> +    list_del(&dev->next_assigned);
> +
> +fail:
> +    spin_unlock(&dtdevs_lock);
> +
> +    return rc;
> +}
> +
> +int iommu_dt_domain_init(struct domain *d)
> +{
> +    struct hvm_iommu *hd = domain_hvm_iommu(d);
> +
> +    INIT_LIST_HEAD(&hd->dt_devices);
> +
> +    return 0;
> +}
> +
> +void iommu_dt_domain_destroy(struct domain *d)
> +{
> +    struct hvm_iommu *hd = domain_hvm_iommu(d);
> +    struct dt_device_node *dev, *_dev;
> +    int rc;
> +
> +    list_for_each_entry_safe(dev, _dev, &hd->dt_devices, next_assigned)
> +    {
> +        rc = iommu_deassign_dt_device(d, dev);
> +        if ( rc )
> +            dprintk(XENLOG_ERR, "Failed to deassign %s in domain %u\n",
> +                    dt_node_full_name(dev), d->domain_id);
> +    }
> +}
> diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
> index d429e60..2aae047 100644
> --- a/xen/include/xen/device_tree.h
> +++ b/xen/include/xen/device_tree.h
> @@ -16,6 +16,7 @@
>  #include <xen/string.h>
>  #include <xen/types.h>
>  #include <xen/stdbool.h>
> +#include <xen/list.h>
>  
>  #define DEVICE_TREE_MAX_DEPTH 16
>  
> @@ -110,6 +111,9 @@ struct dt_device_node {
>      struct dt_device_node *next; /* TODO: Remove it. Only use to know the 
> last children */
>      struct dt_device_node *allnext;
>  
> +    /* IOMMU specific fields */
> +    bool is_protected; /* Tell if the device is protected by an IOMMU */
> +    struct list_head next_assigned;
>  };
>  
>  #define MAX_PHANDLE_ARGS 16
> @@ -325,6 +329,16 @@ static inline domid_t dt_device_used_by(const struct 
> dt_device_node *device)
>      return device->used_by;
>  }
>  
> +static inline void dt_device_set_protected(struct dt_device_node *device)
> +{
> +    device->is_protected = true;
> +}
> +
> +static inline bool dt_device_is_protected(const struct dt_device_node 
> *device)
> +{
> +    return device->is_protected;
> +}
> +
>  static inline bool_t dt_property_name_is_equal(const struct dt_property 
> *pp,
>                                                 const char *name)
>  {
> diff --git a/xen/include/xen/hvm/iommu.h b/xen/include/xen/hvm/iommu.h
> index f8f8a93..1259e16 100644
> --- a/xen/include/xen/hvm/iommu.h
> +++ b/xen/include/xen/hvm/iommu.h
> @@ -21,6 +21,7 @@
>  #define __XEN_HVM_IOMMU_H__
>  
>  #include <xen/iommu.h>
> +#include <xen/list.h>
>  #include <asm/hvm/iommu.h>
>  
>  struct hvm_iommu {
> @@ -28,6 +29,11 @@ struct hvm_iommu {
>  
>      /* iommu_ops */
>      const struct iommu_ops *platform_ops;
> +
> +#ifdef HAS_DEVICE_TREE
> +    /* List of DT devices assigned to this domain */
> +    struct list_head dt_devices;
> +#endif
>  };
>  
>  #endif /* __XEN_HVM_IOMMU_H__ */
> diff --git a/xen/include/xen/iommu.h b/xen/include/xen/iommu.h
> index f556a7e..56f6c5c 100644
> --- a/xen/include/xen/iommu.h
> +++ b/xen/include/xen/iommu.h
> @@ -82,6 +82,16 @@ bool_t pt_irq_need_timer(uint32_t flags);
>  #define PT_IRQ_TIME_OUT MILLISECS(8)
>  #endif /* HAS_PCI */
>  
> +#ifdef HAS_DEVICE_TREE
> +#include <xen/device_tree.h>
> +
> +int iommu_assign_dt_device(struct domain *d, struct dt_device_node *dev);
> +int iommu_deassign_dt_device(struct domain *d, struct dt_device_node *dev);
> +int iommu_dt_domain_init(struct domain *d);
> +void iommu_dt_domain_destroy(struct domain *d);
> +
> +#endif /* HAS_DEVICE_TREE */
> +
>  #ifdef HAS_PCI
>  struct msi_desc;
>  struct msi_msg;
> @@ -103,6 +113,12 @@ struct iommu_ops {
>      int (*update_ire_from_msi)(struct msi_desc *msi_desc, struct msi_msg 
> *msg);
>      void (*read_msi_from_ire)(struct msi_desc *msi_desc, struct msi_msg 
> *msg);
>  #endif /* HAS_PCI */
> +#ifdef HAS_DEVICE_TREE
> +    int (*assign_dt_device)(struct domain *d, const struct dt_device_node 
> *dev);
> +    int (*reassign_dt_device)(struct domain *s, struct domain *t,
> +                              const struct dt_device_node *dev);
> +#endif
> +
>      void (*teardown)(struct domain *d);
>      int (*map_page)(struct domain *d, unsigned long gfn, unsigned long mfn,
>                      unsigned int flags);
> -- 
> 1.7.10.4



_______________________________________________
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®.