// SPDX-License-Identifier: GPL-2.0 /* * iommu.c: IOMMU specific routines for memory management. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1995,2002 Pete Zaitcev (zaitcev@yahoo.com) * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
*/
/* * This can be sized dynamically, but we will do this * only when we have a guidance about actual I/O pressures.
*/ #define IOMMU_RNGE IOMMU_RNGE_256MB #define IOMMU_START 0xF0000000 #define IOMMU_WINSIZE (256*1024*1024U) #define IOMMU_NPTES (IOMMU_WINSIZE/PAGE_SIZE) /* 64K PTEs, 256KB */ #define IOMMU_ORDER 6 /* 4096 * (1<<6) */
/* Allocate IOMMU page table */ /* Stupid alignment constraints give me a headache. We need 256K or 512K or 1M or 2M area aligned to its size and current gfp will fortunately give
it to us. */
tmp = __get_free_pages(GFP_KERNEL, IOMMU_ORDER); if (!tmp) {
prom_printf("Unable to allocate iommu table [0x%lx]\n",
IOMMU_NPTES * sizeof(iopte_t));
prom_halt();
}
iommu->page_table = (iopte_t *)tmp;
/* Initialize new table. */
memset(iommu->page_table, 0, IOMMU_NPTES*sizeof(iopte_t));
flush_cache_all();
flush_tlb_all();
base = __pa((unsignedlong)iommu->page_table) >> 4;
sbus_writel(base, &iommu->regs->base);
iommu_invalidate(iommu->regs);
bitmap = kmalloc(IOMMU_NPTES>>3, GFP_KERNEL); if (!bitmap) {
prom_printf("Unable to allocate iommu bitmap [%d]\n",
(int)(IOMMU_NPTES>>3));
prom_halt();
}
bit_map_init(&iommu->usemap, bitmap, IOMMU_NPTES); /* To be coherent on HyperSparc, the page color of DVMA * and physical addresses must match.
*/ if (srmmu_modtype == HyperSparc)
iommu->usemap.num_colors = vac_cache_size >> PAGE_SHIFT; else
iommu->usemap.num_colors = 1;
/* Flush the iotlb entries to ram. */ /* This could be better if we didn't have to flush whole pages. */ staticvoid iommu_flush_iotlb(iopte_t *iopte, unsignedint niopte)
{ unsignedlong start; unsignedlong end;
/* XXX So what is maxphys for us and how do drivers know it? */ if (!len || len > 256 * 1024) return DMA_MAPPING_ERROR;
/* * We expect unmapped highmem pages to be not in the cache. * XXX Is this a good assumption? * XXX What if someone else unmaps it here and races us?
*/ if (per_page_flush && !PageHighMem(page)) { unsignedlong vaddr, p;
vaddr = (unsignedlong)page_address(page) + offset; for (p = vaddr & PAGE_MASK; p < vaddr + len; p += PAGE_SIZE)
flush_page_for_dma(p);
}
/* page color = pfn of page */
ioptex = bit_map_string_get(&iommu->usemap, npages, pfn); if (ioptex < 0)
panic("iommu out");
busa0 = iommu->start + (ioptex << PAGE_SHIFT);
iopte0 = &iommu->page_table[ioptex];
busa = busa0;
iopte = iopte0; for (i = 0; i < npages; i++) {
iopte_val(*iopte) = MKIOPTE(pfn, IOPERM);
iommu_invalidate_page(iommu->regs, busa);
busa += PAGE_SIZE;
iopte++;
pfn++;
}
set_pte(ptep, mk_pte(virt_to_page(page), dvma_prot));
}
iopte_val(*iopte++) =
MKIOPTE(page_to_pfn(virt_to_page(page)), ioperm_noc);
addr += PAGE_SIZE;
va += PAGE_SIZE;
} /* P3: why do we need this? * * DAVEM: Because there are several aspects, none of which * are handled by a single interface. Some cpus are * completely not I/O DMA coherent, and some have * virtually indexed caches. The driver DMA flushing * methods handle the former case, but here during * IOMMU page table modifications, and usage of non-cacheable * cpu mappings of pages potentially in the cpu caches, we have * to handle the latter case as well.
*/
flush_cache_all();
iommu_flush_iotlb(first, len >> PAGE_SHIFT);
flush_tlb_all();
iommu_invalidate(iommu->regs);
¤ 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.0.2Bemerkung:
(vorverarbeitet)
¤
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.