18c9c727bSJoao Martins // SPDX-License-Identifier: GPL-2.0
28c9c727bSJoao Martins /*
38c9c727bSJoao Martins * Copyright (c) 2022, Oracle and/or its affiliates.
48c9c727bSJoao Martins * Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved
58c9c727bSJoao Martins */
6*1d4684fbSNicolin Chen #include <linux/highmem.h>
78c9c727bSJoao Martins #include <linux/iova_bitmap.h>
88c9c727bSJoao Martins #include <linux/mm.h>
98c9c727bSJoao Martins #include <linux/slab.h>
108c9c727bSJoao Martins
118c9c727bSJoao Martins #define BITS_PER_PAGE (PAGE_SIZE * BITS_PER_BYTE)
128c9c727bSJoao Martins
138c9c727bSJoao Martins /*
148c9c727bSJoao Martins * struct iova_bitmap_map - A bitmap representing an IOVA range
158c9c727bSJoao Martins *
168c9c727bSJoao Martins * Main data structure for tracking mapped user pages of bitmap data.
178c9c727bSJoao Martins *
188c9c727bSJoao Martins * For example, for something recording dirty IOVAs, it will be provided a
198c9c727bSJoao Martins * struct iova_bitmap structure, as a general structure for iterating the
208c9c727bSJoao Martins * total IOVA range. The struct iova_bitmap_map, though, represents the
218c9c727bSJoao Martins * subset of said IOVA space that is pinned by its parent structure (struct
228c9c727bSJoao Martins * iova_bitmap).
238c9c727bSJoao Martins *
248c9c727bSJoao Martins * The user does not need to exact location of the bits in the bitmap.
258c9c727bSJoao Martins * From user perspective the only API available is iova_bitmap_set() which
268c9c727bSJoao Martins * records the IOVA *range* in the bitmap by setting the corresponding
278c9c727bSJoao Martins * bits.
288c9c727bSJoao Martins *
298c9c727bSJoao Martins * The bitmap is an array of u64 whereas each bit represents an IOVA of
308c9c727bSJoao Martins * range of (1 << pgshift). Thus formula for the bitmap data to be set is:
318c9c727bSJoao Martins *
328c9c727bSJoao Martins * data[(iova / page_size) / 64] & (1ULL << (iova % 64))
338c9c727bSJoao Martins */
348c9c727bSJoao Martins struct iova_bitmap_map {
358c9c727bSJoao Martins /* base IOVA representing bit 0 of the first page */
368c9c727bSJoao Martins unsigned long iova;
378c9c727bSJoao Martins
38a84c690eSJoao Martins /* mapped length */
39a84c690eSJoao Martins unsigned long length;
40a84c690eSJoao Martins
418c9c727bSJoao Martins /* page size order that each bit granules to */
428c9c727bSJoao Martins unsigned long pgshift;
438c9c727bSJoao Martins
448c9c727bSJoao Martins /* page offset of the first user page pinned */
458c9c727bSJoao Martins unsigned long pgoff;
468c9c727bSJoao Martins
478c9c727bSJoao Martins /* number of pages pinned */
488c9c727bSJoao Martins unsigned long npages;
498c9c727bSJoao Martins
508c9c727bSJoao Martins /* pinned pages representing the bitmap data */
518c9c727bSJoao Martins struct page **pages;
528c9c727bSJoao Martins };
538c9c727bSJoao Martins
548c9c727bSJoao Martins /*
558c9c727bSJoao Martins * struct iova_bitmap - The IOVA bitmap object
568c9c727bSJoao Martins *
578c9c727bSJoao Martins * Main data structure for iterating over the bitmap data.
588c9c727bSJoao Martins *
598c9c727bSJoao Martins * Abstracts the pinning work and iterates in IOVA ranges.
608c9c727bSJoao Martins * It uses a windowing scheme and pins the bitmap in relatively
618c9c727bSJoao Martins * big ranges e.g.
628c9c727bSJoao Martins *
638c9c727bSJoao Martins * The bitmap object uses one base page to store all the pinned pages
648c9c727bSJoao Martins * pointers related to the bitmap. For sizeof(struct page*) == 8 it stores
658c9c727bSJoao Martins * 512 struct page pointers which, if the base page size is 4K, it means
668c9c727bSJoao Martins * 2M of bitmap data is pinned at a time. If the iova_bitmap page size is
678c9c727bSJoao Martins * also 4K then the range window to iterate is 64G.
688c9c727bSJoao Martins *
698c9c727bSJoao Martins * For example iterating on a total IOVA range of 4G..128G, it will walk
708c9c727bSJoao Martins * through this set of ranges:
718c9c727bSJoao Martins *
728c9c727bSJoao Martins * 4G - 68G-1 (64G)
738c9c727bSJoao Martins * 68G - 128G-1 (64G)
748c9c727bSJoao Martins *
758c9c727bSJoao Martins * An example of the APIs on how to use/iterate over the IOVA bitmap:
768c9c727bSJoao Martins *
778c9c727bSJoao Martins * bitmap = iova_bitmap_alloc(iova, length, page_size, data);
788c9c727bSJoao Martins * if (IS_ERR(bitmap))
798c9c727bSJoao Martins * return PTR_ERR(bitmap);
808c9c727bSJoao Martins *
818c9c727bSJoao Martins * ret = iova_bitmap_for_each(bitmap, arg, dirty_reporter_fn);
828c9c727bSJoao Martins *
838c9c727bSJoao Martins * iova_bitmap_free(bitmap);
848c9c727bSJoao Martins *
858c9c727bSJoao Martins * Each iteration of the @dirty_reporter_fn is called with a unique @iova
868c9c727bSJoao Martins * and @length argument, indicating the current range available through the
878c9c727bSJoao Martins * iova_bitmap. The @dirty_reporter_fn uses iova_bitmap_set() to mark dirty
888c9c727bSJoao Martins * areas (@iova_length) within that provided range, as following:
898c9c727bSJoao Martins *
908c9c727bSJoao Martins * iova_bitmap_set(bitmap, iova, iova_length);
918c9c727bSJoao Martins *
928c9c727bSJoao Martins * The internals of the object uses an index @mapped_base_index that indexes
938c9c727bSJoao Martins * which u64 word of the bitmap is mapped, up to @mapped_total_index.
948c9c727bSJoao Martins * Those keep being incremented until @mapped_total_index is reached while
958c9c727bSJoao Martins * mapping up to PAGE_SIZE / sizeof(struct page*) maximum of pages.
968c9c727bSJoao Martins *
978c9c727bSJoao Martins * The IOVA bitmap is usually located on what tracks DMA mapped ranges or
988c9c727bSJoao Martins * some form of IOVA range tracking that co-relates to the user passed
998c9c727bSJoao Martins * bitmap.
1008c9c727bSJoao Martins */
1018c9c727bSJoao Martins struct iova_bitmap {
1028c9c727bSJoao Martins /* IOVA range representing the currently mapped bitmap data */
1038c9c727bSJoao Martins struct iova_bitmap_map mapped;
1048c9c727bSJoao Martins
1058c9c727bSJoao Martins /* userspace address of the bitmap */
106d18411ecSJoao Martins u8 __user *bitmap;
1078c9c727bSJoao Martins
1088c9c727bSJoao Martins /* u64 index that @mapped points to */
1098c9c727bSJoao Martins unsigned long mapped_base_index;
1108c9c727bSJoao Martins
1118c9c727bSJoao Martins /* how many u64 can we walk in total */
1128c9c727bSJoao Martins unsigned long mapped_total_index;
1138c9c727bSJoao Martins
1148c9c727bSJoao Martins /* base IOVA of the whole bitmap */
1158c9c727bSJoao Martins unsigned long iova;
1168c9c727bSJoao Martins
1178c9c727bSJoao Martins /* length of the IOVA range for the whole bitmap */
1188c9c727bSJoao Martins size_t length;
1198c9c727bSJoao Martins };
1208c9c727bSJoao Martins
1218c9c727bSJoao Martins /*
1228c9c727bSJoao Martins * Converts a relative IOVA to a bitmap index.
1238c9c727bSJoao Martins * This function provides the index into the u64 array (bitmap::bitmap)
1248c9c727bSJoao Martins * for a given IOVA offset.
1258c9c727bSJoao Martins * Relative IOVA means relative to the bitmap::mapped base IOVA
1268c9c727bSJoao Martins * (stored in mapped::iova). All computations in this file are done using
1278c9c727bSJoao Martins * relative IOVAs and thus avoid an extra subtraction against mapped::iova.
1288c9c727bSJoao Martins * The user API iova_bitmap_set() always uses a regular absolute IOVAs.
1298c9c727bSJoao Martins */
iova_bitmap_offset_to_index(struct iova_bitmap * bitmap,unsigned long iova)1308c9c727bSJoao Martins static unsigned long iova_bitmap_offset_to_index(struct iova_bitmap *bitmap,
1318c9c727bSJoao Martins unsigned long iova)
1328c9c727bSJoao Martins {
1338c9c727bSJoao Martins unsigned long pgsize = 1 << bitmap->mapped.pgshift;
1348c9c727bSJoao Martins
1358c9c727bSJoao Martins return iova / (BITS_PER_TYPE(*bitmap->bitmap) * pgsize);
1368c9c727bSJoao Martins }
1378c9c727bSJoao Martins
1388c9c727bSJoao Martins /*
1398c9c727bSJoao Martins * Converts a bitmap index to a *relative* IOVA.
1408c9c727bSJoao Martins */
iova_bitmap_index_to_offset(struct iova_bitmap * bitmap,unsigned long index)1418c9c727bSJoao Martins static unsigned long iova_bitmap_index_to_offset(struct iova_bitmap *bitmap,
1428c9c727bSJoao Martins unsigned long index)
1438c9c727bSJoao Martins {
1448c9c727bSJoao Martins unsigned long pgshift = bitmap->mapped.pgshift;
1458c9c727bSJoao Martins
1468c9c727bSJoao Martins return (index * BITS_PER_TYPE(*bitmap->bitmap)) << pgshift;
1478c9c727bSJoao Martins }
1488c9c727bSJoao Martins
1498c9c727bSJoao Martins /*
1508c9c727bSJoao Martins * Returns the base IOVA of the mapped range.
1518c9c727bSJoao Martins */
iova_bitmap_mapped_iova(struct iova_bitmap * bitmap)1528c9c727bSJoao Martins static unsigned long iova_bitmap_mapped_iova(struct iova_bitmap *bitmap)
1538c9c727bSJoao Martins {
1548c9c727bSJoao Martins unsigned long skip = bitmap->mapped_base_index;
1558c9c727bSJoao Martins
1568c9c727bSJoao Martins return bitmap->iova + iova_bitmap_index_to_offset(bitmap, skip);
1578c9c727bSJoao Martins }
1588c9c727bSJoao Martins
159a84c690eSJoao Martins static unsigned long iova_bitmap_mapped_length(struct iova_bitmap *bitmap);
160a84c690eSJoao Martins
1618c9c727bSJoao Martins /*
1628c9c727bSJoao Martins * Pins the bitmap user pages for the current range window.
1638c9c727bSJoao Martins * This is internal to IOVA bitmap and called when advancing the
1648c9c727bSJoao Martins * index (@mapped_base_index) or allocating the bitmap.
1658c9c727bSJoao Martins */
iova_bitmap_get(struct iova_bitmap * bitmap)1668c9c727bSJoao Martins static int iova_bitmap_get(struct iova_bitmap *bitmap)
1678c9c727bSJoao Martins {
1688c9c727bSJoao Martins struct iova_bitmap_map *mapped = &bitmap->mapped;
1698c9c727bSJoao Martins unsigned long npages;
170d18411ecSJoao Martins u8 __user *addr;
1718c9c727bSJoao Martins long ret;
1728c9c727bSJoao Martins
1738c9c727bSJoao Martins /*
1748c9c727bSJoao Martins * @mapped_base_index is the index of the currently mapped u64 words
1758c9c727bSJoao Martins * that we have access. Anything before @mapped_base_index is not
1768c9c727bSJoao Martins * mapped. The range @mapped_base_index .. @mapped_total_index-1 is
1778c9c727bSJoao Martins * mapped but capped at a maximum number of pages.
1788c9c727bSJoao Martins */
1798c9c727bSJoao Martins npages = DIV_ROUND_UP((bitmap->mapped_total_index -
1808c9c727bSJoao Martins bitmap->mapped_base_index) *
1818c9c727bSJoao Martins sizeof(*bitmap->bitmap), PAGE_SIZE);
1828c9c727bSJoao Martins
1838c9c727bSJoao Martins /*
1848c9c727bSJoao Martins * Bitmap address to be pinned is calculated via pointer arithmetic
1858c9c727bSJoao Martins * with bitmap u64 word index.
1868c9c727bSJoao Martins */
1878c9c727bSJoao Martins addr = bitmap->bitmap + bitmap->mapped_base_index;
1888c9c727bSJoao Martins
1894bbcbc6eSJoao Martins /*
1904bbcbc6eSJoao Martins * We always cap at max number of 'struct page' a base page can fit.
1914bbcbc6eSJoao Martins * This is, for example, on x86 means 2M of bitmap data max.
1924bbcbc6eSJoao Martins */
1934bbcbc6eSJoao Martins npages = min(npages + !!offset_in_page(addr),
1944bbcbc6eSJoao Martins PAGE_SIZE / sizeof(struct page *));
1954bbcbc6eSJoao Martins
1968c9c727bSJoao Martins ret = pin_user_pages_fast((unsigned long)addr, npages,
1978c9c727bSJoao Martins FOLL_WRITE, mapped->pages);
1988c9c727bSJoao Martins if (ret <= 0)
1998c9c727bSJoao Martins return -EFAULT;
2008c9c727bSJoao Martins
2018c9c727bSJoao Martins mapped->npages = (unsigned long)ret;
2028c9c727bSJoao Martins /* Base IOVA where @pages point to i.e. bit 0 of the first page */
2038c9c727bSJoao Martins mapped->iova = iova_bitmap_mapped_iova(bitmap);
2048c9c727bSJoao Martins
2058c9c727bSJoao Martins /*
2068c9c727bSJoao Martins * offset of the page where pinned pages bit 0 is located.
2078c9c727bSJoao Martins * This handles the case where the bitmap is not PAGE_SIZE
2088c9c727bSJoao Martins * aligned.
2098c9c727bSJoao Martins */
2108c9c727bSJoao Martins mapped->pgoff = offset_in_page(addr);
211a84c690eSJoao Martins mapped->length = iova_bitmap_mapped_length(bitmap);
2128c9c727bSJoao Martins return 0;
2138c9c727bSJoao Martins }
2148c9c727bSJoao Martins
2158c9c727bSJoao Martins /*
2168c9c727bSJoao Martins * Unpins the bitmap user pages and clears @npages
2178c9c727bSJoao Martins * (un)pinning is abstracted from API user and it's done when advancing
2188c9c727bSJoao Martins * the index or freeing the bitmap.
2198c9c727bSJoao Martins */
iova_bitmap_put(struct iova_bitmap * bitmap)2208c9c727bSJoao Martins static void iova_bitmap_put(struct iova_bitmap *bitmap)
2218c9c727bSJoao Martins {
2228c9c727bSJoao Martins struct iova_bitmap_map *mapped = &bitmap->mapped;
2238c9c727bSJoao Martins
2248c9c727bSJoao Martins if (mapped->npages) {
2258c9c727bSJoao Martins unpin_user_pages(mapped->pages, mapped->npages);
2268c9c727bSJoao Martins mapped->npages = 0;
2278c9c727bSJoao Martins }
2288c9c727bSJoao Martins }
2298c9c727bSJoao Martins
2308c9c727bSJoao Martins /**
2318c9c727bSJoao Martins * iova_bitmap_alloc() - Allocates an IOVA bitmap object
2328c9c727bSJoao Martins * @iova: Start address of the IOVA range
2338c9c727bSJoao Martins * @length: Length of the IOVA range
2348c9c727bSJoao Martins * @page_size: Page size of the IOVA bitmap. It defines what each bit
2358c9c727bSJoao Martins * granularity represents
2368c9c727bSJoao Martins * @data: Userspace address of the bitmap
2378c9c727bSJoao Martins *
2388c9c727bSJoao Martins * Allocates an IOVA object and initializes all its fields including the
2398c9c727bSJoao Martins * first user pages of @data.
2408c9c727bSJoao Martins *
2418c9c727bSJoao Martins * Return: A pointer to a newly allocated struct iova_bitmap
2428c9c727bSJoao Martins * or ERR_PTR() on error.
2438c9c727bSJoao Martins */
iova_bitmap_alloc(unsigned long iova,size_t length,unsigned long page_size,u64 __user * data)2448c9c727bSJoao Martins struct iova_bitmap *iova_bitmap_alloc(unsigned long iova, size_t length,
2458c9c727bSJoao Martins unsigned long page_size, u64 __user *data)
2468c9c727bSJoao Martins {
2478c9c727bSJoao Martins struct iova_bitmap_map *mapped;
2488c9c727bSJoao Martins struct iova_bitmap *bitmap;
2498c9c727bSJoao Martins int rc;
2508c9c727bSJoao Martins
2518c9c727bSJoao Martins bitmap = kzalloc(sizeof(*bitmap), GFP_KERNEL);
2528c9c727bSJoao Martins if (!bitmap)
2538c9c727bSJoao Martins return ERR_PTR(-ENOMEM);
2548c9c727bSJoao Martins
2558c9c727bSJoao Martins mapped = &bitmap->mapped;
2568c9c727bSJoao Martins mapped->pgshift = __ffs(page_size);
257d18411ecSJoao Martins bitmap->bitmap = (u8 __user *)data;
2588c9c727bSJoao Martins bitmap->mapped_total_index =
2598c9c727bSJoao Martins iova_bitmap_offset_to_index(bitmap, length - 1) + 1;
2608c9c727bSJoao Martins bitmap->iova = iova;
2618c9c727bSJoao Martins bitmap->length = length;
2628c9c727bSJoao Martins mapped->iova = iova;
2638c9c727bSJoao Martins mapped->pages = (struct page **)__get_free_page(GFP_KERNEL);
2648c9c727bSJoao Martins if (!mapped->pages) {
2658c9c727bSJoao Martins rc = -ENOMEM;
2668c9c727bSJoao Martins goto err;
2678c9c727bSJoao Martins }
2688c9c727bSJoao Martins
2698c9c727bSJoao Martins return bitmap;
2708c9c727bSJoao Martins
2718c9c727bSJoao Martins err:
2728c9c727bSJoao Martins iova_bitmap_free(bitmap);
2738c9c727bSJoao Martins return ERR_PTR(rc);
2748c9c727bSJoao Martins }
27513578d4eSJoao Martins EXPORT_SYMBOL_NS_GPL(iova_bitmap_alloc, IOMMUFD);
2768c9c727bSJoao Martins
2778c9c727bSJoao Martins /**
2788c9c727bSJoao Martins * iova_bitmap_free() - Frees an IOVA bitmap object
2798c9c727bSJoao Martins * @bitmap: IOVA bitmap to free
2808c9c727bSJoao Martins *
2818c9c727bSJoao Martins * It unpins and releases pages array memory and clears any leftover
2828c9c727bSJoao Martins * state.
2838c9c727bSJoao Martins */
iova_bitmap_free(struct iova_bitmap * bitmap)2848c9c727bSJoao Martins void iova_bitmap_free(struct iova_bitmap *bitmap)
2858c9c727bSJoao Martins {
2868c9c727bSJoao Martins struct iova_bitmap_map *mapped = &bitmap->mapped;
2878c9c727bSJoao Martins
2888c9c727bSJoao Martins iova_bitmap_put(bitmap);
2898c9c727bSJoao Martins
2908c9c727bSJoao Martins if (mapped->pages) {
2918c9c727bSJoao Martins free_page((unsigned long)mapped->pages);
2928c9c727bSJoao Martins mapped->pages = NULL;
2938c9c727bSJoao Martins }
2948c9c727bSJoao Martins
2958c9c727bSJoao Martins kfree(bitmap);
2968c9c727bSJoao Martins }
29713578d4eSJoao Martins EXPORT_SYMBOL_NS_GPL(iova_bitmap_free, IOMMUFD);
2988c9c727bSJoao Martins
2998c9c727bSJoao Martins /*
3008c9c727bSJoao Martins * Returns the remaining bitmap indexes from mapped_total_index to process for
3018c9c727bSJoao Martins * the currently pinned bitmap pages.
3028c9c727bSJoao Martins */
iova_bitmap_mapped_remaining(struct iova_bitmap * bitmap)3038c9c727bSJoao Martins static unsigned long iova_bitmap_mapped_remaining(struct iova_bitmap *bitmap)
3048c9c727bSJoao Martins {
3058c9c727bSJoao Martins unsigned long remaining, bytes;
3068c9c727bSJoao Martins
3078c9c727bSJoao Martins bytes = (bitmap->mapped.npages << PAGE_SHIFT) - bitmap->mapped.pgoff;
3088c9c727bSJoao Martins
3098c9c727bSJoao Martins remaining = bitmap->mapped_total_index - bitmap->mapped_base_index;
3108c9c727bSJoao Martins remaining = min_t(unsigned long, remaining,
311d18411ecSJoao Martins DIV_ROUND_UP(bytes, sizeof(*bitmap->bitmap)));
3128c9c727bSJoao Martins
3138c9c727bSJoao Martins return remaining;
3148c9c727bSJoao Martins }
3158c9c727bSJoao Martins
3168c9c727bSJoao Martins /*
3178c9c727bSJoao Martins * Returns the length of the mapped IOVA range.
3188c9c727bSJoao Martins */
iova_bitmap_mapped_length(struct iova_bitmap * bitmap)3198c9c727bSJoao Martins static unsigned long iova_bitmap_mapped_length(struct iova_bitmap *bitmap)
3208c9c727bSJoao Martins {
3218c9c727bSJoao Martins unsigned long max_iova = bitmap->iova + bitmap->length - 1;
3228c9c727bSJoao Martins unsigned long iova = iova_bitmap_mapped_iova(bitmap);
3238c9c727bSJoao Martins unsigned long remaining;
3248c9c727bSJoao Martins
3258c9c727bSJoao Martins /*
3268c9c727bSJoao Martins * iova_bitmap_mapped_remaining() returns a number of indexes which
3278c9c727bSJoao Martins * when converted to IOVA gives us a max length that the bitmap
3288c9c727bSJoao Martins * pinned data can cover. Afterwards, that is capped to
3298c9c727bSJoao Martins * only cover the IOVA range in @bitmap::iova .. @bitmap::length.
3308c9c727bSJoao Martins */
3318c9c727bSJoao Martins remaining = iova_bitmap_index_to_offset(bitmap,
3328c9c727bSJoao Martins iova_bitmap_mapped_remaining(bitmap));
3338c9c727bSJoao Martins
3348c9c727bSJoao Martins if (iova + remaining - 1 > max_iova)
3358c9c727bSJoao Martins remaining -= ((iova + remaining - 1) - max_iova);
3368c9c727bSJoao Martins
3378c9c727bSJoao Martins return remaining;
3388c9c727bSJoao Martins }
3398c9c727bSJoao Martins
3408c9c727bSJoao Martins /*
3417a7bba16SJoao Martins * Returns true if [@iova..@iova+@length-1] is part of the mapped IOVA range.
3427a7bba16SJoao Martins */
iova_bitmap_mapped_range(struct iova_bitmap_map * mapped,unsigned long iova,size_t length)3437a7bba16SJoao Martins static bool iova_bitmap_mapped_range(struct iova_bitmap_map *mapped,
3447a7bba16SJoao Martins unsigned long iova, size_t length)
3457a7bba16SJoao Martins {
3467a7bba16SJoao Martins return mapped->npages &&
3477a7bba16SJoao Martins (iova >= mapped->iova &&
3487a7bba16SJoao Martins (iova + length - 1) <= (mapped->iova + mapped->length - 1));
3497a7bba16SJoao Martins }
3507a7bba16SJoao Martins
3517a7bba16SJoao Martins /*
3527a7bba16SJoao Martins * Advances to a selected range, releases the current pinned
3537a7bba16SJoao Martins * pages and pins the next set of bitmap pages.
3547a7bba16SJoao Martins * Returns 0 on success or otherwise errno.
3557a7bba16SJoao Martins */
iova_bitmap_advance_to(struct iova_bitmap * bitmap,unsigned long iova)3567a7bba16SJoao Martins static int iova_bitmap_advance_to(struct iova_bitmap *bitmap,
3577a7bba16SJoao Martins unsigned long iova)
3587a7bba16SJoao Martins {
3597a7bba16SJoao Martins unsigned long index;
3607a7bba16SJoao Martins
3617a7bba16SJoao Martins index = iova_bitmap_offset_to_index(bitmap, iova - bitmap->iova);
3627a7bba16SJoao Martins if (index >= bitmap->mapped_total_index)
3637a7bba16SJoao Martins return -EINVAL;
3647a7bba16SJoao Martins bitmap->mapped_base_index = index;
3657a7bba16SJoao Martins
3667a7bba16SJoao Martins iova_bitmap_put(bitmap);
3677a7bba16SJoao Martins
3687a7bba16SJoao Martins /* Pin the next set of bitmap pages */
3697a7bba16SJoao Martins return iova_bitmap_get(bitmap);
3707a7bba16SJoao Martins }
3717a7bba16SJoao Martins
3728c9c727bSJoao Martins /**
3738c9c727bSJoao Martins * iova_bitmap_for_each() - Iterates over the bitmap
3748c9c727bSJoao Martins * @bitmap: IOVA bitmap to iterate
3758c9c727bSJoao Martins * @opaque: Additional argument to pass to the callback
3768c9c727bSJoao Martins * @fn: Function that gets called for each IOVA range
3778c9c727bSJoao Martins *
3788c9c727bSJoao Martins * Helper function to iterate over bitmap data representing a portion of IOVA
3798c9c727bSJoao Martins * space. It hides the complexity of iterating bitmaps and translating the
3808c9c727bSJoao Martins * mapped bitmap user pages into IOVA ranges to process.
3818c9c727bSJoao Martins *
3828c9c727bSJoao Martins * Return: 0 on success, and an error on failure either upon
3838c9c727bSJoao Martins * iteration or when the callback returns an error.
3848c9c727bSJoao Martins */
iova_bitmap_for_each(struct iova_bitmap * bitmap,void * opaque,iova_bitmap_fn_t fn)3858c9c727bSJoao Martins int iova_bitmap_for_each(struct iova_bitmap *bitmap, void *opaque,
3868c9c727bSJoao Martins iova_bitmap_fn_t fn)
3878c9c727bSJoao Martins {
38853e6b656SJoao Martins return fn(bitmap, bitmap->iova, bitmap->length, opaque);
3898c9c727bSJoao Martins }
39013578d4eSJoao Martins EXPORT_SYMBOL_NS_GPL(iova_bitmap_for_each, IOMMUFD);
3918c9c727bSJoao Martins
3928c9c727bSJoao Martins /**
3938c9c727bSJoao Martins * iova_bitmap_set() - Records an IOVA range in bitmap
3948c9c727bSJoao Martins * @bitmap: IOVA bitmap
3958c9c727bSJoao Martins * @iova: IOVA to start
3968c9c727bSJoao Martins * @length: IOVA range length
3978c9c727bSJoao Martins *
3988c9c727bSJoao Martins * Set the bits corresponding to the range [iova .. iova+length-1] in
3998c9c727bSJoao Martins * the user bitmap.
4008c9c727bSJoao Martins *
4018c9c727bSJoao Martins */
iova_bitmap_set(struct iova_bitmap * bitmap,unsigned long iova,size_t length)4028c9c727bSJoao Martins void iova_bitmap_set(struct iova_bitmap *bitmap,
4038c9c727bSJoao Martins unsigned long iova, size_t length)
4048c9c727bSJoao Martins {
4058c9c727bSJoao Martins struct iova_bitmap_map *mapped = &bitmap->mapped;
4067a7bba16SJoao Martins unsigned long cur_bit, last_bit, last_page_idx;
4077a7bba16SJoao Martins
4087a7bba16SJoao Martins update_indexes:
40953e6b656SJoao Martins if (unlikely(!iova_bitmap_mapped_range(mapped, iova, length))) {
4107a7bba16SJoao Martins
4117a7bba16SJoao Martins /*
4127a7bba16SJoao Martins * The attempt to advance the base index to @iova
4137a7bba16SJoao Martins * may fail if it's out of bounds, or pinning the pages
4147a7bba16SJoao Martins * returns an error.
4157a7bba16SJoao Martins */
4167a7bba16SJoao Martins if (iova_bitmap_advance_to(bitmap, iova))
4177a7bba16SJoao Martins return;
4187a7bba16SJoao Martins }
4197a7bba16SJoao Martins
4207a7bba16SJoao Martins last_page_idx = mapped->npages - 1;
4217a7bba16SJoao Martins cur_bit = ((iova - mapped->iova) >>
4228c9c727bSJoao Martins mapped->pgshift) + mapped->pgoff * BITS_PER_BYTE;
4237a7bba16SJoao Martins last_bit = (((iova + length - 1) - mapped->iova) >>
4248c9c727bSJoao Martins mapped->pgshift) + mapped->pgoff * BITS_PER_BYTE;
4258c9c727bSJoao Martins
4268c9c727bSJoao Martins do {
4278c9c727bSJoao Martins unsigned int page_idx = cur_bit / BITS_PER_PAGE;
4288c9c727bSJoao Martins unsigned int offset = cur_bit % BITS_PER_PAGE;
4298c9c727bSJoao Martins unsigned int nbits = min(BITS_PER_PAGE - offset,
4308c9c727bSJoao Martins last_bit - cur_bit + 1);
4318c9c727bSJoao Martins void *kaddr;
4328c9c727bSJoao Martins
43300fa1a89SJoao Martins if (unlikely(page_idx > last_page_idx)) {
43400fa1a89SJoao Martins unsigned long left =
43500fa1a89SJoao Martins ((last_bit - cur_bit + 1) << mapped->pgshift);
43600fa1a89SJoao Martins
4377a7bba16SJoao Martins iova += (length - left);
4387a7bba16SJoao Martins length = left;
4397a7bba16SJoao Martins goto update_indexes;
44000fa1a89SJoao Martins }
441a4ab7dedSJoao Martins
4428c9c727bSJoao Martins kaddr = kmap_local_page(mapped->pages[page_idx]);
4438c9c727bSJoao Martins bitmap_set(kaddr, offset, nbits);
4448c9c727bSJoao Martins kunmap_local(kaddr);
4458c9c727bSJoao Martins cur_bit += nbits;
4468c9c727bSJoao Martins } while (cur_bit <= last_bit);
4478c9c727bSJoao Martins }
44813578d4eSJoao Martins EXPORT_SYMBOL_NS_GPL(iova_bitmap_set, IOMMUFD);
449