1/* 2 * Copyright �� 2008,2010 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the --- 13 unchanged lines hidden (view full) --- 22 * 23 * Authors: 24 * Eric Anholt <eric@anholt.net> 25 * Chris Wilson <chris@chris-wilson.co.uk> 26 * 27 */ 28 29#include <sys/cdefs.h> |
30__FBSDID("$FreeBSD: stable/10/sys/dev/drm2/i915/i915_gem_execbuffer.c 290454 2015-11-06 16:48:33Z jhb $"); |
31 32#include <dev/drm2/drmP.h> 33#include <dev/drm2/drm.h> 34#include <dev/drm2/i915/i915_drm.h> 35#include <dev/drm2/i915/i915_drv.h> 36#include <dev/drm2/i915/intel_drv.h> 37#include <sys/limits.h> 38#include <sys/sf_buf.h> --- 895 unchanged lines hidden (view full) --- 934static bool 935i915_gem_check_execbuffer(struct drm_i915_gem_execbuffer2 *exec) 936{ 937 return ((exec->batch_start_offset | exec->batch_len) & 0x7) == 0; 938} 939 940static int 941validate_exec_list(struct drm_i915_gem_exec_object2 *exec, int count, |
942 vm_page_t ***map, int **maplen) |
943{ 944 vm_page_t *ma; 945 int i, length, page_count; 946 947 /* XXXKIB various limits checking is missing there */ 948 *map = malloc(count * sizeof(*ma), DRM_I915_GEM, M_WAITOK | M_ZERO); |
949 *maplen = malloc(count * sizeof(*maplen), DRM_I915_GEM, M_WAITOK | 950 M_ZERO); |
951 for (i = 0; i < count; i++) { 952 /* First check for malicious input causing overflow */ 953 if (exec[i].relocation_count > 954 INT_MAX / sizeof(struct drm_i915_gem_relocation_entry)) 955 return -EINVAL; 956 957 length = exec[i].relocation_count * 958 sizeof(struct drm_i915_gem_relocation_entry); --- 5 unchanged lines hidden (view full) --- 964 * Since both start and end of the relocation region 965 * may be not aligned on the page boundary, be 966 * conservative and request a page slot for each 967 * partial page. Thus +2. 968 */ 969 page_count = howmany(length, PAGE_SIZE) + 2; 970 ma = (*map)[i] = malloc(page_count * sizeof(vm_page_t), 971 DRM_I915_GEM, M_WAITOK | M_ZERO); |
972 (*maplen)[i] = vm_fault_quick_hold_pages( 973 &curproc->p_vmspace->vm_map, exec[i].relocs_ptr, length, 974 VM_PROT_READ | VM_PROT_WRITE, ma, page_count); 975 if ((*maplen)[i] == -1) { |
976 free(ma, DRM_I915_GEM); 977 (*map)[i] = NULL; 978 return (-EFAULT); 979 } 980 } 981 982 return 0; 983} --- 135 unchanged lines hidden (view full) --- 1119{ 1120 drm_i915_private_t *dev_priv = dev->dev_private; 1121 struct list_head objects; 1122 struct eb_objects *eb; 1123 struct drm_i915_gem_object *batch_obj; 1124 struct drm_clip_rect *cliprects = NULL; 1125 struct intel_ring_buffer *ring; 1126 vm_page_t **relocs_ma; |
1127 int *relocs_len; |
1128 u32 ctx_id = i915_execbuffer2_get_context_id(*args); 1129 u32 exec_start, exec_len; 1130 u32 seqno; 1131 u32 mask; 1132 int ret, mode, i; 1133 1134 if (!i915_gem_check_execbuffer(args)) { 1135 DRM_DEBUG("execbuf with invalid offset/length\n"); 1136 return -EINVAL; 1137 } 1138 1139 if (args->batch_len == 0) 1140 return (0); 1141 |
1142 ret = validate_exec_list(exec, args->buffer_count, &relocs_ma, 1143 &relocs_len); |
1144 if (ret != 0) 1145 goto pre_struct_lock_err; 1146 1147 switch (args->flags & I915_EXEC_RING_MASK) { 1148 case I915_EXEC_DEFAULT: 1149 case I915_EXEC_RENDER: 1150 ring = &dev_priv->rings[RCS]; 1151 break; 1152 case I915_EXEC_BSD: 1153 ring = &dev_priv->rings[VCS]; 1154 if (ctx_id != 0) { 1155 DRM_DEBUG("Ring %s doesn't support contexts\n", 1156 ring->name); |
1157 ret = -EPERM; 1158 goto pre_struct_lock_err; |
1159 } 1160 break; 1161 case I915_EXEC_BLT: 1162 ring = &dev_priv->rings[BCS]; 1163 if (ctx_id != 0) { 1164 DRM_DEBUG("Ring %s doesn't support contexts\n", 1165 ring->name); |
1166 ret = -EPERM; 1167 goto pre_struct_lock_err; |
1168 } 1169 break; 1170 default: 1171 DRM_DEBUG("execbuf with unknown ring: %d\n", 1172 (int)(args->flags & I915_EXEC_RING_MASK)); 1173 ret = -EINVAL; 1174 goto pre_struct_lock_err; 1175 } 1176 if (!intel_ring_initialized(ring)) { 1177 DRM_DEBUG("execbuf with invalid ring: %d\n", 1178 (int)(args->flags & I915_EXEC_RING_MASK)); |
1179 ret = -EINVAL; 1180 goto pre_struct_lock_err; |
1181 } 1182 1183 mode = args->flags & I915_EXEC_CONSTANTS_MASK; 1184 mask = I915_EXEC_CONSTANTS_MASK; 1185 switch (mode) { 1186 case I915_EXEC_CONSTANTS_REL_GENERAL: 1187 case I915_EXEC_CONSTANTS_ABSOLUTE: 1188 case I915_EXEC_CONSTANTS_REL_SURFACE: --- 215 unchanged lines hidden (view full) --- 1404 list_del_init(&obj->exec_list); 1405 drm_gem_object_unreference(&obj->base); 1406 } 1407 DRM_UNLOCK(dev); 1408 1409pre_struct_lock_err: 1410 for (i = 0; i < args->buffer_count; i++) { 1411 if (relocs_ma[i] != NULL) { |
1412 vm_page_unhold_pages(relocs_ma[i], relocs_len[i]); |
1413 free(relocs_ma[i], DRM_I915_GEM); 1414 } 1415 } |
1416 free(relocs_len, DRM_I915_GEM); |
1417 free(relocs_ma, DRM_I915_GEM); 1418 free(cliprects, DRM_I915_GEM); 1419 return ret; 1420} 1421 1422/* 1423 * Legacy execbuffer just creates an exec2 list from the original exec object 1424 * list array and passes it to the real function. --- 122 unchanged lines hidden --- |