This patch fixes resume/unhibernate on GPROF kernels where kgmon(8) has activated kernel profiling.
I think the problem is that code called from cpu_hatch() does not play nicely with _mcount(), so GPROF kernels crash during resume. I can't point you to which code in particular, but keeping all CPUs out of _mcount() until the primary CPU has completed resume/unhibernate fixes the crash. ok? Index: sys/lib/libkern/mcount.c =================================================================== RCS file: /cvs/src/sys/lib/libkern/mcount.c,v retrieving revision 1.14 diff -u -p -r1.14 mcount.c --- sys/lib/libkern/mcount.c 11 Jan 2022 09:21:34 -0000 1.14 +++ sys/lib/libkern/mcount.c 9 Jul 2023 17:49:55 -0000 @@ -33,6 +33,32 @@ #include <sys/param.h> #include <sys/gmon.h> +#ifdef _KERNEL +#ifdef SUSPEND +#include <sys/atomic.h> + +#include <lib/libkern/libkern.h> /* KASSERT */ + +volatile int mcount_disabled; + +void +mcount_disable(void) +{ + KASSERT(CPU_IS_PRIMARY(curcpu())); + mcount_disabled = 1; + membar_producer(); +} + +void +mcount_enable(void) +{ + KASSERT(CPU_IS_PRIMARY(curcpu())); + mcount_disabled = 0; + membar_producer(); +} +#endif /* SUSPEND */ +#endif /* _KERNEL */ + /* * mcount is called on entry to each function compiled with the profiling * switch set. _mcount(), which is declared in a machine-dependent way @@ -63,7 +89,10 @@ _MCOUNT_DECL(u_long frompc, u_long selfp */ if (gmoninit == 0) return; - +#ifdef SUSPEND + if (mcount_disabled) + return; +#endif if ((p = curcpu()->ci_gmon) == NULL) return; #else Index: sys/kern/subr_suspend.c =================================================================== RCS file: /cvs/src/sys/kern/subr_suspend.c,v retrieving revision 1.15 diff -u -p -r1.15 subr_suspend.c --- sys/kern/subr_suspend.c 2 Jul 2023 19:02:27 -0000 1.15 +++ sys/kern/subr_suspend.c 9 Jul 2023 17:49:55 -0000 @@ -26,6 +26,9 @@ #include <sys/mount.h> #include <sys/syscallargs.h> #include <dev/wscons/wsdisplayvar.h> +#ifdef GPROF +#include <sys/gmon.h> +#endif #ifdef HIBERNATE #include <sys/hibernate.h> #endif @@ -63,6 +66,9 @@ top: if (sleep_showstate(v, sleepmode)) return EOPNOTSUPP; +#ifdef GPROF + mcount_disable(); +#endif #if NWSDISPLAY > 0 wsdisplay_suspend(); #endif @@ -192,6 +198,9 @@ fail_hiballoc: start_periodic_resettodr(); #if NWSDISPLAY > 0 wsdisplay_resume(); +#endif +#ifdef GPROF + mcount_enable(); #endif sys_sync(curproc, NULL, NULL); if (cpu_setperf != NULL) Index: sys/sys/gmon.h =================================================================== RCS file: /cvs/src/sys/sys/gmon.h,v retrieving revision 1.9 diff -u -p -r1.9 gmon.h --- sys/sys/gmon.h 11 Jan 2022 23:59:55 -0000 1.9 +++ sys/sys/gmon.h 9 Jul 2023 17:49:55 -0000 @@ -158,6 +158,10 @@ struct gmonparam { #ifdef _KERNEL extern int gmoninit; /* Is the kernel ready for being profiled? */ +#ifdef SUSPEND +void mcount_disable(void); +void mcount_enable(void); +#endif #else /* !_KERNEL */ #include <sys/cdefs.h> Index: lib/libc/gmon/mcount.c =================================================================== RCS file: /cvs/src/lib/libc/gmon/mcount.c,v retrieving revision 1.16 diff -u -p -r1.16 mcount.c --- lib/libc/gmon/mcount.c 11 Jan 2022 09:21:34 -0000 1.16 +++ lib/libc/gmon/mcount.c 9 Jul 2023 17:49:55 -0000 @@ -31,6 +31,32 @@ #include <sys/types.h> #include <sys/gmon.h> +#ifdef _KERNEL +#ifdef SUSPEND +#include <sys/atomic.h> + +#include <lib/libkern/libkern.h> /* KASSERT */ + +volatile int mcount_disabled; + +void +mcount_disable(void) +{ + KASSERT(CPU_IS_PRIMARY(curcpu())); + mcount_disabled = 1; + membar_producer(); +} + +void +mcount_enable(void) +{ + KASSERT(CPU_IS_PRIMARY(curcpu())); + mcount_disabled = 0; + membar_producer(); +} +#endif /* SUSPEND */ +#endif /* _KERNEL */ + /* * mcount is called on entry to each function compiled with the profiling * switch set. _mcount(), which is declared in a machine-dependent way @@ -61,7 +87,10 @@ _MCOUNT_DECL(u_long frompc, u_long selfp */ if (gmoninit == 0) return; - +#ifdef SUSPEND + if (mcount_disabled) + return; +#endif if ((p = curcpu()->ci_gmon) == NULL) return; #else