On Tue, Dec 24, 2019 at 02:18:37PM +0800, Jason Wang wrote: [...] > > + while (fetch != avail) { > > + cur = &dirty_gfns[fetch % TEST_DIRTY_RING_COUNT]; > > + TEST_ASSERT(cur->pad == 0, "Padding is non-zero: 0x%x", cur->pad); > > + TEST_ASSERT(cur->slot == slot, "Slot number didn't match: " > > + "%u != %u", cur->slot, slot); > > + TEST_ASSERT(cur->offset < num_pages, "Offset overflow: " > > + "0x%llx >= 0x%llx", cur->offset, num_pages); > > + DEBUG("fetch 0x%x offset 0x%llx\n", fetch, cur->offset); > > + test_and_set_bit(cur->offset, bitmap); > > + fetch++; > > > Any reason to use test_and_set_bit()? I guess set_bit() should be > sufficient. Yes. > > > > + count++; > > + } > > + WRITE_ONCE(indices->fetch_index, fetch); > > > Is WRITE_ONCE a must here? No. [...] > > +void *vcpu_map_dirty_ring(struct kvm_vm *vm, uint32_t vcpuid) > > +{ > > + struct vcpu *vcpu; > > + uint32_t size = vm->dirty_ring_size; > > + > > + TEST_ASSERT(size > 0, "Should enable dirty ring first"); > > + > > + vcpu = vcpu_find(vm, vcpuid); > > + > > + TEST_ASSERT(vcpu, "Cannot find vcpu %u", vcpuid); > > + > > + if (!vcpu->dirty_gfns) { > > + vcpu->dirty_gfns_count = size / sizeof(struct kvm_dirty_gfn); > > + vcpu->dirty_gfns = mmap(NULL, size, PROT_READ | PROT_WRITE, > > + MAP_SHARED, vcpu->fd, vm->page_size * > > + KVM_DIRTY_LOG_PAGE_OFFSET); > > > It looks to me that we don't write to dirty_gfn. > > So PROT_READ should be sufficient. Yes. Thanks, -- Peter Xu