Extend the read-only memslot tests in page_fault_test to test read-only PT (Page table) memslots. Note that this was not allowed before commit 406504c7b040 ("KVM: arm64: Fix S1PTW handling on RO memslots") as all S1PTW faults were treated as writes which resulted in an (unrecoverable) exception inside the guest.
Unified · Split
| @@ -829,8 +829,9 @@ static void help(char *name) · 828 unmodified lines | |||
| 829 | 829 | ||
| 830 | #define TEST_RO_MEMSLOT(_access, _mmio_handler, _mmio_exits) \ | 830 | #define TEST_RO_MEMSLOT(_access, _mmio_handler, _mmio_exits) \ |
| 831 | { \ | 831 | { \ |
| 832 | .name = SCAT3(ro_memslot, _access, _with_af), \ | 832 | .name = SCAT2(ro_memslot, _access), \ |
| 833 | .data_memslot_flags = KVM_MEM_READONLY, \ | 833 | .data_memslot_flags = KVM_MEM_READONLY, \ |
| 834 | .pt_memslot_flags = KVM_MEM_READONLY, \ | ||
| 834 | .guest_prepare = { _PREPARE(_access) }, \ | 835 | .guest_prepare = { _PREPARE(_access) }, \ |
| 835 | .guest_test = _access, \ | 836 | .guest_test = _access, \ |
| 836 | .mmio_handler = _mmio_handler, \ | 837 | .mmio_handler = _mmio_handler, \ |
| @@ -841,6 +842,7 @@ static void help(char *name) · 4 unmodified lines | |||
| 841 | { \ | 842 | { \ |
| 842 | .name = SCAT2(ro_memslot_no_syndrome, _access), \ | 843 | .name = SCAT2(ro_memslot_no_syndrome, _access), \ |
| 843 | .data_memslot_flags = KVM_MEM_READONLY, \ | 844 | .data_memslot_flags = KVM_MEM_READONLY, \ |
| 845 | .pt_memslot_flags = KVM_MEM_READONLY, \ | ||
| 844 | .guest_test = _access, \ | 846 | .guest_test = _access, \ |
| 845 | .fail_vcpu_run_handler = fail_vcpu_run_mmio_no_syndrome_handler, \ | 847 | .fail_vcpu_run_handler = fail_vcpu_run_mmio_no_syndrome_handler, \ |
| 846 | .expected_events = { .fail_vcpu_runs = 1 }, \ | 848 | .expected_events = { .fail_vcpu_runs = 1 }, \ |
| @@ -849,9 +851,9 @@ static void help(char *name) · 2 unmodified lines | |||
| 849 | #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, \ |
| 850 | _test_check) \ | 852 | _test_check) \ |
| 851 | { \ | 853 | { \ |
| 852 | .name = SCAT3(ro_memslot, _access, _with_af), \ | 854 | .name = SCAT2(ro_memslot, _access), \ |
| 853 | .data_memslot_flags = KVM_MEM_READONLY | KVM_MEM_LOG_DIRTY_PAGES, \ | 855 | .data_memslot_flags = KVM_MEM_READONLY | KVM_MEM_LOG_DIRTY_PAGES, \ |
| 854 | .pt_memslot_flags = KVM_MEM_LOG_DIRTY_PAGES, \ | 856 | .pt_memslot_flags = KVM_MEM_READONLY | KVM_MEM_LOG_DIRTY_PAGES, \ |
| 855 | .guest_prepare = { _PREPARE(_access) }, \ | 857 | .guest_prepare = { _PREPARE(_access) }, \ |
| 856 | .guest_test = _access, \ | 858 | .guest_test = _access, \ |
| 857 | .guest_test_check = { _test_check }, \ | 859 | .guest_test_check = { _test_check }, \ |
| @@ -863,7 +865,7 @@ static void help(char *name) · 5 unmodified lines | |||
| 863 | { \ | 865 | { \ |
| 864 | .name = SCAT2(ro_memslot_no_syn_and_dlog, _access), \ | 866 | .name = SCAT2(ro_memslot_no_syn_and_dlog, _access), \ |
| 865 | .data_memslot_flags = KVM_MEM_READONLY | KVM_MEM_LOG_DIRTY_PAGES, \ | 867 | .data_memslot_flags = KVM_MEM_READONLY | KVM_MEM_LOG_DIRTY_PAGES, \ |
| 866 | .pt_memslot_flags = KVM_MEM_LOG_DIRTY_PAGES, \ | 868 | .pt_memslot_flags = KVM_MEM_READONLY | KVM_MEM_LOG_DIRTY_PAGES, \ |
| 867 | .guest_test = _access, \ | 869 | .guest_test = _access, \ |
| 868 | .guest_test_check = { _test_check }, \ | 870 | .guest_test_check = { _test_check }, \ |
| 869 | .fail_vcpu_run_handler = fail_vcpu_run_mmio_no_syndrome_handler, \ | 871 | .fail_vcpu_run_handler = fail_vcpu_run_mmio_no_syndrome_handler, \ |
| @@ -875,6 +877,7 @@ static void help(char *name) · 5 unmodified lines | |||
| 875 | { \ | 877 | { \ |
| 876 | .name = SCAT2(ro_memslot_uffd, _access), \ | 878 | .name = SCAT2(ro_memslot_uffd, _access), \ |
| 877 | .data_memslot_flags = KVM_MEM_READONLY, \ | 879 | .data_memslot_flags = KVM_MEM_READONLY, \ |
| 880 | .pt_memslot_flags = KVM_MEM_READONLY, \ | ||
| 878 | .mem_mark_cmd = CMD_HOLE_DATA | CMD_HOLE_PT, \ | 881 | .mem_mark_cmd = CMD_HOLE_DATA | CMD_HOLE_PT, \ |
| 879 | .guest_prepare = { _PREPARE(_access) }, \ | 882 | .guest_prepare = { _PREPARE(_access) }, \ |
| 880 | .guest_test = _access, \ | 883 | .guest_test = _access, \ |
| @@ -890,6 +893,7 @@ static void help(char *name) · 9 unmodified lines | |||
| 890 | { \ | 893 | { \ |
| 891 | .name = SCAT2(ro_memslot_no_syndrome, _access), \ | 894 | .name = SCAT2(ro_memslot_no_syndrome, _access), \ |
| 892 | .data_memslot_flags = KVM_MEM_READONLY, \ | 895 | .data_memslot_flags = KVM_MEM_READONLY, \ |
| 896 | .pt_memslot_flags = KVM_MEM_READONLY, \ | ||
| 893 | .mem_mark_cmd = CMD_HOLE_DATA | CMD_HOLE_PT, \ | 897 | .mem_mark_cmd = CMD_HOLE_DATA | CMD_HOLE_PT, \ |
| 894 | .guest_test = _access, \ | 898 | .guest_test = _access, \ |
| 895 | .uffd_data_handler = _uffd_data_handler, \ | 899 | .uffd_data_handler = _uffd_data_handler, \ |
| @@ -1024,7 +1028,7 @@ static struct test_desc tests[] = { · 128 unmodified lines | |||
| 1024 | guest_check_write_in_dirty_log, | 1028 | guest_check_write_in_dirty_log, |
| 1025 | guest_check_s1ptw_wr_in_dirty_log), | 1029 | guest_check_s1ptw_wr_in_dirty_log), |
| 1026 | /* | 1030 | /* |
| 1027 | * Try accesses when the data memory region is marked read-only | 1031 | * Access when both the PT and data regions are marked read-only |
| 1028 | * (with KVM_MEM_READONLY). Writes with a syndrome result in an | 1032 | * (with KVM_MEM_READONLY). Writes with a syndrome result in an |
| 1029 | * 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 |
| 1030 | * failed vcpu run, and reads/execs with and without syndroms do | 1034 | * failed vcpu run, and reads/execs with and without syndroms do |
| @@ -1040,7 +1044,7 @@ static struct test_desc tests[] = { · 9 unmodified lines | |||
| 1040 | TEST_RO_MEMSLOT_NO_SYNDROME(guest_st_preidx), | 1044 | TEST_RO_MEMSLOT_NO_SYNDROME(guest_st_preidx), |
| 1041 | 1045 | ||
| 1042 | /* | 1046 | /* |
| 1043 | * Access when both the data region is both read-only and marked | 1047 | * The PT and data regions are both read-only and marked |
| 1044 | * 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 |
| 1045 | * 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 |
| 1046 | * 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 |
| @@ -1065,7 +1069,7 @@ static struct test_desc tests[] = { · 18 unmodified lines | |||
| 1065 | guest_check_no_write_in_dirty_log), | 1069 | guest_check_no_write_in_dirty_log), |
| 1066 | 1070 | ||
| 1067 | /* | 1071 | /* |
| 1068 | * 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 |
| 1069 | * holes tracked with userfaultfd. The expected result is the | 1073 | * holes tracked with userfaultfd. The expected result is the |
| 1070 | * union of both userfaultfd and read-only behaviors. For example, | 1074 | * union of both userfaultfd and read-only behaviors. For example, |
| 1071 | * write accesses result in a userfaultfd write fault and an MMIO | 1075 | * write accesses result in a userfaultfd write fault and an MMIO |