Commit d3287fb0 authored by Jithu Joseph's avatar Jithu Joseph Committed by Hans de Goede
Browse files

x86/microcode/intel: Expose collect_cpu_info_early() for IFS



IFS is a CPU feature that allows a binary blob, similar to microcode,
to be loaded and consumed to perform low level validation of CPU
circuitry. In fact, it carries the same Processor Signature
(family/model/stepping) details that are contained in Intel microcode
blobs.

In support of an IFS driver to trigger loading, validation, and running
of these tests blobs, make the functionality of cpu_signatures_match()
and collect_cpu_info_early() available outside of the microcode driver.

Add an "intel_" prefix and drop the "_early" suffix from
collect_cpu_info_early() and EXPORT_SYMBOL_GPL() it. Add
declaration to x86 <asm/cpu.h>

Make cpu_signatures_match() an inline function in x86 <asm/cpu.h>,
and also give it an "intel_" prefix.

No functional change intended.

Reviewed-by: default avatarDan Williams <dan.j.williams@intel.com>
Signed-off-by: default avatarJithu Joseph <jithu.joseph@intel.com>
Co-developed-by: default avatarTony Luck <tony.luck@intel.com>
Signed-off-by: default avatarTony Luck <tony.luck@intel.com>
Reviewed-by: default avatarThomas Gleixner <tglx@linutronix.de>
Acked-by: default avatarBorislav Petkov <bp@suse.de>
Reviewed-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Link: https://lore.kernel.org/r/20220506225410.1652287-2-tony.luck@intel.com


Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
parent 33e21e56
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -76,4 +76,22 @@ static inline void init_ia32_feat_ctl(struct cpuinfo_x86 *c) {}

extern __noendbr void cet_disable(void);

struct ucode_cpu_info;

int intel_cpu_collect_info(struct ucode_cpu_info *uci);

static inline bool intel_cpu_signatures_match(unsigned int s1, unsigned int p1,
					      unsigned int s2, unsigned int p2)
{
	if (s1 != s2)
		return false;

	/* Processor flags are either both 0 ... */
	if (!p1 && !p2)
		return true;

	/* ... or they intersect. */
	return p1 & p2;
}

#endif /* _ASM_X86_CPU_H */
+32 −0
Original line number Diff line number Diff line
@@ -181,6 +181,38 @@ static bool bad_spectre_microcode(struct cpuinfo_x86 *c)
	return false;
}

int intel_cpu_collect_info(struct ucode_cpu_info *uci)
{
	unsigned int val[2];
	unsigned int family, model;
	struct cpu_signature csig = { 0 };
	unsigned int eax, ebx, ecx, edx;

	memset(uci, 0, sizeof(*uci));

	eax = 0x00000001;
	ecx = 0;
	native_cpuid(&eax, &ebx, &ecx, &edx);
	csig.sig = eax;

	family = x86_family(eax);
	model  = x86_model(eax);

	if (model >= 5 || family > 6) {
		/* get processor flags from MSR 0x17 */
		native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
		csig.pf = 1 << ((val[1] >> 18) & 7);
	}

	csig.rev = intel_get_microcode_revision();

	uci->cpu_sig = csig;
	uci->valid = 1;

	return 0;
}
EXPORT_SYMBOL_GPL(intel_cpu_collect_info);

static void early_init_intel(struct cpuinfo_x86 *c)
{
	u64 misc_enable;
+7 −52
Original line number Diff line number Diff line
@@ -45,20 +45,6 @@ static struct microcode_intel *intel_ucode_patch;
/* last level cache size per core */
static int llc_size_per_core;

static inline bool cpu_signatures_match(unsigned int s1, unsigned int p1,
					unsigned int s2, unsigned int p2)
{
	if (s1 != s2)
		return false;

	/* Processor flags are either both 0 ... */
	if (!p1 && !p2)
		return true;

	/* ... or they intersect. */
	return p1 & p2;
}

/*
 * Returns 1 if update has been found, 0 otherwise.
 */
@@ -69,7 +55,7 @@ static int find_matching_signature(void *mc, unsigned int csig, int cpf)
	struct extended_signature *ext_sig;
	int i;

	if (cpu_signatures_match(csig, cpf, mc_hdr->sig, mc_hdr->pf))
	if (intel_cpu_signatures_match(csig, cpf, mc_hdr->sig, mc_hdr->pf))
		return 1;

	/* Look for ext. headers: */
@@ -80,7 +66,7 @@ static int find_matching_signature(void *mc, unsigned int csig, int cpf)
	ext_sig = (void *)ext_hdr + EXT_HEADER_SIZE;

	for (i = 0; i < ext_hdr->count; i++) {
		if (cpu_signatures_match(csig, cpf, ext_sig->sig, ext_sig->pf))
		if (intel_cpu_signatures_match(csig, cpf, ext_sig->sig, ext_sig->pf))
			return 1;
		ext_sig++;
	}
@@ -342,37 +328,6 @@ scan_microcode(void *data, size_t size, struct ucode_cpu_info *uci, bool save)
	return patch;
}

static int collect_cpu_info_early(struct ucode_cpu_info *uci)
{
	unsigned int val[2];
	unsigned int family, model;
	struct cpu_signature csig = { 0 };
	unsigned int eax, ebx, ecx, edx;

	memset(uci, 0, sizeof(*uci));

	eax = 0x00000001;
	ecx = 0;
	native_cpuid(&eax, &ebx, &ecx, &edx);
	csig.sig = eax;

	family = x86_family(eax);
	model  = x86_model(eax);

	if ((model >= 5) || (family > 6)) {
		/* get processor flags from MSR 0x17 */
		native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
		csig.pf = 1 << ((val[1] >> 18) & 7);
	}

	csig.rev = intel_get_microcode_revision();

	uci->cpu_sig = csig;
	uci->valid = 1;

	return 0;
}

static void show_saved_mc(void)
{
#ifdef DEBUG
@@ -386,7 +341,7 @@ static void show_saved_mc(void)
		return;
	}

	collect_cpu_info_early(&uci);
	intel_cpu_collect_info(&uci);

	sig	= uci.cpu_sig.sig;
	pf	= uci.cpu_sig.pf;
@@ -502,7 +457,7 @@ void show_ucode_info_early(void)
	struct ucode_cpu_info uci;

	if (delay_ucode_info) {
		collect_cpu_info_early(&uci);
		intel_cpu_collect_info(&uci);
		print_ucode_info(&uci, current_mc_date);
		delay_ucode_info = 0;
	}
@@ -604,7 +559,7 @@ int __init save_microcode_in_initrd_intel(void)
	if (!(cp.data && cp.size))
		return 0;

	collect_cpu_info_early(&uci);
	intel_cpu_collect_info(&uci);

	scan_microcode(cp.data, cp.size, &uci, true);

@@ -637,7 +592,7 @@ static struct microcode_intel *__load_ucode_intel(struct ucode_cpu_info *uci)
	if (!(cp.data && cp.size))
		return NULL;

	collect_cpu_info_early(uci);
	intel_cpu_collect_info(uci);

	return scan_microcode(cp.data, cp.size, uci, false);
}
@@ -712,7 +667,7 @@ void reload_ucode_intel(void)
	struct microcode_intel *p;
	struct ucode_cpu_info uci;

	collect_cpu_info_early(&uci);
	intel_cpu_collect_info(&uci);

	p = find_patch(&uci);
	if (!p)