@@ -438,6 +438,12 @@
#define MSR_RELOAD_PMC0 0x000014c1
#define MSR_RELOAD_FIXED_CTR0 0x00001309
+/* Memory encryption MSRs */
+#define MSR_IA32_TME_CAPABILITY 0x981
+#define MSR_IA32_TME_ACTIVATE 0x982
+#define MSR_IA32_TME_EXCLUDE_MASK 0x983
+#define MSR_IA32_TME_EXCLUDE_BASE 0x984
+
/*
* AMD64 MSRs. Not complete. See the architecture manual for a more
* complete list.
@@ -863,4 +863,18 @@ bool arch_is_platform_page(u64 paddr);
#define arch_is_platform_page arch_is_platform_page
#endif
+/* 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
+
+#define TME_EXCLUSION_ENABLED(x) ((x) & 0x800) /* Bit 11 */
+
#endif /* _ASM_X86_PROCESSOR_H */
@@ -14,6 +14,7 @@
#include <asm/cpufeature.h>
#include <asm/msr.h>
+#include <asm/processor.h>
#include <asm/bugs.h>
#include <asm/cpu.h>
#include <asm/intel-family.h>
@@ -492,20 +493,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
@@ -84,6 +84,22 @@ static inline struct kvm_cpuid_entry2 *cpuid_entry2_find(
return NULL;
}
+static bool kvm_tme_supported(void)
+{
+ u64 tme_activation, tme_exclusion;
+
+ if (!feature_bit(TME))
+ return false;
+
+ if (rdmsrl_safe(MSR_IA32_TME_EXCLUDE_MASK, &tme_exclusion))
+ return false;
+ if (rdmsrl_safe(MSR_IA32_TME_ACTIVATE, &tme_activation))
+ return false;
+
+ return TME_ACTIVATE_LOCKED(tme_activation) &&
+ !TME_EXCLUSION_ENABLED(tme_exclusion);
+}
+
static int kvm_check_cpuid(struct kvm_vcpu *vcpu,
struct kvm_cpuid_entry2 *entries,
int nent)
@@ -508,6 +524,7 @@ static __always_inline void kvm_cpu_cap_mask(enum cpuid_leafs leaf, u32 mask)
void kvm_set_cpu_caps(void)
{
+ unsigned int f_tme = kvm_tme_supported() ? F(TME) : 0;
#ifdef CONFIG_X86_64
unsigned int f_gbpages = F(GBPAGES);
unsigned int f_lm = F(LM);
@@ -565,7 +582,7 @@ void kvm_set_cpu_caps(void)
F(AVX512VBMI) | F(LA57) | F(PKU) | 0 /*OSPKE*/ | F(RDPID) |
F(AVX512_VPOPCNTDQ) | F(UMIP) | F(AVX512_VBMI2) | F(GFNI) |
F(VAES) | F(VPCLMULQDQ) | F(AVX512_VNNI) | F(AVX512_BITALG) |
- F(CLDEMOTE) | F(MOVDIRI) | F(MOVDIR64B) | 0 /*WAITPKG*/ |
+ f_tme | F(CLDEMOTE) | F(MOVDIRI) | F(MOVDIR64B) | 0 /*WAITPKG*/ |
F(SGX_LC) | F(BUS_LOCK_DETECT)
);
/* Set LA57 based on hardware capability. */
@@ -1913,6 +1913,26 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
case MSR_IA32_DEBUGCTLMSR:
msr_info->data = vmcs_read64(GUEST_IA32_DEBUGCTL);
break;
+ case MSR_IA32_TME_CAPABILITY:
+ if (!guest_cpuid_has(vcpu, X86_FEATURE_TME))
+ return 1;
+ if (rdmsrl_safe(MSR_IA32_TME_CAPABILITY, &msr_info->data))
+ return 1;
+ msr_info->data &= 0x80000005; /* Bit 0, 2, 31 */
+ break;
+ case MSR_IA32_TME_ACTIVATE:
+ if (!guest_cpuid_has(vcpu, X86_FEATURE_TME))
+ return 1;
+ if (rdmsrl_safe(MSR_IA32_TME_ACTIVATE, &msr_info->data))
+ return 1;
+ msr_info->data &= 0x800000FF; /* Bits [0-7] and Bit 31 */
+ break;
+ case MSR_IA32_TME_EXCLUDE_MASK:
+ case MSR_IA32_TME_EXCLUDE_BASE:
+ if (!guest_cpuid_has(vcpu, X86_FEATURE_TME))
+ return 1;
+ msr_info->data = 0x0;
+ break;
default:
find_uret_msr:
msr = vmx_find_uret_msr(vmx, msr_info->index);
Guests running on IceLake have TME-EN disabled in CPUID, and they can't read TME related MSRs [IA32_TME_CAPABILITY, IA32_TME_ACTIVATE, IA32_TME_EXCLUDE_MASK, IA32_TME_EXCLUDE_BASE]. So guests don't know if they are running with TME enabled or not. In this patch, TME information is passed to the guest if the host has `TME-EN` enabled in CPUID and TME MSRs are locked and the exclusion range is disabled. This will guarantee that hardware supports TME, MSRs are locked, so host can't change them and exclusion range is disabled, so TME rules apply on all host memory. In IA32_TME_CAPABILITY and IA32_TME_ACTIVATE we mask out the reserved bits and MKTME related bits. So in IA32_TME_CAPABILITY, we are passing: Bit[0]: Support for AES-XTS 128-bit encryption algorithm Bit[2]: Support for AES-XTS 256-bit encryption algorithm Bit[31]: TME encryption bypass supported And in IA32_TME_ACTIVATE, we are passing: Bit[0]: Lock RO Bit[1]: TME Enable RWL Bit[2]: Key select Bit[3]: Save TME key for Standby Bit[4:7]: Encryption Algorithm Bit[31]: TME Encryption Bypass Enable However IA32_TME_EXCLUDE_MASK and IA32_TME_EXCLUDE_BASE are read by the guest as zero, since we will only pass TME information if the exclusion range is disabled. Those information are helpful for the guest to determine if TME is enabled by the BIOS or not. Signed-off-by: Fares Mehanna <faresx@amazon.de> --- arch/x86/include/asm/msr-index.h | 6 ++++++ arch/x86/include/asm/processor.h | 14 ++++++++++++++ arch/x86/kernel/cpu/intel.c | 15 +-------------- arch/x86/kvm/cpuid.c | 19 ++++++++++++++++++- arch/x86/kvm/vmx/vmx.c | 20 ++++++++++++++++++++ 5 files changed, 59 insertions(+), 15 deletions(-)