diff --git a/sys/compat/linuxkpi/common/include/linux/compat.h b/sys/compat/linuxkpi/common/include/linux/compat.h --- a/sys/compat/linuxkpi/common/include/linux/compat.h +++ b/sys/compat/linuxkpi/common/include/linux/compat.h @@ -41,17 +41,20 @@ extern void linux_free_current(struct task_struct *); extern struct domainset *linux_get_vm_domain_set(int node); +#define __current_unallocated(td) \ + __predict_false((td)->td_lkpi_task == NULL) + static inline void linux_set_current(struct thread *td) { - if (__predict_false(td->td_lkpi_task == NULL)) + if (__current_unallocated(td)) lkpi_alloc_current(td, M_WAITOK); } static inline int linux_set_current_flags(struct thread *td, int flags) { - if (__predict_false(td->td_lkpi_task == NULL)) + if (__current_unallocated(td)) return (lkpi_alloc_current(td, flags)); return (0); } diff --git a/sys/compat/linuxkpi/common/include/linux/slab.h b/sys/compat/linuxkpi/common/include/linux/slab.h --- a/sys/compat/linuxkpi/common/include/linux/slab.h +++ b/sys/compat/linuxkpi/common/include/linux/slab.h @@ -106,12 +106,8 @@ return (flags & GFP_NATIVE_MASK); } -static inline void * -kmalloc(size_t size, gfp_t flags) -{ - return (malloc(MAX(size, sizeof(struct llist_node)), M_KMALLOC, - linux_check_m_flags(flags))); -} +extern void *lkpi_kmalloc(size_t size, gfp_t flags); +#define kmalloc(size, flags) lkpi_kmalloc(size, flags) static inline void * kmalloc_node(size_t size, gfp_t flags, int node) diff --git a/sys/compat/linuxkpi/common/src/linux_slab.c b/sys/compat/linuxkpi/common/src/linux_slab.c --- a/sys/compat/linuxkpi/common/src/linux_slab.c +++ b/sys/compat/linuxkpi/common/src/linux_slab.c @@ -30,6 +30,9 @@ #include #include #include +#include + +#include #include #include @@ -206,6 +209,28 @@ free(c, M_KMALLOC); } +void * +lkpi_kmalloc(size_t size, gfp_t flags) +{ + void *rv; + unsigned int save_fpu_level; + + save_fpu_level = + __current_unallocated(curthread) ? 0 : current->fpu_ctx_level; + if (__predict_false(save_fpu_level != 0)) { + current->fpu_ctx_level = 1; + kernel_fpu_end(); + } + rv = malloc(MAX(size, sizeof(struct llist_node)), M_KMALLOC, + linux_check_m_flags(flags)); + if (__predict_false(save_fpu_level != 0)) { + kernel_fpu_begin(); + current->fpu_ctx_level = save_fpu_level; + } + + return (rv); +} + static void linux_kfree_async_fn(void *context, int pending) {