Skip to content

Commit 31a75cb

Browse files
yianchen2018joergroedel
authored andcommitted
iommu/vt-d: Parse SATC reporting structure
Software should parse every SATC table and all devices in the tables reported by the BIOS and keep the information in kernel list for further reference. Signed-off-by: Yian Chen <[email protected]> Signed-off-by: Lu Baolu <[email protected]> Link: https://lore.kernel.org/r/[email protected] Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent 81d3c75 commit 31a75cb

File tree

3 files changed

+99
-0
lines changed

3 files changed

+99
-0
lines changed

drivers/iommu/intel/dmar.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,7 @@ dmar_table_print_dmar_entry(struct acpi_dmar_header *header)
526526
struct acpi_dmar_reserved_memory *rmrr;
527527
struct acpi_dmar_atsr *atsr;
528528
struct acpi_dmar_rhsa *rhsa;
529+
struct acpi_dmar_satc *satc;
529530

530531
switch (header->type) {
531532
case ACPI_DMAR_TYPE_HARDWARE_UNIT:
@@ -555,6 +556,10 @@ dmar_table_print_dmar_entry(struct acpi_dmar_header *header)
555556
/* We don't print this here because we need to sanity-check
556557
it first. So print it in dmar_parse_one_andd() instead. */
557558
break;
559+
case ACPI_DMAR_TYPE_SATC:
560+
satc = container_of(header, struct acpi_dmar_satc, header);
561+
pr_info("SATC flags: 0x%x\n", satc->flags);
562+
break;
558563
}
559564
}
560565

@@ -642,6 +647,7 @@ parse_dmar_table(void)
642647
.cb[ACPI_DMAR_TYPE_ROOT_ATS] = &dmar_parse_one_atsr,
643648
.cb[ACPI_DMAR_TYPE_HARDWARE_AFFINITY] = &dmar_parse_one_rhsa,
644649
.cb[ACPI_DMAR_TYPE_NAMESPACE] = &dmar_parse_one_andd,
650+
.cb[ACPI_DMAR_TYPE_SATC] = &dmar_parse_one_satc,
645651
};
646652

647653
/*
@@ -2077,6 +2083,7 @@ static guid_t dmar_hp_guid =
20772083
#define DMAR_DSM_FUNC_DRHD 1
20782084
#define DMAR_DSM_FUNC_ATSR 2
20792085
#define DMAR_DSM_FUNC_RHSA 3
2086+
#define DMAR_DSM_FUNC_SATC 4
20802087

20812088
static inline bool dmar_detect_dsm(acpi_handle handle, int func)
20822089
{
@@ -2094,6 +2101,7 @@ static int dmar_walk_dsm_resource(acpi_handle handle, int func,
20942101
[DMAR_DSM_FUNC_DRHD] = ACPI_DMAR_TYPE_HARDWARE_UNIT,
20952102
[DMAR_DSM_FUNC_ATSR] = ACPI_DMAR_TYPE_ROOT_ATS,
20962103
[DMAR_DSM_FUNC_RHSA] = ACPI_DMAR_TYPE_HARDWARE_AFFINITY,
2104+
[DMAR_DSM_FUNC_SATC] = ACPI_DMAR_TYPE_SATC,
20972105
};
20982106

20992107
if (!dmar_detect_dsm(handle, func))

drivers/iommu/intel/iommu.c

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,8 +316,18 @@ struct dmar_atsr_unit {
316316
u8 include_all:1; /* include all ports */
317317
};
318318

319+
struct dmar_satc_unit {
320+
struct list_head list; /* list of SATC units */
321+
struct acpi_dmar_header *hdr; /* ACPI header */
322+
struct dmar_dev_scope *devices; /* target devices */
323+
struct intel_iommu *iommu; /* the corresponding iommu */
324+
int devices_cnt; /* target device count */
325+
u8 atc_required:1; /* ATS is required */
326+
};
327+
319328
static LIST_HEAD(dmar_atsr_units);
320329
static LIST_HEAD(dmar_rmrr_units);
330+
static LIST_HEAD(dmar_satc_units);
321331

322332
#define for_each_rmrr_units(rmrr) \
323333
list_for_each_entry(rmrr, &dmar_rmrr_units, list)
@@ -3716,6 +3726,57 @@ int dmar_check_one_atsr(struct acpi_dmar_header *hdr, void *arg)
37163726
return 0;
37173727
}
37183728

3729+
static struct dmar_satc_unit *dmar_find_satc(struct acpi_dmar_satc *satc)
3730+
{
3731+
struct dmar_satc_unit *satcu;
3732+
struct acpi_dmar_satc *tmp;
3733+
3734+
list_for_each_entry_rcu(satcu, &dmar_satc_units, list,
3735+
dmar_rcu_check()) {
3736+
tmp = (struct acpi_dmar_satc *)satcu->hdr;
3737+
if (satc->segment != tmp->segment)
3738+
continue;
3739+
if (satc->header.length != tmp->header.length)
3740+
continue;
3741+
if (memcmp(satc, tmp, satc->header.length) == 0)
3742+
return satcu;
3743+
}
3744+
3745+
return NULL;
3746+
}
3747+
3748+
int dmar_parse_one_satc(struct acpi_dmar_header *hdr, void *arg)
3749+
{
3750+
struct acpi_dmar_satc *satc;
3751+
struct dmar_satc_unit *satcu;
3752+
3753+
if (system_state >= SYSTEM_RUNNING && !intel_iommu_enabled)
3754+
return 0;
3755+
3756+
satc = container_of(hdr, struct acpi_dmar_satc, header);
3757+
satcu = dmar_find_satc(satc);
3758+
if (satcu)
3759+
return 0;
3760+
3761+
satcu = kzalloc(sizeof(*satcu) + hdr->length, GFP_KERNEL);
3762+
if (!satcu)
3763+
return -ENOMEM;
3764+
3765+
satcu->hdr = (void *)(satcu + 1);
3766+
memcpy(satcu->hdr, hdr, hdr->length);
3767+
satcu->atc_required = satc->flags & 0x1;
3768+
satcu->devices = dmar_alloc_dev_scope((void *)(satc + 1),
3769+
(void *)satc + satc->header.length,
3770+
&satcu->devices_cnt);
3771+
if (satcu->devices_cnt && !satcu->devices) {
3772+
kfree(satcu);
3773+
return -ENOMEM;
3774+
}
3775+
list_add_rcu(&satcu->list, &dmar_satc_units);
3776+
3777+
return 0;
3778+
}
3779+
37193780
static int intel_iommu_add(struct dmar_drhd_unit *dmaru)
37203781
{
37213782
int sp, ret;
@@ -3823,6 +3884,7 @@ static void intel_iommu_free_dmars(void)
38233884
{
38243885
struct dmar_rmrr_unit *rmrru, *rmrr_n;
38253886
struct dmar_atsr_unit *atsru, *atsr_n;
3887+
struct dmar_satc_unit *satcu, *satc_n;
38263888

38273889
list_for_each_entry_safe(rmrru, rmrr_n, &dmar_rmrr_units, list) {
38283890
list_del(&rmrru->list);
@@ -3834,6 +3896,11 @@ static void intel_iommu_free_dmars(void)
38343896
list_del(&atsru->list);
38353897
intel_iommu_free_atsr(atsru);
38363898
}
3899+
list_for_each_entry_safe(satcu, satc_n, &dmar_satc_units, list) {
3900+
list_del(&satcu->list);
3901+
dmar_free_dev_scope(&satcu->devices, &satcu->devices_cnt);
3902+
kfree(satcu);
3903+
}
38373904
}
38383905

38393906
int dmar_find_matched_atsr_unit(struct pci_dev *dev)
@@ -3885,8 +3952,10 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
38853952
int ret;
38863953
struct dmar_rmrr_unit *rmrru;
38873954
struct dmar_atsr_unit *atsru;
3955+
struct dmar_satc_unit *satcu;
38883956
struct acpi_dmar_atsr *atsr;
38893957
struct acpi_dmar_reserved_memory *rmrr;
3958+
struct acpi_dmar_satc *satc;
38903959

38913960
if (!intel_iommu_enabled && system_state >= SYSTEM_RUNNING)
38923961
return 0;
@@ -3927,6 +3996,23 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
39273996
break;
39283997
}
39293998
}
3999+
list_for_each_entry(satcu, &dmar_satc_units, list) {
4000+
satc = container_of(satcu->hdr, struct acpi_dmar_satc, header);
4001+
if (info->event == BUS_NOTIFY_ADD_DEVICE) {
4002+
ret = dmar_insert_dev_scope(info, (void *)(satc + 1),
4003+
(void *)satc + satc->header.length,
4004+
satc->segment, satcu->devices,
4005+
satcu->devices_cnt);
4006+
if (ret > 0)
4007+
break;
4008+
else if (ret < 0)
4009+
return ret;
4010+
} else if (info->event == BUS_NOTIFY_REMOVED_DEVICE) {
4011+
if (dmar_remove_dev_scope(info, satc->segment,
4012+
satcu->devices, satcu->devices_cnt))
4013+
break;
4014+
}
4015+
}
39304016

39314017
return 0;
39324018
}
@@ -4270,6 +4356,9 @@ int __init intel_iommu_init(void)
42704356
if (list_empty(&dmar_atsr_units))
42714357
pr_info("No ATSR found\n");
42724358

4359+
if (list_empty(&dmar_satc_units))
4360+
pr_info("No SATC found\n");
4361+
42734362
if (dmar_map_gfx)
42744363
intel_iommu_gfx_mapped = 1;
42754364

include/linux/dmar.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ extern void intel_iommu_shutdown(void);
138138
extern int dmar_parse_one_rmrr(struct acpi_dmar_header *header, void *arg);
139139
extern int dmar_parse_one_atsr(struct acpi_dmar_header *header, void *arg);
140140
extern int dmar_check_one_atsr(struct acpi_dmar_header *hdr, void *arg);
141+
extern int dmar_parse_one_satc(struct acpi_dmar_header *hdr, void *arg);
141142
extern int dmar_release_one_atsr(struct acpi_dmar_header *hdr, void *arg);
142143
extern int dmar_iommu_hotplug(struct dmar_drhd_unit *dmaru, bool insert);
143144
extern int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info);
@@ -149,6 +150,7 @@ static inline void intel_iommu_shutdown(void) { }
149150
#define dmar_parse_one_atsr dmar_res_noop
150151
#define dmar_check_one_atsr dmar_res_noop
151152
#define dmar_release_one_atsr dmar_res_noop
153+
#define dmar_parse_one_satc dmar_res_noop
152154

153155
static inline int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
154156
{

0 commit comments

Comments
 (0)