162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci
362306a36Sopenharmony_ci#include <linux/mm.h>
462306a36Sopenharmony_ci#include <linux/io-mapping.h>
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci/**
762306a36Sopenharmony_ci * io_mapping_map_user - remap an I/O mapping to userspace
862306a36Sopenharmony_ci * @iomap: the source io_mapping
962306a36Sopenharmony_ci * @vma: user vma to map to
1062306a36Sopenharmony_ci * @addr: target user address to start at
1162306a36Sopenharmony_ci * @pfn: physical address of kernel memory
1262306a36Sopenharmony_ci * @size: size of map area
1362306a36Sopenharmony_ci *
1462306a36Sopenharmony_ci *  Note: this is only safe if the mm semaphore is held when called.
1562306a36Sopenharmony_ci */
1662306a36Sopenharmony_ciint io_mapping_map_user(struct io_mapping *iomap, struct vm_area_struct *vma,
1762306a36Sopenharmony_ci		unsigned long addr, unsigned long pfn, unsigned long size)
1862306a36Sopenharmony_ci{
1962306a36Sopenharmony_ci	vm_flags_t expected_flags = VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP;
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci	if (WARN_ON_ONCE((vma->vm_flags & expected_flags) != expected_flags))
2262306a36Sopenharmony_ci		return -EINVAL;
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci	/* We rely on prevalidation of the io-mapping to skip track_pfn(). */
2562306a36Sopenharmony_ci	return remap_pfn_range_notrack(vma, addr, pfn, size,
2662306a36Sopenharmony_ci		__pgprot((pgprot_val(iomap->prot) & _PAGE_CACHE_MASK) |
2762306a36Sopenharmony_ci			 (pgprot_val(vma->vm_page_prot) & ~_PAGE_CACHE_MASK)));
2862306a36Sopenharmony_ci}
2962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(io_mapping_map_user);
30