Skip to content

x86/microcode: Add staging support for Intel late microcode update - #135

Open
libo-gcs85 wants to merge 1 commit into
openvelinux:5.15-velinuxfrom
libo-gcs85:hotfix/microcode_update_bug_ve
Open

libo-gcs85 wants to merge 1 commit into
openvelinux:5.15-velinuxfrom
libo-gcs85:hotfix/microcode_update_bug_ve

Conversation

@libo-gcs85

Copy link
Copy Markdown

Backport the Intel microcode staging feature from upstream v6.6 (commit 7cdda85ed90c and subsequent series) to 5.10, adapted for kpatch hot-patching deployment.

Intel CPU microcode late-loading via stop_machine() requires all CPUs to be halted during the entire data transfer and activation process. As microcode patch sizes grow, this critical section becomes increasingly long, causing business process timeouts, NMI watchdog false positives, and latency-sensitive workload disruptions.

The staging feature addresses this by pre-loading the microcode image into each CPU package's internal staging buffer via an MMIO mailbox interface before entering stop_machine(). The subsequent activation inside the critical section only needs to trigger the already-staged copy, dramatically reducing the halt time.

Implementation summary:

  • Add staging_available(): two-level MSR enumeration check (ARCH_CAP_MCU_ENUM + MCU_STAGING) with vendor/family/IA64 guard, matching upstream init_intel_microcode() preconditions.
  • Add find_microcode_patch(): mirror intel.c's static find_patch() to locate the matching microcode image from the global microcode_cache list.
  • Add MMIO mailbox read/write helpers, staging state machine, and per-package staging loop — all ported from upstream intel.c with upstream comments preserved.
  • Insert stage_microcode() call in reload_store() inside microcode_mutex critical section, between mutex_lock() and microcode_reload_late(), to protect microcode_cache reads.

Key differences from upstream 6.6 due to 5.10 constraints:

  • All staging code is in core.c (upstream splits across intel.c and internal.h via microcode_ops callback — not viable for kpatch as it would require struct layout changes).
  • CPU traversal uses for_each_online_cpu() + topology_sibling_cpumask() to identify primary threads (upstream uses cpu_primary_thread_mask which does not exist in 5.10).
  • min_t() used instead of min() for PAGE_SIZE vs unsigned int type mismatch in 5.10.
  • Explicit vendor/family/IA64 check added in staging_available() since the code runs in core.c rather than being guarded by init_intel_microcode().

Staging is best-effort: any failure silently falls back to the traditional DRAM-to-engine path inside stop_machine(), preserving existing behavior.

Backport the Intel microcode staging feature from upstream v6.6 (commit
7cdda85ed90c and subsequent series) to 5.10, adapted for kpatch hot-patching
deployment.

Intel CPU microcode late-loading via stop_machine() requires all CPUs to be
halted during the entire data transfer and activation process. As microcode
patch sizes grow, this critical section becomes increasingly long, causing
business process timeouts, NMI watchdog false positives, and latency-sensitive
workload disruptions.

The staging feature addresses this by pre-loading the microcode image into
each CPU package's internal staging buffer via an MMIO mailbox interface
*before* entering stop_machine(). The subsequent activation inside the
critical section only needs to trigger the already-staged copy, dramatically
reducing the halt time.

Implementation summary:
  - Add staging_available(): two-level MSR enumeration check
    (ARCH_CAP_MCU_ENUM + MCU_STAGING) with vendor/family/IA64 guard,
    matching upstream init_intel_microcode() preconditions.
  - Add find_microcode_patch(): mirror intel.c's static find_patch()
    to locate the matching microcode image from the global
    microcode_cache list.
  - Add MMIO mailbox read/write helpers, staging state machine, and
    per-package staging loop — all ported from upstream intel.c with
    upstream comments preserved.
  - Insert stage_microcode() call in reload_store() inside
    microcode_mutex critical section, between mutex_lock() and
    microcode_reload_late(), to protect microcode_cache reads.

Key differences from upstream 6.6 due to 5.10 constraints:
  - All staging code is in core.c (upstream splits across intel.c and
    internal.h via microcode_ops callback — not viable for kpatch as it
    would require struct layout changes).
  - CPU traversal uses for_each_online_cpu() + topology_sibling_cpumask()
    to identify primary threads (upstream uses cpu_primary_thread_mask
    which does not exist in 5.10).
  - min_t() used instead of min() for PAGE_SIZE vs unsigned int type
    mismatch in 5.10.
  - Explicit vendor/family/IA64 check added in staging_available() since
    the code runs in core.c rather than being guarded by
    init_intel_microcode().

Staging is best-effort: any failure silently falls back to the traditional
DRAM-to-engine path inside stop_machine(), preserving existing behavior.

Signed-off-by: Qinyun Tan <qinyuntan@linux.alibaba.com>
Signed-off-by: Bo Li <libo.gcs85@bytedance.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant