[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] vtd: cleanups to iommu code.
# HG changeset patch # User Keir Fraser <keir@xxxxxxxxxxxxx> # Date 1190299282 -3600 # Node ID 7bd5b1f55308bb08228d8c3a4ed778b496f6cf3a # Parent 2477e94450aa11bdaa55d80dee05f6d0bc67f957 vtd: cleanups to iommu code. Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> --- xen/arch/x86/hvm/vmx/vtd/intel-iommu.c | 1349 +++++++++++++++++---------------- 1 files changed, 713 insertions(+), 636 deletions(-) diff -r 2477e94450aa -r 7bd5b1f55308 xen/arch/x86/hvm/vmx/vtd/intel-iommu.c --- a/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c Thu Sep 20 14:15:45 2007 +0100 +++ b/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c Thu Sep 20 15:41:22 2007 +0100 @@ -38,7 +38,7 @@ #define VTDPREFIX extern void print_iommu_regs(struct acpi_drhd_unit *drhd); extern void print_vtd_entries(struct domain *d, int bus, int devfn, - unsigned long gmfn); + unsigned long gmfn); #define DMAR_OPERATION_TIMEOUT (HZ*60) /* 1m */ @@ -51,13 +51,13 @@ void clflush_cache_range(void *adr, int void clflush_cache_range(void *adr, int size) { int i; - for (i = 0; i < size; i += x86_clflush_size) + for ( i = 0; i < size; i += x86_clflush_size ) clflush(adr + i); } static void __iommu_flush_cache(struct iommu *iommu, void *addr, int size) { - if (!ecap_coherent(iommu->ecap)) + if ( !ecap_coherent(iommu->ecap) ) clflush_cache_range(addr, size); } @@ -69,7 +69,7 @@ int nr_iommus; int nr_iommus; /* context entry handling */ static struct context_entry * device_to_context_entry(struct iommu *iommu, - u8 bus, u8 devfn) + u8 bus, u8 devfn) { struct root_entry *root; struct context_entry *context; @@ -78,9 +78,11 @@ static struct context_entry * device_to_ spin_lock_irqsave(&iommu->lock, flags); root = &iommu->root_entry[bus]; - if (!root_present(*root)) { + if ( !root_present(*root) ) + { phy_addr = (unsigned long) alloc_xenheap_page(); - if (!phy_addr) { + if ( !phy_addr ) + { spin_unlock_irqrestore(&iommu->lock, flags); return NULL; } @@ -107,14 +109,15 @@ static int device_context_mapped(struct spin_lock_irqsave(&iommu->lock, flags); root = &iommu->root_entry[bus]; - if (!root_present(*root)) { + if ( !root_present(*root) ) + { ret = 0; goto out; } phy_addr = get_context_addr(*root); context = (struct context_entry *)maddr_to_virt(phy_addr); ret = context_present(context[devfn]); -out: + out: spin_unlock_irqrestore(&iommu->lock, flags); return ret; } @@ -131,7 +134,7 @@ out: #define level_mask(l) (((u64)(-1)) << level_to_offset_bits(l)) #define level_size(l) (1 << level_to_offset_bits(l)) #define align_to_level(addr, l) ((addr + level_size(l) - 1) & level_mask(l)) -static struct dma_pte * addr_to_dma_pte(struct domain *domain, u64 addr) +static struct dma_pte *addr_to_dma_pte(struct domain *domain, u64 addr) { struct hvm_iommu *hd = domain_hvm_iommu(domain); struct acpi_drhd_unit *drhd; @@ -147,41 +150,43 @@ static struct dma_pte * addr_to_dma_pte( addr &= (((u64)1) << addr_width) - 1; spin_lock_irqsave(&hd->mapping_lock, flags); - if (!hd->pgd) { + if ( !hd->pgd ) + { pgd = (struct dma_pte *)alloc_xenheap_page(); - if (!pgd && !hd->pgd) { + if ( !pgd && !hd->pgd ) + { spin_unlock_irqrestore(&hd->mapping_lock, flags); return NULL; } memset((u8*)pgd, 0, PAGE_SIZE); - if (!hd->pgd) + if ( !hd->pgd ) hd->pgd = pgd; else /* somebody is fast */ free_xenheap_page((void *) pgd); } parent = hd->pgd; - while (level > 0) { + while ( level > 0 ) + { u8 *tmp; offset = address_level_offset(addr, level); pte = &parent[offset]; - if (level == 1) + if ( level == 1 ) break; - if (dma_pte_addr(*pte) == 0) { + if ( dma_pte_addr(*pte) == 0 ) + { tmp = alloc_xenheap_page(); - if (tmp == NULL) - gdprintk(XENLOG_ERR VTDPREFIX, - "addr_to_dma_pte: tmp == NULL\n"); - memset(tmp, 0, PAGE_SIZE); iommu_flush_cache_page(iommu, tmp); - if (!tmp && dma_pte_addr(*pte) == 0) { + if ( !tmp && dma_pte_addr(*pte) == 0 ) + { spin_unlock_irqrestore(&hd->mapping_lock, flags); return NULL; } - if (dma_pte_addr(*pte) == 0) { + if ( dma_pte_addr(*pte) == 0 ) + { dma_set_pte_addr(*pte, - virt_to_maddr(tmp)); + virt_to_maddr(tmp)); /* * high level table always sets r/w, last level * page table control read/write @@ -201,7 +206,7 @@ static struct dma_pte * addr_to_dma_pte( /* return address's pte at specific level */ static struct dma_pte *dma_addr_level_pte(struct domain *domain, u64 addr, - int level) + int level) { struct hvm_iommu *hd = domain_hvm_iommu(domain); struct dma_pte *parent, *pte = NULL; @@ -209,13 +214,14 @@ static struct dma_pte *dma_addr_level_pt int offset; parent = hd->pgd; - while (level <= total) { + while ( level <= total ) + { offset = address_level_offset(addr, total); pte = &parent[offset]; - if (level == total) + if ( level == total ) return pte; - if (dma_pte_addr(*pte) == 0) + if ( dma_pte_addr(*pte) == 0 ) break; parent = maddr_to_virt(dma_pte_addr(*pte)); total--; @@ -225,245 +231,257 @@ static struct dma_pte *dma_addr_level_pt static void iommu_flush_write_buffer(struct iommu *iommu) { - u32 val; - unsigned long flag; - unsigned long start_time; - - if (!cap_rwbf(iommu->cap)) - return; - val = iommu->gcmd | DMA_GCMD_WBF; - - spin_lock_irqsave(&iommu->register_lock, flag); - dmar_writel(iommu->reg, DMAR_GCMD_REG, val); - - /* Make sure hardware complete it */ - start_time = jiffies; - while (1) { - val = dmar_readl(iommu->reg, DMAR_GSTS_REG); - if (!(val & DMA_GSTS_WBFS)) - break; - if (time_after(jiffies, start_time + DMAR_OPERATION_TIMEOUT)) - panic("DMAR hardware is malfunctional, please disable IOMMU\n"); - cpu_relax(); - } - spin_unlock_irqrestore(&iommu->register_lock, flag); + u32 val; + unsigned long flag; + unsigned long start_time; + + if ( !cap_rwbf(iommu->cap) ) + return; + val = iommu->gcmd | DMA_GCMD_WBF; + + spin_lock_irqsave(&iommu->register_lock, flag); + dmar_writel(iommu->reg, DMAR_GCMD_REG, val); + + /* Make sure hardware complete it */ + start_time = jiffies; + for ( ; ; ) + { + val = dmar_readl(iommu->reg, DMAR_GSTS_REG); + if ( !(val & DMA_GSTS_WBFS) ) + break; + if ( time_after(jiffies, start_time + DMAR_OPERATION_TIMEOUT) ) + panic("DMAR hardware is malfunctional," + " please disable IOMMU\n"); + cpu_relax(); + } + spin_unlock_irqrestore(&iommu->register_lock, flag); } /* return value determine if we need a write buffer flush */ -static int __iommu_flush_context(struct iommu *iommu, - u16 did, u16 source_id, u8 function_mask, u64 type, - int non_present_entry_flush) -{ - u64 val = 0; - unsigned long flag; - unsigned long start_time; - - /* - * In the non-present entry flush case, if hardware doesn't cache - * non-present entry we do nothing and if hardware cache non-present - * entry, we flush entries of domain 0 (the domain id is used to cache - * any non-present entries) - */ - if (non_present_entry_flush) { - if (!cap_caching_mode(iommu->cap)) - return 1; - else - did = 0; - } - - /* use register invalidation */ - switch (type) - { - case DMA_CCMD_GLOBAL_INVL: - val = DMA_CCMD_GLOBAL_INVL; - break; - case DMA_CCMD_DOMAIN_INVL: - val = DMA_CCMD_DOMAIN_INVL|DMA_CCMD_DID(did); - break; - case DMA_CCMD_DEVICE_INVL: - val = DMA_CCMD_DEVICE_INVL|DMA_CCMD_DID(did) - |DMA_CCMD_SID(source_id)|DMA_CCMD_FM(function_mask); - break; - default: - BUG(); - } - val |= DMA_CCMD_ICC; - - spin_lock_irqsave(&iommu->register_lock, flag); - dmar_writeq(iommu->reg, DMAR_CCMD_REG, val); - - /* Make sure hardware complete it */ - start_time = jiffies; - while (1) { - val = dmar_readq(iommu->reg, DMAR_CCMD_REG); - if (!(val & DMA_CCMD_ICC)) - break; - if (time_after(jiffies, start_time + DMAR_OPERATION_TIMEOUT)) - panic("DMAR hardware is malfunctional, please disable IOMMU\n"); - cpu_relax(); - } - spin_unlock_irqrestore(&iommu->register_lock, flag); - /* flush context entry will implictly flush write buffer */ - return 0; -} - -static int inline iommu_flush_context_global(struct iommu *iommu, - int non_present_entry_flush) -{ - return __iommu_flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL, - non_present_entry_flush); -} - -static int inline iommu_flush_context_domain(struct iommu *iommu, u16 did, - int non_present_entry_flush) -{ - return __iommu_flush_context(iommu, did, 0, 0, DMA_CCMD_DOMAIN_INVL, - non_present_entry_flush); -} - -static int inline iommu_flush_context_device(struct iommu *iommu, - u16 did, u16 source_id, u8 function_mask, int non_present_entry_flush) -{ - return __iommu_flush_context(iommu, did, source_id, function_mask, - DMA_CCMD_DEVICE_INVL, non_present_entry_flush); +static int __iommu_flush_context( + struct iommu *iommu, + u16 did, u16 source_id, u8 function_mask, u64 type, + int non_present_entry_flush) +{ + u64 val = 0; + unsigned long flag; + unsigned long start_time; + + /* + * In the non-present entry flush case, if hardware doesn't cache + * non-present entry we do nothing and if hardware cache non-present + * entry, we flush entries of domain 0 (the domain id is used to cache + * any non-present entries) + */ + if ( non_present_entry_flush ) + { + if ( !cap_caching_mode(iommu->cap) ) + return 1; + else + did = 0; + } + + /* use register invalidation */ + switch ( type ) + { + case DMA_CCMD_GLOBAL_INVL: + val = DMA_CCMD_GLOBAL_INVL; + break; + case DMA_CCMD_DOMAIN_INVL: + val = DMA_CCMD_DOMAIN_INVL|DMA_CCMD_DID(did); + break; + case DMA_CCMD_DEVICE_INVL: + val = DMA_CCMD_DEVICE_INVL|DMA_CCMD_DID(did) + |DMA_CCMD_SID(source_id)|DMA_CCMD_FM(function_mask); + break; + default: + BUG(); + } + val |= DMA_CCMD_ICC; + + spin_lock_irqsave(&iommu->register_lock, flag); + dmar_writeq(iommu->reg, DMAR_CCMD_REG, val); + + /* Make sure hardware complete it */ + start_time = jiffies; + for ( ; ; ) + { + val = dmar_readq(iommu->reg, DMAR_CCMD_REG); + if ( !(val & DMA_CCMD_ICC) ) + break; + if ( time_after(jiffies, start_time + DMAR_OPERATION_TIMEOUT) ) + panic("DMAR hardware is malfunctional, please disable IOMMU\n"); + cpu_relax(); + } + spin_unlock_irqrestore(&iommu->register_lock, flag); + /* flush context entry will implictly flush write buffer */ + return 0; +} + +static int inline iommu_flush_context_global( + struct iommu *iommu, int non_present_entry_flush) +{ + return __iommu_flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL, + non_present_entry_flush); +} + +static int inline iommu_flush_context_domain( + struct iommu *iommu, u16 did, int non_present_entry_flush) +{ + return __iommu_flush_context(iommu, did, 0, 0, DMA_CCMD_DOMAIN_INVL, + non_present_entry_flush); +} + +static int inline iommu_flush_context_device( + struct iommu *iommu, u16 did, u16 source_id, + u8 function_mask, int non_present_entry_flush) +{ + return __iommu_flush_context(iommu, did, source_id, function_mask, + DMA_CCMD_DEVICE_INVL, + non_present_entry_flush); } /* return value determine if we need a write buffer flush */ static int __iommu_flush_iotlb(struct iommu *iommu, u16 did, - u64 addr, unsigned int size_order, u64 type, - int non_present_entry_flush) -{ - int tlb_offset = ecap_iotlb_offset(iommu->ecap); - u64 val = 0, val_iva = 0; - unsigned long flag; - unsigned long start_time; - - /* - * In the non-present entry flush case, if hardware doesn't cache - * non-present entry we do nothing and if hardware cache non-present - * entry, we flush entries of domain 0 (the domain id is used to cache - * any non-present entries) - */ - if (non_present_entry_flush) { - if (!cap_caching_mode(iommu->cap)) - return 1; - else - did = 0; - } - - /* use register invalidation */ - switch (type) { - case DMA_TLB_GLOBAL_FLUSH: - /* global flush doesn't need set IVA_REG */ - val = DMA_TLB_GLOBAL_FLUSH|DMA_TLB_IVT; - break; - case DMA_TLB_DSI_FLUSH: - val = DMA_TLB_DSI_FLUSH|DMA_TLB_IVT|DMA_TLB_DID(did); - break; - case DMA_TLB_PSI_FLUSH: - val = DMA_TLB_PSI_FLUSH|DMA_TLB_IVT|DMA_TLB_DID(did); - /* Note: always flush non-leaf currently */ - val_iva = size_order | addr; - break; - default: - BUG(); - } - /* Note: set drain read/write */ + u64 addr, unsigned int size_order, u64 type, + int non_present_entry_flush) +{ + int tlb_offset = ecap_iotlb_offset(iommu->ecap); + u64 val = 0, val_iva = 0; + unsigned long flag; + unsigned long start_time; + + /* + * In the non-present entry flush case, if hardware doesn't cache + * non-present entry we do nothing and if hardware cache non-present + * entry, we flush entries of domain 0 (the domain id is used to cache + * any non-present entries) + */ + if ( non_present_entry_flush ) + { + if ( !cap_caching_mode(iommu->cap) ) + return 1; + else + did = 0; + } + + /* use register invalidation */ + switch ( type ) + { + case DMA_TLB_GLOBAL_FLUSH: + /* global flush doesn't need set IVA_REG */ + val = DMA_TLB_GLOBAL_FLUSH|DMA_TLB_IVT; + break; + case DMA_TLB_DSI_FLUSH: + val = DMA_TLB_DSI_FLUSH|DMA_TLB_IVT|DMA_TLB_DID(did); + break; + case DMA_TLB_PSI_FLUSH: + val = DMA_TLB_PSI_FLUSH|DMA_TLB_IVT|DMA_TLB_DID(did); + /* Note: always flush non-leaf currently */ + val_iva = size_order | addr; + break; + default: + BUG(); + } + /* Note: set drain read/write */ #if 0 - /* - * This is probably to be super secure.. Looks like we can - * ignore it without any impact. - */ - if (cap_read_drain(iommu->cap)) - val |= DMA_TLB_READ_DRAIN; + /* + * This is probably to be super secure.. Looks like we can + * ignore it without any impact. + */ + if ( cap_read_drain(iommu->cap) ) + val |= DMA_TLB_READ_DRAIN; #endif - if (cap_write_drain(iommu->cap)) - val |= DMA_TLB_WRITE_DRAIN; - - spin_lock_irqsave(&iommu->register_lock, flag); - /* Note: Only uses first TLB reg currently */ - if (val_iva) - dmar_writeq(iommu->reg, tlb_offset, val_iva); - dmar_writeq(iommu->reg, tlb_offset + 8, val); - - /* Make sure hardware complete it */ - start_time = jiffies; - while (1) { - val = dmar_readq(iommu->reg, tlb_offset + 8); - if (!(val & DMA_TLB_IVT)) - break; - if (time_after(jiffies, start_time + DMAR_OPERATION_TIMEOUT)) - panic("DMAR hardware is malfunctional, please disable IOMMU\n"); - cpu_relax(); - } - spin_unlock_irqrestore(&iommu->register_lock, flag); - - /* check IOTLB invalidation granularity */ - if (DMA_TLB_IAIG(val) == 0) - printk(KERN_ERR VTDPREFIX "IOMMU: flush IOTLB failed\n"); - if (DMA_TLB_IAIG(val) != DMA_TLB_IIRG(type)) - printk(KERN_ERR VTDPREFIX "IOMMU: tlb flush request %x, actual %x\n", - (u32)DMA_TLB_IIRG(type), (u32)DMA_TLB_IAIG(val)); - /* flush context entry will implictly flush write buffer */ - return 0; + if ( cap_write_drain(iommu->cap) ) + val |= DMA_TLB_WRITE_DRAIN; + + spin_lock_irqsave(&iommu->register_lock, flag); + /* Note: Only uses first TLB reg currently */ + if ( val_iva ) + dmar_writeq(iommu->reg, tlb_offset, val_iva); + dmar_writeq(iommu->reg, tlb_offset + 8, val); + + /* Make sure hardware complete it */ + start_time = jiffies; + for ( ; ; ) + { + val = dmar_readq(iommu->reg, tlb_offset + 8); + if ( !(val & DMA_TLB_IVT) ) + break; + if ( time_after(jiffies, start_time + DMAR_OPERATION_TIMEOUT) ) + panic("DMAR hardware is malfunctional, please disable IOMMU\n"); + cpu_relax(); + } + spin_unlock_irqrestore(&iommu->register_lock, flag); + + /* check IOTLB invalidation granularity */ + if ( DMA_TLB_IAIG(val) == 0 ) + printk(KERN_ERR VTDPREFIX "IOMMU: flush IOTLB failed\n"); + if ( DMA_TLB_IAIG(val) != DMA_TLB_IIRG(type) ) + printk(KERN_ERR VTDPREFIX "IOMMU: tlb flush request %x, actual %x\n", + (u32)DMA_TLB_IIRG(type), (u32)DMA_TLB_IAIG(val)); + /* flush context entry will implictly flush write buffer */ + return 0; } static int inline iommu_flush_iotlb_global(struct iommu *iommu, - int non_present_entry_flush) -{ - return __iommu_flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH, - non_present_entry_flush); + int non_present_entry_flush) +{ + return __iommu_flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH, + non_present_entry_flush); } static int inline iommu_flush_iotlb_dsi(struct iommu *iommu, u16 did, - int non_present_entry_flush) -{ - return __iommu_flush_iotlb(iommu, did, 0, 0, DMA_TLB_DSI_FLUSH, - non_present_entry_flush); + int non_present_entry_flush) +{ + return __iommu_flush_iotlb(iommu, did, 0, 0, DMA_TLB_DSI_FLUSH, + non_present_entry_flush); } static int inline get_alignment(u64 base, unsigned int size) { - int t = 0; - u64 end; - - end = base + size - 1; - while (base != end) { - t++; - base >>= 1; - end >>= 1; - } - return t; -} - -static int inline iommu_flush_iotlb_psi(struct iommu *iommu, u16 did, - u64 addr, unsigned int pages, int non_present_entry_flush) -{ - unsigned int align; - - BUG_ON(addr & (~PAGE_MASK_4K)); - BUG_ON(pages == 0); - - /* Fallback to domain selective flush if no PSI support */ - if (!cap_pgsel_inv(iommu->cap)) - return iommu_flush_iotlb_dsi(iommu, did, - non_present_entry_flush); - - /* - * PSI requires page size is 2 ^ x, and the base address is naturally - * aligned to the size - */ - align = get_alignment(addr >> PAGE_SHIFT_4K, pages); - /* Fallback to domain selective flush if size is too big */ - if (align > cap_max_amask_val(iommu->cap)) - return iommu_flush_iotlb_dsi(iommu, did, - non_present_entry_flush); - - addr >>= PAGE_SHIFT_4K + align; - addr <<= PAGE_SHIFT_4K + align; - - return __iommu_flush_iotlb(iommu, did, addr, align, - DMA_TLB_PSI_FLUSH, non_present_entry_flush); + int t = 0; + u64 end; + + end = base + size - 1; + while ( base != end ) + { + t++; + base >>= 1; + end >>= 1; + } + return t; +} + +static int inline iommu_flush_iotlb_psi( + struct iommu *iommu, u16 did, + u64 addr, unsigned int pages, int non_present_entry_flush) +{ + unsigned int align; + + BUG_ON(addr & (~PAGE_MASK_4K)); + BUG_ON(pages == 0); + + /* Fallback to domain selective flush if no PSI support */ + if ( !cap_pgsel_inv(iommu->cap) ) + return iommu_flush_iotlb_dsi(iommu, did, + non_present_entry_flush); + + /* + * PSI requires page size is 2 ^ x, and the base address is naturally + * aligned to the size + */ + align = get_alignment(addr >> PAGE_SHIFT_4K, pages); + /* Fallback to domain selective flush if size is too big */ + if ( align > cap_max_amask_val(iommu->cap) ) + return iommu_flush_iotlb_dsi(iommu, did, + non_present_entry_flush); + + addr >>= PAGE_SHIFT_4K + align; + addr <<= PAGE_SHIFT_4K + align; + + return __iommu_flush_iotlb(iommu, did, addr, align, + DMA_TLB_PSI_FLUSH, non_present_entry_flush); } void flush_all(void) @@ -473,7 +491,8 @@ void flush_all(void) int i = 0; wbinvd(); - for_each_drhd_unit(drhd) { + for_each_drhd_unit ( drhd ) + { iommu = drhd->iommu; iommu_flush_context_global(iommu, 0); iommu_flush_iotlb_global(iommu, 0); @@ -493,16 +512,16 @@ static void dma_pte_clear_one(struct dom /* get last level pte */ pte = dma_addr_level_pte(domain, addr, 1); - if (pte) { + if ( pte ) + { dma_clear_pte(*pte); iommu_flush_cache_entry(drhd->iommu, pte); - for_each_drhd_unit(drhd) { + for_each_drhd_unit ( drhd ) + { iommu = drhd->iommu; - if (cap_caching_mode(iommu->cap)) - { + if ( cap_caching_mode(iommu->cap) ) iommu_flush_iotlb_psi(iommu, domain->domain_id, addr, 1, 0); - } else if (cap_rwbf(iommu->cap)) iommu_flush_write_buffer(iommu); } @@ -522,14 +541,14 @@ static void dma_pte_clear_range(struct d end &= PAGE_MASK_4K; /* we don't need lock here, nobody else touches the iova range */ - while (start < end) { + while ( start < end ) + { dma_pte_clear_one(domain, start); start += PAGE_SIZE_4K; } } /* free page table pages. last level pte should already be cleared */ -// static void dma_pte_free_pagetable(struct domain *domain, u64 start, u64 end) void dma_pte_free_pagetable(struct domain *domain, u64 start, u64 end) { struct acpi_drhd_unit *drhd; @@ -549,14 +568,17 @@ void dma_pte_free_pagetable(struct domai /* we don't need lock here, nobody else touches the iova range */ level = 2; - while (level <= total) { + while ( level <= total ) + { tmp = align_to_level(start, level); - if (tmp >= end || (tmp + level_size(level) > end)) + if ( (tmp >= end) || ((tmp + level_size(level)) > end) ) return; - while (tmp < end) { + while ( tmp < end ) + { pte = dma_addr_level_pte(domain, tmp, level); - if (pte) { + if ( pte ) + { free_xenheap_page((void *) maddr_to_virt(dma_pte_addr(*pte))); dma_clear_pte(*pte); iommu_flush_cache_entry(iommu, pte); @@ -565,8 +587,10 @@ void dma_pte_free_pagetable(struct domai } level++; } + /* free pgd */ - if (start == 0 && end == ((((u64)1) << addr_width) - 1)) { + if ( start == 0 && end == ((((u64)1) << addr_width) - 1) ) + { free_xenheap_page((void *)hd->pgd); hd->pgd = NULL; } @@ -580,43 +604,41 @@ static int iommu_set_root_entry(struct i struct root_entry *root; unsigned long flags; - if (iommu == NULL) + if ( iommu == NULL ) gdprintk(XENLOG_ERR VTDPREFIX, - "iommu_set_root_entry: iommu == NULL\n"); - - spin_lock_irqsave(&iommu->lock, flags); - if (!iommu->root_entry) { - spin_unlock_irqrestore(&iommu->lock, flags); + "iommu_set_root_entry: iommu == NULL\n"); + + if ( unlikely(!iommu->root_entry) ) + { root = (struct root_entry *)alloc_xenheap_page(); + if ( root == NULL ) + return -ENOMEM; + memset((u8*)root, 0, PAGE_SIZE); iommu_flush_cache_page(iommu, root); - spin_lock_irqsave(&iommu->lock, flags); - - if (!root && !iommu->root_entry) { - spin_unlock_irqrestore(&iommu->lock, flags); - return -ENOMEM; - } - - if (!iommu->root_entry) - iommu->root_entry = root; - else /* somebody is fast */ + + if ( cmpxchg((unsigned long *)&iommu->root_entry, + 0, (unsigned long)root) != 0 ) free_xenheap_page((void *)root); } - spin_unlock_irqrestore(&iommu->lock, flags); addr = iommu->root_entry; + spin_lock_irqsave(&iommu->register_lock, flags); + dmar_writeq(iommu->reg, DMAR_RTADDR_REG, virt_to_maddr(addr)); cmd = iommu->gcmd | DMA_GCMD_SRTP; dmar_writel(iommu->reg, DMAR_GCMD_REG, cmd); /* Make sure hardware complete it */ - while (1) { + for ( ; ; ) + { sts = dmar_readl(iommu->reg, DMAR_GSTS_REG); - if (sts & DMA_GSTS_RTPS) + if ( sts & DMA_GSTS_RTPS ) break; cpu_relax(); } + spin_unlock_irqrestore(&iommu->register_lock, flags); return 0; @@ -628,16 +650,16 @@ static int iommu_enable_translation(stru unsigned long flags; dprintk(XENLOG_INFO VTDPREFIX, - "iommu_enable_translation: enabling vt-d translation\n"); + "iommu_enable_translation: enabling vt-d translation\n"); spin_lock_irqsave(&iommu->register_lock, flags); iommu->gcmd |= DMA_GCMD_TE; dmar_writel(iommu->reg, DMAR_GCMD_REG, iommu->gcmd); /* Make sure hardware complete it */ - while (1) { + for ( ; ; ) + { sts = dmar_readl(iommu->reg, DMAR_GSTS_REG); - if (sts & DMA_GSTS_TES) { + if ( sts & DMA_GSTS_TES ) break; - } cpu_relax(); } spin_unlock_irqrestore(&iommu->register_lock, flags); @@ -654,10 +676,11 @@ int iommu_disable_translation(struct iom dmar_writel(iommu->reg, DMAR_GCMD_REG, iommu->gcmd); /* Make sure hardware complete it */ - while(1) { + for ( ; ; ) + { sts = dmar_readl(iommu->reg, DMAR_GSTS_REG); - if (!(sts & DMA_GSTS_TES)) - break; + if ( !(sts & DMA_GSTS_TES) ) + break; cpu_relax(); } spin_unlock_irqrestore(&iommu->register_lock, flags); @@ -666,13 +689,13 @@ int iommu_disable_translation(struct iom static struct iommu *vector_to_iommu[NR_VECTORS]; static int iommu_page_fault_do_one(struct iommu *iommu, int type, - u8 fault_reason, u16 source_id, u32 addr) + u8 fault_reason, u16 source_id, u32 addr) { dprintk(XENLOG_WARNING VTDPREFIX, - "iommu_page_fault:%s: DEVICE %x:%x.%x addr %x REASON %x\n", - (type ? "DMA Read" : "DMA Write"), - (source_id >> 8), PCI_SLOT(source_id & 0xFF), - PCI_FUNC(source_id & 0xFF), addr, fault_reason); + "iommu_page_fault:%s: DEVICE %x:%x.%x addr %x REASON %x\n", + (type ? "DMA Read" : "DMA Write"), + (source_id >> 8), PCI_SLOT(source_id & 0xFF), + PCI_FUNC(source_id & 0xFF), addr, fault_reason); print_vtd_entries(current->domain, (source_id >> 8),(source_id & 0xff), (addr >> PAGE_SHIFT)); @@ -681,7 +704,7 @@ static int iommu_page_fault_do_one(struc #define PRIMARY_FAULT_REG_LEN (16) static void iommu_page_fault(int vector, void *dev_id, - struct cpu_user_regs *regs) + struct cpu_user_regs *regs) { struct iommu *iommu = dev_id; int reg, fault_index; @@ -689,29 +712,30 @@ static void iommu_page_fault(int vector, unsigned long flags; dprintk(XENLOG_WARNING VTDPREFIX, - "iommu_page_fault: iommu->reg = %p\n", iommu->reg); + "iommu_page_fault: iommu->reg = %p\n", iommu->reg); spin_lock_irqsave(&iommu->register_lock, flags); fault_status = dmar_readl(iommu->reg, DMAR_FSTS_REG); spin_unlock_irqrestore(&iommu->register_lock, flags); /* FIXME: ignore advanced fault log */ - if (!(fault_status & DMA_FSTS_PPF)) + if ( !(fault_status & DMA_FSTS_PPF) ) return; fault_index = dma_fsts_fault_record_index(fault_status); reg = cap_fault_reg_offset(iommu->cap); - while (1) { + for ( ; ; ) + { u8 fault_reason; u16 source_id; - u32 guest_addr; + u32 guest_addr, data; int type; - u32 data; /* highest 32 bits */ spin_lock_irqsave(&iommu->register_lock, flags); data = dmar_readl(iommu->reg, reg + - fault_index * PRIMARY_FAULT_REG_LEN + 12); - if (!(data & DMA_FRCD_F)) { + fault_index * PRIMARY_FAULT_REG_LEN + 12); + if ( !(data & DMA_FRCD_F) ) + { spin_unlock_irqrestore(&iommu->register_lock, flags); break; } @@ -720,31 +744,32 @@ static void iommu_page_fault(int vector, type = dma_frcd_type(data); data = dmar_readl(iommu->reg, reg + - fault_index * PRIMARY_FAULT_REG_LEN + 8); + fault_index * PRIMARY_FAULT_REG_LEN + 8); source_id = dma_frcd_source_id(data); guest_addr = dmar_readq(iommu->reg, reg + - fault_index * PRIMARY_FAULT_REG_LEN); + fault_index * PRIMARY_FAULT_REG_LEN); guest_addr = dma_frcd_page_addr(guest_addr); /* clear the fault */ dmar_writel(iommu->reg, reg + - fault_index * PRIMARY_FAULT_REG_LEN + 12, DMA_FRCD_F); + fault_index * PRIMARY_FAULT_REG_LEN + 12, DMA_FRCD_F); spin_unlock_irqrestore(&iommu->register_lock, flags); iommu_page_fault_do_one(iommu, type, fault_reason, - source_id, guest_addr); + source_id, guest_addr); fault_index++; - if (fault_index > cap_num_fault_regs(iommu->cap)) + if ( fault_index > cap_num_fault_regs(iommu->cap) ) fault_index = 0; } + /* clear primary fault overflow */ - if (fault_status & DMA_FSTS_PFO) { + if ( fault_status & DMA_FSTS_PFO ) + { spin_lock_irqsave(&iommu->register_lock, flags); dmar_writel(iommu->reg, DMAR_FSTS_REG, DMA_FSTS_PFO); spin_unlock_irqrestore(&iommu->register_lock, flags); } - return; } static void dma_msi_unmask(unsigned int vector) @@ -840,14 +865,15 @@ int iommu_set_interrupt(struct iommu *io irq_vector[vector] = vector; vector_irq[vector] = vector; - if (!vector) { + if ( !vector ) + { gdprintk(XENLOG_ERR VTDPREFIX, "IOMMU: no vectors\n"); return -EINVAL; } irq_desc[vector].handler = &dma_msi_type; ret = request_irq(vector, iommu_page_fault, 0, "dmar", iommu); - if (ret) + if ( ret ) gdprintk(XENLOG_ERR VTDPREFIX, "IOMMU: can't request irq\n"); return vector; } @@ -857,25 +883,27 @@ struct iommu *iommu_alloc(void *hw_data) struct acpi_drhd_unit *drhd = (struct acpi_drhd_unit *) hw_data; struct iommu *iommu; - if (nr_iommus > MAX_IOMMUS) { + if ( nr_iommus > MAX_IOMMUS ) + { gdprintk(XENLOG_ERR VTDPREFIX, - "IOMMU: nr_iommus %d > MAX_IOMMUS\n", nr_iommus); + "IOMMU: nr_iommus %d > MAX_IOMMUS\n", nr_iommus); return NULL; } - + iommu = xmalloc(struct iommu); - if (!iommu) + if ( !iommu ) return NULL; memset(iommu, 0, sizeof(struct iommu)); set_fixmap_nocache(FIX_IOMMU_REGS_BASE_0 + nr_iommus, drhd->address); iommu->reg = (void *) fix_to_virt(FIX_IOMMU_REGS_BASE_0 + nr_iommus); dprintk(XENLOG_INFO VTDPREFIX, - "iommu_alloc: iommu->reg = %p drhd->address = %lx\n", - iommu->reg, drhd->address); + "iommu_alloc: iommu->reg = %p drhd->address = %lx\n", + iommu->reg, drhd->address); nr_iommus++; - if (!iommu->reg) { + if ( !iommu->reg ) + { printk(KERN_ERR VTDPREFIX "IOMMU: can't mapping the region\n"); goto error; } @@ -888,33 +916,30 @@ struct iommu *iommu_alloc(void *hw_data) drhd->iommu = iommu; return iommu; -error: + error: xfree(iommu); return NULL; } static void free_iommu(struct iommu *iommu) { - if (!iommu) + if ( !iommu ) return; - if (iommu->root_entry) + if ( iommu->root_entry ) free_xenheap_page((void *)iommu->root_entry); - if (iommu->reg) + if ( iommu->reg ) iounmap(iommu->reg); free_irq(iommu->vector); xfree(iommu); } -#define guestwidth_to_adjustwidth(gaw) ({ \ - int agaw; \ - int r = (gaw - 12) % 9; \ - if (r == 0) \ - agaw = gaw; \ - else \ - agaw = gaw + 9 - r; \ - if (agaw > 64) \ - agaw = 64; \ +#define guestwidth_to_adjustwidth(gaw) ({ \ + int agaw, r = (gaw - 12) % 9; \ + agaw = (r == 0) ? gaw : (gaw + 9 - r); \ + if ( agaw > 64 ) \ + agaw = 64; \ agaw; }) + int iommu_domain_init(struct domain *domain) { struct hvm_iommu *hd = domain_hvm_iommu(domain); @@ -945,7 +970,7 @@ int iommu_domain_init(struct domain *dom if ( !test_bit(agaw, &sagaw) ) { gdprintk(XENLOG_ERR VTDPREFIX, - "IOMMU: hardware doesn't support the agaw\n"); + "IOMMU: hardware doesn't support the agaw\n"); agaw = find_next_bit(&sagaw, 5, agaw); if (agaw >= 5) return -ENODEV; @@ -965,14 +990,17 @@ static int domain_context_mapping_one( int ret = 0; context = device_to_context_entry(iommu, bus, devfn); - if (!context) { + if ( !context ) + { gdprintk(XENLOG_INFO VTDPREFIX, - "domain_context_mapping_one:context == NULL:bdf = %x:%x:%x \n", - bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); + "domain_context_mapping_one:context == NULL:" + "bdf = %x:%x:%x\n", + bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); return -ENOMEM; } spin_lock_irqsave(&iommu->lock, flags); - if (context_present(*context)) { + if ( context_present(*context) ) + { spin_unlock_irqrestore(&iommu->lock, flags); gdprintk(XENLOG_INFO VTDPREFIX, "domain_context_mapping_one:context present:bdf=%x:%x:%x\n", @@ -982,8 +1010,8 @@ static int domain_context_mapping_one( #ifdef VTD_DEBUG dprintk(XENLOG_INFO VTDPREFIX, - "context_mapping_one_1-%x:%x:%x-*context = %lx %lx\n", - bus, PCI_SLOT(devfn), PCI_FUNC(devfn), context->hi, context->lo); + "context_mapping_one_1-%x:%x:%x-*context = %lx %lx\n", + bus, PCI_SLOT(devfn), PCI_FUNC(devfn), context->hi, context->lo); #endif /* @@ -993,9 +1021,12 @@ static int domain_context_mapping_one( context_set_domain_id(*context, domain->domain_id); context_set_address_width(*context, hd->agaw); - if (ecap_pass_thru(iommu->ecap)) + if ( ecap_pass_thru(iommu->ecap) ) + { context_set_translation_type(*context, CONTEXT_TT_PASS_THRU); - else { + } + else + { context_set_address_root(*context, virt_to_maddr(hd->pgd)); context_set_translation_type(*context, CONTEXT_TT_MULTI_LEVEL); } @@ -1006,13 +1037,14 @@ static int domain_context_mapping_one( #ifdef VTD_DEBUG dprintk(XENLOG_INFO VTDPREFIX, - "context_mapping_one_2-%x:%x:%x-*context=%lx %lx hd->pgd = %p\n", - bus, PCI_SLOT(devfn), PCI_FUNC(devfn), - context->hi, context->lo, hd->pgd); + "context_mapping_one_2-%x:%x:%x-*context=%lx %lx hd->pgd = %p\n", + bus, PCI_SLOT(devfn), PCI_FUNC(devfn), + context->hi, context->lo, hd->pgd); #endif - if (iommu_flush_context_device(iommu, domain->domain_id, - (((u16)bus) << 8) | devfn, DMA_CCMD_MASK_NOBIT, 1)) + if ( iommu_flush_context_device(iommu, domain->domain_id, + (((u16)bus) << 8) | devfn, + DMA_CCMD_MASK_NOBIT, 1) ) iommu_flush_write_buffer(iommu); else iommu_flush_iotlb_dsi(iommu, domain->domain_id, 0); @@ -1025,18 +1057,21 @@ static int __pci_find_next_cap(u8 bus, u u8 id; int ttl = 48; - while (ttl--) { + while ( ttl-- ) + { pos = read_pci_config_byte(bus, PCI_SLOT(devfn), PCI_FUNC(devfn), pos); - if (pos < 0x40) + if ( pos < 0x40 ) break; + pos &= ~3; id = read_pci_config_byte(bus, PCI_SLOT(devfn), PCI_FUNC(devfn), - pos + PCI_CAP_LIST_ID); - - if (id == 0xff) + pos + PCI_CAP_LIST_ID); + + if ( id == 0xff ) break; - if (id == cap) + if ( id == cap ) return pos; + pos += PCI_CAP_LIST_NEXT; } return 0; @@ -1055,17 +1090,18 @@ int pdev_type(struct pci_dev *dev) u16 status; class_device = read_pci_config_16(dev->bus, PCI_SLOT(dev->devfn), - PCI_FUNC(dev->devfn), PCI_CLASS_DEVICE); - if (class_device == PCI_CLASS_BRIDGE_PCI) + PCI_FUNC(dev->devfn), PCI_CLASS_DEVICE); + if ( class_device == PCI_CLASS_BRIDGE_PCI ) return DEV_TYPE_PCI_BRIDGE; status = read_pci_config_16(dev->bus, PCI_SLOT(dev->devfn), - PCI_FUNC(dev->devfn), PCI_STATUS); - - if (!(status & PCI_STATUS_CAP_LIST)) + PCI_FUNC(dev->devfn), PCI_STATUS); + + if ( !(status & PCI_STATUS_CAP_LIST) ) return DEV_TYPE_PCI; - if (__pci_find_next_cap(dev->bus, dev->devfn, PCI_CAPABILITY_LIST, PCI_CAP_ID_EXP)) + if ( __pci_find_next_cap(dev->bus, dev->devfn, + PCI_CAPABILITY_LIST, PCI_CAP_ID_EXP) ) return DEV_TYPE_PCIe_ENDPOINT; return DEV_TYPE_PCI; @@ -1084,65 +1120,81 @@ static int domain_context_mapping( u32 type; type = pdev_type(pdev); - if (type == DEV_TYPE_PCI_BRIDGE) { - sec_bus = read_pci_config_byte(pdev->bus, PCI_SLOT(pdev->devfn), - PCI_FUNC(pdev->devfn), PCI_SECONDARY_BUS); - - if (bus2bridge[sec_bus].bus == 0) { + if ( type == DEV_TYPE_PCI_BRIDGE ) + { + sec_bus = read_pci_config_byte( + pdev->bus, PCI_SLOT(pdev->devfn), + PCI_FUNC(pdev->devfn), PCI_SECONDARY_BUS); + + if ( bus2bridge[sec_bus].bus == 0 ) + { bus2bridge[sec_bus].bus = pdev->bus; bus2bridge[sec_bus].devfn = pdev->devfn; } - sub_bus = read_pci_config_byte(pdev->bus, PCI_SLOT(pdev->devfn), - PCI_FUNC(pdev->devfn), PCI_SUBORDINATE_BUS); - - if (sec_bus != sub_bus) { + sub_bus = read_pci_config_byte( + pdev->bus, PCI_SLOT(pdev->devfn), + PCI_FUNC(pdev->devfn), PCI_SUBORDINATE_BUS); + + if ( sec_bus != sub_bus ) + { dprintk(XENLOG_INFO VTDPREFIX, - "context_mapping: nested PCI bridge not supported\n"); + "context_mapping: nested PCI bridge not supported\n"); dprintk(XENLOG_INFO VTDPREFIX, - " bdf = %x:%x:%x sec_bus = %x sub_bus = %x\n", - pdev->bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), - sec_bus, sub_bus); + " bdf = %x:%x:%x sec_bus = %x sub_bus = %x\n", + pdev->bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), + sec_bus, sub_bus); } } - if (type == DEV_TYPE_PCIe_ENDPOINT) { + if ( type == DEV_TYPE_PCIe_ENDPOINT ) + { gdprintk(XENLOG_INFO VTDPREFIX, - "domain_context_mapping:PCIe : bdf = %x:%x:%x\n", - pdev->bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); + "domain_context_mapping:PCIe : bdf = %x:%x:%x\n", + pdev->bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); ret = domain_context_mapping_one(domain, iommu, - (u8)(pdev->bus), (u8) (pdev->devfn)); + (u8)(pdev->bus), (u8) (pdev->devfn)); } /* PCI devices */ - if (type == DEV_TYPE_PCI) { + if ( type == DEV_TYPE_PCI ) + { gdprintk(XENLOG_INFO VTDPREFIX, - "domain_context_mapping:PCI: bdf = %x:%x:%x\n", - pdev->bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); - - if (pdev->bus == 0) - ret = domain_context_mapping_one(domain, iommu, - (u8)(pdev->bus), (u8) (pdev->devfn)); - else { - if (bus2bridge[pdev->bus].bus != 0) + "domain_context_mapping:PCI: bdf = %x:%x:%x\n", + pdev->bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); + + if ( pdev->bus == 0 ) + { + ret = domain_context_mapping_one( + domain, iommu, (u8)(pdev->bus), (u8) (pdev->devfn)); + } + else + { + if ( bus2bridge[pdev->bus].bus != 0 ) gdprintk(XENLOG_ERR VTDPREFIX, - "domain_context_mapping:bus2bridge[pdev->bus].bus==0\n"); - - ret = domain_context_mapping_one(domain, iommu, - (u8)(bus2bridge[pdev->bus].bus), - (u8)(bus2bridge[pdev->bus].devfn)); + "domain_context_mapping:bus2bridge" + "[pdev->bus].bus==0\n"); + + ret = domain_context_mapping_one( + domain, iommu, + (u8)(bus2bridge[pdev->bus].bus), + (u8)(bus2bridge[pdev->bus].devfn)); /* now map everything behind the PCI bridge */ - for (dev = 0; dev < 32; dev++) { - for (func = 0; func < 8; func++) { - ret = domain_context_mapping_one(domain, iommu, - pdev->bus, (u8)PCI_DEVFN(dev, func)); - if (ret) + for ( dev = 0; dev < 32; dev++ ) + { + for ( func = 0; func < 8; func++ ) + { + ret = domain_context_mapping_one( + domain, iommu, + pdev->bus, (u8)PCI_DEVFN(dev, func)); + if ( ret ) return ret; } } } } + return ret; } @@ -1155,23 +1207,28 @@ static int domain_context_unmap_one( unsigned long flags; context = device_to_context_entry(iommu, bus, devfn); - if (!context) { + if ( !context ) + { gdprintk(XENLOG_INFO VTDPREFIX, - "domain_context_unmap_one-%x:%x:%x- context == NULL:return\n", - bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); + "domain_context_unmap_one-%x:%x:%x- context == NULL:return\n", + bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); return -ENOMEM; } + spin_lock_irqsave(&iommu->lock, flags); - if (!context_present(*context)) { + if ( !context_present(*context) ) + { spin_unlock_irqrestore(&iommu->lock, flags); gdprintk(XENLOG_INFO VTDPREFIX, - "domain_context_unmap_one-%x:%x:%x- context NOT present:return\n", - bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); + "domain_context_unmap_one-%x:%x:%x- " + "context NOT present:return\n", + bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); return 0; } + gdprintk(XENLOG_INFO VTDPREFIX, - "domain_context_unmap_one_1:bdf = %x:%x:%x\n", - bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); + "domain_context_unmap_one_1:bdf = %x:%x:%x\n", + bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); context_clear_present(*context); context_clear_entry(*context); @@ -1181,8 +1238,8 @@ static int domain_context_unmap_one( spin_unlock_irqrestore(&iommu->lock, flags); gdprintk(XENLOG_INFO VTDPREFIX, - "domain_context_unmap_one_2:bdf = %x:%x:%x\n", - bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); + "domain_context_unmap_one_2:bdf = %x:%x:%x\n", + bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); return 0; } @@ -1197,54 +1254,69 @@ static int domain_context_unmap( u32 type; type = pdev_type(pdev); - if (type == DEV_TYPE_PCI_BRIDGE) { - sec_bus = read_pci_config_byte(pdev->bus, PCI_SLOT(pdev->devfn), - PCI_FUNC(pdev->devfn), PCI_SECONDARY_BUS); - sub_bus = read_pci_config_byte(pdev->bus, PCI_SLOT(pdev->devfn), - PCI_FUNC(pdev->devfn), PCI_SUBORDINATE_BUS); + if ( type == DEV_TYPE_PCI_BRIDGE ) + { + sec_bus = read_pci_config_byte( + pdev->bus, PCI_SLOT(pdev->devfn), + PCI_FUNC(pdev->devfn), PCI_SECONDARY_BUS); + sub_bus = read_pci_config_byte( + pdev->bus, PCI_SLOT(pdev->devfn), + PCI_FUNC(pdev->devfn), PCI_SUBORDINATE_BUS); gdprintk(XENLOG_INFO VTDPREFIX, - "domain_context_unmap:BRIDGE:%x:%x:%x sec_bus=%x sub_bus=%x\n", - pdev->bus, PCI_SLOT(pdev->devfn), - PCI_FUNC(pdev->devfn), sec_bus, sub_bus); - } - - if (type == DEV_TYPE_PCIe_ENDPOINT) { + "domain_context_unmap:BRIDGE:%x:%x:%x " + "sec_bus=%x sub_bus=%x\n", + pdev->bus, PCI_SLOT(pdev->devfn), + PCI_FUNC(pdev->devfn), sec_bus, sub_bus); + } + + if ( type == DEV_TYPE_PCIe_ENDPOINT ) + { gdprintk(XENLOG_INFO VTDPREFIX, "domain_context_unmap:PCIe : bdf = %x:%x:%x\n", pdev->bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); ret = domain_context_unmap_one(domain, iommu, - (u8)(pdev->bus), (u8) (pdev->devfn)); + (u8)(pdev->bus), (u8) (pdev->devfn)); } /* PCI devices */ - if (type == DEV_TYPE_PCI) { + if ( type == DEV_TYPE_PCI ) + { gdprintk(XENLOG_INFO VTDPREFIX, "domain_context_unmap:PCI: bdf = %x:%x:%x\n", pdev->bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); - if (pdev->bus == 0) + if ( pdev->bus == 0 ) + { + ret = domain_context_unmap_one( + domain, iommu, + (u8)(pdev->bus), (u8) (pdev->devfn)); + } + else + { + if ( bus2bridge[pdev->bus].bus != 0 ) + gdprintk(XENLOG_INFO VTDPREFIX, + "domain_context_mapping:" + "bus2bridge[pdev->bus].bus==0\n"); + ret = domain_context_unmap_one(domain, iommu, - (u8)(pdev->bus), (u8) (pdev->devfn)); - else { - if (bus2bridge[pdev->bus].bus != 0) - gdprintk(XENLOG_INFO VTDPREFIX, - "domain_context_mapping:bus2bridge[pdev->bus].bus==0\n"); - - ret = domain_context_unmap_one(domain, iommu, - (u8)(bus2bridge[pdev->bus].bus), - (u8)(bus2bridge[pdev->bus].devfn)); + (u8)(bus2bridge[pdev->bus].bus), + (u8)(bus2bridge[pdev->bus].devfn)); /* now map everything behind the PCI bridge */ - for (dev = 0; dev < 32; dev++) { - for (func = 0; func < 8; func++) { - ret = domain_context_unmap_one(domain, iommu, - pdev->bus, (u8)PCI_DEVFN(dev, func)); - if (ret) + for ( dev = 0; dev < 32; dev++ ) + { + for ( func = 0; func < 8; func++ ) + { + ret = domain_context_unmap_one( + domain, iommu, + pdev->bus, (u8)PCI_DEVFN(dev, func)); + if ( ret ) return ret; } } } } + return ret; } @@ -1262,11 +1334,12 @@ void reassign_device_ownership( unsigned long flags; gdprintk(XENLOG_ERR VTDPREFIX, - "reassign_device-%x:%x:%x- source = %d target = %d\n", - bus, PCI_SLOT(devfn), PCI_FUNC(devfn), - source->domain_id, target->domain_id); - - for_each_pdev(source, pdev) { + "reassign_device-%x:%x:%x- source = %d target = %d\n", + bus, PCI_SLOT(devfn), PCI_FUNC(devfn), + source->domain_id, target->domain_id); + + for_each_pdev( source, pdev ) + { if ( (pdev->bus != bus) || (pdev->devfn != devfn) ) continue; @@ -1276,9 +1349,7 @@ void reassign_device_ownership( iommu = drhd->iommu; domain_context_unmap(source, iommu, pdev); - /* - * move pci device from the source domain to target domain. - */ + /* Move pci device from the source domain to target domain. */ spin_lock_irqsave(&source_hd->iommu_list_lock, flags); spin_lock_irqsave(&target_hd->iommu_list_lock, flags); list_move(&pdev->list, &target_hd->pdev_list); @@ -1286,12 +1357,9 @@ void reassign_device_ownership( spin_unlock_irqrestore(&source_hd->iommu_list_lock, flags); status = domain_context_mapping(target, iommu, pdev); - if (status != 0) + if ( status != 0 ) gdprintk(XENLOG_ERR VTDPREFIX, "domain_context_mapping failed\n"); - /* - * We are done. - */ break; } } @@ -1301,37 +1369,37 @@ void return_devices_to_dom0(struct domai struct hvm_iommu *hd = domain_hvm_iommu(d); struct pci_dev *pdev; - while (!list_empty(&hd->pdev_list)) { + while ( !list_empty(&hd->pdev_list) ) + { pdev = list_entry(hd->pdev_list.next, typeof(*pdev), list); dprintk(XENLOG_INFO VTDPREFIX, - "return_devices_to_dom0: bdf = %x:%x:%x\n", - pdev->bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); + "return_devices_to_dom0: bdf = %x:%x:%x\n", + pdev->bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); reassign_device_ownership(d, dom0, pdev->bus, pdev->devfn); } #ifdef VTD_DEBUG - for_each_pdev(dom0, pdev) { + for_each_pdev ( dom0, pdev ) dprintk(XENLOG_INFO VTDPREFIX, - "return_devices_to_dom0:%x: bdf = %x:%x:%x\n", - dom0->domain_id, pdev->bus, - PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); - } + "return_devices_to_dom0:%x: bdf = %x:%x:%x\n", + dom0->domain_id, pdev->bus, + PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); #endif } void iommu_domain_teardown(struct domain *d) { - if (list_empty(&acpi_drhd_units)) - return; + if ( list_empty(&acpi_drhd_units) ) + return; #if CONFIG_PAGING_LEVELS == 3 - { - struct hvm_iommu *hd = domain_hvm_iommu(d); - int level = agaw_to_level(hd->agaw); - struct dma_pte *pgd = NULL; - - switch (level) - { + { + struct hvm_iommu *hd = domain_hvm_iommu(d); + int level = agaw_to_level(hd->agaw); + struct dma_pte *pgd = NULL; + + switch ( level ) + { case VTD_PAGE_TABLE_LEVEL_3: if ( hd->pgd ) free_xenheap_page((void *)hd->pgd); @@ -1347,10 +1415,10 @@ void iommu_domain_teardown(struct domain break; default: gdprintk(XENLOG_ERR VTDPREFIX, - "Unsupported p2m table sharing level!\n"); + "Unsupported p2m table sharing level!\n"); break; - } - } + } + } #endif return_devices_to_dom0(d); } @@ -1361,12 +1429,14 @@ static int domain_context_mapped(struct struct iommu *iommu; int ret; - for_each_drhd_unit(drhd) { + for_each_drhd_unit ( drhd ) + { iommu = drhd->iommu; ret = device_context_mapped(iommu, pdev->bus, pdev->devfn); - if (ret) + if ( ret ) return ret; } + return 0; } @@ -1380,24 +1450,26 @@ int iommu_map_page(struct domain *d, pad iommu = drhd->iommu; /* do nothing if dom0 and iommu supports pass thru */ - if (ecap_pass_thru(iommu->ecap) && (d->domain_id == 0)) + if ( ecap_pass_thru(iommu->ecap) && (d->domain_id == 0) ) return 0; pte = addr_to_dma_pte(d, gfn << PAGE_SHIFT_4K); - if (!pte) + if ( !pte ) return -ENOMEM; dma_set_pte_addr(*pte, mfn << PAGE_SHIFT_4K); dma_set_pte_prot(*pte, DMA_PTE_READ | DMA_PTE_WRITE); iommu_flush_cache_entry(iommu, pte); - for_each_drhd_unit(drhd) { + for_each_drhd_unit ( drhd ) + { iommu = drhd->iommu; - if (cap_caching_mode(iommu->cap)) + if ( cap_caching_mode(iommu->cap) ) iommu_flush_iotlb_psi(iommu, d->domain_id, gfn << PAGE_SHIFT_4K, 1, 0); - else if (cap_rwbf(iommu->cap)) + else if ( cap_rwbf(iommu->cap) ) iommu_flush_write_buffer(iommu); } + return 0; } @@ -1411,7 +1483,7 @@ int iommu_unmap_page(struct domain *d, d iommu = drhd->iommu; /* do nothing if dom0 and iommu supports pass thru */ - if (ecap_pass_thru(iommu->ecap) && (d->domain_id == 0)) + if ( ecap_pass_thru(iommu->ecap) && (d->domain_id == 0) ) return 0; /* get last level pte */ @@ -1422,7 +1494,7 @@ int iommu_unmap_page(struct domain *d, d } int iommu_page_mapping(struct domain *domain, dma_addr_t iova, - void *hpa, size_t size, int prot) + void *hpa, size_t size, int prot) { struct acpi_drhd_unit *drhd; struct iommu *iommu; @@ -1432,16 +1504,17 @@ int iommu_page_mapping(struct domain *do drhd = list_entry(acpi_drhd_units.next, typeof(*drhd), list); iommu = drhd->iommu; - if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0) + if ( (prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0 ) return -EINVAL; iova = (iova >> PAGE_SHIFT_4K) << PAGE_SHIFT_4K; start_pfn = (unsigned long)(((unsigned long) hpa) >> PAGE_SHIFT_4K); end_pfn = (unsigned long) - ((PAGE_ALIGN_4K(((unsigned long)hpa) + size)) >> PAGE_SHIFT_4K); + ((PAGE_ALIGN_4K(((unsigned long)hpa) + size)) >> PAGE_SHIFT_4K); index = 0; - while (start_pfn < end_pfn) { + while ( start_pfn < end_pfn ) + { pte = addr_to_dma_pte(domain, iova + PAGE_SIZE_4K * index); - if (!pte) + if ( !pte ) return -ENOMEM; dma_set_pte_addr(*pte, start_pfn << PAGE_SHIFT_4K); dma_set_pte_prot(*pte, prot); @@ -1450,13 +1523,15 @@ int iommu_page_mapping(struct domain *do index++; } - for_each_drhd_unit(drhd) { + for_each_drhd_unit ( drhd ) + { iommu = drhd->iommu; - if (cap_caching_mode(iommu->cap)) + if ( cap_caching_mode(iommu->cap) ) iommu_flush_iotlb_psi(iommu, domain->domain_id, iova, size, 0); - else if (cap_rwbf(iommu->cap)) + else if ( cap_rwbf(iommu->cap) ) iommu_flush_write_buffer(iommu); } + return 0; } @@ -1477,19 +1552,20 @@ void iommu_flush(struct domain *d, dma_a struct iommu *iommu = NULL; struct dma_pte *pte = (struct dma_pte *) p2m_entry; - for_each_drhd_unit(drhd) { + for_each_drhd_unit ( drhd ) + { iommu = drhd->iommu; - if (cap_caching_mode(iommu->cap)) + if ( cap_caching_mode(iommu->cap) ) iommu_flush_iotlb_psi(iommu, d->domain_id, - gfn << PAGE_SHIFT_4K, 1, 0); - else if (cap_rwbf(iommu->cap)) + gfn << PAGE_SHIFT_4K, 1, 0); + else if ( cap_rwbf(iommu->cap) ) iommu_flush_write_buffer(iommu); } + iommu_flush_cache_entry(iommu, pte); } -int -prepare_device(struct domain *domain, struct pci_dev dev) +int prepare_device(struct domain *domain, struct pci_dev dev) { return 0; } @@ -1506,17 +1582,19 @@ static int iommu_prepare_rmrr_dev( /* page table init */ size = rmrr->end_address - rmrr->base_address + 1; ret = iommu_page_mapping(d, rmrr->base_address, - (void *)rmrr->base_address, size, - DMA_PTE_READ|DMA_PTE_WRITE); - if (ret) + (void *)rmrr->base_address, size, + DMA_PTE_READ|DMA_PTE_WRITE); + if ( ret ) return ret; - if (domain_context_mapped(d, pdev) == 0) { + if ( domain_context_mapped(d, pdev) == 0 ) + { drhd = acpi_find_matched_drhd_unit(pdev); ret = domain_context_mapping(d, drhd->iommu, pdev); - if (!ret) + if ( !ret ) return 0; } + return ret; } @@ -1525,15 +1603,16 @@ void __init setup_dom0_devices(void) struct hvm_iommu *hd = domain_hvm_iommu(dom0); struct acpi_drhd_unit *drhd; struct pci_dev *pdev; - int bus, dev, func; + int bus, dev, func, ret; u32 l; - u8 hdr_type; - int ret; #ifdef DEBUG_VTD_CONTEXT_ENTRY - for (bus = 0; bus < 256; bus++) { - for (dev = 0; dev < 32; dev++) { - for (func = 0; func < 8; func++) { + for ( bus = 0; bus < 256; bus++ ) + { + for ( dev = 0; dev < 32; dev++ ) + { + for ( func = 0; func < 8; func++ ) + { struct context_entry *context; struct pci_dev device; @@ -1541,23 +1620,26 @@ void __init setup_dom0_devices(void) device.devfn = PCI_DEVFN(dev, func); drhd = acpi_find_matched_drhd_unit(&device); context = device_to_context_entry(drhd->iommu, - bus, PCI_DEVFN(dev, func)); - if ((context->lo != 0) || (context->hi != 0)) + bus, PCI_DEVFN(dev, func)); + if ( (context->lo != 0) || (context->hi != 0) ) dprintk(XENLOG_INFO VTDPREFIX, - "setup_dom0_devices-%x:%x:%x- context not 0\n", - bus, dev, func); + "setup_dom0_devices-%x:%x:%x- context not 0\n", + bus, dev, func); } } } #endif - for (bus = 0; bus < 256; bus++) { - for (dev = 0; dev < 32; dev++) { - for (func = 0; func < 8; func++) { + for ( bus = 0; bus < 256; bus++ ) + { + for ( dev = 0; dev < 32; dev++ ) + { + for ( func = 0; func < 8; func++ ) + { l = read_pci_config(bus, dev, func, PCI_VENDOR_ID); /* some broken boards return 0 or ~0 if a slot is empty: */ - if (l == 0xffffffff || l == 0x00000000 || - l == 0x0000ffff || l == 0xffff0000) + if ( (l == 0xffffffff) || (l == 0x00000000) || + (l == 0x0000ffff) || (l == 0xffff0000) ) continue; pdev = xmalloc(struct pci_dev); pdev->bus = bus; @@ -1566,21 +1648,17 @@ void __init setup_dom0_devices(void) drhd = acpi_find_matched_drhd_unit(pdev); ret = domain_context_mapping(dom0, drhd->iommu, pdev); - if (ret != 0) + if ( ret != 0 ) gdprintk(XENLOG_ERR VTDPREFIX, - "domain_context_mapping failed\n"); - - hdr_type = read_pci_config(bus, dev, func, PCI_HEADER_TYPE); - // if ((hdr_type & 0x8) == 0) - // break; + "domain_context_mapping failed\n"); } } } - for_each_pdev(dom0, pdev) { + + for_each_pdev ( dom0, pdev ) dprintk(XENLOG_INFO VTDPREFIX, - "setup_dom0_devices: bdf = %x:%x:%x\n", - pdev->bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); - } + "setup_dom0_devices: bdf = %x:%x:%x\n", + pdev->bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); } void clear_fault_bit(struct iommu *iommu) @@ -1588,32 +1666,14 @@ void clear_fault_bit(struct iommu *iommu u64 val; val = dmar_readq( - iommu->reg, - cap_fault_reg_offset(dmar_readq(iommu->reg,DMAR_CAP_REG))+0x8); + iommu->reg, + cap_fault_reg_offset(dmar_readq(iommu->reg,DMAR_CAP_REG))+0x8); dmar_writeq( - iommu->reg, - cap_fault_reg_offset(dmar_readq(iommu->reg,DMAR_CAP_REG))+8, - val); + iommu->reg, + cap_fault_reg_offset(dmar_readq(iommu->reg,DMAR_CAP_REG))+8, + val); dmar_writel(iommu->reg, DMAR_FSTS_REG, DMA_FSTS_PFO); } - -/* - * Called from ACPI discovery code, once all DMAR's and RMRR's are done - * scanning, we need to run through and initialize as much of it as necessary - */ -int vtd_enable = 1; -static void setup_vtd_enable(char *s) -{ - if ( !strcmp(s, "0") ) - vtd_enable = 0; - else if ( !strcmp(s, "1") ) - vtd_enable = 1; - else - dprintk(XENLOG_INFO VTDPREFIX, - "Unknown vtd_enable value specified: '%s'\n", s); - dprintk(XENLOG_INFO VTDPREFIX, "vtd_enable = %x\n", vtd_enable); -} -custom_param("vtd", setup_vtd_enable); static int init_vtd_hw(void) { @@ -1621,14 +1681,17 @@ static int init_vtd_hw(void) struct iommu *iommu; int ret; - for_each_drhd_unit(drhd) { + for_each_drhd_unit ( drhd ) + { iommu = drhd->iommu; ret = iommu_set_root_entry(iommu); - if (ret) { + if ( ret ) + { gdprintk(XENLOG_ERR VTDPREFIX, "IOMMU: set root entry failed\n"); return -EIO; } } + return 0; } @@ -1638,16 +1701,18 @@ static int enable_vtd_translation(void) struct iommu *iommu; int vector = 0; - for_each_drhd_unit(drhd) { + for_each_drhd_unit ( drhd ) + { iommu = drhd->iommu; vector = iommu_set_interrupt(iommu); dma_msi_data_init(iommu, vector); dma_msi_addr_init(iommu, cpu_physical_id(first_cpu(cpu_online_map))); iommu->vector = vector; clear_fault_bit(iommu); - if (vtd_enable && iommu_enable_translation(iommu)) + if ( iommu_enable_translation(iommu) ) return -EIO; } + return 0; } @@ -1657,13 +1722,15 @@ static void setup_dom0_rmrr(void) struct pci_dev *pdev; int ret; - for_each_rmrr_device(rmrr, pdev) + for_each_rmrr_device ( rmrr, pdev ) ret = iommu_prepare_rmrr_dev(dom0, rmrr, pdev); - if (ret) - gdprintk(XENLOG_ERR VTDPREFIX, - "IOMMU: mapping reserved region failed\n"); - end_for_each_rmrr_device(rmrr, pdev) -} + + if ( ret ) + gdprintk(XENLOG_ERR VTDPREFIX, + "IOMMU: mapping reserved region failed\n"); + + end_for_each_rmrr_device ( rmrr, pdev ) + } int iommu_setup(void) { @@ -1672,7 +1739,7 @@ int iommu_setup(void) struct iommu *iommu; unsigned long i; - if (!vtd_enabled) + if ( !vtd_enabled ) return 0; INIT_LIST_HEAD(&hd->pdev_list); @@ -1690,21 +1757,22 @@ int iommu_setup(void) iommu = drhd->iommu; /* setup 1:1 page table for dom0 */ - for (i = 0; i < max_page; i++) + for ( i = 0; i < max_page; i++ ) iommu_map_page(dom0, i, i); - if (init_vtd_hw()) + if ( init_vtd_hw() ) goto error; setup_dom0_devices(); setup_dom0_rmrr(); - if (enable_vtd_translation()) + if ( enable_vtd_translation() ) goto error; return 0; -error: + error: printk("iommu_setup() failed\n"); - for_each_drhd_unit(drhd) { + for_each_drhd_unit ( drhd ) + { iommu = drhd->iommu; free_iommu(iommu); } @@ -1718,24 +1786,24 @@ int assign_device(struct domain *d, u8 b struct pci_dev *pdev; int ret = 0; - if (list_empty(&acpi_drhd_units)) + if ( list_empty(&acpi_drhd_units) ) return ret; dprintk(XENLOG_INFO VTDPREFIX, - "assign_device: bus = %x dev = %x func = %x\n", - bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); + "assign_device: bus = %x dev = %x func = %x\n", + bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); reassign_device_ownership(dom0, d, bus, devfn); /* setup rmrr identify mapping just once per domain */ - if (list_empty(&hd->pdev_list)) + if ( list_empty(&hd->pdev_list) ) for_each_rmrr_device(rmrr, pdev) ret = iommu_prepare_rmrr_dev(d, rmrr, pdev); - if (ret) - gdprintk(XENLOG_ERR VTDPREFIX, - "IOMMU: mapping reserved region failed\n"); - end_for_each_rmrr_device(rmrr, pdev) - return ret; + if ( ret ) + gdprintk(XENLOG_ERR VTDPREFIX, + "IOMMU: mapping reserved region failed\n"); + end_for_each_rmrr_device(rmrr, pdev) + return ret; } void iommu_set_pgd(struct domain *d) @@ -1743,9 +1811,10 @@ void iommu_set_pgd(struct domain *d) struct hvm_iommu *hd = domain_hvm_iommu(d); unsigned long p2m_table; - if (hd->pgd) { + if ( hd->pgd ) + { gdprintk(XENLOG_INFO VTDPREFIX, - "iommu_set_pgd_1: hd->pgd = %p\n", hd->pgd); + "iommu_set_pgd_1: hd->pgd = %p\n", hd->pgd); hd->pgd = NULL; } p2m_table = mfn_x(pagetable_get_mfn(d->arch.phys_table)); @@ -1762,46 +1831,47 @@ void iommu_set_pgd(struct domain *d) int i; spin_lock_irqsave(&hd->mapping_lock, flags); - if (!hd->pgd) { + if ( !hd->pgd ) + { pgd = (struct dma_pte *)alloc_xenheap_page(); memset((u8*)pgd, 0, PAGE_SIZE); - if (!hd->pgd) + if ( !hd->pgd ) hd->pgd = pgd; else /* somebody is fast */ free_xenheap_page((void *) pgd); } l3e = map_domain_page(p2m_table); - switch(level) + switch ( level ) { - case VTD_PAGE_TABLE_LEVEL_3: /* Weybridge */ - /* We only support 8 entries for the PAE L3 p2m table */ - for ( i = 0; i < 8 ; i++ ) - { - /* Don't create new L2 entry, use ones from p2m table */ - pgd[i].val = l3e[i].l3 | _PAGE_PRESENT | _PAGE_RW; - } - break; - - case VTD_PAGE_TABLE_LEVEL_4: /* Stoakley */ - /* We allocate one more page for the top vtd page table. */ - pmd = (struct dma_pte *)alloc_xenheap_page(); - memset((u8*)pmd, 0, PAGE_SIZE); - pte = &pgd[0]; - dma_set_pte_addr(*pte, virt_to_maddr(pmd)); - dma_set_pte_readable(*pte); - dma_set_pte_writable(*pte); - - for ( i = 0; i < 8; i++ ) - { - /* Don't create new L2 entry, use ones from p2m table */ - pmd[i].val = l3e[i].l3 | _PAGE_PRESENT | _PAGE_RW; - } - break; - default: - gdprintk(XENLOG_ERR VTDPREFIX, - "iommu_set_pgd:Unsupported p2m table sharing level!\n"); - break; + case VTD_PAGE_TABLE_LEVEL_3: /* Weybridge */ + /* We only support 8 entries for the PAE L3 p2m table */ + for ( i = 0; i < 8 ; i++ ) + { + /* Don't create new L2 entry, use ones from p2m table */ + pgd[i].val = l3e[i].l3 | _PAGE_PRESENT | _PAGE_RW; + } + break; + + case VTD_PAGE_TABLE_LEVEL_4: /* Stoakley */ + /* We allocate one more page for the top vtd page table. */ + pmd = (struct dma_pte *)alloc_xenheap_page(); + memset((u8*)pmd, 0, PAGE_SIZE); + pte = &pgd[0]; + dma_set_pte_addr(*pte, virt_to_maddr(pmd)); + dma_set_pte_readable(*pte); + dma_set_pte_writable(*pte); + + for ( i = 0; i < 8; i++ ) + { + /* Don't create new L2 entry, use ones from p2m table */ + pmd[i].val = l3e[i].l3 | _PAGE_PRESENT | _PAGE_RW; + } + break; + default: + gdprintk(XENLOG_ERR VTDPREFIX, + "iommu_set_pgd:Unsupported p2m table sharing level!\n"); + break; } unmap_domain_page(l3e); spin_unlock_irqrestore(&hd->mapping_lock, flags); @@ -1813,37 +1883,37 @@ void iommu_set_pgd(struct domain *d) l3_pgentry_t *l3e; mfn_t pgd_mfn; - switch (level) + switch ( level ) { - case VTD_PAGE_TABLE_LEVEL_3: - l3e = map_domain_page(p2m_table); - if ( (l3e_get_flags(*l3e) & _PAGE_PRESENT) == 0 ) - { - gdprintk(XENLOG_ERR VTDPREFIX, - "iommu_set_pgd: second level wasn't there\n"); - unmap_domain_page(l3e); - return; - } - pgd_mfn = _mfn(l3e_get_pfn(*l3e)); + case VTD_PAGE_TABLE_LEVEL_3: + l3e = map_domain_page(p2m_table); + if ( (l3e_get_flags(*l3e) & _PAGE_PRESENT) == 0 ) + { + gdprintk(XENLOG_ERR VTDPREFIX, + "iommu_set_pgd: second level wasn't there\n"); unmap_domain_page(l3e); - hd->pgd = maddr_to_virt(pagetable_get_paddr( - pagetable_from_mfn(pgd_mfn))); - break; - - case VTD_PAGE_TABLE_LEVEL_4: - pgd_mfn = _mfn(p2m_table); - hd->pgd = maddr_to_virt(pagetable_get_paddr( - pagetable_from_mfn(pgd_mfn))); - break; - default: - gdprintk(XENLOG_ERR VTDPREFIX, - "iommu_set_pgd:Unsupported p2m table sharing level!\n"); - break; + return; + } + pgd_mfn = _mfn(l3e_get_pfn(*l3e)); + unmap_domain_page(l3e); + hd->pgd = maddr_to_virt(pagetable_get_paddr( + pagetable_from_mfn(pgd_mfn))); + break; + + case VTD_PAGE_TABLE_LEVEL_4: + pgd_mfn = _mfn(p2m_table); + hd->pgd = maddr_to_virt(pagetable_get_paddr( + pagetable_from_mfn(pgd_mfn))); + break; + default: + gdprintk(XENLOG_ERR VTDPREFIX, + "iommu_set_pgd:Unsupported p2m table sharing level!\n"); + break; } } #endif gdprintk(XENLOG_INFO VTDPREFIX, - "iommu_set_pgd: hd->pgd = %p\n", hd->pgd); + "iommu_set_pgd: hd->pgd = %p\n", hd->pgd); } @@ -1854,11 +1924,10 @@ int iommu_suspend(void) struct iommu *iommu; int i = 0; - if (!vtd_enable) - return 0; - flush_all(); - for_each_drhd_unit(drhd) { + + for_each_drhd_unit ( drhd ) + { iommu = drhd->iommu; iommu_state[DMAR_RTADDR_REG * i] = (u64) dmar_readq(iommu->reg, DMAR_RTADDR_REG); @@ -1890,36 +1959,44 @@ int iommu_resume(void) struct iommu *iommu; int i = 0; - if (!vtd_enable) - return 0; - flush_all(); init_vtd_hw(); - for_each_drhd_unit(drhd) { + for_each_drhd_unit ( drhd ) + { iommu = drhd->iommu; dmar_writeq( iommu->reg, DMAR_RTADDR_REG, - (u64) iommu_state[DMAR_RTADDR_REG * i]); + (u64) iommu_state[DMAR_RTADDR_REG * i]); dmar_writel(iommu->reg, DMAR_FECTL_REG, - (u32) iommu_state[DMAR_FECTL_REG * i]); + (u32) iommu_state[DMAR_FECTL_REG * i]); dmar_writel(iommu->reg, DMAR_FEDATA_REG, - (u32) iommu_state[DMAR_FEDATA_REG * i]); + (u32) iommu_state[DMAR_FEDATA_REG * i]); dmar_writel(iommu->reg, DMAR_FEADDR_REG, - (u32) iommu_state[DMAR_FEADDR_REG * i]); + (u32) iommu_state[DMAR_FEADDR_REG * i]); dmar_writel(iommu->reg, DMAR_FEUADDR_REG, - (u32) iommu_state[DMAR_FEUADDR_REG * i]); + (u32) iommu_state[DMAR_FEUADDR_REG * i]); dmar_writel(iommu->reg, DMAR_PLMBASE_REG, - (u32) iommu_state[DMAR_PLMBASE_REG * i]); + (u32) iommu_state[DMAR_PLMBASE_REG * i]); dmar_writel(iommu->reg, DMAR_PLMLIMIT_REG, - (u32) iommu_state[DMAR_PLMLIMIT_REG * i]); + (u32) iommu_state[DMAR_PLMLIMIT_REG * i]); dmar_writeq(iommu->reg, DMAR_PHMBASE_REG, - (u64) iommu_state[DMAR_PHMBASE_REG * i]); + (u64) iommu_state[DMAR_PHMBASE_REG * i]); dmar_writeq(iommu->reg, DMAR_PHMLIMIT_REG, - (u64) iommu_state[DMAR_PHMLIMIT_REG * i]); - - if (iommu_enable_translation(iommu)) + (u64) iommu_state[DMAR_PHMLIMIT_REG * i]); + + if ( iommu_enable_translation(iommu) ) return -EIO; i++; } return 0; } + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |