LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [PATCH RFC v1 00/15] iommu/virtio: Nested stage support with Arm
@ 2021-01-15 12:13 Vivek Gautam
  2021-01-15 12:13 ` [PATCH RFC v1 01/15] iommu/arm-smmu-v3: Create a Context Descriptor library Vivek Gautam
                   ` (15 more replies)
  0 siblings, 16 replies; 44+ messages in thread
From: Vivek Gautam @ 2021-01-15 12:13 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, iommu, virtualization
  Cc: joro, will.deacon, mst, robin.murphy, jean-philippe, eric.auger,
	alex.williamson, kevin.tian, jacob.jun.pan, yi.l.liu,
	lorenzo.pieralisi, shameerali.kolothum.thodi, vivek.gautam

This patch-series aims at enabling Nested stage translation in guests
using virtio-iommu as the paravirtualized iommu. The backend is supported
with Arm SMMU-v3 that provides nested stage-1 and stage-2 translation.

This series derives its purpose from various efforts happening to add
support for Shared Virtual Addressing (SVA) in host and guest. On Arm,
most of the support for SVA has already landed. The support for nested
stage translation and fault reporting to guest has been proposed [1].
The related changes required in VFIO [2] framework have also been put
forward.

This series proposes changes in virtio-iommu to program PASID tables
and related stage-1 page tables. A simple iommu-pasid-table library
is added for this purpose that interacts with vendor drivers to
allocate and populate PASID tables.
In Arm SMMUv3 we propose to pull the Context Descriptor (CD) management
code out of the arm-smmu-v3 driver and add that as a glue vendor layer
to support allocating CD tables, and populating them with right values.
These CD tables are essentially the PASID tables and contain stage-1
page table configurations too.
A request to setup these CD tables come from virtio-iommu driver using
the iommu-pasid-table library when running on Arm. The virtio-iommu
then pass these PASID tables to the host using the right virtio backend
and support in VMM.

For testing we have added necessary support in kvmtool. The changes in
kvmtool are based on virtio-iommu development branch by Jean-Philippe
Brucker [3].

The tested kernel branch contains following in the order bottom to top
on the git hash -
a) v5.11-rc3
b) arm-smmu-v3 [1] and vfio [2] changes from Eric to add nested page
   table support for Arm.
c) Smmu test engine patches from Jean-Philippe's branch [4]
d) This series
e) Domain nesting info patches [5][6][7].
f) Changes to add arm-smmu-v3 specific nesting info (to be sent to
   the list).

This kernel is tested on Neoverse reference software stack with
Fixed virtual platform. Public version of the software stack and
FVP is available here[8][9].

A big thanks to Jean-Philippe for his contributions towards this work
and for his valuable guidance.

[1] https://lore.kernel.org/linux-iommu/20201118112151.25412-1-eric.auger@redhat.com/T/
[2] https://lore.kernel.org/kvmarm/20201116110030.32335-12-eric.auger@redhat.com/T/
[3] https://jpbrucker.net/git/kvmtool/log/?h=virtio-iommu/devel
[4] https://jpbrucker.net/git/linux/log/?h=sva/smmute
[5] https://lore.kernel.org/kvm/1599734733-6431-2-git-send-email-yi.l.liu@intel.com/
[6] https://lore.kernel.org/kvm/1599734733-6431-3-git-send-email-yi.l.liu@intel.com/
[7] https://lore.kernel.org/kvm/1599734733-6431-4-git-send-email-yi.l.liu@intel.com/
[8] https://developer.arm.com/tools-and-software/open-source-software/arm-platforms-software/arm-ecosystem-fvps
[9] https://git.linaro.org/landing-teams/working/arm/arm-reference-platforms.git/about/docs/rdn1edge/user-guide.rst

Jean-Philippe Brucker (6):
  iommu/virtio: Add headers for table format probing
  iommu/virtio: Add table format probing
  iommu/virtio: Add headers for binding pasid table in iommu
  iommu/virtio: Add support for INVALIDATE request
  iommu/virtio: Attach Arm PASID tables when available
  iommu/virtio: Add support for Arm LPAE page table format

Vivek Gautam (9):
  iommu/arm-smmu-v3: Create a Context Descriptor library
  iommu: Add a simple PASID table library
  iommu/arm-smmu-v3: Update drivers to work with iommu-pasid-table
  iommu/arm-smmu-v3: Update CD base address info for user-space
  iommu/arm-smmu-v3: Set sync op from consumer driver of cd-lib
  iommu: Add asid_bits to arm smmu-v3 stage1 table info
  iommu/virtio: Update table format probing header
  iommu/virtio: Prepare to add attach pasid table infrastructure
  iommu/virtio: Update fault type and reason info for viommu fault

 drivers/iommu/arm/arm-smmu-v3/Makefile        |   2 +-
 .../arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c      | 283 +++++++
 .../iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c   |  16 +-
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c   | 268 +------
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h   |   4 +-
 drivers/iommu/iommu-pasid-table.h             | 140 ++++
 drivers/iommu/virtio-iommu.c                  | 692 +++++++++++++++++-
 include/uapi/linux/iommu.h                    |   2 +-
 include/uapi/linux/virtio_iommu.h             | 158 +++-
 9 files changed, 1303 insertions(+), 262 deletions(-)
 create mode 100644 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c
 create mode 100644 drivers/iommu/iommu-pasid-table.h

-- 
2.17.1


^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH RFC v1 01/15] iommu/arm-smmu-v3: Create a Context Descriptor library
  2021-01-15 12:13 [PATCH RFC v1 00/15] iommu/virtio: Nested stage support with Arm Vivek Gautam
@ 2021-01-15 12:13 ` Vivek Gautam
  2021-01-15 12:13 ` [PATCH RFC v1 02/15] iommu: Add a simple PASID table library Vivek Gautam
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 44+ messages in thread
From: Vivek Gautam @ 2021-01-15 12:13 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, iommu, virtualization
  Cc: joro, will.deacon, mst, robin.murphy, jean-philippe, eric.auger,
	alex.williamson, kevin.tian, jacob.jun.pan, yi.l.liu,
	lorenzo.pieralisi, shameerali.kolothum.thodi, vivek.gautam

Para-virtualized iommu drivers in guest may require to create and manage
context descriptor (CD) tables as part of PASID table allocations.
The PASID tables are passed to host to configure stage-1 tables in
hardware.
Make way for a library driver for CD management to allow para-
virtualized iommu driver call such code.

Signed-off-by: Vivek Gautam <vivek.gautam@arm.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
Cc: Eric Auger <eric.auger@redhat.com>
Cc: Alex Williamson <alex.williamson@redhat.com>
Cc: Kevin Tian <kevin.tian@intel.com>
Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
Cc: Liu Yi L <yi.l.liu@intel.com>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
---
 drivers/iommu/arm/arm-smmu-v3/Makefile        |   2 +-
 .../arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c      | 223 ++++++++++++++++++
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c   | 216 +----------------
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h   |   3 +
 4 files changed, 228 insertions(+), 216 deletions(-)
 create mode 100644 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c

diff --git a/drivers/iommu/arm/arm-smmu-v3/Makefile b/drivers/iommu/arm/arm-smmu-v3/Makefile
index 54feb1ecccad..ca1a05b8b8ad 100644
--- a/drivers/iommu/arm/arm-smmu-v3/Makefile
+++ b/drivers/iommu/arm/arm-smmu-v3/Makefile
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_ARM_SMMU_V3) += arm_smmu_v3.o
-arm_smmu_v3-objs-y += arm-smmu-v3.o
+arm_smmu_v3-objs-y += arm-smmu-v3.o arm-smmu-v3-cd-lib.o
 arm_smmu_v3-objs-$(CONFIG_ARM_SMMU_V3_SVA) += arm-smmu-v3-sva.o
 arm_smmu_v3-objs := $(arm_smmu_v3-objs-y)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c
new file mode 100644
index 000000000000..97d1786a8a70
--- /dev/null
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c
@@ -0,0 +1,223 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * arm-smmu-v3 context descriptor handling library driver
+ *
+ * Copyright (C) 2021 Arm Ltd.
+ */
+
+#include <linux/dma-iommu.h>
+
+#include "arm-smmu-v3.h"
+
+static int arm_smmu_alloc_cd_leaf_table(struct arm_smmu_device *smmu,
+					struct arm_smmu_l1_ctx_desc *l1_desc)
+{
+	size_t size = CTXDESC_L2_ENTRIES * (CTXDESC_CD_DWORDS << 3);
+
+	l1_desc->l2ptr = dmam_alloc_coherent(smmu->dev, size,
+					     &l1_desc->l2ptr_dma, GFP_KERNEL);
+	if (!l1_desc->l2ptr) {
+		dev_warn(smmu->dev,
+			 "failed to allocate context descriptor table\n");
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+static void arm_smmu_write_cd_l1_desc(__le64 *dst,
+				      struct arm_smmu_l1_ctx_desc *l1_desc)
+{
+	u64 val = (l1_desc->l2ptr_dma & CTXDESC_L1_DESC_L2PTR_MASK) |
+		  CTXDESC_L1_DESC_V;
+
+	/* See comment in arm_smmu_write_ctx_desc() */
+	WRITE_ONCE(*dst, cpu_to_le64(val));
+}
+
+static __le64 *arm_smmu_get_cd_ptr(struct arm_smmu_domain *smmu_domain,
+				   u32 ssid)
+{
+	__le64 *l1ptr;
+	unsigned int idx;
+	struct arm_smmu_l1_ctx_desc *l1_desc;
+	struct arm_smmu_device *smmu = smmu_domain->smmu;
+	struct arm_smmu_ctx_desc_cfg *cdcfg = &smmu_domain->s1_cfg.cdcfg;
+
+	if (smmu_domain->s1_cfg.s1fmt == STRTAB_STE_0_S1FMT_LINEAR)
+		return cdcfg->cdtab + ssid * CTXDESC_CD_DWORDS;
+
+	idx = ssid >> CTXDESC_SPLIT;
+	l1_desc = &cdcfg->l1_desc[idx];
+	if (!l1_desc->l2ptr) {
+		if (arm_smmu_alloc_cd_leaf_table(smmu, l1_desc))
+			return NULL;
+
+		l1ptr = cdcfg->cdtab + idx * CTXDESC_L1_DESC_DWORDS;
+		arm_smmu_write_cd_l1_desc(l1ptr, l1_desc);
+		/* An invalid L1CD can be cached */
+		arm_smmu_sync_cd(smmu_domain, ssid, false);
+	}
+	idx = ssid & (CTXDESC_L2_ENTRIES - 1);
+	return l1_desc->l2ptr + idx * CTXDESC_CD_DWORDS;
+}
+
+int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid,
+			    struct arm_smmu_ctx_desc *cd)
+{
+	/*
+	 * This function handles the following cases:
+	 *
+	 * (1) Install primary CD, for normal DMA traffic (SSID = 0).
+	 * (2) Install a secondary CD, for SID+SSID traffic.
+	 * (3) Update ASID of a CD. Atomically write the first 64 bits of the
+	 *     CD, then invalidate the old entry and mappings.
+	 * (4) Quiesce the context without clearing the valid bit. Disable
+	 *     translation, and ignore any translation fault.
+	 * (5) Remove a secondary CD.
+	 */
+	u64 val;
+	bool cd_live;
+	__le64 *cdptr;
+	struct arm_smmu_device *smmu = smmu_domain->smmu;
+
+	if (WARN_ON(ssid >= (1 << smmu_domain->s1_cfg.s1cdmax)))
+		return -E2BIG;
+
+	cdptr = arm_smmu_get_cd_ptr(smmu_domain, ssid);
+	if (!cdptr)
+		return -ENOMEM;
+
+	val = le64_to_cpu(cdptr[0]);
+	cd_live = !!(val & CTXDESC_CD_0_V);
+
+	if (!cd) { /* (5) */
+		val = 0;
+	} else if (cd == &quiet_cd) { /* (4) */
+		val |= CTXDESC_CD_0_TCR_EPD0;
+	} else if (cd_live) { /* (3) */
+		val &= ~CTXDESC_CD_0_ASID;
+		val |= FIELD_PREP(CTXDESC_CD_0_ASID, cd->asid);
+		/*
+		 * Until CD+TLB invalidation, both ASIDs may be used for tagging
+		 * this substream's traffic
+		 */
+	} else { /* (1) and (2) */
+		cdptr[1] = cpu_to_le64(cd->ttbr & CTXDESC_CD_1_TTB0_MASK);
+		cdptr[2] = 0;
+		cdptr[3] = cpu_to_le64(cd->mair);
+
+		/*
+		 * STE is live, and the SMMU might read dwords of this CD in any
+		 * order. Ensure that it observes valid values before reading
+		 * V=1.
+		 */
+		arm_smmu_sync_cd(smmu_domain, ssid, true);
+
+		val = cd->tcr |
+#ifdef __BIG_ENDIAN
+			CTXDESC_CD_0_ENDI |
+#endif
+			CTXDESC_CD_0_R | CTXDESC_CD_0_A |
+			(cd->mm ? 0 : CTXDESC_CD_0_ASET) |
+			CTXDESC_CD_0_AA64 |
+			FIELD_PREP(CTXDESC_CD_0_ASID, cd->asid) |
+			CTXDESC_CD_0_V;
+
+		/* STALL_MODEL==0b10 && CD.S==0 is ILLEGAL */
+		if (smmu->features & ARM_SMMU_FEAT_STALL_FORCE)
+			val |= CTXDESC_CD_0_S;
+	}
+
+	/*
+	 * The SMMU accesses 64-bit values atomically. See IHI0070Ca 3.21.3
+	 * "Configuration structures and configuration invalidation completion"
+	 *
+	 *   The size of single-copy atomic reads made by the SMMU is
+	 *   IMPLEMENTATION DEFINED but must be at least 64 bits. Any single
+	 *   field within an aligned 64-bit span of a structure can be altered
+	 *   without first making the structure invalid.
+	 */
+	WRITE_ONCE(cdptr[0], cpu_to_le64(val));
+	arm_smmu_sync_cd(smmu_domain, ssid, true);
+	return 0;
+}
+
+int arm_smmu_alloc_cd_tables(struct arm_smmu_domain *smmu_domain)
+{
+	int ret;
+	size_t l1size;
+	size_t max_contexts;
+	struct arm_smmu_device *smmu = smmu_domain->smmu;
+	struct arm_smmu_s1_cfg *cfg = &smmu_domain->s1_cfg;
+	struct arm_smmu_ctx_desc_cfg *cdcfg = &cfg->cdcfg;
+
+	max_contexts = 1 << cfg->s1cdmax;
+
+	if (!(smmu->features & ARM_SMMU_FEAT_2_LVL_CDTAB) ||
+	    max_contexts <= CTXDESC_L2_ENTRIES) {
+		cfg->s1fmt = STRTAB_STE_0_S1FMT_LINEAR;
+		cdcfg->num_l1_ents = max_contexts;
+
+		l1size = max_contexts * (CTXDESC_CD_DWORDS << 3);
+	} else {
+		cfg->s1fmt = STRTAB_STE_0_S1FMT_64K_L2;
+		cdcfg->num_l1_ents = DIV_ROUND_UP(max_contexts,
+						  CTXDESC_L2_ENTRIES);
+
+		cdcfg->l1_desc = devm_kcalloc(smmu->dev, cdcfg->num_l1_ents,
+					      sizeof(*cdcfg->l1_desc),
+					      GFP_KERNEL);
+		if (!cdcfg->l1_desc)
+			return -ENOMEM;
+
+		l1size = cdcfg->num_l1_ents * (CTXDESC_L1_DESC_DWORDS << 3);
+	}
+
+	cdcfg->cdtab = dmam_alloc_coherent(smmu->dev, l1size, &cdcfg->cdtab_dma,
+					   GFP_KERNEL);
+	if (!cdcfg->cdtab) {
+		dev_warn(smmu->dev, "failed to allocate context descriptor\n");
+		ret = -ENOMEM;
+		goto err_free_l1;
+	}
+
+	return 0;
+
+err_free_l1:
+	if (cdcfg->l1_desc) {
+		devm_kfree(smmu->dev, cdcfg->l1_desc);
+		cdcfg->l1_desc = NULL;
+	}
+	return ret;
+}
+
+void arm_smmu_free_cd_tables(struct arm_smmu_domain *smmu_domain)
+{
+	int i;
+	size_t size, l1size;
+	struct arm_smmu_device *smmu = smmu_domain->smmu;
+	struct arm_smmu_ctx_desc_cfg *cdcfg = &smmu_domain->s1_cfg.cdcfg;
+
+	if (cdcfg->l1_desc) {
+		size = CTXDESC_L2_ENTRIES * (CTXDESC_CD_DWORDS << 3);
+
+		for (i = 0; i < cdcfg->num_l1_ents; i++) {
+			if (!cdcfg->l1_desc[i].l2ptr)
+				continue;
+
+			dmam_free_coherent(smmu->dev, size,
+					   cdcfg->l1_desc[i].l2ptr,
+					   cdcfg->l1_desc[i].l2ptr_dma);
+		}
+		devm_kfree(smmu->dev, cdcfg->l1_desc);
+		cdcfg->l1_desc = NULL;
+
+		l1size = cdcfg->num_l1_ents * (CTXDESC_L1_DESC_DWORDS << 3);
+	} else {
+		l1size = cdcfg->num_l1_ents * (CTXDESC_CD_DWORDS << 3);
+	}
+
+	dmam_free_coherent(smmu->dev, l1size, cdcfg->cdtab, cdcfg->cdtab_dma);
+	cdcfg->cdtab_dma = 0;
+	cdcfg->cdtab = NULL;
+}
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 51da068df4e9..13513f2f651a 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -894,8 +894,7 @@ void arm_smmu_tlb_inv_asid(struct arm_smmu_device *smmu, u16 asid)
 	arm_smmu_cmdq_issue_sync(smmu);
 }
 
-static void arm_smmu_sync_cd(struct arm_smmu_domain *smmu_domain,
-			     int ssid, bool leaf)
+void arm_smmu_sync_cd(struct arm_smmu_domain *smmu_domain, int ssid, bool leaf)
 {
 	size_t i;
 	unsigned long flags;
@@ -922,219 +921,6 @@ static void arm_smmu_sync_cd(struct arm_smmu_domain *smmu_domain,
 	arm_smmu_cmdq_batch_submit(smmu, &cmds);
 }
 
-static int arm_smmu_alloc_cd_leaf_table(struct arm_smmu_device *smmu,
-					struct arm_smmu_l1_ctx_desc *l1_desc)
-{
-	size_t size = CTXDESC_L2_ENTRIES * (CTXDESC_CD_DWORDS << 3);
-
-	l1_desc->l2ptr = dmam_alloc_coherent(smmu->dev, size,
-					     &l1_desc->l2ptr_dma, GFP_KERNEL);
-	if (!l1_desc->l2ptr) {
-		dev_warn(smmu->dev,
-			 "failed to allocate context descriptor table\n");
-		return -ENOMEM;
-	}
-	return 0;
-}
-
-static void arm_smmu_write_cd_l1_desc(__le64 *dst,
-				      struct arm_smmu_l1_ctx_desc *l1_desc)
-{
-	u64 val = (l1_desc->l2ptr_dma & CTXDESC_L1_DESC_L2PTR_MASK) |
-		  CTXDESC_L1_DESC_V;
-
-	/* See comment in arm_smmu_write_ctx_desc() */
-	WRITE_ONCE(*dst, cpu_to_le64(val));
-}
-
-static __le64 *arm_smmu_get_cd_ptr(struct arm_smmu_domain *smmu_domain,
-				   u32 ssid)
-{
-	__le64 *l1ptr;
-	unsigned int idx;
-	struct arm_smmu_l1_ctx_desc *l1_desc;
-	struct arm_smmu_device *smmu = smmu_domain->smmu;
-	struct arm_smmu_ctx_desc_cfg *cdcfg = &smmu_domain->s1_cfg.cdcfg;
-
-	if (smmu_domain->s1_cfg.s1fmt == STRTAB_STE_0_S1FMT_LINEAR)
-		return cdcfg->cdtab + ssid * CTXDESC_CD_DWORDS;
-
-	idx = ssid >> CTXDESC_SPLIT;
-	l1_desc = &cdcfg->l1_desc[idx];
-	if (!l1_desc->l2ptr) {
-		if (arm_smmu_alloc_cd_leaf_table(smmu, l1_desc))
-			return NULL;
-
-		l1ptr = cdcfg->cdtab + idx * CTXDESC_L1_DESC_DWORDS;
-		arm_smmu_write_cd_l1_desc(l1ptr, l1_desc);
-		/* An invalid L1CD can be cached */
-		arm_smmu_sync_cd(smmu_domain, ssid, false);
-	}
-	idx = ssid & (CTXDESC_L2_ENTRIES - 1);
-	return l1_desc->l2ptr + idx * CTXDESC_CD_DWORDS;
-}
-
-int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid,
-			    struct arm_smmu_ctx_desc *cd)
-{
-	/*
-	 * This function handles the following cases:
-	 *
-	 * (1) Install primary CD, for normal DMA traffic (SSID = 0).
-	 * (2) Install a secondary CD, for SID+SSID traffic.
-	 * (3) Update ASID of a CD. Atomically write the first 64 bits of the
-	 *     CD, then invalidate the old entry and mappings.
-	 * (4) Quiesce the context without clearing the valid bit. Disable
-	 *     translation, and ignore any translation fault.
-	 * (5) Remove a secondary CD.
-	 */
-	u64 val;
-	bool cd_live;
-	__le64 *cdptr;
-	struct arm_smmu_device *smmu = smmu_domain->smmu;
-
-	if (WARN_ON(ssid >= (1 << smmu_domain->s1_cfg.s1cdmax)))
-		return -E2BIG;
-
-	cdptr = arm_smmu_get_cd_ptr(smmu_domain, ssid);
-	if (!cdptr)
-		return -ENOMEM;
-
-	val = le64_to_cpu(cdptr[0]);
-	cd_live = !!(val & CTXDESC_CD_0_V);
-
-	if (!cd) { /* (5) */
-		val = 0;
-	} else if (cd == &quiet_cd) { /* (4) */
-		val |= CTXDESC_CD_0_TCR_EPD0;
-	} else if (cd_live) { /* (3) */
-		val &= ~CTXDESC_CD_0_ASID;
-		val |= FIELD_PREP(CTXDESC_CD_0_ASID, cd->asid);
-		/*
-		 * Until CD+TLB invalidation, both ASIDs may be used for tagging
-		 * this substream's traffic
-		 */
-	} else { /* (1) and (2) */
-		cdptr[1] = cpu_to_le64(cd->ttbr & CTXDESC_CD_1_TTB0_MASK);
-		cdptr[2] = 0;
-		cdptr[3] = cpu_to_le64(cd->mair);
-
-		/*
-		 * STE is live, and the SMMU might read dwords of this CD in any
-		 * order. Ensure that it observes valid values before reading
-		 * V=1.
-		 */
-		arm_smmu_sync_cd(smmu_domain, ssid, true);
-
-		val = cd->tcr |
-#ifdef __BIG_ENDIAN
-			CTXDESC_CD_0_ENDI |
-#endif
-			CTXDESC_CD_0_R | CTXDESC_CD_0_A |
-			(cd->mm ? 0 : CTXDESC_CD_0_ASET) |
-			CTXDESC_CD_0_AA64 |
-			FIELD_PREP(CTXDESC_CD_0_ASID, cd->asid) |
-			CTXDESC_CD_0_V;
-
-		/* STALL_MODEL==0b10 && CD.S==0 is ILLEGAL */
-		if (smmu->features & ARM_SMMU_FEAT_STALL_FORCE)
-			val |= CTXDESC_CD_0_S;
-	}
-
-	/*
-	 * The SMMU accesses 64-bit values atomically. See IHI0070Ca 3.21.3
-	 * "Configuration structures and configuration invalidation completion"
-	 *
-	 *   The size of single-copy atomic reads made by the SMMU is
-	 *   IMPLEMENTATION DEFINED but must be at least 64 bits. Any single
-	 *   field within an aligned 64-bit span of a structure can be altered
-	 *   without first making the structure invalid.
-	 */
-	WRITE_ONCE(cdptr[0], cpu_to_le64(val));
-	arm_smmu_sync_cd(smmu_domain, ssid, true);
-	return 0;
-}
-
-static int arm_smmu_alloc_cd_tables(struct arm_smmu_domain *smmu_domain)
-{
-	int ret;
-	size_t l1size;
-	size_t max_contexts;
-	struct arm_smmu_device *smmu = smmu_domain->smmu;
-	struct arm_smmu_s1_cfg *cfg = &smmu_domain->s1_cfg;
-	struct arm_smmu_ctx_desc_cfg *cdcfg = &cfg->cdcfg;
-
-	max_contexts = 1 << cfg->s1cdmax;
-
-	if (!(smmu->features & ARM_SMMU_FEAT_2_LVL_CDTAB) ||
-	    max_contexts <= CTXDESC_L2_ENTRIES) {
-		cfg->s1fmt = STRTAB_STE_0_S1FMT_LINEAR;
-		cdcfg->num_l1_ents = max_contexts;
-
-		l1size = max_contexts * (CTXDESC_CD_DWORDS << 3);
-	} else {
-		cfg->s1fmt = STRTAB_STE_0_S1FMT_64K_L2;
-		cdcfg->num_l1_ents = DIV_ROUND_UP(max_contexts,
-						  CTXDESC_L2_ENTRIES);
-
-		cdcfg->l1_desc = devm_kcalloc(smmu->dev, cdcfg->num_l1_ents,
-					      sizeof(*cdcfg->l1_desc),
-					      GFP_KERNEL);
-		if (!cdcfg->l1_desc)
-			return -ENOMEM;
-
-		l1size = cdcfg->num_l1_ents * (CTXDESC_L1_DESC_DWORDS << 3);
-	}
-
-	cdcfg->cdtab = dmam_alloc_coherent(smmu->dev, l1size, &cdcfg->cdtab_dma,
-					   GFP_KERNEL);
-	if (!cdcfg->cdtab) {
-		dev_warn(smmu->dev, "failed to allocate context descriptor\n");
-		ret = -ENOMEM;
-		goto err_free_l1;
-	}
-
-	return 0;
-
-err_free_l1:
-	if (cdcfg->l1_desc) {
-		devm_kfree(smmu->dev, cdcfg->l1_desc);
-		cdcfg->l1_desc = NULL;
-	}
-	return ret;
-}
-
-static void arm_smmu_free_cd_tables(struct arm_smmu_domain *smmu_domain)
-{
-	int i;
-	size_t size, l1size;
-	struct arm_smmu_device *smmu = smmu_domain->smmu;
-	struct arm_smmu_ctx_desc_cfg *cdcfg = &smmu_domain->s1_cfg.cdcfg;
-
-	if (cdcfg->l1_desc) {
-		size = CTXDESC_L2_ENTRIES * (CTXDESC_CD_DWORDS << 3);
-
-		for (i = 0; i < cdcfg->num_l1_ents; i++) {
-			if (!cdcfg->l1_desc[i].l2ptr)
-				continue;
-
-			dmam_free_coherent(smmu->dev, size,
-					   cdcfg->l1_desc[i].l2ptr,
-					   cdcfg->l1_desc[i].l2ptr_dma);
-		}
-		devm_kfree(smmu->dev, cdcfg->l1_desc);
-		cdcfg->l1_desc = NULL;
-
-		l1size = cdcfg->num_l1_ents * (CTXDESC_L1_DESC_DWORDS << 3);
-	} else {
-		l1size = cdcfg->num_l1_ents * (CTXDESC_CD_DWORDS << 3);
-	}
-
-	dmam_free_coherent(smmu->dev, l1size, cdcfg->cdtab, cdcfg->cdtab_dma);
-	cdcfg->cdtab_dma = 0;
-	cdcfg->cdtab = NULL;
-}
-
 bool arm_smmu_free_asid(struct arm_smmu_ctx_desc *cd)
 {
 	bool free;
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index 9cdccf5d79b3..a50a3e4874f9 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -784,6 +784,9 @@ extern struct arm_smmu_ctx_desc quiet_cd;
 
 int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid,
 			    struct arm_smmu_ctx_desc *cd);
+int arm_smmu_alloc_cd_tables(struct arm_smmu_domain *smmu_domain);
+void arm_smmu_free_cd_tables(struct arm_smmu_domain *smmu_domain);
+void arm_smmu_sync_cd(struct arm_smmu_domain *smmu_domain, int ssid, bool leaf);
 void arm_smmu_tlb_inv_asid(struct arm_smmu_device *smmu, u16 asid);
 bool arm_smmu_free_asid(struct arm_smmu_ctx_desc *cd);
 int arm_smmu_atc_inv_domain(struct arm_smmu_domain *smmu_domain, int ssid,
-- 
2.17.1


^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH RFC v1 02/15] iommu: Add a simple PASID table library
  2021-01-15 12:13 [PATCH RFC v1 00/15] iommu/virtio: Nested stage support with Arm Vivek Gautam
  2021-01-15 12:13 ` [PATCH RFC v1 01/15] iommu/arm-smmu-v3: Create a Context Descriptor library Vivek Gautam
@ 2021-01-15 12:13 ` Vivek Gautam
  2021-03-03 17:11   ` Jean-Philippe Brucker
  2021-01-15 12:13 ` [PATCH RFC v1 03/15] iommu/arm-smmu-v3: Update drivers to work with iommu-pasid-table Vivek Gautam
                   ` (13 subsequent siblings)
  15 siblings, 1 reply; 44+ messages in thread
From: Vivek Gautam @ 2021-01-15 12:13 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, iommu, virtualization
  Cc: joro, will.deacon, mst, robin.murphy, jean-philippe, eric.auger,
	alex.williamson, kevin.tian, jacob.jun.pan, yi.l.liu,
	lorenzo.pieralisi, shameerali.kolothum.thodi, vivek.gautam

Add a small API in iommu subsystem to handle PASID table allocation
requests from different consumer drivers, such as a paravirtualized
iommu driver. The API provides ops for allocating and freeing PASID
table, writing to it and managing the table caches.

This library also provides for registering a vendor API that attaches
to these ops. The vendor APIs would eventually perform arch level
implementations for these PASID tables.

Signed-off-by: Vivek Gautam <vivek.gautam@arm.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
Cc: Eric Auger <eric.auger@redhat.com>
Cc: Alex Williamson <alex.williamson@redhat.com>
Cc: Kevin Tian <kevin.tian@intel.com>
Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
Cc: Liu Yi L <yi.l.liu@intel.com>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
---
 drivers/iommu/iommu-pasid-table.h | 134 ++++++++++++++++++++++++++++++
 1 file changed, 134 insertions(+)
 create mode 100644 drivers/iommu/iommu-pasid-table.h

diff --git a/drivers/iommu/iommu-pasid-table.h b/drivers/iommu/iommu-pasid-table.h
new file mode 100644
index 000000000000..bd4f57656f67
--- /dev/null
+++ b/drivers/iommu/iommu-pasid-table.h
@@ -0,0 +1,134 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PASID table management for the IOMMU
+ *
+ * Copyright (C) 2021 Arm Ltd.
+ */
+#ifndef __IOMMU_PASID_TABLE_H
+#define __IOMMU_PASID_TABLE_H
+
+#include <linux/io-pgtable.h>
+
+#include "arm/arm-smmu-v3/arm-smmu-v3.h"
+
+enum pasid_table_fmt {
+	PASID_TABLE_ARM_SMMU_V3,
+	PASID_TABLE_NUM_FMTS,
+};
+
+/**
+ * struct arm_smmu_cfg_info - arm-smmu-v3 specific configuration data
+ *
+ * @s1_cfg: arm-smmu-v3 stage1 config data
+ * @feat_flag: features supported by arm-smmu-v3 implementation
+ */
+struct arm_smmu_cfg_info {
+	struct arm_smmu_s1_cfg	*s1_cfg;
+	u32			feat_flag;
+};
+
+/**
+ * struct iommu_vendor_psdtable_cfg - Configuration data for PASID tables
+ *
+ * @iommu_dev: device performing the DMA table walks
+ * @fmt: The PASID table format
+ * @base: DMA address of the allocated table, set by the vendor driver
+ * @cfg: arm-smmu-v3 specific config data
+ */
+struct iommu_vendor_psdtable_cfg {
+	struct device		*iommu_dev;
+	enum pasid_table_fmt	fmt;
+	dma_addr_t		base;
+	union {
+		struct arm_smmu_cfg_info	cfg;
+	} vendor;
+};
+
+struct iommu_vendor_psdtable_ops;
+
+/**
+ * struct iommu_pasid_table - describes a set of PASID tables
+ *
+ * @cookie: An opaque token provided by the IOMMU driver and passed back to any
+ * callback routine.
+ * @cfg: A copy of the PASID table configuration
+ * @ops: The PASID table operations in use for this set of page tables
+ */
+struct iommu_pasid_table {
+	void					*cookie;
+	struct iommu_vendor_psdtable_cfg	cfg;
+	struct iommu_vendor_psdtable_ops	*ops;
+};
+
+#define pasid_table_cfg_to_table(pst_cfg) \
+	container_of((pst_cfg), struct iommu_pasid_table, cfg)
+
+struct iommu_vendor_psdtable_ops {
+	int (*alloc)(struct iommu_vendor_psdtable_cfg *cfg);
+	void (*free)(struct iommu_vendor_psdtable_cfg *cfg);
+	void (*prepare)(struct iommu_vendor_psdtable_cfg *cfg,
+			struct io_pgtable_cfg *pgtbl_cfg, u32 asid);
+	int (*write)(struct iommu_vendor_psdtable_cfg *cfg, int ssid,
+		     void *cookie);
+	void (*sync)(void *cookie, int ssid, bool leaf);
+};
+
+static inline int iommu_psdtable_alloc(struct iommu_pasid_table *tbl,
+				       struct iommu_vendor_psdtable_cfg *cfg)
+{
+	if (!tbl->ops->alloc)
+		return -ENOSYS;
+
+	return tbl->ops->alloc(cfg);
+}
+
+static inline void iommu_psdtable_free(struct iommu_pasid_table *tbl,
+				       struct iommu_vendor_psdtable_cfg *cfg)
+{
+	if (!tbl->ops->free)
+		return;
+
+	tbl->ops->free(cfg);
+}
+
+static inline int iommu_psdtable_prepare(struct iommu_pasid_table *tbl,
+					 struct iommu_vendor_psdtable_cfg *cfg,
+					 struct io_pgtable_cfg *pgtbl_cfg,
+					 u32 asid)
+{
+	if (!tbl->ops->prepare)
+		return -ENOSYS;
+
+	tbl->ops->prepare(cfg, pgtbl_cfg, asid);
+	return 0;
+}
+
+static inline int iommu_psdtable_write(struct iommu_pasid_table *tbl,
+				       struct iommu_vendor_psdtable_cfg *cfg,
+				       int ssid, void *cookie)
+{
+	if (!tbl->ops->write)
+		return -ENOSYS;
+
+	return tbl->ops->write(cfg, ssid, cookie);
+}
+
+static inline int iommu_psdtable_sync(struct iommu_pasid_table *tbl,
+				      void *cookie, int ssid, bool leaf)
+{
+	if (!tbl->ops->sync)
+		return -ENOSYS;
+
+	tbl->ops->sync(cookie, ssid, leaf);
+	return 0;
+}
+
+/* A placeholder to register vendor specific pasid layer */
+static inline struct iommu_pasid_table *
+iommu_register_pasid_table(enum pasid_table_fmt fmt,
+			   struct device *dev, void *cookie)
+{
+	return NULL;
+}
+
+#endif /* __IOMMU_PASID_TABLE_H */
-- 
2.17.1


^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH RFC v1 03/15] iommu/arm-smmu-v3: Update drivers to work with iommu-pasid-table
  2021-01-15 12:13 [PATCH RFC v1 00/15] iommu/virtio: Nested stage support with Arm Vivek Gautam
  2021-01-15 12:13 ` [PATCH RFC v1 01/15] iommu/arm-smmu-v3: Create a Context Descriptor library Vivek Gautam
  2021-01-15 12:13 ` [PATCH RFC v1 02/15] iommu: Add a simple PASID table library Vivek Gautam
@ 2021-01-15 12:13 ` Vivek Gautam
  2021-01-15 12:13 ` [PATCH RFC v1 04/15] iommu/arm-smmu-v3: Update CD base address info for user-space Vivek Gautam
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 44+ messages in thread
From: Vivek Gautam @ 2021-01-15 12:13 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, iommu, virtualization
  Cc: joro, will.deacon, mst, robin.murphy, jean-philippe, eric.auger,
	alex.williamson, kevin.tian, jacob.jun.pan, yi.l.liu,
	lorenzo.pieralisi, shameerali.kolothum.thodi, vivek.gautam

Update arm-smmu-v3 context descriptor (CD) library driver to work
with iommu-pasid-table APIs. These APIs are then used in arm-smmu-v3
drivers to manage CD tables.

Signed-off-by: Vivek Gautam <vivek.gautam@arm.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
Cc: Eric Auger <eric.auger@redhat.com>
Cc: Alex Williamson <alex.williamson@redhat.com>
Cc: Kevin Tian <kevin.tian@intel.com>
Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
Cc: Liu Yi L <yi.l.liu@intel.com>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
---
 .../arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c      | 127 +++++++++++++-----
 .../iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c   |  16 ++-
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c   |  47 ++++---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h   |   7 +-
 drivers/iommu/iommu-pasid-table.h             |  10 +-
 5 files changed, 144 insertions(+), 63 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c
index 97d1786a8a70..8a7187534706 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c
@@ -8,17 +8,17 @@
 #include <linux/dma-iommu.h>
 
 #include "arm-smmu-v3.h"
+#include "../../iommu-pasid-table.h"
 
-static int arm_smmu_alloc_cd_leaf_table(struct arm_smmu_device *smmu,
+static int arm_smmu_alloc_cd_leaf_table(struct device *dev,
 					struct arm_smmu_l1_ctx_desc *l1_desc)
 {
 	size_t size = CTXDESC_L2_ENTRIES * (CTXDESC_CD_DWORDS << 3);
 
-	l1_desc->l2ptr = dmam_alloc_coherent(smmu->dev, size,
+	l1_desc->l2ptr = dmam_alloc_coherent(dev, size,
 					     &l1_desc->l2ptr_dma, GFP_KERNEL);
 	if (!l1_desc->l2ptr) {
-		dev_warn(smmu->dev,
-			 "failed to allocate context descriptor table\n");
+		dev_warn(dev, "failed to allocate context descriptor table\n");
 		return -ENOMEM;
 	}
 	return 0;
@@ -34,35 +34,39 @@ static void arm_smmu_write_cd_l1_desc(__le64 *dst,
 	WRITE_ONCE(*dst, cpu_to_le64(val));
 }
 
-static __le64 *arm_smmu_get_cd_ptr(struct arm_smmu_domain *smmu_domain,
+static __le64 *arm_smmu_get_cd_ptr(struct iommu_vendor_psdtable_cfg *pst_cfg,
 				   u32 ssid)
 {
 	__le64 *l1ptr;
 	unsigned int idx;
+	struct device *dev = pst_cfg->iommu_dev;
+	struct arm_smmu_cfg_info *cfgi = &pst_cfg->vendor.cfg;
+	struct arm_smmu_s1_cfg *s1cfg = cfgi->s1_cfg;
+	struct arm_smmu_ctx_desc_cfg *cdcfg = &s1cfg->cdcfg;
 	struct arm_smmu_l1_ctx_desc *l1_desc;
-	struct arm_smmu_device *smmu = smmu_domain->smmu;
-	struct arm_smmu_ctx_desc_cfg *cdcfg = &smmu_domain->s1_cfg.cdcfg;
+	struct iommu_pasid_table *tbl = pasid_table_cfg_to_table(pst_cfg);
 
-	if (smmu_domain->s1_cfg.s1fmt == STRTAB_STE_0_S1FMT_LINEAR)
+	if (s1cfg->s1fmt == STRTAB_STE_0_S1FMT_LINEAR)
 		return cdcfg->cdtab + ssid * CTXDESC_CD_DWORDS;
 
 	idx = ssid >> CTXDESC_SPLIT;
 	l1_desc = &cdcfg->l1_desc[idx];
 	if (!l1_desc->l2ptr) {
-		if (arm_smmu_alloc_cd_leaf_table(smmu, l1_desc))
+		if (arm_smmu_alloc_cd_leaf_table(dev, l1_desc))
 			return NULL;
 
 		l1ptr = cdcfg->cdtab + idx * CTXDESC_L1_DESC_DWORDS;
 		arm_smmu_write_cd_l1_desc(l1ptr, l1_desc);
 		/* An invalid L1CD can be cached */
-		arm_smmu_sync_cd(smmu_domain, ssid, false);
+		if (iommu_psdtable_sync(tbl, tbl->cookie, ssid, false))
+			return NULL;
 	}
 	idx = ssid & (CTXDESC_L2_ENTRIES - 1);
 	return l1_desc->l2ptr + idx * CTXDESC_CD_DWORDS;
 }
 
-int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid,
-			    struct arm_smmu_ctx_desc *cd)
+static int arm_smmu_write_ctx_desc(struct iommu_vendor_psdtable_cfg *pst_cfg,
+				   int ssid, void *cookie)
 {
 	/*
 	 * This function handles the following cases:
@@ -78,12 +82,15 @@ int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid,
 	u64 val;
 	bool cd_live;
 	__le64 *cdptr;
-	struct arm_smmu_device *smmu = smmu_domain->smmu;
+	struct arm_smmu_cfg_info *cfgi = &pst_cfg->vendor.cfg;
+	struct arm_smmu_s1_cfg *s1cfg = cfgi->s1_cfg;
+	struct iommu_pasid_table *tbl = pasid_table_cfg_to_table(pst_cfg);
+	struct arm_smmu_ctx_desc *cd = cookie;
 
-	if (WARN_ON(ssid >= (1 << smmu_domain->s1_cfg.s1cdmax)))
+	if (WARN_ON(ssid >= (1 << s1cfg->s1cdmax)))
 		return -E2BIG;
 
-	cdptr = arm_smmu_get_cd_ptr(smmu_domain, ssid);
+	cdptr = arm_smmu_get_cd_ptr(pst_cfg, ssid);
 	if (!cdptr)
 		return -ENOMEM;
 
@@ -111,7 +118,8 @@ int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid,
 		 * order. Ensure that it observes valid values before reading
 		 * V=1.
 		 */
-		arm_smmu_sync_cd(smmu_domain, ssid, true);
+		if (iommu_psdtable_sync(tbl, tbl->cookie, ssid, true))
+			return -ENOSYS;
 
 		val = cd->tcr |
 #ifdef __BIG_ENDIAN
@@ -124,7 +132,7 @@ int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid,
 			CTXDESC_CD_0_V;
 
 		/* STALL_MODEL==0b10 && CD.S==0 is ILLEGAL */
-		if (smmu->features & ARM_SMMU_FEAT_STALL_FORCE)
+		if (cfgi->feat_flag & ARM_SMMU_FEAT_STALL_FORCE)
 			val |= CTXDESC_CD_0_S;
 	}
 
@@ -138,33 +146,55 @@ int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid,
 	 *   without first making the structure invalid.
 	 */
 	WRITE_ONCE(cdptr[0], cpu_to_le64(val));
-	arm_smmu_sync_cd(smmu_domain, ssid, true);
+	if (iommu_psdtable_sync(tbl, tbl->cookie, ssid, true))
+		return -ENOSYS;
+
 	return 0;
 }
 
-int arm_smmu_alloc_cd_tables(struct arm_smmu_domain *smmu_domain)
+static void arm_smmu_prepare_cd(struct iommu_vendor_psdtable_cfg *pst_cfg,
+				struct io_pgtable_cfg *pgtbl_cfg, u32 asid)
+{
+	struct arm_smmu_cfg_info *cfgi = &pst_cfg->vendor.cfg;
+	struct arm_smmu_s1_cfg *s1cfg = cfgi->s1_cfg;
+	typeof(&pgtbl_cfg->arm_lpae_s1_cfg.tcr) tcr = &pgtbl_cfg->arm_lpae_s1_cfg.tcr;
+
+	s1cfg->cd.asid	= (u16)asid;
+	s1cfg->cd.ttbr	= pgtbl_cfg->arm_lpae_s1_cfg.ttbr;
+	s1cfg->cd.tcr	= FIELD_PREP(CTXDESC_CD_0_TCR_T0SZ, tcr->tsz) |
+			  FIELD_PREP(CTXDESC_CD_0_TCR_TG0, tcr->tg) |
+			  FIELD_PREP(CTXDESC_CD_0_TCR_IRGN0, tcr->irgn) |
+			  FIELD_PREP(CTXDESC_CD_0_TCR_ORGN0, tcr->orgn) |
+			  FIELD_PREP(CTXDESC_CD_0_TCR_SH0, tcr->sh) |
+			  FIELD_PREP(CTXDESC_CD_0_TCR_IPS, tcr->ips) |
+			  CTXDESC_CD_0_TCR_EPD1 | CTXDESC_CD_0_AA64;
+	s1cfg->cd.mair	= pgtbl_cfg->arm_lpae_s1_cfg.mair;
+}
+
+static int arm_smmu_alloc_cd_tables(struct iommu_vendor_psdtable_cfg *pst_cfg)
 {
 	int ret;
 	size_t l1size;
 	size_t max_contexts;
-	struct arm_smmu_device *smmu = smmu_domain->smmu;
-	struct arm_smmu_s1_cfg *cfg = &smmu_domain->s1_cfg;
-	struct arm_smmu_ctx_desc_cfg *cdcfg = &cfg->cdcfg;
+	struct device *dev = pst_cfg->iommu_dev;
+	struct arm_smmu_cfg_info *cfgi = &pst_cfg->vendor.cfg;
+	struct arm_smmu_s1_cfg *s1cfg = cfgi->s1_cfg;
+	struct arm_smmu_ctx_desc_cfg *cdcfg = &s1cfg->cdcfg;
 
-	max_contexts = 1 << cfg->s1cdmax;
+	max_contexts = 1 << s1cfg->s1cdmax;
 
-	if (!(smmu->features & ARM_SMMU_FEAT_2_LVL_CDTAB) ||
+	if (!(cfgi->feat_flag & ARM_SMMU_FEAT_2_LVL_CDTAB) ||
 	    max_contexts <= CTXDESC_L2_ENTRIES) {
-		cfg->s1fmt = STRTAB_STE_0_S1FMT_LINEAR;
+		s1cfg->s1fmt = STRTAB_STE_0_S1FMT_LINEAR;
 		cdcfg->num_l1_ents = max_contexts;
 
 		l1size = max_contexts * (CTXDESC_CD_DWORDS << 3);
 	} else {
-		cfg->s1fmt = STRTAB_STE_0_S1FMT_64K_L2;
+		s1cfg->s1fmt = STRTAB_STE_0_S1FMT_64K_L2;
 		cdcfg->num_l1_ents = DIV_ROUND_UP(max_contexts,
 						  CTXDESC_L2_ENTRIES);
 
-		cdcfg->l1_desc = devm_kcalloc(smmu->dev, cdcfg->num_l1_ents,
+		cdcfg->l1_desc = devm_kcalloc(dev, cdcfg->num_l1_ents,
 					      sizeof(*cdcfg->l1_desc),
 					      GFP_KERNEL);
 		if (!cdcfg->l1_desc)
@@ -173,10 +203,10 @@ int arm_smmu_alloc_cd_tables(struct arm_smmu_domain *smmu_domain)
 		l1size = cdcfg->num_l1_ents * (CTXDESC_L1_DESC_DWORDS << 3);
 	}
 
-	cdcfg->cdtab = dmam_alloc_coherent(smmu->dev, l1size, &cdcfg->cdtab_dma,
+	cdcfg->cdtab = dmam_alloc_coherent(dev, l1size, &cdcfg->cdtab_dma,
 					   GFP_KERNEL);
 	if (!cdcfg->cdtab) {
-		dev_warn(smmu->dev, "failed to allocate context descriptor\n");
+		dev_warn(dev, "failed to allocate context descriptor\n");
 		ret = -ENOMEM;
 		goto err_free_l1;
 	}
@@ -185,18 +215,20 @@ int arm_smmu_alloc_cd_tables(struct arm_smmu_domain *smmu_domain)
 
 err_free_l1:
 	if (cdcfg->l1_desc) {
-		devm_kfree(smmu->dev, cdcfg->l1_desc);
+		devm_kfree(dev, cdcfg->l1_desc);
 		cdcfg->l1_desc = NULL;
 	}
 	return ret;
 }
 
-void arm_smmu_free_cd_tables(struct arm_smmu_domain *smmu_domain)
+static void arm_smmu_free_cd_tables(struct iommu_vendor_psdtable_cfg *pst_cfg)
 {
 	int i;
 	size_t size, l1size;
-	struct arm_smmu_device *smmu = smmu_domain->smmu;
-	struct arm_smmu_ctx_desc_cfg *cdcfg = &smmu_domain->s1_cfg.cdcfg;
+	struct device *dev = pst_cfg->iommu_dev;
+	struct arm_smmu_cfg_info *cfgi = &pst_cfg->vendor.cfg;
+	struct arm_smmu_s1_cfg *s1cfg = cfgi->s1_cfg;
+	struct arm_smmu_ctx_desc_cfg *cdcfg = &s1cfg->cdcfg;
 
 	if (cdcfg->l1_desc) {
 		size = CTXDESC_L2_ENTRIES * (CTXDESC_CD_DWORDS << 3);
@@ -205,11 +237,11 @@ void arm_smmu_free_cd_tables(struct arm_smmu_domain *smmu_domain)
 			if (!cdcfg->l1_desc[i].l2ptr)
 				continue;
 
-			dmam_free_coherent(smmu->dev, size,
+			dmam_free_coherent(dev, size,
 					   cdcfg->l1_desc[i].l2ptr,
 					   cdcfg->l1_desc[i].l2ptr_dma);
 		}
-		devm_kfree(smmu->dev, cdcfg->l1_desc);
+		devm_kfree(dev, cdcfg->l1_desc);
 		cdcfg->l1_desc = NULL;
 
 		l1size = cdcfg->num_l1_ents * (CTXDESC_L1_DESC_DWORDS << 3);
@@ -217,7 +249,30 @@ void arm_smmu_free_cd_tables(struct arm_smmu_domain *smmu_domain)
 		l1size = cdcfg->num_l1_ents * (CTXDESC_CD_DWORDS << 3);
 	}
 
-	dmam_free_coherent(smmu->dev, l1size, cdcfg->cdtab, cdcfg->cdtab_dma);
+	dmam_free_coherent(dev, l1size, cdcfg->cdtab, cdcfg->cdtab_dma);
 	cdcfg->cdtab_dma = 0;
 	cdcfg->cdtab = NULL;
 }
+
+struct iommu_vendor_psdtable_ops arm_cd_table_ops = {
+	.alloc	 = arm_smmu_alloc_cd_tables,
+	.free	 = arm_smmu_free_cd_tables,
+	.prepare = arm_smmu_prepare_cd,
+	.write	 = arm_smmu_write_ctx_desc,
+	.sync	 = arm_smmu_sync_cd,
+};
+
+struct iommu_pasid_table *arm_smmu_register_cd_table(struct device *dev,
+						     void *cookie)
+{
+	struct iommu_pasid_table *tbl;
+
+	tbl = devm_kzalloc(dev, sizeof(tbl), GFP_KERNEL);
+	if (!tbl)
+		return NULL;
+
+	tbl->cookie = cookie;
+	tbl->ops = &arm_cd_table_ops;
+
+	return tbl;
+}
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
index e13b092e6004..033eaf6c0f6c 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
@@ -11,6 +11,7 @@
 #include "arm-smmu-v3.h"
 #include "../../iommu-sva-lib.h"
 #include "../../io-pgtable-arm.h"
+#include "../../iommu-pasid-table.h"
 
 struct arm_smmu_mmu_notifier {
 	struct mmu_notifier		mn;
@@ -48,6 +49,7 @@ arm_smmu_share_asid(struct mm_struct *mm, u16 asid)
 	struct arm_smmu_ctx_desc *cd;
 	struct arm_smmu_device *smmu;
 	struct arm_smmu_domain *smmu_domain;
+	struct iommu_pasid_table *tbl;
 
 	cd = xa_load(&arm_smmu_asid_xa, asid);
 	if (!cd)
@@ -63,6 +65,7 @@ arm_smmu_share_asid(struct mm_struct *mm, u16 asid)
 
 	smmu_domain = container_of(cd, struct arm_smmu_domain, s1_cfg.cd);
 	smmu = smmu_domain->smmu;
+	tbl = smmu_domain->tbl;
 
 	ret = xa_alloc(&arm_smmu_asid_xa, &new_asid, cd,
 		       XA_LIMIT(1, (1 << smmu->asid_bits) - 1), GFP_KERNEL);
@@ -79,7 +82,9 @@ arm_smmu_share_asid(struct mm_struct *mm, u16 asid)
 	 * be some overlap between use of both ASIDs, until we invalidate the
 	 * TLB.
 	 */
-	arm_smmu_write_ctx_desc(smmu_domain, 0, cd);
+	ret = iommu_psdtable_write(tbl, &tbl->cfg, 0, cd);
+	if (ret)
+		return ERR_PTR(-ENOSYS);
 
 	/* Invalidate TLB entries previously associated with that context */
 	arm_smmu_tlb_inv_asid(smmu, asid);
@@ -191,6 +196,7 @@ static void arm_smmu_mm_release(struct mmu_notifier *mn, struct mm_struct *mm)
 {
 	struct arm_smmu_mmu_notifier *smmu_mn = mn_to_smmu(mn);
 	struct arm_smmu_domain *smmu_domain = smmu_mn->domain;
+	struct iommu_pasid_table *tbl = smmu_domain->tbl;
 
 	mutex_lock(&sva_lock);
 	if (smmu_mn->cleared) {
@@ -202,7 +208,7 @@ static void arm_smmu_mm_release(struct mmu_notifier *mn, struct mm_struct *mm)
 	 * DMA may still be running. Keep the cd valid to avoid C_BAD_CD events,
 	 * but disable translation.
 	 */
-	arm_smmu_write_ctx_desc(smmu_domain, mm->pasid, &quiet_cd);
+	iommu_psdtable_write(tbl, &tbl->cfg, mm->pasid, &quiet_cd);
 
 	arm_smmu_tlb_inv_asid(smmu_domain->smmu, smmu_mn->cd->asid);
 	arm_smmu_atc_inv_domain(smmu_domain, mm->pasid, 0, 0);
@@ -230,6 +236,7 @@ arm_smmu_mmu_notifier_get(struct arm_smmu_domain *smmu_domain,
 	int ret;
 	struct arm_smmu_ctx_desc *cd;
 	struct arm_smmu_mmu_notifier *smmu_mn;
+	struct iommu_pasid_table *tbl = smmu_domain->tbl;
 
 	list_for_each_entry(smmu_mn, &smmu_domain->mmu_notifiers, list) {
 		if (smmu_mn->mn.mm == mm) {
@@ -259,7 +266,7 @@ arm_smmu_mmu_notifier_get(struct arm_smmu_domain *smmu_domain,
 		goto err_free_cd;
 	}
 
-	ret = arm_smmu_write_ctx_desc(smmu_domain, mm->pasid, cd);
+	ret = iommu_psdtable_write(tbl, &tbl->cfg, mm->pasid, cd);
 	if (ret)
 		goto err_put_notifier;
 
@@ -279,12 +286,13 @@ static void arm_smmu_mmu_notifier_put(struct arm_smmu_mmu_notifier *smmu_mn)
 	struct mm_struct *mm = smmu_mn->mn.mm;
 	struct arm_smmu_ctx_desc *cd = smmu_mn->cd;
 	struct arm_smmu_domain *smmu_domain = smmu_mn->domain;
+	struct iommu_pasid_table *tbl = smmu_domain->tbl;
 
 	if (!refcount_dec_and_test(&smmu_mn->refs))
 		return;
 
 	list_del(&smmu_mn->list);
-	arm_smmu_write_ctx_desc(smmu_domain, mm->pasid, NULL);
+	iommu_psdtable_write(tbl, &tbl->cfg, mm->pasid, NULL);
 
 	/*
 	 * If we went through clear(), we've already invalidated, and no
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 13513f2f651a..2f86c6ac42b6 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -32,6 +32,7 @@
 #include <linux/amba/bus.h>
 
 #include "arm-smmu-v3.h"
+#include "../../iommu-pasid-table.h"
 
 static bool disable_bypass = true;
 module_param(disable_bypass, bool, 0444);
@@ -894,12 +895,13 @@ void arm_smmu_tlb_inv_asid(struct arm_smmu_device *smmu, u16 asid)
 	arm_smmu_cmdq_issue_sync(smmu);
 }
 
-void arm_smmu_sync_cd(struct arm_smmu_domain *smmu_domain, int ssid, bool leaf)
+void arm_smmu_sync_cd(void *cookie, int ssid, bool leaf)
 {
 	size_t i;
 	unsigned long flags;
 	struct arm_smmu_master *master;
 	struct arm_smmu_cmdq_batch cmds = {};
+	struct arm_smmu_domain *smmu_domain = cookie;
 	struct arm_smmu_device *smmu = smmu_domain->smmu;
 	struct arm_smmu_cmdq_ent cmd = {
 		.opcode	= CMDQ_OP_CFGI_CD,
@@ -1797,6 +1799,7 @@ static void arm_smmu_domain_free(struct iommu_domain *domain)
 	struct arm_smmu_device *smmu = smmu_domain->smmu;
 	struct arm_smmu_s1_cfg *s1_cfg = &smmu_domain->s1_cfg;
 	struct arm_smmu_s2_cfg *s2_cfg = &smmu_domain->s2_cfg;
+	struct iommu_pasid_table *tbl = smmu_domain->tbl;
 
 	iommu_put_dma_cookie(domain);
 	free_io_pgtable_ops(smmu_domain->pgtbl_ops);
@@ -1806,7 +1809,7 @@ static void arm_smmu_domain_free(struct iommu_domain *domain)
 		/* Prevent SVA from touching the CD while we're freeing it */
 		mutex_lock(&arm_smmu_asid_lock);
 		if (s1_cfg->cdcfg.cdtab)
-			arm_smmu_free_cd_tables(smmu_domain);
+			iommu_psdtable_free(tbl, &tbl->cfg);
 		arm_smmu_free_asid(&s1_cfg->cd);
 		mutex_unlock(&arm_smmu_asid_lock);
 	}
@@ -1826,7 +1829,8 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain,
 	u32 asid;
 	struct arm_smmu_device *smmu = smmu_domain->smmu;
 	struct arm_smmu_s1_cfg *cfg = &smmu_domain->s1_cfg;
-	typeof(&pgtbl_cfg->arm_lpae_s1_cfg.tcr) tcr = &pgtbl_cfg->arm_lpae_s1_cfg.tcr;
+	struct iommu_vendor_psdtable_cfg *pst_cfg;
+	struct iommu_pasid_table *tbl;
 
 	refcount_set(&cfg->cd.refs, 1);
 
@@ -1837,29 +1841,40 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain,
 	if (ret)
 		goto out_unlock;
 
+	tbl = iommu_register_pasid_table(PASID_TABLE_ARM_SMMU_V3, smmu->dev, smmu_domain);
+	if (!tbl) {
+		ret = -ENOMEM;
+		goto out_free_asid;
+	}
+
+	pst_cfg = &tbl->cfg;
+
+	pst_cfg->iommu_dev = smmu->dev;
+	pst_cfg->fmt = PASID_TABLE_ARM_SMMU_V3;
+	pst_cfg->vendor.cfg.s1_cfg = &smmu_domain->s1_cfg;
+
+	if (smmu->features & ARM_SMMU_FEAT_2_LVL_CDTAB)
+		pst_cfg->vendor.cfg.feat_flag |= ARM_SMMU_FEAT_2_LVL_CDTAB;
+	if (smmu->features & ARM_SMMU_FEAT_STALL_FORCE)
+		pst_cfg->vendor.cfg.feat_flag |= ARM_SMMU_FEAT_STALL_FORCE;
+
 	cfg->s1cdmax = master->ssid_bits;
 
-	ret = arm_smmu_alloc_cd_tables(smmu_domain);
+	smmu_domain->tbl = tbl;
+	ret = iommu_psdtable_alloc(tbl, pst_cfg);
 	if (ret)
 		goto out_free_asid;
 
-	cfg->cd.asid	= (u16)asid;
-	cfg->cd.ttbr	= pgtbl_cfg->arm_lpae_s1_cfg.ttbr;
-	cfg->cd.tcr	= FIELD_PREP(CTXDESC_CD_0_TCR_T0SZ, tcr->tsz) |
-			  FIELD_PREP(CTXDESC_CD_0_TCR_TG0, tcr->tg) |
-			  FIELD_PREP(CTXDESC_CD_0_TCR_IRGN0, tcr->irgn) |
-			  FIELD_PREP(CTXDESC_CD_0_TCR_ORGN0, tcr->orgn) |
-			  FIELD_PREP(CTXDESC_CD_0_TCR_SH0, tcr->sh) |
-			  FIELD_PREP(CTXDESC_CD_0_TCR_IPS, tcr->ips) |
-			  CTXDESC_CD_0_TCR_EPD1 | CTXDESC_CD_0_AA64;
-	cfg->cd.mair	= pgtbl_cfg->arm_lpae_s1_cfg.mair;
+	ret = iommu_psdtable_prepare(tbl, pst_cfg, pgtbl_cfg, asid);
+	if (ret)
+		goto out_free_cd_tables;
 
 	/*
 	 * Note that this will end up calling arm_smmu_sync_cd() before
 	 * the master has been added to the devices list for this domain.
 	 * This isn't an issue because the STE hasn't been installed yet.
 	 */
-	ret = arm_smmu_write_ctx_desc(smmu_domain, 0, &cfg->cd);
+	ret = iommu_psdtable_write(tbl, pst_cfg, 0, &cfg->cd);
 	if (ret)
 		goto out_free_cd_tables;
 
@@ -1867,7 +1882,7 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain,
 	return 0;
 
 out_free_cd_tables:
-	arm_smmu_free_cd_tables(smmu_domain);
+	iommu_psdtable_free(tbl, pst_cfg);
 out_free_asid:
 	arm_smmu_free_asid(&cfg->cd);
 out_unlock:
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index a50a3e4874f9..7f35fbecf280 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -713,6 +713,7 @@ struct arm_smmu_domain {
 	struct arm_smmu_s1_cfg	s1_cfg;
 	struct arm_smmu_s2_cfg	s2_cfg;
 	bool				abort;
+	struct iommu_pasid_table	*tbl;
 
 	struct iommu_domain		domain;
 
@@ -782,11 +783,7 @@ extern struct xarray arm_smmu_asid_xa;
 extern struct mutex arm_smmu_asid_lock;
 extern struct arm_smmu_ctx_desc quiet_cd;
 
-int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid,
-			    struct arm_smmu_ctx_desc *cd);
-int arm_smmu_alloc_cd_tables(struct arm_smmu_domain *smmu_domain);
-void arm_smmu_free_cd_tables(struct arm_smmu_domain *smmu_domain);
-void arm_smmu_sync_cd(struct arm_smmu_domain *smmu_domain, int ssid, bool leaf);
+void arm_smmu_sync_cd(void *cookie, int ssid, bool leaf);
 void arm_smmu_tlb_inv_asid(struct arm_smmu_device *smmu, u16 asid);
 bool arm_smmu_free_asid(struct arm_smmu_ctx_desc *cd);
 int arm_smmu_atc_inv_domain(struct arm_smmu_domain *smmu_domain, int ssid,
diff --git a/drivers/iommu/iommu-pasid-table.h b/drivers/iommu/iommu-pasid-table.h
index bd4f57656f67..7659157d14fa 100644
--- a/drivers/iommu/iommu-pasid-table.h
+++ b/drivers/iommu/iommu-pasid-table.h
@@ -123,12 +123,18 @@ static inline int iommu_psdtable_sync(struct iommu_pasid_table *tbl,
 	return 0;
 }
 
-/* A placeholder to register vendor specific pasid layer */
+struct iommu_pasid_table *arm_smmu_register_cd_table(struct device *dev,
+						     void *cookie);
+
+/* Register vendor specific pasid table management layer */
 static inline struct iommu_pasid_table *
 iommu_register_pasid_table(enum pasid_table_fmt fmt,
 			   struct device *dev, void *cookie)
 {
-	return NULL;
+	if (fmt == PASID_TABLE_ARM_SMMU_V3)
+		return arm_smmu_register_cd_table(dev, cookie);
+	else
+		return NULL;
 }
 
 #endif /* __IOMMU_PASID_TABLE_H */
-- 
2.17.1


^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH RFC v1 04/15] iommu/arm-smmu-v3: Update CD base address info for user-space
  2021-01-15 12:13 [PATCH RFC v1 00/15] iommu/virtio: Nested stage support with Arm Vivek Gautam
                   ` (2 preceding siblings ...)
  2021-01-15 12:13 ` [PATCH RFC v1 03/15] iommu/arm-smmu-v3: Update drivers to work with iommu-pasid-table Vivek Gautam
@ 2021-01-15 12:13 ` Vivek Gautam
  2021-03-03 17:14   ` Jean-Philippe Brucker
  2021-01-15 12:13 ` [PATCH RFC v1 05/15] iommu/arm-smmu-v3: Set sync op from consumer driver of cd-lib Vivek Gautam
                   ` (11 subsequent siblings)
  15 siblings, 1 reply; 44+ messages in thread
From: Vivek Gautam @ 2021-01-15 12:13 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, iommu, virtualization
  Cc: joro, will.deacon, mst, robin.murphy, jean-philippe, eric.auger,
	alex.williamson, kevin.tian, jacob.jun.pan, yi.l.liu,
	lorenzo.pieralisi, shameerali.kolothum.thodi, vivek.gautam

Update base address information in vendor pasid table info to pass that
to user-space for stage1 table management.

Signed-off-by: Vivek Gautam <vivek.gautam@arm.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
Cc: Eric Auger <eric.auger@redhat.com>
Cc: Alex Williamson <alex.williamson@redhat.com>
Cc: Kevin Tian <kevin.tian@intel.com>
Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
Cc: Liu Yi L <yi.l.liu@intel.com>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c
index 8a7187534706..ec37476c8d09 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c
@@ -55,6 +55,9 @@ static __le64 *arm_smmu_get_cd_ptr(struct iommu_vendor_psdtable_cfg *pst_cfg,
 		if (arm_smmu_alloc_cd_leaf_table(dev, l1_desc))
 			return NULL;
 
+		if (s1cfg->s1fmt == STRTAB_STE_0_S1FMT_LINEAR)
+			pst_cfg->base = l1_desc->l2ptr_dma;
+
 		l1ptr = cdcfg->cdtab + idx * CTXDESC_L1_DESC_DWORDS;
 		arm_smmu_write_cd_l1_desc(l1ptr, l1_desc);
 		/* An invalid L1CD can be cached */
@@ -211,6 +214,9 @@ static int arm_smmu_alloc_cd_tables(struct iommu_vendor_psdtable_cfg *pst_cfg)
 		goto err_free_l1;
 	}
 
+	if (s1cfg->s1fmt == STRTAB_STE_0_S1FMT_64K_L2)
+		pst_cfg->base = cdcfg->cdtab_dma;
+
 	return 0;
 
 err_free_l1:
-- 
2.17.1


^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH RFC v1 05/15] iommu/arm-smmu-v3: Set sync op from consumer driver of cd-lib
  2021-01-15 12:13 [PATCH RFC v1 00/15] iommu/virtio: Nested stage support with Arm Vivek Gautam
                   ` (3 preceding siblings ...)
  2021-01-15 12:13 ` [PATCH RFC v1 04/15] iommu/arm-smmu-v3: Update CD base address info for user-space Vivek Gautam
@ 2021-01-15 12:13 ` Vivek Gautam
  2021-03-03 17:15   ` Jean-Philippe Brucker
  2021-01-15 12:13 ` [PATCH RFC v1 06/15] iommu/virtio: Add headers for table format probing Vivek Gautam
                   ` (10 subsequent siblings)
  15 siblings, 1 reply; 44+ messages in thread
From: Vivek Gautam @ 2021-01-15 12:13 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, iommu, virtualization
  Cc: joro, will.deacon, mst, robin.murphy, jean-philippe, eric.auger,
	alex.williamson, kevin.tian, jacob.jun.pan, yi.l.liu,
	lorenzo.pieralisi, shameerali.kolothum.thodi, vivek.gautam

Te change allows different consumers of arm-smmu-v3-cd-lib to set
their respective sync op for pasid entries.

Signed-off-by: Vivek Gautam <vivek.gautam@arm.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
Cc: Eric Auger <eric.auger@redhat.com>
Cc: Alex Williamson <alex.williamson@redhat.com>
Cc: Kevin Tian <kevin.tian@intel.com>
Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
Cc: Liu Yi L <yi.l.liu@intel.com>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c | 1 -
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c        | 7 +++++++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c
index ec37476c8d09..acaa09acecdd 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c
@@ -265,7 +265,6 @@ struct iommu_vendor_psdtable_ops arm_cd_table_ops = {
 	.free	 = arm_smmu_free_cd_tables,
 	.prepare = arm_smmu_prepare_cd,
 	.write	 = arm_smmu_write_ctx_desc,
-	.sync	 = arm_smmu_sync_cd,
 };
 
 struct iommu_pasid_table *arm_smmu_register_cd_table(struct device *dev,
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 2f86c6ac42b6..0c644be22b4b 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -1869,6 +1869,13 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain,
 	if (ret)
 		goto out_free_cd_tables;
 
+	/*
+	 * Strange to setup an op here?
+	 * cd-lib is the actual user of sync op, and therefore the platform
+	 * drivers should assign this sync/maintenance ops as per need.
+	 */
+	tbl->ops->sync = arm_smmu_sync_cd;
+
 	/*
 	 * Note that this will end up calling arm_smmu_sync_cd() before
 	 * the master has been added to the devices list for this domain.
-- 
2.17.1


^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH RFC v1 06/15] iommu/virtio: Add headers for table format probing
  2021-01-15 12:13 [PATCH RFC v1 00/15] iommu/virtio: Nested stage support with Arm Vivek Gautam
                   ` (4 preceding siblings ...)
  2021-01-15 12:13 ` [PATCH RFC v1 05/15] iommu/arm-smmu-v3: Set sync op from consumer driver of cd-lib Vivek Gautam
@ 2021-01-15 12:13 ` Vivek Gautam
  2021-03-03 17:17   ` Jean-Philippe Brucker
  2021-01-15 12:13 ` [PATCH RFC v1 07/15] iommu/virtio: Add " Vivek Gautam
                   ` (9 subsequent siblings)
  15 siblings, 1 reply; 44+ messages in thread
From: Vivek Gautam @ 2021-01-15 12:13 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, iommu, virtualization
  Cc: joro, will.deacon, mst, robin.murphy, jean-philippe, eric.auger,
	alex.williamson, kevin.tian, jacob.jun.pan, yi.l.liu,
	lorenzo.pieralisi, shameerali.kolothum.thodi, vivek.gautam

From: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>

Add required UAPI defines for probing table format for underlying
iommu hardware. The device may provide information about hardware
tables and additional capabilities for each device.
This allows guest to correctly fabricate stage-1 page tables.

Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
[Vivek: Use a single "struct virtio_iommu_probe_table_format" rather
        than separate structures for page table and pasid table format.
	Also update commit message.]
Signed-off-by: Vivek Gautam <vivek.gautam@arm.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
Cc: Eric Auger <eric.auger@redhat.com>
Cc: Alex Williamson <alex.williamson@redhat.com>
Cc: Kevin Tian <kevin.tian@intel.com>
Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
Cc: Liu Yi L <yi.l.liu@intel.com>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
---
 include/uapi/linux/virtio_iommu.h | 44 ++++++++++++++++++++++++++++++-
 1 file changed, 43 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/virtio_iommu.h b/include/uapi/linux/virtio_iommu.h
index 237e36a280cb..43821e33e7af 100644
--- a/include/uapi/linux/virtio_iommu.h
+++ b/include/uapi/linux/virtio_iommu.h
@@ -2,7 +2,7 @@
 /*
  * Virtio-iommu definition v0.12
  *
- * Copyright (C) 2019 Arm Ltd.
+ * Copyright (C) 2019-2021 Arm Ltd.
  */
 #ifndef _UAPI_LINUX_VIRTIO_IOMMU_H
 #define _UAPI_LINUX_VIRTIO_IOMMU_H
@@ -111,6 +111,12 @@ struct virtio_iommu_req_unmap {
 
 #define VIRTIO_IOMMU_PROBE_T_NONE		0
 #define VIRTIO_IOMMU_PROBE_T_RESV_MEM		1
+#define VIRTIO_IOMMU_PROBE_T_PAGE_SIZE_MASK	2
+#define VIRTIO_IOMMU_PROBE_T_INPUT_RANGE	3
+#define VIRTIO_IOMMU_PROBE_T_OUTPUT_SIZE	4
+#define VIRTIO_IOMMU_PROBE_T_PASID_SIZE		5
+#define VIRTIO_IOMMU_PROBE_T_PAGE_TABLE_FMT	6
+#define VIRTIO_IOMMU_PROBE_T_PASID_TABLE_FMT	7
 
 #define VIRTIO_IOMMU_PROBE_T_MASK		0xfff
 
@@ -130,6 +136,42 @@ struct virtio_iommu_probe_resv_mem {
 	__le64					end;
 };
 
+struct virtio_iommu_probe_page_size_mask {
+	struct virtio_iommu_probe_property	head;
+	__u8					reserved[4];
+	__le64					mask;
+};
+
+struct virtio_iommu_probe_input_range {
+	struct virtio_iommu_probe_property	head;
+	__u8					reserved[4];
+	__le64					start;
+	__le64					end;
+};
+
+struct virtio_iommu_probe_output_size {
+	struct virtio_iommu_probe_property	head;
+	__u8					bits;
+	__u8					reserved[3];
+};
+
+struct virtio_iommu_probe_pasid_size {
+	struct virtio_iommu_probe_property	head;
+	__u8					bits;
+	__u8					reserved[3];
+};
+
+/* Arm LPAE page table format */
+#define VIRTIO_IOMMU_FOMRAT_PGTF_ARM_LPAE	1
+/* Arm smmu-v3 type PASID table format */
+#define VIRTIO_IOMMU_FORMAT_PSTF_ARM_SMMU_V3	2
+
+struct virtio_iommu_probe_table_format {
+	struct virtio_iommu_probe_property	head;
+	__le16					format;
+	__u8					reserved[2];
+};
+
 struct virtio_iommu_req_probe {
 	struct virtio_iommu_req_head		head;
 	__le32					endpoint;
-- 
2.17.1


^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH RFC v1 07/15] iommu/virtio: Add table format probing
  2021-01-15 12:13 [PATCH RFC v1 00/15] iommu/virtio: Nested stage support with Arm Vivek Gautam
                   ` (5 preceding siblings ...)
  2021-01-15 12:13 ` [PATCH RFC v1 06/15] iommu/virtio: Add headers for table format probing Vivek Gautam
@ 2021-01-15 12:13 ` Vivek Gautam
  2021-01-15 12:13 ` [PATCH RFC v1 08/15] iommu: Add asid_bits to arm smmu-v3 stage1 table info Vivek Gautam
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 44+ messages in thread
From: Vivek Gautam @ 2021-01-15 12:13 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, iommu, virtualization
  Cc: joro, will.deacon, mst, robin.murphy, jean-philippe, eric.auger,
	alex.williamson, kevin.tian, jacob.jun.pan, yi.l.liu,
	lorenzo.pieralisi, shameerali.kolothum.thodi, vivek.gautam

From: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>

The device may provide information about hardware tables and additional
capabilities for each device. Parse the new probe fields.

Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
[Vivek: Refactor to use "struct virtio_iommu_probe_table_format" rather
        than separate structures for page table and pasid table format.]
Signed-off-by: Vivek Gautam <vivek.gautam@arm.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
Cc: Eric Auger <eric.auger@redhat.com>
Cc: Alex Williamson <alex.williamson@redhat.com>
Cc: Kevin Tian <kevin.tian@intel.com>
Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
Cc: Liu Yi L <yi.l.liu@intel.com>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
---
 drivers/iommu/virtio-iommu.c | 102 ++++++++++++++++++++++++++++++++++-
 1 file changed, 101 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c
index 2bfdd5734844..12d73321dbf4 100644
--- a/drivers/iommu/virtio-iommu.c
+++ b/drivers/iommu/virtio-iommu.c
@@ -78,6 +78,17 @@ struct viommu_endpoint {
 	struct viommu_dev		*viommu;
 	struct viommu_domain		*vdomain;
 	struct list_head		resv_regions;
+
+	/* properties of the physical IOMMU */
+	u64				pgsize_mask;
+	u64				input_start;
+	u64				input_end;
+	u8				output_bits;
+	u8				pasid_bits;
+	/* Preferred PASID table format */
+	void				*pstf;
+	/* Preferred page table format */
+	void				*pgtf;
 };
 
 struct viommu_request {
@@ -457,6 +468,72 @@ static int viommu_add_resv_mem(struct viommu_endpoint *vdev,
 	return 0;
 }
 
+static int viommu_add_pgsize_mask(struct viommu_endpoint *vdev,
+				  struct virtio_iommu_probe_page_size_mask *prop,
+				  size_t len)
+{
+	if (len < sizeof(*prop))
+		return -EINVAL;
+	vdev->pgsize_mask = le64_to_cpu(prop->mask);
+	return 0;
+}
+
+static int viommu_add_input_range(struct viommu_endpoint *vdev,
+				  struct virtio_iommu_probe_input_range *prop,
+				  size_t len)
+{
+	if (len < sizeof(*prop))
+		return -EINVAL;
+	vdev->input_start	= le64_to_cpu(prop->start);
+	vdev->input_end		= le64_to_cpu(prop->end);
+	return 0;
+}
+
+static int viommu_add_output_size(struct viommu_endpoint *vdev,
+				  struct virtio_iommu_probe_output_size *prop,
+				  size_t len)
+{
+	if (len < sizeof(*prop))
+		return -EINVAL;
+	vdev->output_bits = prop->bits;
+	return 0;
+}
+
+static int viommu_add_pasid_size(struct viommu_endpoint *vdev,
+				 struct virtio_iommu_probe_pasid_size *prop,
+				 size_t len)
+{
+	if (len < sizeof(*prop))
+		return -EINVAL;
+	vdev->pasid_bits = prop->bits;
+	return 0;
+}
+
+static int viommu_add_pgtf(struct viommu_endpoint *vdev, void *pgtf, size_t len)
+{
+	/* Select the first page table format available */
+	if (len < sizeof(struct virtio_iommu_probe_table_format) || vdev->pgtf)
+		return -EINVAL;
+
+	vdev->pgtf = kmemdup(pgtf, len, GFP_KERNEL);
+	if (!vdev->pgtf)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static int viommu_add_pstf(struct viommu_endpoint *vdev, void *pstf, size_t len)
+{
+	if (len < sizeof(struct virtio_iommu_probe_table_format) || vdev->pstf)
+		return -EINVAL;
+
+	vdev->pstf = kmemdup(pstf, len, GFP_KERNEL);
+	if (!vdev->pstf)
+		return -ENOMEM;
+
+	return 0;
+}
+
 static int viommu_probe_endpoint(struct viommu_dev *viommu, struct device *dev)
 {
 	int ret;
@@ -493,11 +570,30 @@ static int viommu_probe_endpoint(struct viommu_dev *viommu, struct device *dev)
 
 	while (type != VIRTIO_IOMMU_PROBE_T_NONE &&
 	       cur < viommu->probe_size) {
+		void *value = prop;
 		len = le16_to_cpu(prop->length) + sizeof(*prop);
 
 		switch (type) {
 		case VIRTIO_IOMMU_PROBE_T_RESV_MEM:
-			ret = viommu_add_resv_mem(vdev, (void *)prop, len);
+			ret = viommu_add_resv_mem(vdev, value, len);
+			break;
+		case VIRTIO_IOMMU_PROBE_T_PAGE_SIZE_MASK:
+			ret = viommu_add_pgsize_mask(vdev, value, len);
+			break;
+		case VIRTIO_IOMMU_PROBE_T_INPUT_RANGE:
+			ret = viommu_add_input_range(vdev, value, len);
+			break;
+		case VIRTIO_IOMMU_PROBE_T_OUTPUT_SIZE:
+			ret = viommu_add_output_size(vdev, value, len);
+			break;
+		case VIRTIO_IOMMU_PROBE_T_PASID_SIZE:
+			ret = viommu_add_pasid_size(vdev, value, len);
+			break;
+		case VIRTIO_IOMMU_PROBE_T_PAGE_TABLE_FMT:
+			ret = viommu_add_pgtf(vdev, value, len);
+			break;
+		case VIRTIO_IOMMU_PROBE_T_PASID_TABLE_FMT:
+			ret = viommu_add_pstf(vdev, value, len);
 			break;
 		default:
 			dev_err(dev, "unknown viommu prop 0x%x\n", type);
@@ -899,6 +995,8 @@ static struct iommu_device *viommu_probe_device(struct device *dev)
 
 err_free_dev:
 	generic_iommu_put_resv_regions(dev, &vdev->resv_regions);
+	kfree(vdev->pstf);
+	kfree(vdev->pgtf);
 	kfree(vdev);
 
 	return ERR_PTR(ret);
@@ -915,6 +1013,8 @@ static void viommu_release_device(struct device *dev)
 	vdev = dev_iommu_priv_get(dev);
 
 	generic_iommu_put_resv_regions(dev, &vdev->resv_regions);
+	kfree(vdev->pstf);
+	kfree(vdev->pgtf);
 	kfree(vdev);
 }
 
-- 
2.17.1


^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH RFC v1 08/15] iommu: Add asid_bits to arm smmu-v3 stage1 table info
  2021-01-15 12:13 [PATCH RFC v1 00/15] iommu/virtio: Nested stage support with Arm Vivek Gautam
                   ` (6 preceding siblings ...)
  2021-01-15 12:13 ` [PATCH RFC v1 07/15] iommu/virtio: Add " Vivek Gautam
@ 2021-01-15 12:13 ` Vivek Gautam
  2021-03-03 17:18   ` Jean-Philippe Brucker
  2021-01-15 12:13 ` [PATCH RFC v1 09/15] iommu/virtio: Update table format probing header Vivek Gautam
                   ` (7 subsequent siblings)
  15 siblings, 1 reply; 44+ messages in thread
From: Vivek Gautam @ 2021-01-15 12:13 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, iommu, virtualization
  Cc: joro, will.deacon, mst, robin.murphy, jean-philippe, eric.auger,
	alex.williamson, kevin.tian, jacob.jun.pan, yi.l.liu,
	lorenzo.pieralisi, shameerali.kolothum.thodi, vivek.gautam

aisd_bits data is required to prepare stage-1 tables for arm-smmu-v3.

Signed-off-by: Vivek Gautam <vivek.gautam@arm.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
Cc: Eric Auger <eric.auger@redhat.com>
Cc: Alex Williamson <alex.williamson@redhat.com>
Cc: Kevin Tian <kevin.tian@intel.com>
Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
Cc: Liu Yi L <yi.l.liu@intel.com>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
---
 include/uapi/linux/iommu.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/uapi/linux/iommu.h b/include/uapi/linux/iommu.h
index 082d758dd016..96abbfc7c643 100644
--- a/include/uapi/linux/iommu.h
+++ b/include/uapi/linux/iommu.h
@@ -357,7 +357,7 @@ struct iommu_pasid_smmuv3 {
 	__u32	version;
 	__u8	s1fmt;
 	__u8	s1dss;
-	__u8	padding[2];
+	__u16	asid_bits;
 };
 
 /**
-- 
2.17.1


^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH RFC v1 09/15] iommu/virtio: Update table format probing header
  2021-01-15 12:13 [PATCH RFC v1 00/15] iommu/virtio: Nested stage support with Arm Vivek Gautam
                   ` (7 preceding siblings ...)
  2021-01-15 12:13 ` [PATCH RFC v1 08/15] iommu: Add asid_bits to arm smmu-v3 stage1 table info Vivek Gautam
@ 2021-01-15 12:13 ` Vivek Gautam
  2021-03-03 17:21   ` Jean-Philippe Brucker
  2021-01-15 12:13 ` [PATCH RFC v1 10/15] iommu/virtio: Prepare to add attach pasid table infrastructure Vivek Gautam
                   ` (6 subsequent siblings)
  15 siblings, 1 reply; 44+ messages in thread
From: Vivek Gautam @ 2021-01-15 12:13 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, iommu, virtualization
  Cc: joro, will.deacon, mst, robin.murphy, jean-philippe, eric.auger,
	alex.williamson, kevin.tian, jacob.jun.pan, yi.l.liu,
	lorenzo.pieralisi, shameerali.kolothum.thodi, vivek.gautam

Add info about asid_bits and additional flags to table format
probing header.

Signed-off-by: Vivek Gautam <vivek.gautam@arm.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
Cc: Eric Auger <eric.auger@redhat.com>
Cc: Alex Williamson <alex.williamson@redhat.com>
Cc: Kevin Tian <kevin.tian@intel.com>
Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
Cc: Liu Yi L <yi.l.liu@intel.com>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
---
 include/uapi/linux/virtio_iommu.h | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/virtio_iommu.h b/include/uapi/linux/virtio_iommu.h
index 43821e33e7af..8a0624bab4b2 100644
--- a/include/uapi/linux/virtio_iommu.h
+++ b/include/uapi/linux/virtio_iommu.h
@@ -169,7 +169,10 @@ struct virtio_iommu_probe_pasid_size {
 struct virtio_iommu_probe_table_format {
 	struct virtio_iommu_probe_property	head;
 	__le16					format;
-	__u8					reserved[2];
+	__le16					asid_bits;
+
+	__le32					flags;
+	__u8					reserved[4];
 };
 
 struct virtio_iommu_req_probe {
-- 
2.17.1


^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH RFC v1 10/15] iommu/virtio: Prepare to add attach pasid table infrastructure
  2021-01-15 12:13 [PATCH RFC v1 00/15] iommu/virtio: Nested stage support with Arm Vivek Gautam
                   ` (8 preceding siblings ...)
  2021-01-15 12:13 ` [PATCH RFC v1 09/15] iommu/virtio: Update table format probing header Vivek Gautam
@ 2021-01-15 12:13 ` Vivek Gautam
  2021-01-15 12:13 ` [PATCH RFC v1 11/15] iommu/virtio: Add headers for binding pasid table in iommu Vivek Gautam
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 44+ messages in thread
From: Vivek Gautam @ 2021-01-15 12:13 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, iommu, virtualization
  Cc: joro, will.deacon, mst, robin.murphy, jean-philippe, eric.auger,
	alex.williamson, kevin.tian, jacob.jun.pan, yi.l.liu,
	lorenzo.pieralisi, shameerali.kolothum.thodi, vivek.gautam

In preparation to add attach pasid table op, separate out the
existing attach request code to a separate method.

Signed-off-by: Vivek Gautam <vivek.gautam@arm.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
Cc: Eric Auger <eric.auger@redhat.com>
Cc: Alex Williamson <alex.williamson@redhat.com>
Cc: Kevin Tian <kevin.tian@intel.com>
Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
Cc: Liu Yi L <yi.l.liu@intel.com>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
---
 drivers/iommu/virtio-iommu.c | 73 +++++++++++++++++++++++++-----------
 1 file changed, 51 insertions(+), 22 deletions(-)

diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c
index 12d73321dbf4..ae5dfd3f8269 100644
--- a/drivers/iommu/virtio-iommu.c
+++ b/drivers/iommu/virtio-iommu.c
@@ -52,6 +52,8 @@ struct viommu_dev {
 	/* Supported MAP flags */
 	u32				map_flags;
 	u32				probe_size;
+
+	bool				has_map:1;
 };
 
 struct viommu_mapping {
@@ -60,6 +62,11 @@ struct viommu_mapping {
 	u32				flags;
 };
 
+struct viommu_mm {
+	struct io_pgtable_ops		*ops;
+	struct viommu_domain		*domain;
+};
+
 struct viommu_domain {
 	struct iommu_domain		domain;
 	struct viommu_dev		*viommu;
@@ -67,12 +74,20 @@ struct viommu_domain {
 	unsigned int			id;
 	u32				map_flags;
 
+	/* Default address space when a table is bound */
+	struct viommu_mm		mm;
+
+	/* When no table is bound, use generic mappings */
 	spinlock_t			mappings_lock;
 	struct rb_root_cached		mappings;
 
 	unsigned long			nr_endpoints;
 };
 
+#define vdev_for_each_id(i, eid, vdev)					\
+	for (i = 0; i < vdev->dev->iommu->fwspec->num_ids &&		\
+		({ eid = vdev->dev->iommu->fwspec->ids[i]; 1; }); i++)
+
 struct viommu_endpoint {
 	struct device			*dev;
 	struct viommu_dev		*viommu;
@@ -750,12 +765,40 @@ static void viommu_domain_free(struct iommu_domain *domain)
 	kfree(vdomain);
 }
 
+static int viommu_simple_attach(struct viommu_domain *vdomain,
+				struct viommu_endpoint *vdev)
+{
+	int i, eid, ret;
+	struct virtio_iommu_req_attach req = {
+		.head.type	= VIRTIO_IOMMU_T_ATTACH,
+		.domain		= cpu_to_le32(vdomain->id),
+	};
+
+	if (!vdomain->viommu->has_map)
+		return -ENODEV;
+
+	vdev_for_each_id(i, eid, vdev) {
+		req.endpoint = cpu_to_le32(eid);
+
+		ret = viommu_send_req_sync(vdomain->viommu, &req, sizeof(req));
+		if (ret)
+			return ret;
+	}
+
+	if (!vdomain->nr_endpoints) {
+		/*
+		 * This endpoint is the first to be attached to the domain.
+		 * Replay existing mappings if any (e.g. SW MSI).
+		 */
+		ret = viommu_replay_mappings(vdomain);
+	}
+
+	return ret;
+}
+
 static int viommu_attach_dev(struct iommu_domain *domain, struct device *dev)
 {
-	int i;
 	int ret = 0;
-	struct virtio_iommu_req_attach req;
-	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
 	struct viommu_endpoint *vdev = dev_iommu_priv_get(dev);
 	struct viommu_domain *vdomain = to_viommu_domain(domain);
 
@@ -790,25 +833,9 @@ static int viommu_attach_dev(struct iommu_domain *domain, struct device *dev)
 	if (vdev->vdomain)
 		vdev->vdomain->nr_endpoints--;
 
-	req = (struct virtio_iommu_req_attach) {
-		.head.type	= VIRTIO_IOMMU_T_ATTACH,
-		.domain		= cpu_to_le32(vdomain->id),
-	};
-
-	for (i = 0; i < fwspec->num_ids; i++) {
-		req.endpoint = cpu_to_le32(fwspec->ids[i]);
-
-		ret = viommu_send_req_sync(vdomain->viommu, &req, sizeof(req));
-		if (ret)
-			return ret;
-	}
-
-	if (!vdomain->nr_endpoints) {
-		/*
-		 * This endpoint is the first to be attached to the domain.
-		 * Replay existing mappings (e.g. SW MSI).
-		 */
-		ret = viommu_replay_mappings(vdomain);
+	if (!vdomain->mm.ops) {
+		/* If we couldn't bind any table, use the mapping tree */
+		ret = viommu_simple_attach(vdomain, vdev);
 		if (ret)
 			return ret;
 	}
@@ -1142,6 +1169,8 @@ static int viommu_probe(struct virtio_device *vdev)
 				struct virtio_iommu_config, probe_size,
 				&viommu->probe_size);
 
+	viommu->has_map = virtio_has_feature(vdev, VIRTIO_IOMMU_F_MAP_UNMAP);
+
 	viommu->geometry = (struct iommu_domain_geometry) {
 		.aperture_start	= input_start,
 		.aperture_end	= input_end,
-- 
2.17.1


^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH RFC v1 11/15] iommu/virtio: Add headers for binding pasid table in iommu
  2021-01-15 12:13 [PATCH RFC v1 00/15] iommu/virtio: Nested stage support with Arm Vivek Gautam
                   ` (9 preceding siblings ...)
  2021-01-15 12:13 ` [PATCH RFC v1 10/15] iommu/virtio: Prepare to add attach pasid table infrastructure Vivek Gautam
@ 2021-01-15 12:13 ` Vivek Gautam
  2021-01-15 12:13 ` [PATCH RFC v1 12/15] iommu/virtio: Add support for INVALIDATE request Vivek Gautam
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 44+ messages in thread
From: Vivek Gautam @ 2021-01-15 12:13 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, iommu, virtualization
  Cc: joro, will.deacon, mst, robin.murphy, jean-philippe, eric.auger,
	alex.williamson, kevin.tian, jacob.jun.pan, yi.l.liu,
	lorenzo.pieralisi, shameerali.kolothum.thodi, vivek.gautam

From: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>

Add the required UAPI defines for binding pasid tables in virtio-iommu.
This mode allows to hand stage-1 page tables over to the guest.

Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
[Vivek: Refactor to cleanup headers for invalidation]
Signed-off-by: Vivek Gautam <vivek.gautam@arm.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
Cc: Eric Auger <eric.auger@redhat.com>
Cc: Alex Williamson <alex.williamson@redhat.com>
Cc: Kevin Tian <kevin.tian@intel.com>
Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
Cc: Liu Yi L <yi.l.liu@intel.com>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
---
 include/uapi/linux/virtio_iommu.h | 68 +++++++++++++++++++++++++++++++
 1 file changed, 68 insertions(+)

diff --git a/include/uapi/linux/virtio_iommu.h b/include/uapi/linux/virtio_iommu.h
index 8a0624bab4b2..3481e4a3dd24 100644
--- a/include/uapi/linux/virtio_iommu.h
+++ b/include/uapi/linux/virtio_iommu.h
@@ -16,6 +16,7 @@
 #define VIRTIO_IOMMU_F_BYPASS			3
 #define VIRTIO_IOMMU_F_PROBE			4
 #define VIRTIO_IOMMU_F_MMIO			5
+#define VIRTIO_IOMMU_F_ATTACH_TABLE		6
 
 struct virtio_iommu_range_64 {
 	__le64					start;
@@ -44,6 +45,8 @@ struct virtio_iommu_config {
 #define VIRTIO_IOMMU_T_MAP			0x03
 #define VIRTIO_IOMMU_T_UNMAP			0x04
 #define VIRTIO_IOMMU_T_PROBE			0x05
+#define VIRTIO_IOMMU_T_ATTACH_TABLE		0x06
+#define VIRTIO_IOMMU_T_INVALIDATE		0x07
 
 /* Status types */
 #define VIRTIO_IOMMU_S_OK			0x00
@@ -82,6 +85,37 @@ struct virtio_iommu_req_detach {
 	struct virtio_iommu_req_tail		tail;
 };
 
+struct virtio_iommu_req_attach_table {
+	struct virtio_iommu_req_head		head;
+	__le32					domain;
+	__le32					endpoint;
+	__le16					format;
+	__u8					reserved[62];
+	struct virtio_iommu_req_tail		tail;
+};
+
+#define VIRTIO_IOMMU_PSTF_ARM_SMMU_V3_LINEAR	0x0
+#define VIRTIO_IOMMU_PSTF_ARM_SMMU_V3_4KL2	0x1
+#define VIRTIO_IOMMU_PSTF_ARM_SMMU_V3_64KL2	0x2
+
+#define VIRTIO_IOMMU_PSTF_ARM_SMMU_V3_DSS_TERM	0x0
+#define VIRTIO_IOMMU_PSTF_ARM_SMMU_V3_DSS_BYPASS 0x1
+#define VIRTIO_IOMMU_PSTF_ARM_SMMU_V3_DSS_0	0x2
+
+/* Arm SMMUv3 PASID Table Descriptor */
+struct virtio_iommu_req_attach_pst_arm {
+	struct virtio_iommu_req_head		head;
+	__le32					domain;
+	__le32					endpoint;
+	__le16					format;
+	__u8					s1fmt;
+	__u8					s1dss;
+	__le64					s1contextptr;
+	__le32					s1cdmax;
+	__u8					reserved[48];
+	struct virtio_iommu_req_tail		tail;
+};
+
 #define VIRTIO_IOMMU_MAP_F_READ			(1 << 0)
 #define VIRTIO_IOMMU_MAP_F_WRITE		(1 << 1)
 #define VIRTIO_IOMMU_MAP_F_MMIO			(1 << 2)
@@ -188,6 +222,40 @@ struct virtio_iommu_req_probe {
 	 */
 };
 
+#define VIRTIO_IOMMU_INVAL_G_DOMAIN		(1 << 0)
+#define VIRTIO_IOMMU_INVAL_G_PASID		(1 << 1)
+#define VIRTIO_IOMMU_INVAL_G_VA			(1 << 2)
+
+#define VIRTIO_IOMMU_INV_T_IOTLB		(1 << 0)
+#define VIRTIO_IOMMU_INV_T_DEV_IOTLB		(1 << 1)
+#define VIRTIO_IOMMU_INV_T_PASID		(1 << 2)
+
+#define VIRTIO_IOMMU_INVAL_F_PASID		(1 << 0)
+#define VIRTIO_IOMMU_INVAL_F_ARCHID		(1 << 1)
+#define VIRTIO_IOMMU_INVAL_F_LEAF		(1 << 2)
+
+struct virtio_iommu_req_invalidate {
+	struct virtio_iommu_req_head		head;
+	__le16					inv_gran;
+	__le16					inv_type;
+
+	__le16					flags;
+	__u8					reserved1[2];
+	__le32					domain;
+
+	__le32					pasid;
+	__u8					reserved2[4];
+
+	__le64					archid;
+	__le64					virt_start;
+	__le64					nr_pages;
+
+	/* Page size, in nr of bits, typically 12 for 4k, 30 for 2MB, etc.) */
+	__u8					granule;
+	__u8					reserved3[11];
+	struct virtio_iommu_req_tail		tail;
+};
+
 /* Fault types */
 #define VIRTIO_IOMMU_FAULT_R_UNKNOWN		0
 #define VIRTIO_IOMMU_FAULT_R_DOMAIN		1
-- 
2.17.1


^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH RFC v1 12/15] iommu/virtio: Add support for INVALIDATE request
  2021-01-15 12:13 [PATCH RFC v1 00/15] iommu/virtio: Nested stage support with Arm Vivek Gautam
                   ` (10 preceding siblings ...)
  2021-01-15 12:13 ` [PATCH RFC v1 11/15] iommu/virtio: Add headers for binding pasid table in iommu Vivek Gautam
@ 2021-01-15 12:13 ` Vivek Gautam
  2021-03-03 18:28   ` Jacob Pan
  2021-01-15 12:13 ` [PATCH RFC v1 13/15] iommu/virtio: Attach Arm PASID tables when available Vivek Gautam
                   ` (3 subsequent siblings)
  15 siblings, 1 reply; 44+ messages in thread
From: Vivek Gautam @ 2021-01-15 12:13 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, iommu, virtualization
  Cc: joro, will.deacon, mst, robin.murphy, jean-philippe, eric.auger,
	alex.williamson, kevin.tian, jacob.jun.pan, yi.l.liu,
	lorenzo.pieralisi, shameerali.kolothum.thodi, vivek.gautam

From: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>

Add support for tlb invalidation ops that can send invalidation
requests to back-end virtio-iommu when stage-1 page tables are
supported.

Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
[Vivek: Refactoring the iommu_flush_ops, and adding only one pasid sync
        op that's needed with current iommu-pasid-table infrastructure.
	Also updating uapi defines as required by latest changes]
Signed-off-by: Vivek Gautam <vivek.gautam@arm.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
Cc: Eric Auger <eric.auger@redhat.com>
Cc: Alex Williamson <alex.williamson@redhat.com>
Cc: Kevin Tian <kevin.tian@intel.com>
Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
Cc: Liu Yi L <yi.l.liu@intel.com>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
---
 drivers/iommu/virtio-iommu.c | 95 ++++++++++++++++++++++++++++++++++++
 1 file changed, 95 insertions(+)

diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c
index ae5dfd3f8269..004ea94e3731 100644
--- a/drivers/iommu/virtio-iommu.c
+++ b/drivers/iommu/virtio-iommu.c
@@ -13,6 +13,7 @@
 #include <linux/freezer.h>
 #include <linux/interval_tree.h>
 #include <linux/iommu.h>
+#include <linux/io-pgtable.h>
 #include <linux/module.h>
 #include <linux/of_iommu.h>
 #include <linux/of_platform.h>
@@ -63,6 +64,8 @@ struct viommu_mapping {
 };
 
 struct viommu_mm {
+	int				pasid;
+	u64				archid;
 	struct io_pgtable_ops		*ops;
 	struct viommu_domain		*domain;
 };
@@ -692,6 +695,98 @@ static void viommu_event_handler(struct virtqueue *vq)
 	virtqueue_kick(vq);
 }
 
+/* PASID and pgtable APIs */
+
+static void __viommu_flush_pasid_tlb_all(struct viommu_domain *vdomain,
+					 int pasid, u64 arch_id, int type)
+{
+	struct virtio_iommu_req_invalidate req = {
+		.head.type	= VIRTIO_IOMMU_T_INVALIDATE,
+		.inv_gran	= cpu_to_le32(VIRTIO_IOMMU_INVAL_G_PASID),
+		.flags		= cpu_to_le32(VIRTIO_IOMMU_INVAL_F_PASID),
+		.inv_type	= cpu_to_le32(type),
+
+		.domain		= cpu_to_le32(vdomain->id),
+		.pasid		= cpu_to_le32(pasid),
+		.archid		= cpu_to_le64(arch_id),
+	};
+
+	if (viommu_send_req_sync(vdomain->viommu, &req, sizeof(req)))
+		pr_debug("could not send invalidate request\n");
+}
+
+static void viommu_flush_tlb_add(struct iommu_iotlb_gather *gather,
+				 unsigned long iova, size_t granule,
+				 void *cookie)
+{
+	struct viommu_mm *viommu_mm = cookie;
+	struct viommu_domain *vdomain = viommu_mm->domain;
+	struct iommu_domain *domain = &vdomain->domain;
+
+	iommu_iotlb_gather_add_page(domain, gather, iova, granule);
+}
+
+static void viommu_flush_tlb_walk(unsigned long iova, size_t size,
+				  size_t granule, void *cookie)
+{
+	struct viommu_mm *viommu_mm = cookie;
+	struct viommu_domain *vdomain = viommu_mm->domain;
+	struct virtio_iommu_req_invalidate req = {
+		.head.type	= VIRTIO_IOMMU_T_INVALIDATE,
+		.inv_gran	= cpu_to_le32(VIRTIO_IOMMU_INVAL_G_VA),
+		.inv_type	= cpu_to_le32(VIRTIO_IOMMU_INV_T_IOTLB),
+		.flags		= cpu_to_le32(VIRTIO_IOMMU_INVAL_F_ARCHID),
+
+		.domain		= cpu_to_le32(vdomain->id),
+		.pasid		= cpu_to_le32(viommu_mm->pasid),
+		.archid		= cpu_to_le64(viommu_mm->archid),
+		.virt_start	= cpu_to_le64(iova),
+		.nr_pages	= cpu_to_le64(size / granule),
+		.granule	= ilog2(granule),
+	};
+
+	if (viommu_add_req(vdomain->viommu, &req, sizeof(req)))
+		pr_debug("could not add invalidate request\n");
+}
+
+static void viommu_flush_tlb_all(void *cookie)
+{
+	struct viommu_mm *viommu_mm = cookie;
+
+	if (!viommu_mm->archid)
+		return;
+
+	__viommu_flush_pasid_tlb_all(viommu_mm->domain, viommu_mm->pasid,
+				     viommu_mm->archid,
+				     VIRTIO_IOMMU_INV_T_IOTLB);
+}
+
+static struct iommu_flush_ops viommu_flush_ops = {
+	.tlb_flush_all		= viommu_flush_tlb_all,
+	.tlb_flush_walk		= viommu_flush_tlb_walk,
+	.tlb_add_page		= viommu_flush_tlb_add,
+};
+
+static void viommu_flush_pasid(void *cookie, int pasid, bool leaf)
+{
+	struct viommu_domain *vdomain = cookie;
+	struct virtio_iommu_req_invalidate req = {
+		.head.type	= VIRTIO_IOMMU_T_INVALIDATE,
+		.inv_gran	= cpu_to_le32(VIRTIO_IOMMU_INVAL_G_PASID),
+		.inv_type	= cpu_to_le32(VIRTIO_IOMMU_INV_T_PASID),
+		.flags		= cpu_to_le32(VIRTIO_IOMMU_INVAL_F_PASID),
+
+		.domain		= cpu_to_le32(vdomain->id),
+		.pasid		= cpu_to_le32(pasid),
+	};
+
+	if (leaf)
+		req.flags	|= cpu_to_le32(VIRTIO_IOMMU_INVAL_F_LEAF);
+
+	if (viommu_send_req_sync(vdomain->viommu, &req, sizeof(req)))
+		pr_debug("could not send invalidate request\n");
+}
+
 /* IOMMU API */
 
 static struct iommu_domain *viommu_domain_alloc(unsigned type)
-- 
2.17.1


^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH RFC v1 13/15] iommu/virtio: Attach Arm PASID tables when available
  2021-01-15 12:13 [PATCH RFC v1 00/15] iommu/virtio: Nested stage support with Arm Vivek Gautam
                   ` (11 preceding siblings ...)
  2021-01-15 12:13 ` [PATCH RFC v1 12/15] iommu/virtio: Add support for INVALIDATE request Vivek Gautam
@ 2021-01-15 12:13 ` Vivek Gautam
  2021-03-03 17:25   ` Jean-Philippe Brucker
  2021-01-15 12:13 ` [PATCH RFC v1 14/15] iommu/virtio: Add support for Arm LPAE page table format Vivek Gautam
                   ` (2 subsequent siblings)
  15 siblings, 1 reply; 44+ messages in thread
From: Vivek Gautam @ 2021-01-15 12:13 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, iommu, virtualization
  Cc: joro, will.deacon, mst, robin.murphy, jean-philippe, eric.auger,
	alex.williamson, kevin.tian, jacob.jun.pan, yi.l.liu,
	lorenzo.pieralisi, shameerali.kolothum.thodi, vivek.gautam

From: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>

When the ARM PASID table format is reported in a probe, send an attach
request and install the page tables for iommu_map/iommu_unmap use.
Architecture-specific components are already abstracted to libraries. We
just need to pass config bits around and setup an alternative mechanism to
the mapping tree.

We reuse the convention already adopted by other IOMMU architectures (ARM
SMMU and AMD IOMMU), that entry 0 in the PASID table is reserved for
non-PASID traffic. Bind the PASID table, and setup entry 0 to be modified
with iommu_map/unmap.

Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
[Vivek: Bunch of refactoring and clean-ups to use iommu-pasid-table APIs,
        creating iommu_pasid_table, and configuring based on reported
	pasid format. Couple of additional methods have also been created
	to configure vendor specific pasid configuration]
Signed-off-by: Vivek Gautam <vivek.gautam@arm.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
Cc: Eric Auger <eric.auger@redhat.com>
Cc: Alex Williamson <alex.williamson@redhat.com>
Cc: Kevin Tian <kevin.tian@intel.com>
Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
Cc: Liu Yi L <yi.l.liu@intel.com>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
---
 drivers/iommu/virtio-iommu.c | 314 +++++++++++++++++++++++++++++++++++
 1 file changed, 314 insertions(+)

diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c
index 004ea94e3731..b5222da1dc74 100644
--- a/drivers/iommu/virtio-iommu.c
+++ b/drivers/iommu/virtio-iommu.c
@@ -25,6 +25,7 @@
 #include <linux/wait.h>
 
 #include <uapi/linux/virtio_iommu.h>
+#include "iommu-pasid-table.h"
 
 #define MSI_IOVA_BASE			0x8000000
 #define MSI_IOVA_LENGTH			0x100000
@@ -33,6 +34,9 @@
 #define VIOMMU_EVENT_VQ			1
 #define VIOMMU_NR_VQS			2
 
+/* Some architectures need an Address Space ID for each page table */
+static DEFINE_IDA(asid_ida);
+
 struct viommu_dev {
 	struct iommu_device		iommu;
 	struct device			*dev;
@@ -55,6 +59,7 @@ struct viommu_dev {
 	u32				probe_size;
 
 	bool				has_map:1;
+	bool				has_table:1;
 };
 
 struct viommu_mapping {
@@ -76,6 +81,7 @@ struct viommu_domain {
 	struct mutex			mutex; /* protects viommu pointer */
 	unsigned int			id;
 	u32				map_flags;
+	struct iommu_pasid_table	*pasid_tbl;
 
 	/* Default address space when a table is bound */
 	struct viommu_mm		mm;
@@ -891,6 +897,285 @@ static int viommu_simple_attach(struct viommu_domain *vdomain,
 	return ret;
 }
 
+static int viommu_teardown_pgtable(struct viommu_domain *vdomain)
+{
+	struct iommu_vendor_psdtable_cfg *pst_cfg;
+	struct arm_smmu_cfg_info *cfgi;
+	u32 asid;
+
+	if (!vdomain->mm.ops)
+		return 0;
+
+	free_io_pgtable_ops(vdomain->mm.ops);
+	vdomain->mm.ops = NULL;
+
+	if (vdomain->pasid_tbl) {
+		pst_cfg = &vdomain->pasid_tbl->cfg;
+		cfgi = &pst_cfg->vendor.cfg;
+		asid = cfgi->s1_cfg->cd.asid;
+
+		iommu_psdtable_write(vdomain->pasid_tbl, pst_cfg, 0, NULL);
+		ida_simple_remove(&asid_ida, asid);
+	}
+
+	return 0;
+}
+
+static int viommu_setup_pgtable(struct viommu_endpoint *vdev,
+				struct viommu_domain *vdomain)
+{
+	int ret, id;
+	u32 asid;
+	enum io_pgtable_fmt fmt;
+	struct io_pgtable_ops *ops = NULL;
+	struct viommu_dev *viommu = vdev->viommu;
+	struct virtio_iommu_probe_table_format *desc = vdev->pgtf;
+	struct iommu_pasid_table *tbl = vdomain->pasid_tbl;
+	struct iommu_vendor_psdtable_cfg *pst_cfg;
+	struct arm_smmu_cfg_info *cfgi;
+	struct io_pgtable_cfg cfg = {
+		.iommu_dev	= viommu->dev->parent,
+		.tlb		= &viommu_flush_ops,
+		.pgsize_bitmap	= vdev->pgsize_mask ? vdev->pgsize_mask :
+				  vdomain->domain.pgsize_bitmap,
+		.ias		= (vdev->input_end ? ilog2(vdev->input_end) :
+				   ilog2(vdomain->domain.geometry.aperture_end)) + 1,
+		.oas		= vdev->output_bits,
+	};
+
+	if (!desc)
+		return -EINVAL;
+
+	if (!vdev->output_bits)
+		return -ENODEV;
+
+	switch (le16_to_cpu(desc->format)) {
+	case VIRTIO_IOMMU_FOMRAT_PGTF_ARM_LPAE:
+		fmt = ARM_64_LPAE_S1;
+		break;
+	default:
+		dev_err(vdev->dev, "unsupported page table format 0x%x\n",
+			le16_to_cpu(desc->format));
+		return -EINVAL;
+	}
+
+	if (vdomain->mm.ops) {
+		/*
+		 * TODO: attach additional endpoint to the domain. Check that
+		 * the config is sane.
+		 */
+		return -EEXIST;
+	}
+
+	vdomain->mm.domain = vdomain;
+	ops = alloc_io_pgtable_ops(fmt, &cfg, &vdomain->mm);
+	if (!ops)
+		return -ENOMEM;
+
+	pst_cfg = &tbl->cfg;
+	cfgi = &pst_cfg->vendor.cfg;
+	id = ida_simple_get(&asid_ida, 1, 1 << desc->asid_bits, GFP_KERNEL);
+	if (id < 0) {
+		ret = id;
+		goto err_free_pgtable;
+	}
+
+	asid = id;
+	ret = iommu_psdtable_prepare(tbl, pst_cfg, &cfg, asid);
+	if (ret)
+		goto err_free_asid;
+
+	/*
+	 * Strange to setup an op here?
+	 * cd-lib is the actual user of sync op, and therefore the platform
+	 * drivers should assign this sync/maintenance ops as per need.
+	 */
+	tbl->ops->sync = viommu_flush_pasid;
+
+	/* Right now only PASID 0 supported ?? */
+	ret = iommu_psdtable_write(tbl, pst_cfg, 0, &cfgi->s1_cfg->cd);
+	if (ret)
+		goto err_free_asid;
+
+	vdomain->mm.ops = ops;
+	dev_dbg(vdev->dev, "using page table format 0x%x\n", fmt);
+
+	return 0;
+
+err_free_asid:
+	ida_simple_remove(&asid_ida, asid);
+err_free_pgtable:
+	free_io_pgtable_ops(ops);
+	return ret;
+}
+
+static int viommu_config_arm_pst(struct iommu_vendor_psdtable_cfg *pst_cfg,
+				 struct virtio_iommu_req_attach_pst_arm *req)
+{
+	struct arm_smmu_s1_cfg *s1_cfg = pst_cfg->vendor.cfg.s1_cfg;
+
+	if (!s1_cfg)
+		return -ENODEV;
+
+	req->format	= cpu_to_le16(VIRTIO_IOMMU_FORMAT_PSTF_ARM_SMMU_V3);
+	req->s1fmt	= s1_cfg->s1fmt;
+	req->s1dss	= VIRTIO_IOMMU_PSTF_ARM_SMMU_V3_DSS_0;
+	req->s1contextptr = cpu_to_le64(pst_cfg->base);
+	req->s1cdmax	= cpu_to_le32(s1_cfg->s1cdmax);
+
+	return 0;
+}
+
+static int viommu_config_pst(struct iommu_vendor_psdtable_cfg *pst_cfg,
+			     void *req, enum pasid_table_fmt fmt)
+{
+	int ret;
+
+	switch (fmt) {
+	case PASID_TABLE_ARM_SMMU_V3:
+		ret = viommu_config_arm_pst(pst_cfg, req);
+		break;
+	default:
+		ret = -EINVAL;
+		WARN_ON(1);
+	}
+
+	return ret;
+}
+
+static int viommu_prepare_arm_pst(struct viommu_endpoint *vdev,
+				  struct iommu_vendor_psdtable_cfg *pst_cfg)
+{
+	struct virtio_iommu_probe_table_format *pgtf = vdev->pgtf;
+	struct arm_smmu_cfg_info *cfgi = &pst_cfg->vendor.cfg;
+	struct arm_smmu_s1_cfg *cfg;
+
+	/* Some sanity checks */
+	if (pgtf->asid_bits != 8 && pgtf->asid_bits != 16)
+		return -EINVAL;
+
+	cfg = devm_kzalloc(pst_cfg->iommu_dev, sizeof(cfg), GFP_KERNEL);
+	if (!cfg)
+		return -ENOMEM;
+
+	cfgi->s1_cfg = cfg;
+	cfg->s1cdmax = vdev->pasid_bits;
+	cfg->cd.asid = pgtf->asid_bits;
+
+	pst_cfg->fmt = PASID_TABLE_ARM_SMMU_V3;
+	/* XXX HACK: set feature bit ARM_SMMU_FEAT_2_LVL_CDTAB */
+	pst_cfg->vendor.cfg.feat_flag |= (1 << 1);
+
+	return 0;
+}
+
+static int viommu_prepare_pst(struct viommu_endpoint *vdev,
+			      struct iommu_vendor_psdtable_cfg *pst_cfg,
+			      enum pasid_table_fmt fmt)
+{
+	int ret;
+
+	switch (fmt) {
+	case PASID_TABLE_ARM_SMMU_V3:
+		ret = viommu_prepare_arm_pst(vdev, pst_cfg);
+		break;
+	default:
+		dev_err(vdev->dev, "unsupported PASID table format 0x%x\n", fmt);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int viommu_attach_pasid_table(struct viommu_endpoint *vdev,
+				     struct viommu_domain *vdomain)
+{
+	int ret;
+	int i, eid;
+	enum pasid_table_fmt fmt = -1;
+	struct virtio_iommu_probe_table_format *desc = vdev->pstf;
+	struct virtio_iommu_req_attach_table req = {
+		.head.type	= VIRTIO_IOMMU_T_ATTACH_TABLE,
+		.domain		= cpu_to_le32(vdomain->id),
+	};
+	struct viommu_dev *viommu = vdev->viommu;
+	struct iommu_pasid_table *tbl;
+	struct iommu_vendor_psdtable_cfg *pst_cfg;
+
+	if (!viommu->has_table)
+		return 0;
+
+	if (!desc)
+		return -ENODEV;
+
+	/* Prepare PASID tables configuration */
+	switch (le16_to_cpu(desc->format)) {
+	case VIRTIO_IOMMU_FORMAT_PSTF_ARM_SMMU_V3:
+		fmt = PASID_TABLE_ARM_SMMU_V3;
+		break;
+	default:
+		dev_err(vdev->dev, "unsupported PASID table format 0x%x\n",
+			le16_to_cpu(desc->format));
+		return 0;
+	}
+
+	if (!tbl) {
+		tbl = iommu_register_pasid_table(fmt, viommu->dev->parent, vdomain);
+		if (!tbl)
+			return -ENOMEM;
+
+		vdomain->pasid_tbl = tbl;
+		pst_cfg = &tbl->cfg;
+
+		pst_cfg->iommu_dev = viommu->dev->parent;
+
+		/* Prepare PASID tables info to allocate a new table */
+		ret = viommu_prepare_pst(vdev, pst_cfg, fmt);
+		if (ret)
+			return ret;
+
+		ret = iommu_psdtable_alloc(tbl, pst_cfg);
+		if (ret)
+			return ret;
+
+		pst_cfg->iommu_dev = viommu->dev->parent;
+		pst_cfg->fmt = PASID_TABLE_ARM_SMMU_V3;
+
+		ret = viommu_setup_pgtable(vdev, vdomain);
+		if (ret) {
+			dev_err(vdev->dev, "could not install page tables\n");
+			goto err_free_psdtable;
+		}
+
+		/* Add arch-specific configuration */
+		ret = viommu_config_pst(pst_cfg, (void *)&req, fmt);
+		if (ret)
+			goto err_free_ops;
+
+		vdev_for_each_id(i, eid, vdev) {
+			req.endpoint = cpu_to_le32(eid);
+			ret = viommu_send_req_sync(viommu, &req, sizeof(req));
+			if (ret)
+				goto err_free_ops;
+		}
+	} else {
+		/* TODO: otherwise, check for compatibility with vdev. */
+		return -ENOSYS;
+	}
+
+	dev_dbg(vdev->dev, "uses PASID table format 0x%x\n", fmt);
+
+	return 0;
+
+err_free_ops:
+	if (vdomain->mm.ops)
+		viommu_teardown_pgtable(vdomain);
+err_free_psdtable:
+	iommu_psdtable_free(tbl, &tbl->cfg);
+
+	return ret;
+}
+
 static int viommu_attach_dev(struct iommu_domain *domain, struct device *dev)
 {
 	int ret = 0;
@@ -928,6 +1213,17 @@ static int viommu_attach_dev(struct iommu_domain *domain, struct device *dev)
 	if (vdev->vdomain)
 		vdev->vdomain->nr_endpoints--;
 
+	ret = viommu_attach_pasid_table(vdev, vdomain);
+	if (ret) {
+		/*
+		 * No PASID support, too bad. Perhaps we can bind a single set
+		 * of page tables?
+		 */
+		ret = viommu_setup_pgtable(vdev, vdomain);
+		if (ret)
+			dev_err(vdev->dev, "could not install tables\n");
+	}
+
 	if (!vdomain->mm.ops) {
 		/* If we couldn't bind any table, use the mapping tree */
 		ret = viommu_simple_attach(vdomain, vdev);
@@ -948,6 +1244,10 @@ static int viommu_map(struct iommu_domain *domain, unsigned long iova,
 	u32 flags;
 	struct virtio_iommu_req_map map;
 	struct viommu_domain *vdomain = to_viommu_domain(domain);
+	struct io_pgtable_ops *ops = vdomain->mm.ops;
+
+	if (ops)
+		return ops->map(ops, iova, paddr, size, prot, gfp);
 
 	flags = (prot & IOMMU_READ ? VIRTIO_IOMMU_MAP_F_READ : 0) |
 		(prot & IOMMU_WRITE ? VIRTIO_IOMMU_MAP_F_WRITE : 0) |
@@ -986,6 +1286,10 @@ static size_t viommu_unmap(struct iommu_domain *domain, unsigned long iova,
 	size_t unmapped;
 	struct virtio_iommu_req_unmap unmap;
 	struct viommu_domain *vdomain = to_viommu_domain(domain);
+	struct io_pgtable_ops *ops = vdomain->mm.ops;
+
+	if (ops)
+		return ops->unmap(ops, iova, size, gather);
 
 	unmapped = viommu_del_mappings(vdomain, iova, size);
 	if (unmapped < size)
@@ -1014,6 +1318,10 @@ static phys_addr_t viommu_iova_to_phys(struct iommu_domain *domain,
 	struct viommu_mapping *mapping;
 	struct interval_tree_node *node;
 	struct viommu_domain *vdomain = to_viommu_domain(domain);
+	struct io_pgtable_ops *ops = vdomain->mm.ops;
+
+	if (ops)
+		return ops->iova_to_phys(ops, iova);
 
 	spin_lock_irqsave(&vdomain->mappings_lock, flags);
 	node = interval_tree_iter_first(&vdomain->mappings, iova, iova);
@@ -1264,7 +1572,12 @@ static int viommu_probe(struct virtio_device *vdev)
 				struct virtio_iommu_config, probe_size,
 				&viommu->probe_size);
 
+	viommu->has_table = virtio_has_feature(vdev, VIRTIO_IOMMU_F_ATTACH_TABLE);
 	viommu->has_map = virtio_has_feature(vdev, VIRTIO_IOMMU_F_MAP_UNMAP);
+	if (!viommu->has_table && !viommu->has_map) {
+		ret = -EINVAL;
+		goto err_free_vqs;
+	}
 
 	viommu->geometry = (struct iommu_domain_geometry) {
 		.aperture_start	= input_start,
@@ -1356,6 +1669,7 @@ static unsigned int features[] = {
 	VIRTIO_IOMMU_F_DOMAIN_RANGE,
 	VIRTIO_IOMMU_F_PROBE,
 	VIRTIO_IOMMU_F_MMIO,
+	VIRTIO_IOMMU_F_ATTACH_TABLE,
 };
 
 static struct virtio_device_id id_table[] = {
-- 
2.17.1


^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH RFC v1 14/15] iommu/virtio: Add support for Arm LPAE page table format
  2021-01-15 12:13 [PATCH RFC v1 00/15] iommu/virtio: Nested stage support with Arm Vivek Gautam
                   ` (12 preceding siblings ...)
  2021-01-15 12:13 ` [PATCH RFC v1 13/15] iommu/virtio: Attach Arm PASID tables when available Vivek Gautam
@ 2021-01-15 12:13 ` Vivek Gautam
  2021-01-15 12:13 ` [PATCH RFC v1 15/15] iommu/virtio: Update fault type and reason info for viommu fault Vivek Gautam
  2021-01-19  9:03 ` [PATCH RFC v1 00/15] iommu/virtio: Nested stage support with Arm Auger Eric
  15 siblings, 0 replies; 44+ messages in thread
From: Vivek Gautam @ 2021-01-15 12:13 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, iommu, virtualization
  Cc: joro, will.deacon, mst, robin.murphy, jean-philippe, eric.auger,
	alex.williamson, kevin.tian, jacob.jun.pan, yi.l.liu,
	lorenzo.pieralisi, shameerali.kolothum.thodi, vivek.gautam

From: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>

When PASID isn't supported, we can still register one set of tables.
Add support to register Arm LPAE based page table.

Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
[Vivek: Clean-ups to add right tcr definitions and accomodate
        with parent patches]
Signed-off-by: Vivek Gautam <vivek.gautam@arm.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
Cc: Eric Auger <eric.auger@redhat.com>
Cc: Alex Williamson <alex.williamson@redhat.com>
Cc: Kevin Tian <kevin.tian@intel.com>
Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
Cc: Liu Yi L <yi.l.liu@intel.com>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
---
 drivers/iommu/virtio-iommu.c      | 131 +++++++++++++++++++++++++-----
 include/uapi/linux/virtio_iommu.h |  30 +++++++
 2 files changed, 139 insertions(+), 22 deletions(-)

diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c
index b5222da1dc74..9cc3d35125e9 100644
--- a/drivers/iommu/virtio-iommu.c
+++ b/drivers/iommu/virtio-iommu.c
@@ -135,6 +135,13 @@ struct viommu_event {
 #define to_viommu_domain(domain)	\
 	container_of(domain, struct viommu_domain, domain)
 
+#define VIRTIO_FIELD_PREP(_mask, _shift, _val)			\
+	({							\
+		(((_val) << VIRTIO_IOMMU_PGTF_ARM_ ## _shift) &	\
+		 (VIRTIO_IOMMU_PGTF_ARM_ ## _mask <<		\
+		  VIRTIO_IOMMU_PGTF_ARM_ ## _shift));		\
+	})
+
 static int viommu_get_req_errno(void *buf, size_t len)
 {
 	struct virtio_iommu_req_tail *tail = buf + len - sizeof(*tail);
@@ -897,6 +904,76 @@ static int viommu_simple_attach(struct viommu_domain *vdomain,
 	return ret;
 }
 
+static int viommu_config_arm_pgt(struct viommu_endpoint *vdev,
+				 struct io_pgtable_cfg *cfg,
+				 struct virtio_iommu_req_attach_pgt_arm *req,
+				 u64 *asid)
+{
+	int id;
+	struct virtio_iommu_probe_table_format *pgtf = (void *)vdev->pgtf;
+	typeof(&cfg->arm_lpae_s1_cfg.tcr) tcr = &cfg->arm_lpae_s1_cfg.tcr;
+	u64 __tcr;
+
+	if (pgtf->asid_bits != 8 && pgtf->asid_bits != 16)
+		return -EINVAL;
+
+	id = ida_simple_get(&asid_ida, 1, 1 << pgtf->asid_bits, GFP_KERNEL);
+	if (id < 0)
+		return -ENOMEM;
+
+	__tcr = VIRTIO_FIELD_PREP(T0SZ_MASK, T0SZ_SHIFT, tcr->tsz) |
+		VIRTIO_FIELD_PREP(IRGN0_MASK, IRGN0_SHIFT, tcr->irgn) |
+		VIRTIO_FIELD_PREP(ORGN0_MASK, ORGN0_SHIFT, tcr->orgn) |
+		VIRTIO_FIELD_PREP(SH0_MASK, SH0_SHIFT, tcr->sh) |
+		VIRTIO_FIELD_PREP(TG0_MASK, TG0_SHIFT, tcr->tg) |
+		VIRTIO_IOMMU_PGTF_ARM_EPD1 | VIRTIO_IOMMU_PGTF_ARM_HPD0 |
+		VIRTIO_IOMMU_PGTF_ARM_HPD1;
+
+	req->format	= cpu_to_le16(VIRTIO_IOMMU_FOMRAT_PGTF_ARM_LPAE);
+	req->ttbr	= cpu_to_le64(cfg->arm_lpae_s1_cfg.ttbr);
+	req->tcr	= cpu_to_le64(__tcr);
+	req->mair	= cpu_to_le64(cfg->arm_lpae_s1_cfg.mair);
+	req->asid	= cpu_to_le16(id);
+
+	*asid = id;
+	return 0;
+}
+
+static int viommu_attach_pgtable(struct viommu_endpoint *vdev,
+				 struct viommu_domain *vdomain,
+				 enum io_pgtable_fmt fmt,
+				 struct io_pgtable_cfg *cfg,
+				 u64 *asid)
+{
+	int ret;
+	int i, eid;
+
+	struct virtio_iommu_req_attach_table req = {
+		.head.type	= VIRTIO_IOMMU_T_ATTACH_TABLE,
+		.domain		= cpu_to_le32(vdomain->id),
+	};
+
+	switch (fmt) {
+	case ARM_64_LPAE_S1:
+		ret = viommu_config_arm_pgt(vdev, cfg, (void *)&req, asid);
+		if (ret)
+			return ret;
+		break;
+	default:
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	vdev_for_each_id(i, eid, vdev) {
+		req.endpoint = cpu_to_le32(eid);
+		ret = viommu_send_req_sync(vdomain->viommu, &req, sizeof(req));
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
 static int viommu_teardown_pgtable(struct viommu_domain *vdomain)
 {
 	struct iommu_vendor_psdtable_cfg *pst_cfg;
@@ -972,32 +1049,42 @@ static int viommu_setup_pgtable(struct viommu_endpoint *vdev,
 	if (!ops)
 		return -ENOMEM;
 
-	pst_cfg = &tbl->cfg;
-	cfgi = &pst_cfg->vendor.cfg;
-	id = ida_simple_get(&asid_ida, 1, 1 << desc->asid_bits, GFP_KERNEL);
-	if (id < 0) {
-		ret = id;
-		goto err_free_pgtable;
-	}
+	if (!tbl) {
+		/* No PASID support, send attach_table */
+		ret = viommu_attach_pgtable(vdev, vdomain, fmt, &cfg,
+					    &vdomain->mm.archid);
+		if (ret)
+			goto err_free_pgtable;
+	} else {
+		pst_cfg = &tbl->cfg;
+		cfgi = &pst_cfg->vendor.cfg;
+		id = ida_simple_get(&asid_ida, 1, 1 << desc->asid_bits, GFP_KERNEL);
+		if (id < 0) {
+			ret = id;
+			goto err_free_pgtable;
+		}
 
-	asid = id;
-	ret = iommu_psdtable_prepare(tbl, pst_cfg, &cfg, asid);
-	if (ret)
-		goto err_free_asid;
+		asid = id;
+		ret = iommu_psdtable_prepare(tbl, pst_cfg, &cfg, asid);
+		if (ret)
+			goto err_free_asid;
 
-	/*
-	 * Strange to setup an op here?
-	 * cd-lib is the actual user of sync op, and therefore the platform
-	 * drivers should assign this sync/maintenance ops as per need.
-	 */
-	tbl->ops->sync = viommu_flush_pasid;
+		/*
+		 * Strange to setup an op here?
+		 * cd-lib is the actual user of sync op, and therefore the
+		 * cd-lib consumer drivers should assign this sync/maintenance
+		 * ops as per need.
+		 */
+		tbl->ops->sync = viommu_flush_pasid;
 
-	/* Right now only PASID 0 supported ?? */
-	ret = iommu_psdtable_write(tbl, pst_cfg, 0, &cfgi->s1_cfg->cd);
-	if (ret)
-		goto err_free_asid;
+		/* Right now only PASID 0 supported */
+		ret = iommu_psdtable_write(tbl, pst_cfg, 0, &cfgi->s1_cfg->cd);
+		if (ret)
+			goto err_free_asid;
+
+		vdomain->mm.ops = ops;
+	}
 
-	vdomain->mm.ops = ops;
 	dev_dbg(vdev->dev, "using page table format 0x%x\n", fmt);
 
 	return 0;
diff --git a/include/uapi/linux/virtio_iommu.h b/include/uapi/linux/virtio_iommu.h
index 3481e4a3dd24..608c8d642e1f 100644
--- a/include/uapi/linux/virtio_iommu.h
+++ b/include/uapi/linux/virtio_iommu.h
@@ -116,6 +116,36 @@ struct virtio_iommu_req_attach_pst_arm {
 	struct virtio_iommu_req_tail		tail;
 };
 
+/* TCR_EL1 fields from Arm LPAE format */
+#define VIRTIO_IOMMU_PGTF_ARM_HPD1		(1ULL << 42)
+#define VIRTIO_IOMMU_PGTF_ARM_HPD0		(1ULL << 41)
+#define VIRTIO_IOMMU_PGTF_ARM_EPD1		(1 << 23)
+
+#define VIRTIO_IOMMU_PGTF_ARM_TG0_SHIFT		14
+#define VIRTIO_IOMMU_PGTF_ARM_TG0_MASK		0x3
+#define VIRTIO_IOMMU_PGTF_ARM_SH0_SHIFT		12
+#define VIRTIO_IOMMU_PGTF_ARM_SH0_MASK		0x3
+#define VIRTIO_IOMMU_PGTF_ARM_ORGN0_SHIFT	10
+#define VIRTIO_IOMMU_PGTF_ARM_ORGN0_MASK	0x3
+#define VIRTIO_IOMMU_PGTF_ARM_IRGN0_SHIFT	8
+#define VIRTIO_IOMMU_PGTF_ARM_IRGN0_MASK	0x3
+#define VIRTIO_IOMMU_PGTF_ARM_T0SZ_SHIFT	0
+#define VIRTIO_IOMMU_PGTF_ARM_T0SZ_MASK		0x3f
+
+/* Arm LPAE Page Table Descriptor */
+struct virtio_iommu_req_attach_pgt_arm {
+	struct virtio_iommu_req_head            head;
+	__le32                                  domain;
+	__le32                                  endpoint;
+	__le16                                  format;
+	__le16                                  asid;
+	__le64					tcr;
+	__le64					ttbr;
+	__le64					mair;
+	__u8					reserved[28];
+	struct virtio_iommu_req_tail		tail;
+};
+
 #define VIRTIO_IOMMU_MAP_F_READ			(1 << 0)
 #define VIRTIO_IOMMU_MAP_F_WRITE		(1 << 1)
 #define VIRTIO_IOMMU_MAP_F_MMIO			(1 << 2)
-- 
2.17.1


^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH RFC v1 15/15] iommu/virtio: Update fault type and reason info for viommu fault
  2021-01-15 12:13 [PATCH RFC v1 00/15] iommu/virtio: Nested stage support with Arm Vivek Gautam
                   ` (13 preceding siblings ...)
  2021-01-15 12:13 ` [PATCH RFC v1 14/15] iommu/virtio: Add support for Arm LPAE page table format Vivek Gautam
@ 2021-01-15 12:13 ` Vivek Gautam
  2021-03-03 17:25   ` Jean-Philippe Brucker
  2021-01-19  9:03 ` [PATCH RFC v1 00/15] iommu/virtio: Nested stage support with Arm Auger Eric
  15 siblings, 1 reply; 44+ messages in thread
From: Vivek Gautam @ 2021-01-15 12:13 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, iommu, virtualization
  Cc: joro, will.deacon, mst, robin.murphy, jean-philippe, eric.auger,
	alex.williamson, kevin.tian, jacob.jun.pan, yi.l.liu,
	lorenzo.pieralisi, shameerali.kolothum.thodi, vivek.gautam

Fault type information can tell about a page request fault or
an unreceoverable fault, and further additions to fault reasons
and the related PASID information can help in handling faults
efficiently.

Signed-off-by: Vivek Gautam <vivek.gautam@arm.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
Cc: Eric Auger <eric.auger@redhat.com>
Cc: Alex Williamson <alex.williamson@redhat.com>
Cc: Kevin Tian <kevin.tian@intel.com>
Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
Cc: Liu Yi L <yi.l.liu@intel.com>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
---
 drivers/iommu/virtio-iommu.c      | 27 +++++++++++++++++++++++++--
 include/uapi/linux/virtio_iommu.h | 13 ++++++++++++-
 2 files changed, 37 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c
index 9cc3d35125e9..10ef9e98214a 100644
--- a/drivers/iommu/virtio-iommu.c
+++ b/drivers/iommu/virtio-iommu.c
@@ -652,9 +652,16 @@ static int viommu_fault_handler(struct viommu_dev *viommu,
 	char *reason_str;
 
 	u8 reason	= fault->reason;
+	u16 type	= fault->flt_type;
 	u32 flags	= le32_to_cpu(fault->flags);
 	u32 endpoint	= le32_to_cpu(fault->endpoint);
 	u64 address	= le64_to_cpu(fault->address);
+	u32 pasid	= le32_to_cpu(fault->pasid);
+
+	if (type == VIRTIO_IOMMU_FAULT_F_PAGE_REQ) {
+		dev_info(viommu->dev, "Page request fault - unhandled\n");
+		return 0;
+	}
 
 	switch (reason) {
 	case VIRTIO_IOMMU_FAULT_R_DOMAIN:
@@ -663,6 +670,21 @@ static int viommu_fault_handler(struct viommu_dev *viommu,
 	case VIRTIO_IOMMU_FAULT_R_MAPPING:
 		reason_str = "page";
 		break;
+	case VIRTIO_IOMMU_FAULT_R_WALK_EABT:
+		reason_str = "page walk external abort";
+		break;
+	case VIRTIO_IOMMU_FAULT_R_PTE_FETCH:
+		reason_str = "pte fetch";
+		break;
+	case VIRTIO_IOMMU_FAULT_R_PERMISSION:
+		reason_str = "permission";
+		break;
+	case VIRTIO_IOMMU_FAULT_R_ACCESS:
+		reason_str = "access";
+		break;
+	case VIRTIO_IOMMU_FAULT_R_OOR_ADDRESS:
+		reason_str = "output address";
+		break;
 	case VIRTIO_IOMMU_FAULT_R_UNKNOWN:
 	default:
 		reason_str = "unknown";
@@ -671,8 +693,9 @@ static int viommu_fault_handler(struct viommu_dev *viommu,
 
 	/* TODO: find EP by ID and report_iommu_fault */
 	if (flags & VIRTIO_IOMMU_FAULT_F_ADDRESS)
-		dev_err_ratelimited(viommu->dev, "%s fault from EP %u at %#llx [%s%s%s]\n",
-				    reason_str, endpoint, address,
+		dev_err_ratelimited(viommu->dev,
+				    "%s fault from EP %u PASID %u at %#llx [%s%s%s]\n",
+				    reason_str, endpoint, pasid, address,
 				    flags & VIRTIO_IOMMU_FAULT_F_READ ? "R" : "",
 				    flags & VIRTIO_IOMMU_FAULT_F_WRITE ? "W" : "",
 				    flags & VIRTIO_IOMMU_FAULT_F_EXEC ? "X" : "");
diff --git a/include/uapi/linux/virtio_iommu.h b/include/uapi/linux/virtio_iommu.h
index 608c8d642e1f..a537d82777f7 100644
--- a/include/uapi/linux/virtio_iommu.h
+++ b/include/uapi/linux/virtio_iommu.h
@@ -290,19 +290,30 @@ struct virtio_iommu_req_invalidate {
 #define VIRTIO_IOMMU_FAULT_R_UNKNOWN		0
 #define VIRTIO_IOMMU_FAULT_R_DOMAIN		1
 #define VIRTIO_IOMMU_FAULT_R_MAPPING		2
+#define VIRTIO_IOMMU_FAULT_R_WALK_EABT		3
+#define VIRTIO_IOMMU_FAULT_R_PTE_FETCH		4
+#define VIRTIO_IOMMU_FAULT_R_PERMISSION		5
+#define VIRTIO_IOMMU_FAULT_R_ACCESS		6
+#define VIRTIO_IOMMU_FAULT_R_OOR_ADDRESS	7
 
 #define VIRTIO_IOMMU_FAULT_F_READ		(1 << 0)
 #define VIRTIO_IOMMU_FAULT_F_WRITE		(1 << 1)
 #define VIRTIO_IOMMU_FAULT_F_EXEC		(1 << 2)
 #define VIRTIO_IOMMU_FAULT_F_ADDRESS		(1 << 8)
 
+#define VIRTIO_IOMMU_FAULT_F_DMA_UNRECOV	1
+#define VIRTIO_IOMMU_FAULT_F_PAGE_REQ		2
+
 struct virtio_iommu_fault {
 	__u8					reason;
-	__u8					reserved[3];
+	__le16					flt_type;
+	__u8					reserved;
 	__le32					flags;
 	__le32					endpoint;
 	__u8					reserved2[4];
 	__le64					address;
+	__le32					pasid;
+	__u8					reserved3[4];
 };
 
 #endif
-- 
2.17.1


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH RFC v1 00/15] iommu/virtio: Nested stage support with Arm
  2021-01-15 12:13 [PATCH RFC v1 00/15] iommu/virtio: Nested stage support with Arm Vivek Gautam
                   ` (14 preceding siblings ...)
  2021-01-15 12:13 ` [PATCH RFC v1 15/15] iommu/virtio: Update fault type and reason info for viommu fault Vivek Gautam
@ 2021-01-19  9:03 ` Auger Eric
  2021-01-21 17:34   ` Vivek Kumar Gautam
  15 siblings, 1 reply; 44+ messages in thread
From: Auger Eric @ 2021-01-19  9:03 UTC (permalink / raw)
  To: Vivek Gautam, linux-kernel, linux-arm-kernel, iommu, virtualization
  Cc: joro, will.deacon, mst, robin.murphy, jean-philippe,
	alex.williamson, kevin.tian, jacob.jun.pan, yi.l.liu,
	lorenzo.pieralisi, shameerali.kolothum.thodi

Hi Vivek,

On 1/15/21 1:13 PM, Vivek Gautam wrote:
> This patch-series aims at enabling Nested stage translation in guests
> using virtio-iommu as the paravirtualized iommu. The backend is supported
> with Arm SMMU-v3 that provides nested stage-1 and stage-2 translation.
> 
> This series derives its purpose from various efforts happening to add
> support for Shared Virtual Addressing (SVA) in host and guest. On Arm,
> most of the support for SVA has already landed. The support for nested
> stage translation and fault reporting to guest has been proposed [1].
> The related changes required in VFIO [2] framework have also been put
> forward.
> 
> This series proposes changes in virtio-iommu to program PASID tables
> and related stage-1 page tables. A simple iommu-pasid-table library
> is added for this purpose that interacts with vendor drivers to
> allocate and populate PASID tables.
> In Arm SMMUv3 we propose to pull the Context Descriptor (CD) management
> code out of the arm-smmu-v3 driver and add that as a glue vendor layer
> to support allocating CD tables, and populating them with right values.
> These CD tables are essentially the PASID tables and contain stage-1
> page table configurations too.
> A request to setup these CD tables come from virtio-iommu driver using
> the iommu-pasid-table library when running on Arm. The virtio-iommu
> then pass these PASID tables to the host using the right virtio backend
> and support in VMM.
> 
> For testing we have added necessary support in kvmtool. The changes in
> kvmtool are based on virtio-iommu development branch by Jean-Philippe
> Brucker [3].
> 
> The tested kernel branch contains following in the order bottom to top
> on the git hash -
> a) v5.11-rc3
> b) arm-smmu-v3 [1] and vfio [2] changes from Eric to add nested page
>    table support for Arm.
> c) Smmu test engine patches from Jean-Philippe's branch [4]
> d) This series
> e) Domain nesting info patches [5][6][7].
> f) Changes to add arm-smmu-v3 specific nesting info (to be sent to
>    the list).
> 
> This kernel is tested on Neoverse reference software stack with
> Fixed virtual platform. Public version of the software stack and
> FVP is available here[8][9].
> 
> A big thanks to Jean-Philippe for his contributions towards this work
> and for his valuable guidance.
> 
> [1] https://lore.kernel.org/linux-iommu/20201118112151.25412-1-eric.auger@redhat.com/T/
> [2] https://lore.kernel.org/kvmarm/20201116110030.32335-12-eric.auger@redhat.com/T/
> [3] https://jpbrucker.net/git/kvmtool/log/?h=virtio-iommu/devel
> [4] https://jpbrucker.net/git/linux/log/?h=sva/smmute
> [5] https://lore.kernel.org/kvm/1599734733-6431-2-git-send-email-yi.l.liu@intel.com/
> [6] https://lore.kernel.org/kvm/1599734733-6431-3-git-send-email-yi.l.liu@intel.com/
> [7] https://lore.kernel.org/kvm/1599734733-6431-4-git-send-email-yi.l.liu@intel.com/
> [8] https://developer.arm.com/tools-and-software/open-source-software/arm-platforms-software/arm-ecosystem-fvps
> [9] https://git.linaro.org/landing-teams/working/arm/arm-reference-platforms.git/about/docs/rdn1edge/user-guide.rst

Could you share a public branch where we could find all the kernel pieces.

Thank you in advance

Best Regards

Eric
> 
> Jean-Philippe Brucker (6):
>   iommu/virtio: Add headers for table format probing
>   iommu/virtio: Add table format probing
>   iommu/virtio: Add headers for binding pasid table in iommu
>   iommu/virtio: Add support for INVALIDATE request
>   iommu/virtio: Attach Arm PASID tables when available
>   iommu/virtio: Add support for Arm LPAE page table format
> 
> Vivek Gautam (9):
>   iommu/arm-smmu-v3: Create a Context Descriptor library
>   iommu: Add a simple PASID table library
>   iommu/arm-smmu-v3: Update drivers to work with iommu-pasid-table
>   iommu/arm-smmu-v3: Update CD base address info for user-space
>   iommu/arm-smmu-v3: Set sync op from consumer driver of cd-lib
>   iommu: Add asid_bits to arm smmu-v3 stage1 table info
>   iommu/virtio: Update table format probing header
>   iommu/virtio: Prepare to add attach pasid table infrastructure
>   iommu/virtio: Update fault type and reason info for viommu fault
> 
>  drivers/iommu/arm/arm-smmu-v3/Makefile        |   2 +-
>  .../arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c      | 283 +++++++
>  .../iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c   |  16 +-
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c   | 268 +------
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h   |   4 +-
>  drivers/iommu/iommu-pasid-table.h             | 140 ++++
>  drivers/iommu/virtio-iommu.c                  | 692 +++++++++++++++++-
>  include/uapi/linux/iommu.h                    |   2 +-
>  include/uapi/linux/virtio_iommu.h             | 158 +++-
>  9 files changed, 1303 insertions(+), 262 deletions(-)
>  create mode 100644 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c
>  create mode 100644 drivers/iommu/iommu-pasid-table.h
> 


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH RFC v1 00/15] iommu/virtio: Nested stage support with Arm
  2021-01-19  9:03 ` [PATCH RFC v1 00/15] iommu/virtio: Nested stage support with Arm Auger Eric
@ 2021-01-21 17:34   ` Vivek Kumar Gautam
  2021-01-22 15:49     ` Shameerali Kolothum Thodi
  2021-01-25  8:43     ` Auger Eric
  0 siblings, 2 replies; 44+ messages in thread
From: Vivek Kumar Gautam @ 2021-01-21 17:34 UTC (permalink / raw)
  To: Auger Eric, linux-kernel, linux-arm-kernel, iommu, virtualization
  Cc: joro, will.deacon, mst, robin.murphy, jean-philippe,
	alex.williamson, kevin.tian, jacob.jun.pan, yi.l.liu,
	lorenzo.pieralisi, shameerali.kolothum.thodi

Hi Eric,


On 1/19/21 2:33 PM, Auger Eric wrote:
> Hi Vivek,
> 
> On 1/15/21 1:13 PM, Vivek Gautam wrote:
>> This patch-series aims at enabling Nested stage translation in guests
>> using virtio-iommu as the paravirtualized iommu. The backend is supported
>> with Arm SMMU-v3 that provides nested stage-1 and stage-2 translation.
>>
>> This series derives its purpose from various efforts happening to add
>> support for Shared Virtual Addressing (SVA) in host and guest. On Arm,
>> most of the support for SVA has already landed. The support for nested
>> stage translation and fault reporting to guest has been proposed [1].
>> The related changes required in VFIO [2] framework have also been put
>> forward.
>>
>> This series proposes changes in virtio-iommu to program PASID tables
>> and related stage-1 page tables. A simple iommu-pasid-table library
>> is added for this purpose that interacts with vendor drivers to
>> allocate and populate PASID tables.
>> In Arm SMMUv3 we propose to pull the Context Descriptor (CD) management
>> code out of the arm-smmu-v3 driver and add that as a glue vendor layer
>> to support allocating CD tables, and populating them with right values.
>> These CD tables are essentially the PASID tables and contain stage-1
>> page table configurations too.
>> A request to setup these CD tables come from virtio-iommu driver using
>> the iommu-pasid-table library when running on Arm. The virtio-iommu
>> then pass these PASID tables to the host using the right virtio backend
>> and support in VMM.
>>
>> For testing we have added necessary support in kvmtool. The changes in
>> kvmtool are based on virtio-iommu development branch by Jean-Philippe
>> Brucker [3].
>>
>> The tested kernel branch contains following in the order bottom to top
>> on the git hash -
>> a) v5.11-rc3
>> b) arm-smmu-v3 [1] and vfio [2] changes from Eric to add nested page
>>     table support for Arm.
>> c) Smmu test engine patches from Jean-Philippe's branch [4]
>> d) This series
>> e) Domain nesting info patches [5][6][7].
>> f) Changes to add arm-smmu-v3 specific nesting info (to be sent to
>>     the list).
>>
>> This kernel is tested on Neoverse reference software stack with
>> Fixed virtual platform. Public version of the software stack and
>> FVP is available here[8][9].
>>
>> A big thanks to Jean-Philippe for his contributions towards this work
>> and for his valuable guidance.
>>
>> [1] https://lore.kernel.org/linux-iommu/20201118112151.25412-1-eric.auger@redhat.com/T/
>> [2] https://lore.kernel.org/kvmarm/20201116110030.32335-12-eric.auger@redhat.com/T/
>> [3] https://jpbrucker.net/git/kvmtool/log/?h=virtio-iommu/devel
>> [4] https://jpbrucker.net/git/linux/log/?h=sva/smmute
>> [5] https://lore.kernel.org/kvm/1599734733-6431-2-git-send-email-yi.l.liu@intel.com/
>> [6] https://lore.kernel.org/kvm/1599734733-6431-3-git-send-email-yi.l.liu@intel.com/
>> [7] https://lore.kernel.org/kvm/1599734733-6431-4-git-send-email-yi.l.liu@intel.com/
>> [8] https://developer.arm.com/tools-and-software/open-source-software/arm-platforms-software/arm-ecosystem-fvps
>> [9] https://git.linaro.org/landing-teams/working/arm/arm-reference-platforms.git/about/docs/rdn1edge/user-guide.rst
> 
> Could you share a public branch where we could find all the kernel pieces.
> 
> Thank you in advance

Apologies for the delay. It took a bit of time to sort things out for a 
public branch.
The branch is available in my github now. Please have a look.

https://github.com/vivek-arm/linux/tree/5.11-rc3-nested-pgtbl-arm-smmuv3-virtio-iommu


Thanks and regards
Vivek

> 
> Best Regards
> 
> Eric
>>
>> Jean-Philippe Brucker (6):
>>    iommu/virtio: Add headers for table format probing
>>    iommu/virtio: Add table format probing
>>    iommu/virtio: Add headers for binding pasid table in iommu
>>    iommu/virtio: Add support for INVALIDATE request
>>    iommu/virtio: Attach Arm PASID tables when available
>>    iommu/virtio: Add support for Arm LPAE page table format
>>
>> Vivek Gautam (9):
>>    iommu/arm-smmu-v3: Create a Context Descriptor library
>>    iommu: Add a simple PASID table library
>>    iommu/arm-smmu-v3: Update drivers to work with iommu-pasid-table
>>    iommu/arm-smmu-v3: Update CD base address info for user-space
>>    iommu/arm-smmu-v3: Set sync op from consumer driver of cd-lib
>>    iommu: Add asid_bits to arm smmu-v3 stage1 table info
>>    iommu/virtio: Update table format probing header
>>    iommu/virtio: Prepare to add attach pasid table infrastructure
>>    iommu/virtio: Update fault type and reason info for viommu fault
>>
>>   drivers/iommu/arm/arm-smmu-v3/Makefile        |   2 +-
>>   .../arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c      | 283 +++++++
>>   .../iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c   |  16 +-
>>   drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c   | 268 +------
>>   drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h   |   4 +-
>>   drivers/iommu/iommu-pasid-table.h             | 140 ++++
>>   drivers/iommu/virtio-iommu.c                  | 692 +++++++++++++++++-
>>   include/uapi/linux/iommu.h                    |   2 +-
>>   include/uapi/linux/virtio_iommu.h             | 158 +++-
>>   9 files changed, 1303 insertions(+), 262 deletions(-)
>>   create mode 100644 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c
>>   create mode 100644 drivers/iommu/iommu-pasid-table.h
>>
> 

^ permalink raw reply	[flat|nested] 44+ messages in thread

* RE: [PATCH RFC v1 00/15] iommu/virtio: Nested stage support with Arm
  2021-01-21 17:34   ` Vivek Kumar Gautam
@ 2021-01-22 15:49     ` Shameerali Kolothum Thodi
  2021-01-25 12:55       ` Vivek Kumar Gautam
  2021-01-25  8:43     ` Auger Eric
  1 sibling, 1 reply; 44+ messages in thread
From: Shameerali Kolothum Thodi @ 2021-01-22 15:49 UTC (permalink / raw)
  To: Vivek Kumar Gautam, Auger Eric, linux-kernel, linux-arm-kernel,
	iommu, virtualization
  Cc: joro, will.deacon, mst, robin.murphy, jean-philippe,
	alex.williamson, kevin.tian, jacob.jun.pan, yi.l.liu,
	lorenzo.pieralisi

Hi Vivek,

> -----Original Message-----
> From: Vivek Kumar Gautam [mailto:vivek.gautam@arm.com]
> Sent: 21 January 2021 17:34
> To: Auger Eric <eric.auger@redhat.com>; linux-kernel@vger.kernel.org;
> linux-arm-kernel@lists.infradead.org; iommu@lists.linux-foundation.org;
> virtualization@lists.linux-foundation.org
> Cc: joro@8bytes.org; will.deacon@arm.com; mst@redhat.com;
> robin.murphy@arm.com; jean-philippe@linaro.org;
> alex.williamson@redhat.com; kevin.tian@intel.com;
> jacob.jun.pan@linux.intel.com; yi.l.liu@intel.com; lorenzo.pieralisi@arm.com;
> Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
> Subject: Re: [PATCH RFC v1 00/15] iommu/virtio: Nested stage support with
> Arm
> 
> Hi Eric,
> 
> 
> On 1/19/21 2:33 PM, Auger Eric wrote:
> > Hi Vivek,
> >
> > On 1/15/21 1:13 PM, Vivek Gautam wrote:
> >> This patch-series aims at enabling Nested stage translation in guests
> >> using virtio-iommu as the paravirtualized iommu. The backend is
> >> supported with Arm SMMU-v3 that provides nested stage-1 and stage-2
> translation.
> >>
> >> This series derives its purpose from various efforts happening to add
> >> support for Shared Virtual Addressing (SVA) in host and guest. On
> >> Arm, most of the support for SVA has already landed. The support for
> >> nested stage translation and fault reporting to guest has been proposed [1].
> >> The related changes required in VFIO [2] framework have also been put
> >> forward.
> >>
> >> This series proposes changes in virtio-iommu to program PASID tables
> >> and related stage-1 page tables. A simple iommu-pasid-table library
> >> is added for this purpose that interacts with vendor drivers to
> >> allocate and populate PASID tables.
> >> In Arm SMMUv3 we propose to pull the Context Descriptor (CD)
> >> management code out of the arm-smmu-v3 driver and add that as a glue
> >> vendor layer to support allocating CD tables, and populating them with right
> values.
> >> These CD tables are essentially the PASID tables and contain stage-1
> >> page table configurations too.
> >> A request to setup these CD tables come from virtio-iommu driver
> >> using the iommu-pasid-table library when running on Arm. The
> >> virtio-iommu then pass these PASID tables to the host using the right
> >> virtio backend and support in VMM.
> >>
> >> For testing we have added necessary support in kvmtool. The changes
> >> in kvmtool are based on virtio-iommu development branch by
> >> Jean-Philippe Brucker [3].
> >>
> >> The tested kernel branch contains following in the order bottom to
> >> top on the git hash -
> >> a) v5.11-rc3
> >> b) arm-smmu-v3 [1] and vfio [2] changes from Eric to add nested page
> >>     table support for Arm.
> >> c) Smmu test engine patches from Jean-Philippe's branch [4]
> >> d) This series
> >> e) Domain nesting info patches [5][6][7].
> >> f) Changes to add arm-smmu-v3 specific nesting info (to be sent to
> >>     the list).
> >>
> >> This kernel is tested on Neoverse reference software stack with Fixed
> >> virtual platform. Public version of the software stack and FVP is
> >> available here[8][9].
> >>
> >> A big thanks to Jean-Philippe for his contributions towards this work
> >> and for his valuable guidance.
> >>
> >> [1]
> >> https://lore.kernel.org/linux-iommu/20201118112151.25412-1-eric.auger
> >> @redhat.com/T/ [2]
> >>
> https://lore.kernel.org/kvmarm/20201116110030.32335-12-eric.auger@red
> >> hat.com/T/ [3]
> >> https://jpbrucker.net/git/kvmtool/log/?h=virtio-iommu/devel
> >> [4] https://jpbrucker.net/git/linux/log/?h=sva/smmute
> >> [5]
> >> https://lore.kernel.org/kvm/1599734733-6431-2-git-send-email-yi.l.liu
> >> @intel.com/ [6]
> >> https://lore.kernel.org/kvm/1599734733-6431-3-git-send-email-yi.l.liu
> >> @intel.com/ [7]
> >> https://lore.kernel.org/kvm/1599734733-6431-4-git-send-email-yi.l.liu
> >> @intel.com/ [8]
> >> https://developer.arm.com/tools-and-software/open-source-software/arm
> >> -platforms-software/arm-ecosystem-fvps
> >> [9]
> >> https://git.linaro.org/landing-teams/working/arm/arm-reference-platfo
> >> rms.git/about/docs/rdn1edge/user-guide.rst
> >
> > Could you share a public branch where we could find all the kernel pieces.
> >
> > Thank you in advance
> 
> Apologies for the delay. It took a bit of time to sort things out for a public
> branch.
> The branch is available in my github now. Please have a look.
> 
> https://github.com/vivek-arm/linux/tree/5.11-rc3-nested-pgtbl-arm-smmuv3-vi
> rtio-iommu

Thanks for this. Do you have a corresponding kvmtool branch mentioned above as public?

Thanks,
Shameer


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH RFC v1 00/15] iommu/virtio: Nested stage support with Arm
  2021-01-21 17:34   ` Vivek Kumar Gautam
  2021-01-22 15:49     ` Shameerali Kolothum Thodi
@ 2021-01-25  8:43     ` Auger Eric
  1 sibling, 0 replies; 44+ messages in thread
From: Auger Eric @ 2021-01-25  8:43 UTC (permalink / raw)
  To: Vivek Kumar Gautam, linux-kernel, linux-arm-kernel, iommu,
	virtualization
  Cc: jean-philippe, kevin.tian, jacob.jun.pan, mst, joro, will.deacon,
	shameerali.kolothum.thodi, alex.williamson, yi.l.liu,
	lorenzo.pieralisi, robin.murphy

Hi Vivek,

On 1/21/21 6:34 PM, Vivek Kumar Gautam wrote:
> Hi Eric,
> 
> 
> On 1/19/21 2:33 PM, Auger Eric wrote:
>> Hi Vivek,
>>
>> On 1/15/21 1:13 PM, Vivek Gautam wrote:
>>> This patch-series aims at enabling Nested stage translation in guests
>>> using virtio-iommu as the paravirtualized iommu. The backend is
>>> supported
>>> with Arm SMMU-v3 that provides nested stage-1 and stage-2 translation.
>>>
>>> This series derives its purpose from various efforts happening to add
>>> support for Shared Virtual Addressing (SVA) in host and guest. On Arm,
>>> most of the support for SVA has already landed. The support for nested
>>> stage translation and fault reporting to guest has been proposed [1].
>>> The related changes required in VFIO [2] framework have also been put
>>> forward.
>>>
>>> This series proposes changes in virtio-iommu to program PASID tables
>>> and related stage-1 page tables. A simple iommu-pasid-table library
>>> is added for this purpose that interacts with vendor drivers to
>>> allocate and populate PASID tables.
>>> In Arm SMMUv3 we propose to pull the Context Descriptor (CD) management
>>> code out of the arm-smmu-v3 driver and add that as a glue vendor layer
>>> to support allocating CD tables, and populating them with right values.
>>> These CD tables are essentially the PASID tables and contain stage-1
>>> page table configurations too.
>>> A request to setup these CD tables come from virtio-iommu driver using
>>> the iommu-pasid-table library when running on Arm. The virtio-iommu
>>> then pass these PASID tables to the host using the right virtio backend
>>> and support in VMM.
>>>
>>> For testing we have added necessary support in kvmtool. The changes in
>>> kvmtool are based on virtio-iommu development branch by Jean-Philippe
>>> Brucker [3].
>>>
>>> The tested kernel branch contains following in the order bottom to top
>>> on the git hash -
>>> a) v5.11-rc3
>>> b) arm-smmu-v3 [1] and vfio [2] changes from Eric to add nested page
>>>     table support for Arm.
>>> c) Smmu test engine patches from Jean-Philippe's branch [4]
>>> d) This series
>>> e) Domain nesting info patches [5][6][7].
>>> f) Changes to add arm-smmu-v3 specific nesting info (to be sent to
>>>     the list).
>>>
>>> This kernel is tested on Neoverse reference software stack with
>>> Fixed virtual platform. Public version of the software stack and
>>> FVP is available here[8][9].
>>>
>>> A big thanks to Jean-Philippe for his contributions towards this work
>>> and for his valuable guidance.
>>>
>>> [1]
>>> https://lore.kernel.org/linux-iommu/20201118112151.25412-1-eric.auger@redhat.com/T/
>>>
>>> [2]
>>> https://lore.kernel.org/kvmarm/20201116110030.32335-12-eric.auger@redhat.com/T/
>>>
>>> [3] https://jpbrucker.net/git/kvmtool/log/?h=virtio-iommu/devel
>>> [4] https://jpbrucker.net/git/linux/log/?h=sva/smmute
>>> [5]
>>> https://lore.kernel.org/kvm/1599734733-6431-2-git-send-email-yi.l.liu@intel.com/
>>>
>>> [6]
>>> https://lore.kernel.org/kvm/1599734733-6431-3-git-send-email-yi.l.liu@intel.com/
>>>
>>> [7]
>>> https://lore.kernel.org/kvm/1599734733-6431-4-git-send-email-yi.l.liu@intel.com/
>>>
>>> [8]
>>> https://developer.arm.com/tools-and-software/open-source-software/arm-platforms-software/arm-ecosystem-fvps
>>>
>>> [9]
>>> https://git.linaro.org/landing-teams/working/arm/arm-reference-platforms.git/about/docs/rdn1edge/user-guide.rst
>>>
>>
>> Could you share a public branch where we could find all the kernel
>> pieces.
>>
>> Thank you in advance
> 
> Apologies for the delay. It took a bit of time to sort things out for a
> public branch.
> The branch is available in my github now. Please have a look.
> 
> https://github.com/vivek-arm/linux/tree/5.11-rc3-nested-pgtbl-arm-smmuv3-virtio-iommu

no problem. Thank you for the link.

Best Regards

Eric
> 
> 
> 
> Thanks and regards
> Vivek
> 
>>
>> Best Regards
>>
>> Eric
>>>
>>> Jean-Philippe Brucker (6):
>>>    iommu/virtio: Add headers for table format probing
>>>    iommu/virtio: Add table format probing
>>>    iommu/virtio: Add headers for binding pasid table in iommu
>>>    iommu/virtio: Add support for INVALIDATE request
>>>    iommu/virtio: Attach Arm PASID tables when available
>>>    iommu/virtio: Add support for Arm LPAE page table format
>>>
>>> Vivek Gautam (9):
>>>    iommu/arm-smmu-v3: Create a Context Descriptor library
>>>    iommu: Add a simple PASID table library
>>>    iommu/arm-smmu-v3: Update drivers to work with iommu-pasid-table
>>>    iommu/arm-smmu-v3: Update CD base address info for user-space
>>>    iommu/arm-smmu-v3: Set sync op from consumer driver of cd-lib
>>>    iommu: Add asid_bits to arm smmu-v3 stage1 table info
>>>    iommu/virtio: Update table format probing header
>>>    iommu/virtio: Prepare to add attach pasid table infrastructure
>>>    iommu/virtio: Update fault type and reason info for viommu fault
>>>
>>>   drivers/iommu/arm/arm-smmu-v3/Makefile        |   2 +-
>>>   .../arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c      | 283 +++++++
>>>   .../iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c   |  16 +-
>>>   drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c   | 268 +------
>>>   drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h   |   4 +-
>>>   drivers/iommu/iommu-pasid-table.h             | 140 ++++
>>>   drivers/iommu/virtio-iommu.c                  | 692 +++++++++++++++++-
>>>   include/uapi/linux/iommu.h                    |   2 +-
>>>   include/uapi/linux/virtio_iommu.h             | 158 +++-
>>>   9 files changed, 1303 insertions(+), 262 deletions(-)
>>>   create mode 100644 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c
>>>   create mode 100644 drivers/iommu/iommu-pasid-table.h
>>>
>>
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH RFC v1 00/15] iommu/virtio: Nested stage support with Arm
  2021-01-22 15:49     ` Shameerali Kolothum Thodi
@ 2021-01-25 12:55       ` Vivek Kumar Gautam
  0 siblings, 0 replies; 44+ messages in thread
From: Vivek Kumar Gautam @ 2021-01-25 12:55 UTC (permalink / raw)
  To: Shameerali Kolothum Thodi, Auger Eric, linux-kernel,
	linux-arm-kernel, iommu, virtualization
  Cc: joro, will.deacon, mst, robin.murphy, jean-philippe,
	alex.williamson, kevin.tian, jacob.jun.pan, yi.l.liu,
	lorenzo.pieralisi

Hi Shameer,


On 1/22/21 9:19 PM, Shameerali Kolothum Thodi wrote:
> Hi Vivek,
> 
>> -----Original Message-----
>> From: Vivek Kumar Gautam [mailto:vivek.gautam@arm.com]
>> Sent: 21 January 2021 17:34
>> To: Auger Eric <eric.auger@redhat.com>; linux-kernel@vger.kernel.org;
>> linux-arm-kernel@lists.infradead.org; iommu@lists.linux-foundation.org;
>> virtualization@lists.linux-foundation.org
>> Cc: joro@8bytes.org; will.deacon@arm.com; mst@redhat.com;
>> robin.murphy@arm.com; jean-philippe@linaro.org;
>> alex.williamson@redhat.com; kevin.tian@intel.com;
>> jacob.jun.pan@linux.intel.com; yi.l.liu@intel.com; lorenzo.pieralisi@arm.com;
>> Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
>> Subject: Re: [PATCH RFC v1 00/15] iommu/virtio: Nested stage support with
>> Arm
>>
>> Hi Eric,
>>
>>
>> On 1/19/21 2:33 PM, Auger Eric wrote:
>>> Hi Vivek,
>>>
>>> On 1/15/21 1:13 PM, Vivek Gautam wrote:
>>>> This patch-series aims at enabling Nested stage translation in guests
>>>> using virtio-iommu as the paravirtualized iommu. The backend is
>>>> supported with Arm SMMU-v3 that provides nested stage-1 and stage-2
>> translation.
>>>>
>>>> This series derives its purpose from various efforts happening to add
>>>> support for Shared Virtual Addressing (SVA) in host and guest. On
>>>> Arm, most of the support for SVA has already landed. The support for
>>>> nested stage translation and fault reporting to guest has been proposed [1].
>>>> The related changes required in VFIO [2] framework have also been put
>>>> forward.
>>>>
>>>> This series proposes changes in virtio-iommu to program PASID tables
>>>> and related stage-1 page tables. A simple iommu-pasid-table library
>>>> is added for this purpose that interacts with vendor drivers to
>>>> allocate and populate PASID tables.
>>>> In Arm SMMUv3 we propose to pull the Context Descriptor (CD)
>>>> management code out of the arm-smmu-v3 driver and add that as a glue
>>>> vendor layer to support allocating CD tables, and populating them with right
>> values.
>>>> These CD tables are essentially the PASID tables and contain stage-1
>>>> page table configurations too.
>>>> A request to setup these CD tables come from virtio-iommu driver
>>>> using the iommu-pasid-table library when running on Arm. The
>>>> virtio-iommu then pass these PASID tables to the host using the right
>>>> virtio backend and support in VMM.
>>>>
>>>> For testing we have added necessary support in kvmtool. The changes
>>>> in kvmtool are based on virtio-iommu development branch by
>>>> Jean-Philippe Brucker [3].
>>>>
>>>> The tested kernel branch contains following in the order bottom to
>>>> top on the git hash -
>>>> a) v5.11-rc3
>>>> b) arm-smmu-v3 [1] and vfio [2] changes from Eric to add nested page
>>>>      table support for Arm.
>>>> c) Smmu test engine patches from Jean-Philippe's branch [4]
>>>> d) This series
>>>> e) Domain nesting info patches [5][6][7].
>>>> f) Changes to add arm-smmu-v3 specific nesting info (to be sent to
>>>>      the list).
>>>>
>>>> This kernel is tested on Neoverse reference software stack with Fixed
>>>> virtual platform. Public version of the software stack and FVP is
>>>> available here[8][9].
>>>>
>>>> A big thanks to Jean-Philippe for his contributions towards this work
>>>> and for his valuable guidance.
>>>>
>>>> [1]
>>>> https://lore.kernel.org/linux-iommu/20201118112151.25412-1-eric.auger
>>>> @redhat.com/T/ [2]
>>>>
>> https://lore.kernel.org/kvmarm/20201116110030.32335-12-eric.auger@red
>>>> hat.com/T/ [3]
>>>> https://jpbrucker.net/git/kvmtool/log/?h=virtio-iommu/devel
>>>> [4] https://jpbrucker.net/git/linux/log/?h=sva/smmute
>>>> [5]
>>>> https://lore.kernel.org/kvm/1599734733-6431-2-git-send-email-yi.l.liu
>>>> @intel.com/ [6]
>>>> https://lore.kernel.org/kvm/1599734733-6431-3-git-send-email-yi.l.liu
>>>> @intel.com/ [7]
>>>> https://lore.kernel.org/kvm/1599734733-6431-4-git-send-email-yi.l.liu
>>>> @intel.com/ [8]
>>>> https://developer.arm.com/tools-and-software/open-source-software/arm
>>>> -platforms-software/arm-ecosystem-fvps
>>>> [9]
>>>> https://git.linaro.org/landing-teams/working/arm/arm-reference-platfo
>>>> rms.git/about/docs/rdn1edge/user-guide.rst
>>>
>>> Could you share a public branch where we could find all the kernel pieces.
>>>
>>> Thank you in advance
>>
>> Apologies for the delay. It took a bit of time to sort things out for a public
>> branch.
>> The branch is available in my github now. Please have a look.
>>
>> https://github.com/vivek-arm/linux/tree/5.11-rc3-nested-pgtbl-arm-smmuv3-vi
>> rtio-iommu
>  > Thanks for this. Do you have a corresponding kvmtool branch mentioned 
above as public?

Thanks for showing interest. I will publish the kvmtool branch asap. 
Though the current development is based on Jean's branch for 
virtio-iommu [1], I plan to rebase the changes to master soon.

Thanks & regards
Vivek

[1] https://jpbrucker.net/git/kvmtool/log/?h=virtio-iommu/devel
> 
> Thanks,
> Shameer
> 

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH RFC v1 02/15] iommu: Add a simple PASID table library
  2021-01-15 12:13 ` [PATCH RFC v1 02/15] iommu: Add a simple PASID table library Vivek Gautam
@ 2021-03-03 17:11   ` Jean-Philippe Brucker
  2021-03-12 12:47     ` Vivek Kumar Gautam
  0 siblings, 1 reply; 44+ messages in thread
From: Jean-Philippe Brucker @ 2021-03-03 17:11 UTC (permalink / raw)
  To: Vivek Gautam
  Cc: linux-kernel, linux-arm-kernel, iommu, virtualization, joro,
	will.deacon, mst, robin.murphy, eric.auger, alex.williamson,
	kevin.tian, jacob.jun.pan, yi.l.liu, lorenzo.pieralisi,
	shameerali.kolothum.thodi

Hi Vivek,

Thanks again for working on this. I have a few comments but it looks
sensible overall.

Regarding the overall design, I was initially assigning page directories
instead of whole PASID tables, which would simplify the driver and host
implementation. A major complication, however, is SMMUv3 accesses PASID
tables using a guest-physical address, so there is a messy negotiation
needed between host and guest when the host needs to allocate PASID
tables. Plus vSMMU needs PASID table assignment, so that's what the host
driver will implement.

On Fri, Jan 15, 2021 at 05:43:29PM +0530, Vivek Gautam wrote:
> Add a small API in iommu subsystem to handle PASID table allocation
> requests from different consumer drivers, such as a paravirtualized
> iommu driver. The API provides ops for allocating and freeing PASID
> table, writing to it and managing the table caches.
> 
> This library also provides for registering a vendor API that attaches
> to these ops. The vendor APIs would eventually perform arch level
> implementations for these PASID tables.

Although Arm might be the only vendor to ever use this, I think the
abstraction makes sense and isn't too invasive. Even if we called directly
into the SMMU driver from the virtio one, we'd still need patch 3 and
separate TLB invalidations ops.

> Signed-off-by: Vivek Gautam <vivek.gautam@arm.com>
> Cc: Joerg Roedel <joro@8bytes.org>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Robin Murphy <robin.murphy@arm.com>
> Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
> Cc: Eric Auger <eric.auger@redhat.com>
> Cc: Alex Williamson <alex.williamson@redhat.com>
> Cc: Kevin Tian <kevin.tian@intel.com>
> Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
> Cc: Liu Yi L <yi.l.liu@intel.com>
> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
> ---
>  drivers/iommu/iommu-pasid-table.h | 134 ++++++++++++++++++++++++++++++
>  1 file changed, 134 insertions(+)
>  create mode 100644 drivers/iommu/iommu-pasid-table.h
> 
> diff --git a/drivers/iommu/iommu-pasid-table.h b/drivers/iommu/iommu-pasid-table.h
> new file mode 100644
> index 000000000000..bd4f57656f67
> --- /dev/null
> +++ b/drivers/iommu/iommu-pasid-table.h
> @@ -0,0 +1,134 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * PASID table management for the IOMMU
> + *
> + * Copyright (C) 2021 Arm Ltd.
> + */
> +#ifndef __IOMMU_PASID_TABLE_H
> +#define __IOMMU_PASID_TABLE_H
> +
> +#include <linux/io-pgtable.h>
> +
> +#include "arm/arm-smmu-v3/arm-smmu-v3.h"
> +
> +enum pasid_table_fmt {
> +	PASID_TABLE_ARM_SMMU_V3,
> +	PASID_TABLE_NUM_FMTS,
> +};
> +
> +/**
> + * struct arm_smmu_cfg_info - arm-smmu-v3 specific configuration data
> + *
> + * @s1_cfg: arm-smmu-v3 stage1 config data
> + * @feat_flag: features supported by arm-smmu-v3 implementation
> + */
> +struct arm_smmu_cfg_info {
> +	struct arm_smmu_s1_cfg	*s1_cfg;
> +	u32			feat_flag;
> +};
> +
> +/**
> + * struct iommu_vendor_psdtable_cfg - Configuration data for PASID tables
> + *
> + * @iommu_dev: device performing the DMA table walks
> + * @fmt: The PASID table format
> + * @base: DMA address of the allocated table, set by the vendor driver
> + * @cfg: arm-smmu-v3 specific config data
> + */
> +struct iommu_vendor_psdtable_cfg {
> +	struct device		*iommu_dev;
> +	enum pasid_table_fmt	fmt;
> +	dma_addr_t		base;
> +	union {
> +		struct arm_smmu_cfg_info	cfg;

For the union to be extensible, that field should be called "arm" or
something like that.

Thanks,
Jean

> +	} vendor;
> +};
> +
> +struct iommu_vendor_psdtable_ops;
> +
> +/**
> + * struct iommu_pasid_table - describes a set of PASID tables
> + *
> + * @cookie: An opaque token provided by the IOMMU driver and passed back to any
> + * callback routine.
> + * @cfg: A copy of the PASID table configuration
> + * @ops: The PASID table operations in use for this set of page tables
> + */
> +struct iommu_pasid_table {
> +	void					*cookie;
> +	struct iommu_vendor_psdtable_cfg	cfg;
> +	struct iommu_vendor_psdtable_ops	*ops;
> +};
> +
> +#define pasid_table_cfg_to_table(pst_cfg) \
> +	container_of((pst_cfg), struct iommu_pasid_table, cfg)
> +
> +struct iommu_vendor_psdtable_ops {
> +	int (*alloc)(struct iommu_vendor_psdtable_cfg *cfg);
> +	void (*free)(struct iommu_vendor_psdtable_cfg *cfg);
> +	void (*prepare)(struct iommu_vendor_psdtable_cfg *cfg,
> +			struct io_pgtable_cfg *pgtbl_cfg, u32 asid);
> +	int (*write)(struct iommu_vendor_psdtable_cfg *cfg, int ssid,
> +		     void *cookie);
> +	void (*sync)(void *cookie, int ssid, bool leaf);
> +};
> +
> +static inline int iommu_psdtable_alloc(struct iommu_pasid_table *tbl,
> +				       struct iommu_vendor_psdtable_cfg *cfg)
> +{
> +	if (!tbl->ops->alloc)
> +		return -ENOSYS;
> +
> +	return tbl->ops->alloc(cfg);
> +}
> +
> +static inline void iommu_psdtable_free(struct iommu_pasid_table *tbl,
> +				       struct iommu_vendor_psdtable_cfg *cfg)
> +{
> +	if (!tbl->ops->free)
> +		return;
> +
> +	tbl->ops->free(cfg);
> +}
> +
> +static inline int iommu_psdtable_prepare(struct iommu_pasid_table *tbl,
> +					 struct iommu_vendor_psdtable_cfg *cfg,
> +					 struct io_pgtable_cfg *pgtbl_cfg,
> +					 u32 asid)
> +{
> +	if (!tbl->ops->prepare)
> +		return -ENOSYS;
> +
> +	tbl->ops->prepare(cfg, pgtbl_cfg, asid);
> +	return 0;
> +}
> +
> +static inline int iommu_psdtable_write(struct iommu_pasid_table *tbl,
> +				       struct iommu_vendor_psdtable_cfg *cfg,
> +				       int ssid, void *cookie)
> +{
> +	if (!tbl->ops->write)
> +		return -ENOSYS;
> +
> +	return tbl->ops->write(cfg, ssid, cookie);
> +}
> +
> +static inline int iommu_psdtable_sync(struct iommu_pasid_table *tbl,
> +				      void *cookie, int ssid, bool leaf)
> +{
> +	if (!tbl->ops->sync)
> +		return -ENOSYS;
> +
> +	tbl->ops->sync(cookie, ssid, leaf);
> +	return 0;
> +}
> +
> +/* A placeholder to register vendor specific pasid layer */
> +static inline struct iommu_pasid_table *
> +iommu_register_pasid_table(enum pasid_table_fmt fmt,
> +			   struct device *dev, void *cookie)
> +{
> +	return NULL;
> +}
> +
> +#endif /* __IOMMU_PASID_TABLE_H */
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH RFC v1 04/15] iommu/arm-smmu-v3: Update CD base address info for user-space
  2021-01-15 12:13 ` [PATCH RFC v1 04/15] iommu/arm-smmu-v3: Update CD base address info for user-space Vivek Gautam
@ 2021-03-03 17:14   ` Jean-Philippe Brucker
  2021-03-12 12:31     ` Vivek Kumar Gautam
  0 siblings, 1 reply; 44+ messages in thread
From: Jean-Philippe Brucker @ 2021-03-03 17:14 UTC (permalink / raw)
  To: Vivek Gautam
  Cc: linux-kernel, linux-arm-kernel, iommu, virtualization, joro,
	will.deacon, mst, robin.murphy, eric.auger, alex.williamson,
	kevin.tian, jacob.jun.pan, yi.l.liu, lorenzo.pieralisi,
	shameerali.kolothum.thodi

On Fri, Jan 15, 2021 at 05:43:31PM +0530, Vivek Gautam wrote:
> Update base address information in vendor pasid table info to pass that
> to user-space for stage1 table management.
> 
> Signed-off-by: Vivek Gautam <vivek.gautam@arm.com>
> Cc: Joerg Roedel <joro@8bytes.org>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Robin Murphy <robin.murphy@arm.com>
> Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
> Cc: Eric Auger <eric.auger@redhat.com>
> Cc: Alex Williamson <alex.williamson@redhat.com>
> Cc: Kevin Tian <kevin.tian@intel.com>
> Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
> Cc: Liu Yi L <yi.l.liu@intel.com>
> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
> ---
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c
> index 8a7187534706..ec37476c8d09 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c
> @@ -55,6 +55,9 @@ static __le64 *arm_smmu_get_cd_ptr(struct iommu_vendor_psdtable_cfg *pst_cfg,
>  		if (arm_smmu_alloc_cd_leaf_table(dev, l1_desc))
>  			return NULL;
>  
> +		if (s1cfg->s1fmt == STRTAB_STE_0_S1FMT_LINEAR)
> +			pst_cfg->base = l1_desc->l2ptr_dma;
> +

This isn't the right place, because this path allocates second-level
tables for two-level tables. I don't think we need pst_cfg->base at all,
because for both linear and two-level tables, the base pointer is in
cdcfg->cdtab_dma, which can be read directly.

Thanks,
Jean

>  		l1ptr = cdcfg->cdtab + idx * CTXDESC_L1_DESC_DWORDS;
>  		arm_smmu_write_cd_l1_desc(l1ptr, l1_desc);
>  		/* An invalid L1CD can be cached */
> @@ -211,6 +214,9 @@ static int arm_smmu_alloc_cd_tables(struct iommu_vendor_psdtable_cfg *pst_cfg)
>  		goto err_free_l1;
>  	}
>  
> +	if (s1cfg->s1fmt == STRTAB_STE_0_S1FMT_64K_L2)
> +		pst_cfg->base = cdcfg->cdtab_dma;
> +
>  	return 0;
>  
>  err_free_l1:
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH RFC v1 05/15] iommu/arm-smmu-v3: Set sync op from consumer driver of cd-lib
  2021-01-15 12:13 ` [PATCH RFC v1 05/15] iommu/arm-smmu-v3: Set sync op from consumer driver of cd-lib Vivek Gautam
@ 2021-03-03 17:15   ` Jean-Philippe Brucker
  2021-03-12 12:49     ` Vivek Kumar Gautam
  0 siblings, 1 reply; 44+ messages in thread
From: Jean-Philippe Brucker @ 2021-03-03 17:15 UTC (permalink / raw)
  To: Vivek Gautam
  Cc: linux-kernel, linux-arm-kernel, iommu, virtualization, joro,
	will.deacon, mst, robin.murphy, eric.auger, alex.williamson,
	kevin.tian, jacob.jun.pan, yi.l.liu, lorenzo.pieralisi,
	shameerali.kolothum.thodi

On Fri, Jan 15, 2021 at 05:43:32PM +0530, Vivek Gautam wrote:
> Te change allows different consumers of arm-smmu-v3-cd-lib to set
> their respective sync op for pasid entries.
> 
> Signed-off-by: Vivek Gautam <vivek.gautam@arm.com>
> Cc: Joerg Roedel <joro@8bytes.org>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Robin Murphy <robin.murphy@arm.com>
> Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
> Cc: Eric Auger <eric.auger@redhat.com>
> Cc: Alex Williamson <alex.williamson@redhat.com>
> Cc: Kevin Tian <kevin.tian@intel.com>
> Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
> Cc: Liu Yi L <yi.l.liu@intel.com>
> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
> ---
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c | 1 -
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c        | 7 +++++++
>  2 files changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c
> index ec37476c8d09..acaa09acecdd 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c
> @@ -265,7 +265,6 @@ struct iommu_vendor_psdtable_ops arm_cd_table_ops = {
>  	.free	 = arm_smmu_free_cd_tables,
>  	.prepare = arm_smmu_prepare_cd,
>  	.write	 = arm_smmu_write_ctx_desc,
> -	.sync	 = arm_smmu_sync_cd,
>  };
>  
>  struct iommu_pasid_table *arm_smmu_register_cd_table(struct device *dev,
> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> index 2f86c6ac42b6..0c644be22b4b 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> @@ -1869,6 +1869,13 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain,
>  	if (ret)
>  		goto out_free_cd_tables;
>  
> +	/*
> +	 * Strange to setup an op here?
> +	 * cd-lib is the actual user of sync op, and therefore the platform
> +	 * drivers should assign this sync/maintenance ops as per need.
> +	 */
> +	tbl->ops->sync = arm_smmu_sync_cd;
> +

Modifying a static struct from here doesn't feel right. I think the
interface should be roughly similar to io-pgtable since the principle is
the same. So the sync() op should be separate from arm_cd_table_ops since
it's a callback into the driver. Maybe pass it to
iommu_register_pasid_table().

Thanks,
Jean

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH RFC v1 06/15] iommu/virtio: Add headers for table format probing
  2021-01-15 12:13 ` [PATCH RFC v1 06/15] iommu/virtio: Add headers for table format probing Vivek Gautam
@ 2021-03-03 17:17   ` Jean-Philippe Brucker
  2021-03-12 12:54     ` Vivek Kumar Gautam
  0 siblings, 1 reply; 44+ messages in thread
From: Jean-Philippe Brucker @ 2021-03-03 17:17 UTC (permalink / raw)
  To: Vivek Gautam
  Cc: linux-kernel, linux-arm-kernel, iommu, virtualization, joro,
	will.deacon, mst, robin.murphy, eric.auger, alex.williamson,
	kevin.tian, jacob.jun.pan, yi.l.liu, lorenzo.pieralisi,
	shameerali.kolothum.thodi

On Fri, Jan 15, 2021 at 05:43:33PM +0530, Vivek Gautam wrote:
> From: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
> 
> Add required UAPI defines for probing table format for underlying
> iommu hardware. The device may provide information about hardware
> tables and additional capabilities for each device.
> This allows guest to correctly fabricate stage-1 page tables.
> 
> Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
> [Vivek: Use a single "struct virtio_iommu_probe_table_format" rather
>         than separate structures for page table and pasid table format.

Makes sense. I've integrated that into the spec draft, added more precise
documentation and modified some of the definitions.

The current draft is here:
https://jpbrucker.net/virtio-iommu/spec/virtio-iommu-v0.13.pdf
Posted on the list here
https://lists.oasis-open.org/archives/virtio-dev/202102/msg00012.html

> 	Also update commit message.]
> Signed-off-by: Vivek Gautam <vivek.gautam@arm.com>
> Cc: Joerg Roedel <joro@8bytes.org>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Michael S. Tsirkin <mst@redhat.com>
> Cc: Robin Murphy <robin.murphy@arm.com>
> Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
> Cc: Eric Auger <eric.auger@redhat.com>
> Cc: Alex Williamson <alex.williamson@redhat.com>
> Cc: Kevin Tian <kevin.tian@intel.com>
> Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
> Cc: Liu Yi L <yi.l.liu@intel.com>
> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
> ---
>  include/uapi/linux/virtio_iommu.h | 44 ++++++++++++++++++++++++++++++-
>  1 file changed, 43 insertions(+), 1 deletion(-)
> 
> diff --git a/include/uapi/linux/virtio_iommu.h b/include/uapi/linux/virtio_iommu.h
> index 237e36a280cb..43821e33e7af 100644
> --- a/include/uapi/linux/virtio_iommu.h
> +++ b/include/uapi/linux/virtio_iommu.h
> @@ -2,7 +2,7 @@
>  /*
>   * Virtio-iommu definition v0.12
>   *
> - * Copyright (C) 2019 Arm Ltd.
> + * Copyright (C) 2019-2021 Arm Ltd.

Not strictly necessary. But if you're modifying this comment please also
remove the "v0.12" above

>   */
>  #ifndef _UAPI_LINUX_VIRTIO_IOMMU_H
>  #define _UAPI_LINUX_VIRTIO_IOMMU_H
> @@ -111,6 +111,12 @@ struct virtio_iommu_req_unmap {
>  
>  #define VIRTIO_IOMMU_PROBE_T_NONE		0
>  #define VIRTIO_IOMMU_PROBE_T_RESV_MEM		1
> +#define VIRTIO_IOMMU_PROBE_T_PAGE_SIZE_MASK	2
> +#define VIRTIO_IOMMU_PROBE_T_INPUT_RANGE	3
> +#define VIRTIO_IOMMU_PROBE_T_OUTPUT_SIZE	4
> +#define VIRTIO_IOMMU_PROBE_T_PASID_SIZE		5
> +#define VIRTIO_IOMMU_PROBE_T_PAGE_TABLE_FMT	6
> +#define VIRTIO_IOMMU_PROBE_T_PASID_TABLE_FMT	7

Since there is a single struct we can have a single
VIRTIO_IOMMU_PROBE_T_TABLE_FORMAT.

>  
>  #define VIRTIO_IOMMU_PROBE_T_MASK		0xfff
>  
> @@ -130,6 +136,42 @@ struct virtio_iommu_probe_resv_mem {
>  	__le64					end;
>  };
>  
> +struct virtio_iommu_probe_page_size_mask {
> +	struct virtio_iommu_probe_property	head;
> +	__u8					reserved[4];
> +	__le64					mask;
> +};
> +
> +struct virtio_iommu_probe_input_range {
> +	struct virtio_iommu_probe_property	head;
> +	__u8					reserved[4];
> +	__le64					start;
> +	__le64					end;
> +};
> +
> +struct virtio_iommu_probe_output_size {
> +	struct virtio_iommu_probe_property	head;
> +	__u8					bits;
> +	__u8					reserved[3];
> +};
> +
> +struct virtio_iommu_probe_pasid_size {
> +	struct virtio_iommu_probe_property	head;
> +	__u8					bits;
> +	__u8					reserved[3];
> +};
> +
> +/* Arm LPAE page table format */
> +#define VIRTIO_IOMMU_FOMRAT_PGTF_ARM_LPAE	1

s/FOMRAT/FORMAT

> +/* Arm smmu-v3 type PASID table format */
> +#define VIRTIO_IOMMU_FORMAT_PSTF_ARM_SMMU_V3	2

These should be with the Arm-specific definitions patches 11 and 14

Thanks,
Jean

> +
> +struct virtio_iommu_probe_table_format {
> +	struct virtio_iommu_probe_property	head;
> +	__le16					format;
> +	__u8					reserved[2];
> +};
> +
>  struct virtio_iommu_req_probe {
>  	struct virtio_iommu_req_head		head;
>  	__le32					endpoint;
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH RFC v1 08/15] iommu: Add asid_bits to arm smmu-v3 stage1 table info
  2021-01-15 12:13 ` [PATCH RFC v1 08/15] iommu: Add asid_bits to arm smmu-v3 stage1 table info Vivek Gautam
@ 2021-03-03 17:18   ` Jean-Philippe Brucker
  2021-03-12 12:57     ` Vivek Kumar Gautam
  0 siblings, 1 reply; 44+ messages in thread
From: Jean-Philippe Brucker @ 2021-03-03 17:18 UTC (permalink / raw)
  To: Vivek Gautam
  Cc: linux-kernel, linux-arm-kernel, iommu, virtualization, joro,
	will.deacon, mst, robin.murphy, eric.auger, alex.williamson,
	kevin.tian, jacob.jun.pan, yi.l.liu, lorenzo.pieralisi,
	shameerali.kolothum.thodi

On Fri, Jan 15, 2021 at 05:43:35PM +0530, Vivek Gautam wrote:
> aisd_bits data is required to prepare stage-1 tables for arm-smmu-v3.
> 
> Signed-off-by: Vivek Gautam <vivek.gautam@arm.com>
> Cc: Joerg Roedel <joro@8bytes.org>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Robin Murphy <robin.murphy@arm.com>
> Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
> Cc: Eric Auger <eric.auger@redhat.com>
> Cc: Alex Williamson <alex.williamson@redhat.com>
> Cc: Kevin Tian <kevin.tian@intel.com>
> Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
> Cc: Liu Yi L <yi.l.liu@intel.com>
> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
> ---
>  include/uapi/linux/iommu.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/include/uapi/linux/iommu.h b/include/uapi/linux/iommu.h
> index 082d758dd016..96abbfc7c643 100644
> --- a/include/uapi/linux/iommu.h
> +++ b/include/uapi/linux/iommu.h
> @@ -357,7 +357,7 @@ struct iommu_pasid_smmuv3 {
>  	__u32	version;
>  	__u8	s1fmt;
>  	__u8	s1dss;
> -	__u8	padding[2];
> +	__u16	asid_bits;

Is this used anywhere?  This struct is passed from host userspace to host
kernel to attach the PASID table, so I don't think it needs an asid_bits
field.

Thanks,
Jean


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH RFC v1 09/15] iommu/virtio: Update table format probing header
  2021-01-15 12:13 ` [PATCH RFC v1 09/15] iommu/virtio: Update table format probing header Vivek Gautam
@ 2021-03-03 17:21   ` Jean-Philippe Brucker
  2021-03-12 12:58     ` Vivek Kumar Gautam
  0 siblings, 1 reply; 44+ messages in thread
From: Jean-Philippe Brucker @ 2021-03-03 17:21 UTC (permalink / raw)
  To: Vivek Gautam
  Cc: linux-kernel, linux-arm-kernel, iommu, virtualization, joro,
	will.deacon, mst, robin.murphy, eric.auger, alex.williamson,
	kevin.tian, jacob.jun.pan, yi.l.liu, lorenzo.pieralisi,
	shameerali.kolothum.thodi

On Fri, Jan 15, 2021 at 05:43:36PM +0530, Vivek Gautam wrote:
> Add info about asid_bits and additional flags to table format
> probing header.
> 
> Signed-off-by: Vivek Gautam <vivek.gautam@arm.com>
> Cc: Joerg Roedel <joro@8bytes.org>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Michael S. Tsirkin <mst@redhat.com>
> Cc: Robin Murphy <robin.murphy@arm.com>
> Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
> Cc: Eric Auger <eric.auger@redhat.com>
> Cc: Alex Williamson <alex.williamson@redhat.com>
> Cc: Kevin Tian <kevin.tian@intel.com>
> Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
> Cc: Liu Yi L <yi.l.liu@intel.com>
> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
> ---
>  include/uapi/linux/virtio_iommu.h | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/include/uapi/linux/virtio_iommu.h b/include/uapi/linux/virtio_iommu.h
> index 43821e33e7af..8a0624bab4b2 100644
> --- a/include/uapi/linux/virtio_iommu.h
> +++ b/include/uapi/linux/virtio_iommu.h
> @@ -169,7 +169,10 @@ struct virtio_iommu_probe_pasid_size {
>  struct virtio_iommu_probe_table_format {
>  	struct virtio_iommu_probe_property	head;
>  	__le16					format;
> -	__u8					reserved[2];
> +	__le16					asid_bits;
> +
> +	__le32					flags;

This struct should only contain the head and format fields. asid and flags
should go in a specialized structure - virtio_iommu_probe_pgt_arm64 in the
latest spec draft, where I dropped the asid_bits field in favor of an
"ASID16" flag.

Thanks,
Jean


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH RFC v1 13/15] iommu/virtio: Attach Arm PASID tables when available
  2021-01-15 12:13 ` [PATCH RFC v1 13/15] iommu/virtio: Attach Arm PASID tables when available Vivek Gautam
@ 2021-03-03 17:25   ` Jean-Philippe Brucker
  2021-03-12 13:29     ` Vivek Kumar Gautam
  0 siblings, 1 reply; 44+ messages in thread
From: Jean-Philippe Brucker @ 2021-03-03 17:25 UTC (permalink / raw)
  To: Vivek Gautam
  Cc: linux-kernel, linux-arm-kernel, iommu, virtualization, joro,
	will.deacon, mst, robin.murphy, eric.auger, alex.williamson,
	kevin.tian, jacob.jun.pan, yi.l.liu, lorenzo.pieralisi,
	shameerali.kolothum.thodi

On Fri, Jan 15, 2021 at 05:43:40PM +0530, Vivek Gautam wrote:
[...]
> +static int viommu_setup_pgtable(struct viommu_endpoint *vdev,
> +				struct viommu_domain *vdomain)
> +{
> +	int ret, id;
> +	u32 asid;
> +	enum io_pgtable_fmt fmt;
> +	struct io_pgtable_ops *ops = NULL;
> +	struct viommu_dev *viommu = vdev->viommu;
> +	struct virtio_iommu_probe_table_format *desc = vdev->pgtf;
> +	struct iommu_pasid_table *tbl = vdomain->pasid_tbl;
> +	struct iommu_vendor_psdtable_cfg *pst_cfg;
> +	struct arm_smmu_cfg_info *cfgi;
> +	struct io_pgtable_cfg cfg = {
> +		.iommu_dev	= viommu->dev->parent,
> +		.tlb		= &viommu_flush_ops,
> +		.pgsize_bitmap	= vdev->pgsize_mask ? vdev->pgsize_mask :
> +				  vdomain->domain.pgsize_bitmap,
> +		.ias		= (vdev->input_end ? ilog2(vdev->input_end) :
> +				   ilog2(vdomain->domain.geometry.aperture_end)) + 1,
> +		.oas		= vdev->output_bits,
> +	};
> +
> +	if (!desc)
> +		return -EINVAL;
> +
> +	if (!vdev->output_bits)
> +		return -ENODEV;
> +
> +	switch (le16_to_cpu(desc->format)) {
> +	case VIRTIO_IOMMU_FOMRAT_PGTF_ARM_LPAE:
> +		fmt = ARM_64_LPAE_S1;
> +		break;
> +	default:
> +		dev_err(vdev->dev, "unsupported page table format 0x%x\n",
> +			le16_to_cpu(desc->format));
> +		return -EINVAL;
> +	}
> +
> +	if (vdomain->mm.ops) {
> +		/*
> +		 * TODO: attach additional endpoint to the domain. Check that
> +		 * the config is sane.
> +		 */
> +		return -EEXIST;
> +	}
> +
> +	vdomain->mm.domain = vdomain;
> +	ops = alloc_io_pgtable_ops(fmt, &cfg, &vdomain->mm);
> +	if (!ops)
> +		return -ENOMEM;
> +
> +	pst_cfg = &tbl->cfg;
> +	cfgi = &pst_cfg->vendor.cfg;
> +	id = ida_simple_get(&asid_ida, 1, 1 << desc->asid_bits, GFP_KERNEL);
> +	if (id < 0) {
> +		ret = id;
> +		goto err_free_pgtable;
> +	}
> +
> +	asid = id;
> +	ret = iommu_psdtable_prepare(tbl, pst_cfg, &cfg, asid);
> +	if (ret)
> +		goto err_free_asid;
> +
> +	/*
> +	 * Strange to setup an op here?
> +	 * cd-lib is the actual user of sync op, and therefore the platform
> +	 * drivers should assign this sync/maintenance ops as per need.
> +	 */
> +	tbl->ops->sync = viommu_flush_pasid;

But this function deals with page tables, not pasid tables. As said on an
earlier patch, the TLB flush ops should probably be passed during table
registration - those ops are global so should really be const.

> +
> +	/* Right now only PASID 0 supported ?? */
> +	ret = iommu_psdtable_write(tbl, pst_cfg, 0, &cfgi->s1_cfg->cd);
> +	if (ret)
> +		goto err_free_asid;
> +
> +	vdomain->mm.ops = ops;
> +	dev_dbg(vdev->dev, "using page table format 0x%x\n", fmt);
> +
> +	return 0;
> +
> +err_free_asid:
> +	ida_simple_remove(&asid_ida, asid);
> +err_free_pgtable:
> +	free_io_pgtable_ops(ops);
> +	return ret;
> +}
> +
> +static int viommu_config_arm_pst(struct iommu_vendor_psdtable_cfg *pst_cfg,
> +				 struct virtio_iommu_req_attach_pst_arm *req)
> +{
> +	struct arm_smmu_s1_cfg *s1_cfg = pst_cfg->vendor.cfg.s1_cfg;
> +
> +	if (!s1_cfg)
> +		return -ENODEV;
> +
> +	req->format	= cpu_to_le16(VIRTIO_IOMMU_FORMAT_PSTF_ARM_SMMU_V3);
> +	req->s1fmt	= s1_cfg->s1fmt;
> +	req->s1dss	= VIRTIO_IOMMU_PSTF_ARM_SMMU_V3_DSS_0;
> +	req->s1contextptr = cpu_to_le64(pst_cfg->base);
> +	req->s1cdmax	= cpu_to_le32(s1_cfg->s1cdmax);
> +
> +	return 0;
> +}
> +
> +static int viommu_config_pst(struct iommu_vendor_psdtable_cfg *pst_cfg,
> +			     void *req, enum pasid_table_fmt fmt)
> +{
> +	int ret;
> +
> +	switch (fmt) {
> +	case PASID_TABLE_ARM_SMMU_V3:
> +		ret = viommu_config_arm_pst(pst_cfg, req);
> +		break;
> +	default:
> +		ret = -EINVAL;
> +		WARN_ON(1);
> +	}
> +
> +	return ret;
> +}
> +
> +static int viommu_prepare_arm_pst(struct viommu_endpoint *vdev,
> +				  struct iommu_vendor_psdtable_cfg *pst_cfg)
> +{
> +	struct virtio_iommu_probe_table_format *pgtf = vdev->pgtf;
> +	struct arm_smmu_cfg_info *cfgi = &pst_cfg->vendor.cfg;
> +	struct arm_smmu_s1_cfg *cfg;
> +
> +	/* Some sanity checks */
> +	if (pgtf->asid_bits != 8 && pgtf->asid_bits != 16)
> +		return -EINVAL;

No need for this, next patch cheks asid size in viommu_config_arm_pgt()

> +
> +	cfg = devm_kzalloc(pst_cfg->iommu_dev, sizeof(cfg), GFP_KERNEL);
> +	if (!cfg)
> +		return -ENOMEM;
> +
> +	cfgi->s1_cfg = cfg;
> +	cfg->s1cdmax = vdev->pasid_bits;
> +	cfg->cd.asid = pgtf->asid_bits;

That doesn't look right, cfg->cd.asid takes the ASID value of context 0
but here we're writing a limit. viommu_setup_pgtable() probably needs to
set this field to the allocated ASID, since viommu_teardown_pgtable() uses
it.

> +
> +	pst_cfg->fmt = PASID_TABLE_ARM_SMMU_V3;

Parent function can set this

> +	/* XXX HACK: set feature bit ARM_SMMU_FEAT_2_LVL_CDTAB */
> +	pst_cfg->vendor.cfg.feat_flag |= (1 << 1);

Oh right, this flag is missing. I'll add

  #define VIRTIO_IOMMU_PST_ARM_SMMU3_F_CD2L (1ULL << 1)

to the spec.

> +
> +	return 0;
> +}
> +
> +static int viommu_prepare_pst(struct viommu_endpoint *vdev,
> +			      struct iommu_vendor_psdtable_cfg *pst_cfg,
> +			      enum pasid_table_fmt fmt)
> +{
> +	int ret;
> +
> +	switch (fmt) {
> +	case PASID_TABLE_ARM_SMMU_V3:
> +		ret = viommu_prepare_arm_pst(vdev, pst_cfg);
> +		break;
> +	default:
> +		dev_err(vdev->dev, "unsupported PASID table format 0x%x\n", fmt);
> +		ret = -EINVAL;
> +	}
> +
> +	return ret;
> +}
> +
> +static int viommu_attach_pasid_table(struct viommu_endpoint *vdev,
> +				     struct viommu_domain *vdomain)
> +{
> +	int ret;
> +	int i, eid;
> +	enum pasid_table_fmt fmt = -1;
> +	struct virtio_iommu_probe_table_format *desc = vdev->pstf;
> +	struct virtio_iommu_req_attach_table req = {
> +		.head.type	= VIRTIO_IOMMU_T_ATTACH_TABLE,
> +		.domain		= cpu_to_le32(vdomain->id),
> +	};
> +	struct viommu_dev *viommu = vdev->viommu;
> +	struct iommu_pasid_table *tbl;
> +	struct iommu_vendor_psdtable_cfg *pst_cfg;
> +
> +	if (!viommu->has_table)
> +		return 0;
> +
> +	if (!desc)
> +		return -ENODEV;
> +
> +	/* Prepare PASID tables configuration */
> +	switch (le16_to_cpu(desc->format)) {
> +	case VIRTIO_IOMMU_FORMAT_PSTF_ARM_SMMU_V3:
> +		fmt = PASID_TABLE_ARM_SMMU_V3;
> +		break;
> +	default:
> +		dev_err(vdev->dev, "unsupported PASID table format 0x%x\n",
> +			le16_to_cpu(desc->format));
> +		return 0;
> +	}
> +
> +	if (!tbl) {
> +		tbl = iommu_register_pasid_table(fmt, viommu->dev->parent, vdomain);
> +		if (!tbl)
> +			return -ENOMEM;
> +
> +		vdomain->pasid_tbl = tbl;
> +		pst_cfg = &tbl->cfg;
> +
> +		pst_cfg->iommu_dev = viommu->dev->parent;
> +
> +		/* Prepare PASID tables info to allocate a new table */
> +		ret = viommu_prepare_pst(vdev, pst_cfg, fmt);
> +		if (ret)
> +			return ret;
> +
> +		ret = iommu_psdtable_alloc(tbl, pst_cfg);
> +		if (ret)
> +			return ret;
> +
> +		pst_cfg->iommu_dev = viommu->dev->parent;

Already set by iommu_register_pasid_table() (and needed for DMA
allocations in iommu_psdtable_alloc())

> +		pst_cfg->fmt = PASID_TABLE_ARM_SMMU_V3;

Already set above

> +
> +		ret = viommu_setup_pgtable(vdev, vdomain);
> +		if (ret) {
> +			dev_err(vdev->dev, "could not install page tables\n");
> +			goto err_free_psdtable;
> +		}
> +
> +		/* Add arch-specific configuration */
> +		ret = viommu_config_pst(pst_cfg, (void *)&req, fmt);
> +		if (ret)
> +			goto err_free_ops;
> +
> +		vdev_for_each_id(i, eid, vdev) {
> +			req.endpoint = cpu_to_le32(eid);
> +			ret = viommu_send_req_sync(viommu, &req, sizeof(req));
> +			if (ret)
> +				goto err_free_ops;
> +		}
> +	} else {
> +		/* TODO: otherwise, check for compatibility with vdev. */
> +		return -ENOSYS;
> +	}
> +
> +	dev_dbg(vdev->dev, "uses PASID table format 0x%x\n", fmt);
> +
> +	return 0;
> +
> +err_free_ops:
> +	if (vdomain->mm.ops)
> +		viommu_teardown_pgtable(vdomain);
> +err_free_psdtable:
> +	iommu_psdtable_free(tbl, &tbl->cfg);
> +
> +	return ret;
> +}
> +
>  static int viommu_attach_dev(struct iommu_domain *domain, struct device *dev)
>  {
>  	int ret = 0;
> @@ -928,6 +1213,17 @@ static int viommu_attach_dev(struct iommu_domain *domain, struct device *dev)
>  	if (vdev->vdomain)
>  		vdev->vdomain->nr_endpoints--;
>  
> +	ret = viommu_attach_pasid_table(vdev, vdomain);
> +	if (ret) {
> +		/*
> +		 * No PASID support, too bad. Perhaps we can bind a single set
> +		 * of page tables?
> +		 */
> +		ret = viommu_setup_pgtable(vdev, vdomain);

This cannot work at the moment because viommu_setup_pgtable() writes to
the non-existing pasid table. Probably best to leave this call for next
patch.

Thanks,
Jean

> +		if (ret)
> +			dev_err(vdev->dev, "could not install tables\n");
> +	}
> +
>  	if (!vdomain->mm.ops) {
>  		/* If we couldn't bind any table, use the mapping tree */
>  		ret = viommu_simple_attach(vdomain, vdev);
> @@ -948,6 +1244,10 @@ static int viommu_map(struct iommu_domain *domain, unsigned long iova,
>  	u32 flags;
>  	struct virtio_iommu_req_map map;
>  	struct viommu_domain *vdomain = to_viommu_domain(domain);
> +	struct io_pgtable_ops *ops = vdomain->mm.ops;
> +
> +	if (ops)
> +		return ops->map(ops, iova, paddr, size, prot, gfp);
>  
>  	flags = (prot & IOMMU_READ ? VIRTIO_IOMMU_MAP_F_READ : 0) |
>  		(prot & IOMMU_WRITE ? VIRTIO_IOMMU_MAP_F_WRITE : 0) |
> @@ -986,6 +1286,10 @@ static size_t viommu_unmap(struct iommu_domain *domain, unsigned long iova,
>  	size_t unmapped;
>  	struct virtio_iommu_req_unmap unmap;
>  	struct viommu_domain *vdomain = to_viommu_domain(domain);
> +	struct io_pgtable_ops *ops = vdomain->mm.ops;
> +
> +	if (ops)
> +		return ops->unmap(ops, iova, size, gather);
>  
>  	unmapped = viommu_del_mappings(vdomain, iova, size);
>  	if (unmapped < size)
> @@ -1014,6 +1318,10 @@ static phys_addr_t viommu_iova_to_phys(struct iommu_domain *domain,
>  	struct viommu_mapping *mapping;
>  	struct interval_tree_node *node;
>  	struct viommu_domain *vdomain = to_viommu_domain(domain);
> +	struct io_pgtable_ops *ops = vdomain->mm.ops;
> +
> +	if (ops)
> +		return ops->iova_to_phys(ops, iova);
>  
>  	spin_lock_irqsave(&vdomain->mappings_lock, flags);
>  	node = interval_tree_iter_first(&vdomain->mappings, iova, iova);
> @@ -1264,7 +1572,12 @@ static int viommu_probe(struct virtio_device *vdev)
>  				struct virtio_iommu_config, probe_size,
>  				&viommu->probe_size);
>  
> +	viommu->has_table = virtio_has_feature(vdev, VIRTIO_IOMMU_F_ATTACH_TABLE);
>  	viommu->has_map = virtio_has_feature(vdev, VIRTIO_IOMMU_F_MAP_UNMAP);
> +	if (!viommu->has_table && !viommu->has_map) {
> +		ret = -EINVAL;
> +		goto err_free_vqs;
> +	}
>  
>  	viommu->geometry = (struct iommu_domain_geometry) {
>  		.aperture_start	= input_start,
> @@ -1356,6 +1669,7 @@ static unsigned int features[] = {
>  	VIRTIO_IOMMU_F_DOMAIN_RANGE,
>  	VIRTIO_IOMMU_F_PROBE,
>  	VIRTIO_IOMMU_F_MMIO,
> +	VIRTIO_IOMMU_F_ATTACH_TABLE,
>  };
>  
>  static struct virtio_device_id id_table[] = {
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH RFC v1 15/15] iommu/virtio: Update fault type and reason info for viommu fault
  2021-01-15 12:13 ` [PATCH RFC v1 15/15] iommu/virtio: Update fault type and reason info for viommu fault Vivek Gautam
@ 2021-03-03 17:25   ` Jean-Philippe Brucker
  2021-03-12 13:09     ` Vivek Kumar Gautam
  0 siblings, 1 reply; 44+ messages in thread
From: Jean-Philippe Brucker @ 2021-03-03 17:25 UTC (permalink / raw)
  To: Vivek Gautam
  Cc: linux-kernel, linux-arm-kernel, iommu, virtualization, joro,
	will.deacon, mst, robin.murphy, eric.auger, alex.williamson,
	kevin.tian, jacob.jun.pan, yi.l.liu, lorenzo.pieralisi,
	shameerali.kolothum.thodi

On Fri, Jan 15, 2021 at 05:43:42PM +0530, Vivek Gautam wrote:
> Fault type information can tell about a page request fault or
> an unreceoverable fault, and further additions to fault reasons
> and the related PASID information can help in handling faults
> efficiently.
> 
> Signed-off-by: Vivek Gautam <vivek.gautam@arm.com>
> Cc: Joerg Roedel <joro@8bytes.org>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Michael S. Tsirkin <mst@redhat.com>
> Cc: Robin Murphy <robin.murphy@arm.com>
> Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
> Cc: Eric Auger <eric.auger@redhat.com>
> Cc: Alex Williamson <alex.williamson@redhat.com>
> Cc: Kevin Tian <kevin.tian@intel.com>
> Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
> Cc: Liu Yi L <yi.l.liu@intel.com>
> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
> ---
>  drivers/iommu/virtio-iommu.c      | 27 +++++++++++++++++++++++++--
>  include/uapi/linux/virtio_iommu.h | 13 ++++++++++++-
>  2 files changed, 37 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c
> index 9cc3d35125e9..10ef9e98214a 100644
> --- a/drivers/iommu/virtio-iommu.c
> +++ b/drivers/iommu/virtio-iommu.c
> @@ -652,9 +652,16 @@ static int viommu_fault_handler(struct viommu_dev *viommu,
>  	char *reason_str;
>  
>  	u8 reason	= fault->reason;
> +	u16 type	= fault->flt_type;
>  	u32 flags	= le32_to_cpu(fault->flags);
>  	u32 endpoint	= le32_to_cpu(fault->endpoint);
>  	u64 address	= le64_to_cpu(fault->address);
> +	u32 pasid	= le32_to_cpu(fault->pasid);
> +
> +	if (type == VIRTIO_IOMMU_FAULT_F_PAGE_REQ) {
> +		dev_info(viommu->dev, "Page request fault - unhandled\n");
> +		return 0;
> +	}
>  
>  	switch (reason) {
>  	case VIRTIO_IOMMU_FAULT_R_DOMAIN:
> @@ -663,6 +670,21 @@ static int viommu_fault_handler(struct viommu_dev *viommu,
>  	case VIRTIO_IOMMU_FAULT_R_MAPPING:
>  		reason_str = "page";
>  		break;
> +	case VIRTIO_IOMMU_FAULT_R_WALK_EABT:
> +		reason_str = "page walk external abort";
> +		break;
> +	case VIRTIO_IOMMU_FAULT_R_PTE_FETCH:
> +		reason_str = "pte fetch";
> +		break;
> +	case VIRTIO_IOMMU_FAULT_R_PERMISSION:
> +		reason_str = "permission";
> +		break;
> +	case VIRTIO_IOMMU_FAULT_R_ACCESS:
> +		reason_str = "access";
> +		break;
> +	case VIRTIO_IOMMU_FAULT_R_OOR_ADDRESS:
> +		reason_str = "output address";
> +		break;
>  	case VIRTIO_IOMMU_FAULT_R_UNKNOWN:
>  	default:
>  		reason_str = "unknown";
> @@ -671,8 +693,9 @@ static int viommu_fault_handler(struct viommu_dev *viommu,
>  
>  	/* TODO: find EP by ID and report_iommu_fault */
>  	if (flags & VIRTIO_IOMMU_FAULT_F_ADDRESS)
> -		dev_err_ratelimited(viommu->dev, "%s fault from EP %u at %#llx [%s%s%s]\n",
> -				    reason_str, endpoint, address,
> +		dev_err_ratelimited(viommu->dev,
> +				    "%s fault from EP %u PASID %u at %#llx [%s%s%s]\n",
> +				    reason_str, endpoint, pasid, address,
>  				    flags & VIRTIO_IOMMU_FAULT_F_READ ? "R" : "",
>  				    flags & VIRTIO_IOMMU_FAULT_F_WRITE ? "W" : "",
>  				    flags & VIRTIO_IOMMU_FAULT_F_EXEC ? "X" : "");
> diff --git a/include/uapi/linux/virtio_iommu.h b/include/uapi/linux/virtio_iommu.h
> index 608c8d642e1f..a537d82777f7 100644
> --- a/include/uapi/linux/virtio_iommu.h
> +++ b/include/uapi/linux/virtio_iommu.h
> @@ -290,19 +290,30 @@ struct virtio_iommu_req_invalidate {
>  #define VIRTIO_IOMMU_FAULT_R_UNKNOWN		0
>  #define VIRTIO_IOMMU_FAULT_R_DOMAIN		1
>  #define VIRTIO_IOMMU_FAULT_R_MAPPING		2
> +#define VIRTIO_IOMMU_FAULT_R_WALK_EABT		3
> +#define VIRTIO_IOMMU_FAULT_R_PTE_FETCH		4
> +#define VIRTIO_IOMMU_FAULT_R_PERMISSION		5
> +#define VIRTIO_IOMMU_FAULT_R_ACCESS		6
> +#define VIRTIO_IOMMU_FAULT_R_OOR_ADDRESS	7
>  
>  #define VIRTIO_IOMMU_FAULT_F_READ		(1 << 0)
>  #define VIRTIO_IOMMU_FAULT_F_WRITE		(1 << 1)
>  #define VIRTIO_IOMMU_FAULT_F_EXEC		(1 << 2)
>  #define VIRTIO_IOMMU_FAULT_F_ADDRESS		(1 << 8)
>  
> +#define VIRTIO_IOMMU_FAULT_F_DMA_UNRECOV	1
> +#define VIRTIO_IOMMU_FAULT_F_PAGE_REQ		2

Currently all reported faults are unrecoverable, so to be consistent
DMA_UNRECOV should be 0. But I'd prefer having just a new "page request"
flag in the flags field, instead of the flt_type field.

For page requests we'll also need a 16-bit fault ID field to store the PRI
"page request group index" or the stall "stag". "last" and "privileged"
flags as well, to match the PRI page request. And a new command to
complete a page fault.

> +
>  struct virtio_iommu_fault {
>  	__u8					reason;
> -	__u8					reserved[3];
> +	__le16					flt_type;
> +	__u8					reserved;
>  	__le32					flags;
>  	__le32					endpoint;
>  	__u8					reserved2[4];

Why not replace reserved2 with the pasid?  It fits perfectly :)

Thanks,
Jean

>  	__le64					address;
> +	__le32					pasid;
> +	__u8					reserved3[4];
>  };
>  
>  #endif
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH RFC v1 12/15] iommu/virtio: Add support for INVALIDATE request
  2021-01-15 12:13 ` [PATCH RFC v1 12/15] iommu/virtio: Add support for INVALIDATE request Vivek Gautam
@ 2021-03-03 18:28   ` Jacob Pan
  2021-03-04  5:58     ` Tian, Kevin
  0 siblings, 1 reply; 44+ messages in thread
From: Jacob Pan @ 2021-03-03 18:28 UTC (permalink / raw)
  To: Vivek Gautam
  Cc: linux-kernel, linux-arm-kernel, iommu, virtualization, joro,
	will.deacon, mst, robin.murphy, jean-philippe, eric.auger,
	alex.williamson, kevin.tian, yi.l.liu, lorenzo.pieralisi,
	shameerali.kolothum.thodi, jacob.jun.pan

Hi Vivek,

On Fri, 15 Jan 2021 17:43:39 +0530, Vivek Gautam <vivek.gautam@arm.com>
wrote:

> From: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
> 
> Add support for tlb invalidation ops that can send invalidation
> requests to back-end virtio-iommu when stage-1 page tables are
> supported.
> 
Just curious if it possible to reuse the iommu uapi for invalidation and others.
When we started out designing the iommu uapi, the intention was to support
both emulated and virtio iommu.

> Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
> [Vivek: Refactoring the iommu_flush_ops, and adding only one pasid sync
>         op that's needed with current iommu-pasid-table infrastructure.
> 	Also updating uapi defines as required by latest changes]
> Signed-off-by: Vivek Gautam <vivek.gautam@arm.com>
> Cc: Joerg Roedel <joro@8bytes.org>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Michael S. Tsirkin <mst@redhat.com>
> Cc: Robin Murphy <robin.murphy@arm.com>
> Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
> Cc: Eric Auger <eric.auger@redhat.com>
> Cc: Alex Williamson <alex.williamson@redhat.com>
> Cc: Kevin Tian <kevin.tian@intel.com>
> Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
> Cc: Liu Yi L <yi.l.liu@intel.com>
> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
> ---
>  drivers/iommu/virtio-iommu.c | 95 ++++++++++++++++++++++++++++++++++++
>  1 file changed, 95 insertions(+)
> 
> diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c
> index ae5dfd3f8269..004ea94e3731 100644
> --- a/drivers/iommu/virtio-iommu.c
> +++ b/drivers/iommu/virtio-iommu.c
> @@ -13,6 +13,7 @@
>  #include <linux/freezer.h>
>  #include <linux/interval_tree.h>
>  #include <linux/iommu.h>
> +#include <linux/io-pgtable.h>
>  #include <linux/module.h>
>  #include <linux/of_iommu.h>
>  #include <linux/of_platform.h>
> @@ -63,6 +64,8 @@ struct viommu_mapping {
>  };
>  
>  struct viommu_mm {
> +	int				pasid;
> +	u64				archid;
>  	struct io_pgtable_ops		*ops;
>  	struct viommu_domain		*domain;
>  };
> @@ -692,6 +695,98 @@ static void viommu_event_handler(struct virtqueue
> *vq) virtqueue_kick(vq);
>  }
>  
> +/* PASID and pgtable APIs */
> +
> +static void __viommu_flush_pasid_tlb_all(struct viommu_domain *vdomain,
> +					 int pasid, u64 arch_id, int
> type) +{
> +	struct virtio_iommu_req_invalidate req = {
> +		.head.type	= VIRTIO_IOMMU_T_INVALIDATE,
> +		.inv_gran	=
> cpu_to_le32(VIRTIO_IOMMU_INVAL_G_PASID),
> +		.flags		=
> cpu_to_le32(VIRTIO_IOMMU_INVAL_F_PASID),
> +		.inv_type	= cpu_to_le32(type),
> +
> +		.domain		= cpu_to_le32(vdomain->id),
> +		.pasid		= cpu_to_le32(pasid),
> +		.archid		= cpu_to_le64(arch_id),
> +	};
> +
> +	if (viommu_send_req_sync(vdomain->viommu, &req, sizeof(req)))
> +		pr_debug("could not send invalidate request\n");
> +}
> +
> +static void viommu_flush_tlb_add(struct iommu_iotlb_gather *gather,
> +				 unsigned long iova, size_t granule,
> +				 void *cookie)
> +{
> +	struct viommu_mm *viommu_mm = cookie;
> +	struct viommu_domain *vdomain = viommu_mm->domain;
> +	struct iommu_domain *domain = &vdomain->domain;
> +
> +	iommu_iotlb_gather_add_page(domain, gather, iova, granule);
> +}
> +
> +static void viommu_flush_tlb_walk(unsigned long iova, size_t size,
> +				  size_t granule, void *cookie)
> +{
> +	struct viommu_mm *viommu_mm = cookie;
> +	struct viommu_domain *vdomain = viommu_mm->domain;
> +	struct virtio_iommu_req_invalidate req = {
> +		.head.type	= VIRTIO_IOMMU_T_INVALIDATE,
> +		.inv_gran	= cpu_to_le32(VIRTIO_IOMMU_INVAL_G_VA),
> +		.inv_type	= cpu_to_le32(VIRTIO_IOMMU_INV_T_IOTLB),
> +		.flags		=
> cpu_to_le32(VIRTIO_IOMMU_INVAL_F_ARCHID), +
> +		.domain		= cpu_to_le32(vdomain->id),
> +		.pasid		= cpu_to_le32(viommu_mm->pasid),
> +		.archid		= cpu_to_le64(viommu_mm->archid),
> +		.virt_start	= cpu_to_le64(iova),
> +		.nr_pages	= cpu_to_le64(size / granule),
> +		.granule	= ilog2(granule),
> +	};
> +
> +	if (viommu_add_req(vdomain->viommu, &req, sizeof(req)))
> +		pr_debug("could not add invalidate request\n");
> +}
> +
> +static void viommu_flush_tlb_all(void *cookie)
> +{
> +	struct viommu_mm *viommu_mm = cookie;
> +
> +	if (!viommu_mm->archid)
> +		return;
> +
> +	__viommu_flush_pasid_tlb_all(viommu_mm->domain, viommu_mm->pasid,
> +				     viommu_mm->archid,
> +				     VIRTIO_IOMMU_INV_T_IOTLB);
> +}
> +
> +static struct iommu_flush_ops viommu_flush_ops = {
> +	.tlb_flush_all		= viommu_flush_tlb_all,
> +	.tlb_flush_walk		= viommu_flush_tlb_walk,
> +	.tlb_add_page		= viommu_flush_tlb_add,
> +};
> +
> +static void viommu_flush_pasid(void *cookie, int pasid, bool leaf)
> +{
> +	struct viommu_domain *vdomain = cookie;
> +	struct virtio_iommu_req_invalidate req = {
> +		.head.type	= VIRTIO_IOMMU_T_INVALIDATE,
> +		.inv_gran	=
> cpu_to_le32(VIRTIO_IOMMU_INVAL_G_PASID),
> +		.inv_type	= cpu_to_le32(VIRTIO_IOMMU_INV_T_PASID),
> +		.flags		=
> cpu_to_le32(VIRTIO_IOMMU_INVAL_F_PASID), +
> +		.domain		= cpu_to_le32(vdomain->id),
> +		.pasid		= cpu_to_le32(pasid),
> +	};
> +
> +	if (leaf)
> +		req.flags	|=
> cpu_to_le32(VIRTIO_IOMMU_INVAL_F_LEAF); +
> +	if (viommu_send_req_sync(vdomain->viommu, &req, sizeof(req)))
> +		pr_debug("could not send invalidate request\n");
> +}
> +
>  /* IOMMU API */
>  
>  static struct iommu_domain *viommu_domain_alloc(unsigned type)


Thanks,

Jacob

^ permalink raw reply	[flat|nested] 44+ messages in thread

* RE: [PATCH RFC v1 12/15] iommu/virtio: Add support for INVALIDATE request
  2021-03-03 18:28   ` Jacob Pan
@ 2021-03-04  5:58     ` Tian, Kevin
  2021-03-04  6:16       ` Vivek Kumar Gautam
  0 siblings, 1 reply; 44+ messages in thread
From: Tian, Kevin @ 2021-03-04  5:58 UTC (permalink / raw)
  To: Jacob Pan, Vivek Gautam
  Cc: linux-kernel, linux-arm-kernel, iommu, virtualization, joro,
	will.deacon, mst, robin.murphy, jean-philippe, eric.auger,
	alex.williamson, Liu, Yi L, lorenzo.pieralisi,
	shameerali.kolothum.thodi

> From: Jacob Pan <jacob.jun.pan@linux.intel.com>
> Sent: Thursday, March 4, 2021 2:29 AM
> 
> Hi Vivek,
> 
> On Fri, 15 Jan 2021 17:43:39 +0530, Vivek Gautam <vivek.gautam@arm.com>
> wrote:
> 
> > From: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
> >
> > Add support for tlb invalidation ops that can send invalidation
> > requests to back-end virtio-iommu when stage-1 page tables are
> > supported.
> >
> Just curious if it possible to reuse the iommu uapi for invalidation and others.
> When we started out designing the iommu uapi, the intention was to support
> both emulated and virtio iommu.

IIUC this patch is about the protocol between virtio-iommu frontend and backend.
After the virtio-iommu backend receives invalidation ops, it then needs to
forward the request to the host IOMMU driver through the existing iommu
uapi that you referred to, as a emulated VT-d or SMMU would do.

Thanks
Kevin

> 
> > Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
> > [Vivek: Refactoring the iommu_flush_ops, and adding only one pasid sync
> >         op that's needed with current iommu-pasid-table infrastructure.
> > 	Also updating uapi defines as required by latest changes]
> > Signed-off-by: Vivek Gautam <vivek.gautam@arm.com>
> > Cc: Joerg Roedel <joro@8bytes.org>
> > Cc: Will Deacon <will.deacon@arm.com>
> > Cc: Michael S. Tsirkin <mst@redhat.com>
> > Cc: Robin Murphy <robin.murphy@arm.com>
> > Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
> > Cc: Eric Auger <eric.auger@redhat.com>
> > Cc: Alex Williamson <alex.williamson@redhat.com>
> > Cc: Kevin Tian <kevin.tian@intel.com>
> > Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
> > Cc: Liu Yi L <yi.l.liu@intel.com>
> > Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> > Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
> > ---
> >  drivers/iommu/virtio-iommu.c | 95
> ++++++++++++++++++++++++++++++++++++
> >  1 file changed, 95 insertions(+)
> >
> > diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c
> > index ae5dfd3f8269..004ea94e3731 100644
> > --- a/drivers/iommu/virtio-iommu.c
> > +++ b/drivers/iommu/virtio-iommu.c
> > @@ -13,6 +13,7 @@
> >  #include <linux/freezer.h>
> >  #include <linux/interval_tree.h>
> >  #include <linux/iommu.h>
> > +#include <linux/io-pgtable.h>
> >  #include <linux/module.h>
> >  #include <linux/of_iommu.h>
> >  #include <linux/of_platform.h>
> > @@ -63,6 +64,8 @@ struct viommu_mapping {
> >  };
> >
> >  struct viommu_mm {
> > +	int				pasid;
> > +	u64				archid;
> >  	struct io_pgtable_ops		*ops;
> >  	struct viommu_domain		*domain;
> >  };
> > @@ -692,6 +695,98 @@ static void viommu_event_handler(struct
> virtqueue
> > *vq) virtqueue_kick(vq);
> >  }
> >
> > +/* PASID and pgtable APIs */
> > +
> > +static void __viommu_flush_pasid_tlb_all(struct viommu_domain
> *vdomain,
> > +					 int pasid, u64 arch_id, int
> > type) +{
> > +	struct virtio_iommu_req_invalidate req = {
> > +		.head.type	= VIRTIO_IOMMU_T_INVALIDATE,
> > +		.inv_gran	=
> > cpu_to_le32(VIRTIO_IOMMU_INVAL_G_PASID),
> > +		.flags		=
> > cpu_to_le32(VIRTIO_IOMMU_INVAL_F_PASID),
> > +		.inv_type	= cpu_to_le32(type),
> > +
> > +		.domain		= cpu_to_le32(vdomain->id),
> > +		.pasid		= cpu_to_le32(pasid),
> > +		.archid		= cpu_to_le64(arch_id),
> > +	};
> > +
> > +	if (viommu_send_req_sync(vdomain->viommu, &req, sizeof(req)))
> > +		pr_debug("could not send invalidate request\n");
> > +}
> > +
> > +static void viommu_flush_tlb_add(struct iommu_iotlb_gather *gather,
> > +				 unsigned long iova, size_t granule,
> > +				 void *cookie)
> > +{
> > +	struct viommu_mm *viommu_mm = cookie;
> > +	struct viommu_domain *vdomain = viommu_mm->domain;
> > +	struct iommu_domain *domain = &vdomain->domain;
> > +
> > +	iommu_iotlb_gather_add_page(domain, gather, iova, granule);
> > +}
> > +
> > +static void viommu_flush_tlb_walk(unsigned long iova, size_t size,
> > +				  size_t granule, void *cookie)
> > +{
> > +	struct viommu_mm *viommu_mm = cookie;
> > +	struct viommu_domain *vdomain = viommu_mm->domain;
> > +	struct virtio_iommu_req_invalidate req = {
> > +		.head.type	= VIRTIO_IOMMU_T_INVALIDATE,
> > +		.inv_gran	= cpu_to_le32(VIRTIO_IOMMU_INVAL_G_VA),
> > +		.inv_type	=
> cpu_to_le32(VIRTIO_IOMMU_INV_T_IOTLB),
> > +		.flags		=
> > cpu_to_le32(VIRTIO_IOMMU_INVAL_F_ARCHID), +
> > +		.domain		= cpu_to_le32(vdomain->id),
> > +		.pasid		= cpu_to_le32(viommu_mm->pasid),
> > +		.archid		= cpu_to_le64(viommu_mm->archid),
> > +		.virt_start	= cpu_to_le64(iova),
> > +		.nr_pages	= cpu_to_le64(size / granule),
> > +		.granule	= ilog2(granule),
> > +	};
> > +
> > +	if (viommu_add_req(vdomain->viommu, &req, sizeof(req)))
> > +		pr_debug("could not add invalidate request\n");
> > +}
> > +
> > +static void viommu_flush_tlb_all(void *cookie)
> > +{
> > +	struct viommu_mm *viommu_mm = cookie;
> > +
> > +	if (!viommu_mm->archid)
> > +		return;
> > +
> > +	__viommu_flush_pasid_tlb_all(viommu_mm->domain,
> viommu_mm->pasid,
> > +				     viommu_mm->archid,
> > +				     VIRTIO_IOMMU_INV_T_IOTLB);
> > +}
> > +
> > +static struct iommu_flush_ops viommu_flush_ops = {
> > +	.tlb_flush_all		= viommu_flush_tlb_all,
> > +	.tlb_flush_walk		= viommu_flush_tlb_walk,
> > +	.tlb_add_page		= viommu_flush_tlb_add,
> > +};
> > +
> > +static void viommu_flush_pasid(void *cookie, int pasid, bool leaf)
> > +{
> > +	struct viommu_domain *vdomain = cookie;
> > +	struct virtio_iommu_req_invalidate req = {
> > +		.head.type	= VIRTIO_IOMMU_T_INVALIDATE,
> > +		.inv_gran	=
> > cpu_to_le32(VIRTIO_IOMMU_INVAL_G_PASID),
> > +		.inv_type	=
> cpu_to_le32(VIRTIO_IOMMU_INV_T_PASID),
> > +		.flags		=
> > cpu_to_le32(VIRTIO_IOMMU_INVAL_F_PASID), +
> > +		.domain		= cpu_to_le32(vdomain->id),
> > +		.pasid		= cpu_to_le32(pasid),
> > +	};
> > +
> > +	if (leaf)
> > +		req.flags	|=
> > cpu_to_le32(VIRTIO_IOMMU_INVAL_F_LEAF); +
> > +	if (viommu_send_req_sync(vdomain->viommu, &req, sizeof(req)))
> > +		pr_debug("could not send invalidate request\n");
> > +}
> > +
> >  /* IOMMU API */
> >
> >  static struct iommu_domain *viommu_domain_alloc(unsigned type)
> 
> 
> Thanks,
> 
> Jacob

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH RFC v1 12/15] iommu/virtio: Add support for INVALIDATE request
  2021-03-04  5:58     ` Tian, Kevin
@ 2021-03-04  6:16       ` Vivek Kumar Gautam
  0 siblings, 0 replies; 44+ messages in thread
From: Vivek Kumar Gautam @ 2021-03-04  6:16 UTC (permalink / raw)
  To: Tian, Kevin, Jacob Pan
  Cc: linux-kernel, linux-arm-kernel, iommu, virtualization, joro,
	will.deacon, mst, robin.murphy, jean-philippe, eric.auger,
	alex.williamson, Liu, Yi L, lorenzo.pieralisi,
	shameerali.kolothum.thodi

Hi Jacob, Kevin,


On 3/4/21 11:28 AM, Tian, Kevin wrote:
>> From: Jacob Pan <jacob.jun.pan@linux.intel.com>
>> Sent: Thursday, March 4, 2021 2:29 AM
>>
>> Hi Vivek,
>>
>> On Fri, 15 Jan 2021 17:43:39 +0530, Vivek Gautam <vivek.gautam@arm.com>
>> wrote:
>>
>>> From: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
>>>
>>> Add support for tlb invalidation ops that can send invalidation
>>> requests to back-end virtio-iommu when stage-1 page tables are
>>> supported.
>>>
>> Just curious if it possible to reuse the iommu uapi for invalidation and others.
>> When we started out designing the iommu uapi, the intention was to support
>> both emulated and virtio iommu.
> 
> IIUC this patch is about the protocol between virtio-iommu frontend and backend.
> After the virtio-iommu backend receives invalidation ops, it then needs to
> forward the request to the host IOMMU driver through the existing iommu
> uapi that you referred to, as a emulated VT-d or SMMU would do.

Thanks a lot for looking at the patch.

Yes this patch is to provide the front-end virtio interface for 
invalidation requests during map/unmap and when flushing the pasid 
tables when virtio-iommu requested pasid table (in other words cd tables 
for arm-smmu-v3) from the iommu-pasid-table library.
The kvmtool back-end virtio driver forwards these requests to vfio 
driver which then makes use of iommu uapi to finally request host iommu 
driver for handling these invalidations.

Regards
Vivek

> 
> Thanks
> Kevin
> 
>>
>>> Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
>>> [Vivek: Refactoring the iommu_flush_ops, and adding only one pasid sync
>>>          op that's needed with current iommu-pasid-table infrastructure.
>>> 	Also updating uapi defines as required by latest changes]
>>> Signed-off-by: Vivek Gautam <vivek.gautam@arm.com>
>>> Cc: Joerg Roedel <joro@8bytes.org>
>>> Cc: Will Deacon <will.deacon@arm.com>
>>> Cc: Michael S. Tsirkin <mst@redhat.com>
>>> Cc: Robin Murphy <robin.murphy@arm.com>
>>> Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
>>> Cc: Eric Auger <eric.auger@redhat.com>
>>> Cc: Alex Williamson <alex.williamson@redhat.com>
>>> Cc: Kevin Tian <kevin.tian@intel.com>
>>> Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
>>> Cc: Liu Yi L <yi.l.liu@intel.com>
>>> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
>>> Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
>>> ---
>>>   drivers/iommu/virtio-iommu.c | 95
>> ++++++++++++++++++++++++++++++++++++
>>>   1 file changed, 95 insertions(+)
>>>
>>> diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c
>>> index ae5dfd3f8269..004ea94e3731 100644
>>> --- a/drivers/iommu/virtio-iommu.c
>>> +++ b/drivers/iommu/virtio-iommu.c
>>> @@ -13,6 +13,7 @@
>>>   #include <linux/freezer.h>
>>>   #include <linux/interval_tree.h>
>>>   #include <linux/iommu.h>
>>> +#include <linux/io-pgtable.h>
>>>   #include <linux/module.h>
>>>   #include <linux/of_iommu.h>
>>>   #include <linux/of_platform.h>
>>> @@ -63,6 +64,8 @@ struct viommu_mapping {
>>>   };
>>>
>>>   struct viommu_mm {
>>> +	int				pasid;
>>> +	u64				archid;
>>>   	struct io_pgtable_ops		*ops;
>>>   	struct viommu_domain		*domain;
>>>   };
>>> @@ -692,6 +695,98 @@ static void viommu_event_handler(struct
>> virtqueue
>>> *vq) virtqueue_kick(vq);
>>>   }
>>>
>>> +/* PASID and pgtable APIs */
>>> +
>>> +static void __viommu_flush_pasid_tlb_all(struct viommu_domain
>> *vdomain,
>>> +					 int pasid, u64 arch_id, int
>>> type) +{
>>> +	struct virtio_iommu_req_invalidate req = {
>>> +		.head.type	= VIRTIO_IOMMU_T_INVALIDATE,
>>> +		.inv_gran	=
>>> cpu_to_le32(VIRTIO_IOMMU_INVAL_G_PASID),
>>> +		.flags		=
>>> cpu_to_le32(VIRTIO_IOMMU_INVAL_F_PASID),
>>> +		.inv_type	= cpu_to_le32(type),
>>> +
>>> +		.domain		= cpu_to_le32(vdomain->id),
>>> +		.pasid		= cpu_to_le32(pasid),
>>> +		.archid		= cpu_to_le64(arch_id),
>>> +	};
>>> +
>>> +	if (viommu_send_req_sync(vdomain->viommu, &req, sizeof(req)))
>>> +		pr_debug("could not send invalidate request\n");
>>> +}
>>> +
>>> +static void viommu_flush_tlb_add(struct iommu_iotlb_gather *gather,
>>> +				 unsigned long iova, size_t granule,
>>> +				 void *cookie)
>>> +{
>>> +	struct viommu_mm *viommu_mm = cookie;
>>> +	struct viommu_domain *vdomain = viommu_mm->domain;
>>> +	struct iommu_domain *domain = &vdomain->domain;
>>> +
>>> +	iommu_iotlb_gather_add_page(domain, gather, iova, granule);
>>> +}
>>> +
>>> +static void viommu_flush_tlb_walk(unsigned long iova, size_t size,
>>> +				  size_t granule, void *cookie)
>>> +{
>>> +	struct viommu_mm *viommu_mm = cookie;
>>> +	struct viommu_domain *vdomain = viommu_mm->domain;
>>> +	struct virtio_iommu_req_invalidate req = {
>>> +		.head.type	= VIRTIO_IOMMU_T_INVALIDATE,
>>> +		.inv_gran	= cpu_to_le32(VIRTIO_IOMMU_INVAL_G_VA),
>>> +		.inv_type	=
>> cpu_to_le32(VIRTIO_IOMMU_INV_T_IOTLB),
>>> +		.flags		=
>>> cpu_to_le32(VIRTIO_IOMMU_INVAL_F_ARCHID), +
>>> +		.domain		= cpu_to_le32(vdomain->id),
>>> +		.pasid		= cpu_to_le32(viommu_mm->pasid),
>>> +		.archid		= cpu_to_le64(viommu_mm->archid),
>>> +		.virt_start	= cpu_to_le64(iova),
>>> +		.nr_pages	= cpu_to_le64(size / granule),
>>> +		.granule	= ilog2(granule),
>>> +	};
>>> +
>>> +	if (viommu_add_req(vdomain->viommu, &req, sizeof(req)))
>>> +		pr_debug("could not add invalidate request\n");
>>> +}
>>> +
>>> +static void viommu_flush_tlb_all(void *cookie)
>>> +{
>>> +	struct viommu_mm *viommu_mm = cookie;
>>> +
>>> +	if (!viommu_mm->archid)
>>> +		return;
>>> +
>>> +	__viommu_flush_pasid_tlb_all(viommu_mm->domain,
>> viommu_mm->pasid,
>>> +				     viommu_mm->archid,
>>> +				     VIRTIO_IOMMU_INV_T_IOTLB);
>>> +}
>>> +
>>> +static struct iommu_flush_ops viommu_flush_ops = {
>>> +	.tlb_flush_all		= viommu_flush_tlb_all,
>>> +	.tlb_flush_walk		= viommu_flush_tlb_walk,
>>> +	.tlb_add_page		= viommu_flush_tlb_add,
>>> +};
>>> +
>>> +static void viommu_flush_pasid(void *cookie, int pasid, bool leaf)
>>> +{
>>> +	struct viommu_domain *vdomain = cookie;
>>> +	struct virtio_iommu_req_invalidate req = {
>>> +		.head.type	= VIRTIO_IOMMU_T_INVALIDATE,
>>> +		.inv_gran	=
>>> cpu_to_le32(VIRTIO_IOMMU_INVAL_G_PASID),
>>> +		.inv_type	=
>> cpu_to_le32(VIRTIO_IOMMU_INV_T_PASID),
>>> +		.flags		=
>>> cpu_to_le32(VIRTIO_IOMMU_INVAL_F_PASID), +
>>> +		.domain		= cpu_to_le32(vdomain->id),
>>> +		.pasid		= cpu_to_le32(pasid),
>>> +	};
>>> +
>>> +	if (leaf)
>>> +		req.flags	|=
>>> cpu_to_le32(VIRTIO_IOMMU_INVAL_F_LEAF); +
>>> +	if (viommu_send_req_sync(vdomain->viommu, &req, sizeof(req)))
>>> +		pr_debug("could not send invalidate request\n");
>>> +}
>>> +
>>>   /* IOMMU API */
>>>
>>>   static struct iommu_domain *viommu_domain_alloc(unsigned type)
>>
>>
>> Thanks,
>>
>> Jacob

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH RFC v1 04/15] iommu/arm-smmu-v3: Update CD base address info for user-space
  2021-03-03 17:14   ` Jean-Philippe Brucker
@ 2021-03-12 12:31     ` Vivek Kumar Gautam
  0 siblings, 0 replies; 44+ messages in thread
From: Vivek Kumar Gautam @ 2021-03-12 12:31 UTC (permalink / raw)
  To: Jean-Philippe Brucker
  Cc: linux-kernel, linux-arm-kernel, iommu, virtualization, joro,
	will.deacon, mst, robin.murphy, eric.auger, alex.williamson,
	kevin.tian, jacob.jun.pan, yi.l.liu, lorenzo.pieralisi,
	shameerali.kolothum.thodi

Hi Jean,

On 3/3/21 10:44 PM, Jean-Philippe Brucker wrote:
> On Fri, Jan 15, 2021 at 05:43:31PM +0530, Vivek Gautam wrote:
>> Update base address information in vendor pasid table info to pass that
>> to user-space for stage1 table management.
>>
>> Signed-off-by: Vivek Gautam <vivek.gautam@arm.com>
>> Cc: Joerg Roedel <joro@8bytes.org>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Cc: Robin Murphy <robin.murphy@arm.com>
>> Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
>> Cc: Eric Auger <eric.auger@redhat.com>
>> Cc: Alex Williamson <alex.williamson@redhat.com>
>> Cc: Kevin Tian <kevin.tian@intel.com>
>> Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
>> Cc: Liu Yi L <yi.l.liu@intel.com>
>> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
>> Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
>> ---
>>   drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c | 6 ++++++
>>   1 file changed, 6 insertions(+)
>>
>> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c
>> index 8a7187534706..ec37476c8d09 100644
>> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c
>> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c
>> @@ -55,6 +55,9 @@ static __le64 *arm_smmu_get_cd_ptr(struct iommu_vendor_psdtable_cfg *pst_cfg,
>>   		if (arm_smmu_alloc_cd_leaf_table(dev, l1_desc))
>>   			return NULL;
>>   
>> +		if (s1cfg->s1fmt == STRTAB_STE_0_S1FMT_LINEAR)
>> +			pst_cfg->base = l1_desc->l2ptr_dma;
>> +
> 
> This isn't the right place, because this path allocates second-level
> tables for two-level tables. I don't think we need pst_cfg->base at all,
> because for both linear and two-level tables, the base pointer is in
> cdcfg->cdtab_dma, which can be read directly.

Sure, will remove this.

> 
> Thanks,
> Jean
> 
>>   		l1ptr = cdcfg->cdtab + idx * CTXDESC_L1_DESC_DWORDS;
>>   		arm_smmu_write_cd_l1_desc(l1ptr, l1_desc);
>>   		/* An invalid L1CD can be cached */
>> @@ -211,6 +214,9 @@ static int arm_smmu_alloc_cd_tables(struct iommu_vendor_psdtable_cfg *pst_cfg)
>>   		goto err_free_l1;
>>   	}
>>   
>> +	if (s1cfg->s1fmt == STRTAB_STE_0_S1FMT_64K_L2)
>> +		pst_cfg->base = cdcfg->cdtab_dma;
>> +
>>   	return 0;
>>   
>>   err_free_l1:
>> -- 
>> 2.17.1
>>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH RFC v1 02/15] iommu: Add a simple PASID table library
  2021-03-03 17:11   ` Jean-Philippe Brucker
@ 2021-03-12 12:47     ` Vivek Kumar Gautam
  2021-03-29 16:25       ` Jean-Philippe Brucker
  0 siblings, 1 reply; 44+ messages in thread
From: Vivek Kumar Gautam @ 2021-03-12 12:47 UTC (permalink / raw)
  To: Jean-Philippe Brucker
  Cc: linux-kernel, linux-arm-kernel, iommu, virtualization, joro,
	will.deacon, mst, robin.murphy, eric.auger, alex.williamson,
	kevin.tian, jacob.jun.pan, yi.l.liu, lorenzo.pieralisi,
	shameerali.kolothum.thodi

Hi Jean,


On 3/3/21 10:41 PM, Jean-Philippe Brucker wrote:
> Hi Vivek,
> 
> Thanks again for working on this. I have a few comments but it looks
> sensible overall.

Thanks a lot for reviewing the patch-series. Please find my responses 
inline below.

> 
> Regarding the overall design, I was initially assigning page directories
> instead of whole PASID tables, which would simplify the driver and host
> implementation. A major complication, however, is SMMUv3 accesses PASID
> tables using a guest-physical address, so there is a messy negotiation
> needed between host and guest when the host needs to allocate PASID
> tables. Plus vSMMU needs PASID table assignment, so that's what the host
> driver will implement.

By assigning the page directories, you mean setting up just the stage-1 
page table ops, and passing that information to the host using ATTACH_TABLE?
Right now when using kvmtool, the struct iommu_pasid_table_config is 
populated with the correct information, and this whole memory is mapped 
between host and guest by creating a mem bank using 
kvm__for_each_mem_bank().
Did I get you or did I fail terribly in understanding the point you are 
making here?
If it helps, I will publish my kvmtool branch.

> 
> On Fri, Jan 15, 2021 at 05:43:29PM +0530, Vivek Gautam wrote:
>> Add a small API in iommu subsystem to handle PASID table allocation
>> requests from different consumer drivers, such as a paravirtualized
>> iommu driver. The API provides ops for allocating and freeing PASID
>> table, writing to it and managing the table caches.
>>
>> This library also provides for registering a vendor API that attaches
>> to these ops. The vendor APIs would eventually perform arch level
>> implementations for these PASID tables.
> 
> Although Arm might be the only vendor to ever use this, I think the
> abstraction makes sense and isn't too invasive. Even if we called directly
> into the SMMU driver from the virtio one, we'd still need patch 3 and
> separate TLB invalidations ops.

Right, the idea was to make users of iommu-pasid-table - virtio-iommu or 
the arm-smmu-v3 - consistent. I also noticed that the whole process of 
allocating the pasid tables (or cd tables) and populating them with 
stage-1 page tables in viommu is also in-line with how things are in 
arm-smmu-v3 or atleast that's how the design can be in general - 
allocate pasid_table, and program stage-1 information into it, and then 
pass it across to host.

> 
>> Signed-off-by: Vivek Gautam <vivek.gautam@arm.com>
>> Cc: Joerg Roedel <joro@8bytes.org>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Cc: Robin Murphy <robin.murphy@arm.com>
>> Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
>> Cc: Eric Auger <eric.auger@redhat.com>
>> Cc: Alex Williamson <alex.williamson@redhat.com>
>> Cc: Kevin Tian <kevin.tian@intel.com>
>> Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
>> Cc: Liu Yi L <yi.l.liu@intel.com>
>> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
>> Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
>> ---
>>   drivers/iommu/iommu-pasid-table.h | 134 ++++++++++++++++++++++++++++++
>>   1 file changed, 134 insertions(+)
>>   create mode 100644 drivers/iommu/iommu-pasid-table.h
>>
>> diff --git a/drivers/iommu/iommu-pasid-table.h b/drivers/iommu/iommu-pasid-table.h
>> new file mode 100644
>> index 000000000000..bd4f57656f67
>> --- /dev/null
>> +++ b/drivers/iommu/iommu-pasid-table.h
>> @@ -0,0 +1,134 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * PASID table management for the IOMMU
>> + *
>> + * Copyright (C) 2021 Arm Ltd.
>> + */
>> +#ifndef __IOMMU_PASID_TABLE_H
>> +#define __IOMMU_PASID_TABLE_H
>> +
>> +#include <linux/io-pgtable.h>
>> +
>> +#include "arm/arm-smmu-v3/arm-smmu-v3.h"
>> +
>> +enum pasid_table_fmt {
>> +	PASID_TABLE_ARM_SMMU_V3,
>> +	PASID_TABLE_NUM_FMTS,
>> +};
>> +
>> +/**
>> + * struct arm_smmu_cfg_info - arm-smmu-v3 specific configuration data
>> + *
>> + * @s1_cfg: arm-smmu-v3 stage1 config data
>> + * @feat_flag: features supported by arm-smmu-v3 implementation
>> + */
>> +struct arm_smmu_cfg_info {
>> +	struct arm_smmu_s1_cfg	*s1_cfg;
>> +	u32			feat_flag;
>> +};
>> +
>> +/**
>> + * struct iommu_vendor_psdtable_cfg - Configuration data for PASID tables
>> + *
>> + * @iommu_dev: device performing the DMA table walks
>> + * @fmt: The PASID table format
>> + * @base: DMA address of the allocated table, set by the vendor driver
>> + * @cfg: arm-smmu-v3 specific config data
>> + */
>> +struct iommu_vendor_psdtable_cfg {
>> +	struct device		*iommu_dev;
>> +	enum pasid_table_fmt	fmt;
>> +	dma_addr_t		base;
>> +	union {
>> +		struct arm_smmu_cfg_info	cfg;
> 
> For the union to be extensible, that field should be called "arm" or
> something like that.

Sure. Will amend this.

Thanks,
Vivek

> 
> Thanks,
> Jean
> 
>> +	} vendor;
>> +};
>> +
>> +struct iommu_vendor_psdtable_ops;
>> +
>> +/**
>> + * struct iommu_pasid_table - describes a set of PASID tables
>> + *
>> + * @cookie: An opaque token provided by the IOMMU driver and passed back to any
>> + * callback routine.
>> + * @cfg: A copy of the PASID table configuration
>> + * @ops: The PASID table operations in use for this set of page tables
>> + */
>> +struct iommu_pasid_table {
>> +	void					*cookie;
>> +	struct iommu_vendor_psdtable_cfg	cfg;
>> +	struct iommu_vendor_psdtable_ops	*ops;
>> +};
>> +
>> +#define pasid_table_cfg_to_table(pst_cfg) \
>> +	container_of((pst_cfg), struct iommu_pasid_table, cfg)
>> +
>> +struct iommu_vendor_psdtable_ops {
>> +	int (*alloc)(struct iommu_vendor_psdtable_cfg *cfg);
>> +	void (*free)(struct iommu_vendor_psdtable_cfg *cfg);
>> +	void (*prepare)(struct iommu_vendor_psdtable_cfg *cfg,
>> +			struct io_pgtable_cfg *pgtbl_cfg, u32 asid);
>> +	int (*write)(struct iommu_vendor_psdtable_cfg *cfg, int ssid,
>> +		     void *cookie);
>> +	void (*sync)(void *cookie, int ssid, bool leaf);
>> +};
>> +
>> +static inline int iommu_psdtable_alloc(struct iommu_pasid_table *tbl,
>> +				       struct iommu_vendor_psdtable_cfg *cfg)
>> +{
>> +	if (!tbl->ops->alloc)
>> +		return -ENOSYS;
>> +
>> +	return tbl->ops->alloc(cfg);
>> +}
>> +
>> +static inline void iommu_psdtable_free(struct iommu_pasid_table *tbl,
>> +				       struct iommu_vendor_psdtable_cfg *cfg)
>> +{
>> +	if (!tbl->ops->free)
>> +		return;
>> +
>> +	tbl->ops->free(cfg);
>> +}
>> +
>> +static inline int iommu_psdtable_prepare(struct iommu_pasid_table *tbl,
>> +					 struct iommu_vendor_psdtable_cfg *cfg,
>> +					 struct io_pgtable_cfg *pgtbl_cfg,
>> +					 u32 asid)
>> +{
>> +	if (!tbl->ops->prepare)
>> +		return -ENOSYS;
>> +
>> +	tbl->ops->prepare(cfg, pgtbl_cfg, asid);
>> +	return 0;
>> +}
>> +
>> +static inline int iommu_psdtable_write(struct iommu_pasid_table *tbl,
>> +				       struct iommu_vendor_psdtable_cfg *cfg,
>> +				       int ssid, void *cookie)
>> +{
>> +	if (!tbl->ops->write)
>> +		return -ENOSYS;
>> +
>> +	return tbl->ops->write(cfg, ssid, cookie);
>> +}
>> +
>> +static inline int iommu_psdtable_sync(struct iommu_pasid_table *tbl,
>> +				      void *cookie, int ssid, bool leaf)
>> +{
>> +	if (!tbl->ops->sync)
>> +		return -ENOSYS;
>> +
>> +	tbl->ops->sync(cookie, ssid, leaf);
>> +	return 0;
>> +}
>> +
>> +/* A placeholder to register vendor specific pasid layer */
>> +static inline struct iommu_pasid_table *
>> +iommu_register_pasid_table(enum pasid_table_fmt fmt,
>> +			   struct device *dev, void *cookie)
>> +{
>> +	return NULL;
>> +}
>> +
>> +#endif /* __IOMMU_PASID_TABLE_H */
>> -- 
>> 2.17.1
>>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH RFC v1 05/15] iommu/arm-smmu-v3: Set sync op from consumer driver of cd-lib
  2021-03-03 17:15   ` Jean-Philippe Brucker
@ 2021-03-12 12:49     ` Vivek Kumar Gautam
  0 siblings, 0 replies; 44+ messages in thread
From: Vivek Kumar Gautam @ 2021-03-12 12:49 UTC (permalink / raw)
  To: Jean-Philippe Brucker
  Cc: linux-kernel, linux-arm-kernel, iommu, virtualization, joro,
	will.deacon, mst, robin.murphy, eric.auger, alex.williamson,
	kevin.tian, jacob.jun.pan, yi.l.liu, lorenzo.pieralisi,
	shameerali.kolothum.thodi



On 3/3/21 10:45 PM, Jean-Philippe Brucker wrote:
> On Fri, Jan 15, 2021 at 05:43:32PM +0530, Vivek Gautam wrote:
>> Te change allows different consumers of arm-smmu-v3-cd-lib to set
>> their respective sync op for pasid entries.
>>
>> Signed-off-by: Vivek Gautam <vivek.gautam@arm.com>
>> Cc: Joerg Roedel <joro@8bytes.org>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Cc: Robin Murphy <robin.murphy@arm.com>
>> Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
>> Cc: Eric Auger <eric.auger@redhat.com>
>> Cc: Alex Williamson <alex.williamson@redhat.com>
>> Cc: Kevin Tian <kevin.tian@intel.com>
>> Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
>> Cc: Liu Yi L <yi.l.liu@intel.com>
>> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
>> Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
>> ---
>>   drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c | 1 -
>>   drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c        | 7 +++++++
>>   2 files changed, 7 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c
>> index ec37476c8d09..acaa09acecdd 100644
>> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c
>> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-cd-lib.c
>> @@ -265,7 +265,6 @@ struct iommu_vendor_psdtable_ops arm_cd_table_ops = {
>>   	.free	 = arm_smmu_free_cd_tables,
>>   	.prepare = arm_smmu_prepare_cd,
>>   	.write	 = arm_smmu_write_ctx_desc,
>> -	.sync	 = arm_smmu_sync_cd,
>>   };
>>   
>>   struct iommu_pasid_table *arm_smmu_register_cd_table(struct device *dev,
>> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
>> index 2f86c6ac42b6..0c644be22b4b 100644
>> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
>> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
>> @@ -1869,6 +1869,13 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain,
>>   	if (ret)
>>   		goto out_free_cd_tables;
>>   
>> +	/*
>> +	 * Strange to setup an op here?
>> +	 * cd-lib is the actual user of sync op, and therefore the platform
>> +	 * drivers should assign this sync/maintenance ops as per need.
>> +	 */
>> +	tbl->ops->sync = arm_smmu_sync_cd;
>> +
> 
> Modifying a static struct from here doesn't feel right. I think the
> interface should be roughly similar to io-pgtable since the principle is
> the same. So the sync() op should be separate from arm_cd_table_ops since
> it's a callback into the driver. Maybe pass it to
> iommu_register_pasid_table().

Sure, will take care of this.

Thanks & regards
Vivek

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH RFC v1 06/15] iommu/virtio: Add headers for table format probing
  2021-03-03 17:17   ` Jean-Philippe Brucker
@ 2021-03-12 12:54     ` Vivek Kumar Gautam
  0 siblings, 0 replies; 44+ messages in thread
From: Vivek Kumar Gautam @ 2021-03-12 12:54 UTC (permalink / raw)
  To: Jean-Philippe Brucker
  Cc: linux-kernel, linux-arm-kernel, iommu, virtualization, joro,
	will.deacon, mst, robin.murphy, eric.auger, alex.williamson,
	kevin.tian, jacob.jun.pan, yi.l.liu, lorenzo.pieralisi,
	shameerali.kolothum.thodi



On 3/3/21 10:47 PM, Jean-Philippe Brucker wrote:
> On Fri, Jan 15, 2021 at 05:43:33PM +0530, Vivek Gautam wrote:
>> From: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
>>
>> Add required UAPI defines for probing table format for underlying
>> iommu hardware. The device may provide information about hardware
>> tables and additional capabilities for each device.
>> This allows guest to correctly fabricate stage-1 page tables.
>>
>> Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
>> [Vivek: Use a single "struct virtio_iommu_probe_table_format" rather
>>          than separate structures for page table and pasid table format.
> 
> Makes sense. I've integrated that into the spec draft, added more precise
> documentation and modified some of the definitions.
> 
> The current draft is here:
> https://jpbrucker.net/virtio-iommu/spec/virtio-iommu-v0.13.pdf
> Posted on the list here
> https://lists.oasis-open.org/archives/virtio-dev/202102/msg00012.html

Thanks, I took an initial look, will review it this week.

> 
>> 	Also update commit message.]
>> Signed-off-by: Vivek Gautam <vivek.gautam@arm.com>
>> Cc: Joerg Roedel <joro@8bytes.org>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Cc: Michael S. Tsirkin <mst@redhat.com>
>> Cc: Robin Murphy <robin.murphy@arm.com>
>> Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
>> Cc: Eric Auger <eric.auger@redhat.com>
>> Cc: Alex Williamson <alex.williamson@redhat.com>
>> Cc: Kevin Tian <kevin.tian@intel.com>
>> Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
>> Cc: Liu Yi L <yi.l.liu@intel.com>
>> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
>> Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
>> ---
>>   include/uapi/linux/virtio_iommu.h | 44 ++++++++++++++++++++++++++++++-
>>   1 file changed, 43 insertions(+), 1 deletion(-)
>>
>> diff --git a/include/uapi/linux/virtio_iommu.h b/include/uapi/linux/virtio_iommu.h
>> index 237e36a280cb..43821e33e7af 100644
>> --- a/include/uapi/linux/virtio_iommu.h
>> +++ b/include/uapi/linux/virtio_iommu.h
>> @@ -2,7 +2,7 @@
>>   /*
>>    * Virtio-iommu definition v0.12
>>    *
>> - * Copyright (C) 2019 Arm Ltd.
>> + * Copyright (C) 2019-2021 Arm Ltd.
> 
> Not strictly necessary. But if you're modifying this comment please also
> remove the "v0.12" above

Sure, let me keep the copyright year unchanged until we finalize the 
changes in draft spec.

> 
>>    */
>>   #ifndef _UAPI_LINUX_VIRTIO_IOMMU_H
>>   #define _UAPI_LINUX_VIRTIO_IOMMU_H
>> @@ -111,6 +111,12 @@ struct virtio_iommu_req_unmap {
>>   
>>   #define VIRTIO_IOMMU_PROBE_T_NONE		0
>>   #define VIRTIO_IOMMU_PROBE_T_RESV_MEM		1
>> +#define VIRTIO_IOMMU_PROBE_T_PAGE_SIZE_MASK	2
>> +#define VIRTIO_IOMMU_PROBE_T_INPUT_RANGE	3
>> +#define VIRTIO_IOMMU_PROBE_T_OUTPUT_SIZE	4
>> +#define VIRTIO_IOMMU_PROBE_T_PASID_SIZE		5
>> +#define VIRTIO_IOMMU_PROBE_T_PAGE_TABLE_FMT	6
>> +#define VIRTIO_IOMMU_PROBE_T_PASID_TABLE_FMT	7
> 
> Since there is a single struct we can have a single
> VIRTIO_IOMMU_PROBE_T_TABLE_FORMAT.

Right, that would make sense.

> 
>>   
>>   #define VIRTIO_IOMMU_PROBE_T_MASK		0xfff
>>   
>> @@ -130,6 +136,42 @@ struct virtio_iommu_probe_resv_mem {
>>   	__le64					end;
>>   };
>>   
>> +struct virtio_iommu_probe_page_size_mask {
>> +	struct virtio_iommu_probe_property	head;
>> +	__u8					reserved[4];
>> +	__le64					mask;
>> +};
>> +
>> +struct virtio_iommu_probe_input_range {
>> +	struct virtio_iommu_probe_property	head;
>> +	__u8					reserved[4];
>> +	__le64					start;
>> +	__le64					end;
>> +};
>> +
>> +struct virtio_iommu_probe_output_size {
>> +	struct virtio_iommu_probe_property	head;
>> +	__u8					bits;
>> +	__u8					reserved[3];
>> +};
>> +
>> +struct virtio_iommu_probe_pasid_size {
>> +	struct virtio_iommu_probe_property	head;
>> +	__u8					bits;
>> +	__u8					reserved[3];
>> +};
>> +
>> +/* Arm LPAE page table format */
>> +#define VIRTIO_IOMMU_FOMRAT_PGTF_ARM_LPAE	1
> 
> s/FOMRAT/FORMAT

Sure.

> 
>> +/* Arm smmu-v3 type PASID table format */
>> +#define VIRTIO_IOMMU_FORMAT_PSTF_ARM_SMMU_V3	2
> 
> These should be with the Arm-specific definitions patches 11 and 14

Right, will add these definitions with Arm specific patches.

Best regards
Vivek

[snip]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH RFC v1 08/15] iommu: Add asid_bits to arm smmu-v3 stage1 table info
  2021-03-03 17:18   ` Jean-Philippe Brucker
@ 2021-03-12 12:57     ` Vivek Kumar Gautam
  0 siblings, 0 replies; 44+ messages in thread
From: Vivek Kumar Gautam @ 2021-03-12 12:57 UTC (permalink / raw)
  To: Jean-Philippe Brucker
  Cc: linux-kernel, linux-arm-kernel, iommu, virtualization, joro,
	will.deacon, mst, robin.murphy, eric.auger, alex.williamson,
	kevin.tian, jacob.jun.pan, yi.l.liu, lorenzo.pieralisi,
	shameerali.kolothum.thodi



On 3/3/21 10:48 PM, Jean-Philippe Brucker wrote:
> On Fri, Jan 15, 2021 at 05:43:35PM +0530, Vivek Gautam wrote:
>> aisd_bits data is required to prepare stage-1 tables for arm-smmu-v3.
>>
>> Signed-off-by: Vivek Gautam <vivek.gautam@arm.com>
>> Cc: Joerg Roedel <joro@8bytes.org>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Cc: Robin Murphy <robin.murphy@arm.com>
>> Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
>> Cc: Eric Auger <eric.auger@redhat.com>
>> Cc: Alex Williamson <alex.williamson@redhat.com>
>> Cc: Kevin Tian <kevin.tian@intel.com>
>> Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
>> Cc: Liu Yi L <yi.l.liu@intel.com>
>> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
>> Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
>> ---
>>   include/uapi/linux/iommu.h | 2 +-
>>   1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/include/uapi/linux/iommu.h b/include/uapi/linux/iommu.h
>> index 082d758dd016..96abbfc7c643 100644
>> --- a/include/uapi/linux/iommu.h
>> +++ b/include/uapi/linux/iommu.h
>> @@ -357,7 +357,7 @@ struct iommu_pasid_smmuv3 {
>>   	__u32	version;
>>   	__u8	s1fmt;
>>   	__u8	s1dss;
>> -	__u8	padding[2];
>> +	__u16	asid_bits;
> 
> Is this used anywhere?  This struct is passed from host userspace to host
> kernel to attach the PASID table, so I don't think it needs an asid_bits
> field.

Yea, must have missed removing it from the WIP work. Will remove it.

Thanks
Vivek

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH RFC v1 09/15] iommu/virtio: Update table format probing header
  2021-03-03 17:21   ` Jean-Philippe Brucker
@ 2021-03-12 12:58     ` Vivek Kumar Gautam
  0 siblings, 0 replies; 44+ messages in thread
From: Vivek Kumar Gautam @ 2021-03-12 12:58 UTC (permalink / raw)
  To: Jean-Philippe Brucker
  Cc: linux-kernel, linux-arm-kernel, iommu, virtualization, joro,
	will.deacon, mst, robin.murphy, eric.auger, alex.williamson,
	kevin.tian, jacob.jun.pan, yi.l.liu, lorenzo.pieralisi,
	shameerali.kolothum.thodi



On 3/3/21 10:51 PM, Jean-Philippe Brucker wrote:
> On Fri, Jan 15, 2021 at 05:43:36PM +0530, Vivek Gautam wrote:
>> Add info about asid_bits and additional flags to table format
>> probing header.
>>
>> Signed-off-by: Vivek Gautam <vivek.gautam@arm.com>
>> Cc: Joerg Roedel <joro@8bytes.org>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Cc: Michael S. Tsirkin <mst@redhat.com>
>> Cc: Robin Murphy <robin.murphy@arm.com>
>> Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
>> Cc: Eric Auger <eric.auger@redhat.com>
>> Cc: Alex Williamson <alex.williamson@redhat.com>
>> Cc: Kevin Tian <kevin.tian@intel.com>
>> Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
>> Cc: Liu Yi L <yi.l.liu@intel.com>
>> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
>> Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
>> ---
>>   include/uapi/linux/virtio_iommu.h | 5 ++++-
>>   1 file changed, 4 insertions(+), 1 deletion(-)
>>
>> diff --git a/include/uapi/linux/virtio_iommu.h b/include/uapi/linux/virtio_iommu.h
>> index 43821e33e7af..8a0624bab4b2 100644
>> --- a/include/uapi/linux/virtio_iommu.h
>> +++ b/include/uapi/linux/virtio_iommu.h
>> @@ -169,7 +169,10 @@ struct virtio_iommu_probe_pasid_size {
>>   struct virtio_iommu_probe_table_format {
>>   	struct virtio_iommu_probe_property	head;
>>   	__le16					format;
>> -	__u8					reserved[2];
>> +	__le16					asid_bits;
>> +
>> +	__le32					flags;
> 
> This struct should only contain the head and format fields. asid and flags
> should go in a specialized structure - virtio_iommu_probe_pgt_arm64 in the
> latest spec draft, where I dropped the asid_bits field in favor of an
> "ASID16" flag.

Right, will take care of this looking at the spec draft.

Best regards
Vivek

> 
> Thanks,
> Jean
> 

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH RFC v1 15/15] iommu/virtio: Update fault type and reason info for viommu fault
  2021-03-03 17:25   ` Jean-Philippe Brucker
@ 2021-03-12 13:09     ` Vivek Kumar Gautam
  2021-03-29 16:23       ` Jean-Philippe Brucker
  0 siblings, 1 reply; 44+ messages in thread
From: Vivek Kumar Gautam @ 2021-03-12 13:09 UTC (permalink / raw)
  To: Jean-Philippe Brucker
  Cc: linux-kernel, linux-arm-kernel, iommu, virtualization, joro,
	will.deacon, mst, robin.murphy, eric.auger, alex.williamson,
	kevin.tian, jacob.jun.pan, yi.l.liu, lorenzo.pieralisi,
	shameerali.kolothum.thodi



On 3/3/21 10:55 PM, Jean-Philippe Brucker wrote:
> On Fri, Jan 15, 2021 at 05:43:42PM +0530, Vivek Gautam wrote:
>> Fault type information can tell about a page request fault or
>> an unreceoverable fault, and further additions to fault reasons
>> and the related PASID information can help in handling faults
>> efficiently.
>>
>> Signed-off-by: Vivek Gautam <vivek.gautam@arm.com>
>> Cc: Joerg Roedel <joro@8bytes.org>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Cc: Michael S. Tsirkin <mst@redhat.com>
>> Cc: Robin Murphy <robin.murphy@arm.com>
>> Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
>> Cc: Eric Auger <eric.auger@redhat.com>
>> Cc: Alex Williamson <alex.williamson@redhat.com>
>> Cc: Kevin Tian <kevin.tian@intel.com>
>> Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
>> Cc: Liu Yi L <yi.l.liu@intel.com>
>> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
>> Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
>> ---
>>   drivers/iommu/virtio-iommu.c      | 27 +++++++++++++++++++++++++--
>>   include/uapi/linux/virtio_iommu.h | 13 ++++++++++++-
>>   2 files changed, 37 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c
>> index 9cc3d35125e9..10ef9e98214a 100644
>> --- a/drivers/iommu/virtio-iommu.c
>> +++ b/drivers/iommu/virtio-iommu.c
>> @@ -652,9 +652,16 @@ static int viommu_fault_handler(struct viommu_dev *viommu,
>>   	char *reason_str;
>>   
>>   	u8 reason	= fault->reason;
>> +	u16 type	= fault->flt_type;
>>   	u32 flags	= le32_to_cpu(fault->flags);
>>   	u32 endpoint	= le32_to_cpu(fault->endpoint);
>>   	u64 address	= le64_to_cpu(fault->address);
>> +	u32 pasid	= le32_to_cpu(fault->pasid);
>> +
>> +	if (type == VIRTIO_IOMMU_FAULT_F_PAGE_REQ) {
>> +		dev_info(viommu->dev, "Page request fault - unhandled\n");
>> +		return 0;
>> +	}
>>   
>>   	switch (reason) {
>>   	case VIRTIO_IOMMU_FAULT_R_DOMAIN:
>> @@ -663,6 +670,21 @@ static int viommu_fault_handler(struct viommu_dev *viommu,
>>   	case VIRTIO_IOMMU_FAULT_R_MAPPING:
>>   		reason_str = "page";
>>   		break;
>> +	case VIRTIO_IOMMU_FAULT_R_WALK_EABT:
>> +		reason_str = "page walk external abort";
>> +		break;
>> +	case VIRTIO_IOMMU_FAULT_R_PTE_FETCH:
>> +		reason_str = "pte fetch";
>> +		break;
>> +	case VIRTIO_IOMMU_FAULT_R_PERMISSION:
>> +		reason_str = "permission";
>> +		break;
>> +	case VIRTIO_IOMMU_FAULT_R_ACCESS:
>> +		reason_str = "access";
>> +		break;
>> +	case VIRTIO_IOMMU_FAULT_R_OOR_ADDRESS:
>> +		reason_str = "output address";
>> +		break;
>>   	case VIRTIO_IOMMU_FAULT_R_UNKNOWN:
>>   	default:
>>   		reason_str = "unknown";
>> @@ -671,8 +693,9 @@ static int viommu_fault_handler(struct viommu_dev *viommu,
>>   
>>   	/* TODO: find EP by ID and report_iommu_fault */
>>   	if (flags & VIRTIO_IOMMU_FAULT_F_ADDRESS)
>> -		dev_err_ratelimited(viommu->dev, "%s fault from EP %u at %#llx [%s%s%s]\n",
>> -				    reason_str, endpoint, address,
>> +		dev_err_ratelimited(viommu->dev,
>> +				    "%s fault from EP %u PASID %u at %#llx [%s%s%s]\n",
>> +				    reason_str, endpoint, pasid, address,
>>   				    flags & VIRTIO_IOMMU_FAULT_F_READ ? "R" : "",
>>   				    flags & VIRTIO_IOMMU_FAULT_F_WRITE ? "W" : "",
>>   				    flags & VIRTIO_IOMMU_FAULT_F_EXEC ? "X" : "");
>> diff --git a/include/uapi/linux/virtio_iommu.h b/include/uapi/linux/virtio_iommu.h
>> index 608c8d642e1f..a537d82777f7 100644
>> --- a/include/uapi/linux/virtio_iommu.h
>> +++ b/include/uapi/linux/virtio_iommu.h
>> @@ -290,19 +290,30 @@ struct virtio_iommu_req_invalidate {
>>   #define VIRTIO_IOMMU_FAULT_R_UNKNOWN		0
>>   #define VIRTIO_IOMMU_FAULT_R_DOMAIN		1
>>   #define VIRTIO_IOMMU_FAULT_R_MAPPING		2
>> +#define VIRTIO_IOMMU_FAULT_R_WALK_EABT		3
>> +#define VIRTIO_IOMMU_FAULT_R_PTE_FETCH		4
>> +#define VIRTIO_IOMMU_FAULT_R_PERMISSION		5
>> +#define VIRTIO_IOMMU_FAULT_R_ACCESS		6
>> +#define VIRTIO_IOMMU_FAULT_R_OOR_ADDRESS	7
>>   
>>   #define VIRTIO_IOMMU_FAULT_F_READ		(1 << 0)
>>   #define VIRTIO_IOMMU_FAULT_F_WRITE		(1 << 1)
>>   #define VIRTIO_IOMMU_FAULT_F_EXEC		(1 << 2)
>>   #define VIRTIO_IOMMU_FAULT_F_ADDRESS		(1 << 8)
>>   
>> +#define VIRTIO_IOMMU_FAULT_F_DMA_UNRECOV	1
>> +#define VIRTIO_IOMMU_FAULT_F_PAGE_REQ		2
> 
> Currently all reported faults are unrecoverable, so to be consistent
> DMA_UNRECOV should be 0. But I'd prefer having just a new "page request"
> flag in the flags field, instead of the flt_type field.

Yea, looking at what I am currently trying as well - handle page-request 
and leave all other faults as unrecoverable - I will add the page 
request flag in the structure.

> 
> For page requests we'll also need a 16-bit fault ID field to store the PRI
> "page request group index" or the stall "stag". "last" and "privileged"
> flags as well, to match the PRI page request. And a new command to
> complete a page fault.

Right, will add the fields as suggested.
To complete the page request we would also need to send the response 
back to the host from virtio backend when handling page request. So the 
virtio command should also be accompanied with a vfio api to send the 
page request response back to the host. Isn't it?
This is where the host smmuv3 can send PRI_RESP command to the device to 
complete the page fault.

> 
>> +
>>   struct virtio_iommu_fault {
>>   	__u8					reason;
>> -	__u8					reserved[3];
>> +	__le16					flt_type;
>> +	__u8					reserved;
>>   	__le32					flags;
>>   	__le32					endpoint;
>>   	__u8					reserved2[4];
> 
> Why not replace reserved2 with the pasid?  It fits perfectly :)

Sure, will do it.

Thanks & regards
Vivek

> 
> Thanks,
> Jean
> 
>>   	__le64					address;
>> +	__le32					pasid;
>> +	__u8					reserved3[4];
>>   };
>>   
>>   #endif
>> -- 
>> 2.17.1
>>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH RFC v1 13/15] iommu/virtio: Attach Arm PASID tables when available
  2021-03-03 17:25   ` Jean-Philippe Brucker
@ 2021-03-12 13:29     ` Vivek Kumar Gautam
  2021-03-29 16:21       ` Jean-Philippe Brucker
  0 siblings, 1 reply; 44+ messages in thread
From: Vivek Kumar Gautam @ 2021-03-12 13:29 UTC (permalink / raw)
  To: Jean-Philippe Brucker
  Cc: linux-kernel, linux-arm-kernel, iommu, virtualization, joro,
	will.deacon, mst, robin.murphy, eric.auger, alex.williamson,
	kevin.tian, jacob.jun.pan, yi.l.liu, lorenzo.pieralisi,
	shameerali.kolothum.thodi



On 3/3/21 10:55 PM, Jean-Philippe Brucker wrote:
> On Fri, Jan 15, 2021 at 05:43:40PM +0530, Vivek Gautam wrote:
> [...]
>> +static int viommu_setup_pgtable(struct viommu_endpoint *vdev,
>> +				struct viommu_domain *vdomain)
>> +{
>> +	int ret, id;
>> +	u32 asid;
>> +	enum io_pgtable_fmt fmt;
>> +	struct io_pgtable_ops *ops = NULL;
>> +	struct viommu_dev *viommu = vdev->viommu;
>> +	struct virtio_iommu_probe_table_format *desc = vdev->pgtf;
>> +	struct iommu_pasid_table *tbl = vdomain->pasid_tbl;
>> +	struct iommu_vendor_psdtable_cfg *pst_cfg;
>> +	struct arm_smmu_cfg_info *cfgi;
>> +	struct io_pgtable_cfg cfg = {
>> +		.iommu_dev	= viommu->dev->parent,
>> +		.tlb		= &viommu_flush_ops,
>> +		.pgsize_bitmap	= vdev->pgsize_mask ? vdev->pgsize_mask :
>> +				  vdomain->domain.pgsize_bitmap,
>> +		.ias		= (vdev->input_end ? ilog2(vdev->input_end) :
>> +				   ilog2(vdomain->domain.geometry.aperture_end)) + 1,
>> +		.oas		= vdev->output_bits,
>> +	};
>> +
>> +	if (!desc)
>> +		return -EINVAL;
>> +
>> +	if (!vdev->output_bits)
>> +		return -ENODEV;
>> +
>> +	switch (le16_to_cpu(desc->format)) {
>> +	case VIRTIO_IOMMU_FOMRAT_PGTF_ARM_LPAE:
>> +		fmt = ARM_64_LPAE_S1;
>> +		break;
>> +	default:
>> +		dev_err(vdev->dev, "unsupported page table format 0x%x\n",
>> +			le16_to_cpu(desc->format));
>> +		return -EINVAL;
>> +	}
>> +
>> +	if (vdomain->mm.ops) {
>> +		/*
>> +		 * TODO: attach additional endpoint to the domain. Check that
>> +		 * the config is sane.
>> +		 */
>> +		return -EEXIST;
>> +	}
>> +
>> +	vdomain->mm.domain = vdomain;
>> +	ops = alloc_io_pgtable_ops(fmt, &cfg, &vdomain->mm);
>> +	if (!ops)
>> +		return -ENOMEM;
>> +
>> +	pst_cfg = &tbl->cfg;
>> +	cfgi = &pst_cfg->vendor.cfg;
>> +	id = ida_simple_get(&asid_ida, 1, 1 << desc->asid_bits, GFP_KERNEL);
>> +	if (id < 0) {
>> +		ret = id;
>> +		goto err_free_pgtable;
>> +	}
>> +
>> +	asid = id;
>> +	ret = iommu_psdtable_prepare(tbl, pst_cfg, &cfg, asid);
>> +	if (ret)
>> +		goto err_free_asid;
>> +
>> +	/*
>> +	 * Strange to setup an op here?
>> +	 * cd-lib is the actual user of sync op, and therefore the platform
>> +	 * drivers should assign this sync/maintenance ops as per need.
>> +	 */
>> +	tbl->ops->sync = viommu_flush_pasid;
> 
> But this function deals with page tables, not pasid tables. As said on an
> earlier patch, the TLB flush ops should probably be passed during table
> registration - those ops are global so should really be const.

Right, will amend it.

> 
>> +
>> +	/* Right now only PASID 0 supported ?? */
>> +	ret = iommu_psdtable_write(tbl, pst_cfg, 0, &cfgi->s1_cfg->cd);
>> +	if (ret)
>> +		goto err_free_asid;
>> +
>> +	vdomain->mm.ops = ops;
>> +	dev_dbg(vdev->dev, "using page table format 0x%x\n", fmt);
>> +
>> +	return 0;
>> +
>> +err_free_asid:
>> +	ida_simple_remove(&asid_ida, asid);
>> +err_free_pgtable:
>> +	free_io_pgtable_ops(ops);
>> +	return ret;
>> +}
>> +
>> +static int viommu_config_arm_pst(struct iommu_vendor_psdtable_cfg *pst_cfg,
>> +				 struct virtio_iommu_req_attach_pst_arm *req)
>> +{
>> +	struct arm_smmu_s1_cfg *s1_cfg = pst_cfg->vendor.cfg.s1_cfg;
>> +
>> +	if (!s1_cfg)
>> +		return -ENODEV;
>> +
>> +	req->format	= cpu_to_le16(VIRTIO_IOMMU_FORMAT_PSTF_ARM_SMMU_V3);
>> +	req->s1fmt	= s1_cfg->s1fmt;
>> +	req->s1dss	= VIRTIO_IOMMU_PSTF_ARM_SMMU_V3_DSS_0;
>> +	req->s1contextptr = cpu_to_le64(pst_cfg->base);
>> +	req->s1cdmax	= cpu_to_le32(s1_cfg->s1cdmax);
>> +
>> +	return 0;
>> +}
>> +
>> +static int viommu_config_pst(struct iommu_vendor_psdtable_cfg *pst_cfg,
>> +			     void *req, enum pasid_table_fmt fmt)
>> +{
>> +	int ret;
>> +
>> +	switch (fmt) {
>> +	case PASID_TABLE_ARM_SMMU_V3:
>> +		ret = viommu_config_arm_pst(pst_cfg, req);
>> +		break;
>> +	default:
>> +		ret = -EINVAL;
>> +		WARN_ON(1);
>> +	}
>> +
>> +	return ret;
>> +}
>> +
>> +static int viommu_prepare_arm_pst(struct viommu_endpoint *vdev,
>> +				  struct iommu_vendor_psdtable_cfg *pst_cfg)
>> +{
>> +	struct virtio_iommu_probe_table_format *pgtf = vdev->pgtf;
>> +	struct arm_smmu_cfg_info *cfgi = &pst_cfg->vendor.cfg;
>> +	struct arm_smmu_s1_cfg *cfg;
>> +
>> +	/* Some sanity checks */
>> +	if (pgtf->asid_bits != 8 && pgtf->asid_bits != 16)
>> +		return -EINVAL;
> 
> No need for this, next patch cheks asid size in viommu_config_arm_pgt()

Right, thanks for catching.

> 
>> +
>> +	cfg = devm_kzalloc(pst_cfg->iommu_dev, sizeof(cfg), GFP_KERNEL);
>> +	if (!cfg)
>> +		return -ENOMEM;
>> +
>> +	cfgi->s1_cfg = cfg;
>> +	cfg->s1cdmax = vdev->pasid_bits;
>> +	cfg->cd.asid = pgtf->asid_bits;
> 
> That doesn't look right, cfg->cd.asid takes the ASID value of context 0
> but here we're writing a limit. viommu_setup_pgtable() probably needs to
> set this field to the allocated ASID, since viommu_teardown_pgtable() uses
> it.

Yea, this isn't right. The asid should be assigned to the one that we 
are allocating. I think this is getting over-written when 
iommu_psdtable_prepare() calls into arm_smmu_prepare_cd() where the 
correct asid value is assigned. I will remove this.

> 
>> +
>> +	pst_cfg->fmt = PASID_TABLE_ARM_SMMU_V3;
> 
> Parent function can set this

Sure.

> 
>> +	/* XXX HACK: set feature bit ARM_SMMU_FEAT_2_LVL_CDTAB */
>> +	pst_cfg->vendor.cfg.feat_flag |= (1 << 1);
> 
> Oh right, this flag is missing. I'll add
> 
>    #define VIRTIO_IOMMU_PST_ARM_SMMU3_F_CD2L (1ULL << 1)
> 
> to the spec.

Regarding this Eric pointed out [1] in my other patch about the 
scalability of the approach where we keep adding flags in 
'iommu_nesting_info' corresponding to the arm-smmu-v3 capabilities. I 
guess the same goes to these flags in virtio.
May be the 'iommu_nesting_info' can have a bitmap with the caps for 
vendor specific features, and here we can add the related flags?

> 
>> +
>> +	return 0;
>> +}
>> +
>> +static int viommu_prepare_pst(struct viommu_endpoint *vdev,
>> +			      struct iommu_vendor_psdtable_cfg *pst_cfg,
>> +			      enum pasid_table_fmt fmt)
>> +{
>> +	int ret;
>> +
>> +	switch (fmt) {
>> +	case PASID_TABLE_ARM_SMMU_V3:
>> +		ret = viommu_prepare_arm_pst(vdev, pst_cfg);
>> +		break;
>> +	default:
>> +		dev_err(vdev->dev, "unsupported PASID table format 0x%x\n", fmt);
>> +		ret = -EINVAL;
>> +	}
>> +
>> +	return ret;
>> +}
>> +
>> +static int viommu_attach_pasid_table(struct viommu_endpoint *vdev,
>> +				     struct viommu_domain *vdomain)
>> +{
>> +	int ret;
>> +	int i, eid;
>> +	enum pasid_table_fmt fmt = -1;
>> +	struct virtio_iommu_probe_table_format *desc = vdev->pstf;
>> +	struct virtio_iommu_req_attach_table req = {
>> +		.head.type	= VIRTIO_IOMMU_T_ATTACH_TABLE,
>> +		.domain		= cpu_to_le32(vdomain->id),
>> +	};
>> +	struct viommu_dev *viommu = vdev->viommu;
>> +	struct iommu_pasid_table *tbl;
>> +	struct iommu_vendor_psdtable_cfg *pst_cfg;
>> +
>> +	if (!viommu->has_table)
>> +		return 0;
>> +
>> +	if (!desc)
>> +		return -ENODEV;
>> +
>> +	/* Prepare PASID tables configuration */
>> +	switch (le16_to_cpu(desc->format)) {
>> +	case VIRTIO_IOMMU_FORMAT_PSTF_ARM_SMMU_V3:
>> +		fmt = PASID_TABLE_ARM_SMMU_V3;
>> +		break;
>> +	default:
>> +		dev_err(vdev->dev, "unsupported PASID table format 0x%x\n",
>> +			le16_to_cpu(desc->format));
>> +		return 0;
>> +	}
>> +
>> +	if (!tbl) {
>> +		tbl = iommu_register_pasid_table(fmt, viommu->dev->parent, vdomain);
>> +		if (!tbl)
>> +			return -ENOMEM;
>> +
>> +		vdomain->pasid_tbl = tbl;
>> +		pst_cfg = &tbl->cfg;
>> +
>> +		pst_cfg->iommu_dev = viommu->dev->parent;
>> +
>> +		/* Prepare PASID tables info to allocate a new table */
>> +		ret = viommu_prepare_pst(vdev, pst_cfg, fmt);
>> +		if (ret)
>> +			return ret;
>> +
>> +		ret = iommu_psdtable_alloc(tbl, pst_cfg);
>> +		if (ret)
>> +			return ret;
>> +
>> +		pst_cfg->iommu_dev = viommu->dev->parent;
> 
> Already set by iommu_register_pasid_table() (and needed for DMA
> allocations in iommu_psdtable_alloc())

Right.

> 
>> +		pst_cfg->fmt = PASID_TABLE_ARM_SMMU_V3;
> 
> Already set above

Right.

> 
>> +
>> +		ret = viommu_setup_pgtable(vdev, vdomain);
>> +		if (ret) {
>> +			dev_err(vdev->dev, "could not install page tables\n");
>> +			goto err_free_psdtable;
>> +		}
>> +
>> +		/* Add arch-specific configuration */
>> +		ret = viommu_config_pst(pst_cfg, (void *)&req, fmt);
>> +		if (ret)
>> +			goto err_free_ops;
>> +
>> +		vdev_for_each_id(i, eid, vdev) {
>> +			req.endpoint = cpu_to_le32(eid);
>> +			ret = viommu_send_req_sync(viommu, &req, sizeof(req));
>> +			if (ret)
>> +				goto err_free_ops;
>> +		}
>> +	} else {
>> +		/* TODO: otherwise, check for compatibility with vdev. */
>> +		return -ENOSYS;
>> +	}
>> +
>> +	dev_dbg(vdev->dev, "uses PASID table format 0x%x\n", fmt);
>> +
>> +	return 0;
>> +
>> +err_free_ops:
>> +	if (vdomain->mm.ops)
>> +		viommu_teardown_pgtable(vdomain);
>> +err_free_psdtable:
>> +	iommu_psdtable_free(tbl, &tbl->cfg);
>> +
>> +	return ret;
>> +}
>> +
>>   static int viommu_attach_dev(struct iommu_domain *domain, struct device *dev)
>>   {
>>   	int ret = 0;
>> @@ -928,6 +1213,17 @@ static int viommu_attach_dev(struct iommu_domain *domain, struct device *dev)
>>   	if (vdev->vdomain)
>>   		vdev->vdomain->nr_endpoints--;
>>   
>> +	ret = viommu_attach_pasid_table(vdev, vdomain);
>> +	if (ret) {
>> +		/*
>> +		 * No PASID support, too bad. Perhaps we can bind a single set
>> +		 * of page tables?
>> +		 */
>> +		ret = viommu_setup_pgtable(vdev, vdomain);
> 
> This cannot work at the moment because viommu_setup_pgtable() writes to
> the non-existing pasid table. Probably best to leave this call for next
> patch.

Yea, will move it to the next patch.

Thanks & regards
Vivek

> 
> Thanks,
> Jean
> 
>> +		if (ret)
>> +			dev_err(vdev->dev, "could not install tables\n");
>> +	}
>> +
>>   	if (!vdomain->mm.ops) {
>>   		/* If we couldn't bind any table, use the mapping tree */
>>   		ret = viommu_simple_attach(vdomain, vdev);
>> @@ -948,6 +1244,10 @@ static int viommu_map(struct iommu_domain *domain, unsigned long iova,
>>   	u32 flags;
>>   	struct virtio_iommu_req_map map;
>>   	struct viommu_domain *vdomain = to_viommu_domain(domain);
>> +	struct io_pgtable_ops *ops = vdomain->mm.ops;
>> +
>> +	if (ops)
>> +		return ops->map(ops, iova, paddr, size, prot, gfp);
>>   
>>   	flags = (prot & IOMMU_READ ? VIRTIO_IOMMU_MAP_F_READ : 0) |
>>   		(prot & IOMMU_WRITE ? VIRTIO_IOMMU_MAP_F_WRITE : 0) |
>> @@ -986,6 +1286,10 @@ static size_t viommu_unmap(struct iommu_domain *domain, unsigned long iova,
>>   	size_t unmapped;
>>   	struct virtio_iommu_req_unmap unmap;
>>   	struct viommu_domain *vdomain = to_viommu_domain(domain);
>> +	struct io_pgtable_ops *ops = vdomain->mm.ops;
>> +
>> +	if (ops)
>> +		return ops->unmap(ops, iova, size, gather);
>>   
>>   	unmapped = viommu_del_mappings(vdomain, iova, size);
>>   	if (unmapped < size)
>> @@ -1014,6 +1318,10 @@ static phys_addr_t viommu_iova_to_phys(struct iommu_domain *domain,
>>   	struct viommu_mapping *mapping;
>>   	struct interval_tree_node *node;
>>   	struct viommu_domain *vdomain = to_viommu_domain(domain);
>> +	struct io_pgtable_ops *ops = vdomain->mm.ops;
>> +
>> +	if (ops)
>> +		return ops->iova_to_phys(ops, iova);
>>   
>>   	spin_lock_irqsave(&vdomain->mappings_lock, flags);
>>   	node = interval_tree_iter_first(&vdomain->mappings, iova, iova);
>> @@ -1264,7 +1572,12 @@ static int viommu_probe(struct virtio_device *vdev)
>>   				struct virtio_iommu_config, probe_size,
>>   				&viommu->probe_size);
>>   
>> +	viommu->has_table = virtio_has_feature(vdev, VIRTIO_IOMMU_F_ATTACH_TABLE);
>>   	viommu->has_map = virtio_has_feature(vdev, VIRTIO_IOMMU_F_MAP_UNMAP);
>> +	if (!viommu->has_table && !viommu->has_map) {
>> +		ret = -EINVAL;
>> +		goto err_free_vqs;
>> +	}
>>   
>>   	viommu->geometry = (struct iommu_domain_geometry) {
>>   		.aperture_start	= input_start,
>> @@ -1356,6 +1669,7 @@ static unsigned int features[] = {
>>   	VIRTIO_IOMMU_F_DOMAIN_RANGE,
>>   	VIRTIO_IOMMU_F_PROBE,
>>   	VIRTIO_IOMMU_F_MMIO,
>> +	VIRTIO_IOMMU_F_ATTACH_TABLE,
>>   };
>>   
>>   static struct virtio_device_id id_table[] = {
>> -- 
>> 2.17.1
>>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH RFC v1 13/15] iommu/virtio: Attach Arm PASID tables when available
  2021-03-12 13:29     ` Vivek Kumar Gautam
@ 2021-03-29 16:21       ` Jean-Philippe Brucker
  0 siblings, 0 replies; 44+ messages in thread
From: Jean-Philippe Brucker @ 2021-03-29 16:21 UTC (permalink / raw)
  To: Vivek Kumar Gautam
  Cc: linux-kernel, linux-arm-kernel, iommu, virtualization, joro,
	will.deacon, mst, robin.murphy, eric.auger, alex.williamson,
	kevin.tian, jacob.jun.pan, yi.l.liu, lorenzo.pieralisi,
	shameerali.kolothum.thodi

On Fri, Mar 12, 2021 at 06:59:17PM +0530, Vivek Kumar Gautam wrote:
> > > +	/* XXX HACK: set feature bit ARM_SMMU_FEAT_2_LVL_CDTAB */
> > > +	pst_cfg->vendor.cfg.feat_flag |= (1 << 1);
> > 
> > Oh right, this flag is missing. I'll add
> > 
> >    #define VIRTIO_IOMMU_PST_ARM_SMMU3_F_CD2L (1ULL << 1)
> > 
> > to the spec.
> 
> Regarding this Eric pointed out [1] in my other patch about the scalability
> of the approach where we keep adding flags in 'iommu_nesting_info'
> corresponding to the arm-smmu-v3 capabilities. I guess the same goes to
> these flags in virtio.
> May be the 'iommu_nesting_info' can have a bitmap with the caps for vendor
> specific features, and here we can add the related flags?

Something like that, but I'd keep separate arch-specific structs. Vt-d
reports the capability registers directly through iommu_nesting_info [2].
We could do the same for Arm, copy sanitized values of IDR0..5 into
struct iommu_nesting_info_arm_smmuv3.

I've avoided doing that for virtio-iommu because every field needs a
description in the spec. So where possible I used generic properties that
apply to any architecture, such as page, PASID and address size. What's
left is the minimum arch-specific information to get nested translation
going, leaving out a lot of properties such as big-endian and 32-bit,
which can be added later if needed. The Arm specific properties are split
into page table and pasid table information. Page table info should work
for both SMMUv2 and v3 (where they correspond to an SMMU_IDRx field that
constrains a context descriptor field.) I should move BTM in there since
it's supported by SMMUv2.

Thanks,
Jean

[2] https://lore.kernel.org/linux-iommu/20210302203545.436623-11-yi.l.liu@intel.com/

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH RFC v1 15/15] iommu/virtio: Update fault type and reason info for viommu fault
  2021-03-12 13:09     ` Vivek Kumar Gautam
@ 2021-03-29 16:23       ` Jean-Philippe Brucker
  2021-04-06  6:24         ` Vivek Kumar Gautam
  0 siblings, 1 reply; 44+ messages in thread
From: Jean-Philippe Brucker @ 2021-03-29 16:23 UTC (permalink / raw)
  To: Vivek Kumar Gautam
  Cc: linux-kernel, linux-arm-kernel, iommu, virtualization, joro,
	will.deacon, mst, robin.murphy, eric.auger, alex.williamson,
	kevin.tian, jacob.jun.pan, yi.l.liu, lorenzo.pieralisi,
	shameerali.kolothum.thodi

On Fri, Mar 12, 2021 at 06:39:05PM +0530, Vivek Kumar Gautam wrote:
> To complete the page request we would also need to send the response back to
> the host from virtio backend when handling page request. So the virtio
> command should also be accompanied with a vfio api to send the page request
> response back to the host. Isn't it?
> This is where the host smmuv3 can send PRI_RESP command to the device to
> complete the page fault.

It looks like Eric already has this in the VFIO series:
https://lore.kernel.org/linux-iommu/20210223210625.604517-14-eric.auger@redhat.com/

Thanks,
Jean

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH RFC v1 02/15] iommu: Add a simple PASID table library
  2021-03-12 12:47     ` Vivek Kumar Gautam
@ 2021-03-29 16:25       ` Jean-Philippe Brucker
  0 siblings, 0 replies; 44+ messages in thread
From: Jean-Philippe Brucker @ 2021-03-29 16:25 UTC (permalink / raw)
  To: Vivek Kumar Gautam
  Cc: linux-kernel, linux-arm-kernel, iommu, virtualization, joro,
	will.deacon, mst, robin.murphy, eric.auger, alex.williamson,
	kevin.tian, jacob.jun.pan, yi.l.liu, lorenzo.pieralisi,
	shameerali.kolothum.thodi

On Fri, Mar 12, 2021 at 06:17:55PM +0530, Vivek Kumar Gautam wrote:
> > Regarding the overall design, I was initially assigning page directories
> > instead of whole PASID tables, which would simplify the driver and host
> > implementation. A major complication, however, is SMMUv3 accesses PASID
> > tables using a guest-physical address, so there is a messy negotiation
> > needed between host and guest when the host needs to allocate PASID
> > tables. Plus vSMMU needs PASID table assignment, so that's what the host
> > driver will implement.
> 
> By assigning the page directories, you mean setting up just the stage-1 page
> table ops, and passing that information to the host using ATTACH_TABLE?

Yes. And we can support nested translation with SMMUv2 that way. But with
SMMUv3 the guest has to manage the whole PASID table.

> Right now when using kvmtool, the struct iommu_pasid_table_config is
> populated with the correct information, and this whole memory is mapped
> between host and guest by creating a mem bank using
> kvm__for_each_mem_bank().
> Did I get you or did I fail terribly in understanding the point you are
> making here?

Makes sense

Thanks,
Jean

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH RFC v1 15/15] iommu/virtio: Update fault type and reason info for viommu fault
  2021-03-29 16:23       ` Jean-Philippe Brucker
@ 2021-04-06  6:24         ` Vivek Kumar Gautam
  0 siblings, 0 replies; 44+ messages in thread
From: Vivek Kumar Gautam @ 2021-04-06  6:24 UTC (permalink / raw)
  To: Jean-Philippe Brucker
  Cc: linux-kernel, linux-arm-kernel, iommu, virtualization, joro,
	will.deacon, mst, robin.murphy, eric.auger, alex.williamson,
	kevin.tian, jacob.jun.pan, yi.l.liu, lorenzo.pieralisi,
	shameerali.kolothum.thodi



On 3/29/21 9:53 PM, Jean-Philippe Brucker wrote:
> On Fri, Mar 12, 2021 at 06:39:05PM +0530, Vivek Kumar Gautam wrote:
>> To complete the page request we would also need to send the response back to
>> the host from virtio backend when handling page request. So the virtio
>> command should also be accompanied with a vfio api to send the page request
>> response back to the host. Isn't it?
>> This is where the host smmuv3 can send PRI_RESP command to the device to
>> complete the page fault.
> 
> It looks like Eric already has this in the VFIO series:
> https://lore.kernel.org/linux-iommu/20210223210625.604517-14-eric.auger@redhat.com/

Right, I have taken this change to work on getting the vSVA with 
virtio-iommu.
For this I am adding a new request for virtio-iomm - 
VIRTIO_IOMMU_T_PAGE_RESP, and related struct virtio_iommu_req_page_resp 
that would contain information such as, pasid, grpid, response_code, 
flags, and endpoint. This is inline with struct iommu_page_response.
I will post out the patches for this soon.

Thanks & regards
Vivek

> 
> Thanks,
> Jean
> 

^ permalink raw reply	[flat|nested] 44+ messages in thread

end of thread, other threads:[~2021-04-06  6:24 UTC | newest]

Thread overview: 44+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-15 12:13 [PATCH RFC v1 00/15] iommu/virtio: Nested stage support with Arm Vivek Gautam
2021-01-15 12:13 ` [PATCH RFC v1 01/15] iommu/arm-smmu-v3: Create a Context Descriptor library Vivek Gautam
2021-01-15 12:13 ` [PATCH RFC v1 02/15] iommu: Add a simple PASID table library Vivek Gautam
2021-03-03 17:11   ` Jean-Philippe Brucker
2021-03-12 12:47     ` Vivek Kumar Gautam
2021-03-29 16:25       ` Jean-Philippe Brucker
2021-01-15 12:13 ` [PATCH RFC v1 03/15] iommu/arm-smmu-v3: Update drivers to work with iommu-pasid-table Vivek Gautam
2021-01-15 12:13 ` [PATCH RFC v1 04/15] iommu/arm-smmu-v3: Update CD base address info for user-space Vivek Gautam
2021-03-03 17:14   ` Jean-Philippe Brucker
2021-03-12 12:31     ` Vivek Kumar Gautam
2021-01-15 12:13 ` [PATCH RFC v1 05/15] iommu/arm-smmu-v3: Set sync op from consumer driver of cd-lib Vivek Gautam
2021-03-03 17:15   ` Jean-Philippe Brucker
2021-03-12 12:49     ` Vivek Kumar Gautam
2021-01-15 12:13 ` [PATCH RFC v1 06/15] iommu/virtio: Add headers for table format probing Vivek Gautam
2021-03-03 17:17   ` Jean-Philippe Brucker
2021-03-12 12:54     ` Vivek Kumar Gautam
2021-01-15 12:13 ` [PATCH RFC v1 07/15] iommu/virtio: Add " Vivek Gautam
2021-01-15 12:13 ` [PATCH RFC v1 08/15] iommu: Add asid_bits to arm smmu-v3 stage1 table info Vivek Gautam
2021-03-03 17:18   ` Jean-Philippe Brucker
2021-03-12 12:57     ` Vivek Kumar Gautam
2021-01-15 12:13 ` [PATCH RFC v1 09/15] iommu/virtio: Update table format probing header Vivek Gautam
2021-03-03 17:21   ` Jean-Philippe Brucker
2021-03-12 12:58     ` Vivek Kumar Gautam
2021-01-15 12:13 ` [PATCH RFC v1 10/15] iommu/virtio: Prepare to add attach pasid table infrastructure Vivek Gautam
2021-01-15 12:13 ` [PATCH RFC v1 11/15] iommu/virtio: Add headers for binding pasid table in iommu Vivek Gautam
2021-01-15 12:13 ` [PATCH RFC v1 12/15] iommu/virtio: Add support for INVALIDATE request Vivek Gautam
2021-03-03 18:28   ` Jacob Pan
2021-03-04  5:58     ` Tian, Kevin
2021-03-04  6:16       ` Vivek Kumar Gautam
2021-01-15 12:13 ` [PATCH RFC v1 13/15] iommu/virtio: Attach Arm PASID tables when available Vivek Gautam
2021-03-03 17:25   ` Jean-Philippe Brucker
2021-03-12 13:29     ` Vivek Kumar Gautam
2021-03-29 16:21       ` Jean-Philippe Brucker
2021-01-15 12:13 ` [PATCH RFC v1 14/15] iommu/virtio: Add support for Arm LPAE page table format Vivek Gautam
2021-01-15 12:13 ` [PATCH RFC v1 15/15] iommu/virtio: Update fault type and reason info for viommu fault Vivek Gautam
2021-03-03 17:25   ` Jean-Philippe Brucker
2021-03-12 13:09     ` Vivek Kumar Gautam
2021-03-29 16:23       ` Jean-Philippe Brucker
2021-04-06  6:24         ` Vivek Kumar Gautam
2021-01-19  9:03 ` [PATCH RFC v1 00/15] iommu/virtio: Nested stage support with Arm Auger Eric
2021-01-21 17:34   ` Vivek Kumar Gautam
2021-01-22 15:49     ` Shameerali Kolothum Thodi
2021-01-25 12:55       ` Vivek Kumar Gautam
2021-01-25  8:43     ` Auger Eric

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).