Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 7 Aug 2025 18:46:53 GMT
From:      =?utf-8?Q?Jean-S=C3=A9bastien?= =?utf-8?Q?P=C3=A9dron?= <dumbbell@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: c0fc0facf877 - main - linuxkpi: Call `lkpi_fpu_safe_exec()` in the implementation of kvmalloc()
Message-ID:  <202508071846.577IkrAY018706@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by dumbbell:

URL: https://cgit.FreeBSD.org/src/commit/?id=c0fc0facf877d4e2ad5843d59c15d0d464432962

commit c0fc0facf877d4e2ad5843d59c15d0d464432962
Author:     Jean-Sébastien Pédron <dumbbell@FreeBSD.org>
AuthorDate: 2025-07-26 12:17:26 +0000
Commit:     Jean-Sébastien Pédron <dumbbell@FreeBSD.org>
CommitDate: 2025-08-07 18:46:15 +0000

    linuxkpi: Call `lkpi_fpu_safe_exec()` in the implementation of kvmalloc()
    
    `kvmalloc()` was a simple wrapper around the FreeBSD native `malloc()`.
    Unlike the more involved implementation of `kmalloc()`, it didn't end
    and being the FPU context around the actual call to `malloc()`.
    
    This caused the following panic in the amdgup DRM driver:
    
        panic: malloc: called with spinlock or critical section held
    
    ... triggered by the call:
    
        struct dc_3dlut *lut = kvzalloc(sizeof(*lut), GFP_KERNEL);
    
    (for the record, GFP_KERNEL is defined as M_WAITOK)
    
    Replicating the same behaviour as `kmalloc()`, in other words, ending
    the FPU context before the call to the underlying `malloc()`, and
    beginning it again afterwards solves the problem.
    
    Reviewed by:    olce
    Sponsored by:   The FreeBSD Foundation
    Differential Revision: https://reviews.freebsd.org/D51557
---
 sys/compat/linuxkpi/common/include/linux/slab.h |  3 ++-
 sys/compat/linuxkpi/common/src/linux_slab.c     | 17 +++++++++++++++++
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/sys/compat/linuxkpi/common/include/linux/slab.h b/sys/compat/linuxkpi/common/include/linux/slab.h
index efa5c8cb67b3..47e3d133eb6c 100644
--- a/sys/compat/linuxkpi/common/include/linux/slab.h
+++ b/sys/compat/linuxkpi/common/include/linux/slab.h
@@ -99,6 +99,7 @@ void lkpi_kmem_cache_free(struct linux_kmem_cache *, void *);
 void linux_kmem_cache_destroy(struct linux_kmem_cache *);
 
 void *lkpi_kmalloc(size_t, gfp_t);
+void *lkpi_kvmalloc(size_t, gfp_t);
 void *lkpi___kmalloc(size_t, gfp_t);
 void *lkpi___kmalloc_node(size_t, gfp_t, int);
 void *lkpi_krealloc(void *, size_t, gfp_t);
@@ -225,7 +226,7 @@ vmalloc_32(size_t size)
 static inline void *
 kvmalloc(size_t size, gfp_t flags)
 {
-	return (malloc(size, M_KMALLOC, linux_check_m_flags(flags)));
+	return (lkpi_kvmalloc(size, flags));
 }
 
 static inline void *
diff --git a/sys/compat/linuxkpi/common/src/linux_slab.c b/sys/compat/linuxkpi/common/src/linux_slab.c
index 3d75ca480661..6f71d17a3770 100644
--- a/sys/compat/linuxkpi/common/src/linux_slab.c
+++ b/sys/compat/linuxkpi/common/src/linux_slab.c
@@ -296,6 +296,23 @@ lkpi_kmalloc(size_t size, gfp_t flags)
 	return(lmc.addr);
 }
 
+static void
+lkpi_kvmalloc_cb(void *ctx)
+{
+	struct lkpi_kmalloc_ctx *lmc = ctx;
+
+	lmc->addr = malloc(lmc->size, M_KMALLOC, linux_check_m_flags(lmc->flags));
+}
+
+void *
+lkpi_kvmalloc(size_t size, gfp_t flags)
+{
+	struct lkpi_kmalloc_ctx lmc = { .size = size, .flags = flags };
+
+	lkpi_fpu_safe_exec(&lkpi_kvmalloc_cb, &lmc);
+	return(lmc.addr);
+}
+
 static void
 linux_kfree_async_fn(void *context, int pending)
 {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202508071846.577IkrAY018706>