From 0cc4432642c4f14a932a9f3562f7a9edfce73f13 Mon Sep 17 00:00:00 2001 From: Thiago Jung Bauermann Date: Sat, 26 Apr 2025 16:24:29 -0300 Subject: [PATCH] gdbserver: linux-aarch64: Add variable-size registers and tdesc parameters The target description parameters for SVE are supported. This commit adds a low_fetch_registers method to aarch64_target, so that the VG register can be fetched individually, before the whole SVE regset. This is important to allow calculating the SVE target description parameters and determine the SVE vector register sizes. --- gdbserver/linux-aarch64-low.cc | 88 ++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/gdbserver/linux-aarch64-low.cc b/gdbserver/linux-aarch64-low.cc index 0aa626c5414..ba24bf265c5 100644 --- a/gdbserver/linux-aarch64-low.cc +++ b/gdbserver/linux-aarch64-low.cc @@ -95,6 +95,12 @@ public: bool store_memtags (CORE_ADDR address, size_t len, const gdb::byte_vector &tags, int type) override; + ULONGEST tdesc_parameter_value (regcache *regcache, + unsigned int param_id) override; + + bool is_register_relevant_for_tdesc_parameter (const target_desc *tdesc, + int regnum) override; + protected: void low_arch_setup () override; @@ -143,6 +149,8 @@ protected: bool low_supports_catch_syscall () override; void low_get_syscall_trapinfo (regcache *regcache, int *sysno) override; + + bool low_fetch_register (regcache *regcache, int regno) override; }; /* The singleton target ops object. */ @@ -1034,6 +1042,24 @@ aarch64_target::low_get_syscall_trapinfo (regcache *regcache, int *sysno) collect_register_by_name (regcache, "r7", sysno); } +bool +aarch64_target::low_fetch_register (regcache *regcache, int regno) +{ + if (regno != AARCH64_SVE_VG_REGNUM) + return false; + + user_sve_header header; + if (!read_sve_header (current_thread->id.lwp (), header)) + return false; + + uint64_t vg = sve_vg_from_vl (header.vl); + regcache->raw_supply (AARCH64_SVE_VG_REGNUM, + gdb::make_array_view ((const gdb_byte *) &vg, + sizeof (vg))); + + return true; +} + /* List of condition codes that we need. */ enum aarch64_condition_codes @@ -3452,6 +3478,68 @@ aarch64_target::store_memtags (CORE_ADDR address, size_t len, return false; } +/* FIXME: Document. */ +/* Note: In the XML, vector_length is used in bitsize fields, but internally + GDB expects the size in bytes. */ + +ULONGEST +aarch64_target::tdesc_parameter_value (regcache *regcache, + unsigned int param_id) +{ + gdb_assert (param_id != UINT_MAX); + + /* FIXME: Find some place to cache these values. */ + unsigned int sve_vector_length, sve_predicate_length; + ULONGEST ret; + + std::optional maybe_param_id + = tdesc_parameter_id (regcache->tdesc, "org.gnu.gdb.aarch64.sve", + "vector_length"); + if (maybe_param_id.has_value ()) + sve_vector_length = *maybe_param_id; + else + sve_vector_length = UINT_MAX; + + maybe_param_id = tdesc_parameter_id (regcache->tdesc, + "org.gnu.gdb.aarch64.sve", + "predicate_length"); + if (maybe_param_id.has_value ()) + sve_predicate_length = *maybe_param_id; + else + sve_predicate_length = UINT_MAX; + + if (param_id == sve_vector_length) + { + register_status status + = regcache_raw_read_unsigned (regcache, AARCH64_SVE_VG_REGNUM, &ret); + gdb_assert (status == REG_VALID); + + ret = sve_vl_from_vg (ret); + } + else if (param_id == sve_predicate_length) + { + register_status status + = regcache_raw_read_unsigned (regcache, AARCH64_SVE_VG_REGNUM, &ret); + gdb_assert (status == REG_VALID); + } else + gdb_assert_not_reached ("Unknown parameter %u requested.", param_id); + + return ret; +} + +/* FIXME: Document. */ + +bool +aarch64_target::is_register_relevant_for_tdesc_parameter (const target_desc *tdesc, + int regnum) +{ + if (tdesc->parameters.size () == 0) + return false; + else + /* All current AArch64 parameters depend on VG. */ + return regnum == AARCH64_SVE_VG_REGNUM; +} + /* The linux target ops object. */ linux_process_target *the_linux_target = &the_aarch64_target; -- 2.47.2