summaryrefslogtreecommitdiffstats
path: root/tools/testing/selftests/kvm/lib/aarch64/ucall.c
diff options
context:
space:
mode:
authorSean Christopherson <seanjc@google.com>2022-10-06 00:34:05 +0000
committerSean Christopherson <seanjc@google.com>2022-11-16 16:58:51 -0800
commitdc88244bf5488b04fb7bbe47d8d9c38ff8f7dbb4 (patch)
treebba699266dbfad0d9aa2d063a7af65f1362263a7 /tools/testing/selftests/kvm/lib/aarch64/ucall.c
parentef38871eb22879438d2af8642ed7a52c1616f410 (diff)
downloadlinux-dc88244bf5488b04fb7bbe47d8d9c38ff8f7dbb4.tar.bz2
KVM: selftests: Automatically do init_ucall() for non-barebones VMs
Do init_ucall() automatically during VM creation to kill two (three?) birds with one stone. First, initializing ucall immediately after VM creations allows forcing aarch64's MMIO ucall address to immediately follow memslot0. This is still somewhat fragile as tests could clobber the MMIO address with a new memslot, but it's safe-ish since tests have to be conversative when accounting for memslot0. And this can be hardened in the future by creating a read-only memslot for the MMIO page (KVM ARM exits with MMIO if the guest writes to a read-only memslot). Add a TODO to document that selftests can and should use a memslot for the ucall MMIO (doing so requires yet more rework because tests assumes thay can use all memslots except memslot0). Second, initializing ucall for all VMs prepares for making ucall initialization meaningful on all architectures. aarch64 is currently the only arch that needs to do any setup, but that will change in the future by switching to a pool-based implementation (instead of the current stack-based approach). Lastly, defining the ucall MMIO address from common code will simplify switching all architectures (except s390) to a common MMIO-based ucall implementation (if there's ever sufficient motivation to do so). Cc: Oliver Upton <oliver.upton@linux.dev> Reviewed-by: Andrew Jones <andrew.jones@linux.dev> Tested-by: Peter Gonda <pgonda@google.com> Signed-off-by: Sean Christopherson <seanjc@google.com> Link: https://lore.kernel.org/r/20221006003409.649993-4-seanjc@google.com
Diffstat (limited to 'tools/testing/selftests/kvm/lib/aarch64/ucall.c')
-rw-r--r--tools/testing/selftests/kvm/lib/aarch64/ucall.c54
1 files changed, 3 insertions, 51 deletions
diff --git a/tools/testing/selftests/kvm/lib/aarch64/ucall.c b/tools/testing/selftests/kvm/lib/aarch64/ucall.c
index f214f5cc53d3..f02ae27c3e43 100644
--- a/tools/testing/selftests/kvm/lib/aarch64/ucall.c
+++ b/tools/testing/selftests/kvm/lib/aarch64/ucall.c
@@ -8,60 +8,12 @@
static vm_vaddr_t *ucall_exit_mmio_addr;
-static bool ucall_mmio_init(struct kvm_vm *vm, vm_paddr_t gpa)
+void ucall_arch_init(struct kvm_vm *vm, vm_paddr_t mmio_gpa)
{
- if (kvm_userspace_memory_region_find(vm, gpa, gpa + 1))
- return false;
+ virt_pg_map(vm, mmio_gpa, mmio_gpa);
- virt_pg_map(vm, gpa, gpa);
-
- ucall_exit_mmio_addr = (vm_vaddr_t *)gpa;
+ ucall_exit_mmio_addr = (vm_vaddr_t *)mmio_gpa;
sync_global_to_guest(vm, ucall_exit_mmio_addr);
-
- return true;
-}
-
-void ucall_arch_init(struct kvm_vm *vm, void *arg)
-{
- vm_paddr_t gpa, start, end, step, offset;
- unsigned int bits;
- bool ret;
-
- if (arg) {
- gpa = (vm_paddr_t)arg;
- ret = ucall_mmio_init(vm, gpa);
- TEST_ASSERT(ret, "Can't set ucall mmio address to %lx", gpa);
- return;
- }
-
- /*
- * 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 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.
- */
- bits = vm->va_bits - 1;
- bits = min(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, start - offset))
- return;
- if (ucall_mmio_init(vm, start + offset))
- return;
- }
- TEST_FAIL("Can't find a ucall mmio address");
}
void ucall_arch_uninit(struct kvm_vm *vm)