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 rather 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 <[email protected]> Reviewed-by: Andrew Cooper <[email protected]> --- v4: * Minor spell fix in commit message ("rather") * efi.pandoc: terminate sentence with "enabled". * xen-command-line: State applicability as first line. * reorder cpu hooks. * MICROCODE_OP() comment * MICROCODE_OP() moved next to microcode_ops * Re-arranged platform_ops to turn them into smaller hunks. --- docs/admin-guide/microcode-loading.rst | 2 ++ docs/misc/efi.pandoc | 2 ++ docs/misc/xen-command-line.pandoc | 7 ++++--- 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 | 3 +++ xen/arch/x86/efi/efi-boot.h | 3 ++- xen/arch/x86/platform_hypercall.c | 10 ++++++++-- 10 files changed, 63 insertions(+), 20 deletions(-) diff --git a/docs/admin-guide/microcode-loading.rst b/docs/admin-guide/microcode-loading.rst index a07e25802f..148bc8559b 100644 --- a/docs/admin-guide/microcode-loading.rst +++ b/docs/admin-guide/microcode-loading.rst @@ -23,6 +23,8 @@ 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 11c1ac3346..8198a7f063 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 enabled. + ###`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 15f7a315a4..0eca489b7d 100644 --- a/docs/misc/xen-command-line.pandoc +++ b/docs/misc/xen-command-line.pandoc @@ -2751,9 +2751,10 @@ performance. Applicability: x86 Default: `scan` is selectable via Kconfig, `nmi,digest-check` -Controls for CPU microcode loading. For early loading, this parameter can -specify how and where to find the microcode update blob. For late loading, -this parameter specifies if the update happens within a NMI handler. +Controls for CPU microcode loading, available when `CONFIG_MICROCODE_LOADING` is +enabled. For early loading, this parameter can specify how and where to find the +microcode update blob. For late loading, this parameter specifies if the update +happens within a NMI handler. 'integer' specifies the CPU microcode update blob module index. When positive, this specifies the n-th module (in the GrUB entry, zero based) to be used diff --git a/xen/arch/x86/Kconfig b/xen/arch/x86/Kconfig index d5705e4bff..61f58aa829 100644 --- a/xen/arch/x86/Kconfig +++ b/xen/arch/x86/Kconfig @@ -331,8 +331,22 @@ 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 71b041c84b..c1ab6deb4d 100644 --- a/xen/arch/x86/cpu/microcode/amd.c +++ b/xen/arch/x86/cpu/microcode/amd.c @@ -561,11 +561,11 @@ 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, .collect_cpu_info = collect_cpu_info, - .apply_microcode = apply_microcode, - .compare = amd_compare, - .cpio_path = amd_cpio_path, + .cpu_request_microcode = MICROCODE_OP(cpu_request_microcode), + .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) @@ -574,7 +574,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 +615,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 dabdb95b4c..efaf808f1a 100644 --- a/xen/arch/x86/cpu/microcode/core.c +++ b/xen/arch/x86/cpu/microcode/core.c @@ -58,7 +58,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; /* @@ -104,6 +104,7 @@ 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. @@ -162,6 +163,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 +471,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 +615,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) { @@ -645,6 +648,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 +662,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 ( !IS_ENABLED(CONFIG_MICROCODE_LOADING) || !ucode_ops.apply_microcode ) return -EOPNOTSUPP; spin_lock(µcode_mutex); @@ -678,6 +682,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 +739,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: @@ -898,6 +904,9 @@ 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 281993e725..dac464961a 100644 --- a/xen/arch/x86/cpu/microcode/intel.c +++ b/xen/arch/x86/cpu/microcode/intel.c @@ -408,17 +408,20 @@ 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, .collect_cpu_info = collect_cpu_info, - .apply_microcode = apply_microcode, - .compare = intel_compare, - .cpio_path = intel_cpio_path, + .cpu_request_microcode = MICROCODE_OP(cpu_request_microcode), + .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 e6c965dc99..77ce816c1a 100644 --- a/xen/arch/x86/cpu/microcode/private.h +++ b/xen/arch/x86/cpu/microcode/private.h @@ -8,6 +8,9 @@ /* Opaque. Internals are vendor-specific. */ struct microcode_patch; +/* Aids dead-code elimination of the static hooks */ +#define MICROCODE_OP(x) (IS_ENABLED(CONFIG_MICROCODE_LOADING) ? (x) : NULL) + struct microcode_ops { /* * Parse a microcode container. Format is vendor-specific. 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 f8eca48170..2ac9fc2d96 100644 --- a/xen/arch/x86/platform_hypercall.c +++ b/xen/arch/x86/platform_hypercall.c @@ -317,8 +317,11 @@ ret_t do_platform_op( { XEN_GUEST_HANDLE(const_void) data; - guest_from_compat_handle(data, op->u.microcode.data); + ret = -EOPNOTSUPP; + if ( !IS_ENABLED(CONFIG_MICROCODE_LOADING) ) + break; + guest_from_compat_handle(data, op->u.microcode.data); ret = ucode_update_hcall(data, op->u.microcode.length, 0); break; } @@ -327,8 +330,11 @@ ret_t do_platform_op( { XEN_GUEST_HANDLE(const_void) data; - guest_from_compat_handle(data, op->u.microcode2.data); + ret = -EOPNOTSUPP; + if ( !IS_ENABLED(CONFIG_MICROCODE_LOADING) ) + break; + guest_from_compat_handle(data, op->u.microcode2.data); ret = ucode_update_hcall(data, op->u.microcode2.length, op->u.microcode2.flags); break; -- 2.43.0
