Enhance the CR.WP toggling test to do additional tests via the emulator as these used to trigger bugs when CR0.WP is guest owned. Link: https://lore.kernel.org/kvm/ea3a8fbc-2bf8-7442-e498-3e5818384c83@xxxxxxxxxxxxxx/ Signed-off-by: Mathias Krause <minipli@xxxxxxxxxxxxxx> --- x86/access.c | 46 +++++++++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/x86/access.c b/x86/access.c index ae5e7d8e8892..21967434bc18 100644 --- a/x86/access.c +++ b/x86/access.c @@ -1107,27 +1107,43 @@ static int check_write_cr0wp(ac_pt_env_t *pt_env) * We load CR0.WP with the inverse value of what would be used during * the access test and toggle EFER.NX to flush and rebuild the current * MMU context based on that value. + * + * This used to trigger a bug in the emulator we try to test via FEP. */ + for (;;) { + const char *fep = (at.flags & AC_FEP_MASK) ? "FEP " : ""; - set_cr0_wp(1); - set_efer_nx(1); - set_efer_nx(0); + set_cr0_wp(1); + set_efer_nx(1); + set_efer_nx(0); - if (!ac_test_do_access(&at)) { - printf("%s: CR0.WP=0 r/o write fail\n", __FUNCTION__); - err++; - } + if (!ac_test_do_access(&at)) { + printf("%s: %sCR0.WP=0 r/o write fail\n", __FUNCTION__, fep); + err++; + } - at.flags |= AC_CPU_CR0_WP_MASK; - __ac_set_expected_status(&at, false); + at.flags |= AC_CPU_CR0_WP_MASK; + __ac_set_expected_status(&at, false); - set_cr0_wp(0); - set_efer_nx(1); - set_efer_nx(0); + set_cr0_wp(0); + set_efer_nx(1); + set_efer_nx(0); - if (!ac_test_do_access(&at)) { - printf("%s: CR0.WP=1 r/o write deny fail\n", __FUNCTION__); - err++; + if (!ac_test_do_access(&at)) { + printf("%s: %sCR0.WP=1 r/o write deny fail\n", __FUNCTION__, fep); + err++; + } + + if (!fep_available) + break; + + if (at.flags & AC_FEP_MASK) + break; + + /* Re-test via the emulator */ + at.flags |= AC_FEP_MASK; + at.flags ^= AC_CPU_CR0_WP_MASK; + __ac_set_expected_status(&at, false); } return err == 0; -- 2.39.2