[PATCH 0/3] zstd: probe the CPU for BMI2 support once, not per context

From: Usama Arif

Date: Wed Aug 26 2026 - 08:26:39 EST


zstd picks between BMI2 and generic code paths at runtime, and issues
CPUID to decide every time a compression or decompression context is set
up. The answer cannot change while the kernel is running.

It is not a cold path: squashfs calls zstd_init_dstream() for every block
it decompresses, and erofs, btrfs, f2fs and crypto/zstd all initialise a
context per operation. Each probe is two serializing CPUID instructions
on x86.

Patch 1 routes ZSTD_initStaticCCtx() through ZSTD_cpuSupportsBmi2()
instead of open-coding the probe, which also fixes it testing for BMI2
without BMI1 - the bodies it selects are tagged
TARGET_ATTRIBUTE("lzcnt,bmi,bmi2"), so both are needed. No CPU in the
field implements BMI2 without BMI1, so this is latent. Patch 2 skips the
probe when DYNAMIC_BMI2 is 0, where every consumer ignores the flag
anyway. Patch 3 caches the result.

A 4 KiB crypto_acomp benchmark [1] in a one-vCPU KVM guest, twelve boots
of nine 30,000-operation rounds, median per-round mean over 108 rounds:

compress decompress
unpatched 16,756 ns 3,455 ns
patched 13,646 ns 1,002 ns
-3,110 ns -2,452 ns
(18.6%) (71.0%)

The main reason is because CPUID is an unconditional VM exit.

[1] https://gist.github.com/uarif1/5cf02f0e22c23f0d1b3d84348f12914c

Usama Arif (3):
zstd: use ZSTD_cpuSupportsBmi2() in ZSTD_initStaticCCtx()
zstd: skip the BMI2 probe when dynamic BMI2 dispatch is disabled
zstd: probe the CPU for BMI2 support only once

lib/zstd/common/zstd_internal.h | 22 ++++++++++++++++++++--
lib/zstd/compress/zstd_compress.c | 2 +-
2 files changed, 21 insertions(+), 3 deletions(-)


base-commit: 4b18edbd8e70f7e6860d56370f13244896d0f95c
--
2.53.0-Meta