anv: setup BO flags at state_pool/block_pool creation
[mesa.git] / src / intel / vulkan / anv_allocator.c
index 708b32b34520f247014d90711463db90348e49f0..8ed32b3c6731f5ecb919fbae2fc3eb3b1f879ced 100644 (file)
  * IN THE SOFTWARE.
  */
 
-#include <stdint.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <limits.h>
 #include <assert.h>
-#include <linux/futex.h>
 #include <linux/memfd.h>
-#include <sys/time.h>
 #include <sys/mman.h>
-#include <sys/syscall.h>
 
 #include "anv_private.h"
 
 #include "util/hash_table.h"
+#include "util/simple_mtx.h"
 
 #ifdef HAVE_VALGRIND
 #define VG_NOACCESS_READ(__ptr) ({                       \
@@ -112,25 +109,6 @@ struct anv_mmap_cleanup {
 
 #define ANV_MMAP_CLEANUP_INIT ((struct anv_mmap_cleanup){0})
 
-static inline long
-sys_futex(void *addr1, int op, int val1,
-          struct timespec *timeout, void *addr2, int val3)
-{
-   return syscall(SYS_futex, addr1, op, val1, timeout, addr2, val3);
-}
-
-static inline int
-futex_wake(uint32_t *addr, int count)
-{
-   return sys_futex(addr, FUTEX_WAKE, count, NULL, NULL, 0);
-}
-
-static inline int
-futex_wait(uint32_t *addr, int32_t value)
-{
-   return sys_futex(addr, FUTEX_WAIT, value, NULL, NULL, 0);
-}
-
 static inline int
 memfd_create(const char *name, unsigned int flags)
 {
@@ -263,11 +241,13 @@ anv_block_pool_expand_range(struct anv_block_pool *pool,
 VkResult
 anv_block_pool_init(struct anv_block_pool *pool,
                     struct anv_device *device,
-                    uint32_t initial_size)
+                    uint32_t initial_size,
+                    uint64_t bo_flags)
 {
    VkResult result;
 
    pool->device = device;
+   pool->bo_flags = bo_flags;
    anv_bo_init(&pool->bo, 0, 0);
 
    pool->fd = memfd_create("block pool", MFD_CLOEXEC);
@@ -361,12 +341,14 @@ anv_block_pool_expand_range(struct anv_block_pool *pool,
               MAP_SHARED | MAP_POPULATE, pool->fd,
               BLOCK_POOL_MEMFD_CENTER - center_bo_offset);
    if (map == MAP_FAILED)
-      return vk_errorf(VK_ERROR_MEMORY_MAP_FAILED, "mmap failed: %m");
+      return vk_errorf(pool->device->instance, pool->device,
+                       VK_ERROR_MEMORY_MAP_FAILED, "mmap failed: %m");
 
    gem_handle = anv_gem_userptr(pool->device, map, size);
    if (gem_handle == 0) {
       munmap(map, size);
-      return vk_errorf(VK_ERROR_TOO_MANY_OBJECTS, "userptr failed: %m");
+      return vk_errorf(pool->device->instance, pool->device,
+                       VK_ERROR_TOO_MANY_OBJECTS, "userptr failed: %m");
    }
 
    cleanup->map = map;
@@ -418,6 +400,7 @@ anv_block_pool_expand_range(struct anv_block_pool *pool,
     * hard work for us.
     */
    anv_bo_init(&pool->bo, gem_handle, size);
+   pool->bo.flags = pool->bo_flags;
    pool->bo.map = map;
 
    return VK_SUCCESS;
@@ -535,8 +518,7 @@ anv_block_pool_grow(struct anv_block_pool *pool, struct anv_block_state *state)
 
    result = anv_block_pool_expand_range(pool, center_bo_offset, size);
 
-   if (pool->device->instance->physicalDevice.has_exec_async)
-      pool->bo.flags |= EXEC_OBJECT_ASYNC;
+   pool->bo.flags = pool->bo_flags;
 
 done:
    pthread_mutex_unlock(&pool->device->mutex);
@@ -585,7 +567,7 @@ anv_block_pool_alloc_new(struct anv_block_pool *pool,
             futex_wake(&pool_state->end, INT_MAX);
          return state.next;
       } else {
-         futex_wait(&pool_state->end, state.end);
+         futex_wait(&pool_state->end, state.end, NULL);
          continue;
       }
    }
@@ -626,10 +608,12 @@ anv_block_pool_alloc_back(struct anv_block_pool *pool,
 VkResult
 anv_state_pool_init(struct anv_state_pool *pool,
                     struct anv_device *device,
-                    uint32_t block_size)
+                    uint32_t block_size,
+                    uint64_t bo_flags)
 {
    VkResult result = anv_block_pool_init(&pool->block_pool, device,
-                                         block_size * 16);
+                                         block_size * 16,
+                                         bo_flags);
    if (result != VK_SUCCESS)
       return result;
 
@@ -682,7 +666,7 @@ anv_fixed_size_state_pool_alloc_new(struct anv_fixed_size_state_pool *pool,
          futex_wake(&pool->block.end, INT_MAX);
       return offset;
    } else {
-      futex_wait(&pool->block.end, block.end);
+      futex_wait(&pool->block.end, block.end, NULL);
       goto restart;
    }
 }
@@ -971,9 +955,11 @@ struct bo_pool_bo_link {
 };
 
 void
-anv_bo_pool_init(struct anv_bo_pool *pool, struct anv_device *device)
+anv_bo_pool_init(struct anv_bo_pool *pool, struct anv_device *device,
+                 uint64_t bo_flags)
 {
    pool->device = device;
+   pool->bo_flags = bo_flags;
    memset(pool->free_list, 0, sizeof(pool->free_list));
 
    VG(VALGRIND_CREATE_MEMPOOL(pool, 0, false));
@@ -1025,11 +1011,7 @@ anv_bo_pool_alloc(struct anv_bo_pool *pool, struct anv_bo *bo, uint32_t size)
    if (result != VK_SUCCESS)
       return result;
 
-   if (pool->device->instance->physicalDevice.supports_48bit_addresses)
-      new_bo.flags |= EXEC_OBJECT_SUPPORTS_48B_ADDRESS;
-
-   if (pool->device->instance->physicalDevice.has_exec_async)
-      new_bo.flags |= EXEC_OBJECT_ASYNC;
+   new_bo.flags = pool->bo_flags;
 
    assert(new_bo.size == pow2_size);
 
@@ -1190,7 +1172,7 @@ anv_bo_cache_init(struct anv_bo_cache *cache)
 
    if (pthread_mutex_init(&cache->mutex, NULL)) {
       _mesa_hash_table_destroy(cache->bo_map, NULL);
-      return vk_errorf(VK_ERROR_OUT_OF_HOST_MEMORY,
+      return vk_errorf(NULL, NULL, VK_ERROR_OUT_OF_HOST_MEMORY,
                        "pthread_mutex_init failed: %m");
    }
 
@@ -1270,13 +1252,10 @@ anv_bo_cache_alloc(struct anv_device *device,
 VkResult
 anv_bo_cache_import(struct anv_device *device,
                     struct anv_bo_cache *cache,
-                    int fd, uint64_t size, struct anv_bo **bo_out)
+                    int fd, struct anv_bo **bo_out)
 {
    pthread_mutex_lock(&cache->mutex);
 
-   /* The kernel is going to give us whole pages anyway */
-   size = align_u64(size, 4096);
-
    uint32_t gem_handle = anv_gem_fd_to_handle(device, fd);
    if (!gem_handle) {
       pthread_mutex_unlock(&cache->mutex);
@@ -1285,22 +1264,10 @@ anv_bo_cache_import(struct anv_device *device,
 
    struct anv_cached_bo *bo = anv_bo_cache_lookup_locked(cache, gem_handle);
    if (bo) {
-      if (bo->bo.size != size) {
-         pthread_mutex_unlock(&cache->mutex);
-         return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR);
-      }
       __sync_fetch_and_add(&bo->refcount, 1);
    } else {
-      /* For security purposes, we reject BO imports where the size does not
-       * match exactly.  This prevents a malicious client from passing a
-       * buffer to a trusted client, lying about the size, and telling the
-       * trusted client to try and texture from an image that goes
-       * out-of-bounds.  This sort of thing could lead to GPU hangs or worse
-       * in the trusted client.  The trusted client can protect itself against
-       * this sort of attack but only if it can trust the buffer size.
-       */
-      off_t import_size = lseek(fd, 0, SEEK_END);
-      if (import_size == (off_t)-1 || import_size != size) {
+      off_t size = lseek(fd, 0, SEEK_END);
+      if (size == (off_t)-1) {
          anv_gem_close(device, gem_handle);
          pthread_mutex_unlock(&cache->mutex);
          return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR);
@@ -1322,18 +1289,6 @@ anv_bo_cache_import(struct anv_device *device,
    }
 
    pthread_mutex_unlock(&cache->mutex);
-
-   /* From the Vulkan spec:
-    *
-    *    "Importing memory from a file descriptor transfers ownership of
-    *    the file descriptor from the application to the Vulkan
-    *    implementation. The application must not perform any operations on
-    *    the file descriptor after a successful import."
-    *
-    * If the import fails, we leave the file descriptor open.
-    */
-   close(fd);
-
    *bo_out = &bo->bo;
 
    return VK_SUCCESS;