Arm architecture support
For a non-openSUSE specific overview, you can check:
- Armv8-A Architecture support in GNU toolchain (ARM website)
- Armv8-A Architecture support in LLVM toolchain (ARM website)
- Table of Arm Architecture features vs Kernel Versions (Arm website)
On openSUSE, the various arm functions can be:
- Supported:
- if package version support it, and option is enabled at build time (and your hardware support it)
- Unsupported:
- if package version does not support it
- if option is disabled at build time
ARMv8.0 mandatory features
ARMv8.0 - FP (Floating point)
Version: 15.1+ Enabled by default.
ARMv8.0 - SIMD (Single Instruction Multiple Data)
Version: 15.1+ Enabled by default.
Additional/Optional ARMv8 features
Here are options which are optional for ARMv8.0, or part of later architectures (8.1, 8.2, etc.). Some of the options can be detected at runtime and used only if available, with minor overhead, and thus can be safely enabled, but others would break older hardware and are not enabled by default, but can be used manually, if required.
ARMv8.1 - CRC32
Version: 15.1+ Disabled by default.
CRC32 is an extension optional in ARMv8.0, mandatory in ARMv8.1, to compute a Cyclic Redundancy Check (CRC) calculation.
With GCC, you need to pass +crc to -march flag.
When supported by your hardware, you should fine this line in the kernel log:
CPU features: detected: CRC32 instructions
ARMv8.1 - PAN (Privileged Access Never)
Version: 15.1+ Enabled by default.
PAN is an additional security mechanism against possible software attacks. It prevents the kernel or hypervisor from accessing user-space (EL0) memory directly.
This option will cause any unprotected (not using copy_to_user et al) memory access to fail with a permission fault.
When supported by your hardware, you should fine this line in the kernel log:
CPU features: detected: Privileged Access Never
ARMv8.1 - LSE (Large System Extension) atomics
Version: Tumbleweed Fully enabled by default.
The atomic instructions can be used as an alternative to Load-exclusive/Store-exclusive (ldx/stx) instructions (ARMv8.0), to improve the implementation of atomic memory updates in very large systems. LSE atomics are generally fairer than the old atomics. Also LSE atomics have been found to be quicker (lower mean time needed) and more consistent in performance (lower variance between runs too).
With GCC 9.3.1+, you can enable/disable out-of-line atomics with -moutline-atomics and -mno-outline-atomics that choose the correct path at runtime.
With GCC 10.1+, out-of-line atomics are enabled by default, so Tumbleweed have it enabled since snapshot 20200602.
With GCC13, LSE (and LSE2) is added to to libatomic, which disable outline atomics, and use LSE ifuncs for 1-8 byte atomics (and LSE2 ifuncs for 16-byte atomics).
If you want to test it with qemu and your host does not support it, use -cpu max and disable kvm (slow), please note that you need qemu 3.0, or later.
When supported by your hardware, you should fine this line in the kernel log:
CPU features: detected: LSE atomic instructions
ARMv8.2 - SVE (Scalable Vector Extension)
Version: 15.1+ Disabled by default, requires gcc8 with explicit option.
SVE is the next-generation SIMD instruction set for AArch64, which includes a scalable vector length.
With GCC8+, you can enable SVE support by adding +sve to -march=xyz or to -mcpu=xyz. It is not enabled by default since SVE is only supported on ARMv8.2+ hardware.
If you want to test it with qemu and your host does not support it, use -cpu max and disable kvm (slow), please note that you need qemu 3.1, or later.
When supported by your hardware, you should fine those lines in the kernel log:
CPU features: detected: Scalable Vector Extension SVE: maximum available vector length 256 bytes per vector SVE: default vector length 64 bytes per vector
ARMv8.2 - FP16/FPHP (Half-precision Floating Point)
Version: 15.1+ Disabled by default, requires gcc7 with explicit option.
FP16 is a half precision floating point format (on 16 bits), optional on ARMv8.2.
With GCC7+, you can enable FP16 support by adding +fp16 to -march=xyz or to -mcpu=xyz. It is not enabled by default since FP16 is only supported on some ARMv8.2+ hardware.
ARMv8.3 - PAuth (Pointer Authentication)
On ARMv8.3 hardware and newer, it allows to sign and authenticate pointers against secret keys. The purpose of this pointer authentication is to mitigate ROP attacks and other potential buffer-overrun-style attacks.
For more information, you can watch the video from SUSE Labs 2019 about Pointer Authentication: https://www.youtube.com/watch?v=iW3mXDSijSQ
When supported by your hardware, you should fine those lines in the kernel log:
CPU features: detected: Address authentication (architected algorithm) CPU features: detected: Generic authentication (architected algorithm)
If you want to test it with qemu and your host does not support it, use -M virt -cpu max and disable kvm (slow), please note that you need qemu 4.0, or later. To improve the speed of the Pointer Auth algorithm, you can use -M virt -cpu max,pauth-impdef=true
Kernel 5.12 adds the ability to disable Pointer Authentication with arm64.nopauth. See: commit f8da5752
Pointer Authentication - User-space support
Version: 15.2+ Disabled by default.
Version: Tumbleweed Enabled by default.
User-space support is enabled on Tumbleweed and Leap 15.2 kernels.
To use it, you just need to pass -mbranch-protection=pac-ret[+leaf] or -mbranch-protection=standard (which also enables BTI) option to GCC (older GCC can use -msign-return-address, but this is deprecated in GCC9).
-mbranch-protection=standard has been enabled in Factory for aarch64 on Friday 20th of November 2020. First Tumbleweed snapshot including this option is snapshot 20201129. If a package does not build properly with this option, please report it upstream. As a workaround, you can remove this option as done for llvm7: https://build.opensuse.org/request/show/850379
Pointer Authentication - Kernel-space support
Version: Tumbleweed Enabled by default
Kernel-space support has been merged in kernel 5.7 and thus is not supported in Leap yet, but it is enabled by default on Tumbleweed, since snapshot 20200612.
ARMv8.3/8.4 - NV (Nested Virtualization)
Patches for Nested Virtualization on ARMv8.3+ are not included in upstream kernel yet.
ARMv8.4 - LSE2 (Large System Extension) atomics
Version: Tumbleweed Fully enabled by default.
GCC13 adds support for LSE and LSE2 to libatomic.
This disable outline atomics, and use LSE ifuncs for 1-8 byte atomics and LSE2 ifuncs for 16-byte atomics.
On Neoverse V1, 16-byte atomics are ~4x faster due to avoiding locks.
Qemu does not support it yet (version 7.2.0)
When supported by your hardware, you should fine this line in the kernel log:
CPU features: detected: LSE2 atomic instructions
ARMv8.5 - BTI (Branch Target Identification)
Version: Tumbleweed Enabled by default (in kernel and in user-space)
On ARMv8.5 hardware and newer, it allows to sign and authenticate Branch Target against secret keys.
You can enable BTI support by adding -mbranch-protection=bti or -mbranch-protection=standard (standard also enables Pointer Auth and will enable GCS once available). Enabled in kernel config since snapshot 20200821 (kernel 5.8).
When supported by your hardware, you should fine this line in the kernel log:
CPU features: detected: Branch Target Identification
For user-space, -mbranch-protection=standard has been enabled in Factory for aarch64 on Friday 20th of November 2020. First Tumbleweed snapshot including this option is snapshot 20201129. If a package does not build properly with this option, please report it upstream. As a workaround, you can remove this option as done for llvm7: https://build.opensuse.org/request/show/850110
Kernel 5.12 adds the ability to disable BTI with arm64.nobti. See: commit 93ad55b7852
If you want to test it with qemu and your host does not support it, use -M virt -cpu max and disable kvm (slow), please note that you need qemu 4.0, or later.
ARMv8.5 - MTE (Memory Tagging Extension)
The Arm MTE implements lock and key access to memory. Locks can be set on memory and keys provided during memory access. If the key matches the lock, the access is permitted. If it does not match, an error is reported.
More details can be found on Arm_Memory_Tagging_Extension_Whitepaper.pdf
MTE will allow heap and stack tagging. Only heap tagging is ready for now.
Heap tagging
Heap tagging enablement requires Kernel configuration updates:
CONFIG_ARM64_MTE
in 5.10+: User-space enablement for heap tagging (In Tumbleweed since snapshot 20210108)CONFIG_KASAN_HW_TAGS
in 5.11+: In-kernel enablement for heap tagging (synchronous only). In 5.13+, MTE asynchronous support for KASan has been added. Asynchronous is faster but does not allow precise identification of the illegal access.
User-space support
Version: Tumbleweed User-space enabled since snapshot 20210223
glibc 2.33+ (in Tumbleweed since snapshot 20210221) checks hwcap to make use of it, or not, depending on the hardware capabilities. glibc 2.34 will include some performance enhancements: http://patches-tcwg.linaro.org/cover/50130/
You also need to set an env variable for glibc:
export GLIBC_TUNABLES=âglibc.mem.tagging=Xâ
with X a value set according to upstream documentation:
This tunable takes a value between 0 and 255 and acts as a bitmask that enables various capabilities. Bit 0 (the least significant bit) causes the malloc subsystem to allocate tagged memory, with each allocation being assigned a random tag. Bit 1 enables precise faulting mode for tag violations on systems that support deferred tag violation reporting. This may cause programs to run more slowly. Other bits are currently reserved.
You also need to set another env variable for Python:
- Python pymalloc is not compatible with MTE yet, so python should not use pymalloc, but the glibc malloc. For this, you can set the PYTHONMALLOC env variable:
export PYTHONMALLOC=malloc
Upstream bug report: https://bugs.python.org/issue43593
Please note that GCC10+ and LLVM9+ are required to compile glibc/kernel with MTE.
When supported by your hardware, you should fine this line in the kernel log:
CPU features: detected: Memory Tagging Extension
If you want to test it with qemu, please note that you need qemu 5.1, or later. Then, you need to explicitly enable it with -M virt,mte=on -cpu max and disable kvm (slow).
You can try the following simple test program written in C: (no gcc option required as it uses features already enabled in glibc)
#include <stdlib.h> /* Generate an MTE fault for a UAF (Use-After-Free): * - Use qemu with '-machine virt,mte=on -cpu max' _without_ kvm * - export GLIBC_TUNABLES="glibc.mem.tagging=X" * where X has the following meanings: * 0 Disabled (default) * 1 asynchronous mode - useful to at least test and understand * 3 synchronous mode - what we probably want for openSUSE * Details on: https://sourceware.org/pipermail/libc-alpha/attachments/20201218/cf93aeb4/attachment.bin */ int main(){ int* a; a = malloc(sizeof(int)); *a = 42; free(a); *a = 24; /* Should fail here */ return 0; }
In-kernel support
Version: Tumbleweed
In-kernel enabled in kernel-debug
since snapshot 20210504
MTE in-kernel support is done via KASAN with hardware based tag.
This is enabled in Tumbleweed as part of kernel-debug
enablement.
Please note that GCC10+ and LLVM9+ are required to compile glibc/kernel with MTE.
When supported by your hardware, you should fine this line in the kernel log:
[ 0.000000] CPU features: detected: Memory Tagging Extension [ 0.000000] kasan: KernelAddressSanitizer initialized
If you want to test it with qemu, please note that you need qemu 5.1, or later. Then, you need to explicitly enable it with -M virt,mte=on -cpu max
and disable kvm (slow).
Upstream documentation on KASAN: https://www.kernel.org/doc/html/latest/dev-tools/kasan.html
Stack tagging
Not applicable for Linux.
HyperV - Guest support
On aarch64, Tumbleweed supports HyperV as a guest, since snapshot 20211125 (kernel 5.15).
It also supports SecureBoot since shim is now signed by Microsoft for aarch64, since snapshot 20240923.
Optional 32-bit support on Armv8.x
Some Armv8.x SoCs does support 32-bit
Some Armv8.x SoCs support 32-bit, such as Ampere eMAG, HoneyComb_LX2K and more. Thus, you can use it to build and run 32-bit in userspace and kernel.
When supported by your hardware, you should fine those lines in the kernel log:
kernel: CPU features: detected: 32-bit EL0 Support kernel: CPU features: detected: 32-bit EL1 Support
Some Armv8.x SoCs do not support 32-bit, at all
Some Armv8.x SoCs do not support 32-bit at all, such as ThunderX and ThunderX2 machines.
Some Armv8.x SoCs support 32-bit only in userspace
Some Armv8.x SoC, such as the N1SDP, support 32-bit only in userspace.
When supported by your hardware, you should fine this line in the kernel log:
kernel: CPU features: detected: 32-bit EL0 Support
On such a system, if you try to start qemu with kvm enabled with a 32-bit kernel, you will get the following error:
qemu-system-aarch64: can't apply global host-arm-cpu.aarch64=off: 'aarch64' feature cannot be disabled unless KVM is enabled and 32-bit EL1 is supported
The openSUSE:Factory:ARM project is configured to use an aarch64 kernel for building armv6l and armv7l packages and images.
Armv6/7 information
ARM 32-bit KVM host support removed in kernel 5.7
Arm 32-bit KVM host support has been removed in kernel 5.7 with commit 541ad0150ca4aa663a2
So, you need to use Leap if you need 32-bit KVM host support.