sme: Add support for SME

Enable SME support in gdbserver by adjusting the usual fields.  There is
not much to this patch because the code is either in gdb or it is shared
between gdbserver and gdb.  One exception is the bump to gdbserver's
PBUFSIZ from 18432 to 131104.

Since the ZA register can be quite big (256 * 256 bytes), the g/G remote
packet will also become quite big

From gdbserver/tdesc.cc:init_target_desc, I estimated the new size should
be at least (2 * 256 * 256 + 32), which yields 131104.

It is also unlikely we will find a process starting up with SVL set to 256.

Ideally we'd adjust the packet size dynamically based on what we need, but
for now this should do.

Please note we have the same limitation for SME that we have for SVE, and
that is the fact gdbserver cannot communicate vector length changes to gdb
via the remote protocol.

Thiago is working on this improvement, which hopefully will be able to be
adapted to SME in an easy way.

Co-Authored-By: Ezra Sitorus <ezra.sitorus@arm.com>
Reviewed-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
This commit is contained in:
Luis Machado 2022-11-15 09:07:09 +00:00
parent 223dbdd276
commit b816042e88
3 changed files with 68 additions and 1 deletions

View File

@ -41,6 +41,7 @@
#include "gdb_proc_service.h"
#include "arch/aarch64.h"
#include "arch/aarch64-mte-linux.h"
#include "arch/aarch64-scalable-linux.h"
#include "linux-aarch32-tdesc.h"
#include "linux-aarch64-tdesc.h"
#include "nat/aarch64-mte-linux-ptrace.h"
@ -750,6 +751,52 @@ aarch64_sve_regs_copy_from_regcache (struct regcache *regcache, void *buf)
memcpy (buf, sve_state.data (), sve_state.size ());
}
/* Wrapper for aarch64_za_regs_copy_to_reg_buf, to help copying NT_ARM_ZA
state from the thread (BUF) to the register cache. */
static void
aarch64_za_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 za_regnum = find_regno (regcache->tdesc, "za");
int svg_regnum = find_regno (regcache->tdesc, "svg");
int svcr_regnum = find_regno (regcache->tdesc, "svcr");
/* Update the register cache. aarch64_za_regs_copy_to_reg_buf handles
fetching the NT_ARM_ZA state from thread TID. */
aarch64_za_regs_copy_to_reg_buf (tid, regcache, za_regnum, svg_regnum,
svcr_regnum);
}
/* Wrapper for aarch64_za_regs_copy_from_reg_buf, to help copying NT_ARM_ZA
state from the register cache to the thread (BUF). */
static void
aarch64_za_regs_copy_from_regcache (struct regcache *regcache, void *buf)
{
int tid = lwpid_of (current_thread);
int za_regnum = find_regno (regcache->tdesc, "za");
int svg_regnum = find_regno (regcache->tdesc, "svg");
int svcr_regnum = find_regno (regcache->tdesc, "svcr");
/* Update the thread NT_ARM_ZA state. aarch64_za_regs_copy_from_reg_buf
handles writing the ZA state back to thread TID. */
aarch64_za_regs_copy_from_reg_buf (tid, regcache, za_regnum, svg_regnum,
svcr_regnum);
/* We need to return the expected data in BUF, so copy whatever the kernel
already has to BUF. */
/* Obtain a dump of ZA from ptrace. */
gdb::byte_vector za_state = aarch64_fetch_za_regset (tid);
memcpy (buf, za_state.data (), za_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.
@ -772,6 +819,11 @@ static struct regset_info aarch64_regsets[] =
0, EXTENDED_REGS,
aarch64_sve_regs_copy_from_regcache, aarch64_sve_regs_copy_to_regcache
},
/* Scalable Matrix Extension (SME) ZA register. */
{ PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_ZA,
0, EXTENDED_REGS,
aarch64_za_regs_copy_from_regcache, aarch64_za_regs_copy_to_regcache
},
/* PAC registers. */
{ PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_PAC_MASK,
0, OPTIONAL_REGS,
@ -839,6 +891,10 @@ aarch64_adjust_register_sets (const struct aarch64_features &features)
if (features.tls > 0)
regset->size = AARCH64_TLS_REGISTER_SIZE * features.tls;
break;
case NT_ARM_ZA:
if (features.svq > 0)
regset->size = ZA_PT_SIZE (features.svq);
break;
default:
gdb_assert_not_reached ("Unknown register set found.");
}
@ -873,6 +929,10 @@ aarch64_target::low_arch_setup ()
features.mte = linux_get_hwcap2 (pid, 8) & HWCAP2_MTE;
features.tls = aarch64_tls_register_count (tid);
/* Scalable Matrix Extension feature and size check. */
if (linux_get_hwcap2 (pid, 8) & HWCAP2_SME)
features.svq = aarch64_za_get_svq (tid);
current_process ()->tdesc = aarch64_linux_read_description (features);
/* Adjust the register sets we should use for this particular set of

View File

@ -41,6 +41,11 @@ aarch64_linux_read_description (const aarch64_features &features)
error (_("VQ is %" PRIu64 ", maximum supported value is %d"), features.vq,
AARCH64_MAX_SVE_VQ);
if (features.svq > AARCH64_MAX_SVE_VQ)
error (_("Streaming svq is %" PRIu8 ", maximum supported value is %d"),
features.svq,
AARCH64_MAX_SVE_VQ);
struct target_desc *tdesc = tdesc_aarch64_map[features];
if (tdesc == NULL)
@ -56,6 +61,8 @@ aarch64_linux_read_description (const aarch64_features &features)
if (features.vq > 0)
expedited_registers.push_back ("vg");
if (features.svq > 0)
expedited_registers.push_back ("svg");
expedited_registers.push_back (nullptr);

View File

@ -104,7 +104,7 @@ extern int in_queued_stop_replies (ptid_t ptid);
/* Buffer sizes for transferring memory, registers, etc. Set to a constant
value to accommodate multiple register formats. This value must be at least
as large as the largest register set supported by gdbserver. */
#define PBUFSIZ 18432
#define PBUFSIZ 131104
/* Definition for an unknown syscall, used basically in error-cases. */
#define UNKNOWN_SYSCALL (-1)