|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [RFC PATCH 05/21] xen/arm: vsmmuv3: Add dummy support for virtual SMMUv3 for guests
Hi Rahul,
On 01/12/2022 17:02, Rahul Singh wrote:
>
>
> domain_viommu_init() will be called during domain creation and will add
> the dummy trap handler for virtual IOMMUs for guests.
>
> A host IOMMU list will be created when host IOMMU devices are probed
> and this list will be used to create the IOMMU device tree node for
> dom0. For dom0, 1-1 mapping will be established between vIOMMU in dom0
> and physical IOMMU.
>
> For domUs, the 1-N mapping will be established between domU and physical
> IOMMUs. A new area has been reserved in the arm guest physical map at
> which the emulated vIOMMU node is created in the device tree.
>
> Also set the vIOMMU type to vSMMUv3 to enable vIOMMU framework to call
> vSMMUv3 domain creation/destroy functions.
>
> Signed-off-by: Rahul Singh <rahul.singh@xxxxxxx>
> ---
> xen/arch/arm/domain.c | 3 +-
> xen/arch/arm/include/asm/domain.h | 4 +
> xen/arch/arm/include/asm/viommu.h | 20 ++++
> xen/drivers/passthrough/Kconfig | 8 ++
> xen/drivers/passthrough/arm/Makefile | 1 +
> xen/drivers/passthrough/arm/smmu-v3.c | 7 ++
> xen/drivers/passthrough/arm/viommu.c | 30 ++++++
> xen/drivers/passthrough/arm/vsmmu-v3.c | 124 +++++++++++++++++++++++++
> xen/drivers/passthrough/arm/vsmmu-v3.h | 20 ++++
> xen/include/public/arch-arm.h | 7 +-
> 10 files changed, 222 insertions(+), 2 deletions(-)
> create mode 100644 xen/drivers/passthrough/arm/vsmmu-v3.c
> create mode 100644 xen/drivers/passthrough/arm/vsmmu-v3.h
>
> diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
> index 2a85209736..9a2b613500 100644
> --- a/xen/arch/arm/domain.c
> +++ b/xen/arch/arm/domain.c
> @@ -692,7 +692,8 @@ int arch_sanitise_domain_config(struct
> xen_domctl_createdomain *config)
> return -EINVAL;
> }
>
> - if ( config->arch.viommu_type != XEN_DOMCTL_CONFIG_VIOMMU_NONE )
> + if ( config->arch.viommu_type != XEN_DOMCTL_CONFIG_VIOMMU_NONE &&
> + config->arch.viommu_type != viommu_get_type() )
> {
> dprintk(XENLOG_INFO,
> "vIOMMU type requested not supported by the platform or
> Xen\n");
> diff --git a/xen/arch/arm/include/asm/domain.h
> b/xen/arch/arm/include/asm/domain.h
> index 2ce6764322..8eb4eb5fd6 100644
> --- a/xen/arch/arm/include/asm/domain.h
> +++ b/xen/arch/arm/include/asm/domain.h
> @@ -114,6 +114,10 @@ struct arch_domain
> void *tee;
> #endif
>
> +#ifdef CONFIG_VIRTUAL_IOMMU
> + struct list_head viommu_list; /* List of virtual IOMMUs */
> +#endif
> +
> } __cacheline_aligned;
>
> struct arch_vcpu
> diff --git a/xen/arch/arm/include/asm/viommu.h
> b/xen/arch/arm/include/asm/viommu.h
> index 7cd3818a12..4785877e2a 100644
> --- a/xen/arch/arm/include/asm/viommu.h
> +++ b/xen/arch/arm/include/asm/viommu.h
> @@ -5,9 +5,21 @@
> #ifdef CONFIG_VIRTUAL_IOMMU
>
> #include <xen/lib.h>
> +#include <xen/list.h>
> #include <xen/types.h>
> #include <public/xen.h>
>
> +extern struct list_head host_iommu_list;
> +
> +/* data structure for each hardware IOMMU */
> +struct host_iommu {
> + struct list_head entry;
> + const struct dt_device_node *dt_node;
> + paddr_t addr;
> + paddr_t size;
> + uint32_t irq;
You want this to be int and not unsigned. The reason is ...
> +};
> +
> struct viommu_ops {
> /*
> * Called during domain construction if toolstack requests to enable
> @@ -35,6 +47,8 @@ struct viommu_desc {
> int domain_viommu_init(struct domain *d, uint16_t viommu_type);
> int viommu_relinquish_resources(struct domain *d);
> uint16_t viommu_get_type(void);
> +void add_to_host_iommu_list(paddr_t addr, paddr_t size,
> + const struct dt_device_node *node);
>
> #else
>
> @@ -56,6 +70,12 @@ static inline int viommu_relinquish_resources(struct
> domain *d)
> return 0;
> }
>
> +static inline void add_to_host_iommu_list(paddr_t addr, paddr_t size,
> + const struct dt_device_node *node)
> +{
> + return;
> +}
> +
> #endif /* CONFIG_VIRTUAL_IOMMU */
>
> #endif /* __ARCH_ARM_VIOMMU_H__ */
> diff --git a/xen/drivers/passthrough/Kconfig b/xen/drivers/passthrough/Kconfig
> index 19924fa2de..4c725f5f67 100644
> --- a/xen/drivers/passthrough/Kconfig
> +++ b/xen/drivers/passthrough/Kconfig
> @@ -41,6 +41,14 @@ config VIRTUAL_IOMMU
> help
> Support virtual IOMMU infrastructure to implement vIOMMU.
>
> +config VIRTUAL_ARM_SMMU_V3
> + bool "ARM Ltd. Virtual SMMUv3 Support (UNSUPPORTED)" if UNSUPPORTED
> + depends on ARM_SMMU_V3 && VIRTUAL_IOMMU
> + help
> + Support for implementations of the virtual ARM System MMU
> architecture
> + version 3. Virtual SMMUv3 is unsupported feature and should not be
> used
> + in production.
> +
> endif
>
> config IOMMU_FORCE_PT_SHARE
> diff --git a/xen/drivers/passthrough/arm/Makefile
> b/xen/drivers/passthrough/arm/Makefile
> index 4cc54f3f4d..e758a9d6aa 100644
> --- a/xen/drivers/passthrough/arm/Makefile
> +++ b/xen/drivers/passthrough/arm/Makefile
> @@ -3,3 +3,4 @@ obj-$(CONFIG_ARM_SMMU) += smmu.o
> obj-$(CONFIG_IPMMU_VMSA) += ipmmu-vmsa.o
> obj-$(CONFIG_ARM_SMMU_V3) += smmu-v3.o
> obj-$(CONFIG_VIRTUAL_IOMMU) += viommu.o
> +obj-$(CONFIG_VIRTUAL_ARM_SMMU_V3) += vsmmu-v3.o
> diff --git a/xen/drivers/passthrough/arm/smmu-v3.c
> b/xen/drivers/passthrough/arm/smmu-v3.c
> index 9174d2dedd..4f96fdb92f 100644
> --- a/xen/drivers/passthrough/arm/smmu-v3.c
> +++ b/xen/drivers/passthrough/arm/smmu-v3.c
> @@ -91,6 +91,7 @@
> #include <asm/platform.h>
>
> #include "smmu-v3.h"
> +#include "vsmmu-v3.h"
>
> #define ARM_SMMU_VTCR_SH_IS 3
> #define ARM_SMMU_VTCR_RGN_WBWA 1
> @@ -2680,6 +2681,9 @@ static int arm_smmu_device_probe(struct platform_device
> *pdev)
> list_add(&smmu->devices, &arm_smmu_devices);
> spin_unlock(&arm_smmu_devices_lock);
>
> + /* Add to host IOMMU list to initialize vIOMMU for dom0 */
> + add_to_host_iommu_list(ioaddr, iosize, dev_to_dt(pdev));
> +
> return 0;
>
>
> @@ -2936,6 +2940,9 @@ static __init int arm_smmu_dt_init(struct
> dt_device_node *dev,
>
> iommu_set_ops(&arm_smmu_iommu_ops);
>
> + /* Set vIOMMU type to SMMUv3 */
> + vsmmuv3_set_type();
> +
> return 0;
> }
>
> diff --git a/xen/drivers/passthrough/arm/viommu.c
> b/xen/drivers/passthrough/arm/viommu.c
> index 7ab6061e34..53ae46349a 100644
> --- a/xen/drivers/passthrough/arm/viommu.c
> +++ b/xen/drivers/passthrough/arm/viommu.c
> @@ -2,12 +2,42 @@
>
> #include <xen/errno.h>
> #include <xen/init.h>
> +#include <xen/irq.h>
> #include <xen/types.h>
>
> #include <asm/viommu.h>
>
> +/* List of all host IOMMUs */
> +LIST_HEAD(host_iommu_list);
> +
> const struct viommu_desc __read_mostly *cur_viommu;
>
> +/* Common function for adding to host_iommu_list */
> +void add_to_host_iommu_list(paddr_t addr, paddr_t size,
> + const struct dt_device_node *node)
> +{
> + struct host_iommu *iommu_data;
> +
> + iommu_data = xzalloc(struct host_iommu);
> + if ( !iommu_data )
> + panic("vIOMMU: Cannot allocate memory for host IOMMU data\n");
> +
> + iommu_data->addr = addr;
> + iommu_data->size = size;
> + iommu_data->dt_node = node;
> + iommu_data->irq = platform_get_irq(node, 0);
you are assigning platform_get_irq to it which can return a negative number in
case of failure.
In your current implementation, the following check does not make sense as
unsigned can never be negative.
> + if ( iommu_data->irq < 0 )
> + {
> + gdprintk(XENLOG_ERR,
> + "vIOMMU: Cannot find a valid IOMMU irq\n");
> + return;
> + }
> +
> + printk("vIOMMU: Found IOMMU @0x%"PRIx64"\n", addr);
> +
> + list_add_tail(&iommu_data->entry, &host_iommu_list);
> +}
> +
> int domain_viommu_init(struct domain *d, uint16_t viommu_type)
> {
> if ( viommu_type == XEN_DOMCTL_CONFIG_VIOMMU_NONE )
> diff --git a/xen/drivers/passthrough/arm/vsmmu-v3.c
> b/xen/drivers/passthrough/arm/vsmmu-v3.c
> new file mode 100644
> index 0000000000..6b4009e5ef
> --- /dev/null
> +++ b/xen/drivers/passthrough/arm/vsmmu-v3.c
> @@ -0,0 +1,124 @@
> +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
> +
> +#include <xen/param.h>
> +#include <xen/sched.h>
> +#include <asm/mmio.h>
> +#include <asm/viommu.h>
> +
> +/* Struct to hold the vIOMMU ops and vIOMMU type */
> +extern const struct viommu_desc __read_mostly *cur_viommu;
> +
> +struct virt_smmu {
> + struct domain *d;
> + struct list_head viommu_list;
> +};
> +
> +static int vsmmuv3_mmio_write(struct vcpu *v, mmio_info_t *info,
> + register_t r, void *priv)
> +{
> + return IO_HANDLED;
> +}
> +
> +static int vsmmuv3_mmio_read(struct vcpu *v, mmio_info_t *info,
> + register_t *r, void *priv)
> +{
> + return IO_HANDLED;
> +}
> +
> +static const struct mmio_handler_ops vsmmuv3_mmio_handler = {
> + .read = vsmmuv3_mmio_read,
> + .write = vsmmuv3_mmio_write,
> +};
> +
> +static int vsmmuv3_init_single(struct domain *d, paddr_t addr, paddr_t size)
> +{
> + struct virt_smmu *smmu;
> +
> + smmu = xzalloc(struct virt_smmu);
> + if ( !smmu )
> + return -ENOMEM;
> +
> + smmu->d = d;
> +
> + register_mmio_handler(d, &vsmmuv3_mmio_handler, addr, size, smmu);
> +
> + /* Register the vIOMMU to be able to clean it up later. */
> + list_add_tail(&smmu->viommu_list, &d->arch.viommu_list);
> +
> + return 0;
> +}
> +
> +int domain_vsmmuv3_init(struct domain *d)
> +{
> + int ret;
> + INIT_LIST_HEAD(&d->arch.viommu_list);
> +
> + if ( is_hardware_domain(d) )
> + {
> + struct host_iommu *hw_iommu;
> +
> + list_for_each_entry(hw_iommu, &host_iommu_list, entry)
> + {
> + ret = vsmmuv3_init_single(d, hw_iommu->addr, hw_iommu->size);
> + if ( ret )
> + return ret;
> + }
> + }
> + else
> + {
> + ret = vsmmuv3_init_single(d, GUEST_VSMMUV3_BASE, GUEST_VSMMUV3_SIZE);
> + if ( ret )
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +int vsmmuv3_relinquish_resources(struct domain *d)
> +{
> + struct virt_smmu *pos, *temp;
> +
> + /* Cope with unitialized vIOMMU */
> + 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_del(&pos->viommu_list);
> + xfree(pos);
> + }
> +
> + return 0;
> +}
> +
> +static const struct viommu_ops vsmmuv3_ops = {
> + .domain_init = domain_vsmmuv3_init,
> + .relinquish_resources = vsmmuv3_relinquish_resources,
> +};
> +
> +static const struct viommu_desc vsmmuv3_desc = {
> + .ops = &vsmmuv3_ops,
> + .viommu_type = XEN_DOMCTL_CONFIG_VIOMMU_SMMUV3,
> +};
> +
> +void __init vsmmuv3_set_type(void)
> +{
> + const struct viommu_desc *desc = &vsmmuv3_desc;
> +
> + if ( cur_viommu && (cur_viommu != desc) )
> + {
> + printk("WARNING: Cannot set vIOMMU, already set to a different
> value\n");
> + return;
> + }
> +
> + cur_viommu = desc;
> +}
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/xen/drivers/passthrough/arm/vsmmu-v3.h
> b/xen/drivers/passthrough/arm/vsmmu-v3.h
> new file mode 100644
> index 0000000000..e11f85b431
> --- /dev/null
> +++ b/xen/drivers/passthrough/arm/vsmmu-v3.h
> @@ -0,0 +1,20 @@
> +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
> +#ifndef __ARCH_ARM_VSMMU_V3_H__
> +#define __ARCH_ARM_VSMMU_V3_H__
> +
> +#include <asm/viommu.h>
> +
> +#ifdef CONFIG_VIRTUAL_ARM_SMMU_V3
> +
> +void vsmmuv3_set_type(void);
> +
> +#else
> +
> +static inline void vsmmuv3_set_type(void)
> +{
> + return;
> +}
> +
> +#endif /* CONFIG_VIRTUAL_ARM_SMMU_V3 */
> +
> +#endif /* __ARCH_ARM_VSMMU_V3_H__ */
> diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h
> index 33d32835e7..24b52fa017 100644
> --- a/xen/include/public/arch-arm.h
> +++ b/xen/include/public/arch-arm.h
> @@ -297,7 +297,8 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
> #define XEN_DOMCTL_CONFIG_TEE_NONE 0
> #define XEN_DOMCTL_CONFIG_TEE_OPTEE 1
>
> -#define XEN_DOMCTL_CONFIG_VIOMMU_NONE 0
> +#define XEN_DOMCTL_CONFIG_VIOMMU_NONE 0
> +#define XEN_DOMCTL_CONFIG_VIOMMU_SMMUV3 1
>
> struct xen_arch_domainconfig {
> /* IN/OUT */
> @@ -418,6 +419,10 @@ typedef uint64_t xen_callback_t;
> #define GUEST_GICV3_GICR0_BASE xen_mk_ullong(0x03020000) /* vCPU0..127 */
> #define GUEST_GICV3_GICR0_SIZE xen_mk_ullong(0x01000000)
>
> +/* vsmmuv3 ITS mappings */
> +#define GUEST_VSMMUV3_BASE xen_mk_ullong(0x04040000)
> +#define GUEST_VSMMUV3_SIZE xen_mk_ullong(0x00040000)
> +
> /*
> * 256 MB is reserved for VPCI configuration space based on calculation
> * 256 buses x 32 devices x 8 functions x 4 KB = 256 MB
> --
> 2.25.1
>
>
~Michal
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |