* [PATCH 0/3] raid: remove obsolete MMX optimized code
@ 2026-10-25 19:12 Eric Biggers
2026-10-25 19:12 ` [PATCH 1/3] xor: " Eric Biggers
` (4 more replies)
0 siblings, 5 replies; 8+ messages in thread
From: Eric Biggers @ 2026-10-25 19:12 UTC (permalink / raw)
To: linux-raid, Andrew Morton
Cc: linux-crypto, x86, linux-kernel, Christoph Hellwig, Eric Biggers
This series retires 32-bit MMX optimizations for RAID.
Affected CPUs, such as the Pentium MMX and Pentium II, will just fall
back to the existing well-tested scalar code instead.
This was the only remaining MMX optimized code in the kernel. MMX
optimizations for the much more commonly called functions memcpy(),
copy_page(), and clear_page() were already removed years ago by commit
c6dbd3e5e69c ("x86/mmx_32: Remove X86_USE_3DNOW"). There are zero MMX
optimizations for anything else, like crypto or CRC, which left the RAID
code as an outlier.
Patch 3 also cleans up the CPU feature checks in the RAID6 code.
Eric Biggers (3):
xor: remove MMX optimized code
raid6: remove MMX optimized code
raid6: simplify CPU feature checks
lib/raid/raid6/Makefile | 4 -
lib/raid/raid6/x86/mmx.c | 118 --------
lib/raid/raid6/x86/pq_arch.h | 69 +----
lib/raid/raid6/x86/sse1.c | 136 ---------
lib/raid/xor/Makefile | 2 +-
lib/raid/xor/x86/xor-mmx.c | 515 -----------------------------------
lib/raid/xor/x86/xor_arch.h | 5 -
7 files changed, 12 insertions(+), 837 deletions(-)
delete mode 100644 lib/raid/raid6/x86/mmx.c
delete mode 100644 lib/raid/raid6/x86/sse1.c
delete mode 100644 lib/raid/xor/x86/xor-mmx.c
base-commit: 21a7f44fd0765fcc5194130b28767786eba1d1e7
--
2.56.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/3] xor: remove obsolete MMX optimized code
2026-10-25 19:12 [PATCH 0/3] raid: remove obsolete MMX optimized code Eric Biggers
@ 2026-10-25 19:12 ` Eric Biggers
2026-10-25 19:12 ` [PATCH 2/3] raid6: " Eric Biggers
` (3 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Eric Biggers @ 2026-10-25 19:12 UTC (permalink / raw)
To: linux-raid, Andrew Morton
Cc: linux-crypto, x86, linux-kernel, Christoph Hellwig, Eric Biggers
The MMX optimized XOR code is used only on 25-year old 32-bit CPUs that
lack SSE support -- and only on systems that actually have a RAID array.
Those CPUs already have well-tested scalar C fallbacks.
Together with the RAID6 code, it's also the only remaining MMX optimized
code in the kernel. MMX optimizations for the much more commonly called
functions memcpy(), copy_page(), and clear_page() were already removed
years ago by commit c6dbd3e5e69c ("x86/mmx_32: Remove X86_USE_3DNOW").
Remove the MMX optimized XOR code.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
lib/raid/xor/Makefile | 2 +-
lib/raid/xor/x86/xor-mmx.c | 515 ------------------------------------
lib/raid/xor/x86/xor_arch.h | 5 -
3 files changed, 1 insertion(+), 521 deletions(-)
delete mode 100644 lib/raid/xor/x86/xor-mmx.c
diff --git a/lib/raid/xor/Makefile b/lib/raid/xor/Makefile
index e1e3455c219de..0b6ddacf442c3 100644
--- a/lib/raid/xor/Makefile
+++ b/lib/raid/xor/Makefile
@@ -30,7 +30,7 @@ xor-$(CONFIG_RISCV_ISA_V) += riscv/xor.o riscv/xor-glue.o
xor-$(CONFIG_SPARC32) += sparc/xor-sparc32.o
xor-$(CONFIG_SPARC64) += sparc/xor-sparc64.o sparc/xor-sparc64-glue.o
xor-$(CONFIG_S390) += s390/xor.o
-xor-$(CONFIG_X86_32) += x86/xor-avx.o x86/xor-sse.o x86/xor-mmx.o
+xor-$(CONFIG_X86_32) += x86/xor-avx.o x86/xor-sse.o
xor-$(CONFIG_X86_64) += x86/xor-avx.o x86/xor-sse.o x86/xor-avx512.o
obj-y += tests/
diff --git a/lib/raid/xor/x86/xor-mmx.c b/lib/raid/xor/x86/xor-mmx.c
deleted file mode 100644
index 63a8b0444fcef..0000000000000
--- a/lib/raid/xor/x86/xor-mmx.c
+++ /dev/null
@@ -1,515 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Optimized XOR parity functions for MMX.
- *
- * Copyright (C) 1998 Ingo Molnar.
- */
-#include <asm/fpu/api.h>
-#include "xor_impl.h"
-#include "xor_arch.h"
-
-#define LD(x, y) " movq 8*("#x")(%1), %%mm"#y" ;\n"
-#define ST(x, y) " movq %%mm"#y", 8*("#x")(%1) ;\n"
-#define XO1(x, y) " pxor 8*("#x")(%2), %%mm"#y" ;\n"
-#define XO2(x, y) " pxor 8*("#x")(%3), %%mm"#y" ;\n"
-#define XO3(x, y) " pxor 8*("#x")(%4), %%mm"#y" ;\n"
-#define XO4(x, y) " pxor 8*("#x")(%5), %%mm"#y" ;\n"
-
-static void
-xor_pII_mmx_2(unsigned long bytes, unsigned long * __restrict p1,
- const unsigned long * __restrict p2)
-{
- unsigned long lines = bytes >> 7;
-
- asm volatile(
-#undef BLOCK
-#define BLOCK(i) \
- LD(i, 0) \
- LD(i + 1, 1) \
- LD(i + 2, 2) \
- LD(i + 3, 3) \
- XO1(i, 0) \
- ST(i, 0) \
- XO1(i+1, 1) \
- ST(i+1, 1) \
- XO1(i + 2, 2) \
- ST(i + 2, 2) \
- XO1(i + 3, 3) \
- ST(i + 3, 3)
-
- " .align 32 ;\n"
- " 1: ;\n"
-
- BLOCK(0)
- BLOCK(4)
- BLOCK(8)
- BLOCK(12)
-
- " addl $128, %1 ;\n"
- " addl $128, %2 ;\n"
- " decl %0 ;\n"
- " jnz 1b ;\n"
- : "+r" (lines),
- "+r" (p1), "+r" (p2)
- :
- : "memory");
-}
-
-static void
-xor_pII_mmx_3(unsigned long bytes, unsigned long * __restrict p1,
- const unsigned long * __restrict p2,
- const unsigned long * __restrict p3)
-{
- unsigned long lines = bytes >> 7;
-
- asm volatile(
-#undef BLOCK
-#define BLOCK(i) \
- LD(i, 0) \
- LD(i + 1, 1) \
- LD(i + 2, 2) \
- LD(i + 3, 3) \
- XO1(i, 0) \
- XO1(i + 1, 1) \
- XO1(i + 2, 2) \
- XO1(i + 3, 3) \
- XO2(i, 0) \
- ST(i, 0) \
- XO2(i + 1, 1) \
- ST(i + 1, 1) \
- XO2(i + 2, 2) \
- ST(i + 2, 2) \
- XO2(i + 3, 3) \
- ST(i + 3, 3)
-
- " .align 32 ;\n"
- " 1: ;\n"
-
- BLOCK(0)
- BLOCK(4)
- BLOCK(8)
- BLOCK(12)
-
- " addl $128, %1 ;\n"
- " addl $128, %2 ;\n"
- " addl $128, %3 ;\n"
- " decl %0 ;\n"
- " jnz 1b ;\n"
- : "+r" (lines),
- "+r" (p1), "+r" (p2), "+r" (p3)
- :
- : "memory");
-}
-
-static void
-xor_pII_mmx_4(unsigned long bytes, unsigned long * __restrict p1,
- const unsigned long * __restrict p2,
- const unsigned long * __restrict p3,
- const unsigned long * __restrict p4)
-{
- unsigned long lines = bytes >> 7;
-
- asm volatile(
-#undef BLOCK
-#define BLOCK(i) \
- LD(i, 0) \
- LD(i + 1, 1) \
- LD(i + 2, 2) \
- LD(i + 3, 3) \
- XO1(i, 0) \
- XO1(i + 1, 1) \
- XO1(i + 2, 2) \
- XO1(i + 3, 3) \
- XO2(i, 0) \
- XO2(i + 1, 1) \
- XO2(i + 2, 2) \
- XO2(i + 3, 3) \
- XO3(i, 0) \
- ST(i, 0) \
- XO3(i + 1, 1) \
- ST(i + 1, 1) \
- XO3(i + 2, 2) \
- ST(i + 2, 2) \
- XO3(i + 3, 3) \
- ST(i + 3, 3)
-
- " .align 32 ;\n"
- " 1: ;\n"
-
- BLOCK(0)
- BLOCK(4)
- BLOCK(8)
- BLOCK(12)
-
- " addl $128, %1 ;\n"
- " addl $128, %2 ;\n"
- " addl $128, %3 ;\n"
- " addl $128, %4 ;\n"
- " decl %0 ;\n"
- " jnz 1b ;\n"
- : "+r" (lines),
- "+r" (p1), "+r" (p2), "+r" (p3), "+r" (p4)
- :
- : "memory");
-}
-
-
-static void
-xor_pII_mmx_5(unsigned long bytes, unsigned long * __restrict p1,
- const unsigned long * __restrict p2,
- const unsigned long * __restrict p3,
- const unsigned long * __restrict p4,
- const unsigned long * __restrict p5)
-{
- unsigned long lines = bytes >> 7;
-
- /* Make sure GCC forgets anything it knows about p4 or p5,
- such that it won't pass to the asm volatile below a
- register that is shared with any other variable. That's
- because we modify p4 and p5 there, but we can't mark them
- as read/write, otherwise we'd overflow the 10-asm-operands
- limit of GCC < 3.1. */
- asm("" : "+r" (p4), "+r" (p5));
-
- asm volatile(
-#undef BLOCK
-#define BLOCK(i) \
- LD(i, 0) \
- LD(i + 1, 1) \
- LD(i + 2, 2) \
- LD(i + 3, 3) \
- XO1(i, 0) \
- XO1(i + 1, 1) \
- XO1(i + 2, 2) \
- XO1(i + 3, 3) \
- XO2(i, 0) \
- XO2(i + 1, 1) \
- XO2(i + 2, 2) \
- XO2(i + 3, 3) \
- XO3(i, 0) \
- XO3(i + 1, 1) \
- XO3(i + 2, 2) \
- XO3(i + 3, 3) \
- XO4(i, 0) \
- ST(i, 0) \
- XO4(i + 1, 1) \
- ST(i + 1, 1) \
- XO4(i + 2, 2) \
- ST(i + 2, 2) \
- XO4(i + 3, 3) \
- ST(i + 3, 3)
-
- " .align 32 ;\n"
- " 1: ;\n"
-
- BLOCK(0)
- BLOCK(4)
- BLOCK(8)
- BLOCK(12)
-
- " addl $128, %1 ;\n"
- " addl $128, %2 ;\n"
- " addl $128, %3 ;\n"
- " addl $128, %4 ;\n"
- " addl $128, %5 ;\n"
- " decl %0 ;\n"
- " jnz 1b ;\n"
- : "+r" (lines),
- "+r" (p1), "+r" (p2), "+r" (p3)
- : "r" (p4), "r" (p5)
- : "memory");
-
- /* p4 and p5 were modified, and now the variables are dead.
- Clobber them just to be sure nobody does something stupid
- like assuming they have some legal value. */
- asm("" : "=r" (p4), "=r" (p5));
-}
-
-#undef LD
-#undef XO1
-#undef XO2
-#undef XO3
-#undef XO4
-#undef ST
-#undef BLOCK
-
-static void
-xor_p5_mmx_2(unsigned long bytes, unsigned long * __restrict p1,
- const unsigned long * __restrict p2)
-{
- unsigned long lines = bytes >> 6;
-
- asm volatile(
- " .align 32 ;\n"
- " 1: ;\n"
- " movq (%1), %%mm0 ;\n"
- " movq 8(%1), %%mm1 ;\n"
- " pxor (%2), %%mm0 ;\n"
- " movq 16(%1), %%mm2 ;\n"
- " movq %%mm0, (%1) ;\n"
- " pxor 8(%2), %%mm1 ;\n"
- " movq 24(%1), %%mm3 ;\n"
- " movq %%mm1, 8(%1) ;\n"
- " pxor 16(%2), %%mm2 ;\n"
- " movq 32(%1), %%mm4 ;\n"
- " movq %%mm2, 16(%1) ;\n"
- " pxor 24(%2), %%mm3 ;\n"
- " movq 40(%1), %%mm5 ;\n"
- " movq %%mm3, 24(%1) ;\n"
- " pxor 32(%2), %%mm4 ;\n"
- " movq 48(%1), %%mm6 ;\n"
- " movq %%mm4, 32(%1) ;\n"
- " pxor 40(%2), %%mm5 ;\n"
- " movq 56(%1), %%mm7 ;\n"
- " movq %%mm5, 40(%1) ;\n"
- " pxor 48(%2), %%mm6 ;\n"
- " pxor 56(%2), %%mm7 ;\n"
- " movq %%mm6, 48(%1) ;\n"
- " movq %%mm7, 56(%1) ;\n"
-
- " addl $64, %1 ;\n"
- " addl $64, %2 ;\n"
- " decl %0 ;\n"
- " jnz 1b ;\n"
- : "+r" (lines),
- "+r" (p1), "+r" (p2)
- :
- : "memory");
-}
-
-static void
-xor_p5_mmx_3(unsigned long bytes, unsigned long * __restrict p1,
- const unsigned long * __restrict p2,
- const unsigned long * __restrict p3)
-{
- unsigned long lines = bytes >> 6;
-
- asm volatile(
- " .align 32,0x90 ;\n"
- " 1: ;\n"
- " movq (%1), %%mm0 ;\n"
- " movq 8(%1), %%mm1 ;\n"
- " pxor (%2), %%mm0 ;\n"
- " movq 16(%1), %%mm2 ;\n"
- " pxor 8(%2), %%mm1 ;\n"
- " pxor (%3), %%mm0 ;\n"
- " pxor 16(%2), %%mm2 ;\n"
- " movq %%mm0, (%1) ;\n"
- " pxor 8(%3), %%mm1 ;\n"
- " pxor 16(%3), %%mm2 ;\n"
- " movq 24(%1), %%mm3 ;\n"
- " movq %%mm1, 8(%1) ;\n"
- " movq 32(%1), %%mm4 ;\n"
- " movq 40(%1), %%mm5 ;\n"
- " pxor 24(%2), %%mm3 ;\n"
- " movq %%mm2, 16(%1) ;\n"
- " pxor 32(%2), %%mm4 ;\n"
- " pxor 24(%3), %%mm3 ;\n"
- " pxor 40(%2), %%mm5 ;\n"
- " movq %%mm3, 24(%1) ;\n"
- " pxor 32(%3), %%mm4 ;\n"
- " pxor 40(%3), %%mm5 ;\n"
- " movq 48(%1), %%mm6 ;\n"
- " movq %%mm4, 32(%1) ;\n"
- " movq 56(%1), %%mm7 ;\n"
- " pxor 48(%2), %%mm6 ;\n"
- " movq %%mm5, 40(%1) ;\n"
- " pxor 56(%2), %%mm7 ;\n"
- " pxor 48(%3), %%mm6 ;\n"
- " pxor 56(%3), %%mm7 ;\n"
- " movq %%mm6, 48(%1) ;\n"
- " movq %%mm7, 56(%1) ;\n"
-
- " addl $64, %1 ;\n"
- " addl $64, %2 ;\n"
- " addl $64, %3 ;\n"
- " decl %0 ;\n"
- " jnz 1b ;\n"
- : "+r" (lines),
- "+r" (p1), "+r" (p2), "+r" (p3)
- :
- : "memory" );
-}
-
-static void
-xor_p5_mmx_4(unsigned long bytes, unsigned long * __restrict p1,
- const unsigned long * __restrict p2,
- const unsigned long * __restrict p3,
- const unsigned long * __restrict p4)
-{
- unsigned long lines = bytes >> 6;
-
- asm volatile(
- " .align 32,0x90 ;\n"
- " 1: ;\n"
- " movq (%1), %%mm0 ;\n"
- " movq 8(%1), %%mm1 ;\n"
- " pxor (%2), %%mm0 ;\n"
- " movq 16(%1), %%mm2 ;\n"
- " pxor 8(%2), %%mm1 ;\n"
- " pxor (%3), %%mm0 ;\n"
- " pxor 16(%2), %%mm2 ;\n"
- " pxor 8(%3), %%mm1 ;\n"
- " pxor (%4), %%mm0 ;\n"
- " movq 24(%1), %%mm3 ;\n"
- " pxor 16(%3), %%mm2 ;\n"
- " pxor 8(%4), %%mm1 ;\n"
- " movq %%mm0, (%1) ;\n"
- " movq 32(%1), %%mm4 ;\n"
- " pxor 24(%2), %%mm3 ;\n"
- " pxor 16(%4), %%mm2 ;\n"
- " movq %%mm1, 8(%1) ;\n"
- " movq 40(%1), %%mm5 ;\n"
- " pxor 32(%2), %%mm4 ;\n"
- " pxor 24(%3), %%mm3 ;\n"
- " movq %%mm2, 16(%1) ;\n"
- " pxor 40(%2), %%mm5 ;\n"
- " pxor 32(%3), %%mm4 ;\n"
- " pxor 24(%4), %%mm3 ;\n"
- " movq %%mm3, 24(%1) ;\n"
- " movq 56(%1), %%mm7 ;\n"
- " movq 48(%1), %%mm6 ;\n"
- " pxor 40(%3), %%mm5 ;\n"
- " pxor 32(%4), %%mm4 ;\n"
- " pxor 48(%2), %%mm6 ;\n"
- " movq %%mm4, 32(%1) ;\n"
- " pxor 56(%2), %%mm7 ;\n"
- " pxor 40(%4), %%mm5 ;\n"
- " pxor 48(%3), %%mm6 ;\n"
- " pxor 56(%3), %%mm7 ;\n"
- " movq %%mm5, 40(%1) ;\n"
- " pxor 48(%4), %%mm6 ;\n"
- " pxor 56(%4), %%mm7 ;\n"
- " movq %%mm6, 48(%1) ;\n"
- " movq %%mm7, 56(%1) ;\n"
-
- " addl $64, %1 ;\n"
- " addl $64, %2 ;\n"
- " addl $64, %3 ;\n"
- " addl $64, %4 ;\n"
- " decl %0 ;\n"
- " jnz 1b ;\n"
- : "+r" (lines),
- "+r" (p1), "+r" (p2), "+r" (p3), "+r" (p4)
- :
- : "memory");
-}
-
-static void
-xor_p5_mmx_5(unsigned long bytes, unsigned long * __restrict p1,
- const unsigned long * __restrict p2,
- const unsigned long * __restrict p3,
- const unsigned long * __restrict p4,
- const unsigned long * __restrict p5)
-{
- unsigned long lines = bytes >> 6;
-
- /* Make sure GCC forgets anything it knows about p4 or p5,
- such that it won't pass to the asm volatile below a
- register that is shared with any other variable. That's
- because we modify p4 and p5 there, but we can't mark them
- as read/write, otherwise we'd overflow the 10-asm-operands
- limit of GCC < 3.1. */
- asm("" : "+r" (p4), "+r" (p5));
-
- asm volatile(
- " .align 32,0x90 ;\n"
- " 1: ;\n"
- " movq (%1), %%mm0 ;\n"
- " movq 8(%1), %%mm1 ;\n"
- " pxor (%2), %%mm0 ;\n"
- " pxor 8(%2), %%mm1 ;\n"
- " movq 16(%1), %%mm2 ;\n"
- " pxor (%3), %%mm0 ;\n"
- " pxor 8(%3), %%mm1 ;\n"
- " pxor 16(%2), %%mm2 ;\n"
- " pxor (%4), %%mm0 ;\n"
- " pxor 8(%4), %%mm1 ;\n"
- " pxor 16(%3), %%mm2 ;\n"
- " movq 24(%1), %%mm3 ;\n"
- " pxor (%5), %%mm0 ;\n"
- " pxor 8(%5), %%mm1 ;\n"
- " movq %%mm0, (%1) ;\n"
- " pxor 16(%4), %%mm2 ;\n"
- " pxor 24(%2), %%mm3 ;\n"
- " movq %%mm1, 8(%1) ;\n"
- " pxor 16(%5), %%mm2 ;\n"
- " pxor 24(%3), %%mm3 ;\n"
- " movq 32(%1), %%mm4 ;\n"
- " movq %%mm2, 16(%1) ;\n"
- " pxor 24(%4), %%mm3 ;\n"
- " pxor 32(%2), %%mm4 ;\n"
- " movq 40(%1), %%mm5 ;\n"
- " pxor 24(%5), %%mm3 ;\n"
- " pxor 32(%3), %%mm4 ;\n"
- " pxor 40(%2), %%mm5 ;\n"
- " movq %%mm3, 24(%1) ;\n"
- " pxor 32(%4), %%mm4 ;\n"
- " pxor 40(%3), %%mm5 ;\n"
- " movq 48(%1), %%mm6 ;\n"
- " movq 56(%1), %%mm7 ;\n"
- " pxor 32(%5), %%mm4 ;\n"
- " pxor 40(%4), %%mm5 ;\n"
- " pxor 48(%2), %%mm6 ;\n"
- " pxor 56(%2), %%mm7 ;\n"
- " movq %%mm4, 32(%1) ;\n"
- " pxor 48(%3), %%mm6 ;\n"
- " pxor 56(%3), %%mm7 ;\n"
- " pxor 40(%5), %%mm5 ;\n"
- " pxor 48(%4), %%mm6 ;\n"
- " pxor 56(%4), %%mm7 ;\n"
- " movq %%mm5, 40(%1) ;\n"
- " pxor 48(%5), %%mm6 ;\n"
- " pxor 56(%5), %%mm7 ;\n"
- " movq %%mm6, 48(%1) ;\n"
- " movq %%mm7, 56(%1) ;\n"
-
- " addl $64, %1 ;\n"
- " addl $64, %2 ;\n"
- " addl $64, %3 ;\n"
- " addl $64, %4 ;\n"
- " addl $64, %5 ;\n"
- " decl %0 ;\n"
- " jnz 1b ;\n"
- : "+r" (lines),
- "+r" (p1), "+r" (p2), "+r" (p3)
- : "r" (p4), "r" (p5)
- : "memory");
-
- /* p4 and p5 were modified, and now the variables are dead.
- Clobber them just to be sure nobody does something stupid
- like assuming they have some legal value. */
- asm("" : "=r" (p4), "=r" (p5));
-}
-
-DO_XOR_BLOCKS(pII_mmx_inner, xor_pII_mmx_2, xor_pII_mmx_3, xor_pII_mmx_4,
- xor_pII_mmx_5);
-
-static void xor_gen_pII_mmx(void *dest, void **srcs, unsigned int src_cnt,
- unsigned int bytes)
-{
- kernel_fpu_begin();
- xor_gen_pII_mmx_inner(dest, srcs, src_cnt, bytes);
- kernel_fpu_end();
-}
-
-struct xor_block_template xor_block_pII_mmx = {
- .name = "pII_mmx",
- .xor_gen = xor_gen_pII_mmx,
-};
-
-DO_XOR_BLOCKS(p5_mmx_inner, xor_p5_mmx_2, xor_p5_mmx_3, xor_p5_mmx_4,
- xor_p5_mmx_5);
-
-static void xor_gen_p5_mmx(void *dest, void **srcs, unsigned int src_cnt,
- unsigned int bytes)
-{
- kernel_fpu_begin();
- xor_gen_p5_mmx_inner(dest, srcs, src_cnt, bytes);
- kernel_fpu_end();
-}
-
-struct xor_block_template xor_block_p5_mmx = {
- .name = "p5_mmx",
- .xor_gen = xor_gen_p5_mmx,
-};
diff --git a/lib/raid/xor/x86/xor_arch.h b/lib/raid/xor/x86/xor_arch.h
index ed5921d2e2aad..3bc0e1650b78c 100644
--- a/lib/raid/xor/x86/xor_arch.h
+++ b/lib/raid/xor/x86/xor_arch.h
@@ -1,8 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include <asm/cpufeature.h>
-extern struct xor_block_template xor_block_pII_mmx;
-extern struct xor_block_template xor_block_p5_mmx;
extern struct xor_block_template xor_block_sse;
extern struct xor_block_template xor_block_sse_pf64;
extern struct xor_block_template xor_block_avx;
@@ -33,9 +31,6 @@ static __always_inline void __init arch_xor_init(void)
*/
xor_register(&xor_block_sse);
xor_register(&xor_block_sse_pf64);
- } else if (boot_cpu_has(X86_FEATURE_MMX)) {
- xor_register(&xor_block_pII_mmx);
- xor_register(&xor_block_p5_mmx);
} else {
xor_register(&xor_block_8regs);
xor_register(&xor_block_8regs_p);
--
2.56.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 2/3] raid6: remove obsolete MMX optimized code
2026-10-25 19:12 [PATCH 0/3] raid: remove obsolete MMX optimized code Eric Biggers
2026-10-25 19:12 ` [PATCH 1/3] xor: " Eric Biggers
@ 2026-10-25 19:12 ` Eric Biggers
2026-10-25 19:12 ` [PATCH 3/3] raid6: simplify CPU feature checks Eric Biggers
` (2 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Eric Biggers @ 2026-10-25 19:12 UTC (permalink / raw)
To: linux-raid, Andrew Morton
Cc: linux-crypto, x86, linux-kernel, Christoph Hellwig, Eric Biggers
The MMX optimized RAID6 code is used only on 25-year old 32-bit CPUs
that lack SSE2 support -- and only on systems that actually have a RAID
array. Those CPUs already have well-tested scalar C fallbacks.
It's also the only remaining MMX optimized code in the kernel. MMX
optimizations for the much more commonly called functions memcpy(),
copy_page(), and clear_page() were already removed years ago by
commit c6dbd3e5e69c ("x86/mmx_32: Remove X86_USE_3DNOW").
Remove the MMX optimized RAID6 code. This includes
lib/raid/raid6/x86/sse1.c, which was really an MMX implementation with
SSE1 prefetches and non-temporal stores added on top.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
lib/raid/raid6/Makefile | 4 --
lib/raid/raid6/x86/mmx.c | 118 ------------------------------
lib/raid/raid6/x86/pq_arch.h | 18 -----
lib/raid/raid6/x86/sse1.c | 136 -----------------------------------
4 files changed, 276 deletions(-)
delete mode 100644 lib/raid/raid6/x86/mmx.c
delete mode 100644 lib/raid/raid6/x86/sse1.c
diff --git a/lib/raid/raid6/Makefile b/lib/raid/raid6/Makefile
index 5cdb7223de2af..0bfc20a60ae92 100644
--- a/lib/raid/raid6/Makefile
+++ b/lib/raid/raid6/Makefile
@@ -38,10 +38,6 @@ raid6_pq-$(CONFIG_RISCV_ISA_V) += riscv/rvv.o \
riscv/recov_rvv.o
raid6_pq-$(CONFIG_S390) += s390/s390vx8.o \
s390/recov_s390xc.o
-ifeq ($(CONFIG_X86),y)
-raid6_pq-$(CONFIG_X86_32) += x86/mmx.o \
- x86/sse1.o
-endif
raid6_pq-$(CONFIG_X86) += x86/sse2.o \
x86/avx2.o \
x86/avx512.o \
diff --git a/lib/raid/raid6/x86/mmx.c b/lib/raid/raid6/x86/mmx.c
deleted file mode 100644
index afa82536142da..0000000000000
--- a/lib/raid/raid6/x86/mmx.c
+++ /dev/null
@@ -1,118 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright 2002 H. Peter Anvin - All Rights Reserved
- *
- * MMX implementation of RAID-6 syndrome functions.
- */
-
-#include <asm/cpufeature.h>
-#include <asm/fpu/api.h>
-#include "algos.h"
-
-/* Shared with raid6/sse1.c */
-const struct raid6_mmx_constants {
- u64 x1d;
-} raid6_mmx_constants = {
- 0x1d1d1d1d1d1d1d1dULL,
-};
-
-/*
- * Plain MMX implementation
- */
-static void raid6_mmx1_gen_syndrome(int disks, size_t bytes, void **ptrs)
-{
- u8 **dptr = (u8 **)ptrs;
- u8 *p, *q;
- int d, z, z0;
-
- z0 = disks - 3; /* Highest data disk */
- p = dptr[z0+1]; /* XOR parity */
- q = dptr[z0+2]; /* RS syndrome */
-
- kernel_fpu_begin();
-
- asm volatile("movq %0,%%mm0" : : "m" (raid6_mmx_constants.x1d));
- asm volatile("pxor %mm5,%mm5"); /* Zero temp */
-
- for ( d = 0 ; d < bytes ; d += 8 ) {
- asm volatile("movq %0,%%mm2" : : "m" (dptr[z0][d])); /* P[0] */
- asm volatile("movq %mm2,%mm4"); /* Q[0] */
- for ( z = z0-1 ; z >= 0 ; z-- ) {
- asm volatile("movq %0,%%mm6" : : "m" (dptr[z][d]));
- asm volatile("pcmpgtb %mm4,%mm5");
- asm volatile("paddb %mm4,%mm4");
- asm volatile("pand %mm0,%mm5");
- asm volatile("pxor %mm5,%mm4");
- asm volatile("pxor %mm5,%mm5");
- asm volatile("pxor %mm6,%mm2");
- asm volatile("pxor %mm6,%mm4");
- }
- asm volatile("movq %%mm2,%0" : "=m" (p[d]));
- asm volatile("pxor %mm2,%mm2");
- asm volatile("movq %%mm4,%0" : "=m" (q[d]));
- asm volatile("pxor %mm4,%mm4");
- }
-
- kernel_fpu_end();
-}
-
-const struct raid6_calls raid6_mmxx1 = {
- .gen_syndrome = raid6_mmx1_gen_syndrome,
- .name = "mmxx1",
-};
-
-/*
- * Unrolled-by-2 MMX implementation
- */
-static void raid6_mmx2_gen_syndrome(int disks, size_t bytes, void **ptrs)
-{
- u8 **dptr = (u8 **)ptrs;
- u8 *p, *q;
- int d, z, z0;
-
- z0 = disks - 3; /* Highest data disk */
- p = dptr[z0+1]; /* XOR parity */
- q = dptr[z0+2]; /* RS syndrome */
-
- kernel_fpu_begin();
-
- asm volatile("movq %0,%%mm0" : : "m" (raid6_mmx_constants.x1d));
- asm volatile("pxor %mm5,%mm5"); /* Zero temp */
- asm volatile("pxor %mm7,%mm7"); /* Zero temp */
-
- for ( d = 0 ; d < bytes ; d += 16 ) {
- asm volatile("movq %0,%%mm2" : : "m" (dptr[z0][d])); /* P[0] */
- asm volatile("movq %0,%%mm3" : : "m" (dptr[z0][d+8]));
- asm volatile("movq %mm2,%mm4"); /* Q[0] */
- asm volatile("movq %mm3,%mm6"); /* Q[1] */
- for ( z = z0-1 ; z >= 0 ; z-- ) {
- asm volatile("pcmpgtb %mm4,%mm5");
- asm volatile("pcmpgtb %mm6,%mm7");
- asm volatile("paddb %mm4,%mm4");
- asm volatile("paddb %mm6,%mm6");
- asm volatile("pand %mm0,%mm5");
- asm volatile("pand %mm0,%mm7");
- asm volatile("pxor %mm5,%mm4");
- asm volatile("pxor %mm7,%mm6");
- asm volatile("movq %0,%%mm5" : : "m" (dptr[z][d]));
- asm volatile("movq %0,%%mm7" : : "m" (dptr[z][d+8]));
- asm volatile("pxor %mm5,%mm2");
- asm volatile("pxor %mm7,%mm3");
- asm volatile("pxor %mm5,%mm4");
- asm volatile("pxor %mm7,%mm6");
- asm volatile("pxor %mm5,%mm5");
- asm volatile("pxor %mm7,%mm7");
- }
- asm volatile("movq %%mm2,%0" : "=m" (p[d]));
- asm volatile("movq %%mm3,%0" : "=m" (p[d+8]));
- asm volatile("movq %%mm4,%0" : "=m" (q[d]));
- asm volatile("movq %%mm6,%0" : "=m" (q[d+8]));
- }
-
- kernel_fpu_end();
-}
-
-const struct raid6_calls raid6_mmxx2 = {
- .gen_syndrome = raid6_mmx2_gen_syndrome,
- .name = "mmxx2",
-};
diff --git a/lib/raid/raid6/x86/pq_arch.h b/lib/raid/raid6/x86/pq_arch.h
index 02f8843b05372..4a863b253b909 100644
--- a/lib/raid/raid6/x86/pq_arch.h
+++ b/lib/raid/raid6/x86/pq_arch.h
@@ -2,10 +2,6 @@
#include <asm/cpufeature.h>
-extern const struct raid6_calls raid6_mmxx1;
-extern const struct raid6_calls raid6_mmxx2;
-extern const struct raid6_calls raid6_sse1x1;
-extern const struct raid6_calls raid6_sse1x2;
extern const struct raid6_calls raid6_sse2x1;
extern const struct raid6_calls raid6_sse2x2;
extern const struct raid6_calls raid6_sse2x4;
@@ -50,13 +46,6 @@ static inline bool raid6_has_sse2(void)
boot_cpu_has(X86_FEATURE_XMM2);
}
-static inline bool raid6_has_sse1_or_mmxext(void)
-{
- return boot_cpu_has(X86_FEATURE_MMX) &&
- (boot_cpu_has(X86_FEATURE_XMM) ||
- boot_cpu_has(X86_FEATURE_MMXEXT));
-}
-
static __always_inline void __init arch_raid6_init(void)
{
if (raid6_has_avx2()) {
@@ -78,13 +67,6 @@ static __always_inline void __init arch_raid6_init(void)
raid6_algo_add(&raid6_sse2x4);
} else {
raid6_algo_add_default();
- if (raid6_has_sse1_or_mmxext()) {
- raid6_algo_add(&raid6_sse1x1);
- raid6_algo_add(&raid6_sse1x2);
- } else if (boot_cpu_has(X86_FEATURE_MMX)) {
- raid6_algo_add(&raid6_mmxx1);
- raid6_algo_add(&raid6_mmxx2);
- }
}
if (raid6_has_avx512())
diff --git a/lib/raid/raid6/x86/sse1.c b/lib/raid/raid6/x86/sse1.c
deleted file mode 100644
index f4b260df522a3..0000000000000
--- a/lib/raid/raid6/x86/sse1.c
+++ /dev/null
@@ -1,136 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright 2002 H. Peter Anvin - All Rights Reserved
- *
- * SSE-1/MMXEXT implementation of RAID-6 syndrome functions.
- *
- * This is really an MMX implementation, but it requires SSE-1 or AMD MMXEXT for
- * prefetch support and a few other features. The support for nontemporal
- * memory accesses is enough to make this worthwhile as a separate
- * implementation.
- */
-
-#include <asm/cpufeature.h>
-#include <asm/fpu/api.h>
-#include "algos.h"
-
-/* Defined in raid6/mmx.c */
-extern const struct raid6_mmx_constants {
- u64 x1d;
-} raid6_mmx_constants;
-
-/*
- * Plain SSE1 implementation
- */
-static void raid6_sse11_gen_syndrome(int disks, size_t bytes, void **ptrs)
-{
- u8 **dptr = (u8 **)ptrs;
- u8 *p, *q;
- int d, z, z0;
-
- z0 = disks - 3; /* Highest data disk */
- p = dptr[z0+1]; /* XOR parity */
- q = dptr[z0+2]; /* RS syndrome */
-
- kernel_fpu_begin();
-
- asm volatile("movq %0,%%mm0" : : "m" (raid6_mmx_constants.x1d));
- asm volatile("pxor %mm5,%mm5"); /* Zero temp */
-
- for ( d = 0 ; d < bytes ; d += 8 ) {
- asm volatile("prefetchnta %0" : : "m" (dptr[z0][d]));
- asm volatile("movq %0,%%mm2" : : "m" (dptr[z0][d])); /* P[0] */
- asm volatile("prefetchnta %0" : : "m" (dptr[z0-1][d]));
- asm volatile("movq %mm2,%mm4"); /* Q[0] */
- asm volatile("movq %0,%%mm6" : : "m" (dptr[z0-1][d]));
- for ( z = z0-2 ; z >= 0 ; z-- ) {
- asm volatile("prefetchnta %0" : : "m" (dptr[z][d]));
- asm volatile("pcmpgtb %mm4,%mm5");
- asm volatile("paddb %mm4,%mm4");
- asm volatile("pand %mm0,%mm5");
- asm volatile("pxor %mm5,%mm4");
- asm volatile("pxor %mm5,%mm5");
- asm volatile("pxor %mm6,%mm2");
- asm volatile("pxor %mm6,%mm4");
- asm volatile("movq %0,%%mm6" : : "m" (dptr[z][d]));
- }
- asm volatile("pcmpgtb %mm4,%mm5");
- asm volatile("paddb %mm4,%mm4");
- asm volatile("pand %mm0,%mm5");
- asm volatile("pxor %mm5,%mm4");
- asm volatile("pxor %mm5,%mm5");
- asm volatile("pxor %mm6,%mm2");
- asm volatile("pxor %mm6,%mm4");
-
- asm volatile("movntq %%mm2,%0" : "=m" (p[d]));
- asm volatile("movntq %%mm4,%0" : "=m" (q[d]));
- }
-
- asm volatile("sfence" : : : "memory");
- kernel_fpu_end();
-}
-
-const struct raid6_calls raid6_sse1x1 = {
- .gen_syndrome = raid6_sse11_gen_syndrome,
- .name = "sse1x1",
-};
-
-/*
- * Unrolled-by-2 SSE1 implementation
- */
-static void raid6_sse12_gen_syndrome(int disks, size_t bytes, void **ptrs)
-{
- u8 **dptr = (u8 **)ptrs;
- u8 *p, *q;
- int d, z, z0;
-
- z0 = disks - 3; /* Highest data disk */
- p = dptr[z0+1]; /* XOR parity */
- q = dptr[z0+2]; /* RS syndrome */
-
- kernel_fpu_begin();
-
- asm volatile("movq %0,%%mm0" : : "m" (raid6_mmx_constants.x1d));
- asm volatile("pxor %mm5,%mm5"); /* Zero temp */
- asm volatile("pxor %mm7,%mm7"); /* Zero temp */
-
- /* We uniformly assume a single prefetch covers at least 16 bytes */
- for ( d = 0 ; d < bytes ; d += 16 ) {
- asm volatile("prefetchnta %0" : : "m" (dptr[z0][d]));
- asm volatile("movq %0,%%mm2" : : "m" (dptr[z0][d])); /* P[0] */
- asm volatile("movq %0,%%mm3" : : "m" (dptr[z0][d+8])); /* P[1] */
- asm volatile("movq %mm2,%mm4"); /* Q[0] */
- asm volatile("movq %mm3,%mm6"); /* Q[1] */
- for ( z = z0-1 ; z >= 0 ; z-- ) {
- asm volatile("prefetchnta %0" : : "m" (dptr[z][d]));
- asm volatile("pcmpgtb %mm4,%mm5");
- asm volatile("pcmpgtb %mm6,%mm7");
- asm volatile("paddb %mm4,%mm4");
- asm volatile("paddb %mm6,%mm6");
- asm volatile("pand %mm0,%mm5");
- asm volatile("pand %mm0,%mm7");
- asm volatile("pxor %mm5,%mm4");
- asm volatile("pxor %mm7,%mm6");
- asm volatile("movq %0,%%mm5" : : "m" (dptr[z][d]));
- asm volatile("movq %0,%%mm7" : : "m" (dptr[z][d+8]));
- asm volatile("pxor %mm5,%mm2");
- asm volatile("pxor %mm7,%mm3");
- asm volatile("pxor %mm5,%mm4");
- asm volatile("pxor %mm7,%mm6");
- asm volatile("pxor %mm5,%mm5");
- asm volatile("pxor %mm7,%mm7");
- }
- asm volatile("movntq %%mm2,%0" : "=m" (p[d]));
- asm volatile("movntq %%mm3,%0" : "=m" (p[d+8]));
- asm volatile("movntq %%mm4,%0" : "=m" (q[d]));
- asm volatile("movntq %%mm6,%0" : "=m" (q[d+8]));
- }
-
- asm volatile("sfence" : :: "memory");
- kernel_fpu_end();
-}
-
-const struct raid6_calls raid6_sse1x2 = {
- .gen_syndrome = raid6_sse12_gen_syndrome,
- .name = "sse1x2",
-};
--
2.56.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 3/3] raid6: simplify CPU feature checks
2026-10-25 19:12 [PATCH 0/3] raid: remove obsolete MMX optimized code Eric Biggers
2026-10-25 19:12 ` [PATCH 1/3] xor: " Eric Biggers
2026-10-25 19:12 ` [PATCH 2/3] raid6: " Eric Biggers
@ 2026-10-25 19:12 ` Eric Biggers
2026-10-26 14:57 ` David Laight
2026-10-26 15:00 ` [PATCH 0/3] raid: remove obsolete MMX optimized code David Laight
2026-10-27 15:07 ` Christoph Hellwig
4 siblings, 1 reply; 8+ messages in thread
From: Eric Biggers @ 2026-10-25 19:12 UTC (permalink / raw)
To: linux-raid, Andrew Morton
Cc: linux-crypto, x86, linux-kernel, Christoph Hellwig, Eric Biggers
Remove unnecessary checks for features that are prerequisites for other
features, such as AVX which is a prerequisite for AVX2.
(Note: in most cases arch/x86/kernel/cpu/cpuid-deps.c warns about
missing prerequisites rather than enforcing them. This is intentional,
and it does not mean the prerequisites should be checked elsewhere.)
Then, move the raid6_recov_algo_add() lines into the appropriate places
just above so that the same CPU features aren't checked multiple times.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
lib/raid/raid6/x86/pq_arch.h | 51 ++++++++----------------------------
1 file changed, 11 insertions(+), 40 deletions(-)
diff --git a/lib/raid/raid6/x86/pq_arch.h b/lib/raid/raid6/x86/pq_arch.h
index 4a863b253b909..418e4d4a2930f 100644
--- a/lib/raid/raid6/x86/pq_arch.h
+++ b/lib/raid/raid6/x86/pq_arch.h
@@ -16,63 +16,34 @@ extern const struct raid6_recov_calls raid6_recov_ssse3;
extern const struct raid6_recov_calls raid6_recov_avx2;
extern const struct raid6_recov_calls raid6_recov_avx512;
-static inline int raid6_has_avx512(void)
-{
- return boot_cpu_has(X86_FEATURE_AVX2) &&
- boot_cpu_has(X86_FEATURE_AVX) &&
- boot_cpu_has(X86_FEATURE_AVX512F) &&
- boot_cpu_has(X86_FEATURE_AVX512BW) &&
- boot_cpu_has(X86_FEATURE_AVX512VL) &&
- boot_cpu_has(X86_FEATURE_AVX512DQ);
-}
-
-static inline bool raid6_has_avx2(void)
-{
- return boot_cpu_has(X86_FEATURE_AVX2) && boot_cpu_has(X86_FEATURE_AVX);
-}
-
-static inline bool raid6_has_ssse3(void)
-{
- return boot_cpu_has(X86_FEATURE_XMM) &&
- boot_cpu_has(X86_FEATURE_XMM2) &&
- boot_cpu_has(X86_FEATURE_SSSE3);
-}
-
-static inline bool raid6_has_sse2(void)
-{
- return boot_cpu_has(X86_FEATURE_MMX) &&
- boot_cpu_has(X86_FEATURE_FXSR) &&
- boot_cpu_has(X86_FEATURE_XMM) &&
- boot_cpu_has(X86_FEATURE_XMM2);
-}
-
static __always_inline void __init arch_raid6_init(void)
{
- if (raid6_has_avx2()) {
+ if (boot_cpu_has(X86_FEATURE_AVX2)) {
raid6_algo_add(&raid6_avx2x1);
raid6_algo_add(&raid6_avx2x2);
if (IS_ENABLED(CONFIG_X86_64))
raid6_algo_add(&raid6_avx2x4);
- if (raid6_has_avx512()) {
+ if (boot_cpu_has(X86_FEATURE_AVX512BW) &&
+ boot_cpu_has(X86_FEATURE_AVX512VL) &&
+ boot_cpu_has(X86_FEATURE_AVX512DQ)) {
raid6_algo_add(&raid6_avx512x1);
raid6_algo_add(&raid6_avx512x2);
if (IS_ENABLED(CONFIG_X86_64))
raid6_algo_add(&raid6_avx512x4);
+ raid6_recov_algo_add(&raid6_recov_avx512);
+ } else {
+ raid6_recov_algo_add(&raid6_recov_avx2);
}
- } else if (IS_ENABLED(CONFIG_X86_64) || raid6_has_sse2()) {
+ } else if (IS_ENABLED(CONFIG_X86_64) ||
+ boot_cpu_has(X86_FEATURE_XMM2)) {
/* x86_64 can assume SSE2 as baseline */
raid6_algo_add(&raid6_sse2x1);
raid6_algo_add(&raid6_sse2x2);
if (IS_ENABLED(CONFIG_X86_64))
raid6_algo_add(&raid6_sse2x4);
+ if (boot_cpu_has(X86_FEATURE_SSSE3))
+ raid6_recov_algo_add(&raid6_recov_ssse3);
} else {
raid6_algo_add_default();
}
-
- if (raid6_has_avx512())
- raid6_recov_algo_add(&raid6_recov_avx512);
- else if (raid6_has_avx2())
- raid6_recov_algo_add(&raid6_recov_avx2);
- else if (raid6_has_ssse3())
- raid6_recov_algo_add(&raid6_recov_ssse3);
}
--
2.56.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 3/3] raid6: simplify CPU feature checks
2026-10-25 19:12 ` [PATCH 3/3] raid6: simplify CPU feature checks Eric Biggers
@ 2026-10-26 14:57 ` David Laight
2026-10-26 18:47 ` Eric Biggers
0 siblings, 1 reply; 8+ messages in thread
From: David Laight @ 2026-10-26 14:57 UTC (permalink / raw)
To: Eric Biggers
Cc: linux-raid, Andrew Morton, linux-crypto, x86, linux-kernel,
Christoph Hellwig
On Sun, 25 Oct 2026 12:12:07 -0700
Eric Biggers <ebiggers@kernel.org> wrote:
> Remove unnecessary checks for features that are prerequisites for other
> features, such as AVX which is a prerequisite for AVX2.
>
> (Note: in most cases arch/x86/kernel/cpu/cpuid-deps.c warns about
> missing prerequisites rather than enforcing them. This is intentional,
> and it does not mean the prerequisites should be checked elsewhere.)
>
> Then, move the raid6_recov_algo_add() lines into the appropriate places
> just above so that the same CPU features aren't checked multiple times.
>
> Signed-off-by: Eric Biggers <ebiggers@kernel.org>
> ---
> lib/raid/raid6/x86/pq_arch.h | 51 ++++++++----------------------------
> 1 file changed, 11 insertions(+), 40 deletions(-)
>
> diff --git a/lib/raid/raid6/x86/pq_arch.h b/lib/raid/raid6/x86/pq_arch.h
> index 4a863b253b909..418e4d4a2930f 100644
> --- a/lib/raid/raid6/x86/pq_arch.h
> +++ b/lib/raid/raid6/x86/pq_arch.h
> @@ -16,63 +16,34 @@ extern const struct raid6_recov_calls raid6_recov_ssse3;
> extern const struct raid6_recov_calls raid6_recov_avx2;
> extern const struct raid6_recov_calls raid6_recov_avx512;
>
> ...
> static __always_inline void __init arch_raid6_init(void)
> {
> - if (raid6_has_avx2()) {
> + if (boot_cpu_has(X86_FEATURE_AVX2)) {
> raid6_algo_add(&raid6_avx2x1);
> raid6_algo_add(&raid6_avx2x2);
> if (IS_ENABLED(CONFIG_X86_64))
> raid6_algo_add(&raid6_avx2x4);
> - if (raid6_has_avx512()) {
> + if (boot_cpu_has(X86_FEATURE_AVX512BW) &&
> + boot_cpu_has(X86_FEATURE_AVX512VL) &&
> + boot_cpu_has(X86_FEATURE_AVX512DQ)) {
> raid6_algo_add(&raid6_avx512x1);
> raid6_algo_add(&raid6_avx512x2);
> if (IS_ENABLED(CONFIG_X86_64))
> raid6_algo_add(&raid6_avx512x4);
> + raid6_recov_algo_add(&raid6_recov_avx512);
> + } else {
> + raid6_recov_algo_add(&raid6_recov_avx2);
Is that right (you haven't changed it)?
You get both the avx2 and axv512 normal algorithms, but only one
of the recov ones.
I presume these are added in addition to the generic C code and
some startup test decides which is fastest and so used?
David
> }
> - } else if (IS_ENABLED(CONFIG_X86_64) || raid6_has_sse2()) {
> + } else if (IS_ENABLED(CONFIG_X86_64) ||
> + boot_cpu_has(X86_FEATURE_XMM2)) {
> /* x86_64 can assume SSE2 as baseline */
> raid6_algo_add(&raid6_sse2x1);
> raid6_algo_add(&raid6_sse2x2);
> if (IS_ENABLED(CONFIG_X86_64))
> raid6_algo_add(&raid6_sse2x4);
> + if (boot_cpu_has(X86_FEATURE_SSSE3))
> + raid6_recov_algo_add(&raid6_recov_ssse3);
> } else {
> raid6_algo_add_default();
> }
> -
> - if (raid6_has_avx512())
> - raid6_recov_algo_add(&raid6_recov_avx512);
> - else if (raid6_has_avx2())
> - raid6_recov_algo_add(&raid6_recov_avx2);
> - else if (raid6_has_ssse3())
> - raid6_recov_algo_add(&raid6_recov_ssse3);
> }
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 0/3] raid: remove obsolete MMX optimized code
2026-10-25 19:12 [PATCH 0/3] raid: remove obsolete MMX optimized code Eric Biggers
` (2 preceding siblings ...)
2026-10-25 19:12 ` [PATCH 3/3] raid6: simplify CPU feature checks Eric Biggers
@ 2026-10-26 15:00 ` David Laight
2026-10-27 15:07 ` Christoph Hellwig
4 siblings, 0 replies; 8+ messages in thread
From: David Laight @ 2026-10-26 15:00 UTC (permalink / raw)
To: Eric Biggers
Cc: linux-raid, Andrew Morton, linux-crypto, x86, linux-kernel,
Christoph Hellwig
On Sun, 25 Oct 2026 12:12:04 -0700
Eric Biggers <ebiggers@kernel.org> wrote:
> This series retires 32-bit MMX optimizations for RAID.
>
> Affected CPUs, such as the Pentium MMX and Pentium II, will just fall
> back to the existing well-tested scalar code instead.
Seems like a good idea.
I wonder if all that loop unrolling was needed :-)
David
>
> This was the only remaining MMX optimized code in the kernel. MMX
> optimizations for the much more commonly called functions memcpy(),
> copy_page(), and clear_page() were already removed years ago by commit
> c6dbd3e5e69c ("x86/mmx_32: Remove X86_USE_3DNOW"). There are zero MMX
> optimizations for anything else, like crypto or CRC, which left the RAID
> code as an outlier.
>
> Patch 3 also cleans up the CPU feature checks in the RAID6 code.
>
> Eric Biggers (3):
> xor: remove MMX optimized code
> raid6: remove MMX optimized code
> raid6: simplify CPU feature checks
>
> lib/raid/raid6/Makefile | 4 -
> lib/raid/raid6/x86/mmx.c | 118 --------
> lib/raid/raid6/x86/pq_arch.h | 69 +----
> lib/raid/raid6/x86/sse1.c | 136 ---------
> lib/raid/xor/Makefile | 2 +-
> lib/raid/xor/x86/xor-mmx.c | 515 -----------------------------------
> lib/raid/xor/x86/xor_arch.h | 5 -
> 7 files changed, 12 insertions(+), 837 deletions(-)
> delete mode 100644 lib/raid/raid6/x86/mmx.c
> delete mode 100644 lib/raid/raid6/x86/sse1.c
> delete mode 100644 lib/raid/xor/x86/xor-mmx.c
>
>
> base-commit: 21a7f44fd0765fcc5194130b28767786eba1d1e7
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 3/3] raid6: simplify CPU feature checks
2026-10-26 14:57 ` David Laight
@ 2026-10-26 18:47 ` Eric Biggers
0 siblings, 0 replies; 8+ messages in thread
From: Eric Biggers @ 2026-10-26 18:47 UTC (permalink / raw)
To: David Laight
Cc: linux-raid, Andrew Morton, linux-crypto, x86, linux-kernel,
Christoph Hellwig
On Mon, Oct 26, 2026 at 02:57:04PM +0000, David Laight wrote:
> On Sun, 25 Oct 2026 12:12:07 -0700
> Eric Biggers <ebiggers@kernel.org> wrote:
>
> > Remove unnecessary checks for features that are prerequisites for other
> > features, such as AVX which is a prerequisite for AVX2.
> >
> > (Note: in most cases arch/x86/kernel/cpu/cpuid-deps.c warns about
> > missing prerequisites rather than enforcing them. This is intentional,
> > and it does not mean the prerequisites should be checked elsewhere.)
> >
> > Then, move the raid6_recov_algo_add() lines into the appropriate places
> > just above so that the same CPU features aren't checked multiple times.
> >
> > Signed-off-by: Eric Biggers <ebiggers@kernel.org>
> > ---
> > lib/raid/raid6/x86/pq_arch.h | 51 ++++++++----------------------------
> > 1 file changed, 11 insertions(+), 40 deletions(-)
> >
> > diff --git a/lib/raid/raid6/x86/pq_arch.h b/lib/raid/raid6/x86/pq_arch.h
> > index 4a863b253b909..418e4d4a2930f 100644
> > --- a/lib/raid/raid6/x86/pq_arch.h
> > +++ b/lib/raid/raid6/x86/pq_arch.h
> > @@ -16,63 +16,34 @@ extern const struct raid6_recov_calls raid6_recov_ssse3;
> > extern const struct raid6_recov_calls raid6_recov_avx2;
> > extern const struct raid6_recov_calls raid6_recov_avx512;
> >
> > ...
> > static __always_inline void __init arch_raid6_init(void)
> > {
> > - if (raid6_has_avx2()) {
> > + if (boot_cpu_has(X86_FEATURE_AVX2)) {
> > raid6_algo_add(&raid6_avx2x1);
> > raid6_algo_add(&raid6_avx2x2);
> > if (IS_ENABLED(CONFIG_X86_64))
> > raid6_algo_add(&raid6_avx2x4);
> > - if (raid6_has_avx512()) {
> > + if (boot_cpu_has(X86_FEATURE_AVX512BW) &&
> > + boot_cpu_has(X86_FEATURE_AVX512VL) &&
> > + boot_cpu_has(X86_FEATURE_AVX512DQ)) {
> > raid6_algo_add(&raid6_avx512x1);
> > raid6_algo_add(&raid6_avx512x2);
> > if (IS_ENABLED(CONFIG_X86_64))
> > raid6_algo_add(&raid6_avx512x4);
> > + raid6_recov_algo_add(&raid6_recov_avx512);
> > + } else {
> > + raid6_recov_algo_add(&raid6_recov_avx2);
>
> Is that right (you haven't changed it)?
> You get both the avx2 and axv512 normal algorithms, but only one
> of the recov ones.
>
> I presume these are added in addition to the generic C code and
> some startup test decides which is fastest and so used?
Yes, it's unchanged from before.
The raid6 library implements runtime benchmark-based selection for
struct raid6_algo, but not for struct raid6_recov_algo where only one
can be registered. As always, you're welcome to check the code rather
than speculate; see lib/raid/raid6/algos.c.
Yes, it's inconsistent. However, changing that is outside the scope of
this series. (FWIW, none of the crypto or CRC code uses runtime
benchmark-based selection. I think it's not worth it.)
- Eric
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 0/3] raid: remove obsolete MMX optimized code
2026-10-25 19:12 [PATCH 0/3] raid: remove obsolete MMX optimized code Eric Biggers
` (3 preceding siblings ...)
2026-10-26 15:00 ` [PATCH 0/3] raid: remove obsolete MMX optimized code David Laight
@ 2026-10-27 15:07 ` Christoph Hellwig
4 siblings, 0 replies; 8+ messages in thread
From: Christoph Hellwig @ 2026-10-27 15:07 UTC (permalink / raw)
To: Eric Biggers
Cc: linux-raid, Andrew Morton, linux-crypto, x86, linux-kernel,
Christoph Hellwig
Looks good:
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-10-27 15:07 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-25 19:12 [PATCH 0/3] raid: remove obsolete MMX optimized code Eric Biggers
2026-10-25 19:12 ` [PATCH 1/3] xor: " Eric Biggers
2026-10-25 19:12 ` [PATCH 2/3] raid6: " Eric Biggers
2026-10-25 19:12 ` [PATCH 3/3] raid6: simplify CPU feature checks Eric Biggers
2026-10-26 14:57 ` David Laight
2026-10-26 18:47 ` Eric Biggers
2026-10-26 15:00 ` [PATCH 0/3] raid: remove obsolete MMX optimized code David Laight
2026-10-27 15:07 ` Christoph Hellwig
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®