Skip to content

[Deepin-Kernel-SIG] [linux 6.18-y] [Deepin] deepin: arm64: cpufeature: disable LSE on some cpus#1564

Merged
opsiff merged 1 commit intodeepin-community:linux-6.18.yfrom
opsiff:linux-6.18.y-2026-03-16-kp920
Mar 16, 2026
Merged

[Deepin-Kernel-SIG] [linux 6.18-y] [Deepin] deepin: arm64: cpufeature: disable LSE on some cpus#1564
opsiff merged 1 commit intodeepin-community:linux-6.18.yfrom
opsiff:linux-6.18.y-2026-03-16-kp920

Conversation

@opsiff
Copy link
Member

@opsiff opsiff commented Mar 16, 2026

deepin inclusion
category: performance

Disable LSE (Large System Extensions) atomic instructions on some systems to improve performance of per-CPU atomic operations. LSE atomics can exhibit significant overhead on certain microarchitectures (e.g., TSV110) due
to "far atomic" implementations bypassing L1 cache. LL/SC (Load-Link/Store-Conditional) is substantially faster.

The default value is 0 (enabled), which automatically disables LSE on some systems. Set to 1 to skip the check enablement on our test systems regardless of performance impact.

When this feature is active, the kernel logs:
"LSE atomics: use llsc for performance, use lse_disable_check=1 to disable the feature."

PS:
Test with byte-unixbench6 in kp920 24c and 64GB memory, improve whole scores by 3.8%.

Test with https://github.com/leitao/debug/tree/main/LSE percpu_bench CPU0:
LSE (stadd) (c 0, d 0): p50: 029.00 ns p95: 029.09 ns p99: 029.12 ns LL/SC (c 0, d 0): p50: 006.57 ns p95: 006.57 ns p99: 006.57 ns LDADD (c 0, d 0): p50: 069.55 ns p95: 069.57 ns p99: 069.71 ns CPU1:
LSE (stadd) (c 0, d 0): p50: 005.79 ns p95: 029.00 ns p99: 029.01 ns LL/SC (c 0, d 0): p50: 006.56 ns p95: 006.58 ns p99: 006.58 ns LDADD (c 0, d 0): p50: 010.04 ns p95: 010.06 ns p99: 010.06 ns CPU2:
LSE (stadd) (c 0, d 0): p50: 005.79 ns p95: 005.79 ns p99: 005.79 ns LL/SC (c 0, d 0): p50: 006.57 ns p95: 006.57 ns p99: 006.57 ns LDADD (c 0, d 0): p50: 069.53 ns p95: 069.56 ns p99: 069.58 ns ...
CPU23:
LSE (stadd) (c 0, d 0): p50: 005.79 ns p95: 005.79 ns p99: 005.79 ns LL/SC (c 0, d 0): p50: 006.57 ns p95: 006.57 ns p99: 006.57 ns LDADD (c 0, d 0): p50: 064.93 ns p95: 064.95 ns p99: 064.97 ns

Link: https://lore.kernel.org/r/e7d539ed-ced0-4b96-8ecd-048a5b803b85@paulmck-laptop [1]
Link: #1320
Link: #1302

(cherry picked from commit 6afecf6) Conflicts:
Documentation/admin-guide/kernel-parameters.txt
(cherry picked from commit 192bed85ce35986c892192933148fd743d775ddf)

Summary by Sourcery

Gate arm64 LSE atomic support behind a CPU-specific capability check that can be overridden via a new kernel parameter.

New Features:

  • Introduce an arm64 capability matcher that selectively disables LSE atomics on microarchitectures where LL/SC performs better, currently targeting HiSilicon TSV110.
  • Add the lse_disable_check kernel parameter to allow overriding the automatic LSE disabling logic on affected systems.

Enhancements:

  • Wire the LSE atomic capability to the new matcher so that the platform can automatically choose LL/SC-based atomics for improved performance on specific CPUs.

@sourcery-ai
Copy link

sourcery-ai bot commented Mar 16, 2026

Reviewer's Guide

Introduces an arm64 runtime check to selectively disable LSE atomics on known slow microarchitectures (currently HiSilicon TSV110), gated by a new boot parameter, and wires this check into the existing LSE capability detection.

Class diagram for updated arm64 LSE capability detection

classDiagram
    class arm64_cpu_capabilities {
        +const char* desc
        +int capability
        +int type
        +bool (*matches)(const arm64_cpu_capabilities* cap, int scope)
        +unsigned int field
        +unsigned int sign
    }

    class arm64_features_entry_LSE_ATOMICS {
        +desc = "LSE atomic instructions"
        +capability = ARM64_HAS_LSE_ATOMICS
        +type = ARM64_CPUCAP_SYSTEM_FEATURE
        +matches = has_lse_capability_check
    }

    class cpufeature_module {
        +bool lse_disable_check
        +int arm64_lse_disable_check(char* str)
        +bool has_lse_capability_check(const arm64_cpu_capabilities* cap, int scope)
        +bool has_cpuid_feature(const arm64_cpu_capabilities* cap, int scope)
    }

    class midr_range {
        +unsigned long min_midr
        +unsigned long max_midr
    }

    class lse_disable_list {
        +midr_range entries
        +MIDR_ALL_VERSIONS(MIDR_HISI_TSV110)
        +sentinel
    }

    class early_param_system {
        +void early_param(const char* name, int (*fn)(char* str))
    }

    cpufeature_module "1" o-- "many" arm64_cpu_capabilities : defines
    arm64_features_entry_LSE_ATOMICS --|> arm64_cpu_capabilities : instance_of

    cpufeature_module --> lse_disable_list : queries
    cpufeature_module --> midr_range : uses

    cpufeature_module --> early_param_system : registers arm64_lse_disable_check

    cpufeature_module ..> arm64_features_entry_LSE_ATOMICS : assigns matches = has_lse_capability_check
Loading

File-Level Changes

Change Details Files
Add runtime boot-parameter-controlled check to disable LSE atomics on specific CPUs and integrate it into the arm64 CPU feature matching path.
  • Introduce lse_disable_check global flag and early_param parser to control behaviour via the lse_disable_check= kernel command line option.
  • Define has_lse_capability_check() that consults a midr_range blacklist (currently MIDR_HISI_TSV110) and, when matched and not overridden, forces LSE capability off and logs an informational message at system scope.
  • Replace the LSE capability .matches callback from has_cpuid_feature to has_lse_capability_check in the arm64_features[] table so that LSE enablement now passes through the new logic.
arch/arm64/kernel/cpufeature.c
Document the new lse_disable_check kernel boot parameter in the admin guide.
  • Add an entry for lse_disable_check describing its purpose (disabling LSE atomics on certain CPUs for performance), default value, and override semantics.
Documentation/admin-guide/kernel-parameters.txt

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • The lse_disable_check flag has inverted semantics relative to its name (0 = perform the check/possibly disable LSE, 1 = skip the check and keep LSE), which is easy to misinterpret; consider renaming it (e.g. to lse_force_enable or similar) to better reflect what a true value does.
  • The lse_disable_list array is defined as a local static const inside has_lse_capability_check; moving it to file scope would avoid re-declaring it on each call and make it easier to extend or share with other feature checks in the future.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The `lse_disable_check` flag has inverted semantics relative to its name (0 = perform the check/possibly disable LSE, 1 = skip the check and keep LSE), which is easy to misinterpret; consider renaming it (e.g. to `lse_force_enable` or similar) to better reflect what a true value does.
- The `lse_disable_list` array is defined as a local `static const` inside `has_lse_capability_check`; moving it to file scope would avoid re-declaring it on each call and make it easier to extend or share with other feature checks in the future.

## Individual Comments

### Comment 1
<location path="arch/arm64/kernel/cpufeature.c" line_range="1727-1731" />
<code_context>
+static bool has_lse_capability_check(const struct arm64_cpu_capabilities *cap,
+										 int scope)
+{
+	/* List of CPUs that LSE are slow more than llsc */
+	static const struct midr_range lse_disable_list[] = {
+		MIDR_ALL_VERSIONS(MIDR_HISI_TSV110),
</code_context>
<issue_to_address>
**nitpick (typo):** Clarify the English in this comment for readability.

The phrase "LSE are slow more than llsc" is unclear. Consider rephrasing to something like "List of CPUs where LSE atomics are slower than LL/SC" or "List of CPUs on which LSE atomics are slower than LL/SC" for readability.

```suggestion
static bool has_lse_capability_check(const struct arm64_cpu_capabilities *cap,
										 int scope)
{
	/* List of CPUs on which LSE atomics are slower than LL/SC */
	static const struct midr_range lse_disable_list[] = {
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +1727 to +1731
static bool has_lse_capability_check(const struct arm64_cpu_capabilities *cap,
int scope)
{
/* List of CPUs that LSE are slow more than llsc */
static const struct midr_range lse_disable_list[] = {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick (typo): Clarify the English in this comment for readability.

The phrase "LSE are slow more than llsc" is unclear. Consider rephrasing to something like "List of CPUs where LSE atomics are slower than LL/SC" or "List of CPUs on which LSE atomics are slower than LL/SC" for readability.

Suggested change
static bool has_lse_capability_check(const struct arm64_cpu_capabilities *cap,
int scope)
{
/* List of CPUs that LSE are slow more than llsc */
static const struct midr_range lse_disable_list[] = {
static bool has_lse_capability_check(const struct arm64_cpu_capabilities *cap,
int scope)
{
/* List of CPUs on which LSE atomics are slower than LL/SC */
static const struct midr_range lse_disable_list[] = {

@Avenger-285714
Copy link
Member

/approve

@deepin-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: Avenger-285714

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds an arm64 CPU-specific capability check to selectively disable LSE atomic instructions on known slow microarchitectures (currently HiSilicon TSV110), with an early boot parameter override and corresponding documentation.

Changes:

  • Add lse_disable_check early kernel parameter and a new LSE capability matcher in arch/arm64/kernel/cpufeature.c.
  • Disable the LSE capability on TSV110 by default (unless overridden) and emit an informational log when it triggers.
  • Document lse_disable_check in Documentation/admin-guide/kernel-parameters.txt.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.

File Description
arch/arm64/kernel/cpufeature.c Introduces lse_disable_check and routes LSE capability matching through a TSV110-based disable list.
Documentation/admin-guide/kernel-parameters.txt Documents the new boot parameter and the resulting kernel log message.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +3512 to +3514
The default value is 0 (enabled), which automatically
disables LSE on some systems. Set to 1 to bypass
the automatic disabling of LSE on affected systems.
the automatic disabling of LSE on affected systems.

When this feature is active, the kernel logs:
"LSE atomics: use llsc for performance, use lse_disable_check=1 to disable the feature."
};

/* Disable LSE when lse_disable_check is 0 and in lse_disable_list */
if (lse_disable_check == 0 && is_midr_in_range_list(read_cpuid_id(), lse_disable_list)) {
early_param("lse_disable_check", arm64_lse_disable_check);

static bool has_lse_capability_check(const struct arm64_cpu_capabilities *cap,
int scope)
/* Disable LSE when lse_disable_check is 0 and in lse_disable_list */
if (lse_disable_check == 0 && is_midr_in_range_list(read_cpuid_id(), lse_disable_list)) {
if (scope == SCOPE_SYSTEM)
pr_info("LSE atomics: use llsc for performance, use lse_disable_check=1 to disable the feature.\n");
deepin inclusion
category: performance

Disable LSE (Large System Extensions) atomic instructions
on some systems to improve performance of per-CPU atomic
operations. LSE atomics can exhibit significant overhead
on certain microarchitectures (e.g., TSV110) due
to "far atomic" implementations	bypassing L1 cache. LL/SC
(Load-Link/Store-Conditional) is substantially faster.

The default value is 0 (enabled), which automatically
disables LSE on some systems. Set to 1 to skip the check
enablement on our test systems regardless of performance
impact.

When this feature is active, the kernel logs:
"LSE atomics: use llsc for performance, use lse_disable_check=1 to disable the feature."

PS:
Test with byte-unixbench6 in kp920 24c and 64GB memory,
improve whole scores by 3.8%.

Test with https://github.com/leitao/debug/tree/main/LSE percpu_bench
CPU0:
LSE (stadd) (c 0, d 0): p50: 029.00 ns p95: 029.09 ns p99: 029.12 ns
LL/SC (c 0, d 0): p50: 006.57 ns p95: 006.57 ns p99: 006.57 ns
LDADD (c 0, d 0): p50: 069.55 ns p95: 069.57 ns p99: 069.71 ns
CPU1:
LSE (stadd) (c 0, d 0): p50: 005.79 ns p95: 029.00 ns p99: 029.01 ns
LL/SC (c 0, d 0): p50: 006.56 ns p95: 006.58 ns p99: 006.58 ns
LDADD (c 0, d 0): p50: 010.04 ns p95: 010.06 ns p99: 010.06 ns
CPU2:
LSE (stadd) (c 0, d 0): p50: 005.79 ns p95: 005.79 ns p99: 005.79 ns
LL/SC (c 0, d 0): p50: 006.57 ns p95: 006.57 ns p99: 006.57 ns
LDADD (c 0, d 0): p50: 069.53 ns p95: 069.56 ns p99: 069.58 ns
...
CPU23:
LSE (stadd) (c 0, d 0): p50: 005.79 ns p95: 005.79 ns p99: 005.79 ns
LL/SC (c 0, d 0): p50: 006.57 ns p95: 006.57 ns p99: 006.57 ns
LDADD (c 0, d 0): p50: 064.93 ns p95: 064.95 ns p99: 064.97 ns

Link: https://lore.kernel.org/r/e7d539ed-ced0-4b96-8ecd-048a5b803b85@paulmck-laptop [1]
Link: deepin-community#1320
Link: deepin-community#1302
Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
(cherry picked from commit 6afecf6)
Conflicts:
	Documentation/admin-guide/kernel-parameters.txt
[Modified for ("arm64: Modify _midr_range() functions to read MIDR/REVIDR internally")]
(cherry picked from commit 192bed85ce35986c892192933148fd743d775ddf)
Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
@opsiff opsiff force-pushed the linux-6.18.y-2026-03-16-kp920 branch from 6833b40 to fb71850 Compare March 16, 2026 14:31
@opsiff opsiff merged commit 14918ea into deepin-community:linux-6.18.y Mar 16, 2026
5 of 8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants