Thread (36 messages) 36 messages, 4 authors, 2011-10-17

[PATCH v3 1/6] iommu/core: split mapping to page sizes as supported by the hardware

From: Ohad Ben-Cohen <hidden>
Date: 2011-09-27 12:26:51
Also in: kvm, linux-omap, lkml

On Tue, Sep 27, 2011 at 1:05 PM, Roedel, Joerg [off-list ref] wrote:
On Fri, Sep 16, 2011 at 01:51:41PM -0400, Ohad Ben-Cohen wrote:
quoted
?int iommu_map(struct iommu_domain *domain, unsigned long iova,
- ? ? ? ? ? ? phys_addr_t paddr, int gfp_order, int prot)
+ ? ? ? ? ? ? phys_addr_t paddr, size_t size, int prot)
?{
- ? ? ? size_t size;
+ ? ? ? int ret = 0;
+
+ ? ? ? /*
+ ? ? ? ?* both the virtual address and the physical one, as well as
+ ? ? ? ?* the size of the mapping, must be aligned (at least) to the
+ ? ? ? ?* size of the smallest page supported by the hardware
+ ? ? ? ?*/
+ ? ? ? if (!IS_ALIGNED(iova | paddr | size, iommu_min_pagesz)) {
+ ? ? ? ? ? ? ? pr_err("unaligned: iova 0x%lx pa 0x%lx size 0x%lx min_pagesz "
+ ? ? ? ? ? ? ? ? ? ? ? "0x%x\n", iova, (unsigned long)paddr,
+ ? ? ? ? ? ? ? ? ? ? ? (unsigned long)size, iommu_min_pagesz);
+ ? ? ? ? ? ? ? return -EINVAL;
+ ? ? ? }
+
+ ? ? ? pr_debug("map: iova 0x%lx pa 0x%lx size 0x%lx\n", iova,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (unsigned long)paddr, (unsigned long)size);
+
+ ? ? ? while (size) {
+ ? ? ? ? ? ? ? unsigned long pgsize = iommu_min_pagesz;
+ ? ? ? ? ? ? ? unsigned long idx = iommu_min_page_idx;
+ ? ? ? ? ? ? ? unsigned long addr_merge = iova | paddr;
+ ? ? ? ? ? ? ? int order;
+
+ ? ? ? ? ? ? ? /* find the max page size with which iova, paddr are aligned */
+ ? ? ? ? ? ? ? for (;;) {
+ ? ? ? ? ? ? ? ? ? ? ? unsigned long try_pgsize;
+
+ ? ? ? ? ? ? ? ? ? ? ? idx = find_next_bit(iommu_pgsize_bitmap,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? iommu_nr_page_bits, idx + 1);
+
+ ? ? ? ? ? ? ? ? ? ? ? /* no more pages to check ? */
+ ? ? ? ? ? ? ? ? ? ? ? if (idx >= iommu_nr_page_bits)
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
+
+ ? ? ? ? ? ? ? ? ? ? ? try_pgsize = 1 << idx;

- ? ? ? size ? ? ? ? = 0x1000UL << gfp_order;
+ ? ? ? ? ? ? ? ? ? ? ? /* page too big ? addresses not aligned ? */
+ ? ? ? ? ? ? ? ? ? ? ? if (size < try_pgsize ||
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? !IS_ALIGNED(addr_merge, try_pgsize))
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;

- ? ? ? BUG_ON(!IS_ALIGNED(iova | paddr, size));
+ ? ? ? ? ? ? ? ? ? ? ? pgsize = try_pgsize;
+ ? ? ? ? ? ? ? }
With an unsigned long you can use plain and fast bit_ops instead of the
full bitmap functions.
Not sure I follow; the only bit operation I'm using while mapping is
find_next_bit() (which is a bitops.h method).

What other faster variant are you referring to ?

Thanks,
Ohad.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help