diff --git a/SOURCES/0001-i965-bufmgr-Handle-NULL-bufmgr-in-brw_bufmgr_get_for.patch b/SOURCES/0001-i965-bufmgr-Handle-NULL-bufmgr-in-brw_bufmgr_get_for.patch
new file mode 100644
index 0000000..243f385
--- /dev/null
+++ b/SOURCES/0001-i965-bufmgr-Handle-NULL-bufmgr-in-brw_bufmgr_get_for.patch
@@ -0,0 +1,36 @@
+From 735971d5a22a55b43f043f70cf5e973354d53852 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Michel=20D=C3=A4nzer?= <mdaenzer@redhat.com>
+Date: Tue, 27 Oct 2020 11:40:05 +0100
+Subject: [PATCH] i965/bufmgr: Handle NULL bufmgr in brw_bufmgr_get_for_fd
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+brw_bufmgr_create can return NULL, in which case we'd crash in
+list_addtail.
+
+Reported by Coverity/clang.
+
+Fixes: 4094558e8643 ("i965: share buffer managers across screens")
+Signed-off-by: Michel Dänzer <mdaenzer@redhat.com>
+---
+ src/mesa/drivers/dri/i965/brw_bufmgr.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/src/mesa/drivers/dri/i965/brw_bufmgr.c b/src/mesa/drivers/dri/i965/brw_bufmgr.c
+index 5a8680704eb..04cb2448a3e 100644
+--- a/src/mesa/drivers/dri/i965/brw_bufmgr.c
++++ b/src/mesa/drivers/dri/i965/brw_bufmgr.c
+@@ -1916,7 +1916,8 @@ brw_bufmgr_get_for_fd(struct gen_device_info *devinfo, int fd, bool bo_reuse)
+    }
+ 
+    bufmgr = brw_bufmgr_create(devinfo, fd, bo_reuse);
+-   list_addtail(&bufmgr->link, &global_bufmgr_list);
++   if (bufmgr)
++      list_addtail(&bufmgr->link, &global_bufmgr_list);
+ 
+  unlock:
+    mtx_unlock(&global_bufmgr_list_mutex);
+-- 
+2.28.0
+
diff --git a/SOURCES/0001-i965-initialize-bo_reuse-when-creating-brw_bufmgr.patch b/SOURCES/0001-i965-initialize-bo_reuse-when-creating-brw_bufmgr.patch
new file mode 100644
index 0000000..23c59e9
--- /dev/null
+++ b/SOURCES/0001-i965-initialize-bo_reuse-when-creating-brw_bufmgr.patch
@@ -0,0 +1,154 @@
+From 453530d58df83fac6f7191f56e75ddb00ec855d7 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Tapani=20P=C3=A4lli?= <tapani.palli@intel.com>
+Date: Wed, 28 Aug 2019 14:29:53 +0300
+Subject: [PATCH 1/8] i965: initialize bo_reuse when creating brw_bufmgr
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Fixes a possible data race spotted while debugging on other EGL
+related failures where glFinish and eglCreateContext are going on at
+the same time:
+
+  ==11558== Possible data race during read of size 1 at 0x5E78CD0 by thread #23
+  ==11558== Locks held: 1, at address 0x5E77CA8
+  ==11558==    at 0x61B71D4: bo_alloc_internal (brw_bufmgr.c:639)
+  ==11558==    by 0x61B7328: brw_bo_alloc (brw_bufmgr.c:669)
+  ==11558==    by 0x61EF975: recreate_growing_buffer (intel_batchbuffer.c:231)
+  ==11558==    by 0x61EFAAE: intel_batchbuffer_reset (intel_batchbuffer.c:255)
+  ==11558==    by 0x61EFB85: intel_batchbuffer_reset_and_clear_render_cache (intel_batchbuffer.c:280)
+  ==11558==    by 0x61F0507: brw_new_batch (intel_batchbuffer.c:551)
+  ==11558==    by 0x61F12C1: _intel_batchbuffer_flush_fence (intel_batchbuffer.c:888)
+  ==11558==    by 0x61BDD6B: intel_glFlush (brw_context.c:296)
+  ==11558==    by 0x61BDDB9: intel_finish (brw_context.c:307)
+  ==11558==    by 0x623831B: _mesa_Finish (context.c:1906)
+  ==11558==    by 0x46D556: deqp::egl::GLES2ThreadTest::Operation::execute(tcu::ThreadUtil::Thread&)
+  ==11558==    by 0x721502: tcu::ThreadUtil::Thread::run()
+  ==11558==
+  ==11558== This conflicts with a previous write of size 1 by thread #26
+  ==11558== Locks held: 1, at address 0x5D09878
+  ==11558==    at 0x61B98A9: brw_bufmgr_enable_reuse (brw_bufmgr.c:1541)
+  ==11558==    by 0x61BF09D: brw_process_driconf_options (brw_context.c:854)
+  ==11558==    by 0x61BF6CA: brwCreateContext (brw_context.c:993)
+  ==11558==    by 0x621181F: driCreateContextAttribs (dri_util.c:473)
+  ==11558==    by 0x53FE87B: dri2_create_context (egl_dri2.c:1388)
+  ==11558==    by 0x53EE7BE: eglCreateContext (eglapi.c:807)
+  ==11558==    by 0x5C8AB9: eglw::FuncPtrLibrary::createContext(void*, void*, void*, int const*) const
+  ==11558==    by 0x46E027: deqp::egl::GLES2ThreadTest::CreateContext::exec(tcu::ThreadUtil::Thread&)
+
+Signed-off-by: Tapani Pälli <tapani.palli@intel.com>
+Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
+Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
+(cherry picked from commit b65de51dcf7d5e6d1a6ccdb5121c385f5360de00)
+---
+ src/mesa/drivers/dri/i965/brw_bufmgr.c   | 16 ++--------------
+ src/mesa/drivers/dri/i965/brw_bufmgr.h   |  4 ++--
+ src/mesa/drivers/dri/i965/brw_context.c  |  9 ---------
+ src/mesa/drivers/dri/i965/intel_screen.c | 12 +++++++++++-
+ 4 files changed, 15 insertions(+), 26 deletions(-)
+
+diff --git a/src/mesa/drivers/dri/i965/brw_bufmgr.c b/src/mesa/drivers/dri/i965/brw_bufmgr.c
+index f1675b191c1..e676fbd9d18 100644
+--- a/src/mesa/drivers/dri/i965/brw_bufmgr.c
++++ b/src/mesa/drivers/dri/i965/brw_bufmgr.c
+@@ -1529,19 +1529,6 @@ brw_bo_flink(struct brw_bo *bo, uint32_t *name)
+    return 0;
+ }
+ 
+-/**
+- * Enables unlimited caching of buffer objects for reuse.
+- *
+- * This is potentially very memory expensive, as the cache at each bucket
+- * size is only bounded by how many buffers of that size we've managed to have
+- * in flight at once.
+- */
+-void
+-brw_bufmgr_enable_reuse(struct brw_bufmgr *bufmgr)
+-{
+-   bufmgr->bo_reuse = true;
+-}
+-
+ static void
+ add_bucket(struct brw_bufmgr *bufmgr, int size)
+ {
+@@ -1684,7 +1671,7 @@ brw_using_softpin(struct brw_bufmgr *bufmgr)
+  * \param fd File descriptor of the opened DRM device.
+  */
+ struct brw_bufmgr *
+-brw_bufmgr_init(struct gen_device_info *devinfo, int fd)
++brw_bufmgr_init(struct gen_device_info *devinfo, int fd, bool bo_reuse)
+ {
+    struct brw_bufmgr *bufmgr;
+ 
+@@ -1714,6 +1701,7 @@ brw_bufmgr_init(struct gen_device_info *devinfo, int fd)
+ 
+    bufmgr->has_llc = devinfo->has_llc;
+    bufmgr->has_mmap_wc = gem_param(fd, I915_PARAM_MMAP_VERSION) > 0;
++   bufmgr->bo_reuse = bo_reuse;
+ 
+    const uint64_t _4GB = 4ull << 30;
+ 
+diff --git a/src/mesa/drivers/dri/i965/brw_bufmgr.h b/src/mesa/drivers/dri/i965/brw_bufmgr.h
+index 32fc7a553c9..a85c8f37bef 100644
+--- a/src/mesa/drivers/dri/i965/brw_bufmgr.h
++++ b/src/mesa/drivers/dri/i965/brw_bufmgr.h
+@@ -343,11 +343,11 @@ int brw_bo_busy(struct brw_bo *bo);
+ int brw_bo_madvise(struct brw_bo *bo, int madv);
+ 
+ /* drm_bacon_bufmgr_gem.c */
+-struct brw_bufmgr *brw_bufmgr_init(struct gen_device_info *devinfo, int fd);
++struct brw_bufmgr *brw_bufmgr_init(struct gen_device_info *devinfo, int fd,
++                                   bool bo_reuse);
+ struct brw_bo *brw_bo_gem_create_from_name(struct brw_bufmgr *bufmgr,
+                                            const char *name,
+                                            unsigned int handle);
+-void brw_bufmgr_enable_reuse(struct brw_bufmgr *bufmgr);
+ 
+ int brw_bo_wait(struct brw_bo *bo, int64_t timeout_ns);
+ 
+diff --git a/src/mesa/drivers/dri/i965/brw_context.c b/src/mesa/drivers/dri/i965/brw_context.c
+index 6ba64e4e06d..6d218e49754 100644
+--- a/src/mesa/drivers/dri/i965/brw_context.c
++++ b/src/mesa/drivers/dri/i965/brw_context.c
+@@ -822,15 +822,6 @@ brw_process_driconf_options(struct brw_context *brw)
+                        brw->driContext->driScreenPriv->myNum,
+                        "i965", NULL);
+ 
+-   int bo_reuse_mode = driQueryOptioni(options, "bo_reuse");
+-   switch (bo_reuse_mode) {
+-   case DRI_CONF_BO_REUSE_DISABLED:
+-      break;
+-   case DRI_CONF_BO_REUSE_ALL:
+-      brw_bufmgr_enable_reuse(brw->bufmgr);
+-      break;
+-   }
+-
+    if (INTEL_DEBUG & DEBUG_NO_HIZ) {
+        brw->has_hiz = false;
+        /* On gen6, you can only do separate stencil with HIZ. */
+diff --git a/src/mesa/drivers/dri/i965/intel_screen.c b/src/mesa/drivers/dri/i965/intel_screen.c
+index c3bd30f7837..1feaf18219c 100644
+--- a/src/mesa/drivers/dri/i965/intel_screen.c
++++ b/src/mesa/drivers/dri/i965/intel_screen.c
+@@ -1870,7 +1870,17 @@ intel_init_bufmgr(struct intel_screen *screen)
+    if (getenv("INTEL_NO_HW") != NULL)
+       screen->no_hw = true;
+ 
+-   screen->bufmgr = brw_bufmgr_init(&screen->devinfo, dri_screen->fd);
++   bool bo_reuse = false;
++   int bo_reuse_mode = driQueryOptioni(&screen->optionCache, "bo_reuse");
++   switch (bo_reuse_mode) {
++   case DRI_CONF_BO_REUSE_DISABLED:
++      break;
++   case DRI_CONF_BO_REUSE_ALL:
++      bo_reuse = true;
++      break;
++   }
++
++   screen->bufmgr = brw_bufmgr_init(&screen->devinfo, dri_screen->fd, bo_reuse);
+    if (screen->bufmgr == NULL) {
+       fprintf(stderr, "[%s:%u] Error initializing buffer manager.\n",
+ 	      __func__, __LINE__);
+-- 
+2.23.0
+
diff --git a/SOURCES/0002-i965-store-DRM-fd-on-intel_screen.patch b/SOURCES/0002-i965-store-DRM-fd-on-intel_screen.patch
new file mode 100644
index 0000000..c53f5b7
--- /dev/null
+++ b/SOURCES/0002-i965-store-DRM-fd-on-intel_screen.patch
@@ -0,0 +1,307 @@
+From 649c8ed3f369aa11e3bdbb4784b61d2e6000cb6a Mon Sep 17 00:00:00 2001
+From: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
+Date: Fri, 6 Mar 2020 16:56:25 +0200
+Subject: [PATCH 2/8] i965: store DRM fd on intel_screen
+
+v2: Fix storing of drm fd (Ajax)
+
+[mustard: backport to 18.3.4 - ajax]
+
+Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
+(cherry picked from commit b9d3d93769a96d973e379673e712a11b408f7712)
+---
+ .../drivers/dri/i965/brw_performance_query.c  | 27 +++++++------------
+ src/mesa/drivers/dri/i965/brw_reset.c         |  6 ++---
+ src/mesa/drivers/dri/i965/intel_batchbuffer.c |  6 ++---
+ src/mesa/drivers/dri/i965/intel_screen.c      | 14 +++++-----
+ src/mesa/drivers/dri/i965/intel_screen.h      |  3 +++
+ 5 files changed, 22 insertions(+), 34 deletions(-)
+
+diff --git a/src/mesa/drivers/dri/i965/brw_performance_query.c b/src/mesa/drivers/dri/i965/brw_performance_query.c
+index 10e3d024f17..703c79c4f97 100644
+--- a/src/mesa/drivers/dri/i965/brw_performance_query.c
++++ b/src/mesa/drivers/dri/i965/brw_performance_query.c
+@@ -1103,7 +1103,6 @@ brw_begin_perf_query(struct gl_context *ctx,
+ 
+       /* If the OA counters aren't already on, enable them. */
+       if (brw->perfquery.oa_stream_fd == -1) {
+-         __DRIscreen *screen = brw->screen->driScrnPriv;
+          const struct gen_device_info *devinfo = &brw->screen->devinfo;
+ 
+          /* The period_exponent gives a sampling period as follows:
+@@ -1163,7 +1162,7 @@ brw_begin_perf_query(struct gl_context *ctx,
+                                        metric_id,
+                                        query->oa_format,
+                                        period_exponent,
+-                                       screen->fd, /* drm fd */
++                                       brw->screen->fd, /* drm fd */
+                                        brw->hw_ctx))
+             return false;
+       } else {
+@@ -1847,8 +1846,6 @@ enumerate_sysfs_metrics(struct brw_context *brw)
+ static bool
+ kernel_has_dynamic_config_support(struct brw_context *brw)
+ {
+-   __DRIscreen *screen = brw->screen->driScrnPriv;
+-
+    hash_table_foreach(brw->perfquery.oa_metrics_table, entry) {
+       struct brw_perf_query_info *query = entry->data;
+       char config_path[280];
+@@ -1859,7 +1856,7 @@ kernel_has_dynamic_config_support(struct brw_context *brw)
+ 
+       /* Look for the test config, which we know we can't replace. */
+       if (read_file_uint64(config_path, &config_id) && config_id == 1) {
+-         return drmIoctl(screen->fd, DRM_IOCTL_I915_PERF_REMOVE_CONFIG,
++         return drmIoctl(brw->screen->fd, DRM_IOCTL_I915_PERF_REMOVE_CONFIG,
+                          &config_id) < 0 && errno == ENOENT;
+       }
+    }
+@@ -1870,8 +1867,6 @@ kernel_has_dynamic_config_support(struct brw_context *brw)
+ static void
+ init_oa_configs(struct brw_context *brw)
+ {
+-   __DRIscreen *screen = brw->screen->driScrnPriv;
+-
+    hash_table_foreach(brw->perfquery.oa_metrics_table, entry) {
+       const struct brw_perf_query_info *query = entry->data;
+       struct drm_i915_perf_oa_config config;
+@@ -1902,7 +1897,7 @@ init_oa_configs(struct brw_context *brw)
+       config.n_flex_regs = query->n_flex_regs;
+       config.flex_regs_ptr = (uintptr_t) query->flex_regs;
+ 
+-      ret = drmIoctl(screen->fd, DRM_IOCTL_I915_PERF_ADD_CONFIG, &config);
++      ret = drmIoctl(brw->screen->fd, DRM_IOCTL_I915_PERF_ADD_CONFIG, &config);
+       if (ret < 0) {
+          DBG("Failed to load \"%s\" (%s) metrics set in kernel: %s\n",
+              query->name, query->guid, strerror(errno));
+@@ -1917,7 +1912,6 @@ init_oa_configs(struct brw_context *brw)
+ static bool
+ query_topology(struct brw_context *brw)
+ {
+-   __DRIscreen *screen = brw->screen->driScrnPriv;
+    struct drm_i915_query_item item = {
+       .query_id = DRM_I915_QUERY_TOPOLOGY_INFO,
+    };
+@@ -1926,14 +1920,14 @@ query_topology(struct brw_context *brw)
+       .items_ptr = (uintptr_t) &item,
+    };
+ 
+-   if (drmIoctl(screen->fd, DRM_IOCTL_I915_QUERY, &query))
++   if (drmIoctl(brw->screen->fd, DRM_IOCTL_I915_QUERY, &query))
+       return false;
+ 
+    struct drm_i915_query_topology_info *topo_info =
+       (struct drm_i915_query_topology_info *) calloc(1, item.length);
+    item.data_ptr = (uintptr_t) topo_info;
+ 
+-   if (drmIoctl(screen->fd, DRM_IOCTL_I915_QUERY, &query) ||
++   if (drmIoctl(brw->screen->fd, DRM_IOCTL_I915_QUERY, &query) ||
+        item.length <= 0)
+       return false;
+ 
+@@ -1948,21 +1942,20 @@ query_topology(struct brw_context *brw)
+ static bool
+ getparam_topology(struct brw_context *brw)
+ {
+-   __DRIscreen *screen = brw->screen->driScrnPriv;
+    drm_i915_getparam_t gp;
+    int ret;
+ 
+    int slice_mask = 0;
+    gp.param = I915_PARAM_SLICE_MASK;
+    gp.value = &slice_mask;
+-   ret = drmIoctl(screen->fd, DRM_IOCTL_I915_GETPARAM, &gp);
++   ret = drmIoctl(brw->screen->fd, DRM_IOCTL_I915_GETPARAM, &gp);
+    if (ret)
+       return false;
+ 
+    int subslice_mask = 0;
+    gp.param = I915_PARAM_SUBSLICE_MASK;
+    gp.value = &subslice_mask;
+-   ret = drmIoctl(screen->fd, DRM_IOCTL_I915_GETPARAM, &gp);
++   ret = drmIoctl(brw->screen->fd, DRM_IOCTL_I915_GETPARAM, &gp);
+    if (ret)
+       return false;
+ 
+@@ -2013,7 +2006,6 @@ init_oa_sys_vars(struct brw_context *brw)
+ {
+    const struct gen_device_info *devinfo = &brw->screen->devinfo;
+    uint64_t min_freq_mhz = 0, max_freq_mhz = 0;
+-   __DRIscreen *screen = brw->screen->driScrnPriv;
+ 
+    if (!read_sysfs_drm_device_file_uint64(brw, "gt_min_freq_mhz", &min_freq_mhz))
+       return false;
+@@ -2041,7 +2033,7 @@ init_oa_sys_vars(struct brw_context *brw)
+    brw->perfquery.sys_vars.gt_min_freq = min_freq_mhz * 1000000;
+    brw->perfquery.sys_vars.gt_max_freq = max_freq_mhz * 1000000;
+    brw->perfquery.sys_vars.timestamp_frequency = devinfo->timestamp_frequency;
+-   brw->perfquery.sys_vars.revision = intel_device_get_revision(screen->fd);
++   brw->perfquery.sys_vars.revision = intel_device_get_revision(brw->screen->fd);
+    compute_topology_builtins(brw);
+ 
+    return true;
+@@ -2050,7 +2042,6 @@ init_oa_sys_vars(struct brw_context *brw)
+ static bool
+ get_sysfs_dev_dir(struct brw_context *brw)
+ {
+-   __DRIscreen *screen = brw->screen->driScrnPriv;
+    struct stat sb;
+    int min, maj;
+    DIR *drmdir;
+@@ -2059,7 +2050,7 @@ get_sysfs_dev_dir(struct brw_context *brw)
+ 
+    brw->perfquery.sysfs_dev_dir[0] = '\0';
+ 
+-   if (fstat(screen->fd, &sb)) {
++   if (fstat(brw->screen->fd, &sb)) {
+       DBG("Failed to stat DRM fd\n");
+       return false;
+    }
+diff --git a/src/mesa/drivers/dri/i965/brw_reset.c b/src/mesa/drivers/dri/i965/brw_reset.c
+index ad8c44f2d1c..90518780eb8 100644
+--- a/src/mesa/drivers/dri/i965/brw_reset.c
++++ b/src/mesa/drivers/dri/i965/brw_reset.c
+@@ -35,7 +35,6 @@ GLenum
+ brw_get_graphics_reset_status(struct gl_context *ctx)
+ {
+    struct brw_context *brw = brw_context(ctx);
+-   __DRIscreen *dri_screen = brw->screen->driScrnPriv;
+    struct drm_i915_reset_stats stats = { .ctx_id = brw->hw_ctx };
+ 
+    /* If hardware contexts are not being used (or
+@@ -51,7 +50,7 @@ brw_get_graphics_reset_status(struct gl_context *ctx)
+    if (brw->reset_count != 0)
+       return GL_NO_ERROR;
+ 
+-   if (drmIoctl(dri_screen->fd, DRM_IOCTL_I915_GET_RESET_STATS, &stats) != 0)
++   if (drmIoctl(brw->screen->fd, DRM_IOCTL_I915_GET_RESET_STATS, &stats) != 0)
+       return GL_NO_ERROR;
+ 
+    /* A reset was observed while a batch from this context was executing.
+@@ -77,10 +76,9 @@ brw_get_graphics_reset_status(struct gl_context *ctx)
+ void
+ brw_check_for_reset(struct brw_context *brw)
+ {
+-   __DRIscreen *dri_screen = brw->screen->driScrnPriv;
+    struct drm_i915_reset_stats stats = { .ctx_id = brw->hw_ctx };
+ 
+-   if (drmIoctl(dri_screen->fd, DRM_IOCTL_I915_GET_RESET_STATS, &stats) != 0)
++   if (drmIoctl(brw->screen->fd, DRM_IOCTL_I915_GET_RESET_STATS, &stats) != 0)
+       return;
+ 
+    if (stats.batch_active > 0 || stats.batch_pending > 0)
+diff --git a/src/mesa/drivers/dri/i965/intel_batchbuffer.c b/src/mesa/drivers/dri/i965/intel_batchbuffer.c
+index 6207de5a06f..7237e51ab5a 100644
+--- a/src/mesa/drivers/dri/i965/intel_batchbuffer.c
++++ b/src/mesa/drivers/dri/i965/intel_batchbuffer.c
+@@ -683,8 +683,7 @@ throttle(struct brw_context *brw)
+    }
+ 
+    if (brw->need_flush_throttle) {
+-      __DRIscreen *dri_screen = brw->screen->driScrnPriv;
+-      drmCommandNone(dri_screen->fd, DRM_I915_GEM_THROTTLE);
++      drmCommandNone(brw->screen->fd, DRM_I915_GEM_THROTTLE);
+       brw->need_flush_throttle = false;
+    }
+ }
+@@ -749,7 +748,6 @@ execbuffer(int fd,
+ static int
+ submit_batch(struct brw_context *brw, int in_fence_fd, int *out_fence_fd)
+ {
+-   __DRIscreen *dri_screen = brw->screen->driScrnPriv;
+    struct intel_batchbuffer *batch = &brw->batch;
+    int ret = 0;
+ 
+@@ -816,7 +814,7 @@ submit_batch(struct brw_context *brw, int in_fence_fd, int *out_fence_fd)
+          batch->exec_bos[index] = tmp_bo;
+       }
+ 
+-      ret = execbuffer(dri_screen->fd, batch, brw->hw_ctx,
++      ret = execbuffer(brw->screen->fd, batch, brw->hw_ctx,
+                        4 * USED_BATCH(*batch),
+                        in_fence_fd, out_fence_fd, flags);
+ 
+diff --git a/src/mesa/drivers/dri/i965/intel_screen.c b/src/mesa/drivers/dri/i965/intel_screen.c
+index 1feaf18219c..3e02c11700c 100644
+--- a/src/mesa/drivers/dri/i965/intel_screen.c
++++ b/src/mesa/drivers/dri/i965/intel_screen.c
+@@ -1636,7 +1636,7 @@ intel_get_param(struct intel_screen *screen, int param, int *value)
+    gp.param = param;
+    gp.value = value;
+ 
+-   if (drmIoctl(screen->driScrnPriv->fd, DRM_IOCTL_I915_GETPARAM, &gp) == -1) {
++   if (drmIoctl(screen->fd, DRM_IOCTL_I915_GETPARAM, &gp) == -1) {
+       ret = -errno;
+       if (ret != -EINVAL)
+          _mesa_warning(NULL, "drm_i915_getparam: %d", ret);
+@@ -1865,8 +1865,6 @@ err_out:
+ static bool
+ intel_init_bufmgr(struct intel_screen *screen)
+ {
+-   __DRIscreen *dri_screen = screen->driScrnPriv;
+-
+    if (getenv("INTEL_NO_HW") != NULL)
+       screen->no_hw = true;
+ 
+@@ -1880,7 +1878,7 @@ intel_init_bufmgr(struct intel_screen *screen)
+       break;
+    }
+ 
+-   screen->bufmgr = brw_bufmgr_init(&screen->devinfo, dri_screen->fd, bo_reuse);
++   screen->bufmgr = brw_bufmgr_init(&screen->devinfo, screen->fd, bo_reuse);
+    if (screen->bufmgr == NULL) {
+       fprintf(stderr, "[%s:%u] Error initializing buffer manager.\n",
+ 	      __func__, __LINE__);
+@@ -2038,8 +2036,7 @@ intel_detect_pipelined_register(struct intel_screen *screen,
+    /* Don't bother with error checking - if the execbuf fails, the
+     * value won't be written and we'll just report that there's no access.
+     */
+-   __DRIscreen *dri_screen = screen->driScrnPriv;
+-   drmIoctl(dri_screen->fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf);
++   drmIoctl(screen->fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf);
+ 
+    /* Check whether the value got written. */
+    void *results_map = brw_bo_map(NULL, results, MAP_READ);
+@@ -2475,6 +2472,7 @@ __DRIconfig **intelInitScreen2(__DRIscreen *dri_screen)
+    screen->driScrnPriv = dri_screen;
+    dri_screen->driverPrivate = (void *) screen;
+ 
++   screen->fd = dri_screen->fd;
+    screen->deviceID = gen_get_pci_device_id_override();
+    if (screen->deviceID < 0)
+       screen->deviceID = intel_get_integer(screen, I915_PARAM_CHIPSET_ID);
+@@ -2531,7 +2529,7 @@ __DRIconfig **intelInitScreen2(__DRIscreen *dri_screen)
+       screen->max_gtt_map_object_size = gtt_size / 4;
+    }
+ 
+-   screen->aperture_threshold = get_aperture_size(dri_screen->fd) * 3 / 4;
++   screen->aperture_threshold = get_aperture_size(screen->fd) * 3 / 4;
+ 
+    screen->hw_has_swizzling = intel_detect_swizzling(screen);
+    screen->hw_has_timestamp = intel_detect_timestamp(screen);
+@@ -2720,7 +2718,7 @@ __DRIconfig **intelInitScreen2(__DRIscreen *dri_screen)
+       struct drm_i915_reset_stats stats;
+       memset(&stats, 0, sizeof(stats));
+ 
+-      const int ret = drmIoctl(dri_screen->fd, DRM_IOCTL_I915_GET_RESET_STATS, &stats);
++      const int ret = drmIoctl(screen->fd, DRM_IOCTL_I915_GET_RESET_STATS, &stats);
+ 
+       screen->has_context_reset_notification =
+          (ret != -1 || errno != EINVAL);
+diff --git a/src/mesa/drivers/dri/i965/intel_screen.h b/src/mesa/drivers/dri/i965/intel_screen.h
+index 8d56fcd9e7a..6145afd56c5 100644
+--- a/src/mesa/drivers/dri/i965/intel_screen.h
++++ b/src/mesa/drivers/dri/i965/intel_screen.h
+@@ -56,6 +56,9 @@ struct intel_screen
+    /** Bytes of aperture usage beyond which execbuf is likely to fail. */
+    uint64_t aperture_threshold;
+ 
++   /** DRM fd associated with this screen. Not owned by this object. Do not close. */
++   int fd;
++
+    bool no_hw;
+    bool hw_has_swizzling;
+    bool has_exec_fence; /**< I915_PARAM_HAS_EXEC_FENCE */
+-- 
+2.23.0
+
diff --git a/SOURCES/0003-i965-share-buffer-managers-across-screens.patch b/SOURCES/0003-i965-share-buffer-managers-across-screens.patch
new file mode 100644
index 0000000..bca965a
--- /dev/null
+++ b/SOURCES/0003-i965-share-buffer-managers-across-screens.patch
@@ -0,0 +1,239 @@
+From f2ccb19e3e15a04fda47f8b0fcb08e32903031a1 Mon Sep 17 00:00:00 2001
+From: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
+Date: Fri, 6 Mar 2020 17:06:25 +0200
+Subject: [PATCH 3/8] i965: share buffer managers across screens
+
+Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
+---
+ src/mesa/drivers/dri/i965/brw_bufmgr.c   | 84 ++++++++++++++++++++++--
+ src/mesa/drivers/dri/i965/brw_bufmgr.h   | 11 ++--
+ src/mesa/drivers/dri/i965/intel_screen.c |  7 +-
+ 3 files changed, 92 insertions(+), 10 deletions(-)
+
+diff --git a/src/mesa/drivers/dri/i965/brw_bufmgr.c b/src/mesa/drivers/dri/i965/brw_bufmgr.c
+index e676fbd9d18..32758f2b9ff 100644
+--- a/src/mesa/drivers/dri/i965/brw_bufmgr.c
++++ b/src/mesa/drivers/dri/i965/brw_bufmgr.c
+@@ -139,6 +139,10 @@ struct bo_cache_bucket {
+ };
+ 
+ struct brw_bufmgr {
++   uint32_t refcount;
++
++   struct list_head link;
++
+    int fd;
+ 
+    mtx_t lock;
+@@ -160,6 +164,12 @@ struct brw_bufmgr {
+    uint64_t initial_kflags;
+ };
+ 
++static mtx_t global_bufmgr_list_mutex = _MTX_INITIALIZER_NP;
++static struct list_head global_bufmgr_list = {
++   .next = &global_bufmgr_list,
++   .prev = &global_bufmgr_list,
++};
++
+ static int bo_set_tiling_internal(struct brw_bo *bo, uint32_t tiling_mode,
+                                   uint32_t stride);
+ 
+@@ -1292,8 +1302,19 @@ brw_bo_wait(struct brw_bo *bo, int64_t timeout_ns)
+ }
+ 
+ void
+-brw_bufmgr_destroy(struct brw_bufmgr *bufmgr)
++brw_bufmgr_unref(struct brw_bufmgr *bufmgr)
+ {
++   mtx_lock(&global_bufmgr_list_mutex);
++   if (p_atomic_dec_zero(&bufmgr->refcount)) {
++      list_del(&bufmgr->link);
++   } else {
++      bufmgr = NULL;
++   }
++   mtx_unlock(&global_bufmgr_list_mutex);
++
++   if (!bufmgr)
++      return;
++
+    mtx_destroy(&bufmgr->lock);
+ 
+    /* Free any cached buffer objects we were going to reuse */
+@@ -1322,6 +1343,9 @@ brw_bufmgr_destroy(struct brw_bufmgr *bufmgr)
+       }
+    }
+ 
++   close(bufmgr->fd);
++   bufmgr->fd = -1;
++
+    free(bufmgr);
+ }
+ 
+@@ -1664,14 +1688,21 @@ brw_using_softpin(struct brw_bufmgr *bufmgr)
+    return bufmgr->initial_kflags & EXEC_OBJECT_PINNED;
+ }
+ 
++static struct brw_bufmgr *
++brw_bufmgr_ref(struct brw_bufmgr *bufmgr)
++{
++   p_atomic_inc(&bufmgr->refcount);
++   return bufmgr;
++}
++
+ /**
+  * Initializes the GEM buffer manager, which uses the kernel to allocate, map,
+  * and manage map buffer objections.
+  *
+  * \param fd File descriptor of the opened DRM device.
+  */
+-struct brw_bufmgr *
+-brw_bufmgr_init(struct gen_device_info *devinfo, int fd, bool bo_reuse)
++static struct brw_bufmgr *
++brw_bufmgr_create(struct gen_device_info *devinfo, int fd, bool bo_reuse)
+ {
+    struct brw_bufmgr *bufmgr;
+ 
+@@ -1688,9 +1719,16 @@ brw_bufmgr_init(struct gen_device_info *devinfo, int fd, bool bo_reuse)
+     * Don't do this! Ensure that each library/bufmgr has its own device
+     * fd so that its namespace does not clash with another.
+     */
+-   bufmgr->fd = fd;
++   bufmgr->fd = dup(fd);
++   if (bufmgr->fd < 0) {
++      free(bufmgr);
++      return NULL;
++   }
++
++   p_atomic_set(&bufmgr->refcount, 1);
+ 
+    if (mtx_init(&bufmgr->lock, mtx_plain) != 0) {
++      close(bufmgr->fd);
+       free(bufmgr);
+       return NULL;
+    }
+@@ -1725,6 +1763,7 @@ brw_bufmgr_init(struct gen_device_info *devinfo, int fd, bool bo_reuse)
+           * might actually mean requiring 4.14.
+           */
+          fprintf(stderr, "i965 requires softpin (Kernel 4.5) on Gen10+.");
++         close(bufmgr->fd);
+          free(bufmgr);
+          return NULL;
+       }
+@@ -1739,3 +1778,40 @@ brw_bufmgr_init(struct gen_device_info *devinfo, int fd, bool bo_reuse)
+ 
+    return bufmgr;
+ }
++
++struct brw_bufmgr *
++brw_bufmgr_get_for_fd(struct gen_device_info *devinfo, int fd, bool bo_reuse)
++{
++   struct stat st;
++
++   if (fstat(fd, &st))
++      return NULL;
++
++   struct brw_bufmgr *bufmgr = NULL;
++
++   mtx_lock(&global_bufmgr_list_mutex);
++   list_for_each_entry(struct brw_bufmgr, iter_bufmgr, &global_bufmgr_list, link) {
++      struct stat iter_st;
++      if (fstat(iter_bufmgr->fd, &iter_st))
++         continue;
++
++      if (st.st_rdev == iter_st.st_rdev) {
++         bufmgr = brw_bufmgr_ref(iter_bufmgr);
++         goto unlock;
++      }
++   }
++
++   bufmgr = brw_bufmgr_create(devinfo, fd, bo_reuse);
++   list_addtail(&bufmgr->link, &global_bufmgr_list);
++
++ unlock:
++   mtx_unlock(&global_bufmgr_list_mutex);
++
++   return bufmgr;
++}
++
++int
++brw_bufmgr_get_fd(struct brw_bufmgr *bufmgr)
++{
++   return bufmgr->fd;
++}
+diff --git a/src/mesa/drivers/dri/i965/brw_bufmgr.h b/src/mesa/drivers/dri/i965/brw_bufmgr.h
+index a85c8f37bef..3d8729da487 100644
+--- a/src/mesa/drivers/dri/i965/brw_bufmgr.h
++++ b/src/mesa/drivers/dri/i965/brw_bufmgr.h
+@@ -300,9 +300,9 @@ int brw_bo_subdata(struct brw_bo *bo, uint64_t offset,
+ void brw_bo_wait_rendering(struct brw_bo *bo);
+ 
+ /**
+- * Tears down the buffer manager instance.
++ * Unref a buffer manager instance.
+  */
+-void brw_bufmgr_destroy(struct brw_bufmgr *bufmgr);
++void brw_bufmgr_unref(struct brw_bufmgr *bufmgr);
+ 
+ /**
+  * Get the current tiling (and resulting swizzling) mode for the bo.
+@@ -343,8 +343,9 @@ int brw_bo_busy(struct brw_bo *bo);
+ int brw_bo_madvise(struct brw_bo *bo, int madv);
+ 
+ /* drm_bacon_bufmgr_gem.c */
+-struct brw_bufmgr *brw_bufmgr_init(struct gen_device_info *devinfo, int fd,
+-                                   bool bo_reuse);
++struct brw_bufmgr *brw_bufmgr_get_for_fd(struct gen_device_info *devinfo, int fd,
++                                         bool bo_reuse);
++
+ struct brw_bo *brw_bo_gem_create_from_name(struct brw_bufmgr *bufmgr,
+                                            const char *name,
+                                            unsigned int handle);
+@@ -359,6 +360,8 @@ int brw_hw_context_set_priority(struct brw_bufmgr *bufmgr,
+ 
+ void brw_destroy_hw_context(struct brw_bufmgr *bufmgr, uint32_t ctx_id);
+ 
++int brw_bufmgr_get_fd(struct brw_bufmgr *bufmgr);
++
+ int brw_bo_gem_export_to_prime(struct brw_bo *bo, int *prime_fd);
+ struct brw_bo *brw_bo_gem_create_from_prime(struct brw_bufmgr *bufmgr,
+                                             int prime_fd);
+diff --git a/src/mesa/drivers/dri/i965/intel_screen.c b/src/mesa/drivers/dri/i965/intel_screen.c
+index 3e02c11700c..c374837c4a1 100644
+--- a/src/mesa/drivers/dri/i965/intel_screen.c
++++ b/src/mesa/drivers/dri/i965/intel_screen.c
+@@ -1668,7 +1668,7 @@ intelDestroyScreen(__DRIscreen * sPriv)
+ {
+    struct intel_screen *screen = sPriv->driverPrivate;
+ 
+-   brw_bufmgr_destroy(screen->bufmgr);
++   brw_bufmgr_unref(screen->bufmgr);
+    driDestroyOptionInfo(&screen->optionCache);
+ 
+    disk_cache_destroy(screen->disk_cache);
+@@ -1865,6 +1865,8 @@ err_out:
+ static bool
+ intel_init_bufmgr(struct intel_screen *screen)
+ {
++   __DRIscreen *dri_screen = screen->driScrnPriv;
++
+    if (getenv("INTEL_NO_HW") != NULL)
+       screen->no_hw = true;
+ 
+@@ -1878,12 +1880,13 @@ intel_init_bufmgr(struct intel_screen *screen)
+       break;
+    }
+ 
+-   screen->bufmgr = brw_bufmgr_init(&screen->devinfo, screen->fd, bo_reuse);
++   screen->bufmgr = brw_bufmgr_get_for_fd(&screen->devinfo, dri_screen->fd, bo_reuse);
+    if (screen->bufmgr == NULL) {
+       fprintf(stderr, "[%s:%u] Error initializing buffer manager.\n",
+ 	      __func__, __LINE__);
+       return false;
+    }
++   screen->fd = brw_bufmgr_get_fd(screen->bufmgr);
+ 
+    if (!intel_get_boolean(screen, I915_PARAM_HAS_EXEC_NO_RELOC)) {
+       fprintf(stderr, "[%s: %u] Kernel 3.9 required.\n", __func__, __LINE__);
+-- 
+2.23.0
+
diff --git a/SOURCES/0004-util-Add-os_same_file_description-helper.patch b/SOURCES/0004-util-Add-os_same_file_description-helper.patch
new file mode 100644
index 0000000..c5c2474
--- /dev/null
+++ b/SOURCES/0004-util-Add-os_same_file_description-helper.patch
@@ -0,0 +1,273 @@
+From cd24e64b088c692c74f4383241df8d48d1007b31 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Michel=20D=C3=A4nzer?= <mdaenzer@redhat.com>
+Date: Mon, 6 Jan 2020 18:24:52 +0100
+Subject: [PATCH 4/8] util: Add os_same_file_description helper
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Acked-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
+Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3202>
+
+(cherry picked from commit f76cbc7901f7d500f5a4f74aedfd29970d1efd00)
+
+Signed-off-by: Michel Dänzer <mdaenzer@redhat.com>
+---
+ src/util/Makefile.sources |   2 +
+ src/util/meson.build      |   1 +
+ src/util/os_file.c        | 165 ++++++++++++++++++++++++++++++++++++++
+ src/util/os_file.h        |  45 +++++++++++
+ 4 files changed, 213 insertions(+)
+ create mode 100644 src/util/os_file.c
+ create mode 100644 src/util/os_file.h
+
+diff --git a/src/util/Makefile.sources b/src/util/Makefile.sources
+index b4d23947ab7..02e7a5e598b 100644
+--- a/src/util/Makefile.sources
++++ b/src/util/Makefile.sources
+@@ -27,6 +27,8 @@ MESA_UTIL_FILES := \
+ 	mesa-sha1.h \
+ 	os_time.c \
+ 	os_time.h \
++	os_file.c \
++	os_file.h \
+ 	os_misc.c \
+ 	os_misc.h \
+ 	u_process.c \
+diff --git a/src/util/meson.build b/src/util/meson.build
+index 156621aff65..d612e31952d 100644
+--- a/src/util/meson.build
++++ b/src/util/meson.build
+@@ -51,6 +51,7 @@ files_mesa_util = files(
+   'mesa-sha1.h',
+   'os_time.c',
+   'os_time.h',
++  'os_file.c',
+   'os_misc.c',
+   'os_misc.h',
+   'u_process.c',
+diff --git a/src/util/os_file.c b/src/util/os_file.c
+new file mode 100644
+index 00000000000..b502ff4b0ef
+--- /dev/null
++++ b/src/util/os_file.c
+@@ -0,0 +1,165 @@
++/*
++ * Copyright 2019 Intel Corporation
++ * SPDX-License-Identifier: MIT
++ */
++
++#include "os_file.h"
++
++#include <errno.h>
++#include <fcntl.h>
++#include <stdlib.h>
++#include <sys/stat.h>
++
++
++#if defined(WIN32)
++#include <io.h>
++#define open _open
++#define fdopen _fdopen
++#define O_CREAT _O_CREAT
++#define O_EXCL _O_EXCL
++#define O_WRONLY _O_WRONLY
++#endif
++
++
++FILE *
++os_file_create_unique(const char *filename, int filemode)
++{
++   int fd = open(filename, O_CREAT | O_EXCL | O_WRONLY, filemode);
++   if (fd == -1)
++      return NULL;
++   return fdopen(fd, "w");
++}
++
++
++#if defined(__linux__)
++
++#include <fcntl.h>
++#include <linux/kcmp.h>
++#include <sys/stat.h>
++#include <sys/syscall.h>
++#include <unistd.h>
++
++
++static ssize_t
++readN(int fd, char *buf, size_t len)
++{
++   int err = -ENODATA;
++   size_t total = 0;
++   do {
++      ssize_t ret = read(fd, buf + total, len - total);
++
++      if (ret < 0)
++         ret = -errno;
++
++      if (ret == -EINTR || ret == -EAGAIN)
++         continue;
++
++      if (ret <= 0) {
++         err = ret;
++         break;
++      }
++
++      total += ret;
++   } while (total != len);
++
++   return total ? (ssize_t)total : err;
++}
++
++char *
++os_read_file(const char *filename)
++{
++   /* Note that this also serves as a slight margin to avoid a 2x grow when
++    * the file is just a few bytes larger when we read it than when we
++    * fstat'ed it.
++    * The string's NULL terminator is also included in here.
++    */
++   size_t len = 64;
++
++   int fd = open(filename, O_RDONLY);
++   if (fd == -1) {
++      /* errno set by open() */
++      return NULL;
++   }
++
++   /* Pre-allocate a buffer at least the size of the file if we can read
++    * that information.
++    */
++   struct stat stat;
++   if (fstat(fd, &stat) == 0)
++      len += stat.st_size;
++
++   char *buf = malloc(len);
++   if (!buf) {
++      close(fd);
++      errno = -ENOMEM;
++      return NULL;
++   }
++
++   ssize_t actually_read;
++   size_t offset = 0, remaining = len - 1;
++   while ((actually_read = readN(fd, buf + offset, remaining)) == (ssize_t)remaining) {
++      char *newbuf = realloc(buf, 2 * len);
++      if (!newbuf) {
++         free(buf);
++         close(fd);
++         errno = -ENOMEM;
++         return NULL;
++      }
++
++      buf = newbuf;
++      len *= 2;
++      offset += actually_read;
++      remaining = len - offset - 1;
++   }
++
++   close(fd);
++
++   if (actually_read > 0)
++      offset += actually_read;
++
++   /* Final resize to actual size */
++   len = offset + 1;
++   char *newbuf = realloc(buf, len);
++   if (!newbuf) {
++      free(buf);
++      errno = -ENOMEM;
++      return NULL;
++   }
++   buf = newbuf;
++
++   buf[offset] = '\0';
++
++   return buf;
++}
++
++bool
++os_same_file_description(int fd1, int fd2)
++{
++   pid_t pid = getpid();
++
++   return syscall(SYS_kcmp, pid, pid, KCMP_FILE, fd1, fd2) == 0;
++}
++
++#else
++
++#include "u_debug.h"
++
++char *
++os_read_file(const char *filename)
++{
++   errno = -ENOSYS;
++   return NULL;
++}
++
++bool
++os_same_file_description(int fd1, int fd2)
++{
++   if (fd1 == fd2)
++      return true;
++
++   debug_warn_once("Can't tell if different file descriptors reference the same"
++                   " file description, false negatives might cause trouble!\n");
++   return false;
++}
++
++#endif
+diff --git a/src/util/os_file.h b/src/util/os_file.h
+new file mode 100644
+index 00000000000..1972beba32b
+--- /dev/null
++++ b/src/util/os_file.h
+@@ -0,0 +1,45 @@
++/*
++ * Copyright 2019 Intel Corporation
++ * SPDX-License-Identifier: MIT
++ *
++ * File operations helpers
++ */
++
++#ifndef _OS_FILE_H_
++#define _OS_FILE_H_
++
++#include <stdbool.h>
++#include <stdio.h>
++
++#ifdef  __cplusplus
++extern "C" {
++#endif
++
++/*
++ * Create a new file and opens it for writing-only.
++ * If the given filename already exists, nothing is done and NULL is returned.
++ * `errno` gets set to the failure reason; if that is not EEXIST, the caller
++ * might want to do something other than trying again.
++ */
++FILE *
++os_file_create_unique(const char *filename, int filemode);
++
++/*
++ * Read a file.
++ * Returns a char* that the caller must free(), or NULL and sets errno.
++ */
++char *
++os_read_file(const char *filename);
++
++/*
++ * Returns true if the two file descriptors passed in can be determined to
++ * reference the same file description, false otherwise
++ */
++bool
++os_same_file_description(int fd1, int fd2);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* _OS_FILE_H_ */
+-- 
+2.26.2
+
diff --git a/SOURCES/0005-util-remove-the-dependency-on-kcmp.h.patch b/SOURCES/0005-util-remove-the-dependency-on-kcmp.h.patch
new file mode 100644
index 0000000..534be6d
--- /dev/null
+++ b/SOURCES/0005-util-remove-the-dependency-on-kcmp.h.patch
@@ -0,0 +1,43 @@
+From a75e8b98e0c043d02df7014b63520063c8191a62 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= <marek.olsak@amd.com>
+Date: Tue, 18 Feb 2020 16:12:23 -0500
+Subject: [PATCH 5/8] util: remove the dependency on kcmp.h
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Fixes: f76cbc7901f7 "util: Add os_same_file_description helper"
+
+Acked-by: Eric Engestrom <eric@engestrom.ch>
+Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
+Tested-by: Marge Bot <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3860>
+Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3860>
+
+(cherry picked from commit f7bfb10c69dfe48a91e35523cb5ee641bdbf6988)
+
+Signed-off-by: Michel Dänzer <mdaenzer@redhat.com>
+---
+ src/util/os_file.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/src/util/os_file.c b/src/util/os_file.c
+index b502ff4b0ef..128fe872db1 100644
+--- a/src/util/os_file.c
++++ b/src/util/os_file.c
+@@ -34,11 +34,12 @@ os_file_create_unique(const char *filename, int filemode)
+ #if defined(__linux__)
+ 
+ #include <fcntl.h>
+-#include <linux/kcmp.h>
+ #include <sys/stat.h>
+ #include <sys/syscall.h>
+ #include <unistd.h>
+ 
++/* copied from <linux/kcmp.h> */
++#define KCMP_FILE 0
+ 
+ static ssize_t
+ readN(int fd, char *buf, size_t len)
+-- 
+2.26.2
+
diff --git a/SOURCES/0006-util-Change-os_same_file_description-return-type-fro.patch b/SOURCES/0006-util-Change-os_same_file_description-return-type-fro.patch
new file mode 100644
index 0000000..8d38ebe
--- /dev/null
+++ b/SOURCES/0006-util-Change-os_same_file_description-return-type-fro.patch
@@ -0,0 +1,99 @@
+From 0de5ad2f5083fcf19e579f5a70641e0da0e70dc4 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Michel=20D=C3=A4nzer?= <mdaenzer@redhat.com>
+Date: Tue, 18 Feb 2020 19:04:00 +0100
+Subject: [PATCH 6/8] util: Change os_same_file_description return type from
+ bool to int
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This allows communicating that it wasn't possible to determine whether
+the two file descriptors reference the same file description. When
+that's the case, log a warning in the amdgpu winsys.
+
+In turn, remove the corresponding debugging output from the fallback
+os_same_file_description implementation. It depends on the caller if
+false negatives are problematic or not.
+
+Reviewed-by: Eric Engestrom <eric@engestrom.ch>
+Reviewed-by: Marek Olšák <marek.olsak@amd.com>
+Tested-by: Marge Bot <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3879>
+Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3879>
+
+(cherry picked from commit f5a8958910f53d924d062cbf024cebe4134f757a)
+
+Signed-off-by: Michel Dänzer <mdaenzer@redhat.com>
+---
+ src/util/os_file.c | 18 +++++++++++-------
+ src/util/os_file.h | 10 +++++++---
+ 2 files changed, 18 insertions(+), 10 deletions(-)
+
+diff --git a/src/util/os_file.c b/src/util/os_file.c
+index 128fe872db1..228f1e823c5 100644
+--- a/src/util/os_file.c
++++ b/src/util/os_file.c
+@@ -133,12 +133,16 @@ os_read_file(const char *filename)
+    return buf;
+ }
+ 
+-bool
++int
+ os_same_file_description(int fd1, int fd2)
+ {
+    pid_t pid = getpid();
+ 
+-   return syscall(SYS_kcmp, pid, pid, KCMP_FILE, fd1, fd2) == 0;
++   /* Same file descriptor trivially implies same file description */
++   if (fd1 == fd2)
++      return 0;
++
++   return syscall(SYS_kcmp, pid, pid, KCMP_FILE, fd1, fd2);
+ }
+ 
+ #else
+@@ -152,15 +156,15 @@ os_read_file(const char *filename)
+    return NULL;
+ }
+ 
+-bool
++int
+ os_same_file_description(int fd1, int fd2)
+ {
++   /* Same file descriptor trivially implies same file description */
+    if (fd1 == fd2)
+-      return true;
++      return 0;
+ 
+-   debug_warn_once("Can't tell if different file descriptors reference the same"
+-                   " file description, false negatives might cause trouble!\n");
+-   return false;
++   /* Otherwise we can't tell */
++   return -1;
+ }
+ 
+ #endif
+diff --git a/src/util/os_file.h b/src/util/os_file.h
+index 1972beba32b..58639476f60 100644
+--- a/src/util/os_file.h
++++ b/src/util/os_file.h
+@@ -32,10 +32,14 @@ char *
+ os_read_file(const char *filename);
+ 
+ /*
+- * Returns true if the two file descriptors passed in can be determined to
+- * reference the same file description, false otherwise
++ * Try to determine if two file descriptors reference the same file description
++ *
++ * Return values:
++ * - 0:   They reference the same file description
++ * - > 0: They do not reference the same file description
++ * - < 0: Unable to determine whether they reference the same file description
+  */
+-bool
++int
+ os_same_file_description(int fd1, int fd2);
+ 
+ #ifdef __cplusplus
+-- 
+2.26.2
+
diff --git a/SOURCES/0007-i965-don-t-forget-to-set-screen-on-duped-image.patch b/SOURCES/0007-i965-don-t-forget-to-set-screen-on-duped-image.patch
new file mode 100644
index 0000000..bf11827
--- /dev/null
+++ b/SOURCES/0007-i965-don-t-forget-to-set-screen-on-duped-image.patch
@@ -0,0 +1,38 @@
+From 7680f8685e8b5dccc58babecf451ceab77fd373b Mon Sep 17 00:00:00 2001
+From: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
+Date: Tue, 2 Jun 2020 11:52:35 +0300
+Subject: [PATCH 7/8] i965: don't forget to set screen on duped image
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+We'll start using this field more for querying image properties.
+Without it we run into a crash.
+
+Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
+Cc: <mesa-stable@lists.freedesktop.org>
+Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
+Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4861>
+
+(cherry picked from commit e41e820648b1cb662cbe938c73d755331d48c6db)
+
+Signed-off-by: Michel Dänzer <mdaenzer@redhat.com>
+---
+ src/mesa/drivers/dri/i965/intel_screen.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/mesa/drivers/dri/i965/intel_screen.c b/src/mesa/drivers/dri/i965/intel_screen.c
+index 93f0f8ef401..9c8b0814506 100644
+--- a/src/mesa/drivers/dri/i965/intel_screen.c
++++ b/src/mesa/drivers/dri/i965/intel_screen.c
+@@ -943,6 +943,7 @@ intel_dup_image(__DRIimage *orig_image, void *loaderPrivate)
+       return NULL;
+ 
+    brw_bo_reference(orig_image->bo);
++   image->screen          = orig_image->screen;
+    image->bo              = orig_image->bo;
+    image->internal_format = orig_image->internal_format;
+    image->planar_format   = orig_image->planar_format;
+-- 
+2.26.2
+
diff --git a/SOURCES/0008-i965-fix-export-of-GEM-handles.patch b/SOURCES/0008-i965-fix-export-of-GEM-handles.patch
new file mode 100644
index 0000000..5c02f7e
--- /dev/null
+++ b/SOURCES/0008-i965-fix-export-of-GEM-handles.patch
@@ -0,0 +1,342 @@
+From dfadbfc2c4c6dae3e2d21bfcccabb704d2fa6705 Mon Sep 17 00:00:00 2001
+From: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
+Date: Sat, 2 May 2020 16:59:19 +0300
+Subject: [PATCH 8/8] i965: fix export of GEM handles
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+We reuse DRM file descriptors internally. Therefore when we export a
+GEM handle we must do so in the file descriptor used externally.
+
+v2: Fix dmabuf leak
+    Fix GEM handle leaks by tracking exported handles
+
+v3: Check os_same_file_description error (Michel)
+    Don't create multiple exports for a given GEM table
+
+v4: Add WARN_ONCE (Ken)
+
+v5: Remove blank line (Ian)
+    Remove unused field (Ian)
+
+Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
+Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/2882
+Fixes: 4094558e8643 ("i965: share buffer managers across screens")
+Tested-by: Eric Engestrom <eric@engestrom.ch>
+Tested-by: Tapani Pälli <tapani.palli@intel.com>
+Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
+Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4861>
+
+(cherry picked from commit 57e4d0aa1c16d3be36ccee4065c55901cb6fad43)
+
+Signed-off-by: Michel Dänzer <mdaenzer@redhat.com>
+---
+ src/mesa/drivers/dri/i965/brw_bufmgr.c        | 120 +++++++++++++++++-
+ src/mesa/drivers/dri/i965/brw_bufmgr.h        |  20 +++
+ src/mesa/drivers/dri/i965/intel_batchbuffer.c |   6 +
+ src/mesa/drivers/dri/i965/intel_screen.c      |  11 +-
+ 4 files changed, 152 insertions(+), 5 deletions(-)
+
+diff --git a/src/mesa/drivers/dri/i965/brw_bufmgr.c b/src/mesa/drivers/dri/i965/brw_bufmgr.c
+index 72e61b6bee7..c64878c1275 100644
+--- a/src/mesa/drivers/dri/i965/brw_bufmgr.c
++++ b/src/mesa/drivers/dri/i965/brw_bufmgr.c
+@@ -61,6 +61,7 @@
+ #include "util/macros.h"
+ #include "util/hash_table.h"
+ #include "util/list.h"
++#include "util/os_file.h"
+ #include "util/u_dynarray.h"
+ #include "util/vma.h"
+ #include "brw_bufmgr.h"
+@@ -77,6 +78,20 @@
+ #define VG(x)
+ #endif
+ 
++/* Bufmgr is not aware of brw_context. */
++#undef WARN_ONCE
++#define WARN_ONCE(cond, fmt...) do {                            \
++   if (unlikely(cond)) {                                        \
++      static bool _warned = false;                              \
++      if (!_warned) {                                           \
++         fprintf(stderr, "WARNING: ");                          \
++         fprintf(stderr, fmt);                                  \
++         _warned = true;                                        \
++      }                                                         \
++   }                                                            \
++} while (0)
++
++
+ /* VALGRIND_FREELIKE_BLOCK unfortunately does not actually undo the earlier
+  * VALGRIND_MALLOCLIKE_BLOCK but instead leaves vg convinced the memory is
+  * leaked. All because it does not call VG(cli_free) from its
+@@ -138,6 +153,16 @@ struct bo_cache_bucket {
+    struct util_dynarray vma_list[BRW_MEMZONE_COUNT];
+ };
+ 
++struct bo_export {
++   /** File descriptor associated with a handle export. */
++   int drm_fd;
++
++   /** GEM handle in drm_fd */
++   uint32_t gem_handle;
++
++   struct list_head link;
++};
++
+ struct brw_bufmgr {
+    uint32_t refcount;
+ 
+@@ -496,6 +521,18 @@ brw_bo_cache_purge_bucket(struct brw_bufmgr *bufmgr,
+    }
+ }
+ 
++static struct brw_bo *
++bo_calloc(void)
++{
++   struct brw_bo *bo = calloc(1, sizeof(*bo));
++   if (!bo)
++      return NULL;
++
++   list_inithead(&bo->exports);
++
++   return bo;
++}
++
+ static struct brw_bo *
+ bo_alloc_internal(struct brw_bufmgr *bufmgr,
+                   const char *name,
+@@ -569,6 +606,7 @@ retry:
+       }
+ 
+       if (alloc_from_cache) {
++         assert(list_empty(&bo->exports));
+          if (!brw_bo_madvise(bo, I915_MADV_WILLNEED)) {
+             bo_free(bo);
+             brw_bo_cache_purge_bucket(bufmgr, bucket);
+@@ -601,7 +639,7 @@ retry:
+          bo->gtt_offset = 0ull;
+       }
+    } else {
+-      bo = calloc(1, sizeof(*bo));
++      bo = bo_calloc();
+       if (!bo)
+          goto err;
+ 
+@@ -772,11 +810,12 @@ brw_bo_gem_create_from_name(struct brw_bufmgr *bufmgr,
+     */
+    bo = hash_find_bo(bufmgr->handle_table, open_arg.handle);
+    if (bo) {
++      assert(list_empty(&bo->exports));
+       brw_bo_reference(bo);
+       goto out;
+    }
+ 
+-   bo = calloc(1, sizeof(*bo));
++   bo = bo_calloc();
+    if (!bo)
+       goto out;
+ 
+@@ -846,6 +885,8 @@ bo_free(struct brw_bo *bo)
+ 
+       entry = _mesa_hash_table_search(bufmgr->handle_table, &bo->gem_handle);
+       _mesa_hash_table_remove(bufmgr->handle_table, entry);
++   } else {
++      assert(list_empty(&bo->exports));
+    }
+ 
+    /* Close this object */
+@@ -895,6 +936,14 @@ bo_unreference_final(struct brw_bo *bo, time_t time)
+ 
+    DBG("bo_unreference final: %d (%s)\n", bo->gem_handle, bo->name);
+ 
++   list_for_each_entry_safe(struct bo_export, export, &bo->exports, link) {
++      struct drm_gem_close close = { .handle = export->gem_handle };
++      drmIoctl(export->drm_fd, DRM_IOCTL_GEM_CLOSE, &close);
++
++      list_del(&export->link);
++      free(export);
++   }
++
+    bucket = bucket_for_size(bufmgr, bo->size);
+    /* Put the buffer into our internal cache for reuse if we can. */
+    if (bufmgr->bo_reuse && bo->reusable && bucket != NULL &&
+@@ -1414,11 +1463,12 @@ brw_bo_gem_create_from_prime_internal(struct brw_bufmgr *bufmgr, int prime_fd,
+     */
+    bo = hash_find_bo(bufmgr->handle_table, handle);
+    if (bo) {
++      assert(list_empty(&bo->exports));
+       brw_bo_reference(bo);
+       goto out;
+    }
+ 
+-   bo = calloc(1, sizeof(*bo));
++   bo = bo_calloc();
+    if (!bo)
+       goto out;
+ 
+@@ -1553,6 +1603,70 @@ brw_bo_flink(struct brw_bo *bo, uint32_t *name)
+    return 0;
+ }
+ 
++int
++brw_bo_export_gem_handle_for_device(struct brw_bo *bo, int drm_fd,
++                                    uint32_t *out_handle)
++{
++   struct brw_bufmgr *bufmgr = bo->bufmgr;
++
++   /* Only add the new GEM handle to the list of export if it belongs to a
++    * different GEM device. Otherwise we might close the same buffer multiple
++    * times.
++    */
++   int ret = os_same_file_description(drm_fd, bufmgr->fd);
++   WARN_ONCE(ret < 0,
++             "Kernel has no file descriptor comparison support: %s\n",
++             strerror(errno));
++   if (ret == 0) {
++      *out_handle = brw_bo_export_gem_handle(bo);
++      return 0;
++   }
++
++   struct bo_export *export = calloc(1, sizeof(*export));
++   if (!export)
++      return -ENOMEM;
++
++   export->drm_fd = drm_fd;
++
++   int dmabuf_fd = -1;
++   int err = brw_bo_gem_export_to_prime(bo, &dmabuf_fd);
++   if (err) {
++      free(export);
++      return err;
++   }
++
++   mtx_lock(&bufmgr->lock);
++   err = drmPrimeFDToHandle(drm_fd, dmabuf_fd, &export->gem_handle);
++   close(dmabuf_fd);
++   if (err) {
++      mtx_unlock(&bufmgr->lock);
++      free(export);
++      return err;
++   }
++
++   bool found = false;
++   list_for_each_entry(struct bo_export, iter, &bo->exports, link) {
++      if (iter->drm_fd != drm_fd)
++         continue;
++      /* Here we assume that for a given DRM fd, we'll always get back the
++       * same GEM handle for a given buffer.
++       */
++      assert(iter->gem_handle == export->gem_handle);
++      free(export);
++      export = iter;
++      found = true;
++      break;
++   }
++   if (!found)
++      list_addtail(&export->link, &bo->exports);
++
++   mtx_unlock(&bufmgr->lock);
++
++   *out_handle = export->gem_handle;
++
++   return 0;
++}
++
+ static void
+ add_bucket(struct brw_bufmgr *bufmgr, int size)
+ {
+diff --git a/src/mesa/drivers/dri/i965/brw_bufmgr.h b/src/mesa/drivers/dri/i965/brw_bufmgr.h
+index 65508195d95..d1fd4ccdc6c 100644
+--- a/src/mesa/drivers/dri/i965/brw_bufmgr.h
++++ b/src/mesa/drivers/dri/i965/brw_bufmgr.h
+@@ -39,6 +39,7 @@
+ #include <stdio.h>
+ #include <time.h>
+ 
++#include "c11/threads.h"
+ #include "util/u_atomic.h"
+ #include "util/list.h"
+ 
+@@ -179,6 +180,13 @@ struct brw_bo {
+    /** BO cache list */
+    struct list_head head;
+ 
++   /**
++    * List of GEM handle exports of this buffer (bo_export).
++    *
++    * Hold bufmgr->lock when using this list.
++    */
++   struct list_head exports;
++
+    /**
+     * Boolean of whether this buffer can be re-used
+     */
+@@ -372,6 +380,18 @@ struct brw_bo *brw_bo_gem_create_from_prime_tiled(struct brw_bufmgr *bufmgr,
+ 
+ uint32_t brw_bo_export_gem_handle(struct brw_bo *bo);
+ 
++/**
++ * Exports a bo as a GEM handle into a given DRM file descriptor
++ * \param bo Buffer to export
++ * \param drm_fd File descriptor where the new handle is created
++ * \param out_handle Pointer to store the new handle
++ *
++ * Returns 0 if the buffer was successfully exported, a non zero error code
++ * otherwise.
++ */
++int brw_bo_export_gem_handle_for_device(struct brw_bo *bo, int drm_fd,
++                                        uint32_t *out_handle);
++
+ int brw_reg_read(struct brw_bufmgr *bufmgr, uint32_t offset,
+                  uint64_t *result);
+ 
+diff --git a/src/mesa/drivers/dri/i965/intel_batchbuffer.c b/src/mesa/drivers/dri/i965/intel_batchbuffer.c
+index 7237e51ab5a..c8a7f238831 100644
+--- a/src/mesa/drivers/dri/i965/intel_batchbuffer.c
++++ b/src/mesa/drivers/dri/i965/intel_batchbuffer.c
+@@ -513,11 +513,17 @@ grow_buffer(struct brw_context *brw,
+    new_bo->refcount = bo->refcount;
+    bo->refcount = 1;
+ 
++   assert(list_empty(&bo->exports));
++   assert(list_empty(&new_bo->exports));
++
+    struct brw_bo tmp;
+    memcpy(&tmp, bo, sizeof(struct brw_bo));
+    memcpy(bo, new_bo, sizeof(struct brw_bo));
+    memcpy(new_bo, &tmp, sizeof(struct brw_bo));
+ 
++   list_inithead(&bo->exports);
++   list_inithead(&new_bo->exports);
++
+    grow->partial_bo = new_bo; /* the one reference of the OLD bo */
+    grow->partial_bytes = existing_bytes;
+ }
+diff --git a/src/mesa/drivers/dri/i965/intel_screen.c b/src/mesa/drivers/dri/i965/intel_screen.c
+index 9c8b0814506..db97dcaabcb 100644
+--- a/src/mesa/drivers/dri/i965/intel_screen.c
++++ b/src/mesa/drivers/dri/i965/intel_screen.c
+@@ -864,9 +864,16 @@ intel_query_image(__DRIimage *image, int attrib, int *value)
+    case __DRI_IMAGE_ATTRIB_STRIDE:
+       *value = image->pitch;
+       return true;
+-   case __DRI_IMAGE_ATTRIB_HANDLE:
+-      *value = brw_bo_export_gem_handle(image->bo);
++   case __DRI_IMAGE_ATTRIB_HANDLE: {
++      __DRIscreen *dri_screen = image->screen->driScrnPriv;
++      uint32_t handle;
++      if (brw_bo_export_gem_handle_for_device(image->bo,
++                                              dri_screen->fd,
++                                              &handle))
++         return false;
++      *value = handle;
+       return true;
++   }
+    case __DRI_IMAGE_ATTRIB_NAME:
+       return !brw_bo_flink(image->bo, (uint32_t *) value);
+    case __DRI_IMAGE_ATTRIB_FORMAT:
+-- 
+2.26.2
+
diff --git a/SPECS/mesa.spec b/SPECS/mesa.spec
index 184c701..6c18e42 100644
--- a/SPECS/mesa.spec
+++ b/SPECS/mesa.spec
@@ -61,7 +61,7 @@
 Summary: Mesa graphics libraries
 Name: mesa
 Version: 18.3.4
-Release: 10%{?dist}
+Release: 12%{?dist}
 License: MIT
 Group: System Environment/Libraries
 URL: http://www.mesa3d.org
@@ -97,6 +97,17 @@ Patch21: 0001-pkgconfig-Fix-gl.pc-when-glvnd-is-enabled.patch
 
 Patch31: 0001-llvmpipe-use-ppc64le-ppc64-Large-code-model-for-JIT-.patch
 
+# i965 multi-screen fix
+Patch40: 0001-i965-initialize-bo_reuse-when-creating-brw_bufmgr.patch
+Patch41: 0002-i965-store-DRM-fd-on-intel_screen.patch
+Patch42: 0003-i965-share-buffer-managers-across-screens.patch
+Patch43: 0004-util-Add-os_same_file_description-helper.patch
+Patch44: 0005-util-remove-the-dependency-on-kcmp.h.patch
+Patch45: 0006-util-Change-os_same_file_description-return-type-fro.patch
+Patch46: 0007-i965-don-t-forget-to-set-screen-on-duped-image.patch
+Patch47: 0008-i965-fix-export-of-GEM-handles.patch
+Patch48: 0001-i965-bufmgr-Handle-NULL-bufmgr-in-brw_bufmgr_get_for.patch
+
 BuildRequires: pkgconfig autoconf automake libtool
 %if %{with_hardware}
 BuildRequires: kernel-headers
@@ -358,6 +369,16 @@ grep -q ^/ src/gallium/auxiliary/vl/vl_decoder.c && exit 1
 #%patch21 -p1 -b .glpc
 %patch31 -p1 -b .codemodel
 
+%patch40 -p1 -b .multi965.1
+%patch41 -p1 -b .multi965.2
+%patch42 -p1 -b .multi965.3
+%patch43 -p1 -b .util-Add-os_same_file_description-helper
+%patch44 -p1 -b .util-remove-the-dependency-on-kcmp.h
+%patch45 -p1 -b .util-Change-os_same_file_description-return-type-fro
+%patch46 -p1 -b .i965-don-t-forget-to-set-screen-on-duped-image
+%patch47 -p1 -b .i965-fix-export-of-GEM-handles
+%patch48 -p1 -b .i965-bufmgr-Handle-NULL-bufmgr-in-brw_bufmgr_get_for
+
 %if 0%{with_private_llvm}
 sed -i 's/\[llvm-config\]/\[llvm-private-config-%{__isa_bits}\]/g' configure.ac
 sed -i 's/`$LLVM_CONFIG --version`/$LLVM_VERSION_MAJOR.$LLVM_VERSION_MINOR-rhel/' configure.ac
@@ -673,6 +694,12 @@ rm -rf $RPM_BUILD_ROOT
 %endif
 
 %changelog
+* Tue Oct 27 2020 Michel Dänzer <mdaenzer@redhat.com> - 18.3.4-12
+- Fix for defect reported by Coverity/clang (#1803811)
+
+* Fri Oct 23 2020 Michel Dänzer <mdaenzer@redhat.com> - 18.3.4-11
+- Backport upstream i965 multi-screen fixes (#1803811)
+
 * Thu Jun 18 2020 Adam Jackson <ajax@redhat.com> - 18.3.4-10
 - Revert the previous fix due to regressions in Firefox, Chrome, etc.