struct dmar_domain {
        int     id;                     /* domain id */
-       struct intel_iommu *iommu;      /* back pointer to owning iommu */
+       unsigned long iommu_bmp;        /* bitmap of iommus this domain uses*/
 
        struct list_head devices;       /* all devices' list */
        struct iova_domain iovad;       /* iova's that belong to this domain */
        kmem_cache_free(iommu_iova_cache, iova);
 }
 
+/* in native case, each domain is related to only one iommu */
+static struct intel_iommu *domain_get_iommu(struct dmar_domain *domain)
+{
+       int iommu_id;
+
+       iommu_id = find_first_bit(&domain->iommu_bmp, g_num_of_iommus);
+       if (iommu_id < 0 || iommu_id >= g_num_of_iommus)
+               return NULL;
+
+       return g_iommus[iommu_id];
+}
+
 /* Gets context entry for a given bus and devfn */
 static struct context_entry * device_to_context_entry(struct intel_iommu *iommu,
                u8 bus, u8 devfn)
        int level = agaw_to_level(domain->agaw);
        int offset;
        unsigned long flags;
+       struct intel_iommu *iommu = domain_get_iommu(domain);
 
        BUG_ON(!domain->pgd);
 
                                        flags);
                                return NULL;
                        }
-                       __iommu_flush_cache(domain->iommu, tmp_page,
+                       __iommu_flush_cache(iommu, tmp_page,
                                        PAGE_SIZE);
                        dma_set_pte_addr(pte, virt_to_phys(tmp_page));
                        /*
                         */
                        dma_set_pte_readable(pte);
                        dma_set_pte_writable(pte);
-                       __iommu_flush_cache(domain->iommu, pte, sizeof(*pte));
+                       __iommu_flush_cache(iommu, pte, sizeof(*pte));
                }
                parent = phys_to_virt(dma_pte_addr(pte));
                level--;
 static void dma_pte_clear_one(struct dmar_domain *domain, u64 addr)
 {
        struct dma_pte *pte = NULL;
+       struct intel_iommu *iommu = domain_get_iommu(domain);
 
        /* get last level pte */
        pte = dma_addr_level_pte(domain, addr, 1);
 
        if (pte) {
                dma_clear_pte(pte);
-               __iommu_flush_cache(domain->iommu, pte, sizeof(*pte));
+               __iommu_flush_cache(iommu, pte, sizeof(*pte));
        }
 }
 
        int total = agaw_to_level(domain->agaw);
        int level;
        u64 tmp;
+       struct intel_iommu *iommu = domain_get_iommu(domain);
 
        start &= (((u64)1) << addr_width) - 1;
        end &= (((u64)1) << addr_width) - 1;
                                free_pgtable_page(
                                        phys_to_virt(dma_pte_addr(pte)));
                                dma_clear_pte(pte);
-                               __iommu_flush_cache(domain->iommu,
+                               __iommu_flush_cache(iommu,
                                                pte, sizeof(*pte));
                        }
                        tmp += level_size(level);
 
        set_bit(num, iommu->domain_ids);
        domain->id = num;
-       domain->iommu = iommu;
+       memset(&domain->iommu_bmp, 0, sizeof(unsigned long));
+       set_bit(iommu->seq_id, &domain->iommu_bmp);
        domain->flags = 0;
        iommu->domains[num] = domain;
        spin_unlock_irqrestore(&iommu->lock, flags);
 static void iommu_free_domain(struct dmar_domain *domain)
 {
        unsigned long flags;
+       struct intel_iommu *iommu;
+
+       iommu = domain_get_iommu(domain);
 
-       spin_lock_irqsave(&domain->iommu->lock, flags);
-       clear_bit(domain->id, domain->iommu->domain_ids);
-       spin_unlock_irqrestore(&domain->iommu->lock, flags);
+       spin_lock_irqsave(&iommu->lock, flags);
+       clear_bit(domain->id, iommu->domain_ids);
+       spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
 static struct iova_domain reserved_iova_list;
        domain_reserve_special_ranges(domain);
 
        /* calculate AGAW */
-       iommu = domain->iommu;
+       iommu = domain_get_iommu(domain);
        if (guest_width > cap_mgaw(iommu->cap))
                guest_width = cap_mgaw(iommu->cap);
        domain->gaw = guest_width;
                u8 bus, u8 devfn)
 {
        struct context_entry *context;
-       struct intel_iommu *iommu = domain->iommu;
+       struct intel_iommu *iommu = domain_get_iommu(domain);
        unsigned long flags;
 
        pr_debug("Set context mapping for %02x:%02x.%d\n",
 {
        int ret;
        struct pci_dev *tmp, *parent;
+       struct intel_iommu *iommu = domain_get_iommu(domain);
 
-       ret = device_context_mapped(domain->iommu,
+       ret = device_context_mapped(iommu,
                pdev->bus->number, pdev->devfn);
        if (!ret)
                return ret;
        /* Secondary interface's bus number and devfn 0 */
        parent = pdev->bus->self;
        while (parent != tmp) {
-               ret = device_context_mapped(domain->iommu, parent->bus->number,
+               ret = device_context_mapped(iommu, parent->bus->number,
                        parent->devfn);
                if (!ret)
                        return ret;
                parent = parent->bus->self;
        }
        if (tmp->is_pcie)
-               return device_context_mapped(domain->iommu,
+               return device_context_mapped(iommu,
                        tmp->subordinate->number, 0);
        else
-               return device_context_mapped(domain->iommu,
+               return device_context_mapped(iommu,
                        tmp->bus->number, tmp->devfn);
 }
 
        struct dma_pte *pte;
        int index;
        int addr_width = agaw_to_width(domain->agaw);
+       struct intel_iommu *iommu = domain_get_iommu(domain);
 
        hpa &= (((u64)1) << addr_width) - 1;
 
                BUG_ON(dma_pte_addr(pte));
                dma_set_pte_addr(pte, start_pfn << VTD_PAGE_SHIFT);
                dma_set_pte_prot(pte, prot);
-               __iommu_flush_cache(domain->iommu, pte, sizeof(*pte));
+               __iommu_flush_cache(iommu, pte, sizeof(*pte));
                start_pfn++;
                index++;
        }
 
 static void detach_domain_for_dev(struct dmar_domain *domain, u8 bus, u8 devfn)
 {
-       clear_context_table(domain->iommu, bus, devfn);
-       domain->iommu->flush.flush_context(domain->iommu, 0, 0, 0,
+       struct intel_iommu *iommu = domain_get_iommu(domain);
+
+       clear_context_table(iommu, bus, devfn);
+       iommu->flush.flush_context(iommu, 0, 0, 0,
                                           DMA_CCMD_GLOBAL_INVL, 0);
-       domain->iommu->flush.flush_iotlb(domain->iommu, 0, 0, 0,
+       iommu->flush.flush_iotlb(iommu, 0, 0, 0,
                                         DMA_TLB_GLOBAL_FLUSH, 0);
 }
 
        struct iova *iova;
        int prot = 0;
        int ret;
+       struct intel_iommu *iommu;
 
        BUG_ON(dir == DMA_NONE);
        if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
        if (!domain)
                return 0;
 
+       iommu = domain_get_iommu(domain);
        size = aligned_size((u64)paddr, size);
 
        iova = __intel_alloc_iova(hwdev, domain, size, pdev->dma_mask);
         * mappings..
         */
        if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
-                       !cap_zlr(domain->iommu->cap))
+                       !cap_zlr(iommu->cap))
                prot |= DMA_PTE_READ;
        if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
                prot |= DMA_PTE_WRITE;
                goto error;
 
        /* it's a non-present to present mapping */
-       ret = iommu_flush_iotlb_psi(domain->iommu, domain->id,
+       ret = iommu_flush_iotlb_psi(iommu, domain->id,
                        start_paddr, size >> VTD_PAGE_SHIFT, 1);
        if (ret)
-               iommu_flush_write_buffer(domain->iommu);
+               iommu_flush_write_buffer(iommu);
 
        return start_paddr + ((u64)paddr & (~PAGE_MASK));
 
 {
        unsigned long flags;
        int next, iommu_id;
+       struct intel_iommu *iommu;
 
        spin_lock_irqsave(&async_umap_flush_lock, flags);
        if (list_size == HIGH_WATER_MARK)
                flush_unmaps();
 
-       iommu_id = dom->iommu->seq_id;
+       iommu = domain_get_iommu(dom);
+       iommu_id = iommu->seq_id;
 
        next = deferred_flush[iommu_id].next;
        deferred_flush[iommu_id].domain[next] = dom;
        struct dmar_domain *domain;
        unsigned long start_addr;
        struct iova *iova;
+       struct intel_iommu *iommu;
 
        if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
                return;
        domain = find_domain(pdev);
        BUG_ON(!domain);
 
+       iommu = domain_get_iommu(domain);
+
        iova = find_iova(&domain->iovad, IOVA_PFN(dev_addr));
        if (!iova)
                return;
        /* free page tables */
        dma_pte_free_pagetable(domain, start_addr, start_addr + size);
        if (intel_iommu_strict) {
-               if (iommu_flush_iotlb_psi(domain->iommu,
+               if (iommu_flush_iotlb_psi(iommu,
                        domain->id, start_addr, size >> VTD_PAGE_SHIFT, 0))
-                       iommu_flush_write_buffer(domain->iommu);
+                       iommu_flush_write_buffer(iommu);
                /* free iova */
                __free_iova(&domain->iovad, iova);
        } else {
        size_t size = 0;
        void *addr;
        struct scatterlist *sg;
+       struct intel_iommu *iommu;
 
        if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
                return;
 
        domain = find_domain(pdev);
+       BUG_ON(!domain);
+
+       iommu = domain_get_iommu(domain);
 
        iova = find_iova(&domain->iovad, IOVA_PFN(sglist[0].dma_address));
        if (!iova)
        /* free page tables */
        dma_pte_free_pagetable(domain, start_addr, start_addr + size);
 
-       if (iommu_flush_iotlb_psi(domain->iommu, domain->id, start_addr,
+       if (iommu_flush_iotlb_psi(iommu, domain->id, start_addr,
                        size >> VTD_PAGE_SHIFT, 0))
-               iommu_flush_write_buffer(domain->iommu);
+               iommu_flush_write_buffer(iommu);
 
        /* free iova */
        __free_iova(&domain->iovad, iova);
        int ret;
        struct scatterlist *sg;
        unsigned long start_addr;
+       struct intel_iommu *iommu;
 
        BUG_ON(dir == DMA_NONE);
        if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
        if (!domain)
                return 0;
 
+       iommu = domain_get_iommu(domain);
+
        for_each_sg(sglist, sg, nelems, i) {
                addr = SG_ENT_VIRT_ADDRESS(sg);
                addr = (void *)virt_to_phys(addr);
         * mappings..
         */
        if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
-                       !cap_zlr(domain->iommu->cap))
+                       !cap_zlr(iommu->cap))
                prot |= DMA_PTE_READ;
        if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
                prot |= DMA_PTE_WRITE;
        }
 
        /* it's a non-present to present mapping */
-       if (iommu_flush_iotlb_psi(domain->iommu, domain->id,
+       if (iommu_flush_iotlb_psi(iommu, domain->id,
                        start_addr, offset >> VTD_PAGE_SHIFT, 1))
-               iommu_flush_write_buffer(domain->iommu);
+               iommu_flush_write_buffer(iommu);
        return nelems;
 }