path: root/sys/amd64
diff options
authorBruce Evans <bde@FreeBSD.org>2018-06-02 05:48:44 +0000
committerBruce Evans <bde@FreeBSD.org>2018-06-02 05:48:44 +0000
commit49c871278a2004345c7abbdc1ef0a560121b6c06 (patch)
treec53b45dc19dc1ed4929108ba644c12c44cfa8640 /sys/amd64
parent66b3f031f02dcdca304d920930322c20659d30a5 (diff)
Fix high resolution kernel profiling just enough to not crash at boot
time, especially for SMP. If configured, it turns itself on at boot time for calibration, so is fragile even if never otherwise used. Both types of kernel profiling were supposed to use a global spinlock in the SMP case. If hi-res profiling is configured (but not necessarily used), this was supposed to be optimized by only using it when necessary, and slightly more efficiently, in asm. But it was not done at all for mcount entry where it is necessary. This caused crashes in the SMP case when either type of profiling was enabled. For mcount exit, it only caused wrong times. The times were wrongest with an i8254 timer since using that requires exclusive access to the hardware. The i8254 timer was too slow to use here 20 years ago and is much less usable now, but it is the default for the SMP case since TSCs weren't invariant when SMP was new. Do the locking in all hi-res SMP cases for simplicity. Calibration uses special asms, and the clobber lists in these were sort of inverted. They contained the arg and return registers which are not clobbered, but on amd64 they didn't contain the residue of the call-used registers which may be clobbered (%r10 and %r11). This usually caused hangs at boot time. This usually affected even the UP case.
Notes: svn path=/head/; revision=334522
Diffstat (limited to 'sys/amd64')
2 files changed, 24 insertions, 6 deletions
diff --git a/sys/amd64/amd64/prof_machdep.c b/sys/amd64/amd64/prof_machdep.c
index 895d1950b076..5b3e83977ead 100644
--- a/sys/amd64/amd64/prof_machdep.c
+++ b/sys/amd64/amd64/prof_machdep.c
@@ -56,6 +56,20 @@ static int cputime_prof_active;
#endif /* GUPROF */
+#if defined(SMP) && defined(GUPROF)
+#define MPLOCK " \n\
+ movl $1,%edx \n\
+9: \n\
+ xorl %eax,%eax \n\
+ lock \n\
+ cmpxchgl %edx,mcount_lock \n\
+ jne 9b \n"
+#define MPUNLOCK "movl $0,mcount_lock \n"
+#else /* !(SMP && GUPROF) */
+#define MPLOCK
+#define MPUNLOCK
+#endif /* SMP && GUPROF */
__asm(" \n\
GM_STATE = 0 \n\
@@ -111,8 +125,10 @@ __mcount: \n\
movq 7*8(%rsp),%rsi \n\
pushfq \n\
- cli \n\
- call mcount \n\
+ cli \n"
+ MPLOCK " \n\
+ call mcount \n"
+ MPUNLOCK " \n\
popfq \n\
popq %r9 \n\
popq %r8 \n\
@@ -163,8 +179,10 @@ GMON_PROF_HIRES = 4 \n\
pushq %r9 \n\
movq 7*8(%rsp),%rdi \n\
pushfq \n\
- cli \n\
- call mexitcount \n\
+ cli \n"
+ MPLOCK " \n\
+ call mexitcount \n"
+ MPUNLOCK " \n\
popfq \n\
popq %r9 \n\
popq %r8 \n\
diff --git a/sys/amd64/include/profile.h b/sys/amd64/include/profile.h
index 97af17d5e662..2e19918cfb76 100644
--- a/sys/amd64/include/profile.h
+++ b/sys/amd64/include/profile.h
@@ -64,11 +64,11 @@
__asm __volatile("pushq %0; call __mcount; popq %%rcx" \
: \
: "i" (label) \
- : "ax", "dx", "cx", "di", "si", "r8", "r9", "memory")
+ : "cx", "r10", "r11", "memory")
__asm __volatile("call .mexitcount; 1:" \
: : \
- : "ax", "dx", "cx", "di", "si", "r8", "r9", "memory")
+ : "r10", "r11", "memory")
__asm __volatile("movq $1b,%0" : "=rm" (labelp))