Skip to content

[FMV] Update definition of __aarch64_cpu_features - #431

Open
Lukacma wants to merge 3 commits into
ARM-software:mainfrom
Lukacma:main
Open

Lukacma wants to merge 3 commits into
ARM-software:mainfrom
Lukacma:main

Conversation

@Lukacma

@Lukacma Lukacma commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Updates the Application Binary Interface (ABI) requirements for Function Multi-versioning (FMV) on System V platforms.

The type of the global variable __aarch64_cpu_features changes from uint64_t to a struct, aligning the specification with the LLVM and GCC implementations. New feature fields extend FMV support in line with the ACLE proposal.

The update also introduces two control fields: FEAT_EXT, which indicates the presence of an additional field in the structure, and FEAT_INIT, which indicates whether the variable has been initialized in line with LLVM and GCC implementation.

Comment thread sysvabi64/sysvabi64.rst
+-------------------+----------+
| FEAT_FLAGM | 1U << 1 |
+-------------------+----------+
| FEAT_FLAGM2 | 1U << 2 |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FEAT_FLAGM2 was redefined, but it is fixed now; however, that causes the later feature IDs to change.
We should double-check if that would break anything.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC it could make a difference if binary objects from two different compilers, one before this change, and one after are mixed in the same "link-unit" and the resolver function is global to the program rather than the TU.

I don't think we can change the assignment of existing bits, unless we tie the resolver function to the generated code. For example we could version the resolver functions and variables so that both could exist within the same program.

For the sake of one redundant bit I think we can mark it as reserved. In theory if both GCC and LLVM have used the same feature bit then we could reuse it for something else.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So for this I just copied what is implemented in both LLVM and GCC. Both have bit 4 denote FEAT_FP16FML (For LLVM it has been like this for at least 2 years). So I think the double definition of FEAT_FLAGM2 is just spec bug. I assume that is what the comment is about ?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does indeed look like a spec bug, that is disappointing that we didn't spot it earlier. I guess we trusted a big table, and concentrated on the the surrounding text.

Apologies in advance for being a pain; would you be able to split that bug fix into a separate patch, with a change-history entry https://github.com/ARM-software/abi-aa/blob/main/sysvabi64/sysvabi64.rst#212change-history

I think it is important that we get that fixed before the next ABI release and it will help to have a single commit highlighting it. It is definitely not obvious for reviewers not familiar with the implementation.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay. I split the fix into #432

Comment thread sysvabi64/sysvabi64.rst
+-------------------+----------+
| FEAT_FLAGM | 1U << 1 |
+-------------------+----------+
| FEAT_FLAGM2 | 1U << 2 |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC it could make a difference if binary objects from two different compilers, one before this change, and one after are mixed in the same "link-unit" and the resolver function is global to the program rather than the TU.

I don't think we can change the assignment of existing bits, unless we tie the resolver function to the generated code. For example we could version the resolver functions and variables so that both could exist within the same program.

For the sake of one redundant bit I think we can mark it as reserved. In theory if both GCC and LLVM have used the same feature bit then we could reuse it for something else.

Comment thread sysvabi64/sysvabi64.rst Outdated
The CPU feature table lists FEAT_FLAGM2 at both bits 2 and 3. The
duplicate shifts every subsequent documented feature by one bit,
from FEAT_FP16FML through FEAT_MOPS.

Remove the duplicate at bit 3 and decrement the subsequent bit
positions, preserving the existing gaps. Record the correction in
the change history.
Comment thread sysvabi64/sysvabi64.rst
+-------------------+------------+
| FEAT_EXT | 1ULL << 62 |
+-------------------+------------+
| FEAT_INIT | 1ULL << 63 |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FEAT_INIT is really redundant since it's an internal implementation detail that does not need to be part of the ABI. It's not used, instead the implementation just compares with zero.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I only documented what is currently implemented in both LLVM and GCC here. If we want to remove it and reuse for features, it wouldn't be backwards compatible with existing runtime libraries. Additionally, if we remove it, how would we know that the struct was initialized ? Or do we just assume that all CPUs will have at least one of these features enabled ?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There will always be several features (eg. all CPUs have FEAT_FP which is kind of redundant), so the existing libgcc implementation just checks for zero. Note there isn't an issue if you really have zero features - it just overwrites the zero with another zero... Hence adding some init bit is just over engineering something simple.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's fair. Then as long as we are okay with redesigning __aarch64_cpu_features in not backwards compatible way I can remove the field from the spec and reuse it for a feature?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I am not clear what the backwards compatibility requirements of this need to be.

Its communication between the compiler runtime library and the compiler generated code so I think they should largely be kept in sync with each other?

@Wilco1 how much do we care about this sort of thing?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm its used in the generated FMV resolvers

eg: https://godbolt.org/z/d53b9j84v requires the __init_cpu_features_resolver to initialize __aarch64_cpu_features correctly

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So if you changed the compiler runtime library to one that used different flag layout, then there would be an issue

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is why the flags are listed in the ABI spec.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I see what you mean, yeah fair enough

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assuming we want to support link compatibility with objects that have been compiled using the older layout and only one runtime library. I think we'll need to either preserve the layout of the first 64-bits [1], or use a new function name so that each layout matches the right runtime library function.

[1] There are likely some bits that have never been used by FMV. It may be possible to move these without breaking anything in practice. That's not risk free though.

Comment thread sysvabi64/sysvabi64.rst
| FEAT_INIT | 1ULL << 63 |
+-------------------+------------+

.. table:: CPU features detected in ``features2``

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to reserve FEAT_EXT2 or not yet?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's first design how to extend the field without software needing to check multiple bits (eg. use a different resolver name).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants