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

From: AKASHI Takahiro
Date: Tue Oct 20 2015 - 04:01:38 EST


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

--
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/