[PATCH] zstd: use kernel CPU feature detection on x86
From: Usama Arif
Date: Thu Aug 27 2026 - 08:34:41 EST
Zstd currently probes CPUID while initializing each compression or
decompression context. This bypasses the x86 feature policy used by the
rest of the kernel and repeats a serializing instruction sequence for
every context.
Use cpu_feature_enabled() in the normal x86 compressor and decompressor
objects. Check ABM, BMI1, and BMI2 because the dispatched functions are
compiled with lzcnt, bmi, and bmi2. The checks are alternatives-patched
at boot.
The effect is especially visible under virtualization, where CPUID
normally causes a VM exit. A 4 KiB crypto_acomp benchmark was run in
one-vCPU KVM guests. Comparing the unpatched baseline with this
three-patch series, the median reported ns/op values were:
before after
compression 16,777 13,635 ns/op (-18.7%)
decompression 3,454 1,006 ns/op (-70.9%)
Keep the existing raw CPUID fallback for preboot and other builds which
cannot use the normal x86 feature infrastructure. Also retain the early
return when dynamic dispatch is disabled.
Signed-off-by: Usama Arif <usama.arif@xxxxxxxxx>
---
lib/zstd/Makefile | 5 +++++
lib/zstd/common/zstd_internal.h | 18 ++++++++++++++----
2 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/lib/zstd/Makefile b/lib/zstd/Makefile
index be218b5e0ed59..db1d1439f5447 100644
--- a/lib/zstd/Makefile
+++ b/lib/zstd/Makefile
@@ -42,3 +42,8 @@ zstd_common-y := \
common/error_private.o \
common/fse_decompress.o \
common/zstd_common.o \
+
+ifeq ($(CONFIG_X86),y)
+CFLAGS_compress/zstd_compress.o += -DZSTD_USE_KERNEL_CPU_FEATURES
+CFLAGS_decompress/zstd_decompress.o += -DZSTD_USE_KERNEL_CPU_FEATURES
+endif
diff --git a/lib/zstd/common/zstd_internal.h b/lib/zstd/common/zstd_internal.h
index 41f190b533209..f7d3bca650747 100644
--- a/lib/zstd/common/zstd_internal.h
+++ b/lib/zstd/common/zstd_internal.h
@@ -31,6 +31,11 @@
#include "fse.h"
#include "huf.h"
#include <linux/xxhash.h> /* XXH_reset, update, digest */
+
+/* Use the kernel's CPU feature policy in normal x86 kernel builds. */
+#if defined(ZSTD_USE_KERNEL_CPU_FEATURES)
+#include <asm/cpufeature.h>
+#endif
#define ZSTD_TRACE 0
/* ---- static assert (debug) --- */
@@ -311,12 +316,17 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
*/
MEM_STATIC int ZSTD_cpuSupportsBmi2(void)
{
-#if DYNAMIC_BMI2
- ZSTD_cpuid_t cpuid = ZSTD_cpuid();
- return ZSTD_cpuid_bmi1(cpuid) && ZSTD_cpuid_bmi2(cpuid);
-#else
+#if !DYNAMIC_BMI2
/* Nothing looks at the flag in this configuration. */
return 0;
+#elif defined(ZSTD_USE_KERNEL_CPU_FEATURES)
+ return cpu_feature_enabled(X86_FEATURE_ABM) &&
+ cpu_feature_enabled(X86_FEATURE_BMI1) &&
+ cpu_feature_enabled(X86_FEATURE_BMI2);
+#else
+ ZSTD_cpuid_t cpuid = ZSTD_cpuid();
+ return ZSTD_cpuid_bmi1(cpuid) &&
+ ZSTD_cpuid_bmi2(cpuid);
#endif
}
--
2.53.0-Meta