From 4ce92328339a8ddf610cd2e371b7763cf5d25bd1 Mon Sep 17 00:00:00 2001 From: Srinath Parvathaneni Date: Mon, 20 Oct 2025 14:07:55 +0100 Subject: [PATCH] aarch64: Add support for menable-sysreg-checking flag. 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 | 1 + gcc/config/aarch64/aarch64.cc | 7 ++++- gcc/config/aarch64/aarch64.opt | 5 ++++ gcc/doc/invoke.texi | 6 ++++ .../aarch64/acle/asm-inlined-sysreg-1.c | 28 ++++++++++++++++++ .../aarch64/acle/asm-inlined-sysreg-2.c | 29 +++++++++++++++++++ .../gcc.target/aarch64/acle/rwsr-gated-1.c | 14 +++++++++ .../gcc.target/aarch64/acle/rwsr-gated-2.c | 14 +++++++++ gcc/testsuite/lib/target-supports.exp | 10 +++++++ 9 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.target/aarch64/acle/asm-inlined-sysreg-1.c create mode 100644 gcc/testsuite/gcc.target/aarch64/acle/asm-inlined-sysreg-2.c create mode 100644 gcc/testsuite/gcc.target/aarch64/acle/rwsr-gated-1.c create mode 100644 gcc/testsuite/gcc.target/aarch64/acle/rwsr-gated-2.c diff --git a/gcc/config/aarch64/aarch64-elf.h b/gcc/config/aarch64/aarch64-elf.h index f6ebb723715..57c5a319d7c 100644 --- a/gcc/config/aarch64/aarch64-elf.h +++ b/gcc/config/aarch64/aarch64-elf.h @@ -136,6 +136,7 @@ #define ASM_SPEC "\ %{mbig-endian:-EB} \ %{mlittle-endian:-EL} \ +%{menable-sysreg-checking} \ %(asm_cpu_spec)" \ ASM_MABI_SPEC #endif diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc index f28d670b55f..b86064148fe 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -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; } diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt index 8aae953e60d..fc3f632d93b 100644 --- a/gcc/config/aarch64/aarch64.opt +++ b/gcc/config/aarch64/aarch64.opt @@ -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. diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 9c64acb5daf..189b2662012 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -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 index 00000000000..3912c75b315 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/acle/asm-inlined-sysreg-1.c @@ -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 index 00000000000..e6c96005705 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/acle/asm-inlined-sysreg-2.c @@ -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 index 00000000000..35a54597cd8 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/acle/rwsr-gated-1.c @@ -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 + +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 index 00000000000..49e9769f710 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/acle/rwsr-gated-2.c @@ -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 + +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'" } */ +} diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 4ee8d12362d..2d45ddaadc0 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -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 { -- 2.47.3