Cc: Sourabh Jain <sourabhjain(a)linux.ibm.com>
Cc: Hari Bathini <hbathini(a)linux.ibm.com>
Cc: Mahesh J Salgaonkar <mahesh(a)linux.ibm.com>
Cc: Naveen N. Rao <naveen.n.rao(a)linux.vnet.ibm.com>
Cc: Lianbo Jiang <lijiang(a)redhat.com>
Cc: HAGIO KAZUHITO(萩尾 一仁) <k-hagio-ab(a)nec.com>
Cc: Tao Liu <ltao(a)redhat.com>
Cc: Alexey Makhalov <alexey.makhalov(a)broadcom.com>
Cc: Aditya Gupta <adityag(a)linux.ibm.com>
Signed-off-by: Tao Liu <ltao(a)redhat.com>
---
arm64.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
defs.h | 36 +++++++++++++++++
2 files changed, 148 insertions(+), 8 deletions(-)
diff --git a/arm64.c b/arm64.c
index 06e7451..cedaee9 100644
--- a/arm64.c
+++ b/arm64.c
@@ -120,6 +120,11 @@ static void arm64_get_struct_page_size(struct machine_specific *ms);
#define mte_tag_reset(addr) (((ulong)addr & ~mte_tag_shifted(KASAN_TAG_KERNEL)) | \
mte_tag_shifted(KASAN_TAG_KERNEL))
+struct user_regs_bitmap_struct {
+ struct arm64_pt_regs ur;
+ ulong bitmap[32];
+};
+
static inline bool is_mte_kvaddr(ulong addr)
{
/* check for ARM64_MTE enabled */
@@ -196,6 +201,94 @@ out:
machdep->is_page_ptr = arm64_vmemmap_is_page_ptr;
}
+static int
+arm64_get_current_task_reg(int regno, const char *name,
+ int size, void *value)
+{
+ struct bt_info bt_info, bt_setup;
+ struct task_context *tc;
+ struct user_regs_bitmap_struct *ur_bitmap;
+ ulong ip, sp;
+ bool ret = FALSE;
+
+ switch (regno) {
+ case X0_REGNUM ... PC_REGNUM:
+ break;
+ default:
+ return FALSE;
+ }
+
+ tc = CURRENT_CONTEXT();
+ if (!tc)
+ return FALSE;
+ BZERO(&bt_setup, sizeof(struct bt_info));
+ clone_bt_info(&bt_setup, &bt_info, tc);
+ fill_stackbuf(&bt_info);
+
+ get_dumpfile_regs(&bt_info, &sp, &ip);
+ if (bt_info.stackbuf)
+ FREEBUF(bt_info.stackbuf);
+ ur_bitmap = (struct user_regs_bitmap_struct *)bt_info.machdep;
+ if (!ur_bitmap)
+ return FALSE;
+
+ if (!bt_info.need_free) {
+ goto get_all;
+ }
+
+ switch (regno) {
+ case X0_REGNUM ... X30_REGNUM:
+ if (!NUM_IN_BITMAP(ur_bitmap->bitmap,
+ REG_SEQ(arm64_pt_regs, regs[0]) + regno - X0_REGNUM)) {
+ FREEBUF(ur_bitmap);
+ return FALSE;
+ }
+ break;
+ case SP_REGNUM:
+ if (!NUM_IN_BITMAP(ur_bitmap->bitmap,
+ REG_SEQ(arm64_pt_regs, sp))) {
+ FREEBUF(ur_bitmap);
+ return FALSE;
+ }
+ break;
+ case PC_REGNUM:
+ if (!NUM_IN_BITMAP(ur_bitmap->bitmap,
+ REG_SEQ(arm64_pt_regs, pc))) {
+ FREEBUF(ur_bitmap);
+ return FALSE;
+ }
+ break;
+ }
+
+get_all:
+ switch (regno) {
+ case X0_REGNUM ... X30_REGNUM:
+ if (size != sizeof(ur_bitmap->ur.regs[regno]))
+ break;
+ memcpy(value, &ur_bitmap->ur.regs[regno], size);
+ ret = TRUE;
+ break;
+ case SP_REGNUM:
+ if (size != sizeof(ur_bitmap->ur.sp))
+ break;
+ memcpy(value, &ur_bitmap->ur.sp, size);
+ ret = TRUE;
+ break;
+ case PC_REGNUM:
+ if (size != sizeof(ur_bitmap->ur.pc))
+ break;
+ memcpy(value, &ur_bitmap->ur.pc, size);
+ ret = TRUE;
+ break;
+ }
+
+ if (bt_info.need_free) {
+ FREEBUF(ur_bitmap);
+ bt_info.need_free = FALSE;
+ }
+ return ret;
+}
+
/*
* Do all necessary machine-specific setup here. This is called several times
* during initialization.
@@ -520,6 +613,7 @@ arm64_init(int when)
machdep->dumpfile_init = NULL;
machdep->verify_line_number = NULL;
machdep->init_kernel_pgd = arm64_init_kernel_pgd;
+ machdep->get_current_task_reg = arm64_get_current_task_reg;
/* use machdep parameters */
arm64_calc_phys_offset();
@@ -654,6 +748,7 @@ arm64_init(int when)
*/
if (!LIVE())
arm64_get_crash_notes();
+ gdb_change_thread_context();
break;
case LOG_ONLY:
@@ -4011,6 +4106,7 @@ arm64_get_dumpfile_stackframe(struct bt_info *bt, struct
arm64_stackframe *frame
try_kernel:
frame->sp = ptregs->sp;
frame->fp = ptregs->regs[29];
+ bt->machdep = ptregs;
}
if (arm64_in_kdump_text(bt, frame) ||
@@ -4039,23 +4135,31 @@ arm64_get_stackframe(struct bt_info *bt, struct arm64_stackframe
*frame)
static void
arm64_get_stack_frame(struct bt_info *bt, ulong *pcp, ulong *spp)
{
- int ret;
+ struct user_regs_bitmap_struct *ur_bitmap;
struct arm64_stackframe stackframe = { 0 };
if (DUMPFILE() && is_task_active(bt->task)) {
- ret = arm64_get_dumpfile_stackframe(bt, &stackframe);
+ arm64_get_dumpfile_stackframe(bt, &stackframe);
+ bt->need_free = FALSE;
} else {
if (bt->flags & BT_SKIP_IDLE)
bt->flags &= ~BT_SKIP_IDLE;
- ret = arm64_get_stackframe(bt, &stackframe);
+ arm64_get_stackframe(bt, &stackframe);
+
+ ur_bitmap = (struct user_regs_bitmap_struct *)GETBUF(sizeof(*ur_bitmap));
+ memset(ur_bitmap, 0, sizeof(*ur_bitmap));
+ ur_bitmap->ur.pc = stackframe.pc;
+ ur_bitmap->ur.sp = stackframe.sp;
+ ur_bitmap->ur.regs[29] = stackframe.fp;
+ SET_BIT(ur_bitmap->bitmap, REG_SEQ(arm64_pt_regs, pc));
+ SET_BIT(ur_bitmap->bitmap, REG_SEQ(arm64_pt_regs, sp));
+ SET_BIT(ur_bitmap->bitmap, REG_SEQ(arm64_pt_regs, regs[0])
+ + X29_REGNUM - X0_REGNUM);
+ bt->machdep = ur_bitmap;
+ bt->need_free = TRUE;
}
- if (!ret)
- error(WARNING,
- "cannot determine starting stack frame for task %lx\n",
- bt->task);
-
bt->frameptr = stackframe.fp;
if (pcp)
*pcp = stackframe.pc;
diff --git a/defs.h b/defs.h
index abfa923..104ec48 100644
--- a/defs.h
+++ b/defs.h
@@ -8111,6 +8111,42 @@ enum x86_64_regnum {
LAST_REGNUM
};
+enum arm64_regnum {
+ X0_REGNUM,
+ X1_REGNUM,
+ X2_REGNUM,
+ X3_REGNUM,
+ X4_REGNUM,
+ X5_REGNUM,
+ X6_REGNUM,
+ X7_REGNUM,
+ X8_REGNUM,
+ X9_REGNUM,
+ X10_REGNUM,
+ X11_REGNUM,
+ X12_REGNUM,
+ X13_REGNUM,
+ X14_REGNUM,
+ X15_REGNUM,
+ X16_REGNUM,
+ X17_REGNUM,
+ X18_REGNUM,
+ X19_REGNUM,
+ X20_REGNUM,
+ X21_REGNUM,
+ X22_REGNUM,
+ X23_REGNUM,
+ X24_REGNUM,
+ X25_REGNUM,
+ X26_REGNUM,
+ X27_REGNUM,
+ X28_REGNUM,
+ X29_REGNUM,
+ X30_REGNUM,
+ SP_REGNUM,
+ PC_REGNUM,
+};
+
/*
* Register numbers to make crash_target->fetch_registers()
* ---> machdep->get_current_task_reg() work properly.
--
2.40.1