:p
atchew
Login
Hi, The series is mostly a refactor between everything needed to load microcode and the bare minimum to probe the current microcode revision. The Kconfig option keeps the reading of microcode rev data around, as it's very relevant for security and debuggability in order to deduce which erratas apply to the current platform. The idea is to move everything that must still be compiled with !CONFIG_UCODE onto {,amd-,intel-}base.c, then remove everything else conditionally at the Makefile level. Renaming files (e.g: s/base/core/ and s/core/common/) would better reflect post-series reality, but it'd be annoying for later backports in this general area. Cheers, Alejandro Alejandro Vallejo (4): x86: Split out AMD-specific code to be executed without ucode loading x86: Split out Intel-specific code to be executed without ucode loading x86: Split out early_microcode_load() and microcode_load_one() x86: Add Kconfig option to disable microcode loading xen/arch/x86/Kconfig | 12 ++++ xen/arch/x86/cpu/microcode/Makefile | 9 ++- xen/arch/x86/cpu/microcode/amd-base.c | 55 +++++++++++++++++++ xen/arch/x86/cpu/microcode/amd.c | 55 ++----------------- xen/arch/x86/cpu/microcode/amd.h | 15 +++++ xen/arch/x86/cpu/microcode/base.c | 73 +++++++++++++++++++++++++ xen/arch/x86/cpu/microcode/core.c | 58 +------------------- xen/arch/x86/cpu/microcode/intel-base.c | 50 +++++++++++++++++ xen/arch/x86/cpu/microcode/intel.c | 56 +++---------------- xen/arch/x86/cpu/microcode/intel.h | 16 ++++++ xen/arch/x86/cpu/microcode/private.h | 14 +++++ xen/arch/x86/efi/efi-boot.h | 2 +- xen/arch/x86/platform_hypercall.c | 2 + 13 files changed, 259 insertions(+), 158 deletions(-) create mode 100644 xen/arch/x86/cpu/microcode/amd-base.c create mode 100644 xen/arch/x86/cpu/microcode/amd.h create mode 100644 xen/arch/x86/cpu/microcode/base.c create mode 100644 xen/arch/x86/cpu/microcode/intel-base.c create mode 100644 xen/arch/x86/cpu/microcode/intel.h base-commit: e00c1673992e07ed31e9c60fefa8d053491abbe6 -- 2.43.0
Some code must be executed even with microcode loading disabled to find out the current microcode revision. This is important to determine active erratas and such. With the intent of stripping microcode loading via Kconfig, move such essential AMD-specific code to an amd-base.c file. Not a functional change. Signed-off-by: Alejandro Vallejo <alejandro.garciavallejo@amd.com> --- xen/arch/x86/cpu/microcode/Makefile | 1 + xen/arch/x86/cpu/microcode/amd-base.c | 50 ++++++++++++++++++++++++ xen/arch/x86/cpu/microcode/amd.c | 55 +++------------------------ xen/arch/x86/cpu/microcode/amd.h | 15 ++++++++ 4 files changed, 72 insertions(+), 49 deletions(-) create mode 100644 xen/arch/x86/cpu/microcode/amd-base.c create mode 100644 xen/arch/x86/cpu/microcode/amd.h diff --git a/xen/arch/x86/cpu/microcode/Makefile b/xen/arch/x86/cpu/microcode/Makefile index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/cpu/microcode/Makefile +++ b/xen/arch/x86/cpu/microcode/Makefile @@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_AMD) += amd.o +obj-$(CONFIG_AMD) += amd-base.o obj-y += core.o obj-$(CONFIG_INTEL) += intel.o diff --git a/xen/arch/x86/cpu/microcode/amd-base.c b/xen/arch/x86/cpu/microcode/amd-base.c new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/xen/arch/x86/cpu/microcode/amd-base.c @@ -XXX,XX +XXX,XX @@ +#include <xen/init.h> + +#include <asm/msr.h> +#include <asm/processor.h> +#include <asm/x86-vendors.h> + +#include "amd.h" + +#define pr_debug(x...) ((void)0) + +static void cf_check collect_cpu_info(void) +{ + struct cpu_signature *csig = &this_cpu(cpu_sig); + + memset(csig, 0, sizeof(*csig)); + + csig->sig = cpuid_eax(1); + rdmsrl(MSR_AMD_PATCHLEVEL, csig->rev); + + pr_debug("microcode: CPU%d collect_cpu_info: patch_id=%#x\n", + smp_processor_id(), csig->rev); +} + +static const struct microcode_ops __initconst_cf_clobber amd_ucode_ops = { + .cpu_request_microcode = amd_cpu_request_microcode, + .collect_cpu_info = collect_cpu_info, + .apply_microcode = amd_apply_microcode, + .compare = amd_compare, + .cpio_path = amd_cpio_path, +}; + +void __init ucode_probe_amd(struct microcode_ops *ops) +{ + /* + * The Entrysign vulnerability (SB-7033, CVE-2024-36347) affects Zen1-5 + * CPUs. Taint Xen if digest checking is turned off. + */ + if ( boot_cpu_data.family >= 0x17 && boot_cpu_data.family <= 0x1a && + !opt_digest_check ) + { + printk(XENLOG_WARNING + "Microcode patch additional digest checks disabled\n"); + add_taint(TAINT_CPU_OUT_OF_SPEC); + } + + if ( boot_cpu_data.family < 0x10 ) + return; + + *ops = amd_ucode_ops; +} diff --git a/xen/arch/x86/cpu/microcode/amd.c b/xen/arch/x86/cpu/microcode/amd.c index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/cpu/microcode/amd.c +++ b/xen/arch/x86/cpu/microcode/amd.c @@ -XXX,XX +XXX,XX @@ #include <asm/msr.h> -#include "private.h" - -#define pr_debug(x...) ((void)0) +#include "amd.h" struct equiv_cpu_entry { uint32_t installed_cpu; @@ -XXX,XX +XXX,XX @@ static bool check_digest(const struct container_microcode *mc) return true; } -static void cf_check collect_cpu_info(void) -{ - struct cpu_signature *csig = &this_cpu(cpu_sig); - - memset(csig, 0, sizeof(*csig)); - - csig->sig = cpuid_eax(1); - rdmsrl(MSR_AMD_PATCHLEVEL, csig->rev); - - pr_debug("microcode: CPU%d collect_cpu_info: patch_id=%#x\n", - smp_processor_id(), csig->rev); -} - static bool verify_patch_size(uint32_t patch_size) { uint32_t max_size; @@ -XXX,XX +XXX,XX @@ static bool microcode_fits_cpu(const struct microcode_patch *patch) return equiv.id == patch->processor_rev_id; } -static int cf_check amd_compare( +int cf_check amd_compare( const struct microcode_patch *old, const struct microcode_patch *new) { /* Both patches to compare are supposed to be applicable to local CPU. */ @@ -XXX,XX +XXX,XX @@ static bool check_min_rev(const struct microcode_patch *patch) return this_cpu(cpu_sig).rev >= patch->min_rev; } -static int cf_check apply_microcode(const struct microcode_patch *patch, - unsigned int flags) +int cf_check amd_apply_microcode(const struct microcode_patch *patch, + unsigned int flags) { int hw_err, result; unsigned int cpu = smp_processor_id(); @@ -XXX,XX +XXX,XX @@ static int scan_equiv_cpu_table(const struct container_equiv_table *et) return -ESRCH; } -static struct microcode_patch *cf_check cpu_request_microcode( +struct microcode_patch *cf_check amd_cpu_request_microcode( const void *buf, size_t size, bool make_copy) { const struct microcode_patch *saved = NULL; @@ -XXX,XX +XXX,XX @@ static struct microcode_patch *cf_check cpu_request_microcode( return patch; } -static const char __initconst amd_cpio_path[] = +const char __initconst amd_cpio_path[] = "kernel/x86/microcode/AuthenticAMD.bin"; -static const struct microcode_ops __initconst_cf_clobber amd_ucode_ops = { - .cpu_request_microcode = cpu_request_microcode, - .collect_cpu_info = collect_cpu_info, - .apply_microcode = apply_microcode, - .compare = amd_compare, - .cpio_path = amd_cpio_path, -}; - -void __init ucode_probe_amd(struct microcode_ops *ops) -{ - /* - * The Entrysign vulnerability (SB-7033, CVE-2024-36347) affects Zen1-5 - * CPUs. Taint Xen if digest checking is turned off. - */ - if ( boot_cpu_data.family >= 0x17 && boot_cpu_data.family <= 0x1a && - !opt_digest_check ) - { - printk(XENLOG_WARNING - "Microcode patch additional digest checks disabled\n"); - add_taint(TAINT_CPU_OUT_OF_SPEC); - } - - if ( boot_cpu_data.family < 0x10 ) - return; - - *ops = amd_ucode_ops; -} - #if 0 /* Manual CONFIG_SELF_TESTS */ static void __init __constructor test_digests_sorted(void) { diff --git a/xen/arch/x86/cpu/microcode/amd.h b/xen/arch/x86/cpu/microcode/amd.h new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/xen/arch/x86/cpu/microcode/amd.h @@ -XXX,XX +XXX,XX @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef ASM_X86_MICROCODE_AMD_H +#define ASM_X86_MICROCODE_AMD_H + +#include "private.h" + +int cf_check amd_compare(const struct microcode_patch *old, + const struct microcode_patch *new); +int cf_check amd_apply_microcode(const struct microcode_patch *patch, + unsigned int flags); +struct microcode_patch *cf_check amd_cpu_request_microcode( + const void *buf, size_t size, bool make_copy); +extern const char amd_cpio_path[]; + +#endif /* ASM_X86_MICROCODE_AMD_H */ -- 2.43.0
Some code must be executed even with microcode loading disabled to find out the current microcode revision. This is important to determine active erratas and such. With the intent of stripping microcode loading via Kconfig, move such essential Intel-specific code to an intel-base.c file. Not a functional change. Signed-off-by: Alejandro Vallejo <alejandro.garciavallejo@amd.com> --- xen/arch/x86/cpu/microcode/Makefile | 1 + xen/arch/x86/cpu/microcode/intel-base.c | 48 +++++++++++++++++++++ xen/arch/x86/cpu/microcode/intel.c | 56 ++++--------------------- xen/arch/x86/cpu/microcode/intel.h | 16 +++++++ 4 files changed, 72 insertions(+), 49 deletions(-) create mode 100644 xen/arch/x86/cpu/microcode/intel-base.c create mode 100644 xen/arch/x86/cpu/microcode/intel.h diff --git a/xen/arch/x86/cpu/microcode/Makefile b/xen/arch/x86/cpu/microcode/Makefile index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/cpu/microcode/Makefile +++ b/xen/arch/x86/cpu/microcode/Makefile @@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_AMD) += amd.o obj-$(CONFIG_AMD) += amd-base.o obj-y += core.o obj-$(CONFIG_INTEL) += intel.o +obj-$(CONFIG_INTEL) += intel-base.o diff --git a/xen/arch/x86/cpu/microcode/intel-base.c b/xen/arch/x86/cpu/microcode/intel-base.c new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/xen/arch/x86/cpu/microcode/intel-base.c @@ -XXX,XX +XXX,XX @@ +#include <xen/init.h> + +#include <asm/msr.h> +#include <asm/processor.h> + +#include "intel.h" + +#define pr_debug(x...) ((void)0) + +static void cf_check collect_cpu_info(void) +{ + struct cpu_signature *csig = &this_cpu(cpu_sig); + uint64_t msr_content; + + memset(csig, 0, sizeof(*csig)); + + rdmsrl(MSR_IA32_PLATFORM_ID, msr_content); + csig->pf = 1 << ((msr_content >> 50) & 7); + + /* + * Obtaining the microcode version involves writing 0 to the "read only" + * UCODE_REV MSR, executing any CPUID instruction, after which a nonzero + * revision should appear. + */ + wrmsrl(MSR_IA32_UCODE_REV, 0); + csig->sig = cpuid_eax(1); + rdmsrl(MSR_IA32_UCODE_REV, msr_content); + csig->rev = msr_content >> 32; + + pr_debug("microcode: collect_cpu_info : sig=%#x, pf=%#x, rev=%#x\n", + csig->sig, csig->pf, csig->rev); +} + +static const struct microcode_ops __initconst_cf_clobber intel_ucode_ops = { + .cpu_request_microcode = intel_cpu_request_microcode, + .apply_microcode = intel_apply_microcode, + .collect_cpu_info = collect_cpu_info, + .compare = intel_compare, + .cpio_path = intel_cpio_path, +}; + +void __init ucode_probe_intel(struct microcode_ops *ops) +{ + *ops = intel_ucode_ops; + + if ( !intel_can_load_microcode() ) + ops->apply_microcode = NULL; +} diff --git a/xen/arch/x86/cpu/microcode/intel.c b/xen/arch/x86/cpu/microcode/intel.c index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/cpu/microcode/intel.c +++ b/xen/arch/x86/cpu/microcode/intel.c @@ -XXX,XX +XXX,XX @@ #include <asm/processor.h> #include <asm/system.h> -#include "private.h" - -#define pr_debug(x...) ((void)0) +#include "intel.h" struct microcode_patch { uint32_t hdrver; @@ -XXX,XX +XXX,XX @@ static bool signature_matches(const struct cpu_signature *cpu_sig, return cpu_sig->pf & ucode_pf; } -static void cf_check collect_cpu_info(void) -{ - struct cpu_signature *csig = &this_cpu(cpu_sig); - uint64_t msr_content; - - memset(csig, 0, sizeof(*csig)); - - rdmsrl(MSR_IA32_PLATFORM_ID, msr_content); - csig->pf = 1 << ((msr_content >> 50) & 7); - - /* - * Obtaining the microcode version involves writing 0 to the "read only" - * UCODE_REV MSR, executing any CPUID instruction, after which a nonzero - * revision should appear. - */ - wrmsrl(MSR_IA32_UCODE_REV, 0); - csig->sig = cpuid_eax(1); - rdmsrl(MSR_IA32_UCODE_REV, msr_content); - csig->rev = msr_content >> 32; - - pr_debug("microcode: collect_cpu_info : sig=%#x, pf=%#x, rev=%#x\n", - csig->sig, csig->pf, csig->rev); -} - /* * Sanity check a blob which is expected to be a microcode patch. The 48 byte * header is of a known format, and together with totalsize are within the @@ -XXX,XX +XXX,XX @@ static bool microcode_fits_cpu(const struct microcode_patch *mc) return false; } -static int cf_check intel_compare( +int cf_check intel_compare( const struct microcode_patch *old, const struct microcode_patch *new) { /* @@ -XXX,XX +XXX,XX @@ static int cf_check intel_compare( return compare_revisions(old->rev, new->rev); } -static int cf_check apply_microcode(const struct microcode_patch *patch, - unsigned int flags) +int cf_check intel_apply_microcode(const struct microcode_patch *patch, + unsigned int flags) { uint64_t msr_content; unsigned int cpu = smp_processor_id(); @@ -XXX,XX +XXX,XX @@ static int cf_check apply_microcode(const struct microcode_patch *patch, return 0; } -static struct microcode_patch *cf_check cpu_request_microcode( +struct microcode_patch *cf_check intel_cpu_request_microcode( const void *buf, size_t size, bool make_copy) { int error = 0; @@ -XXX,XX +XXX,XX @@ static struct microcode_patch *cf_check cpu_request_microcode( return patch; } -static bool __init can_load_microcode(void) +bool __init intel_can_load_microcode(void) { uint64_t mcu_ctrl; @@ -XXX,XX +XXX,XX @@ static bool __init can_load_microcode(void) return !(mcu_ctrl & MCU_CONTROL_DIS_MCU_LOAD); } -static const char __initconst intel_cpio_path[] = +const char __initconst intel_cpio_path[] = "kernel/x86/microcode/GenuineIntel.bin"; - -static const struct microcode_ops __initconst_cf_clobber intel_ucode_ops = { - .cpu_request_microcode = cpu_request_microcode, - .collect_cpu_info = collect_cpu_info, - .apply_microcode = apply_microcode, - .compare = intel_compare, - .cpio_path = intel_cpio_path, -}; - -void __init ucode_probe_intel(struct microcode_ops *ops) -{ - *ops = intel_ucode_ops; - - if ( !can_load_microcode() ) - ops->apply_microcode = NULL; -} diff --git a/xen/arch/x86/cpu/microcode/intel.h b/xen/arch/x86/cpu/microcode/intel.h new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/xen/arch/x86/cpu/microcode/intel.h @@ -XXX,XX +XXX,XX @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef ASM_X86_MICROCODE_INTEL_H +#define ASM_X86_MICROCODE_INTEL_H + +#include "private.h" + +bool intel_can_load_microcode(void); +int cf_check intel_compare(const struct microcode_patch *old, + const struct microcode_patch *new); +int cf_check intel_apply_microcode(const struct microcode_patch *patch, + unsigned int flags); +struct microcode_patch *cf_check intel_cpu_request_microcode( + const void *buf, size_t size, bool make_copy); +extern const char intel_cpio_path[]; + +#endif /* ASM_X86_MICROCODE_INTEL_H */ -- 2.43.0
A later patch compiles out most of the microcode loading code by removing core.c from the Makefile based on Kconfig. These functions are important to set up the ucode_op to read the microcode revision and report it on every CPU. Not a functional change. Signed-off-by: Alejandro Vallejo <alejandro.garciavallejo@amd.com> --- xen/arch/x86/cpu/microcode/Makefile | 1 + xen/arch/x86/cpu/microcode/base.c | 72 ++++++++++++++++++++++++++++ xen/arch/x86/cpu/microcode/core.c | 57 +--------------------- xen/arch/x86/cpu/microcode/private.h | 14 ++++++ 4 files changed, 89 insertions(+), 55 deletions(-) create mode 100644 xen/arch/x86/cpu/microcode/base.c diff --git a/xen/arch/x86/cpu/microcode/Makefile b/xen/arch/x86/cpu/microcode/Makefile index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/cpu/microcode/Makefile +++ b/xen/arch/x86/cpu/microcode/Makefile @@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_AMD) += amd.o obj-$(CONFIG_AMD) += amd-base.o +obj-y += base.o obj-y += core.o obj-$(CONFIG_INTEL) += intel.o obj-$(CONFIG_INTEL) += intel-base.o diff --git a/xen/arch/x86/cpu/microcode/base.c b/xen/arch/x86/cpu/microcode/base.c new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/xen/arch/x86/cpu/microcode/base.c @@ -XXX,XX +XXX,XX @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#include <xen/alternative-call.h> + +#include <xen/errno.h> +#include <xen/init.h> +#include <xen/lib.h> + +#include <asm/asm_defns.h> +#include <asm/cpufeature.h> +#include <asm/x86-vendors.h> +#include <asm/microcode.h> + +#include "private.h" + +struct microcode_ops __ro_after_init ucode_ops; + +int microcode_update_one(void) +{ + /* + * This path is used for APs and S3 resume. Read the microcode revision + * if possible, even if we can't load microcode. + */ + if ( ucode_ops.collect_cpu_info ) + alternative_vcall(ucode_ops.collect_cpu_info); + + return _microcode_update_one(); +} + +int __init early_microcode_init(struct boot_info *bi) +{ + const struct cpuinfo_x86 *c = &boot_cpu_data; + + switch ( c->vendor ) + { + case X86_VENDOR_AMD: + ucode_probe_amd(&ucode_ops); + break; + + case X86_VENDOR_INTEL: + ucode_probe_intel(&ucode_ops); + break; + } + + if ( !ucode_ops.collect_cpu_info ) + { + printk(XENLOG_INFO "Microcode loading not available\n"); + return -ENODEV; + } + + ucode_ops.collect_cpu_info(); + + printk(XENLOG_INFO "BSP microcode revision: 0x%08x\n", this_cpu(cpu_sig).rev); + + /* + * Some hypervisors deliberately report a microcode revision of -1 to + * mean that they will not accept microcode updates. + * + * It's also possible the hardware might have built-in support to disable + * updates and someone (e.g: a baremetal cloud provider) disabled them. + * + * Take the hint in either case and ignore the microcode interface. + */ + if ( !ucode_ops.apply_microcode || this_cpu(cpu_sig).rev == ~0 ) + { + printk(XENLOG_INFO "Microcode loading disabled due to: %s\n", + ucode_ops.apply_microcode ? "rev = ~0" : "HW toggle"); + ucode_ops.apply_microcode = NULL; + return -ENODEV; + } + + return early_microcode_load(bi); +} diff --git a/xen/arch/x86/cpu/microcode/core.c b/xen/arch/x86/cpu/microcode/core.c index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/cpu/microcode/core.c +++ b/xen/arch/x86/cpu/microcode/core.c @@ -XXX,XX +XXX,XX @@ static int __init cf_check parse_ucode(const char *s) } custom_param("ucode", parse_ucode); -static struct microcode_ops __ro_after_init ucode_ops; - static DEFINE_SPINLOCK(microcode_mutex); DEFINE_PER_CPU(struct cpu_signature, cpu_sig); @@ -XXX,XX +XXX,XX @@ int ucode_update_hcall(XEN_GUEST_HANDLE(const_void) buf, } /* Load a cached update to current cpu */ -int microcode_update_one(void) +int _microcode_update_one(void) { int rc; @@ -XXX,XX +XXX,XX @@ static int __init cf_check microcode_init_cache(void) } presmp_initcall(microcode_init_cache); -/* - * There are several tasks: - * - Locate the ucode blob in the boot modules. - * - Parse and attempt in-place load. - * - Inform microcode_init_cache() of how to find the blob again. - */ -static int __init early_microcode_load(struct boot_info *bi) +int __init early_microcode_load(struct boot_info *bi) { void *data = NULL; size_t size; @@ -XXX,XX +XXX,XX @@ static int __init early_microcode_load(struct boot_info *bi) return rc; } - -int __init early_microcode_init(struct boot_info *bi) -{ - const struct cpuinfo_x86 *c = &boot_cpu_data; - - switch ( c->vendor ) - { - case X86_VENDOR_AMD: - ucode_probe_amd(&ucode_ops); - break; - - case X86_VENDOR_INTEL: - ucode_probe_intel(&ucode_ops); - break; - } - - if ( !ucode_ops.collect_cpu_info ) - { - printk(XENLOG_INFO "Microcode loading not available\n"); - return -ENODEV; - } - - ucode_ops.collect_cpu_info(); - - printk(XENLOG_INFO "BSP microcode revision: 0x%08x\n", this_cpu(cpu_sig).rev); - - /* - * Some hypervisors deliberately report a microcode revision of -1 to - * mean that they will not accept microcode updates. - * - * It's also possible the hardware might have built-in support to disable - * updates and someone (e.g: a baremetal cloud provider) disabled them. - * - * Take the hint in either case and ignore the microcode interface. - */ - if ( !ucode_ops.apply_microcode || this_cpu(cpu_sig).rev == ~0 ) - { - printk(XENLOG_INFO "Microcode loading disabled due to: %s\n", - ucode_ops.apply_microcode ? "rev = ~0" : "HW toggle"); - ucode_ops.apply_microcode = NULL; - return -ENODEV; - } - - return early_microcode_load(bi); -} diff --git a/xen/arch/x86/cpu/microcode/private.h b/xen/arch/x86/cpu/microcode/private.h index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/cpu/microcode/private.h +++ b/xen/arch/x86/cpu/microcode/private.h @@ -XXX,XX +XXX,XX @@ #include <asm/microcode.h> +struct boot_info; + /* Opaque. Internals are vendor-specific. */ struct microcode_patch; @@ -XXX,XX +XXX,XX @@ struct microcode_ops { }; extern bool opt_digest_check; +extern struct microcode_ops ucode_ops; /* * Microcode loading falls into one of 3 states. @@ -XXX,XX +XXX,XX @@ void ucode_probe_intel(struct microcode_ops *ops); static inline void ucode_probe_intel(struct microcode_ops *ops) {} #endif +/* + * There are several tasks: + * - Locate the ucode blob in the boot modules. + * - Parse and attempt in-place load. + * - Inform microcode_init_cache() of how to find the blob again. + */ +int early_microcode_load(struct boot_info *bi); + +/* Attempt performaing a microcode load */ +int _microcode_update_one(void); + #endif /* ASM_X86_MICROCODE_PRIVATE_H */ -- 2.43.0
Keeps around the microcode revision reading logic, as that's security sensitive to detect out-of-date patforms and report them. Move cpu_sig to base.c, because that's externally visible symbol outside the microcode subsystem and we need it always accesible. Signed-off-by: Alejandro Vallejo <alejandro.garciavallejo@amd.com> --- xen/arch/x86/Kconfig | 12 ++++++++++++ xen/arch/x86/cpu/microcode/Makefile | 6 +++--- xen/arch/x86/cpu/microcode/amd-base.c | 9 +++++++-- xen/arch/x86/cpu/microcode/base.c | 21 +++++++++++---------- xen/arch/x86/cpu/microcode/core.c | 1 - xen/arch/x86/cpu/microcode/intel-base.c | 6 ++++-- xen/arch/x86/efi/efi-boot.h | 2 +- xen/arch/x86/platform_hypercall.c | 2 ++ 8 files changed, 40 insertions(+), 19 deletions(-) diff --git a/xen/arch/x86/Kconfig b/xen/arch/x86/Kconfig index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/Kconfig +++ b/xen/arch/x86/Kconfig @@ -XXX,XX +XXX,XX @@ config REQUIRE_NX was unavailable. However, if enabled, Xen will no longer boot on any CPU which is lacking NX support. +config UCODE + bool "Microcode loading" + default y + help + Support updating the microcode revision of available CPUs with a newer + vendor-provided microcode blob. Microcode updates address some classes of + silicon defects. It's a very common delivery mechanism for fixes or + workarounds for speculative execution vulnerabilities. + + If unsure, say Y + config UCODE_SCAN_DEFAULT bool "Scan for microcode by default" + depends on UCODE help During boot, Xen can scan the multiboot images for a CPIO archive containing CPU microcode to be loaded, which is Linux's mechanism for diff --git a/xen/arch/x86/cpu/microcode/Makefile b/xen/arch/x86/cpu/microcode/Makefile index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/cpu/microcode/Makefile +++ b/xen/arch/x86/cpu/microcode/Makefile @@ -XXX,XX +XXX,XX @@ -obj-$(CONFIG_AMD) += amd.o +obj-$(filter $(CONFIG_AMD),$(CONFIG_UCODE)) += amd.o obj-$(CONFIG_AMD) += amd-base.o obj-y += base.o -obj-y += core.o -obj-$(CONFIG_INTEL) += intel.o +obj-$(CONFIG_UCODE) += core.o +obj-$(filter $(CONFIG_INTEL),$(CONFIG_UCODE)) += intel.o obj-$(CONFIG_INTEL) += intel-base.o diff --git a/xen/arch/x86/cpu/microcode/amd-base.c b/xen/arch/x86/cpu/microcode/amd-base.c index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/cpu/microcode/amd-base.c +++ b/xen/arch/x86/cpu/microcode/amd-base.c @@ -XXX,XX +XXX,XX @@ static void cf_check collect_cpu_info(void) } static const struct microcode_ops __initconst_cf_clobber amd_ucode_ops = { - .cpu_request_microcode = amd_cpu_request_microcode, .collect_cpu_info = collect_cpu_info, +#ifdef CONFIG_UCODE + .cpu_request_microcode = amd_cpu_request_microcode, .apply_microcode = amd_apply_microcode, .compare = amd_compare, .cpio_path = amd_cpio_path, +#endif /* CONFIG_UCODE */ }; void __init ucode_probe_amd(struct microcode_ops *ops) { /* * The Entrysign vulnerability (SB-7033, CVE-2024-36347) affects Zen1-5 - * CPUs. Taint Xen if digest checking is turned off. + * CPUs. Taint Xen if digest checking is turned off and microcode loading is + * compiled in. */ +#ifdef CONFIG_UCODE if ( boot_cpu_data.family >= 0x17 && boot_cpu_data.family <= 0x1a && !opt_digest_check ) { @@ -XXX,XX +XXX,XX @@ void __init ucode_probe_amd(struct microcode_ops *ops) "Microcode patch additional digest checks disabled\n"); add_taint(TAINT_CPU_OUT_OF_SPEC); } +#endif /* CONFIG_UCODE */ if ( boot_cpu_data.family < 0x10 ) return; diff --git a/xen/arch/x86/cpu/microcode/base.c b/xen/arch/x86/cpu/microcode/base.c index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/cpu/microcode/base.c +++ b/xen/arch/x86/cpu/microcode/base.c @@ -XXX,XX +XXX,XX @@ #include "private.h" struct microcode_ops __ro_after_init ucode_ops; +DEFINE_PER_CPU(struct cpu_signature, cpu_sig); int microcode_update_one(void) { @@ -XXX,XX +XXX,XX @@ int microcode_update_one(void) if ( ucode_ops.collect_cpu_info ) alternative_vcall(ucode_ops.collect_cpu_info); + if ( !IS_ENABLED(CONFIG_UCODE) ) + return 0; + return _microcode_update_one(); } @@ -XXX,XX +XXX,XX @@ int __init early_microcode_init(struct boot_info *bi) { const struct cpuinfo_x86 *c = &boot_cpu_data; - switch ( c->vendor ) - { - case X86_VENDOR_AMD: + if ( IS_ENABLED(CONFIG_AMD) && c->vendor == X86_VENDOR_AMD ) ucode_probe_amd(&ucode_ops); - break; - - case X86_VENDOR_INTEL: + else if ( IS_ENABLED(CONFIG_INTEL) && c->vendor == X86_VENDOR_INTEL ) ucode_probe_intel(&ucode_ops); - break; - } if ( !ucode_ops.collect_cpu_info ) { @@ -XXX,XX +XXX,XX @@ int __init early_microcode_init(struct boot_info *bi) * * Take the hint in either case and ignore the microcode interface. */ - if ( !ucode_ops.apply_microcode || this_cpu(cpu_sig).rev == ~0 ) + if ( !IS_ENABLED(CONFIG_UCODE) || !ucode_ops.apply_microcode || + this_cpu(cpu_sig).rev == ~0 ) { printk(XENLOG_INFO "Microcode loading disabled due to: %s\n", - ucode_ops.apply_microcode ? "rev = ~0" : "HW toggle"); + !IS_ENABLED(CONFIG_UCODE) ? "not compiled-in" : + ucode_ops.apply_microcode ? "rev = ~0" : + "HW toggle"); ucode_ops.apply_microcode = NULL; return -ENODEV; } diff --git a/xen/arch/x86/cpu/microcode/core.c b/xen/arch/x86/cpu/microcode/core.c index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/cpu/microcode/core.c +++ b/xen/arch/x86/cpu/microcode/core.c @@ -XXX,XX +XXX,XX @@ custom_param("ucode", parse_ucode); static DEFINE_SPINLOCK(microcode_mutex); -DEFINE_PER_CPU(struct cpu_signature, cpu_sig); /* Store error code of the work done in NMI handler */ static DEFINE_PER_CPU(int, loading_err); diff --git a/xen/arch/x86/cpu/microcode/intel-base.c b/xen/arch/x86/cpu/microcode/intel-base.c index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/cpu/microcode/intel-base.c +++ b/xen/arch/x86/cpu/microcode/intel-base.c @@ -XXX,XX +XXX,XX @@ static void cf_check collect_cpu_info(void) } static const struct microcode_ops __initconst_cf_clobber intel_ucode_ops = { + .collect_cpu_info = collect_cpu_info, +#ifdef CONFIG_UCODE .cpu_request_microcode = intel_cpu_request_microcode, .apply_microcode = intel_apply_microcode, - .collect_cpu_info = collect_cpu_info, .compare = intel_compare, .cpio_path = intel_cpio_path, +#endif /* CONFIG_UCODE */ }; void __init ucode_probe_intel(struct microcode_ops *ops) { *ops = intel_ucode_ops; - if ( !intel_can_load_microcode() ) + if ( IS_ENABLED(CONFIG_UCODE) && !intel_can_load_microcode() ) ops->apply_microcode = NULL; } diff --git a/xen/arch/x86/efi/efi-boot.h b/xen/arch/x86/efi/efi-boot.h index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/efi/efi-boot.h +++ b/xen/arch/x86/efi/efi-boot.h @@ -XXX,XX +XXX,XX @@ static void __init efi_arch_cfg_file_late(const EFI_LOADED_IMAGE *image, { union string name; - if ( read_section(image, L"ucode", &ucode, NULL) ) + if ( !IS_ENABLED(CONFIG_UCODE) || read_section(image, L"ucode", &ucode, NULL) ) return; name.s = get_value(&cfg, section, "ucode"); diff --git a/xen/arch/x86/platform_hypercall.c b/xen/arch/x86/platform_hypercall.c index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/platform_hypercall.c +++ b/xen/arch/x86/platform_hypercall.c @@ -XXX,XX +XXX,XX @@ ret_t do_platform_op( break; } +#ifdef CONFIG_UCODE case XENPF_microcode_update: { XEN_GUEST_HANDLE(const_void) data; @@ -XXX,XX +XXX,XX @@ ret_t do_platform_op( op->u.microcode2.flags); break; } +#endif /* CONFIG_UCODE */ case XENPF_platform_quirk: { -- 2.43.0
Hi, One more day, one more revision. Same as v2 with feedback addressed. v1: https://lore.kernel.org/xen-devel/20251112162219.226075-1-alejandro.garciavallejo@amd.com/ v2: https://lore.kernel.org/xen-devel/20260112150259.74535-1-alejandro.garciavallejo@amd.com/ pipeline (green): https://gitlab.com/xen-project/people/agvallejo/xen/-/pipelines/2260019646 Cheers, Alejandro Alejandro Vallejo (4): x86/ucode: Fix typo s/mitigiated/mitigated/ x86/ucode: Rename UCODE_SCAN_DEFAULT to MICROCODE_SCAN_DEFAULT earlycpio: lib-ify earlycpio.c x86/ucode: Add Kconfig option to remove microcode loading automation/gitlab-ci/build.yaml | 2 +- docs/admin-guide/microcode-loading.rst | 2 ++ docs/misc/efi.pandoc | 2 ++ docs/misc/xen-command-line.pandoc | 4 ++-- docs/misra/exclude-list.json | 8 ++++---- xen/arch/x86/Kconfig | 16 +++++++++++++++- xen/arch/x86/cpu/microcode/amd.c | 22 ++++++++++++---------- xen/arch/x86/cpu/microcode/core.c | 17 +++++++++++++---- xen/arch/x86/cpu/microcode/intel.c | 11 +++++++---- xen/arch/x86/cpu/microcode/private.h | 2 ++ xen/arch/x86/efi/efi-boot.h | 3 ++- xen/arch/x86/platform_hypercall.c | 22 +++++++++++++++------- xen/common/Makefile | 2 +- xen/lib/Makefile | 1 + xen/{common => lib}/earlycpio.c | 0 15 files changed, 79 insertions(+), 35 deletions(-) rename xen/{common => lib}/earlycpio.c (100%) base-commit: a2a34d76643e49ccc949296c9a45888034e50b55 -- 2.43.0
Not a functional change. Signed-off-by: Alejandro Vallejo <alejandro.garciavallejo@amd.com> Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com> --- v3: * No changes --- xen/arch/x86/cpu/microcode/amd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xen/arch/x86/cpu/microcode/amd.c b/xen/arch/x86/cpu/microcode/amd.c index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/cpu/microcode/amd.c +++ b/xen/arch/x86/cpu/microcode/amd.c @@ -XXX,XX +XXX,XX @@ static const struct patch_digest { } patch_digests[] = { #include "amd-patch-digests.c" }; -static bool __ro_after_init entrysign_mitigiated_in_firmware; +static bool __ro_after_init entrysign_mitigated_in_firmware; static int cf_check cmp_patch_id(const void *key, const void *elem) { @@ -XXX,XX +XXX,XX @@ static bool check_digest(const struct container_microcode *mc) * the digest of the patch against a list of known provenance. */ if ( boot_cpu_data.family < 0x17 || boot_cpu_data.family > 0x1a || - entrysign_mitigiated_in_firmware || !opt_digest_check ) + entrysign_mitigated_in_firmware || !opt_digest_check ) return true; pd = bsearch(&patch->patch_id, patch_digests, ARRAY_SIZE(patch_digests), @@ -XXX,XX +XXX,XX @@ void __init amd_check_entrysign(void) */ if ( (uint8_t)curr_rev >= fixed_rev ) { - entrysign_mitigiated_in_firmware = true; + entrysign_mitigated_in_firmware = true; return; } -- 2.43.0
We'd rather have the full spelling in Kconfig. Adjusts every other reference to the name too. Not a functional change. Signed-off-by: Alejandro Vallejo <alejandro.garciavallejo@amd.com> --- v3: * New patch. Previously integrated in larger patch. --- automation/gitlab-ci/build.yaml | 2 +- docs/misc/xen-command-line.pandoc | 2 +- xen/arch/x86/Kconfig | 2 +- xen/arch/x86/cpu/microcode/core.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/automation/gitlab-ci/build.yaml b/automation/gitlab-ci/build.yaml index XXXXXXX..XXXXXXX 100644 --- a/automation/gitlab-ci/build.yaml +++ b/automation/gitlab-ci/build.yaml @@ -XXX,XX +XXX,XX @@ alpine-3.18-gcc-debug: CONFIG_ARGO=y CONFIG_UBSAN=y CONFIG_UBSAN_FATAL=y - CONFIG_UCODE_SCAN_DEFAULT=y + CONFIG_MICROCODE_SCAN_DEFAULT=y CONFIG_XHCI=y debian-13-x86_64-gcc-debug: diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc index XXXXXXX..XXXXXXX 100644 --- a/docs/misc/xen-command-line.pandoc +++ b/docs/misc/xen-command-line.pandoc @@ -XXX,XX +XXX,XX @@ microcode in the cpio name space must be: - on AMD : kernel/x86/microcode/AuthenticAMD.bin When using xen.efi, the `ucode=<filename>` config file setting takes precedence over `scan`. The default value for `scan` is set with -`CONFIG_UCODE_SCAN_DEFAULT`. +`CONFIG_MICROCODE_SCAN_DEFAULT`. 'nmi' determines late loading is performed in NMI handler or just in stop_machine context. In NMI handler, even NMIs are blocked, which is diff --git a/xen/arch/x86/Kconfig b/xen/arch/x86/Kconfig index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/Kconfig +++ b/xen/arch/x86/Kconfig @@ -XXX,XX +XXX,XX @@ config REQUIRE_NX was unavailable. However, if enabled, Xen will no longer boot on any CPU which is lacking NX support. -config UCODE_SCAN_DEFAULT +config MICROCODE_SCAN_DEFAULT bool "Scan for microcode by default" help During boot, Xen can scan the multiboot images for a CPIO archive diff --git a/xen/arch/x86/cpu/microcode/core.c b/xen/arch/x86/cpu/microcode/core.c index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/cpu/microcode/core.c +++ b/xen/arch/x86/cpu/microcode/core.c @@ -XXX,XX +XXX,XX @@ static struct microcode_patch *microcode_cache; * location we require that they are not both active together. */ static int __initdata opt_mod_idx; -static bool __initdata opt_scan = IS_ENABLED(CONFIG_UCODE_SCAN_DEFAULT); +static bool __initdata opt_scan = IS_ENABLED(CONFIG_MICROCODE_SCAN_DEFAULT); bool __ro_after_init opt_digest_check = true; /* -- 2.43.0
It's only used for microcode loading on x86. By lib-ifying it we can make it go away automatically when microcode loading becomes an optional feature in follow-up patches. Signed-off-by: Alejandro Vallejo <alejandro.garciavallejo@amd.com> --- v3: * New patch. Subsumes earlier conditionalisation of earlycpio.c on CONFIG_MICROCODE_LOADING. --- docs/misra/exclude-list.json | 8 ++++---- xen/common/Makefile | 2 +- xen/lib/Makefile | 1 + xen/{common => lib}/earlycpio.c | 0 4 files changed, 6 insertions(+), 5 deletions(-) rename xen/{common => lib}/earlycpio.c (100%) diff --git a/docs/misra/exclude-list.json b/docs/misra/exclude-list.json index XXXXXXX..XXXXXXX 100644 --- a/docs/misra/exclude-list.json +++ b/docs/misra/exclude-list.json @@ -XXX,XX +XXX,XX @@ "rel_path": "common/bunzip2.c", "comment": "Imported from Linux, ignore for now" }, - { - "rel_path": "common/earlycpio.c", - "comment": "Imported from Linux, ignore for now" - }, { "rel_path": "common/gzip/*", "comment": "Imported from Linux, ignore for now" @@ -XXX,XX +XXX,XX @@ "rel_path": "include/xen/decompress.h", "comment": "Imported from Linux, ignore for now" }, + { + "rel_path": "lib/earlycpio.c", + "comment": "Imported from Linux, ignore for now" + }, { "rel_path": "lib/find-next-bit.c", "comment": "Imported from Linux, ignore for now" diff --git a/xen/common/Makefile b/xen/common/Makefile index XXXXXXX..XXXXXXX 100644 --- a/xen/common/Makefile +++ b/xen/common/Makefile @@ -XXX,XX +XXX,XX @@ obj-y += wait.o obj-bin-y += warning.init.o obj-y += xmalloc_tlsf.o -obj-bin-$(CONFIG_X86) += $(foreach n,decompress bunzip2 unxz unlzma lzo unlzo unlz4 unzstd earlycpio,$(n).init.o) +obj-bin-$(CONFIG_X86) += $(foreach n,decompress bunzip2 unxz unlzma lzo unlzo unlz4 unzstd,$(n).init.o) obj-$(CONFIG_COMPAT) += $(addprefix compat/,domain.o memory.o multicall.o xlat.o) diff --git a/xen/lib/Makefile b/xen/lib/Makefile index XXXXXXX..XXXXXXX 100644 --- a/xen/lib/Makefile +++ b/xen/lib/Makefile @@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_X86) += x86/ lib-y += bsearch.o lib-y += ctors.o lib-y += ctype.o +lib-y += earlycpio.o lib-y += find-next-bit.o lib-y += generic-ffsl.o lib-y += generic-flsl.o diff --git a/xen/common/earlycpio.c b/xen/lib/earlycpio.c similarity index 100% rename from xen/common/earlycpio.c rename to xen/lib/earlycpio.c -- 2.43.0
Amend docs to reflect ucode= command/stanza depend on MICROCODE_LOADING being set. The new MICROCODE_OP() is a conditional setter for the microcode_ops struct. By using IS_ENABLED() there ratehr than ifdef we allow DCE to remove all statics no longer used when microcode loading is disabled without tagging them with __maybe_unused. Signed-off-by: Alejandro Vallejo <alejandro.garciavallejo@amd.com> --- v3: * Moved MICROCODE_SCAN_DEFAULT to a separate patch * Added doc change to admin-guide * Added Andrew's suggestion for Kconfig help text * Inlined can_apply_microcode() macro in core.c * Kept the platform-ops, gating them on CONFIG_MICROCODE_LOADING through the new MICROCODE_OP() macro. --- docs/admin-guide/microcode-loading.rst | 2 ++ docs/misc/efi.pandoc | 2 ++ docs/misc/xen-command-line.pandoc | 2 +- xen/arch/x86/Kconfig | 14 ++++++++++++++ xen/arch/x86/cpu/microcode/amd.c | 16 +++++++++------- xen/arch/x86/cpu/microcode/core.c | 15 ++++++++++++--- xen/arch/x86/cpu/microcode/intel.c | 11 +++++++---- xen/arch/x86/cpu/microcode/private.h | 2 ++ xen/arch/x86/efi/efi-boot.h | 3 ++- xen/arch/x86/platform_hypercall.c | 22 +++++++++++++++------- 10 files changed, 66 insertions(+), 23 deletions(-) diff --git a/docs/admin-guide/microcode-loading.rst b/docs/admin-guide/microcode-loading.rst index XXXXXXX..XXXXXXX 100644 --- a/docs/admin-guide/microcode-loading.rst +++ b/docs/admin-guide/microcode-loading.rst @@ -XXX,XX +XXX,XX @@ TSX errata which necessitated disabling the feature entirely), or the addition of brand new features (e.g. the Spectre v2 controls to work around speculative execution vulnerabilities). +Microcode loading support in Xen is controlled by the +``CONFIG_MICROCODE_LOADING`` Kconfig option. Boot time microcode loading --------------------------- diff --git a/docs/misc/efi.pandoc b/docs/misc/efi.pandoc index XXXXXXX..XXXXXXX 100644 --- a/docs/misc/efi.pandoc +++ b/docs/misc/efi.pandoc @@ -XXX,XX +XXX,XX @@ Specifies an XSM module to load. Specifies a CPU microcode blob to load. (x86 only) +Only available when Xen is compiled with CONFIG_MICROCODE_LOADING. + ###`dtb=<filename>` Specifies a device tree file to load. The platform firmware may provide a diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc index XXXXXXX..XXXXXXX 100644 --- a/docs/misc/xen-command-line.pandoc +++ b/docs/misc/xen-command-line.pandoc @@ -XXX,XX +XXX,XX @@ performance. ### ucode > `= List of [ <integer> | scan=<bool>, nmi=<bool>, digest-check=<bool> ]` - Applicability: x86 + Applicability: x86 with CONFIG_MICROCODE_LOADING active Default: `scan` is selectable via Kconfig, `nmi,digest-check` Controls for CPU microcode loading. For early loading, this parameter can diff --git a/xen/arch/x86/Kconfig b/xen/arch/x86/Kconfig index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/Kconfig +++ b/xen/arch/x86/Kconfig @@ -XXX,XX +XXX,XX @@ config REQUIRE_NX was unavailable. However, if enabled, Xen will no longer boot on any CPU which is lacking NX support. +config MICROCODE_LOADING + bool "Microcode loading" + default y + help + Microcode updates for CPUs fix errata and provide new functionality for + software to work around bugs, such as the speculative execution + vulnerabilities. It is common for OSes to carry updated microcode as + software tends to get updated more frequently than firmware. + + For embedded environments where a full firmware/software stack is being + provided, it might not be necessary for Xen to need to load microcode + itself. + config MICROCODE_SCAN_DEFAULT bool "Scan for microcode by default" + depends on MICROCODE_LOADING help During boot, Xen can scan the multiboot images for a CPIO archive containing CPU microcode to be loaded, which is Linux's mechanism for diff --git a/xen/arch/x86/cpu/microcode/amd.c b/xen/arch/x86/cpu/microcode/amd.c index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/cpu/microcode/amd.c +++ b/xen/arch/x86/cpu/microcode/amd.c @@ -XXX,XX +XXX,XX @@ static const char __initconst amd_cpio_path[] = "kernel/x86/microcode/AuthenticAMD.bin"; static const struct microcode_ops __initconst_cf_clobber amd_ucode_ops = { - .cpu_request_microcode = cpu_request_microcode, + .cpu_request_microcode = MICROCODE_OP(cpu_request_microcode), .collect_cpu_info = collect_cpu_info, - .apply_microcode = apply_microcode, - .compare = amd_compare, - .cpio_path = amd_cpio_path, + .apply_microcode = MICROCODE_OP(apply_microcode), + .compare = MICROCODE_OP(amd_compare), + .cpio_path = MICROCODE_OP(amd_cpio_path), }; void __init ucode_probe_amd(struct microcode_ops *ops) @@ -XXX,XX +XXX,XX @@ void __init ucode_probe_amd(struct microcode_ops *ops) * The Entrysign vulnerability (SB-7033, CVE-2024-36347) affects Zen1-5 * CPUs. Taint Xen if digest checking is turned off. */ - if ( boot_cpu_data.family >= 0x17 && boot_cpu_data.family <= 0x1a && + if ( IS_ENABLED(CONFIG_MICROCODE_LOADING) && + boot_cpu_data.family >= 0x17 && boot_cpu_data.family <= 0x1a && !opt_digest_check ) { printk(XENLOG_WARNING @@ -XXX,XX +XXX,XX @@ void __init amd_check_entrysign(void) unsigned int curr_rev; uint8_t fixed_rev; - if ( boot_cpu_data.vendor != X86_VENDOR_AMD || - boot_cpu_data.family < 0x17 || + if ( !IS_ENABLED(CONFIG_MICROCODE_LOADING) || + boot_cpu_data.vendor != X86_VENDOR_AMD || + boot_cpu_data.family < 0x17 || boot_cpu_data.family > 0x1a ) return; diff --git a/xen/arch/x86/cpu/microcode/core.c b/xen/arch/x86/cpu/microcode/core.c index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/cpu/microcode/core.c +++ b/xen/arch/x86/cpu/microcode/core.c @@ -XXX,XX +XXX,XX @@ */ #define MICROCODE_UPDATE_TIMEOUT_US 1000000 -static bool __initdata ucode_mod_forced; +static bool __initdata __maybe_unused ucode_mod_forced; static unsigned int nr_cores; /* @@ -XXX,XX +XXX,XX @@ static int __initdata opt_mod_idx; static bool __initdata opt_scan = IS_ENABLED(CONFIG_MICROCODE_SCAN_DEFAULT); bool __ro_after_init opt_digest_check = true; +#ifdef CONFIG_MICROCODE_LOADING /* * Used by the EFI path only, when xen.cfg identifies an explicit microcode * file. Overrides ucode=<int>|scan on the regular command line. @@ -XXX,XX +XXX,XX @@ static int __init cf_check parse_ucode(const char *s) return rc; } custom_param("ucode", parse_ucode); +#endif /* CONFIG_MICROCODE_LOADING */ static struct microcode_ops __ro_after_init ucode_ops; @@ -XXX,XX +XXX,XX @@ struct ucode_buf { char buffer[]; }; -static long cf_check ucode_update_hcall_cont(void *data) +static long cf_check __maybe_unused ucode_update_hcall_cont(void *data) { struct microcode_patch *patch = NULL; int ret, result; @@ -XXX,XX +XXX,XX @@ static long cf_check ucode_update_hcall_cont(void *data) return ret; } +#ifdef CONFIG_MICROCODE_LOADING int ucode_update_hcall(XEN_GUEST_HANDLE(const_void) buf, unsigned long len, unsigned int flags) { @@ -XXX,XX +XXX,XX @@ int ucode_update_hcall(XEN_GUEST_HANDLE(const_void) buf, */ return continue_hypercall_on_cpu(0, ucode_update_hcall_cont, buffer); } +#endif /* CONFIG_MICROCODE_LOADING */ /* Load a cached update to current cpu */ int microcode_update_one(void) @@ -XXX,XX +XXX,XX @@ int microcode_update_one(void) if ( ucode_ops.collect_cpu_info ) alternative_vcall(ucode_ops.collect_cpu_info); - if ( !ucode_ops.apply_microcode ) + if ( !IS_ENABLED(CONFIG_MICROCODE_LOADING) || !ucode_ops.apply_microcode ) return -EOPNOTSUPP; spin_lock(µcode_mutex); @@ -XXX,XX +XXX,XX @@ int microcode_update_one(void) */ static int __initdata early_mod_idx = -1; +#ifdef CONFIG_MICROCODE_LOADING static int __init cf_check microcode_init_cache(void) { struct boot_info *bi = &xen_boot_info; @@ -XXX,XX +XXX,XX @@ static int __init cf_check microcode_init_cache(void) return rc; } presmp_initcall(microcode_init_cache); +#endif /* CONFIG_MICROCODE_LOADING */ /* * There are several tasks: @@ -XXX,XX +XXX,XX @@ int __init early_microcode_init(struct boot_info *bi) printk(XENLOG_INFO "BSP microcode revision: 0x%08x\n", this_cpu(cpu_sig).rev); + if ( !IS_ENABLED(CONFIG_MICROCODE_LOADING) ) + return -ENODEV; + /* * Some hypervisors deliberately report a microcode revision of -1 to * mean that they will not accept microcode updates. diff --git a/xen/arch/x86/cpu/microcode/intel.c b/xen/arch/x86/cpu/microcode/intel.c index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/cpu/microcode/intel.c +++ b/xen/arch/x86/cpu/microcode/intel.c @@ -XXX,XX +XXX,XX @@ static const char __initconst intel_cpio_path[] = "kernel/x86/microcode/GenuineIntel.bin"; static const struct microcode_ops __initconst_cf_clobber intel_ucode_ops = { - .cpu_request_microcode = cpu_request_microcode, + .cpu_request_microcode = MICROCODE_OP(cpu_request_microcode), .collect_cpu_info = collect_cpu_info, - .apply_microcode = apply_microcode, - .compare = intel_compare, - .cpio_path = intel_cpio_path, + .apply_microcode = MICROCODE_OP(apply_microcode), + .compare = MICROCODE_OP(intel_compare), + .cpio_path = MICROCODE_OP(intel_cpio_path), }; void __init ucode_probe_intel(struct microcode_ops *ops) { *ops = intel_ucode_ops; + if ( !IS_ENABLED(CONFIG_MICROCODE_LOADING) ) + return; + if ( !can_load_microcode() ) ops->apply_microcode = NULL; } diff --git a/xen/arch/x86/cpu/microcode/private.h b/xen/arch/x86/cpu/microcode/private.h index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/cpu/microcode/private.h +++ b/xen/arch/x86/cpu/microcode/private.h @@ -XXX,XX +XXX,XX @@ void ucode_probe_intel(struct microcode_ops *ops); static inline void ucode_probe_intel(struct microcode_ops *ops) {} #endif +#define MICROCODE_OP(x) (IS_ENABLED(CONFIG_MICROCODE_LOADING) ? (x) : NULL) + #endif /* ASM_X86_MICROCODE_PRIVATE_H */ diff --git a/xen/arch/x86/efi/efi-boot.h b/xen/arch/x86/efi/efi-boot.h index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/efi/efi-boot.h +++ b/xen/arch/x86/efi/efi-boot.h @@ -XXX,XX +XXX,XX @@ static void __init efi_arch_cfg_file_late(const EFI_LOADED_IMAGE *image, { union string name; - if ( read_section(image, L"ucode", &ucode, NULL) ) + if ( !IS_ENABLED(CONFIG_MICROCODE_LOADING) || + read_section(image, L"ucode", &ucode, NULL) ) return; name.s = get_value(&cfg, section, "ucode"); diff --git a/xen/arch/x86/platform_hypercall.c b/xen/arch/x86/platform_hypercall.c index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/platform_hypercall.c +++ b/xen/arch/x86/platform_hypercall.c @@ -XXX,XX +XXX,XX @@ ret_t do_platform_op( case XENPF_microcode_update: { - XEN_GUEST_HANDLE(const_void) data; + ret = -EOPNOTSUPP; + if ( IS_ENABLED(CONFIG_MICROCODE_LOADING) ) + { + XEN_GUEST_HANDLE(const_void) data; - guest_from_compat_handle(data, op->u.microcode.data); + guest_from_compat_handle(data, op->u.microcode.data); + ret = ucode_update_hcall(data, op->u.microcode.length, 0); + } - ret = ucode_update_hcall(data, op->u.microcode.length, 0); break; } case XENPF_microcode_update2: { - XEN_GUEST_HANDLE(const_void) data; + ret = -EOPNOTSUPP; + if ( IS_ENABLED(CONFIG_MICROCODE_LOADING) ) + { + XEN_GUEST_HANDLE(const_void) data; - guest_from_compat_handle(data, op->u.microcode2.data); + guest_from_compat_handle(data, op->u.microcode2.data); + ret = ucode_update_hcall(data, op->u.microcode2.length, + op->u.microcode2.flags); + } - ret = ucode_update_hcall(data, op->u.microcode2.length, - op->u.microcode2.flags); break; } -- 2.43.0