Skip to content

Commit 4de354e

Browse files
LuBaolujoergroedel
authored andcommitted
iommu/vt-d: Delegate the identity domain to upper layer
This allows the iommu generic layer to allocate an identity domain and attach it to a device. Hence, the identity domain is delegated to upper layer. As a side effect, iommu_identity_mapping can't be used to check the existence of identity domains any more. Signed-off-by: James Sewart <[email protected]> Signed-off-by: Lu Baolu <[email protected]> Signed-off-by: Joerg Roedel <[email protected]>
1 parent f273a45 commit 4de354e

File tree

1 file changed

+58
-32
lines changed

1 file changed

+58
-32
lines changed

drivers/iommu/intel-iommu.c

Lines changed: 58 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@ static void domain_context_clear(struct intel_iommu *iommu,
350350
struct device *dev);
351351
static int domain_detach_iommu(struct dmar_domain *domain,
352352
struct intel_iommu *iommu);
353+
static bool device_is_rmrr_locked(struct device *dev);
353354

354355
#ifdef CONFIG_INTEL_IOMMU_DEFAULT_ON
355356
int dmar_disabled = 0;
@@ -2808,7 +2809,9 @@ static int md_domain_init(struct dmar_domain *domain, int guest_width);
28082809

28092810
static int __init si_domain_init(int hw)
28102811
{
2811-
int nid, ret;
2812+
struct dmar_rmrr_unit *rmrr;
2813+
struct device *dev;
2814+
int i, nid, ret;
28122815

28132816
si_domain = alloc_domain(DOMAIN_FLAG_STATIC_IDENTITY);
28142817
if (!si_domain)
@@ -2819,8 +2822,6 @@ static int __init si_domain_init(int hw)
28192822
return -EFAULT;
28202823
}
28212824

2822-
pr_debug("Identity mapping domain allocated\n");
2823-
28242825
if (hw)
28252826
return 0;
28262827

@@ -2836,16 +2837,38 @@ static int __init si_domain_init(int hw)
28362837
}
28372838
}
28382839

2840+
/*
2841+
* Normally we use DMA domains for devices which have RMRRs. But we
2842+
* loose this requirement for graphic and usb devices. Identity map
2843+
* the RMRRs for graphic and USB devices so that they could use the
2844+
* si_domain.
2845+
*/
2846+
for_each_rmrr_units(rmrr) {
2847+
for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt,
2848+
i, dev) {
2849+
unsigned long long start = rmrr->base_address;
2850+
unsigned long long end = rmrr->end_address;
2851+
2852+
if (device_is_rmrr_locked(dev))
2853+
continue;
2854+
2855+
if (WARN_ON(end < start ||
2856+
end >> agaw_to_width(si_domain->agaw)))
2857+
continue;
2858+
2859+
ret = iommu_domain_identity_map(si_domain, start, end);
2860+
if (ret)
2861+
return ret;
2862+
}
2863+
}
2864+
28392865
return 0;
28402866
}
28412867

28422868
static int identity_mapping(struct device *dev)
28432869
{
28442870
struct device_domain_info *info;
28452871

2846-
if (likely(!iommu_identity_mapping))
2847-
return 0;
2848-
28492872
info = dev->archdata.iommu;
28502873
if (info && info != DUMMY_DEVICE_DOMAIN_INFO)
28512874
return (info->domain == si_domain);
@@ -3431,11 +3454,9 @@ static int __init init_dmars(void)
34313454

34323455
check_tylersburg_isoch();
34333456

3434-
if (iommu_identity_mapping) {
3435-
ret = si_domain_init(hw_pass_through);
3436-
if (ret)
3437-
goto free_iommu;
3438-
}
3457+
ret = si_domain_init(hw_pass_through);
3458+
if (ret)
3459+
goto free_iommu;
34393460

34403461

34413462
/*
@@ -3628,9 +3649,6 @@ static bool iommu_need_mapping(struct device *dev)
36283649
if (iommu_dummy(dev))
36293650
return false;
36303651

3631-
if (!iommu_identity_mapping)
3632-
return true;
3633-
36343652
found = identity_mapping(dev);
36353653
if (found) {
36363654
if (iommu_should_identity_map(dev, 0))
@@ -5051,32 +5069,40 @@ static struct iommu_domain *intel_iommu_domain_alloc(unsigned type)
50515069
struct dmar_domain *dmar_domain;
50525070
struct iommu_domain *domain;
50535071

5054-
if (type != IOMMU_DOMAIN_UNMANAGED)
5055-
return NULL;
5072+
switch (type) {
5073+
case IOMMU_DOMAIN_UNMANAGED:
5074+
dmar_domain = alloc_domain(DOMAIN_FLAG_VIRTUAL_MACHINE);
5075+
if (!dmar_domain) {
5076+
pr_err("Can't allocate dmar_domain\n");
5077+
return NULL;
5078+
}
5079+
if (md_domain_init(dmar_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
5080+
pr_err("Domain initialization failed\n");
5081+
domain_exit(dmar_domain);
5082+
return NULL;
5083+
}
5084+
domain_update_iommu_cap(dmar_domain);
50565085

5057-
dmar_domain = alloc_domain(DOMAIN_FLAG_VIRTUAL_MACHINE);
5058-
if (!dmar_domain) {
5059-
pr_err("Can't allocate dmar_domain\n");
5060-
return NULL;
5061-
}
5062-
if (md_domain_init(dmar_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
5063-
pr_err("Domain initialization failed\n");
5064-
domain_exit(dmar_domain);
5086+
domain = &dmar_domain->domain;
5087+
domain->geometry.aperture_start = 0;
5088+
domain->geometry.aperture_end =
5089+
__DOMAIN_MAX_ADDR(dmar_domain->gaw);
5090+
domain->geometry.force_aperture = true;
5091+
5092+
return domain;
5093+
case IOMMU_DOMAIN_IDENTITY:
5094+
return &si_domain->domain;
5095+
default:
50655096
return NULL;
50665097
}
5067-
domain_update_iommu_cap(dmar_domain);
5068-
5069-
domain = &dmar_domain->domain;
5070-
domain->geometry.aperture_start = 0;
5071-
domain->geometry.aperture_end = __DOMAIN_MAX_ADDR(dmar_domain->gaw);
5072-
domain->geometry.force_aperture = true;
50735098

5074-
return domain;
5099+
return NULL;
50755100
}
50765101

50775102
static void intel_iommu_domain_free(struct iommu_domain *domain)
50785103
{
5079-
domain_exit(to_dmar_domain(domain));
5104+
if (domain != &si_domain->domain)
5105+
domain_exit(to_dmar_domain(domain));
50805106
}
50815107

50825108
/*

0 commit comments

Comments
 (0)