Skip to content

Commit f7fa674

Browse files
vishals4ghbonzini
authored andcommitted
KVM: selftests: Add helpers to convert guest memory b/w private and shared
Add helpers to convert memory between private and shared via KVM's memory attributes, as well as helpers to free/allocate guest_memfd memory via fallocate(). Userspace, i.e. tests, is NOT required to do fallocate() when converting memory, as the attributes are the single source of truth. Provide allocate() helpers so that tests can mimic a userspace that frees private memory on conversion, e.g. to prioritize memory usage over performance. Signed-off-by: Vishal Annapurve <vannapurve@google.com> Co-developed-by: Sean Christopherson <seanjc@google.com> Signed-off-by: Sean Christopherson <seanjc@google.com> Message-Id: <20231027182217.3615211-28-seanjc@google.com> Reviewed-by: Fuad Tabba <tabba@google.com> Tested-by: Fuad Tabba <tabba@google.com Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1 parent bb2968a commit f7fa674

2 files changed

Lines changed: 76 additions & 0 deletions

File tree

tools/testing/selftests/kvm/include/kvm_util_base.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,54 @@ static inline void vm_enable_cap(struct kvm_vm *vm, uint32_t cap, uint64_t arg0)
333333
vm_ioctl(vm, KVM_ENABLE_CAP, &enable_cap);
334334
}
335335

336+
static inline void vm_set_memory_attributes(struct kvm_vm *vm, uint64_t gpa,
337+
uint64_t size, uint64_t attributes)
338+
{
339+
struct kvm_memory_attributes attr = {
340+
.attributes = attributes,
341+
.address = gpa,
342+
.size = size,
343+
.flags = 0,
344+
};
345+
346+
/*
347+
* KVM_SET_MEMORY_ATTRIBUTES overwrites _all_ attributes. These flows
348+
* need significant enhancements to support multiple attributes.
349+
*/
350+
TEST_ASSERT(!attributes || attributes == KVM_MEMORY_ATTRIBUTE_PRIVATE,
351+
"Update me to support multiple attributes!");
352+
353+
vm_ioctl(vm, KVM_SET_MEMORY_ATTRIBUTES, &attr);
354+
}
355+
356+
357+
static inline void vm_mem_set_private(struct kvm_vm *vm, uint64_t gpa,
358+
uint64_t size)
359+
{
360+
vm_set_memory_attributes(vm, gpa, size, KVM_MEMORY_ATTRIBUTE_PRIVATE);
361+
}
362+
363+
static inline void vm_mem_set_shared(struct kvm_vm *vm, uint64_t gpa,
364+
uint64_t size)
365+
{
366+
vm_set_memory_attributes(vm, gpa, size, 0);
367+
}
368+
369+
void vm_guest_mem_fallocate(struct kvm_vm *vm, uint64_t gpa, uint64_t size,
370+
bool punch_hole);
371+
372+
static inline void vm_guest_mem_punch_hole(struct kvm_vm *vm, uint64_t gpa,
373+
uint64_t size)
374+
{
375+
vm_guest_mem_fallocate(vm, gpa, size, true);
376+
}
377+
378+
static inline void vm_guest_mem_allocate(struct kvm_vm *vm, uint64_t gpa,
379+
uint64_t size)
380+
{
381+
vm_guest_mem_fallocate(vm, gpa, size, false);
382+
}
383+
336384
void vm_enable_dirty_ring(struct kvm_vm *vm, uint32_t ring_size);
337385
const char *vm_guest_mode_string(uint32_t i);
338386

tools/testing/selftests/kvm/lib/kvm_util.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1167,6 +1167,34 @@ void vm_mem_region_delete(struct kvm_vm *vm, uint32_t slot)
11671167
__vm_mem_region_delete(vm, memslot2region(vm, slot), true);
11681168
}
11691169

1170+
void vm_guest_mem_fallocate(struct kvm_vm *vm, uint64_t base, uint64_t size,
1171+
bool punch_hole)
1172+
{
1173+
const int mode = FALLOC_FL_KEEP_SIZE | (punch_hole ? FALLOC_FL_PUNCH_HOLE : 0);
1174+
struct userspace_mem_region *region;
1175+
uint64_t end = base + size;
1176+
uint64_t gpa, len;
1177+
off_t fd_offset;
1178+
int ret;
1179+
1180+
for (gpa = base; gpa < end; gpa += len) {
1181+
uint64_t offset;
1182+
1183+
region = userspace_mem_region_find(vm, gpa, gpa);
1184+
TEST_ASSERT(region && region->region.flags & KVM_MEM_GUEST_MEMFD,
1185+
"Private memory region not found for GPA 0x%lx", gpa);
1186+
1187+
offset = gpa - region->region.guest_phys_addr;
1188+
fd_offset = region->region.guest_memfd_offset + offset;
1189+
len = min_t(uint64_t, end - gpa, region->region.memory_size - offset);
1190+
1191+
ret = fallocate(region->region.guest_memfd, mode, fd_offset, len);
1192+
TEST_ASSERT(!ret, "fallocate() failed to %s at %lx (len = %lu), fd = %d, mode = %x, offset = %lx\n",
1193+
punch_hole ? "punch hole" : "allocate", gpa, len,
1194+
region->region.guest_memfd, mode, fd_offset);
1195+
}
1196+
}
1197+
11701198
/* Returns the size of a vCPU's kvm_run structure. */
11711199
static int vcpu_mmap_sz(void)
11721200
{

0 commit comments

Comments
 (0)