mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [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
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ 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] 7+ 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
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ 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] 7+ 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
  2026-10-26 15:00 ` [PATCH 0/3] raid: remove obsolete MMX optimized code David Laight
  3 siblings, 0 replies; 7+ 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] 7+ 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
  3 siblings, 1 reply; 7+ 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] 7+ 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; 7+ 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] 7+ 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
  3 siblings, 0 replies; 7+ 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] 7+ 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; 7+ 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] 7+ messages in thread

end of thread, other threads:[~2026-10-26 18:47 UTC | newest]

Thread overview: 7+ 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

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®