From fb3ad5d24e353bcf3c5c5f7cfff095bfa2a308cf Mon Sep 17 00:00:00 2001 From: Ryan Moeller Date: Thu, 10 Dec 2020 00:29:00 -0500 Subject: [PATCH] FreeBSD: Do zcommon_init sooner to avoid FPU panic There has been a panic affecting some system configurations where the thread FPU context is disturbed during the fletcher 4 benchmarks, leading to a panic at boot. module_init() registers zcommon_init to run in the last subsystem (SI_SUB_LAST). Running it as soon as interrupts have been configured (SI_SUB_INT_CONFIG_HOOKS) makes sure we have finished the benchmarks before we start doing other things. While it's not clear *how* the FPU context was being disturbed, this does seem to avoid it. Add a module_init_early() macro to run zcommon_init() at this earlier point on FreeBSD. On Linux this is defined as module_init(). Authored by: Konstantin Belousov Reviewed-by: Brian Behlendorf Signed-off-by: Ryan Moeller Closes #11302 --- include/os/freebsd/spl/sys/mod_os.h | 7 +++++++ include/os/linux/kernel/linux/mod_compat.h | 2 ++ module/zcommon/zfs_prop.c | 2 +- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/include/os/freebsd/spl/sys/mod_os.h b/include/os/freebsd/spl/sys/mod_os.h index ec1da1a46a..9b1bdfbffe 100644 --- a/include/os/freebsd/spl/sys/mod_os.h +++ b/include/os/freebsd/spl/sys/mod_os.h @@ -93,6 +93,13 @@ wrap_ ## fn(void *dummy __unused) \ } \ SYSINIT(zfs_ ## fn, SI_SUB_LAST, SI_ORDER_FIRST, wrap_ ## fn, NULL) +#define module_init_early(fn) \ +static void \ +wrap_ ## fn(void *dummy __unused) \ +{ \ + fn(); \ +} \ +SYSINIT(zfs_ ## fn, SI_SUB_INT_CONFIG_HOOKS, SI_ORDER_FIRST, wrap_ ## fn, NULL) #define module_exit(fn) \ static void \ diff --git a/include/os/linux/kernel/linux/mod_compat.h b/include/os/linux/kernel/linux/mod_compat.h index 1c48df5cbd..779f1bf91d 100644 --- a/include/os/linux/kernel/linux/mod_compat.h +++ b/include/os/linux/kernel/linux/mod_compat.h @@ -150,4 +150,6 @@ enum scope_prefix_types { #define ZFS_MODULE_LICENSE(s) MODULE_LICENSE(s) #define ZFS_MODULE_VERSION(s) MODULE_VERSION(s) +#define module_init_early(fn) module_init(fn) + #endif /* _MOD_COMPAT_H */ diff --git a/module/zcommon/zfs_prop.c b/module/zcommon/zfs_prop.c index 89ddc59b22..b78331187e 100644 --- a/module/zcommon/zfs_prop.c +++ b/module/zcommon/zfs_prop.c @@ -1016,7 +1016,7 @@ zcommon_fini(void) kfpu_fini(); } -module_init(zcommon_init); +module_init_early(zcommon_init); module_exit(zcommon_fini); #endif