Commit 42a7f6e3 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'x86_microcode_for_v6.6_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 microcode loading updates from Borislav Petkov:
 "The first, cleanup part of the microcode loader reorg tglx has been
  working on. The other part wasn't fully ready in time so it will
  follow on later.

  This part makes the loader core code as it is practically enabled on
  pretty much every baremetal machine so there's no need to have the
  Kconfig items.

  In addition, there are cleanups which prepare for future feature
  enablement"

* tag 'x86_microcode_for_v6.6_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/microcode: Remove remaining references to CONFIG_MICROCODE_AMD
  x86/microcode/intel: Remove pointless mutex
  x86/microcode/intel: Remove debug code
  x86/microcode: Move core specific defines to local header
  x86/microcode/intel: Rename get_datasize() since its used externally
  x86/microcode: Make reload_early_microcode() static
  x86/microcode: Include vendor headers into microcode.h
  x86/microcode/intel: Move microcode functions out of cpu/intel.c
  x86/microcode: Hide the config knob
  x86/mm: Remove unused microcode.h include
  x86/microcode: Remove microcode_mutex
  x86/microcode/AMD: Rip out static buffers
parents f31f663f 4d2b7483
Loading
Loading
Loading
Loading
+1 −37
Original line number Diff line number Diff line
@@ -1308,44 +1308,8 @@ config X86_REBOOTFIXUPS
	  Say N otherwise.

config MICROCODE
	bool "CPU microcode loading support"
	default y
	def_bool y
	depends on CPU_SUP_AMD || CPU_SUP_INTEL
	help
	  If you say Y here, you will be able to update the microcode on
	  Intel and AMD processors. The Intel support is for the IA32 family,
	  e.g. Pentium Pro, Pentium II, Pentium III, Pentium 4, Xeon etc. The
	  AMD support is for families 0x10 and later. You will obviously need
	  the actual microcode binary data itself which is not shipped with
	  the Linux kernel.

	  The preferred method to load microcode from a detached initrd is described
	  in Documentation/arch/x86/microcode.rst. For that you need to enable
	  CONFIG_BLK_DEV_INITRD in order for the loader to be able to scan the
	  initrd for microcode blobs.

	  In addition, you can build the microcode into the kernel. For that you
	  need to add the vendor-supplied microcode to the CONFIG_EXTRA_FIRMWARE
	  config option.

config MICROCODE_INTEL
	bool "Intel microcode loading support"
	depends on CPU_SUP_INTEL && MICROCODE
	default MICROCODE
	help
	  This options enables microcode patch loading support for Intel
	  processors.

	  For the current Intel microcode data package go to
	  <https://downloadcenter.intel.com> and search for
	  'Linux Processor Microcode Data File'.

config MICROCODE_AMD
	bool "AMD microcode loading support"
	depends on CPU_SUP_AMD && MICROCODE
	help
	  If you select this option, microcode patch loading support for AMD
	  processors will be enabled.

config MICROCODE_LATE_LOADING
	bool "Late microcode loading (DANGEROUS)"
+0 −1
Original line number Diff line number Diff line
@@ -33,7 +33,6 @@ CONFIG_HYPERVISOR_GUEST=y
CONFIG_PARAVIRT=y
CONFIG_NR_CPUS=8
CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y
CONFIG_MICROCODE_AMD=y
CONFIG_X86_MSR=y
CONFIG_X86_CPUID=y
CONFIG_X86_CHECK_BIOS_CORRUPTION=y
+0 −1
Original line number Diff line number Diff line
@@ -31,7 +31,6 @@ CONFIG_SMP=y
CONFIG_HYPERVISOR_GUEST=y
CONFIG_PARAVIRT=y
CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y
CONFIG_MICROCODE_AMD=y
CONFIG_X86_MSR=y
CONFIG_X86_CPUID=y
CONFIG_NUMA=y
+51 −106
Original line number Diff line number Diff line
@@ -2,138 +2,83 @@
#ifndef _ASM_X86_MICROCODE_H
#define _ASM_X86_MICROCODE_H

#include <asm/cpu.h>
#include <linux/earlycpio.h>
#include <linux/initrd.h>
#include <asm/microcode_amd.h>

struct ucode_patch {
	struct list_head plist;
	void *data;		/* Intel uses only this one */
	unsigned int size;
	u32 patch_id;
	u16 equiv_cpu;
};

extern struct list_head microcode_cache;

struct cpu_signature {
	unsigned int sig;
	unsigned int pf;
	unsigned int rev;
};

struct device;

enum ucode_state {
	UCODE_OK	= 0,
	UCODE_NEW,
	UCODE_UPDATED,
	UCODE_NFOUND,
	UCODE_ERROR,
struct ucode_cpu_info {
	struct cpu_signature	cpu_sig;
	void			*mc;
};

struct microcode_ops {
	enum ucode_state (*request_microcode_fw) (int cpu, struct device *);

	void (*microcode_fini_cpu) (int cpu);
#ifdef CONFIG_MICROCODE
void load_ucode_bsp(void);
void load_ucode_ap(void);
void microcode_bsp_resume(void);
#else
static inline void load_ucode_bsp(void)	{ }
static inline void load_ucode_ap(void) { }
static inline void microcode_bsp_resume(void) { }
#endif

	/*
	 * The generic 'microcode_core' part guarantees that
	 * the callbacks below run on a target cpu when they
	 * are being called.
	 * See also the "Synchronization" section in microcode_core.c.
	 */
	enum ucode_state (*apply_microcode) (int cpu);
	int (*collect_cpu_info) (int cpu, struct cpu_signature *csig);
#ifdef CONFIG_CPU_SUP_INTEL
/* Intel specific microcode defines. Public for IFS */
struct microcode_header_intel {
	unsigned int	hdrver;
	unsigned int	rev;
	unsigned int	date;
	unsigned int	sig;
	unsigned int	cksum;
	unsigned int	ldrver;
	unsigned int	pf;
	unsigned int	datasize;
	unsigned int	totalsize;
	unsigned int	metasize;
	unsigned int	reserved[2];
};

struct ucode_cpu_info {
	struct cpu_signature	cpu_sig;
	void			*mc;
struct microcode_intel {
	struct microcode_header_intel	hdr;
	unsigned int			bits[];
};
extern struct ucode_cpu_info ucode_cpu_info[];
struct cpio_data find_microcode_in_initrd(const char *path, bool use_pa);

#ifdef CONFIG_MICROCODE_INTEL
extern struct microcode_ops * __init init_intel_microcode(void);
#else
static inline struct microcode_ops * __init init_intel_microcode(void)
{
	return NULL;
}
#endif /* CONFIG_MICROCODE_INTEL */
#define DEFAULT_UCODE_DATASIZE		(2000)
#define MC_HEADER_SIZE			(sizeof(struct microcode_header_intel))
#define MC_HEADER_TYPE_MICROCODE	1
#define MC_HEADER_TYPE_IFS		2

#ifdef CONFIG_MICROCODE_AMD
extern struct microcode_ops * __init init_amd_microcode(void);
extern void __exit exit_amd_microcode(void);
#else
static inline struct microcode_ops * __init init_amd_microcode(void)
static inline int intel_microcode_get_datasize(struct microcode_header_intel *hdr)
{
	return NULL;
	return hdr->datasize ? : DEFAULT_UCODE_DATASIZE;
}
static inline void __exit exit_amd_microcode(void) {}
#endif

#define MAX_UCODE_COUNT 128

#define QCHAR(a, b, c, d) ((a) + ((b) << 8) + ((c) << 16) + ((d) << 24))
#define CPUID_INTEL1 QCHAR('G', 'e', 'n', 'u')
#define CPUID_INTEL2 QCHAR('i', 'n', 'e', 'I')
#define CPUID_INTEL3 QCHAR('n', 't', 'e', 'l')
#define CPUID_AMD1 QCHAR('A', 'u', 't', 'h')
#define CPUID_AMD2 QCHAR('e', 'n', 't', 'i')
#define CPUID_AMD3 QCHAR('c', 'A', 'M', 'D')

#define CPUID_IS(a, b, c, ebx, ecx, edx)	\
		(!((ebx ^ (a))|(edx ^ (b))|(ecx ^ (c))))

/*
 * In early loading microcode phase on BSP, boot_cpu_data is not set up yet.
 * x86_cpuid_vendor() gets vendor id for BSP.
 *
 * In 32 bit AP case, accessing boot_cpu_data needs linear address. To simplify
 * coding, we still use x86_cpuid_vendor() to get vendor id for AP.
 *
 * x86_cpuid_vendor() gets vendor information directly from CPUID.
 */
static inline int x86_cpuid_vendor(void)
static inline u32 intel_get_microcode_revision(void)
{
	u32 eax = 0x00000000;
	u32 ebx, ecx = 0, edx;
	u32 rev, dummy;

	native_cpuid(&eax, &ebx, &ecx, &edx);
	native_wrmsrl(MSR_IA32_UCODE_REV, 0);

	if (CPUID_IS(CPUID_INTEL1, CPUID_INTEL2, CPUID_INTEL3, ebx, ecx, edx))
		return X86_VENDOR_INTEL;
	/* As documented in the SDM: Do a CPUID 1 here */
	native_cpuid_eax(1);

	if (CPUID_IS(CPUID_AMD1, CPUID_AMD2, CPUID_AMD3, ebx, ecx, edx))
		return X86_VENDOR_AMD;
	/* get the current revision from MSR 0x8B */
	native_rdmsr(MSR_IA32_UCODE_REV, dummy, rev);

	return X86_VENDOR_UNKNOWN;
	return rev;
}

static inline unsigned int x86_cpuid_family(void)
{
	u32 eax = 0x00000001;
	u32 ebx, ecx = 0, edx;

	native_cpuid(&eax, &ebx, &ecx, &edx);
void show_ucode_info_early(void);

	return x86_family(eax);
}
#else /* CONFIG_CPU_SUP_INTEL */
static inline void show_ucode_info_early(void) { }
#endif /* !CONFIG_CPU_SUP_INTEL */

#ifdef CONFIG_MICROCODE
extern void __init load_ucode_bsp(void);
extern void load_ucode_ap(void);
void reload_early_microcode(unsigned int cpu);
extern bool initrd_gone;
void microcode_bsp_resume(void);
#else
static inline void __init load_ucode_bsp(void)			{ }
static inline void load_ucode_ap(void)				{ }
static inline void reload_early_microcode(unsigned int cpu)	{ }
static inline void microcode_bsp_resume(void)			{ }
#ifdef CONFIG_CPU_SUP_AMD
void amd_check_microcode(void);
#else /* CONFIG_CPU_SUP_AMD */
static inline void amd_check_microcode(void) {}
#endif

#endif /* _ASM_X86_MICROCODE_H */
+0 −60
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_X86_MICROCODE_AMD_H
#define _ASM_X86_MICROCODE_AMD_H

#include <asm/microcode.h>

#define UCODE_MAGIC			0x00414d44
#define UCODE_EQUIV_CPU_TABLE_TYPE	0x00000000
#define UCODE_UCODE_TYPE		0x00000001

#define SECTION_HDR_SIZE		8
#define CONTAINER_HDR_SZ		12

struct equiv_cpu_entry {
	u32	installed_cpu;
	u32	fixed_errata_mask;
	u32	fixed_errata_compare;
	u16	equiv_cpu;
	u16	res;
} __attribute__((packed));

struct microcode_header_amd {
	u32	data_code;
	u32	patch_id;
	u16	mc_patch_data_id;
	u8	mc_patch_data_len;
	u8	init_flag;
	u32	mc_patch_data_checksum;
	u32	nb_dev_id;
	u32	sb_dev_id;
	u16	processor_rev_id;
	u8	nb_rev_id;
	u8	sb_rev_id;
	u8	bios_api_rev;
	u8	reserved1[3];
	u32	match_reg[8];
} __attribute__((packed));

struct microcode_amd {
	struct microcode_header_amd	hdr;
	unsigned int			mpb[];
};

#define PATCH_MAX_SIZE (3 * PAGE_SIZE)

#ifdef CONFIG_MICROCODE_AMD
extern void __init load_ucode_amd_bsp(unsigned int family);
extern void load_ucode_amd_ap(unsigned int family);
extern int __init save_microcode_in_initrd_amd(unsigned int family);
void reload_ucode_amd(unsigned int cpu);
extern void amd_check_microcode(void);
#else
static inline void __init load_ucode_amd_bsp(unsigned int family) {}
static inline void load_ucode_amd_ap(unsigned int family) {}
static inline int __init
save_microcode_in_initrd_amd(unsigned int family) { return -EINVAL; }
static inline void reload_ucode_amd(unsigned int cpu) {}
static inline void amd_check_microcode(void) {}
#endif
#endif /* _ASM_X86_MICROCODE_AMD_H */
Loading