/* To invalidate the DART, set the DARTCNTL_FLUSHTLB bit in the * control register and wait for it to clear. * * Gotcha: Sometimes, the DART won't detect that the bit gets * set. If so, clear it and set it again.
*/
limit = 0;
wait_more:
l = 0; while ((DART_IN(DART_CNTL) & DART_CNTL_U4_IONE) && l < (1L << limit)) {
rmb();
l++;
}
if (l == (1L << limit)) { if (limit < 4) {
limit++; goto wait_more;
} else
panic("DART: TLB did not flush after waiting a long " "time. Buggy U4 ?");
}
staticvoid dart_cache_sync(unsignedint *base, unsignedint count)
{ /* * We add 1 to the number of entries to flush, following a * comment in Darwin indicating that the memory controller * can prefetch unmapped memory under some circumstances.
*/ unsignedlong start = (unsignedlong)base; unsignedlong end = start + (count + 1) * sizeof(unsignedint); unsignedint tmp;
/* Perform a standard cache flush */
flush_dcache_range(start, end);
/* * Perform the sequence described in the CPC925 manual to * ensure all the data gets to a point the cache incoherent * DART hardware will see.
*/ asmvolatile(" sync;" " isync;" " dcbf 0,%1;" " sync;" " isync;" " lwz %0,0(%1);" " isync" : "=r" (tmp) : "r" (end) : "memory");
}
if (dart_is_u4) {
rpn = index; while (npages--)
dart_tlb_invalidate_one(rpn++);
} else {
dart_dirty = 1;
} return 0;
}
staticvoid dart_free(struct iommu_table *tbl, long index, long npages)
{ unsignedint *dp, *orig_dp; long orig_npages = npages;
/* We don't worry about flushing the TLB cache. The only drawback of * not doing it is that we won't catch buggy device drivers doing * bad DMAs, but then no 32-bit architecture ever does either.
*/
/* 512 pages (2MB) is max DART tablesize. */
dart_tablesize = 1UL << 21;
/* * 16MB (1 << 24) alignment. We allocate a full 16Mb chuck since we * will blow up an entire large page anyway in the kernel mapping.
*/
dart_tablebase = memblock_alloc_try_nid_raw(SZ_16M, SZ_16M,
MEMBLOCK_LOW_LIMIT, SZ_2G,
NUMA_NO_NODE); if (!dart_tablebase)
panic("Failed to allocate 16MB below 2GB for DART table\n");
/* Allocate a spare page to map all invalid DART pages. We need to do * that to work around what looks like a problem with the HT bridge * prefetching into invalid pages and corrupting data
*/
tmp = memblock_phys_alloc(DART_PAGE_SIZE, DART_PAGE_SIZE); if (!tmp)
panic("DART: table allocation failed\n");
/* IOMMU disabled by the user ? bail out */ if (iommu_is_off) return -ENODEV;
/* * Only use the DART if the machine has more than 1GB of RAM * or if requested with iommu=on on cmdline. * * 1GB of RAM is picked as limit because some default devices * (i.e. Airport Extreme) have 30 bit address range limits.
*/
if (!iommu_force_on && memblock_end_of_DRAM() <= 0x40000000ull) return -ENODEV;
/* Get DART registers */ if (of_address_to_resource(dart_node, 0, &r))
panic("DART: can't get register base ! ");
/* Map in DART registers */
dart = ioremap(r.start, resource_size(&r)); if (dart == NULL)
panic("DART: Cannot map registers!");
/* Allocate the DART and dummy page */
allocate_dart();
/* Fill initial table */ for (i = 0; i < dart_tablesize/4; i++)
dart_tablebase[i] = dart_emptyval;
/* Push to memory */
dart_cache_sync(dart_tablebase, dart_tablesize / sizeof(u32));
/* Initialize DART with table base and enable it. */
base = ((unsignedlong)dart_tablebase) >> DART_PAGE_SHIFT;
size = dart_tablesize >> DART_PAGE_SHIFT; if (dart_is_u4) {
size &= DART_SIZE_U4_SIZE_MASK;
DART_OUT(DART_BASE_U4, base);
DART_OUT(DART_SIZE_U4, size);
DART_OUT(DART_CNTL, DART_CNTL_U4_ENABLE);
} else {
size &= DART_CNTL_U3_SIZE_MASK;
DART_OUT(DART_CNTL,
DART_CNTL_U3_ENABLE |
(base << DART_CNTL_U3_BASE_SHIFT) |
(size << DART_CNTL_U3_SIZE_SHIFT));
}
/* Invalidate DART to get rid of possible stale TLBs */
dart_tlb_invalidate_all();
printk(KERN_INFO "DART IOMMU initialized for %s type chipset\n",
dart_is_u4 ? "U4" : "U3");
staticvoid iommu_table_dart_setup(void)
{
iommu_table_dart.it_busno = 0;
iommu_table_dart.it_offset = 0; /* it_size is in number of entries */
iommu_table_dart.it_size = dart_tablesize / sizeof(u32);
iommu_table_dart.it_page_shift = IOMMU_PAGE_SHIFT_4K;
/* Initialize the common IOMMU code */
iommu_table_dart.it_base = (unsignedlong)dart_tablebase;
iommu_table_dart.it_index = 0;
iommu_table_dart.it_blocksize = 1;
iommu_table_dart.it_ops = &iommu_dart_ops; if (!iommu_init_table(&iommu_table_dart, -1, 0, 0))
panic("Failed to initialize iommu table");
/* Reserve the last page of the DART to avoid possible prefetch * past the DART mapped area
*/
set_bit(iommu_table_dart.it_size - 1, iommu_table_dart.it_map);
}
/* Find the DART in the device-tree */
dn = of_find_compatible_node(NULL, "dart", "u3-dart"); if (dn == NULL) {
dn = of_find_compatible_node(NULL, "dart", "u4-dart"); if (dn == NULL) return; /* use default direct_dma_ops */
dart_is_u4 = 1;
}
/* Initialize the DART HW */ if (dart_init(dn) != 0) {
of_node_put(dn); return;
} /* * U4 supports a DART bypass, we use it for 64-bit capable devices to * improve performance. However, that only works for devices connected * to the U4 own PCIe interface, not bridged through hypertransport. * We need the device to support at least 40 bits of addresses.
*/
controller_ops->dma_dev_setup = pci_dma_dev_setup_dart;
controller_ops->dma_bus_setup = pci_dma_bus_setup_dart;
controller_ops->iommu_bypass_supported = iommu_bypass_supported_dart;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.