From owner-svn-src-all@freebsd.org Wed Oct 21 20:49:47 2015 Return-Path: Delivered-To: svn-src-all@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 3DF93A1BE0C; Wed, 21 Oct 2015 20:49:47 +0000 (UTC) (envelope-from jhb@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 0CCDC1144; Wed, 21 Oct 2015 20:49:46 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id t9LKnk4B002446; Wed, 21 Oct 2015 20:49:46 GMT (envelope-from jhb@FreeBSD.org) Received: (from jhb@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id t9LKnkkj002445; Wed, 21 Oct 2015 20:49:46 GMT (envelope-from jhb@FreeBSD.org) Message-Id: <201510212049.t9LKnkkj002445@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: jhb set sender to jhb@FreeBSD.org using -f From: John Baldwin Date: Wed, 21 Oct 2015 20:49:46 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r289719 - head/sys/dev/drm2/i915 X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 21 Oct 2015 20:49:47 -0000 Author: jhb Date: Wed Oct 21 20:49:45 2015 New Revision: 289719 URL: https://svnweb.freebsd.org/changeset/base/289719 Log: i915_gem_do_execbuffer() holds the pages backing each relocation region for various reasons while executing user commands. After these commands are completed, the pages backing the relocation regions are unheld. Since relocation regions do not have to be page aligned, the code in validate_exec_list() allocates 2 extra page pointers in the array of held pages populated by vm_fault_quick_hold_pages(). However, the cleanup code that unheld the pages always assumed that only the buffer size / PAGE_SIZE pages were used. This meant that non-page aligned buffers would not unheld the last 1 or 2 pages in the list. Fix this by saving the number of held pages returned by vm_fault_quick_hold_pages() for each relocation region and using this count during cleanup. Reviewed by: dumbbell, kib MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D3965 Modified: head/sys/dev/drm2/i915/i915_gem_execbuffer.c Modified: head/sys/dev/drm2/i915/i915_gem_execbuffer.c ============================================================================== --- head/sys/dev/drm2/i915/i915_gem_execbuffer.c Wed Oct 21 19:56:16 2015 (r289718) +++ head/sys/dev/drm2/i915/i915_gem_execbuffer.c Wed Oct 21 20:49:45 2015 (r289719) @@ -941,13 +941,15 @@ i915_gem_check_execbuffer(struct drm_i91 static int validate_exec_list(struct drm_i915_gem_exec_object2 *exec, int count, - vm_page_t ***map) + vm_page_t ***map, int **maplen) { vm_page_t *ma; int i, length, page_count; /* XXXKIB various limits checking is missing there */ *map = malloc(count * sizeof(*ma), DRM_I915_GEM, M_WAITOK | M_ZERO); + *maplen = malloc(count * sizeof(*maplen), DRM_I915_GEM, M_WAITOK | + M_ZERO); for (i = 0; i < count; i++) { /* First check for malicious input causing overflow */ if (exec[i].relocation_count > @@ -969,9 +971,10 @@ validate_exec_list(struct drm_i915_gem_e page_count = howmany(length, PAGE_SIZE) + 2; ma = (*map)[i] = malloc(page_count * sizeof(vm_page_t), DRM_I915_GEM, M_WAITOK | M_ZERO); - if (vm_fault_quick_hold_pages(&curproc->p_vmspace->vm_map, - exec[i].relocs_ptr, length, VM_PROT_READ | VM_PROT_WRITE, - ma, page_count) == -1) { + (*maplen)[i] = vm_fault_quick_hold_pages( + &curproc->p_vmspace->vm_map, exec[i].relocs_ptr, length, + VM_PROT_READ | VM_PROT_WRITE, ma, page_count); + if ((*maplen)[i] == -1) { free(ma, DRM_I915_GEM); (*map)[i] = NULL; return (-EFAULT); @@ -1123,6 +1126,7 @@ i915_gem_do_execbuffer(struct drm_device struct drm_clip_rect *cliprects = NULL; struct intel_ring_buffer *ring; vm_page_t **relocs_ma; + int *relocs_len; u32 ctx_id = i915_execbuffer2_get_context_id(*args); u32 exec_start, exec_len; u32 seqno; @@ -1137,7 +1141,8 @@ i915_gem_do_execbuffer(struct drm_device if (args->batch_len == 0) return (0); - ret = validate_exec_list(exec, args->buffer_count, &relocs_ma); + ret = validate_exec_list(exec, args->buffer_count, &relocs_ma, + &relocs_len); if (ret != 0) goto pre_struct_lock_err; @@ -1411,13 +1416,11 @@ err: pre_struct_lock_err: for (i = 0; i < args->buffer_count; i++) { if (relocs_ma[i] != NULL) { - vm_page_unhold_pages(relocs_ma[i], howmany( - exec[i].relocation_count * - sizeof(struct drm_i915_gem_relocation_entry), - PAGE_SIZE)); + vm_page_unhold_pages(relocs_ma[i], relocs_len[i]); free(relocs_ma[i], DRM_I915_GEM); } } + free(relocs_len, DRM_I915_GEM); free(relocs_ma, DRM_I915_GEM); free(cliprects, DRM_I915_GEM); return ret;