* [PATCH v3 0/5] gdb/aarch64: Add POR_EL0 register support for FEAT_S1POE
@ 2026-07-14 20:15 srinath.parvathaneni
2026-07-14 20:15 ` [PATCH v3 1/5] [PATCH 1/5] " srinath.parvathaneni
` (4 more replies)
0 siblings, 5 replies; 22+ messages in thread
From: srinath.parvathaneni @ 2026-07-14 20:15 UTC (permalink / raw)
To: gdb-patches
Cc: luis.machado.foss, guinevere, thiago.bauermann, Ezra.Sitorus,
Matthieu.Longo, simark, Srinath Parvathaneni
From: Srinath Parvathaneni <srinath.parvathaneni@arm.com>
Changes v2 -> v3:
Patch 1:
* Address review comments.
* After discussion, retain the _EL0 suffix for the POE register.
* Merge the POR_EL0 custom printing support from v2 Patch 2.
* Update the XML description to use the POR_EL0_FLAGS type for
custom register printing.
Patch 2:
* Corresponds to v2 Patch 3.
* No functional changes.
* Approved by Thiago Jung Bauermann.
Patch 3:
* Corresponds to v2 Patch 4.
* No functional changes.
* Approved by Thiago Jung Bauermann.
Patch 4:
* The BFD/readelf changes from v2 Patch 5 have been posted separately
to binutils-gdb and have since been approved and committed.
* Corresponds to v2 Patch 6.
* Address review comments on the GDB core file support.
Patch 5:
* Corresponds to v2 Patch 7.
* Address review comments.
* Update the tests to reflect the POR_EL0 custom string shown by
`info registers por_el0` and `print $por_el0`.
* Fix aarch64-poe-core.exp test issues.
* Rebased onto current upstream master, including:
* Matthieu Longo's "gdb: align siginfo_t with the Linux kernel definition".
* My "gdb: Fix assignment to TYPE_CODE_FLAGS registers" patch.
----------------
Changes v1 -> v2:
* Rebased the SIGSEGV diagnostic support on Matthieu Longo's generic
"siginfo_t" changes, using the new "_._addr_pkey.si_pkey" layout
instead of introducing a target-specific "siginfo_t" extension.
* Split the original series into smaller, subsystem-specific patches:
* GDB register support
* POR_EL0 pretty printing
* SIGSEGV diagnostics
* gdbserver support
* BFD/readelf core file support
* GDB core file support
* Testsuite
* Separated BFD/readelf and GDB core file support into independent
patches.
* Retained FEAT_S1POE expansion as "Permission Overlay Extension" after internal discussion.
* Removed the POR_EL0 permission decoding string (e.g. `por_el0[pkey=<value>] = rwx`) from
SIGSEGV diagnostics, as displaying permissions without also showing base and effective
permissions can be misleading to users.
* Rebased the series onto current upstream master + Matthieu's patch
"gdb: align siginfo_t with the Linux kernel definition"
----------------
Hi,
This series adds support for the AArch64 Permission Overlay Extension
(FEAT_S1POE) in GDB and gdbserver.
The series introduces support for the POR_EL0 register, allowing GDB
to read and write it using the Linux NT_ARM_POE regset. It also improves
SIGSEGV diagnostics for Permission Overlay violations, extends gdbserver
to transfer POR_EL0 during remote debugging, restores POR_EL0 from core
files, and adds testsuite coverage.
The BFD/readelf support for the NT_ARM_POE core note has already been
posted and approved separately.
commit d15490528409305f97004a2860fdb04543862774
Author: Srinath Parvathaneni <srinath.parvathaneni@arm.com>
Date: Thu Jul 2 13:57:25 2026 +0000
bfd/readelf: Add core file support for FEAT_S1POE
The series consists of the following patches:
[1/5] gdb/aarch64: Add POR_EL0 register support
Add support for reading and writing the POR_EL0 register using the Linux
NT_ARM_POE regset.
[2/5] gdb: Improve SIGSEGV diagnostics for POE faults
Report the faulting address together with the associated protection key
for Permission Overlay violations.
[3/5] gdbserver/aarch64: Add POR_EL0 register support
Transfer the POR register through the Linux NT_ARM_POE regset during
remote debugging.
[4/5] gdb/aarch64: Add core file support for FEAT_S1POE
Restore the POR_EL0 register from Linux core files and signal frames.
[5/5] gdb/testsuite: Add FEAT_S1POE testcases
Add tests covering POR_EL0 register access, SIGSEGV diagnostics,
fix-and-continue support, and core file support.
The series has been tested natively and using gdbserver with remote GDB
on an FVP built using shrinkwrap with a Linux kernel configured with
CONFIG_ARM64_POE=y and a glibc version providing userspace POE support.
Regression tested on aarch64-none-linux-gnu with no regressions.
Ok for GDB master?
----------
>> This series adds support for the AArch64 Permission Overlay Extension
>> (FEAT_S1POE) in GDB, gdbserver, BFD and the testsuite.
>
> Hi Srinath!
>
> I don't know much about the arm architecture or this extension in
> specific, but it seems that it at least adds new registers so this seems
> like a valid question: Do these impact recording of ARM instructions
> with the record-full subsystem at all?
>
> It would be nice to have a gdb.reverse test that exercises some (ideally
> all) new instructions if there are any, and some other instructions that
> manipulate those new registers, if needed.
>
> This isn't required to get this series merged, of course, but it would
> be very nice to have it.
Hi Guinevere,
As far as I understand, FEAT_S1POE doesn't introduce any new AArch64
instructions in userspace, it only exposes the POR_EL0 register, which
is accessed through the Linux Protection-key APIs. The register itself
is managed by the kernel rather than being modified by normal AArch64
instructions. Because of that, I don't think this support has any impact
on the record-full subsystem.
Thanks for the suggestion about adding gdb.reverse tests. I'll keep that
in mind for other feature support.
Regards,
Srinath
Srinath Parvathaneni (5):
gdb/aarch64: Add POR_EL0 register support for FEAT_S1POE
gdb: Improve SIGSEGV diagnostics for POE faults
gdbserver/aarch64: Add POR_EL0 register support
gdb/aarch64: Add core file support for FEAT_S1POE
gdb/testsuite: Add FEAT_S1POE testcases
gdb/Makefile.in | 2 +
gdb/aarch64-linux-nat.c | 64 +++++++++++
gdb/aarch64-linux-tdep.c | 71 +++++++++++-
gdb/aarch64-tdep.c | 23 ++++
gdb/aarch64-tdep.h | 10 ++
gdb/arch/aarch64-poe-linux.h | 29 +++++
gdb/arch/aarch64.c | 4 +
gdb/arch/aarch64.h | 8 +-
gdb/features/Makefile | 1 +
gdb/features/aarch64-poe.c | 68 ++++++++++++
gdb/features/aarch64-poe.xml | 47 ++++++++
gdb/nat/aarch64-poe-linux.h | 29 +++++
gdb/testsuite/gdb.arch/aarch64-poe-core.exp | 101 ++++++++++++++++++
gdb/testsuite/gdb.arch/aarch64-poe-sigsegv. | 0
gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.c | 52 +++++++++
.../gdb.arch/aarch64-poe-sigsegv.exp | 58 ++++++++++
gdb/testsuite/gdb.arch/aarch64-poe.c | 29 +++++
gdb/testsuite/gdb.arch/aarch64-poe.exp | 46 ++++++++
gdb/testsuite/lib/gdb.exp | 55 ++++++++++
gdbserver/linux-aarch64-low.cc | 30 ++++++
20 files changed, 723 insertions(+), 4 deletions(-)
create mode 100644 gdb/arch/aarch64-poe-linux.h
create mode 100644 gdb/features/aarch64-poe.c
create mode 100644 gdb/features/aarch64-poe.xml
create mode 100644 gdb/nat/aarch64-poe-linux.h
create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe-core.exp
create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.
create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.c
create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.exp
create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe.c
create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe.exp
--
2.43.0
^ permalink raw reply [flat|nested] 22+ messages in thread* [PATCH v3 1/5] [PATCH 1/5] gdb/aarch64: Add POR_EL0 register support for FEAT_S1POE 2026-07-14 20:15 [PATCH v3 0/5] gdb/aarch64: Add POR_EL0 register support for FEAT_S1POE srinath.parvathaneni @ 2026-07-14 20:15 ` srinath.parvathaneni 2026-07-21 19:53 ` Luis 2026-07-21 20:25 ` Luis 2026-07-14 20:15 ` [PATCH v3 2/5] [PATCH 2/5] gdb: Improve SIGSEGV diagnostics for POE faults srinath.parvathaneni ` (3 subsequent siblings) 4 siblings, 2 replies; 22+ messages in thread From: srinath.parvathaneni @ 2026-07-14 20:15 UTC (permalink / raw) To: gdb-patches Cc: luis.machado.foss, guinevere, thiago.bauermann, Ezra.Sitorus, Matthieu.Longo, simark, Srinath Parvathaneni From: Srinath Parvathaneni <srinath.parvathaneni@arm.com> Add support for the FEAT_S1POE POR_EL0 register on AArch64. This patch adds POR_EL0 to the AArch64 register set and reads/writes it using the NT_ARM_POE ptrace regset. With this change, POR_EL0 is available through: * info registers * info registers por_el0 * p $por_el0 * p/x $por_el0 * set $por_el0 = <value> Example: (gdb) info register por_el0 por_el0 0x7 [ P15=--- P14=--- P13=--- P12=--- P11=--- P10=--- P9=--- P8=--- P7=--- P6=--- P5=--- P4=--- P3=--- P2=--- P1=--- P0=rwx ] (gdb) set $por_el0=0xffffffff77777777 (gdb) info register por_el0 por_el0 0xffffffff77777777 [ P15=??? P14=??? P13=??? P12=??? P11=??? P10=??? P9=??? P8=??? P7=rwx P6=rwx P5=rwx P4=rwx P3=rwx P2=rwx P1=rwx P0=rwx ] (gdb) p $por_el0 $1 = [ P15=??? P14=??? P13=??? P12=??? P11=??? P10=??? P9=??? P8=??? P7=rwx P6=rwx P5=rwx P4=rwx P3=rwx P2=rwx P1=rwx P0=rwx ] (gdb) p/x $por_el0 $2 = 0xffffffff77777777 (gdb) set $por_el0=0x57 (gdb) info register por_el0 por_el0 0x57 [ P15=--- P14=--- P13=--- P12=--- P11=--- P10=--- P9=--- P8=--- P7=--- P6=--- P5=--- P4=--- P3=--- P2=--- P1=rw- P0=rwx ] (gdb) set $por_el0=0xf7f7f7f7f7f7f7f7 (gdb) info register por_el0 por_el0 0xf7f7f7f7f7f7f7f7 [ P15=??? P14=rwx P13=??? P12=rwx P11=??? P10=rwx P9=??? P8=rwx P7=??? P6=rwx P5=??? P4=rwx P3=??? P2=rwx P1=??? P0=rwx ] (gdb) --- gdb/Makefile.in | 2 ++ gdb/aarch64-linux-nat.c | 64 +++++++++++++++++++++++++++++++++ gdb/aarch64-tdep.c | 23 ++++++++++++ gdb/aarch64-tdep.h | 10 ++++++ gdb/arch/aarch64-poe-linux.h | 29 +++++++++++++++ gdb/arch/aarch64.c | 4 +++ gdb/arch/aarch64.h | 8 ++++- gdb/features/Makefile | 1 + gdb/features/aarch64-poe.c | 68 ++++++++++++++++++++++++++++++++++++ gdb/features/aarch64-poe.xml | 47 +++++++++++++++++++++++++ gdb/nat/aarch64-poe-linux.h | 29 +++++++++++++++ 11 files changed, 284 insertions(+), 1 deletion(-) create mode 100644 gdb/arch/aarch64-poe-linux.h create mode 100644 gdb/features/aarch64-poe.c create mode 100644 gdb/features/aarch64-poe.xml create mode 100644 gdb/nat/aarch64-poe-linux.h diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 57f384170ab..3dc9cd07dcb 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -1292,6 +1292,7 @@ HFILES_NO_SRCDIR = \ arch/aarch32.h \ arch/aarch64-fpmr-linux.h \ arch/aarch64-gcs-linux.h \ + arch/aarch64-poe-linux.h \ arch/aarch64.h \ arch/aarch64-insn.h \ arch/aarch64-mte.h \ @@ -1540,6 +1541,7 @@ HFILES_NO_SRCDIR = \ namespace.h \ nat/aarch64-fpmr-linux.h \ nat/aarch64-gcs-linux.h \ + nat/aarch64-poe-linux.h \ nat/aarch64-hw-point.h \ nat/aarch64-linux.h \ nat/aarch64-linux-hw-point.h \ diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c index 52ace4aab41..8e29c42908c 100644 --- a/gdb/aarch64-linux-nat.c +++ b/gdb/aarch64-linux-nat.c @@ -34,6 +34,7 @@ #include "arch/arm.h" #include "nat/aarch64-fpmr-linux.h" #include "nat/aarch64-gcs-linux.h" +#include "nat/aarch64-poe-linux.h" #include "nat/aarch64-linux.h" #include "nat/aarch64-linux-hw-point.h" #include "nat/aarch64-mte-linux-ptrace.h" @@ -602,6 +603,54 @@ store_gcsregs_to_thread (regcache *regcache) perror_with_name (_("Unable to store GCS registers")); } +/* Fill GDB's register array with the POE register value from the current + thread. */ + +static void +fetch_poeregs_from_thread (regcache *regcache) +{ + aarch64_gdbarch_tdep *tdep + = gdbarch_tdep<aarch64_gdbarch_tdep> (regcache->arch ()); + + gdb_assert (tdep->has_poe ()); + + uint64_t user_poe; + iovec iovec; + + iovec.iov_base = &user_poe; + iovec.iov_len = sizeof (user_poe); + + int tid = get_ptrace_pid (regcache->ptid ()); + if (ptrace (PTRACE_GETREGSET, tid, NT_ARM_POE, &iovec) != 0) + perror_with_name (_("Unable to fetch POE register")); + + regcache->raw_supply (tdep->poe_regnum, &user_poe); +} + +/* Store the NT_ARM_POE register contents from GDB's REGCACHE to the + thread associated with REGCACHE. */ + +static void +store_poeregs_to_thread (struct regcache *regcache) +{ + aarch64_gdbarch_tdep *tdep + = gdbarch_tdep<aarch64_gdbarch_tdep> (regcache->arch ()); + + gdb_assert (tdep->has_poe ()); + + int tid = regcache->ptid ().lwp (); + + iovec iovec; + uint64_t user_poe; + iovec.iov_base = &user_poe; + iovec.iov_len = sizeof (user_poe); + + regcache->raw_collect (tdep->poe_regnum, &user_poe); + + if (ptrace (PTRACE_SETREGSET, tid, NT_ARM_POE, &iovec) != 0) + perror_with_name (_("Unable to store POE register")); +} + /* Fill GDB's REGCACHE with the FPMR register set content from the thread associated with REGCACHE. */ @@ -683,6 +732,9 @@ aarch64_fetch_registers (struct regcache *regcache, int regno) if (tdep->has_gcs_linux ()) fetch_gcsregs_from_thread (regcache); + if (tdep->has_poe ()) + fetch_poeregs_from_thread (regcache); + if (tdep->has_fpmr ()) fetch_fpmr_from_thread (regcache); } @@ -722,6 +774,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); + /* POE register? */ + else if (tdep->has_poe () && (regno == tdep->poe_regnum)) + fetch_poeregs_from_thread (regcache); /* FPMR? */ else if (tdep->has_fpmr () && (regno == tdep->fpmr_regnum)) fetch_fpmr_from_thread (regcache); @@ -802,6 +857,9 @@ aarch64_store_registers (struct regcache *regcache, int regno) if (tdep->has_fpmr ()) store_fpmr_to_thread (regcache); + + if (tdep->has_poe ()) + store_poeregs_to_thread (regcache); } /* General purpose register? */ else if (regno < AARCH64_V0_REGNUM) @@ -836,6 +894,9 @@ aarch64_store_registers (struct regcache *regcache, int regno) /* FPMR? */ else if (tdep->has_fpmr () && regno == tdep->fpmr_regnum) store_fpmr_to_thread (regcache); + /* POE register? */ + else if (tdep->has_poe () && regno == tdep->poe_regnum) + store_poeregs_to_thread (regcache); /* PAuth registers are read-only. */ } @@ -1024,6 +1085,9 @@ aarch64_linux_nat_target::read_description () /* Check for FPMR. */ features.fpmr = hwcap2 & HWCAP2_FPMR; + /* Check for POE support. */ + features.poe = hwcap2 & HWCAP2_POE; + return aarch64_read_description (features); } diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index a84da1fd59e..2e86d6e0452 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -164,6 +164,11 @@ static const char *const aarch64_gcs_register_names[] = { "gcspr" }; +static const char *const aarch64_poe_register_names[] = { + /* Permission Overlay Extension Register. */ + "por_el0" +}; + static const char *const aarch64_gcs_linux_register_names[] = { /* Field in struct user_gcs. */ "gcs_features_enabled", @@ -4136,6 +4141,10 @@ aarch64_features_from_target_desc (const struct target_desc *tdesc) features.fpmr = (tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.fpmr") != nullptr); + /* Check for POE feature. */ + features.poe = (tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.poe") + != nullptr); + return features; } @@ -4556,6 +4565,19 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) fpmr_regnum, "fpmr"); } + int poe_regnum = -1; + const struct tdesc_feature *feature_poe + = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.poe"); + if (feature_poe != nullptr) + { + poe_regnum = num_regs; + for (i = 0; i < ARRAY_SIZE (aarch64_poe_register_names); i++) + valid_p &= tdesc_numbered_register (feature_poe, tdesc_data.get (), + poe_regnum + i, + aarch64_poe_register_names[i]); + num_regs++; + } + int first_sme_regnum = -1; int first_sme2_regnum = -1; int first_sme_pseudo_regnum = -1; @@ -4756,6 +4778,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) tdep->gcs_reg_base = first_gcs_regnum; tdep->gcs_linux_reg_base = first_gcs_linux_regnum; tdep->fpmr_regnum = fpmr_regnum; + tdep->poe_regnum = poe_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 dff05a08f84..3c5d10beee5 100644 --- a/gdb/aarch64-tdep.h +++ b/gdb/aarch64-tdep.h @@ -208,6 +208,16 @@ struct aarch64_gdbarch_tdep : gdbarch_tdep_base return gcs_linux_reg_base != -1; } + /* POE register. This is -1 if no POE feature is available. */ + int poe_regnum = -1; + + /* Returns true if the target supports the POE feature. */ + bool + has_poe () const + { + return poe_regnum != -1; + } + /* First FPMR register. This is -1 if FPMR is not supported. */ int fpmr_regnum = -1; diff --git a/gdb/arch/aarch64-poe-linux.h b/gdb/arch/aarch64-poe-linux.h new file mode 100644 index 00000000000..8623fa43b54 --- /dev/null +++ b/gdb/arch/aarch64-poe-linux.h @@ -0,0 +1,29 @@ +/* Common Linux target-dependent definitions for AArch64 POE + + Copyright (C) 2026 Free Software Foundation, Inc. + + This file is part of GDB. + + 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/>. */ + +#ifndef GDB_ARCH_AARCH64_POE_LINUX_H +#define GDB_ARCH_AARCH64_POE_LINUX_H + +/* Feature check for Permission Overlay Extension. */ +#define AARCH64_HWCAP2_POE (1ULL << 63) + +/* Data or instruction abort caused by Protection Key Violation. */ +#define AARCH64_SEGV_PKUERR 4 + +#endif /* GDB_ARCH_AARCH64_POE_LINUX_H. */ diff --git a/gdb/arch/aarch64.c b/gdb/arch/aarch64.c index 2401a325b7b..a567938d06d 100644 --- a/gdb/arch/aarch64.c +++ b/gdb/arch/aarch64.c @@ -28,6 +28,7 @@ #include "../features/aarch64-sme2.c" #include "../features/aarch64-tls.c" #include "../features/aarch64-gcs.c" +#include "../features/aarch64-poe.c" #include "../features/aarch64-gcs-linux.c" /* See arch/aarch64.h. */ @@ -77,6 +78,9 @@ aarch64_create_target_description (const aarch64_features &features) if (features.fpmr) regnum = create_feature_aarch64_fpmr (tdesc.get (), regnum); + if (features.poe) + regnum = create_feature_aarch64_poe (tdesc.get (), regnum); + return tdesc; } diff --git a/gdb/arch/aarch64.h b/gdb/arch/aarch64.h index cf7318cbe74..ba90d55c3bb 100644 --- a/gdb/arch/aarch64.h +++ b/gdb/arch/aarch64.h @@ -35,6 +35,8 @@ struct aarch64_features bool pauth = false; bool mte = false; bool fpmr = false; + /* Whether the Permission Overlay Extension (FEAT_S1POE) is supported. */ + bool poe = false; /* A positive TLS value indicates the number of TLS registers available. */ uint8_t tls = 0; @@ -70,7 +72,8 @@ inline bool operator==(const aarch64_features &lhs, const aarch64_features &rhs) && lhs.sme2 == rhs.sme2 && lhs.gcs == rhs.gcs && lhs.gcs_linux == rhs.gcs_linux - && lhs.fpmr == rhs.fpmr; + && lhs.fpmr == rhs.fpmr + && lhs.poe == rhs.poe; } namespace std @@ -103,6 +106,9 @@ namespace std /* FPMR feature. */ h = h << 1 | features.fpmr; + + /* POE feature. */ + h = h << 1 | features.poe; return h; } }; diff --git a/gdb/features/Makefile b/gdb/features/Makefile index 161a7453d66..cc77e5bb652 100644 --- a/gdb/features/Makefile +++ b/gdb/features/Makefile @@ -207,6 +207,7 @@ FEATURE_XMLFILES = aarch64-core.xml \ aarch64-pauth.xml \ aarch64-mte.xml \ aarch64-gcs.xml \ + aarch64-poe.xml \ aarch64-gcs-linux.xml \ arc/v1-core.xml \ arc/v1-aux.xml \ diff --git a/gdb/features/aarch64-poe.c b/gdb/features/aarch64-poe.c new file mode 100644 index 00000000000..4bd795e9fe6 --- /dev/null +++ b/gdb/features/aarch64-poe.c @@ -0,0 +1,68 @@ +/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro: + Original: aarch64-poe.xml */ + +#include "gdbsupport/tdesc.h" + +static int +create_feature_aarch64_poe (struct target_desc *result, long regnum) +{ + struct tdesc_feature *feature; + + feature = tdesc_create_feature (result, "org.gnu.gdb.aarch64.poe"); + tdesc_type_with_fields *type_with_fields; + type_with_fields = tdesc_create_enum (feature, "por_el0_fmt", 4); + tdesc_add_enum_value (type_with_fields, 0, "---"); + tdesc_add_enum_value (type_with_fields, 1, "r--"); + tdesc_add_enum_value (type_with_fields, 2, "--x"); + tdesc_add_enum_value (type_with_fields, 3, "r-x"); + tdesc_add_enum_value (type_with_fields, 4, "-w-"); + tdesc_add_enum_value (type_with_fields, 5, "rw-"); + tdesc_add_enum_value (type_with_fields, 6, "-wx"); + tdesc_add_enum_value (type_with_fields, 7, "rwx"); + tdesc_add_enum_value (type_with_fields, 8, "???"); + tdesc_add_enum_value (type_with_fields, 9, "???"); + tdesc_add_enum_value (type_with_fields, 10, "???"); + tdesc_add_enum_value (type_with_fields, 11, "???"); + tdesc_add_enum_value (type_with_fields, 12, "???"); + tdesc_add_enum_value (type_with_fields, 13, "???"); + tdesc_add_enum_value (type_with_fields, 14, "???"); + tdesc_add_enum_value (type_with_fields, 15, "???"); + + type_with_fields = tdesc_create_flags (feature, "por_el0_flags", 8); + tdesc_type *field_type; + field_type = tdesc_named_type (feature, "por_el0_fmt"); + tdesc_add_typed_bitfield (type_with_fields, "P15", 60, 63, field_type); + field_type = tdesc_named_type (feature, "por_el0_fmt"); + tdesc_add_typed_bitfield (type_with_fields, "P14", 56, 59, field_type); + field_type = tdesc_named_type (feature, "por_el0_fmt"); + tdesc_add_typed_bitfield (type_with_fields, "P13", 52, 55, field_type); + field_type = tdesc_named_type (feature, "por_el0_fmt"); + tdesc_add_typed_bitfield (type_with_fields, "P12", 48, 51, field_type); + field_type = tdesc_named_type (feature, "por_el0_fmt"); + tdesc_add_typed_bitfield (type_with_fields, "P11", 44, 47, field_type); + field_type = tdesc_named_type (feature, "por_el0_fmt"); + tdesc_add_typed_bitfield (type_with_fields, "P10", 40, 43, field_type); + field_type = tdesc_named_type (feature, "por_el0_fmt"); + tdesc_add_typed_bitfield (type_with_fields, "P9", 36, 39, field_type); + field_type = tdesc_named_type (feature, "por_el0_fmt"); + tdesc_add_typed_bitfield (type_with_fields, "P8", 32, 35, field_type); + field_type = tdesc_named_type (feature, "por_el0_fmt"); + tdesc_add_typed_bitfield (type_with_fields, "P7", 28, 31, field_type); + field_type = tdesc_named_type (feature, "por_el0_fmt"); + tdesc_add_typed_bitfield (type_with_fields, "P6", 24, 27, field_type); + field_type = tdesc_named_type (feature, "por_el0_fmt"); + tdesc_add_typed_bitfield (type_with_fields, "P5", 20, 23, field_type); + field_type = tdesc_named_type (feature, "por_el0_fmt"); + tdesc_add_typed_bitfield (type_with_fields, "P4", 16, 19, field_type); + field_type = tdesc_named_type (feature, "por_el0_fmt"); + tdesc_add_typed_bitfield (type_with_fields, "P3", 12, 15, field_type); + field_type = tdesc_named_type (feature, "por_el0_fmt"); + tdesc_add_typed_bitfield (type_with_fields, "P2", 8, 11, field_type); + field_type = tdesc_named_type (feature, "por_el0_fmt"); + tdesc_add_typed_bitfield (type_with_fields, "P1", 4, 7, field_type); + field_type = tdesc_named_type (feature, "por_el0_fmt"); + tdesc_add_typed_bitfield (type_with_fields, "P0", 0, 3, field_type); + + tdesc_create_reg (feature, "por_el0", regnum++, 1, "system", 64, "por_el0_flags"); + return regnum; +} diff --git a/gdb/features/aarch64-poe.xml b/gdb/features/aarch64-poe.xml new file mode 100644 index 00000000000..58fc4f80d5c --- /dev/null +++ b/gdb/features/aarch64-poe.xml @@ -0,0 +1,47 @@ +<?xml version="1.0"?> +<!-- Copyright (C) 2026 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.poe"> + <enum id="por_el0_fmt" size="4"> + <evalue name="---" value="0"/> + <evalue name="r--" value="1"/> + <evalue name="--x" value="2"/> + <evalue name="r-x" value="3"/> + <evalue name="-w-" value="4"/> + <evalue name="rw-" value="5"/> + <evalue name="-wx" value="6"/> + <evalue name="rwx" value="7"/> + <evalue name="???" value="8"/> + <evalue name="???" value="9"/> + <evalue name="???" value="10"/> + <evalue name="???" value="11"/> + <evalue name="???" value="12"/> + <evalue name="???" value="13"/> + <evalue name="???" value="14"/> + <evalue name="???" value="15"/> + </enum> + <flags id="por_el0_flags" size="8"> + <field name="P15" start="60" end="63" type="por_el0_fmt"/> + <field name="P14" start="56" end="59" type="por_el0_fmt"/> + <field name="P13" start="52" end="55" type="por_el0_fmt"/> + <field name="P12" start="48" end="51" type="por_el0_fmt"/> + <field name="P11" start="44" end="47" type="por_el0_fmt"/> + <field name="P10" start="40" end="43" type="por_el0_fmt"/> + <field name="P9" start="36" end="39" type="por_el0_fmt"/> + <field name="P8" start="32" end="35" type="por_el0_fmt"/> + <field name="P7" start="28" end="31" type="por_el0_fmt"/> + <field name="P6" start="24" end="27" type="por_el0_fmt"/> + <field name="P5" start="20" end="23" type="por_el0_fmt"/> + <field name="P4" start="16" end="19" type="por_el0_fmt"/> + <field name="P3" start="12" end="15" type="por_el0_fmt"/> + <field name="P2" start="8" end="11" type="por_el0_fmt"/> + <field name="P1" start="4" end="7" type="por_el0_fmt"/> + <field name="P0" start="0" end="3" type="por_el0_fmt"/> + </flags> + <reg name="por_el0" bitsize="64" type="por_el0_flags" group="system"/> +</feature> diff --git a/gdb/nat/aarch64-poe-linux.h b/gdb/nat/aarch64-poe-linux.h new file mode 100644 index 00000000000..f3d0256da3f --- /dev/null +++ b/gdb/nat/aarch64-poe-linux.h @@ -0,0 +1,29 @@ +/* Common native Linux definitions for AArch64 Permission Overlay Extension. + + Copyright (C) 2026 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 <asm/hwcap.h> +#ifndef GDB_NAT_AARCH64_POE_LINUX_H +#define GDB_NAT_AARCH64_POE_LINUX_H + +/* Feature check for Permission Overlay Extension. */ +#ifndef HWCAP2_POE +#define HWCAP2_POE (1ULL << 63) +#endif /* HWCAP2_POE. */ + +#endif /* GDB_NAT_AARCH64_POE_LINUX_H. */ -- 2.43.0 ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3 1/5] [PATCH 1/5] gdb/aarch64: Add POR_EL0 register support for FEAT_S1POE 2026-07-14 20:15 ` [PATCH v3 1/5] [PATCH 1/5] " srinath.parvathaneni @ 2026-07-21 19:53 ` Luis 2026-07-25 6:20 ` Thiago Jung Bauermann 2026-07-21 20:25 ` Luis 1 sibling, 1 reply; 22+ messages in thread From: Luis @ 2026-07-21 19:53 UTC (permalink / raw) To: srinath.parvathaneni, gdb-patches Cc: guinevere, thiago.bauermann, Ezra.Sitorus, Matthieu.Longo, simark, Peter Maydell On 14/07/2026 21:15, srinath.parvathaneni@arm.com wrote: > From: Srinath Parvathaneni <srinath.parvathaneni@arm.com> > > Add support for the FEAT_S1POE POR_EL0 register on AArch64. > > This patch adds POR_EL0 to the AArch64 register set and reads/writes it > using the NT_ARM_POE ptrace regset. Just a general comment, but por_el0 is unfortunate naming for a userspace register. But alas, it's been done that way in the Linux kernel as far as I can tell. > > With this change, POR_EL0 is available through: > * info registers > * info registers por_el0 > * p $por_el0 > * p/x $por_el0 > * set $por_el0 = <value> > > Example: > (gdb) info register por_el0 > por_el0 0x7 [ P15=--- P14=--- P13=--- P12=--- P11=--- P10=--- P9=--- P8=--- P7=--- P6=--- P5=--- P4=--- P3=--- P2=--- P1=--- P0=rwx ] > (gdb) set $por_el0=0xffffffff77777777 > (gdb) info register por_el0 > por_el0 0xffffffff77777777 [ P15=??? P14=??? P13=??? P12=??? P11=??? P10=??? P9=??? P8=??? P7=rwx P6=rwx P5=rwx P4=rwx P3=rwx P2=rwx P1=rwx P0=rwx ] > (gdb) p $por_el0 > $1 = [ P15=??? P14=??? P13=??? P12=??? P11=??? P10=??? P9=??? P8=??? P7=rwx P6=rwx P5=rwx P4=rwx P3=rwx P2=rwx P1=rwx P0=rwx ] > (gdb) p/x $por_el0 > $2 = 0xffffffff77777777 > (gdb) set $por_el0=0x57 > (gdb) info register por_el0 > por_el0 0x57 [ P15=--- P14=--- P13=--- P12=--- P11=--- P10=--- P9=--- P8=--- P7=--- P6=--- P5=--- P4=--- P3=--- P2=--- P1=rw- P0=rwx ] > (gdb) set $por_el0=0xf7f7f7f7f7f7f7f7 > (gdb) info register por_el0 > por_el0 0xf7f7f7f7f7f7f7f7 [ P15=??? P14=rwx P13=??? P12=rwx P11=??? P10=rwx P9=??? P8=rwx P7=??? P6=rwx P5=??? P4=rwx P3=??? P2=rwx P1=??? P0=rwx ] > (gdb) Looking at the output above I think it is a bit hard to read. Have you considered keeping the original register as it is and having pseudo-registers that print appropriately? If a user wants to see, say, P15, it doesn´t help we print everything else along with it. The other alternative is having a python pretty printer that goes alongside the feature. > --- > gdb/Makefile.in | 2 ++ > gdb/aarch64-linux-nat.c | 64 +++++++++++++++++++++++++++++++++ > gdb/aarch64-tdep.c | 23 ++++++++++++ > gdb/aarch64-tdep.h | 10 ++++++ > gdb/arch/aarch64-poe-linux.h | 29 +++++++++++++++ > gdb/arch/aarch64.c | 4 +++ > gdb/arch/aarch64.h | 8 ++++- > gdb/features/Makefile | 1 + > gdb/features/aarch64-poe.c | 68 ++++++++++++++++++++++++++++++++++++ > gdb/features/aarch64-poe.xml | 47 +++++++++++++++++++++++++ > gdb/nat/aarch64-poe-linux.h | 29 +++++++++++++++ > 11 files changed, 284 insertions(+), 1 deletion(-) > create mode 100644 gdb/arch/aarch64-poe-linux.h > create mode 100644 gdb/features/aarch64-poe.c > create mode 100644 gdb/features/aarch64-poe.xml > create mode 100644 gdb/nat/aarch64-poe-linux.h > > diff --git a/gdb/Makefile.in b/gdb/Makefile.in > index 57f384170ab..3dc9cd07dcb 100644 > --- a/gdb/Makefile.in > +++ b/gdb/Makefile.in > @@ -1292,6 +1292,7 @@ HFILES_NO_SRCDIR = \ > arch/aarch32.h \ > arch/aarch64-fpmr-linux.h \ > arch/aarch64-gcs-linux.h \ > + arch/aarch64-poe-linux.h \ > arch/aarch64.h \ > arch/aarch64-insn.h \ > arch/aarch64-mte.h \ > @@ -1540,6 +1541,7 @@ HFILES_NO_SRCDIR = \ > namespace.h \ > nat/aarch64-fpmr-linux.h \ > nat/aarch64-gcs-linux.h \ > + nat/aarch64-poe-linux.h \ > nat/aarch64-hw-point.h \ > nat/aarch64-linux.h \ > nat/aarch64-linux-hw-point.h \ > diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c > index 52ace4aab41..8e29c42908c 100644 > --- a/gdb/aarch64-linux-nat.c > +++ b/gdb/aarch64-linux-nat.c > @@ -34,6 +34,7 @@ > #include "arch/arm.h" > #include "nat/aarch64-fpmr-linux.h" > #include "nat/aarch64-gcs-linux.h" > +#include "nat/aarch64-poe-linux.h" > #include "nat/aarch64-linux.h" > #include "nat/aarch64-linux-hw-point.h" > #include "nat/aarch64-mte-linux-ptrace.h" > @@ -602,6 +603,54 @@ store_gcsregs_to_thread (regcache *regcache) > perror_with_name (_("Unable to store GCS registers")); > } > > +/* Fill GDB's register array with the POE register value from the current > + thread. */ > + > +static void > +fetch_poeregs_from_thread (regcache *regcache) > +{ > + aarch64_gdbarch_tdep *tdep > + = gdbarch_tdep<aarch64_gdbarch_tdep> (regcache->arch ()); > + > + gdb_assert (tdep->has_poe ()); > + > + uint64_t user_poe; > + iovec iovec; > + > + iovec.iov_base = &user_poe; > + iovec.iov_len = sizeof (user_poe); > + > + int tid = get_ptrace_pid (regcache->ptid ()); > + if (ptrace (PTRACE_GETREGSET, tid, NT_ARM_POE, &iovec) != 0) > + perror_with_name (_("Unable to fetch POE register")); > + > + regcache->raw_supply (tdep->poe_regnum, &user_poe); > +} > + > +/* Store the NT_ARM_POE register contents from GDB's REGCACHE to the > + thread associated with REGCACHE. */ > + Nit: Let's keep things consistent register contents or register value. We should pick one and go with it. > +static void > +store_poeregs_to_thread (struct regcache *regcache) > +{ > + aarch64_gdbarch_tdep *tdep > + = gdbarch_tdep<aarch64_gdbarch_tdep> (regcache->arch ()); > + > + gdb_assert (tdep->has_poe ()); > + > + int tid = regcache->ptid ().lwp (); > + > + iovec iovec; > + uint64_t user_poe; > + iovec.iov_base = &user_poe; > + iovec.iov_len = sizeof (user_poe); > + > + regcache->raw_collect (tdep->poe_regnum, &user_poe); > + > + if (ptrace (PTRACE_SETREGSET, tid, NT_ARM_POE, &iovec) != 0) > + perror_with_name (_("Unable to store POE register")); > +} > + > /* Fill GDB's REGCACHE with the FPMR register set content from the > thread associated with REGCACHE. */ > > @@ -683,6 +732,9 @@ aarch64_fetch_registers (struct regcache *regcache, int regno) > if (tdep->has_gcs_linux ()) > fetch_gcsregs_from_thread (regcache); > > + if (tdep->has_poe ()) > + fetch_poeregs_from_thread (regcache); > + > if (tdep->has_fpmr ()) > fetch_fpmr_from_thread (regcache); > } > @@ -722,6 +774,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); > + /* POE register? */ > + else if (tdep->has_poe () && (regno == tdep->poe_regnum)) > + fetch_poeregs_from_thread (regcache); > /* FPMR? */ > else if (tdep->has_fpmr () && (regno == tdep->fpmr_regnum)) > fetch_fpmr_from_thread (regcache); > @@ -802,6 +857,9 @@ aarch64_store_registers (struct regcache *regcache, int regno) > > if (tdep->has_fpmr ()) > store_fpmr_to_thread (regcache); > + > + if (tdep->has_poe ()) > + store_poeregs_to_thread (regcache); > } > /* General purpose register? */ > else if (regno < AARCH64_V0_REGNUM) > @@ -836,6 +894,9 @@ aarch64_store_registers (struct regcache *regcache, int regno) > /* FPMR? */ > else if (tdep->has_fpmr () && regno == tdep->fpmr_regnum) > store_fpmr_to_thread (regcache); > + /* POE register? */ > + else if (tdep->has_poe () && regno == tdep->poe_regnum) > + store_poeregs_to_thread (regcache); > > /* PAuth registers are read-only. */ > } > @@ -1024,6 +1085,9 @@ aarch64_linux_nat_target::read_description () > /* Check for FPMR. */ > features.fpmr = hwcap2 & HWCAP2_FPMR; > > + /* Check for POE support. */ > + features.poe = hwcap2 & HWCAP2_POE; > + > return aarch64_read_description (features); > } > > diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c > index a84da1fd59e..2e86d6e0452 100644 > --- a/gdb/aarch64-tdep.c > +++ b/gdb/aarch64-tdep.c > @@ -164,6 +164,11 @@ static const char *const aarch64_gcs_register_names[] = { > "gcspr" > }; > > +static const char *const aarch64_poe_register_names[] = { > + /* Permission Overlay Extension Register. */ > + "por_el0" > +}; > + > static const char *const aarch64_gcs_linux_register_names[] = { > /* Field in struct user_gcs. */ > "gcs_features_enabled", > @@ -4136,6 +4141,10 @@ aarch64_features_from_target_desc (const struct target_desc *tdesc) > features.fpmr = (tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.fpmr") > != nullptr); > > + /* Check for POE feature. */ > + features.poe = (tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.poe") > + != nullptr); > + > return features; > } > > @@ -4556,6 +4565,19 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) > fpmr_regnum, "fpmr"); > } > > + int poe_regnum = -1; > + const struct tdesc_feature *feature_poe > + = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.poe"); > + if (feature_poe != nullptr) > + { > + poe_regnum = num_regs; > + for (i = 0; i < ARRAY_SIZE (aarch64_poe_register_names); i++) > + valid_p &= tdesc_numbered_register (feature_poe, tdesc_data.get (), > + poe_regnum + i, > + aarch64_poe_register_names[i]); > + num_regs++; > + } > + > int first_sme_regnum = -1; > int first_sme2_regnum = -1; > int first_sme_pseudo_regnum = -1; > @@ -4756,6 +4778,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) > tdep->gcs_reg_base = first_gcs_regnum; > tdep->gcs_linux_reg_base = first_gcs_linux_regnum; > tdep->fpmr_regnum = fpmr_regnum; > + tdep->poe_regnum = poe_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 dff05a08f84..3c5d10beee5 100644 > --- a/gdb/aarch64-tdep.h > +++ b/gdb/aarch64-tdep.h > @@ -208,6 +208,16 @@ struct aarch64_gdbarch_tdep : gdbarch_tdep_base > return gcs_linux_reg_base != -1; > } > > + /* POE register. This is -1 if no POE feature is available. */ > + int poe_regnum = -1; > + > + /* Returns true if the target supports the POE feature. */ > + bool > + has_poe () const > + { > + return poe_regnum != -1; > + } > + > /* First FPMR register. This is -1 if FPMR is not supported. */ > int fpmr_regnum = -1; > > diff --git a/gdb/arch/aarch64-poe-linux.h b/gdb/arch/aarch64-poe-linux.h > new file mode 100644 > index 00000000000..8623fa43b54 > --- /dev/null > +++ b/gdb/arch/aarch64-poe-linux.h > @@ -0,0 +1,29 @@ > +/* Common Linux target-dependent definitions for AArch64 POE > + > + Copyright (C) 2026 Free Software Foundation, Inc. > + > + This file is part of GDB. > + > + 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/>. */ > + > +#ifndef GDB_ARCH_AARCH64_POE_LINUX_H > +#define GDB_ARCH_AARCH64_POE_LINUX_H > + > +/* Feature check for Permission Overlay Extension. */ > +#define AARCH64_HWCAP2_POE (1ULL << 63) > + > +/* Data or instruction abort caused by Protection Key Violation. */ > +#define AARCH64_SEGV_PKUERR 4 Do we have plans to support this in QEMU bare metal by any chance? Just wondering how that would look like. Have you checked with Peter Maydell? > + > +#endif /* GDB_ARCH_AARCH64_POE_LINUX_H. */ > diff --git a/gdb/arch/aarch64.c b/gdb/arch/aarch64.c > index 2401a325b7b..a567938d06d 100644 > --- a/gdb/arch/aarch64.c > +++ b/gdb/arch/aarch64.c > @@ -28,6 +28,7 @@ > #include "../features/aarch64-sme2.c" > #include "../features/aarch64-tls.c" > #include "../features/aarch64-gcs.c" > +#include "../features/aarch64-poe.c" > #include "../features/aarch64-gcs-linux.c" > > /* See arch/aarch64.h. */ > @@ -77,6 +78,9 @@ aarch64_create_target_description (const aarch64_features &features) > if (features.fpmr) > regnum = create_feature_aarch64_fpmr (tdesc.get (), regnum); > > + if (features.poe) > + regnum = create_feature_aarch64_poe (tdesc.get (), regnum); > + > return tdesc; > } > > diff --git a/gdb/arch/aarch64.h b/gdb/arch/aarch64.h > index cf7318cbe74..ba90d55c3bb 100644 > --- a/gdb/arch/aarch64.h > +++ b/gdb/arch/aarch64.h > @@ -35,6 +35,8 @@ struct aarch64_features > bool pauth = false; > bool mte = false; > bool fpmr = false; > + /* Whether the Permission Overlay Extension (FEAT_S1POE) is supported. */ > + bool poe = false; > > /* A positive TLS value indicates the number of TLS registers available. */ > uint8_t tls = 0; > @@ -70,7 +72,8 @@ inline bool operator==(const aarch64_features &lhs, const aarch64_features &rhs) > && lhs.sme2 == rhs.sme2 > && lhs.gcs == rhs.gcs > && lhs.gcs_linux == rhs.gcs_linux > - && lhs.fpmr == rhs.fpmr; > + && lhs.fpmr == rhs.fpmr > + && lhs.poe == rhs.poe; > } > > namespace std > @@ -103,6 +106,9 @@ namespace std > > /* FPMR feature. */ > h = h << 1 | features.fpmr; > + > + /* POE feature. */ > + h = h << 1 | features.poe; > return h; > } > }; > diff --git a/gdb/features/Makefile b/gdb/features/Makefile > index 161a7453d66..cc77e5bb652 100644 > --- a/gdb/features/Makefile > +++ b/gdb/features/Makefile > @@ -207,6 +207,7 @@ FEATURE_XMLFILES = aarch64-core.xml \ > aarch64-pauth.xml \ > aarch64-mte.xml \ > aarch64-gcs.xml \ > + aarch64-poe.xml \ > aarch64-gcs-linux.xml \ > arc/v1-core.xml \ > arc/v1-aux.xml \ > diff --git a/gdb/features/aarch64-poe.c b/gdb/features/aarch64-poe.c > new file mode 100644 > index 00000000000..4bd795e9fe6 > --- /dev/null > +++ b/gdb/features/aarch64-poe.c > @@ -0,0 +1,68 @@ > +/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro: > + Original: aarch64-poe.xml */ > + > +#include "gdbsupport/tdesc.h" > + > +static int > +create_feature_aarch64_poe (struct target_desc *result, long regnum) > +{ > + struct tdesc_feature *feature; > + > + feature = tdesc_create_feature (result, "org.gnu.gdb.aarch64.poe"); > + tdesc_type_with_fields *type_with_fields; > + type_with_fields = tdesc_create_enum (feature, "por_el0_fmt", 4); > + tdesc_add_enum_value (type_with_fields, 0, "---"); > + tdesc_add_enum_value (type_with_fields, 1, "r--"); > + tdesc_add_enum_value (type_with_fields, 2, "--x"); > + tdesc_add_enum_value (type_with_fields, 3, "r-x"); > + tdesc_add_enum_value (type_with_fields, 4, "-w-"); > + tdesc_add_enum_value (type_with_fields, 5, "rw-"); > + tdesc_add_enum_value (type_with_fields, 6, "-wx"); > + tdesc_add_enum_value (type_with_fields, 7, "rwx"); > + tdesc_add_enum_value (type_with_fields, 8, "???"); > + tdesc_add_enum_value (type_with_fields, 9, "???"); > + tdesc_add_enum_value (type_with_fields, 10, "???"); > + tdesc_add_enum_value (type_with_fields, 11, "???"); > + tdesc_add_enum_value (type_with_fields, 12, "???"); > + tdesc_add_enum_value (type_with_fields, 13, "???"); > + tdesc_add_enum_value (type_with_fields, 14, "???"); > + tdesc_add_enum_value (type_with_fields, 15, "???"); I'm not a fan of this. Have we considered alternatives like pseudo-registers that map to/from the raw POR value? It feels like this is working around a gdb deficiency of not having a proper type, and the right way to solve this would be extending gdb in some way. With a pseudo-register all of this would be interiorized in gdb, and we would be left with only the raw POR value of 64 bits. > + > + type_with_fields = tdesc_create_flags (feature, "por_el0_flags", 8); > + tdesc_type *field_type; > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P15", 60, 63, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P14", 56, 59, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P13", 52, 55, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P12", 48, 51, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P11", 44, 47, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P10", 40, 43, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P9", 36, 39, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P8", 32, 35, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P7", 28, 31, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P6", 24, 27, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P5", 20, 23, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P4", 16, 19, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P3", 12, 15, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P2", 8, 11, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P1", 4, 7, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P0", 0, 3, field_type); Likewise for the above. This is hardcoding the interpretation of the individual bitfields into the XML. Maybe Thiago has a different opinion here. > + > + tdesc_create_reg (feature, "por_el0", regnum++, 1, "system", 64, "por_el0_flags"); > + return regnum; > +} > diff --git a/gdb/features/aarch64-poe.xml b/gdb/features/aarch64-poe.xml > new file mode 100644 > index 00000000000..58fc4f80d5c > --- /dev/null > +++ b/gdb/features/aarch64-poe.xml > @@ -0,0 +1,47 @@ > +<?xml version="1.0"?> > +<!-- Copyright (C) 2026 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.poe"> > + <enum id="por_el0_fmt" size="4"> > + <evalue name="---" value="0"/> > + <evalue name="r--" value="1"/> > + <evalue name="--x" value="2"/> > + <evalue name="r-x" value="3"/> > + <evalue name="-w-" value="4"/> > + <evalue name="rw-" value="5"/> > + <evalue name="-wx" value="6"/> > + <evalue name="rwx" value="7"/> > + <evalue name="???" value="8"/> > + <evalue name="???" value="9"/> > + <evalue name="???" value="10"/> > + <evalue name="???" value="11"/> > + <evalue name="???" value="12"/> > + <evalue name="???" value="13"/> > + <evalue name="???" value="14"/> > + <evalue name="???" value="15"/> > + </enum> > + <flags id="por_el0_flags" size="8"> > + <field name="P15" start="60" end="63" type="por_el0_fmt"/> > + <field name="P14" start="56" end="59" type="por_el0_fmt"/> > + <field name="P13" start="52" end="55" type="por_el0_fmt"/> > + <field name="P12" start="48" end="51" type="por_el0_fmt"/> > + <field name="P11" start="44" end="47" type="por_el0_fmt"/> > + <field name="P10" start="40" end="43" type="por_el0_fmt"/> > + <field name="P9" start="36" end="39" type="por_el0_fmt"/> > + <field name="P8" start="32" end="35" type="por_el0_fmt"/> > + <field name="P7" start="28" end="31" type="por_el0_fmt"/> > + <field name="P6" start="24" end="27" type="por_el0_fmt"/> > + <field name="P5" start="20" end="23" type="por_el0_fmt"/> > + <field name="P4" start="16" end="19" type="por_el0_fmt"/> > + <field name="P3" start="12" end="15" type="por_el0_fmt"/> > + <field name="P2" start="8" end="11" type="por_el0_fmt"/> > + <field name="P1" start="4" end="7" type="por_el0_fmt"/> > + <field name="P0" start="0" end="3" type="por_el0_fmt"/> > + </flags> > + <reg name="por_el0" bitsize="64" type="por_el0_flags" group="system"/> > +</feature> > diff --git a/gdb/nat/aarch64-poe-linux.h b/gdb/nat/aarch64-poe-linux.h > new file mode 100644 > index 00000000000..f3d0256da3f > --- /dev/null > +++ b/gdb/nat/aarch64-poe-linux.h > @@ -0,0 +1,29 @@ > +/* Common native Linux definitions for AArch64 Permission Overlay Extension. > + > + Copyright (C) 2026 Free Software Foundation, Inc. > + > + This file is part of GDB. > + > + 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 <asm/hwcap.h> > +#ifndef GDB_NAT_AARCH64_POE_LINUX_H > +#define GDB_NAT_AARCH64_POE_LINUX_H > + > +/* Feature check for Permission Overlay Extension. */ > +#ifndef HWCAP2_POE > +#define HWCAP2_POE (1ULL << 63) > +#endif /* HWCAP2_POE. */ > + > +#endif /* GDB_NAT_AARCH64_POE_LINUX_H. */ ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3 1/5] [PATCH 1/5] gdb/aarch64: Add POR_EL0 register support for FEAT_S1POE 2026-07-21 19:53 ` Luis @ 2026-07-25 6:20 ` Thiago Jung Bauermann 2026-07-25 7:37 ` Luis 0 siblings, 1 reply; 22+ messages in thread From: Thiago Jung Bauermann @ 2026-07-25 6:20 UTC (permalink / raw) To: Luis Cc: srinath.parvathaneni, gdb-patches, guinevere, Ezra.Sitorus, Matthieu.Longo, simark, Peter Maydell Luis <luis.machado.foss@gmail.com> writes: > On 14/07/2026 21:15, srinath.parvathaneni@arm.com wrote: >> From: Srinath Parvathaneni <srinath.parvathaneni@arm.com> >> Add support for the FEAT_S1POE POR_EL0 register on AArch64. >> This patch adds POR_EL0 to the AArch64 register set and reads/writes it >> using the NT_ARM_POE ptrace regset. > > Just a general comment, but por_el0 is unfortunate naming for a userspace register. But > alas, it's been done that way in the Linux kernel as far as I can tell. Do you mean the _el0 suffix? We had a discussion about it here: https://inbox.sourceware.org/gdb-patches/87a4sgikk4.fsf@linaro.org/ Srinath responded: > That said, after discussing this with kernel/KVM developers, there are valid > debugging scenarios (e.g. KGDB or guest debugging via KVM/QEMU) where exposing > `POR_EL0`, `POR_EL1`, and `POR_EL2` simultaneously would be useful. This seems > like a broader GDB register naming issue rather than something specific to > FEAT_S1POE. And Marc Zyngier too: > It would certainly make our life easier if GDB was in general adopting > the architecture nomenclature. > > It is probably fine to have a "shorthand" such as POR for POR_EL0, but > I'd like to make sure that it is possible to unambiguously target the > correct register for the cases where we have to debug a full guest > (which is something people actively do using the QEMU GDB stubs). So as Marc says perhaps we could have an alias por for por_el0, like we have lr for x30, or (in the other direction) x31 for sp? >> diff --git a/gdb/features/aarch64-poe.c b/gdb/features/aarch64-poe.c >> new file mode 100644 >> index 00000000000..4bd795e9fe6 >> --- /dev/null >> +++ b/gdb/features/aarch64-poe.c >> @@ -0,0 +1,68 @@ >> +/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro: >> + Original: aarch64-poe.xml */ >> + >> +#include "gdbsupport/tdesc.h" >> + >> +static int >> +create_feature_aarch64_poe (struct target_desc *result, long regnum) >> +{ >> + struct tdesc_feature *feature; >> + >> + feature = tdesc_create_feature (result, "org.gnu.gdb.aarch64.poe"); >> + tdesc_type_with_fields *type_with_fields; >> + type_with_fields = tdesc_create_enum (feature, "por_el0_fmt", 4); >> + tdesc_add_enum_value (type_with_fields, 0, "---"); >> + tdesc_add_enum_value (type_with_fields, 1, "r--"); >> + tdesc_add_enum_value (type_with_fields, 2, "--x"); >> + tdesc_add_enum_value (type_with_fields, 3, "r-x"); >> + tdesc_add_enum_value (type_with_fields, 4, "-w-"); >> + tdesc_add_enum_value (type_with_fields, 5, "rw-"); >> + tdesc_add_enum_value (type_with_fields, 6, "-wx"); >> + tdesc_add_enum_value (type_with_fields, 7, "rwx"); >> + tdesc_add_enum_value (type_with_fields, 8, "???"); >> + tdesc_add_enum_value (type_with_fields, 9, "???"); >> + tdesc_add_enum_value (type_with_fields, 10, "???"); >> + tdesc_add_enum_value (type_with_fields, 11, "???"); >> + tdesc_add_enum_value (type_with_fields, 12, "???"); >> + tdesc_add_enum_value (type_with_fields, 13, "???"); >> + tdesc_add_enum_value (type_with_fields, 14, "???"); >> + tdesc_add_enum_value (type_with_fields, 15, "???"); > > I'm not a fan of this. Have we considered alternatives like pseudo-registers that map > to/from the raw POR value? > > It feels like this is working around a gdb deficiency of not having a proper type, and the > right way to solve this would be extending gdb in some way. > > With a pseudo-register all of this would be interiorized in gdb, and we would be left with > only the raw POR value of 64 bits. > >> + >> + type_with_fields = tdesc_create_flags (feature, "por_el0_flags", 8); >> + tdesc_type *field_type; >> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >> + tdesc_add_typed_bitfield (type_with_fields, "P15", 60, 63, field_type); >> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >> + tdesc_add_typed_bitfield (type_with_fields, "P14", 56, 59, field_type); >> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >> + tdesc_add_typed_bitfield (type_with_fields, "P13", 52, 55, field_type); >> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >> + tdesc_add_typed_bitfield (type_with_fields, "P12", 48, 51, field_type); >> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >> + tdesc_add_typed_bitfield (type_with_fields, "P11", 44, 47, field_type); >> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >> + tdesc_add_typed_bitfield (type_with_fields, "P10", 40, 43, field_type); >> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >> + tdesc_add_typed_bitfield (type_with_fields, "P9", 36, 39, field_type); >> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >> + tdesc_add_typed_bitfield (type_with_fields, "P8", 32, 35, field_type); >> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >> + tdesc_add_typed_bitfield (type_with_fields, "P7", 28, 31, field_type); >> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >> + tdesc_add_typed_bitfield (type_with_fields, "P6", 24, 27, field_type); >> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >> + tdesc_add_typed_bitfield (type_with_fields, "P5", 20, 23, field_type); >> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >> + tdesc_add_typed_bitfield (type_with_fields, "P4", 16, 19, field_type); >> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >> + tdesc_add_typed_bitfield (type_with_fields, "P3", 12, 15, field_type); >> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >> + tdesc_add_typed_bitfield (type_with_fields, "P2", 8, 11, field_type); >> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >> + tdesc_add_typed_bitfield (type_with_fields, "P1", 4, 7, field_type); >> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >> + tdesc_add_typed_bitfield (type_with_fields, "P0", 0, 3, field_type); > > Likewise for the above. This is hardcoding the interpretation of the individual bitfields > into the XML. > > Maybe Thiago has a different opinion here. The interpretation is fixed by the architecture, so hardcoding it makes sense IMHO. But I don't feel strongly about this. -- Thiago (he/him) ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3 1/5] [PATCH 1/5] gdb/aarch64: Add POR_EL0 register support for FEAT_S1POE 2026-07-25 6:20 ` Thiago Jung Bauermann @ 2026-07-25 7:37 ` Luis 2026-07-25 18:44 ` Thiago Jung Bauermann 0 siblings, 1 reply; 22+ messages in thread From: Luis @ 2026-07-25 7:37 UTC (permalink / raw) To: Thiago Jung Bauermann Cc: srinath.parvathaneni, gdb-patches, guinevere, Ezra.Sitorus, Matthieu.Longo, simark, Peter Maydell On 25/07/2026 07:20, Thiago Jung Bauermann wrote: > Luis <luis.machado.foss@gmail.com> writes: > >> On 14/07/2026 21:15, srinath.parvathaneni@arm.com wrote: >>> From: Srinath Parvathaneni <srinath.parvathaneni@arm.com> >>> Add support for the FEAT_S1POE POR_EL0 register on AArch64. >>> This patch adds POR_EL0 to the AArch64 register set and reads/writes it >>> using the NT_ARM_POE ptrace regset. >> >> Just a general comment, but por_el0 is unfortunate naming for a userspace register. But >> alas, it's been done that way in the Linux kernel as far as I can tell. > > Do you mean the _el0 suffix? We had a discussion about it here: > > https://inbox.sourceware.org/gdb-patches/87a4sgikk4.fsf@linaro.org/ > > Srinath responded: > >> That said, after discussing this with kernel/KVM developers, there are valid >> debugging scenarios (e.g. KGDB or guest debugging via KVM/QEMU) where exposing >> `POR_EL0`, `POR_EL1`, and `POR_EL2` simultaneously would be useful. This seems >> like a broader GDB register naming issue rather than something specific to >> FEAT_S1POE. > > And Marc Zyngier too: > >> It would certainly make our life easier if GDB was in general adopting >> the architecture nomenclature. >> >> It is probably fine to have a "shorthand" such as POR for POR_EL0, but >> I'd like to make sure that it is possible to unambiguously target the >> correct register for the cases where we have to debug a full guest >> (which is something people actively do using the QEMU GDB stubs). > > So as Marc says perhaps we could have an alias por for por_el0, like we > have lr for x30, or (in the other direction) x31 for sp? > Naming registers after their architectural names is fine as long as they're really exposed as their architectural selves. Sometimes we don't get exposed purely architectural registers via ptrace, so it would be a bit confusing to do that. If we have plans to support QEMU bare metal, using the architectural name also makes sense. >>> diff --git a/gdb/features/aarch64-poe.c b/gdb/features/aarch64-poe.c >>> new file mode 100644 >>> index 00000000000..4bd795e9fe6 >>> --- /dev/null >>> +++ b/gdb/features/aarch64-poe.c >>> @@ -0,0 +1,68 @@ >>> +/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro: >>> + Original: aarch64-poe.xml */ >>> + >>> +#include "gdbsupport/tdesc.h" >>> + >>> +static int >>> +create_feature_aarch64_poe (struct target_desc *result, long regnum) >>> +{ >>> + struct tdesc_feature *feature; >>> + >>> + feature = tdesc_create_feature (result, "org.gnu.gdb.aarch64.poe"); >>> + tdesc_type_with_fields *type_with_fields; >>> + type_with_fields = tdesc_create_enum (feature, "por_el0_fmt", 4); >>> + tdesc_add_enum_value (type_with_fields, 0, "---"); >>> + tdesc_add_enum_value (type_with_fields, 1, "r--"); >>> + tdesc_add_enum_value (type_with_fields, 2, "--x"); >>> + tdesc_add_enum_value (type_with_fields, 3, "r-x"); >>> + tdesc_add_enum_value (type_with_fields, 4, "-w-"); >>> + tdesc_add_enum_value (type_with_fields, 5, "rw-"); >>> + tdesc_add_enum_value (type_with_fields, 6, "-wx"); >>> + tdesc_add_enum_value (type_with_fields, 7, "rwx"); >>> + tdesc_add_enum_value (type_with_fields, 8, "???"); >>> + tdesc_add_enum_value (type_with_fields, 9, "???"); >>> + tdesc_add_enum_value (type_with_fields, 10, "???"); >>> + tdesc_add_enum_value (type_with_fields, 11, "???"); >>> + tdesc_add_enum_value (type_with_fields, 12, "???"); >>> + tdesc_add_enum_value (type_with_fields, 13, "???"); >>> + tdesc_add_enum_value (type_with_fields, 14, "???"); >>> + tdesc_add_enum_value (type_with_fields, 15, "???"); >> >> I'm not a fan of this. Have we considered alternatives like pseudo-registers that map >> to/from the raw POR value? >> >> It feels like this is working around a gdb deficiency of not having a proper type, and the >> right way to solve this would be extending gdb in some way. >> >> With a pseudo-register all of this would be interiorized in gdb, and we would be left with >> only the raw POR value of 64 bits. >> >>> + >>> + type_with_fields = tdesc_create_flags (feature, "por_el0_flags", 8); >>> + tdesc_type *field_type; >>> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >>> + tdesc_add_typed_bitfield (type_with_fields, "P15", 60, 63, field_type); >>> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >>> + tdesc_add_typed_bitfield (type_with_fields, "P14", 56, 59, field_type); >>> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >>> + tdesc_add_typed_bitfield (type_with_fields, "P13", 52, 55, field_type); >>> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >>> + tdesc_add_typed_bitfield (type_with_fields, "P12", 48, 51, field_type); >>> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >>> + tdesc_add_typed_bitfield (type_with_fields, "P11", 44, 47, field_type); >>> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >>> + tdesc_add_typed_bitfield (type_with_fields, "P10", 40, 43, field_type); >>> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >>> + tdesc_add_typed_bitfield (type_with_fields, "P9", 36, 39, field_type); >>> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >>> + tdesc_add_typed_bitfield (type_with_fields, "P8", 32, 35, field_type); >>> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >>> + tdesc_add_typed_bitfield (type_with_fields, "P7", 28, 31, field_type); >>> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >>> + tdesc_add_typed_bitfield (type_with_fields, "P6", 24, 27, field_type); >>> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >>> + tdesc_add_typed_bitfield (type_with_fields, "P5", 20, 23, field_type); >>> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >>> + tdesc_add_typed_bitfield (type_with_fields, "P4", 16, 19, field_type); >>> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >>> + tdesc_add_typed_bitfield (type_with_fields, "P3", 12, 15, field_type); >>> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >>> + tdesc_add_typed_bitfield (type_with_fields, "P2", 8, 11, field_type); >>> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >>> + tdesc_add_typed_bitfield (type_with_fields, "P1", 4, 7, field_type); >>> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >>> + tdesc_add_typed_bitfield (type_with_fields, "P0", 0, 3, field_type); >> >> Likewise for the above. This is hardcoding the interpretation of the individual bitfields >> into the XML. >> >> Maybe Thiago has a different opinion here. > > The interpretation is fixed by the architecture, so hardcoding it makes > sense IMHO. But I don't feel strongly about this. > Sorry, I wasn´t clear in my comment. The interpretation of the bits is dictated by the architecture, but does it also require us to expose the raw register as a segmented view with withP<0-15> entries? The last part seems more like a visualization aid to me, and that could be handled internally by gdb instead of via XML. ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3 1/5] [PATCH 1/5] gdb/aarch64: Add POR_EL0 register support for FEAT_S1POE 2026-07-25 7:37 ` Luis @ 2026-07-25 18:44 ` Thiago Jung Bauermann 0 siblings, 0 replies; 22+ messages in thread From: Thiago Jung Bauermann @ 2026-07-25 18:44 UTC (permalink / raw) To: Luis Cc: srinath.parvathaneni, gdb-patches, guinevere, Ezra.Sitorus, Matthieu.Longo, simark, Peter Maydell Luis <luis.machado.foss@gmail.com> writes: > On 25/07/2026 07:20, Thiago Jung Bauermann wrote: >> Luis <luis.machado.foss@gmail.com> writes: >> >>> On 14/07/2026 21:15, srinath.parvathaneni@arm.com wrote: >>>> From: Srinath Parvathaneni <srinath.parvathaneni@arm.com> >>>> Add support for the FEAT_S1POE POR_EL0 register on AArch64. >>>> This patch adds POR_EL0 to the AArch64 register set and reads/writes it >>>> using the NT_ARM_POE ptrace regset. >>> >>> Just a general comment, but por_el0 is unfortunate naming for a userspace register. But >>> alas, it's been done that way in the Linux kernel as far as I can tell. >> Do you mean the _el0 suffix? We had a discussion about it here: >> https://inbox.sourceware.org/gdb-patches/87a4sgikk4.fsf@linaro.org/ >> Srinath responded: >> >>> That said, after discussing this with kernel/KVM developers, there are valid >>> debugging scenarios (e.g. KGDB or guest debugging via KVM/QEMU) where exposing >>> `POR_EL0`, `POR_EL1`, and `POR_EL2` simultaneously would be useful. This seems >>> like a broader GDB register naming issue rather than something specific to >>> FEAT_S1POE. >> And Marc Zyngier too: >> >>> It would certainly make our life easier if GDB was in general adopting >>> the architecture nomenclature. >>> >>> It is probably fine to have a "shorthand" such as POR for POR_EL0, but >>> I'd like to make sure that it is possible to unambiguously target the >>> correct register for the cases where we have to debug a full guest >>> (which is something people actively do using the QEMU GDB stubs). >> So as Marc says perhaps we could have an alias por for por_el0, like we >> have lr for x30, or (in the other direction) x31 for sp? >> > > Naming registers after their architectural names is fine as long as they're really exposed > as their architectural selves. Sometimes we don't get exposed purely architectural > registers via ptrace, so it would be a bit confusing to do that. Ah, now I got it. Yes, I agree. > If we have plans to support QEMU bare metal, using the architectural name also makes > sense. Agreed. >>>> diff --git a/gdb/features/aarch64-poe.c b/gdb/features/aarch64-poe.c >>>> new file mode 100644 >>>> index 00000000000..4bd795e9fe6 >>>> --- /dev/null >>>> +++ b/gdb/features/aarch64-poe.c >>>> @@ -0,0 +1,68 @@ >>>> +/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro: >>>> + Original: aarch64-poe.xml */ >>>> + >>>> +#include "gdbsupport/tdesc.h" >>>> + >>>> +static int >>>> +create_feature_aarch64_poe (struct target_desc *result, long regnum) >>>> +{ >>>> + struct tdesc_feature *feature; >>>> + >>>> + feature = tdesc_create_feature (result, "org.gnu.gdb.aarch64.poe"); >>>> + tdesc_type_with_fields *type_with_fields; >>>> + type_with_fields = tdesc_create_enum (feature, "por_el0_fmt", 4); >>>> + tdesc_add_enum_value (type_with_fields, 0, "---"); >>>> + tdesc_add_enum_value (type_with_fields, 1, "r--"); >>>> + tdesc_add_enum_value (type_with_fields, 2, "--x"); >>>> + tdesc_add_enum_value (type_with_fields, 3, "r-x"); >>>> + tdesc_add_enum_value (type_with_fields, 4, "-w-"); >>>> + tdesc_add_enum_value (type_with_fields, 5, "rw-"); >>>> + tdesc_add_enum_value (type_with_fields, 6, "-wx"); >>>> + tdesc_add_enum_value (type_with_fields, 7, "rwx"); >>>> + tdesc_add_enum_value (type_with_fields, 8, "???"); >>>> + tdesc_add_enum_value (type_with_fields, 9, "???"); >>>> + tdesc_add_enum_value (type_with_fields, 10, "???"); >>>> + tdesc_add_enum_value (type_with_fields, 11, "???"); >>>> + tdesc_add_enum_value (type_with_fields, 12, "???"); >>>> + tdesc_add_enum_value (type_with_fields, 13, "???"); >>>> + tdesc_add_enum_value (type_with_fields, 14, "???"); >>>> + tdesc_add_enum_value (type_with_fields, 15, "???"); >>> >>> I'm not a fan of this. Have we considered alternatives like pseudo-registers that map >>> to/from the raw POR value? >>> >>> It feels like this is working around a gdb deficiency of not having a proper type, and >>> the >>> right way to solve this would be extending gdb in some way. >>> >>> With a pseudo-register all of this would be interiorized in gdb, and we would be left >>> with >>> only the raw POR value of 64 bits. >>> >>>> + >>>> + type_with_fields = tdesc_create_flags (feature, "por_el0_flags", 8); >>>> + tdesc_type *field_type; >>>> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >>>> + tdesc_add_typed_bitfield (type_with_fields, "P15", 60, 63, field_type); >>>> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >>>> + tdesc_add_typed_bitfield (type_with_fields, "P14", 56, 59, field_type); >>>> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >>>> + tdesc_add_typed_bitfield (type_with_fields, "P13", 52, 55, field_type); >>>> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >>>> + tdesc_add_typed_bitfield (type_with_fields, "P12", 48, 51, field_type); >>>> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >>>> + tdesc_add_typed_bitfield (type_with_fields, "P11", 44, 47, field_type); >>>> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >>>> + tdesc_add_typed_bitfield (type_with_fields, "P10", 40, 43, field_type); >>>> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >>>> + tdesc_add_typed_bitfield (type_with_fields, "P9", 36, 39, field_type); >>>> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >>>> + tdesc_add_typed_bitfield (type_with_fields, "P8", 32, 35, field_type); >>>> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >>>> + tdesc_add_typed_bitfield (type_with_fields, "P7", 28, 31, field_type); >>>> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >>>> + tdesc_add_typed_bitfield (type_with_fields, "P6", 24, 27, field_type); >>>> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >>>> + tdesc_add_typed_bitfield (type_with_fields, "P5", 20, 23, field_type); >>>> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >>>> + tdesc_add_typed_bitfield (type_with_fields, "P4", 16, 19, field_type); >>>> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >>>> + tdesc_add_typed_bitfield (type_with_fields, "P3", 12, 15, field_type); >>>> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >>>> + tdesc_add_typed_bitfield (type_with_fields, "P2", 8, 11, field_type); >>>> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >>>> + tdesc_add_typed_bitfield (type_with_fields, "P1", 4, 7, field_type); >>>> + field_type = tdesc_named_type (feature, "por_el0_fmt"); >>>> + tdesc_add_typed_bitfield (type_with_fields, "P0", 0, 3, field_type); >>> >>> Likewise for the above. This is hardcoding the interpretation of the individual bitfields >>> into the XML. >>> >>> Maybe Thiago has a different opinion here. >> The interpretation is fixed by the architecture, so hardcoding it makes >> sense IMHO. But I don't feel strongly about this. >> > > Sorry, I wasn´t clear in my comment. The interpretation of the bits is dictated by the > architecture, but does it also require us to expose the raw register as a segmented view > with withP<0-15> entries? > > The last part seems more like a visualization aid to me, and that could be handled > internally by gdb instead of via XML. Ah, understood. Now (and having read your other email) I see what you mean with using pseudo-registers. Indeed having pseudo-registers to access individual protection keys sounds like a good idea if we expcet users to want to do that. -- Thiago (he/him) ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3 1/5] [PATCH 1/5] gdb/aarch64: Add POR_EL0 register support for FEAT_S1POE 2026-07-14 20:15 ` [PATCH v3 1/5] [PATCH 1/5] " srinath.parvathaneni 2026-07-21 19:53 ` Luis @ 2026-07-21 20:25 ` Luis 2026-07-23 9:29 ` Srinath Parvathaneni 1 sibling, 1 reply; 22+ messages in thread From: Luis @ 2026-07-21 20:25 UTC (permalink / raw) To: srinath.parvathaneni, gdb-patches Cc: guinevere, thiago.bauermann, Ezra.Sitorus, Matthieu.Longo, simark Sorry, missed some... On 14/07/2026 21:15, srinath.parvathaneni@arm.com wrote: > From: Srinath Parvathaneni <srinath.parvathaneni@arm.com> > > Add support for the FEAT_S1POE POR_EL0 register on AArch64. > > This patch adds POR_EL0 to the AArch64 register set and reads/writes it > using the NT_ARM_POE ptrace regset. > > With this change, POR_EL0 is available through: > * info registers > * info registers por_el0 > * p $por_el0 > * p/x $por_el0 > * set $por_el0 = <value> > > Example: > (gdb) info register por_el0 > por_el0 0x7 [ P15=--- P14=--- P13=--- P12=--- P11=--- P10=--- P9=--- P8=--- P7=--- P6=--- P5=--- P4=--- P3=--- P2=--- P1=--- P0=rwx ] > (gdb) set $por_el0=0xffffffff77777777 > (gdb) info register por_el0 > por_el0 0xffffffff77777777 [ P15=??? P14=??? P13=??? P12=??? P11=??? P10=??? P9=??? P8=??? P7=rwx P6=rwx P5=rwx P4=rwx P3=rwx P2=rwx P1=rwx P0=rwx ] > (gdb) p $por_el0 > $1 = [ P15=??? P14=??? P13=??? P12=??? P11=??? P10=??? P9=??? P8=??? P7=rwx P6=rwx P5=rwx P4=rwx P3=rwx P2=rwx P1=rwx P0=rwx ] > (gdb) p/x $por_el0 > $2 = 0xffffffff77777777 > (gdb) set $por_el0=0x57 > (gdb) info register por_el0 > por_el0 0x57 [ P15=--- P14=--- P13=--- P12=--- P11=--- P10=--- P9=--- P8=--- P7=--- P6=--- P5=--- P4=--- P3=--- P2=--- P1=rw- P0=rwx ] > (gdb) set $por_el0=0xf7f7f7f7f7f7f7f7 > (gdb) info register por_el0 > por_el0 0xf7f7f7f7f7f7f7f7 [ P15=??? P14=rwx P13=??? P12=rwx P11=??? P10=rwx P9=??? P8=rwx P7=??? P6=rwx P5=??? P4=rwx P3=??? P2=rwx P1=??? P0=rwx ] > (gdb) > --- > gdb/Makefile.in | 2 ++ > gdb/aarch64-linux-nat.c | 64 +++++++++++++++++++++++++++++++++ > gdb/aarch64-tdep.c | 23 ++++++++++++ > gdb/aarch64-tdep.h | 10 ++++++ > gdb/arch/aarch64-poe-linux.h | 29 +++++++++++++++ > gdb/arch/aarch64.c | 4 +++ > gdb/arch/aarch64.h | 8 ++++- > gdb/features/Makefile | 1 + > gdb/features/aarch64-poe.c | 68 ++++++++++++++++++++++++++++++++++++ > gdb/features/aarch64-poe.xml | 47 +++++++++++++++++++++++++ > gdb/nat/aarch64-poe-linux.h | 29 +++++++++++++++ > 11 files changed, 284 insertions(+), 1 deletion(-) > create mode 100644 gdb/arch/aarch64-poe-linux.h > create mode 100644 gdb/features/aarch64-poe.c > create mode 100644 gdb/features/aarch64-poe.xml > create mode 100644 gdb/nat/aarch64-poe-linux.h > > diff --git a/gdb/Makefile.in b/gdb/Makefile.in > index 57f384170ab..3dc9cd07dcb 100644 > --- a/gdb/Makefile.in > +++ b/gdb/Makefile.in > @@ -1292,6 +1292,7 @@ HFILES_NO_SRCDIR = \ > arch/aarch32.h \ > arch/aarch64-fpmr-linux.h \ > arch/aarch64-gcs-linux.h \ > + arch/aarch64-poe-linux.h \ > arch/aarch64.h \ > arch/aarch64-insn.h \ > arch/aarch64-mte.h \ > @@ -1540,6 +1541,7 @@ HFILES_NO_SRCDIR = \ > namespace.h \ > nat/aarch64-fpmr-linux.h \ > nat/aarch64-gcs-linux.h \ > + nat/aarch64-poe-linux.h \ > nat/aarch64-hw-point.h \ > nat/aarch64-linux.h \ > nat/aarch64-linux-hw-point.h \ Let's keep these entries sorted alphabetically. > diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c > index 52ace4aab41..8e29c42908c 100644 > --- a/gdb/aarch64-linux-nat.c > +++ b/gdb/aarch64-linux-nat.c > @@ -34,6 +34,7 @@ > #include "arch/arm.h" > #include "nat/aarch64-fpmr-linux.h" > #include "nat/aarch64-gcs-linux.h" > +#include "nat/aarch64-poe-linux.h" > #include "nat/aarch64-linux.h" > #include "nat/aarch64-linux-hw-point.h" > #include "nat/aarch64-mte-linux-ptrace.h" > @@ -602,6 +603,54 @@ store_gcsregs_to_thread (regcache *regcache) > perror_with_name (_("Unable to store GCS registers")); > } > > +/* Fill GDB's register array with the POE register value from the current > + thread. */ > + > +static void > +fetch_poeregs_from_thread (regcache *regcache) > +{ > + aarch64_gdbarch_tdep *tdep > + = gdbarch_tdep<aarch64_gdbarch_tdep> (regcache->arch ()); > + > + gdb_assert (tdep->has_poe ()); > + > + uint64_t user_poe; > + iovec iovec; > + > + iovec.iov_base = &user_poe; > + iovec.iov_len = sizeof (user_poe); > + > + int tid = get_ptrace_pid (regcache->ptid ()); > + if (ptrace (PTRACE_GETREGSET, tid, NT_ARM_POE, &iovec) != 0) > + perror_with_name (_("Unable to fetch POE register")); > + > + regcache->raw_supply (tdep->poe_regnum, &user_poe); > +} > + > +/* Store the NT_ARM_POE register contents from GDB's REGCACHE to the > + thread associated with REGCACHE. */ wront identation above. > + > +static void > +store_poeregs_to_thread (struct regcache *regcache) > +{ > + aarch64_gdbarch_tdep *tdep > + = gdbarch_tdep<aarch64_gdbarch_tdep> (regcache->arch ()); > + > + gdb_assert (tdep->has_poe ()); > + > + int tid = regcache->ptid ().lwp (); > + > + iovec iovec; > + uint64_t user_poe; > + iovec.iov_base = &user_poe; > + iovec.iov_len = sizeof (user_poe); > + > + regcache->raw_collect (tdep->poe_regnum, &user_poe); > + > + if (ptrace (PTRACE_SETREGSET, tid, NT_ARM_POE, &iovec) != 0) > + perror_with_name (_("Unable to store POE register")); > +} > + > /* Fill GDB's REGCACHE with the FPMR register set content from the > thread associated with REGCACHE. */ > > @@ -683,6 +732,9 @@ aarch64_fetch_registers (struct regcache *regcache, int regno) > if (tdep->has_gcs_linux ()) > fetch_gcsregs_from_thread (regcache); > > + if (tdep->has_poe ()) > + fetch_poeregs_from_thread (regcache); > + > if (tdep->has_fpmr ()) > fetch_fpmr_from_thread (regcache); > } > @@ -722,6 +774,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); > + /* POE register? */ > + else if (tdep->has_poe () && (regno == tdep->poe_regnum)) > + fetch_poeregs_from_thread (regcache); > /* FPMR? */ > else if (tdep->has_fpmr () && (regno == tdep->fpmr_regnum)) > fetch_fpmr_from_thread (regcache); > @@ -802,6 +857,9 @@ aarch64_store_registers (struct regcache *regcache, int regno) > > if (tdep->has_fpmr ()) > store_fpmr_to_thread (regcache); > + > + if (tdep->has_poe ()) > + store_poeregs_to_thread (regcache); > } > /* General purpose register? */ > else if (regno < AARCH64_V0_REGNUM) > @@ -836,6 +894,9 @@ aarch64_store_registers (struct regcache *regcache, int regno) > /* FPMR? */ > else if (tdep->has_fpmr () && regno == tdep->fpmr_regnum) > store_fpmr_to_thread (regcache); > + /* POE register? */ > + else if (tdep->has_poe () && regno == tdep->poe_regnum) > + store_poeregs_to_thread (regcache); > > /* PAuth registers are read-only. */ > } > @@ -1024,6 +1085,9 @@ aarch64_linux_nat_target::read_description () > /* Check for FPMR. */ > features.fpmr = hwcap2 & HWCAP2_FPMR; > > + /* Check for POE support. */ > + features.poe = hwcap2 & HWCAP2_POE; > + > return aarch64_read_description (features); > } > > diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c > index a84da1fd59e..2e86d6e0452 100644 > --- a/gdb/aarch64-tdep.c > +++ b/gdb/aarch64-tdep.c > @@ -164,6 +164,11 @@ static const char *const aarch64_gcs_register_names[] = { > "gcspr" > }; > > +static const char *const aarch64_poe_register_names[] = { > + /* Permission Overlay Extension Register. */ > + "por_el0" > +}; > + > static const char *const aarch64_gcs_linux_register_names[] = { > /* Field in struct user_gcs. */ > "gcs_features_enabled", > @@ -4136,6 +4141,10 @@ aarch64_features_from_target_desc (const struct target_desc *tdesc) > features.fpmr = (tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.fpmr") > != nullptr); > > + /* Check for POE feature. */ > + features.poe = (tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.poe") > + != nullptr); > + > return features; > } > > @@ -4556,6 +4565,19 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) > fpmr_regnum, "fpmr"); > } > > + int poe_regnum = -1; > + const struct tdesc_feature *feature_poe > + = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.poe"); > + if (feature_poe != nullptr) > + { > + poe_regnum = num_regs; > + for (i = 0; i < ARRAY_SIZE (aarch64_poe_register_names); i++) > + valid_p &= tdesc_numbered_register (feature_poe, tdesc_data.get (), > + poe_regnum + i, > + aarch64_poe_register_names[i]); > + num_regs++; > + } > + > int first_sme_regnum = -1; > int first_sme2_regnum = -1; > int first_sme_pseudo_regnum = -1; > @@ -4756,6 +4778,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) > tdep->gcs_reg_base = first_gcs_regnum; > tdep->gcs_linux_reg_base = first_gcs_linux_regnum; > tdep->fpmr_regnum = fpmr_regnum; > + tdep->poe_regnum = poe_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 dff05a08f84..3c5d10beee5 100644 > --- a/gdb/aarch64-tdep.h > +++ b/gdb/aarch64-tdep.h > @@ -208,6 +208,16 @@ struct aarch64_gdbarch_tdep : gdbarch_tdep_base > return gcs_linux_reg_base != -1; > } > > + /* POE register. This is -1 if no POE feature is available. */ > + int poe_regnum = -1; > + > + /* Returns true if the target supports the POE feature. */ > + bool > + has_poe () const > + { > + return poe_regnum != -1; > + } > + > /* First FPMR register. This is -1 if FPMR is not supported. */ > int fpmr_regnum = -1; > > diff --git a/gdb/arch/aarch64-poe-linux.h b/gdb/arch/aarch64-poe-linux.h > new file mode 100644 > index 00000000000..8623fa43b54 > --- /dev/null > +++ b/gdb/arch/aarch64-poe-linux.h > @@ -0,0 +1,29 @@ > +/* Common Linux target-dependent definitions for AArch64 POE > + > + Copyright (C) 2026 Free Software Foundation, Inc. > + > + This file is part of GDB. > + > + 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/>. */ > + > +#ifndef GDB_ARCH_AARCH64_POE_LINUX_H > +#define GDB_ARCH_AARCH64_POE_LINUX_H > + > +/* Feature check for Permission Overlay Extension. */ > +#define AARCH64_HWCAP2_POE (1ULL << 63) > + > +/* Data or instruction abort caused by Protection Key Violation. */ > +#define AARCH64_SEGV_PKUERR 4 > + > +#endif /* GDB_ARCH_AARCH64_POE_LINUX_H. */ > diff --git a/gdb/arch/aarch64.c b/gdb/arch/aarch64.c > index 2401a325b7b..a567938d06d 100644 > --- a/gdb/arch/aarch64.c > +++ b/gdb/arch/aarch64.c > @@ -28,6 +28,7 @@ > #include "../features/aarch64-sme2.c" > #include "../features/aarch64-tls.c" > #include "../features/aarch64-gcs.c" > +#include "../features/aarch64-poe.c" > #include "../features/aarch64-gcs-linux.c" > > /* See arch/aarch64.h. */ > @@ -77,6 +78,9 @@ aarch64_create_target_description (const aarch64_features &features) > if (features.fpmr) > regnum = create_feature_aarch64_fpmr (tdesc.get (), regnum); > > + if (features.poe) > + regnum = create_feature_aarch64_poe (tdesc.get (), regnum); > + > return tdesc; > } > > diff --git a/gdb/arch/aarch64.h b/gdb/arch/aarch64.h > index cf7318cbe74..ba90d55c3bb 100644 > --- a/gdb/arch/aarch64.h > +++ b/gdb/arch/aarch64.h > @@ -35,6 +35,8 @@ struct aarch64_features > bool pauth = false; > bool mte = false; > bool fpmr = false; > + /* Whether the Permission Overlay Extension (FEAT_S1POE) is supported. */ > + bool poe = false; > > /* A positive TLS value indicates the number of TLS registers available. */ > uint8_t tls = 0; > @@ -70,7 +72,8 @@ inline bool operator==(const aarch64_features &lhs, const aarch64_features &rhs) > && lhs.sme2 == rhs.sme2 > && lhs.gcs == rhs.gcs > && lhs.gcs_linux == rhs.gcs_linux > - && lhs.fpmr == rhs.fpmr; > + && lhs.fpmr == rhs.fpmr > + && lhs.poe == rhs.poe; > } > > namespace std > @@ -103,6 +106,9 @@ namespace std > > /* FPMR feature. */ > h = h << 1 | features.fpmr; > + > + /* POE feature. */ > + h = h << 1 | features.poe; > return h; > } > }; > diff --git a/gdb/features/Makefile b/gdb/features/Makefile > index 161a7453d66..cc77e5bb652 100644 > --- a/gdb/features/Makefile > +++ b/gdb/features/Makefile > @@ -207,6 +207,7 @@ FEATURE_XMLFILES = aarch64-core.xml \ > aarch64-pauth.xml \ > aarch64-mte.xml \ > aarch64-gcs.xml \ > + aarch64-poe.xml \ > aarch64-gcs-linux.xml \ > arc/v1-core.xml \ > arc/v1-aux.xml \ > diff --git a/gdb/features/aarch64-poe.c b/gdb/features/aarch64-poe.c > new file mode 100644 > index 00000000000..4bd795e9fe6 > --- /dev/null > +++ b/gdb/features/aarch64-poe.c > @@ -0,0 +1,68 @@ > +/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro: > + Original: aarch64-poe.xml */ > + > +#include "gdbsupport/tdesc.h" > + > +static int > +create_feature_aarch64_poe (struct target_desc *result, long regnum) > +{ > + struct tdesc_feature *feature; > + > + feature = tdesc_create_feature (result, "org.gnu.gdb.aarch64.poe"); > + tdesc_type_with_fields *type_with_fields; > + type_with_fields = tdesc_create_enum (feature, "por_el0_fmt", 4); > + tdesc_add_enum_value (type_with_fields, 0, "---"); > + tdesc_add_enum_value (type_with_fields, 1, "r--"); > + tdesc_add_enum_value (type_with_fields, 2, "--x"); > + tdesc_add_enum_value (type_with_fields, 3, "r-x"); > + tdesc_add_enum_value (type_with_fields, 4, "-w-"); > + tdesc_add_enum_value (type_with_fields, 5, "rw-"); > + tdesc_add_enum_value (type_with_fields, 6, "-wx"); > + tdesc_add_enum_value (type_with_fields, 7, "rwx"); > + tdesc_add_enum_value (type_with_fields, 8, "???"); > + tdesc_add_enum_value (type_with_fields, 9, "???"); > + tdesc_add_enum_value (type_with_fields, 10, "???"); > + tdesc_add_enum_value (type_with_fields, 11, "???"); > + tdesc_add_enum_value (type_with_fields, 12, "???"); > + tdesc_add_enum_value (type_with_fields, 13, "???"); > + tdesc_add_enum_value (type_with_fields, 14, "???"); > + tdesc_add_enum_value (type_with_fields, 15, "???"); > + > + type_with_fields = tdesc_create_flags (feature, "por_el0_flags", 8); > + tdesc_type *field_type; > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P15", 60, 63, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P14", 56, 59, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P13", 52, 55, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P12", 48, 51, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P11", 44, 47, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P10", 40, 43, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P9", 36, 39, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P8", 32, 35, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P7", 28, 31, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P6", 24, 27, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P5", 20, 23, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P4", 16, 19, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P3", 12, 15, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P2", 8, 11, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P1", 4, 7, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P0", 0, 3, field_type); > + > + tdesc_create_reg (feature, "por_el0", regnum++, 1, "system", 64, "por_el0_flags"); > + return regnum; > +} > diff --git a/gdb/features/aarch64-poe.xml b/gdb/features/aarch64-poe.xml > new file mode 100644 > index 00000000000..58fc4f80d5c > --- /dev/null > +++ b/gdb/features/aarch64-poe.xml > @@ -0,0 +1,47 @@ > +<?xml version="1.0"?> > +<!-- Copyright (C) 2026 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.poe"> > + <enum id="por_el0_fmt" size="4"> > + <evalue name="---" value="0"/> > + <evalue name="r--" value="1"/> > + <evalue name="--x" value="2"/> > + <evalue name="r-x" value="3"/> > + <evalue name="-w-" value="4"/> > + <evalue name="rw-" value="5"/> > + <evalue name="-wx" value="6"/> > + <evalue name="rwx" value="7"/> > + <evalue name="???" value="8"/> > + <evalue name="???" value="9"/> > + <evalue name="???" value="10"/> > + <evalue name="???" value="11"/> > + <evalue name="???" value="12"/> > + <evalue name="???" value="13"/> > + <evalue name="???" value="14"/> > + <evalue name="???" value="15"/> > + </enum> > + <flags id="por_el0_flags" size="8"> > + <field name="P15" start="60" end="63" type="por_el0_fmt"/> > + <field name="P14" start="56" end="59" type="por_el0_fmt"/> > + <field name="P13" start="52" end="55" type="por_el0_fmt"/> > + <field name="P12" start="48" end="51" type="por_el0_fmt"/> > + <field name="P11" start="44" end="47" type="por_el0_fmt"/> > + <field name="P10" start="40" end="43" type="por_el0_fmt"/> > + <field name="P9" start="36" end="39" type="por_el0_fmt"/> > + <field name="P8" start="32" end="35" type="por_el0_fmt"/> > + <field name="P7" start="28" end="31" type="por_el0_fmt"/> > + <field name="P6" start="24" end="27" type="por_el0_fmt"/> > + <field name="P5" start="20" end="23" type="por_el0_fmt"/> > + <field name="P4" start="16" end="19" type="por_el0_fmt"/> > + <field name="P3" start="12" end="15" type="por_el0_fmt"/> > + <field name="P2" start="8" end="11" type="por_el0_fmt"/> > + <field name="P1" start="4" end="7" type="por_el0_fmt"/> > + <field name="P0" start="0" end="3" type="por_el0_fmt"/> > + </flags> > + <reg name="por_el0" bitsize="64" type="por_el0_flags" group="system"/> > +</feature> > diff --git a/gdb/nat/aarch64-poe-linux.h b/gdb/nat/aarch64-poe-linux.h > new file mode 100644 > index 00000000000..f3d0256da3f > --- /dev/null > +++ b/gdb/nat/aarch64-poe-linux.h > @@ -0,0 +1,29 @@ > +/* Common native Linux definitions for AArch64 Permission Overlay Extension. > + > + Copyright (C) 2026 Free Software Foundation, Inc. > + > + This file is part of GDB. > + > + 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 <asm/hwcap.h> Shouldn´t the above be inside the include guard? > +#ifndef GDB_NAT_AARCH64_POE_LINUX_H > +#define GDB_NAT_AARCH64_POE_LINUX_H > + > +/* Feature check for Permission Overlay Extension. */ > +#ifndef HWCAP2_POE > +#define HWCAP2_POE (1ULL << 63) > +#endif /* HWCAP2_POE. */ > + > +#endif /* GDB_NAT_AARCH64_POE_LINUX_H. */ ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3 1/5] [PATCH 1/5] gdb/aarch64: Add POR_EL0 register support for FEAT_S1POE 2026-07-21 20:25 ` Luis @ 2026-07-23 9:29 ` Srinath Parvathaneni 2026-07-25 6:13 ` Thiago Jung Bauermann 0 siblings, 1 reply; 22+ messages in thread From: Srinath Parvathaneni @ 2026-07-23 9:29 UTC (permalink / raw) To: Luis, gdb-patches Cc: guinevere, thiago.bauermann, Ezra Sitorus, Matthieu Longo, simark, Yury Khrustalev [-- Attachment #1: Type: text/plain, Size: 25629 bytes --] >> * p/x $por_el0 >> * set $por_el0 = <value> >> >> Example: >> (gdb) info register por_el0 >> por_el0 0x7 [ P15=--- P14=--- P13=--- P12=--- P11=--- P10=--- P9=--- P8=--- P7=--- P6=--- P5=--- P4=--- P3=--- P2=--- P1=--- P0=rwx ] >> (gdb) set $por_el0=0xffffffff77777777 >> (gdb) info register por_el0 >> por_el0 0xffffffff77777777 [ P15=??? P14=??? P13=??? P12=??? P11=??? P10=??? P9=??? P8=??? P7=rwx P6=rwx P5=rwx P4=rwx P3=rwx P2=rwx P1=rwx P0=rwx ] >> (gdb) p $por_el0 >> $1 = [ P15=??? P14=??? P13=??? P12=??? P11=??? P10=??? P9=??? P8=??? P7=rwx P6=rwx P5=rwx P4=rwx P3=rwx P2=rwx P1=rwx P0=rwx ] >> (gdb) p/x $por_el0 >> $2 = 0xffffffff77777777 >> (gdb) set $por_el0=0x57 >> (gdb) info register por_el0 >> por_el0 0x57 [ P15=--- P14=--- P13=--- P12=--- P11=--- P10=--- P9=--- P8=--- P7=--- P6=--- P5=--- P4=--- P3=--- P2=--- P1=rw- P0=rwx ] >> (gdb) set $por_el0=0xf7f7f7f7f7f7f7f7 >> (gdb) info register por_el0 >> por_el0 0xf7f7f7f7f7f7f7f7 [ P15=??? P14=rwx P13=??? P12=rwx P11=??? P10=rwx P9=??? P8=rwx P7=??? P6=rwx P5=??? P4=rwx P3=??? P2=rwx P1=??? P0=rwx ] >> (gdb) > >Looking at the output above I think it is a bit hard to read. > >Have you considered keeping the original register as it is and having >pseudo-registers that print appropriately? > >If a user wants to see, say, P15, it doesn´t help we print everything >else along with it. > >The other alternative is having a python pretty printer that goes >alongside the feature. > Hi Luis, Thanks for the suggestions. The reason I chose to decode the register inline is that the raw 64 bit register value by itself is not particularly useful. For example, if we kept the original formatting, the user would see something like: (gdb) set $por_el0 = 0xf7f7f7f7f7f7f7f7 (gdb) info register por_el0 por_el0 0xf7f7f7f7f7f7f7f7 17868022691004925943 Neither of hexadecimal nor the decimal value tells the user which protection key has which permissions without manually decoding each 4-bit nibble. Although the architecture defines POR_EL0 as a single 64 bit register, it doesn't define separate P0-P15 fields. I introduced the P0-P15 labels to identify each 4-bit nibble, since each nibble corresponds to one protection key's permission encoding. We also considered only displaying nibbles that have at least one permission enabled, while displaying "???" when the reserved fourth bit of a nibble is set. For example: (gdb) set $por_el0 = 0x57 (gdb) info register por_el0 por_el0 0x57 [ P1=rw- P0=rwx ] (gdb) set $por_el0 = 0xf7 (gdb) info register por_el0 por_el0 0xf7 [ P1=??? P0=rwx ] However, we thought that approach could be misleading because it hides the remaining protection keys rather than explicitly showing that they are all "---", please let me know if you feel this approach is better? Regarding the Python pretty-printer suggestion, could you elaborate a bit on what you have in mind? Would you prefer the Python pretty printer to display the same string format, or a shorter form that still allows accessing each nibble individually (e.g., P0, P5, etc.)? Also, could you provide a simple example of the expected output? Thanks, Sri. ________________________________ From: Luis <luis.machado.foss@gmail.com> Sent: 21 July 2026 21:25 To: Srinath Parvathaneni <Srinath.Parvathaneni@arm.com>; gdb-patches@sourceware.org <gdb-patches@sourceware.org> Cc: guinevere@redhat.com <guinevere@redhat.com>; thiago.bauermann@linaro.org <thiago.bauermann@linaro.org>; Ezra Sitorus <Ezra.Sitorus@arm.com>; Matthieu Longo <Matthieu.Longo@arm.com>; simark@simark.ca <simark@simark.ca> Subject: Re: [PATCH v3 1/5] [PATCH 1/5] gdb/aarch64: Add POR_EL0 register support for FEAT_S1POE Sorry, missed some... On 14/07/2026 21:15, srinath.parvathaneni@arm.com wrote: > From: Srinath Parvathaneni <srinath.parvathaneni@arm.com> > > Add support for the FEAT_S1POE POR_EL0 register on AArch64. > > This patch adds POR_EL0 to the AArch64 register set and reads/writes it > using the NT_ARM_POE ptrace regset. > > With this change, POR_EL0 is available through: > * info registers > * info registers por_el0 > * p $por_el0 > * p/x $por_el0 > * set $por_el0 = <value> > > Example: > (gdb) info register por_el0 > por_el0 0x7 [ P15=--- P14=--- P13=--- P12=--- P11=--- P10=--- P9=--- P8=--- P7=--- P6=--- P5=--- P4=--- P3=--- P2=--- P1=--- P0=rwx ] > (gdb) set $por_el0=0xffffffff77777777 > (gdb) info register por_el0 > por_el0 0xffffffff77777777 [ P15=??? P14=??? P13=??? P12=??? P11=??? P10=??? P9=??? P8=??? P7=rwx P6=rwx P5=rwx P4=rwx P3=rwx P2=rwx P1=rwx P0=rwx ] > (gdb) p $por_el0 > $1 = [ P15=??? P14=??? P13=??? P12=??? P11=??? P10=??? P9=??? P8=??? P7=rwx P6=rwx P5=rwx P4=rwx P3=rwx P2=rwx P1=rwx P0=rwx ] > (gdb) p/x $por_el0 > $2 = 0xffffffff77777777 > (gdb) set $por_el0=0x57 > (gdb) info register por_el0 > por_el0 0x57 [ P15=--- P14=--- P13=--- P12=--- P11=--- P10=--- P9=--- P8=--- P7=--- P6=--- P5=--- P4=--- P3=--- P2=--- P1=rw- P0=rwx ] > (gdb) set $por_el0=0xf7f7f7f7f7f7f7f7 > (gdb) info register por_el0 > por_el0 0xf7f7f7f7f7f7f7f7 [ P15=??? P14=rwx P13=??? P12=rwx P11=??? P10=rwx P9=??? P8=rwx P7=??? P6=rwx P5=??? P4=rwx P3=??? P2=rwx P1=??? P0=rwx ] > (gdb) > --- > gdb/Makefile.in | 2 ++ > gdb/aarch64-linux-nat.c | 64 +++++++++++++++++++++++++++++++++ > gdb/aarch64-tdep.c | 23 ++++++++++++ > gdb/aarch64-tdep.h | 10 ++++++ > gdb/arch/aarch64-poe-linux.h | 29 +++++++++++++++ > gdb/arch/aarch64.c | 4 +++ > gdb/arch/aarch64.h | 8 ++++- > gdb/features/Makefile | 1 + > gdb/features/aarch64-poe.c | 68 ++++++++++++++++++++++++++++++++++++ > gdb/features/aarch64-poe.xml | 47 +++++++++++++++++++++++++ > gdb/nat/aarch64-poe-linux.h | 29 +++++++++++++++ > 11 files changed, 284 insertions(+), 1 deletion(-) > create mode 100644 gdb/arch/aarch64-poe-linux.h > create mode 100644 gdb/features/aarch64-poe.c > create mode 100644 gdb/features/aarch64-poe.xml > create mode 100644 gdb/nat/aarch64-poe-linux.h > > diff --git a/gdb/Makefile.in b/gdb/Makefile.in > index 57f384170ab..3dc9cd07dcb 100644 > --- a/gdb/Makefile.in > +++ b/gdb/Makefile.in > @@ -1292,6 +1292,7 @@ HFILES_NO_SRCDIR = \ > arch/aarch32.h \ > arch/aarch64-fpmr-linux.h \ > arch/aarch64-gcs-linux.h \ > + arch/aarch64-poe-linux.h \ > arch/aarch64.h \ > arch/aarch64-insn.h \ > arch/aarch64-mte.h \ > @@ -1540,6 +1541,7 @@ HFILES_NO_SRCDIR = \ > namespace.h \ > nat/aarch64-fpmr-linux.h \ > nat/aarch64-gcs-linux.h \ > + nat/aarch64-poe-linux.h \ > nat/aarch64-hw-point.h \ > nat/aarch64-linux.h \ > nat/aarch64-linux-hw-point.h \ Let's keep these entries sorted alphabetically. > diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c > index 52ace4aab41..8e29c42908c 100644 > --- a/gdb/aarch64-linux-nat.c > +++ b/gdb/aarch64-linux-nat.c > @@ -34,6 +34,7 @@ > #include "arch/arm.h" > #include "nat/aarch64-fpmr-linux.h" > #include "nat/aarch64-gcs-linux.h" > +#include "nat/aarch64-poe-linux.h" > #include "nat/aarch64-linux.h" > #include "nat/aarch64-linux-hw-point.h" > #include "nat/aarch64-mte-linux-ptrace.h" > @@ -602,6 +603,54 @@ store_gcsregs_to_thread (regcache *regcache) > perror_with_name (_("Unable to store GCS registers")); > } > > +/* Fill GDB's register array with the POE register value from the current > + thread. */ > + > +static void > +fetch_poeregs_from_thread (regcache *regcache) > +{ > + aarch64_gdbarch_tdep *tdep > + = gdbarch_tdep<aarch64_gdbarch_tdep> (regcache->arch ()); > + > + gdb_assert (tdep->has_poe ()); > + > + uint64_t user_poe; > + iovec iovec; > + > + iovec.iov_base = &user_poe; > + iovec.iov_len = sizeof (user_poe); > + > + int tid = get_ptrace_pid (regcache->ptid ()); > + if (ptrace (PTRACE_GETREGSET, tid, NT_ARM_POE, &iovec) != 0) > + perror_with_name (_("Unable to fetch POE register")); > + > + regcache->raw_supply (tdep->poe_regnum, &user_poe); > +} > + > +/* Store the NT_ARM_POE register contents from GDB's REGCACHE to the > + thread associated with REGCACHE. */ wront identation above. > + > +static void > +store_poeregs_to_thread (struct regcache *regcache) > +{ > + aarch64_gdbarch_tdep *tdep > + = gdbarch_tdep<aarch64_gdbarch_tdep> (regcache->arch ()); > + > + gdb_assert (tdep->has_poe ()); > + > + int tid = regcache->ptid ().lwp (); > + > + iovec iovec; > + uint64_t user_poe; > + iovec.iov_base = &user_poe; > + iovec.iov_len = sizeof (user_poe); > + > + regcache->raw_collect (tdep->poe_regnum, &user_poe); > + > + if (ptrace (PTRACE_SETREGSET, tid, NT_ARM_POE, &iovec) != 0) > + perror_with_name (_("Unable to store POE register")); > +} > + > /* Fill GDB's REGCACHE with the FPMR register set content from the > thread associated with REGCACHE. */ > > @@ -683,6 +732,9 @@ aarch64_fetch_registers (struct regcache *regcache, int regno) > if (tdep->has_gcs_linux ()) > fetch_gcsregs_from_thread (regcache); > > + if (tdep->has_poe ()) > + fetch_poeregs_from_thread (regcache); > + > if (tdep->has_fpmr ()) > fetch_fpmr_from_thread (regcache); > } > @@ -722,6 +774,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); > + /* POE register? */ > + else if (tdep->has_poe () && (regno == tdep->poe_regnum)) > + fetch_poeregs_from_thread (regcache); > /* FPMR? */ > else if (tdep->has_fpmr () && (regno == tdep->fpmr_regnum)) > fetch_fpmr_from_thread (regcache); > @@ -802,6 +857,9 @@ aarch64_store_registers (struct regcache *regcache, int regno) > > if (tdep->has_fpmr ()) > store_fpmr_to_thread (regcache); > + > + if (tdep->has_poe ()) > + store_poeregs_to_thread (regcache); > } > /* General purpose register? */ > else if (regno < AARCH64_V0_REGNUM) > @@ -836,6 +894,9 @@ aarch64_store_registers (struct regcache *regcache, int regno) > /* FPMR? */ > else if (tdep->has_fpmr () && regno == tdep->fpmr_regnum) > store_fpmr_to_thread (regcache); > + /* POE register? */ > + else if (tdep->has_poe () && regno == tdep->poe_regnum) > + store_poeregs_to_thread (regcache); > > /* PAuth registers are read-only. */ > } > @@ -1024,6 +1085,9 @@ aarch64_linux_nat_target::read_description () > /* Check for FPMR. */ > features.fpmr = hwcap2 & HWCAP2_FPMR; > > + /* Check for POE support. */ > + features.poe = hwcap2 & HWCAP2_POE; > + > return aarch64_read_description (features); > } > > diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c > index a84da1fd59e..2e86d6e0452 100644 > --- a/gdb/aarch64-tdep.c > +++ b/gdb/aarch64-tdep.c > @@ -164,6 +164,11 @@ static const char *const aarch64_gcs_register_names[] = { > "gcspr" > }; > > +static const char *const aarch64_poe_register_names[] = { > + /* Permission Overlay Extension Register. */ > + "por_el0" > +}; > + > static const char *const aarch64_gcs_linux_register_names[] = { > /* Field in struct user_gcs. */ > "gcs_features_enabled", > @@ -4136,6 +4141,10 @@ aarch64_features_from_target_desc (const struct target_desc *tdesc) > features.fpmr = (tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.fpmr") > != nullptr); > > + /* Check for POE feature. */ > + features.poe = (tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.poe") > + != nullptr); > + > return features; > } > > @@ -4556,6 +4565,19 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) > fpmr_regnum, "fpmr"); > } > > + int poe_regnum = -1; > + const struct tdesc_feature *feature_poe > + = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.poe"); > + if (feature_poe != nullptr) > + { > + poe_regnum = num_regs; > + for (i = 0; i < ARRAY_SIZE (aarch64_poe_register_names); i++) > + valid_p &= tdesc_numbered_register (feature_poe, tdesc_data.get (), > + poe_regnum + i, > + aarch64_poe_register_names[i]); > + num_regs++; > + } > + > int first_sme_regnum = -1; > int first_sme2_regnum = -1; > int first_sme_pseudo_regnum = -1; > @@ -4756,6 +4778,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) > tdep->gcs_reg_base = first_gcs_regnum; > tdep->gcs_linux_reg_base = first_gcs_linux_regnum; > tdep->fpmr_regnum = fpmr_regnum; > + tdep->poe_regnum = poe_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 dff05a08f84..3c5d10beee5 100644 > --- a/gdb/aarch64-tdep.h > +++ b/gdb/aarch64-tdep.h > @@ -208,6 +208,16 @@ struct aarch64_gdbarch_tdep : gdbarch_tdep_base > return gcs_linux_reg_base != -1; > } > > + /* POE register. This is -1 if no POE feature is available. */ > + int poe_regnum = -1; > + > + /* Returns true if the target supports the POE feature. */ > + bool > + has_poe () const > + { > + return poe_regnum != -1; > + } > + > /* First FPMR register. This is -1 if FPMR is not supported. */ > int fpmr_regnum = -1; > > diff --git a/gdb/arch/aarch64-poe-linux.h b/gdb/arch/aarch64-poe-linux.h > new file mode 100644 > index 00000000000..8623fa43b54 > --- /dev/null > +++ b/gdb/arch/aarch64-poe-linux.h > @@ -0,0 +1,29 @@ > +/* Common Linux target-dependent definitions for AArch64 POE > + > + Copyright (C) 2026 Free Software Foundation, Inc. > + > + This file is part of GDB. > + > + 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/>. */ > + > +#ifndef GDB_ARCH_AARCH64_POE_LINUX_H > +#define GDB_ARCH_AARCH64_POE_LINUX_H > + > +/* Feature check for Permission Overlay Extension. */ > +#define AARCH64_HWCAP2_POE (1ULL << 63) > + > +/* Data or instruction abort caused by Protection Key Violation. */ > +#define AARCH64_SEGV_PKUERR 4 > + > +#endif /* GDB_ARCH_AARCH64_POE_LINUX_H. */ > diff --git a/gdb/arch/aarch64.c b/gdb/arch/aarch64.c > index 2401a325b7b..a567938d06d 100644 > --- a/gdb/arch/aarch64.c > +++ b/gdb/arch/aarch64.c > @@ -28,6 +28,7 @@ > #include "../features/aarch64-sme2.c" > #include "../features/aarch64-tls.c" > #include "../features/aarch64-gcs.c" > +#include "../features/aarch64-poe.c" > #include "../features/aarch64-gcs-linux.c" > > /* See arch/aarch64.h. */ > @@ -77,6 +78,9 @@ aarch64_create_target_description (const aarch64_features &features) > if (features.fpmr) > regnum = create_feature_aarch64_fpmr (tdesc.get (), regnum); > > + if (features.poe) > + regnum = create_feature_aarch64_poe (tdesc.get (), regnum); > + > return tdesc; > } > > diff --git a/gdb/arch/aarch64.h b/gdb/arch/aarch64.h > index cf7318cbe74..ba90d55c3bb 100644 > --- a/gdb/arch/aarch64.h > +++ b/gdb/arch/aarch64.h > @@ -35,6 +35,8 @@ struct aarch64_features > bool pauth = false; > bool mte = false; > bool fpmr = false; > + /* Whether the Permission Overlay Extension (FEAT_S1POE) is supported. */ > + bool poe = false; > > /* A positive TLS value indicates the number of TLS registers available. */ > uint8_t tls = 0; > @@ -70,7 +72,8 @@ inline bool operator==(const aarch64_features &lhs, const aarch64_features &rhs) > && lhs.sme2 == rhs.sme2 > && lhs.gcs == rhs.gcs > && lhs.gcs_linux == rhs.gcs_linux > - && lhs.fpmr == rhs.fpmr; > + && lhs.fpmr == rhs.fpmr > + && lhs.poe == rhs.poe; > } > > namespace std > @@ -103,6 +106,9 @@ namespace std > > /* FPMR feature. */ > h = h << 1 | features.fpmr; > + > + /* POE feature. */ > + h = h << 1 | features.poe; > return h; > } > }; > diff --git a/gdb/features/Makefile b/gdb/features/Makefile > index 161a7453d66..cc77e5bb652 100644 > --- a/gdb/features/Makefile > +++ b/gdb/features/Makefile > @@ -207,6 +207,7 @@ FEATURE_XMLFILES = aarch64-core.xml \ > aarch64-pauth.xml \ > aarch64-mte.xml \ > aarch64-gcs.xml \ > + aarch64-poe.xml \ > aarch64-gcs-linux.xml \ > arc/v1-core.xml \ > arc/v1-aux.xml \ > diff --git a/gdb/features/aarch64-poe.c b/gdb/features/aarch64-poe.c > new file mode 100644 > index 00000000000..4bd795e9fe6 > --- /dev/null > +++ b/gdb/features/aarch64-poe.c > @@ -0,0 +1,68 @@ > +/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro: > + Original: aarch64-poe.xml */ > + > +#include "gdbsupport/tdesc.h" > + > +static int > +create_feature_aarch64_poe (struct target_desc *result, long regnum) > +{ > + struct tdesc_feature *feature; > + > + feature = tdesc_create_feature (result, "org.gnu.gdb.aarch64.poe"); > + tdesc_type_with_fields *type_with_fields; > + type_with_fields = tdesc_create_enum (feature, "por_el0_fmt", 4); > + tdesc_add_enum_value (type_with_fields, 0, "---"); > + tdesc_add_enum_value (type_with_fields, 1, "r--"); > + tdesc_add_enum_value (type_with_fields, 2, "--x"); > + tdesc_add_enum_value (type_with_fields, 3, "r-x"); > + tdesc_add_enum_value (type_with_fields, 4, "-w-"); > + tdesc_add_enum_value (type_with_fields, 5, "rw-"); > + tdesc_add_enum_value (type_with_fields, 6, "-wx"); > + tdesc_add_enum_value (type_with_fields, 7, "rwx"); > + tdesc_add_enum_value (type_with_fields, 8, "???"); > + tdesc_add_enum_value (type_with_fields, 9, "???"); > + tdesc_add_enum_value (type_with_fields, 10, "???"); > + tdesc_add_enum_value (type_with_fields, 11, "???"); > + tdesc_add_enum_value (type_with_fields, 12, "???"); > + tdesc_add_enum_value (type_with_fields, 13, "???"); > + tdesc_add_enum_value (type_with_fields, 14, "???"); > + tdesc_add_enum_value (type_with_fields, 15, "???"); > + > + type_with_fields = tdesc_create_flags (feature, "por_el0_flags", 8); > + tdesc_type *field_type; > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P15", 60, 63, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P14", 56, 59, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P13", 52, 55, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P12", 48, 51, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P11", 44, 47, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P10", 40, 43, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P9", 36, 39, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P8", 32, 35, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P7", 28, 31, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P6", 24, 27, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P5", 20, 23, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P4", 16, 19, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P3", 12, 15, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P2", 8, 11, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P1", 4, 7, field_type); > + field_type = tdesc_named_type (feature, "por_el0_fmt"); > + tdesc_add_typed_bitfield (type_with_fields, "P0", 0, 3, field_type); > + > + tdesc_create_reg (feature, "por_el0", regnum++, 1, "system", 64, "por_el0_flags"); > + return regnum; > +} > diff --git a/gdb/features/aarch64-poe.xml b/gdb/features/aarch64-poe.xml > new file mode 100644 > index 00000000000..58fc4f80d5c > --- /dev/null > +++ b/gdb/features/aarch64-poe.xml > @@ -0,0 +1,47 @@ > +<?xml version="1.0"?> > +<!-- Copyright (C) 2026 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.poe"> > + <enum id="por_el0_fmt" size="4"> > + <evalue name="---" value="0"/> > + <evalue name="r--" value="1"/> > + <evalue name="--x" value="2"/> > + <evalue name="r-x" value="3"/> > + <evalue name="-w-" value="4"/> > + <evalue name="rw-" value="5"/> > + <evalue name="-wx" value="6"/> > + <evalue name="rwx" value="7"/> > + <evalue name="???" value="8"/> > + <evalue name="???" value="9"/> > + <evalue name="???" value="10"/> > + <evalue name="???" value="11"/> > + <evalue name="???" value="12"/> > + <evalue name="???" value="13"/> > + <evalue name="???" value="14"/> > + <evalue name="???" value="15"/> > + </enum> > + <flags id="por_el0_flags" size="8"> > + <field name="P15" start="60" end="63" type="por_el0_fmt"/> > + <field name="P14" start="56" end="59" type="por_el0_fmt"/> > + <field name="P13" start="52" end="55" type="por_el0_fmt"/> > + <field name="P12" start="48" end="51" type="por_el0_fmt"/> > + <field name="P11" start="44" end="47" type="por_el0_fmt"/> > + <field name="P10" start="40" end="43" type="por_el0_fmt"/> > + <field name="P9" start="36" end="39" type="por_el0_fmt"/> > + <field name="P8" start="32" end="35" type="por_el0_fmt"/> > + <field name="P7" start="28" end="31" type="por_el0_fmt"/> > + <field name="P6" start="24" end="27" type="por_el0_fmt"/> > + <field name="P5" start="20" end="23" type="por_el0_fmt"/> > + <field name="P4" start="16" end="19" type="por_el0_fmt"/> > + <field name="P3" start="12" end="15" type="por_el0_fmt"/> > + <field name="P2" start="8" end="11" type="por_el0_fmt"/> > + <field name="P1" start="4" end="7" type="por_el0_fmt"/> > + <field name="P0" start="0" end="3" type="por_el0_fmt"/> > + </flags> > + <reg name="por_el0" bitsize="64" type="por_el0_flags" group="system"/> > +</feature> > diff --git a/gdb/nat/aarch64-poe-linux.h b/gdb/nat/aarch64-poe-linux.h > new file mode 100644 > index 00000000000..f3d0256da3f > --- /dev/null > +++ b/gdb/nat/aarch64-poe-linux.h > @@ -0,0 +1,29 @@ > +/* Common native Linux definitions for AArch64 Permission Overlay Extension. > + > + Copyright (C) 2026 Free Software Foundation, Inc. > + > + This file is part of GDB. > + > + 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 <asm/hwcap.h> Shouldn´t the above be inside the include guard? > +#ifndef GDB_NAT_AARCH64_POE_LINUX_H > +#define GDB_NAT_AARCH64_POE_LINUX_H > + > +/* Feature check for Permission Overlay Extension. */ > +#ifndef HWCAP2_POE > +#define HWCAP2_POE (1ULL << 63) > +#endif /* HWCAP2_POE. */ > + > +#endif /* GDB_NAT_AARCH64_POE_LINUX_H. */ [-- Attachment #2: Type: text/html, Size: 52836 bytes --] ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3 1/5] [PATCH 1/5] gdb/aarch64: Add POR_EL0 register support for FEAT_S1POE 2026-07-23 9:29 ` Srinath Parvathaneni @ 2026-07-25 6:13 ` Thiago Jung Bauermann 2026-07-25 7:29 ` Luis 0 siblings, 1 reply; 22+ messages in thread From: Thiago Jung Bauermann @ 2026-07-25 6:13 UTC (permalink / raw) To: Srinath Parvathaneni Cc: Luis, gdb-patches, guinevere, Ezra Sitorus, Matthieu Longo, simark, Yury Khrustalev Srinath Parvathaneni <Srinath.Parvathaneni@arm.com> writes: >>> * p/x $por_el0 >>> * set $por_el0 = <value> >>> >>> Example: >>> (gdb) info register por_el0 >>> por_el0 0x7 [ P15=--- P14=--- P13=--- P12=--- P11=--- P10=--- P9=--- P8=--- P7=--- > P6=--- P5=--- P4=--- P3=--- P2=--- P1=--- P0=rwx ] >>> (gdb) set $por_el0=0xffffffff77777777 >>> (gdb) info register por_el0 >>> por_el0 0xffffffff77777777 [ P15=??? P14=??? P13=??? P12=??? P11=??? P10=??? P9=??? > P8=??? P7=rwx P6=rwx P5=rwx P4=rwx P3=rwx P2=rwx P1=rwx P0=rwx ] >>> (gdb) p $por_el0 >>> $1 = [ P15=??? P14=??? P13=??? P12=??? P11=??? P10=??? P9=??? P8=??? P7=rwx P6=rwx > P5=rwx P4=rwx P3=rwx P2=rwx P1=rwx P0=rwx ] >>> (gdb) p/x $por_el0 >>> $2 = 0xffffffff77777777 >>> (gdb) set $por_el0=0x57 >>> (gdb) info register por_el0 >>> por_el0 0x57 [ P15=--- P14=--- P13=--- P12=--- P11=--- P10=--- P9=--- P8=--- P7=--- > P6=--- P5=--- P4=--- P3=--- P2=--- P1=rw- P0=rwx ] >>> (gdb) set $por_el0=0xf7f7f7f7f7f7f7f7 >>> (gdb) info register por_el0 >>> por_el0 0xf7f7f7f7f7f7f7f7 [ P15=??? P14=rwx P13=??? P12=rwx P11=??? P10=rwx P9=??? > P8=rwx P7=??? P6=rwx P5=??? P4=rwx P3=??? P2=rwx P1=??? P0=rwx ] >>> (gdb) >> >>Looking at the output above I think it is a bit hard to read. I think part of the reason for it being hard to read is that the output is very wide. One way to address this is Srinath's suggestion below to not print zeroed keys. Another would be to improve the output of the flag type to add line breaks when the terminal's width is reached, as is done when printing array values. Another option would be to use a struct rather than a flags type. Then there would be one type per field, and it would be possible to display (and set) only one key. Not sure which of them I prefer. The struct idea has the advantage of letting the user easily set protection keys individually. OTOH it's not printed isn a very compact way. If easily displaying/setting individual keys isn't that important, I think I slightly prefer not printing zeroed keys as Srinath suggests, possibly coupled with adding line breaks when the line is too long, to address the case of having many keys set in the register. >>Have you considered keeping the original register as it is and having >>pseudo-registers that print appropriately? >> >>If a user wants to see, say, P15, it doesn´t help we print everything >>else along with it. >> >>The other alternative is having a python pretty printer that goes >>alongside the feature. >> > > Hi Luis, > > Thanks for the suggestions. > > The reason I chose to decode the register inline is that the raw 64 bit register > value by itself is not particularly useful. For example, if we kept the original > formatting, the user would see something like: > > (gdb) set $por_el0 = 0xf7f7f7f7f7f7f7f7 > (gdb) info register por_el0 > por_el0 0xf7f7f7f7f7f7f7f7 17868022691004925943 > > Neither of hexadecimal nor the decimal value tells the user which protection key > has which permissions without manually decoding each 4-bit nibble. > > Although the architecture defines POR_EL0 as a single 64 bit register, it > doesn't define separate P0-P15 fields. I introduced the P0-P15 labels > to identify each 4-bit nibble, since each nibble corresponds to one protection > key's permission encoding. I agree that if the raw register value isn't useful, then it makes sense to use a more elaborate type for it. > We also considered only displaying nibbles that have at least one permission > enabled, while displaying "???" when the reserved fourth bit of a nibble is set. > For example: > > (gdb) set $por_el0 = 0x57 > (gdb) info register por_el0 > por_el0 0x57 [ P1=rw- P0=rwx ] > > (gdb) set $por_el0 = 0xf7 > (gdb) info register por_el0 > por_el0 0xf7 [ P1=??? P0=rwx ] > > However, we thought that approach could be misleading because it hides the > remaining protection keys rather than explicitly showing that they are all > "---", please let me know if you feel this approach is better? I think this is better than the output in the commit message. Especially in the "info register" case where the raw value is also shown so it's not hard to see that ommitted keys are zeroed. Even with the print command, using print/x will show the raw value too. I have a couple more comments on the patch: >> diff --git a/gdb/arch/aarch64-poe-linux.h b/gdb/arch/aarch64-poe-linux.h >> new file mode 100644 >> index 00000000000..8623fa43b54 >> --- /dev/null >> +++ b/gdb/arch/aarch64-poe-linux.h >> @@ -0,0 +1,29 @@ >> +/* Common Linux target-dependent definitions for AArch64 POE >> + >> + Copyright (C) 2026 Free Software Foundation, Inc. >> + >> + This file is part of GDB. >> + >> + 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/>. */ >> + >> +#ifndef GDB_ARCH_AARCH64_POE_LINUX_H >> +#define GDB_ARCH_AARCH64_POE_LINUX_H >> + >> +/* Feature check for Permission Overlay Extension. */ >> +#define AARCH64_HWCAP2_POE (1ULL << 63) >> + >> +/* Data or instruction abort caused by Protection Key Violation. */ >> +#define AARCH64_SEGV_PKUERR 4 >> + >> +#endif /* GDB_ARCH_AARCH64_POE_LINUX_H. */ check-include-guards.py complains about the comment above: $ gdb/check-include-guards.py gdb/arch/aarch64-poe-linux.h gdb/arch/aarch64-poe-linux.h:29: wrong endif line $ gdb/check-include-guards.py --update gdb/arch/aarch64-poe-linux.h $ git diff diff --git a/gdb/arch/aarch64-poe-linux.h b/gdb/arch/aarch64-poe-linux.h index 8623fa43b549..d6e4a001cbf9 100644 --- a/gdb/arch/aarch64-poe-linux.h +++ b/gdb/arch/aarch64-poe-linux.h @@ -26,4 +26,4 @@ /* Data or instruction abort caused by Protection Key Violation. */ #define AARCH64_SEGV_PKUERR 4 -#endif /* GDB_ARCH_AARCH64_POE_LINUX_H. */ +#endif /* GDB_ARCH_AARCH64_POE_LINUX_H */ Also, nothing in this patch uses this file. It should be moved to patch 2. -- Thiago (he/him) ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3 1/5] [PATCH 1/5] gdb/aarch64: Add POR_EL0 register support for FEAT_S1POE 2026-07-25 6:13 ` Thiago Jung Bauermann @ 2026-07-25 7:29 ` Luis 0 siblings, 0 replies; 22+ messages in thread From: Luis @ 2026-07-25 7:29 UTC (permalink / raw) To: Thiago Jung Bauermann, Srinath Parvathaneni Cc: gdb-patches, guinevere, Ezra Sitorus, Matthieu Longo, simark, Yury Khrustalev Hi, On 25/07/2026 07:13, Thiago Jung Bauermann wrote: > Srinath Parvathaneni <Srinath.Parvathaneni@arm.com> writes: > >>>> * p/x $por_el0 >>>> * set $por_el0 = <value> >>>> >>>> Example: >>>> (gdb) info register por_el0 >>>> por_el0 0x7 [ P15=--- P14=--- P13=--- P12=--- P11=--- P10=--- P9=--- P8=--- P7=--- >> P6=--- P5=--- P4=--- P3=--- P2=--- P1=--- P0=rwx ] >>>> (gdb) set $por_el0=0xffffffff77777777 >>>> (gdb) info register por_el0 >>>> por_el0 0xffffffff77777777 [ P15=??? P14=??? P13=??? P12=??? P11=??? P10=??? P9=??? >> P8=??? P7=rwx P6=rwx P5=rwx P4=rwx P3=rwx P2=rwx P1=rwx P0=rwx ] >>>> (gdb) p $por_el0 >>>> $1 = [ P15=??? P14=??? P13=??? P12=??? P11=??? P10=??? P9=??? P8=??? P7=rwx P6=rwx >> P5=rwx P4=rwx P3=rwx P2=rwx P1=rwx P0=rwx ] >>>> (gdb) p/x $por_el0 >>>> $2 = 0xffffffff77777777 >>>> (gdb) set $por_el0=0x57 >>>> (gdb) info register por_el0 >>>> por_el0 0x57 [ P15=--- P14=--- P13=--- P12=--- P11=--- P10=--- P9=--- P8=--- P7=--- >> P6=--- P5=--- P4=--- P3=--- P2=--- P1=rw- P0=rwx ] >>>> (gdb) set $por_el0=0xf7f7f7f7f7f7f7f7 >>>> (gdb) info register por_el0 >>>> por_el0 0xf7f7f7f7f7f7f7f7 [ P15=??? P14=rwx P13=??? P12=rwx P11=??? P10=rwx P9=??? >> P8=rwx P7=??? P6=rwx P5=??? P4=rwx P3=??? P2=rwx P1=??? P0=rwx ] >>>> (gdb) >>> >>> Looking at the output above I think it is a bit hard to read. > > I think part of the reason for it being hard to read is that the output > is very wide. Indeed. I mean, as an overview it's fine. But it really depends on the most common use case for this register. What I want to steer clear from is something like we have for SVE registers. It is a barrage of text that isn´t very easy to use. > > One way to address this is Srinath's suggestion below to not print > zeroed keys. Another would be to improve the output of the flag type to > add line breaks when the terminal's width is reached, as is done when > printing array values. > > Another option would be to use a struct rather than a flags type. Then > there would be one type per field, and it would be possible to display > (and set) only one key. > > Not sure which of them I prefer. The struct idea has the advantage of > letting the user easily set protection keys individually. OTOH it's > not printed isn a very compact way. > > If easily displaying/setting individual keys isn't that important, I > think I slightly prefer not printing zeroed keys as Srinath suggests, > possibly coupled with adding line breaks when the line is too long, to > address the case of having many keys set in the register. > Good suggestions. I'd say if users want... - An overview with permissions, then print what we have above - To use it as a mask, we should have the raw value - To read/write individual P<x> entries within the register, then we should have pseudo-registers that map back to por_el0. The pseudo registers would leave the interpretation of the raw values out of the XML, therefore remote stubs wouldn´t need to pass that sort of information. Stretching it a little bit, remote stubs could even send a modified version of these fields in the XML and gdb would start printing something else. ^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v3 2/5] [PATCH 2/5] gdb: Improve SIGSEGV diagnostics for POE faults 2026-07-14 20:15 [PATCH v3 0/5] gdb/aarch64: Add POR_EL0 register support for FEAT_S1POE srinath.parvathaneni 2026-07-14 20:15 ` [PATCH v3 1/5] [PATCH 1/5] " srinath.parvathaneni @ 2026-07-14 20:15 ` srinath.parvathaneni 2026-07-21 20:30 ` Luis 2026-07-14 20:15 ` [PATCH v3 3/5] [PATCH 3/5] gdbserver/aarch64: Add POR_EL0 register support srinath.parvathaneni ` (2 subsequent siblings) 4 siblings, 1 reply; 22+ messages in thread From: srinath.parvathaneni @ 2026-07-14 20:15 UTC (permalink / raw) To: gdb-patches Cc: luis.machado.foss, guinevere, thiago.bauermann, Ezra.Sitorus, Matthieu.Longo, simark, Srinath Parvathaneni From: Srinath Parvathaneni <srinath.parvathaneni@arm.com> When a SIGSEGV is caused by a Permission Overlay violation, include additional information in GDB's error message to help identify the failing address along with the responsible protection key causing this fault. Example: (gdb) c Continuing. Program received signal SIGSEGV, Segmentation fault Protection Key Violation while accessing address 0x0000fffff7ff3000 with Protection Key = 1. 0x0000aaaaaaaa0a3c in main () at poe_sigsegv.c:26 Approved-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org> --- gdb/aarch64-linux-tdep.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c index f11eccc1bc1..b8a02ab9972 100644 --- a/gdb/aarch64-linux-tdep.c +++ b/gdb/aarch64-linux-tdep.c @@ -53,6 +53,7 @@ #include "arch/aarch64-fpmr-linux.h" #include "arch/aarch64-gcs-linux.h" +#include "arch/aarch64-poe-linux.h" #include "arch/aarch64-mte.h" #include "arch/aarch64-mte-linux.h" #include "arch/aarch64-pauth-linux.h" @@ -2675,11 +2676,12 @@ aarch64_linux_report_signal_info (struct gdbarch *gdbarch, { aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch); - if (!(tdep->has_mte () || tdep->has_gcs ()) || siggnal != GDB_SIGNAL_SEGV) + if (!(tdep->has_mte () || tdep->has_gcs () || tdep->has_poe ()) + || siggnal != GDB_SIGNAL_SEGV) return; CORE_ADDR fault_addr = 0; - long si_code = 0, si_errno = 0; + long si_code = 0, si_errno = 0, si_pkey = -1; try { @@ -2687,6 +2689,9 @@ aarch64_linux_report_signal_info (struct gdbarch *gdbarch, violation. */ si_code = parse_and_eval_long ("$_siginfo.si_code"); si_errno = parse_and_eval_long ("$_siginfo.si_errno"); + if (tdep->has_poe ()) + si_pkey = parse_and_eval_long + ("$_siginfo._sifields._sigfault._._addr_pkey.si_pkey"); fault_addr = parse_and_eval_long ("$_siginfo._sifields._sigfault.si_addr"); @@ -2703,6 +2708,8 @@ aarch64_linux_report_signal_info (struct gdbarch *gdbarch, meaning = _("Memory tag violation"); else if (si_code == AARCH64_SEGV_CPERR && si_errno == 0) meaning = _("Guarded Control Stack error"); + else if (si_code == AARCH64_SEGV_PKUERR) + meaning = _("Protection Key Violation"); else return; @@ -2734,6 +2741,14 @@ aarch64_linux_report_signal_info (struct gdbarch *gdbarch, uiout->field_string ("logical-tag", hex_string (ltag)); } } + /* For POE SEGSEGV, show additional information. */ + else if (si_code == AARCH64_SEGV_PKUERR) + { + uiout->text (_(" while accessing address ")); + uiout->field_core_addr ("fault-addr", gdbarch, fault_addr); + uiout->text (" with Protection Key = "); + uiout->field_signed ("protection-key", si_pkey); + } else if (si_code != AARCH64_SEGV_CPERR) { uiout->text ("\n"); @@ -3054,7 +3069,7 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) aarch64_linux_decode_memtag_section); } - if (tdep->has_mte () || tdep->has_gcs ()) + if (tdep->has_mte () || tdep->has_gcs () || tdep->has_poe ()) set_gdbarch_report_signal_info (gdbarch, aarch64_linux_report_signal_info); /* Initialize the aarch64_linux_record_tdep. */ -- 2.43.0 ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3 2/5] [PATCH 2/5] gdb: Improve SIGSEGV diagnostics for POE faults 2026-07-14 20:15 ` [PATCH v3 2/5] [PATCH 2/5] gdb: Improve SIGSEGV diagnostics for POE faults srinath.parvathaneni @ 2026-07-21 20:30 ` Luis 2026-07-22 9:41 ` Matthieu Longo 0 siblings, 1 reply; 22+ messages in thread From: Luis @ 2026-07-21 20:30 UTC (permalink / raw) To: srinath.parvathaneni, gdb-patches Cc: guinevere, thiago.bauermann, Ezra.Sitorus, Matthieu.Longo, simark On 14/07/2026 21:15, srinath.parvathaneni@arm.com wrote: > From: Srinath Parvathaneni <srinath.parvathaneni@arm.com> > > When a SIGSEGV is caused by a Permission Overlay violation, include > additional information in GDB's error message to help identify the > failing address along with the responsible protection key causing > this fault. > > Example: > (gdb) c > Continuing. > > Program received signal SIGSEGV, Segmentation fault > Protection Key Violation while accessing address 0x0000fffff7ff3000 with Protection Key = 1. > 0x0000aaaaaaaa0a3c in main () at poe_sigsegv.c:26 > > Approved-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org> > --- > gdb/aarch64-linux-tdep.c | 21 ++++++++++++++++++--- > 1 file changed, 18 insertions(+), 3 deletions(-) > > diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c > index f11eccc1bc1..b8a02ab9972 100644 > --- a/gdb/aarch64-linux-tdep.c > +++ b/gdb/aarch64-linux-tdep.c > @@ -53,6 +53,7 @@ > > #include "arch/aarch64-fpmr-linux.h" > #include "arch/aarch64-gcs-linux.h" > +#include "arch/aarch64-poe-linux.h" > #include "arch/aarch64-mte.h" > #include "arch/aarch64-mte-linux.h" > #include "arch/aarch64-pauth-linux.h" > @@ -2675,11 +2676,12 @@ aarch64_linux_report_signal_info (struct gdbarch *gdbarch, > { > aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch); > > - if (!(tdep->has_mte () || tdep->has_gcs ()) || siggnal != GDB_SIGNAL_SEGV) > + if (!(tdep->has_mte () || tdep->has_gcs () || tdep->has_poe ()) > + || siggnal != GDB_SIGNAL_SEGV) > return; > > CORE_ADDR fault_addr = 0; > - long si_code = 0, si_errno = 0; > + long si_code = 0, si_errno = 0, si_pkey = -1; > > try > { > @@ -2687,6 +2689,9 @@ aarch64_linux_report_signal_info (struct gdbarch *gdbarch, > violation. */ > si_code = parse_and_eval_long ("$_siginfo.si_code"); > si_errno = parse_and_eval_long ("$_siginfo.si_errno"); > + if (tdep->has_poe ()) > + si_pkey = parse_and_eval_long > + ("$_siginfo._sifields._sigfault._._addr_pkey.si_pkey"); > > fault_addr > = parse_and_eval_long ("$_siginfo._sifields._sigfault.si_addr"); > @@ -2703,6 +2708,8 @@ aarch64_linux_report_signal_info (struct gdbarch *gdbarch, > meaning = _("Memory tag violation"); > else if (si_code == AARCH64_SEGV_CPERR && si_errno == 0) > meaning = _("Guarded Control Stack error"); > + else if (si_code == AARCH64_SEGV_PKUERR) > + meaning = _("Protection Key Violation"); > else > return; > > @@ -2734,6 +2741,14 @@ aarch64_linux_report_signal_info (struct gdbarch *gdbarch, > uiout->field_string ("logical-tag", hex_string (ltag)); > } > } > + /* For POE SEGSEGV, show additional information. */ Is this really supposed to be POE SEGSEGV or is it a typo? > + else if (si_code == AARCH64_SEGV_PKUERR) > + { > + uiout->text (_(" while accessing address ")); > + uiout->field_core_addr ("fault-addr", gdbarch, fault_addr); > + uiout->text (" with Protection Key = "); Missing internationalization above. > + uiout->field_signed ("protection-key", si_pkey); > + } > else if (si_code != AARCH64_SEGV_CPERR) > { > uiout->text ("\n"); > @@ -3054,7 +3069,7 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) > aarch64_linux_decode_memtag_section); > } > > - if (tdep->has_mte () || tdep->has_gcs ()) > + if (tdep->has_mte () || tdep->has_gcs () || tdep->has_poe ()) > set_gdbarch_report_signal_info (gdbarch, aarch64_linux_report_signal_info); > > /* Initialize the aarch64_linux_record_tdep. */ ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3 2/5] [PATCH 2/5] gdb: Improve SIGSEGV diagnostics for POE faults 2026-07-21 20:30 ` Luis @ 2026-07-22 9:41 ` Matthieu Longo 2026-07-22 23:11 ` Luis 0 siblings, 1 reply; 22+ messages in thread From: Matthieu Longo @ 2026-07-22 9:41 UTC (permalink / raw) To: Luis, srinath.parvathaneni, gdb-patches Cc: guinevere, thiago.bauermann, Ezra.Sitorus, simark On 21/07/2026 21:30, Luis wrote: > On 14/07/2026 21:15, srinath.parvathaneni@arm.com wrote: >> From: Srinath Parvathaneni <srinath.parvathaneni@arm.com> >> >> diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c >> index f11eccc1bc1..b8a02ab9972 100644 >> --- a/gdb/aarch64-linux-tdep.c >> +++ b/gdb/aarch64-linux-tdep.c >> @@ -2734,6 +2741,14 @@ aarch64_linux_report_signal_info (struct gdbarch *gdbarch, >> uiout->field_string ("logical-tag", hex_string (ltag)); >> } >> } >> + /* For POE SEGSEGV, show additional information. */ > > Is this really supposed to be POE SEGSEGV or is it a typo? > For now, in my knowledge, AARCH64_SEGV_PKUERR is only used for POE. However, it will also be used soon for another upcoming feature. I would recommend to either simply eliminate the comment, or make it more clear like /* For memory permission faults, e.g. due to a permission overlay restriction when feature POE is enabled. */ Matthieu ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3 2/5] [PATCH 2/5] gdb: Improve SIGSEGV diagnostics for POE faults 2026-07-22 9:41 ` Matthieu Longo @ 2026-07-22 23:11 ` Luis 2026-07-23 9:03 ` Srinath Parvathaneni 0 siblings, 1 reply; 22+ messages in thread From: Luis @ 2026-07-22 23:11 UTC (permalink / raw) To: Matthieu Longo, srinath.parvathaneni, gdb-patches Cc: guinevere, thiago.bauermann, Ezra.Sitorus, simark On 22/07/2026 10:41, Matthieu Longo wrote: > On 21/07/2026 21:30, Luis wrote: >> On 14/07/2026 21:15, srinath.parvathaneni@arm.com wrote: >>> From: Srinath Parvathaneni <srinath.parvathaneni@arm.com> >>> >>> diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c >>> index f11eccc1bc1..b8a02ab9972 100644 >>> --- a/gdb/aarch64-linux-tdep.c >>> +++ b/gdb/aarch64-linux-tdep.c >>> @@ -2734,6 +2741,14 @@ aarch64_linux_report_signal_info (struct gdbarch *gdbarch, >>> uiout->field_string ("logical-tag", hex_string (ltag)); >>> } >>> } >>> + /* For POE SEGSEGV, show additional information. */ >> >> Is this really supposed to be POE SEGSEGV or is it a typo? >> > > For now, in my knowledge, AARCH64_SEGV_PKUERR is only used for POE. > However, it will also be used soon for another upcoming feature. > I would recommend to either simply eliminate the comment, or make it more clear like > > /* For memory permission faults, e.g. due to a permission overlay > restriction when feature POE is enabled. */ > > Matthieu Sorry, I may not have been clear, but I was referring specifically to the SEGSEGV. Should it be SIGSEGV instead? ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3 2/5] [PATCH 2/5] gdb: Improve SIGSEGV diagnostics for POE faults 2026-07-22 23:11 ` Luis @ 2026-07-23 9:03 ` Srinath Parvathaneni 2026-07-25 7:39 ` Luis 0 siblings, 1 reply; 22+ messages in thread From: Srinath Parvathaneni @ 2026-07-23 9:03 UTC (permalink / raw) To: Luis, Matthieu Longo, gdb-patches Cc: guinevere, thiago.bauermann, Ezra Sitorus, simark [-- Attachment #1: Type: text/plain, Size: 2829 bytes --] > >>>> + /* For POE SEGSEGV, show additional information. */ >>> >>> Is this really supposed to be POE SEGSEGV or is it a typo? >>> >> >> For now, in my knowledge, AARCH64_SEGV_PKUERR is only used for POE. >> However, it will also be used soon for another upcoming feature. >> I would recommend to either simply eliminate the comment, or make it more clear like >> >> /* For memory permission faults, e.g. due to a permission overlay >> restriction when feature POE is enabled. */ >> >> Matthieu > >Sorry, I may not have been clear, but I was referring specifically to >the SEGSEGV. Should it be SIGSEGV instead? Yes Luis, that's a typo. It should be SIGSEGV instead of SEGSEGV, thanks for spotting it, I will update in the re-spin. Regarding the comment itself, while SIGSEGV already implies a memory fault, AARCH64_SEGV_PKUERR is currently only generated for Permission Overlay violations. I think something like following would be more accurate description. /* Additional information for SIGSEGV caused by a permission overlay violation. */ Regards, Sri. ________________________________ From: Luis <luis.machado.foss@gmail.com> Sent: 23 July 2026 00:11 To: Matthieu Longo <Matthieu.Longo@arm.com>; Srinath Parvathaneni <Srinath.Parvathaneni@arm.com>; gdb-patches@sourceware.org <gdb-patches@sourceware.org> Cc: guinevere@redhat.com <guinevere@redhat.com>; thiago.bauermann@linaro.org <thiago.bauermann@linaro.org>; Ezra Sitorus <Ezra.Sitorus@arm.com>; simark@simark.ca <simark@simark.ca> Subject: Re: [PATCH v3 2/5] [PATCH 2/5] gdb: Improve SIGSEGV diagnostics for POE faults On 22/07/2026 10:41, Matthieu Longo wrote: > On 21/07/2026 21:30, Luis wrote: >> On 14/07/2026 21:15, srinath.parvathaneni@arm.com wrote: >>> From: Srinath Parvathaneni <srinath.parvathaneni@arm.com> >>> >>> diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c >>> index f11eccc1bc1..b8a02ab9972 100644 >>> --- a/gdb/aarch64-linux-tdep.c >>> +++ b/gdb/aarch64-linux-tdep.c >>> @@ -2734,6 +2741,14 @@ aarch64_linux_report_signal_info (struct gdbarch *gdbarch, >>> uiout->field_string ("logical-tag", hex_string (ltag)); >>> } >>> } >>> + /* For POE SEGSEGV, show additional information. */ >> >> Is this really supposed to be POE SEGSEGV or is it a typo? >> > > For now, in my knowledge, AARCH64_SEGV_PKUERR is only used for POE. > However, it will also be used soon for another upcoming feature. > I would recommend to either simply eliminate the comment, or make it more clear like > > /* For memory permission faults, e.g. due to a permission overlay > restriction when feature POE is enabled. */ > > Matthieu Sorry, I may not have been clear, but I was referring specifically to the SEGSEGV. Should it be SIGSEGV instead? [-- Attachment #2: Type: text/html, Size: 9143 bytes --] ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3 2/5] [PATCH 2/5] gdb: Improve SIGSEGV diagnostics for POE faults 2026-07-23 9:03 ` Srinath Parvathaneni @ 2026-07-25 7:39 ` Luis 0 siblings, 0 replies; 22+ messages in thread From: Luis @ 2026-07-25 7:39 UTC (permalink / raw) To: Srinath Parvathaneni, Matthieu Longo, gdb-patches Cc: guinevere, thiago.bauermann, Ezra Sitorus, simark On 23/07/2026 10:03, Srinath Parvathaneni wrote: > > > >>>> + /* For POE SEGSEGV, show additional information. */ > >>> > >>> Is this really supposed to be POE SEGSEGV or is it a typo? > >>> > >> > >> For now, in my knowledge, AARCH64_SEGV_PKUERR is only used for POE. > >> However, it will also be used soon for another upcoming feature. > >> I would recommend to either simply eliminate the comment, or make it > more clear like > >> > >> /* For memory permission faults, e.g. due to a permission overlay > >> restriction when feature POE is enabled. */ > >> > >> Matthieu > > > >Sorry, I may not have been clear, but I was referring specifically to > >the SEGSEGV. Should it be SIGSEGV instead? > > Yes Luis, that's a typo. It should be SIGSEGV instead of SEGSEGV, thanks for > spotting it, I will update in the re-spin. > Got it. Thanks. > Regarding the comment itself, while SIGSEGV already implies a memory fault, > AARCH64_SEGV_PKUERR is currently only generated for Permission Overlay > violations. I think something like following would be more accurate > description. > > /* Additional information for SIGSEGV caused by a permission overlay > violation. */ Yes, I think that reads a bit better. ^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v3 3/5] [PATCH 3/5] gdbserver/aarch64: Add POR_EL0 register support 2026-07-14 20:15 [PATCH v3 0/5] gdb/aarch64: Add POR_EL0 register support for FEAT_S1POE srinath.parvathaneni 2026-07-14 20:15 ` [PATCH v3 1/5] [PATCH 1/5] " srinath.parvathaneni 2026-07-14 20:15 ` [PATCH v3 2/5] [PATCH 2/5] gdb: Improve SIGSEGV diagnostics for POE faults srinath.parvathaneni @ 2026-07-14 20:15 ` srinath.parvathaneni 2026-07-14 20:15 ` [PATCH v3 4/5] [PATCH 4/5] gdb/aarch64: Add core file support for FEAT_S1POE srinath.parvathaneni 2026-07-14 20:15 ` [PATCH v3 5/5] [PATCH 5/5] gdb/testsuite: Add FEAT_S1POE testcases srinath.parvathaneni 4 siblings, 0 replies; 22+ messages in thread From: srinath.parvathaneni @ 2026-07-14 20:15 UTC (permalink / raw) To: gdb-patches Cc: luis.machado.foss, guinevere, thiago.bauermann, Ezra.Sitorus, Matthieu.Longo, simark, Srinath Parvathaneni From: Srinath Parvathaneni <srinath.parvathaneni@arm.com> Add support for transferring the POR_EL0 register between the Linux kernel and GDB during remote debugging. This patch implements the necessary `fill` and `store` operations using the `NT_ARM_POE` regset, allowing GDB to read and write the POR_EL0 register when debugging a remote target that supports FEAT_S1POE. Approved-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org> --- gdbserver/linux-aarch64-low.cc | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/gdbserver/linux-aarch64-low.cc b/gdbserver/linux-aarch64-low.cc index a2588a6e2a9..d326341e63a 100644 --- a/gdbserver/linux-aarch64-low.cc +++ b/gdbserver/linux-aarch64-low.cc @@ -45,6 +45,7 @@ #include "linux-aarch32-tdesc.h" #include "linux-aarch64-tdesc.h" #include "nat/aarch64-fpmr-linux.h" +#include "nat/aarch64-poe-linux.h" #include "nat/aarch64-gcs-linux.h" #include "nat/aarch64-mte-linux-ptrace.h" #include "nat/aarch64-scalable-linux-ptrace.h" @@ -250,6 +251,26 @@ aarch64_store_fpregset (struct regcache *regcache, const void *buf) supply_register (regcache, AARCH64_FPCR_REGNUM, ®set->fpcr); } +/* Fill BUF with the POE (POR_EL0) register set from the regcache. */ + +static void +aarch64_fill_por_el0_regset (struct regcache *regcache, void *buf) +{ + uint64_t *poe = (uint64_t *) buf; + int poe_regnum = find_regno (regcache->tdesc, "por_el0"); + collect_register (regcache, poe_regnum, poe); +} + +/* Store the POE (POR_EL0) register set to regcache. */ + +static void +aarch64_store_por_el0_regset (struct regcache *regcache, const void *buf) +{ + uint64_t *poe = (uint64_t *) buf; + int poe_regnum = find_regno (regcache->tdesc, "por_el0"); + supply_register (regcache, poe_regnum, poe); +} + /* Fill BUF with the FPMR register set from the regcache. */ static void @@ -901,6 +922,10 @@ static struct regset_info aarch64_regsets[] = { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_FPMR, 0, OPTIONAL_REGS, aarch64_fill_fpmr_regset, aarch64_store_fpmr_regset }, + /* POE register (POR_EL0). */ + { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_POE, + 0, OPTIONAL_REGS, + aarch64_fill_por_el0_regset, aarch64_store_por_el0_regset }, /* TLS register. */ { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_TLS, 0, OPTIONAL_REGS, @@ -980,6 +1005,10 @@ aarch64_adjust_register_sets (const struct aarch64_features &features) if (features.fpmr) regset->size = sizeof (uint64_t); break; + case NT_ARM_POE: + if (features.poe) + regset->size = sizeof (uint64_t); + break; default: gdb_assert_not_reached ("Unknown register set found."); } @@ -1010,6 +1039,7 @@ aarch64_target::low_arch_setup () 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; + features.poe = linux_get_hwcap2 (pid, 8) & HWCAP2_POE; /* Scalable Matrix Extension feature and size check. */ if (linux_get_hwcap2 (pid, 8) & HWCAP2_SME) -- 2.43.0 ^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v3 4/5] [PATCH 4/5] gdb/aarch64: Add core file support for FEAT_S1POE 2026-07-14 20:15 [PATCH v3 0/5] gdb/aarch64: Add POR_EL0 register support for FEAT_S1POE srinath.parvathaneni ` (2 preceding siblings ...) 2026-07-14 20:15 ` [PATCH v3 3/5] [PATCH 3/5] gdbserver/aarch64: Add POR_EL0 register support srinath.parvathaneni @ 2026-07-14 20:15 ` srinath.parvathaneni 2026-07-21 20:14 ` Luis 2026-07-14 20:15 ` [PATCH v3 5/5] [PATCH 5/5] gdb/testsuite: Add FEAT_S1POE testcases srinath.parvathaneni 4 siblings, 1 reply; 22+ messages in thread From: srinath.parvathaneni @ 2026-07-14 20:15 UTC (permalink / raw) To: gdb-patches Cc: luis.machado.foss, guinevere, thiago.bauermann, Ezra.Sitorus, Matthieu.Longo, simark, Srinath Parvathaneni From: Srinath Parvathaneni <srinath.parvathaneni@arm.com> Add support for POR_EL0 dumps/reads for core files and also the support for reading the POE values in the signal frame. --- gdb/aarch64-linux-tdep.c | 50 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c index b8a02ab9972..94ed3234009 100644 --- a/gdb/aarch64-linux-tdep.c +++ b/gdb/aarch64-linux-tdep.c @@ -171,6 +171,7 @@ #define AARCH64_ZT_MAGIC 0x5a544e01 #define AARCH64_GCS_MAGIC 0x47435300 #define AARCH64_FPMR_MAGIC 0x46504d52 +#define AARCH64_POE_MAGIC 0x504f4530 /* Defines for the extra_context that follows an AARCH64_EXTRA_MAGIC. */ #define AARCH64_EXTRA_DATAP_OFFSET 8 @@ -220,6 +221,9 @@ /* FPMR constants. */ #define AARCH64_FPMR_OFFSET 8 +/* POE constants. */ +#define AARCH64_POE_OFFSET 8 + /* Holds information about the signal frame. */ struct aarch64_linux_sigframe { @@ -273,6 +277,10 @@ struct aarch64_linux_sigframe /* FPMR value. */ CORE_ADDR fpmr = 0; + /* True if we have an POE entry in the signal context, false otherwise. */ + bool poe_available = false; + /* FPMR value. */ + CORE_ADDR poe = 0; }; /* Read an aarch64_ctx, returning the magic value, and setting *SIZE to the @@ -605,6 +613,22 @@ aarch64_linux_read_signal_frame_info (const frame_info_ptr &this_frame, section += size; break; } + case AARCH64_POE_MAGIC: + { + gdb_byte buf[8]; + if (target_read_memory (section + AARCH64_POE_OFFSET, + buf, 8) != 0) + { + warning (_("Failed to read the POE section address from the" + " signal frame context.")); + section += size; + break; + } + signal_frame.poe = extract_unsigned_integer (buf, 8, byte_order); + signal_frame.poe_available = true; + section += size; + break; + } case AARCH64_EXTRA_MAGIC: { /* Extra is always the last valid section in reserved and points to @@ -775,6 +799,13 @@ aarch64_linux_sigframe_init (const struct tramp_frame *self, signal_frame.fpmr); } + /* Handle POE register. */ + if (tdep->has_poe () && signal_frame.poe_available) + { + trad_frame_set_reg_value (this_cache, tdep->poe_regnum, + signal_frame.poe); + } + /* 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 () @@ -828,6 +859,7 @@ aarch64_linux_sigframe_prev_arch (const frame_info_ptr &this_frame, 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; + features.poe = signal_frame.poe_available; struct gdbarch_info info; info.bfd_arch_info = bfd_lookup_arch (bfd_arch_aarch64, bfd_mach_aarch64); @@ -1655,6 +1687,23 @@ aarch64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch, &aarch64_linux_fpmr_regset, "FPMR", cb_data); } + if (tdep->has_poe ()) + { + const struct regcache_map_entry poe_regmap[] = + { + { 1, tdep->poe_regnum, sizeof (uint64_t) }, + { 0 } + }; + + const struct regset aarch64_linux_poe_regset = + { + poe_regmap, regcache_supply_regset, regcache_collect_regset + }; + + cb (".reg-aarch-poe", sizeof (uint64_t), sizeof (uint64_t), + &aarch64_linux_poe_regset, "POE register", cb_data); + } + if (tdep->has_pauth ()) { /* Create this on the fly in order to handle the variable location. */ @@ -1768,6 +1817,7 @@ aarch64_linux_core_read_description (struct gdbarch *gdbarch, features.gcs = features.gcs_linux = hwcap & AARCH64_HWCAP_GCS; features.mte = hwcap2 & AARCH64_HWCAP2_MTE; features.fpmr = hwcap2 & AARCH64_HWCAP2_FPMR; + features.poe = hwcap2 & AARCH64_HWCAP2_POE; /* Handle the TLS section. */ asection *tls = bfd_get_section_by_name (abfd, ".reg-aarch-tls"); -- 2.43.0 ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3 4/5] [PATCH 4/5] gdb/aarch64: Add core file support for FEAT_S1POE 2026-07-14 20:15 ` [PATCH v3 4/5] [PATCH 4/5] gdb/aarch64: Add core file support for FEAT_S1POE srinath.parvathaneni @ 2026-07-21 20:14 ` Luis 0 siblings, 0 replies; 22+ messages in thread From: Luis @ 2026-07-21 20:14 UTC (permalink / raw) To: srinath.parvathaneni, gdb-patches Cc: guinevere, thiago.bauermann, Ezra.Sitorus, Matthieu.Longo, simark On 14/07/2026 21:15, srinath.parvathaneni@arm.com wrote: > From: Srinath Parvathaneni <srinath.parvathaneni@arm.com> > > Add support for POR_EL0 dumps/reads for core files and also the > support for reading the POE values in the signal frame. You might want to split this patch in two for corefile and signal frame support, or update the patch subject to clarify what this is doing. > --- > gdb/aarch64-linux-tdep.c | 50 ++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 50 insertions(+) > > diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c > index b8a02ab9972..94ed3234009 100644 > --- a/gdb/aarch64-linux-tdep.c > +++ b/gdb/aarch64-linux-tdep.c > @@ -171,6 +171,7 @@ > #define AARCH64_ZT_MAGIC 0x5a544e01 > #define AARCH64_GCS_MAGIC 0x47435300 > #define AARCH64_FPMR_MAGIC 0x46504d52 > +#define AARCH64_POE_MAGIC 0x504f4530 > > /* Defines for the extra_context that follows an AARCH64_EXTRA_MAGIC. */ > #define AARCH64_EXTRA_DATAP_OFFSET 8 > @@ -220,6 +221,9 @@ > /* FPMR constants. */ > #define AARCH64_FPMR_OFFSET 8 > > +/* POE constants. */ > +#define AARCH64_POE_OFFSET 8 > + > /* Holds information about the signal frame. */ > struct aarch64_linux_sigframe > { > @@ -273,6 +277,10 @@ struct aarch64_linux_sigframe > /* FPMR value. */ > CORE_ADDR fpmr = 0; > > + /* True if we have an POE entry in the signal context, false otherwise. */ Nit: s/an POE/a POE > + bool poe_available = false; > + /* FPMR value. */ Spurious change above? > + CORE_ADDR poe = 0; > }; > > /* Read an aarch64_ctx, returning the magic value, and setting *SIZE to the > @@ -605,6 +613,22 @@ aarch64_linux_read_signal_frame_info (const frame_info_ptr &this_frame, > section += size; > break; > } > + case AARCH64_POE_MAGIC: > + { > + gdb_byte buf[8]; > + if (target_read_memory (section + AARCH64_POE_OFFSET, > + buf, 8) != 0) > + { > + warning (_("Failed to read the POE section address from the" > + " signal frame context.")); > + section += size; > + break; > + } > + signal_frame.poe = extract_unsigned_integer (buf, 8, byte_order); > + signal_frame.poe_available = true; > + section += size; > + break; > + } > case AARCH64_EXTRA_MAGIC: > { > /* Extra is always the last valid section in reserved and points to > @@ -775,6 +799,13 @@ aarch64_linux_sigframe_init (const struct tramp_frame *self, > signal_frame.fpmr); > } > > + /* Handle POE register. */ > + if (tdep->has_poe () && signal_frame.poe_available) > + { > + trad_frame_set_reg_value (this_cache, tdep->poe_regnum, > + signal_frame.poe); Is the identation off above? > + } > + > /* 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 () > @@ -828,6 +859,7 @@ aarch64_linux_sigframe_prev_arch (const frame_info_ptr &this_frame, > 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; > + features.poe = signal_frame.poe_available; > > struct gdbarch_info info; > info.bfd_arch_info = bfd_lookup_arch (bfd_arch_aarch64, bfd_mach_aarch64); > @@ -1655,6 +1687,23 @@ aarch64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch, > &aarch64_linux_fpmr_regset, "FPMR", cb_data); > } > > + if (tdep->has_poe ()) > + { > + const struct regcache_map_entry poe_regmap[] = > + { > + { 1, tdep->poe_regnum, sizeof (uint64_t) }, > + { 0 } > + }; > + > + const struct regset aarch64_linux_poe_regset = > + { > + poe_regmap, regcache_supply_regset, regcache_collect_regset > + }; > + > + cb (".reg-aarch-poe", sizeof (uint64_t), sizeof (uint64_t), > + &aarch64_linux_poe_regset, "POE register", cb_data); > + } > + > if (tdep->has_pauth ()) > { > /* Create this on the fly in order to handle the variable location. */ > @@ -1768,6 +1817,7 @@ aarch64_linux_core_read_description (struct gdbarch *gdbarch, > features.gcs = features.gcs_linux = hwcap & AARCH64_HWCAP_GCS; > features.mte = hwcap2 & AARCH64_HWCAP2_MTE; > features.fpmr = hwcap2 & AARCH64_HWCAP2_FPMR; > + features.poe = hwcap2 & AARCH64_HWCAP2_POE; > > /* Handle the TLS section. */ > asection *tls = bfd_get_section_by_name (abfd, ".reg-aarch-tls"); ^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v3 5/5] [PATCH 5/5] gdb/testsuite: Add FEAT_S1POE testcases 2026-07-14 20:15 [PATCH v3 0/5] gdb/aarch64: Add POR_EL0 register support for FEAT_S1POE srinath.parvathaneni ` (3 preceding siblings ...) 2026-07-14 20:15 ` [PATCH v3 4/5] [PATCH 4/5] gdb/aarch64: Add core file support for FEAT_S1POE srinath.parvathaneni @ 2026-07-14 20:15 ` srinath.parvathaneni 2026-07-21 20:38 ` Luis 2026-07-25 6:23 ` Thiago Jung Bauermann 4 siblings, 2 replies; 22+ messages in thread From: srinath.parvathaneni @ 2026-07-14 20:15 UTC (permalink / raw) To: gdb-patches Cc: luis.machado.foss, guinevere, thiago.bauermann, Ezra.Sitorus, Matthieu.Longo, simark, Srinath Parvathaneni From: Srinath Parvathaneni <srinath.parvathaneni@arm.com> Add testcases for POR_EL0 register access, SIGSEGV diagnostics, fix-and-continue support (updating $por_el0 after SIGSEGV and continuing with signal 0), and core file support. --- gdb/testsuite/gdb.arch/aarch64-poe-core.exp | 101 ++++++++++++++++++ gdb/testsuite/gdb.arch/aarch64-poe-sigsegv. | 0 gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.c | 52 +++++++++ .../gdb.arch/aarch64-poe-sigsegv.exp | 58 ++++++++++ gdb/testsuite/gdb.arch/aarch64-poe.c | 29 +++++ gdb/testsuite/gdb.arch/aarch64-poe.exp | 46 ++++++++ gdb/testsuite/lib/gdb.exp | 55 ++++++++++ 7 files changed, 341 insertions(+) create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe-core.exp create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe-sigsegv. create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.c create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.exp create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe.c create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe.exp diff --git a/gdb/testsuite/gdb.arch/aarch64-poe-core.exp b/gdb/testsuite/gdb.arch/aarch64-poe-core.exp new file mode 100644 index 00000000000..22fe646ac43 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-poe-core.exp @@ -0,0 +1,101 @@ +# Copyright (C) 2026 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 POR_EL0. + +proc check_poe_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" \ + "Protection Key Violation while accessing address ${::hex} with Protection Key = ${::decimal}\\." \ + "#0 ${::hex} in main \\(.*\\) at .*" \ + ".*buf\\\[0\\\] = 42;.*"] \ + "load core file"] + } { + untested "failed to load core file" + return -1 + } + + # Check the value of POR_EL0 in the core file. + gdb_test "print/x \$por_el0" " = 0x37" \ + "por_el0 contents from core file" +} + +require allow_aarch64_poe_tests + +standard_testfile aarch64-poe-sigsegv.c + +if {[prepare_for_testing "failed to prepare" ${testfile} ${srcfile}]} { + return +} + +set binfile [standard_output_file ${testfile}] + +if {![runto_main]} { + return +} + +set poe_crash_re [multi_line \ + "Program received signal SIGSEGV, Segmentation fault" \ + "Protection Key Violation while accessing address ${::hex} with Protection Key = ${::decimal}\\." \ + ".*buf\\\[0\\\] = 42;.*"] + +gdb_test_multiple "continue" "run to POE crash" { + -re "$poe_crash_re$gdb_prompt $" { + pass $gdb_test_name + } + + -re ".*exited with code 01.*$gdb_prompt $" { + unsupported "POE userspace support unavailable" + return + } +} + +# 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_poe_core_file $gcore_filename + } +} else { + fail "gcore corefile not generated" +} + +if {$core_generated} { + clean_restart + gdb_load ${binfile} + with_test_prefix "native corefile" { + check_poe_core_file $core_filename + } +} else { + untested "native corefile not generated" +} diff --git a/gdb/testsuite/gdb.arch/aarch64-poe-sigsegv. b/gdb/testsuite/gdb.arch/aarch64-poe-sigsegv. new file mode 100644 index 00000000000..e69de29bb2d diff --git a/gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.c b/gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.c new file mode 100644 index 00000000000..5346e51dbba --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.c @@ -0,0 +1,52 @@ +/* This test program is part of GDB, the GNU debugger. + + Copyright 2026 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 AArch64's POE Extension. */ + +/* This test is based on the Linux kernel documentation for Memory + Protection Keys, including the arm64 Permission Overlay Extension + (FEAT_S1POE) support described in + Documentation/core-api/protection-keys.rst. */ + +#define _GNU_SOURCE +#include <sys/mman.h> +#include <unistd.h> + +int +main (void) +{ + long pagesize = sysconf (_SC_PAGESIZE); + + int *buf = mmap (NULL, pagesize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (buf == MAP_FAILED) + return 1; + + int pkey = pkey_alloc (0, 0); + if (pkey == -1) + return 1; + + if (pkey_mprotect (buf, pagesize, PROT_READ | PROT_WRITE, pkey) == -1) + return 1; + + if (pkey_set (pkey, PKEY_DISABLE_WRITE) == -1) + return 1; + + buf[0] = 42; /* Expect SIGSEGV POE violation. */ + + return 0; +} diff --git a/gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.exp b/gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.exp new file mode 100644 index 00000000000..19eafd14a2f --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.exp @@ -0,0 +1,58 @@ +# Copyright (C) 2026 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/>. + +# Test a binary that supports FEAT_S1POE and exposes POR_EL0 register. + +global hex +global decimal + +if {![allow_aarch64_poe_tests]} { + unsupported "AArch64 POE not supported" + return +} + +standard_testfile +if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } { + return +} + +if {![runto_main]} { + return +} + +# Display POE violation SIGSEGV error message. +set poe_sigsegv_re [multi_line \ + "Program received signal SIGSEGV, Segmentation fault" \ + "Protection Key Violation while accessing address ${hex} with Protection Key = ${decimal}"] + +gdb_test_multiple "continue" "display POE violation information" { + -re "$poe_sigsegv_re.*$gdb_prompt $" { + pass $gdb_test_name + } + -re ".*exited with code 01.*$gdb_prompt $" { + unsupported "POE userspace support unavailable" + return + } +} + +# Fix the POE permissions (set $por_el0) and continue without delivering SIGSEGV. +gdb_test_no_output "set \$por_el0 = 0x57" \ + "allow write access by updating POR_EL0" + +gdb_test_multiple "signal 0" "continue after fixing POE fault" { + -re ".*exited normally.*$gdb_prompt $" { + pass $gdb_test_name + } +} diff --git a/gdb/testsuite/gdb.arch/aarch64-poe.c b/gdb/testsuite/gdb.arch/aarch64-poe.c new file mode 100644 index 00000000000..2c95dc2a99b --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-poe.c @@ -0,0 +1,29 @@ +/* This test program is part of GDB, the GNU debugger. + + Copyright 2026 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 AArch64's POE Extension. */ + +/* This test is based on the Linux kernel documentation for Memory + Protection Keys, including the arm64 Permission Overlay Extension + (FEAT_S1POE) support described in + Documentation/core-api/protection-keys.rst. */ + +int +main (void) +{ + return 0; +} diff --git a/gdb/testsuite/gdb.arch/aarch64-poe.exp b/gdb/testsuite/gdb.arch/aarch64-poe.exp new file mode 100644 index 00000000000..5aea0350d81 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-poe.exp @@ -0,0 +1,46 @@ +# Copyright (C) 2026 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/>. + +# Test a binary that uses POE and exposed POR_EL0 register. + +global hex +global decimal + +if {![allow_aarch64_poe_tests]} { + unsupported "AArch64 POE not supported" + return +} + +standard_testfile +if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } { + return +} + +if {![runto_main]} { + return +} + +# Validate the presence of the POE register. +gdb_test "info registers por_el0" \ + "por_el0\[ \t\]+$hex.*" \ + "info register por_el0 available" + +gdb_test "p \$por_el0" \ + "\\$\[0-9\]+ = .*" \ + "print por_el0 available" + +gdb_test "p/x \$por_el0" \ + "\\$\[0-9\]+ = ${hex}" \ + "print/x por_el0 available" diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp index a40c87c6727..ab573f50660 100644 --- a/gdb/testsuite/lib/gdb.exp +++ b/gdb/testsuite/lib/gdb.exp @@ -5645,6 +5645,61 @@ gdb_caching_proc allow_aarch64_gcs_tests {} { return $allow_gcs_tests } +# Run a test on the target to see if it supports AArch64 POE extensions. +# Return 1 if so, 0 if it does not. Note this causes a restart of GDB. + +gdb_caching_proc allow_aarch64_poe_tests {} { + global srcdir subdir gdb_prompt inferior_exited_re + + set me "allow_aarch64_poe_tests" + + if {![is_aarch64_target]} { + return 0 + } + + # Compile a program that tests the POE feature. + set src { + #include <stdbool.h> + #include <sys/auxv.h> + + /* Feature check for POE feature. */ + #ifndef HWCAP2_POE + #define HWCAP2_POE (1ULL << 63) + #endif + + int main (void) { + bool poe_supported = getauxval (AT_HWCAP2) & HWCAP2_POE; + + /* Return success if POE is supported. */ + return !poe_supported; + } + } + + if {![gdb_simple_compile $me $src executable]} { + return 0 + } + + # Compilation succeeded so now run it via gdb. + set allow_poe_tests 0 + clean_restart + gdb_load $obj + gdb_run_cmd + gdb_expect { + -re ".*$inferior_exited_re normally.*${gdb_prompt} $" { + verbose -log "\n$me: poe support detected" + set allow_poe_tests 1 + } + -re ".*$inferior_exited_re with code 01.*${gdb_prompt} $" { + verbose -log "\n$me: poe support not detected" + } + } + gdb_exit + + remote_file build delete $obj + verbose "$me: returning $allow_poe_tests" 2 + return $allow_poe_tests +} + # A helper that compiles a test case to see if __int128 is supported. proc gdb_int128_helper {lang} { return [gdb_can_simple_compile "i128-for-$lang" { -- 2.43.0 ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3 5/5] [PATCH 5/5] gdb/testsuite: Add FEAT_S1POE testcases 2026-07-14 20:15 ` [PATCH v3 5/5] [PATCH 5/5] gdb/testsuite: Add FEAT_S1POE testcases srinath.parvathaneni @ 2026-07-21 20:38 ` Luis 2026-07-25 6:23 ` Thiago Jung Bauermann 1 sibling, 0 replies; 22+ messages in thread From: Luis @ 2026-07-21 20:38 UTC (permalink / raw) To: srinath.parvathaneni, gdb-patches Cc: guinevere, thiago.bauermann, Ezra.Sitorus, Matthieu.Longo, simark On 14/07/2026 21:15, srinath.parvathaneni@arm.com wrote: > From: Srinath Parvathaneni <srinath.parvathaneni@arm.com> > > Add testcases for POR_EL0 register access, SIGSEGV diagnostics, fix-and-continue > support (updating $por_el0 after SIGSEGV and continuing with signal 0), and core > file support. > --- > gdb/testsuite/gdb.arch/aarch64-poe-core.exp | 101 ++++++++++++++++++ > gdb/testsuite/gdb.arch/aarch64-poe-sigsegv. | 0 > gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.c | 52 +++++++++ > .../gdb.arch/aarch64-poe-sigsegv.exp | 58 ++++++++++ > gdb/testsuite/gdb.arch/aarch64-poe.c | 29 +++++ > gdb/testsuite/gdb.arch/aarch64-poe.exp | 46 ++++++++ > gdb/testsuite/lib/gdb.exp | 55 ++++++++++ > 7 files changed, 341 insertions(+) > create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe-core.exp > create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe-sigsegv. Stray file. Please remove. > create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.c > create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.exp > create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe.c > create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe.exp > > diff --git a/gdb/testsuite/gdb.arch/aarch64-poe-core.exp b/gdb/testsuite/gdb.arch/aarch64-poe-core.exp > new file mode 100644 > index 00000000000..22fe646ac43 > --- /dev/null > +++ b/gdb/testsuite/gdb.arch/aarch64-poe-core.exp > @@ -0,0 +1,101 @@ > +# Copyright (C) 2026 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 POR_EL0. > + > +proc check_poe_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" \ > + "Protection Key Violation while accessing address ${::hex} with Protection Key = ${::decimal}\\." \ > + "#0 ${::hex} in main \\(.*\\) at .*" \ > + ".*buf\\\[0\\\] = 42;.*"] \ > + "load core file"] > + } { > + untested "failed to load core file" > + return -1 > + } > + > + # Check the value of POR_EL0 in the core file. > + gdb_test "print/x \$por_el0" " = 0x37" \ > + "por_el0 contents from core file" > +} > + > +require allow_aarch64_poe_tests > + > +standard_testfile aarch64-poe-sigsegv.c > + > +if {[prepare_for_testing "failed to prepare" ${testfile} ${srcfile}]} { > + return > +} > + > +set binfile [standard_output_file ${testfile}] > + > +if {![runto_main]} { > + return > +} > + > +set poe_crash_re [multi_line \ > + "Program received signal SIGSEGV, Segmentation fault" \ > + "Protection Key Violation while accessing address ${::hex} with Protection Key = ${::decimal}\\." \ > + ".*buf\\\[0\\\] = 42;.*"] > + > +gdb_test_multiple "continue" "run to POE crash" { > + -re "$poe_crash_re$gdb_prompt $" { > + pass $gdb_test_name > + } > + > + -re ".*exited with code 01.*$gdb_prompt $" { > + unsupported "POE userspace support unavailable" > + return > + } > +} > + > +# 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_poe_core_file $gcore_filename > + } > +} else { > + fail "gcore corefile not generated" > +} > + > +if {$core_generated} { > + clean_restart > + gdb_load ${binfile} > + with_test_prefix "native corefile" { > + check_poe_core_file $core_filename > + } > +} else { > + untested "native corefile not generated" > +} > diff --git a/gdb/testsuite/gdb.arch/aarch64-poe-sigsegv. b/gdb/testsuite/gdb.arch/aarch64-poe-sigsegv. > new file mode 100644 > index 00000000000..e69de29bb2d > diff --git a/gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.c b/gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.c > new file mode 100644 > index 00000000000..5346e51dbba > --- /dev/null > +++ b/gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.c > @@ -0,0 +1,52 @@ > +/* This test program is part of GDB, the GNU debugger. > + > + Copyright 2026 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 AArch64's POE Extension. */ > + > +/* This test is based on the Linux kernel documentation for Memory > + Protection Keys, including the arm64 Permission Overlay Extension > + (FEAT_S1POE) support described in > + Documentation/core-api/protection-keys.rst. */ > + > +#define _GNU_SOURCE > +#include <sys/mman.h> > +#include <unistd.h> > + > +int > +main (void) > +{ > + long pagesize = sysconf (_SC_PAGESIZE); > + > + int *buf = mmap (NULL, pagesize, PROT_READ | PROT_WRITE, > + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); > + if (buf == MAP_FAILED) > + return 1; > + > + int pkey = pkey_alloc (0, 0); > + if (pkey == -1) > + return 1; > + > + if (pkey_mprotect (buf, pagesize, PROT_READ | PROT_WRITE, pkey) == -1) > + return 1; > + > + if (pkey_set (pkey, PKEY_DISABLE_WRITE) == -1) > + return 1; > + > + buf[0] = 42; /* Expect SIGSEGV POE violation. */ > + > + return 0; > +} > diff --git a/gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.exp b/gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.exp > new file mode 100644 > index 00000000000..19eafd14a2f > --- /dev/null > +++ b/gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.exp > @@ -0,0 +1,58 @@ > +# Copyright (C) 2026 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/>. > + > +# Test a binary that supports FEAT_S1POE and exposes POR_EL0 register. > + > +global hex > +global decimal > + > +if {![allow_aarch64_poe_tests]} { > + unsupported "AArch64 POE not supported" > + return > +} Please use... require allow_aarch64_poe_tests ... instead. > + > +standard_testfile > +if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } { > + return > +} > + > +if {![runto_main]} { > + return > +} > + > +# Display POE violation SIGSEGV error message. > +set poe_sigsegv_re [multi_line \ > + "Program received signal SIGSEGV, Segmentation fault" \ > + "Protection Key Violation while accessing address ${hex} with Protection Key = ${decimal}"] > + > +gdb_test_multiple "continue" "display POE violation information" { > + -re "$poe_sigsegv_re.*$gdb_prompt $" { > + pass $gdb_test_name > + } > + -re ".*exited with code 01.*$gdb_prompt $" { > + unsupported "POE userspace support unavailable" > + return > + } > +} > + > +# Fix the POE permissions (set $por_el0) and continue without delivering SIGSEGV. > +gdb_test_no_output "set \$por_el0 = 0x57" \ > + "allow write access by updating POR_EL0" > + > +gdb_test_multiple "signal 0" "continue after fixing POE fault" { > + -re ".*exited normally.*$gdb_prompt $" { > + pass $gdb_test_name > + } > +} > diff --git a/gdb/testsuite/gdb.arch/aarch64-poe.c b/gdb/testsuite/gdb.arch/aarch64-poe.c > new file mode 100644 > index 00000000000..2c95dc2a99b > --- /dev/null > +++ b/gdb/testsuite/gdb.arch/aarch64-poe.c > @@ -0,0 +1,29 @@ > +/* This test program is part of GDB, the GNU debugger. > + > + Copyright 2026 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 AArch64's POE Extension. */ > + > +/* This test is based on the Linux kernel documentation for Memory > + Protection Keys, including the arm64 Permission Overlay Extension > + (FEAT_S1POE) support described in > + Documentation/core-api/protection-keys.rst. */ > + > +int > +main (void) > +{ > + return 0; > +} > diff --git a/gdb/testsuite/gdb.arch/aarch64-poe.exp b/gdb/testsuite/gdb.arch/aarch64-poe.exp > new file mode 100644 > index 00000000000..5aea0350d81 > --- /dev/null > +++ b/gdb/testsuite/gdb.arch/aarch64-poe.exp > @@ -0,0 +1,46 @@ > +# Copyright (C) 2026 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/>. > + > +# Test a binary that uses POE and exposed POR_EL0 register. > + > +global hex > +global decimal > + > +if {![allow_aarch64_poe_tests]} { > + unsupported "AArch64 POE not supported" > + return > +} Please use... require allow_aarch64_poe_tests ... instead. > + > +standard_testfile > +if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } { > + return > +} > + > +if {![runto_main]} { > + return > +} > + > +# Validate the presence of the POE register. > +gdb_test "info registers por_el0" \ > + "por_el0\[ \t\]+$hex.*" \ > + "info register por_el0 available" > + > +gdb_test "p \$por_el0" \ > + "\\$\[0-9\]+ = .*" \ > + "print por_el0 available" > + > +gdb_test "p/x \$por_el0" \ > + "\\$\[0-9\]+ = ${hex}" \ > + "print/x por_el0 available" > diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp > index a40c87c6727..ab573f50660 100644 > --- a/gdb/testsuite/lib/gdb.exp > +++ b/gdb/testsuite/lib/gdb.exp > @@ -5645,6 +5645,61 @@ gdb_caching_proc allow_aarch64_gcs_tests {} { > return $allow_gcs_tests > } > > +# Run a test on the target to see if it supports AArch64 POE extensions. > +# Return 1 if so, 0 if it does not. Note this causes a restart of GDB. > + > +gdb_caching_proc allow_aarch64_poe_tests {} { > + global srcdir subdir gdb_prompt inferior_exited_re > + > + set me "allow_aarch64_poe_tests" > + > + if {![is_aarch64_target]} { > + return 0 > + } > + > + # Compile a program that tests the POE feature. > + set src { > + #include <stdbool.h> > + #include <sys/auxv.h> > + > + /* Feature check for POE feature. */ > + #ifndef HWCAP2_POE > + #define HWCAP2_POE (1ULL << 63) > + #endif > + > + int main (void) { > + bool poe_supported = getauxval (AT_HWCAP2) & HWCAP2_POE; > + > + /* Return success if POE is supported. */ > + return !poe_supported; > + } > + } > + > + if {![gdb_simple_compile $me $src executable]} { > + return 0 > + } > + > + # Compilation succeeded so now run it via gdb. > + set allow_poe_tests 0 > + clean_restart > + gdb_load $obj > + gdb_run_cmd > + gdb_expect { > + -re ".*$inferior_exited_re normally.*${gdb_prompt} $" { > + verbose -log "\n$me: poe support detected" > + set allow_poe_tests 1 > + } > + -re ".*$inferior_exited_re with code 01.*${gdb_prompt} $" { > + verbose -log "\n$me: poe support not detected" > + } > + } > + gdb_exit > + > + remote_file build delete $obj > + verbose "$me: returning $allow_poe_tests" 2 > + return $allow_poe_tests > +} > + > # A helper that compiles a test case to see if __int128 is supported. > proc gdb_int128_helper {lang} { > return [gdb_can_simple_compile "i128-for-$lang" { Are we missing a signal frame test? ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3 5/5] [PATCH 5/5] gdb/testsuite: Add FEAT_S1POE testcases 2026-07-14 20:15 ` [PATCH v3 5/5] [PATCH 5/5] gdb/testsuite: Add FEAT_S1POE testcases srinath.parvathaneni 2026-07-21 20:38 ` Luis @ 2026-07-25 6:23 ` Thiago Jung Bauermann 1 sibling, 0 replies; 22+ messages in thread From: Thiago Jung Bauermann @ 2026-07-25 6:23 UTC (permalink / raw) To: srinath.parvathaneni Cc: gdb-patches, luis.machado.foss, guinevere, Ezra.Sitorus, Matthieu.Longo, simark <srinath.parvathaneni@arm.com> writes: > From: Srinath Parvathaneni <srinath.parvathaneni@arm.com> > > Add testcases for POR_EL0 register access, SIGSEGV diagnostics, fix-and-continue > support (updating $por_el0 after SIGSEGV and continuing with signal 0), and core > file support. > --- > gdb/testsuite/gdb.arch/aarch64-poe-core.exp | 101 ++++++++++++++++++ > gdb/testsuite/gdb.arch/aarch64-poe-sigsegv. | 0 > gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.c | 52 +++++++++ > .../gdb.arch/aarch64-poe-sigsegv.exp | 58 ++++++++++ > gdb/testsuite/gdb.arch/aarch64-poe.c | 29 +++++ > gdb/testsuite/gdb.arch/aarch64-poe.exp | 46 ++++++++ > gdb/testsuite/lib/gdb.exp | 55 ++++++++++ > 7 files changed, 341 insertions(+) > create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe-core.exp > create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe-sigsegv. > create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.c > create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe-sigsegv.exp > create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe.c > create mode 100644 gdb/testsuite/gdb.arch/aarch64-poe.exp I don't have anything to add to Luis' comments, except to say that the tests now pass in my testing. Thanks for making the changes! PS: I don't have comments on patches 2-4. -- Thiago (he/him) ^ permalink raw reply [flat|nested] 22+ messages in thread
end of thread, other threads:[~2026-07-25 18:45 UTC | newest] Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-07-14 20:15 [PATCH v3 0/5] gdb/aarch64: Add POR_EL0 register support for FEAT_S1POE srinath.parvathaneni 2026-07-14 20:15 ` [PATCH v3 1/5] [PATCH 1/5] " srinath.parvathaneni 2026-07-21 19:53 ` Luis 2026-07-25 6:20 ` Thiago Jung Bauermann 2026-07-25 7:37 ` Luis 2026-07-25 18:44 ` Thiago Jung Bauermann 2026-07-21 20:25 ` Luis 2026-07-23 9:29 ` Srinath Parvathaneni 2026-07-25 6:13 ` Thiago Jung Bauermann 2026-07-25 7:29 ` Luis 2026-07-14 20:15 ` [PATCH v3 2/5] [PATCH 2/5] gdb: Improve SIGSEGV diagnostics for POE faults srinath.parvathaneni 2026-07-21 20:30 ` Luis 2026-07-22 9:41 ` Matthieu Longo 2026-07-22 23:11 ` Luis 2026-07-23 9:03 ` Srinath Parvathaneni 2026-07-25 7:39 ` Luis 2026-07-14 20:15 ` [PATCH v3 3/5] [PATCH 3/5] gdbserver/aarch64: Add POR_EL0 register support srinath.parvathaneni 2026-07-14 20:15 ` [PATCH v3 4/5] [PATCH 4/5] gdb/aarch64: Add core file support for FEAT_S1POE srinath.parvathaneni 2026-07-21 20:14 ` Luis 2026-07-14 20:15 ` [PATCH v3 5/5] [PATCH 5/5] gdb/testsuite: Add FEAT_S1POE testcases srinath.parvathaneni 2026-07-21 20:38 ` Luis 2026-07-25 6:23 ` Thiago Jung Bauermann
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox