From 5a491cb2d889f03952182d611d2ac6e15c3c5845 Mon Sep 17 00:00:00 2001 From: Leonid Chistov Date: Thu, 1 Oct 2015 11:23:50 +0300 Subject: [PATCH] arm64: Support for restore of ARM64 Neon callee-saved registers during unwind --- src/aarch64/Ginit.c | 4 +++- src/aarch64/Gregs.c | 7 +++++-- src/aarch64/Gresume.c | 21 +++++++++++++++++---- src/aarch64/unwind_i.h | 2 ++ 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/aarch64/Ginit.c b/src/aarch64/Ginit.c index 667c4764..ab3999f3 100644 --- a/src/aarch64/Ginit.c +++ b/src/aarch64/Ginit.c @@ -43,8 +43,10 @@ PROTECTED unw_addr_space_t unw_local_addr_space = &local_addr_space; static inline void * uc_addr (ucontext_t *uc, int reg) { - if (reg >= UNW_AARCH64_X0 && reg <= UNW_AARCH64_V31) + if (reg >= UNW_AARCH64_X0 && reg < UNW_AARCH64_V0) return &uc->uc_mcontext.regs[reg]; + else if (reg >= UNW_AARCH64_V0 && reg <= UNW_AARCH64_V31) + return &GET_FPCTX(uc)->vregs[reg - UNW_AARCH64_V0]; else return NULL; } diff --git a/src/aarch64/Gregs.c b/src/aarch64/Gregs.c index 104fd62a..a8843734 100644 --- a/src/aarch64/Gregs.c +++ b/src/aarch64/Gregs.c @@ -110,6 +110,9 @@ HIDDEN int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp, int write) { - Debug (1, "bad register number %u\n", reg); - return -UNW_EBADREG; + dwarf_loc_t loc = c->dwarf.loc[reg]; + if (write) + return dwarf_putfp (&c->dwarf, loc, *valp); + else + return dwarf_getfp (&c->dwarf, loc, valp); } diff --git a/src/aarch64/Gresume.c b/src/aarch64/Gresume.c index d9acfa7c..65517a25 100644 --- a/src/aarch64/Gresume.c +++ b/src/aarch64/Gresume.c @@ -40,7 +40,7 @@ aarch64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) { /* Since there are no signals involved here we restore EH and non scratch registers only. */ - unsigned long regs[15]; + unsigned long regs[24]; regs[0] = uc->uc_mcontext.regs[0]; regs[1] = uc->uc_mcontext.regs[1]; regs[2] = uc->uc_mcontext.regs[2]; @@ -55,7 +55,16 @@ aarch64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) regs[11] = uc->uc_mcontext.regs[26]; regs[12] = uc->uc_mcontext.regs[27]; regs[13] = uc->uc_mcontext.regs[28]; - regs[14] = uc->uc_mcontext.regs[30]; /* LR */ + regs[14] = uc->uc_mcontext.regs[29]; /* FP */ + regs[15] = uc->uc_mcontext.regs[30]; /* LR */ + regs[16] = GET_FPCTX(uc)->vregs[8]; + regs[17] = GET_FPCTX(uc)->vregs[9]; + regs[18] = GET_FPCTX(uc)->vregs[10]; + regs[19] = GET_FPCTX(uc)->vregs[11]; + regs[20] = GET_FPCTX(uc)->vregs[12]; + regs[21] = GET_FPCTX(uc)->vregs[13]; + regs[22] = GET_FPCTX(uc)->vregs[14]; + regs[23] = GET_FPCTX(uc)->vregs[15]; unsigned long sp = uc->uc_mcontext.sp; struct regs_overlay { @@ -72,7 +81,11 @@ aarch64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) "ldp x23, x24, [x4,64]\n" "ldp x25, x26, [x4,80]\n" "ldp x27, x28, [x4,96]\n" - "ldr x30, [x4,112]\n" + "ldp x29, x30, [x4,112]\n" + "ldp d8, d9, [x4,128]\n" + "ldp d10, d11, [x4,144]\n" + "ldp d12, d13, [x4,160]\n" + "ldp d14, d15, [x4,176]\n" "mov sp, x5\n" "ret \n" : @@ -147,7 +160,7 @@ establish_machine_state (struct cursor *c) Debug (8, "copying out cursor state\n"); - for (reg = 0; reg <= UNW_AARCH64_PSTATE; ++reg) + for (reg = 0; reg <= UNW_AARCH64_V31; ++reg) { Debug (16, "copying %s %d\n", unw_regname (reg), reg); if (unw_is_fpreg (reg)) diff --git a/src/aarch64/unwind_i.h b/src/aarch64/unwind_i.h index 79b342cd..3d324c2b 100644 --- a/src/aarch64/unwind_i.h +++ b/src/aarch64/unwind_i.h @@ -59,4 +59,6 @@ extern int aarch64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, } while (0) #endif +#define GET_FPCTX(uc) ((struct fpsimd_context *)(&uc->uc_mcontext.__reserved)) + #endif /* unwind_i_h */