OSDN Git Service

arm64: remove EL0 exception frame record
authorMark Rutland <mark.rutland@arm.com>
Wed, 13 Jan 2021 17:31:55 +0000 (17:31 +0000)
committerWill Deacon <will@kernel.org>
Wed, 20 Jan 2021 12:47:54 +0000 (12:47 +0000)
When entering an exception from EL0, the entry code creates a synthetic
frame record with a NULL PC. This was used by the code introduced in
commit:

  7326749801396105 ("arm64: unwind: reference pt_regs via embedded stack frame")

... to discover exception entries on the stack and dump the associated
pt_regs. Since the NULL PC was undesirable for the stacktrace, we added
a special case to unwind_frame() to prevent the NULL PC from being
logged.

Since commit:

  a25ffd3a6302a678 ("arm64: traps: Don't print stack or raw PC/LR values in backtraces")

... we no longer try to dump the pt_regs as part of a stacktrace, and
hence no longer need the synthetic exception record.

This patch removes the synthetic exception record and the associated
special case in unwind_frame(). Instead, EL0 exceptions set the FP to
NULL, as is the case for other terminal records (e.g. when a kernel
thread starts). The synthetic record for exceptions from EL1 is
retrained as this has useful unwind information for the interrupted
context.

To make the terminal case a bit clearer, an explicit check is added to
the start of unwind_frame(). This would otherwise be caught implicitly
by the on_accessible_stack() checks.

Reported-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
Link: https://lore.kernel.org/r/20210113173155.43063-1-broonie@kernel.org
Signed-off-by: Will Deacon <will@kernel.org>
arch/arm64/kernel/entry.S
arch/arm64/kernel/stacktrace.c

index c9bae73..89fd390 100644 (file)
@@ -261,16 +261,16 @@ alternative_else_nop_endif
        stp     lr, x21, [sp, #S_LR]
 
        /*
-        * In order to be able to dump the contents of struct pt_regs at the
-        * time the exception was taken (in case we attempt to walk the call
-        * stack later), chain it together with the stack frames.
+        * For exceptions from EL0, terminate the callchain here.
+        * For exceptions from EL1, create a synthetic frame record so the
+        * interrupted code shows up in the backtrace.
         */
        .if \el == 0
-       stp     xzr, xzr, [sp, #S_STACKFRAME]
+       mov     x29, xzr
        .else
        stp     x29, x22, [sp, #S_STACKFRAME]
-       .endif
        add     x29, sp, #S_STACKFRAME
+       .endif
 
 #ifdef CONFIG_ARM64_SW_TTBR0_PAN
 alternative_if_not ARM64_HAS_PAN
index fa56af1..0fb4212 100644 (file)
@@ -44,6 +44,10 @@ int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame)
        unsigned long fp = frame->fp;
        struct stack_info info;
 
+       /* Terminal record; nothing to unwind */
+       if (!fp)
+               return -EINVAL;
+
        if (fp & 0xf)
                return -EINVAL;
 
@@ -104,15 +108,6 @@ int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame)
 
        frame->pc = ptrauth_strip_insn_pac(frame->pc);
 
-       /*
-        * Frames created upon entry from EL0 have NULL FP and PC values, so
-        * don't bother reporting these. Frames created by __noreturn functions
-        * might have a valid FP even if PC is bogus, so only terminate where
-        * both are NULL.
-        */
-       if (!frame->fp && !frame->pc)
-               return -EINVAL;
-
        return 0;
 }
 NOKPROBE_SYMBOL(unwind_frame);