| // SPDX-License-Identifier: GPL-2.0 |
| /* Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES. |
| * |
| * The iopt_pages is the center of the storage and motion of PFNs. Each |
| * iopt_pages represents a logical linear array of full PFNs. The array is 0 |
| * based and has npages in it. Accessors use 'index' to refer to the entry in |
| * this logical array, regardless of its storage location. |
| * |
| * PFNs are stored in a tiered scheme: |
| * 1) iopt_pages::pinned_pfns xarray |
| * 2) An iommu_domain |
| * 3) The origin of the PFNs, i.e. the userspace pointer |
| * |
| * PFN have to be copied between all combinations of tiers, depending on the |
| * configuration. |
| * |
| * When a PFN is taken out of the userspace pointer it is pinned exactly once. |
| * The storage locations of the PFN's index are tracked in the two interval |
| * trees. If no interval includes the index then it is not pinned. |
| * |
| * If access_itree includes the PFN's index then an in-kernel access has |
| * requested the page. The PFN is stored in the xarray so other requestors can |
| * continue to find it. |
| * |
| * If the domains_itree includes the PFN's index then an iommu_domain is storing |
| * the PFN and it can be read back using iommu_iova_to_phys(). To avoid |
| * duplicating storage the xarray is not used if only iommu_domains are using |
| * the PFN's index. |
| * |
| * As a general principle this is designed so that destroy never fails. This |
| * means removing an iommu_domain or releasing a in-kernel access will not fail |
| * due to insufficient memory. In practice this means some cases have to hold |
| * PFNs in the xarray even though they are also being stored in an iommu_domain. |
| * |
| * While the iopt_pages can use an iommu_domain as storage, it does not have an |
| * IOVA itself. Instead the iopt_area represents a range of IOVA and uses the |
| * iopt_pages as the PFN provider. Multiple iopt_areas can share the iopt_pages |
| * and reference their own slice of the PFN array, with sub page granularity. |
| * |
| * In this file the term 'last' indicates an inclusive and closed interval, eg |
| * [0,0] refers to a single PFN. 'end' means an open range, eg [0,0) refers to |
| * no PFNs. |
| * |
| * Be cautious of overflow. An IOVA can go all the way up to U64_MAX, so |
| * last_iova + 1 can overflow. An iopt_pages index will always be much less than |
| * ULONG_MAX so last_index + 1 cannot overflow. |
| */ |
| #include <linux/overflow.h> |
| #include <linux/slab.h> |
| #include <linux/iommu.h> |
| #include <linux/sched/mm.h> |
| #include <linux/highmem.h> |
| #include <linux/kthread.h> |
| #include <linux/iommufd.h> |
| |
| #include "io_pagetable.h" |
| #include "double_span.h" |
| |
| #define TEMP_MEMORY_LIMIT 65536 |
| #define BATCH_BACKUP_SIZE 32 |
| |
| /* |
| * More memory makes pin_user_pages() and the batching more efficient, but as |
| * this is only a performance optimization don't try too hard to get it. A 64k |
| * allocation can hold about 26M of 4k pages and 13G of 2M pages in an |
| * pfn_batch. Various destroy paths cannot fail and provide a small amount of |
| * stack memory as a backup contingency. If backup_len is given this cannot |
| * fail. |
| */ |
| static void *temp_kmalloc(size_t *size, void *backup, size_t backup_len) |
| { |
| void *res; |
| |
| if (WARN_ON(*size == 0)) |
| return NULL; |
| |
| if (*size < backup_len) |
| return backup; |
| *size = min_t(size_t, *size, TEMP_MEMORY_LIMIT); |
| res = kmalloc(*size, GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY); |
| if (res) |
| return res; |
| *size = PAGE_SIZE; |
| if (backup_len) { |
| res = kmalloc(*size, GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY); |
| if (res) |
| return res; |
| *size = backup_len; |
| return backup; |
| } |
| return kmalloc(*size, GFP_KERNEL); |
| } |
| |
| void interval_tree_double_span_iter_update( |
| struct interval_tree_double_span_iter *iter) |
| { |
| unsigned long last_hole = ULONG_MAX; |
| unsigned int i; |
| |
| for (i = 0; i != ARRAY_SIZE(iter->spans); i++) { |
| if (interval_tree_span_iter_done(&iter->spans[i])) { |
| iter->is_used = -1; |
| return; |
| } |
| |
| if (iter->spans[i].is_hole) { |
| last_hole = min(last_hole, iter->spans[i].last_hole); |
| continue; |
| } |
| |
| iter->is_used = i + 1; |
| iter->start_used = iter->spans[i].start_used; |
| iter->last_used = min(iter->spans[i].last_used, last_hole); |
| return; |
| } |
| |
| iter->is_used = 0; |
| iter->start_hole = iter->spans[0].start_hole; |
| iter->last_hole = |
| min(iter->spans[0].last_hole, iter->spans[1].last_hole); |
| } |
| |
| void interval_tree_double_span_iter_first( |
| struct interval_tree_double_span_iter *iter, |
| struct rb_root_cached *itree1, struct rb_root_cached *itree2, |
| unsigned long first_index, unsigned long last_index) |
| { |
| unsigned int i; |
| |
| iter->itrees[0] = itree1; |
| iter->itrees[1] = itree2; |
| for (i = 0; i != ARRAY_SIZE(iter->spans); i++) |
| interval_tree_span_iter_first(&iter->spans[i], iter->itrees[i], |
| first_index, last_index); |
| interval_tree_double_span_iter_update(iter); |
| } |
| |
| void interval_tree_double_span_iter_next( |
| struct interval_tree_double_span_iter *iter) |
| { |
| unsigned int i; |
| |
| if (iter->is_used == -1 || |
| iter->last_hole == iter->spans[0].last_index) { |
| iter->is_used = -1; |
| return; |
| } |
| |
| for (i = 0; i != ARRAY_SIZE(iter->spans); i++) |
| interval_tree_span_iter_advance( |
| &iter->spans[i], iter->itrees[i], iter->last_hole + 1); |
| interval_tree_double_span_iter_update(iter); |
| } |
| |
| static void iopt_pages_add_npinned(struct iopt_pages *pages, size_t npages) |
| { |
| pages->npinned += npages; |
| } |
| |
| static void iopt_pages_sub_npinned(struct iopt_pages *pages, size_t npages) |
| { |
| pages->npinned -= npages; |
| } |
| |
| static void iopt_pages_err_unpin(struct iopt_pages *pages, |
| unsigned long start_index, |
| unsigned long last_index, |
| struct page **page_list) |
| { |
| unsigned long npages = last_index - start_index + 1; |
| |
| unpin_user_pages(page_list, npages); |
| iopt_pages_sub_npinned(pages, npages); |
| } |
| |
| /* |
| * index is the number of PAGE_SIZE units from the start of the area's |
| * iopt_pages. If the iova is sub page-size then the area has an iova that |
| * covers a portion of the first and last pages in the range. |
| */ |
| static unsigned long iopt_area_index_to_iova(struct iopt_area *area, |
| unsigned long index) |
| { |
| index -= iopt_area_index(area); |
| if (index == 0) |
| return iopt_area_iova(area); |
| return iopt_area_iova(area) - area->page_offset + index * PAGE_SIZE; |
| } |
| |
| static unsigned long iopt_area_index_to_iova_last(struct iopt_area *area, |
| unsigned long index) |
| { |
| if (index == iopt_area_last_index(area)) |
| return iopt_area_last_iova(area); |
| return iopt_area_iova(area) - area->page_offset + |
| (index - iopt_area_index(area) + 1) * PAGE_SIZE - 1; |
| } |
| |
| static void iommu_unmap_nofail(struct iommu_domain *domain, unsigned long iova, |
| size_t size) |
| { |
| size_t ret; |
| |
| ret = iommu_unmap(domain, iova, size); |
| /* |
| * It is a logic error in this code or a driver bug if the IOMMU unmaps |
| * something other than exactly as requested. This implies that the |
| * iommu driver may not fail unmap for reasons beyond bad agruments. |
| * Particularly, the iommu driver may not do a memory allocation on the |
| * unmap path. |
| */ |
| WARN_ON(ret != size); |
| } |
| |
| static struct iopt_area *iopt_pages_find_domain_area(struct iopt_pages *pages, |
| unsigned long index) |
| { |
| struct interval_tree_node *node; |
| |
| node = interval_tree_iter_first(&pages->domains_itree, index, index); |
| if (!node) |
| return NULL; |
| return container_of(node, struct iopt_area, pages_node); |
| } |
| |
| /* |
| * A simple datastructure to hold a vector of PFNs, optimized for contiguous |
| * PFNs. This is used as a temporary holding memory for shuttling pfns from one |
| * place to another. Generally everything is made more efficient if operations |
| * work on the largest possible grouping of pfns. eg fewer lock/unlock cycles, |
| * better cache locality, etc |
| */ |
| struct pfn_batch { |
| unsigned long *pfns; |
| u32 *npfns; |
| unsigned int array_size; |
| unsigned int end; |
| unsigned int total_pfns; |
| }; |
| |
| static void batch_clear(struct pfn_batch *batch) |
| { |
| batch->total_pfns = 0; |
| batch->end = 0; |
| batch->pfns[0] = 0; |
| batch->npfns[0] = 0; |
| } |
| |
| /* |
| * Carry means we carry a portion of the final hugepage over to the front of the |
| * batch |
| */ |
| static void batch_clear_carry(struct pfn_batch *batch, unsigned int keep_pfns) |
| { |
| if (!keep_pfns) |
| return batch_clear(batch); |
| |
| batch->total_pfns = keep_pfns; |
| batch->npfns[0] = keep_pfns; |
| batch->pfns[0] = batch->pfns[batch->end - 1] + |
| (batch->npfns[batch->end - 1] - keep_pfns); |
| batch->end = 0; |
| } |
| |
| static void batch_skip_carry(struct pfn_batch *batch, unsigned int skip_pfns) |
| { |
| if (!batch->total_pfns) |
| return; |
| skip_pfns = min(batch->total_pfns, skip_pfns); |
| batch->pfns[0] += skip_pfns; |
| batch->npfns[0] -= skip_pfns; |
| batch->total_pfns -= skip_pfns; |
| } |
| |
| static int __batch_init(struct pfn_batch *batch, size_t max_pages, void *backup, |
| size_t backup_len) |
| { |
| const size_t elmsz = sizeof(*batch->pfns) + sizeof(*batch->npfns); |
| size_t size = max_pages * elmsz; |
| |
| batch->pfns = temp_kmalloc(&size, backup, backup_len); |
| if (!batch->pfns) |
| return -ENOMEM; |
| batch->array_size = size / elmsz; |
| batch->npfns = (u32 *)(batch->pfns + batch->array_size); |
| batch_clear(batch); |
| return 0; |
| } |
| |
| static int batch_init(struct pfn_batch *batch, size_t max_pages) |
| { |
| return __batch_init(batch, max_pages, NULL, 0); |
| } |
| |
| static void batch_init_backup(struct pfn_batch *batch, size_t max_pages, |
| void *backup, size_t backup_len) |
| { |
| __batch_init(batch, max_pages, backup, backup_len); |
| } |
| |
| static void batch_destroy(struct pfn_batch *batch, void *backup) |
| { |
| if (batch->pfns != backup) |
| kfree(batch->pfns); |
| } |
| |
| /* true if the pfn could be added, false otherwise */ |
| static bool batch_add_pfn(struct pfn_batch *batch, unsigned long pfn) |
| { |
| const unsigned int MAX_NPFNS = type_max(typeof(*batch->npfns)); |
| |
| if (batch->end && |
| pfn == batch->pfns[batch->end - 1] + batch->npfns[batch->end - 1] && |
| batch->npfns[batch->end - 1] != MAX_NPFNS) { |
| batch->npfns[batch->end - 1]++; |
| batch->total_pfns++; |
| return true; |
| } |
| if (batch->end == batch->array_size) |
| return false; |
| batch->total_pfns++; |
| batch->pfns[batch->end] = pfn; |
| batch->npfns[batch->end] = 1; |
| batch->end++; |
| return true; |
| } |
| |
| /* |
| * Fill the batch with pfns from the domain. When the batch is full, or it |
| * reaches last_index, the function will return. The caller should use |
| * batch->total_pfns to determine the starting point for the next iteration. |
| */ |
| static void batch_from_domain(struct pfn_batch *batch, |
| struct iommu_domain *domain, |
| struct iopt_area *area, unsigned long start_index, |
| unsigned long last_index) |
| { |
| unsigned int page_offset = 0; |
| unsigned long iova; |
| phys_addr_t phys; |
| |
| iova = iopt_area_index_to_iova(area, start_index); |
| if (start_index == iopt_area_index(area)) |
| page_offset = area->page_offset; |
| while (start_index <= last_index) { |
| /* |
| * This is pretty slow, it would be nice to get the page size |
| * back from the driver, or have the driver directly fill the |
| * batch. |
| */ |
| phys = iommu_iova_to_phys(domain, iova) - page_offset; |
| if (!batch_add_pfn(batch, PHYS_PFN(phys))) |
| return; |
| iova += PAGE_SIZE - page_offset; |
| page_offset = 0; |
| start_index++; |
| } |
| } |
| |
| static struct page **raw_pages_from_domain(struct iommu_domain *domain, |
| struct iopt_area *area, |
| unsigned long start_index, |
| unsigned long last_index, |
| struct page **out_pages) |
| { |
| unsigned int page_offset = 0; |
| unsigned long iova; |
| phys_addr_t phys; |
| |
| iova = iopt_area_index_to_iova(area, start_index); |
| if (start_index == iopt_area_index(area)) |
| page_offset = area->page_offset; |
| while (start_index <= last_index) { |
| phys = iommu_iova_to_phys(domain, iova) - page_offset; |
| *(out_pages++) = pfn_to_page(PHYS_PFN(phys)); |
| iova += PAGE_SIZE - page_offset; |
| page_offset = 0; |
| start_index++; |
| } |
| return out_pages; |
| } |
| |
| /* Continues reading a domain until we reach a discontiguity in the pfns. */ |
| static void batch_from_domain_continue(struct pfn_batch *batch, |
| struct iommu_domain *domain, |
| struct iopt_area *area, |
| unsigned long start_index, |
| unsigned long last_index) |
| { |
| unsigned int array_size = batch->array_size; |
| |
| batch->array_size = batch->end; |
| batch_from_domain(batch, domain, area, start_index, last_index); |
| batch->array_size = array_size; |
| } |
| |
| /* |
| * This is part of the VFIO compatibility support for VFIO_TYPE1_IOMMU. That |
| * mode permits splitting a mapped area up, and then one of the splits is |
| * unmapped. Doing this normally would cause us to violate our invariant of |
| * pairing map/unmap. Thus, to support old VFIO compatibility disable support |
| * for batching consecutive PFNs. All PFNs mapped into the iommu are done in |
| * PAGE_SIZE units, not larger or smaller. |
| */ |
| static int batch_iommu_map_small(struct iommu_domain *domain, |
| unsigned long iova, phys_addr_t paddr, |
| size_t size, int prot) |
| { |
| unsigned long start_iova = iova; |
| int rc; |
| |
| while (size) { |
| rc = iommu_map(domain, iova, paddr, PAGE_SIZE, prot); |
| if (rc) |
| goto err_unmap; |
| iova += PAGE_SIZE; |
| paddr += PAGE_SIZE; |
| size -= PAGE_SIZE; |
| } |
| return 0; |
| |
| err_unmap: |
| if (start_iova != iova) |
| iommu_unmap_nofail(domain, start_iova, iova - start_iova); |
| return rc; |
| } |
| |
| static int batch_to_domain(struct pfn_batch *batch, struct iommu_domain *domain, |
| struct iopt_area *area, unsigned long start_index) |
| { |
| bool disable_large_pages = area->iopt->disable_large_pages; |
| unsigned long last_iova = iopt_area_last_iova(area); |
| unsigned int page_offset = 0; |
| unsigned long start_iova; |
| unsigned long next_iova; |
| unsigned int cur = 0; |
| unsigned long iova; |
| int rc; |
| |
| /* The first index might be a partial page */ |
| if (start_index == iopt_area_index(area)) |
| page_offset = area->page_offset; |
| next_iova = iova = start_iova = |
| iopt_area_index_to_iova(area, start_index); |
| while (cur < batch->end) { |
| next_iova = min(last_iova + 1, |
| next_iova + batch->npfns[cur] * PAGE_SIZE - |
| page_offset); |
| if (disable_large_pages) |
| rc = batch_iommu_map_small( |
| domain, iova, |
| PFN_PHYS(batch->pfns[cur]) + page_offset, |
| next_iova - iova, area->iommu_prot); |
| else |
| rc = iommu_map(domain, iova, |
| PFN_PHYS(batch->pfns[cur]) + page_offset, |
| next_iova - iova, area->iommu_prot); |
| if (rc) |
| goto err_unmap; |
| iova = next_iova; |
| page_offset = 0; |
| cur++; |
| } |
| return 0; |
| err_unmap: |
| if (start_iova != iova) |
| iommu_unmap_nofail(domain, start_iova, iova - start_iova); |
| return rc; |
| } |
| |
| static void batch_from_xarray(struct pfn_batch *batch, struct xarray *xa, |
| unsigned long start_index, |
| unsigned long last_index) |
| { |
| XA_STATE(xas, xa, start_index); |
| void *entry; |
| |
| rcu_read_lock(); |
| while (true) { |
| entry = xas_next(&xas); |
| if (xas_retry(&xas, entry)) |
| continue; |
| WARN_ON(!xa_is_value(entry)); |
| if (!batch_add_pfn(batch, xa_to_value(entry)) || |
| start_index == last_index) |
| break; |
| start_index++; |
| } |
| rcu_read_unlock(); |
| } |
| |
| static void batch_from_xarray_clear(struct pfn_batch *batch, struct xarray *xa, |
| unsigned long start_index, |
| unsigned long last_index) |
| { |
| XA_STATE(xas, xa, start_index); |
| void *entry; |
| |
| xas_lock(&xas); |
| while (true) { |
| entry = xas_next(&xas); |
| if (xas_retry(&xas, entry)) |
| continue; |
| WARN_ON(!xa_is_value(entry)); |
| if (!batch_add_pfn(batch, xa_to_value(entry))) |
| break; |
| xas_store(&xas, NULL); |
| if (start_index == last_index) |
| break; |
| start_index++; |
| } |
| xas_unlock(&xas); |
| } |
| |
| static void clear_xarray(struct xarray *xa, unsigned long start_index, |
| unsigned long last_index) |
| { |
| XA_STATE(xas, xa, start_index); |
| void *entry; |
| |
| xas_lock(&xas); |
| xas_for_each(&xas, entry, last_index) |
| xas_store(&xas, NULL); |
| xas_unlock(&xas); |
| } |
| |
| static int pages_to_xarray(struct xarray *xa, unsigned long start_index, |
| unsigned long last_index, struct page **pages) |
| { |
| struct page **end_pages = pages + (last_index - start_index) + 1; |
| XA_STATE(xas, xa, start_index); |
| |
| do { |
| void *old; |
| |
| xas_lock(&xas); |
| while (pages != end_pages) { |
| old = xas_store(&xas, xa_mk_value(page_to_pfn(*pages))); |
| if (xas_error(&xas)) |
| break; |
| WARN_ON(old); |
| pages++; |
| xas_next(&xas); |
| } |
| xas_unlock(&xas); |
| } while (xas_nomem(&xas, GFP_KERNEL)); |
| |
| if (xas_error(&xas)) { |
| if (xas.xa_index != start_index) |
| clear_xarray(xa, start_index, xas.xa_index - 1); |
| return xas_error(&xas); |
| } |
| return 0; |
| } |
| |
| static void batch_from_pages(struct pfn_batch *batch, struct page **pages, |
| size_t npages) |
| { |
| struct page **end = pages + npages; |
| |
| for (; pages != end; pages++) |
| if (!batch_add_pfn(batch, page_to_pfn(*pages))) |
| break; |
| } |
| |
| static void batch_unpin(struct pfn_batch *batch, struct iopt_pages *pages, |
| unsigned int first_page_off, size_t npages) |
| { |
| unsigned int cur = 0; |
| |
| while (first_page_off) { |
| if (batch->npfns[cur] > first_page_off) |
| break; |
| first_page_off -= batch->npfns[cur]; |
| cur++; |
| } |
| |
| while (npages) { |
| size_t to_unpin = min_t(size_t, npages, |
| batch->npfns[cur] - first_page_off); |
| |
| unpin_user_page_range_dirty_lock( |
| pfn_to_page(batch->pfns[cur] + first_page_off), |
| to_unpin, pages->writable); |
| iopt_pages_sub_npinned(pages, to_unpin); |
| cur++; |
| first_page_off = 0; |
| npages -= to_unpin; |
| } |
| } |
| |
| static void copy_data_page(struct page *page, void *data, unsigned long offset, |
| size_t length, unsigned int flags) |
| { |
| void *mem; |
| |
| mem = kmap_local_page(page); |
| if (flags & IOMMUFD_ACCESS_RW_WRITE) { |
| memcpy(mem + offset, data, length); |
| set_page_dirty_lock(page); |
| } else { |
| memcpy(data, mem + offset, length); |
| } |
| kunmap_local(mem); |
| } |
| |
| static unsigned long batch_rw(struct pfn_batch *batch, void *data, |
| unsigned long offset, unsigned long length, |
| unsigned int flags) |
| { |
| unsigned long copied = 0; |
| unsigned int npage = 0; |
| unsigned int cur = 0; |
| |
| while (cur < batch->end) { |
| unsigned long bytes = min(length, PAGE_SIZE - offset); |
| |
| copy_data_page(pfn_to_page(batch->pfns[cur] + npage), data, |
| offset, bytes, flags); |
| offset = 0; |
| length -= bytes; |
| data += bytes; |
| copied += bytes; |
| npage++; |
| if (npage == batch->npfns[cur]) { |
| npage = 0; |
| cur++; |
| } |
| if (!length) |
| break; |
| } |
| return copied; |
| } |
| |
| /* pfn_reader_user is just the pin_user_pages() path */ |
| struct pfn_reader_user { |
| struct page **upages; |
| size_t upages_len; |
| unsigned long upages_start; |
| unsigned long upages_end; |
| unsigned int gup_flags; |
| /* |
| * 1 means mmget() and mmap_read_lock(), 0 means only mmget(), -1 is |
| * neither |
| */ |
| int locked; |
| }; |
| |
| static void pfn_reader_user_init(struct pfn_reader_user *user, |
| struct iopt_pages *pages) |
| { |
| user->upages = NULL; |
| user->upages_start = 0; |
| user->upages_end = 0; |
| user->locked = -1; |
| |
| if (pages->writable) { |
| user->gup_flags = FOLL_LONGTERM | FOLL_WRITE; |
| } else { |
| /* Still need to break COWs on read */ |
| user->gup_flags = FOLL_LONGTERM | FOLL_FORCE | FOLL_WRITE; |
| } |
| } |
| |
| static void pfn_reader_user_destroy(struct pfn_reader_user *user, |
| struct iopt_pages *pages) |
| { |
| if (user->locked != -1) { |
| if (user->locked) |
| mmap_read_unlock(pages->source_mm); |
| if (pages->source_mm != current->mm) |
| mmput(pages->source_mm); |
| user->locked = 0; |
| } |
| |
| kfree(user->upages); |
| user->upages = NULL; |
| } |
| |
| static int pfn_reader_user_pin(struct pfn_reader_user *user, |
| struct iopt_pages *pages, |
| unsigned long start_index, |
| unsigned long last_index) |
| { |
| bool remote_mm = pages->source_mm != current->mm; |
| unsigned long npages; |
| uintptr_t uptr; |
| long rc; |
| |
| if (!user->upages) { |
| /* All undone in pfn_reader_destroy() */ |
| user->upages_len = |
| (last_index - start_index + 1) * sizeof(*user->upages); |
| user->upages = temp_kmalloc(&user->upages_len, NULL, 0); |
| if (!user->upages) |
| return -ENOMEM; |
| } |
| |
| if (user->locked == -1) { |
| /* |
| * The majority of usages will run the map task within the mm |
| * providing the pages, so we can optimize into |
| * get_user_pages_fast() |
| */ |
| if (remote_mm) { |
| if (!mmget_not_zero(pages->source_mm)) |
| return -EFAULT; |
| } |
| user->locked = 0; |
| } |
| |
| npages = min_t(unsigned long, last_index - start_index + 1, |
| user->upages_len / sizeof(*user->upages)); |
| |
| uptr = (uintptr_t)(pages->uptr + start_index * PAGE_SIZE); |
| if (!remote_mm) |
| rc = pin_user_pages_fast(uptr, npages, user->gup_flags, |
| user->upages); |
| else { |
| if (!user->locked) { |
| mmap_read_lock(pages->source_mm); |
| user->locked = 1; |
| } |
| /* |
| * FIXME: last NULL can be &pfns->locked once the GUP patch |
| * is merged. |
| */ |
| rc = pin_user_pages_remote(pages->source_mm, uptr, npages, |
| user->gup_flags, user->upages, NULL, |
| NULL); |
| } |
| if (rc <= 0) { |
| if (WARN_ON(!rc)) |
| return -EFAULT; |
| return rc; |
| } |
| iopt_pages_add_npinned(pages, rc); |
| user->upages_start = start_index; |
| user->upages_end = start_index + rc; |
| return 0; |
| } |
| |
| /* This is the "modern" and faster accounting method used by io_uring */ |
| static int incr_user_locked_vm(struct iopt_pages *pages, unsigned long npages) |
| { |
| unsigned long lock_limit; |
| unsigned long cur_pages; |
| unsigned long new_pages; |
| |
| lock_limit = task_rlimit(pages->source_task, RLIMIT_MEMLOCK) >> |
| PAGE_SHIFT; |
| npages = pages->npinned - pages->last_npinned; |
| do { |
| cur_pages = atomic_long_read(&pages->source_user->locked_vm); |
| new_pages = cur_pages + npages; |
| if (new_pages > lock_limit) |
| return -ENOMEM; |
| } while (atomic_long_cmpxchg(&pages->source_user->locked_vm, cur_pages, |
| new_pages) != cur_pages); |
| return 0; |
| } |
| |
| static void decr_user_locked_vm(struct iopt_pages *pages, unsigned long npages) |
| { |
| if (WARN_ON(atomic_long_read(&pages->source_user->locked_vm) < npages)) |
| return; |
| atomic_long_sub(npages, &pages->source_user->locked_vm); |
| } |
| |
| /* This is the accounting method used for compatibility with VFIO */ |
| static int update_mm_locked_vm(struct iopt_pages *pages, unsigned long npages, |
| bool inc, struct pfn_reader_user *user) |
| { |
| bool do_put = false; |
| int rc; |
| |
| if (user && user->locked) { |
| mmap_read_unlock(pages->source_mm); |
| user->locked = 0; |
| /* If we had the lock then we also have a get */ |
| } else if ((!user || !user->upages) && |
| pages->source_mm != current->mm) { |
| if (!mmget_not_zero(pages->source_mm)) |
| return -EINVAL; |
| do_put = true; |
| } |
| |
| mmap_write_lock(pages->source_mm); |
| rc = __account_locked_vm(pages->source_mm, npages, inc, |
| pages->source_task, false); |
| mmap_write_unlock(pages->source_mm); |
| |
| if (do_put) |
| mmput(pages->source_mm); |
| return rc; |
| } |
| |
| static int do_update_pinned(struct iopt_pages *pages, unsigned long npages, |
| bool inc, struct pfn_reader_user *user) |
| { |
| int rc = 0; |
| |
| switch (pages->account_mode) { |
| case IOPT_PAGES_ACCOUNT_NONE: |
| break; |
| case IOPT_PAGES_ACCOUNT_USER: |
| if (inc) |
| rc = incr_user_locked_vm(pages, npages); |
| else |
| decr_user_locked_vm(pages, npages); |
| break; |
| case IOPT_PAGES_ACCOUNT_MM: |
| rc = update_mm_locked_vm(pages, npages, inc, user); |
| break; |
| } |
| if (rc) |
| return rc; |
| |
| pages->last_npinned = pages->npinned; |
| if (inc) |
| atomic64_add(npages, &pages->source_mm->pinned_vm); |
| else |
| atomic64_sub(npages, &pages->source_mm->pinned_vm); |
| return 0; |
| } |
| |
| static void update_unpinned(struct iopt_pages *pages) |
| { |
| if (WARN_ON(pages->npinned > pages->last_npinned)) |
| return; |
| if (pages->npinned == pages->last_npinned) |
| return; |
| do_update_pinned(pages, pages->last_npinned - pages->npinned, false, |
| NULL); |
| } |
| |
| /* |
| * Changes in the number of pages pinned is done after the pages have been read |
| * and processed. If the user lacked the limit then the error unwind will unpin |
| * everything that was just pinned. This is because it is expensive to calculate |
| * how many pages we have already pinned within a range to generate an accurate |
| * prediction in advance of doing the work to actually pin them. |
| */ |
| static int pfn_reader_user_update_pinned(struct pfn_reader_user *user, |
| struct iopt_pages *pages) |
| { |
| unsigned long npages; |
| bool inc; |
| |
| lockdep_assert_held(&pages->mutex); |
| |
| if (pages->npinned == pages->last_npinned) |
| return 0; |
| |
| if (pages->npinned < pages->last_npinned) { |
| npages = pages->last_npinned - pages->npinned; |
| inc = false; |
| } else { |
| npages = pages->npinned - pages->last_npinned; |
| inc = true; |
| } |
| return do_update_pinned(pages, npages, inc, user); |
| } |
| |
| /* |
| * PFNs are stored in three places, in order of preference: |
| * - The iopt_pages xarray. This is only populated if there is a |
| * iopt_pages_access |
| * - The iommu_domain under an area |
| * - The original PFN source, ie pages->source_mm |
| * |
| * This iterator reads the pfns optimizing to load according to the |
| * above order. |
| */ |
| struct pfn_reader { |
| struct iopt_pages *pages; |
| struct interval_tree_double_span_iter span; |
| struct pfn_batch batch; |
| unsigned long batch_start_index; |
| unsigned long batch_end_index; |
| unsigned long last_index; |
| |
| struct pfn_reader_user user; |
| }; |
| |
| static int pfn_reader_update_pinned(struct pfn_reader *pfns) |
| { |
| return pfn_reader_user_update_pinned(&pfns->user, pfns->pages); |
| } |
| |
| /* |
| * The batch can contain a mixture of pages that are still in use and pages that |
| * need to be unpinned. Unpin only pages that are not held anywhere else. |
| */ |
| static void pfn_reader_unpin(struct pfn_reader *pfns) |
| { |
| unsigned long last = pfns->batch_end_index - 1; |
| unsigned long start = pfns->batch_start_index; |
| struct interval_tree_double_span_iter span; |
| struct iopt_pages *pages = pfns->pages; |
| |
| lockdep_assert_held(&pages->mutex); |
| |
| interval_tree_for_each_double_span(&span, &pages->access_itree, |
| &pages->domains_itree, start, last) { |
| if (span.is_used) |
| continue; |
| |
| batch_unpin(&pfns->batch, pages, span.start_hole - start, |
| span.last_hole - span.start_hole + 1); |
| } |
| } |
| |
| /* Process a single span to load it from the proper storage */ |
| static int pfn_reader_fill_span(struct pfn_reader *pfns) |
| { |
| struct interval_tree_double_span_iter *span = &pfns->span; |
| unsigned long start_index = pfns->batch_end_index; |
| struct iopt_area *area; |
| int rc; |
| |
| if (span->is_used == 1) { |
| batch_from_xarray(&pfns->batch, &pfns->pages->pinned_pfns, |
| start_index, span->last_used); |
| return 0; |
| } |
| |
| if (span->is_used == 2) { |
| /* |
| * Pull as many pages from the first domain we find in the |
| * target span. If it is too small then we will be called again |
| * and we'll find another area. |
| */ |
| area = iopt_pages_find_domain_area(pfns->pages, start_index); |
| if (WARN_ON(!area)) |
| return -EINVAL; |
| |
| /* The storage_domain cannot change without the pages mutex */ |
| batch_from_domain( |
| &pfns->batch, area->storage_domain, area, start_index, |
| min(iopt_area_last_index(area), span->last_used)); |
| return 0; |
| } |
| |
| if (start_index >= pfns->user.upages_end) { |
| rc = pfn_reader_user_pin(&pfns->user, pfns->pages, start_index, |
| span->last_hole); |
| if (rc) |
| return rc; |
| } |
| |
| batch_from_pages(&pfns->batch, |
| pfns->user.upages + |
| (start_index - pfns->user.upages_start), |
| pfns->user.upages_end - start_index); |
| return 0; |
| } |
| |
| static bool pfn_reader_done(struct pfn_reader *pfns) |
| { |
| return pfns->batch_start_index == pfns->last_index + 1; |
| } |
| |
| static int pfn_reader_next(struct pfn_reader *pfns) |
| { |
| int rc; |
| |
| batch_clear(&pfns->batch); |
| pfns->batch_start_index = pfns->batch_end_index; |
| |
| while (pfns->batch_end_index != pfns->last_index + 1) { |
| unsigned int npfns = pfns->batch.total_pfns; |
| |
| rc = pfn_reader_fill_span(pfns); |
| if (rc) |
| return rc; |
| |
| if (WARN_ON(!pfns->batch.total_pfns)) |
| return -EINVAL; |
| |
| pfns->batch_end_index = |
| pfns->batch_start_index + pfns->batch.total_pfns; |
| if (pfns->batch_end_index == pfns->span.last_used + 1) |
| interval_tree_double_span_iter_next(&pfns->span); |
| |
| /* Batch is full */ |
| if (npfns == pfns->batch.total_pfns) |
| return 0; |
| } |
| return 0; |
| } |
| |
| static int pfn_reader_init(struct pfn_reader *pfns, struct iopt_pages *pages, |
| unsigned long start_index, unsigned long last_index) |
| { |
| int rc; |
| |
| lockdep_assert_held(&pages->mutex); |
| |
| pfns->pages = pages; |
| pfns->batch_start_index = start_index; |
| pfns->batch_end_index = start_index; |
| pfns->last_index = last_index; |
| pfn_reader_user_init(&pfns->user, pages); |
| rc = batch_init(&pfns->batch, last_index - start_index + 1); |
| if (rc) |
| return rc; |
| interval_tree_double_span_iter_first(&pfns->span, &pages->access_itree, |
| &pages->domains_itree, start_index, |
| last_index); |
| return 0; |
| } |
| |
| /* |
| * There are many assertions regarding the state of pages->npinned vs |
| * pages->last_pinned, for instance something like unmapping a domain must only |
| * decrement the npinned, and pfn_reader_destroy() must be called only after all |
| * the pins are updated. This is fine for success flows, but error flows |
| * sometimes need to release the pins held inside the pfn_reader before going on |
| * to complete unmapping and releasing pins held in domains. |
| */ |
| static void pfn_reader_release_pins(struct pfn_reader *pfns) |
| { |
| struct iopt_pages *pages = pfns->pages; |
| |
| if (pfns->user.upages_end > pfns->batch_end_index) { |
| size_t npages = pfns->user.upages_end - pfns->batch_end_index; |
| |
| /* Any pages not transferred to the batch are just unpinned */ |
| unpin_user_pages(pfns->user.upages + (pfns->batch_end_index - |
| pfns->user.upages_start), |
| npages); |
| iopt_pages_sub_npinned(pages, npages); |
| pfns->user.upages_end = pfns->batch_end_index; |
| } |
| if (pfns->batch_start_index != pfns->batch_end_index) { |
| pfn_reader_unpin(pfns); |
| pfns->batch_start_index = pfns->batch_end_index; |
| } |
| } |
| |
| static void pfn_reader_destroy(struct pfn_reader *pfns) |
| { |
| struct iopt_pages *pages = pfns->pages; |
| |
| pfn_reader_release_pins(pfns); |
| pfn_reader_user_destroy(&pfns->user, pfns->pages); |
| batch_destroy(&pfns->batch, NULL); |
| WARN_ON(pages->last_npinned != pages->npinned); |
| } |
| |
| static int pfn_reader_first(struct pfn_reader *pfns, struct iopt_pages *pages, |
| unsigned long start_index, unsigned long last_index) |
| { |
| int rc; |
| |
| rc = pfn_reader_init(pfns, pages, start_index, last_index); |
| if (rc) |
| return rc; |
| rc = pfn_reader_next(pfns); |
| if (rc) { |
| pfn_reader_destroy(pfns); |
| return rc; |
| } |
| return 0; |
| } |