Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'topic/iomem-mmap-vs-gup-2021-02-22' of git://anongit.freedesktop.org/drm/drm

Pull follow_pfn() updates from Daniel Vetter:
"Fixes around VM_FPNMAP and follow_pfn:

- replace mm/frame_vector.c by get_user_pages in misc/habana and
drm/exynos drivers, then move that into media as it's sole user

- close race in generic_access_phys

- s390 pci ioctl fix of this series landed in 5.11 already

- properly revoke iomem mappings (/dev/mem, pci files)"

* tag 'topic/iomem-mmap-vs-gup-2021-02-22' of git://anongit.freedesktop.org/drm/drm:
PCI: Revoke mappings like devmem
PCI: Also set up legacy files only after sysfs init
sysfs: Support zapping of binary attr mmaps
resource: Move devmem revoke code to resource framework
/dev/mem: Only set filp->f_mapping
PCI: Obey iomem restrictions for procfs mmap
mm: Close race in generic_access_phys
media: videobuf2: Move frame_vector into media subsystem
mm/frame-vector: Use FOLL_LONGTERM
misc/habana: Use FOLL_LONGTERM for userptr
misc/habana: Stop using frame_vector helpers
drm/exynos: Use FOLL_LONGTERM for g2d cmdlists
drm/exynos: Stop using frame_vector helpers

+287 -245
+1 -85
drivers/char/mem.c
··· 31 31 #include <linux/uio.h> 32 32 #include <linux/uaccess.h> 33 33 #include <linux/security.h> 34 - #include <linux/pseudo_fs.h> 35 - #include <uapi/linux/magic.h> 36 - #include <linux/mount.h> 37 34 38 35 #ifdef CONFIG_IA64 39 36 # include <linux/efi.h> ··· 826 829 return ret; 827 830 } 828 831 829 - static struct inode *devmem_inode; 830 - 831 - #ifdef CONFIG_IO_STRICT_DEVMEM 832 - void revoke_devmem(struct resource *res) 833 - { 834 - /* pairs with smp_store_release() in devmem_init_inode() */ 835 - struct inode *inode = smp_load_acquire(&devmem_inode); 836 - 837 - /* 838 - * Check that the initialization has completed. Losing the race 839 - * is ok because it means drivers are claiming resources before 840 - * the fs_initcall level of init and prevent /dev/mem from 841 - * establishing mappings. 842 - */ 843 - if (!inode) 844 - return; 845 - 846 - /* 847 - * The expectation is that the driver has successfully marked 848 - * the resource busy by this point, so devmem_is_allowed() 849 - * should start returning false, however for performance this 850 - * does not iterate the entire resource range. 851 - */ 852 - if (devmem_is_allowed(PHYS_PFN(res->start)) && 853 - devmem_is_allowed(PHYS_PFN(res->end))) { 854 - /* 855 - * *cringe* iomem=relaxed says "go ahead, what's the 856 - * worst that can happen?" 857 - */ 858 - return; 859 - } 860 - 861 - unmap_mapping_range(inode->i_mapping, res->start, resource_size(res), 1); 862 - } 863 - #endif 864 - 865 832 static int open_port(struct inode *inode, struct file *filp) 866 833 { 867 834 int rc; ··· 845 884 * revocations when drivers want to take over a /dev/mem mapped 846 885 * range. 847 886 */ 848 - inode->i_mapping = devmem_inode->i_mapping; 849 - filp->f_mapping = inode->i_mapping; 887 + filp->f_mapping = iomem_get_mapping(); 850 888 851 889 return 0; 852 890 } ··· 977 1017 978 1018 static struct class *mem_class; 979 1019 980 - static int devmem_fs_init_fs_context(struct fs_context *fc) 981 - { 982 - return init_pseudo(fc, DEVMEM_MAGIC) ? 0 : -ENOMEM; 983 - } 984 - 985 - static struct file_system_type devmem_fs_type = { 986 - .name = "devmem", 987 - .owner = THIS_MODULE, 988 - .init_fs_context = devmem_fs_init_fs_context, 989 - .kill_sb = kill_anon_super, 990 - }; 991 - 992 - static int devmem_init_inode(void) 993 - { 994 - static struct vfsmount *devmem_vfs_mount; 995 - static int devmem_fs_cnt; 996 - struct inode *inode; 997 - int rc; 998 - 999 - rc = simple_pin_fs(&devmem_fs_type, &devmem_vfs_mount, &devmem_fs_cnt); 1000 - if (rc < 0) { 1001 - pr_err("Cannot mount /dev/mem pseudo filesystem: %d\n", rc); 1002 - return rc; 1003 - } 1004 - 1005 - inode = alloc_anon_inode(devmem_vfs_mount->mnt_sb); 1006 - if (IS_ERR(inode)) { 1007 - rc = PTR_ERR(inode); 1008 - pr_err("Cannot allocate inode for /dev/mem: %d\n", rc); 1009 - simple_release_fs(&devmem_vfs_mount, &devmem_fs_cnt); 1010 - return rc; 1011 - } 1012 - 1013 - /* 1014 - * Publish /dev/mem initialized. 1015 - * Pairs with smp_load_acquire() in revoke_devmem(). 1016 - */ 1017 - smp_store_release(&devmem_inode, inode); 1018 - 1019 - return 0; 1020 - } 1021 - 1022 1020 static int __init chr_dev_init(void) 1023 1021 { 1024 1022 int minor; ··· 997 1079 * Create /dev/port? 998 1080 */ 999 1081 if ((minor == DEVPORT_MINOR) && !arch_has_dev_port()) 1000 - continue; 1001 - if ((minor == DEVMEM_MINOR) && devmem_init_inode() != 0) 1002 1082 continue; 1003 1083 1004 1084 device_create(mem_class, NULL, MKDEV(MEM_MAJOR, minor),
-1
drivers/gpu/drm/exynos/Kconfig
··· 89 89 config DRM_EXYNOS_G2D 90 90 bool "G2D" 91 91 depends on VIDEO_SAMSUNG_S5P_G2D=n || COMPILE_TEST 92 - select FRAME_VECTOR 93 92 help 94 93 Choose this option if you want to use Exynos G2D for DRM. 95 94
+21 -27
drivers/gpu/drm/exynos/exynos_drm_g2d.c
··· 205 205 dma_addr_t dma_addr; 206 206 unsigned long userptr; 207 207 unsigned long size; 208 - struct frame_vector *vec; 208 + struct page **pages; 209 + unsigned int npages; 209 210 struct sg_table *sgt; 210 211 atomic_t refcount; 211 212 bool in_pool; ··· 379 378 bool force) 380 379 { 381 380 struct g2d_cmdlist_userptr *g2d_userptr = obj; 382 - struct page **pages; 383 381 384 382 if (!obj) 385 383 return; ··· 398 398 dma_unmap_sgtable(to_dma_dev(g2d->drm_dev), g2d_userptr->sgt, 399 399 DMA_BIDIRECTIONAL, 0); 400 400 401 - pages = frame_vector_pages(g2d_userptr->vec); 402 - if (!IS_ERR(pages)) { 403 - int i; 404 - 405 - for (i = 0; i < frame_vector_count(g2d_userptr->vec); i++) 406 - set_page_dirty_lock(pages[i]); 407 - } 408 - put_vaddr_frames(g2d_userptr->vec); 409 - frame_vector_destroy(g2d_userptr->vec); 401 + unpin_user_pages_dirty_lock(g2d_userptr->pages, g2d_userptr->npages, 402 + true); 403 + kvfree(g2d_userptr->pages); 410 404 411 405 if (!g2d_userptr->out_of_list) 412 406 list_del_init(&g2d_userptr->list); ··· 468 474 offset = userptr & ~PAGE_MASK; 469 475 end = PAGE_ALIGN(userptr + size); 470 476 npages = (end - start) >> PAGE_SHIFT; 471 - g2d_userptr->vec = frame_vector_create(npages); 472 - if (!g2d_userptr->vec) { 477 + g2d_userptr->pages = kvmalloc_array(npages, sizeof(*g2d_userptr->pages), 478 + GFP_KERNEL); 479 + if (!g2d_userptr->pages) { 473 480 ret = -ENOMEM; 474 481 goto err_free; 475 482 } 476 483 477 - ret = get_vaddr_frames(start, npages, FOLL_FORCE | FOLL_WRITE, 478 - g2d_userptr->vec); 484 + ret = pin_user_pages_fast(start, npages, 485 + FOLL_FORCE | FOLL_WRITE | FOLL_LONGTERM, 486 + g2d_userptr->pages); 479 487 if (ret != npages) { 480 488 DRM_DEV_ERROR(g2d->dev, 481 489 "failed to get user pages from userptr.\n"); 482 490 if (ret < 0) 483 - goto err_destroy_framevec; 491 + goto err_destroy_pages; 492 + npages = ret; 484 493 ret = -EFAULT; 485 - goto err_put_framevec; 494 + goto err_unpin_pages; 486 495 } 487 - if (frame_vector_to_pages(g2d_userptr->vec) < 0) { 488 - ret = -EFAULT; 489 - goto err_put_framevec; 490 - } 496 + g2d_userptr->npages = npages; 491 497 492 498 sgt = kzalloc(sizeof(*sgt), GFP_KERNEL); 493 499 if (!sgt) { 494 500 ret = -ENOMEM; 495 - goto err_put_framevec; 501 + goto err_unpin_pages; 496 502 } 497 503 498 504 ret = sg_alloc_table_from_pages(sgt, 499 - frame_vector_pages(g2d_userptr->vec), 505 + g2d_userptr->pages, 500 506 npages, offset, size, GFP_KERNEL); 501 507 if (ret < 0) { 502 508 DRM_DEV_ERROR(g2d->dev, "failed to get sgt from pages.\n"); ··· 532 538 err_free_sgt: 533 539 kfree(sgt); 534 540 535 - err_put_framevec: 536 - put_vaddr_frames(g2d_userptr->vec); 541 + err_unpin_pages: 542 + unpin_user_pages(g2d_userptr->pages, npages); 537 543 538 - err_destroy_framevec: 539 - frame_vector_destroy(g2d_userptr->vec); 544 + err_destroy_pages: 545 + kvfree(g2d_userptr->pages); 540 546 541 547 err_free: 542 548 kfree(g2d_userptr);
-1
drivers/media/common/videobuf2/Kconfig
··· 9 9 10 10 config VIDEOBUF2_MEMOPS 11 11 tristate 12 - select FRAME_VECTOR 13 12 14 13 config VIDEOBUF2_DMA_CONTIG 15 14 tristate
+1
drivers/media/common/videobuf2/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 2 videobuf2-common-objs := videobuf2-core.o 3 + videobuf2-common-objs += frame_vector.o 3 4 4 5 ifeq ($(CONFIG_TRACEPOINTS),y) 5 6 videobuf2-common-objs += vb2-trace.o
+1 -2
drivers/media/common/videobuf2/videobuf2-memops.c
··· 40 40 unsigned long first, last; 41 41 unsigned long nr; 42 42 struct frame_vector *vec; 43 - unsigned int flags = FOLL_FORCE | FOLL_WRITE; 44 43 45 44 first = start >> PAGE_SHIFT; 46 45 last = (start + length - 1) >> PAGE_SHIFT; ··· 47 48 vec = frame_vector_create(nr); 48 49 if (!vec) 49 50 return ERR_PTR(-ENOMEM); 50 - ret = get_vaddr_frames(start & PAGE_MASK, nr, flags, vec); 51 + ret = get_vaddr_frames(start & PAGE_MASK, nr, vec); 51 52 if (ret < 0) 52 53 goto out_destroy; 53 54 /* We accept only complete set of PFNs */
-1
drivers/media/platform/omap/Kconfig
··· 12 12 depends on VIDEO_V4L2 13 13 select VIDEOBUF2_DMA_CONTIG 14 14 select OMAP2_VRFB if ARCH_OMAP2 || ARCH_OMAP3 15 - select FRAME_VECTOR 16 15 help 17 16 V4L2 Display driver support for OMAP2/3 based boards.
-1
drivers/misc/habanalabs/Kconfig
··· 6 6 config HABANA_AI 7 7 tristate "HabanaAI accelerators (habanalabs)" 8 8 depends on PCI && HAS_IOMEM 9 - select FRAME_VECTOR 10 9 select GENERIC_ALLOCATOR 11 10 select HWMON 12 11 help
+4 -2
drivers/misc/habanalabs/common/habanalabs.h
··· 1089 1089 * struct hl_userptr - memory mapping chunk information 1090 1090 * @vm_type: type of the VM. 1091 1091 * @job_node: linked-list node for hanging the object on the Job's list. 1092 - * @vec: pointer to the frame vector. 1092 + * @pages: pointer to struct page array 1093 + * @npages: size of @pages array 1093 1094 * @sgt: pointer to the scatter-gather table that holds the pages. 1094 1095 * @dir: for DMA unmapping, the direction must be supplied, so save it. 1095 1096 * @debugfs_list: node in debugfs list of command submissions. ··· 1101 1100 struct hl_userptr { 1102 1101 enum vm_type_t vm_type; /* must be first */ 1103 1102 struct list_head job_node; 1104 - struct frame_vector *vec; 1103 + struct page **pages; 1104 + unsigned int npages; 1105 1105 struct sg_table *sgt; 1106 1106 enum dma_data_direction dir; 1107 1107 struct list_head debugfs_list;
+19 -33
drivers/misc/habanalabs/common/memory.c
··· 1436 1436 return -EFAULT; 1437 1437 } 1438 1438 1439 - userptr->vec = frame_vector_create(npages); 1440 - if (!userptr->vec) { 1441 - dev_err(hdev->dev, "Failed to create frame vector\n"); 1439 + userptr->pages = kvmalloc_array(npages, sizeof(*userptr->pages), 1440 + GFP_KERNEL); 1441 + if (!userptr->pages) 1442 1442 return -ENOMEM; 1443 - } 1444 1443 1445 - rc = get_vaddr_frames(start, npages, FOLL_FORCE | FOLL_WRITE, 1446 - userptr->vec); 1444 + rc = pin_user_pages_fast(start, npages, 1445 + FOLL_FORCE | FOLL_WRITE | FOLL_LONGTERM, 1446 + userptr->pages); 1447 1447 1448 1448 if (rc != npages) { 1449 1449 dev_err(hdev->dev, 1450 1450 "Failed to map host memory, user ptr probably wrong\n"); 1451 1451 if (rc < 0) 1452 - goto destroy_framevec; 1452 + goto destroy_pages; 1453 + npages = rc; 1453 1454 rc = -EFAULT; 1454 - goto put_framevec; 1455 + goto put_pages; 1455 1456 } 1456 - 1457 - if (frame_vector_to_pages(userptr->vec) < 0) { 1458 - dev_err(hdev->dev, 1459 - "Failed to translate frame vector to pages\n"); 1460 - rc = -EFAULT; 1461 - goto put_framevec; 1462 - } 1457 + userptr->npages = npages; 1463 1458 1464 1459 rc = sg_alloc_table_from_pages(userptr->sgt, 1465 - frame_vector_pages(userptr->vec), 1466 - npages, offset, size, GFP_ATOMIC); 1460 + userptr->pages, 1461 + npages, offset, size, GFP_ATOMIC); 1467 1462 if (rc < 0) { 1468 1463 dev_err(hdev->dev, "failed to create SG table from pages\n"); 1469 - goto put_framevec; 1464 + goto put_pages; 1470 1465 } 1471 1466 1472 1467 return 0; 1473 1468 1474 - put_framevec: 1475 - put_vaddr_frames(userptr->vec); 1476 - destroy_framevec: 1477 - frame_vector_destroy(userptr->vec); 1469 + put_pages: 1470 + unpin_user_pages(userptr->pages, npages); 1471 + destroy_pages: 1472 + kvfree(userptr->pages); 1478 1473 return rc; 1479 1474 } 1480 1475 ··· 1555 1560 */ 1556 1561 void hl_unpin_host_memory(struct hl_device *hdev, struct hl_userptr *userptr) 1557 1562 { 1558 - struct page **pages; 1559 - 1560 1563 hl_debugfs_remove_userptr(hdev, userptr); 1561 1564 1562 1565 if (userptr->dma_mapped) ··· 1562 1569 userptr->sgt->nents, 1563 1570 userptr->dir); 1564 1571 1565 - pages = frame_vector_pages(userptr->vec); 1566 - if (!IS_ERR(pages)) { 1567 - int i; 1568 - 1569 - for (i = 0; i < frame_vector_count(userptr->vec); i++) 1570 - set_page_dirty_lock(pages[i]); 1571 - } 1572 - put_vaddr_frames(userptr->vec); 1573 - frame_vector_destroy(userptr->vec); 1572 + unpin_user_pages_dirty_lock(userptr->pages, userptr->npages, true); 1573 + kvfree(userptr->pages); 1574 1574 1575 1575 list_del(&userptr->job_node); 1576 1576
+11
drivers/pci/pci-sysfs.c
··· 927 927 { 928 928 int error; 929 929 930 + if (!sysfs_initialized) 931 + return; 932 + 930 933 b->legacy_io = kcalloc(2, sizeof(struct bin_attribute), 931 934 GFP_ATOMIC); 932 935 if (!b->legacy_io) ··· 942 939 b->legacy_io->read = pci_read_legacy_io; 943 940 b->legacy_io->write = pci_write_legacy_io; 944 941 b->legacy_io->mmap = pci_mmap_legacy_io; 942 + b->legacy_io->mapping = iomem_get_mapping(); 945 943 pci_adjust_legacy_attr(b, pci_mmap_io); 946 944 error = device_create_bin_file(&b->dev, b->legacy_io); 947 945 if (error) ··· 955 951 b->legacy_mem->size = 1024*1024; 956 952 b->legacy_mem->attr.mode = 0600; 957 953 b->legacy_mem->mmap = pci_mmap_legacy_mem; 954 + b->legacy_io->mapping = iomem_get_mapping(); 958 955 pci_adjust_legacy_attr(b, pci_mmap_mem); 959 956 error = device_create_bin_file(&b->dev, b->legacy_mem); 960 957 if (error) ··· 1171 1166 res_attr->mmap = pci_mmap_resource_uc; 1172 1167 } 1173 1168 } 1169 + if (res_attr->mmap) 1170 + res_attr->mapping = iomem_get_mapping(); 1174 1171 res_attr->attr.name = res_attr_name; 1175 1172 res_attr->attr.mode = 0600; 1176 1173 res_attr->size = pci_resource_len(pdev, num); ··· 1455 1448 static int __init pci_sysfs_init(void) 1456 1449 { 1457 1450 struct pci_dev *pdev = NULL; 1451 + struct pci_bus *pbus = NULL; 1458 1452 int retval; 1459 1453 1460 1454 sysfs_initialized = 1; ··· 1466 1458 return retval; 1467 1459 } 1468 1460 } 1461 + 1462 + while ((pbus = pci_find_next_bus(pbus))) 1463 + pci_create_legacy_files(pbus); 1469 1464 1470 1465 return 0; 1471 1466 }
+6
drivers/pci/proc.c
··· 274 274 else 275 275 return -EINVAL; 276 276 } 277 + 278 + if (dev->resource[i].flags & IORESOURCE_MEM && 279 + iomem_is_exclusive(dev->resource[i].start)) 280 + return -EINVAL; 281 + 277 282 ret = pci_mmap_page_range(dev, i, vma, 278 283 fpriv->mmap_state, write_combine); 279 284 if (ret < 0) ··· 298 293 fpriv->write_combine = 0; 299 294 300 295 file->private_data = fpriv; 296 + file->f_mapping = iomem_get_mapping(); 301 297 302 298 return 0; 303 299 }
+11
fs/sysfs/file.c
··· 170 170 return battr->mmap(of->file, kobj, battr, vma); 171 171 } 172 172 173 + static int sysfs_kf_bin_open(struct kernfs_open_file *of) 174 + { 175 + struct bin_attribute *battr = of->kn->priv; 176 + 177 + if (battr->mapping) 178 + of->file->f_mapping = battr->mapping; 179 + 180 + return 0; 181 + } 182 + 173 183 void sysfs_notify(struct kobject *kobj, const char *dir, const char *attr) 174 184 { 175 185 struct kernfs_node *kn = kobj->sd, *tmp; ··· 251 241 .read = sysfs_kf_bin_read, 252 242 .write = sysfs_kf_bin_write, 253 243 .mmap = sysfs_kf_bin_mmap, 244 + .open = sysfs_kf_bin_open, 254 245 }; 255 246 256 247 int sysfs_add_file_mode_ns(struct kernfs_node *parent,
+1 -5
include/linux/ioport.h
··· 334 334 res->flags = IORESOURCE_IRQ | IORESOURCE_DISABLED | IORESOURCE_UNSET; 335 335 } 336 336 337 - #ifdef CONFIG_IO_STRICT_DEVMEM 338 - void revoke_devmem(struct resource *res); 339 - #else 340 - static inline void revoke_devmem(struct resource *res) { }; 341 - #endif 337 + extern struct address_space *iomem_get_mapping(void); 342 338 343 339 #endif /* __ASSEMBLY__ */ 344 340 #endif /* _LINUX_IOPORT_H */
+2 -43
include/linux/mm.h
··· 593 593 vm_fault_t (*pfn_mkwrite)(struct vm_fault *vmf); 594 594 595 595 /* called by access_process_vm when get_user_pages() fails, typically 596 - * for use by special VMAs that can switch between memory and hardware 596 + * for use by special VMAs. See also generic_access_phys() for a generic 597 + * implementation useful for any iomem mapping. 597 598 */ 598 599 int (*access)(struct vm_area_struct *vma, unsigned long addr, 599 600 void *buf, int len, int write); ··· 1761 1760 int account_locked_vm(struct mm_struct *mm, unsigned long pages, bool inc); 1762 1761 int __account_locked_vm(struct mm_struct *mm, unsigned long pages, bool inc, 1763 1762 struct task_struct *task, bool bypass_rlim); 1764 - 1765 - /* Container for pinned pfns / pages */ 1766 - struct frame_vector { 1767 - unsigned int nr_allocated; /* Number of frames we have space for */ 1768 - unsigned int nr_frames; /* Number of frames stored in ptrs array */ 1769 - bool got_ref; /* Did we pin pages by getting page ref? */ 1770 - bool is_pfns; /* Does array contain pages or pfns? */ 1771 - void *ptrs[]; /* Array of pinned pfns / pages. Use 1772 - * pfns_vector_pages() or pfns_vector_pfns() 1773 - * for access */ 1774 - }; 1775 - 1776 - struct frame_vector *frame_vector_create(unsigned int nr_frames); 1777 - void frame_vector_destroy(struct frame_vector *vec); 1778 - int get_vaddr_frames(unsigned long start, unsigned int nr_pfns, 1779 - unsigned int gup_flags, struct frame_vector *vec); 1780 - void put_vaddr_frames(struct frame_vector *vec); 1781 - int frame_vector_to_pages(struct frame_vector *vec); 1782 - void frame_vector_to_pfns(struct frame_vector *vec); 1783 - 1784 - static inline unsigned int frame_vector_count(struct frame_vector *vec) 1785 - { 1786 - return vec->nr_frames; 1787 - } 1788 - 1789 - static inline struct page **frame_vector_pages(struct frame_vector *vec) 1790 - { 1791 - if (vec->is_pfns) { 1792 - int err = frame_vector_to_pages(vec); 1793 - 1794 - if (err) 1795 - return ERR_PTR(err); 1796 - } 1797 - return (struct page **)(vec->ptrs); 1798 - } 1799 - 1800 - static inline unsigned long *frame_vector_pfns(struct frame_vector *vec) 1801 - { 1802 - if (!vec->is_pfns) 1803 - frame_vector_to_pfns(vec); 1804 - return (unsigned long *)(vec->ptrs); 1805 - } 1806 1763 1807 1764 struct kvec; 1808 1765 int get_kernel_pages(const struct kvec *iov, int nr_pages, int write,
+2
include/linux/sysfs.h
··· 164 164 165 165 struct file; 166 166 struct vm_area_struct; 167 + struct address_space; 167 168 168 169 struct bin_attribute { 169 170 struct attribute attr; 170 171 size_t size; 171 172 void *private; 173 + struct address_space *mapping; 172 174 ssize_t (*read)(struct file *, struct kobject *, struct bin_attribute *, 173 175 char *, loff_t, size_t); 174 176 ssize_t (*write)(struct file *, struct kobject *, struct bin_attribute *,
+47
include/media/frame_vector.h
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #ifndef _MEDIA_FRAME_VECTOR_H 3 + #define _MEDIA_FRAME_VECTOR_H 4 + 5 + /* Container for pinned pfns / pages in frame_vector.c */ 6 + struct frame_vector { 7 + unsigned int nr_allocated; /* Number of frames we have space for */ 8 + unsigned int nr_frames; /* Number of frames stored in ptrs array */ 9 + bool got_ref; /* Did we pin pages by getting page ref? */ 10 + bool is_pfns; /* Does array contain pages or pfns? */ 11 + void *ptrs[]; /* Array of pinned pfns / pages. Use 12 + * pfns_vector_pages() or pfns_vector_pfns() 13 + * for access */ 14 + }; 15 + 16 + struct frame_vector *frame_vector_create(unsigned int nr_frames); 17 + void frame_vector_destroy(struct frame_vector *vec); 18 + int get_vaddr_frames(unsigned long start, unsigned int nr_pfns, 19 + struct frame_vector *vec); 20 + void put_vaddr_frames(struct frame_vector *vec); 21 + int frame_vector_to_pages(struct frame_vector *vec); 22 + void frame_vector_to_pfns(struct frame_vector *vec); 23 + 24 + static inline unsigned int frame_vector_count(struct frame_vector *vec) 25 + { 26 + return vec->nr_frames; 27 + } 28 + 29 + static inline struct page **frame_vector_pages(struct frame_vector *vec) 30 + { 31 + if (vec->is_pfns) { 32 + int err = frame_vector_to_pages(vec); 33 + 34 + if (err) 35 + return ERR_PTR(err); 36 + } 37 + return (struct page **)(vec->ptrs); 38 + } 39 + 40 + static inline unsigned long *frame_vector_pfns(struct frame_vector *vec) 41 + { 42 + if (!vec->is_pfns) 43 + frame_vector_to_pfns(vec); 44 + return (unsigned long *)(vec->ptrs); 45 + } 46 + 47 + #endif /* _MEDIA_FRAME_VECTOR_H */
+1
include/media/videobuf2-core.h
··· 18 18 #include <linux/dma-buf.h> 19 19 #include <linux/bitops.h> 20 20 #include <media/media-request.h> 21 + #include <media/frame_vector.h> 21 22 22 23 #define VB2_MAX_FRAME (32) 23 24 #define VB2_MAX_PLANES (8)
+97 -1
kernel/resource.c
··· 18 18 #include <linux/spinlock.h> 19 19 #include <linux/fs.h> 20 20 #include <linux/proc_fs.h> 21 + #include <linux/pseudo_fs.h> 21 22 #include <linux/sched.h> 22 23 #include <linux/seq_file.h> 23 24 #include <linux/device.h> 24 25 #include <linux/pfn.h> 25 26 #include <linux/mm.h> 27 + #include <linux/mount.h> 26 28 #include <linux/resource_ext.h> 29 + #include <uapi/linux/magic.h> 27 30 #include <asm/io.h> 28 31 29 32 ··· 1122 1119 1123 1120 static DECLARE_WAIT_QUEUE_HEAD(muxed_resource_wait); 1124 1121 1122 + static struct inode *iomem_inode; 1123 + 1124 + #ifdef CONFIG_IO_STRICT_DEVMEM 1125 + static void revoke_iomem(struct resource *res) 1126 + { 1127 + /* pairs with smp_store_release() in iomem_init_inode() */ 1128 + struct inode *inode = smp_load_acquire(&iomem_inode); 1129 + 1130 + /* 1131 + * Check that the initialization has completed. Losing the race 1132 + * is ok because it means drivers are claiming resources before 1133 + * the fs_initcall level of init and prevent iomem_get_mapping users 1134 + * from establishing mappings. 1135 + */ 1136 + if (!inode) 1137 + return; 1138 + 1139 + /* 1140 + * The expectation is that the driver has successfully marked 1141 + * the resource busy by this point, so devmem_is_allowed() 1142 + * should start returning false, however for performance this 1143 + * does not iterate the entire resource range. 1144 + */ 1145 + if (devmem_is_allowed(PHYS_PFN(res->start)) && 1146 + devmem_is_allowed(PHYS_PFN(res->end))) { 1147 + /* 1148 + * *cringe* iomem=relaxed says "go ahead, what's the 1149 + * worst that can happen?" 1150 + */ 1151 + return; 1152 + } 1153 + 1154 + unmap_mapping_range(inode->i_mapping, res->start, resource_size(res), 1); 1155 + } 1156 + #else 1157 + static void revoke_iomem(struct resource *res) {} 1158 + #endif 1159 + 1160 + struct address_space *iomem_get_mapping(void) 1161 + { 1162 + /* 1163 + * This function is only called from file open paths, hence guaranteed 1164 + * that fs_initcalls have completed and no need to check for NULL. But 1165 + * since revoke_iomem can be called before the initcall we still need 1166 + * the barrier to appease checkers. 1167 + */ 1168 + return smp_load_acquire(&iomem_inode)->i_mapping; 1169 + } 1170 + 1125 1171 /** 1126 1172 * __request_region - create a new busy resource region 1127 1173 * @parent: parent resource descriptor ··· 1238 1186 write_unlock(&resource_lock); 1239 1187 1240 1188 if (res && orig_parent == &iomem_resource) 1241 - revoke_devmem(res); 1189 + revoke_iomem(res); 1242 1190 1243 1191 return res; 1244 1192 } ··· 1837 1785 strict_iomem_checks = 1; 1838 1786 return 1; 1839 1787 } 1788 + 1789 + static int iomem_fs_init_fs_context(struct fs_context *fc) 1790 + { 1791 + return init_pseudo(fc, DEVMEM_MAGIC) ? 0 : -ENOMEM; 1792 + } 1793 + 1794 + static struct file_system_type iomem_fs_type = { 1795 + .name = "iomem", 1796 + .owner = THIS_MODULE, 1797 + .init_fs_context = iomem_fs_init_fs_context, 1798 + .kill_sb = kill_anon_super, 1799 + }; 1800 + 1801 + static int __init iomem_init_inode(void) 1802 + { 1803 + static struct vfsmount *iomem_vfs_mount; 1804 + static int iomem_fs_cnt; 1805 + struct inode *inode; 1806 + int rc; 1807 + 1808 + rc = simple_pin_fs(&iomem_fs_type, &iomem_vfs_mount, &iomem_fs_cnt); 1809 + if (rc < 0) { 1810 + pr_err("Cannot mount iomem pseudo filesystem: %d\n", rc); 1811 + return rc; 1812 + } 1813 + 1814 + inode = alloc_anon_inode(iomem_vfs_mount->mnt_sb); 1815 + if (IS_ERR(inode)) { 1816 + rc = PTR_ERR(inode); 1817 + pr_err("Cannot allocate inode for iomem: %d\n", rc); 1818 + simple_release_fs(&iomem_vfs_mount, &iomem_fs_cnt); 1819 + return rc; 1820 + } 1821 + 1822 + /* 1823 + * Publish iomem revocation inode initialized. 1824 + * Pairs with smp_load_acquire() in revoke_iomem(). 1825 + */ 1826 + smp_store_release(&iomem_inode, inode); 1827 + 1828 + return 0; 1829 + } 1830 + 1831 + fs_initcall(iomem_init_inode); 1840 1832 1841 1833 __setup("iomem=", strict_iomem);
-3
mm/Kconfig
··· 804 804 config VMAP_PFN 805 805 bool 806 806 807 - config FRAME_VECTOR 808 - bool 809 - 810 807 config ARCH_USES_HIGH_VMA_FLAGS 811 808 bool 812 809 config ARCH_HAS_PKEYS
-1
mm/Makefile
··· 110 110 obj-$(CONFIG_CMA_DEBUGFS) += cma_debug.o 111 111 obj-$(CONFIG_USERFAULTFD) += userfaultfd.o 112 112 obj-$(CONFIG_IDLE_PAGE_TRACKING) += page_idle.o 113 - obj-$(CONFIG_FRAME_VECTOR) += frame_vector.o 114 113 obj-$(CONFIG_DEBUG_PAGE_REF) += debug_page_ref.o 115 114 obj-$(CONFIG_HARDENED_USERCOPY) += usercopy.o 116 115 obj-$(CONFIG_PERCPU_STATS) += percpu-stats.o
+19 -36
mm/frame_vector.c drivers/media/common/videobuf2/frame_vector.c
··· 8 8 #include <linux/pagemap.h> 9 9 #include <linux/sched.h> 10 10 11 + #include <media/frame_vector.h> 12 + 11 13 /** 12 14 * get_vaddr_frames() - map virtual addresses to pfns 13 15 * @start: starting user address ··· 34 32 * This function takes care of grabbing mmap_lock as necessary. 35 33 */ 36 34 int get_vaddr_frames(unsigned long start, unsigned int nr_frames, 37 - unsigned int gup_flags, struct frame_vector *vec) 35 + struct frame_vector *vec) 38 36 { 39 37 struct mm_struct *mm = current->mm; 40 38 struct vm_area_struct *vma; 41 39 int ret = 0; 42 40 int err; 43 - int locked; 44 41 45 42 if (nr_frames == 0) 46 43 return 0; ··· 49 48 50 49 start = untagged_addr(start); 51 50 52 - mmap_read_lock(mm); 53 - locked = 1; 54 - vma = find_vma_intersection(mm, start, start + 1); 55 - if (!vma) { 56 - ret = -EFAULT; 57 - goto out; 58 - } 59 - 60 - /* 61 - * While get_vaddr_frames() could be used for transient (kernel 62 - * controlled lifetime) pinning of memory pages all current 63 - * users establish long term (userspace controlled lifetime) 64 - * page pinning. Treat get_vaddr_frames() like 65 - * get_user_pages_longterm() and disallow it for filesystem-dax 66 - * mappings. 67 - */ 68 - if (vma_is_fsdax(vma)) { 69 - ret = -EOPNOTSUPP; 70 - goto out; 71 - } 72 - 73 - if (!(vma->vm_flags & (VM_IO | VM_PFNMAP))) { 51 + ret = pin_user_pages_fast(start, nr_frames, 52 + FOLL_FORCE | FOLL_WRITE | FOLL_LONGTERM, 53 + (struct page **)(vec->ptrs)); 54 + if (ret > 0) { 74 55 vec->got_ref = true; 75 56 vec->is_pfns = false; 76 - ret = pin_user_pages_locked(start, nr_frames, 77 - gup_flags, (struct page **)(vec->ptrs), &locked); 78 - goto out; 57 + goto out_unlocked; 79 58 } 80 59 60 + mmap_read_lock(mm); 81 61 vec->got_ref = false; 82 62 vec->is_pfns = true; 63 + ret = 0; 83 64 do { 84 65 unsigned long *nums = frame_vector_pfns(vec); 66 + 67 + vma = find_vma_intersection(mm, start, start + 1); 68 + if (!vma) 69 + break; 85 70 86 71 while (ret < nr_frames && start + PAGE_SIZE <= vma->vm_end) { 87 72 err = follow_pfn(vma, start, &nums[ret]); ··· 79 92 start += PAGE_SIZE; 80 93 ret++; 81 94 } 82 - /* 83 - * We stop if we have enough pages or if VMA doesn't completely 84 - * cover the tail page. 85 - */ 86 - if (ret >= nr_frames || start < vma->vm_end) 95 + /* Bail out if VMA doesn't completely cover the tail page. */ 96 + if (start < vma->vm_end) 87 97 break; 88 - vma = find_vma_intersection(mm, start, start + 1); 89 - } while (vma && vma->vm_flags & (VM_IO | VM_PFNMAP)); 98 + } while (ret < nr_frames); 90 99 out: 91 - if (locked) 92 - mmap_read_unlock(mm); 100 + mmap_read_unlock(mm); 101 + out_unlocked: 93 102 if (!ret) 94 103 ret = -EFAULT; 95 104 if (ret > 0)
+43 -3
mm/memory.c
··· 4798 4798 return ret; 4799 4799 } 4800 4800 4801 + /** 4802 + * generic_access_phys - generic implementation for iomem mmap access 4803 + * @vma: the vma to access 4804 + * @addr: userspace addres, not relative offset within @vma 4805 + * @buf: buffer to read/write 4806 + * @len: length of transfer 4807 + * @write: set to FOLL_WRITE when writing, otherwise reading 4808 + * 4809 + * This is a generic implementation for &vm_operations_struct.access for an 4810 + * iomem mapping. This callback is used by access_process_vm() when the @vma is 4811 + * not page based. 4812 + */ 4801 4813 int generic_access_phys(struct vm_area_struct *vma, unsigned long addr, 4802 4814 void *buf, int len, int write) 4803 4815 { 4804 4816 resource_size_t phys_addr; 4805 4817 unsigned long prot = 0; 4806 4818 void __iomem *maddr; 4807 - int offset = addr & (PAGE_SIZE-1); 4819 + pte_t *ptep, pte; 4820 + spinlock_t *ptl; 4821 + int offset = offset_in_page(addr); 4822 + int ret = -EINVAL; 4808 4823 4809 - if (follow_phys(vma, addr, write, &prot, &phys_addr)) 4824 + if (!(vma->vm_flags & (VM_IO | VM_PFNMAP))) 4825 + return -EINVAL; 4826 + 4827 + retry: 4828 + if (follow_pte(vma->vm_mm, addr, &ptep, &ptl)) 4829 + return -EINVAL; 4830 + pte = *ptep; 4831 + pte_unmap_unlock(ptep, ptl); 4832 + 4833 + prot = pgprot_val(pte_pgprot(pte)); 4834 + phys_addr = (resource_size_t)pte_pfn(pte) << PAGE_SHIFT; 4835 + 4836 + if ((write & FOLL_WRITE) && !pte_write(pte)) 4810 4837 return -EINVAL; 4811 4838 4812 4839 maddr = ioremap_prot(phys_addr, PAGE_ALIGN(len + offset), prot); 4813 4840 if (!maddr) 4814 4841 return -ENOMEM; 4815 4842 4843 + if (follow_pte(vma->vm_mm, addr, &ptep, &ptl)) 4844 + goto out_unmap; 4845 + 4846 + if (!pte_same(pte, *ptep)) { 4847 + pte_unmap_unlock(ptep, ptl); 4848 + iounmap(maddr); 4849 + 4850 + goto retry; 4851 + } 4852 + 4816 4853 if (write) 4817 4854 memcpy_toio(maddr + offset, buf, len); 4818 4855 else 4819 4856 memcpy_fromio(buf, maddr + offset, len); 4857 + ret = len; 4858 + pte_unmap_unlock(ptep, ptl); 4859 + out_unmap: 4820 4860 iounmap(maddr); 4821 4861 4822 - return len; 4862 + return ret; 4823 4863 } 4824 4864 EXPORT_SYMBOL_GPL(generic_access_phys); 4825 4865 #endif