History

Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm

Pull kvm fixes from Paolo Bonzini: "ARM64: - Yet another fix for non-CPU accesses to the memory backing the VGICv3 subsystem - A set of fixes for the setlftest checking for the S1PTW behaviour after the fix that went in ealier in the cycle" * tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm: KVM: selftests: aarch64: Test read-only PT memory regions KVM: selftests: aarch64: Fix check of dirty log PT write KVM: selftests: aarch64: Do not default to dirty PTE pages on all S1PTWs KVM: selftests: aarch64: Relax userfaultfd read vs. write checks KVM: arm64: Allow no running vcpu on saving vgic3 pending table KVM: arm64: Allow no running vcpu on restoring vgic3 LPI pending status KVM: arm64: Add helper vgic_write_guest_lock()

Linus Torvalds committed 3 years ago

Commit c00f4dd2 parents 2ab2ba4 25b72cf6 files · +132 −98Browse files

Unified · Split

6 files
  1. Documentation/virt/kvm/api.rst +7 −3
  2. arch/arm64/kvm/vgic/vgic-its.c +5 −8
  3. arch/arm64/kvm/vgic/vgic-v3.c +2 −2
  4. arch/arm64/kvm/vgic/vgic.h +14 −0
  5. include/kvm/arm_vgic.h +1 −1
  6. tools/testing/selftests/kvm/aarch64/page_fault_test.c +103 −84
Documentation/virt/kvm/api.rst+7−3
@@ -8070,9 +8070,13 @@ considering the state as complete. VMM needs to ensure that the dirty · 8069 unmodified lines
8070state is final and avoid missing dirty pages from another ioctl ordered8070state is final and avoid missing dirty pages from another ioctl ordered
8071after the bitmap collection.8071after the bitmap collection.
8072 8072
8073NOTE: One example of using the backup bitmap is saving arm64 vgic/its8073NOTE: Multiple examples of using the backup bitmap: (1) save vgic/its
8074tables through KVM_DEV_ARM_{VGIC_GRP_CTRL, ITS_SAVE_TABLES} command on8074tables through command KVM_DEV_ARM_{VGIC_GRP_CTRL, ITS_SAVE_TABLES} on
8075KVM device "kvm-arm-vgic-its" when dirty ring is enabled.8075KVM device "kvm-arm-vgic-its". (2) restore vgic/its tables through
8076command KVM_DEV_ARM_{VGIC_GRP_CTRL, ITS_RESTORE_TABLES} on KVM device
8077"kvm-arm-vgic-its". VGICv3 LPI pending status is restored. (3) save
8078vgic3 pending table through KVM_DEV_ARM_VGIC_{GRP_CTRL, SAVE_PENDING_TABLES}
8079command on KVM device "kvm-arm-vgic-v3".
8076 8080
80778.30 KVM_CAP_XEN_HVM80818.30 KVM_CAP_XEN_HVM
8078--------------------8082--------------------
arch/arm64/kvm/vgic/vgic-its.c+5−8
@@ -2187,7 +2187,7 @@ static int vgic_its_save_ite(struct vgic_its *its, struct its_device *dev, · 2186 unmodified lines
2187 ((u64)ite->irq->intid << KVM_ITS_ITE_PINTID_SHIFT) |2187 ((u64)ite->irq->intid << KVM_ITS_ITE_PINTID_SHIFT) |
2188 ite->collection->collection_id;2188 ite->collection->collection_id;
2189 val = cpu_to_le64(val);2189 val = cpu_to_le64(val);
2190 return kvm_write_guest_lock(kvm, gpa, &val, ite_esz);2190 return vgic_write_guest_lock(kvm, gpa, &val, ite_esz);
2191}2191}
2192 2192
2193/**2193/**
@@ -2339,7 +2339,7 @@ static int vgic_its_save_dte(struct vgic_its *its, struct its_device *dev, · 145 unmodified lines
2339 (itt_addr_field << KVM_ITS_DTE_ITTADDR_SHIFT) |2339 (itt_addr_field << KVM_ITS_DTE_ITTADDR_SHIFT) |
2340 (dev->num_eventid_bits - 1));2340 (dev->num_eventid_bits - 1));
2341 val = cpu_to_le64(val);2341 val = cpu_to_le64(val);
2342 return kvm_write_guest_lock(kvm, ptr, &val, dte_esz);2342 return vgic_write_guest_lock(kvm, ptr, &val, dte_esz);
2343}2343}
2344 2344
2345/**2345/**
@@ -2526,7 +2526,7 @@ static int vgic_its_save_cte(struct vgic_its *its, · 180 unmodified lines
2526 ((u64)collection->target_addr << KVM_ITS_CTE_RDBASE_SHIFT) |2526 ((u64)collection->target_addr << KVM_ITS_CTE_RDBASE_SHIFT) |
2527 collection->collection_id);2527 collection->collection_id);
2528 val = cpu_to_le64(val);2528 val = cpu_to_le64(val);
2529 return kvm_write_guest_lock(its->dev->kvm, gpa, &val, esz);2529 return vgic_write_guest_lock(its->dev->kvm, gpa, &val, esz);
2530}2530}
2531 2531
2532/*2532/*
@@ -2607,7 +2607,7 @@ static int vgic_its_save_collection_table(struct vgic_its *its) · 74 unmodified lines
2607 */2607 */
2608 val = 0;2608 val = 0;
2609 BUG_ON(cte_esz > sizeof(val));2609 BUG_ON(cte_esz > sizeof(val));
2610 ret = kvm_write_guest_lock(its->dev->kvm, gpa, &val, cte_esz);2610 ret = vgic_write_guest_lock(its->dev->kvm, gpa, &val, cte_esz);
2611 return ret;2611 return ret;
2612}2612}
2613 2613
@@ -2743,7 +2743,6 @@ static int vgic_its_has_attr(struct kvm_device *dev, · 129 unmodified lines
2743static int vgic_its_ctrl(struct kvm *kvm, struct vgic_its *its, u64 attr)2743static int vgic_its_ctrl(struct kvm *kvm, struct vgic_its *its, u64 attr)
2744{2744{
2745 const struct vgic_its_abi *abi = vgic_its_get_abi(its);2745 const struct vgic_its_abi *abi = vgic_its_get_abi(its);
2746 struct vgic_dist *dist = &kvm->arch.vgic;
2747 int ret = 0;2746 int ret = 0;
2748 2747
2749 if (attr == KVM_DEV_ARM_VGIC_CTRL_INIT) /* Nothing to do */2748 if (attr == KVM_DEV_ARM_VGIC_CTRL_INIT) /* Nothing to do */
@@ -2763,9 +2762,7 @@ static int vgic_its_ctrl(struct kvm *kvm, struct vgic_its *its, u64 attr) · 13 unmodified lines
2763 vgic_its_reset(kvm, its);2762 vgic_its_reset(kvm, its);
2764 break;2763 break;
2765 case KVM_DEV_ARM_ITS_SAVE_TABLES:2764 case KVM_DEV_ARM_ITS_SAVE_TABLES:
2766 dist->save_its_tables_in_progress = true;
2767 ret = abi->save_tables(its);2765 ret = abi->save_tables(its);
2768 dist->save_its_tables_in_progress = false;
2769 break;2766 break;
2770 case KVM_DEV_ARM_ITS_RESTORE_TABLES:2767 case KVM_DEV_ARM_ITS_RESTORE_TABLES:
2771 ret = abi->restore_tables(its);2768 ret = abi->restore_tables(its);
@@ -2792,7 +2789,7 @@ bool kvm_arch_allow_write_without_running_vcpu(struct kvm *kvm) · 20 unmodified lines
2792{2789{
2793 struct vgic_dist *dist = &kvm->arch.vgic;2790 struct vgic_dist *dist = &kvm->arch.vgic;
2794 2791
2795 return dist->save_its_tables_in_progress;2792 return dist->table_write_in_progress;
2796}2793}
2797 2794
2798static int vgic_its_set_attr(struct kvm_device *dev,2795static int vgic_its_set_attr(struct kvm_device *dev,
arch/arm64/kvm/vgic/vgic-v3.c+2−2
@@ -339,7 +339,7 @@ retry: · 338 unmodified lines
339 if (status) {339 if (status) {
340 /* clear consumed data */340 /* clear consumed data */
341 val &= ~(1 << bit_nr);341 val &= ~(1 << bit_nr);
342 ret = kvm_write_guest_lock(kvm, ptr, &val, 1);342 ret = vgic_write_guest_lock(kvm, ptr, &val, 1);
343 if (ret)343 if (ret)
344 return ret;344 return ret;
345 }345 }
@@ -434,7 +434,7 @@ int vgic_v3_save_pending_tables(struct kvm *kvm) · 88 unmodified lines
434 else434 else
435 val &= ~(1 << bit_nr);435 val &= ~(1 << bit_nr);
436 436
437 ret = kvm_write_guest_lock(kvm, ptr, &val, 1);437 ret = vgic_write_guest_lock(kvm, ptr, &val, 1);
438 if (ret)438 if (ret)
439 goto out;439 goto out;
440 }440 }
arch/arm64/kvm/vgic/vgic.h+14−0
@@ -6,6 +6,7 @@ · 5 unmodified lines
6#define __KVM_ARM_VGIC_NEW_H__6#define __KVM_ARM_VGIC_NEW_H__
7 7
8#include <linux/irqchip/arm-gic-common.h>8#include <linux/irqchip/arm-gic-common.h>
9#include <asm/kvm_mmu.h>
9 10
10#define PRODUCT_ID_KVM 0x4b /* ASCII code K */11#define PRODUCT_ID_KVM 0x4b /* ASCII code K */
11#define IMPLEMENTER_ARM 0x43b12#define IMPLEMENTER_ARM 0x43b
@@ -131,6 +132,19 @@ static inline bool vgic_irq_is_multi_sgi(struct vgic_irq *irq) · 119 unmodified lines
131 return vgic_irq_get_lr_count(irq) > 1;132 return vgic_irq_get_lr_count(irq) > 1;
132}133}
133 134
135static inline int vgic_write_guest_lock(struct kvm *kvm, gpa_t gpa,
136 const void *data, unsigned long len)
137{
138 struct vgic_dist *dist = &kvm->arch.vgic;
139 int ret;
140
141 dist->table_write_in_progress = true;
142 ret = kvm_write_guest_lock(kvm, gpa, data, len);
143 dist->table_write_in_progress = false;
144
145 return ret;
146}
147
134/*148/*
135 * This struct provides an intermediate representation of the fields contained149 * This struct provides an intermediate representation of the fields contained
136 * in the GICH_VMCR and ICH_VMCR registers, such that code exporting the GIC150 * in the GICH_VMCR and ICH_VMCR registers, such that code exporting the GIC
include/kvm/arm_vgic.h+1−1
@@ -263,7 +263,7 @@ struct vgic_dist { · 262 unmodified lines
263 struct vgic_io_device dist_iodev;263 struct vgic_io_device dist_iodev;
264 264
265 bool has_its;265 bool has_its;
266 bool save_its_tables_in_progress;266 bool table_write_in_progress;
267 267
268 /*268 /*
269 * Contains the attributes and gpa of the LPI configuration table.269 * Contains the attributes and gpa of the LPI configuration table.
tools/testing/selftests/kvm/aarch64/page_fault_test.c+103−84
@@ -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
240static void guest_check_no_s1ptw_wr_in_dirty_log(void)
241{
242 GUEST_SYNC(CMD_CHECK_NO_S1PTW_WR_IN_DIRTY_LOG);
243}
244
240static void guest_exec(void)245static 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. */
306static int uffd_generic_handler(int uffd_mode, int uffd, struct uffd_msg *msg,311static 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
340static int uffd_pt_write_handler(int mode, int uffd, struct uffd_msg *msg)344static 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
345static 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
350static int uffd_data_read_handler(int mode, int uffd, struct uffd_msg *msg)349static 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
355static void setup_uffd_args(struct userspace_mem_region *region,354static 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 both964 * 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 for988 * 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 in992 * 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-only1031 * Access when both the PT and data regions are marked read-only
1006 * (with KVM_MEM_READONLY). Writes with a syndrome result in an1032 * (with KVM_MEM_READONLY). Writes with a syndrome result in an
1007 * MMIO exit, writes with no syndrome (e.g., CAS) result in a1033 * MMIO exit, writes with no syndrome (e.g., CAS) result in a
1008 * failed vcpu run, and reads/execs with and without syndroms do1034 * 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 marked1047 * The PT and data regions are both read-only and marked
1022 * for dirty logging at the same time. The expected result is that1048 * for dirty logging at the same time. The expected result is that
1023 * for writes there should be no write in the dirty log. The1049 * for writes there should be no write in the dirty log. The
1024 * readonly handling is the same as if the memslot was not marked1050 * 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 with1072 * The PT and data regions are both read-only and punched with
1047 * holes tracked with userfaultfd. The expected result is the1073 * 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 MMIO1075 * 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 getting1077 * 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};