On Sun, Jul 09, 2023 at 12:52:20PM -0500, Scott Cheloha wrote: > 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?
To be honest, I'm not sure we need something like this. GPROF is already a special case and poeple running a GPROF kernel should probably stop the collection of profile data before suspend/hibernate. Unless someone wants to gprof suspend/hibernate but then doing this will result in bad data. Another option is to abort zzz/ZZZ if kernel profiling is running. In your diff I would remove these asserts: KASSERT(CPU_IS_PRIMARY(curcpu())); The code does not require the primary cpu there and KASSERT are not for free. > 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 > -- :wq Claudio