Skip to content

Commit fd5dff9

Browse files
ssuthiku-amdjoergroedel
authored andcommitted
iommu/amd: Modify set_dte_entry() to use 256-bit DTE helpers
Also, the set_dte_entry() is used to program several DTE fields (e.g. stage1 table, stage2 table, domain id, and etc.), which is difficult to keep track with current implementation. Therefore, separate logic for clearing DTE (i.e. make_clear_dte) and another function for setting up the GCR3 Table Root Pointer, GIOV, GV, GLX, and GuestPagingMode into another function set_dte_gcr3_table(). Reviewed-by: Jason Gunthorpe <[email protected]> Signed-off-by: Suravee Suthikulpanit <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent 8b3f787 commit fd5dff9

File tree

4 files changed

+106
-68
lines changed

4 files changed

+106
-68
lines changed

drivers/iommu/amd/amd_iommu.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,3 +184,5 @@ void amd_iommu_domain_set_pgtable(struct protection_domain *domain,
184184
struct dev_table_entry *get_dev_table(struct amd_iommu *iommu);
185185

186186
#endif
187+
188+
struct dev_table_entry *amd_iommu_get_ivhd_dte_flags(u16 segid, u16 devid);

drivers/iommu/amd/amd_iommu_types.h

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -409,22 +409,17 @@
409409
#define DTE_FLAG_HAD (3ULL << 7)
410410
#define DTE_FLAG_GIOV BIT_ULL(54)
411411
#define DTE_FLAG_GV BIT_ULL(55)
412-
#define DTE_GLX_SHIFT (56)
413-
#define DTE_GLX_MASK (3)
412+
#define DTE_GLX GENMASK_ULL(57, 56)
414413
#define DTE_FLAG_IR BIT_ULL(61)
415414
#define DTE_FLAG_IW BIT_ULL(62)
416415

417416
#define DTE_FLAG_IOTLB BIT_ULL(32)
418417
#define DTE_FLAG_MASK (0x3ffULL << 32)
419418
#define DEV_DOMID_MASK 0xffffULL
420419

421-
#define DTE_GCR3_VAL_A(x) (((x) >> 12) & 0x00007ULL)
422-
#define DTE_GCR3_VAL_B(x) (((x) >> 15) & 0x0ffffULL)
423-
#define DTE_GCR3_VAL_C(x) (((x) >> 31) & 0x1fffffULL)
424-
425-
#define DTE_GCR3_SHIFT_A 58
426-
#define DTE_GCR3_SHIFT_B 16
427-
#define DTE_GCR3_SHIFT_C 43
420+
#define DTE_GCR3_14_12 GENMASK_ULL(60, 58)
421+
#define DTE_GCR3_30_15 GENMASK_ULL(31, 16)
422+
#define DTE_GCR3_51_31 GENMASK_ULL(63, 43)
428423

429424
#define DTE_GPT_LEVEL_SHIFT 54
430425
#define DTE_GPT_LEVEL_MASK GENMASK_ULL(55, 54)

drivers/iommu/amd/init.c

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,11 +1089,9 @@ static bool __copy_device_table(struct amd_iommu *iommu)
10891089
}
10901090
/* If gcr3 table existed, mask it out */
10911091
if (old_devtb[devid].data[0] & DTE_FLAG_GV) {
1092-
tmp = DTE_GCR3_VAL_B(~0ULL) << DTE_GCR3_SHIFT_B;
1093-
tmp |= DTE_GCR3_VAL_C(~0ULL) << DTE_GCR3_SHIFT_C;
1092+
tmp = (DTE_GCR3_30_15 | DTE_GCR3_51_31);
10941093
pci_seg->old_dev_tbl_cpy[devid].data[1] &= ~tmp;
1095-
tmp = DTE_GCR3_VAL_A(~0ULL) << DTE_GCR3_SHIFT_A;
1096-
tmp |= DTE_FLAG_GV;
1094+
tmp = (DTE_GCR3_14_12 | DTE_FLAG_GV);
10971095
pci_seg->old_dev_tbl_cpy[devid].data[0] &= ~tmp;
10981096
}
10991097
}
@@ -1144,6 +1142,30 @@ static bool copy_device_table(void)
11441142
return true;
11451143
}
11461144

1145+
struct dev_table_entry *amd_iommu_get_ivhd_dte_flags(u16 segid, u16 devid)
1146+
{
1147+
struct ivhd_dte_flags *e;
1148+
unsigned int best_len = UINT_MAX;
1149+
struct dev_table_entry *dte = NULL;
1150+
1151+
for_each_ivhd_dte_flags(e) {
1152+
/*
1153+
* Need to go through the whole list to find the smallest range,
1154+
* which contains the devid.
1155+
*/
1156+
if ((e->segid == segid) &&
1157+
(e->devid_first <= devid) && (devid <= e->devid_last)) {
1158+
unsigned int len = e->devid_last - e->devid_first;
1159+
1160+
if (len < best_len) {
1161+
dte = &(e->dte);
1162+
best_len = len;
1163+
}
1164+
}
1165+
}
1166+
return dte;
1167+
}
1168+
11471169
static bool search_ivhd_dte_flags(u16 segid, u16 first, u16 last)
11481170
{
11491171
struct ivhd_dte_flags *e;

drivers/iommu/amd/iommu.c

Lines changed: 74 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1949,90 +1949,109 @@ int amd_iommu_clear_gcr3(struct iommu_dev_data *dev_data, ioasid_t pasid)
19491949
return ret;
19501950
}
19511951

1952+
static void make_clear_dte(struct iommu_dev_data *dev_data, struct dev_table_entry *ptr,
1953+
struct dev_table_entry *new)
1954+
{
1955+
/* All existing DTE must have V bit set */
1956+
new->data128[0] = DTE_FLAG_V;
1957+
new->data128[1] = 0;
1958+
}
1959+
1960+
/*
1961+
* Note:
1962+
* The old value for GCR3 table and GPT have been cleared from caller.
1963+
*/
1964+
static void set_dte_gcr3_table(struct amd_iommu *iommu,
1965+
struct iommu_dev_data *dev_data,
1966+
struct dev_table_entry *target)
1967+
{
1968+
struct gcr3_tbl_info *gcr3_info = &dev_data->gcr3_info;
1969+
u64 gcr3;
1970+
1971+
if (!gcr3_info->gcr3_tbl)
1972+
return;
1973+
1974+
pr_debug("%s: devid=%#x, glx=%#x, gcr3_tbl=%#llx\n",
1975+
__func__, dev_data->devid, gcr3_info->glx,
1976+
(unsigned long long)gcr3_info->gcr3_tbl);
1977+
1978+
gcr3 = iommu_virt_to_phys(gcr3_info->gcr3_tbl);
1979+
1980+
target->data[0] |= DTE_FLAG_GV |
1981+
FIELD_PREP(DTE_GLX, gcr3_info->glx) |
1982+
FIELD_PREP(DTE_GCR3_14_12, gcr3 >> 12);
1983+
if (pdom_is_v2_pgtbl_mode(dev_data->domain))
1984+
target->data[0] |= DTE_FLAG_GIOV;
1985+
1986+
target->data[1] |= FIELD_PREP(DTE_GCR3_30_15, gcr3 >> 15) |
1987+
FIELD_PREP(DTE_GCR3_51_31, gcr3 >> 31);
1988+
1989+
/* Guest page table can only support 4 and 5 levels */
1990+
if (amd_iommu_gpt_level == PAGE_MODE_5_LEVEL)
1991+
target->data[2] |= FIELD_PREP(DTE_GPT_LEVEL_MASK, GUEST_PGTABLE_5_LEVEL);
1992+
else
1993+
target->data[2] |= FIELD_PREP(DTE_GPT_LEVEL_MASK, GUEST_PGTABLE_4_LEVEL);
1994+
}
1995+
19521996
static void set_dte_entry(struct amd_iommu *iommu,
19531997
struct iommu_dev_data *dev_data)
19541998
{
1955-
u64 pte_root = 0;
1956-
u64 flags = 0;
1957-
u32 old_domid;
1958-
u16 devid = dev_data->devid;
19591999
u16 domid;
2000+
u32 old_domid;
2001+
struct dev_table_entry *initial_dte;
2002+
struct dev_table_entry new = {};
19602003
struct protection_domain *domain = dev_data->domain;
1961-
struct dev_table_entry *dev_table = get_dev_table(iommu);
19622004
struct gcr3_tbl_info *gcr3_info = &dev_data->gcr3_info;
2005+
struct dev_table_entry *dte = &get_dev_table(iommu)[dev_data->devid];
19632006

19642007
if (gcr3_info && gcr3_info->gcr3_tbl)
19652008
domid = dev_data->gcr3_info.domid;
19662009
else
19672010
domid = domain->id;
19682011

2012+
make_clear_dte(dev_data, dte, &new);
2013+
19692014
if (domain->iop.mode != PAGE_MODE_NONE)
1970-
pte_root = iommu_virt_to_phys(domain->iop.root);
2015+
new.data[0] = iommu_virt_to_phys(domain->iop.root);
19712016

1972-
pte_root |= (domain->iop.mode & DEV_ENTRY_MODE_MASK)
2017+
new.data[0] |= (domain->iop.mode & DEV_ENTRY_MODE_MASK)
19732018
<< DEV_ENTRY_MODE_SHIFT;
19742019

1975-
pte_root |= DTE_FLAG_IR | DTE_FLAG_IW | DTE_FLAG_V;
2020+
new.data[0] |= DTE_FLAG_IR | DTE_FLAG_IW | DTE_FLAG_V;
19762021

19772022
/*
1978-
* When SNP is enabled, Only set TV bit when IOMMU
1979-
* page translation is in use.
2023+
* When SNP is enabled, we can only support TV=1 with non-zero domain ID.
2024+
* This is prevented by the SNP-enable and IOMMU_DOMAIN_IDENTITY check in
2025+
* do_iommu_domain_alloc().
19802026
*/
1981-
if (!amd_iommu_snp_en || (domid != 0))
1982-
pte_root |= DTE_FLAG_TV;
1983-
1984-
flags = dev_table[devid].data[1];
1985-
1986-
if (dev_data->ats_enabled)
1987-
flags |= DTE_FLAG_IOTLB;
2027+
WARN_ON(amd_iommu_snp_en && (domid == 0));
2028+
new.data[0] |= DTE_FLAG_TV;
19882029

19892030
if (dev_data->ppr)
1990-
pte_root |= 1ULL << DEV_ENTRY_PPR;
2031+
new.data[0] |= 1ULL << DEV_ENTRY_PPR;
19912032

19922033
if (domain->dirty_tracking)
1993-
pte_root |= DTE_FLAG_HAD;
1994-
1995-
if (gcr3_info && gcr3_info->gcr3_tbl) {
1996-
u64 gcr3 = iommu_virt_to_phys(gcr3_info->gcr3_tbl);
1997-
u64 glx = gcr3_info->glx;
1998-
u64 tmp;
1999-
2000-
pte_root |= DTE_FLAG_GV;
2001-
pte_root |= (glx & DTE_GLX_MASK) << DTE_GLX_SHIFT;
2034+
new.data[0] |= DTE_FLAG_HAD;
20022035

2003-
/* First mask out possible old values for GCR3 table */
2004-
tmp = DTE_GCR3_VAL_B(~0ULL) << DTE_GCR3_SHIFT_B;
2005-
flags &= ~tmp;
2006-
2007-
tmp = DTE_GCR3_VAL_C(~0ULL) << DTE_GCR3_SHIFT_C;
2008-
flags &= ~tmp;
2009-
2010-
/* Encode GCR3 table into DTE */
2011-
tmp = DTE_GCR3_VAL_A(gcr3) << DTE_GCR3_SHIFT_A;
2012-
pte_root |= tmp;
2013-
2014-
tmp = DTE_GCR3_VAL_B(gcr3) << DTE_GCR3_SHIFT_B;
2015-
flags |= tmp;
2016-
2017-
tmp = DTE_GCR3_VAL_C(gcr3) << DTE_GCR3_SHIFT_C;
2018-
flags |= tmp;
2036+
if (dev_data->ats_enabled)
2037+
new.data[1] |= DTE_FLAG_IOTLB;
20192038

2020-
if (amd_iommu_gpt_level == PAGE_MODE_5_LEVEL) {
2021-
dev_table[devid].data[2] |=
2022-
((u64)GUEST_PGTABLE_5_LEVEL << DTE_GPT_LEVEL_SHIFT);
2023-
}
2039+
old_domid = READ_ONCE(dte->data[1]) & DEV_DOMID_MASK;
2040+
new.data[1] |= domid;
20242041

2025-
/* GIOV is supported with V2 page table mode only */
2026-
if (pdom_is_v2_pgtbl_mode(domain))
2027-
pte_root |= DTE_FLAG_GIOV;
2042+
/*
2043+
* Restore cached persistent DTE bits, which can be set by information
2044+
* in IVRS table. See set_dev_entry_from_acpi().
2045+
*/
2046+
initial_dte = amd_iommu_get_ivhd_dte_flags(iommu->pci_seg->id, dev_data->devid);
2047+
if (initial_dte) {
2048+
new.data128[0] |= initial_dte->data128[0];
2049+
new.data128[1] |= initial_dte->data128[1];
20282050
}
20292051

2030-
flags &= ~DEV_DOMID_MASK;
2031-
flags |= domid;
2052+
set_dte_gcr3_table(iommu, dev_data, &new);
20322053

2033-
old_domid = dev_table[devid].data[1] & DEV_DOMID_MASK;
2034-
dev_table[devid].data[1] = flags;
2035-
dev_table[devid].data[0] = pte_root;
2054+
update_dte256(iommu, dev_data, &new);
20362055

20372056
/*
20382057
* A kdump kernel might be replacing a domain ID that was copied from

0 commit comments

Comments
 (0)