Repository navigation
Description
Building with RUSTFLAGS="-C target_cpu=cortex-a72" statically enables the target_feature="aes", target_feature="crc", target_feature="pmuv3", and target_feature="sha2". However, at least the crypto features AES, CRC, and SHA2 are optional on this CPU. The definition for this target is wrong. See the upstream LLVM bug: llvm/llvm-project#90365.
The main consequence is that crypto libraries that use cfg(target_feature = ...) feature detection for these hardware instructions are getting miscompiled, causing the programs to, at best, crash with an illegal instruction exception. This particular affects Raspberry Pi users compiling with RUSTLFAGS=-target-cpu=native. From briansmith/ring#1858 (comment):
$ rustc --print cfg --target=aarch64-unknown-linux-gnu -C target_cpu=cortex-a72 | grep feature target_feature="aes" target_feature="crc" target_feature="neon" target_feature="pmuv3" target_feature="sha2"Without
-C target_cpu=cortex-a72we get the correct feature flags:$ rustc --print cfg --target=aarch64-unknown-linux-gnu | grep feature target_feature="neon"
I verified this is an issue on Rust 1.61 stable, 1.78 stable, and rustc 1.80.0-nightly (6e1d947 2024-05-10).
Although some crypto libraries may work around this issue, these workarounds have negative consequences. In the case of ring's workaround, the result of the workaround is bloat and worse performance on all AArch64 CPUs that actually are guaranteed to have the crypto extensions (except on Fuchsia, Windows, and macOS).
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsBlocked By LLVM
Activity
apiraino commentedon May 13, 2024
WG-prioritization assigning priority (Zulip discussion).
Since in our support list this arch has the most support:
@rustbot label -I-prioritize +P-critical
briansmith commentedon May 17, 2024
From today's comment in the upstream LLVM issue:
Assuming that is accurate, there are a few interesting things:
-C target_cputo be safe by default, rustc cannot delegate its defaults to LLVM. rustc should turn off feature flags for optional features by default. Basically-C target_cpuis generally not a memory-safe option. This should be documented retroactively for old versions and fixed for newer versions.briansmith commentedon May 17, 2024
Also, from the LLVM issue:
So, one workaround would be to use that. But, I don't see rustc providing a mechanism to choose the ARM architecture level instead of a specific CPU.
15 remaining items
workingjubilee commentedon Oct 2, 2024
heads up crabs, llvm/llvm-project#95694 got merged, I'll let y'all figure out how to backport that or what.
briansmith commentedon Oct 4, 2024
This isn't fixed upstream though? Maybe the
target-cpu=nativecase is fixed thanks to your effort but thetarget_cpu=cortex-a72case is still an issue.nikic commentedon Oct 4, 2024
The
-C target-cpu=nativebehavior was a plain bug. The-C target-cpu=cortext-a72behavior is just a difference in opinion.workingjubilee commentedon Oct 4, 2024
@briansmith It's a separate issue because it applies to almost every single
-Ctarget-cputhat isn't-Ctarget-cpu=nativefor AArch64. It requires a different solution, even if it is fixed upstream by successfully armwrestling LLVM into changing every single CPU def.RalfJung commentedon Feb 3, 2025
Does
-C target_cpu=cortex-a72+nofeat(mentioned in the LLVM issue) help here, or is+nofeata clang thing?briansmith commentedon Feb 3, 2025
For reference, there is now a more general LLVM issue (llvm/llvm-project#113008).
I want to emphasize that because of this, and the more general issue, basically
cfg(target_feature)andstd::arch::is_aarch64_feature_detected()are safety hazards for very common usage scenerios, and we (my projects) have to limit our use of them. But then that also limits which OSs we support because we have to write OS-specific code for feature detection for the crypto extensions.The problem with expecting this to be dealt with upstream for existing targets is that it is a substantial compatibility-breaking change for them, and/or a performance regression for some existing projects.
Thus, I do think we should try to work around it in the Rust compiler, instead of waiting for it to be fixed upstream.
briansmith commentedon Feb 3, 2025
So it seems like
nofeat"works" in the sense that it causes the-C target_cputo be (very much not silently) ignored.RalfJung commentedon Feb 3, 2025
Hm maybe I understood the
+nofeatcomment. Someone also says in that issueSo maybe it has to be
+noaesor+nocryptoor so? But I can't get that to emittarget_feature="neon"which I assume is what you are looking for.briansmith commentedon Feb 3, 2025
it seems like when you pass
-C target_cpuit disables all the default target features and then enables the target features for the given CPU? This seems to be why "neon" doesn't get enabled when we pass in an invalid/unrecognized target_cpu like-C target_cpu=cortex-a72+nofeator-C target_cpu=cortex-a72+nocrypto.By the way, the issue I am working around is that some (Linux?) distributors compile all packages with
-C target_cpu=cortex-a72for Raspberry Pi. So I have to make sure I ignore the crypto extensions reported by#[cfg(target_feature)]for AArch64 because otherwise people think the bug is in ring.RalfJung commentedon Feb 3, 2025
If it's a distro-level issue, it should be possible for them to add further flags / adjust their target spec to avoid enabling features that the Raspberry Pi does not have.
LLVM hasn't cared much for compatibility around target features before, so this is not a very strong argument.
Anyway I don't have a strong opinion for how to fix this; I just know the rustc implementation of this so I know it would be a quite terrible hack to work around this on the rustc side, and not very sustainable.