TCG always allows setting CR4.SMEP, even when the CPUID bit is disabled. In this case, however, the test causes a triple fault because it tries to execute a user page with CR4.SMEP=1. The right way to do the test is to go through set_cr4_smep. Change set_cr4_smep to return whether an exception happened, and use it in ac_test_run. Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx> --- x86/access.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/x86/access.c b/x86/access.c index 56d17a1..640ca8c 100644 --- a/x86/access.c +++ b/x86/access.c @@ -192,23 +192,25 @@ void set_cr0_wp(int wp) write_cr0(cr0); } -void set_cr4_smep(int smep) +unsigned set_cr4_smep(int smep) { unsigned long cr4 = read_cr4(); unsigned long old_cr4 = cr4; extern u64 ptl2[]; + unsigned r; cr4 &= ~CR4_SMEP_MASK; if (smep) cr4 |= CR4_SMEP_MASK; if (old_cr4 == cr4) - return; + return 0; if (smep) ptl2[2] &= ~PT_USER_MASK; - write_cr4(cr4); + r = write_cr4_checking(cr4); if (!smep) ptl2[2] |= PT_USER_MASK; + return r; } void set_cr4_pke(int pke) @@ -951,9 +953,8 @@ int ac_test_run(void) } if (!(cpuid_7_ebx & (1 << 7))) { - unsigned long cr4 = read_cr4(); tests++; - if (write_cr4_checking(cr4 | CR4_SMEP_MASK) == GP_VECTOR) { + if (set_cr4_smep(1) == GP_VECTOR) { successes++; invalid_mask |= AC_CPU_CR4_SMEP_MASK; printf("CR4.SMEP not available, disabling SMEP tests\n"); -- 2.13.5