diff --git a/tdx-compliance/README.md b/tdx-compliance/README.md index 55eb7b23..6aa894e4 100644 --- a/tdx-compliance/README.md +++ b/tdx-compliance/README.md @@ -34,8 +34,11 @@ insmod tdx-compliance To run all kinds of compliance tests, simply enter the following command: ```bash -echo all > /sys/kernel/debug/tdx/tdx-tests +echo all [version]> /sys/kernel/debug/tdx/tdx-tests ``` +the compliance tests of all versions will be tested in default. + +If you want to test against a specific TDX-Module version, use `[version]` option, the currently selectable version is "1.0" or "1.5". To view the results and logs, use this command: ```bash @@ -63,7 +66,7 @@ interface /sys/kernel/debug/tdx/tdx-tests. Usage: Run cpuid compliance tests: ``` -echo cpuid > /sys/kernel/debug/tdx/tdx-tests +echo cpuid [version] > /sys/kernel/debug/tdx/tdx-tests ``` * MSR @@ -75,7 +78,7 @@ the behavior of the MSRs' read and write. Usage: Run MSR compliance tests: ``` -each msr > /sys/kernel/debug/tdx/tdx-tests +each msr [version] > /sys/kernel/debug/tdx/tdx-tests ``` * CR(Control Registers) @@ -87,7 +90,7 @@ can be used to enable or disable the pagination mechanism, etc. Usage: ``` -echo cr > /sys/kernel/debug/tdx/tdx-tests +echo cr [version] > /sys/kernel/debug/tdx/tdx-tests ``` ## Contact: diff --git a/tdx-compliance/tdx-compliance-cr.h b/tdx-compliance/tdx-compliance-cr.h index 85d80a8c..a809819f 100644 --- a/tdx-compliance/tdx-compliance-cr.h +++ b/tdx-compliance/tdx-compliance-cr.h @@ -36,6 +36,22 @@ static int pre_cond_cr0_combine(struct test_cr *c) return 0; } +static int pre_cond_cr4_perfmon(struct test_cr *c) +{ + struct test_cpuid cpuid_perf = DEF_CPUID_TEST(0xa, 0); + + run_cpuid(&cpuid_perf); + + /* CPUID(0xa,0x0).* */ + if (cpuid_perf.regs.eax.val == 0 && cpuid_perf.regs.ebx.val == 0 && + cpuid_perf.regs.ecx.val == 0 && cpuid_perf.regs.edx.val == 0) { + c->excp.expect = X86_TRAP_GP; + return 0; + } + + return -1; +} + static int pre_cond_cr4_kl(struct test_cr *c) { struct test_cpuid cpuid_kl = DEF_CPUID_TEST(0x7, 0); @@ -104,54 +120,60 @@ static int pre_cond_cr4_uint(struct test_cr *c) #define NO_EXCP 0 #define NO_PRE_COND NULL -#define DEF_GET_CR0(_mask, _expect, _excp, _precond) \ +#define DEF_GET_CR0(_mask, _expect, _excp, _precond, _vsn) \ { \ .name = "CR0_GET_" #_mask, \ + .version = _vsn, \ .reg.expect = _expect, \ .reg.mask = _mask, \ .run_cr_get = get_cr0, \ .pre_condition = _precond, \ } -#define DEF_SET_CR0(_mask, _excp, _precond) \ +#define DEF_SET_CR0(_mask, _excp, _precond, _vsn) \ { \ .name = "CR0_SET_" #_mask, \ + .version = _vsn, \ .reg.mask = _mask, \ .excp.expect = _excp, \ .run_cr_set = set_cr0_bit, \ .pre_condition = _precond, \ } -#define DEF_CLEAR_CR0(_mask, _excp, _precond) \ +#define DEF_CLEAR_CR0(_mask, _excp, _precond, _vsn) \ { \ .name = "CR0_SET_" #_mask, \ + .version = _vsn, \ .reg.mask = _mask, \ .excp.expect = _excp, \ .run_cr_set = set_cr0_clear_bit, \ .pre_condition = _precond, \ } -#define DEF_GET_CR4(_mask, _expect, _excp, _precond) \ +#define DEF_GET_CR4(_mask, _expect, _excp, _precond, _vsn) \ { \ .name = "CR4_GET_" #_mask, \ + .version = _vsn, \ .reg.expect = _expect, \ .reg.mask = _mask, \ .run_cr_get = get_cr4, \ .pre_condition = _precond, \ } -#define DEF_SET_CR4(_mask, _excp, _precond) \ +#define DEF_SET_CR4(_mask, _excp, _precond, _vsn) \ { \ .name = "CR4_SET_" #_mask, \ + .version = _vsn, \ .reg.mask = _mask, \ .excp.expect = _excp, \ .run_cr_set = set_cr4_bit, \ .pre_condition = _precond, \ } -#define DEF_XCH_CR4(_mask, _excp, _precond) \ +#define DEF_XCH_CR4(_mask, _excp, _precond, _vsn) \ { \ .name = "CR4_XCH_" #_mask, \ + .version = _vsn, \ .reg.mask = _mask, \ .excp.expect = _excp, \ .run_cr_set = set_cr4_exchange_bit, \ @@ -174,61 +196,67 @@ struct test_cr cr_list[] = { * bits PE(0) and NE(5) are always set to 1 * bits NW(29) and CD(30) are always cleared to 0 */ - DEF_GET_CR0(X86_CR0_CD, BIT_CLEAR, NO_EXCP, NO_PRE_COND), - DEF_GET_CR0(X86_CR0_NW, BIT_CLEAR, NO_EXCP, NO_PRE_COND), - DEF_GET_CR0(X86_CR0_PE, BIT_SET, NO_EXCP, NO_PRE_COND), - DEF_GET_CR0(X86_CR0_NE, BIT_SET, NO_EXCP, NO_PRE_COND), + DEF_GET_CR0(X86_CR0_CD, BIT_CLEAR, NO_EXCP, NO_PRE_COND, VER1_0 | VER1_5), + DEF_GET_CR0(X86_CR0_NW, BIT_CLEAR, NO_EXCP, NO_PRE_COND, VER1_0 | VER1_5), + DEF_GET_CR0(X86_CR0_PE, BIT_SET, NO_EXCP, NO_PRE_COND, VER1_0 | VER1_5), + DEF_GET_CR0(X86_CR0_NE, BIT_SET, NO_EXCP, NO_PRE_COND, VER1_0 | VER1_5), - DEF_GET_CR4(X86_CR4_SMXE, BIT_CLEAR, NO_EXCP, NO_PRE_COND), - DEF_GET_CR4(X86_CR4_VMXE, BIT_CLEAR, NO_EXCP, NO_PRE_COND), - DEF_GET_CR4(X86_CR4_MCE, BIT_SET, NO_EXCP, NO_PRE_COND), + DEF_GET_CR4(X86_CR4_SMXE, BIT_CLEAR, NO_EXCP, NO_PRE_COND, VER1_0 | VER1_5), + DEF_GET_CR4(X86_CR4_VMXE, BIT_CLEAR, NO_EXCP, NO_PRE_COND, VER1_0 | VER1_5), + DEF_GET_CR4(X86_CR4_MCE, BIT_SET, NO_EXCP, NO_PRE_COND, VER1_0 | VER1_5), - DEF_CLEAR_CR0(X86_CR0_PE, X86_TRAP_GP, NO_PRE_COND), - DEF_CLEAR_CR0(X86_CR0_NE, X86_TRAP_GP, NO_PRE_COND), - DEF_CLEAR_CR0(X86_CR0_PE | X86_CR0_PG, NO_EXCP, pre_cond_cr0_combine), + DEF_CLEAR_CR0(X86_CR0_PE, X86_TRAP_GP, NO_PRE_COND, VER1_0 | VER1_5), + DEF_CLEAR_CR0(X86_CR0_NE, X86_TRAP_GP, NO_PRE_COND, VER1_0 | VER1_5), + DEF_CLEAR_CR0(X86_CR0_PE | X86_CR0_PG, NO_EXCP, pre_cond_cr0_combine, VER1_0 | VER1_5), - DEF_SET_CR0(X86_CR0_NW, X86_TRAP_VE, NO_PRE_COND), - DEF_SET_CR0(X86_CR0_CD, X86_TRAP_VE, NO_PRE_COND), + DEF_SET_CR0(X86_CR0_NW, X86_TRAP_VE, NO_PRE_COND, VER1_0 | VER1_5), + DEF_SET_CR0(X86_CR0_CD, X86_TRAP_VE, NO_PRE_COND, VER1_0 | VER1_5), /* * TD attempts to modify them results in a #VE, * bits VMXE(13) and SMXE(14) are fixed to 0. */ - DEF_XCH_CR4(X86_CR4_VMXE | X86_CR4_SMXE, X86_TRAP_VE, NO_PRE_COND), + DEF_XCH_CR4(X86_CR4_VMXE | X86_CR4_SMXE, X86_TRAP_VE, NO_PRE_COND, VER1_0 | VER1_5), /* - * TD attempts to modify them results in a #VE, + * TD attempts to modify bit MCE(6) results in a #VE, * bits MCE(6) are fixed to 1. */ - DEF_XCH_CR4(X86_CR4_MCE, X86_TRAP_VE, NO_PRE_COND), + DEF_XCH_CR4(X86_CR4_MCE, X86_TRAP_VE, NO_PRE_COND, VER1_0 | VER1_5), + + /* + * TD attempts to set bit PCE(8) results in a #GP(0), + * if the TD's ATTRIBUTES.PERFMON is 0. + */ + DEF_SET_CR4(X86_CR4_PCE, NO_EXCP, pre_cond_cr4_perfmon, VER1_0), /* * TD attempts to set bit KL(19) results in a #GP(0), * if the TD's ATTRIBUTES.KL is 0. */ - DEF_SET_CR4(X86_CR4_KL, NO_EXCP, pre_cond_cr4_kl), + DEF_SET_CR4(X86_CR4_KL, NO_EXCP, pre_cond_cr4_kl, VER1_0 | VER1_5), /* * TD attempts to set bit PKS(24) results in a #GP(0), * if the TD's ATTRIBUTES.PKS is 0. */ - DEF_SET_CR4(X86_CR4_PKS, NO_EXCP, pre_cond_cr4_pks), + DEF_SET_CR4(X86_CR4_PKS, NO_EXCP, pre_cond_cr4_pks, VER1_0 | VER1_5), /* * TD modification of CR4 bit PKE(22) is prevented, * depending on TD's XFAM. */ - DEF_XCH_CR4(X86_CR4_PKE, NO_EXCP, pre_cond_cr4_pke), + DEF_XCH_CR4(X86_CR4_PKE, NO_EXCP, pre_cond_cr4_pke, VER1_0 | VER1_5), /* * TD modification of CR4 bit CET(23) is prevented, * depending on TD's XFAM. */ - DEF_XCH_CR4(X86_CR4_CET, NO_EXCP, pre_cond_cr4_cet), + DEF_XCH_CR4(X86_CR4_CET, NO_EXCP, pre_cond_cr4_cet, VER1_0 | VER1_5), /* * TD modification of CR4 bit UINT(25) is prevented, * depending on TD's XFAM */ - DEF_XCH_CR4(X86_CR4_UINT, NO_EXCP, pre_cond_cr4_uint), + DEF_XCH_CR4(X86_CR4_UINT, NO_EXCP, pre_cond_cr4_uint, VER1_0 | VER1_5), }; diff --git a/tdx-compliance/tdx-compliance-msr.h b/tdx-compliance/tdx-compliance-msr.h index 649ef693..967aeb9e 100644 --- a/tdx-compliance/tdx-compliance-msr.h +++ b/tdx-compliance/tdx-compliance-msr.h @@ -246,7 +246,7 @@ struct test_msr msr_cases[] = { DEF_WRITE_MSR(MSR_IA32_TSC, X86_TRAP_VE, NO_PRE_COND, VER1_0 | VER1_5), DEF_READ_MSR(MSR_IA32_SPEC_CTRL, NO_EXCP, NO_PRE_COND, VER1_0 | VER1_5), DEF_WRITE_MSR(MSR_IA32_SPEC_CTRL, NO_EXCP, NO_PRE_COND, VER1_0 | VER1_5), - DEF_READ_MSR(MSR_IA32_PRED_CMD, NO_EXCP, NO_PRE_COND, VER1_5), + DEF_READ_MSR(MSR_IA32_PRED_CMD, NO_EXCP, NO_PRE_COND, VER1_0), DEF_READ_MSR(MSR_IA32_PRED_CMD, X86_TRAP_GP, NO_PRE_COND, VER1_5), DEF_WRITE_MSR(MSR_IA32_PRED_CMD, NO_EXCP, NO_PRE_COND, VER1_0 | VER1_5), DEF_READ_MSR(MSR_IA32_MKTME_PARTITIONING, X86_TRAP_VE, pre_0x7_edx18, VER1_0 | VER1_5), @@ -274,7 +274,7 @@ struct test_msr msr_cases[] = { DEF_WRITE_MSR(MSR_IA32_ARCH_CAPABILITIES, X86_TRAP_GP, NO_PRE_COND, VER1_5), DEF_READ_MSR(MSR_IA32_FLUSH_CMD, NO_EXCP, NO_PRE_COND, VER1_0), DEF_READ_MSR(MSR_IA32_FLUSH_CMD, X86_TRAP_GP, NO_PRE_COND, VER1_5), - DEF_WRITE_MSR(MSR_IA32_FLUSH_CMD, NO_EXCP, NO_PRE_COND, VER1_5), + DEF_WRITE_MSR(MSR_IA32_FLUSH_CMD, NO_EXCP, NO_PRE_COND, VER1_0 | VER1_5), DEF_READ_MSR(MSR_IA32_TSX_CTRL, X86_TRAP_GP, NO_PRE_COND, VER1_0), DEF_WRITE_MSR(MSR_IA32_TSX_CTRL, X86_TRAP_GP, NO_PRE_COND, VER1_0), DEF_READ_MSR(MSR_IA32_TSX_CTRL, NO_EXCP, pre_tsx, VER1_5), @@ -334,7 +334,7 @@ struct test_msr msr_cases[] = { DEF_WRITE_MSR(MSR_PEBS_FRONTEND, NO_EXCP, pre_perfmon, VER1_0 | VER1_5), DEF_READ_MSR(MSR_IA32_VMX_BASIC, X86_TRAP_GP, NO_PRE_COND, VER1_0), DEF_READ_MSR(MSR_IA32_VMX_BASIC, NO_EXCP, NO_PRE_COND, VER1_5), - DEF_WRITE_MSR(MSR_IA32_VMX_BASIC, X86_TRAP_GP, NO_PRE_COND, VER1_5), + DEF_WRITE_MSR(MSR_IA32_VMX_BASIC, X86_TRAP_GP, NO_PRE_COND, VER1_0 | VER1_5), DEF_READ_MSR(MSR_IA32_VMX_PINBASED_CTLS, X86_TRAP_GP, NO_PRE_COND, VER1_0), DEF_READ_MSR(MSR_IA32_VMX_PINBASED_CTLS, X86_TRAP_VE, NO_PRE_COND, VER1_5), DEF_WRITE_MSR(MSR_IA32_VMX_PINBASED_CTLS, X86_TRAP_GP, NO_PRE_COND, VER1_0 | VER1_5), diff --git a/tdx-compliance/tdx-compliance.c b/tdx-compliance/tdx-compliance.c index 20ada063..dbd7010d 100644 --- a/tdx-compliance/tdx-compliance.c +++ b/tdx-compliance/tdx-compliance.c @@ -330,6 +330,8 @@ static int run_all_cr(void) if (operation & 0x8000 && strcmp(str_input, t->name) != 0) continue; + if (!(spec_version & t->version)) continue; + if (t->run_cr_get) t->reg.val = t->run_cr_get(); @@ -348,7 +350,8 @@ static int run_all_cr(void) t->ret = check_results_cr(t); t->ret == 1 ? stat_pass++ : stat_fail++; - pr_buf("%d: %s:\t %s\n", ++stat_total, t->name, + version_name = get_version(t->version); + pr_buf("%d: %s%s:\t %s\n", ++stat_total, t->name, version_name, result_str(t->ret)); } return 0; @@ -358,7 +361,7 @@ static ssize_t tdx_tests_proc_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { - return simple_read_from_buffer(buffer, count, ppos, buf_ret, SIZE_BUF); + return simple_read_from_buffer(buffer, count, ppos, buf_ret, cnt_log); } static ssize_t diff --git a/tdx-compliance/tdx-compliance.h b/tdx-compliance/tdx-compliance.h index e20d31a5..0e155def 100644 --- a/tdx-compliance/tdx-compliance.h +++ b/tdx-compliance/tdx-compliance.h @@ -60,6 +60,7 @@ struct excp { struct test_cr { char *name; /* The name of the case */ + int version; int ret; /* The result of the test, 1 for pass */ struct cr_reg reg; struct excp excp; /* The test's predicted and actual trap number */