Amend docs to reflect ucode= commands depend on MICROCODE_LOADING being set.
While at it, rename UCODE_SCAN_DEFAULT to MICROCODE_SCAN_DEFAULT for consistency. Signed-off-by: Alejandro Vallejo <[email protected]> --- v2: * Rely aggressively on DCE and ifdef/IS_ENABLED rather than file refactoring * Add a note about CONFIG_MICROCODE_LOADING to xen-command-line.pandoc * Rename UCODE to MICROCODE_LOADING * Rename UCODE_SCAN_DEFAULT to MICROCODE_SCAN_DEFAULT in order to avoid having some options with UCODE and some with MICROCODE. * Remove earlycpio.init.o from the build when !CONFIG_MICROCODE_LOADING --- automation/gitlab-ci/build.yaml | 2 +- docs/misc/efi.pandoc | 2 ++ docs/misc/xen-command-line.pandoc | 4 ++-- xen/arch/x86/Kconfig | 14 +++++++++++++- xen/arch/x86/cpu/microcode/amd.c | 22 +++++++++++++--------- xen/arch/x86/cpu/microcode/core.c | 25 ++++++++++++++++++------- xen/arch/x86/cpu/microcode/intel.c | 16 +++++++++------- xen/arch/x86/efi/efi-boot.h | 3 ++- xen/arch/x86/platform_hypercall.c | 2 ++ xen/common/Makefile | 3 ++- 10 files changed, 64 insertions(+), 29 deletions(-) diff --git a/automation/gitlab-ci/build.yaml b/automation/gitlab-ci/build.yaml index a6fc55c2d5..b69bad9202 100644 --- a/automation/gitlab-ci/build.yaml +++ b/automation/gitlab-ci/build.yaml @@ -310,7 +310,7 @@ 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/efi.pandoc b/docs/misc/efi.pandoc index 11c1ac3346..c3fb1f3a30 100644 --- a/docs/misc/efi.pandoc +++ b/docs/misc/efi.pandoc @@ -104,6 +104,8 @@ 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 50d7edb248..866fa2f951 100644 --- a/docs/misc/xen-command-line.pandoc +++ b/docs/misc/xen-command-line.pandoc @@ -2748,7 +2748,7 @@ 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 @@ -2773,7 +2773,7 @@ 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 c808c989fc..1353ec9a3f 100644 --- a/xen/arch/x86/Kconfig +++ b/xen/arch/x86/Kconfig @@ -331,8 +331,20 @@ 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_LOADING + 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 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 71b041c84b..6abdc7813b 100644 --- a/xen/arch/x86/cpu/microcode/amd.c +++ b/xen/arch/x86/cpu/microcode/amd.c @@ -264,7 +264,7 @@ static bool microcode_fits_cpu(const struct microcode_patch *patch) return equiv.id == patch->processor_rev_id; } -static int cf_check amd_compare( +static int cf_check __maybe_unused amd_compare( const struct microcode_patch *old, const struct microcode_patch *new) { /* Both patches to compare are supposed to be applicable to local CPU. */ @@ -310,8 +310,8 @@ 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) +static int cf_check __maybe_unused apply_microcode( + const struct microcode_patch *patch, unsigned int flags) { int hw_err, result; unsigned int cpu = smp_processor_id(); @@ -422,7 +422,7 @@ static int scan_equiv_cpu_table(const struct container_equiv_table *et) return -ESRCH; } -static struct microcode_patch *cf_check cpu_request_microcode( +static __maybe_unused struct microcode_patch *cf_check cpu_request_microcode( const void *buf, size_t size, bool make_copy) { const struct microcode_patch *saved = NULL; @@ -557,15 +557,17 @@ static struct microcode_patch *cf_check cpu_request_microcode( return patch; } -static const char __initconst amd_cpio_path[] = +static const char __initconst __maybe_unused 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, +#ifdef CONFIG_MICROCODE_LOADING + .cpu_request_microcode = cpu_request_microcode, .apply_microcode = apply_microcode, .compare = amd_compare, .cpio_path = amd_cpio_path, +#endif /* CONFIG_MICROCODE_LOADING */ }; void __init ucode_probe_amd(struct microcode_ops *ops) @@ -574,7 +576,8 @@ 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 @@ -614,8 +617,9 @@ 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 fe47c3a6c1..aec99834fd 100644 --- a/xen/arch/x86/cpu/microcode/core.c +++ b/xen/arch/x86/cpu/microcode/core.c @@ -44,6 +44,9 @@ #include "private.h" +#define can_apply_microcode(ops) (IS_ENABLED(CONFIG_MICROCODE_LOADING) && \ + (ops).apply_microcode) + /* * Before performing a late microcode update on any thread, we * rendezvous all cpus in stop_machine context. The timeout for @@ -58,7 +61,7 @@ */ #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; /* @@ -101,9 +104,10 @@ 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; +#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. @@ -162,6 +166,7 @@ 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; @@ -469,7 +474,7 @@ 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; @@ -613,6 +618,7 @@ 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) { @@ -622,7 +628,7 @@ int ucode_update_hcall(XEN_GUEST_HANDLE(const_void) buf, if ( flags & ~XENPF_UCODE_FORCE ) return -EINVAL; - if ( !ucode_ops.apply_microcode ) + if ( !can_apply_microcode(ucode_ops) ) return -EINVAL; buffer = xmalloc_flex_struct(struct ucode_buf, buffer, len); @@ -645,6 +651,7 @@ 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) @@ -658,7 +665,7 @@ int microcode_update_one(void) if ( ucode_ops.collect_cpu_info ) alternative_vcall(ucode_ops.collect_cpu_info); - if ( !ucode_ops.apply_microcode ) + if ( !can_apply_microcode(ucode_ops) ) return -EOPNOTSUPP; spin_lock(µcode_mutex); @@ -678,6 +685,7 @@ 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; @@ -734,6 +742,7 @@ static int __init cf_check microcode_init_cache(void) return rc; } presmp_initcall(microcode_init_cache); +#endif /* CONFIG_MICROCODE_LOADING */ /* * There are several tasks: @@ -907,10 +916,12 @@ 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 ( !can_apply_microcode(ucode_ops) || 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_MICROCODE_LOADING) ? "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/intel.c b/xen/arch/x86/cpu/microcode/intel.c index 281993e725..d9895018b4 100644 --- a/xen/arch/x86/cpu/microcode/intel.c +++ b/xen/arch/x86/cpu/microcode/intel.c @@ -273,7 +273,7 @@ static bool microcode_fits_cpu(const struct microcode_patch *mc) return false; } -static int cf_check intel_compare( +static int __maybe_unused cf_check intel_compare( const struct microcode_patch *old, const struct microcode_patch *new) { /* @@ -286,8 +286,8 @@ 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) +static int cf_check __maybe_unused apply_microcode( + const struct microcode_patch *patch, unsigned int flags) { uint64_t msr_content; unsigned int cpu = smp_processor_id(); @@ -333,7 +333,7 @@ static int cf_check apply_microcode(const struct microcode_patch *patch, return 0; } -static struct microcode_patch *cf_check cpu_request_microcode( +static __maybe_unused struct microcode_patch *cf_check cpu_request_microcode( const void *buf, size_t size, bool make_copy) { int error = 0; @@ -404,21 +404,23 @@ static bool __init can_load_microcode(void) return !(mcu_ctrl & MCU_CONTROL_DIS_MCU_LOAD); } -static const char __initconst intel_cpio_path[] = +static const char __initconst __maybe_unused 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, +#ifdef CONFIG_MICROCODE_LOADING + .cpu_request_microcode = cpu_request_microcode, .apply_microcode = apply_microcode, .compare = intel_compare, .cpio_path = intel_cpio_path, +#endif /* CONFIG_MICROCODE_LOADING */ }; void __init ucode_probe_intel(struct microcode_ops *ops) { *ops = intel_ucode_ops; - if ( !can_load_microcode() ) + if ( IS_ENABLED(CONFIG_MICROCODE_LOADING) && !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 0194720003..42a2c46b5e 100644 --- a/xen/arch/x86/efi/efi-boot.h +++ b/xen/arch/x86/efi/efi-boot.h @@ -295,7 +295,8 @@ 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 79bb99e0b6..5e83965d21 100644 --- a/xen/arch/x86/platform_hypercall.c +++ b/xen/arch/x86/platform_hypercall.c @@ -307,6 +307,7 @@ ret_t do_platform_op( break; } +#ifdef CONFIG_MICROCODE_LOADING case XENPF_microcode_update: { XEN_GUEST_HANDLE(const_void) data; @@ -327,6 +328,7 @@ ret_t do_platform_op( op->u.microcode2.flags); break; } +#endif /* CONFIG_MICROCODE_LOADING */ case XENPF_platform_quirk: { diff --git a/xen/common/Makefile b/xen/common/Makefile index 92c97d641e..1e6c92e554 100644 --- a/xen/common/Makefile +++ b/xen/common/Makefile @@ -65,7 +65,8 @@ 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_MICROCODE_LOADING) += earlycpio.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) -- 2.43.0
