Skip to content

Commit 92d03cc

Browse files
Jiang Liujoergroedel
authored andcommitted
iommu/vt-d: Reduce duplicated code to handle virtual machine domains
Reduce duplicated code to handle virtual machine domains, there's no functionality changes. It also improves code readability. Signed-off-by: Jiang Liu <[email protected]> Signed-off-by: Joerg Roedel <[email protected]>
1 parent e85bb5d commit 92d03cc

File tree

1 file changed

+45
-132
lines changed

1 file changed

+45
-132
lines changed

drivers/iommu/intel-iommu.c

Lines changed: 45 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -425,9 +425,12 @@ static LIST_HEAD(unmaps_to_do);
425425
static int timer_on;
426426
static long list_size;
427427

428+
static void domain_exit(struct dmar_domain *domain);
428429
static void domain_remove_dev_info(struct dmar_domain *domain);
429430
static void domain_remove_one_dev_info(struct dmar_domain *domain,
430431
struct pci_dev *pdev);
432+
static void iommu_detach_dependent_devices(struct intel_iommu *iommu,
433+
struct pci_dev *pdev);
431434

432435
#ifdef CONFIG_INTEL_IOMMU_DEFAULT_ON
433436
int dmar_disabled = 0;
@@ -1286,10 +1289,6 @@ static int iommu_init_domains(struct intel_iommu *iommu)
12861289
return 0;
12871290
}
12881291

1289-
1290-
static void domain_exit(struct dmar_domain *domain);
1291-
static void vm_domain_exit(struct dmar_domain *domain);
1292-
12931292
static void free_dmar_iommu(struct intel_iommu *iommu)
12941293
{
12951294
struct dmar_domain *domain;
@@ -1304,12 +1303,8 @@ static void free_dmar_iommu(struct intel_iommu *iommu)
13041303
spin_lock_irqsave(&domain->iommu_lock, flags);
13051304
count = --domain->iommu_count;
13061305
spin_unlock_irqrestore(&domain->iommu_lock, flags);
1307-
if (count == 0) {
1308-
if (domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE)
1309-
vm_domain_exit(domain);
1310-
else
1311-
domain_exit(domain);
1312-
}
1306+
if (count == 0)
1307+
domain_exit(domain);
13131308
}
13141309
}
13151310

@@ -1327,17 +1322,26 @@ static void free_dmar_iommu(struct intel_iommu *iommu)
13271322
free_context_table(iommu);
13281323
}
13291324

1330-
static struct dmar_domain *alloc_domain(void)
1325+
static struct dmar_domain *alloc_domain(bool vm)
13311326
{
1327+
/* domain id for virtual machine, it won't be set in context */
1328+
static atomic_t vm_domid = ATOMIC_INIT(0);
13321329
struct dmar_domain *domain;
13331330

13341331
domain = alloc_domain_mem();
13351332
if (!domain)
13361333
return NULL;
13371334

13381335
domain->nid = -1;
1336+
domain->iommu_count = 0;
13391337
memset(domain->iommu_bmp, 0, sizeof(domain->iommu_bmp));
13401338
domain->flags = 0;
1339+
spin_lock_init(&domain->iommu_lock);
1340+
INIT_LIST_HEAD(&domain->devices);
1341+
if (vm) {
1342+
domain->id = atomic_inc_return(&vm_domid);
1343+
domain->flags = DOMAIN_FLAG_VIRTUAL_MACHINE;
1344+
}
13411345

13421346
return domain;
13431347
}
@@ -1374,22 +1378,16 @@ static void iommu_detach_domain(struct dmar_domain *domain,
13741378
{
13751379
unsigned long flags;
13761380
int num, ndomains;
1377-
int found = 0;
13781381

13791382
spin_lock_irqsave(&iommu->lock, flags);
13801383
ndomains = cap_ndoms(iommu->cap);
13811384
for_each_set_bit(num, iommu->domain_ids, ndomains) {
13821385
if (iommu->domains[num] == domain) {
1383-
found = 1;
1386+
clear_bit(num, iommu->domain_ids);
1387+
iommu->domains[num] = NULL;
13841388
break;
13851389
}
13861390
}
1387-
1388-
if (found) {
1389-
clear_bit(num, iommu->domain_ids);
1390-
clear_bit(iommu->seq_id, domain->iommu_bmp);
1391-
iommu->domains[num] = NULL;
1392-
}
13931391
spin_unlock_irqrestore(&iommu->lock, flags);
13941392
}
13951393

@@ -1461,8 +1459,6 @@ static int domain_init(struct dmar_domain *domain, int guest_width)
14611459
unsigned long sagaw;
14621460

14631461
init_iova_domain(&domain->iovad, DMA_32BIT_PFN);
1464-
spin_lock_init(&domain->iommu_lock);
1465-
14661462
domain_reserve_special_ranges(domain);
14671463

14681464
/* calculate AGAW */
@@ -1481,7 +1477,6 @@ static int domain_init(struct dmar_domain *domain, int guest_width)
14811477
return -ENODEV;
14821478
}
14831479
domain->agaw = agaw;
1484-
INIT_LIST_HEAD(&domain->devices);
14851480

14861481
if (ecap_coherent(iommu->ecap))
14871482
domain->iommu_coherency = 1;
@@ -1518,7 +1513,9 @@ static void domain_exit(struct dmar_domain *domain)
15181513
if (!intel_iommu_strict)
15191514
flush_unmaps_timeout(0);
15201515

1516+
/* remove associated devices */
15211517
domain_remove_dev_info(domain);
1518+
15221519
/* destroy iovas */
15231520
put_iova_domain(&domain->iovad);
15241521

@@ -1528,8 +1525,10 @@ static void domain_exit(struct dmar_domain *domain)
15281525
/* free page tables */
15291526
dma_pte_free_pagetable(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
15301527

1528+
/* clear attached or cached domains */
15311529
for_each_active_iommu(iommu, drhd)
1532-
if (test_bit(iommu->seq_id, domain->iommu_bmp))
1530+
if (domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE ||
1531+
test_bit(iommu->seq_id, domain->iommu_bmp))
15331532
iommu_detach_domain(domain, iommu);
15341533

15351534
free_domain_mem(domain);
@@ -1921,7 +1920,7 @@ static inline void unlink_domain_info(struct device_domain_info *info)
19211920
static void domain_remove_dev_info(struct dmar_domain *domain)
19221921
{
19231922
struct device_domain_info *info;
1924-
unsigned long flags;
1923+
unsigned long flags, flags2;
19251924
struct intel_iommu *iommu;
19261925

19271926
spin_lock_irqsave(&device_domain_lock, flags);
@@ -1934,8 +1933,22 @@ static void domain_remove_dev_info(struct dmar_domain *domain)
19341933
iommu_disable_dev_iotlb(info);
19351934
iommu = device_to_iommu(info->segment, info->bus, info->devfn);
19361935
iommu_detach_dev(iommu, info->bus, info->devfn);
1937-
free_devinfo_mem(info);
19381936

1937+
if (domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) {
1938+
iommu_detach_dependent_devices(iommu, info->dev);
1939+
/* clear this iommu in iommu_bmp, update iommu count
1940+
* and capabilities
1941+
*/
1942+
spin_lock_irqsave(&domain->iommu_lock, flags2);
1943+
if (test_and_clear_bit(iommu->seq_id,
1944+
domain->iommu_bmp)) {
1945+
domain->iommu_count--;
1946+
domain_update_iommu_cap(domain);
1947+
}
1948+
spin_unlock_irqrestore(&domain->iommu_lock, flags2);
1949+
}
1950+
1951+
free_devinfo_mem(info);
19391952
spin_lock_irqsave(&device_domain_lock, flags);
19401953
}
19411954
spin_unlock_irqrestore(&device_domain_lock, flags);
@@ -2055,7 +2068,7 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
20552068
iommu = drhd->iommu;
20562069

20572070
/* Allocate and intialize new domain for the device */
2058-
domain = alloc_domain();
2071+
domain = alloc_domain(false);
20592072
if (!domain)
20602073
goto error;
20612074
if (iommu_attach_domain(domain, iommu)) {
@@ -2220,10 +2233,12 @@ static int __init si_domain_init(int hw)
22202233
struct intel_iommu *iommu;
22212234
int nid, ret = 0;
22222235

2223-
si_domain = alloc_domain();
2236+
si_domain = alloc_domain(false);
22242237
if (!si_domain)
22252238
return -EFAULT;
22262239

2240+
si_domain->flags = DOMAIN_FLAG_STATIC_IDENTITY;
2241+
22272242
for_each_active_iommu(iommu, drhd) {
22282243
ret = iommu_attach_domain(si_domain, iommu);
22292244
if (ret) {
@@ -2237,7 +2252,6 @@ static int __init si_domain_init(int hw)
22372252
return -EFAULT;
22382253
}
22392254

2240-
si_domain->flags = DOMAIN_FLAG_STATIC_IDENTITY;
22412255
pr_debug("IOMMU: identity mapping domain is domain %d\n",
22422256
si_domain->id);
22432257

@@ -3810,77 +3824,18 @@ static void domain_remove_one_dev_info(struct dmar_domain *domain,
38103824
}
38113825
}
38123826

3813-
static void vm_domain_remove_all_dev_info(struct dmar_domain *domain)
3814-
{
3815-
struct device_domain_info *info;
3816-
struct intel_iommu *iommu;
3817-
unsigned long flags1, flags2;
3818-
3819-
spin_lock_irqsave(&device_domain_lock, flags1);
3820-
while (!list_empty(&domain->devices)) {
3821-
info = list_entry(domain->devices.next,
3822-
struct device_domain_info, link);
3823-
unlink_domain_info(info);
3824-
spin_unlock_irqrestore(&device_domain_lock, flags1);
3825-
3826-
iommu_disable_dev_iotlb(info);
3827-
iommu = device_to_iommu(info->segment, info->bus, info->devfn);
3828-
iommu_detach_dev(iommu, info->bus, info->devfn);
3829-
iommu_detach_dependent_devices(iommu, info->dev);
3830-
3831-
/* clear this iommu in iommu_bmp, update iommu count
3832-
* and capabilities
3833-
*/
3834-
spin_lock_irqsave(&domain->iommu_lock, flags2);
3835-
if (test_and_clear_bit(iommu->seq_id,
3836-
domain->iommu_bmp)) {
3837-
domain->iommu_count--;
3838-
domain_update_iommu_cap(domain);
3839-
}
3840-
spin_unlock_irqrestore(&domain->iommu_lock, flags2);
3841-
3842-
free_devinfo_mem(info);
3843-
spin_lock_irqsave(&device_domain_lock, flags1);
3844-
}
3845-
spin_unlock_irqrestore(&device_domain_lock, flags1);
3846-
}
3847-
3848-
/* domain id for virtual machine, it won't be set in context */
3849-
static atomic_t vm_domid = ATOMIC_INIT(0);
3850-
3851-
static struct dmar_domain *iommu_alloc_vm_domain(void)
3852-
{
3853-
struct dmar_domain *domain;
3854-
3855-
domain = alloc_domain_mem();
3856-
if (!domain)
3857-
return NULL;
3858-
3859-
domain->id = atomic_inc_return(&vm_domid);
3860-
domain->nid = -1;
3861-
memset(domain->iommu_bmp, 0, sizeof(domain->iommu_bmp));
3862-
domain->flags = DOMAIN_FLAG_VIRTUAL_MACHINE;
3863-
3864-
return domain;
3865-
}
3866-
38673827
static int md_domain_init(struct dmar_domain *domain, int guest_width)
38683828
{
38693829
int adjust_width;
38703830

38713831
init_iova_domain(&domain->iovad, DMA_32BIT_PFN);
3872-
spin_lock_init(&domain->iommu_lock);
3873-
38743832
domain_reserve_special_ranges(domain);
38753833

38763834
/* calculate AGAW */
38773835
domain->gaw = guest_width;
38783836
adjust_width = guestwidth_to_adjustwidth(guest_width);
38793837
domain->agaw = width_to_agaw(adjust_width);
38803838

3881-
INIT_LIST_HEAD(&domain->devices);
3882-
3883-
domain->iommu_count = 0;
38843839
domain->iommu_coherency = 0;
38853840
domain->iommu_snooping = 0;
38863841
domain->iommu_superpage = 0;
@@ -3895,53 +3850,11 @@ static int md_domain_init(struct dmar_domain *domain, int guest_width)
38953850
return 0;
38963851
}
38973852

3898-
static void iommu_free_vm_domain(struct dmar_domain *domain)
3899-
{
3900-
unsigned long flags;
3901-
struct dmar_drhd_unit *drhd;
3902-
struct intel_iommu *iommu;
3903-
unsigned long i;
3904-
unsigned long ndomains;
3905-
3906-
for_each_active_iommu(iommu, drhd) {
3907-
ndomains = cap_ndoms(iommu->cap);
3908-
for_each_set_bit(i, iommu->domain_ids, ndomains) {
3909-
if (iommu->domains[i] == domain) {
3910-
spin_lock_irqsave(&iommu->lock, flags);
3911-
clear_bit(i, iommu->domain_ids);
3912-
iommu->domains[i] = NULL;
3913-
spin_unlock_irqrestore(&iommu->lock, flags);
3914-
break;
3915-
}
3916-
}
3917-
}
3918-
}
3919-
3920-
static void vm_domain_exit(struct dmar_domain *domain)
3921-
{
3922-
/* Domain 0 is reserved, so dont process it */
3923-
if (!domain)
3924-
return;
3925-
3926-
vm_domain_remove_all_dev_info(domain);
3927-
/* destroy iovas */
3928-
put_iova_domain(&domain->iovad);
3929-
3930-
/* clear ptes */
3931-
dma_pte_clear_range(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
3932-
3933-
/* free page tables */
3934-
dma_pte_free_pagetable(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
3935-
3936-
iommu_free_vm_domain(domain);
3937-
free_domain_mem(domain);
3938-
}
3939-
39403853
static int intel_iommu_domain_init(struct iommu_domain *domain)
39413854
{
39423855
struct dmar_domain *dmar_domain;
39433856

3944-
dmar_domain = iommu_alloc_vm_domain();
3857+
dmar_domain = alloc_domain(true);
39453858
if (!dmar_domain) {
39463859
printk(KERN_ERR
39473860
"intel_iommu_domain_init: dmar_domain == NULL\n");
@@ -3950,7 +3863,7 @@ static int intel_iommu_domain_init(struct iommu_domain *domain)
39503863
if (md_domain_init(dmar_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
39513864
printk(KERN_ERR
39523865
"intel_iommu_domain_init() failed\n");
3953-
vm_domain_exit(dmar_domain);
3866+
domain_exit(dmar_domain);
39543867
return -ENOMEM;
39553868
}
39563869
domain_update_iommu_cap(dmar_domain);
@@ -3968,7 +3881,7 @@ static void intel_iommu_domain_destroy(struct iommu_domain *domain)
39683881
struct dmar_domain *dmar_domain = domain->priv;
39693882

39703883
domain->priv = NULL;
3971-
vm_domain_exit(dmar_domain);
3884+
domain_exit(dmar_domain);
39723885
}
39733886

39743887
static int intel_iommu_attach_device(struct iommu_domain *domain,

0 commit comments

Comments
 (0)