From owner-svn-src-head@freebsd.org Fri Jul 7 13:44:15 2017 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 89E06DA3A97; Fri, 7 Jul 2017 13:44:15 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 609947AD4E; Fri, 7 Jul 2017 13:44:15 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v67DiEs9024495; Fri, 7 Jul 2017 13:44:14 GMT (envelope-from hselasky@FreeBSD.org) Received: (from hselasky@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v67DiErd024494; Fri, 7 Jul 2017 13:44:14 GMT (envelope-from hselasky@FreeBSD.org) Message-Id: <201707071344.v67DiErd024494@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: hselasky set sender to hselasky@FreeBSD.org using -f From: Hans Petter Selasky Date: Fri, 7 Jul 2017 13:44:14 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r320775 - head/sys/compat/linuxkpi/common/src X-SVN-Group: head X-SVN-Commit-Author: hselasky X-SVN-Commit-Paths: head/sys/compat/linuxkpi/common/src X-SVN-Commit-Revision: 320775 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 07 Jul 2017 13:44:15 -0000 Author: hselasky Date: Fri Jul 7 13:44:14 2017 New Revision: 320775 URL: https://svnweb.freebsd.org/changeset/base/320775 Log: Complete r320189 which allows a NULL VM fault handler in the LinuxKPI. Instead of mapping a dummy page upon a page fault, map the page pointed to by the physical address given by IDX_TO_OFF(vmap->vm_pfn). To simplify the implementation use OBJT_DEVICE to implement our own linux_cdev_pager_fault() instead of using the existing linux_cdev_pager_populate(). Some minor code factoring while at it. Reviewed by: markj @ MFC after: 1 week Sponsored by: Mellanox Technologies Modified: head/sys/compat/linuxkpi/common/src/linux_compat.c Modified: head/sys/compat/linuxkpi/common/src/linux_compat.c ============================================================================== --- head/sys/compat/linuxkpi/common/src/linux_compat.c Fri Jul 7 13:15:00 2017 (r320774) +++ head/sys/compat/linuxkpi/common/src/linux_compat.c Fri Jul 7 13:44:14 2017 (r320775) @@ -474,11 +474,57 @@ linux_file_free(struct linux_file *filp) } static int +linux_cdev_pager_fault(vm_object_t vm_obj, vm_ooffset_t offset, int prot, + vm_page_t *mres) +{ + struct vm_area_struct *vmap; + + vmap = linux_cdev_handle_find(vm_obj->handle); + + MPASS(vmap != NULL); + MPASS(vmap->vm_private_data == vm_obj->handle); + + if (likely(vmap->vm_ops != NULL && offset < vmap->vm_len)) { + vm_paddr_t paddr = IDX_TO_OFF(vmap->vm_pfn) + offset; + vm_page_t page; + + if (((*mres)->flags & PG_FICTITIOUS) != 0) { + /* + * If the passed in result page is a fake + * page, update it with the new physical + * address. + */ + page = *mres; + vm_page_updatefake(page, paddr, vm_obj->memattr); + } else { + /* + * Replace the passed in "mres" page with our + * own fake page and free up the all of the + * original pages. + */ + VM_OBJECT_WUNLOCK(vm_obj); + page = vm_page_getfake(paddr, vm_obj->memattr); + VM_OBJECT_WLOCK(vm_obj); + + vm_page_replace_checked(page, vm_obj, + (*mres)->pindex, *mres); + + vm_page_lock(*mres); + vm_page_free(*mres); + vm_page_unlock(*mres); + *mres = page; + } + page->valid = VM_PAGE_BITS_ALL; + return (VM_PAGER_OK); + } + return (VM_PAGER_FAIL); +} + +static int linux_cdev_pager_populate(vm_object_t vm_obj, vm_pindex_t pidx, int fault_type, vm_prot_t max_prot, vm_pindex_t *first, vm_pindex_t *last) { struct vm_area_struct *vmap; - struct vm_fault vmf; int err; linux_set_current(curthread); @@ -488,18 +534,20 @@ linux_cdev_pager_populate(vm_object_t vm_obj, vm_pinde MPASS(vmap != NULL); MPASS(vmap->vm_private_data == vm_obj->handle); - /* fill out VM fault structure */ - vmf.virtual_address = (void *)((uintptr_t)pidx << PAGE_SHIFT); - vmf.flags = (fault_type & VM_PROT_WRITE) ? FAULT_FLAG_WRITE : 0; - vmf.pgoff = 0; - vmf.page = NULL; - VM_OBJECT_WUNLOCK(vm_obj); down_write(&vmap->vm_mm->mmap_sem); - if (unlikely(vmap->vm_ops == NULL || vmap->vm_ops->fault == NULL)) { + if (unlikely(vmap->vm_ops == NULL)) { err = VM_FAULT_SIGBUS; } else { + struct vm_fault vmf; + + /* fill out VM fault structure */ + vmf.virtual_address = (void *)((uintptr_t)pidx << PAGE_SHIFT); + vmf.flags = (fault_type & VM_PROT_WRITE) ? FAULT_FLAG_WRITE : 0; + vmf.pgoff = 0; + vmf.page = NULL; + vmap->vm_pfn_count = 0; vmap->vm_pfn_pcount = &vmap->vm_pfn_count; vmap->vm_obj = vm_obj; @@ -631,10 +679,19 @@ linux_cdev_pager_dtor(void *handle) linux_cdev_handle_free(vmap); } -static struct cdev_pager_ops linux_cdev_pager_ops = { +static struct cdev_pager_ops linux_cdev_pager_ops[2] = { + { + /* OBJT_MGTDEVICE */ .cdev_pg_populate = linux_cdev_pager_populate, .cdev_pg_ctor = linux_cdev_pager_ctor, .cdev_pg_dtor = linux_cdev_pager_dtor + }, + { + /* OBJT_DEVICE */ + .cdev_pg_fault = linux_cdev_pager_fault, + .cdev_pg_ctor = linux_cdev_pager_ctor, + .cdev_pg_dtor = linux_cdev_pager_dtor + }, }; static int @@ -1184,8 +1241,15 @@ linux_dev_mmap_single(struct cdev *dev, vm_ooffset_t * vmap = linux_cdev_handle_insert(vm_private_data, vmap); - *object = cdev_pager_allocate(vm_private_data, OBJT_MGTDEVICE, - &linux_cdev_pager_ops, size, nprot, *offset, curthread->td_ucred); + if (vmap->vm_ops->fault == NULL) { + *object = cdev_pager_allocate(vm_private_data, OBJT_DEVICE, + &linux_cdev_pager_ops[1], size, nprot, *offset, + curthread->td_ucred); + } else { + *object = cdev_pager_allocate(vm_private_data, OBJT_MGTDEVICE, + &linux_cdev_pager_ops[0], size, nprot, *offset, + curthread->td_ucred); + } if (*object == NULL) { linux_cdev_handle_remove(vmap); @@ -1196,7 +1260,8 @@ linux_dev_mmap_single(struct cdev *dev, vm_ooffset_t * struct sglist *sg; sg = sglist_alloc(1, M_WAITOK); - sglist_append_phys(sg, (vm_paddr_t)vmap->vm_pfn << PAGE_SHIFT, vmap->vm_len); + sglist_append_phys(sg, + (vm_paddr_t)vmap->vm_pfn << PAGE_SHIFT, vmap->vm_len); *object = vm_pager_allocate(OBJT_SG, sg, vmap->vm_len, nprot, 0, curthread->td_ucred);