Re: [PATCH v2 1/2] arm64: revamp unwind_frame for interrupt stack

From: Jungseok Lee
Date: Tue Oct 20 2015 - 09:26:42 EST


On Oct 20, 2015, at 5:00 PM, AKASHI Takahiro wrote:
> This patch allows unwind_frame() to traverse from interrupt stack
> to process stack correctly by having a dummy stack frame for irq
> exception entry created at its prologue.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@xxxxxxxxxx>
> ---
> arch/arm64/kernel/entry.S | 22 ++++++++++++++++++++--
> arch/arm64/kernel/stacktrace.c | 14 +++++++++++++-
> 2 files changed, 33 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
> index c8e0bcf..779f807 100644
> --- a/arch/arm64/kernel/entry.S
> +++ b/arch/arm64/kernel/entry.S
> @@ -186,8 +186,26 @@ alternative_endif
> and x23, x23, #~(IRQ_STACK_SIZE - 1)
> cmp x20, x23 // check irq re-enterance
> mov x19, sp
> - csel x23, x19, x24, eq // x24 = top of irq stack
> - mov sp, x23
> + beq 1f
> + mov sp, x24 // x24 = top of irq stack
> + stp x29, x19, [sp, #-16]! // for sanity check
> + stp x29, x22, [sp, #-16]! // dummy stack frame
> + mov x29, sp
> +1:
> + /*
> + * Layout of interrupt stack after this macro is invoked:
> + *
> + * | |
> + *-0x20+----------------+ <= dummy stack frame
> + * | fp | : fp on process stack
> + *-0x18+----------------+
> + * | lr | : return address
> + *-0x10+----------------+
> + * | fp (copy) | : for sanity check
> + * -0x8+----------------+
> + * | sp | : sp on process stack
> + * 0x0+----------------+
> + */
> .endm
>
> /*
> diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
> index 407991b..03611a1 100644
> --- a/arch/arm64/kernel/stacktrace.c
> +++ b/arch/arm64/kernel/stacktrace.c
> @@ -43,12 +43,24 @@ int notrace unwind_frame(struct stackframe *frame)
> low = frame->sp;
> high = ALIGN(low, THREAD_SIZE);
>
> - if (fp < low || fp > high - 0x18 || fp & 0xf)
> + if (fp < low || fp > high - 0x20 || fp & 0xf)
> return -EINVAL;
>
> frame->sp = fp + 0x10;
> frame->fp = *(unsigned long *)(fp);
> /*
> + * check whether we are going to walk trough from interrupt stack
> + * to process stack
> + * If the previous frame is the initial (dummy) stack frame on
> + * interrupt stack, frame->sp now points to just below the frame
> + * (dummy frame + 0x10).
> + * See entry.S
> + */
> +#define STACK_LOW(addr) round_down((addr), THREAD_SIZE)
> + if ((STACK_LOW(frame->sp) != STACK_LOW(frame->fp)) &&
> + (frame->fp == *(unsigned long *)frame->sp))
> + frame->sp = *((unsigned long *)(frame->sp + 8));
> + /*
> * -4 here because we care about the PC at time of bl,
> * not where the return will go.
> */
> --
> 1.7.9.5

How about folding the following hunk into this patch?
The comment would be helpful for people to follow this code.

----8<----

diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index f1303c5..0ff7db3 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -122,7 +122,8 @@
* x21 - aborted SP
* x22 - aborted PC
* x23 - aborted PSTATE
- */
+ * x29 - aborted FP
+ */
.endm

.macro kernel_exit, el

----8<----

Best Regards
Jungseok Lee--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/