]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
arm64: fpsimd: Use assembler for baseline SME instructions
authorMark Rutland <mark.rutland@arm.com>
Wed, 3 Jun 2026 11:06:20 +0000 (12:06 +0100)
committerWill Deacon <will@kernel.org>
Wed, 3 Jun 2026 15:50:48 +0000 (16:50 +0100)
We currently support assemblers which do not support SME instructions,
and have macros to manually encode SME instructions. This was
necessary historically as SME support was developed before assembler
support was widely available, but things have changed:

* All currently supported versions of LLVM support baseline SME
  instructions. Building the kernel requires LLVM 15+, while LLVM 13+
  supports SME.

* GNU binutils has supported baseline SME instructions since 2.38, which
  was released on 09 February 2022. Toolchains using this or later are
  widely available. For example Debian 12 (released on 10 June 2023)
  provides binutils 2.40. Toolchains provided kernel.org provide
  binutils 2.38+ since the GCC 12.1.0 release (released between 06 May
  2022 and 17 August 2022).

* For various reasons, SME support was marked as BROKEN, and re-enabled
  in v6.16 (released on 27 July 2025). The earliest support LTS kernel
  with SME support is v6.18.y, v6.18 was tagged on 30 November 2025, and
  contemporary toolchains (GCC 15.2 and binutils 2.45) supported
  baseline SME instructions.

* Any distribution which intends to support SME will presumably have a
  toolchain that supports baseline SME instructions such that userspace
  can be built.

Considering the above, there's no practical benefit to allowing SME to
be built when the toolchain doesn't support baseline SME instructions.

Make CONFIG_ARM64_SME depend on assembler support for SME, and remove
the manual encoding of SME instructions. The various _sme_<insn> macros
are kept for now, and will be cleaned up in subsequent patches.

A couple of SME2 instructions require a more recent toolchain, and are
left as-is for now. I've looked through releases of binutils and LLVM to
find when support was added, and noted this in a comment.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Reviewed-by: Mark Brown <broonie@kernel.org>
Reviewed-by: Vladimir Murzin <vladimir.murzin@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Fuad Tabba <tabba@google.com>
Cc: James Morse <james.morse@arm.com>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Oliver Upton <oupton@kernel.org>
Cc: Will Deacon <will@kernel.org>
Signed-off-by: Will Deacon <will@kernel.org>
arch/arm64/Kconfig
arch/arm64/include/asm/fpsimdmacros.h

index fe60738e5943ba279e5571862423df4fed3db661..378e50fef247a5ae1e24369dfe64774fb3d5d162 100644 (file)
@@ -2247,10 +2247,15 @@ config ARM64_SVE
          booting the kernel.  If unsure and you are not observing these
          symptoms, you should assume that it is safe to say Y.
 
+config AS_HAS_SME
+       # Supported by LLVM 13+ and binutils 2.38+
+       def_bool $(as-instr,.arch_extension sme)
+
 config ARM64_SME
        bool "ARM Scalable Matrix Extension support"
        default y
        depends on ARM64_SVE
+       depends on AS_HAS_SME
        help
          The Scalable Matrix Extension (SME) is an extension to the AArch64
          execution state which utilises a substantial subset of the SVE
index 4ba23e493cb69eaac79127e341ae60e384f3e42d..4a9bf46e529132024706ee491d0f190e926f494b 100644 (file)
        pfalse  p\np\().b
 .endm
 
-/* SME instruction encodings for non-SME-capable assemblers */
-/* (pre binutils 2.38/LLVM 13) */
+/* Deprecated macros for SME instructions */
 
 /* RDSVL X\nx, #\imm */
 .macro _sme_rdsvl nx, imm
-       _check_general_reg \nx
-       _check_num (\imm), -0x20, 0x1f
-       .inst   0x04bf5800                      \
-               | (\nx)                         \
-               | (((\imm) & 0x3f) << 5)
+       .arch_extension sme
+       rdsvl x\nx, #\imm
 .endm
 
 /*
  * STR (vector from ZA array):
- *     STR ZA[\nw, #\offset], [X\nxbase, #\offset, MUL VL]
+ *     STR ZA[W\nw, #\offset], [X\nxbase, #\offset, MUL VL]
  */
 .macro _sme_str_zav nw, nxbase, offset=0
-       _sme_check_wv \nw
-       _check_general_reg \nxbase
-       _check_num (\offset), -0x100, 0xff
-       .inst   0xe1200000                      \
-               | (((\nw) & 3) << 13)           \
-               | ((\nxbase) << 5)              \
-               | ((\offset) & 7)
+       .arch_extension sme
+       str     za[w\nw, #\offset], [x\nxbase, #\offset, MUL VL]
 .endm
 
 /*
  * LDR (vector to ZA array):
- *     LDR ZA[\nw, #\offset], [X\nxbase, #\offset, MUL VL]
+ *     LDR ZA[w\nw, #\offset], [X\nxbase, #\offset, MUL VL]
  */
 .macro _sme_ldr_zav nw, nxbase, offset=0
-       _sme_check_wv \nw
-       _check_general_reg \nxbase
-       _check_num (\offset), -0x100, 0xff
-       .inst   0xe1000000                      \
-               | (((\nw) & 3) << 13)           \
-               | ((\nxbase) << 5)              \
-               | ((\offset) & 7)
+       .arch_extension sme
+       ldr     za[w\nw, #\offset], [x\nxbase, #\offset, MUL VL]
 .endm
 
+/*
+ * SME2 instruction encodings for older assemblers.
+ * Supported by binutils 2.41+.
+ * Supported by LLVM 16+
+ */
+
 /*
  * LDR (ZT0)
  *