[Mesa-dev] [PATCH 1/2] RFC i965: Bypass a couple of libraries for syscall on x84_64

Chris Wilson chris at chris-wilson.co.uk
Mon Jun 19 11:32:19 UTC 2017


On linux/x86_64, calling into the kernel is just a single instruction
with the parameters passed via registers. We can therefre shortcircuit a
couple of library indirections around ioctl() which as much as the
switch into the kernel itself. Aside from the PLT indirection, libc's
ioctl() has a slight impedance mismatch with the kernel interface in
that it converts the -errno return into -1 + errno, which we immediately
convert back into -errno for ourselves!

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
Cc: Kenneth Graunke <kenneth at whitecape.org>
Cc: Matt Turner <mattst88 at gmail.com>
Cc: Jason Ekstrand <jason.ekstrand at intel.com>
---
 src/intel/common/sys_ioctl.h           | 37 +++++++++++++
 src/mesa/drivers/dri/i965/brw_bufmgr.c | 99 ++++++++++++++--------------------
 2 files changed, 76 insertions(+), 60 deletions(-)
 create mode 100644 src/intel/common/sys_ioctl.h

diff --git a/src/intel/common/sys_ioctl.h b/src/intel/common/sys_ioctl.h
new file mode 100644
index 0000000000..69880650e3
--- /dev/null
+++ b/src/intel/common/sys_ioctl.h
@@ -0,0 +1,37 @@
+#ifndef SYS_IOCTL_H
+#define SYS_IOCTL_H
+
+#include <sys/syscall.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+static inline long __sys_ioctl(int fd, unsigned long cmd, void *arg)
+{
+   long result;
+
+#if defined(__linux__) && defined(__GNUC__) && defined (__x86_64__)
+   __asm__("syscall"
+           : "=a" (result)
+           : "0" (__NR_ioctl), "D" (fd), "S" (cmd), "d" (arg)
+           : "cc", "rcx", "r11", "memory");
+#else
+   result = ioctl(fd, cmd, arg);
+   if (result == -1)
+      result = -errno;
+#endif
+
+   return result;
+}
+
+static inline long sys_ioctl(int fd, unsigned long cmd, void *arg)
+{
+   long result;
+
+   do {
+      result = __sys_ioctl(fd, cmd, arg);
+   } while (result == -EINTR || result == -EAGAIN);
+
+   return result;
+}
+
+#endif
diff --git a/src/mesa/drivers/dri/i965/brw_bufmgr.c b/src/mesa/drivers/dri/i965/brw_bufmgr.c
index 98634cc4b6..b1b55d79f0 100644
--- a/src/mesa/drivers/dri/i965/brw_bufmgr.c
+++ b/src/mesa/drivers/dri/i965/brw_bufmgr.c
@@ -58,6 +58,7 @@
 #endif
 #include "common/gen_debug.h"
 #include "common/gen_device_info.h"
+#include "common/sys_ioctl.h"
 #include "libdrm_macros.h"
 #include "main/macros.h"
 #include "util/macros.h"
@@ -204,7 +205,7 @@ __brw_bo_busy(struct brw_bo *bo)
    /* If we hit an error here, it means that bo->gem_handle is invalid.
     * Treat it as being idle (busy.busy is left as 0) and move along.
     */
-   drmIoctl(bo->bufmgr->fd, DRM_IOCTL_I915_GEM_BUSY, &busy);
+   __sys_ioctl(bo->bufmgr->fd, DRM_IOCTL_I915_GEM_BUSY, &busy);
 
    bo->idle = !busy.busy;
    return busy.busy;
@@ -238,7 +239,7 @@ brw_bo_madvise(struct brw_bo *bo, int state)
    madv.handle = bo->gem_handle;
    madv.madv = state;
    madv.retained = 1;
-   drmIoctl(bo->bufmgr->fd, DRM_IOCTL_I915_GEM_MADVISE, &madv);
+   sys_ioctl(bo->bufmgr->fd, DRM_IOCTL_I915_GEM_MADVISE, &madv);
 
    return madv.retained;
 }
@@ -267,7 +268,6 @@ bo_alloc_internal(struct brw_bufmgr *bufmgr,
 {
    struct brw_bo *bo;
    unsigned int page_size = getpagesize();
-   int ret;
    struct bo_cache_bucket *bucket;
    bool alloc_from_cache;
    uint64_t bo_size;
@@ -348,8 +348,7 @@ retry:
       memclear(create);
       create.size = bo_size;
 
-      ret = drmIoctl(bufmgr->fd, DRM_IOCTL_I915_GEM_CREATE, &create);
-      if (ret != 0) {
+      if (sys_ioctl(bufmgr->fd, DRM_IOCTL_I915_GEM_CREATE, &create)) {
          free(bo);
          goto err;
       }
@@ -453,7 +452,6 @@ brw_bo_gem_create_from_name(struct brw_bufmgr *bufmgr,
                             const char *name, unsigned int handle)
 {
    struct brw_bo *bo;
-   int ret;
    struct drm_gem_open open_arg;
    struct drm_i915_gem_get_tiling get_tiling;
 
@@ -472,10 +470,8 @@ brw_bo_gem_create_from_name(struct brw_bufmgr *bufmgr,
 
    memclear(open_arg);
    open_arg.name = handle;
-   ret = drmIoctl(bufmgr->fd, DRM_IOCTL_GEM_OPEN, &open_arg);
-   if (ret != 0) {
-      DBG("Couldn't reference %s handle 0x%08x: %s\n",
-          name, handle, strerror(errno));
+   if (sys_ioctl(bufmgr->fd, DRM_IOCTL_GEM_OPEN, &open_arg)) {
+      DBG("Couldn't reference %s handle 0x%08x\n", name, handle);
       bo = NULL;
       goto out;
    }
@@ -509,8 +505,7 @@ brw_bo_gem_create_from_name(struct brw_bufmgr *bufmgr,
 
    memclear(get_tiling);
    get_tiling.handle = bo->gem_handle;
-   ret = drmIoctl(bufmgr->fd, DRM_IOCTL_I915_GEM_GET_TILING, &get_tiling);
-   if (ret != 0)
+   if (sys_ioctl(bufmgr->fd, DRM_IOCTL_I915_GEM_GET_TILING, &get_tiling))
       goto err_unref;
 
    bo->tiling_mode = get_tiling.tiling_mode;
@@ -534,7 +529,6 @@ bo_free(struct brw_bo *bo)
    struct brw_bufmgr *bufmgr = bo->bufmgr;
    struct drm_gem_close close;
    struct hash_entry *entry;
-   int ret;
 
    if (bo->map_cpu) {
       VG(VALGRIND_FREELIKE_BLOCK(bo->map_cpu, 0));
@@ -558,10 +552,9 @@ bo_free(struct brw_bo *bo)
    /* Close this object */
    memclear(close);
    close.handle = bo->gem_handle;
-   ret = drmIoctl(bufmgr->fd, DRM_IOCTL_GEM_CLOSE, &close);
-   if (ret != 0) {
-      DBG("DRM_IOCTL_GEM_CLOSE %d failed (%s): %s\n",
-          bo->gem_handle, bo->name, strerror(errno));
+   if (sys_ioctl(bufmgr->fd, DRM_IOCTL_GEM_CLOSE, &close)) {
+      DBG("DRM_IOCTL_GEM_CLOSE %d failed (%s)\n",
+          bo->gem_handle, bo->name);
    }
    free(bo);
 }
@@ -668,7 +661,7 @@ __brw_bo_set_caching(struct brw_bo *bo, int caching)
       .handle = bo->gem_handle,
       .caching = caching
    };
-   return drmIoctl(bo->bufmgr->fd, DRM_IOCTL_I915_GEM_SET_CACHING, &arg) == 0;
+   return sys_ioctl(bo->bufmgr->fd, DRM_IOCTL_I915_GEM_SET_CACHING, &arg) == 0;
 }
 
 void
@@ -696,10 +689,9 @@ set_domain(struct brw_context *brw, const char *action,
 
    double elapsed = unlikely(brw && brw->perf_debug) ? -get_time() : 0.0;
 
-   if (drmIoctl(bo->bufmgr->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &sd) != 0) {
-      DBG("%s:%d: Error setting memory domains %d (%08x %08x): %s.\n",
-          __FILE__, __LINE__, bo->gem_handle, read_domains, write_domain,
-          strerror(errno));
+   if (sys_ioctl(bo->bufmgr->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &sd)) {
+      DBG("%s:%d: Error setting memory domains %d (%08x %08x)\n",
+          __FILE__, __LINE__, bo->gem_handle, read_domains, write_domain);
    }
 
    if (unlikely(brw && brw->perf_debug)) {
@@ -726,11 +718,9 @@ brw_bo_map_cpu(struct brw_context *brw, struct brw_bo *bo, unsigned flags)
       memclear(mmap_arg);
       mmap_arg.handle = bo->gem_handle;
       mmap_arg.size = bo->size;
-      int ret = drmIoctl(bufmgr->fd, DRM_IOCTL_I915_GEM_MMAP, &mmap_arg);
-      if (ret != 0) {
-         ret = -errno;
-         DBG("%s:%d: Error mapping buffer %d (%s): %s .\n",
-             __FILE__, __LINE__, bo->gem_handle, bo->name, strerror(errno));
+      if (sys_ioctl(bufmgr->fd, DRM_IOCTL_I915_GEM_MMAP, &mmap_arg)) {
+         DBG("%s:%d: Error mapping buffer %d (%s)\n",
+             __FILE__, __LINE__, bo->gem_handle, bo->name);
          pthread_mutex_unlock(&bufmgr->lock);
          return NULL;
       }
@@ -772,10 +762,9 @@ brw_bo_map_gtt(struct brw_context *brw, struct brw_bo *bo, unsigned flags)
       mmap_arg.handle = bo->gem_handle;
 
       /* Get the fake offset back... */
-      int ret = drmIoctl(bufmgr->fd, DRM_IOCTL_I915_GEM_MMAP_GTT, &mmap_arg);
-      if (ret != 0) {
-         DBG("%s:%d: Error preparing buffer map %d (%s): %s .\n",
-             __FILE__, __LINE__, bo->gem_handle, bo->name, strerror(errno));
+      if (sys_ioctl(bufmgr->fd, DRM_IOCTL_I915_GEM_MMAP_GTT, &mmap_arg)) {
+         DBG("%s:%d: Error preparing buffer map %d (%s)\n",
+             __FILE__, __LINE__, bo->gem_handle, bo->name);
          pthread_mutex_unlock(&bufmgr->lock);
          return NULL;
       }
@@ -891,12 +880,11 @@ brw_bo_subdata(struct brw_bo *bo, uint64_t offset,
    pwrite.offset = offset;
    pwrite.size = size;
    pwrite.data_ptr = (uint64_t) (uintptr_t) data;
-   ret = drmIoctl(bufmgr->fd, DRM_IOCTL_I915_GEM_PWRITE, &pwrite);
+   ret = sys_ioctl(bufmgr->fd, DRM_IOCTL_I915_GEM_PWRITE, &pwrite);
    if (ret != 0) {
-      ret = -errno;
       DBG("%s:%d: Error writing data to buffer %d: "
           "(%"PRIu64" %"PRIu64") %s .\n",
-          __FILE__, __LINE__, bo->gem_handle, offset, size, strerror(errno));
+          __FILE__, __LINE__, bo->gem_handle, offset, size, strerror(-ret));
    }
 
    return ret;
@@ -915,12 +903,11 @@ brw_bo_get_subdata(struct brw_bo *bo, uint64_t offset,
    pread.offset = offset;
    pread.size = size;
    pread.data_ptr = (uint64_t) (uintptr_t) data;
-   ret = drmIoctl(bufmgr->fd, DRM_IOCTL_I915_GEM_PREAD, &pread);
+   ret = sys_ioctl(bufmgr->fd, DRM_IOCTL_I915_GEM_PREAD, &pread);
    if (ret != 0) {
-      ret = -errno;
       DBG("%s:%d: Error reading data from buffer %d: "
           "(%"PRIu64" %"PRIu64") %s .\n",
-          __FILE__, __LINE__, bo->gem_handle, offset, size, strerror(errno));
+          __FILE__, __LINE__, bo->gem_handle, offset, size, strerror(-ret));
    }
 
    return ret;
@@ -966,16 +953,11 @@ brw_bo_wait(struct brw_bo *bo, int64_t timeout_ns)
 {
    struct brw_bufmgr *bufmgr = bo->bufmgr;
    struct drm_i915_gem_wait wait;
-   int ret;
 
    memclear(wait);
    wait.bo_handle = bo->gem_handle;
    wait.timeout_ns = timeout_ns;
-   ret = drmIoctl(bufmgr->fd, DRM_IOCTL_I915_GEM_WAIT, &wait);
-   if (ret == -1)
-      return -errno;
-
-   return ret;
+   return sys_ioctl(bufmgr->fd, DRM_IOCTL_I915_GEM_WAIT, &wait);
 }
 
 void
@@ -1022,10 +1004,10 @@ bo_set_tiling_internal(struct brw_bo *bo, uint32_t tiling_mode,
       set_tiling.tiling_mode = tiling_mode;
       set_tiling.stride = stride;
 
-      ret = ioctl(bufmgr->fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling);
-   } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
-   if (ret == -1)
-      return -errno;
+      ret = __sys_ioctl(bufmgr->fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling);
+   } while (ret == -EINTR || ret == -EAGAIN);
+   if (ret)
+      return ret;
 
    bo->tiling_mode = set_tiling.tiling_mode;
    bo->swizzle_mode = set_tiling.swizzle_mode;
@@ -1096,7 +1078,7 @@ brw_bo_gem_create_from_prime(struct brw_bufmgr *bufmgr, int prime_fd)
 
    memclear(get_tiling);
    get_tiling.handle = bo->gem_handle;
-   if (drmIoctl(bufmgr->fd, DRM_IOCTL_I915_GEM_GET_TILING, &get_tiling))
+   if (sys_ioctl(bufmgr->fd, DRM_IOCTL_I915_GEM_GET_TILING, &get_tiling))
       goto err;
 
    bo->tiling_mode = get_tiling.tiling_mode;
@@ -1135,11 +1117,13 @@ brw_bo_flink(struct brw_bo *bo, uint32_t *name)
 
    if (!bo->global_name) {
       struct drm_gem_flink flink;
+      int ret;
 
       memclear(flink);
       flink.handle = bo->gem_handle;
-      if (drmIoctl(bufmgr->fd, DRM_IOCTL_GEM_FLINK, &flink))
-         return -errno;
+      ret = sys_ioctl(bufmgr->fd, DRM_IOCTL_GEM_FLINK, &flink);
+      if (ret)
+         return ret;
 
       pthread_mutex_lock(&bufmgr->lock);
       if (!bo->global_name) {
@@ -1212,14 +1196,10 @@ uint32_t
 brw_create_hw_context(struct brw_bufmgr *bufmgr)
 {
    struct drm_i915_gem_context_create create;
-   int ret;
 
    memclear(create);
-   ret = drmIoctl(bufmgr->fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &create);
-   if (ret != 0) {
-      DBG("DRM_IOCTL_I915_GEM_CONTEXT_CREATE failed: %s\n", strerror(errno));
-      return 0;
-   }
+   if (sys_ioctl(bufmgr->fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &create))
+      DBG("DRM_IOCTL_I915_GEM_CONTEXT_CREATE failed\n");
 
    return create.ctx_id;
 }
@@ -1230,9 +1210,8 @@ brw_destroy_hw_context(struct brw_bufmgr *bufmgr, uint32_t ctx_id)
    struct drm_i915_gem_context_destroy d = {.ctx_id = ctx_id };
 
    if (ctx_id != 0 &&
-       drmIoctl(bufmgr->fd, DRM_IOCTL_I915_GEM_CONTEXT_DESTROY, &d) != 0) {
-      fprintf(stderr, "DRM_IOCTL_I915_GEM_CONTEXT_DESTROY failed: %s\n",
-              strerror(errno));
+       sys_ioctl(bufmgr->fd, DRM_IOCTL_I915_GEM_CONTEXT_DESTROY, &d)) {
+	   DBG("DRM_IOCTL_I915_GEM_CONTEXT_DESTROY failed\n");
    }
 }
 
@@ -1245,7 +1224,7 @@ brw_reg_read(struct brw_bufmgr *bufmgr, uint32_t offset, uint64_t *result)
    memclear(reg_read);
    reg_read.offset = offset;
 
-   ret = drmIoctl(bufmgr->fd, DRM_IOCTL_I915_REG_READ, &reg_read);
+   ret = sys_ioctl(bufmgr->fd, DRM_IOCTL_I915_REG_READ, &reg_read);
 
    *result = reg_read.val;
    return ret;
-- 
2.11.0



More information about the mesa-dev mailing list