* [PATCH v4 1/6] gdb/aarch64: Enable FPMR for AArch64 in gdb on Linux
2025-10-31 15:16 [PATCH v4 0/6] gdb/aarch64: Support for FPMR Ezra.Sitorus
@ 2025-10-31 15:16 ` Ezra.Sitorus
2025-10-31 15:16 ` [PATCH v4 2/6] gdbserver/aarch64: Enable FPMR for AArch64 in gdbserver " Ezra.Sitorus
` (4 subsequent siblings)
5 siblings, 0 replies; 13+ messages in thread
From: Ezra.Sitorus @ 2025-10-31 15:16 UTC (permalink / raw)
To: gdb-patches; +Cc: luis.machado.foss, Ezra Sitorus
From: Ezra Sitorus <ezra.sitorus@arm.com>
The Floating Point Mode Register controls the behaviours of FP8
instructions. This patch add FPMR to GDB if it is enabled on the
target.
---
Changes from v1->v2:
* Addressed comments/whitespace/formatting issues.
* gdb/arch/aarch64.h: operator() takes fpmr into account now.
* Defined HWCAP2_FPMR in gdb/arch/aarch64.h
Changes from v2->v3:
* Formatting fixes.
* Moved initialisation of fpmr variables closer to where they are used.
Changes from v3->v4:
* Formatting in comment.
Ezra
gdb/aarch64-linux-nat.c | 57 +++++++++++++++++++++++++++++++++++
gdb/aarch64-linux-tdep.c | 1 +
gdb/aarch64-tdep.c | 15 +++++++++
gdb/aarch64-tdep.h | 9 ++++++
gdb/arch/aarch64.c | 4 +++
gdb/arch/aarch64.h | 12 +++++++-
gdb/features/Makefile | 1 +
gdb/features/aarch64-fpmr.c | 44 +++++++++++++++++++++++++++
gdb/features/aarch64-fpmr.xml | 57 +++++++++++++++++++++++++++++++++++
9 files changed, 199 insertions(+), 1 deletion(-)
create mode 100644 gdb/features/aarch64-fpmr.c
create mode 100644 gdb/features/aarch64-fpmr.xml
diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
index 89ecedda57d..503a41c973d 100644
--- a/gdb/aarch64-linux-nat.c
+++ b/gdb/aarch64-linux-nat.c
@@ -604,6 +604,48 @@ store_gcsregs_to_thread (regcache *regcache)
perror_with_name (_("Unable to store GCS registers"));
}
+/* Fill GDB's REGCACHE with the FPMR register set content from the
+ thread associated with REGCACHE. */
+
+static void
+fetch_fpmr_from_thread (struct regcache *regcache)
+{
+ aarch64_gdbarch_tdep *tdep
+ = gdbarch_tdep<aarch64_gdbarch_tdep> (regcache->arch ());
+
+ int tid = regcache->ptid ().lwp ();
+
+ struct iovec iov;
+ uint64_t val;
+ iov.iov_base = &val;
+ iov.iov_len = sizeof (val);
+
+ if (ptrace (PTRACE_GETREGSET, tid, NT_ARM_FPMR, &iov) < 0)
+ perror_with_name (_("Unable to fetch FPMR register set"));
+ regcache->raw_supply (tdep->fpmr_regnum, &val);
+}
+
+/* Store the NT_ARM_FPMR register set contents from GDB's REGCACHE to the
+ thread associated with REGCACHE. */
+
+static void
+store_fpmr_to_thread (struct regcache *regcache)
+{
+ aarch64_gdbarch_tdep *tdep
+ = gdbarch_tdep<aarch64_gdbarch_tdep> (regcache->arch ());
+
+ int tid = regcache->ptid ().lwp ();
+
+ struct iovec iov;
+ uint64_t val;
+ iov.iov_base = &val;
+ iov.iov_len = sizeof (val);
+
+ regcache->raw_collect (tdep->fpmr_regnum, (char *) &val);
+ if (ptrace (PTRACE_SETREGSET, tid, NT_ARM_FPMR, &iov) < 0)
+ perror_with_name (_("Unable to store FPMR register set"));
+}
+
/* The AArch64 version of the "fetch_registers" target_ops method. Fetch
REGNO from the target and place the result into REGCACHE. */
@@ -642,6 +684,9 @@ aarch64_fetch_registers (struct regcache *regcache, int regno)
if (tdep->has_gcs_linux ())
fetch_gcsregs_from_thread (regcache);
+
+ if (tdep->has_fpmr ())
+ fetch_fpmr_from_thread (regcache);
}
/* General purpose register? */
else if (regno < AARCH64_V0_REGNUM)
@@ -679,6 +724,9 @@ aarch64_fetch_registers (struct regcache *regcache, int regno)
&& (regno == tdep->gcs_reg_base || regno == tdep->gcs_linux_reg_base
|| regno == tdep->gcs_linux_reg_base + 1))
fetch_gcsregs_from_thread (regcache);
+ /* FPMR? */
+ else if (tdep->has_fpmr () && (regno == tdep->fpmr_regnum))
+ fetch_fpmr_from_thread (regcache);
}
/* A version of the "fetch_registers" target_ops method used when running
@@ -753,6 +801,9 @@ aarch64_store_registers (struct regcache *regcache, int regno)
if (tdep->has_gcs_linux ())
store_gcsregs_to_thread (regcache);
+
+ if (tdep->has_fpmr ())
+ store_fpmr_to_thread (regcache);
}
/* General purpose register? */
else if (regno < AARCH64_V0_REGNUM)
@@ -784,6 +835,9 @@ aarch64_store_registers (struct regcache *regcache, int regno)
&& (regno == tdep->gcs_reg_base || regno == tdep->gcs_linux_reg_base
|| regno == tdep->gcs_linux_reg_base + 1))
store_gcsregs_to_thread (regcache);
+ /* FPMR? */
+ else if (tdep->has_fpmr () && regno == tdep->fpmr_regnum)
+ store_fpmr_to_thread (regcache);
/* PAuth registers are read-only. */
}
@@ -969,6 +1023,9 @@ aarch64_linux_nat_target::read_description ()
if ((hwcap2 & HWCAP2_SME2) || (hwcap2 & HWCAP2_SME2P1))
features.sme2 = supports_zt_registers (tid);
+ /* Check for FPMR. */
+ features.fpmr = hwcap2 & HWCAP2_FPMR;
+
return aarch64_read_description (features);
}
diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
index 048be4f3532..10b44d978af 100644
--- a/gdb/aarch64-linux-tdep.c
+++ b/gdb/aarch64-linux-tdep.c
@@ -1712,6 +1712,7 @@ aarch64_linux_core_read_description (struct gdbarch *gdbarch,
features.pauth = hwcap & AARCH64_HWCAP_PACA;
features.gcs = features.gcs_linux = hwcap & HWCAP_GCS;
features.mte = hwcap2 & HWCAP2_MTE;
+ features.fpmr = hwcap2 & HWCAP2_FPMR;
/* Handle the TLS section. */
asection *tls = bfd_get_section_by_name (abfd, ".reg-aarch-tls");
diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index 500ac77d75a..969554ed571 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -4140,6 +4140,10 @@ aarch64_features_from_target_desc (const struct target_desc *tdesc)
features.gcs_linux = (tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.gcs.linux")
!= nullptr);
+ /* Check for FPMR feature. */
+ features.fpmr = (tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.fpmr")
+ != nullptr);
+
return features;
}
@@ -4550,6 +4554,16 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
num_pseudo_regs += 32; /* add the Bn scalar register pseudos */
}
+ int fpmr_regnum = -1;
+ const struct tdesc_feature *feature_fpmr
+ = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.fpmr");
+ if (feature_fpmr != nullptr)
+ {
+ fpmr_regnum = num_regs++;
+ valid_p &= tdesc_numbered_register (feature_fpmr, tdesc_data.get (),
+ fpmr_regnum, "fpmr");
+ }
+
int first_sme_regnum = -1;
int first_sme2_regnum = -1;
int first_sme_pseudo_regnum = -1;
@@ -4749,6 +4763,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
tdep->tls_register_count = tls_register_count;
tdep->gcs_reg_base = first_gcs_regnum;
tdep->gcs_linux_reg_base = first_gcs_linux_regnum;
+ tdep->fpmr_regnum = fpmr_regnum;
/* Set the SME register set details. The pseudo-registers will be adjusted
later. */
diff --git a/gdb/aarch64-tdep.h b/gdb/aarch64-tdep.h
index 99e7d26ce4a..9acd29b2d88 100644
--- a/gdb/aarch64-tdep.h
+++ b/gdb/aarch64-tdep.h
@@ -207,6 +207,15 @@ struct aarch64_gdbarch_tdep : gdbarch_tdep_base
{
return gcs_linux_reg_base != -1;
}
+
+ /* First FPMR register. This is -1 if FPMR is not supported. */
+ int fpmr_regnum = -1;
+
+ bool
+ has_fpmr () const
+ {
+ return fpmr_regnum != -1;
+ }
};
const target_desc *aarch64_read_description (const aarch64_features &features);
diff --git a/gdb/arch/aarch64.c b/gdb/arch/aarch64.c
index dff2bc16003..622138f43b5 100644
--- a/gdb/arch/aarch64.c
+++ b/gdb/arch/aarch64.c
@@ -20,6 +20,7 @@
#include "../features/aarch64-core.c"
#include "../features/aarch64-fpu.c"
+#include "../features/aarch64-fpmr.c"
#include "../features/aarch64-sve.c"
#include "../features/aarch64-pauth.c"
#include "../features/aarch64-mte.c"
@@ -73,6 +74,9 @@ aarch64_create_target_description (const aarch64_features &features)
if (features.gcs_linux)
regnum = create_feature_aarch64_gcs_linux (tdesc.get (), regnum);
+ if (features.fpmr)
+ regnum = create_feature_aarch64_fpmr (tdesc.get (), regnum);
+
return tdesc.release ();
}
diff --git a/gdb/arch/aarch64.h b/gdb/arch/aarch64.h
index 679d845df74..8f4ba9c9e0c 100644
--- a/gdb/arch/aarch64.h
+++ b/gdb/arch/aarch64.h
@@ -34,6 +34,7 @@ struct aarch64_features
uint64_t vq = 0;
bool pauth = false;
bool mte = false;
+ bool fpmr = false;
/* A positive TLS value indicates the number of TLS registers available. */
uint8_t tls = 0;
@@ -68,7 +69,8 @@ inline bool operator==(const aarch64_features &lhs, const aarch64_features &rhs)
&& lhs.svq == rhs.svq
&& lhs.sme2 == rhs.sme2
&& lhs.gcs == rhs.gcs
- && lhs.gcs_linux == rhs.gcs_linux;
+ && lhs.gcs_linux == rhs.gcs_linux
+ && lhs.fpmr == rhs.fpmr;
}
namespace std
@@ -94,6 +96,9 @@ namespace std
/* SME2 feature. */
h = h << 1 | features.sme2;
+
+ /* FPMR feature. */
+ h = h << 1 | features.fpmr;
return h;
}
};
@@ -238,4 +243,9 @@ enum aarch64_regnum
/* Size of the SME2 ZT0 register in bytes. */
#define AARCH64_SME2_ZT0_SIZE 64
+/* Feature check for Floating Point Mode Register. */
+#ifndef HWCAP2_FPMR
+#define HWCAP2_FPMR (1ULL << 48)
+#endif /* HWCAP2_FPMR */
+
#endif /* GDB_ARCH_AARCH64_H */
diff --git a/gdb/features/Makefile b/gdb/features/Makefile
index d17c349b6cf..ed1b8bf119c 100644
--- a/gdb/features/Makefile
+++ b/gdb/features/Makefile
@@ -201,6 +201,7 @@ $(outdir)/%.dat: %.xml number-regs.xsl sort-regs.xsl gdbserver-regs.xsl
# For targets with feature based target descriptions,
# the set of xml files we'll generate .c files for GDB from.
FEATURE_XMLFILES = aarch64-core.xml \
+ aarch64-fpmr.xml \
aarch64-fpu.xml \
aarch64-pauth.xml \
aarch64-mte.xml \
diff --git a/gdb/features/aarch64-fpmr.c b/gdb/features/aarch64-fpmr.c
new file mode 100644
index 00000000000..a372b12530b
--- /dev/null
+++ b/gdb/features/aarch64-fpmr.c
@@ -0,0 +1,44 @@
+/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro:
+ Original: aarch64-fpmr.xml */
+
+#include "gdbsupport/tdesc.h"
+
+static int
+create_feature_aarch64_fpmr (struct target_desc *result, long regnum)
+{
+ struct tdesc_feature *feature;
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.aarch64.fpmr");
+ tdesc_type_with_fields *type_with_fields;
+ type_with_fields = tdesc_create_enum (feature, "fp8_fmt", 3);
+ tdesc_add_enum_value (type_with_fields, 0, "E5M2");
+ tdesc_add_enum_value (type_with_fields, 1, "E4M3");
+
+ type_with_fields = tdesc_create_enum (feature, "osc", 1);
+ tdesc_add_enum_value (type_with_fields, 0, "Inf/NaN");
+ tdesc_add_enum_value (type_with_fields, 1, "MaxNormal");
+
+ type_with_fields = tdesc_create_enum (feature, "osm", 1);
+ tdesc_add_enum_value (type_with_fields, 0, "Inf");
+ tdesc_add_enum_value (type_with_fields, 1, "MaxNormal");
+
+ type_with_fields = tdesc_create_flags (feature, "fpmr_flags", 8);
+ tdesc_type *field_type;
+ field_type = tdesc_named_type (feature, "fp8_fmt");
+ tdesc_add_typed_bitfield (type_with_fields, "F8S1", 0, 2, field_type);
+ field_type = tdesc_named_type (feature, "fp8_fmt");
+ tdesc_add_typed_bitfield (type_with_fields, "F8S2", 3, 5, field_type);
+ field_type = tdesc_named_type (feature, "fp8_fmt");
+ tdesc_add_typed_bitfield (type_with_fields, "F8D", 6, 8, field_type);
+ field_type = tdesc_named_type (feature, "osm");
+ tdesc_add_typed_bitfield (type_with_fields, "OSM", 14, 14, field_type);
+ field_type = tdesc_named_type (feature, "osc");
+ tdesc_add_typed_bitfield (type_with_fields, "OSC", 15, 15, field_type);
+ tdesc_add_bitfield (type_with_fields, "LSCALE", 16, 22);
+ field_type = tdesc_named_type (feature, "int8");
+ tdesc_add_typed_bitfield (type_with_fields, "NSCALE", 24, 31, field_type);
+ tdesc_add_bitfield (type_with_fields, "LSCALE2", 32, 37);
+
+ tdesc_create_reg (feature, "fpmr", regnum++, 1, NULL, 64, "fpmr_flags");
+ return regnum;
+}
diff --git a/gdb/features/aarch64-fpmr.xml b/gdb/features/aarch64-fpmr.xml
new file mode 100644
index 00000000000..3e888432786
--- /dev/null
+++ b/gdb/features/aarch64-fpmr.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2025 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.aarch64.fpmr">
+
+ <!-- FP8 format for F8S1, F8S2 and F8D fields. This is either E5M2 or
+ E4M3. -->
+ <enum id="fp8_fmt" size="3">
+ <evalue name="E5M2" value="0"/>
+ <evalue name="E4M3" value="1"/>
+ </enum>
+
+ <!-- Overflow saturation for FP8 convert instructions. Specifies the result
+ when a floating-point overflow exception is detected. -->
+ <enum id="osc" size="1">
+ <!-- Infinity or NaN is generated. -->
+ <evalue name="Inf/NaN" value="0"/>
+ <!-- Maximum normal number is generated. -->
+ <evalue name="MaxNormal" value="1"/>
+ </enum>
+
+ <!-- Overflow saturation for FP8 multiplication instructions. Specifies the
+ result when a floating-point overflow exception is detected. -->
+ <enum id="osm" size="1">
+ <!-- Infinity generated. -->
+ <evalue name="Inf" value="0"/>
+ <!-- Maximum normal number is generated. -->
+ <evalue name="MaxNormal" value="1"/>
+ </enum>
+
+ <flags id="fpmr_flags" size="8">
+ <!-- SRC1 Format. -->
+ <field name="F8S1" start="0" end="2" type="fp8_fmt"/>
+ <!-- SRC2 Format. -->
+ <field name="F8S2" start="3" end="5" type="fp8_fmt"/>
+ <!-- F8D Format. -->
+ <field name="F8D" start="6" end="8" type="fp8_fmt"/>
+ <!-- OSM. -->
+ <field name="OSM" start="14" end="14" type="osm"/>
+ <!-- OSC. -->
+ <field name="OSC" start="15" end="15" type="osc"/>
+ <!-- LSCALE. -->
+ <field name="LSCALE" start="16" end="22"/>
+ <!-- NSCALE. -->
+ <field name="NSCALE" start="24" end="31" type="int8"/>
+ <!-- LSCALE2. -->
+ <field name="LSCALE2" start="32" end="37"/>
+ </flags>
+
+ <reg name="fpmr" bitsize="64" type="fpmr_flags"/>
+
+</feature>
--
2.45.2
^ permalink raw reply [flat|nested] 13+ messages in thread* [PATCH v4 2/6] gdbserver/aarch64: Enable FPMR for AArch64 in gdbserver on Linux
2025-10-31 15:16 [PATCH v4 0/6] gdb/aarch64: Support for FPMR Ezra.Sitorus
2025-10-31 15:16 ` [PATCH v4 1/6] gdb/aarch64: Enable FPMR for AArch64 in gdb on Linux Ezra.Sitorus
@ 2025-10-31 15:16 ` Ezra.Sitorus
2025-10-31 15:16 ` [PATCH v4 3/6] gdb/aarch64: signal frame support for fpmr Ezra.Sitorus
` (3 subsequent siblings)
5 siblings, 0 replies; 13+ messages in thread
From: Ezra.Sitorus @ 2025-10-31 15:16 UTC (permalink / raw)
To: gdb-patches; +Cc: luis.machado.foss, Ezra Sitorus
From: Ezra Sitorus <ezra.sitorus@arm.com>
Add support for FPMR in gdbserver.
---
Changes from v1->v2:
* Addressed comments/whitespace/formatting issues.
* gdb/arch/aarch64.h: operator() takes fpmr into account now.
* Defined HWCAP2_FPMR in gdb/arch/aarch64.h
Changes from v2->v3:
* Formatting fixes.
* Moved initialisation of fpmr variables closer to where they are used.
Ezra
gdbserver/linux-aarch64-low.cc | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/gdbserver/linux-aarch64-low.cc b/gdbserver/linux-aarch64-low.cc
index 9d3ac803e7b..d63f3e2ad2c 100644
--- a/gdbserver/linux-aarch64-low.cc
+++ b/gdbserver/linux-aarch64-low.cc
@@ -248,6 +248,26 @@ aarch64_store_fpregset (struct regcache *regcache, const void *buf)
supply_register (regcache, AARCH64_FPCR_REGNUM, ®set->fpcr);
}
+/* Fill BUF with the FPMR register set from the regcache. */
+
+static void
+aarch64_fill_fpmr_regset (struct regcache *regcache, void *buf)
+{
+ uint64_t *fpmr = (uint64_t *) buf;
+ int fpmr_regnum = find_regno (regcache->tdesc, "fpmr");
+ collect_register (regcache, fpmr_regnum, fpmr);
+}
+
+/* Store the FPMR register set to regcache. */
+
+static void
+aarch64_store_fpmr_regset (struct regcache *regcache, const void *buf)
+{
+ uint64_t *fpmr = (uint64_t *) buf;
+ int fpmr_regnum = find_regno (regcache->tdesc, "fpmr");
+ supply_register (regcache, fpmr_regnum, fpmr);
+}
+
/* Store the pauth registers to regcache. */
static void
@@ -879,6 +899,10 @@ static struct regset_info aarch64_regsets[] =
{ PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_TAGGED_ADDR_CTRL,
0, OPTIONAL_REGS,
aarch64_fill_mteregset, aarch64_store_mteregset },
+ /* Floating Point Mode Register (FPMR). */
+ { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_FPMR,
+ 0, OPTIONAL_REGS,
+ aarch64_fill_fpmr_regset, aarch64_store_fpmr_regset },
/* TLS register. */
{ PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_TLS,
0, OPTIONAL_REGS,
@@ -954,6 +978,10 @@ aarch64_adjust_register_sets (const struct aarch64_features &features)
if (features.gcs_linux)
regset->size = sizeof (user_gcs);
break;
+ case NT_ARM_FPMR:
+ if (features.fpmr)
+ regset->size = sizeof (uint64_t);
+ break;
default:
gdb_assert_not_reached ("Unknown register set found.");
}
@@ -986,6 +1014,7 @@ aarch64_target::low_arch_setup ()
features.mte = linux_get_hwcap2 (pid, 8) & HWCAP2_MTE;
features.tls = aarch64_tls_register_count (tid);
features.gcs = features.gcs_linux = linux_get_hwcap (pid, 8) & HWCAP_GCS;
+ features.fpmr = linux_get_hwcap2 (pid, 8) & HWCAP2_FPMR;
/* Scalable Matrix Extension feature and size check. */
if (linux_get_hwcap2 (pid, 8) & HWCAP2_SME)
--
2.45.2
^ permalink raw reply [flat|nested] 13+ messages in thread* [PATCH v4 3/6] gdb/aarch64: signal frame support for fpmr
2025-10-31 15:16 [PATCH v4 0/6] gdb/aarch64: Support for FPMR Ezra.Sitorus
2025-10-31 15:16 ` [PATCH v4 1/6] gdb/aarch64: Enable FPMR for AArch64 in gdb on Linux Ezra.Sitorus
2025-10-31 15:16 ` [PATCH v4 2/6] gdbserver/aarch64: Enable FPMR for AArch64 in gdbserver " Ezra.Sitorus
@ 2025-10-31 15:16 ` Ezra.Sitorus
2025-10-31 15:16 ` [PATCH v4 4/6] gdb/aarch64: core file support for FPMR Ezra.Sitorus
` (2 subsequent siblings)
5 siblings, 0 replies; 13+ messages in thread
From: Ezra.Sitorus @ 2025-10-31 15:16 UTC (permalink / raw)
To: gdb-patches; +Cc: luis.machado.foss, Ezra Sitorus
From: Ezra Sitorus <ezra.sitorus@arm.com>
Add support for FPMR in signal frames and restore contents of FPMR.
---
Changes from v1->v2:
* Addressed comments/whitespace/formatting issues.
* gdb/arch/aarch64.h: operator() takes fpmr into account now.
* Defined HWCAP2_FPMR in gdb/arch/aarch64.h
Changes from v2->v3:
* Formatting fixes.
* Moved initialisation of fpmr variables closer to where they are used.
Ezra
gdb/aarch64-linux-tdep.c | 34 ++++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
index 10b44d978af..5346ae39eda 100644
--- a/gdb/aarch64-linux-tdep.c
+++ b/gdb/aarch64-linux-tdep.c
@@ -167,6 +167,7 @@
#define AARCH64_TPIDR2_MAGIC 0x54504902
#define AARCH64_ZT_MAGIC 0x5a544e01
#define AARCH64_GCS_MAGIC 0x47435300
+#define AARCH64_FPMR_MAGIC 0x46504d52
/* Defines for the extra_context that follows an AARCH64_EXTRA_MAGIC. */
#define AARCH64_EXTRA_DATAP_OFFSET 8
@@ -213,6 +214,9 @@
/* features_enabled value offset in the GCS signal frame context. */
#define AARCH64_GCS_CONTEXT_FEATURES_ENABLED_OFFSET 16
+/* FPMR constants. */
+#define AARCH64_FPMR_OFFSET 8
+
/* Holds information about the signal frame. */
struct aarch64_linux_sigframe
{
@@ -260,6 +264,12 @@ struct aarch64_linux_sigframe
uint64_t gcspr;
/* Flags indicating which GCS features are enabled for the thread. */
uint64_t gcs_features_enabled;
+
+ /* True if we have an FPMR entry in the signal context, false otherwise. */
+ bool fpmr_available = false;
+ /* FPMR value. */
+ CORE_ADDR fpmr = 0;
+
};
/* Read an aarch64_ctx, returning the magic value, and setting *SIZE to the
@@ -576,6 +586,22 @@ aarch64_linux_read_signal_frame_info (const frame_info_ptr &this_frame,
section += size;
break;
}
+ case AARCH64_FPMR_MAGIC:
+ {
+ gdb_byte buf[8];
+ if (target_read_memory (section + AARCH64_FPMR_OFFSET,
+ buf, 8) != 0)
+ {
+ warning (_("Failed to read the FPMR section address from the"
+ " signal frame context."));
+ section += size;
+ break;
+ }
+ signal_frame.fpmr = extract_unsigned_integer (buf, 8, byte_order);
+ signal_frame.fpmr_available = true;
+ section += size;
+ break;
+ }
case AARCH64_EXTRA_MAGIC:
{
/* Extra is always the last valid section in reserved and points to
@@ -739,6 +765,13 @@ aarch64_linux_sigframe_init (const struct tramp_frame *self,
}
}
+ /* Handle FPMR. */
+ if (tdep->has_fpmr () && signal_frame.fpmr_available != 0)
+ {
+ trad_frame_set_reg_value (this_cache, tdep->fpmr_regnum,
+ signal_frame.fpmr);
+ }
+
/* Restore the tpidr2 register, if the target supports it and if there is
an entry for it. */
if (signal_frame.tpidr2_section != 0 && tdep->has_tls ()
@@ -791,6 +824,7 @@ aarch64_linux_sigframe_prev_arch (const frame_info_ptr &this_frame,
aarch64_features features = aarch64_features_from_target_desc (tdesc);
features.vq = sve_vq_from_vl (signal_frame.vl);
features.svq = (uint8_t) sve_vq_from_vl (signal_frame.svl);
+ features.fpmr = signal_frame.fpmr_available;
struct gdbarch_info info;
info.bfd_arch_info = bfd_lookup_arch (bfd_arch_aarch64, bfd_mach_aarch64);
--
2.45.2
^ permalink raw reply [flat|nested] 13+ messages in thread* [PATCH v4 4/6] gdb/aarch64: core file support for FPMR
2025-10-31 15:16 [PATCH v4 0/6] gdb/aarch64: Support for FPMR Ezra.Sitorus
` (2 preceding siblings ...)
2025-10-31 15:16 ` [PATCH v4 3/6] gdb/aarch64: signal frame support for fpmr Ezra.Sitorus
@ 2025-10-31 15:16 ` Ezra.Sitorus
2025-10-31 15:16 ` [PATCH v4 5/6] gdb/aarch64: Tests for fpmr Ezra.Sitorus
2025-10-31 15:16 ` [PATCH v4 6/6] gdb/doc: Document AArch64 FPMR support Ezra.Sitorus
5 siblings, 0 replies; 13+ messages in thread
From: Ezra.Sitorus @ 2025-10-31 15:16 UTC (permalink / raw)
To: gdb-patches; +Cc: luis.machado.foss, Ezra Sitorus
From: Ezra Sitorus <ezra.sitorus@arm.com>
Add support for FPMR dumps/reads for core files.
---
Changes from v1->v2:
* Addressed comments/whitespace/formatting issues.
Changes from v2->v3:
* Removed supply/collect functions for FPMR register set
* Used generic supply/collect functions like MTE register set.
Ezra
gdb/aarch64-linux-tdep.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
index 5346ae39eda..6966dc1ab0f 100644
--- a/gdb/aarch64-linux-tdep.c
+++ b/gdb/aarch64-linux-tdep.c
@@ -1635,6 +1635,23 @@ aarch64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
}
}
+ if (tdep->has_fpmr ())
+ {
+ const struct regcache_map_entry fpmr_regmap[] =
+ {
+ { 1, tdep->fpmr_regnum, sizeof (uint64_t) },
+ { 0 }
+ };
+
+ const struct regset aarch64_linux_fpmr_regset =
+ {
+ fpmr_regmap, regcache_supply_regset, regcache_collect_regset
+ };
+
+ cb (".reg-aarch-fpmr", sizeof (uint64_t), sizeof (uint64_t),
+ &aarch64_linux_fpmr_regset, "FPMR", cb_data);
+ }
+
if (tdep->has_pauth ())
{
/* Create this on the fly in order to handle the variable location. */
--
2.45.2
^ permalink raw reply [flat|nested] 13+ messages in thread* [PATCH v4 5/6] gdb/aarch64: Tests for fpmr
2025-10-31 15:16 [PATCH v4 0/6] gdb/aarch64: Support for FPMR Ezra.Sitorus
` (3 preceding siblings ...)
2025-10-31 15:16 ` [PATCH v4 4/6] gdb/aarch64: core file support for FPMR Ezra.Sitorus
@ 2025-10-31 15:16 ` Ezra.Sitorus
2025-11-09 20:11 ` Luis
2025-10-31 15:16 ` [PATCH v4 6/6] gdb/doc: Document AArch64 FPMR support Ezra.Sitorus
5 siblings, 1 reply; 13+ messages in thread
From: Ezra.Sitorus @ 2025-10-31 15:16 UTC (permalink / raw)
To: gdb-patches; +Cc: luis.machado.foss, Ezra Sitorus
From: Ezra Sitorus <ezra.sitorus@arm.com>
Add tests for FPMR support in gdb/gdbserver. These tests check
availability of FPMR, reading/writing to FPMR, core file generation and
preservation under sighandler frame unwinding.
A run of the full gdb testsuite has been done on aarch64-none-linux-gnu
without FPMR support. The gdb.arch tests were run on Shrinkwrap with
FPMR support.
---
Changes from v1->v2:
* Removed fpmr modification functions to make the tests easier to
follow.
* Test writing to fpmr in aarch64-fpmr.exp from outside the inferior
program.
* Rewrite allow_aarch64_fpmr_tests to follow allow_aarch64_sve_tests.
Changes from v2->v3:
* tclint: only messages now is for line length for aarch64-fpmr.exp. I
think this is ok as it makes the test string readable.
* Addressed comments/whitespace/formatting issues.
* gdb.exp:allow_aarch64_fpmr_tests reads FPMR in both cases.
Changes from v3->v4:
* Formatting and comments
* I've tried to fix indentation issues. There's some differences in the
AArch64 tests, and they also don't quite matchup with tclformat which I
used in the previous patch. I've hopefully addressed them this time!
Ezra
gdb/testsuite/gdb.arch/aarch64-fpmr-core.c | 40 ++++++
gdb/testsuite/gdb.arch/aarch64-fpmr-core.exp | 97 ++++++++++++++
.../gdb.arch/aarch64-fpmr-sighandler.c | 55 ++++++++
.../gdb.arch/aarch64-fpmr-sighandler.exp | 74 +++++++++++
gdb/testsuite/gdb.arch/aarch64-fpmr.c | 118 ++++++++++++++++++
gdb/testsuite/gdb.arch/aarch64-fpmr.exp | 99 +++++++++++++++
gdb/testsuite/lib/gdb.exp | 66 ++++++++++
7 files changed, 549 insertions(+)
create mode 100644 gdb/testsuite/gdb.arch/aarch64-fpmr-core.c
create mode 100644 gdb/testsuite/gdb.arch/aarch64-fpmr-core.exp
create mode 100644 gdb/testsuite/gdb.arch/aarch64-fpmr-sighandler.c
create mode 100644 gdb/testsuite/gdb.arch/aarch64-fpmr-sighandler.exp
create mode 100644 gdb/testsuite/gdb.arch/aarch64-fpmr.c
create mode 100644 gdb/testsuite/gdb.arch/aarch64-fpmr.exp
diff --git a/gdb/testsuite/gdb.arch/aarch64-fpmr-core.c b/gdb/testsuite/gdb.arch/aarch64-fpmr-core.c
new file mode 100644
index 00000000000..045f36b5351
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-fpmr-core.c
@@ -0,0 +1,40 @@
+/* This file is part of GDB, the GNU debugger.
+
+ Copyright 2008-2025 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <stdint.h>
+
+uint64_t crash_address = 0;
+
+void
+set_fpmr (uint64_t value)
+{
+ register uint64_t x0_val asm ("x0") = value;
+ /* msr fpmr, x0 */
+ __asm__ volatile (".inst 0xd51b4440" : : );
+}
+
+int
+main (void)
+{
+ set_fpmr (0x3fff7fc049);
+
+ /* Check FPMR. */
+
+ *((uint64_t *) crash_address) = 0xDEAD; /* crash point */
+
+ return 1;
+}
diff --git a/gdb/testsuite/gdb.arch/aarch64-fpmr-core.exp b/gdb/testsuite/gdb.arch/aarch64-fpmr-core.exp
new file mode 100644
index 00000000000..5ab2072c30f
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-fpmr-core.exp
@@ -0,0 +1,97 @@
+# Copyright (C) 2018-2025 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the gdb testsuite.
+
+# Test generating and reading a core file with FPMR.
+
+proc check_fpmr_core_file {core_filename} {
+ # Load the core file.
+ if {
+ [gdb_test "core $core_filename" \
+ [multi_line \
+ "Core was generated by .*" \
+ "Program terminated with signal SIGSEGV, Segmentation fault\\." \
+ "#0 ${::hex} in main \\(.*\\) at .*" \
+ ".* \\*\\(\\(uint64_t \\*\\) crash_address\\) = 0xDEAD.*"] \
+ "load core file"]
+ } {
+ untested "failed to generate core file"
+ return -1
+ }
+
+ # Check the value of FPMR in the core file.
+ gdb_test "print/x \$fpmr" " = 0x3fff7fc049" \
+ "fpmr contents from core file"
+}
+
+require is_aarch64_target
+require allow_aarch64_fpmr_tests
+
+standard_testfile
+if {[prepare_for_testing "failed to prepare" ${testfile} ${srcfile}]} {
+ return -1
+}
+
+set binfile [standard_output_file ${testfile}]
+
+if {![runto_main]} {
+ return -1
+}
+
+set crash_breakpoint "crash point"
+gdb_breakpoint [gdb_get_line_number $crash_breakpoint]
+gdb_continue_to_breakpoint $crash_breakpoint
+
+gdb_test "print/x \$fpmr" " = 0x3fff7fc049" "fpmr contents from core file"
+
+gdb_test "continue" \
+ [multi_line \
+ "Program received signal SIGSEGV, Segmentation fault\\." \
+ "${::hex} in main \\(\\).* at .*" \
+ ".* \\*\\(\\(uint64_t \\*\\) crash_address\\) = 0xDEAD.*"] \
+ "run to crash"
+
+# Generate the gcore core file.
+set gcore_filename [standard_output_file "${testfile}.gcore"]
+set gcore_generated [gdb_gcore_cmd "$gcore_filename" "generate gcore file"]
+
+# Generate a native core file.
+set core_filename [core_find ${binfile}]
+set core_generated [expr {$core_filename != ""}]
+
+# At this point we have a couple core files, the gcore one generated by GDB
+# and the native one generated by the Linux Kernel. Make sure GDB can read
+# both correctly.
+
+if {$gcore_generated} {
+ clean_restart
+ gdb_load ${binfile}
+ with_test_prefix "gcore corefile" {
+ check_fpmr_core_file $gcore_filename
+ }
+} else {
+ fail "gcore corefile not generated"
+}
+
+if {$core_generated} {
+ clean_restart
+ gdb_load ${binfile}
+ with_test_prefix "native corefile" {
+ check_fpmr_core_file $core_filename
+ }
+} else {
+ untested "native corefile not generated"
+}
diff --git a/gdb/testsuite/gdb.arch/aarch64-fpmr-sighandler.c b/gdb/testsuite/gdb.arch/aarch64-fpmr-sighandler.c
new file mode 100644
index 00000000000..a561e7654a3
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-fpmr-sighandler.c
@@ -0,0 +1,55 @@
+/* This file is part of GDB, the GNU debugger.
+
+ Copyright 2008-2025 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <stdint.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+void
+set_fpmr (uint64_t value)
+{
+ register uint64_t x0_val asm ("x0") = value;
+ /* msr fpmr, x0 */
+ __asm__ volatile (".inst 0xd51b4440" : : );
+}
+
+void
+handler (int sig)
+{
+ set_fpmr (0xff008041);
+ exit (0);
+}
+
+int
+main ()
+{
+ /* Ensure no signals are blocked. */
+ sigset_t newset;
+ sigemptyset (&newset);
+ sigprocmask (SIG_SETMASK, &newset, NULL);
+
+ signal (SIGILL, handler);
+
+ set_fpmr (0x3fff7fc049);
+
+ /* 0x06000000 : Causes an illegal instruction. Value undefined as per ARM
+ Architecture Reference Manual ARMv8, Section C4.1. */
+ __asm __volatile (".inst 0x06000000");
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.arch/aarch64-fpmr-sighandler.exp b/gdb/testsuite/gdb.arch/aarch64-fpmr-sighandler.exp
new file mode 100644
index 00000000000..ca8f29ec9e4
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-fpmr-sighandler.exp
@@ -0,0 +1,74 @@
+# Copyright 2018-2025 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# This file is part of the gdb testsuite.
+#
+# Test FPMR register set is properly preserved when unwinding sighandler frames.
+
+require is_aarch64_target
+require allow_aarch64_fpmr_tests
+
+standard_testfile
+if {[prepare_for_testing "failed to prepare" ${testfile} ${srcfile}]} {
+ return -1
+}
+
+if {![runto_main]} {
+ return -1
+}
+
+set reg_main_value "0x3fff7fc049"
+set reg_handler_value "0xff008041"
+
+proc check_fpmr {value} {
+ gdb_test "print /x \$fpmr" ".* = {?$value}?" \
+ "check register \$fpmr has value $value"
+}
+
+# Run until end of signal handler.
+
+gdb_test "continue" "Continuing.*Program received signal SIGILL.*" \
+ "continue until signal"
+
+gdb_breakpoint [gdb_get_line_number "exit (0)"]
+gdb_continue_to_breakpoint "exit" ".*exit.*"
+
+set handlerframe [get_current_frame_number]
+set mainframe [expr {$handlerframe + 2}]
+
+# Check register values.
+
+with_test_prefix "handler frame 1st" {
+ check_fpmr $reg_handler_value
+}
+
+# Switch to the frame for main (), and check register values.
+
+gdb_test "frame $mainframe" "#$mainframe.*main ().*" \
+ "set to main frame"
+
+with_test_prefix "main frame" {
+ check_fpmr $reg_main_value
+}
+
+# Switch back to the signal handler frame, and check register values.
+
+gdb_test "frame $handlerframe" \
+ "#$handlerframe.*handler \\\(sig=4\\\).*" \
+ "set to signal handler frame"
+
+with_test_prefix "handler frame 2nd" {
+ check_fpmr $reg_handler_value
+}
diff --git a/gdb/testsuite/gdb.arch/aarch64-fpmr.c b/gdb/testsuite/gdb.arch/aarch64-fpmr.c
new file mode 100644
index 00000000000..89298d1c6a8
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-fpmr.c
@@ -0,0 +1,118 @@
+/* This file is part of GDB, the GNU debugger.
+
+ Copyright 2008-2025 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <stdint.h>
+
+enum FPM_FORMAT
+{
+ E5M2,
+ E4M3,
+};
+
+enum FPM_OVERFLOW
+{
+ INFNAN,
+ SATURATE,
+};
+
+void
+set_fpmr (uint64_t value)
+{
+ register uint64_t x0_val asm ("x0") = value;
+ __asm__ volatile (".inst 0xd51b4440" : : );
+ /* msr fpmr, x0 */
+}
+
+uint64_t
+modify_src1_fmt (uint64_t fpmr, uint64_t fmt)
+{
+ return (fpmr & ~(0x7)) | (fmt & 0x7);
+}
+
+uint64_t
+modify_src2_fmt (uint64_t fpmr, uint64_t fmt)
+{
+ return (fpmr & ~((0x7) << 3)) | ((fmt & 0x7) << 3);
+}
+
+uint64_t
+modify_dst_fmt (uint64_t fpmr, uint64_t fmt)
+{
+ return (fpmr & ~((0x7) << 6)) | ((fmt & 0x7) << 6);
+}
+
+uint64_t
+modify_osm (uint64_t fpmr, uint64_t overflow)
+{
+ return (fpmr & ~((0x1) << 14)) | ((overflow & 0x1) << 14);
+}
+
+uint64_t
+modify_osc (uint64_t fpmr, uint64_t overflow)
+{
+ return (fpmr & ~((0x1) << 15)) | ((overflow & 0x1) << 15);
+}
+
+uint64_t
+modify_lscale (uint64_t fpmr, uint64_t scale)
+{
+ return (fpmr & ~((0x7f) << 16)) | ((scale & 0x7f) << 16);
+}
+
+uint64_t
+modify_nscale (uint64_t fpmr, uint64_t scale)
+{
+ return (fpmr & ~((0xff) << 24)) | ((scale & 0xff) << 24);
+}
+
+uint64_t
+modify_lscale2 (uint64_t fpmr, uint64_t scale)
+{
+ return (fpmr & ~((uint64_t)(0x3f) << 32)) | ((uint64_t)(scale & 0x3f) << 32);
+}
+
+int
+main (void)
+{
+ uint64_t fpmr = 0;
+
+ fpmr = modify_src1_fmt (fpmr, E4M3);
+ set_fpmr (fpmr); /* SRC1 */
+
+ fpmr = modify_src2_fmt (fpmr, E4M3);
+ set_fpmr (fpmr); /* SRC2 */
+
+ fpmr = modify_dst_fmt (fpmr, E4M3);
+ set_fpmr (fpmr); /* DST */
+
+ fpmr = modify_osm (fpmr, SATURATE);
+ set_fpmr (fpmr); /* OSM */
+
+ fpmr = modify_osc (fpmr, SATURATE);
+ set_fpmr (fpmr); /* OSC */
+
+ fpmr = modify_lscale (fpmr, -1);
+ set_fpmr (fpmr); /* LSCALE */
+
+ fpmr = modify_nscale (fpmr, -1);
+ set_fpmr (fpmr); /* NSCALE */
+
+ fpmr = modify_lscale2 (fpmr, -1);
+ set_fpmr (fpmr); /* LSCALE2 */
+
+ return 1;
+}
diff --git a/gdb/testsuite/gdb.arch/aarch64-fpmr.exp b/gdb/testsuite/gdb.arch/aarch64-fpmr.exp
new file mode 100644
index 00000000000..142d8172332
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-fpmr.exp
@@ -0,0 +1,99 @@
+# Copyright 2023-2025 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+# Exercise reading/writing FPMR when it is present.
+
+require is_aarch64_target
+require allow_aarch64_fpmr_tests
+
+standard_testfile
+if {[prepare_for_testing "failed to prepare" ${testfile} ${srcfile}]} {
+ return -1
+}
+
+if {![runto_main]} {
+ return -1
+}
+
+gdb_test_multiple "info register \$fpmr" "Test FPMR SRC1 E5M2" {
+ -re ".*\r\n.*\[ \
+ F8S1=E5M2 \
+ F8S2=E5M2 \
+ F8D=E5M2 \
+ OSM=Inf \
+ OSC=Inf/NaN \
+ LSCALE=0 \
+ NSCALE=0 \
+ LSCALE2=0 \]" {
+ pass "FPMR SRC1 matches E5M2"
+ }
+}
+
+set breakpoints \
+ [list \
+ "SRC1" \
+ "SRC2" \
+ "DST" \
+ "OSM" \
+ "OSC" \
+ "LSCALE" \
+ "NSCALE" \
+ "LSCALE2"]
+
+set reg_values \
+ [list \
+ ".*\r\n.*\[ F8S1=E4M3 F8S2=E5M2 F8D=E5M2 OSM=Inf OSC=Inf/NaN LSCALE=0 NSCALE=0 LSCALE2=0 \]" \
+ ".*\r\n.*\[ F8S1=E4M3 F8S2=E4M3 F8D=E5M2 OSM=Inf OSC=Inf/NaN LSCALE=0 NSCALE=0 LSCALE2=0 \]" \
+ ".*\r\n.*\[ F8S1=E4M3 F8S2=E4M3 F8D=E4M3 OSM=Inf OSC=Inf/NaN LSCALE=0 NSCALE=0 LSCALE2=0 \]" \
+ ".*\r\n.*\[ F8S1=E4M3 F8S2=E4M3 F8D=E4M3 OSM=MaxNormal OSC=Inf/NaN LSCALE=0 NSCALE=0 LSCALE2=0 \]" \
+ ".*\r\n.*\[ F8S1=E4M3 F8S2=E4M3 F8D=E4M3 OSM=MaxNormal OSC=MaxNormal LSCALE=0 NSCALE=0 LSCALE2=0 \]" \
+ ".*\r\n.*\[ F8S1=E4M3 F8S2=E4M3 F8D=E4M3 OSM=MaxNormal OSC=MaxNormal LSCALE=127 NSCALE=0 LSCALE2=0 \]" \
+ ".*\r\n.*\[ F8S1=E4M3 F8S2=E4M3 F8D=E4M3 OSM=MaxNormal OSC=MaxNormal LSCALE=127 NSCALE=255 LSCALE2=0 \]" \
+ ".*\r\n.*\[ F8S1=E4M3 F8S2=E4M3 F8D=E4M3 OSM=MaxNormal OSC=MaxNormal LSCALE=127 NSCALE=255 LSCALE2=63 \]"]
+
+set pass_messages \
+ [list \
+ "FPMR SRC1 matches E4M3" \
+ "FPMR SRC2 matches E4M3" \
+ "FPMR DST matches E4M3" \
+ "FPMR OSM matches MaxNormal" \
+ "FPMR OSC matches MaxNormal" \
+ "FPMR LSCALE matches" \
+ "FPMR NSCALE matches" \
+ "FPMR LSCALE2 matches"]
+
+for {set i 0} {$i < 8} {incr i} {
+ set bp [lindex $breakpoints $i]
+ gdb_breakpoint [gdb_get_line_number $bp]
+ gdb_continue_to_breakpoint $bp
+
+ gdb_test_multiple "info register \$fpmr" "" {
+ -re [lindex $reg_values $i] {
+ pass [lindex $pass_messages $i]
+ }
+ }
+}
+
+gdb_test_multiple "set \$fpmr=0x0" "" {
+ -re ".*\r\n.*\[ F8S1=E5M2 F8S2=E5M2 F8D=E5M2 OSM=Inf OSC=Inf/NaN LSCALE=0 NSCALE=0 LSCALE2=0 \]" {
+ pass "Reset FPMR to 0 from GDB"
+ }
+}
+
+gdb_test_multiple "set \$fpmr=0x3f007f4008" "" {
+ -re ".*\r\n.*\[ F8S1=E5M2 F8S2=E4M3 F8D=E5M2 OSM=MaxNormal OSC=Inf/NaN LSCALE=127 NSCALE=0 LSCALE2=63 \]" {
+ pass "Write to FPMR from GDB"
+ }
+}
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index 930462f63fa..cdb6ccdfa35 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -5201,6 +5201,72 @@ proc aarch64_supports_sme_svl { length } {
return 1
}
+# Run a test on the target to see if it supports the AArch64 FPMR feature.
+# Return 1 if so, 0 if it does not. Note this causes a restart of GDB.
+
+gdb_caching_proc allow_aarch64_fpmr_tests {} {
+ global srcdir subdir gdb_prompt inferior_exited_re
+
+ set me "allow_aarch64_fpmr_tests"
+
+ if { ![is_aarch64_target]} {
+ return 0
+ }
+
+ set compile_flags "{additional_flags=-march=armv8-a}"
+
+ # Compile a test program reading FPMR.
+ set src {
+ int main() {
+ asm volatile ("mrs x0, fpmr");
+ return 0;
+ }
+ }
+ if {![gdb_simple_compile $me $src executable $compile_flags]} {
+ # Try again, but with a raw hex instruction so we don't rely on
+ # assembler support for FPMR.
+
+ set compile_flags "{additional_flags=-march=armv8-a}"
+
+ # Compile a test program reading FPMR.
+ set src {
+ int main() {
+ asm volatile (".word 0xD53B4440");
+ return 0;
+ }
+ }
+
+ if {![gdb_simple_compile $me $src executable $compile_flags]} {
+ return 0
+ }
+ }
+
+ # Compilation succeeded so now run it via gdb.
+ clean_restart
+ gdb_load $obj
+ gdb_run_cmd
+
+ gdb_expect {
+ -re ".*Illegal instruction.*${gdb_prompt} $" {
+ verbose -log "\n$me fpmr support not detected"
+ set allow_fpmr_tests 0
+ }
+ -re ".*$inferior_exited_re normally.*${gdb_prompt} $" {
+ verbose -log "\n$me: fpmr support detected"
+ set allow_fpmr_tests 1
+ }
+ default {
+ warning "\n$me: default case taken"
+ set allow_fpmr_tests 0
+ }
+ }
+ gdb_exit
+ remote_file build delete $obj
+
+ verbose "$me: returning $allow_fpmr_tests" 2
+ return $allow_fpmr_tests
+}
+
# Run a test on the target to see if it supports AArch64 MOPS (Memory
# Operations) extensions. Return 1 if so, 0 if it does not. Note this
# causes a restart of GDB.
--
2.45.2
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH v4 5/6] gdb/aarch64: Tests for fpmr
2025-10-31 15:16 ` [PATCH v4 5/6] gdb/aarch64: Tests for fpmr Ezra.Sitorus
@ 2025-11-09 20:11 ` Luis
0 siblings, 0 replies; 13+ messages in thread
From: Luis @ 2025-11-09 20:11 UTC (permalink / raw)
To: Ezra.Sitorus, gdb-patches
Hi Ezra,
On 31/10/2025 15:16, Ezra.Sitorus@arm.com wrote:
> From: Ezra Sitorus <ezra.sitorus@arm.com>
>
> Add tests for FPMR support in gdb/gdbserver. These tests check
> availability of FPMR, reading/writing to FPMR, core file generation and
> preservation under sighandler frame unwinding.
>
> A run of the full gdb testsuite has been done on aarch64-none-linux-gnu
> without FPMR support. The gdb.arch tests were run on Shrinkwrap with
> FPMR support.
> ---
> Changes from v1->v2:
> * Removed fpmr modification functions to make the tests easier to
> follow.
> * Test writing to fpmr in aarch64-fpmr.exp from outside the inferior
> program.
> * Rewrite allow_aarch64_fpmr_tests to follow allow_aarch64_sve_tests.
>
> Changes from v2->v3:
> * tclint: only messages now is for line length for aarch64-fpmr.exp. I
> think this is ok as it makes the test string readable.
> * Addressed comments/whitespace/formatting issues.
> * gdb.exp:allow_aarch64_fpmr_tests reads FPMR in both cases.
>
> Changes from v3->v4:
> * Formatting and comments
> * I've tried to fix indentation issues. There's some differences in the
> AArch64 tests, and they also don't quite matchup with tclformat which I
> used in the previous patch. I've hopefully addressed them this time!
>
> Ezra
>
> gdb/testsuite/gdb.arch/aarch64-fpmr-core.c | 40 ++++++
> gdb/testsuite/gdb.arch/aarch64-fpmr-core.exp | 97 ++++++++++++++
> .../gdb.arch/aarch64-fpmr-sighandler.c | 55 ++++++++
> .../gdb.arch/aarch64-fpmr-sighandler.exp | 74 +++++++++++
> gdb/testsuite/gdb.arch/aarch64-fpmr.c | 118 ++++++++++++++++++
> gdb/testsuite/gdb.arch/aarch64-fpmr.exp | 99 +++++++++++++++
> gdb/testsuite/lib/gdb.exp | 66 ++++++++++
> 7 files changed, 549 insertions(+)
> create mode 100644 gdb/testsuite/gdb.arch/aarch64-fpmr-core.c
> create mode 100644 gdb/testsuite/gdb.arch/aarch64-fpmr-core.exp
> create mode 100644 gdb/testsuite/gdb.arch/aarch64-fpmr-sighandler.c
> create mode 100644 gdb/testsuite/gdb.arch/aarch64-fpmr-sighandler.exp
> create mode 100644 gdb/testsuite/gdb.arch/aarch64-fpmr.c
> create mode 100644 gdb/testsuite/gdb.arch/aarch64-fpmr.exp
>
> diff --git a/gdb/testsuite/gdb.arch/aarch64-fpmr-core.c b/gdb/testsuite/gdb.arch/aarch64-fpmr-core.c
> new file mode 100644
> index 00000000000..045f36b5351
> --- /dev/null
> +++ b/gdb/testsuite/gdb.arch/aarch64-fpmr-core.c
> @@ -0,0 +1,40 @@
> +/* This file is part of GDB, the GNU debugger.
> +
> + Copyright 2008-2025 Free Software Foundation, Inc.
> +
> + This program is free software; you can redistribute it and/or modify
> + it under the terms of the GNU General Public License as published by
> + the Free Software Foundation; either version 3 of the License, or
> + (at your option) any later version.
> +
> + This program is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + GNU General Public License for more details.
> +
> + You should have received a copy of the GNU General Public License
> + along with this program. If not, see <http://www.gnu.org/licenses/>. */
> +
> +#include <stdint.h>
> +
> +uint64_t crash_address = 0;
> +
> +void
> +set_fpmr (uint64_t value)
> +{
> + register uint64_t x0_val asm ("x0") = value;
> + /* msr fpmr, x0 */
> + __asm__ volatile (".inst 0xd51b4440" : : );
> +}
> +
> +int
> +main (void)
> +{
> + set_fpmr (0x3fff7fc049);
> +
> + /* Check FPMR. */
> +
> + *((uint64_t *) crash_address) = 0xDEAD; /* crash point */
> +
> + return 1;
> +}
> diff --git a/gdb/testsuite/gdb.arch/aarch64-fpmr-core.exp b/gdb/testsuite/gdb.arch/aarch64-fpmr-core.exp
> new file mode 100644
> index 00000000000..5ab2072c30f
> --- /dev/null
> +++ b/gdb/testsuite/gdb.arch/aarch64-fpmr-core.exp
> @@ -0,0 +1,97 @@
> +# Copyright (C) 2018-2025 Free Software Foundation, Inc.
> +#
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program. If not, see <http://www.gnu.org/licenses/>.
> +
> +# This file is part of the gdb testsuite.
> +
> +# Test generating and reading a core file with FPMR.
> +
> +proc check_fpmr_core_file {core_filename} {
> + # Load the core file.
> + if {
> + [gdb_test "core $core_filename" \
> + [multi_line \
> + "Core was generated by .*" \
> + "Program terminated with signal SIGSEGV, Segmentation fault\\." \
> + "#0 ${::hex} in main \\(.*\\) at .*" \
> + ".* \\*\\(\\(uint64_t \\*\\) crash_address\\) = 0xDEAD.*"] \
> + "load core file"]
> + } {
> + untested "failed to generate core file"
> + return -1
> + }
> +
> + # Check the value of FPMR in the core file.
> + gdb_test "print/x \$fpmr" " = 0x3fff7fc049" \
> + "fpmr contents from core file"
> +}
> +
> +require is_aarch64_target
> +require allow_aarch64_fpmr_tests
> +
> +standard_testfile
> +if {[prepare_for_testing "failed to prepare" ${testfile} ${srcfile}]} {
> + return -1
> +}
> +
> +set binfile [standard_output_file ${testfile}]
> +
> +if {![runto_main]} {
> + return -1
> +}
> +
> +set crash_breakpoint "crash point"
> +gdb_breakpoint [gdb_get_line_number $crash_breakpoint]
> +gdb_continue_to_breakpoint $crash_breakpoint
> +
> +gdb_test "print/x \$fpmr" " = 0x3fff7fc049" "fpmr contents from core file"
> +
> +gdb_test "continue" \
> + [multi_line \
> + "Program received signal SIGSEGV, Segmentation fault\\." \
> + "${::hex} in main \\(\\).* at .*" \
> + ".* \\*\\(\\(uint64_t \\*\\) crash_address\\) = 0xDEAD.*"] \
> + "run to crash"
> +
> +# Generate the gcore core file.
> +set gcore_filename [standard_output_file "${testfile}.gcore"]
> +set gcore_generated [gdb_gcore_cmd "$gcore_filename" "generate gcore file"]
> +
> +# Generate a native core file.
> +set core_filename [core_find ${binfile}]
> +set core_generated [expr {$core_filename != ""}]
> +
> +# At this point we have a couple core files, the gcore one generated by GDB
> +# and the native one generated by the Linux Kernel. Make sure GDB can read
> +# both correctly.
> +
> +if {$gcore_generated} {
> + clean_restart
> + gdb_load ${binfile}
> + with_test_prefix "gcore corefile" {
> + check_fpmr_core_file $gcore_filename
> + }
> +} else {
> + fail "gcore corefile not generated"
> +}
> +
> +if {$core_generated} {
> + clean_restart
> + gdb_load ${binfile}
> + with_test_prefix "native corefile" {
> + check_fpmr_core_file $core_filename
> + }
> +} else {
> + untested "native corefile not generated"
> +}
> diff --git a/gdb/testsuite/gdb.arch/aarch64-fpmr-sighandler.c b/gdb/testsuite/gdb.arch/aarch64-fpmr-sighandler.c
> new file mode 100644
> index 00000000000..a561e7654a3
> --- /dev/null
> +++ b/gdb/testsuite/gdb.arch/aarch64-fpmr-sighandler.c
> @@ -0,0 +1,55 @@
> +/* This file is part of GDB, the GNU debugger.
> +
> + Copyright 2008-2025 Free Software Foundation, Inc.
> +
> + This program is free software; you can redistribute it and/or modify
> + it under the terms of the GNU General Public License as published by
> + the Free Software Foundation; either version 3 of the License, or
> + (at your option) any later version.
> +
> + This program is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + GNU General Public License for more details.
> +
> + You should have received a copy of the GNU General Public License
> + along with this program. If not, see <http://www.gnu.org/licenses/>. */
> +
> +#include <stdint.h>
> +#include <signal.h>
> +#include <unistd.h>
> +#include <stdlib.h>
> +
> +void
> +set_fpmr (uint64_t value)
> +{
> + register uint64_t x0_val asm ("x0") = value;
> + /* msr fpmr, x0 */
> + __asm__ volatile (".inst 0xd51b4440" : : );
> +}
> +
> +void
> +handler (int sig)
> +{
> + set_fpmr (0xff008041);
> + exit (0);
> +}
> +
> +int
> +main ()
> +{
> + /* Ensure no signals are blocked. */
> + sigset_t newset;
> + sigemptyset (&newset);
> + sigprocmask (SIG_SETMASK, &newset, NULL);
> +
> + signal (SIGILL, handler);
> +
> + set_fpmr (0x3fff7fc049);
> +
> + /* 0x06000000 : Causes an illegal instruction. Value undefined as per ARM
> + Architecture Reference Manual ARMv8, Section C4.1. */
> + __asm __volatile (".inst 0x06000000");
> +
> + return 0;
> +}
> diff --git a/gdb/testsuite/gdb.arch/aarch64-fpmr-sighandler.exp b/gdb/testsuite/gdb.arch/aarch64-fpmr-sighandler.exp
> new file mode 100644
> index 00000000000..ca8f29ec9e4
> --- /dev/null
> +++ b/gdb/testsuite/gdb.arch/aarch64-fpmr-sighandler.exp
> @@ -0,0 +1,74 @@
> +# Copyright 2018-2025 Free Software Foundation, Inc.
> +#
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program. If not, see <http://www.gnu.org/licenses/>.
> +#
> +# This file is part of the gdb testsuite.
> +#
> +# Test FPMR register set is properly preserved when unwinding sighandler frames.
> +
> +require is_aarch64_target
> +require allow_aarch64_fpmr_tests
> +
> +standard_testfile
> +if {[prepare_for_testing "failed to prepare" ${testfile} ${srcfile}]} {
> + return -1
> +}
> +
> +if {![runto_main]} {
> + return -1
> +}
> +
> +set reg_main_value "0x3fff7fc049"
> +set reg_handler_value "0xff008041"
> +
> +proc check_fpmr {value} {
> + gdb_test "print /x \$fpmr" ".* = {?$value}?" \
> + "check register \$fpmr has value $value"
> +}
> +
> +# Run until end of signal handler.
> +
> +gdb_test "continue" "Continuing.*Program received signal SIGILL.*" \
> + "continue until signal"
> +
> +gdb_breakpoint [gdb_get_line_number "exit (0)"]
> +gdb_continue_to_breakpoint "exit" ".*exit.*"
> +
> +set handlerframe [get_current_frame_number]
> +set mainframe [expr {$handlerframe + 2}]
> +
> +# Check register values.
> +
> +with_test_prefix "handler frame 1st" {
> + check_fpmr $reg_handler_value
> +}
> +
> +# Switch to the frame for main (), and check register values.
> +
> +gdb_test "frame $mainframe" "#$mainframe.*main ().*" \
> + "set to main frame"
> +
> +with_test_prefix "main frame" {
> + check_fpmr $reg_main_value
> +}
> +
> +# Switch back to the signal handler frame, and check register values.
> +
> +gdb_test "frame $handlerframe" \
> + "#$handlerframe.*handler \\\(sig=4\\\).*" \
> + "set to signal handler frame"
> +
> +with_test_prefix "handler frame 2nd" {
> + check_fpmr $reg_handler_value
> +}
> diff --git a/gdb/testsuite/gdb.arch/aarch64-fpmr.c b/gdb/testsuite/gdb.arch/aarch64-fpmr.c
> new file mode 100644
> index 00000000000..89298d1c6a8
> --- /dev/null
> +++ b/gdb/testsuite/gdb.arch/aarch64-fpmr.c
> @@ -0,0 +1,118 @@
> +/* This file is part of GDB, the GNU debugger.
> +
> + Copyright 2008-2025 Free Software Foundation, Inc.
> +
> + This program is free software; you can redistribute it and/or modify
> + it under the terms of the GNU General Public License as published by
> + the Free Software Foundation; either version 3 of the License, or
> + (at your option) any later version.
> +
> + This program is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + GNU General Public License for more details.
> +
> + You should have received a copy of the GNU General Public License
> + along with this program. If not, see <http://www.gnu.org/licenses/>. */
> +
> +#include <stdint.h>
> +
> +enum FPM_FORMAT
> +{
> + E5M2,
> + E4M3,
> +};
> +
> +enum FPM_OVERFLOW
> +{
> + INFNAN,
> + SATURATE,
> +};
> +
> +void
> +set_fpmr (uint64_t value)
> +{
> + register uint64_t x0_val asm ("x0") = value;
> + __asm__ volatile (".inst 0xd51b4440" : : );
> + /* msr fpmr, x0 */
> +}
> +
> +uint64_t
> +modify_src1_fmt (uint64_t fpmr, uint64_t fmt)
> +{
> + return (fpmr & ~(0x7)) | (fmt & 0x7);
> +}
> +
> +uint64_t
> +modify_src2_fmt (uint64_t fpmr, uint64_t fmt)
> +{
> + return (fpmr & ~((0x7) << 3)) | ((fmt & 0x7) << 3);
> +}
> +
> +uint64_t
> +modify_dst_fmt (uint64_t fpmr, uint64_t fmt)
> +{
> + return (fpmr & ~((0x7) << 6)) | ((fmt & 0x7) << 6);
> +}
> +
> +uint64_t
> +modify_osm (uint64_t fpmr, uint64_t overflow)
> +{
> + return (fpmr & ~((0x1) << 14)) | ((overflow & 0x1) << 14);
> +}
> +
> +uint64_t
> +modify_osc (uint64_t fpmr, uint64_t overflow)
> +{
> + return (fpmr & ~((0x1) << 15)) | ((overflow & 0x1) << 15);
> +}
> +
> +uint64_t
> +modify_lscale (uint64_t fpmr, uint64_t scale)
> +{
> + return (fpmr & ~((0x7f) << 16)) | ((scale & 0x7f) << 16);
> +}
> +
> +uint64_t
> +modify_nscale (uint64_t fpmr, uint64_t scale)
> +{
> + return (fpmr & ~((0xff) << 24)) | ((scale & 0xff) << 24);
> +}
> +
> +uint64_t
> +modify_lscale2 (uint64_t fpmr, uint64_t scale)
> +{
> + return (fpmr & ~((uint64_t)(0x3f) << 32)) | ((uint64_t)(scale & 0x3f) << 32);
> +}
> +
> +int
> +main (void)
> +{
> + uint64_t fpmr = 0;
> +
> + fpmr = modify_src1_fmt (fpmr, E4M3);
> + set_fpmr (fpmr); /* SRC1 */
> +
> + fpmr = modify_src2_fmt (fpmr, E4M3);
> + set_fpmr (fpmr); /* SRC2 */
> +
> + fpmr = modify_dst_fmt (fpmr, E4M3);
> + set_fpmr (fpmr); /* DST */
> +
> + fpmr = modify_osm (fpmr, SATURATE);
> + set_fpmr (fpmr); /* OSM */
> +
> + fpmr = modify_osc (fpmr, SATURATE);
> + set_fpmr (fpmr); /* OSC */
> +
> + fpmr = modify_lscale (fpmr, -1);
> + set_fpmr (fpmr); /* LSCALE */
> +
> + fpmr = modify_nscale (fpmr, -1);
> + set_fpmr (fpmr); /* NSCALE */
> +
> + fpmr = modify_lscale2 (fpmr, -1);
> + set_fpmr (fpmr); /* LSCALE2 */
> +
> + return 1;
> +}
> diff --git a/gdb/testsuite/gdb.arch/aarch64-fpmr.exp b/gdb/testsuite/gdb.arch/aarch64-fpmr.exp
> new file mode 100644
> index 00000000000..142d8172332
> --- /dev/null
> +++ b/gdb/testsuite/gdb.arch/aarch64-fpmr.exp
> @@ -0,0 +1,99 @@
> +# Copyright 2023-2025 Free Software Foundation, Inc.
> +
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program. If not, see <http://www.gnu.org/licenses/>. */
> +
> +# Exercise reading/writing FPMR when it is present.
> +
> +require is_aarch64_target
> +require allow_aarch64_fpmr_tests
> +
> +standard_testfile
> +if {[prepare_for_testing "failed to prepare" ${testfile} ${srcfile}]} {
> + return -1
> +}
> +
> +if {![runto_main]} {
> + return -1
> +}
> +
> +gdb_test_multiple "info register \$fpmr" "Test FPMR SRC1 E5M2" {
> + -re ".*\r\n.*\[ \
> + F8S1=E5M2 \
> + F8S2=E5M2 \
> + F8D=E5M2 \
> + OSM=Inf \
> + OSC=Inf/NaN \
> + LSCALE=0 \
> + NSCALE=0 \
> + LSCALE2=0 \]" {
> + pass "FPMR SRC1 matches E5M2"
> + }
> +}
> +
> +set breakpoints \
> + [list \
> + "SRC1" \
> + "SRC2" \
> + "DST" \
> + "OSM" \
> + "OSC" \
> + "LSCALE" \
> + "NSCALE" \
> + "LSCALE2"]
> +
> +set reg_values \
> + [list \
> + ".*\r\n.*\[ F8S1=E4M3 F8S2=E5M2 F8D=E5M2 OSM=Inf OSC=Inf/NaN LSCALE=0 NSCALE=0 LSCALE2=0 \]" \
> + ".*\r\n.*\[ F8S1=E4M3 F8S2=E4M3 F8D=E5M2 OSM=Inf OSC=Inf/NaN LSCALE=0 NSCALE=0 LSCALE2=0 \]" \
> + ".*\r\n.*\[ F8S1=E4M3 F8S2=E4M3 F8D=E4M3 OSM=Inf OSC=Inf/NaN LSCALE=0 NSCALE=0 LSCALE2=0 \]" \
> + ".*\r\n.*\[ F8S1=E4M3 F8S2=E4M3 F8D=E4M3 OSM=MaxNormal OSC=Inf/NaN LSCALE=0 NSCALE=0 LSCALE2=0 \]" \
> + ".*\r\n.*\[ F8S1=E4M3 F8S2=E4M3 F8D=E4M3 OSM=MaxNormal OSC=MaxNormal LSCALE=0 NSCALE=0 LSCALE2=0 \]" \
> + ".*\r\n.*\[ F8S1=E4M3 F8S2=E4M3 F8D=E4M3 OSM=MaxNormal OSC=MaxNormal LSCALE=127 NSCALE=0 LSCALE2=0 \]" \
> + ".*\r\n.*\[ F8S1=E4M3 F8S2=E4M3 F8D=E4M3 OSM=MaxNormal OSC=MaxNormal LSCALE=127 NSCALE=255 LSCALE2=0 \]" \
> + ".*\r\n.*\[ F8S1=E4M3 F8S2=E4M3 F8D=E4M3 OSM=MaxNormal OSC=MaxNormal LSCALE=127 NSCALE=255 LSCALE2=63 \]"]
> +
> +set pass_messages \
> + [list \
> + "FPMR SRC1 matches E4M3" \
> + "FPMR SRC2 matches E4M3" \
> + "FPMR DST matches E4M3" \
> + "FPMR OSM matches MaxNormal" \
> + "FPMR OSC matches MaxNormal" \
> + "FPMR LSCALE matches" \
> + "FPMR NSCALE matches" \
> + "FPMR LSCALE2 matches"]
> +
> +for {set i 0} {$i < 8} {incr i} {
> + set bp [lindex $breakpoints $i]
> + gdb_breakpoint [gdb_get_line_number $bp]
> + gdb_continue_to_breakpoint $bp
> +
> + gdb_test_multiple "info register \$fpmr" "" {
> + -re [lindex $reg_values $i] {
> + pass [lindex $pass_messages $i]
> + }
> + }
> +}
> +
> +gdb_test_multiple "set \$fpmr=0x0" "" {
> + -re ".*\r\n.*\[ F8S1=E5M2 F8S2=E5M2 F8D=E5M2 OSM=Inf OSC=Inf/NaN LSCALE=0 NSCALE=0 LSCALE2=0 \]" {
> + pass "Reset FPMR to 0 from GDB"
> + }
> +}
> +
> +gdb_test_multiple "set \$fpmr=0x3f007f4008" "" {
> + -re ".*\r\n.*\[ F8S1=E5M2 F8S2=E4M3 F8D=E5M2 OSM=MaxNormal OSC=Inf/NaN LSCALE=127 NSCALE=0 LSCALE2=63 \]" {
> + pass "Write to FPMR from GDB"
> + }
> +}
> diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
> index 930462f63fa..cdb6ccdfa35 100644
> --- a/gdb/testsuite/lib/gdb.exp
> +++ b/gdb/testsuite/lib/gdb.exp
> @@ -5201,6 +5201,72 @@ proc aarch64_supports_sme_svl { length } {
> return 1
> }
>
> +# Run a test on the target to see if it supports the AArch64 FPMR feature.
> +# Return 1 if so, 0 if it does not. Note this causes a restart of GDB.
> +
> +gdb_caching_proc allow_aarch64_fpmr_tests {} {
> + global srcdir subdir gdb_prompt inferior_exited_re
> +
> + set me "allow_aarch64_fpmr_tests"
> +
> + if { ![is_aarch64_target]} {
> + return 0
> + }
> +
> + set compile_flags "{additional_flags=-march=armv8-a}"
> +
> + # Compile a test program reading FPMR.
> + set src {
> + int main() {
> + asm volatile ("mrs x0, fpmr");
> + return 0;
> + }
> + }
> + if {![gdb_simple_compile $me $src executable $compile_flags]} {
> + # Try again, but with a raw hex instruction so we don't rely on
> + # assembler support for FPMR.
> +
> + set compile_flags "{additional_flags=-march=armv8-a}"
> +
> + # Compile a test program reading FPMR.
> + set src {
> + int main() {
> + asm volatile (".word 0xD53B4440");
> + return 0;
> + }
> + }
> +
> + if {![gdb_simple_compile $me $src executable $compile_flags]} {
> + return 0
> + }
> + }
> +
> + # Compilation succeeded so now run it via gdb.
> + clean_restart
> + gdb_load $obj
> + gdb_run_cmd
> +
> + gdb_expect {
> + -re ".*Illegal instruction.*${gdb_prompt} $" {
> + verbose -log "\n$me fpmr support not detected"
> + set allow_fpmr_tests 0
> + }
> + -re ".*$inferior_exited_re normally.*${gdb_prompt} $" {
> + verbose -log "\n$me: fpmr support detected"
> + set allow_fpmr_tests 1
> + }
> + default {
> + warning "\n$me: default case taken"
> + set allow_fpmr_tests 0
> + }
> + }
> + gdb_exit
> + remote_file build delete $obj
> +
> + verbose "$me: returning $allow_fpmr_tests" 2
> + return $allow_fpmr_tests
> +}
> +
> # Run a test on the target to see if it supports AArch64 MOPS (Memory
> # Operations) extensions. Return 1 if so, 0 if it does not. Note this
> # causes a restart of GDB.
Thanks! This is OK.
Approved-By: Luis Machado <luis.machado.foss@gmail.com>
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v4 6/6] gdb/doc: Document AArch64 FPMR support
2025-10-31 15:16 [PATCH v4 0/6] gdb/aarch64: Support for FPMR Ezra.Sitorus
` (4 preceding siblings ...)
2025-10-31 15:16 ` [PATCH v4 5/6] gdb/aarch64: Tests for fpmr Ezra.Sitorus
@ 2025-10-31 15:16 ` Ezra.Sitorus
2025-10-31 16:57 ` Eli Zaretskii
2025-11-09 20:15 ` Luis
5 siblings, 2 replies; 13+ messages in thread
From: Ezra.Sitorus @ 2025-10-31 15:16 UTC (permalink / raw)
To: gdb-patches; +Cc: luis.machado.foss, Ezra Sitorus
From: Ezra Sitorus <ezra.sitorus@arm.com>
Add NEWS entry and document new feature in gdb.texinfo.
---
Changes from v3->v4:
* Removed unrelated changes in NEWS
* Fixup of index entry
* Formatting
Ezra
gdb/NEWS | 2 ++
gdb/doc/gdb.texinfo | 71 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 73 insertions(+)
diff --git a/gdb/NEWS b/gdb/NEWS
index 01bd1524c7a..30683e7c3c7 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -14,6 +14,8 @@
this flag is used gdbserver will not escape special shell characters
within the inferior arguments.
+* Support for Floating Point Mode Register (FPMR) in AArch64.
+
* New targets
GNU/Linux/MicroBlaze (gdbserver) microblazeel-*linux*
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 676143be416..6574eff9390 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -27080,6 +27080,26 @@ Program received signal SIGSEGV, Segmentation fault
Guarded Control Stack error.
@end smallexample
+@subsubsection AArch64 Floating Point Mode Register
+@cindex floating point mode register, AArch64
+@cindex FPMR, AArch64
+
+When @value{GDBN} is debugging the AArch64 architecture and the Floating Point
+Mode Register (FPMR) is available, then @value{GDBN} will make the @code{fpmr}
+available. This register determines the behaviour of FP8 instructions.
+
+To aid debugging, @value{GDBN} interprets the mode or value of each field in
+@code{fpmr}.
+
+@smallexample
+p $fpmr
+$1 = [ F8S1=E5M2 F8S2=E5M2 F8D=E5M2 OSM=Inf OSC=Inf/NaN LSCALE=0 NSCALE=0 LSCALE2=0 ]
+@end smallexample
+
+For more information about FPMR, please refer to the official
+@uref{https://developer.arm.com/documentation/ddi0601/latest,ignored,
+architecture registers documentation}.
+
@node x86
@subsection x86
@@ -49770,6 +49790,57 @@ documentation} in the Linux kernel.
Extra registers are allowed in these features, but they will not affect
@value{GDBN}.
+@subsubsection AArch64 FPMR feature
+
+The @samp{org.gnu.gdb.aarch64.fpmr} optional feature was introduced so
+@value{GDBN} could detect support for the Floating Point Mode Register
+extension. If present, this feature must have the following register:
+
+@itemize @minus
+@item
+@samp{fpmr}, the floating point mode register. It is represented as
+if it were a 64-bit register with a custom flags type.
+@end itemize
+
+The custom flags type allows @value{GDBN} to print a human-friendly
+representation of the contents of @code{fpmr} should contain:
+
+@itemize @minus
+
+@item
+@code{F8S1}, which is either @code{E5M2} or @code{E4M3}
+
+@item
+@code{F8S2}, which is either @code{E5M2} or @code{E4M3}
+
+@item
+@code{F8D}, which is either @code{E5M2} or @code{E4M3}
+
+@item
+@code{OSM}, which is either @code{Inf} or @code{MaxNormal}
+
+@item
+@code{OSC}, which is either @code{Inf/NaN} or @code{MaxNormal}
+
+@item
+@code{LSCALE}, which is a 7-bit unsigned value
+
+@item
+@code{NSCALE}, which is actually an 8-bit signed value but represented as an
+8-bit unsigned value
+
+@item
+@code{LSCALE2}, which is a 6-bit unsigned value
+
+@end itemize
+
+Extra registers are allowed in this feature, but they will not affect
+@value{GDBN}.
+
+For more information about FPMR, please refer to the official
+@uref{https://developer.arm.com/documentation/ddi0601/latest,ignored,
+architecture registers documentation}.
+
@node Alpha Features
@subsection Alpha Features
@cindex target descriptions, Alpha Features
--
2.45.2
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH v4 6/6] gdb/doc: Document AArch64 FPMR support
2025-10-31 15:16 ` [PATCH v4 6/6] gdb/doc: Document AArch64 FPMR support Ezra.Sitorus
@ 2025-10-31 16:57 ` Eli Zaretskii
2025-11-09 20:15 ` Luis
1 sibling, 0 replies; 13+ messages in thread
From: Eli Zaretskii @ 2025-10-31 16:57 UTC (permalink / raw)
To: Ezra.Sitorus; +Cc: gdb-patches, luis.machado.foss
> From: <Ezra.Sitorus@arm.com>
> CC: <luis.machado.foss@gmail.com>, Ezra Sitorus <ezra.sitorus@arm.com>
> Date: Fri, 31 Oct 2025 15:16:41 +0000
>
> From: Ezra Sitorus <ezra.sitorus@arm.com>
>
> Add NEWS entry and document new feature in gdb.texinfo.
> ---
> Changes from v3->v4:
> * Removed unrelated changes in NEWS
> * Fixup of index entry
> * Formatting
>
> Ezra
>
> gdb/NEWS | 2 ++
> gdb/doc/gdb.texinfo | 71 +++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 73 insertions(+)
Thanks.
> diff --git a/gdb/NEWS b/gdb/NEWS
> index 01bd1524c7a..30683e7c3c7 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -14,6 +14,8 @@
> this flag is used gdbserver will not escape special shell characters
> within the inferior arguments.
>
> +* Support for Floating Point Mode Register (FPMR) in AArch64.
This part is okay.
> +When @value{GDBN} is debugging the AArch64 architecture and the Floating Point
> +Mode Register (FPMR) is available, then @value{GDBN} will make the @code{fpmr}
^^^^
"@acronym{FPMR}"
> +available. This register determines the behaviour of FP8 instructions.
^^^^^^^^^ ^^^
"behavior" (we use US English spelling) and "@code{FP8}".
> +For more information about FPMR, please refer to the official
^^^^
@acronym{FPMR}
> +For more information about FPMR, please refer to the official
Likewise.
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH v4 6/6] gdb/doc: Document AArch64 FPMR support
2025-10-31 15:16 ` [PATCH v4 6/6] gdb/doc: Document AArch64 FPMR support Ezra.Sitorus
2025-10-31 16:57 ` Eli Zaretskii
@ 2025-11-09 20:15 ` Luis
2025-11-10 12:00 ` Eli Zaretskii
2025-11-10 17:28 ` Ezra Sitorus
1 sibling, 2 replies; 13+ messages in thread
From: Luis @ 2025-11-09 20:15 UTC (permalink / raw)
To: Ezra.Sitorus, gdb-patches, Eli Zaretskii
Hi,
On 31/10/2025 15:16, Ezra.Sitorus@arm.com wrote:
> From: Ezra Sitorus <ezra.sitorus@arm.com>
>
> Add NEWS entry and document new feature in gdb.texinfo.
> ---
> Changes from v3->v4:
> * Removed unrelated changes in NEWS
> * Fixup of index entry
> * Formatting
>
> Ezra
>
> gdb/NEWS | 2 ++
> gdb/doc/gdb.texinfo | 71 +++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 73 insertions(+)
>
> diff --git a/gdb/NEWS b/gdb/NEWS
> index 01bd1524c7a..30683e7c3c7 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -14,6 +14,8 @@
> this flag is used gdbserver will not escape special shell characters
> within the inferior arguments.
>
> +* Support for Floating Point Mode Register (FPMR) in AArch64.
> +
> * New targets
>
> GNU/Linux/MicroBlaze (gdbserver) microblazeel-*linux*
> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
> index 676143be416..6574eff9390 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -27080,6 +27080,26 @@ Program received signal SIGSEGV, Segmentation fault
> Guarded Control Stack error.
> @end smallexample
>
> +@subsubsection AArch64 Floating Point Mode Register
> +@cindex floating point mode register, AArch64
> +@cindex FPMR, AArch64
> +
> +When @value{GDBN} is debugging the AArch64 architecture and the Floating Point
> +Mode Register (FPMR) is available, then @value{GDBN} will make the @code{fpmr}
> +available. This register determines the behaviour of FP8 instructions.
> +
> +To aid debugging, @value{GDBN} interprets the mode or value of each field in
> +@code{fpmr}.
> +
> +@smallexample
> +p $fpmr
> +$1 = [ F8S1=E5M2 F8S2=E5M2 F8D=E5M2 OSM=Inf OSC=Inf/NaN LSCALE=0 NSCALE=0 LSCALE2=0 ]
> +@end smallexample
> +
> +For more information about FPMR, please refer to the official
> +@uref{https://developer.arm.com/documentation/ddi0601/latest,ignored,
> +architecture registers documentation}.
> +
> @node x86
> @subsection x86
>
> @@ -49770,6 +49790,57 @@ documentation} in the Linux kernel.
> Extra registers are allowed in these features, but they will not affect
> @value{GDBN}.
>
> +@subsubsection AArch64 FPMR feature
> +
> +The @samp{org.gnu.gdb.aarch64.fpmr} optional feature was introduced so
> +@value{GDBN} could detect support for the Floating Point Mode Register
> +extension. If present, this feature must have the following register:
> +
> +@itemize @minus
> +@item
> +@samp{fpmr}, the floating point mode register. It is represented as
> +if it were a 64-bit register with a custom flags type.
> +@end itemize
> +
> +The custom flags type allows @value{GDBN} to print a human-friendly
> +representation of the contents of @code{fpmr} should contain:
> +
> +@itemize @minus
> +
> +@item
> +@code{F8S1}, which is either @code{E5M2} or @code{E4M3}
> +
> +@item
> +@code{F8S2}, which is either @code{E5M2} or @code{E4M3}
> +
> +@item
> +@code{F8D}, which is either @code{E5M2} or @code{E4M3}
> +
> +@item
> +@code{OSM}, which is either @code{Inf} or @code{MaxNormal}
> +
> +@item
> +@code{OSC}, which is either @code{Inf/NaN} or @code{MaxNormal}
> +
> +@item
> +@code{LSCALE}, which is a 7-bit unsigned value
> +
> +@item
> +@code{NSCALE}, which is actually an 8-bit signed value but represented as an
> +8-bit unsigned value
> +
> +@item
> +@code{LSCALE2}, which is a 6-bit unsigned value
> +
> +@end itemize
> +
> +Extra registers are allowed in this feature, but they will not affect
> +@value{GDBN}.
> +
> +For more information about FPMR, please refer to the official
> +@uref{https://developer.arm.com/documentation/ddi0601/latest,ignored,
> +architecture registers documentation}.
> +
> @node Alpha Features
> @subsection Alpha Features
> @cindex target descriptions, Alpha Features
I have no further comments on this one. Once Eli is happy with the
documentation changes, please push the series. If you don´t have commit
access yet, I can do that for you.
Thanks!
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH v4 6/6] gdb/doc: Document AArch64 FPMR support
2025-11-09 20:15 ` Luis
@ 2025-11-10 12:00 ` Eli Zaretskii
2025-11-10 17:28 ` Ezra Sitorus
1 sibling, 0 replies; 13+ messages in thread
From: Eli Zaretskii @ 2025-11-10 12:00 UTC (permalink / raw)
To: Luis; +Cc: Ezra.Sitorus, gdb-patches
> Date: Sun, 9 Nov 2025 20:15:04 +0000
> From: Luis <luis.machado.foss@gmail.com>
>
> I have no further comments on this one. Once Eli is happy with the
> documentation changes, please push the series. If you don´t have commit
> access yet, I can do that for you.
I hope I'm not confused: according to my records, I've reviewed this
series on Oct 31 and posted my review then, see
https://sourceware.org/pipermail/gdb-patches/2025-October/222254.html
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 6/6] gdb/doc: Document AArch64 FPMR support
2025-11-09 20:15 ` Luis
2025-11-10 12:00 ` Eli Zaretskii
@ 2025-11-10 17:28 ` Ezra Sitorus
2025-11-14 7:38 ` Luis
1 sibling, 1 reply; 13+ messages in thread
From: Ezra Sitorus @ 2025-11-10 17:28 UTC (permalink / raw)
To: Luis; +Cc: gdb-patches, Eli Zaretskii
Hi all,
On Sun, Nov 09, 2025 at 08:15:04PM +0000, Luis wrote:
> I have no further comments on this one. Once Eli is happy with the
> documentation changes, please push the series. If you don�t have commit
> access yet, I can do that for you.
>
Just to double check, are we treating commit access to binutils the same as
for gdb? If they're different then I only have access to binutils.
Am I right in thinking also that each patch requires an 'Approved-By' (and
'Reviewed-By' as well for the news/doc patch) line at the end of the commit
message? What happens if this isn't added?
Ezra
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 6/6] gdb/doc: Document AArch64 FPMR support
2025-11-10 17:28 ` Ezra Sitorus
@ 2025-11-14 7:38 ` Luis
0 siblings, 0 replies; 13+ messages in thread
From: Luis @ 2025-11-14 7:38 UTC (permalink / raw)
To: Ezra Sitorus; +Cc: gdb-patches, Eli Zaretskii
[-- Attachment #1: Type: text/plain, Size: 1119 bytes --]
Hi,
On Mon, Nov 10, 2025, 17:28 Ezra Sitorus <ezra.sitorus@arm.com> wrote:
> Hi all,
>
> On Sun, Nov 09, 2025 at 08:15:04PM +0000, Luis wrote:
>
> > I have no further comments on this one. Once Eli is happy with the
> > documentation changes, please push the series. If you don�t have commit
> > access yet, I can do that for you.
> >
>
> Just to double check, are we treating commit access to binutils the same as
> for gdb? If they're different then I only have access to binutils.
>
They are the same. If you have commit access to binutils, then you have it
for gdb as well.
> Am I right in thinking also that each patch requires an 'Approved-By' (and
> 'Reviewed-By' as well for the news/doc patch) line at the end of the commit
> message? What happens if this isn't added?
>
Yes. I've given approval for all the non-documentation ones. Eli approves
the docs, but he may have given a Reviewed-By because the docs potentially
contain arch-specific things.
If so, I'm ok with the docs too.
Thanks!
Approved-By: Luis Machado <luis.machado.foss@gmail.com>
> Ezra
>
[-- Attachment #2: Type: text/html, Size: 2266 bytes --]
^ permalink raw reply [flat|nested] 13+ messages in thread