git: efe35aecb801 - stable/13 - Handle functions that use a nop in the arm64 fbt

From: Andrew Turner <andrew_at_FreeBSD.org>
Date: Tue, 22 Feb 2022 16:40:19 UTC
The branch stable/13 has been updated by andrew:

URL: https://cgit.FreeBSD.org/src/commit/?id=efe35aecb801d5f361ab1adb159a65ac141c3435

commit efe35aecb801d5f361ab1adb159a65ac141c3435
Author:     Andrew Turner <andrew@FreeBSD.org>
AuthorDate: 2021-01-13 11:08:19 +0000
Commit:     Andrew Turner <andrew@FreeBSD.org>
CommitDate: 2022-02-22 16:23:07 +0000

    Handle functions that use a nop in the arm64 fbt
    
    To trace leaf asm functions we can insert a single nop instruction as
    the first instruction in a function and trigger off this.
    
    Reviewed by:    gnn
    Sponsored by:   Innovate UK
    Differential Revision:  https://reviews.freebsd.org/D28132
    
    (cherry picked from commit 28d945204ea1014d7de6906af8470ed8b3311335)
---
 sys/arm64/include/asm.h                            |  8 +++-
 .../contrib/opensolaris/uts/common/sys/dtrace.h    |  2 +
 sys/cddl/dev/dtrace/aarch64/dtrace_subr.c          |  5 +++
 sys/cddl/dev/fbt/aarch64/fbt_isa.c                 | 51 ++++++++++++++--------
 4 files changed, 46 insertions(+), 20 deletions(-)

diff --git a/sys/arm64/include/asm.h b/sys/arm64/include/asm.h
index 05e618500e59..32b79d256e80 100644
--- a/sys/arm64/include/asm.h
+++ b/sys/arm64/include/asm.h
@@ -38,9 +38,15 @@
 
 #define	_C_LABEL(x)	x
 
+#ifdef KDTRACE_HOOKS
+#define	DTRACE_NOP	nop
+#else
+#define	DTRACE_NOP
+#endif
+
 #define	LENTRY(sym)						\
 	.text; .align 2; .type sym,#function; sym:		\
-	.cfi_startproc
+	.cfi_startproc; DTRACE_NOP
 #define	ENTRY(sym)						\
 	.globl sym; LENTRY(sym)
 #define	EENTRY(sym)						\
diff --git a/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h b/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h
index 2bedd01cf3e7..f15a971f12be 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h
@@ -2466,6 +2466,8 @@ extern void dtrace_helpers_destroy(proc_t *);
 #define	B_DATA_MASK	0x00ffffff
 #define	B_INSTR		0x14000000
 
+#define	NOP_INSTR	0xd503201f
+
 #define	RET_INSTR	0xd65f03c0
 
 #define	SUB_MASK	0xffc00000
diff --git a/sys/cddl/dev/dtrace/aarch64/dtrace_subr.c b/sys/cddl/dev/dtrace/aarch64/dtrace_subr.c
index ede6353a803f..74b3bf7ed7d1 100644
--- a/sys/cddl/dev/dtrace/aarch64/dtrace_subr.c
+++ b/sys/cddl/dev/dtrace/aarch64/dtrace_subr.c
@@ -314,6 +314,11 @@ dtrace_invop_start(struct trapframe *frame)
 		return (0);
 	}
 
+	if (invop == NOP_INSTR) {
+		frame->tf_elr += INSN_SIZE;
+		return (0);
+	}
+
 	if ((invop & B_MASK) == B_INSTR) {
 		data = (invop & B_DATA_MASK);
 		/* The data is the number of 4-byte words to change the pc */
diff --git a/sys/cddl/dev/fbt/aarch64/fbt_isa.c b/sys/cddl/dev/fbt/aarch64/fbt_isa.c
index adc355e3296b..d00aabf0cc81 100644
--- a/sys/cddl/dev/fbt/aarch64/fbt_isa.c
+++ b/sys/cddl/dev/fbt/aarch64/fbt_isa.c
@@ -120,28 +120,41 @@ fbt_provide_module_function(linker_file_t lf, int symindx,
 
 	/* Look for stp (pre-indexed) operation */
 	found = false;
-	for (; instr < limit; instr++) {
-		/* Some functions start with "stp xt1, xt2, [xn, <const>]!" */
-		if ((*instr & LDP_STP_MASK) == STP_64) {
+	/*
+	 * If the first instruction is a nop it's a specially marked
+	 * asm function. We only support a nop first as it's not a normal
+	 * part of the function prologue.
+	 */
+	if (*instr == NOP_INSTR)
+		found = true;
+	if (!found) {
+		for (; instr < limit; instr++) {
 			/*
-			 * Assume any other store of this type means we
-			 * are past the function prolog.
+			 * Some functions start with
+			 * "stp xt1, xt2, [xn, <const>]!"
 			 */
-			if (((*instr >> ADDR_SHIFT) & ADDR_MASK) == 31)
-				found = true;
-			break;
-		}
+			if ((*instr & LDP_STP_MASK) == STP_64) {
+				/*
+				 * Assume any other store of this type means we
+				 * are past the function prolog.
+				 */
+				if (((*instr >> ADDR_SHIFT) & ADDR_MASK) == 31)
+					found = true;
+				break;
+			}
 
-		/*
-		 * Some functions start with a "sub sp, sp, <const>"
-		 * Sometimes the compiler will have a sub instruction that
-		 * is not of the above type so don't stop if we see one.
-		 */
-		if ((*instr & SUB_MASK) == SUB_INSTR &&
-		    ((*instr >> SUB_RD_SHIFT) & SUB_R_MASK) == 31 &&
-		    ((*instr >> SUB_RN_SHIFT) & SUB_R_MASK) == 31) {
-			found = true;
-			break;
+			/*
+			 * Some functions start with a "sub sp, sp, <const>"
+			 * Sometimes the compiler will have a sub instruction
+			 * that is not of the above type so don't stop if we
+			 * see one.
+			 */
+			if ((*instr & SUB_MASK) == SUB_INSTR &&
+			    ((*instr >> SUB_RD_SHIFT) & SUB_R_MASK) == 31 &&
+			    ((*instr >> SUB_RN_SHIFT) & SUB_R_MASK) == 31) {
+				found = true;
+				break;
+			}
 		}
 	}