[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20251021014324.5837-16-suravee.suthikulpanit@amd.com>
Date: Tue, 21 Oct 2025 01:43:23 +0000
From: Suravee Suthikulpanit <suravee.suthikulpanit@....com>
To: <jgg@...dia.com>, <nicolinc@...dia.com>
CC: <linux-kernel@...r.kernel.org>, <robin.murphy@....com>, <will@...nel.org>,
<joro@...tes.org>, <kevin.tian@...el.com>, <jsnitsel@...hat.com>,
<vasant.hegde@....com>, <iommu@...ts.linux.dev>, <santosh.shukla@....com>,
<sairaj.arunkodilkar@....com>, <jon.grimm@....com>,
<prashanthpra@...gle.com>, <wvw@...gle.com>, <wnliu@...gle.com>,
<gptran@...gle.com>, <kpsingh@...gle.com>, <joao.m.martins@...cle.com>,
<alejandro.j.jimenez@...cle.com>, Suravee Suthikulpanit
<suravee.suthikulpanit@....com>
Subject: [PATCH v4 15/16] iommu/amd: Refactor logic to program the host page table in DTE
Introduce the set_dte_v1() helper function to configure IOMMU host (v1)
page table into DTE.
There is no functional change.
Suggested-by: Jason Gunthorpe <jgg@...dia.com>
Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@....com>
---
drivers/iommu/amd/amd_iommu.h | 3 ++
drivers/iommu/amd/iommu.c | 57 ++++++++++++++++++++---------------
2 files changed, 35 insertions(+), 25 deletions(-)
diff --git a/drivers/iommu/amd/amd_iommu.h b/drivers/iommu/amd/amd_iommu.h
index cfb63de7732a..5e61fdb2c6c0 100644
--- a/drivers/iommu/amd/amd_iommu.h
+++ b/drivers/iommu/amd/amd_iommu.h
@@ -190,6 +190,9 @@ struct iommu_dev_data *search_dev_data(struct amd_iommu *iommu, u16 devid);
int amd_iommu_completion_wait(struct amd_iommu *iommu);
/* DTE */
+void amd_iommu_set_dte_v1(struct iommu_dev_data *dev_data,
+ struct protection_domain *domain,
+ struct dev_table_entry *new);
int amd_iommu_device_flush_dte(struct iommu_dev_data *dev_data);
void amd_iommu_update_dte256(struct amd_iommu *iommu,
struct iommu_dev_data *dev_data,
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index e3330f3b8c14..428008cff06a 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -2041,16 +2041,12 @@ int amd_iommu_clear_gcr3(struct iommu_dev_data *dev_data, ioasid_t pasid)
* Note:
* The old value for GCR3 table and GPT have been cleared from caller.
*/
-static void set_dte_gcr3_table(struct amd_iommu *iommu,
- struct iommu_dev_data *dev_data,
+static void set_dte_gcr3_table(struct iommu_dev_data *dev_data,
struct dev_table_entry *target)
{
struct gcr3_tbl_info *gcr3_info = &dev_data->gcr3_info;
u64 gcr3;
- if (!gcr3_info->gcr3_tbl)
- return;
-
pr_debug("%s: devid=%#x, glx=%#x, gcr3_tbl=%#llx\n",
__func__, dev_data->devid, gcr3_info->glx,
(unsigned long long)gcr3_info->gcr3_tbl);
@@ -2071,6 +2067,26 @@ static void set_dte_gcr3_table(struct amd_iommu *iommu,
target->data[2] |= FIELD_PREP(DTE_GPT_LEVEL_MASK, GUEST_PGTABLE_5_LEVEL);
else
target->data[2] |= FIELD_PREP(DTE_GPT_LEVEL_MASK, GUEST_PGTABLE_4_LEVEL);
+
+ /* Note: PRI is only supported w/ GCR3 table */
+ if (dev_data->ppr)
+ target->data[0] |= 1ULL << DEV_ENTRY_PPR;
+}
+
+void amd_iommu_set_dte_v1(struct iommu_dev_data *dev_data,
+ struct protection_domain *domain,
+ struct dev_table_entry *new)
+{
+ u64 htrp;
+
+ new->data[0] |= FIELD_PREP(DTE_MODE_MASK, domain->iop.mode);
+
+ htrp = FIELD_GET(GENMASK_ULL(51, 12), iommu_virt_to_phys(domain->iop.root));
+ new->data[0] |= FIELD_PREP(DTE_HOST_TRP, htrp);
+
+ /* Note Dirty tracking is used for v1 table only for now */
+ if (domain->dirty_tracking)
+ new->data[0] |= DTE_FLAG_HAD;
}
static void set_dte_entry(struct amd_iommu *iommu,
@@ -2088,37 +2104,28 @@ static void set_dte_entry(struct amd_iommu *iommu,
else
domid = domain->id;
- amd_iommu_make_clear_dte(dev_data, &new);
-
- if (domain->iop.mode != PAGE_MODE_NONE)
- new.data[0] |= iommu_virt_to_phys(domain->iop.root);
-
- new.data[0] |= (domain->iop.mode & DEV_ENTRY_MODE_MASK)
- << DEV_ENTRY_MODE_SHIFT;
-
- new.data[0] |= DTE_FLAG_IR | DTE_FLAG_IW;
-
/*
* When SNP is enabled, we can only support TV=1 with non-zero domain ID.
* This is prevented by the SNP-enable and IOMMU_DOMAIN_IDENTITY check in
* do_iommu_domain_alloc().
*/
WARN_ON(amd_iommu_snp_en && (domid == 0));
- new.data[0] |= DTE_FLAG_TV;
- if (dev_data->ppr)
- new.data[0] |= 1ULL << DEV_ENTRY_PPR;
+ amd_iommu_make_clear_dte(dev_data, &new);
- if (domain->dirty_tracking)
- new.data[0] |= DTE_FLAG_HAD;
+ old_domid = READ_ONCE(dte->data[1]) & DTE_DOMID_MASK;
- if (dev_data->ats_enabled)
- new.data[1] |= DTE_FLAG_IOTLB;
+ if (gcr3_info && gcr3_info->gcr3_tbl)
+ set_dte_gcr3_table(dev_data, &new);
+ else if (domain->iop.mode != PAGE_MODE_NONE)
+ amd_iommu_set_dte_v1(dev_data, domain, &new);
- old_domid = READ_ONCE(dte->data[1]) & DTE_DOMID_MASK;
- new.data[1] |= domid;
+ /* Note: The IR, IW, TV, DOMID are needed for both v1 and gcr3 table */
+ new.data[0] |= DTE_FLAG_IR | DTE_FLAG_IW | DTE_FLAG_TV;
+ new.data[1] |= FIELD_PREP(DTE_DOMID_MASK, domid);
- set_dte_gcr3_table(iommu, dev_data, &new);
+ if (dev_data->ats_enabled)
+ new.data[1] |= DTE_FLAG_IOTLB;
amd_iommu_update_dte256(iommu, dev_data, &new);
--
2.34.1
Powered by blists - more mailing lists