Commit 6890cb1a authored by Paolo Bonzini's avatar Paolo Bonzini Committed by Dave Hansen
Browse files

x86/cpu/intel: Detect TME keyid bits before setting MTRR mask registers



MKTME repurposes the high bit of physical address to key id for encryption
key and, even though MAXPHYADDR in CPUID[0x80000008] remains the same,
the valid bits in the MTRR mask register are based on the reduced number
of physical address bits.

detect_tme() in arch/x86/kernel/cpu/intel.c detects TME and subtracts
it from the total usable physical bits, but it is called too late.
Move the call to early_init_intel() so that it is called in setup_arch(),
before MTRRs are setup.

This fixes boot on TDX-enabled systems, which until now only worked with
"disable_mtrr_cleanup".  Without the patch, the values written to the
MTRRs mask registers were 52-bit wide (e.g. 0x000fffff_80000800) and
the writes failed; with the patch, the values are 46-bit wide, which
matches the reduced MAXPHYADDR that is shown in /proc/cpuinfo.

Reported-by: default avatarZixi Chen <zixchen@redhat.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
Signed-off-by: default avatarDave Hansen <dave.hansen@linux.intel.com>
Cc:stable@vger.kernel.org
Link: https://lore.kernel.org/all/20240131230902.1867092-3-pbonzini%40redhat.com
parent 9a458198
Loading
Loading
Loading
Loading
+91 −87
Original line number Diff line number Diff line
@@ -184,6 +184,90 @@ static bool bad_spectre_microcode(struct cpuinfo_x86 *c)
	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_POLICY(x)		((x >> 4) & 0xf)	/* Bits 7:4 */
#define TME_ACTIVATE_POLICY_AES_XTS_128	0

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

#define TME_ACTIVATE_CRYPTO_ALGS(x)	((x >> 48) & 0xffff)	/* Bits 63:48 */
#define TME_ACTIVATE_CRYPTO_AES_XTS_128	1

/* Values for mktme_status (SW only construct) */
#define MKTME_ENABLED			0
#define MKTME_DISABLED			1
#define MKTME_UNINITIALIZED		2
static int mktme_status = MKTME_UNINITIALIZED;

static void detect_tme_early(struct cpuinfo_x86 *c)
{
	u64 tme_activate, tme_policy, tme_crypto_algs;
	int keyid_bits = 0, nr_keyids = 0;
	static u64 tme_activate_cpu0 = 0;

	rdmsrl(MSR_IA32_TME_ACTIVATE, tme_activate);

	if (mktme_status != MKTME_UNINITIALIZED) {
		if (tme_activate != tme_activate_cpu0) {
			/* Broken BIOS? */
			pr_err_once("x86/tme: configuration is inconsistent between CPUs\n");
			pr_err_once("x86/tme: MKTME is not usable\n");
			mktme_status = MKTME_DISABLED;

			/* Proceed. We may need to exclude bits from x86_phys_bits. */
		}
	} else {
		tme_activate_cpu0 = tme_activate;
	}

	if (!TME_ACTIVATE_LOCKED(tme_activate) || !TME_ACTIVATE_ENABLED(tme_activate)) {
		pr_info_once("x86/tme: not enabled by BIOS\n");
		mktme_status = MKTME_DISABLED;
		return;
	}

	if (mktme_status != MKTME_UNINITIALIZED)
		goto detect_keyid_bits;

	pr_info("x86/tme: enabled by BIOS\n");

	tme_policy = TME_ACTIVATE_POLICY(tme_activate);
	if (tme_policy != TME_ACTIVATE_POLICY_AES_XTS_128)
		pr_warn("x86/tme: Unknown policy is active: %#llx\n", tme_policy);

	tme_crypto_algs = TME_ACTIVATE_CRYPTO_ALGS(tme_activate);
	if (!(tme_crypto_algs & TME_ACTIVATE_CRYPTO_AES_XTS_128)) {
		pr_err("x86/mktme: No known encryption algorithm is supported: %#llx\n",
				tme_crypto_algs);
		mktme_status = MKTME_DISABLED;
	}
detect_keyid_bits:
	keyid_bits = TME_ACTIVATE_KEYID_BITS(tme_activate);
	nr_keyids = (1UL << keyid_bits) - 1;
	if (nr_keyids) {
		pr_info_once("x86/mktme: enabled by BIOS\n");
		pr_info_once("x86/mktme: %d KeyIDs available\n", nr_keyids);
	} else {
		pr_info_once("x86/mktme: disabled by BIOS\n");
	}

	if (mktme_status == MKTME_UNINITIALIZED) {
		/* MKTME is usable */
		mktme_status = MKTME_ENABLED;
	}

	/*
	 * KeyID bits effectively lower the number of physical address
	 * bits.  Update cpuinfo_x86::x86_phys_bits accordingly.
	 */
	c->x86_phys_bits -= keyid_bits;
}

static void early_init_intel(struct cpuinfo_x86 *c)
{
	u64 misc_enable;
@@ -322,6 +406,13 @@ static void early_init_intel(struct cpuinfo_x86 *c)
	 */
	if (detect_extended_topology_early(c) < 0)
		detect_ht_early(c);

	/*
	 * Adjust the number of physical bits early because it affects the
	 * valid bits of the MTRR mask registers.
	 */
	if (cpu_has(c, X86_FEATURE_TME))
		detect_tme_early(c);
}

static void bsp_init_intel(struct cpuinfo_x86 *c)
@@ -482,90 +573,6 @@ static void srat_detect_node(struct cpuinfo_x86 *c)
#endif
}

#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_POLICY(x)		((x >> 4) & 0xf)	/* Bits 7:4 */
#define TME_ACTIVATE_POLICY_AES_XTS_128	0

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

#define TME_ACTIVATE_CRYPTO_ALGS(x)	((x >> 48) & 0xffff)	/* Bits 63:48 */
#define TME_ACTIVATE_CRYPTO_AES_XTS_128	1

/* Values for mktme_status (SW only construct) */
#define MKTME_ENABLED			0
#define MKTME_DISABLED			1
#define MKTME_UNINITIALIZED		2
static int mktme_status = MKTME_UNINITIALIZED;

static void detect_tme(struct cpuinfo_x86 *c)
{
	u64 tme_activate, tme_policy, tme_crypto_algs;
	int keyid_bits = 0, nr_keyids = 0;
	static u64 tme_activate_cpu0 = 0;

	rdmsrl(MSR_IA32_TME_ACTIVATE, tme_activate);

	if (mktme_status != MKTME_UNINITIALIZED) {
		if (tme_activate != tme_activate_cpu0) {
			/* Broken BIOS? */
			pr_err_once("x86/tme: configuration is inconsistent between CPUs\n");
			pr_err_once("x86/tme: MKTME is not usable\n");
			mktme_status = MKTME_DISABLED;

			/* Proceed. We may need to exclude bits from x86_phys_bits. */
		}
	} else {
		tme_activate_cpu0 = tme_activate;
	}

	if (!TME_ACTIVATE_LOCKED(tme_activate) || !TME_ACTIVATE_ENABLED(tme_activate)) {
		pr_info_once("x86/tme: not enabled by BIOS\n");
		mktme_status = MKTME_DISABLED;
		return;
	}

	if (mktme_status != MKTME_UNINITIALIZED)
		goto detect_keyid_bits;

	pr_info("x86/tme: enabled by BIOS\n");

	tme_policy = TME_ACTIVATE_POLICY(tme_activate);
	if (tme_policy != TME_ACTIVATE_POLICY_AES_XTS_128)
		pr_warn("x86/tme: Unknown policy is active: %#llx\n", tme_policy);

	tme_crypto_algs = TME_ACTIVATE_CRYPTO_ALGS(tme_activate);
	if (!(tme_crypto_algs & TME_ACTIVATE_CRYPTO_AES_XTS_128)) {
		pr_err("x86/mktme: No known encryption algorithm is supported: %#llx\n",
				tme_crypto_algs);
		mktme_status = MKTME_DISABLED;
	}
detect_keyid_bits:
	keyid_bits = TME_ACTIVATE_KEYID_BITS(tme_activate);
	nr_keyids = (1UL << keyid_bits) - 1;
	if (nr_keyids) {
		pr_info_once("x86/mktme: enabled by BIOS\n");
		pr_info_once("x86/mktme: %d KeyIDs available\n", nr_keyids);
	} else {
		pr_info_once("x86/mktme: disabled by BIOS\n");
	}

	if (mktme_status == MKTME_UNINITIALIZED) {
		/* MKTME is usable */
		mktme_status = MKTME_ENABLED;
	}

	/*
	 * KeyID bits effectively lower the number of physical address
	 * bits.  Update cpuinfo_x86::x86_phys_bits accordingly.
	 */
	c->x86_phys_bits -= keyid_bits;
}

static void init_cpuid_fault(struct cpuinfo_x86 *c)
{
	u64 msr;
@@ -702,9 +709,6 @@ static void init_intel(struct cpuinfo_x86 *c)

	init_ia32_feat_ctl(c);

	if (cpu_has(c, X86_FEATURE_TME))
		detect_tme(c);

	init_intel_misc_features(c);

	split_lock_init();