* [PATCH v7 1/8] iommufd: Add data structure for Intel VT-d stage-1 domain allocation
2023-10-24 15:14 [PATCH v7 0/8] Add Intel VT-d nested translation (part 1/2) Yi Liu
@ 2023-10-24 15:14 ` Yi Liu
2023-10-24 15:14 ` [PATCH v7 2/8] iommu/vt-d: Extend dmar_domain to support nested domain Yi Liu
` (7 subsequent siblings)
8 siblings, 0 replies; 18+ messages in thread
From: Yi Liu @ 2023-10-24 15:14 UTC (permalink / raw)
To: joro, alex.williamson, jgg, kevin.tian, robin.murphy, baolu.lu
Cc: cohuck, eric.auger, nicolinc, kvm, mjrosato, chao.p.peng,
yi.l.liu, yi.y.sun, peterx, jasowang, shameerali.kolothum.thodi,
lulu, suravee.suthikulpanit, iommu, linux-kernel, linux-kselftest,
zhenzhong.duan, joao.m.martins
This adds IOMMU_HWPT_DATA_VTD_S1 for stage-1 hw_pagetable of Intel
VT-d and the corressponding data structure for userspace specified parameter
for the domain allocation.
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Signed-off-by: Yi Liu <yi.l.liu@intel.com>
---
include/uapi/linux/iommufd.h | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/include/uapi/linux/iommufd.h b/include/uapi/linux/iommufd.h
index aa9282ebbc7e..3a66d3888393 100644
--- a/include/uapi/linux/iommufd.h
+++ b/include/uapi/linux/iommufd.h
@@ -362,12 +362,42 @@ enum iommufd_hwpt_alloc_flags {
IOMMU_HWPT_ALLOC_DIRTY_TRACKING = 1 << 1,
};
+/**
+ * enum iommu_hwpt_vtd_s1_flags - Intel VT-d stage-1 page table
+ * entry attributes
+ * @IOMMU_VTD_S1_SRE: Supervisor request
+ * @IOMMU_VTD_S1_EAFE: Extended access enable
+ * @IOMMU_VTD_S1_WPE: Write protect enable
+ */
+enum iommu_hwpt_vtd_s1_flags {
+ IOMMU_VTD_S1_SRE = 1 << 0,
+ IOMMU_VTD_S1_EAFE = 1 << 1,
+ IOMMU_VTD_S1_WPE = 1 << 2,
+};
+
+/**
+ * struct iommu_hwpt_vtd_s1 - Intel VT-d stage-1 page table
+ * info (IOMMU_HWPT_DATA_VTD_S1)
+ * @flags: Combination of enum iommu_hwpt_vtd_s1_flags
+ * @pgtbl_addr: The base address of the stage-1 page table.
+ * @addr_width: The address width of the stage-1 page table
+ * @__reserved: Must be 0
+ */
+struct iommu_hwpt_vtd_s1 {
+ __aligned_u64 flags;
+ __aligned_u64 pgtbl_addr;
+ __u32 addr_width;
+ __u32 __reserved;
+};
+
/**
* enum iommu_hwpt_data_type - IOMMU HWPT Data Type
* @IOMMU_HWPT_DATA_NONE: no data
+ * @IOMMU_HWPT_DATA_VTD_S1: Intel VT-d stage-1 page table
*/
enum iommu_hwpt_data_type {
IOMMU_HWPT_DATA_NONE,
+ IOMMU_HWPT_DATA_VTD_S1,
};
/**
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH v7 2/8] iommu/vt-d: Extend dmar_domain to support nested domain
2023-10-24 15:14 [PATCH v7 0/8] Add Intel VT-d nested translation (part 1/2) Yi Liu
2023-10-24 15:14 ` [PATCH v7 1/8] iommufd: Add data structure for Intel VT-d stage-1 domain allocation Yi Liu
@ 2023-10-24 15:14 ` Yi Liu
2023-10-24 15:14 ` [PATCH v7 3/8] iommu/vt-d: Add helper for nested domain allocation Yi Liu
` (6 subsequent siblings)
8 siblings, 0 replies; 18+ messages in thread
From: Yi Liu @ 2023-10-24 15:14 UTC (permalink / raw)
To: joro, alex.williamson, jgg, kevin.tian, robin.murphy, baolu.lu
Cc: cohuck, eric.auger, nicolinc, kvm, mjrosato, chao.p.peng,
yi.l.liu, yi.y.sun, peterx, jasowang, shameerali.kolothum.thodi,
lulu, suravee.suthikulpanit, iommu, linux-kernel, linux-kselftest,
zhenzhong.duan, joao.m.martins
From: Lu Baolu <baolu.lu@linux.intel.com>
The nested domain fields are exclusive to those that used for a DMA
remapping domain. Use union to avoid memory waste.
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
Signed-off-by: Yi Liu <yi.l.liu@intel.com>
---
drivers/iommu/intel/iommu.h | 36 ++++++++++++++++++++++++++++++------
1 file changed, 30 insertions(+), 6 deletions(-)
diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h
index cc7301579773..244f111ea0bb 100644
--- a/drivers/iommu/intel/iommu.h
+++ b/drivers/iommu/intel/iommu.h
@@ -25,6 +25,7 @@
#include <asm/cacheflush.h>
#include <asm/iommu.h>
+#include <uapi/linux/iommufd.h>
/*
* VT-d hardware uses 4KiB page size regardless of host page size.
@@ -605,15 +606,38 @@ struct dmar_domain {
struct list_head devices; /* all devices' list */
struct list_head dev_pasids; /* all attached pasids */
- struct dma_pte *pgd; /* virtual address */
- int gaw; /* max guest address width */
-
- /* adjusted guest address width, 0 is level 2 30-bit */
- int agaw;
int iommu_superpage;/* Level of superpages supported:
0 == 4KiB (no superpages), 1 == 2MiB,
2 == 1GiB, 3 == 512GiB, 4 == 1TiB */
- u64 max_addr; /* maximum mapped address */
+ union {
+ /* DMA remapping domain */
+ struct {
+ /* virtual address */
+ struct dma_pte *pgd;
+ /* max guest address width */
+ int gaw;
+ /*
+ * adjusted guest address width:
+ * 0: level 2 30-bit
+ * 1: level 3 39-bit
+ * 2: level 4 48-bit
+ * 3: level 5 57-bit
+ */
+ int agaw;
+ /* maximum mapped address */
+ u64 max_addr;
+ };
+
+ /* Nested user domain */
+ struct {
+ /* parent page table which the user domain is nested on */
+ struct dmar_domain *s2_domain;
+ /* user page table pointer (in GPA) */
+ unsigned long s1_pgtbl;
+ /* page table attributes */
+ struct iommu_hwpt_vtd_s1 s1_cfg;
+ };
+ };
struct iommu_domain domain; /* generic domain data structure for
iommu core */
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH v7 3/8] iommu/vt-d: Add helper for nested domain allocation
2023-10-24 15:14 [PATCH v7 0/8] Add Intel VT-d nested translation (part 1/2) Yi Liu
2023-10-24 15:14 ` [PATCH v7 1/8] iommufd: Add data structure for Intel VT-d stage-1 domain allocation Yi Liu
2023-10-24 15:14 ` [PATCH v7 2/8] iommu/vt-d: Extend dmar_domain to support nested domain Yi Liu
@ 2023-10-24 15:14 ` Yi Liu
2023-10-24 15:14 ` [PATCH v7 4/8] iommu/vt-d: Add helper to setup pasid nested translation Yi Liu
` (5 subsequent siblings)
8 siblings, 0 replies; 18+ messages in thread
From: Yi Liu @ 2023-10-24 15:14 UTC (permalink / raw)
To: joro, alex.williamson, jgg, kevin.tian, robin.murphy, baolu.lu
Cc: cohuck, eric.auger, nicolinc, kvm, mjrosato, chao.p.peng,
yi.l.liu, yi.y.sun, peterx, jasowang, shameerali.kolothum.thodi,
lulu, suravee.suthikulpanit, iommu, linux-kernel, linux-kselftest,
zhenzhong.duan, joao.m.martins, Jacob Pan
From: Lu Baolu <baolu.lu@linux.intel.com>
This adds helper for accepting user parameters and allocate a nested
domain.
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com>
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
Signed-off-by: Yi Liu <yi.l.liu@intel.com>
---
drivers/iommu/intel/Makefile | 2 +-
drivers/iommu/intel/iommu.h | 2 ++
drivers/iommu/intel/nested.c | 55 ++++++++++++++++++++++++++++++++++++
3 files changed, 58 insertions(+), 1 deletion(-)
create mode 100644 drivers/iommu/intel/nested.c
diff --git a/drivers/iommu/intel/Makefile b/drivers/iommu/intel/Makefile
index 7af3b8a4f2a0..5dabf081a779 100644
--- a/drivers/iommu/intel/Makefile
+++ b/drivers/iommu/intel/Makefile
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_DMAR_TABLE) += dmar.o
-obj-$(CONFIG_INTEL_IOMMU) += iommu.o pasid.o
+obj-$(CONFIG_INTEL_IOMMU) += iommu.o pasid.o nested.o
obj-$(CONFIG_DMAR_TABLE) += trace.o cap_audit.o
obj-$(CONFIG_DMAR_PERF) += perf.o
obj-$(CONFIG_INTEL_IOMMU_DEBUGFS) += debugfs.o
diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h
index 244f111ea0bb..43108424f315 100644
--- a/drivers/iommu/intel/iommu.h
+++ b/drivers/iommu/intel/iommu.h
@@ -884,6 +884,8 @@ void *alloc_pgtable_page(int node, gfp_t gfp);
void free_pgtable_page(void *vaddr);
void iommu_flush_write_buffer(struct intel_iommu *iommu);
struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devfn);
+struct iommu_domain *intel_nested_domain_alloc(struct iommu_domain *s2_domain,
+ const struct iommu_user_data *user_data);
#ifdef CONFIG_INTEL_IOMMU_SVM
void intel_svm_check(struct intel_iommu *iommu);
diff --git a/drivers/iommu/intel/nested.c b/drivers/iommu/intel/nested.c
new file mode 100644
index 000000000000..859c60bead05
--- /dev/null
+++ b/drivers/iommu/intel/nested.c
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * nested.c - nested mode translation support
+ *
+ * Copyright (C) 2023 Intel Corporation
+ *
+ * Author: Lu Baolu <baolu.lu@linux.intel.com>
+ * Jacob Pan <jacob.jun.pan@linux.intel.com>
+ * Yi Liu <yi.l.liu@intel.com>
+ */
+
+#define pr_fmt(fmt) "DMAR: " fmt
+
+#include <linux/iommu.h>
+
+#include "iommu.h"
+
+static void intel_nested_domain_free(struct iommu_domain *domain)
+{
+ kfree(to_dmar_domain(domain));
+}
+
+static const struct iommu_domain_ops intel_nested_domain_ops = {
+ .free = intel_nested_domain_free,
+};
+
+struct iommu_domain *intel_nested_domain_alloc(struct iommu_domain *s2_domain,
+ const struct iommu_user_data *user_data)
+{
+ struct iommu_hwpt_vtd_s1 vtd;
+ struct dmar_domain *domain;
+ int ret;
+
+ ret = iommu_copy_struct_from_user(&vtd, user_data,
+ IOMMU_HWPT_DATA_VTD_S1, __reserved);
+ if (ret)
+ return ERR_PTR(ret);
+
+ domain = kzalloc(sizeof(*domain), GFP_KERNEL_ACCOUNT);
+ if (!domain)
+ return ERR_PTR(-ENOMEM);
+
+ domain->use_first_level = true;
+ domain->s2_domain = to_dmar_domain(s2_domain);
+ domain->s1_pgtbl = vtd.pgtbl_addr;
+ domain->s1_cfg = vtd;
+ domain->domain.ops = &intel_nested_domain_ops;
+ domain->domain.type = IOMMU_DOMAIN_NESTED;
+ INIT_LIST_HEAD(&domain->devices);
+ INIT_LIST_HEAD(&domain->dev_pasids);
+ spin_lock_init(&domain->lock);
+ xa_init(&domain->iommu_array);
+
+ return &domain->domain;
+}
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH v7 4/8] iommu/vt-d: Add helper to setup pasid nested translation
2023-10-24 15:14 [PATCH v7 0/8] Add Intel VT-d nested translation (part 1/2) Yi Liu
` (2 preceding siblings ...)
2023-10-24 15:14 ` [PATCH v7 3/8] iommu/vt-d: Add helper for nested domain allocation Yi Liu
@ 2023-10-24 15:14 ` Yi Liu
2023-10-24 15:14 ` [PATCH v7 5/8] iommu/vt-d: Make domain attach helpers to be extern Yi Liu
` (4 subsequent siblings)
8 siblings, 0 replies; 18+ messages in thread
From: Yi Liu @ 2023-10-24 15:14 UTC (permalink / raw)
To: joro, alex.williamson, jgg, kevin.tian, robin.murphy, baolu.lu
Cc: cohuck, eric.auger, nicolinc, kvm, mjrosato, chao.p.peng,
yi.l.liu, yi.y.sun, peterx, jasowang, shameerali.kolothum.thodi,
lulu, suravee.suthikulpanit, iommu, linux-kernel, linux-kselftest,
zhenzhong.duan, joao.m.martins, Jacob Pan
From: Lu Baolu <baolu.lu@linux.intel.com>
The configurations are passed in from the user when the user domain is
allocated. This helper interprets these configurations according to the
data structure defined in uapi/linux/iommufd.h. The EINVAL error will be
returned if any of configurations are not compatible with the hardware
capabilities. The caller can retry with another compatible user domain.
The encoding of fields of each pasid entry is defined in section 9.6 of
the VT-d spec.
Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com>
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
Signed-off-by: Yi Liu <yi.l.liu@intel.com>
---
drivers/iommu/intel/pasid.c | 112 ++++++++++++++++++++++++++++++++++++
drivers/iommu/intel/pasid.h | 2 +
2 files changed, 114 insertions(+)
diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
index b9264b9174e8..74e8e4c17e81 100644
--- a/drivers/iommu/intel/pasid.c
+++ b/drivers/iommu/intel/pasid.c
@@ -370,6 +370,15 @@ static inline bool pasid_get_ssade(struct pasid_entry *pe)
return pasid_get_bits(&pe->val[0]) & (1 << 9);
}
+/*
+ * Setup the SRE(Supervisor Request Enable) field (Bit 128) of a
+ * scalable mode PASID entry.
+ */
+static inline void pasid_set_sre(struct pasid_entry *pe)
+{
+ pasid_set_bits(&pe->val[2], 1 << 0, 1);
+}
+
/*
* Setup the WPE(Write Protect Enable) field (Bit 132) of a
* scalable mode PASID entry.
@@ -437,6 +446,15 @@ pasid_set_flpm(struct pasid_entry *pe, u64 value)
pasid_set_bits(&pe->val[2], GENMASK_ULL(3, 2), value << 2);
}
+/*
+ * Setup the Extended Access Flag Enable (EAFE) field (Bit 135)
+ * of a scalable mode PASID entry.
+ */
+static inline void pasid_set_eafe(struct pasid_entry *pe)
+{
+ pasid_set_bits(&pe->val[2], 1 << 7, 1 << 7);
+}
+
static void
pasid_cache_invalidation_with_pasid(struct intel_iommu *iommu,
u16 did, u32 pasid)
@@ -822,3 +840,97 @@ void intel_pasid_setup_page_snoop_control(struct intel_iommu *iommu,
if (!cap_caching_mode(iommu->cap))
devtlb_invalidation_with_pasid(iommu, dev, pasid);
}
+
+/**
+ * intel_pasid_setup_nested() - Set up PASID entry for nested translation.
+ * @iommu: IOMMU which the device belong to
+ * @dev: Device to be set up for translation
+ * @pasid: PASID to be programmed in the device PASID table
+ * @domain: User stage-1 domain nested on a stage-2 domain
+ *
+ * This is used for nested translation. The input domain should be
+ * nested type and nested on a parent with 'is_nested_parent' flag
+ * set.
+ */
+int intel_pasid_setup_nested(struct intel_iommu *iommu, struct device *dev,
+ u32 pasid, struct dmar_domain *domain)
+{
+ struct iommu_hwpt_vtd_s1 *s1_cfg = &domain->s1_cfg;
+ pgd_t *s1_gpgd = (pgd_t *)(uintptr_t)domain->s1_pgtbl;
+ struct dmar_domain *s2_domain = domain->s2_domain;
+ u16 did = domain_id_iommu(domain, iommu);
+ struct dma_pte *pgd = s2_domain->pgd;
+ struct pasid_entry *pte;
+
+ /* Address width should match the address width supported by hardware */
+ switch (s1_cfg->addr_width) {
+ case ADDR_WIDTH_4LEVEL:
+ break;
+ case ADDR_WIDTH_5LEVEL:
+ if (!cap_fl5lp_support(iommu->cap)) {
+ dev_err_ratelimited(dev,
+ "5-level paging not supported\n");
+ return -EINVAL;
+ }
+ break;
+ default:
+ dev_err_ratelimited(dev, "Invalid stage-1 address width %d\n",
+ s1_cfg->addr_width);
+ return -EINVAL;
+ }
+
+ if ((s1_cfg->flags & IOMMU_VTD_S1_SRE) && !ecap_srs(iommu->ecap)) {
+ pr_err_ratelimited("No supervisor request support on %s\n",
+ iommu->name);
+ return -EINVAL;
+ }
+
+ if ((s1_cfg->flags & IOMMU_VTD_S1_EAFE) && !ecap_eafs(iommu->ecap)) {
+ pr_err_ratelimited("No extended access flag support on %s\n",
+ iommu->name);
+ return -EINVAL;
+ }
+
+ spin_lock(&iommu->lock);
+ pte = intel_pasid_get_entry(dev, pasid);
+ if (!pte) {
+ spin_unlock(&iommu->lock);
+ return -ENODEV;
+ }
+ if (pasid_pte_is_present(pte)) {
+ spin_unlock(&iommu->lock);
+ return -EBUSY;
+ }
+
+ pasid_clear_entry(pte);
+
+ if (s1_cfg->addr_width == ADDR_WIDTH_5LEVEL)
+ pasid_set_flpm(pte, 1);
+
+ pasid_set_flptr(pte, (uintptr_t)s1_gpgd);
+
+ if (s1_cfg->flags & IOMMU_VTD_S1_SRE) {
+ pasid_set_sre(pte);
+ if (s1_cfg->flags & IOMMU_VTD_S1_WPE)
+ pasid_set_wpe(pte);
+ }
+
+ if (s1_cfg->flags & IOMMU_VTD_S1_EAFE)
+ pasid_set_eafe(pte);
+
+ if (s2_domain->force_snooping)
+ pasid_set_pgsnp(pte);
+
+ pasid_set_slptr(pte, virt_to_phys(pgd));
+ pasid_set_fault_enable(pte);
+ pasid_set_domain_id(pte, did);
+ pasid_set_address_width(pte, s2_domain->agaw);
+ pasid_set_page_snoop(pte, !!ecap_smpwc(iommu->ecap));
+ pasid_set_translation_type(pte, PASID_ENTRY_PGTT_NESTED);
+ pasid_set_present(pte);
+ spin_unlock(&iommu->lock);
+
+ pasid_flush_caches(iommu, pte, pasid, did);
+
+ return 0;
+}
diff --git a/drivers/iommu/intel/pasid.h b/drivers/iommu/intel/pasid.h
index 958050b093aa..dd37611175cc 100644
--- a/drivers/iommu/intel/pasid.h
+++ b/drivers/iommu/intel/pasid.h
@@ -113,6 +113,8 @@ int intel_pasid_setup_dirty_tracking(struct intel_iommu *iommu,
int intel_pasid_setup_pass_through(struct intel_iommu *iommu,
struct dmar_domain *domain,
struct device *dev, u32 pasid);
+int intel_pasid_setup_nested(struct intel_iommu *iommu, struct device *dev,
+ u32 pasid, struct dmar_domain *domain);
void intel_pasid_tear_down_entry(struct intel_iommu *iommu,
struct device *dev, u32 pasid,
bool fault_ignore);
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH v7 5/8] iommu/vt-d: Make domain attach helpers to be extern
2023-10-24 15:14 [PATCH v7 0/8] Add Intel VT-d nested translation (part 1/2) Yi Liu
` (3 preceding siblings ...)
2023-10-24 15:14 ` [PATCH v7 4/8] iommu/vt-d: Add helper to setup pasid nested translation Yi Liu
@ 2023-10-24 15:14 ` Yi Liu
2023-10-24 15:14 ` [PATCH v7 6/8] iommu/vt-d: Set the nested domain to a device Yi Liu
` (3 subsequent siblings)
8 siblings, 0 replies; 18+ messages in thread
From: Yi Liu @ 2023-10-24 15:14 UTC (permalink / raw)
To: joro, alex.williamson, jgg, kevin.tian, robin.murphy, baolu.lu
Cc: cohuck, eric.auger, nicolinc, kvm, mjrosato, chao.p.peng,
yi.l.liu, yi.y.sun, peterx, jasowang, shameerali.kolothum.thodi,
lulu, suravee.suthikulpanit, iommu, linux-kernel, linux-kselftest,
zhenzhong.duan, joao.m.martins
This makes the helpers visible to nested.c.
Suggested-by: Lu Baolu <baolu.lu@linux.intel.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
Signed-off-by: Yi Liu <yi.l.liu@intel.com>
---
drivers/iommu/intel/iommu.c | 15 ++++++---------
drivers/iommu/intel/iommu.h | 7 +++++++
2 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index cb64759b3d95..292baa64188b 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -282,7 +282,6 @@ static LIST_HEAD(dmar_satc_units);
#define for_each_rmrr_units(rmrr) \
list_for_each_entry(rmrr, &dmar_rmrr_units, list)
-static void device_block_translation(struct device *dev);
static void intel_iommu_domain_free(struct iommu_domain *domain);
int dmar_disabled = !IS_ENABLED(CONFIG_INTEL_IOMMU_DEFAULT_ON);
@@ -561,7 +560,7 @@ static unsigned long domain_super_pgsize_bitmap(struct dmar_domain *domain)
}
/* Some capabilities may be different across iommus */
-static void domain_update_iommu_cap(struct dmar_domain *domain)
+void domain_update_iommu_cap(struct dmar_domain *domain)
{
domain_update_iommu_coherency(domain);
domain->iommu_superpage = domain_update_iommu_superpage(domain, NULL);
@@ -1779,8 +1778,7 @@ static struct dmar_domain *alloc_domain(unsigned int type)
return domain;
}
-static int domain_attach_iommu(struct dmar_domain *domain,
- struct intel_iommu *iommu)
+int domain_attach_iommu(struct dmar_domain *domain, struct intel_iommu *iommu)
{
struct iommu_domain_info *info, *curr;
unsigned long ndomains;
@@ -1829,8 +1827,7 @@ static int domain_attach_iommu(struct dmar_domain *domain,
return ret;
}
-static void domain_detach_iommu(struct dmar_domain *domain,
- struct intel_iommu *iommu)
+void domain_detach_iommu(struct dmar_domain *domain, struct intel_iommu *iommu)
{
struct iommu_domain_info *info;
@@ -3975,7 +3972,7 @@ static void dmar_remove_one_dev_info(struct device *dev)
* all DMA requests without PASID from the device are blocked. If the page
* table has been set, clean up the data structures.
*/
-static void device_block_translation(struct device *dev)
+void device_block_translation(struct device *dev)
{
struct device_domain_info *info = dev_iommu_priv_get(dev);
struct intel_iommu *iommu = info->iommu;
@@ -4128,8 +4125,8 @@ static void intel_iommu_domain_free(struct iommu_domain *domain)
domain_exit(to_dmar_domain(domain));
}
-static int prepare_domain_attach_device(struct iommu_domain *domain,
- struct device *dev)
+int prepare_domain_attach_device(struct iommu_domain *domain,
+ struct device *dev)
{
struct dmar_domain *dmar_domain = to_dmar_domain(domain);
struct intel_iommu *iommu;
diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h
index 43108424f315..d5aaaedf2094 100644
--- a/drivers/iommu/intel/iommu.h
+++ b/drivers/iommu/intel/iommu.h
@@ -878,6 +878,13 @@ int qi_submit_sync(struct intel_iommu *iommu, struct qi_desc *desc,
*/
#define QI_OPT_WAIT_DRAIN BIT(0)
+int domain_attach_iommu(struct dmar_domain *domain, struct intel_iommu *iommu);
+void domain_detach_iommu(struct dmar_domain *domain, struct intel_iommu *iommu);
+void device_block_translation(struct device *dev);
+int prepare_domain_attach_device(struct iommu_domain *domain,
+ struct device *dev);
+void domain_update_iommu_cap(struct dmar_domain *domain);
+
int dmar_ir_support(void);
void *alloc_pgtable_page(int node, gfp_t gfp);
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH v7 6/8] iommu/vt-d: Set the nested domain to a device
2023-10-24 15:14 [PATCH v7 0/8] Add Intel VT-d nested translation (part 1/2) Yi Liu
` (4 preceding siblings ...)
2023-10-24 15:14 ` [PATCH v7 5/8] iommu/vt-d: Make domain attach helpers to be extern Yi Liu
@ 2023-10-24 15:14 ` Yi Liu
2023-10-25 7:33 ` Tian, Kevin
2023-10-24 15:14 ` [PATCH v7 7/8] iommu/vt-d: Add nested domain allocation Yi Liu
` (2 subsequent siblings)
8 siblings, 1 reply; 18+ messages in thread
From: Yi Liu @ 2023-10-24 15:14 UTC (permalink / raw)
To: joro, alex.williamson, jgg, kevin.tian, robin.murphy, baolu.lu
Cc: cohuck, eric.auger, nicolinc, kvm, mjrosato, chao.p.peng,
yi.l.liu, yi.y.sun, peterx, jasowang, shameerali.kolothum.thodi,
lulu, suravee.suthikulpanit, iommu, linux-kernel, linux-kselftest,
zhenzhong.duan, joao.m.martins, Jacob Pan
This adds the helper for setting the nested domain to a device hence
enable nested domain usage on Intel VT-d.
Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com>
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
Signed-off-by: Yi Liu <yi.l.liu@intel.com>
---
drivers/iommu/intel/nested.c | 54 ++++++++++++++++++++++++++++++++++++
1 file changed, 54 insertions(+)
diff --git a/drivers/iommu/intel/nested.c b/drivers/iommu/intel/nested.c
index 859c60bead05..d9197dd72748 100644
--- a/drivers/iommu/intel/nested.c
+++ b/drivers/iommu/intel/nested.c
@@ -12,8 +12,61 @@
#define pr_fmt(fmt) "DMAR: " fmt
#include <linux/iommu.h>
+#include <linux/pci.h>
+#include <linux/pci-ats.h>
#include "iommu.h"
+#include "pasid.h"
+
+static int intel_nested_attach_dev(struct iommu_domain *domain,
+ struct device *dev)
+{
+ struct device_domain_info *info = dev_iommu_priv_get(dev);
+ struct dmar_domain *dmar_domain = to_dmar_domain(domain);
+ struct intel_iommu *iommu = info->iommu;
+ unsigned long flags;
+ int ret = 0;
+
+ if (info->domain)
+ device_block_translation(dev);
+
+ if (iommu->agaw < dmar_domain->s2_domain->agaw) {
+ dev_err_ratelimited(dev, "Adjusted guest address width not compatible\n");
+ return -ENODEV;
+ }
+
+ /*
+ * Stage-1 domain cannot work alone, it is nested on a s2_domain.
+ * The s2_domain will be used in nested translation, hence needs
+ * to ensure the s2_domain is compatible with this IOMMU.
+ */
+ ret = prepare_domain_attach_device(&dmar_domain->s2_domain->domain, dev);
+ if (ret) {
+ dev_err_ratelimited(dev, "s2 domain is not compatible\n");
+ return ret;
+ }
+
+ ret = domain_attach_iommu(dmar_domain, iommu);
+ if (ret) {
+ dev_err_ratelimited(dev, "Failed to attach domain to iommu\n");
+ return ret;
+ }
+
+ ret = intel_pasid_setup_nested(iommu, dev,
+ IOMMU_NO_PASID, dmar_domain);
+ if (ret) {
+ domain_detach_iommu(dmar_domain, iommu);
+ dev_err_ratelimited(dev, "Failed to setup pasid entry\n");
+ return ret;
+ }
+
+ info->domain = dmar_domain;
+ spin_lock_irqsave(&dmar_domain->lock, flags);
+ list_add(&info->link, &dmar_domain->devices);
+ spin_unlock_irqrestore(&dmar_domain->lock, flags);
+
+ return 0;
+}
static void intel_nested_domain_free(struct iommu_domain *domain)
{
@@ -21,6 +74,7 @@ static void intel_nested_domain_free(struct iommu_domain *domain)
}
static const struct iommu_domain_ops intel_nested_domain_ops = {
+ .attach_dev = intel_nested_attach_dev,
.free = intel_nested_domain_free,
};
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* RE: [PATCH v7 6/8] iommu/vt-d: Set the nested domain to a device
2023-10-24 15:14 ` [PATCH v7 6/8] iommu/vt-d: Set the nested domain to a device Yi Liu
@ 2023-10-25 7:33 ` Tian, Kevin
0 siblings, 0 replies; 18+ messages in thread
From: Tian, Kevin @ 2023-10-25 7:33 UTC (permalink / raw)
To: Liu, Yi L, joro@8bytes.org, alex.williamson@redhat.com,
jgg@nvidia.com, robin.murphy@arm.com, baolu.lu@linux.intel.com
Cc: cohuck@redhat.com, eric.auger@redhat.com, nicolinc@nvidia.com,
kvm@vger.kernel.org, mjrosato@linux.ibm.com,
chao.p.peng@linux.intel.com, yi.y.sun@linux.intel.com,
peterx@redhat.com, jasowang@redhat.com,
shameerali.kolothum.thodi@huawei.com, lulu@redhat.com,
suravee.suthikulpanit@amd.com, iommu@lists.linux.dev,
linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org,
Duan, Zhenzhong, Martins, Joao, Jacob Pan
> From: Liu, Yi L <yi.l.liu@intel.com>
> Sent: Tuesday, October 24, 2023 11:14 PM
>
> This adds the helper for setting the nested domain to a device hence
> enable nested domain usage on Intel VT-d.
>
> Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com>
> Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
> Signed-off-by: Yi Liu <yi.l.liu@intel.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v7 7/8] iommu/vt-d: Add nested domain allocation
2023-10-24 15:14 [PATCH v7 0/8] Add Intel VT-d nested translation (part 1/2) Yi Liu
` (5 preceding siblings ...)
2023-10-24 15:14 ` [PATCH v7 6/8] iommu/vt-d: Set the nested domain to a device Yi Liu
@ 2023-10-24 15:14 ` Yi Liu
2023-10-24 23:03 ` Jason Gunthorpe
2023-10-24 15:14 ` [PATCH v7 8/8] iommu/vt-d: Disallow read-only mappings to nest parent domain Yi Liu
2023-10-25 12:07 ` [PATCH v7 0/8] Add Intel VT-d nested translation (part 1/2) Jason Gunthorpe
8 siblings, 1 reply; 18+ messages in thread
From: Yi Liu @ 2023-10-24 15:14 UTC (permalink / raw)
To: joro, alex.williamson, jgg, kevin.tian, robin.murphy, baolu.lu
Cc: cohuck, eric.auger, nicolinc, kvm, mjrosato, chao.p.peng,
yi.l.liu, yi.y.sun, peterx, jasowang, shameerali.kolothum.thodi,
lulu, suravee.suthikulpanit, iommu, linux-kernel, linux-kselftest,
zhenzhong.duan, joao.m.martins
From: Lu Baolu <baolu.lu@linux.intel.com>
This adds the support for IOMMU_HWPT_DATA_VTD_S1 type. And 'nested_parent'
is added to mark the nested parent domain to sanitize the input parent domain.
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
Signed-off-by: Yi Liu <yi.l.liu@intel.com>
---
drivers/iommu/intel/iommu.c | 67 +++++++++++++++++++++++++------------
drivers/iommu/intel/iommu.h | 1 +
2 files changed, 46 insertions(+), 22 deletions(-)
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 292baa64188b..85366862fb5e 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -4077,46 +4077,69 @@ intel_iommu_domain_alloc_user(struct device *dev, u32 flags,
struct iommu_domain *parent,
const struct iommu_user_data *user_data)
{
- struct iommu_domain *domain;
struct intel_iommu *iommu;
bool dirty_tracking;
+ bool nested_parent;
if (flags &
(~(IOMMU_HWPT_ALLOC_NEST_PARENT | IOMMU_HWPT_ALLOC_DIRTY_TRACKING)))
return ERR_PTR(-EOPNOTSUPP);
- if (parent || user_data)
- return ERR_PTR(-EOPNOTSUPP);
-
iommu = device_to_iommu(dev, NULL, NULL);
if (!iommu)
return ERR_PTR(-ENODEV);
- if ((flags & IOMMU_HWPT_ALLOC_NEST_PARENT) && !nested_supported(iommu))
- return ERR_PTR(-EOPNOTSUPP);
-
+ nested_parent = flags & IOMMU_HWPT_ALLOC_NEST_PARENT;
dirty_tracking = (flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING);
- if (dirty_tracking && !ssads_supported(iommu))
- return ERR_PTR(-EOPNOTSUPP);
- /*
- * domain_alloc_user op needs to fully initialize a domain
- * before return, so uses iommu_domain_alloc() here for
- * simple.
- */
- domain = iommu_domain_alloc(dev->bus);
- if (!domain)
- domain = ERR_PTR(-ENOMEM);
+ if (!user_data) { /* Must be PAGING domain */
+ struct iommu_domain *domain;
- if (!IS_ERR(domain) && dirty_tracking) {
- if (to_dmar_domain(domain)->use_first_level) {
- iommu_domain_free(domain);
+ if (nested_parent && !nested_supported(iommu))
return ERR_PTR(-EOPNOTSUPP);
+ if (dirty_tracking && !ssads_supported(iommu))
+ return ERR_PTR(-EOPNOTSUPP);
+ if (parent)
+ return ERR_PTR(-EINVAL);
+
+ /*
+ * domain_alloc_user op needs to fully initialize a domain
+ * before return, so uses iommu_domain_alloc() here for
+ * simple.
+ */
+ domain = iommu_domain_alloc(dev->bus);
+ if (!domain)
+ return ERR_PTR(-ENOMEM);
+
+ if (nested_parent)
+ to_dmar_domain(domain)->nested_parent = true;
+
+ if (dirty_tracking) {
+ if (to_dmar_domain(domain)->use_first_level) {
+ iommu_domain_free(domain);
+ return ERR_PTR(-EOPNOTSUPP);
+ }
+ domain->dirty_ops = &intel_dirty_ops;
}
- domain->dirty_ops = &intel_dirty_ops;
+
+ return domain;
}
- return domain;
+ /* Must be nested domain */
+ if (user_data->type != IOMMU_HWPT_DATA_VTD_S1)
+ return ERR_PTR(-EOPNOTSUPP);
+ if (!nested_supported(iommu))
+ return ERR_PTR(-EOPNOTSUPP);
+ if (!parent || parent->ops != intel_iommu_ops.default_domain_ops)
+ return ERR_PTR(-EINVAL);
+ if (!to_dmar_domain(parent)->nested_parent)
+ return ERR_PTR(-EINVAL);
+ if (nested_parent)
+ return ERR_PTR(-EINVAL);
+ if (dirty_tracking)
+ return ERR_PTR(-EINVAL);
+
+ return intel_nested_domain_alloc(parent, user_data);
}
static void intel_iommu_domain_free(struct iommu_domain *domain)
diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h
index d5aaaedf2094..65e660eb1f47 100644
--- a/drivers/iommu/intel/iommu.h
+++ b/drivers/iommu/intel/iommu.h
@@ -601,6 +601,7 @@ struct dmar_domain {
* level.
*/
u8 dirty_tracking:1; /* Dirty tracking is enabled */
+ u8 nested_parent:1; /* Has other domains nested on it */
spinlock_t lock; /* Protect device tracking lists */
struct list_head devices; /* all devices' list */
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [PATCH v7 7/8] iommu/vt-d: Add nested domain allocation
2023-10-24 15:14 ` [PATCH v7 7/8] iommu/vt-d: Add nested domain allocation Yi Liu
@ 2023-10-24 23:03 ` Jason Gunthorpe
2023-10-25 7:34 ` Tian, Kevin
2023-10-25 9:02 ` Yi Liu
0 siblings, 2 replies; 18+ messages in thread
From: Jason Gunthorpe @ 2023-10-24 23:03 UTC (permalink / raw)
To: Yi Liu
Cc: joro, alex.williamson, kevin.tian, robin.murphy, baolu.lu, cohuck,
eric.auger, nicolinc, kvm, mjrosato, chao.p.peng, yi.y.sun,
peterx, jasowang, shameerali.kolothum.thodi, lulu,
suravee.suthikulpanit, iommu, linux-kernel, linux-kselftest,
zhenzhong.duan, joao.m.martins
On Tue, Oct 24, 2023 at 08:14:11AM -0700, Yi Liu wrote:
> From: Lu Baolu <baolu.lu@linux.intel.com>
>
> This adds the support for IOMMU_HWPT_DATA_VTD_S1 type. And 'nested_parent'
> is added to mark the nested parent domain to sanitize the input parent domain.
>
> Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
> Signed-off-by: Yi Liu <yi.l.liu@intel.com>
> ---
> drivers/iommu/intel/iommu.c | 67 +++++++++++++++++++++++++------------
> drivers/iommu/intel/iommu.h | 1 +
> 2 files changed, 46 insertions(+), 22 deletions(-)
I think it should be written like this:
@@ -4077,38 +4082,39 @@ intel_iommu_domain_alloc_user(struct device *dev, u32 flags,
struct iommu_domain *parent,
const struct iommu_user_data *user_data)
{
+ struct device_domain_info *info = dev_iommu_priv_get(dev);
+ bool dirty_tracking = flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING;
+ bool nested_parent = flags & IOMMU_HWPT_ALLOC_NEST_PARENT;
+ struct intel_iommu *iommu = info->iommu;
struct iommu_domain *domain;
- struct intel_iommu *iommu;
- bool dirty_tracking;
+
+ /* Must be NESTING domain */
+ if (parent) {
+ if (!nested_supported(iommu) || flags)
+ return ERR_PTR(-EOPNOTSUPP);
+ return intel_nested_domain_alloc(parent, user_data);
+ }
if (flags &
(~(IOMMU_HWPT_ALLOC_NEST_PARENT | IOMMU_HWPT_ALLOC_DIRTY_TRACKING)))
return ERR_PTR(-EOPNOTSUPP);
-
- if (parent || user_data)
+ if (nested_parent && !nested_supported(iommu))
return ERR_PTR(-EOPNOTSUPP);
-
- iommu = device_to_iommu(dev, NULL, NULL);
- if (!iommu)
- return ERR_PTR(-ENODEV);
-
- if ((flags & IOMMU_HWPT_ALLOC_NEST_PARENT) && !nested_supported(iommu))
- return ERR_PTR(-EOPNOTSUPP);
-
- dirty_tracking = (flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING);
- if (dirty_tracking && !ssads_supported(iommu))
+ if (user_data || (dirty_tracking && !ssads_supported(iommu)))
return ERR_PTR(-EOPNOTSUPP);
/*
- * domain_alloc_user op needs to fully initialize a domain
- * before return, so uses iommu_domain_alloc() here for
- * simple.
+ * domain_alloc_user op needs to fully initialize a domain before
+ * return, so uses iommu_domain_alloc() here for simple.
*/
domain = iommu_domain_alloc(dev->bus);
if (!domain)
- domain = ERR_PTR(-ENOMEM);
+ return ERR_PTR(-ENOMEM);
- if (!IS_ERR(domain) && dirty_tracking) {
+ if (nested_parent)
+ to_dmar_domain(domain)->nested_parent = true;
+
+ if (dirty_tracking) {
if (to_dmar_domain(domain)->use_first_level) {
iommu_domain_free(domain);
return ERR_PTR(-EOPNOTSUPP);
@@ -4849,6 +4855,7 @@ static void *intel_iommu_hw_info(struct device *dev, u32 *length, u32 *type)
if (!vtd)
return ERR_PTR(-ENOMEM);
+ vtd->flags = IOMMU_HW_INFO_VTD_ERRATA_772415_SPR17;
vtd->cap_reg = iommu->cap;
vtd->ecap_reg = iommu->ecap;
*length = sizeof(*vtd);
diff --git a/drivers/iommu/intel/nested.c b/drivers/iommu/intel/nested.c
index d9197dd72748b1..b5a5563ab32c6b 100644
--- a/drivers/iommu/intel/nested.c
+++ b/drivers/iommu/intel/nested.c
@@ -78,13 +78,21 @@ static const struct iommu_domain_ops intel_nested_domain_ops = {
.free = intel_nested_domain_free,
};
-struct iommu_domain *intel_nested_domain_alloc(struct iommu_domain *s2_domain,
+struct iommu_domain *intel_nested_domain_alloc(struct iommu_domain *parent,
const struct iommu_user_data *user_data)
{
+ struct dmar_domain *s2_domain = to_dmar_domain(parent);
struct iommu_hwpt_vtd_s1 vtd;
struct dmar_domain *domain;
int ret;
+ /* Must be nested domain */
+ if (user_data->type != IOMMU_HWPT_DATA_VTD_S1)
+ return ERR_PTR(-EOPNOTSUPP);
+ if (parent->ops != intel_iommu_ops.default_domain_ops ||
+ !s2_domain->nested_parent)
+ return ERR_PTR(-EINVAL);
+
ret = iommu_copy_struct_from_user(&vtd, user_data,
IOMMU_HWPT_DATA_VTD_S1, __reserved);
if (ret)
@@ -95,7 +103,7 @@ struct iommu_domain *intel_nested_domain_alloc(struct iommu_domain *s2_domain,
return ERR_PTR(-ENOMEM);
domain->use_first_level = true;
- domain->s2_domain = to_dmar_domain(s2_domain);
+ domain->s2_domain = s2_domain;
domain->s1_pgtbl = vtd.pgtbl_addr;
domain->s1_cfg = vtd;
domain->domain.ops = &intel_nested_domain_ops;
^ permalink raw reply related [flat|nested] 18+ messages in thread* RE: [PATCH v7 7/8] iommu/vt-d: Add nested domain allocation
2023-10-24 23:03 ` Jason Gunthorpe
@ 2023-10-25 7:34 ` Tian, Kevin
2023-10-25 11:49 ` Jason Gunthorpe
2023-10-25 9:02 ` Yi Liu
1 sibling, 1 reply; 18+ messages in thread
From: Tian, Kevin @ 2023-10-25 7:34 UTC (permalink / raw)
To: Jason Gunthorpe, Liu, Yi L
Cc: joro@8bytes.org, alex.williamson@redhat.com, robin.murphy@arm.com,
baolu.lu@linux.intel.com, cohuck@redhat.com,
eric.auger@redhat.com, nicolinc@nvidia.com, kvm@vger.kernel.org,
mjrosato@linux.ibm.com, chao.p.peng@linux.intel.com,
yi.y.sun@linux.intel.com, peterx@redhat.com, jasowang@redhat.com,
shameerali.kolothum.thodi@huawei.com, lulu@redhat.com,
suravee.suthikulpanit@amd.com, iommu@lists.linux.dev,
linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org,
Duan, Zhenzhong, Martins, Joao
> From: Jason Gunthorpe <jgg@nvidia.com>
> Sent: Wednesday, October 25, 2023 7:03 AM
>
> @@ -4849,6 +4855,7 @@ static void *intel_iommu_hw_info(struct device
> *dev, u32 *length, u32 *type)
> if (!vtd)
> return ERR_PTR(-ENOMEM);
>
> + vtd->flags = IOMMU_HW_INFO_VTD_ERRATA_772415_SPR17;
this doesn't belong to this patch. otherwise looks good:
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v7 7/8] iommu/vt-d: Add nested domain allocation
2023-10-25 7:34 ` Tian, Kevin
@ 2023-10-25 11:49 ` Jason Gunthorpe
0 siblings, 0 replies; 18+ messages in thread
From: Jason Gunthorpe @ 2023-10-25 11:49 UTC (permalink / raw)
To: Tian, Kevin
Cc: Liu, Yi L, joro@8bytes.org, alex.williamson@redhat.com,
robin.murphy@arm.com, baolu.lu@linux.intel.com, cohuck@redhat.com,
eric.auger@redhat.com, nicolinc@nvidia.com, kvm@vger.kernel.org,
mjrosato@linux.ibm.com, chao.p.peng@linux.intel.com,
yi.y.sun@linux.intel.com, peterx@redhat.com, jasowang@redhat.com,
shameerali.kolothum.thodi@huawei.com, lulu@redhat.com,
suravee.suthikulpanit@amd.com, iommu@lists.linux.dev,
linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org,
Duan, Zhenzhong, Martins, Joao
On Wed, Oct 25, 2023 at 07:34:20AM +0000, Tian, Kevin wrote:
> > From: Jason Gunthorpe <jgg@nvidia.com>
> > Sent: Wednesday, October 25, 2023 7:03 AM
> >
> > @@ -4849,6 +4855,7 @@ static void *intel_iommu_hw_info(struct device
> > *dev, u32 *length, u32 *type)
> > if (!vtd)
> > return ERR_PTR(-ENOMEM);
> >
> > + vtd->flags = IOMMU_HW_INFO_VTD_ERRATA_772415_SPR17;
>
> this doesn't belong to this patch. otherwise looks good:
Ah.. It seems to be some artifact of how I make this diff, it is was
fine in the actual commit.
Thanks,
Jason
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v7 7/8] iommu/vt-d: Add nested domain allocation
2023-10-24 23:03 ` Jason Gunthorpe
2023-10-25 7:34 ` Tian, Kevin
@ 2023-10-25 9:02 ` Yi Liu
1 sibling, 0 replies; 18+ messages in thread
From: Yi Liu @ 2023-10-25 9:02 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: joro, alex.williamson, kevin.tian, robin.murphy, baolu.lu, cohuck,
eric.auger, nicolinc, kvm, mjrosato, chao.p.peng, yi.y.sun,
peterx, jasowang, shameerali.kolothum.thodi, lulu,
suravee.suthikulpanit, iommu, linux-kernel, linux-kselftest,
zhenzhong.duan, joao.m.martins
On 2023/10/25 07:03, Jason Gunthorpe wrote:
> On Tue, Oct 24, 2023 at 08:14:11AM -0700, Yi Liu wrote:
>> From: Lu Baolu <baolu.lu@linux.intel.com>
>>
>> This adds the support for IOMMU_HWPT_DATA_VTD_S1 type. And 'nested_parent'
>> is added to mark the nested parent domain to sanitize the input parent domain.
>>
>> Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
>> Signed-off-by: Yi Liu <yi.l.liu@intel.com>
>> ---
>> drivers/iommu/intel/iommu.c | 67 +++++++++++++++++++++++++------------
>> drivers/iommu/intel/iommu.h | 1 +
>> 2 files changed, 46 insertions(+), 22 deletions(-)
>
> I think it should be written like this:
>
> @@ -4077,38 +4082,39 @@ intel_iommu_domain_alloc_user(struct device *dev, u32 flags,
> struct iommu_domain *parent,
> const struct iommu_user_data *user_data)
> {
> + struct device_domain_info *info = dev_iommu_priv_get(dev);
> + bool dirty_tracking = flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING;
> + bool nested_parent = flags & IOMMU_HWPT_ALLOC_NEST_PARENT;
> + struct intel_iommu *iommu = info->iommu;
> struct iommu_domain *domain;
> - struct intel_iommu *iommu;
> - bool dirty_tracking;
> +
> + /* Must be NESTING domain */
> + if (parent) {
> + if (!nested_supported(iommu) || flags)
> + return ERR_PTR(-EOPNOTSUPP);
> + return intel_nested_domain_alloc(parent, user_data);
> + }
>
> if (flags &
> (~(IOMMU_HWPT_ALLOC_NEST_PARENT | IOMMU_HWPT_ALLOC_DIRTY_TRACKING)))
> return ERR_PTR(-EOPNOTSUPP);
> -
> - if (parent || user_data)
> + if (nested_parent && !nested_supported(iommu))
> return ERR_PTR(-EOPNOTSUPP);
> -
> - iommu = device_to_iommu(dev, NULL, NULL);
> - if (!iommu)
> - return ERR_PTR(-ENODEV);
> -
> - if ((flags & IOMMU_HWPT_ALLOC_NEST_PARENT) && !nested_supported(iommu))
> - return ERR_PTR(-EOPNOTSUPP);
> -
> - dirty_tracking = (flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING);
> - if (dirty_tracking && !ssads_supported(iommu))
> + if (user_data || (dirty_tracking && !ssads_supported(iommu)))
> return ERR_PTR(-EOPNOTSUPP);
>
> /*
> - * domain_alloc_user op needs to fully initialize a domain
> - * before return, so uses iommu_domain_alloc() here for
> - * simple.
> + * domain_alloc_user op needs to fully initialize a domain before
> + * return, so uses iommu_domain_alloc() here for simple.
> */
> domain = iommu_domain_alloc(dev->bus);
> if (!domain)
> - domain = ERR_PTR(-ENOMEM);
> + return ERR_PTR(-ENOMEM);
>
> - if (!IS_ERR(domain) && dirty_tracking) {
> + if (nested_parent)
> + to_dmar_domain(domain)->nested_parent = true;
> +
> + if (dirty_tracking) {
> if (to_dmar_domain(domain)->use_first_level) {
> iommu_domain_free(domain);
> return ERR_PTR(-EOPNOTSUPP);
> @@ -4849,6 +4855,7 @@ static void *intel_iommu_hw_info(struct device *dev, u32 *length, u32 *type)
> if (!vtd)
> return ERR_PTR(-ENOMEM);
>
> + vtd->flags = IOMMU_HW_INFO_VTD_ERRATA_772415_SPR17;
this flag is introduced in [8/8]. still make sense to keep it there?
> vtd->cap_reg = iommu->cap;
> vtd->ecap_reg = iommu->ecap;
> *length = sizeof(*vtd);
> diff --git a/drivers/iommu/intel/nested.c b/drivers/iommu/intel/nested.c
> index d9197dd72748b1..b5a5563ab32c6b 100644
> --- a/drivers/iommu/intel/nested.c
> +++ b/drivers/iommu/intel/nested.c
> @@ -78,13 +78,21 @@ static const struct iommu_domain_ops intel_nested_domain_ops = {
> .free = intel_nested_domain_free,
> };
>
> -struct iommu_domain *intel_nested_domain_alloc(struct iommu_domain *s2_domain,
> +struct iommu_domain *intel_nested_domain_alloc(struct iommu_domain *parent,
> const struct iommu_user_data *user_data)
> {
> + struct dmar_domain *s2_domain = to_dmar_domain(parent);
> struct iommu_hwpt_vtd_s1 vtd;
> struct dmar_domain *domain;
> int ret;
>
> + /* Must be nested domain */
> + if (user_data->type != IOMMU_HWPT_DATA_VTD_S1)
> + return ERR_PTR(-EOPNOTSUPP);
> + if (parent->ops != intel_iommu_ops.default_domain_ops ||
> + !s2_domain->nested_parent)
> + return ERR_PTR(-EINVAL);
> +
> ret = iommu_copy_struct_from_user(&vtd, user_data,
> IOMMU_HWPT_DATA_VTD_S1, __reserved);
> if (ret)
> @@ -95,7 +103,7 @@ struct iommu_domain *intel_nested_domain_alloc(struct iommu_domain *s2_domain,
> return ERR_PTR(-ENOMEM);
>
> domain->use_first_level = true;
> - domain->s2_domain = to_dmar_domain(s2_domain);
> + domain->s2_domain = s2_domain;
> domain->s1_pgtbl = vtd.pgtbl_addr;
> domain->s1_cfg = vtd;
> domain->domain.ops = &intel_nested_domain_ops;
--
Regards,
Yi Liu
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v7 8/8] iommu/vt-d: Disallow read-only mappings to nest parent domain
2023-10-24 15:14 [PATCH v7 0/8] Add Intel VT-d nested translation (part 1/2) Yi Liu
` (6 preceding siblings ...)
2023-10-24 15:14 ` [PATCH v7 7/8] iommu/vt-d: Add nested domain allocation Yi Liu
@ 2023-10-24 15:14 ` Yi Liu
2023-10-25 7:35 ` Tian, Kevin
2023-10-25 12:07 ` [PATCH v7 0/8] Add Intel VT-d nested translation (part 1/2) Jason Gunthorpe
8 siblings, 1 reply; 18+ messages in thread
From: Yi Liu @ 2023-10-24 15:14 UTC (permalink / raw)
To: joro, alex.williamson, jgg, kevin.tian, robin.murphy, baolu.lu
Cc: cohuck, eric.auger, nicolinc, kvm, mjrosato, chao.p.peng,
yi.l.liu, yi.y.sun, peterx, jasowang, shameerali.kolothum.thodi,
lulu, suravee.suthikulpanit, iommu, linux-kernel, linux-kselftest,
zhenzhong.duan, joao.m.martins
From: Lu Baolu <baolu.lu@linux.intel.com>
When remapping hardware is configured by system software in scalable mode
as Nested (PGTT=011b) and with PWSNP field Set in the PASID-table-entry,
it may Set Accessed bit and Dirty bit (and Extended Access bit if enabled)
in first-stage page-table entries even when second-stage mappings indicate
that corresponding first-stage page-table is Read-Only.
As the result, contents of pages designated by VMM as Read-Only can be
modified by IOMMU via PML5E (PML4E for 4-level tables) access as part of
address translation process due to DMAs issued by Guest.
This disallows read-only mappings in the domain that is supposed to be used
as nested parent. Reference from Sapphire Rapids Specification Update [1],
errata details, SPR17. Userspace should know this limitation by checking
the IOMMU_HW_INFO_VTD_ERRATA_772415_SPR17 flag reported in the IOMMU_GET_HW_INFO
ioctl.
[1] https://www.intel.com/content/www/us/en/content-details/772415/content-details.html
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
Signed-off-by: Yi Liu <yi.l.liu@intel.com>
---
drivers/iommu/intel/iommu.c | 6 ++++++
include/uapi/linux/iommufd.h | 12 +++++++++++-
2 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 85366862fb5e..1a50d3f53713 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -2194,6 +2194,11 @@ __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0)
return -EINVAL;
+ if (!(prot & DMA_PTE_WRITE) && domain->nested_parent) {
+ pr_err_ratelimited("Read-only mapping is disallowed on the domain which serves as the parent in a nested configuration, due to HW errata (ERRATA_772415_SPR17)\n");
+ return -EINVAL;
+ }
+
attr = prot & (DMA_PTE_READ | DMA_PTE_WRITE | DMA_PTE_SNP);
attr |= DMA_FL_PTE_PRESENT;
if (domain->use_first_level) {
@@ -4872,6 +4877,7 @@ static void *intel_iommu_hw_info(struct device *dev, u32 *length, u32 *type)
if (!vtd)
return ERR_PTR(-ENOMEM);
+ vtd->flags = IOMMU_HW_INFO_VTD_ERRATA_772415_SPR17;
vtd->cap_reg = iommu->cap;
vtd->ecap_reg = iommu->ecap;
*length = sizeof(*vtd);
diff --git a/include/uapi/linux/iommufd.h b/include/uapi/linux/iommufd.h
index 3a66d3888393..cb7d17e3b4e7 100644
--- a/include/uapi/linux/iommufd.h
+++ b/include/uapi/linux/iommufd.h
@@ -444,10 +444,20 @@ struct iommu_hwpt_alloc {
};
#define IOMMU_HWPT_ALLOC _IO(IOMMUFD_TYPE, IOMMUFD_CMD_HWPT_ALLOC)
+/**
+ * enum iommu_hw_info_vtd_flags - Flags for VT-d hw_info
+ * @IOMMU_HW_INFO_VTD_ERRATA_772415_SPR17: If set, disallow nesting on domains
+ * with read-only mapping.
+ * https://www.intel.com/content/www/us/en/content-details/772415/content-details.html
+ */
+enum iommu_hw_info_vtd_flags {
+ IOMMU_HW_INFO_VTD_ERRATA_772415_SPR17 = 1 << 0,
+};
+
/**
* struct iommu_hw_info_vtd - Intel VT-d hardware information
*
- * @flags: Must be 0
+ * @flags: Combination of enum iommu_hw_info_vtd_flags
* @__reserved: Must be 0
*
* @cap_reg: Value of Intel VT-d capability register defined in VT-d spec
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread* RE: [PATCH v7 8/8] iommu/vt-d: Disallow read-only mappings to nest parent domain
2023-10-24 15:14 ` [PATCH v7 8/8] iommu/vt-d: Disallow read-only mappings to nest parent domain Yi Liu
@ 2023-10-25 7:35 ` Tian, Kevin
2023-10-25 9:03 ` Yi Liu
0 siblings, 1 reply; 18+ messages in thread
From: Tian, Kevin @ 2023-10-25 7:35 UTC (permalink / raw)
To: Liu, Yi L, joro@8bytes.org, alex.williamson@redhat.com,
jgg@nvidia.com, robin.murphy@arm.com, baolu.lu@linux.intel.com
Cc: cohuck@redhat.com, eric.auger@redhat.com, nicolinc@nvidia.com,
kvm@vger.kernel.org, mjrosato@linux.ibm.com,
chao.p.peng@linux.intel.com, yi.y.sun@linux.intel.com,
peterx@redhat.com, jasowang@redhat.com,
shameerali.kolothum.thodi@huawei.com, lulu@redhat.com,
suravee.suthikulpanit@amd.com, iommu@lists.linux.dev,
linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org,
Duan, Zhenzhong, Martins, Joao
> From: Liu, Yi L <yi.l.liu@intel.com>
> Sent: Tuesday, October 24, 2023 11:14 PM
>
> +/**
> + * enum iommu_hw_info_vtd_flags - Flags for VT-d hw_info
> + * @IOMMU_HW_INFO_VTD_ERRATA_772415_SPR17: If set, disallow
> nesting on domains
> + * with read-only mapping.
with how it's implemented now the description should be revised to:
"If set, disallow read-only mappings on a nested_parent domain"
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v7 8/8] iommu/vt-d: Disallow read-only mappings to nest parent domain
2023-10-25 7:35 ` Tian, Kevin
@ 2023-10-25 9:03 ` Yi Liu
0 siblings, 0 replies; 18+ messages in thread
From: Yi Liu @ 2023-10-25 9:03 UTC (permalink / raw)
To: Tian, Kevin, joro@8bytes.org, alex.williamson@redhat.com,
jgg@nvidia.com, robin.murphy@arm.com, baolu.lu@linux.intel.com
Cc: cohuck@redhat.com, eric.auger@redhat.com, nicolinc@nvidia.com,
kvm@vger.kernel.org, mjrosato@linux.ibm.com,
chao.p.peng@linux.intel.com, yi.y.sun@linux.intel.com,
peterx@redhat.com, jasowang@redhat.com,
shameerali.kolothum.thodi@huawei.com, lulu@redhat.com,
suravee.suthikulpanit@amd.com, iommu@lists.linux.dev,
linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org,
Duan, Zhenzhong, Martins, Joao
On 2023/10/25 15:35, Tian, Kevin wrote:
>> From: Liu, Yi L <yi.l.liu@intel.com>
>> Sent: Tuesday, October 24, 2023 11:14 PM
>>
>> +/**
>> + * enum iommu_hw_info_vtd_flags - Flags for VT-d hw_info
>> + * @IOMMU_HW_INFO_VTD_ERRATA_772415_SPR17: If set, disallow
>> nesting on domains
>> + * with read-only mapping.
>
> with how it's implemented now the description should be revised to:
>
> "If set, disallow read-only mappings on a nested_parent domain"
sure.
--
Regards,
Yi Liu
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v7 0/8] Add Intel VT-d nested translation (part 1/2)
2023-10-24 15:14 [PATCH v7 0/8] Add Intel VT-d nested translation (part 1/2) Yi Liu
` (7 preceding siblings ...)
2023-10-24 15:14 ` [PATCH v7 8/8] iommu/vt-d: Disallow read-only mappings to nest parent domain Yi Liu
@ 2023-10-25 12:07 ` Jason Gunthorpe
2023-10-26 4:50 ` Yi Liu
8 siblings, 1 reply; 18+ messages in thread
From: Jason Gunthorpe @ 2023-10-25 12:07 UTC (permalink / raw)
To: Yi Liu
Cc: joro, alex.williamson, kevin.tian, robin.murphy, baolu.lu, cohuck,
eric.auger, nicolinc, kvm, mjrosato, chao.p.peng, yi.y.sun,
peterx, jasowang, shameerali.kolothum.thodi, lulu,
suravee.suthikulpanit, iommu, linux-kernel, linux-kselftest,
zhenzhong.duan, joao.m.martins
On Tue, Oct 24, 2023 at 08:14:04AM -0700, Yi Liu wrote:
> Lu Baolu (5):
> iommu/vt-d: Extend dmar_domain to support nested domain
> iommu/vt-d: Add helper for nested domain allocation
> iommu/vt-d: Add helper to setup pasid nested translation
> iommu/vt-d: Add nested domain allocation
> iommu/vt-d: Disallow read-only mappings to nest parent domain
>
> Yi Liu (3):
> iommufd: Add data structure for Intel VT-d stage-1 domain allocation
> iommu/vt-d: Make domain attach helpers to be extern
> iommu/vt-d: Set the nested domain to a device
I put this in linux-next too
I think we will need a v8 on the list
Jason
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [PATCH v7 0/8] Add Intel VT-d nested translation (part 1/2)
2023-10-25 12:07 ` [PATCH v7 0/8] Add Intel VT-d nested translation (part 1/2) Jason Gunthorpe
@ 2023-10-26 4:50 ` Yi Liu
0 siblings, 0 replies; 18+ messages in thread
From: Yi Liu @ 2023-10-26 4:50 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: joro, alex.williamson, kevin.tian, robin.murphy, baolu.lu, cohuck,
eric.auger, nicolinc, kvm, mjrosato, chao.p.peng, yi.y.sun,
peterx, jasowang, shameerali.kolothum.thodi, lulu,
suravee.suthikulpanit, iommu, linux-kernel, linux-kselftest,
zhenzhong.duan, joao.m.martins
On 2023/10/25 20:07, Jason Gunthorpe wrote:
> On Tue, Oct 24, 2023 at 08:14:04AM -0700, Yi Liu wrote:
>
>> Lu Baolu (5):
>> iommu/vt-d: Extend dmar_domain to support nested domain
>> iommu/vt-d: Add helper for nested domain allocation
>> iommu/vt-d: Add helper to setup pasid nested translation
>> iommu/vt-d: Add nested domain allocation
>> iommu/vt-d: Disallow read-only mappings to nest parent domain
>>
>> Yi Liu (3):
>> iommufd: Add data structure for Intel VT-d stage-1 domain allocation
>> iommu/vt-d: Make domain attach helpers to be extern
>> iommu/vt-d: Set the nested domain to a device
>
> I put this in linux-next too
>
> I think we will need a v8 on the list
yes, v8 is posted:
https://lore.kernel.org/linux-iommu/20231026044216.64964-1-yi.l.liu@intel.com/
along with a v7 of the iommufd nesting:
https://lore.kernel.org/linux-iommu/20231026043938.63898-1-yi.l.liu@intel.com/
--
Regards,
Yi Liu
^ permalink raw reply [flat|nested] 18+ messages in thread