GUEST_SYNC(i);
        }
 
+       for (gpa = start_gpa; gpa < end_gpa; gpa += stride)
+               *((volatile uint64_t *)gpa);
+       GUEST_SYNC(2);
+
        GUEST_ASSERT(0);
 }
 
        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;
 }
 
        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;
        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