svn commit: r290454 - in stable: 10/sys/dev/drm2/i915 9/sys/dev/drm2/i915
John Baldwin
jhb at FreeBSD.org
Fri Nov 6 16:48:35 UTC 2015
Author: jhb
Date: Fri Nov 6 16:48:33 2015
New Revision: 290454
URL: https://svnweb.freebsd.org/changeset/base/290454
Log:
MFC 288452,289719:
288452:
Most error cases in i915_gem_do_execbuffer() jump to one of two labels to
release resources (such as unholding pages) when errors occur. Some
recently added error checks return immediately instead of jumping to a
label resulting in leaks. Fix these to jump to a label to do cleanup
instead.
Note that stable/9 does not have the "recently added" error checks, but
it does have some older error checks (that were are no longer present
in stable/10 and head) that have the same bug and this fixes those
instead.
289719:
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.
Modified:
stable/9/sys/dev/drm2/i915/i915_gem_execbuffer.c
Directory Properties:
stable/9/sys/ (props changed)
stable/9/sys/dev/ (props changed)
Changes in other areas also in this revision:
Modified:
stable/10/sys/dev/drm2/i915/i915_gem_execbuffer.c
Directory Properties:
stable/10/ (props changed)
Modified: stable/9/sys/dev/drm2/i915/i915_gem_execbuffer.c
==============================================================================
--- stable/9/sys/dev/drm2/i915/i915_gem_execbuffer.c Fri Nov 6 16:43:22 2015 (r290453)
+++ stable/9/sys/dev/drm2/i915/i915_gem_execbuffer.c Fri Nov 6 16:48:33 2015 (r290454)
@@ -953,13 +953,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 >
@@ -981,9 +983,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);
@@ -1130,6 +1133,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 exec_start, exec_len;
u32 seqno;
u32 mask;
@@ -1143,7 +1147,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;
@@ -1155,14 +1160,16 @@ i915_gem_do_execbuffer(struct drm_device
case I915_EXEC_BSD:
if (!HAS_BSD(dev)) {
DRM_DEBUG("execbuf with invalid ring (BSD)\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto pre_struct_lock_err;
}
ring = &dev_priv->rings[VCS];
break;
case I915_EXEC_BLT:
if (!HAS_BLT(dev)) {
DRM_DEBUG("execbuf with invalid ring (BLT)\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto pre_struct_lock_err;
}
ring = &dev_priv->rings[BCS];
break;
@@ -1390,13 +1397,11 @@ struct_lock_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;
More information about the svn-src-stable-9
mailing list