lib/raid/xor: x86: Add AVX-512 optimized xor_gen()
Subsystems (3)
PATCH v3 1/1 lib/raid/xor: x86: Add AVX-512 optimized xor_gen()
Add an implementation of xor_gen() using AVX-512.
It uses 512-bit vectors, i.e. ZMM registers. It also uses the vpternlogq instruction to do three-input XORs when applicable.
It's enabled on x86_64 CPUs that have AVX512F && !PREFER_YMM. In practice that means:
- AMD Zen 4 and later (client and server)
- Intel Sapphire Rapids and later (server)
- Intel Rocket Lake (client)
- Intel Nova Lake and later (client)
The !PREFER_YMM condition excludes the older AVX-512 implementations in Intel Skylake Server and Intel Ice Lake. They could run this code, but they're known to have overly-eager downclocking when ZMM registers are used. This is the same policy that the crypto and CRC code uses.
Benchmark on AMD Ryzen 9 9950X (Zen 5):
src_cnt avx avx512 Improvement
======= ========== ========== ===========
1 56353 MB/s 75388 MB/s 33%
2 54274 MB/s 68409 MB/s 26%
3 44649 MB/s 64042 MB/s 43%
4 41315 MB/s 55002 MB/s 33%Note: for now I omitted the cpu_has_xfeatures() check that the AVX-512 optimized crypto and CRC code does, since it's not implemented on User-Mode Linux and it's never been present in the RAID6 code either.
---
Changed in v3:
- Renamed p0-p4 to p1-p5 to match the inline asm indices
- Swapped the base and index registers to the logical order
- Added David's Reviewed-by
Changed in v2:
- Fixed build on UML
- Reworked the implementation
lib/raid/xor/Makefile | 2 +- lib/raid/xor/x86/xor-avx512.c | 121 ++++++++++++++++++++++++++++++++++ lib/raid/xor/x86/xor_arch.h | 26 ++++---- 3 files changed, 137 insertions(+), 12 deletions(-) create mode 100644 lib/raid/xor/x86/xor-avx512.c
lib/raid/xor/Makefile +1 -1
@@ -26,11 +26,11 @@ xor-$(CONFIG_ALTIVEC) += powerpc/xor_vmx.o powerpc/xor_vmx_glue.o 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_64) += 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/ CFLAGS_arm/xor-neon.o += $(CC_FLAGS_FPU) CFLAGS_REMOVE_arm/xor-neon.o += $(CC_FLAGS_NO_FPU)
lib/raid/xor/x86/xor-avx512.c new file +121 -0
121 lines not on this page · raw message
lib/raid/xor/x86/xor_arch.h +15 -11
@@ -4,26 +4,30 @@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; +extern struct xor_block_template xor_block_avx512; -/* -* When SSE is available, use it as it can write around L2. We may also be able -* to load into the L1 only depending on how the cpu deals with a load to a line -* that is being prefetched. -* -* When AVX2 is available, force using it as it is better by all measures. -* -* 32-bit without MMX can fall back to the generic routines. -*/ static __always_inline void __init arch_xor_init(void) { -if (boot_cpu_has (X86_FEATURE_AVX ) && -boot_cpu_has (X86_FEATURE_OSXSAVE )) { +if (IS_ENABLED (CONFIG_X86_64 ) &&boot_cpu_has (X86_FEATURE_AVX512F ) && +boot_cpu_has (X86_FEATURE_OSXSAVE ) && + !boot_cpu_has (X86_FEATURE_PREFER_YMM )) { +/* AVX-512 will be the best; no need to try others. */ +/* !PREFER_YMM excludes CPUs with overly-eager downclocking. */ +xor_force (&xor_block_avx512); + }else if (boot_cpu_has (X86_FEATURE_AVX ) && +boot_cpu_has (X86_FEATURE_OSXSAVE )) { +/* AVX will be the best; no need to try others. */ xor_force (&xor_block_avx); }else if (IS_ENABLED (CONFIG_X86_64 ) ||boot_cpu_has (X86_FEATURE_XMM )) { +/* +* When SSE is available, use it as it can write around L2. We +* may also be able to load into the L1 only depending on how +* the cpu deals with a load to a line that is being prefetched. +*/ 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);
base-commit: 8cd9520d35a6c38db6567e97dd93b1f11f185dc6
Signature · 1 line
2.54.0
[email protected]
AI reviewThank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [High] The AVX-512 XOR implementation is forced based solely on `boot_cpu_has(X86_FEATURE_AVX512F)`…
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] The AVX-512 XOR implementation is forced based solely on boot_cpu_has(X86_FEATURE_AVX512F) without checking if the OS actually manages ZMM registers via cpu_has_xfeatures(). This introduces an Undefined Opcode (#UD) kernel panic vulnerability on systems where AVX-512 is supported by the CPU but restricted in XCR0. --
commit b63aaca8e8b386ef1820d1caac3bce2cb328e8c3
Author: Eric Biggers <[email protected]>
lib/raid/xor: x86: Add AVX-512 optimized xor_gen()
This commit adds an AVX-512 implementation of xor_gen() using 512-bit ZMM registers and the vpternlogq instruction. It enables this implementation on x86_64 CPUs that support AVX512F but do not prefer YMM registers, avoiding known downclocking issues on older architectures. The implementation explicitly omits the cpu_has_xfeatures() check.
Quoted 3 lines
Note: for now I omitted the
cpu_has_xfeatures()check that the AVX-512 optimized crypto and CRC code does, since it's not implemented on User-Mode Linux and it's never been present in the RAID6 code either.
[Severity: High]
Does omitting the cpu_has_xfeatures() check introduce a potential Invalid Opcode exception in virtualized environments?
If a hypervisor advertises AVX512F in CPUID but omits the AVX-512 FPU extended state from XSTATE, boot_cpu_has(X86_FEATURE_AVX512F) will evaluate to true, but the OS will not enable AVX-512 in XCR0. Executing 512-bit EVEX instructions without XCR0[7:5] enabled causes an Invalid Opcode exception and kernel panic.
Would it be safer to preserve this check, perhaps providing a stub or using ifdef for User-Mode Linux compatibility instead?
Quoted 4 lines
lib/raid/xor/x86/xor_arch.h +0
-0
[ ... ]
Quoted 6 lines
lib/raid/xor/x86/xor_arch.h +1
-0@@ -6,22 +6,26 @@ 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; +extern struct xor_block_template xor_block_avx512;
lib/raid/xor/x86/xor_arch.h extern struct xor_block_template xor_block_p5_mmx; · line 18
Quoted 10 lines
lib/raid/xor/x86/xor_arch.h +6
-2static __always_inline void __init arch_xor_init(void) { -if (boot_cpu_has (X86_FEATURE_AVX ) && -boot_cpu_has (X86_FEATURE_OSXSAVE )) { +if (IS_ENABLED (CONFIG_X86_64 ) &&boot_cpu_has (X86_FEATURE_AVX512F ) && +boot_cpu_has (X86_FEATURE_OSXSAVE ) && + !boot_cpu_has (X86_FEATURE_PREFER_YMM )) { +/* AVX-512 will be the best; no need to try others. */ +/* !PREFER_YMM excludes CPUs with overly-eager downclocking. */ +xor_force (&xor_block_avx512);
[Severity: High]
Can this force the AVX-512 implementation on systems that do not actually support ZMM registers in the OS?
During boot, fpu__init_system_xstate() limits fpu_kernel_cfg.max_features based on the XSTATE leaf, but does not clear X86_FEATURE_AVX512F from boot_cpu_data.x86_capability. As a result, this check passes and forces xor_block_avx512, which then attempts to execute AVX-512 instructions on an unsupported FPU context.
Is it necessary to include cpu_has_xfeatures(XFEATURE_MASK_AVX512, NULL) here to verify the FPU context supports these instructions before forcing the block?
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
Quoted 3 lines · Eric Biggers
Note: for now I omitted the
cpu_has_xfeatures()check that the AVX-512 optimized crypto and CRC code does, since it's not implemented on User-Mode Linux and it's never been present in the RAID6 code either.
By the way, Sashiko keeps complaining about this decision.
Maybe the x86 maintainers have some advice here?
For context: on x86 processors, executing AVX or AVX512 instructions requires not just that the CPU supports the feature, but also that the operating system has set certain bits in XCR0. For example all EVEX coded instructions (i.e. AVX-512) require XCR0=111xx111b. (See Intel manual "2.6.11.1 State Dependent #UD".)
Therefore most of the kernel's AVX and AVX512 optimized code checks not just X86_FEATURE_AVX* but also calls cpu_has_xfeatures() to check XCR0.
But "most" isn't all. The RAID6 code for example doesn't check cpu_has_xfeatures(). So if you e.g. boot a kernel in QEMU using "-cpu max,xsave=off", it already crashes when the RAID6 code does its boot-time benchmark.
Part of the reason for that omission probably is that UML doesn't provide an implementation of cpu_has_xfeatures(). And the x86 RAID (XOR and RAID6) code is enabled on UML.
It could be implemented for UML by using the xgetbv instruction, like what userspace programs do. (We'd also need to copy the XFEATURE_MASK_* constants, as UML can't include arch/x86/include/asm/fpu/types.h)
But I wanted to ask: do we really care about the case where features are "supported" but their XCR0 bits aren't set? Perhaps the kernel just doesn't/shouldn't support weird cases like "-cpu max,xsave=off"?
If this case indeed needs to be handled, could we make things easier for the kernel's AVX and AVX-512 optimized code? Currently AVX-512 needs:
if (boot_cpu_has(X86_FEATURE_AVX512F) &&
cpu_has_xfeatures(XFEATURE_MASK_FP | XFEATURE_MASK_SSE |
XFEATURE_MASK_YMM | XFEATURE_MASK_AVX512, NULL))
How about we make X86_FEATURE_AVX512F depend on XCR0=111xx111, and X86_FEATURE_AVX depend on XCR0=xxxxx111? Then the cpu_has_xfeatures() check wouldn't be needed. Is there any reason not to do that?
- Eric
Quoted 5 lines · Eric Biggers
But I wanted to ask: do we really care about the case where features are "supported" but their XCR0 bits aren't set? Perhaps the kernel just doesn't/shouldn't support weird cases like "-cpu max,xsave=off"?
Yes, our aim is to support only configurations which are actually present in real hardware and not a "oh, it would be good if it did that, just because..."
Quoted 10 lines
If this case indeed needs to be handled, could we make things easier for the kernel's AVX and AVX-512 optimized code? Currently AVX-512 needs:
if (
boot_cpu_has(X86_FEATURE_AVX512F)&&
cpu_has_xfeatures(XFEATURE_MASK_FP |XFEATURE_MASK_SSE|
XFEATURE_MASK_YMM|XFEATURE_MASK_AVX512, NULL))How about we make
X86_FEATURE_AVX512Fdepend on XCR0=111xx111, andX86_FEATURE_AVXdepend on XCR0=xxxxx111? Then thecpu_has_xfeatures()check wouldn't be needed. Is there any reason not to do that?
How do you want to accomplish that? Very early during boot on the BSP you sanity-check XCR0 and clear feature flags if components are not set?
Thx.
Signature · 1 line
Small device. Typos and formatting crap
Quoted 10 lines · Borislav Petkov
Quoted 5 lines · Eric Biggers
But I wanted to ask: do we really care about the case where features are "supported" but their XCR0 bits aren't set? Perhaps the kernel just doesn't/shouldn't support weird cases like "-cpu max,xsave=off"?
Yes, our aim is to support only configurations which are actually present in real hardware and not a "oh, it would be good if it did that, just because..."
Seems reasonable to me. Would the same apply to UML here?
Quoted 7 lines
Quoted 7 lines
If this case indeed needs to be handled, could we make things easier for the kernel's AVX and AVX-512 optimized code? Currently AVX-512 needs:
if (
boot_cpu_has(X86_FEATURE_AVX512F)&&
cpu_has_xfeatures(XFEATURE_MASK_FP |XFEATURE_MASK_SSE|
XFEATURE_MASK_YMM|XFEATURE_MASK_AVX512, NULL))
Quoted 7 lines
Quoted 3 lines
How about we make
X86_FEATURE_AVX512Fdepend on XCR0=111xx111, andX86_FEATURE_AVXdepend on XCR0=xxxxx111? Then thecpu_has_xfeatures()check wouldn't be needed. Is there any reason not to do that?How do you want to accomplish that? Very early during boot on the BSP you sanity-check XCR0 and clear feature flags if components are not set?
That would be the idea. Something similar to what arch/x86/kernel/cpu/cpuid-deps.c does. Except that seems to only enforce the dependencies when the kernel itself is disabling things; if the hypervisor is broken then it just warns.
In any case, I'd like these to go away:
$ git grep cpu_has_xfeatures | wc -l
31- Eric
Quoted 8 lines · Eric Biggers
Quoted 7 lines · Borislav Petkov
Quoted 5 lines · Eric Biggers
But I wanted to ask: do we really care about the case where features are "supported" but their XCR0 bits aren't set? Perhaps the kernel just doesn't/shouldn't support weird cases like "-cpu max,xsave=off"?
Quoted 5 lines
Quoted 3 lines
Yes, our aim is to support only configurations which are actually present in real hardware and not a "oh, it would be good if it did that, just because..."
Seems reasonable to me. Would the same apply to UML here?
Good question.
Richi?
Quoted 11 lines
Quoted 11 lines
Quoted 10 lines
If this case indeed needs to be handled, could we make things easier for the kernel's AVX and AVX-512 optimized code? Currently AVX-512 needs:
if (
boot_cpu_has(X86_FEATURE_AVX512F)&&
cpu_has_xfeatures(XFEATURE_MASK_FP |XFEATURE_MASK_SSE|
XFEATURE_MASK_YMM|XFEATURE_MASK_AVX512, NULL))How about we make
X86_FEATURE_AVX512Fdepend on XCR0=111xx111, andX86_FEATURE_AVXdepend on XCR0=xxxxx111? Then thecpu_has_xfeatures()check wouldn't be needed. Is there any reason not to do that?
Quoted 6 lines
Quoted 3 lines
How do you want to accomplish that? Very early during boot on the BSP you sanity-check XCR0 and clear feature flags if components are not set?
That would be the idea. Something similar to what
arch/x86/kernel/cpu/cpuid-deps.cdoes.
Yap.
Quoted 2 lines
Except that seems to only enforce the dependencies when the kernel itself is disabling things; if the hypervisor is broken then it just warns.
Not the kernel's problem. We deliberately don't want to maintain a zoo of options which are not present in real hw. If HV is doing funny things, oh well...
Quoted 4 lines
In any case, I'd like these to go away:
$ git grep cpu_has_xfeatures | wc -l 31
Yeah, all in crypto. I can certainly see why.
@dhansen, any other thoughts?
Thx.
Signature · 4 lines
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquetteQuoted 8 lines · Borislav Petkov
Quoted 5 lines
In any case, I'd like these to go away:
$ git grep cpu_has_xfeatures | wc -l 31Yeah, all in crypto. I can certainly see why.
@dhansen, any other thoughts?
If we can get rid of cpu_has_xfeatures(), I'm all for it. I'm not quite sure how the code would look so I'm reserving judgement until I see the patches. But it's worth a try.
Quoted 6 lines · Dave Hansen
Quoted 5 lines · Borislav Petkov
Quoted 5 lines
In any case, I'd like these to go away:
$ git grep cpu_has_xfeatures | wc -l 31
Quoted 7 lines
Quoted 3 lines
Yeah, all in crypto. I can certainly see why.
@dhansen, any other thoughts?
If we can get rid of
cpu_has_xfeatures(), I'm all for it. I'm not quite sure how the code would look so I'm reserving judgement until I see the patches. But it's worth a try.
I think the most important part is to be consistent. Either use it everywhere or not at all.
Quoted 27 lines · On Mon, 15 Jun 2026 13:10:50 -0700 Eric Biggers <[email protected]> wrote:
Quoted 3 lines · Eric Biggers
Note: for now I omitted the
cpu_has_xfeatures()check that the AVX-512 optimized crypto and CRC code does, since it's not implemented on User-Mode Linux and it's never been present in the RAID6 code either.By the way, Sashiko keeps complaining about this decision.
Maybe the x86 maintainers have some advice here?
For context: on x86 processors, executing AVX or AVX512 instructions requires not just that the CPU supports the feature, but also that the operating system has set certain bits in XCR0. For example all EVEX coded instructions (i.e. AVX-512) require XCR0=111xx111b. (See Intel manual "2.6.11.1 State Dependent #UD".)
Therefore most of the kernel's AVX and AVX512 optimized code checks not just X86_FEATURE_AVX* but also calls
cpu_has_xfeatures()to check XCR0.But "most" isn't all. The RAID6 code for example doesn't check
cpu_has_xfeatures(). So if you e.g. boot a kernel in QEMU using "-cpu max,xsave=off", it already crashes when the RAID6 code does its boot-time benchmark.Part of the reason for that omission probably is that UML doesn't provide an implementation of
cpu_has_xfeatures(). And the x86 RAID (XOR and RAID6) code is enabled on UML.
Quoted 7 lines
It could be implemented for UML by using the xgetbv instruction, like what userspace programs do. (We'd also need to copy the XFEATURE_MASK_* constants, as UML can't include
arch/x86/include/asm/fpu/types.h)But I wanted to ask: do we really care about the case where features are "supported" but their XCR0 bits aren't set? Perhaps the kernel just doesn't/shouldn't support weird cases like "-cpu max,xsave=off"?
I think that case definitely matters for userspace.
Isn't it what happens when you run an old OS on a new cpu?
I remember cases where people were compiling programs that used AVX (possibly from gcc's cpu=native) but the os hadn't been updated to actually save the relevant registers.
The programs 'sort of worked' until a process switch failed to preserve the registers.
So the check you need to do is looking at XCR0 rather than anything else.
Quoted 11 lines
If this case indeed needs to be handled, could we make things easier for the kernel's AVX and AVX-512 optimized code? Currently AVX-512 needs:
if (
boot_cpu_has(X86_FEATURE_AVX512F)&&
cpu_has_xfeatures(XFEATURE_MASK_FP |XFEATURE_MASK_SSE|
XFEATURE_MASK_YMM|XFEATURE_MASK_AVX512, NULL))How about we make
X86_FEATURE_AVX512Fdepend on XCR0=111xx111, andX86_FEATURE_AVXdepend on XCR0=xxxxx111? Then thecpu_has_xfeatures()check wouldn't be needed. Is there any reason not to do that?
If cpu_has_xfeatures() is checking (a copy of) XCR0 isn't it enough to just check that XFEATURE_MASK_AVX512 is set - it doesn't make any sense for the other bits to be clear at the same time.
If the XCR0 copy is sane/sanitised you only need to check one bit. That would let you #define the constant to 0 if the kernel is built without the feature and the compiler will optimise the code away.
Then the test would just be:
if (can_use_xfeature(XFEATURE_AVX512))
-- David
Quoted 2 lines
- Eric
Can use the xor: prefix used for all other commits to lib/raid/xor?
Quoted 8 lines
Benchmark on AMD Ryzen 9 9950X (Zen 5):
src_cnt avx avx512 Improvement ======= ========== ========== =========== 1 56353 MB/s 75388 MB/s 33% 2 54274 MB/s 68409 MB/s 26% 3 44649 MB/s 64042 MB/s 43% 4 41315 MB/s 55002 MB/s 33%
On my Zen 5 mobile (AMD Ryzen AI 7 PRO 350) both the existing AVX2 and this AVX512 code give numbers in the 200+ GB/s range. Not sure if is just the different benchmarking or something else going on.
FYI, one or 2 sources are basically useless as they RAID5 configs that have no benefits over simple mirroring and thus the numbers aren't too interesting.
lib/raid/xor/x86/xor-avx512.c line 104
Quoted 2 lines
lib/raid/xor/x86/xor-avx512.c new file +2
-0+DO_XOR_BLOCKS (avx512_inner, xor_avx512_2, xor_avx512_3, xor_avx512_4, + xor_avx512_5);
Is there really much of a benefit of doing the historic DO_XOR_BLOCKS vs doing the loop manually? Especially as the common cases for a modern RAID will usually loop over more disks than this was built for. I.e., in practice one or two source buffers only happen at the end of a loop over more disks.
Quoted 11 lines · On Wed, 17 Jun 2026 07:56:53 +0200 Christoph Hellwig <[email protected]> wrote:
Can use the xor: prefix used for all other commits to
lib/raid/xor?Quoted 8 lines
Benchmark on AMD Ryzen 9 9950X (Zen 5):
src_cnt avx avx512 Improvement ======= ========== ========== =========== 1 56353 MB/s 75388 MB/s 33% 2 54274 MB/s 68409 MB/s 26% 3 44649 MB/s 64042 MB/s 43% 4 41315 MB/s 55002 MB/s 33%
Quoted 3 lines
On my Zen 5 mobile (AMD Ryzen AI 7 PRO 350) both the existing AVX2 and this AVX512 code give numbers in the 200+ GB/s range. Not sure if is just the different benchmarking or something else going on.
I'd expect benchmarking of the xor loop to show that it is doing 2 memory reads every clock.
At 5GHz (I'm sure my zen5 will reach that single threaded) that is 320 GB/s for src_cnt == 1 and 160 GB/s for src_cnt == 3.
200 GB/s with 32 byte cache reads would need a 200/32 = 6GHz cpu just for the reads.
But I expect Eric is benchmarking more code and may be limited by data cache refills.
Quoted 4 lines
FYI, one or 2 sources are basically useless as they RAID5 configs that have no benefits over simple mirroring and thus the numbers aren't too interesting.
With three disks you xor two buffers (src_count == 1) to get the parity to write to the third - so that is a valid RAID5 config.
Quoted 9 lines
lib/raid/xor/x86/xor-avx512.c line 104
Quoted 3 lines
lib/raid/xor/x86/xor-avx512.c new file +2
-0+DO_XOR_BLOCKS (avx512_inner, xor_avx512_2, xor_avx512_3, xor_avx512_4, + xor_avx512_5);Is there really much of a benefit of doing the historic
DO_XOR_BLOCKSvs doing the loop manually? Especially as the common cases for a modern RAID will usually loop over more disks than this was built for. I.e., in practice one or two source buffers only happen at the end of a loop over more disks.
I stopped looking at what was being tested at that point :-)
David
Quoted 6 lines · David Laight
Quoted 3 lines
FYI, one or 2 sources are basically useless as they RAID5 configs that have no benefits over simple mirroring and thus the numbers aren't too interesting.
With three disks you xor two buffers (
src_count== 1) to get the parity to write to the third - so that is a valid RAID5 config.
Sure. It did not say it is invalid, it just isn't very useful.
Quoted 10 lines · On Thu, 18 Jun 2026 11:25:00 +0200 Christoph Hellwig <[email protected]> wrote:
Quoted 6 lines · David Laight
Quoted 3 lines
FYI, one or 2 sources are basically useless as they RAID5 configs that have no benefits over simple mirroring and thus the numbers aren't too interesting.
With three disks you xor two buffers (
src_count== 1) to get the parity to write to the third - so that is a valid RAID5 config.Sure. It did not say it is invalid, it just isn't very useful.
It gives you 2/3 the total capacity, mirroring only gives 1/2. But for a lot of uses I suspect disks are cheap enough that mirroring is usually the 'best bet'.
It also means that there are a set of catastrophic failures that can be more easily recovered.
It is probably more important to ensure all the disks in a raid set come from different production lines - otherwise they are likely to fail at the same time.
At least modern disks don't (seem to) suffer from 'sticky oil' which would tend to stop them restarting after they got cold while turned off. Raid doesn't help when multiple disks fail to start!
David
Quoted 11 lines · Christoph Hellwig
Can use the xor: prefix used for all other commits to
lib/raid/xor?Quoted 8 lines
Benchmark on AMD Ryzen 9 9950X (Zen 5):
src_cnt avx avx512 Improvement ======= ========== ========== =========== 1 56353 MB/s 75388 MB/s 33% 2 54274 MB/s 68409 MB/s 26% 3 44649 MB/s 64042 MB/s 43% 4 41315 MB/s 55002 MB/s 33%
Quoted 3 lines
On my Zen 5 mobile (AMD Ryzen AI 7 PRO 350) both the existing AVX2 and this AVX512 code give numbers in the 200+ GB/s range. Not sure if is just the different benchmarking or something else going on.
I used lib/raid/xor/xor-core.c which measures the throughput of parity data generated, whereas your proposed xor_benchmark() in xor_kunit measures the throughput of source data consumed. I don't know which makes more sense, but we should make them consistent with each other.
Quoted 4 lines
FYI, one or 2 sources are basically useless as they RAID5 configs that have no benefits over simple mirroring and thus the numbers aren't too interesting.
Quoted 8 lines
lib/raid/xor/x86/xor-avx512.c line 104
Quoted 2 lines
lib/raid/xor/x86/xor-avx512.c new file +2
-0+DO_XOR_BLOCKS (avx512_inner, xor_avx512_2, xor_avx512_3, xor_avx512_4, + xor_avx512_5);Is there really much of a benefit of doing the historic
DO_XOR_BLOCKSvs doing the loop manually? Especially as the common cases for a modern RAID will usually loop over more disks than this was built for. I.e., in practice one or two source buffers only happen at the end of a loop over more disks.
There's not really a way out of unrolling by source buffer count, as otherwise the pointers would continuously have to be reloaded into registers. That's why your proposal was so slow (see the numbers I gave in https://lore.kernel.org/linux-crypto/20260612055933.GA6675@sol/ ). It could be something different from 2-5 specifically, or open-coded instead of using the macro if that's all you're asking for, but at a high level the unrolling by source buffer count does seem to be needed.
- Eric