[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <06d43a86-204f-4658-9759-d24b7038b2d3@intel.com>
Date: Wed, 13 Aug 2025 11:21:23 -0700
From: Dave Hansen <dave.hansen@...el.com>
To: "Chang S. Bae" <chang.seok.bae@...el.com>, x86@...nel.org
Cc: tglx@...utronix.de, mingo@...hat.com, bp@...en8.de,
dave.hansen@...ux.intel.com, colinmitchell@...gle.com, chao.gao@...el.com,
abusse@...zon.de, linux-kernel@...r.kernel.org
Subject: Re: [PATCH v4 2/6] x86/microcode/intel: Establish staging control
logic
On 8/13/25 10:26, Chang S. Bae wrote:
> When microcode staging is initiated, operations are carried out through
> an MMIO interface. Each package has a unique interface specified by the
> IA32_MCU_STAGING_MBOX_ADDR MSR, which maps to a set of 32-bit registers.
>
> Prepare staging with the following steps:
>
> 1. Ensure the microcode image is 32-bit aligned to match the MMIO
> register size.
>
> 2. Identify each MMIO interface based on its per-package scope.
>
> 3. Invoke the staging function for each identified interface, which
> will be implemented separately.
>
> Also, define cpu_primary_thread_mask for the CONFIG_SMP=n case, allowing
> consistent use when narrowing down primary threads to locate the
> per-package interface.
...
> static inline unsigned int topology_amd_nodes_per_pkg(void) { return 1; }
> +#define cpu_primary_thread_mask cpu_none_mask
> #endif /* !CONFIG_SMP */
Isn't 'cpu_none_mask' a mask containing no CPUs? How can that possible
work here:
for_each_cpu(cpu, cpu_primary_thread_mask) {
? Wouldn't it just not run through the for loop at all on CONFIG_SMP=n?
Is that what we want for some reason? I would have thought that we'd
still want to find the MMIO address for CPU 0, the one and only CPU.
> static inline void arch_fix_phys_package_id(int num, u32 slot)
> diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c
> index 371ca6eac00e..468c4d3d5d66 100644
> --- a/arch/x86/kernel/cpu/microcode/intel.c
> +++ b/arch/x86/kernel/cpu/microcode/intel.c
> @@ -299,6 +299,55 @@ static __init struct microcode_intel *scan_microcode(void *data, size_t size,
> return size ? NULL : patch;
> }
>
> +/*
> + * Handle the staging process using the mailbox MMIO interface.
> + * Return the result state.
> + */
> +static enum ucode_state do_stage(u64 mmio_pa)
> +{
> + pr_debug_once("Staging implementation is pending.\n");
> + return UCODE_ERROR;
> +}
> +
> +static void stage_microcode(void)
> +{
> + unsigned int pkg_id = UINT_MAX;
> + enum ucode_state ret;
> + int cpu, err;
> + u64 mmio_pa;
> +
> + if (!IS_ALIGNED(get_totalsize(&ucode_patch_late->hdr), sizeof(u32)))
> + return;
> +
> + lockdep_assert_cpus_held();
> +
> + /*
> + * The MMIO address is unique per package, and all the SMT
> + * primary threads are online here. Find each MMIO space by
> + * their package ids to avoid duplicate staging.
> + */
> + for_each_cpu(cpu, cpu_primary_thread_mask) {
> + if (topology_logical_package_id(cpu) == pkg_id)
> + continue;
> + pkg_id = topology_logical_package_id(cpu);
> +
> + err = rdmsrl_on_cpu(cpu, MSR_IA32_MCU_STAGING_MBOX_ADDR, &mmio_pa);
> + if (WARN_ON_ONCE(err))
> + return;
> +
> + ret = do_stage(mmio_pa);
> + if (ret != UCODE_OK) {
> + pr_err("Error: staging failed with %s for CPU%d at package %u.\n",
> + ret == UCODE_TIMEOUT ? "timeout" : "error state",
> + cpu, pkg_id);
> + return;
> + }
> + }
> +
> + pr_info("Staging of patch revision 0x%x succeeded.\n",
> + ((struct microcode_header_intel *)ucode_patch_late)->rev);
> +}
Hmmm. Consider:
static struct microcode_intel *ucode_patch_late __read_mostly;
and:
struct microcode_intel {
struct microcode_header_intel hdr;
unsigned int bits[];
};
So isn't this whole ugly cast thing equivalent to:
ucode_patch_late->hdr.rev
?
Powered by blists - more mailing lists