xref: /linux/mm/io-mapping.c (revision 8be98d2f2a0a262f8bf8a0bc1fdf522b3c7aab17)
1*1fbaf8fcSChristoph Hellwig // SPDX-License-Identifier: GPL-2.0-only
2*1fbaf8fcSChristoph Hellwig 
3*1fbaf8fcSChristoph Hellwig #include <linux/mm.h>
4*1fbaf8fcSChristoph Hellwig #include <linux/io-mapping.h>
5*1fbaf8fcSChristoph Hellwig 
6*1fbaf8fcSChristoph Hellwig /**
7*1fbaf8fcSChristoph Hellwig  * io_mapping_map_user - remap an I/O mapping to userspace
8*1fbaf8fcSChristoph Hellwig  * @iomap: the source io_mapping
9*1fbaf8fcSChristoph Hellwig  * @vma: user vma to map to
10*1fbaf8fcSChristoph Hellwig  * @addr: target user address to start at
11*1fbaf8fcSChristoph Hellwig  * @pfn: physical address of kernel memory
12*1fbaf8fcSChristoph Hellwig  * @size: size of map area
13*1fbaf8fcSChristoph Hellwig  *
14*1fbaf8fcSChristoph Hellwig  *  Note: this is only safe if the mm semaphore is held when called.
15*1fbaf8fcSChristoph Hellwig  */
io_mapping_map_user(struct io_mapping * iomap,struct vm_area_struct * vma,unsigned long addr,unsigned long pfn,unsigned long size)16*1fbaf8fcSChristoph Hellwig int io_mapping_map_user(struct io_mapping *iomap, struct vm_area_struct *vma,
17*1fbaf8fcSChristoph Hellwig 		unsigned long addr, unsigned long pfn, unsigned long size)
18*1fbaf8fcSChristoph Hellwig {
19*1fbaf8fcSChristoph Hellwig 	vm_flags_t expected_flags = VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP;
20*1fbaf8fcSChristoph Hellwig 
21*1fbaf8fcSChristoph Hellwig 	if (WARN_ON_ONCE((vma->vm_flags & expected_flags) != expected_flags))
22*1fbaf8fcSChristoph Hellwig 		return -EINVAL;
23*1fbaf8fcSChristoph Hellwig 
24*1fbaf8fcSChristoph Hellwig 	/* We rely on prevalidation of the io-mapping to skip track_pfn(). */
25*1fbaf8fcSChristoph Hellwig 	return remap_pfn_range_notrack(vma, addr, pfn, size,
26*1fbaf8fcSChristoph Hellwig 		__pgprot((pgprot_val(iomap->prot) & _PAGE_CACHE_MASK) |
27*1fbaf8fcSChristoph Hellwig 			 (pgprot_val(vma->vm_page_prot) & ~_PAGE_CACHE_MASK)));
28*1fbaf8fcSChristoph Hellwig }
29*1fbaf8fcSChristoph Hellwig EXPORT_SYMBOL_GPL(io_mapping_map_user);
30