Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

kvm: selftests: aarch64: dirty_log_test: support greater than 40-bit IPAs

When KVM has KVM_CAP_ARM_VM_IPA_SIZE we can test with > 40-bit IPAs by
using the 'type' field of KVM_CREATE_VM.

Signed-off-by: Andrew Jones <drjones@redhat.com>
Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>

authored by

Andrew Jones and committed by
Paolo Bonzini
8cee5816 cdbd2428

+42 -9
+27 -4
tools/testing/selftests/kvm/dirty_log_test.c
··· 216 216 } 217 217 218 218 static struct kvm_vm *create_vm(enum vm_guest_mode mode, uint32_t vcpuid, 219 - uint64_t extra_mem_pages, void *guest_code) 219 + uint64_t extra_mem_pages, void *guest_code, 220 + unsigned long type) 220 221 { 221 222 struct kvm_vm *vm; 222 223 uint64_t extra_pg_pages = extra_mem_pages / 512 * 2; 223 224 224 - vm = vm_create(mode, DEFAULT_GUEST_PHY_PAGES + extra_pg_pages, O_RDWR); 225 + vm = _vm_create(mode, DEFAULT_GUEST_PHY_PAGES + extra_pg_pages, 226 + O_RDWR, type); 225 227 kvm_vm_elf_load(vm, program_invocation_name, 0, 0); 226 228 #ifdef __x86_64__ 227 229 vm_create_irqchip(vm); ··· 240 238 struct kvm_vm *vm; 241 239 uint64_t max_gfn; 242 240 unsigned long *bmap; 241 + unsigned long type = 0; 243 242 244 243 switch (mode) { 245 244 case VM_MODE_P52V48_4K: ··· 249 246 break; 250 247 case VM_MODE_P52V48_64K: 251 248 guest_pa_bits = 52; 249 + guest_page_shift = 16; 250 + break; 251 + case VM_MODE_P48V48_4K: 252 + guest_pa_bits = 48; 253 + guest_page_shift = 12; 254 + break; 255 + case VM_MODE_P48V48_64K: 256 + guest_pa_bits = 48; 252 257 guest_page_shift = 16; 253 258 break; 254 259 case VM_MODE_P40V48_4K: ··· 282 271 */ 283 272 guest_pa_bits = 39; 284 273 #endif 274 + #ifdef __aarch64__ 275 + if (guest_pa_bits != 40) 276 + type = KVM_VM_TYPE_ARM_IPA_SIZE(guest_pa_bits); 277 + #endif 285 278 max_gfn = (1ul << (guest_pa_bits - guest_page_shift)) - 1; 286 279 guest_page_size = (1ul << guest_page_shift); 287 280 /* 1G of guest page sized pages */ ··· 306 291 bmap = bitmap_alloc(host_num_pages); 307 292 host_bmap_track = bitmap_alloc(host_num_pages); 308 293 309 - vm = create_vm(mode, VCPU_ID, guest_num_pages, guest_code); 294 + vm = create_vm(mode, VCPU_ID, guest_num_pages, guest_code, type); 310 295 311 296 #ifdef USE_CLEAR_DIRTY_LOG 312 297 struct kvm_enable_cap cap = {}; ··· 423 408 unsigned long interval = TEST_HOST_LOOP_INTERVAL; 424 409 bool mode_selected = false; 425 410 uint64_t phys_offset = 0; 426 - unsigned int mode; 411 + unsigned int mode, host_ipa_limit; 427 412 int opt, i; 428 413 429 414 #ifdef USE_CLEAR_DIRTY_LOG ··· 439 424 #ifdef __aarch64__ 440 425 vm_guest_mode_params_init(VM_MODE_P40V48_4K, true, true); 441 426 vm_guest_mode_params_init(VM_MODE_P40V48_64K, true, true); 427 + 428 + host_ipa_limit = kvm_check_cap(KVM_CAP_ARM_VM_IPA_SIZE); 429 + if (host_ipa_limit >= 52) 430 + vm_guest_mode_params_init(VM_MODE_P52V48_64K, true, true); 431 + if (host_ipa_limit >= 48) { 432 + vm_guest_mode_params_init(VM_MODE_P48V48_4K, true, true); 433 + vm_guest_mode_params_init(VM_MODE_P48V48_64K, true, true); 434 + } 442 435 #endif 443 436 444 437 while ((opt = getopt(argc, argv, "hi:I:p:m:")) != -1) {
+2
tools/testing/selftests/kvm/include/kvm_util.h
··· 56 56 int vm_enable_cap(struct kvm_vm *vm, struct kvm_enable_cap *cap); 57 57 58 58 struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm); 59 + struct kvm_vm *_vm_create(enum vm_guest_mode mode, uint64_t phy_pages, 60 + int perm, unsigned long type); 59 61 void kvm_vm_free(struct kvm_vm *vmp); 60 62 void kvm_vm_restart(struct kvm_vm *vmp, int perm); 61 63 void kvm_vm_release(struct kvm_vm *vmp);
+12 -5
tools/testing/selftests/kvm/lib/kvm_util.c
··· 85 85 return ret; 86 86 } 87 87 88 - static void vm_open(struct kvm_vm *vm, int perm) 88 + static void vm_open(struct kvm_vm *vm, int perm, unsigned long type) 89 89 { 90 90 vm->kvm_fd = open(KVM_DEV_PATH, perm); 91 91 if (vm->kvm_fd < 0) 92 92 exit(KSFT_SKIP); 93 93 94 - vm->fd = ioctl(vm->kvm_fd, KVM_CREATE_VM, NULL); 94 + vm->fd = ioctl(vm->kvm_fd, KVM_CREATE_VM, type); 95 95 TEST_ASSERT(vm->fd >= 0, "KVM_CREATE_VM ioctl failed, " 96 96 "rc: %i errno: %i", vm->fd, errno); 97 97 } ··· 126 126 * descriptor to control the created VM is created with the permissions 127 127 * given by perm (e.g. O_RDWR). 128 128 */ 129 - struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm) 129 + struct kvm_vm *_vm_create(enum vm_guest_mode mode, uint64_t phy_pages, 130 + int perm, unsigned long type) 130 131 { 131 132 struct kvm_vm *vm; 132 133 int kvm_fd; ··· 136 135 TEST_ASSERT(vm != NULL, "Insufficient Memory"); 137 136 138 137 vm->mode = mode; 139 - vm_open(vm, perm); 138 + vm->type = type; 139 + vm_open(vm, perm, type); 140 140 141 141 /* Setup mode specific traits. */ 142 142 switch (vm->mode) { ··· 207 205 return vm; 208 206 } 209 207 208 + struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm) 209 + { 210 + return _vm_create(mode, phy_pages, perm, 0); 211 + } 212 + 210 213 /* 211 214 * VM Restart 212 215 * ··· 229 222 { 230 223 struct userspace_mem_region *region; 231 224 232 - vm_open(vmp, perm); 225 + vm_open(vmp, perm, vmp->type); 233 226 if (vmp->has_irqchip) 234 227 vm_create_irqchip(vmp); 235 228
+1
tools/testing/selftests/kvm/lib/kvm_util_internal.h
··· 44 44 45 45 struct kvm_vm { 46 46 int mode; 47 + unsigned long type; 47 48 int kvm_fd; 48 49 int fd; 49 50 unsigned int pgtable_levels;