]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
KVM: selftests: Add a read-only mprotect() phase to mmu_stress_test
authorSean Christopherson <seanjc@google.com>
Thu, 28 Nov 2024 00:55:43 +0000 (16:55 -0800)
committerSean Christopherson <seanjc@google.com>
Wed, 18 Dec 2024 22:15:01 +0000 (14:15 -0800)
Add a third phase of mmu_stress_test to verify that mprotect()ing guest
memory to make it read-only doesn't cause explosions, e.g. to verify KVM
correctly handles the resulting mmu_notifier invalidations.

Reviewed-by: James Houghton <jthoughton@google.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Link: https://lore.kernel.org/r/20241128005547.4077116-13-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
tools/testing/selftests/kvm/mmu_stress_test.c

index c6bf18cb7c89ca7a7e52d2af2bd1aa2094c4525a..0918fade92671ee981a9ba488348b0cca8c56380 100644 (file)
@@ -28,6 +28,10 @@ static void guest_code(uint64_t start_gpa, uint64_t end_gpa, uint64_t stride)
                GUEST_SYNC(i);
        }
 
+       for (gpa = start_gpa; gpa < end_gpa; gpa += stride)
+               *((volatile uint64_t *)gpa);
+       GUEST_SYNC(2);
+
        GUEST_ASSERT(0);
 }
 
@@ -95,6 +99,10 @@ static void *vcpu_worker(void *data)
        run_vcpu(vcpu, 1);
        rendezvous_with_boss();
 
+       /* Stage 2, read all of guest memory, which is now read-only. */
+       run_vcpu(vcpu, 2);
+       rendezvous_with_boss();
+
        return NULL;
 }
 
@@ -175,7 +183,7 @@ int main(int argc, char *argv[])
        const uint64_t start_gpa = SZ_4G;
        const int first_slot = 1;
 
-       struct timespec time_start, time_run1, time_reset, time_run2;
+       struct timespec time_start, time_run1, time_reset, time_run2, time_ro;
        uint64_t max_gpa, gpa, slot_size, max_mem, i;
        int max_slots, slot, opt, fd;
        bool hugepages = false;
@@ -279,14 +287,20 @@ int main(int argc, char *argv[])
        rendezvous_with_vcpus(&time_reset, "reset");
        rendezvous_with_vcpus(&time_run2, "run 2");
 
+       mprotect(mem, slot_size, PROT_READ);
+       rendezvous_with_vcpus(&time_ro, "mprotect RO");
+
+       time_ro    = timespec_sub(time_ro,     time_run2);
        time_run2  = timespec_sub(time_run2,   time_reset);
-       time_reset = timespec_sub(time_reset, time_run1);
+       time_reset = timespec_sub(time_reset,  time_run1);
        time_run1  = timespec_sub(time_run1,   time_start);
 
-       pr_info("run1 = %ld.%.9lds, reset = %ld.%.9lds, run2 =  %ld.%.9lds\n",
+       pr_info("run1 = %ld.%.9lds, reset = %ld.%.9lds, run2 = %ld.%.9lds, "
+               "ro = %ld.%.9lds\n",
                time_run1.tv_sec, time_run1.tv_nsec,
                time_reset.tv_sec, time_reset.tv_nsec,
-               time_run2.tv_sec, time_run2.tv_nsec);
+               time_run2.tv_sec, time_run2.tv_nsec,
+               time_ro.tv_sec, time_ro.tv_nsec);
 
        /*
         * Delete even numbered slots (arbitrary) and unmap the first half of