Skip to content

Commit c0fc0fa

Browse files
committed
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
1 parent 3c4b3ba commit c0fc0fa

File tree

2 files changed

+19
-1
lines changed

2 files changed

+19
-1
lines changed

sys/compat/linuxkpi/common/include/linux/slab.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ void lkpi_kmem_cache_free(struct linux_kmem_cache *, void *);
9999
void linux_kmem_cache_destroy(struct linux_kmem_cache *);
100100

101101
void *lkpi_kmalloc(size_t, gfp_t);
102+
void *lkpi_kvmalloc(size_t, gfp_t);
102103
void *lkpi___kmalloc(size_t, gfp_t);
103104
void *lkpi___kmalloc_node(size_t, gfp_t, int);
104105
void *lkpi_krealloc(void *, size_t, gfp_t);
@@ -225,7 +226,7 @@ vmalloc_32(size_t size)
225226
static inline void *
226227
kvmalloc(size_t size, gfp_t flags)
227228
{
228-
return (malloc(size, M_KMALLOC, linux_check_m_flags(flags)));
229+
return (lkpi_kvmalloc(size, flags));
229230
}
230231

231232
static inline void *

sys/compat/linuxkpi/common/src/linux_slab.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,23 @@ lkpi_kmalloc(size_t size, gfp_t flags)
296296
return(lmc.addr);
297297
}
298298

299+
static void
300+
lkpi_kvmalloc_cb(void *ctx)
301+
{
302+
struct lkpi_kmalloc_ctx *lmc = ctx;
303+
304+
lmc->addr = malloc(lmc->size, M_KMALLOC, linux_check_m_flags(lmc->flags));
305+
}
306+
307+
void *
308+
lkpi_kvmalloc(size_t size, gfp_t flags)
309+
{
310+
struct lkpi_kmalloc_ctx lmc = { .size = size, .flags = flags };
311+
312+
lkpi_fpu_safe_exec(&lkpi_kvmalloc_cb, &lmc);
313+
return(lmc.addr);
314+
}
315+
299316
static void
300317
linux_kfree_async_fn(void *context, int pending)
301318
{

0 commit comments

Comments
 (0)