Skip to content

Commit 5e98c4b

Browse files
Weidong Hanjoergroedel
authored andcommitted
Allocation and free functions of virtual machine domain
virtual machine domain is different from native DMA-API domain, implement separate allocation and free functions for virtual machine domain. Signed-off-by: Weidong Han <weidong.han@intel.com> Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
1 parent 5331fe6 commit 5e98c4b

File tree

1 file changed

+105
-2
lines changed

1 file changed

+105
-2
lines changed

drivers/pci/intel-iommu.c

Lines changed: 105 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1216,6 +1216,7 @@ static int iommu_init_domains(struct intel_iommu *iommu)
12161216

12171217

12181218
static void domain_exit(struct dmar_domain *domain);
1219+
static void vm_domain_exit(struct dmar_domain *domain);
12191220

12201221
void free_dmar_iommu(struct intel_iommu *iommu)
12211222
{
@@ -1229,8 +1230,12 @@ void free_dmar_iommu(struct intel_iommu *iommu)
12291230
clear_bit(i, iommu->domain_ids);
12301231

12311232
spin_lock_irqsave(&domain->iommu_lock, flags);
1232-
if (--domain->iommu_count == 0)
1233-
domain_exit(domain);
1233+
if (--domain->iommu_count == 0) {
1234+
if (domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE)
1235+
vm_domain_exit(domain);
1236+
else
1237+
domain_exit(domain);
1238+
}
12341239
spin_unlock_irqrestore(&domain->iommu_lock, flags);
12351240

12361241
i = find_next_bit(iommu->domain_ids,
@@ -2792,6 +2797,104 @@ static void vm_domain_remove_all_dev_info(struct dmar_domain *domain)
27922797
spin_unlock_irqrestore(&device_domain_lock, flags1);
27932798
}
27942799

2800+
/* domain id for virtual machine, it won't be set in context */
2801+
static unsigned long vm_domid;
2802+
2803+
static struct dmar_domain *iommu_alloc_vm_domain(void)
2804+
{
2805+
struct dmar_domain *domain;
2806+
2807+
domain = alloc_domain_mem();
2808+
if (!domain)
2809+
return NULL;
2810+
2811+
domain->id = vm_domid++;
2812+
memset(&domain->iommu_bmp, 0, sizeof(unsigned long));
2813+
domain->flags = DOMAIN_FLAG_VIRTUAL_MACHINE;
2814+
2815+
return domain;
2816+
}
2817+
2818+
static int vm_domain_init(struct dmar_domain *domain, int guest_width)
2819+
{
2820+
int adjust_width;
2821+
2822+
init_iova_domain(&domain->iovad, DMA_32BIT_PFN);
2823+
spin_lock_init(&domain->mapping_lock);
2824+
spin_lock_init(&domain->iommu_lock);
2825+
2826+
domain_reserve_special_ranges(domain);
2827+
2828+
/* calculate AGAW */
2829+
domain->gaw = guest_width;
2830+
adjust_width = guestwidth_to_adjustwidth(guest_width);
2831+
domain->agaw = width_to_agaw(adjust_width);
2832+
2833+
INIT_LIST_HEAD(&domain->devices);
2834+
2835+
domain->iommu_count = 0;
2836+
domain->iommu_coherency = 0;
2837+
2838+
/* always allocate the top pgd */
2839+
domain->pgd = (struct dma_pte *)alloc_pgtable_page();
2840+
if (!domain->pgd)
2841+
return -ENOMEM;
2842+
domain_flush_cache(domain, domain->pgd, PAGE_SIZE);
2843+
return 0;
2844+
}
2845+
2846+
static void iommu_free_vm_domain(struct dmar_domain *domain)
2847+
{
2848+
unsigned long flags;
2849+
struct dmar_drhd_unit *drhd;
2850+
struct intel_iommu *iommu;
2851+
unsigned long i;
2852+
unsigned long ndomains;
2853+
2854+
for_each_drhd_unit(drhd) {
2855+
if (drhd->ignored)
2856+
continue;
2857+
iommu = drhd->iommu;
2858+
2859+
ndomains = cap_ndoms(iommu->cap);
2860+
i = find_first_bit(iommu->domain_ids, ndomains);
2861+
for (; i < ndomains; ) {
2862+
if (iommu->domains[i] == domain) {
2863+
spin_lock_irqsave(&iommu->lock, flags);
2864+
clear_bit(i, iommu->domain_ids);
2865+
iommu->domains[i] = NULL;
2866+
spin_unlock_irqrestore(&iommu->lock, flags);
2867+
break;
2868+
}
2869+
i = find_next_bit(iommu->domain_ids, ndomains, i+1);
2870+
}
2871+
}
2872+
}
2873+
2874+
static void vm_domain_exit(struct dmar_domain *domain)
2875+
{
2876+
u64 end;
2877+
2878+
/* Domain 0 is reserved, so dont process it */
2879+
if (!domain)
2880+
return;
2881+
2882+
vm_domain_remove_all_dev_info(domain);
2883+
/* destroy iovas */
2884+
put_iova_domain(&domain->iovad);
2885+
end = DOMAIN_MAX_ADDR(domain->gaw);
2886+
end = end & (~VTD_PAGE_MASK);
2887+
2888+
/* clear ptes */
2889+
dma_pte_clear_range(domain, 0, end);
2890+
2891+
/* free page tables */
2892+
dma_pte_free_pagetable(domain, 0, end);
2893+
2894+
iommu_free_vm_domain(domain);
2895+
free_domain_mem(domain);
2896+
}
2897+
27952898
void intel_iommu_domain_exit(struct dmar_domain *domain)
27962899
{
27972900
u64 end;

0 commit comments

Comments
 (0)