diff options
Diffstat (limited to 'tools/testing/selftests/kvm')
-rw-r--r-- | tools/testing/selftests/kvm/lib/ucall.c | 30 |
1 files changed, 19 insertions, 11 deletions
diff --git a/tools/testing/selftests/kvm/lib/ucall.c b/tools/testing/selftests/kvm/lib/ucall.c index 694bc2eaa63e..a2ab38be2f47 100644 --- a/tools/testing/selftests/kvm/lib/ucall.c +++ b/tools/testing/selftests/kvm/lib/ucall.c @@ -35,6 +35,7 @@ void ucall_init(struct kvm_vm *vm, ucall_type_t type, void *arg) if (type == UCALL_MMIO) { vm_paddr_t gpa, start, end, step, offset; + unsigned bits; bool ret; if (arg) { @@ -45,23 +46,30 @@ void ucall_init(struct kvm_vm *vm, ucall_type_t type, void *arg) } /* - * Find an address within the allowed virtual address space, - * that does _not_ have a KVM memory region associated with it. - * Identity mapping an address like this allows the guest to + * Find an address within the allowed physical and virtual address + * spaces, that does _not_ have a KVM memory region associated with + * it. Identity mapping an address like this allows the guest to * access it, but as KVM doesn't know what to do with it, it * will assume it's something userspace handles and exit with * KVM_EXIT_MMIO. Well, at least that's how it works for AArch64. - * Here we start with a guess that the addresses around two - * thirds of the VA space are unmapped and then work both down - * and up from there in 1/12 VA space sized steps. + * Here we start with a guess that the addresses around 5/8th + * of the allowed space are unmapped and then work both down and + * up from there in 1/16th allowed space sized steps. + * + * Note, we need to use VA-bits - 1 when calculating the allowed + * virtual address space for an identity mapping because the upper + * half of the virtual address space is the two's complement of the + * lower and won't match physical addresses. */ - start = 1ul << (vm->va_bits * 2 / 3); - end = 1ul << vm->va_bits; - step = 1ul << (vm->va_bits / 12); + bits = vm->va_bits - 1; + bits = vm->pa_bits < bits ? vm->pa_bits : bits; + end = 1ul << bits; + start = end * 5 / 8; + step = end / 16; for (offset = 0; offset < end - start; offset += step) { - if (ucall_mmio_init(vm, (gpa - offset) & ~(vm->page_size - 1))) + if (ucall_mmio_init(vm, start - offset)) return; - if (ucall_mmio_init(vm, (gpa + offset) & ~(vm->page_size - 1))) + if (ucall_mmio_init(vm, start + offset)) return; } TEST_ASSERT(false, "Can't find a ucall mmio address"); |