[PATCH v1] aarch64: Remove guarding restrictions on system registers by default.

Alice Carlotti alice.carlotti@arm.com
Wed Jun 11 11:57:05 GMT 2025


On Wed, Jun 11, 2025 at 12:16:16PM +0100, Srinath Parvathaneni wrote:
> Hi,
> 
> On 6/11/25 10:44, Jan Beulich wrote:
> > On 11.06.2025 11:28, Srinath Parvathaneni wrote:
> > > 
> > > The current implementation of system register in assembler are
> > > guarded by following rules:
> > > 1. No restrictions.
> > > 2. Architecture version (eg: armv8.5-a)
> > > 3. Architecture features (eg:+sve)
> > > 4. Combination of both architecture version and architecture
> > >     feature (eg: armv9.5-a+profile).
> > > 5. Combination of multiple architecture features (eg: +memtag+pops).
> > > 
> > > In this patch we are removing all the above mentioned guarding
> > > restrictions and making the system registers available by default
> > > in the assembler.
> > 
> > You say what you do, but not why. That's a relevant part towards accepting
> > (or rejecting) such a change, though. Plus ...
> > 
> 
> I'm making this changes so that GNU assembler aligns with LLVM in which the
> system registers are available by default without any guarding.
> 

This isn't true - I think LLVM recently changed whether they guard newly-added
system registers, but older system registers still retain their guarding.  I
don't think LLVM's approach makes sense.

The actual reasons for this change are:

1. Many system registers are gated by architecture features that don't have a
toolchain flag, so we can't accurately determine whether a system register
should be available based upon existing flags.  We don't want to add new
toolchain flags just to enable more precise system register gating, since that
would approximately double the number of toolchain flags needed.

2. Many system register access constraints are actually quite complicated
(depending on the combination of a large number of features and runtime checks
that aren't really relevant to the compiler/assembler) so we can't model this
perfectly anyway.

3. Existing feature guards are inconsistent and often too restrictive, which
means that there is generally no set of features we can use to enable the
correct system registers without incorrectly enabling some unsupported data
processing instructions.

4. In practice, anyone making direct use of system registers is probably
already checking the constraints themselves before trying to use them, so
doesn't need the assembler getting in their way with mostly inaccurate checks.

5. We've heard from kernel developers that the strict gating of system
registers means that it generally isn't practical for them to use named system
registers.  I think they currently work around this by using the encodings
directly, bypassing the assembler.

So disabling these broken checks by default is clearly beneficial, and a
corresponding change has already been merged in GCC 15 [1].

When we first proposed this internally, it was suggested that some users might
still benefit from some checking, which is where the -menable-sysreg-checking
flag originated.  This flag is intended to report whenever a system register is
used that requires a feature or architecture version that hasn't been enabled
in the toolchain (but does have an available toolchain flag).  It would err on
the side of permissiveness when dedicated toolchain flags aren't available
(which typically means gating upon the earliest architecture version at which
the system register is allowed to be implemented).

These permissive checks will require the gating conditions to be adjusted for
many system registers (which I think isn't part of this patch).   For example,
many system registers that were introduced as part of Armv8.x-a are allowed to
be implemented in Armv8.(x-1)-a, but existing gating in Binutils tended to
require Armv8.x-a instead.

I hope this helps provide more context for our intentions; I haven't yet looked
at the implementation in this patch to see whether it matches my explanation.

Alice

[1] https://gcc.gnu.org/pipermail/gcc-patches/2025-April/681129.html


> 
> > > Also we are adding a command line flag "-menable-sysreg-checking",
> > > which enforces the current restrictions on system registers.
> > 
> > ... from that I conclude you don't really remove the restrictions (from
> > the sources), but merely don't enforce them.
> > 
> 
> Yes, you are right. I should correct my wording here. In this patch we are
> not removing the guarding restrictions on system registers but we are
> disabling those checks and they are enforced by passing mentioned
> command line option.
> 
> I will later edit the commit message accordingly.
> 
> > > But there is one exception with the default behaviour, even though we
> > > have removed all the restrictions on system registers, the 128 bit
> > > system instructions like mrrs and msrr which uses the 128 bit system
> > > registers as operands, are not available unless we pass
> > > ".arch_extension d128" directive or "+d128" flag to the assembler.
> > > 
> > > eg:
> > > 	.arch_extension d128 // For the msrr and mrrs instructions.
> > >          msrr    rcwmask_el1, x2, x3
> > >          mrrs    x2, x3, rcwmask_el1
> > > 
> > > All the current system registers *.d files are added with
> > > "-menable-sysreg-checking" flag to assembler, so that all those
> > > system registers get testing with current guarding restrictions.
> > > 
> > > Also we have tested the assembler behaviour with this patch for
> > > following scenarios:
> > > 1. sysregs with no guarding reatrictions.
> > > 2. sysregs with no guarding restrictions + "-menable-sysreg-checking".
> > > 3. sysregs with guarding restrictions + "-menable-sysreg-checking".
> > > 
> > > Regression tested for aarch64-none-elf target and found no regressions.
> > 
> > Exporting a variable from a shared library is, imo, not very nice.
> > As an aside, the variable would also better be of type bool. Just
> > that struct aarch64_option_table's respective field type doesn't
> > allow for that (which hence imposes a restriction on libopcode
> > despite being gas-internal).
> > 
> > Jan
> 
> I agree it is not ideal to exporting variable from a shared library, but the
> code related to system register checking is spread across multiple files and
> I don't see an alternative.
> 
> Also use of bool seems more appropriate but aarch64_option_table doesn't
> allow this as you have already mentioned. I tried modifying the "struct
> aarch64_option_table" but that results in lot of unnecessary code changes
> and also some code changes in common files.
> 
> I'm open to any suggestions, if there are any alternative ways to approach
> this, please let me know.
> 
> Regards,
> Srinath.


More information about the Binutils mailing list