arch/x86/kernel/cpu/intel.c

Source file repositories/reference/linux-study-clean/arch/x86/kernel/cpu/intel.c

File Facts

System
Linux kernel
Corpus path
arch/x86/kernel/cpu/intel.c
Extension
.c
Size
21448 bytes
Lines
778
Domain
Architecture Layer
Bucket
arch/x86
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

struct sku_microcode {
	u32 vfm;
	u8 stepping;
	u32 microcode;
};
static const struct sku_microcode spectre_bad_microcodes[] = {
	{ INTEL_KABYLAKE,	0x0B,	0x80 },
	{ INTEL_KABYLAKE,	0x0A,	0x80 },
	{ INTEL_KABYLAKE,	0x09,	0x80 },
	{ INTEL_KABYLAKE_L,	0x0A,	0x80 },
	{ INTEL_KABYLAKE_L,	0x09,	0x80 },
	{ INTEL_SKYLAKE_X,	0x03,	0x0100013e },
	{ INTEL_SKYLAKE_X,	0x04,	0x0200003c },
	{ INTEL_BROADWELL,	0x04,	0x28 },
	{ INTEL_BROADWELL_G,	0x01,	0x1b },
	{ INTEL_BROADWELL_D,	0x02,	0x14 },
	{ INTEL_BROADWELL_D,	0x03,	0x07000011 },
	{ INTEL_BROADWELL_X,	0x01,	0x0b000025 },
	{ INTEL_HASWELL_L,	0x01,	0x21 },
	{ INTEL_HASWELL_G,	0x01,	0x18 },
	{ INTEL_HASWELL,	0x03,	0x23 },
	{ INTEL_HASWELL_X,	0x02,	0x3b },
	{ INTEL_HASWELL_X,	0x04,	0x10 },
	{ INTEL_IVYBRIDGE_X,	0x04,	0x42a },
	/* Observed in the wild */
	{ INTEL_SANDYBRIDGE_X,	0x06,	0x61b },
	{ INTEL_SANDYBRIDGE_X,	0x07,	0x712 },
};

static bool bad_spectre_microcode(struct cpuinfo_x86 *c)
{
	int i;

	/*
	 * We know that the hypervisor lie to us on the microcode version so
	 * we may as well hope that it is running the correct version.
	 */
	if (cpu_has(c, X86_FEATURE_HYPERVISOR))
		return false;

	for (i = 0; i < ARRAY_SIZE(spectre_bad_microcodes); i++) {
		if (c->x86_vfm == spectre_bad_microcodes[i].vfm &&
		    c->x86_stepping == spectre_bad_microcodes[i].stepping)
			return (c->microcode <= spectre_bad_microcodes[i].microcode);
	}
	return false;
}

#define MSR_IA32_TME_ACTIVATE		0x982

/* Helpers to access TME_ACTIVATE MSR */
#define TME_ACTIVATE_LOCKED(x)		(x & 0x1)
#define TME_ACTIVATE_ENABLED(x)		(x & 0x2)

#define TME_ACTIVATE_KEYID_BITS(x)	((x >> 32) & 0xf)	/* Bits 35:32 */

static void detect_tme_early(struct cpuinfo_x86 *c)
{
	u64 tme_activate;
	int keyid_bits;

	rdmsrq(MSR_IA32_TME_ACTIVATE, tme_activate);

	if (!TME_ACTIVATE_LOCKED(tme_activate) || !TME_ACTIVATE_ENABLED(tme_activate)) {
		pr_info_once("x86/tme: not enabled by BIOS\n");
		clear_cpu_cap(c, X86_FEATURE_TME);
		return;
	}
	pr_info_once("x86/tme: enabled by BIOS\n");
	keyid_bits = TME_ACTIVATE_KEYID_BITS(tme_activate);
	if (!keyid_bits)
		return;

	/*
	 * KeyID bits are set by BIOS and can be present regardless
	 * of whether the kernel is using them. They effectively lower
	 * the number of physical address bits.
	 *
	 * Update cpuinfo_x86::x86_phys_bits accordingly.
	 */
	c->x86_phys_bits -= keyid_bits;
	pr_info_once("x86/mktme: BIOS enabled: x86_phys_bits reduced by %d\n",
		     keyid_bits);
}

void intel_unlock_cpuid_leafs(struct cpuinfo_x86 *c)
{
	if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
		return;

Annotation

Implementation Notes