Arm architecture support

Jump to: navigation, search

For a non-openSUSE specific overview, you can check:

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).

It is highly recommended to use elfutils 0.181 and GCC 10.2 and later to enable Pointer Authentication, because they include required fixes!

-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.

With GCC9+, you can enable BTI support by adding -mbranch-protection=bti or -mbranch-protection=standard (which also enable Pointer Auth). User-space & Kernel support are enabled since snapshot 20200821 (kernel 5.8). Tumbleweed has enabled the BTI config options in the kernel, but userspace did not enable it yet:

CONFIG_ARM64_BTI=y
CONFIG_ARM64_BTI_KERNEL=y
CONFIG_CC_HAS_BRANCH_PROT_PAC_RET_BTI=y

When supported by your hardware, you should fine this line in the kernel log:

CPU features: detected: Branch Target Identification

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.

It is highly recommended to use GCC 10.2 and later or LLVM 10.0.1 or later, to enable BTI, because they include lots of fixes!

For user-sapce, -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

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). But a bug make the boot to hang atm. See: https://gitlab.com/cki-project/kernel-ark/-/merge_requests/1393/diffs?commit_id=7d618ce2e9c1bfd89e4efec78396c0d2c6974ad8

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.