diff options
author | Alan Hayward <alan.hayward@arm.com> | 2018-05-11 11:52:56 +0100 |
---|---|---|
committer | Simon Marchi <simon.marchi@ericsson.com> | 2018-06-01 10:40:20 -0400 |
commit | e884af534b7e77ba214e8bd8d7ba8fb6009231a4 (patch) | |
tree | 9da28d4411ef18d194c40cad6130f8bdb0380399 /gdb/aarch64-linux-nat.c | |
parent | d56bdeb9c2e434b91d5e6d605b92bb1cd21177e5 (diff) | |
download | binutils-users/simark/regcache-for-alan.zip binutils-users/simark/regcache-for-alan.tar.gz binutils-users/simark/regcache-for-alan.tar.bz2 |
Ptrace support for Aarch64 SVEusers/simark/regcache-for-alan
Add support for reading and writing registers for Aarch64 SVE.
I've made this functionality common as it will be required for
gdbserver when gdbsever sve support is added.
Given that gdbserver does not yet call this function, I am
happy to remove the regcache commonise functions from the
previous patch. However, this would result in code in nat/
that does not compile for gdbserver. I wanted to avoid that.
We need to support the cases where the kernel only gives us a
fpsimd structure. This occurs when there is no active SVE state
in the kernel (for example, after starting a new process).
As per the covering email description, I've included large chunks
of linux kernel headers within an ifdef. Formatting of these macros
remains identical to the Kernel versions (ie not adapted to GNU style).
Added checks to make sure the vector length has not changed whilst
the process is running.
2018-05-11 Alan Hayward <alan.hayward@arm.com>
gdb/
* aarch64-linux-nat.c (fetch_sveregs_from_thread): New function.
(store_sveregs_to_thread): Likewise.
(aarch64_linux_fetch_inferior_registers): Check for SVE.
(aarch64_linux_store_inferior_registers): Likewise.
* nat/aarch64-sve-linux-ptrace.c (aarch64_sve_get_sveregs): New
function.
(aarch64_sve_regs_copy_to_regcache): Likewise.
(aarch64_sve_regs_copy_from_regcache): Likewise.
* nat/aarch64-sve-linux-ptrace.h (aarch64_sve_get_sveregs): New
declaration.
(aarch64_sve_regs_copy_to_regcache): Likewise.
(aarch64_sve_regs_copy_from_regcache): Likewise.
(sve_context): Structure from Linux headers.
(SVE_SIG_ZREGS_SIZE): Define from Linux headers.
(SVE_SIG_ZREG_SIZE): Likewise.
(SVE_SIG_PREG_SIZE): Likewise.
(SVE_SIG_FFR_SIZE): Likewise.
(SVE_SIG_REGS_OFFSET): Likewise.
(SVE_SIG_ZREGS_OFFSET): Likewise.
(SVE_SIG_ZREG_OFFSET): Likewise.
(SVE_SIG_ZREGS_SIZE): Likewise.
(SVE_SIG_PREGS_OFFSET): Likewise.
(SVE_SIG_PREG_OFFSET): Likewise.
(SVE_SIG_PREGS_SIZE): Likewise.
(SVE_SIG_FFR_OFFSET): Likewise.
(SVE_SIG_REGS_SIZE): Likewise.
(SVE_SIG_CONTEXT_SIZE): Likewise.
(SVE_PT_REGS_MASK): Likewise.
(SVE_PT_REGS_FPSIMD): Likewise.
(SVE_PT_REGS_SVE): Likewise.
(SVE_PT_VL_INHERIT): Likewise.
(SVE_PT_VL_ONEXEC): Likewise.
(SVE_PT_REGS_OFFSET): Likewise.
(SVE_PT_FPSIMD_OFFSET): Likewise.
(SVE_PT_FPSIMD_SIZE): Likewise.
(SVE_PT_SVE_ZREG_SIZE): Likewise.
(SVE_PT_SVE_PREG_SIZE): Likewise.
(SVE_PT_SVE_FFR_SIZE): Likewise.
(SVE_PT_SVE_FPSR_SIZE): Likewise.
(SVE_PT_SVE_FPCR_SIZE): Likewise.
(__SVE_SIG_TO_PT): Likewise.
(SVE_PT_SVE_OFFSET): Likewise.
(SVE_PT_SVE_ZREGS_OFFSET): Likewise.
(SVE_PT_SVE_ZREG_OFFSET): Likewise.
(SVE_PT_SVE_ZREGS_SIZE): Likewise.
(SVE_PT_SVE_PREGS_OFFSET): Likewise.
(SVE_PT_SVE_PREG_OFFSET): Likewise.
(SVE_PT_SVE_PREGS_SIZE): Likewise.
(SVE_PT_SVE_FFR_OFFSET): Likewise.
(SVE_PT_SVE_FPSR_OFFSET): Likewise.
(SVE_PT_SVE_FPCR_OFFSET): Likewise.
(SVE_PT_SVE_SIZE): Likewise.
(SVE_PT_SIZE): Likewise.
(HAS_SVE_STATE): New define.
gdbserver
* Makefile.in: Add aarch64-sve-linux-ptrace.c.
Diffstat (limited to 'gdb/aarch64-linux-nat.c')
-rw-r--r-- | gdb/aarch64-linux-nat.c | 57 |
1 files changed, 55 insertions, 2 deletions
diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c index 79dd9ce..8165594 100644 --- a/gdb/aarch64-linux-nat.c +++ b/gdb/aarch64-linux-nat.c @@ -384,19 +384,65 @@ store_fpregs_to_thread (ptid_t ptid, const reg_buffer *regcache) } } +/* Fill GDB's register array with the sve register values + from the current thread. */ + +static void +fetch_sveregs_from_thread (ptid_t ptid, reg_buffer *regcache) +{ + gdb_byte *base = aarch64_sve_get_sveregs (ptid.lwp ()); + aarch64_sve_regs_copy_to_regcache (regcache, base); + xfree (base); +} + +/* Store to the current thread the valid sve register + values in the GDB's register array. */ + +static void +store_sveregs_to_thread (ptid_t ptid, reg_buffer *regcache) +{ + gdb_byte *base; + int ret, tid; + struct iovec iovec; + + tid = ptid_get_lwp (inferior_ptid); + + /* Obtain a dump of SVE registers from ptrace. */ + base = aarch64_sve_get_sveregs (tid); + + /* Overwrite with regcache state. */ + aarch64_sve_regs_copy_from_regcache (regcache, base); + + /* Write back to the kernel. */ + iovec.iov_base = base; + iovec.iov_len = ((struct user_sve_header *) base)->size; + ret = ptrace (PTRACE_SETREGSET, tid, NT_ARM_SVE, &iovec); + xfree (base); + + if (ret < 0) + perror_with_name (_("Unable to store sve registers")); +} + /* Implement the "fetch_registers" target_ops method. */ void aarch64_linux_nat_target::fetch_registers (ptid_t ptid, reg_buffer *regcache, int regno) { + struct gdbarch_tdep *tdep = gdbarch_tdep (regcache->arch ()); + if (regno == -1) { fetch_gregs_from_thread (ptid, regcache); - fetch_fpregs_from_thread (ptid, regcache); + if (tdep->has_sve ()) + fetch_sveregs_from_thread (ptid, regcache); + else + fetch_fpregs_from_thread (ptid, regcache); } else if (regno < AARCH64_V0_REGNUM) fetch_gregs_from_thread (ptid, regcache); + else if (tdep->has_sve ()) + fetch_sveregs_from_thread (ptid, regcache); else fetch_fpregs_from_thread (ptid, regcache); } @@ -407,13 +453,20 @@ void aarch64_linux_nat_target::store_registers (ptid_t ptid, reg_buffer *regcache, int regno) { + struct gdbarch_tdep *tdep = gdbarch_tdep (regcache->arch ()); + if (regno == -1) { store_gregs_to_thread (ptid, regcache); - store_fpregs_to_thread (ptid, regcache); + if (tdep->has_sve ()) + store_sveregs_to_thread (ptid, regcache); + else + store_fpregs_to_thread (ptid, regcache); } else if (regno < AARCH64_V0_REGNUM) store_gregs_to_thread (ptid, regcache); + else if (tdep->has_sve ()) + store_sveregs_to_thread (ptid, regcache); else store_fpregs_to_thread (ptid, regcache); } |