mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Usama Arif <usama.arif@linux.dev>
To: dsterba@suse.com, linux-kernel@vger.kernel.org, terrelln@fb.com,
	linux-crypto@vger.kernel.org, yosry@kernel.org
Cc: hannes@cmpxchg.org, nphamcs@gmail.com, chengming.zhou@linux.dev,
	shakeel.butt@linux.dev, kernel-team@meta.com,
	Usama Arif <usama.arif@linux.dev>
Subject: [PATCH 3/3] zstd: probe the CPU for BMI2 support only once
Date: Wed, 26 Aug 2026 05:25:38 -0700	[thread overview]
Message-ID: <20260826122558.2662013-4-usama.arif@linux.dev> (raw)
In-Reply-To: <20260826122558.2662013-1-usama.arif@linux.dev>

ZSTD_cpuSupportsBmi2() issues CPUID on every context setup for an answer
that cannot change while the kernel is running.  On x86 that is two
serializing CPUID instructions, and the callers are not rare:
squashfs, erofs, btrfs, f2fs and crypto/zstd all initialise a context
per operation, so a busy squashfs or zswap workload pays for it per
block or per page.  Under KVM it is worse, because CPUID is an
unconditional VM exit.

Cache the result.  Keeping the cache as a single int with a negative
sentinel, rather than a copy of ZSTD_cpuid_t, keeps it to one word: a
racing pair of probes computes the same value from the same CPUID leaf,
so the unsynchronized access is benign, and READ_ONCE()/WRITE_ONCE()
keep the compiler and KCSAN in agreement about that.

ZSTD_cpuSupportsBmi2() is MEM_STATIC, so each translation unit that
inlines it gets its own cache - three in a modular build, plus one in
each preboot decompressor.  That is a handful of ints in bss and one
extra probe apiece, not worth avoiding.

The cached answer is the one the probing CPU reported.  zstd could
already be migrated between the probe and the use of the flag, so this
does not introduce a heterogeneity question that was not there before.

Suggested-by: Yosry Ahmed <yosry@kernel.org>
Signed-off-by: Usama Arif <usama.arif@linux.dev>
---
 lib/zstd/common/zstd_internal.h | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/lib/zstd/common/zstd_internal.h b/lib/zstd/common/zstd_internal.h
index 41f190b533209..b179f44753598 100644
--- a/lib/zstd/common/zstd_internal.h
+++ b/lib/zstd/common/zstd_internal.h
@@ -312,8 +312,21 @@ 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);
+    /*
+     * The answer cannot change over the life of the kernel, so probe
+     * once.  Racing probes compute the same value, so the unsynchronized
+     * access is benign; the annotations are there to keep it that way.
+     */
+    static int supported = -1;
+    int s = READ_ONCE(supported);
+
+    if (s < 0) {
+        ZSTD_cpuid_t const cpuid = ZSTD_cpuid();
+
+        s = ZSTD_cpuid_bmi1(cpuid) && ZSTD_cpuid_bmi2(cpuid);
+        WRITE_ONCE(supported, s);
+    }
+    return s;
 #else
     /* Nothing looks at the flag in this configuration. */
     return 0;
-- 
2.53.0-Meta


  parent reply	other threads:[~2026-08-26 12:26 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-26 12:25 [PATCH 0/3] zstd: probe the CPU for BMI2 support once, not per context Usama Arif
2026-08-26 12:25 ` [PATCH 1/3] zstd: use ZSTD_cpuSupportsBmi2() in ZSTD_initStaticCCtx() Usama Arif
2026-08-26 12:25 ` [PATCH 2/3] zstd: skip the BMI2 probe when dynamic BMI2 dispatch is disabled Usama Arif
2026-08-26 12:25 ` Usama Arif [this message]
2026-08-26 17:10 ` [PATCH 0/3] zstd: probe the CPU for BMI2 support once, not per context Nhat Pham
2026-08-27  2:39 ` Eric Biggers
2026-08-27 14:21   ` Usama Arif

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260826122558.2662013-4-usama.arif@linux.dev \
    --to=usama.arif@linux.dev \
    --cc=chengming.zhou@linux.dev \
    --cc=dsterba@suse.com \
    --cc=hannes@cmpxchg.org \
    --cc=kernel-team@meta.com \
    --cc=linux-crypto@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=nphamcs@gmail.com \
    --cc=shakeel.butt@linux.dev \
    --cc=terrelln@fb.com \
    --cc=yosry@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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®