[kvm-unit-tests RFC v2 16/18] x86 TDX: Modify the MSR test to be compatible with TDX

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Zhenzhong Duan <zhenzhong.duan@xxxxxxxxx>

According to TDX Module 1.5 ABI Sepc, Table 2.1 MSR Virtualization, the
following modifications are made in MSRs test.

1. Skip sub-tests about MSR_IA32_MISC_ENABLE and MSR_CSTAR, since
changing those MSRs are unsupported:
  - MSR_IA32_MISC_ENABLE is reading native and #VE in writing.
  - MSR_CSTAR is #VE in reading/writing and its simulation is not
    supported in TDX host side.

2. Skip the x2apic-msrs test in x2apic disabled mode. The TDX guest only
supports X2APIC, and cannot disable APIC.

3. Add readable flag for x2apic MSRs if TDX guest.

There is a gap between VMX and TDX about read registers in the virtual
APIC page. KVM will intercept reads to non-existent MSRs[1], the TDX
doesn't validate it and directly reads **native**. So add a readable
flag for x2apic MSRs if TDX guest to avoid #GP checking for RDMSR.

4. Add #VE check for MSR operation fault.

For some MSRs, e.g., MCE-related MSR, they are virtualized by #VE in
tdx. The exception of invalid RDMSR/WRMSR for it is #VE instead of #GP,
so correct it in the test_rdmsr_fault() and test_wrmsr_fault().

[1] KVM: VMX: Always intercept accesses to unsupported "extended" x2APIC
regs, https://lore.kernel.org/r/20230107011025.565472-6-seanjc@xxxxxxxxxx

Signed-off-by: Zhenzhong Duan <zhenzhong.duan@xxxxxxxxx>
Reviewed-by: Yu Zhang <yu.c.zhang@xxxxxxxxx>
Link: https://lore.kernel.org/r/20220303071907.650203-16-zhenzhong.duan@xxxxxxxxx
Co-developed-by: Qian Wen <qian.wen@xxxxxxxxx>
Signed-off-by: Qian Wen <qian.wen@xxxxxxxxx>
---
 x86/msr.c | 46 ++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 38 insertions(+), 8 deletions(-)

diff --git a/x86/msr.c b/x86/msr.c
index 3a041fab..b1392487 100644
--- a/x86/msr.c
+++ b/x86/msr.c
@@ -5,6 +5,7 @@
 #include "processor.h"
 #include "msr.h"
 #include <stdlib.h>
+#include "tdx.h"
 
 /*
  * This test allows two modes:
@@ -97,9 +98,11 @@ static void test_wrmsr(u32 msr, const char *name, unsigned long long val)
 static void test_wrmsr_fault(u32 msr, const char *name, unsigned long long val)
 {
 	unsigned char vector = wrmsr_safe(msr, val);
-
-	report(vector == GP_VECTOR,
-	       "Expected #GP on WRSMR(%s, 0x%llx), got vector %d",
+	bool pass = false;
+	if (vector == GP_VECTOR || (vector == VE_VECTOR && is_tdx_guest()))
+		pass = true;
+	report(pass,
+	       "Expected #GP/#VE on WRSMR(%s, 0x%llx), got vector %d",
 	       name, val, vector);
 }
 
@@ -107,13 +110,20 @@ static void test_rdmsr_fault(u32 msr, const char *name)
 {
 	uint64_t ignored;
 	unsigned char vector = rdmsr_safe(msr, &ignored);
-
-	report(vector == GP_VECTOR,
-	       "Expected #GP on RDSMR(%s), got vector %d", name, vector);
+	bool pass = false;
+	if (vector == GP_VECTOR || (vector == VE_VECTOR && is_tdx_guest()))
+		pass = true;
+	report(pass,
+	       "Expected #GP/#VE on RDSMR(%s), got vector %d", name, vector);
 }
 
 static void test_msr(struct msr_info *msr, bool is_64bit_host)
 {
+	/* Changing MSR_IA32_MISC_ENABLE and MSR_CSTAR is unsupported in TDX */
+	if ((msr->index == MSR_IA32_MISC_ENABLE || msr->index == MSR_CSTAR) &&
+	    is_tdx_guest())
+		return;
+
 	if (is_64bit_host || !msr->is_64bit_only) {
 		__test_msr_rw(msr->index, msr->name, msr->value, msr->keep);
 
@@ -223,6 +233,24 @@ static void test_mce_msrs(void)
 	}
 }
 
+static enum x2apic_reg_semantics get_x2apic_reg_semantics2(u32 reg)
+{
+	enum x2apic_reg_semantics ret;
+	ret = get_x2apic_reg_semantics(reg);
+
+	if (is_tdx_guest()) {
+		switch (reg) {
+		case APIC_ARBPRI:
+		case APIC_EOI:
+		case APIC_RRR:
+		case APIC_DFR:
+		case APIC_SELF_IPI:
+			ret |= X2APIC_RO;
+		}
+	}
+	return ret;
+}
+
 static void __test_x2apic_msrs(bool x2apic_enabled)
 {
 	enum x2apic_reg_semantics semantics;
@@ -234,7 +262,7 @@ static void __test_x2apic_msrs(bool x2apic_enabled)
 		snprintf(msr_name, sizeof(msr_name), "x2APIC MSR 0x%x", index);
 
 		if (x2apic_enabled)
-			semantics = get_x2apic_reg_semantics(i);
+			semantics = get_x2apic_reg_semantics2(i);
 		else
 			semantics = X2APIC_INVALID;
 
@@ -270,13 +298,15 @@ static void __test_x2apic_msrs(bool x2apic_enabled)
 
 static void test_x2apic_msrs(void)
 {
+	if (is_tdx_guest())
+		goto test_x2apic;
 	reset_apic();
 
 	__test_x2apic_msrs(false);
 
 	if (!enable_x2apic())
 		return;
-
+test_x2apic:
 	__test_x2apic_msrs(true);
 }
 
-- 
2.25.1





[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux