summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorcognet <cognet@FreeBSD.org>2004-09-23 22:29:18 +0000
committercognet <cognet@FreeBSD.org>2004-09-23 22:29:18 +0000
commit23f2e2a20b6449ec661a66404dce328390cee1b4 (patch)
treefe463a68a390a1b1ac82f88cbde50e09c4f7dfc7
parentbce0b28077deb8caa2ff2f2df09b6028f7629e02 (diff)
downloadFreeBSD-src-23f2e2a20b6449ec661a66404dce328390cee1b4.zip
FreeBSD-src-23f2e2a20b6449ec661a66404dce328390cee1b4.tar.gz
Implement _mcount().
Obtained from: NetBSD
-rw-r--r--sys/arm/include/profile.h101
1 files changed, 52 insertions, 49 deletions
diff --git a/sys/arm/include/profile.h b/sys/arm/include/profile.h
index 4c5321b..ae80795 100644
--- a/sys/arm/include/profile.h
+++ b/sys/arm/include/profile.h
@@ -37,41 +37,56 @@
#ifndef _MACHINE_PROFILE_H_
#define _MACHINE_PROFILE_H_
-#ifdef _KERNEL
-
/*
- * Config generates something to tell the compiler to align functions on 16
+ * Config generates something to tell the compiler to align functions on 32
* byte boundaries. A strict alignment is good for keeping the tables small.
*/
#define FUNCTION_ALIGNMENT 16
+
+#define _MCOUNT_DECL void mcount
+
+typedef u_long fptrdiff_t;
+
/*
- * The kernel uses assembler stubs instead of unportable inlines.
- * This is mainly to save a little time when profiling is not enabled,
- * which is the usual case for the kernel.
+ * Cannot implement mcount in C as GCC will trash the ip register when it
+ * pushes a trapframe. Pity we cannot insert assembly before the function
+ * prologue.
*/
-#define _MCOUNT_DECL void mcount
-#define MCOUNT
-#ifdef GUPROF
-#define MCOUNT_DECL(s)
-#define MCOUNT_ENTER(s)
-#define MCOUNT_EXIT(s)
-#else
-#define MCOUNT_DECL(s) u_long s;
-#ifdef SMP
-extern int mcount_lock;
-#define MCOUNT_ENTER(s) { s = intr_disable(); \
- while (!atomic_cmpset_acq_int(&mcount_lock, 0, 1)) \
- /* nothing */ ; }
-#define MCOUNT_EXIT(s) { atomic_store_rel_int(&mcount_lock, 0); \
- intr_restore(s); }
-#else
-#define MCOUNT_ENTER(s) { s = read_eflags(); disable_intr(); }
-#define MCOUNT_EXIT(s) (write_eflags(s))
+#ifndef PLTSYM
+#define PLTSYM
#endif
-#endif /* GUPROF */
+#define MCOUNT \
+ __asm__(".text"); \
+ __asm__(".align 0"); \
+ __asm__(".type _mcount ,%function"); \
+ __asm__(".global _mcount"); \
+ __asm__("_mcount:"); \
+ /* \
+ * Preserve registers that are trashed during mcount \
+ */ \
+ __asm__("stmfd sp!, {r0-r3, ip, lr}"); \
+ /* \
+ * find the return address for mcount, \
+ * and the return address for mcount's caller. \
+ * \
+ * frompcindex = pc pushed by call into self. \
+ */ \
+ __asm__("mov r0, ip"); \
+ /* \
+ * selfpc = pc pushed by mcount call \
+ */ \
+ __asm__("mov r1, lr"); \
+ /* \
+ * Call the real mcount code \
+ */ \
+ __asm__("bl mcount"); \
+ /* \
+ * Restore registers that were trashed during mcount \
+ */ \
+ __asm__("ldmfd sp!, {r0-r3, lr, pc}");
void bintr(void);
void btrap(void);
void eintr(void);
@@ -85,38 +100,26 @@ void user(void);
((pc >= (uintfptr_t)bintr) ? (uintfptr_t)bintr : \
(uintfptr_t)btrap) : ~0U)
-#else /* !_KERNEL */
-
-#define FUNCTION_ALIGNMENT 4
-
-#define _MCOUNT_DECL static __inline void _mcount
-#define MCOUNT
-
-typedef unsigned int uintfptr_t;
+#ifdef _KERNEL
-#endif /* _KERNEL */
+#define MCOUNT_DECL(s) register_t s;
+#include <machine/asm.h>
+#include <machine/cpufunc.h>
/*
- * An unsigned integral type that can hold non-negative difference between
- * function pointers.
+ * splhigh() and splx() are heavyweight, and call mcount(). Therefore
+ * we disabled interrupts (IRQ, but not FIQ) directly on the CPU.
+ *
+ * We're lucky that the CPSR and 's' both happen to be 'int's.
*/
-typedef u_int fptrdiff_t;
-
-#ifdef _KERNEL
+#define MCOUNT_ENTER(s) {s = intr_disable(); } /* kill IRQ */
+#define MCOUNT_EXIT(s) {intr_restore(s); } /* restore old value */
void mcount(uintfptr_t frompc, uintfptr_t selfpc);
-#else /* !_KERNEL */
-
-#include <sys/cdefs.h>
-
-__BEGIN_DECLS
-#ifdef __GNUC__
-void mcount(void) __asm(".mcount");
-#endif
-__END_DECLS
-
+#else
+typedef u_int uintfptr_t;
#endif /* _KERNEL */
#endif /* !_MACHINE_PROFILE_H_ */
OpenPOWER on IntegriCloud