Skip to content

Commit 7bea695

Browse files
ssuthiku-amdjoergroedel
authored andcommitted
iommu/amd: Introduce struct ivhd_dte_flags to store persistent DTE flags
During early initialization, the driver parses IVRS IVHD block to get list of downstream devices along with their DTE flags (i.e INITPass, EIntPass, NMIPass, SysMgt, Lint0Pass, Lint1Pass). This information is currently store in the device DTE, and needs to be preserved when clearing and configuring each DTE, which makes it difficult to manage. Introduce struct ivhd_dte_flags to store IVHD DTE settings for a device or range of devices, which are stored in the amd_ivhd_dev_flags_list during initial IVHD parsing. 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 82582f8 commit 7bea695

File tree

2 files changed

+100
-29
lines changed

2 files changed

+100
-29
lines changed

drivers/iommu/amd/amd_iommu_types.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,8 @@
220220
#define DEV_ENTRY_EX 0x67
221221
#define DEV_ENTRY_SYSMGT1 0x68
222222
#define DEV_ENTRY_SYSMGT2 0x69
223+
#define DTE_DATA1_SYSMGT_MASK GENMASK_ULL(41, 40)
224+
223225
#define DEV_ENTRY_IRQ_TBL_EN 0x80
224226
#define DEV_ENTRY_INIT_PASS 0xb8
225227
#define DEV_ENTRY_EINT_PASS 0xb9
@@ -516,6 +518,9 @@ extern struct kmem_cache *amd_iommu_irq_cache;
516518
#define for_each_pdom_dev_data_safe(pdom_dev_data, next, pdom) \
517519
list_for_each_entry_safe((pdom_dev_data), (next), &pdom->dev_data_list, list)
518520

521+
#define for_each_ivhd_dte_flags(entry) \
522+
list_for_each_entry((entry), &amd_ivhd_dev_flags_list, list)
523+
519524
struct amd_iommu;
520525
struct iommu_domain;
521526
struct irq_domain;
@@ -884,6 +889,17 @@ struct dev_table_entry {
884889
u64 data[4];
885890
};
886891

892+
/*
893+
* Structure to sture persistent DTE flags from IVHD
894+
*/
895+
struct ivhd_dte_flags {
896+
struct list_head list;
897+
u16 segid;
898+
u16 devid_first;
899+
u16 devid_last;
900+
struct dev_table_entry dte;
901+
};
902+
887903
/*
888904
* One entry for unity mappings parsed out of the ACPI table.
889905
*/

drivers/iommu/amd/init.c

Lines changed: 84 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,8 @@ bool amd_iommu_snp_en;
174174
EXPORT_SYMBOL(amd_iommu_snp_en);
175175

176176
LIST_HEAD(amd_iommu_pci_seg_list); /* list of all PCI segments */
177-
LIST_HEAD(amd_iommu_list); /* list of all AMD IOMMUs in the
178-
system */
177+
LIST_HEAD(amd_iommu_list); /* list of all AMD IOMMUs in the system */
178+
LIST_HEAD(amd_ivhd_dev_flags_list); /* list of all IVHD device entry settings */
179179

180180
/* Number of IOMMUs present in the system */
181181
static int amd_iommus_present;
@@ -984,6 +984,14 @@ static void iommu_enable_gt(struct amd_iommu *iommu)
984984
}
985985

986986
/* sets a specific bit in the device table entry. */
987+
static void set_dte_bit(struct dev_table_entry *dte, u8 bit)
988+
{
989+
int i = (bit >> 6) & 0x03;
990+
int _bit = bit & 0x3f;
991+
992+
dte->data[i] |= (1UL << _bit);
993+
}
994+
987995
static void __set_dev_entry_bit(struct dev_table_entry *dev_table,
988996
u16 devid, u8 bit)
989997
{
@@ -1136,6 +1144,19 @@ static bool copy_device_table(void)
11361144
return true;
11371145
}
11381146

1147+
static bool search_ivhd_dte_flags(u16 segid, u16 first, u16 last)
1148+
{
1149+
struct ivhd_dte_flags *e;
1150+
1151+
for_each_ivhd_dte_flags(e) {
1152+
if ((e->segid == segid) &&
1153+
(e->devid_first == first) &&
1154+
(e->devid_last == last))
1155+
return true;
1156+
}
1157+
return false;
1158+
}
1159+
11391160
void amd_iommu_apply_erratum_63(struct amd_iommu *iommu, u16 devid)
11401161
{
11411162
int sysmgt;
@@ -1151,27 +1172,66 @@ void amd_iommu_apply_erratum_63(struct amd_iommu *iommu, u16 devid)
11511172
* This function takes the device specific flags read from the ACPI
11521173
* table and sets up the device table entry with that information
11531174
*/
1154-
static void __init set_dev_entry_from_acpi(struct amd_iommu *iommu,
1155-
u16 devid, u32 flags, u32 ext_flags)
1175+
static void __init
1176+
set_dev_entry_from_acpi_range(struct amd_iommu *iommu, u16 first, u16 last,
1177+
u32 flags, u32 ext_flags)
11561178
{
1157-
if (flags & ACPI_DEVFLAG_INITPASS)
1158-
set_dev_entry_bit(iommu, devid, DEV_ENTRY_INIT_PASS);
1159-
if (flags & ACPI_DEVFLAG_EXTINT)
1160-
set_dev_entry_bit(iommu, devid, DEV_ENTRY_EINT_PASS);
1161-
if (flags & ACPI_DEVFLAG_NMI)
1162-
set_dev_entry_bit(iommu, devid, DEV_ENTRY_NMI_PASS);
1163-
if (flags & ACPI_DEVFLAG_SYSMGT1)
1164-
set_dev_entry_bit(iommu, devid, DEV_ENTRY_SYSMGT1);
1165-
if (flags & ACPI_DEVFLAG_SYSMGT2)
1166-
set_dev_entry_bit(iommu, devid, DEV_ENTRY_SYSMGT2);
1167-
if (flags & ACPI_DEVFLAG_LINT0)
1168-
set_dev_entry_bit(iommu, devid, DEV_ENTRY_LINT0_PASS);
1169-
if (flags & ACPI_DEVFLAG_LINT1)
1170-
set_dev_entry_bit(iommu, devid, DEV_ENTRY_LINT1_PASS);
1179+
int i;
1180+
struct dev_table_entry dte = {};
1181+
1182+
/* Parse IVHD DTE setting flags and store information */
1183+
if (flags) {
1184+
struct ivhd_dte_flags *d;
11711185

1172-
amd_iommu_apply_erratum_63(iommu, devid);
1186+
if (search_ivhd_dte_flags(iommu->pci_seg->id, first, last))
1187+
return;
11731188

1174-
amd_iommu_set_rlookup_table(iommu, devid);
1189+
d = kzalloc(sizeof(struct ivhd_dte_flags), GFP_KERNEL);
1190+
if (!d)
1191+
return;
1192+
1193+
pr_debug("%s: devid range %#x:%#x\n", __func__, first, last);
1194+
1195+
if (flags & ACPI_DEVFLAG_INITPASS)
1196+
set_dte_bit(&dte, DEV_ENTRY_INIT_PASS);
1197+
if (flags & ACPI_DEVFLAG_EXTINT)
1198+
set_dte_bit(&dte, DEV_ENTRY_EINT_PASS);
1199+
if (flags & ACPI_DEVFLAG_NMI)
1200+
set_dte_bit(&dte, DEV_ENTRY_NMI_PASS);
1201+
if (flags & ACPI_DEVFLAG_SYSMGT1)
1202+
set_dte_bit(&dte, DEV_ENTRY_SYSMGT1);
1203+
if (flags & ACPI_DEVFLAG_SYSMGT2)
1204+
set_dte_bit(&dte, DEV_ENTRY_SYSMGT2);
1205+
if (flags & ACPI_DEVFLAG_LINT0)
1206+
set_dte_bit(&dte, DEV_ENTRY_LINT0_PASS);
1207+
if (flags & ACPI_DEVFLAG_LINT1)
1208+
set_dte_bit(&dte, DEV_ENTRY_LINT1_PASS);
1209+
1210+
/* Apply erratum 63, which needs info in initial_dte */
1211+
if (FIELD_GET(DTE_DATA1_SYSMGT_MASK, dte.data[1]) == 0x1)
1212+
dte.data[0] |= DTE_FLAG_IW;
1213+
1214+
memcpy(&d->dte, &dte, sizeof(dte));
1215+
d->segid = iommu->pci_seg->id;
1216+
d->devid_first = first;
1217+
d->devid_last = last;
1218+
list_add_tail(&d->list, &amd_ivhd_dev_flags_list);
1219+
}
1220+
1221+
for (i = first; i <= last; i++) {
1222+
if (flags) {
1223+
struct dev_table_entry *dev_table = get_dev_table(iommu);
1224+
1225+
memcpy(&dev_table[i], &dte, sizeof(dte));
1226+
}
1227+
amd_iommu_set_rlookup_table(iommu, i);
1228+
}
1229+
}
1230+
1231+
static void __init set_dev_entry_from_acpi(struct amd_iommu *iommu,
1232+
u16 devid, u32 flags, u32 ext_flags)
1233+
{
1234+
set_dev_entry_from_acpi_range(iommu, devid, devid, flags, ext_flags);
11751235
}
11761236

11771237
int __init add_special_device(u8 type, u8 id, u32 *devid, bool cmd_line)
@@ -1332,9 +1392,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu,
13321392
case IVHD_DEV_ALL:
13331393

13341394
DUMP_printk(" DEV_ALL\t\t\tsetting: %#02x\n", e->flags);
1335-
1336-
for (dev_i = 0; dev_i <= pci_seg->last_bdf; ++dev_i)
1337-
set_dev_entry_from_acpi(iommu, dev_i, e->flags, 0);
1395+
set_dev_entry_from_acpi_range(iommu, 0, pci_seg->last_bdf, e->flags, 0);
13381396
break;
13391397
case IVHD_DEV_SELECT:
13401398

@@ -1428,14 +1486,11 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu,
14281486

14291487
devid = e->devid;
14301488
for (dev_i = devid_start; dev_i <= devid; ++dev_i) {
1431-
if (alias) {
1489+
if (alias)
14321490
pci_seg->alias_table[dev_i] = devid_to;
1433-
set_dev_entry_from_acpi(iommu,
1434-
devid_to, flags, ext_flags);
1435-
}
1436-
set_dev_entry_from_acpi(iommu, dev_i,
1437-
flags, ext_flags);
14381491
}
1492+
set_dev_entry_from_acpi_range(iommu, devid_start, devid, flags, ext_flags);
1493+
set_dev_entry_from_acpi(iommu, devid_to, flags, ext_flags);
14391494
break;
14401495
case IVHD_DEV_SPECIAL: {
14411496
u8 handle, type;

0 commit comments

Comments
 (0)