diff --git a/gdbserver/linux-aarch64-low.cc b/gdbserver/linux-aarch64-low.cc index e887e39b1c2..fcbe7bb64d7 100644 --- a/gdbserver/linux-aarch64-low.cc +++ b/gdbserver/linux-aarch64-low.cc @@ -797,6 +797,46 @@ aarch64_za_regs_copy_from_regcache (struct regcache *regcache, void *buf) memcpy (buf, za_state.data (), za_state.size ()); } +/* Wrapper for aarch64_zt_regs_copy_to_reg_buf, to help copying NT_ARM_ZT + state from the thread (BUF) to the register cache. */ + +static void +aarch64_zt_regs_copy_to_regcache (struct regcache *regcache, + ATTRIBUTE_UNUSED const void *buf) +{ + /* BUF is unused here since we collect the data straight from a ptrace + request, therefore bypassing gdbserver's own call to ptrace. */ + int tid = lwpid_of (current_thread); + + int zt_regnum = find_regno (regcache->tdesc, "zt0"); + + /* Update the register cache. aarch64_zt_regs_copy_to_reg_buf handles + fetching the NT_ARM_ZT state from thread TID. */ + aarch64_zt_regs_copy_to_reg_buf (tid, regcache, zt_regnum); +} + +/* Wrapper for aarch64_zt_regs_copy_from_reg_buf, to help copying NT_ARM_ZT + state from the register cache to the thread (BUF). */ + +static void +aarch64_zt_regs_copy_from_regcache (struct regcache *regcache, void *buf) +{ + int tid = lwpid_of (current_thread); + + int zt_regnum = find_regno (regcache->tdesc, "zt0"); + + /* Update the thread NT_ARM_ZT state. aarch64_zt_regs_copy_from_reg_buf + handles writing the ZT state back to thread TID. */ + aarch64_zt_regs_copy_from_reg_buf (tid, regcache, zt_regnum); + + /* We need to return the expected data in BUF, so copy whatever the kernel + already has to BUF. */ + + /* Obtain a dump of NT_ARM_ZT from ptrace. */ + gdb::byte_vector zt_state = aarch64_fetch_zt_regset (tid); + memcpy (buf, zt_state.data (), zt_state.size ()); +} + /* Array containing all the possible register sets for AArch64/Linux. During architecture setup, these will be checked against the HWCAP/HWCAP2 bits for validity and enabled/disabled accordingly. @@ -824,6 +864,11 @@ static struct regset_info aarch64_regsets[] = 0, EXTENDED_REGS, aarch64_za_regs_copy_from_regcache, aarch64_za_regs_copy_to_regcache }, + /* Scalable Matrix Extension 2 (SME2) ZT registers. */ + { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_ZT, + 0, EXTENDED_REGS, + aarch64_zt_regs_copy_from_regcache, aarch64_zt_regs_copy_to_regcache + }, /* PAC registers. */ { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_PAC_MASK, 0, OPTIONAL_REGS, @@ -895,6 +940,10 @@ aarch64_adjust_register_sets (const struct aarch64_features &features) if (features.svq > 0) regset->size = ZA_PT_SIZE (features.svq); break; + case NT_ARM_ZT: + if (features.sme2) + regset->size = AARCH64_SME2_ZT0_SIZE; + break; default: gdb_assert_not_reached ("Unknown register set found."); } @@ -933,6 +982,14 @@ aarch64_target::low_arch_setup () if (linux_get_hwcap2 (pid, 8) & HWCAP2_SME) features.svq = aarch64_za_get_svq (tid); + /* Scalable Matrix Extension 2 feature check. */ + CORE_ADDR hwcap2 = linux_get_hwcap2 (pid, 8); + if ((hwcap2 & HWCAP2_SME2) || (hwcap2 & HWCAP2_SME2P1)) + { + /* Make sure ptrace supports NT_ARM_ZT. */ + features.sme2 = supports_zt_registers (tid); + } + current_process ()->tdesc = aarch64_linux_read_description (features); /* Adjust the register sets we should use for this particular set of