linux/drivers/iommu/iommufd/iova_bitmap.c

// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (c) 2022, Oracle and/or its affiliates.
 * Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved
 */
#include <linux/iova_bitmap.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/highmem.h>

#define BITS_PER_PAGE

/*
 * struct iova_bitmap_map - A bitmap representing an IOVA range
 *
 * Main data structure for tracking mapped user pages of bitmap data.
 *
 * For example, for something recording dirty IOVAs, it will be provided a
 * struct iova_bitmap structure, as a general structure for iterating the
 * total IOVA range. The struct iova_bitmap_map, though, represents the
 * subset of said IOVA space that is pinned by its parent structure (struct
 * iova_bitmap).
 *
 * The user does not need to exact location of the bits in the bitmap.
 * From user perspective the only API available is iova_bitmap_set() which
 * records the IOVA *range* in the bitmap by setting the corresponding
 * bits.
 *
 * The bitmap is an array of u64 whereas each bit represents an IOVA of
 * range of (1 << pgshift). Thus formula for the bitmap data to be set is:
 *
 *   data[(iova / page_size) / 64] & (1ULL << (iova % 64))
 */
struct iova_bitmap_map {};

/*
 * struct iova_bitmap - The IOVA bitmap object
 *
 * Main data structure for iterating over the bitmap data.
 *
 * Abstracts the pinning work and iterates in IOVA ranges.
 * It uses a windowing scheme and pins the bitmap in relatively
 * big ranges e.g.
 *
 * The bitmap object uses one base page to store all the pinned pages
 * pointers related to the bitmap. For sizeof(struct page*) == 8 it stores
 * 512 struct page pointers which, if the base page size is 4K, it means
 * 2M of bitmap data is pinned at a time. If the iova_bitmap page size is
 * also 4K then the range window to iterate is 64G.
 *
 * For example iterating on a total IOVA range of 4G..128G, it will walk
 * through this set of ranges:
 *
 *    4G  -  68G-1 (64G)
 *    68G - 128G-1 (64G)
 *
 * An example of the APIs on how to use/iterate over the IOVA bitmap:
 *
 *   bitmap = iova_bitmap_alloc(iova, length, page_size, data);
 *   if (IS_ERR(bitmap))
 *       return PTR_ERR(bitmap);
 *
 *   ret = iova_bitmap_for_each(bitmap, arg, dirty_reporter_fn);
 *
 *   iova_bitmap_free(bitmap);
 *
 * Each iteration of the @dirty_reporter_fn is called with a unique @iova
 * and @length argument, indicating the current range available through the
 * iova_bitmap. The @dirty_reporter_fn uses iova_bitmap_set() to mark dirty
 * areas (@iova_length) within that provided range, as following:
 *
 *   iova_bitmap_set(bitmap, iova, iova_length);
 *
 * The internals of the object uses an index @mapped_base_index that indexes
 * which u64 word of the bitmap is mapped, up to @mapped_total_index.
 * Those keep being incremented until @mapped_total_index is reached while
 * mapping up to PAGE_SIZE / sizeof(struct page*) maximum of pages.
 *
 * The IOVA bitmap is usually located on what tracks DMA mapped ranges or
 * some form of IOVA range tracking that co-relates to the user passed
 * bitmap.
 */
struct iova_bitmap {};

/*
 * Converts a relative IOVA to a bitmap index.
 * This function provides the index into the u64 array (bitmap::bitmap)
 * for a given IOVA offset.
 * Relative IOVA means relative to the bitmap::mapped base IOVA
 * (stored in mapped::iova). All computations in this file are done using
 * relative IOVAs and thus avoid an extra subtraction against mapped::iova.
 * The user API iova_bitmap_set() always uses a regular absolute IOVAs.
 */
static unsigned long iova_bitmap_offset_to_index(struct iova_bitmap *bitmap,
						 unsigned long iova)
{}

/*
 * Converts a bitmap index to a *relative* IOVA.
 */
static unsigned long iova_bitmap_index_to_offset(struct iova_bitmap *bitmap,
						 unsigned long index)
{}

/*
 * Returns the base IOVA of the mapped range.
 */
static unsigned long iova_bitmap_mapped_iova(struct iova_bitmap *bitmap)
{}

static unsigned long iova_bitmap_mapped_length(struct iova_bitmap *bitmap);

/*
 * Pins the bitmap user pages for the current range window.
 * This is internal to IOVA bitmap and called when advancing the
 * index (@mapped_base_index) or allocating the bitmap.
 */
static int iova_bitmap_get(struct iova_bitmap *bitmap)
{}

/*
 * Unpins the bitmap user pages and clears @npages
 * (un)pinning is abstracted from API user and it's done when advancing
 * the index or freeing the bitmap.
 */
static void iova_bitmap_put(struct iova_bitmap *bitmap)
{}

/**
 * iova_bitmap_alloc() - Allocates an IOVA bitmap object
 * @iova: Start address of the IOVA range
 * @length: Length of the IOVA range
 * @page_size: Page size of the IOVA bitmap. It defines what each bit
 *             granularity represents
 * @data: Userspace address of the bitmap
 *
 * Allocates an IOVA object and initializes all its fields including the
 * first user pages of @data.
 *
 * Return: A pointer to a newly allocated struct iova_bitmap
 * or ERR_PTR() on error.
 */
struct iova_bitmap *iova_bitmap_alloc(unsigned long iova, size_t length,
				      unsigned long page_size, u64 __user *data)
{}
EXPORT_SYMBOL_NS_GPL();

/**
 * iova_bitmap_free() - Frees an IOVA bitmap object
 * @bitmap: IOVA bitmap to free
 *
 * It unpins and releases pages array memory and clears any leftover
 * state.
 */
void iova_bitmap_free(struct iova_bitmap *bitmap)
{}
EXPORT_SYMBOL_NS_GPL();

/*
 * Returns the remaining bitmap indexes from mapped_total_index to process for
 * the currently pinned bitmap pages.
 */
static unsigned long iova_bitmap_mapped_remaining(struct iova_bitmap *bitmap)
{}

/*
 * Returns the length of the mapped IOVA range.
 */
static unsigned long iova_bitmap_mapped_length(struct iova_bitmap *bitmap)
{}

/*
 * Returns true if [@iova..@iova+@length-1] is part of the mapped IOVA range.
 */
static bool iova_bitmap_mapped_range(struct iova_bitmap_map *mapped,
				     unsigned long iova, size_t length)
{}

/*
 * Advances to a selected range, releases the current pinned
 * pages and pins the next set of bitmap pages.
 * Returns 0 on success or otherwise errno.
 */
static int iova_bitmap_advance_to(struct iova_bitmap *bitmap,
				  unsigned long iova)
{}

/**
 * iova_bitmap_for_each() - Iterates over the bitmap
 * @bitmap: IOVA bitmap to iterate
 * @opaque: Additional argument to pass to the callback
 * @fn: Function that gets called for each IOVA range
 *
 * Helper function to iterate over bitmap data representing a portion of IOVA
 * space. It hides the complexity of iterating bitmaps and translating the
 * mapped bitmap user pages into IOVA ranges to process.
 *
 * Return: 0 on success, and an error on failure either upon
 * iteration or when the callback returns an error.
 */
int iova_bitmap_for_each(struct iova_bitmap *bitmap, void *opaque,
			 iova_bitmap_fn_t fn)
{}
EXPORT_SYMBOL_NS_GPL();

/**
 * iova_bitmap_set() - Records an IOVA range in bitmap
 * @bitmap: IOVA bitmap
 * @iova: IOVA to start
 * @length: IOVA range length
 *
 * Set the bits corresponding to the range [iova .. iova+length-1] in
 * the user bitmap.
 *
 */
void iova_bitmap_set(struct iova_bitmap *bitmap,
		     unsigned long iova, size_t length)
{}
EXPORT_SYMBOL_NS_GPL();