Mesa (staging/21.2): drm-shim: Support kernels with >4k pages

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Mon Aug 16 19:02:11 UTC 2021


Module: Mesa
Branch: staging/21.2
Commit: ca9ab792c6fcb752d868e09461831d992ff07c6f
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=ca9ab792c6fcb752d868e09461831d992ff07c6f

Author: Alyssa Rosenzweig <alyssa at collabora.com>
Date:   Thu Aug 12 18:54:49 2021 +0000

drm-shim: Support kernels with >4k pages

mmap requires its offset is page aligned, but the current code only
guarantees 4k alignment, causing drm-shim to break badly on kernels with
>4k page sizes. This fixes drm-shim on my Apple M1, running bare metal
Linux with 16k pages. It probably also fixes exotic PowerPC systems with
64k pages.

Signed-off-by: Alyssa Rosenzweig <alyssa at collabora.com>
Reviewed-by: Zoltan Boszormenyi <zboszor at gmail.com>
Reviewed-by: Adam Jackson <ajax at redhat.com>
Reviewed-by: Emma Anholt <emma at anholt.net>
Cc: mesa-stable
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12347>
(cherry picked from commit 38f39cc1e21569c1bc0ffa56d402d042761be16c)

---

 .pick_status.json     |  2 +-
 src/drm-shim/device.c | 23 +++++++++++++++++++++--
 2 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/.pick_status.json b/.pick_status.json
index 199798dbbf3..f4f3e109d89 100644
--- a/.pick_status.json
+++ b/.pick_status.json
@@ -517,7 +517,7 @@
         "description": "drm-shim: Support kernels with >4k pages",
         "nominated": true,
         "nomination_type": 0,
-        "resolution": 0,
+        "resolution": 1,
         "main_sha": null,
         "because_sha": null
     },
diff --git a/src/drm-shim/device.c b/src/drm-shim/device.c
index a70189cd777..211eb2e5781 100644
--- a/src/drm-shim/device.c
+++ b/src/drm-shim/device.c
@@ -57,6 +57,8 @@ memfd_create(const char *name, unsigned int flags)
 /* Global state for the shim shared between libc, core, and driver. */
 struct shim_device shim_device;
 
+long shim_page_size;
+
 static uint32_t
 uint_key_hash(const void *key)
 {
@@ -88,7 +90,21 @@ drm_shim_device_init(void)
    ASSERTED int ret = ftruncate(shim_device.mem_fd, SHIM_MEM_SIZE);
    assert(ret == 0);
 
-   util_vma_heap_init(&shim_device.mem_heap, 4096, SHIM_MEM_SIZE - 4096);
+   /* The man page for mmap() says
+    *
+    *    offset must be a multiple of the page size as returned by
+    *    sysconf(_SC_PAGE_SIZE).
+    *
+    * Depending on the configuration of the kernel, this may not be 4096. Get
+    * this page size once and use it as the page size throughout, ensuring that
+    * are offsets are page-size aligned as required. Otherwise, mmap will fail
+    * with EINVAL.
+    */
+
+   shim_page_size = sysconf(_SC_PAGE_SIZE);
+
+   util_vma_heap_init(&shim_device.mem_heap, shim_page_size,
+                      SHIM_MEM_SIZE - shim_page_size);
 
    drm_shim_driver_init();
 }
@@ -270,7 +286,7 @@ drm_shim_bo_init(struct shim_bo *bo, size_t size)
 {
 
    mtx_lock(&shim_device.mem_lock);
-   bo->mem_addr = util_vma_heap_alloc(&shim_device.mem_heap, size, 4096);
+   bo->mem_addr = util_vma_heap_alloc(&shim_device.mem_heap, size, shim_page_size);
    mtx_unlock(&shim_device.mem_lock);
    assert(bo->mem_addr);
 
@@ -361,5 +377,8 @@ drm_shim_mmap(struct shim_fd *shim_fd, size_t length, int prot, int flags,
 {
    struct shim_bo *bo = (void *)(uintptr_t)offset;
 
+   /* The offset we pass to mmap must be aligned to the page size */
+   assert((bo->mem_addr & (shim_page_size - 1)) == 0);
+
    return mmap(NULL, length, prot, flags, shim_device.mem_fd, bo->mem_addr);
 }



More information about the mesa-commit mailing list