]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
aarch64: Add support for menable-sysreg-checking flag.
authorSrinath Parvathaneni <srinath.parvathaneni@arm.com>
Mon, 20 Oct 2025 13:07:55 +0000 (14:07 +0100)
committerSrinath Parvathaneni <srinath.parvathaneni@arm.com>
Mon, 20 Oct 2025 13:26:08 +0000 (14:26 +0100)
Hi All,

In the current Binutils we have disabled the feature gating for sysreg
by default and we have introduced a new flag "-menable-sysreg-checking"
to renable some of this checking.

However in GCC, we have disabled the feature gating of sysreg to read/write
intrinsics __arm_[wr]sr* and we have not added any mechanism to check the
feature gating if needed similar to Binutils.

This patch adds the support for the flag "-menable-sysreg-checking" which
renables some of the feature checking of sysreg to read/write intrinsics
__arm_[wr]sr* similar to Binutils.

For inline assembly, sysreg checks are not performed by CC1 and are
instead delegated to the assembler. By default, the assembler does not
perform these checks either. With this patch, the -menable-sysreg-checking
flag passed to the compiler will also be propagated to the assembler,
enabling sysreg checking for inline assembly.

gcc/ChangeLog:

* config/aarch64/aarch64-elf.h (ASM_SPEC): Update the macro.
* config/aarch64/aarch64.cc (aarch64_valid_sysreg_name_p):
Add feature check condition.
(aarch64_retrieve_sysreg): Likewise.
* config/aarch64/aarch64.opt (menable-sysreg-checking):
Define new flag.
* doc/invoke.texi (menable-sysreg-checking): Document new flag.

gcc/testsuite/ChangeLog:

* gcc.target/aarch64/acle/asm-inlined-sysreg-1.c: New test.
* gcc.target/aarch64/acle/asm-inlined-sysreg-2.c: Likewise.
* gcc.target/aarch64/acle/rwsr-gated-1.c: Likewise.
* gcc.target/aarch64/acle/rwsr-gated-2.c: Likewise.
* lib/target-supports.exp
(check_effective_target_aarch64_sysreg_guarding_ok): Check
assembler support of -menable-sysreg-checking flag.

gcc/config/aarch64/aarch64-elf.h
gcc/config/aarch64/aarch64.cc
gcc/config/aarch64/aarch64.opt
gcc/doc/invoke.texi
gcc/testsuite/gcc.target/aarch64/acle/asm-inlined-sysreg-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/acle/asm-inlined-sysreg-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/acle/rwsr-gated-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/acle/rwsr-gated-2.c [new file with mode: 0644]
gcc/testsuite/lib/target-supports.exp

index f6ebb723715ad0f092f14f06e733eff2b4fe3a1e..57c5a319d7c731d4d51e5638b6ea507c225659f4 100644 (file)
 #define ASM_SPEC "\
 %{mbig-endian:-EB} \
 %{mlittle-endian:-EL} \
+%{menable-sysreg-checking} \
 %(asm_cpu_spec)" \
 ASM_MABI_SPEC
 #endif
index f28d670b55f0316001d627ed70369ade2ad762da..b86064148feab6036035d93deb06d1ed3e245963 100644 (file)
@@ -31663,7 +31663,9 @@ aarch64_valid_sysreg_name_p (const char *regname)
   const sysreg_t *sysreg = aarch64_lookup_sysreg_map (regname);
   if (sysreg == NULL)
     return aarch64_is_implem_def_reg (regname);
-  return true;
+
+  return (!aarch64_enable_sysreg_guarding
+         || ((~aarch64_isa_flags & sysreg->arch_reqs) == 0));
 }
 
 /* Return the generic sysreg specification for a valid system register
@@ -31686,6 +31688,9 @@ aarch64_retrieve_sysreg (const char *regname, bool write_p, bool is128op)
   if ((write_p && (sysreg->properties & F_REG_READ))
       || (!write_p && (sysreg->properties & F_REG_WRITE)))
     return NULL;
+  if (aarch64_enable_sysreg_guarding
+      && ((~aarch64_isa_flags & sysreg->arch_reqs) != 0))
+    return NULL;
   return sysreg->encoding;
 }
 
index 8aae953e60d1bcac9ea372c95e19881b9ed3e6d5..fc3f632d93b14e5e390186192904a989c2757b78 100644 (file)
@@ -82,6 +82,11 @@ mbig-endian
 Target RejectNegative Mask(BIG_END)
 Assume target CPU is configured as big endian.
 
+menable-sysreg-checking
+Target RejectNegative Var(aarch64_enable_sysreg_guarding) Init(0)
+Generates an error message if an attempt is made to access a system register
+which is not available on the target architecture.
+
 mgeneral-regs-only
 Target RejectNegative Mask(GENERAL_REGS_ONLY) Save
 Generate code which uses only the general registers.
index 9c64acb5daf10dd0528f917143bb6cba7c3a97c3..189b2662012c92d001e18b91d793ce509b330d2e 100644 (file)
@@ -826,6 +826,7 @@ Objective-C and Objective-C++ Dialects}.
 
 @emph{AArch64 Options} (@ref{AArch64 Options})
 @gccoptlist{-mabi=@var{name}  -mbig-endian  -mlittle-endian
+-menable-sysreg-checking
 -mgeneral-regs-only
 -mcmodel=tiny  -mcmodel=small  -mcmodel=large
 -mstrict-align  -mno-strict-align
@@ -22159,6 +22160,11 @@ The @samp{ilp32} model is deprecated.
 Generate big-endian code.  This is the default when GCC is configured for an
 @samp{aarch64_be-*-*} target.
 
+@opindex menable-sysreg-checking
+@item -menable-sysreg-checking
+Generates an error message if an attempt is made to access a system register
+which is not available on the target architecture.
+
 @opindex mgeneral-regs-only
 @item -mgeneral-regs-only
 Generate code which uses only the general-purpose registers.  This will prevent
diff --git a/gcc/testsuite/gcc.target/aarch64/acle/asm-inlined-sysreg-1.c b/gcc/testsuite/gcc.target/aarch64/acle/asm-inlined-sysreg-1.c
new file mode 100644 (file)
index 0000000..3912c75
--- /dev/null
@@ -0,0 +1,28 @@
+/* { dg-do assemble { target elf } } */
+/* { dg-require-effective-target aarch64_sysreg_guarding_ok } */
+/* { dg-additional-options "-march=armv8-a -menable-sysreg-checking -###" } */
+/* Ensure the system registers passed through inline assembly are rejected by
+   assembler when guarding is enabled through "-menable-sysreg-checking" command
+   line flag and proper feature flags are not passed.  */
+
+#define INPUT 1
+
+static inline void
+read_write_using_sysreg (int mode)
+{
+  int b;
+
+  /* write to gcspr_el0.  */
+  asm volatile ("msr gcspr_el0, %[r]" ::[r] "r" (mode):);
+
+  /* Read from gcspr_el0.  */
+  asm volatile ("mrs %[r], gcspr_el0" :[r] "=r"(b)::);
+}
+
+int main()
+{
+  read_write_using_sysreg (INPUT);
+  return 0;
+}
+/* { dg-prune-output "^(COMPILER_PATH|LIBRARY_PATH|COLLECT_GCC_OPTIONS)=.*" } */
+/* { dg-message ".*\/.*as .*-menable-sysreg-checking" "assembler options" {target aarch64-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.target/aarch64/acle/asm-inlined-sysreg-2.c b/gcc/testsuite/gcc.target/aarch64/acle/asm-inlined-sysreg-2.c
new file mode 100644 (file)
index 0000000..e6c9600
--- /dev/null
@@ -0,0 +1,29 @@
+/* { dg-do assemble { target elf} } */
+/* { dg-require-effective-target aarch64_sysreg_guarding_ok } */
+/* { dg-options "-save-temps -O2 -menable-sysreg-checking -march=armv8-a+gcs" } */
+/* Ensure that system registers passed through inline assembly are properly
+   gated on the feature flags, when the guarding is enabled through
+   "-menable-sysreg-checking" command line flag.  */
+
+#define INPUT 1
+
+static inline void
+read_write_using_sysreg (int mode)
+{
+  int b;
+
+  /* write to gcspr_el0.  */
+  asm volatile ("msr gcspr_el0, %[r]" ::[r] "r" (mode):);
+
+  /* Read from gcspr_el0.  */
+  asm volatile ("mrs %[r], gcspr_el0" :[r] "=r"(b)::);
+}
+
+int main()
+{
+  read_write_using_sysreg (INPUT);
+  return 0;
+}
+
+/* { { dg-final { scan-assembler {msr\s+gcspr_el0,\s+x0} } } */
+/* { { dg-final { scan-assembler {mrs\s+x0,\s+gcspr_el0} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/acle/rwsr-gated-1.c b/gcc/testsuite/gcc.target/aarch64/acle/rwsr-gated-1.c
new file mode 100644 (file)
index 0000000..35a5459
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-menable-sysreg-checking -march=armv8-a+sve2+sme" } */
+/* Ensure that system registers are properly gated on the feature flags, when
+   the guarding is enabled through "-menable-sysreg-checking" command line
+   flag.  */
+
+#include <arm_acle.h>
+
+uint64_t
+foo (uint64_t a)
+{
+  __arm_wsr64 ("zcr_el1", a); /* { { dg-final { scan-assembler "msr\ts3_0_c1_c2_0, x0" } } */
+  return __arm_rsr64 ("smcr_el1"); /* { { dg-final { scan-assembler "mrs\tx0, s3_0_c1_c2_6" } } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/acle/rwsr-gated-2.c b/gcc/testsuite/gcc.target/aarch64/acle/rwsr-gated-2.c
new file mode 100644 (file)
index 0000000..49e9769
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-menable-sysreg-checking -march=armv8-a" } */
+/* Ensure the system registers are rejected by compiler when guarding is
+   enabled through "-menable-sysreg-checking" command line flag and proper
+   feature flags are not passed.  */
+
+#include <arm_acle.h>
+
+uint64_t
+foo (uint64_t a)
+{
+  __arm_wsr64 ("zcr_el1", a); /* { dg-error "invalid system register name 'zcr_el1'" } */
+  return __arm_rsr64 ("smcr_el1"); /* { dg-error "invalid system register name 'smcr_el1'" } */
+}
index 4ee8d12362de2ceaf3d3c3f9a1ff5de4b05680ee..2d45ddaadc0f7018389e876f4f89d511172d2c44 100644 (file)
@@ -12573,6 +12573,16 @@ foreach { aarch64_ext } $exts_sve2 {
     }]
 }
 
+proc check_effective_target_aarch64_sysreg_guarding_ok { } {
+    if { [istarget aarch64*-*-*] && [check_effective_target_elf] } {
+       return [check_no_compiler_messages aarch64_assembler object {
+           __asm__ ("msr\ts3_3_c9_c13_4, x0");
+       } "-menable-sysreg-checking"]
+    } else {
+       return 0
+    }
+}
+
 proc check_effective_target_aarch64_asm_sve2p1_ok { } {
     if { [istarget aarch64*-*-*] } {
        return [check_no_compiler_messages aarch64_sve2p1_assembler object {