Use MMIO to force KVM to emulate the flds isntruction in emulator_error_test, rather than relying on KVM_CAP_SMALLER_MAXPHYADDR. KVM_CAP_SMALLER_MAXPHYADDR is not enabled by default when TDP is enabled. So developers that run all selftests against KVM in its default configuration do not get test coverage of KVM_CAP_EXIT_ON_EMULATION_FAILURE. When TDP is disabled, KVM_CAP_SMALLER_MAXPHYADDR is enabled by default, but emulator_error_test actually fails because KVM does not need to emulate flds. i.e. The test fails to induce and emulation failure. Fixes: 39bbcc3a4e39 ("selftests: kvm: Allows userspace to handle emulation errors.") Signed-off-by: David Matlack <dmatlack@xxxxxxxxxx> --- .../kvm/x86_64/emulator_error_test.c | 36 ++++++------------- 1 file changed, 10 insertions(+), 26 deletions(-) diff --git a/tools/testing/selftests/kvm/x86_64/emulator_error_test.c b/tools/testing/selftests/kvm/x86_64/emulator_error_test.c index 236e11755ba6..2dff57991d31 100644 --- a/tools/testing/selftests/kvm/x86_64/emulator_error_test.c +++ b/tools/testing/selftests/kvm/x86_64/emulator_error_test.c @@ -11,18 +11,12 @@ #include "kvm_util.h" #include "vmx.h" -#define MAXPHYADDR 36 - -#define MEM_REGION_GVA 0x0000123456789000 -#define MEM_REGION_GPA 0x0000000700000000 -#define MEM_REGION_SLOT 10 -#define MEM_REGION_SIZE PAGE_SIZE +#define MMIO_REGION_GPA 0x700000000 +#define MMIO_REGION_GVA 0x700000000 static void guest_code(void) { - __asm__ __volatile__("flds (%[addr])" - :: [addr]"r"(MEM_REGION_GVA)); - + __asm__ __volatile__("flds (%[addr])" :: [addr]"r"(MMIO_REGION_GVA)); GUEST_DONE(); } @@ -152,34 +146,24 @@ int main(int argc, char *argv[]) { struct kvm_vcpu *vcpu; struct kvm_vm *vm; - uint64_t gpa, pte; - uint64_t *hva; int rc; /* Tell stdout not to buffer its content */ setbuf(stdout, NULL); - TEST_REQUIRE(kvm_has_cap(KVM_CAP_SMALLER_MAXPHYADDR)); - vm = vm_create_with_one_vcpu(&vcpu, guest_code); - vcpu_set_cpuid_maxphyaddr(vcpu, MAXPHYADDR); - rc = kvm_check_cap(KVM_CAP_EXIT_ON_EMULATION_FAILURE); TEST_ASSERT(rc, "KVM_CAP_EXIT_ON_EMULATION_FAILURE is unavailable"); vm_enable_cap(vm, KVM_CAP_EXIT_ON_EMULATION_FAILURE, 1); - vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, - MEM_REGION_GPA, MEM_REGION_SLOT, - MEM_REGION_SIZE / PAGE_SIZE, 0); - gpa = vm_phy_pages_alloc(vm, MEM_REGION_SIZE / PAGE_SIZE, - MEM_REGION_GPA, MEM_REGION_SLOT); - TEST_ASSERT(gpa == MEM_REGION_GPA, "Failed vm_phy_pages_alloc\n"); - virt_map(vm, MEM_REGION_GVA, MEM_REGION_GPA, 1); - hva = addr_gpa2hva(vm, MEM_REGION_GPA); - memset(hva, 0, PAGE_SIZE); - pte = vm_get_page_table_entry(vm, vcpu, MEM_REGION_GVA); - vm_set_page_table_entry(vm, vcpu, MEM_REGION_GVA, pte | (1ull << 36)); + /* + * Create a virtual mapping so the guest can access MMIO_REGION_GPA. + * MMIO_REGION_GPA is not mapped by a memslot so KVM will treat the + * access as MMIO and attempt to emulate the flds instruction, which + * will then generate an emulation error. + */ + virt_map(vm, MMIO_REGION_GVA, MMIO_REGION_GPA, 1); vcpu_run(vcpu); process_exit_on_emulation_error(vcpu); -- 2.38.0.rc1.362.ged0d419d3c-goog