git: 6b5db9d3af04 - stable/13 - hwpmc: simplify arm64 kernel stack unwinding

From: Mitchell Horne <mhorne_at_FreeBSD.org>
Date: Fri, 09 Jun 2023 19:58:08 UTC
The branch stable/13 has been updated by mhorne:

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

commit 6b5db9d3af0497e4538d6fd43df2596172867568
Author:     Mitchell Horne <mhorne@FreeBSD.org>
AuthorDate: 2023-05-05 21:58:40 +0000
Commit:     Mitchell Horne <mhorne@FreeBSD.org>
CommitDate: 2023-06-09 18:14:59 +0000

    hwpmc: simplify arm64 kernel stack unwinding
    
    Use the unwind_frame() function, which properly validates the frame
    pointer and uses ADDR_MAKE_CANONICAL() for the pc, required when PAC is
    enabled.
    
    Reviewed by:    andrew, markj, jkoshy
    MFC after:      2 weeks
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D39934
    
    (cherry picked from commit 5387495773e9e92441b795c0eb8c2a3ecc25708a)
---
 sys/dev/hwpmc/hwpmc_arm64_md.c | 31 ++++++++++---------------------
 1 file changed, 10 insertions(+), 21 deletions(-)

diff --git a/sys/dev/hwpmc/hwpmc_arm64_md.c b/sys/dev/hwpmc/hwpmc_arm64_md.c
index 015bee227f89..996c91eea592 100644
--- a/sys/dev/hwpmc/hwpmc_arm64_md.c
+++ b/sys/dev/hwpmc/hwpmc_arm64_md.c
@@ -62,7 +62,8 @@ int
 pmc_save_kernel_callchain(uintptr_t *cc, int maxsamples,
     struct trapframe *tf)
 {
-	uintptr_t pc, r, stackstart, stackend, fp;
+	struct unwind_state frame;
+	uintptr_t stackstart, stackend;
 	struct thread *td;
 	int count;
 
@@ -70,38 +71,26 @@ pmc_save_kernel_callchain(uintptr_t *cc, int maxsamples,
 	    __LINE__));
 
 	td = curthread;
-	pc = PMC_TRAPFRAME_TO_PC(tf);
-	*cc++ = pc;
+	frame.pc = PMC_TRAPFRAME_TO_PC(tf);
+	*cc++ = frame.pc;
 
 	if (maxsamples <= 1)
 		return (1);
 
 	stackstart = (uintptr_t) td->td_kstack;
 	stackend = (uintptr_t) td->td_kstack + td->td_kstack_pages * PAGE_SIZE;
-	fp = PMC_TRAPFRAME_TO_FP(tf);
+	frame.fp = PMC_TRAPFRAME_TO_FP(tf);
 
-	if (!PMC_IN_KERNEL(pc) ||
-	    !PMC_IN_KERNEL_STACK(fp, stackstart, stackend))
+	if (!PMC_IN_KERNEL(frame.pc) ||
+	    !PMC_IN_KERNEL_STACK(frame.fp, stackstart, stackend))
 		return (1);
 
 	for (count = 1; count < maxsamples; count++) {
-		/* Use saved lr as pc. */
-		r = fp + sizeof(uintptr_t);
-		if (!PMC_IN_KERNEL_STACK(r, stackstart, stackend))
-			break;
-		pc = *(uintptr_t *)r;
-		if (!PMC_IN_KERNEL(pc))
-			break;
-
-		*cc++ = pc;
-
-		/* Switch to next frame up */
-		r = fp;
-		if (!PMC_IN_KERNEL_STACK(r, stackstart, stackend))
+		if (!unwind_frame(curthread, &frame))
 			break;
-		fp = *(uintptr_t *)r;
-		if (!PMC_IN_KERNEL_STACK(fp, stackstart, stackend))
+		if (!PMC_IN_KERNEL(frame.pc))
 			break;
+		*cc++ = frame.pc;
 	}
 
 	return (count);