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

Re: [PATCH v5 20/22] xen/arm: vIOMMU vSID->pSID mapping layer


  • To: Milan Djokic <milan_djokic@xxxxxxxx>
  • From: Mykyta Poturai <Mykyta_Poturai@xxxxxxxx>
  • Date: Tue, 10 Nov 2026 09:57:28 +0000
  • Accept-language: en-US
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=epam.com; dmarc=pass action=none header.from=epam.com; dkim=pass header.d=epam.com; arc=none
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=YR8RkwZxtdX8uP8dmfZNQxtrb2BBOkdj4QS60eDZTSU=; b=b+42EWwxjPhzOP6dvHKqRlT0yuMGkZVdhYzjTluORTwSAm7bMwXqnZL/WCsXrryknkqi0uFi7jVxsLCaoYMOEAsJtID40n95isH7HiwMbIjdYMN6Q4nH+5pPnml34iGuCfLRGW7huPZSiZWZaFlAjAS5a8yW/7PrVN+5TTaqrLazNeIXARJNi0TKJtwrJ4AwZRJ90cJfWm2osqplhV2a9IvuvNYS7Mw7NwDp59ULMb4NXfjlTJbKZG/azBTlNhYJtvrRC2aJ/o99XcnrgpI4Ty2QvVm3mQrrMEtAjDfMycFx5E/z7wXxmM7nvvZJ0PlBZ8r7+KLB26C/7z0aFb8Y7g==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=k4m+GtRUfAVm5wmX+/gdB5IXC/dQBEEn525hDyzCt2DEoJgYF9tg5myy6qhtOJA6JBJZCarOWF4z3sjoTT1jcy9x8IAgy2tr8qrMNWwGtSygxsE8rIauh4PpwXi2ia1ZDwCxoNw/KfakRUVIkIrm0UxFL3UX05tvINV+AFKQ2vNiQ2/6i9jwnN75uowudDN6/5Wm+QgT47eMvk3z/PU0EFGMG3U+Xa4uM0NSWeyxtY5B2iOkeuqGPaVEhbx+3vLOKHRNGS6SYo5iwu/afstPMOL/kZkiGOGL5H1pbjJmac9joEpZGpX4COZ3uyHrtx06oQmY64TKtj2T1s7zeYCyvw==
  • Authentication-results: eu.smtp.expurgate.cloud; dkim=pass header.s=selector1 header.d=epam.com header.i="@epam.com" header.h="From:Date:Subject:Message-ID:Content-Type:MIME-Version:x-ms-exchange-senderadcheck"
  • Authentication-results: mx.microsoft.com 1; dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=epam.com;
  • Cc: Mykyta Poturai <Mykyta_Poturai@xxxxxxxx>, "xen-devel@xxxxxxxxxxxxxxxxxxxx" <xen-devel@xxxxxxxxxxxxxxxxxxxx>, Stefano Stabellini <sstabellini@xxxxxxxxxx>, Julien Grall <julien@xxxxxxx>, Bertrand Marquis <bertrand.marquis@xxxxxxx>, Michal Orzel <michal.orzel@xxxxxxx>, Volodymyr Babchuk <Volodymyr_Babchuk@xxxxxxxx>, Rahul Singh <rahul.singh@xxxxxxx>, Jan Beulich <jbeulich@xxxxxxxx>, Roger Pau Monné <roger@xxxxxxxxxxxxxx>
  • Delivery-date: Tue, 10 Nov 2026 09:57:54 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>
  • Thread-index: AQHda7koX4FG1lKLjU2XVKKJzideWbcnHCwA
  • Thread-topic: [PATCH v5 20/22] xen/arm: vIOMMU vSID->pSID mapping layer

On Tue, Nov 03, 2026 at 17:30:54 +0000, Milan Djokic wrote:
> Introduce a vIOMMU mapping layer to support passthrough of IOMMU devices
> attached to different physical IOMMUs, including devices with the same
> Stream ID.
>
> Add a new generic vIOMMU API, viommu_allocate_vsid(), which allocates a
> guest vSID and maps it to the input pSID and the backing physical SMMU.
>
> Once the mapping is established, the guest uses the vSID for stage-1
> commands, and Xen translates the vSID to the corresponding pSID before
> processing the command on the physical SMMU.
>
> Implement usage of the new API for dom0less guests. Allocate vSIDs when
> creating the guest device tree and replace the original pSIDs with vSIDs
> that are subsequently used by the guest driver.
>
> Signed-off-by: Milan Djokic <milan_djokic@xxxxxxxx>
> ---
>  xen/arch/arm/include/asm/viommu.h       |  12 ++
>  xen/common/device-tree/dom0less-build.c |  35 +++--
>  xen/drivers/passthrough/arm/smmu-v3.c   |  10 +-
>  xen/drivers/passthrough/arm/viommu.c    |   9 ++
>  xen/drivers/passthrough/arm/vsmmu-v3.c  | 184 +++++++++++++++++++++++-
>  xen/include/xen/iommu.h                 |   6 +-
>  6 files changed, 242 insertions(+), 14 deletions(-)
>
> diff --git a/xen/arch/arm/include/asm/viommu.h 
> b/xen/arch/arm/include/asm/viommu.h
> index 5ae21042f0..3d0eb92655 100644
> --- a/xen/arch/arm/include/asm/viommu.h
> +++ b/xen/arch/arm/include/asm/viommu.h
> @@ -34,6 +34,16 @@ struct viommu_ops {
>       * Called during domain destruction to free resources used by vIOMMU.
>       */
>      int (*relinquish_resources)(struct domain *d);
> +
> +    /*
> +     * Allocate free vSID/vRID for the guest device and establish vID->pID 
> mapping
> +     * Called during domain device assignment.
> +     * Returns 0 on success and sets vsid argument to newly allocated 
> vSID/vRID
> +     * mapped to physical ID (id argument).
> +     * Negative error code returned if allocation fails.
> +     */
> +    int (*allocate_vsid)(struct domain *d, uint32_t id, uint32_t phandle,
> +                         uint32_t *vsid);
>  };
>
>  struct viommu_desc {
> @@ -54,6 +64,8 @@ extern struct list_head host_iommu_list;
>  int domain_viommu_init(struct domain *d, uint8_t viommu_type);
>  int viommu_relinquish_resources(struct domain *d);
>  uint8_t viommu_get_type(void);
> +int viommu_allocate_vsid(struct domain *d, uint32_t id, uint32_t phandle,
> +                         uint32_t *vsid);
>  void add_to_host_iommu_list(paddr_t addr, paddr_t size,
>                              const struct dt_device_node *node,
>                              const void *iommu);
> diff --git a/xen/common/device-tree/dom0less-build.c 
> b/xen/common/device-tree/dom0less-build.c
> index 970f89ef68..3b2a888698 100644
> --- a/xen/common/device-tree/dom0less-build.c
> +++ b/xen/common/device-tree/dom0less-build.c
> @@ -32,6 +32,10 @@
>  #include <xen/static-memory.h>
>  #include <xen/static-shmem.h>
>
> +#ifdef CONFIG_ARM_VIRTUAL_IOMMU
> +#include <asm/viommu.h>
> +#endif
> +
>  #define XENSTORE_PFN_LATE_ALLOC UINT64_MAX
>
>  static domid_t __initdata xs_domid = DOMID_INVALID;
> @@ -333,11 +337,12 @@ static int __init handle_prop_pfdt(struct kernel_info 
> *kinfo,
>  }
>
>  #ifdef CONFIG_ARM_VIRTUAL_IOMMU
> -static int __init modify_pfdt_node(void *pfdt, int nodeoff)
> +static int __init modify_pfdt_node(void *pfdt, int nodeoff, struct domain *d)
>  {
>      int proplen, i, rc;
>      const fdt32_t *prop;
>      fdt32_t *prop_c;
> +    uint32_t psid, phandle, vsid;
>
>      prop = fdt_getprop(pfdt, nodeoff, "iommus", &proplen);
>      if ( !prop )
> @@ -347,10 +352,23 @@ static int __init modify_pfdt_node(void *pfdt, int 
> nodeoff)
>      if ( !prop_c )
>          return -ENOMEM;
>
> +    /*
> +     * Assign <vIOMMU vSID> pairs to iommus property and establish
> +     * vSID->pSID mappings
> +     */
>      for ( i = 0; i < proplen / 8; ++i )
>      {
> +        phandle = fdt32_to_cpu(prop[i * 2]);
> +        psid = fdt32_to_cpu(prop[i * 2 + 1]);
> +        rc = viommu_allocate_vsid(d, psid, phandle, &vsid);
> +        if ( rc )
> +        {
> +            dprintk(XENLOG_ERR, "(DOMID=%u) Failed to allocate vSID for "
> +                    "pSID: %u, pIOMMU: %u", d->domain_id, psid, phandle);

Missing \n?

> +            goto out;
> +        }
>          prop_c[i * 2] = cpu_to_fdt32(GUEST_PHANDLE_VSMMUV3);
> -        prop_c[i * 2 + 1] = prop[i * 2 + 1];
> +        prop_c[i * 2 + 1] = cpu_to_fdt32(vsid);
>      }
>
>      rc = fdt_setprop(pfdt, nodeoff, "iommus", prop_c, proplen);
> @@ -365,7 +383,8 @@ static int __init modify_pfdt_node(void *pfdt, int 
> nodeoff)
>      return rc;
>  }
>  #else
> -static inline int __init modify_pfdt_node(void *pfdt, int nodeoff)
> +static inline int __init modify_pfdt_node(void *pfdt, int nodeoff,
> +                                          struct domain *d)
>  {
>      return -EOPNOTSUPP;
>  }
> @@ -374,7 +393,7 @@ static inline int __init modify_pfdt_node(void *pfdt, int 
> nodeoff)
>  static int __init scan_pfdt_node(struct kernel_info *kinfo, void *pfdt,
>                                   int nodeoff,
>                                   uint32_t address_cells, uint32_t size_cells,
> -                                 bool scan_passthrough_prop)
> +                                 bool scan_passthrough_prop, struct domain 
> *d)
>  {
>      int rc = 0;
>      void *fdt = kinfo->fdt;
> @@ -397,12 +416,12 @@ static int __init scan_pfdt_node(struct kernel_info 
> *kinfo, void *pfdt,
>      node_next = fdt_first_subnode(pfdt, nodeoff);
>      while ( node_next > 0 )
>      {
> -        rc = modify_pfdt_node(pfdt, node_next);
> +        rc = modify_pfdt_node(pfdt, node_next, d);
>          if ( rc )
>              return rc;
>
>          rc = scan_pfdt_node(kinfo, pfdt, node_next, address_cells, 
> size_cells,
> -                            scan_passthrough_prop);
> +                            scan_passthrough_prop, d);
>          if ( rc )
>              return rc;
>
> @@ -489,7 +508,7 @@ static int __init domain_handle_dtb_boot_module(struct 
> domain *d,
>              res = scan_pfdt_node(kinfo, pfdt, node_next,
>                                   DT_ROOT_NODE_ADDR_CELLS_DEFAULT,
>                                   DT_ROOT_NODE_SIZE_CELLS_DEFAULT,
> -                                 false);
> +                                 false, d);
>              if ( res )
>                  goto out;
>              continue;
> @@ -499,7 +518,7 @@ static int __init domain_handle_dtb_boot_module(struct 
> domain *d,
>              res = scan_pfdt_node(kinfo, pfdt, node_next,
>                                   DT_ROOT_NODE_ADDR_CELLS_DEFAULT,
>                                   DT_ROOT_NODE_SIZE_CELLS_DEFAULT,
> -                                 true);
> +                                 true, d);
>              if ( res )
>                  goto out;
>              continue;
> diff --git a/xen/drivers/passthrough/arm/smmu-v3.c 
> b/xen/drivers/passthrough/arm/smmu-v3.c
> index f213b3de12..b0ec004960 100644
> --- a/xen/drivers/passthrough/arm/smmu-v3.c
> +++ b/xen/drivers/passthrough/arm/smmu-v3.c
> @@ -3103,7 +3103,7 @@ static struct arm_smmu_device 
> *arm_smmu_get_by_dev(const struct device *dev)
>  }
>
>  static struct iommu_domain *arm_smmu_get_domain_by_sid(struct domain *d,
> -                             u32 sid)
> +                             u32 sid, const struct arm_smmu_device *smmu)
>  {
>       int i;
>       unsigned long flags;
> @@ -3119,6 +3119,9 @@ static struct iommu_domain 
> *arm_smmu_get_domain_by_sid(struct domain *d,
>       list_for_each_entry(io_domain, &xen_domain->contexts, list) {
>               smmu_domain = to_smmu_domain(io_domain);
>
> +             if (smmu_domain->smmu != smmu)
> +                     continue;
> +
>               spin_lock_irqsave(&smmu_domain->devices_lock, flags);
>               list_for_each_entry(master, &smmu_domain->devices, domain_head) 
> {
>                       for (i = 0; i < master->num_streams; i++) {
> @@ -3347,7 +3350,8 @@ static void arm_smmu_iommu_xen_domain_teardown(struct 
> domain *d)
>  }
>
>  static int arm_smmu_attach_guest_config(struct domain *d, uint32_t sid,
> -             const struct iommu_guest_config *cfg)
> +                             const struct iommu_guest_config *cfg,
> +                             const struct arm_smmu_device *smmu)
>  {
>       int ret = -EINVAL;
>       unsigned long flags;
> @@ -3357,7 +3361,7 @@ static int arm_smmu_attach_guest_config(struct domain 
> *d, uint32_t sid,
>       struct iommu_domain *io_domain;
>
>       spin_lock(&xen_domain->lock);
> -     io_domain = arm_smmu_get_domain_by_sid(d, sid);
> +     io_domain = arm_smmu_get_domain_by_sid(d, sid, smmu);
>       if (!io_domain) {
>               ret = -ENODEV;
>               goto out;
> diff --git a/xen/drivers/passthrough/arm/viommu.c 
> b/xen/drivers/passthrough/arm/viommu.c
> index b4b91ab1cb..e476567b49 100644
> --- a/xen/drivers/passthrough/arm/viommu.c
> +++ b/xen/drivers/passthrough/arm/viommu.c
> @@ -76,6 +76,15 @@ int viommu_relinquish_resources(struct domain *d)
>      return cur_viommu->ops->relinquish_resources(d);
>  }
>
> +int viommu_allocate_vsid(struct domain *d, uint32_t id, uint32_t phandle,
> +                         uint32_t *vsid)
> +{
> +    if ( !cur_viommu )
> +        return -ENODEV;
> +
> +    return cur_viommu->ops->allocate_vsid(d, id, phandle, vsid);
> +}
> +
>  uint8_t viommu_get_type(void)
>  {
>      if ( !cur_viommu || host_iommu_list_incomplete ||
> diff --git a/xen/drivers/passthrough/arm/vsmmu-v3.c 
> b/xen/drivers/passthrough/arm/vsmmu-v3.c
> index 24588affe9..5d225ccc08 100644
> --- a/xen/drivers/passthrough/arm/vsmmu-v3.c
> +++ b/xen/drivers/passthrough/arm/vsmmu-v3.c
> @@ -86,6 +86,8 @@
>  #define smmu_get_ste_s1ctxptr(x)    FIELD_PREP(STRTAB_STE_0_S1CTXPTR_MASK, \
>                                      FIELD_GET(STRTAB_STE_0_S1CTXPTR_MASK, x))
>
> +#define MAX_VSID   (1 << SMMU_IDR1_SIDSIZE)
> +
>  /* event queue entry */
>  struct arm_smmu_evtq_ent {
>      /* Common fields */
> @@ -133,6 +135,14 @@ struct arm_vsmmu_queue {
>      uint8_t     max_n_shift;
>  };
>
> +/* vSID->pSID mapping entry */
> +struct vsid_entry {
> +    struct list_head entry;
> +    uint32_t    vsid;
> +    uint32_t    psid;
> +    struct arm_smmu_device *smmu;
> +};
> +
>  struct virt_smmu {
>      struct      domain *d;
>      struct      list_head viommu_list;
> @@ -157,6 +167,8 @@ struct virt_smmu {
>      spinlock_t  cr2_lock;
>      spinlock_t  strtab_cfg_lock;
>      spinlock_t  irq_cfg_lock;
> +    spinlock_t vsids_lock;
> +    struct list_head vsids;
>  };
>
>  /* Helper functions */
> @@ -379,8 +391,31 @@ int arm_vsmmu_handle_evt(struct domain *d, struct device 
> *dev, uint64_t *evt)
>      }
>      else
>      {
> +        uint32_t sid = FIELD_GET(EVTQ_0_SID, evt[0]);
> +        struct vsid_entry *vsid;
> +        bool found = false;
> +
>          smmu = list_entry(d->arch.viommu_list.next,
>                            struct virt_smmu, viommu_list);
> +
> +        spin_lock(&smmu->vsids_lock);
> +
> +        /* Translate pSID->vSID */
> +        list_for_each_entry(vsid, &smmu->vsids, entry)
> +        {
> +            if ( vsid->psid == sid && vsid->smmu->dev == dev )
> +            {
> +                evt[0] &= ~EVTQ_0_SID;
> +                evt[0] |= FIELD_PREP(EVTQ_0_SID, vsid->vsid);
> +                found = true;
> +                break;
> +            }
> +        }
> +
> +        spin_unlock(&smmu->vsids_lock);
> +
> +        if ( !found )
> +            return -ENOENT;
>      }
>
>      ret = arm_vsmmu_write_evtq(smmu, evt);
> @@ -558,6 +593,71 @@ static int arm_vsmmu_handle_cfgi_ste(struct virt_smmu 
> *smmu, uint64_t *cmdptr)
>      struct arm_vsmmu_s1_trans_cfg s1_cfg = {0};
>      uint32_t sid = smmu_cmd_get_sid(cmdptr[0]);
>      struct iommu_guest_config guest_cfg = {0};
> +    struct arm_smmu_device *phys_smmu = NULL;
> +    struct host_iommu *host_iommu;
> +    uint32_t psid;
> +    struct arm_smmu_evtq_ent ent = {
> +        .opcode = EVT_ID_BAD_STREAMID,
> +        .sid = sid,
> +        .c_bad_ste_streamid = {
> +            .ssid = 0,
> +            .ssv = false,
> +        },
> +    };
> +
> +    /* vIOMMU->pIOMMU identity mapped for HW domain */
> +    if ( domain_use_host_layout(d) )
> +    {
> +        psid = sid;
> +        list_for_each_entry(host_iommu, &host_iommu_list, entry)
> +        {
> +            if ( host_iommu->addr == smmu->addr )
> +            {
> +                phys_smmu = (struct arm_smmu_device *) host_iommu->iommu;
> +                break;
> +            }
> +        }
> +    }
> +    else {
> +        struct vsid_entry *vsid_entry;
> +        bool entry_found = false;
> +
> +        spin_lock(&smmu->vsids_lock);
> +        /* vSID out of range or no vSIDs allocated */
> +        if ( sid >= MAX_VSID || list_empty(&smmu->vsids) )
> +        {
> +            spin_unlock(&smmu->vsids_lock);
> +            arm_vsmmu_send_event(smmu, &ent);
> +            return -EINVAL;
> +        }
> +
> +        /* get vSID entry corresponding to passed vSID */
> +        list_for_each_entry(vsid_entry, &smmu->vsids, entry)
> +            if ( vsid_entry->vsid == sid )
> +            {
> +                entry_found = true;
> +                break;
> +            }
> +
> +        /* vSID not mapped */
> +        if ( !entry_found )
> +        {
> +            spin_unlock(&smmu->vsids_lock);
> +            arm_vsmmu_send_event(smmu, &ent);
> +            return -EINVAL;
> +        }
> +
> +        psid = vsid_entry->psid;
> +        phys_smmu = vsid_entry->smmu;
> +        spin_unlock(&smmu->vsids_lock);
> +    }
> +
> +    /* vSID mapped to invalid physical SMMU */
> +    if (!phys_smmu)
> +    {
> +        arm_vsmmu_send_event(smmu, &ent);
> +        return -EINVAL;
> +    }
>
>      ret = arm_vsmmu_find_ste(smmu, sid, ste);
>      if ( ret )
> @@ -578,7 +678,7 @@ static int arm_vsmmu_handle_cfgi_ste(struct virt_smmu 
> *smmu, uint64_t *cmdptr)
>      else
>          guest_cfg.config = ARM_SMMU_DOMAIN_S1;
>
> -    ret = hd->platform_ops->attach_guest_config(d, sid, &guest_cfg);
> +    ret = hd->platform_ops->attach_guest_config(d, psid, &guest_cfg, 
> phys_smmu);
>      if ( ret )
>          return ret;
>
> @@ -1189,6 +1289,13 @@ static int vsmmuv3_init_single(struct domain *d, 
> paddr_t addr,
>      smmu->cmdq.ent_size = CMDQ_ENT_DWORDS * DWORDS_BYTES;
>      smmu->evtq.ent_size = EVTQ_ENT_DWORDS * DWORDS_BYTES;
>
> +    /*
> +     * vSID->pSID mapping layer is only used in the context of domains that
> +     * are not direct-mapped
> +     */
> +    if ( !domain_use_host_layout(d) )
> +        INIT_LIST_HEAD(&smmu->vsids);
> +
>      spin_lock_init(&smmu->cmd_queue_lock);
>      spin_lock_init(&smmu->evt_queue_lock);
>      spin_lock_init(&smmu->gerror_lock);
> @@ -1197,6 +1304,7 @@ static int vsmmuv3_init_single(struct domain *d, 
> paddr_t addr,
>      spin_lock_init(&smmu->cr2_lock);
>      spin_lock_init(&smmu->strtab_cfg_lock);
>      spin_lock_init(&smmu->irq_cfg_lock);
> +    spin_lock_init(&smmu->vsids_lock);
>
>      ret = vgic_reserve_virq(d, virq);
>      if ( !ret )
> @@ -1317,8 +1425,16 @@ static int vsmmuv3_relinquish_resources(struct domain 
> *d)
>      if ( list_head_is_null(&d->arch.viommu_list) )
>          return 0;
>
> -    list_for_each_entry_safe(pos, temp, &d->arch.viommu_list, viommu_list )
> +    list_for_each_entry_safe(pos, temp, &d->arch.viommu_list, viommu_list)
>      {
> +        struct vsid_entry *vsid, *vsid_temp;
> +
> +        list_for_each_entry_safe(vsid, vsid_temp, &pos->vsids, entry)
> +        {
> +            list_del(&vsid->entry);
> +            xfree(vsid);
> +        }

Can this break for host_layout domains? The list is only initialized for non
host_layout ones.

> +
>          list_del(&pos->viommu_list);
>          xfree(pos);
>      }
> @@ -1326,8 +1442,72 @@ static int vsmmuv3_relinquish_resources(struct domain 
> *d)
>      return 0;
>  }
>
> +static int vsmmuv3_allocate_vsid(struct domain *d, uint32_t id,
> +                                 uint32_t phandle, uint32_t *vsid)
> +{
> +    uint32_t i = 0;
> +    struct virt_smmu *smmu;
> +    struct host_iommu *host_iommu;
> +    struct arm_smmu_device *phys_smmu = NULL;
> +    struct vsid_entry *entry;
> +    struct list_head *vsid_head;
> +
> +    /* vSID->pSID mapping layer not used for direct-mapped domains */
> +    if ( domain_use_host_layout(d) )
> +        return -EOPNOTSUPP;
> +
> +    if ( list_head_is_null(&d->arch.viommu_list) )
> +        return -ENODEV;
> +
> +    smmu = list_first_entry(&d->arch.viommu_list, struct virt_smmu, 
> viommu_list);
> +
> +    /*
> +     * Find the physical SMMU corresponding to the device-tree phandle.
> +     */
> +    list_for_each_entry(host_iommu, &host_iommu_list, entry)
> +    {
> +        if ( host_iommu->dt_node->phandle == phandle )
> +        {
> +            phys_smmu = (struct arm_smmu_device *) host_iommu->iommu;
> +            break;
> +        }
> +    }
> +
> +    if ( !phys_smmu )
> +        return -ENODEV;
> +
> +    spin_lock(&smmu->vsids_lock);
> +    /* Get first free vSID index */
> +    list_for_each(vsid_head, &smmu->vsids)
> +        i++;
> +
> +    /* Max number of vSIDs already allocated? */
> +    if ( i == MAX_VSID )
> +    {
> +        spin_unlock(&smmu->vsids_lock);
> +        return -ENOMEM;
> +    }
> +
> +    entry = xzalloc(struct vsid_entry);
> +    if ( !entry )
> +    {
> +        spin_unlock(&smmu->vsids_lock);
> +        return -ENOMEM;
> +    }
> +
> +    /* Establish vSID->pSID mapping */
> +    entry->vsid = i;
> +    entry->psid = id;
> +    entry->smmu = phys_smmu;
> +    *vsid = entry->vsid;
> +    list_add_tail(&entry->entry, &smmu->vsids);
> +    spin_unlock(&smmu->vsids_lock);
> +    return 0;
> +}
> +

Is it okay for multiple vsids to be mapped to the same psid?

>  static const struct viommu_ops vsmmuv3_ops = {
>      .domain_init = domain_vsmmuv3_init,
> +    .allocate_vsid = vsmmuv3_allocate_vsid,
>      .relinquish_resources = vsmmuv3_relinquish_resources,
>  };
>
> diff --git a/xen/include/xen/iommu.h b/xen/include/xen/iommu.h
> index 253f8bb6cb..c94ee4f08e 100644
> --- a/xen/include/xen/iommu.h
> +++ b/xen/include/xen/iommu.h
> @@ -312,7 +312,10 @@ static inline int iommu_add_dt_pci_sideband_ids(struct 
> pci_dev *pdev)
>  #endif /* HAS_DEVICE_TREE_DISCOVERY */
>
>  struct page_info;
> +#ifdef CONFIG_ARM
>  struct iommu_guest_config;
> +struct arm_smmu_device;
> +#endif
>
>  /*
>   * Any non-zero value returned from callbacks of this type will cause the
> @@ -391,7 +394,8 @@ struct iommu_ops {
>
>  #ifdef CONFIG_ARM
>      int (*attach_guest_config)(struct domain *d, uint32_t sid,
> -                               const struct iommu_guest_config *cfg);
> +                               const struct iommu_guest_config *cfg,
> +                               const struct arm_smmu_device *smmu);
>  #endif
>  };

Isn't arm_smmu_device a little too specific? This will be a problem if other
IOMMU implementation tries to add support for this. Maybe replace with void* and
let specific driver cast it to it's own type?

Thanks,
Mykyta


 


Rackspace

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