summaryrefslogtreecommitdiff
path: root/tools/testing/selftests/kvm/include/kvm_util_base.h
diff options
context:
space:
mode:
authorSean Christopherson <seanjc@google.com>2022-10-06 03:34:07 +0300
committerSean Christopherson <seanjc@google.com>2022-11-17 03:58:52 +0300
commit03b4750533fc6519845ac2ca0e1d88a81ac260a1 (patch)
tree99e5e4f85b571c7ba46dc1c11107944c60821843 /tools/testing/selftests/kvm/include/kvm_util_base.h
parentcf4694be2b2cf74945e50d39a02ea2307c4495f4 (diff)
downloadlinux-03b4750533fc6519845ac2ca0e1d88a81ac260a1.tar.xz
KVM: selftests: Make arm64's MMIO ucall multi-VM friendly
Fix a mostly-theoretical bug where ARM's ucall MMIO setup could result in different VMs stomping on each other by cloberring the global pointer. Fix the most obvious issue by saving the MMIO gpa into the VM. A more subtle bug is that creating VMs in parallel (on multiple tasks) could result in a VM using the wrong address. Synchronizing a global to a guest effectively snapshots the value on a per-VM basis, i.e. the "global" is already prepped to work with multiple VMs, but setting the global in the host is not thread-safe. To fix that bug, add write_guest_global() to allow stuffing a VM's copy of a "global" without modifying the host value. 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-6-seanjc@google.com
Diffstat (limited to 'tools/testing/selftests/kvm/include/kvm_util_base.h')
-rw-r--r--tools/testing/selftests/kvm/include/kvm_util_base.h15
1 files changed, 15 insertions, 0 deletions
diff --git a/tools/testing/selftests/kvm/include/kvm_util_base.h b/tools/testing/selftests/kvm/include/kvm_util_base.h
index 3bf2333ef95d..a7047e0767d3 100644
--- a/tools/testing/selftests/kvm/include/kvm_util_base.h
+++ b/tools/testing/selftests/kvm/include/kvm_util_base.h
@@ -16,6 +16,7 @@
#include <linux/kvm.h>
#include "linux/rbtree.h"
+#include <asm/atomic.h>
#include <sys/ioctl.h>
@@ -81,6 +82,7 @@ struct kvm_vm {
struct sparsebit *vpages_mapped;
bool has_irqchip;
bool pgd_created;
+ vm_paddr_t ucall_mmio_addr;
vm_paddr_t pgd;
vm_vaddr_t gdt;
vm_vaddr_t tss;
@@ -722,6 +724,19 @@ kvm_userspace_memory_region_find(struct kvm_vm *vm, uint64_t start,
memcpy(&(g), _p, sizeof(g)); \
})
+/*
+ * Write a global value, but only in the VM's (guest's) domain. Primarily used
+ * for "globals" that hold per-VM values (VMs always duplicate code and global
+ * data into their own region of physical memory), but can be used anytime it's
+ * undesirable to change the host's copy of the global.
+ */
+#define write_guest_global(vm, g, val) ({ \
+ typeof(g) *_p = addr_gva2hva(vm, (vm_vaddr_t)&(g)); \
+ typeof(g) _val = val; \
+ \
+ memcpy(_p, &(_val), sizeof(g)); \
+})
+
void assert_on_unhandled_exception(struct kvm_vcpu *vcpu);
void vcpu_arch_dump(FILE *stream, struct kvm_vcpu *vcpu,