x86/cpu/intel: Detect TME keyid bits before setting MTRR mask registers
authorPaolo Bonzini <pbonzini@redhat.com>
Wed, 31 Jan 2024 23:09:02 +0000 (00:09 +0100)
committerDave Hansen <dave.hansen@linux.intel.com>
Mon, 26 Feb 2024 16:16:16 +0000 (08:16 -0800)
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: Zixi Chen <zixchen@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Cc:stable@vger.kernel.org
Link: https://lore.kernel.org/all/20240131230902.1867092-3-pbonzini%40redhat.com
arch/x86/kernel/cpu/intel.c

index a927a8f..40dec9b 100644 (file)
@@ -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();