| @@ -237,6 +237,11 @@ static void guest_check_s1ptw_wr_in_dirty_log(void) · 236 unmodified lines |
| 237 | GUEST_SYNC(CMD_CHECK_S1PTW_WR_IN_DIRTY_LOG); | 237 | GUEST_SYNC(CMD_CHECK_S1PTW_WR_IN_DIRTY_LOG); |
| 238 | } | 238 | } |
| 239 | | 239 | |
| | 240 | static void guest_check_no_s1ptw_wr_in_dirty_log(void) |
| | 241 | { |
| | 242 | GUEST_SYNC(CMD_CHECK_NO_S1PTW_WR_IN_DIRTY_LOG); |
| | 243 | } |
| | 244 | |
| 240 | static void guest_exec(void) | 245 | static void guest_exec(void) |
| 241 | { | 246 | { |
| 242 | int (*code)(void) = (int (*)(void))TEST_EXEC_GVA; | 247 | int (*code)(void) = (int (*)(void))TEST_EXEC_GVA; |
| @@ -304,7 +309,7 @@ static struct uffd_args { · 61 unmodified lines |
| 304 | | 309 | |
| 305 | /* Returns true to continue the test, and false if it should be skipped. */ | 310 | /* Returns true to continue the test, and false if it should be skipped. */ |
| 306 | static int uffd_generic_handler(int uffd_mode, int uffd, struct uffd_msg *msg, | 311 | static int uffd_generic_handler(int uffd_mode, int uffd, struct uffd_msg *msg, |
| 307 | struct uffd_args *args, bool expect_write) | 312 | struct uffd_args *args) |
| 308 | { | 313 | { |
| 309 | uint64_t addr = msg->arg.pagefault.address; | 314 | uint64_t addr = msg->arg.pagefault.address; |
| 310 | uint64_t flags = msg->arg.pagefault.flags; | 315 | uint64_t flags = msg->arg.pagefault.flags; |
| @@ -313,7 +318,6 @@ static int uffd_generic_handler(int uffd_mode, int uffd, struct uffd_msg *msg, · 2 unmodified lines |
| 313 | | 318 | |
| 314 | TEST_ASSERT(uffd_mode == UFFDIO_REGISTER_MODE_MISSING, | 319 | TEST_ASSERT(uffd_mode == UFFDIO_REGISTER_MODE_MISSING, |
| 315 | "The only expected UFFD mode is MISSING"); | 320 | "The only expected UFFD mode is MISSING"); |
| 316 | ASSERT_EQ(!!(flags & UFFD_PAGEFAULT_FLAG_WRITE), expect_write); | | |
| 317 | ASSERT_EQ(addr, (uint64_t)args->hva); | 321 | ASSERT_EQ(addr, (uint64_t)args->hva); |
| 318 | | 322 | |
| 319 | pr_debug("uffd fault: addr=%p write=%d\n", | 323 | pr_debug("uffd fault: addr=%p write=%d\n", |
| @@ -337,19 +341,14 @@ static int uffd_generic_handler(int uffd_mode, int uffd, struct uffd_msg *msg, · 17 unmodified lines |
| 337 | return 0; | 341 | return 0; |
| 338 | } | 342 | } |
| 339 | | 343 | |
| 340 | static int uffd_pt_write_handler(int mode, int uffd, struct uffd_msg *msg) | 344 | static int uffd_pt_handler(int mode, int uffd, struct uffd_msg *msg) |
| 341 | { | | |
| 342 | return uffd_generic_handler(mode, uffd, msg, &pt_args, true); | | |
| 343 | } | | |
| 344 | | | |
| 345 | static int uffd_data_write_handler(int mode, int uffd, struct uffd_msg *msg) | | |
| 346 | { | 345 | { |
| 347 | return uffd_generic_handler(mode, uffd, msg, &data_args, true); | 346 | return uffd_generic_handler(mode, uffd, msg, &pt_args); |
| 348 | } | 347 | } |
| 349 | | 348 | |
| 350 | static int uffd_data_read_handler(int mode, int uffd, struct uffd_msg *msg) | 349 | static int uffd_data_handler(int mode, int uffd, struct uffd_msg *msg) |
| 351 | { | 350 | { |
| 352 | return uffd_generic_handler(mode, uffd, msg, &data_args, false); | 351 | return uffd_generic_handler(mode, uffd, msg, &data_args); |
| 353 | } | 352 | } |
| 354 | | 353 | |
| 355 | static void setup_uffd_args(struct userspace_mem_region *region, | 354 | static void setup_uffd_args(struct userspace_mem_region *region, |
| @@ -471,9 +470,12 @@ static bool handle_cmd(struct kvm_vm *vm, int cmd) · 115 unmodified lines |
| 471 | { | 470 | { |
| 472 | struct userspace_mem_region *data_region, *pt_region; | 471 | struct userspace_mem_region *data_region, *pt_region; |
| 473 | bool continue_test = true; | 472 | bool continue_test = true; |
| | 473 | uint64_t pte_gpa, pte_pg; |
| 474 | | 474 | |
| 475 | data_region = vm_get_mem_region(vm, MEM_REGION_TEST_DATA); | 475 | data_region = vm_get_mem_region(vm, MEM_REGION_TEST_DATA); |
| 476 | pt_region = vm_get_mem_region(vm, MEM_REGION_PT); | 476 | pt_region = vm_get_mem_region(vm, MEM_REGION_PT); |
| | 477 | pte_gpa = addr_hva2gpa(vm, virt_get_pte_hva(vm, TEST_GVA)); |
| | 478 | pte_pg = (pte_gpa - pt_region->region.guest_phys_addr) / getpagesize(); |
| 477 | | 479 | |
| 478 | if (cmd == CMD_SKIP_TEST) | 480 | if (cmd == CMD_SKIP_TEST) |
| 479 | continue_test = false; | 481 | continue_test = false; |
| @@ -486,13 +488,13 @@ static bool handle_cmd(struct kvm_vm *vm, int cmd) · 6 unmodified lines |
| 486 | TEST_ASSERT(check_write_in_dirty_log(vm, data_region, 0), | 488 | TEST_ASSERT(check_write_in_dirty_log(vm, data_region, 0), |
| 487 | "Missing write in dirty log"); | 489 | "Missing write in dirty log"); |
| 488 | if (cmd & CMD_CHECK_S1PTW_WR_IN_DIRTY_LOG) | 490 | if (cmd & CMD_CHECK_S1PTW_WR_IN_DIRTY_LOG) |
| 489 | TEST_ASSERT(check_write_in_dirty_log(vm, pt_region, 0), | 491 | TEST_ASSERT(check_write_in_dirty_log(vm, pt_region, pte_pg), |
| 490 | "Missing s1ptw write in dirty log"); | 492 | "Missing s1ptw write in dirty log"); |
| 491 | if (cmd & CMD_CHECK_NO_WRITE_IN_DIRTY_LOG) | 493 | if (cmd & CMD_CHECK_NO_WRITE_IN_DIRTY_LOG) |
| 492 | TEST_ASSERT(!check_write_in_dirty_log(vm, data_region, 0), | 494 | TEST_ASSERT(!check_write_in_dirty_log(vm, data_region, 0), |
| 493 | "Unexpected write in dirty log"); | 495 | "Unexpected write in dirty log"); |
| 494 | if (cmd & CMD_CHECK_NO_S1PTW_WR_IN_DIRTY_LOG) | 496 | if (cmd & CMD_CHECK_NO_S1PTW_WR_IN_DIRTY_LOG) |
| 495 | TEST_ASSERT(!check_write_in_dirty_log(vm, pt_region, 0), | 497 | TEST_ASSERT(!check_write_in_dirty_log(vm, pt_region, pte_pg), |
| 496 | "Unexpected s1ptw write in dirty log"); | 498 | "Unexpected s1ptw write in dirty log"); |
| 497 | | 499 | |
| 498 | return continue_test; | 500 | return continue_test; |
| @@ -797,7 +799,7 @@ static void help(char *name) · 298 unmodified lines |
| 797 | .expected_events = { .uffd_faults = _uffd_faults, }, \ | 799 | .expected_events = { .uffd_faults = _uffd_faults, }, \ |
| 798 | } | 800 | } |
| 799 | | 801 | |
| 800 | #define TEST_DIRTY_LOG(_access, _with_af, _test_check) \ | 802 | #define TEST_DIRTY_LOG(_access, _with_af, _test_check, _pt_check) \ |
| 801 | { \ | 803 | { \ |
| 802 | .name = SCAT3(dirty_log, _access, _with_af), \ | 804 | .name = SCAT3(dirty_log, _access, _with_af), \ |
| 803 | .data_memslot_flags = KVM_MEM_LOG_DIRTY_PAGES, \ | 805 | .data_memslot_flags = KVM_MEM_LOG_DIRTY_PAGES, \ |
| @@ -805,13 +807,12 @@ static void help(char *name) · 1 unmodified line |
| 805 | .guest_prepare = { _PREPARE(_with_af), \ | 807 | .guest_prepare = { _PREPARE(_with_af), \ |
| 806 | _PREPARE(_access) }, \ | 808 | _PREPARE(_access) }, \ |
| 807 | .guest_test = _access, \ | 809 | .guest_test = _access, \ |
| 808 | .guest_test_check = { _CHECK(_with_af), _test_check, \ | 810 | .guest_test_check = { _CHECK(_with_af), _test_check, _pt_check }, \ |
| 809 | guest_check_s1ptw_wr_in_dirty_log}, \ | | |
| 810 | .expected_events = { 0 }, \ | 811 | .expected_events = { 0 }, \ |
| 811 | } | 812 | } |
| 812 | | 813 | |
| 813 | #define TEST_UFFD_AND_DIRTY_LOG(_access, _with_af, _uffd_data_handler, \ | 814 | #define TEST_UFFD_AND_DIRTY_LOG(_access, _with_af, _uffd_data_handler, \ |
| 814 | _uffd_faults, _test_check) \ | 815 | _uffd_faults, _test_check, _pt_check) \ |
| 815 | { \ | 816 | { \ |
| 816 | .name = SCAT3(uffd_and_dirty_log, _access, _with_af), \ | 817 | .name = SCAT3(uffd_and_dirty_log, _access, _with_af), \ |
| 817 | .data_memslot_flags = KVM_MEM_LOG_DIRTY_PAGES, \ | 818 | .data_memslot_flags = KVM_MEM_LOG_DIRTY_PAGES, \ |
| @@ -820,16 +821,17 @@ static void help(char *name) · 2 unmodified lines |
| 820 | _PREPARE(_access) }, \ | 821 | _PREPARE(_access) }, \ |
| 821 | .guest_test = _access, \ | 822 | .guest_test = _access, \ |
| 822 | .mem_mark_cmd = CMD_HOLE_DATA | CMD_HOLE_PT, \ | 823 | .mem_mark_cmd = CMD_HOLE_DATA | CMD_HOLE_PT, \ |
| 823 | .guest_test_check = { _CHECK(_with_af), _test_check }, \ | 824 | .guest_test_check = { _CHECK(_with_af), _test_check, _pt_check }, \ |
| 824 | .uffd_data_handler = _uffd_data_handler, \ | 825 | .uffd_data_handler = _uffd_data_handler, \ |
| 825 | .uffd_pt_handler = uffd_pt_write_handler, \ | 826 | .uffd_pt_handler = uffd_pt_handler, \ |
| 826 | .expected_events = { .uffd_faults = _uffd_faults, }, \ | 827 | .expected_events = { .uffd_faults = _uffd_faults, }, \ |
| 827 | } | 828 | } |
| 828 | | 829 | |
| 829 | #define TEST_RO_MEMSLOT(_access, _mmio_handler, _mmio_exits) \ | 830 | #define TEST_RO_MEMSLOT(_access, _mmio_handler, _mmio_exits) \ |
| 830 | { \ | 831 | { \ |
| 831 | .name = SCAT3(ro_memslot, _access, _with_af), \ | 832 | .name = SCAT2(ro_memslot, _access), \ |
| 832 | .data_memslot_flags = KVM_MEM_READONLY, \ | 833 | .data_memslot_flags = KVM_MEM_READONLY, \ |
| | 834 | .pt_memslot_flags = KVM_MEM_READONLY, \ |
| 833 | .guest_prepare = { _PREPARE(_access) }, \ | 835 | .guest_prepare = { _PREPARE(_access) }, \ |
| 834 | .guest_test = _access, \ | 836 | .guest_test = _access, \ |
| 835 | .mmio_handler = _mmio_handler, \ | 837 | .mmio_handler = _mmio_handler, \ |
| @@ -840,6 +842,7 @@ static void help(char *name) · 4 unmodified lines |
| 840 | { \ | 842 | { \ |
| 841 | .name = SCAT2(ro_memslot_no_syndrome, _access), \ | 843 | .name = SCAT2(ro_memslot_no_syndrome, _access), \ |
| 842 | .data_memslot_flags = KVM_MEM_READONLY, \ | 844 | .data_memslot_flags = KVM_MEM_READONLY, \ |
| | 845 | .pt_memslot_flags = KVM_MEM_READONLY, \ |
| 843 | .guest_test = _access, \ | 846 | .guest_test = _access, \ |
| 844 | .fail_vcpu_run_handler = fail_vcpu_run_mmio_no_syndrome_handler, \ | 847 | .fail_vcpu_run_handler = fail_vcpu_run_mmio_no_syndrome_handler, \ |
| 845 | .expected_events = { .fail_vcpu_runs = 1 }, \ | 848 | .expected_events = { .fail_vcpu_runs = 1 }, \ |
| @@ -848,9 +851,9 @@ static void help(char *name) · 2 unmodified lines |
| 848 | #define TEST_RO_MEMSLOT_AND_DIRTY_LOG(_access, _mmio_handler, _mmio_exits, \ | 851 | #define TEST_RO_MEMSLOT_AND_DIRTY_LOG(_access, _mmio_handler, _mmio_exits, \ |
| 849 | _test_check) \ | 852 | _test_check) \ |
| 850 | { \ | 853 | { \ |
| 851 | .name = SCAT3(ro_memslot, _access, _with_af), \ | 854 | .name = SCAT2(ro_memslot, _access), \ |
| 852 | .data_memslot_flags = KVM_MEM_READONLY | KVM_MEM_LOG_DIRTY_PAGES, \ | 855 | .data_memslot_flags = KVM_MEM_READONLY | KVM_MEM_LOG_DIRTY_PAGES, \ |
| 853 | .pt_memslot_flags = KVM_MEM_LOG_DIRTY_PAGES, \ | 856 | .pt_memslot_flags = KVM_MEM_READONLY | KVM_MEM_LOG_DIRTY_PAGES, \ |
| 854 | .guest_prepare = { _PREPARE(_access) }, \ | 857 | .guest_prepare = { _PREPARE(_access) }, \ |
| 855 | .guest_test = _access, \ | 858 | .guest_test = _access, \ |
| 856 | .guest_test_check = { _test_check }, \ | 859 | .guest_test_check = { _test_check }, \ |
| @@ -862,7 +865,7 @@ static void help(char *name) · 5 unmodified lines |
| 862 | { \ | 865 | { \ |
| 863 | .name = SCAT2(ro_memslot_no_syn_and_dlog, _access), \ | 866 | .name = SCAT2(ro_memslot_no_syn_and_dlog, _access), \ |
| 864 | .data_memslot_flags = KVM_MEM_READONLY | KVM_MEM_LOG_DIRTY_PAGES, \ | 867 | .data_memslot_flags = KVM_MEM_READONLY | KVM_MEM_LOG_DIRTY_PAGES, \ |
| 865 | .pt_memslot_flags = KVM_MEM_LOG_DIRTY_PAGES, \ | 868 | .pt_memslot_flags = KVM_MEM_READONLY | KVM_MEM_LOG_DIRTY_PAGES, \ |
| 866 | .guest_test = _access, \ | 869 | .guest_test = _access, \ |
| 867 | .guest_test_check = { _test_check }, \ | 870 | .guest_test_check = { _test_check }, \ |
| 868 | .fail_vcpu_run_handler = fail_vcpu_run_mmio_no_syndrome_handler, \ | 871 | .fail_vcpu_run_handler = fail_vcpu_run_mmio_no_syndrome_handler, \ |
| @@ -874,11 +877,12 @@ static void help(char *name) · 5 unmodified lines |
| 874 | { \ | 877 | { \ |
| 875 | .name = SCAT2(ro_memslot_uffd, _access), \ | 878 | .name = SCAT2(ro_memslot_uffd, _access), \ |
| 876 | .data_memslot_flags = KVM_MEM_READONLY, \ | 879 | .data_memslot_flags = KVM_MEM_READONLY, \ |
| | 880 | .pt_memslot_flags = KVM_MEM_READONLY, \ |
| 877 | .mem_mark_cmd = CMD_HOLE_DATA | CMD_HOLE_PT, \ | 881 | .mem_mark_cmd = CMD_HOLE_DATA | CMD_HOLE_PT, \ |
| 878 | .guest_prepare = { _PREPARE(_access) }, \ | 882 | .guest_prepare = { _PREPARE(_access) }, \ |
| 879 | .guest_test = _access, \ | 883 | .guest_test = _access, \ |
| 880 | .uffd_data_handler = _uffd_data_handler, \ | 884 | .uffd_data_handler = _uffd_data_handler, \ |
| 881 | .uffd_pt_handler = uffd_pt_write_handler, \ | 885 | .uffd_pt_handler = uffd_pt_handler, \ |
| 882 | .mmio_handler = _mmio_handler, \ | 886 | .mmio_handler = _mmio_handler, \ |
| 883 | .expected_events = { .mmio_exits = _mmio_exits, \ | 887 | .expected_events = { .mmio_exits = _mmio_exits, \ |
| 884 | .uffd_faults = _uffd_faults }, \ | 888 | .uffd_faults = _uffd_faults }, \ |
| @@ -889,10 +893,11 @@ static void help(char *name) · 4 unmodified lines |
| 889 | { \ | 893 | { \ |
| 890 | .name = SCAT2(ro_memslot_no_syndrome, _access), \ | 894 | .name = SCAT2(ro_memslot_no_syndrome, _access), \ |
| 891 | .data_memslot_flags = KVM_MEM_READONLY, \ | 895 | .data_memslot_flags = KVM_MEM_READONLY, \ |
| | 896 | .pt_memslot_flags = KVM_MEM_READONLY, \ |
| 892 | .mem_mark_cmd = CMD_HOLE_DATA | CMD_HOLE_PT, \ | 897 | .mem_mark_cmd = CMD_HOLE_DATA | CMD_HOLE_PT, \ |
| 893 | .guest_test = _access, \ | 898 | .guest_test = _access, \ |
| 894 | .uffd_data_handler = _uffd_data_handler, \ | 899 | .uffd_data_handler = _uffd_data_handler, \ |
| 895 | .uffd_pt_handler = uffd_pt_write_handler, \ | 900 | .uffd_pt_handler = uffd_pt_handler, \ |
| 896 | .fail_vcpu_run_handler = fail_vcpu_run_mmio_no_syndrome_handler, \ | 901 | .fail_vcpu_run_handler = fail_vcpu_run_mmio_no_syndrome_handler, \ |
| 897 | .expected_events = { .fail_vcpu_runs = 1, \ | 902 | .expected_events = { .fail_vcpu_runs = 1, \ |
| 898 | .uffd_faults = _uffd_faults }, \ | 903 | .uffd_faults = _uffd_faults }, \ |
| @@ -933,44 +938,51 @@ static struct test_desc tests[] = { · 34 unmodified lines |
| 933 | * (S1PTW). | 938 | * (S1PTW). |
| 934 | */ | 939 | */ |
| 935 | TEST_UFFD(guest_read64, with_af, CMD_HOLE_DATA | CMD_HOLE_PT, | 940 | TEST_UFFD(guest_read64, with_af, CMD_HOLE_DATA | CMD_HOLE_PT, |
| 936 | uffd_data_read_handler, uffd_pt_write_handler, 2), | 941 | uffd_data_handler, uffd_pt_handler, 2), |
| 937 | /* no_af should also lead to a PT write. */ | | |
| 938 | TEST_UFFD(guest_read64, no_af, CMD_HOLE_DATA | CMD_HOLE_PT, | 942 | TEST_UFFD(guest_read64, no_af, CMD_HOLE_DATA | CMD_HOLE_PT, |
| 939 | uffd_data_read_handler, uffd_pt_write_handler, 2), | 943 | uffd_data_handler, uffd_pt_handler, 2), |
| 940 | /* Note how that cas invokes the read handler. */ | | |
| 941 | TEST_UFFD(guest_cas, with_af, CMD_HOLE_DATA | CMD_HOLE_PT, | 944 | TEST_UFFD(guest_cas, with_af, CMD_HOLE_DATA | CMD_HOLE_PT, |
| 942 | uffd_data_read_handler, uffd_pt_write_handler, 2), | 945 | uffd_data_handler, uffd_pt_handler, 2), |
| 943 | /* | 946 | /* |
| 944 | * Can't test guest_at with_af as it's IMPDEF whether the AF is set. | 947 | * Can't test guest_at with_af as it's IMPDEF whether the AF is set. |
| 945 | * The S1PTW fault should still be marked as a write. | 948 | * The S1PTW fault should still be marked as a write. |
| 946 | */ | 949 | */ |
| 947 | TEST_UFFD(guest_at, no_af, CMD_HOLE_DATA | CMD_HOLE_PT, | 950 | TEST_UFFD(guest_at, no_af, CMD_HOLE_DATA | CMD_HOLE_PT, |
| 948 | uffd_data_read_handler, uffd_pt_write_handler, 1), | 951 | uffd_no_handler, uffd_pt_handler, 1), |
| 949 | TEST_UFFD(guest_ld_preidx, with_af, CMD_HOLE_DATA | CMD_HOLE_PT, | 952 | TEST_UFFD(guest_ld_preidx, with_af, CMD_HOLE_DATA | CMD_HOLE_PT, |
| 950 | uffd_data_read_handler, uffd_pt_write_handler, 2), | 953 | uffd_data_handler, uffd_pt_handler, 2), |
| 951 | TEST_UFFD(guest_write64, with_af, CMD_HOLE_DATA | CMD_HOLE_PT, | 954 | TEST_UFFD(guest_write64, with_af, CMD_HOLE_DATA | CMD_HOLE_PT, |
| 952 | uffd_data_write_handler, uffd_pt_write_handler, 2), | 955 | uffd_data_handler, uffd_pt_handler, 2), |
| 953 | TEST_UFFD(guest_dc_zva, with_af, CMD_HOLE_DATA | CMD_HOLE_PT, | 956 | TEST_UFFD(guest_dc_zva, with_af, CMD_HOLE_DATA | CMD_HOLE_PT, |
| 954 | uffd_data_write_handler, uffd_pt_write_handler, 2), | 957 | uffd_data_handler, uffd_pt_handler, 2), |
| 955 | TEST_UFFD(guest_st_preidx, with_af, CMD_HOLE_DATA | CMD_HOLE_PT, | 958 | TEST_UFFD(guest_st_preidx, with_af, CMD_HOLE_DATA | CMD_HOLE_PT, |
| 956 | uffd_data_write_handler, uffd_pt_write_handler, 2), | 959 | uffd_data_handler, uffd_pt_handler, 2), |
| 957 | TEST_UFFD(guest_exec, with_af, CMD_HOLE_DATA | CMD_HOLE_PT, | 960 | TEST_UFFD(guest_exec, with_af, CMD_HOLE_DATA | CMD_HOLE_PT, |
| 958 | uffd_data_read_handler, uffd_pt_write_handler, 2), | 961 | uffd_data_handler, uffd_pt_handler, 2), |
| 959 | | 962 | |
| 960 | /* | 963 | /* |
| 961 | * Try accesses when the data and PT memory regions are both | 964 | * Try accesses when the data and PT memory regions are both |
| 962 | * tracked for dirty logging. | 965 | * tracked for dirty logging. |
| 963 | */ | 966 | */ |
| 964 | TEST_DIRTY_LOG(guest_read64, with_af, guest_check_no_write_in_dirty_log), | 967 | TEST_DIRTY_LOG(guest_read64, with_af, guest_check_no_write_in_dirty_log, |
| 965 | /* no_af should also lead to a PT write. */ | 968 | guest_check_s1ptw_wr_in_dirty_log), |
| 966 | TEST_DIRTY_LOG(guest_read64, no_af, guest_check_no_write_in_dirty_log), | 969 | TEST_DIRTY_LOG(guest_read64, no_af, guest_check_no_write_in_dirty_log, |
| 967 | TEST_DIRTY_LOG(guest_ld_preidx, with_af, guest_check_no_write_in_dirty_log), | 970 | guest_check_no_s1ptw_wr_in_dirty_log), |
| 968 | TEST_DIRTY_LOG(guest_at, no_af, guest_check_no_write_in_dirty_log), | 971 | TEST_DIRTY_LOG(guest_ld_preidx, with_af, |
| 969 | TEST_DIRTY_LOG(guest_exec, with_af, guest_check_no_write_in_dirty_log), | 972 | guest_check_no_write_in_dirty_log, |
| 970 | TEST_DIRTY_LOG(guest_write64, with_af, guest_check_write_in_dirty_log), | 973 | guest_check_s1ptw_wr_in_dirty_log), |
| 971 | TEST_DIRTY_LOG(guest_cas, with_af, guest_check_write_in_dirty_log), | 974 | TEST_DIRTY_LOG(guest_at, no_af, guest_check_no_write_in_dirty_log, |
| 972 | TEST_DIRTY_LOG(guest_dc_zva, with_af, guest_check_write_in_dirty_log), | 975 | guest_check_no_s1ptw_wr_in_dirty_log), |
| 973 | TEST_DIRTY_LOG(guest_st_preidx, with_af, guest_check_write_in_dirty_log), | 976 | TEST_DIRTY_LOG(guest_exec, with_af, guest_check_no_write_in_dirty_log, |
| | 977 | guest_check_s1ptw_wr_in_dirty_log), |
| | 978 | TEST_DIRTY_LOG(guest_write64, with_af, guest_check_write_in_dirty_log, |
| | 979 | guest_check_s1ptw_wr_in_dirty_log), |
| | 980 | TEST_DIRTY_LOG(guest_cas, with_af, guest_check_write_in_dirty_log, |
| | 981 | guest_check_s1ptw_wr_in_dirty_log), |
| | 982 | TEST_DIRTY_LOG(guest_dc_zva, with_af, guest_check_write_in_dirty_log, |
| | 983 | guest_check_s1ptw_wr_in_dirty_log), |
| | 984 | TEST_DIRTY_LOG(guest_st_preidx, with_af, guest_check_write_in_dirty_log, |
| | 985 | guest_check_s1ptw_wr_in_dirty_log), |
| 974 | | 986 | |
| 975 | /* | 987 | /* |
| 976 | * Access when the data and PT memory regions are both marked for | 988 | * Access when the data and PT memory regions are both marked for |
| @@ -980,29 +992,43 @@ static struct test_desc tests[] = { · 3 unmodified lines |
| 980 | * fault, and nothing in the dirty log. Any S1PTW should result in | 992 | * fault, and nothing in the dirty log. Any S1PTW should result in |
| 981 | * a write in the dirty log and a userfaultfd write. | 993 | * a write in the dirty log and a userfaultfd write. |
| 982 | */ | 994 | */ |
| 983 | TEST_UFFD_AND_DIRTY_LOG(guest_read64, with_af, uffd_data_read_handler, 2, | 995 | TEST_UFFD_AND_DIRTY_LOG(guest_read64, with_af, |
| 984 | guest_check_no_write_in_dirty_log), | 996 | uffd_data_handler, 2, |
| 985 | /* no_af should also lead to a PT write. */ | 997 | guest_check_no_write_in_dirty_log, |
| 986 | TEST_UFFD_AND_DIRTY_LOG(guest_read64, no_af, uffd_data_read_handler, 2, | 998 | guest_check_s1ptw_wr_in_dirty_log), |
| 987 | guest_check_no_write_in_dirty_log), | 999 | TEST_UFFD_AND_DIRTY_LOG(guest_read64, no_af, |
| 988 | TEST_UFFD_AND_DIRTY_LOG(guest_ld_preidx, with_af, uffd_data_read_handler, | 1000 | uffd_data_handler, 2, |
| 989 | 2, guest_check_no_write_in_dirty_log), | 1001 | guest_check_no_write_in_dirty_log, |
| 990 | TEST_UFFD_AND_DIRTY_LOG(guest_at, with_af, 0, 1, | 1002 | guest_check_no_s1ptw_wr_in_dirty_log), |
| 991 | guest_check_no_write_in_dirty_log), | 1003 | TEST_UFFD_AND_DIRTY_LOG(guest_ld_preidx, with_af, |
| 992 | TEST_UFFD_AND_DIRTY_LOG(guest_exec, with_af, uffd_data_read_handler, 2, | 1004 | uffd_data_handler, |
| 993 | guest_check_no_write_in_dirty_log), | 1005 | 2, guest_check_no_write_in_dirty_log, |
| 994 | TEST_UFFD_AND_DIRTY_LOG(guest_write64, with_af, uffd_data_write_handler, | 1006 | guest_check_s1ptw_wr_in_dirty_log), |
| 995 | 2, guest_check_write_in_dirty_log), | 1007 | TEST_UFFD_AND_DIRTY_LOG(guest_at, with_af, uffd_no_handler, 1, |
| 996 | TEST_UFFD_AND_DIRTY_LOG(guest_cas, with_af, uffd_data_read_handler, 2, | 1008 | guest_check_no_write_in_dirty_log, |
| 997 | guest_check_write_in_dirty_log), | 1009 | guest_check_s1ptw_wr_in_dirty_log), |
| 998 | TEST_UFFD_AND_DIRTY_LOG(guest_dc_zva, with_af, uffd_data_write_handler, | 1010 | TEST_UFFD_AND_DIRTY_LOG(guest_exec, with_af, |
| 999 | 2, guest_check_write_in_dirty_log), | 1011 | uffd_data_handler, 2, |
| | 1012 | guest_check_no_write_in_dirty_log, |
| | 1013 | guest_check_s1ptw_wr_in_dirty_log), |
| | 1014 | TEST_UFFD_AND_DIRTY_LOG(guest_write64, with_af, |
| | 1015 | uffd_data_handler, |
| | 1016 | 2, guest_check_write_in_dirty_log, |
| | 1017 | guest_check_s1ptw_wr_in_dirty_log), |
| | 1018 | TEST_UFFD_AND_DIRTY_LOG(guest_cas, with_af, |
| | 1019 | uffd_data_handler, 2, |
| | 1020 | guest_check_write_in_dirty_log, |
| | 1021 | guest_check_s1ptw_wr_in_dirty_log), |
| | 1022 | TEST_UFFD_AND_DIRTY_LOG(guest_dc_zva, with_af, |
| | 1023 | uffd_data_handler, |
| | 1024 | 2, guest_check_write_in_dirty_log, |
| | 1025 | guest_check_s1ptw_wr_in_dirty_log), |
| 1000 | TEST_UFFD_AND_DIRTY_LOG(guest_st_preidx, with_af, | 1026 | TEST_UFFD_AND_DIRTY_LOG(guest_st_preidx, with_af, |
| 1001 | uffd_data_write_handler, 2, | 1027 | uffd_data_handler, 2, |
| 1002 | guest_check_write_in_dirty_log), | 1028 | guest_check_write_in_dirty_log, |
| 1003 | | 1029 | guest_check_s1ptw_wr_in_dirty_log), |
| 1004 | /* | 1030 | /* |
| 1005 | * Try accesses when the data memory region is marked read-only | 1031 | * Access when both the PT and data regions are marked read-only |
| 1006 | * (with KVM_MEM_READONLY). Writes with a syndrome result in an | 1032 | * (with KVM_MEM_READONLY). Writes with a syndrome result in an |
| 1007 | * MMIO exit, writes with no syndrome (e.g., CAS) result in a | 1033 | * MMIO exit, writes with no syndrome (e.g., CAS) result in a |
| 1008 | * failed vcpu run, and reads/execs with and without syndroms do | 1034 | * failed vcpu run, and reads/execs with and without syndroms do |
| @@ -1018,7 +1044,7 @@ static struct test_desc tests[] = { · 9 unmodified lines |
| 1018 | TEST_RO_MEMSLOT_NO_SYNDROME(guest_st_preidx), | 1044 | TEST_RO_MEMSLOT_NO_SYNDROME(guest_st_preidx), |
| 1019 | | 1045 | |
| 1020 | /* | 1046 | /* |
| 1021 | * Access when both the data region is both read-only and marked | 1047 | * The PT and data regions are both read-only and marked |
| 1022 | * for dirty logging at the same time. The expected result is that | 1048 | * for dirty logging at the same time. The expected result is that |
| 1023 | * for writes there should be no write in the dirty log. The | 1049 | * for writes there should be no write in the dirty log. The |
| 1024 | * readonly handling is the same as if the memslot was not marked | 1050 | * readonly handling is the same as if the memslot was not marked |
| @@ -1043,7 +1069,7 @@ static struct test_desc tests[] = { · 18 unmodified lines |
| 1043 | guest_check_no_write_in_dirty_log), | 1069 | guest_check_no_write_in_dirty_log), |
| 1044 | | 1070 | |
| 1045 | /* | 1071 | /* |
| 1046 | * Access when the data region is both read-only and punched with | 1072 | * The PT and data regions are both read-only and punched with |
| 1047 | * holes tracked with userfaultfd. The expected result is the | 1073 | * holes tracked with userfaultfd. The expected result is the |
| 1048 | * union of both userfaultfd and read-only behaviors. For example, | 1074 | * union of both userfaultfd and read-only behaviors. For example, |
| 1049 | * write accesses result in a userfaultfd write fault and an MMIO | 1075 | * write accesses result in a userfaultfd write fault and an MMIO |
| @@ -1051,22 +1077,15 @@ static struct test_desc tests[] = { · 1 unmodified line |
| 1051 | * no userfaultfd write fault. Reads result in userfaultfd getting | 1077 | * no userfaultfd write fault. Reads result in userfaultfd getting |
| 1052 | * triggered. | 1078 | * triggered. |
| 1053 | */ | 1079 | */ |
| 1054 | TEST_RO_MEMSLOT_AND_UFFD(guest_read64, 0, 0, | 1080 | TEST_RO_MEMSLOT_AND_UFFD(guest_read64, 0, 0, uffd_data_handler, 2), |
| 1055 | uffd_data_read_handler, 2), | 1081 | TEST_RO_MEMSLOT_AND_UFFD(guest_ld_preidx, 0, 0, uffd_data_handler, 2), |
| 1056 | TEST_RO_MEMSLOT_AND_UFFD(guest_ld_preidx, 0, 0, | 1082 | TEST_RO_MEMSLOT_AND_UFFD(guest_at, 0, 0, uffd_no_handler, 1), |
| 1057 | uffd_data_read_handler, 2), | 1083 | TEST_RO_MEMSLOT_AND_UFFD(guest_exec, 0, 0, uffd_data_handler, 2), |
| 1058 | TEST_RO_MEMSLOT_AND_UFFD(guest_at, 0, 0, | | |
| 1059 | uffd_no_handler, 1), | | |
| 1060 | TEST_RO_MEMSLOT_AND_UFFD(guest_exec, 0, 0, | | |
| 1061 | uffd_data_read_handler, 2), | | |
| 1062 | TEST_RO_MEMSLOT_AND_UFFD(guest_write64, mmio_on_test_gpa_handler, 1, | 1084 | TEST_RO_MEMSLOT_AND_UFFD(guest_write64, mmio_on_test_gpa_handler, 1, |
| 1063 | uffd_data_write_handler, 2), | 1085 | uffd_data_handler, 2), |
| 1064 | TEST_RO_MEMSLOT_NO_SYNDROME_AND_UFFD(guest_cas, | 1086 | TEST_RO_MEMSLOT_NO_SYNDROME_AND_UFFD(guest_cas, uffd_data_handler, 2), |
| 1065 | uffd_data_read_handler, 2), | 1087 | TEST_RO_MEMSLOT_NO_SYNDROME_AND_UFFD(guest_dc_zva, uffd_no_handler, 1), |
| 1066 | TEST_RO_MEMSLOT_NO_SYNDROME_AND_UFFD(guest_dc_zva, | 1088 | TEST_RO_MEMSLOT_NO_SYNDROME_AND_UFFD(guest_st_preidx, uffd_no_handler, 1), |
| 1067 | uffd_no_handler, 1), | | |
| 1068 | TEST_RO_MEMSLOT_NO_SYNDROME_AND_UFFD(guest_st_preidx, | | |
| 1069 | uffd_no_handler, 1), | | |
| 1070 | | 1089 | |
| 1071 | { 0 } | 1090 | { 0 } |
| 1072 | }; | 1091 | }; |