All of lore.kernel.org
 help / color / mirror / Atom feed
From: Michael Roth <michael.roth@amd.com>
To: <linux-kselftest@vger.kernel.org>
Cc: <kvm@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
	<x86@kernel.org>, Nathan Tempelman <natet@google.com>,
	Marc Orr <marcorr@google.com>,
	"Steve Rutherford" <srutherford@google.com>,
	Sean Christopherson <seanjc@google.com>,
	Mingwei Zhang <mizhang@google.com>,
	Brijesh Singh <brijesh.singh@amd.com>,
	Tom Lendacky <thomas.lendacky@amd.com>,
	Varad Gautam <varad.gautam@suse.com>,
	Shuah Khan <shuah@kernel.org>,
	Vitaly Kuznetsov <vkuznets@redhat.com>,
	"David Woodhouse" <dwmw@amazon.co.uk>,
	Ricardo Koller <ricarkol@google.com>,
	"Jim Mattson" <jmattson@google.com>,
	Joerg Roedel <joro@8bytes.org>,
	"Thomas Gleixner" <tglx@linutronix.de>,
	Ingo Molnar <mingo@redhat.com>, "Borislav Petkov" <bp@alien8.de>,
	"H . Peter Anvin" <hpa@zytor.com>,
	"Christian Borntraeger" <borntraeger@linux.ibm.com>,
	Janosch Frank <frankja@linux.ibm.com>,
	David Hildenbrand <david@redhat.com>,
	"Claudio Imbrenda" <imbrenda@linux.ibm.com>,
	Marc Zyngier <maz@kernel.org>, James Morse <james.morse@arm.com>,
	Alexandru Elisei <alexandru.elisei@arm.com>,
	"Suzuki K Poulose" <suzuki.poulose@arm.com>,
	<kvmarm@lists.cs.columbia.edu>
Subject: [PATCH RFC 03/10] kvm: selftests: introduce ucall_ops for test/arch-specific ucall implementations
Date: Fri, 10 Dec 2021 10:46:13 -0600	[thread overview]
Message-ID: <20211210164620.11636-4-michael.roth@amd.com> (raw)
In-Reply-To: <20211210164620.11636-1-michael.roth@amd.com>

To support SEV, x86 tests will need an alternative to using PIO
instructions to handle ucall-related functionality since ucall structs
are currently allocated on the guest stack, which will generally be
encrypted memory that can't be accessed by tests through the normal
mechanisms (along with some other complications which will requires
some new ucall interfaces as well).

To prepare for this, introduce a ucall_ops struct and supporting
interfaces that can be used to define multiple ucall implementations
that can be selected on a per-test basis, and re-work the existing
PIO-based ucall implementation to make use of these changes. Subsequent
patches will do the same for other archs as well, and then extend this
ops interface to address complications when dealing with
encrypted/private guest memory.

Signed-off-by: Michael Roth <michael.roth@amd.com>
---
 tools/testing/selftests/kvm/Makefile          |  2 +-
 .../testing/selftests/kvm/include/kvm_util.h  | 10 ++
 .../selftests/kvm/include/ucall_common.h      | 17 +++-
 .../selftests/kvm/include/x86_64/ucall.h      | 18 ++++
 .../testing/selftests/kvm/lib/ucall_common.c  | 95 +++++++++++++++++++
 .../testing/selftests/kvm/lib/x86_64/ucall.c  | 46 ++++-----
 6 files changed, 157 insertions(+), 31 deletions(-)
 create mode 100644 tools/testing/selftests/kvm/include/x86_64/ucall.h
 create mode 100644 tools/testing/selftests/kvm/lib/ucall_common.c

diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile
index c4e34717826a..05bff4039890 100644
--- a/tools/testing/selftests/kvm/Makefile
+++ b/tools/testing/selftests/kvm/Makefile
@@ -34,7 +34,7 @@ ifeq ($(ARCH),s390)
 endif
 
 LIBKVM = lib/assert.c lib/elf.c lib/io.c lib/kvm_util.c lib/rbtree.c lib/sparsebit.c lib/test_util.c lib/guest_modes.c lib/perf_test_util.c
-LIBKVM_x86_64 = lib/x86_64/apic.c lib/x86_64/processor.c lib/x86_64/vmx.c lib/x86_64/svm.c lib/x86_64/ucall.c lib/x86_64/handlers.S
+LIBKVM_x86_64 = lib/x86_64/apic.c lib/x86_64/processor.c lib/x86_64/vmx.c lib/x86_64/svm.c lib/x86_64/ucall.c lib/x86_64/handlers.S lib/ucall_common.c
 LIBKVM_aarch64 = lib/aarch64/processor.c lib/aarch64/ucall.c lib/aarch64/handlers.S lib/aarch64/spinlock.c lib/aarch64/gic.c lib/aarch64/gic_v3.c lib/aarch64/vgic.c
 LIBKVM_s390x = lib/s390x/processor.c lib/s390x/ucall.c lib/s390x/diag318_test_handler.c
 
diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h
index c9286811a4cb..2701bf98c0db 100644
--- a/tools/testing/selftests/kvm/include/kvm_util.h
+++ b/tools/testing/selftests/kvm/include/kvm_util.h
@@ -8,6 +8,16 @@
 #define SELFTEST_KVM_UTIL_H
 
 #include "kvm_util_base.h"
+/*
+ * TODO: ucall.h contains arch-specific declarations along with
+ * ucall_common.h. For now only a subset of archs provide the
+ * new header. Once all archs implement the new header the #include for
+ * ucall_common.h can be dropped.
+ */
+#ifdef __x86_64__
+#include "ucall.h"
+#else
 #include "ucall_common.h"
+#endif
 
 #endif /* SELFTEST_KVM_UTIL_H */
diff --git a/tools/testing/selftests/kvm/include/ucall_common.h b/tools/testing/selftests/kvm/include/ucall_common.h
index 9eecc9d40b79..fcd32607dcff 100644
--- a/tools/testing/selftests/kvm/include/ucall_common.h
+++ b/tools/testing/selftests/kvm/include/ucall_common.h
@@ -1,8 +1,12 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * tools/testing/selftests/kvm/include/kvm_util.h
+ * Common interfaces related to ucall support.
+ *
+ * A ucall is a hypercall to userspace.
  *
  * Copyright (C) 2018, Google LLC.
+ * Copyright (C) 2018, Red Hat, Inc.
+ * Copyright (C) 2021, Advanced Micro Devices, Inc.
  */
 #ifndef SELFTEST_KVM_UCALL_COMMON_H
 #define SELFTEST_KVM_UCALL_COMMON_H
@@ -14,6 +18,7 @@ enum {
 	UCALL_ABORT,
 	UCALL_DONE,
 	UCALL_UNHANDLED,
+	UCALL_NOT_IMPLEMENTED,
 };
 
 #define UCALL_MAX_ARGS 6
@@ -23,8 +28,18 @@ struct ucall {
 	uint64_t args[UCALL_MAX_ARGS];
 };
 
+struct ucall_ops {
+	const char *name;
+	void (*init)(struct kvm_vm *vm, void *arg);
+	void (*uninit)(struct kvm_vm *vm);
+	void (*send_cmd)(struct ucall *uc);
+	uint64_t (*recv_cmd)(struct kvm_vm *vm, uint32_t vcpu_id, struct ucall *uc);
+};
+
 void ucall_init(struct kvm_vm *vm, void *arg);
 void ucall_uninit(struct kvm_vm *vm);
+void ucall_init_ops(struct kvm_vm *vm, void *arg, const struct ucall_ops *ops);
+void ucall_uninit_ops(struct kvm_vm *vm);
 void ucall(uint64_t cmd, int nargs, ...);
 uint64_t get_ucall(struct kvm_vm *vm, uint32_t vcpu_id, struct ucall *uc);
 
diff --git a/tools/testing/selftests/kvm/include/x86_64/ucall.h b/tools/testing/selftests/kvm/include/x86_64/ucall.h
new file mode 100644
index 000000000000..8366bdc9c04e
--- /dev/null
+++ b/tools/testing/selftests/kvm/include/x86_64/ucall.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Arch-specific ucall implementations.
+ *
+ * A ucall is a "hypercall to userspace".
+ *
+ * Copyright (C) 2021 Advanced Micro Devices
+ */
+#ifndef SELFTEST_KVM_UCALL_H
+#define SELFTEST_KVM_UCALL_H
+
+#include "ucall_common.h"
+
+extern const struct ucall_ops ucall_ops_pio;
+
+extern const struct ucall_ops ucall_ops_default;
+
+#endif /* SELFTEST_KVM_UCALL_H */
diff --git a/tools/testing/selftests/kvm/lib/ucall_common.c b/tools/testing/selftests/kvm/lib/ucall_common.c
new file mode 100644
index 000000000000..db0129edcbc1
--- /dev/null
+++ b/tools/testing/selftests/kvm/lib/ucall_common.c
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Common interfaces related to ucall support. A ucall is a hypercall to
+ * userspace.
+ *
+ * Copyright (C) 2018, Red Hat, Inc.
+ * Copyright (C) 2021, Advanced Micro Devices, Inc.
+ */
+#include "kvm_util_base.h"
+#include "ucall_common.h"
+
+extern const struct ucall_ops ucall_ops_default;
+
+/* Some archs rely on a default that is available even without ucall_init(). */
+#if defined(__x86_64__) || defined(__s390x__)
+static const struct ucall_ops *ucall_ops = &ucall_ops_default;
+#else
+static const struct ucall_ops *ucall_ops;
+#endif
+
+void ucall_init_ops(struct kvm_vm *vm, void *arg, const struct ucall_ops *ops)
+{
+	TEST_ASSERT(ops, "ucall ops must be specified");
+	ucall_ops = ops;
+	sync_global_to_guest(vm, ucall_ops);
+
+	if (ucall_ops->init)
+		ucall_ops->init(vm, arg);
+}
+
+void ucall_init(struct kvm_vm *vm, void *arg)
+{
+	ucall_init_ops(vm, arg, &ucall_ops_default);
+}
+
+void ucall_uninit_ops(struct kvm_vm *vm)
+{
+	if (ucall_ops && ucall_ops->uninit)
+		ucall_ops->uninit(vm);
+
+	ucall_ops = NULL;
+	sync_global_to_guest(vm, ucall_ops);
+}
+
+void ucall_uninit(struct kvm_vm *vm)
+{
+	ucall_uninit_ops(vm);
+}
+
+static void ucall_process_args(struct ucall *uc, uint64_t cmd, int nargs, va_list va_args)
+{
+	int i;
+
+	nargs = nargs <= UCALL_MAX_ARGS ? nargs : UCALL_MAX_ARGS;
+	uc->cmd = cmd;
+
+	for (i = 0; i < nargs; ++i)
+		uc->args[i] = va_arg(va_args, uint64_t);
+}
+
+/*
+ * Allocate/populate a ucall buffer from the guest's stack and then generate an
+ * exit to host userspace. ucall_ops->send_cmd should have some way of
+ * communicating the address of the ucall buffer to the host.
+ */
+void ucall(uint64_t cmd, int nargs, ...)
+{
+	struct ucall uc;
+	va_list va;
+
+	if (!ucall_ops->send_cmd)
+		return;
+
+	va_start(va, nargs);
+	ucall_process_args(&uc, cmd, nargs, va);
+	va_end(va);
+
+	ucall_ops->send_cmd(&uc);
+}
+
+/*
+ * Parse the ucall buffer allocated by the guest via ucall() to determine what
+ * ucall message/command was sent by the guest. If 'uc' is provided, copy the
+ * contents of the guest's ucall buffer into it.
+ */
+uint64_t get_ucall(struct kvm_vm *vm, uint32_t vcpu_id, struct ucall *uc)
+{
+	if (!ucall_ops->recv_cmd)
+		return UCALL_NOT_IMPLEMENTED;
+
+	if (uc)
+		memset(uc, 0, sizeof(*uc));
+
+	return ucall_ops->recv_cmd(vm, vcpu_id, uc);
+}
diff --git a/tools/testing/selftests/kvm/lib/x86_64/ucall.c b/tools/testing/selftests/kvm/lib/x86_64/ucall.c
index a3489973e290..f5d9aba0d803 100644
--- a/tools/testing/selftests/kvm/lib/x86_64/ucall.c
+++ b/tools/testing/selftests/kvm/lib/x86_64/ucall.c
@@ -1,48 +1,28 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * ucall support. A ucall is a "hypercall to userspace".
+ * Arch-specific ucall implementations.
+ *
+ * A ucall is a "hypercall to userspace".
  *
  * Copyright (C) 2018, Red Hat, Inc.
  */
-#include "kvm_util.h"
+#include "kvm_util_base.h"
+#include "ucall.h"
 
 #define UCALL_PIO_PORT ((uint16_t)0x1000)
 
-void ucall_init(struct kvm_vm *vm, void *arg)
-{
-}
-
-void ucall_uninit(struct kvm_vm *vm)
-{
-}
-
-void ucall(uint64_t cmd, int nargs, ...)
+static void ucall_ops_pio_send_cmd(struct ucall *uc)
 {
-	struct ucall uc = {
-		.cmd = cmd,
-	};
-	va_list va;
-	int i;
-
-	nargs = nargs <= UCALL_MAX_ARGS ? nargs : UCALL_MAX_ARGS;
-
-	va_start(va, nargs);
-	for (i = 0; i < nargs; ++i)
-		uc.args[i] = va_arg(va, uint64_t);
-	va_end(va);
-
 	asm volatile("in %[port], %%al"
-		: : [port] "d" (UCALL_PIO_PORT), "D" (&uc) : "rax", "memory");
+		: : [port] "d" (UCALL_PIO_PORT), "D" (uc) : "rax", "memory");
 }
 
-uint64_t get_ucall(struct kvm_vm *vm, uint32_t vcpu_id, struct ucall *uc)
+static uint64_t ucall_ops_pio_recv_cmd(struct kvm_vm *vm, uint32_t vcpu_id,
+				       struct ucall *uc)
 {
 	struct kvm_run *run = vcpu_state(vm, vcpu_id);
 	struct ucall ucall = {};
 
-	if (uc)
-		memset(uc, 0, sizeof(*uc));
-
 	if (run->exit_reason == KVM_EXIT_IO && run->io.port == UCALL_PIO_PORT) {
 		struct kvm_regs regs;
 
@@ -57,3 +37,11 @@ uint64_t get_ucall(struct kvm_vm *vm, uint32_t vcpu_id, struct ucall *uc)
 
 	return ucall.cmd;
 }
+
+const struct ucall_ops ucall_ops_pio = {
+	.name = "PIO",
+	.send_cmd = ucall_ops_pio_send_cmd,
+	.recv_cmd = ucall_ops_pio_recv_cmd,
+};
+
+const struct ucall_ops ucall_ops_default = ucall_ops_pio;
-- 
2.25.1


WARNING: multiple messages have this Message-ID (diff)
From: Michael Roth <michael.roth@amd.com>
To: <linux-kselftest@vger.kernel.org>
Cc: Brijesh Singh <brijesh.singh@amd.com>,
	kvm@vger.kernel.org, David Hildenbrand <david@redhat.com>,
	Marc Orr <marcorr@google.com>, "H . Peter Anvin" <hpa@zytor.com>,
	Claudio Imbrenda <imbrenda@linux.ibm.com>,
	Shuah Khan <shuah@kernel.org>,
	kvmarm@lists.cs.columbia.edu, Nathan Tempelman <natet@google.com>,
	Janosch Frank <frankja@linux.ibm.com>,
	Marc Zyngier <maz@kernel.org>, Joerg Roedel <joro@8bytes.org>,
	x86@kernel.org, Ingo Molnar <mingo@redhat.com>,
	Mingwei Zhang <mizhang@google.com>,
	Christian Borntraeger <borntraeger@linux.ibm.com>,
	Tom Lendacky <thomas.lendacky@amd.com>,
	Borislav Petkov <bp@alien8.de>,
	Thomas Gleixner <tglx@linutronix.de>,
	Varad Gautam <varad.gautam@suse.com>,
	Jim Mattson <jmattson@google.com>,
	Steve Rutherford <srutherford@google.com>,
	linux-kernel@vger.kernel.org,
	Vitaly Kuznetsov <vkuznets@redhat.com>,
	David Woodhouse <dwmw@amazon.co.uk>
Subject: [PATCH RFC 03/10] kvm: selftests: introduce ucall_ops for test/arch-specific ucall implementations
Date: Fri, 10 Dec 2021 10:46:13 -0600	[thread overview]
Message-ID: <20211210164620.11636-4-michael.roth@amd.com> (raw)
In-Reply-To: <20211210164620.11636-1-michael.roth@amd.com>

To support SEV, x86 tests will need an alternative to using PIO
instructions to handle ucall-related functionality since ucall structs
are currently allocated on the guest stack, which will generally be
encrypted memory that can't be accessed by tests through the normal
mechanisms (along with some other complications which will requires
some new ucall interfaces as well).

To prepare for this, introduce a ucall_ops struct and supporting
interfaces that can be used to define multiple ucall implementations
that can be selected on a per-test basis, and re-work the existing
PIO-based ucall implementation to make use of these changes. Subsequent
patches will do the same for other archs as well, and then extend this
ops interface to address complications when dealing with
encrypted/private guest memory.

Signed-off-by: Michael Roth <michael.roth@amd.com>
---
 tools/testing/selftests/kvm/Makefile          |  2 +-
 .../testing/selftests/kvm/include/kvm_util.h  | 10 ++
 .../selftests/kvm/include/ucall_common.h      | 17 +++-
 .../selftests/kvm/include/x86_64/ucall.h      | 18 ++++
 .../testing/selftests/kvm/lib/ucall_common.c  | 95 +++++++++++++++++++
 .../testing/selftests/kvm/lib/x86_64/ucall.c  | 46 ++++-----
 6 files changed, 157 insertions(+), 31 deletions(-)
 create mode 100644 tools/testing/selftests/kvm/include/x86_64/ucall.h
 create mode 100644 tools/testing/selftests/kvm/lib/ucall_common.c

diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile
index c4e34717826a..05bff4039890 100644
--- a/tools/testing/selftests/kvm/Makefile
+++ b/tools/testing/selftests/kvm/Makefile
@@ -34,7 +34,7 @@ ifeq ($(ARCH),s390)
 endif
 
 LIBKVM = lib/assert.c lib/elf.c lib/io.c lib/kvm_util.c lib/rbtree.c lib/sparsebit.c lib/test_util.c lib/guest_modes.c lib/perf_test_util.c
-LIBKVM_x86_64 = lib/x86_64/apic.c lib/x86_64/processor.c lib/x86_64/vmx.c lib/x86_64/svm.c lib/x86_64/ucall.c lib/x86_64/handlers.S
+LIBKVM_x86_64 = lib/x86_64/apic.c lib/x86_64/processor.c lib/x86_64/vmx.c lib/x86_64/svm.c lib/x86_64/ucall.c lib/x86_64/handlers.S lib/ucall_common.c
 LIBKVM_aarch64 = lib/aarch64/processor.c lib/aarch64/ucall.c lib/aarch64/handlers.S lib/aarch64/spinlock.c lib/aarch64/gic.c lib/aarch64/gic_v3.c lib/aarch64/vgic.c
 LIBKVM_s390x = lib/s390x/processor.c lib/s390x/ucall.c lib/s390x/diag318_test_handler.c
 
diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h
index c9286811a4cb..2701bf98c0db 100644
--- a/tools/testing/selftests/kvm/include/kvm_util.h
+++ b/tools/testing/selftests/kvm/include/kvm_util.h
@@ -8,6 +8,16 @@
 #define SELFTEST_KVM_UTIL_H
 
 #include "kvm_util_base.h"
+/*
+ * TODO: ucall.h contains arch-specific declarations along with
+ * ucall_common.h. For now only a subset of archs provide the
+ * new header. Once all archs implement the new header the #include for
+ * ucall_common.h can be dropped.
+ */
+#ifdef __x86_64__
+#include "ucall.h"
+#else
 #include "ucall_common.h"
+#endif
 
 #endif /* SELFTEST_KVM_UTIL_H */
diff --git a/tools/testing/selftests/kvm/include/ucall_common.h b/tools/testing/selftests/kvm/include/ucall_common.h
index 9eecc9d40b79..fcd32607dcff 100644
--- a/tools/testing/selftests/kvm/include/ucall_common.h
+++ b/tools/testing/selftests/kvm/include/ucall_common.h
@@ -1,8 +1,12 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * tools/testing/selftests/kvm/include/kvm_util.h
+ * Common interfaces related to ucall support.
+ *
+ * A ucall is a hypercall to userspace.
  *
  * Copyright (C) 2018, Google LLC.
+ * Copyright (C) 2018, Red Hat, Inc.
+ * Copyright (C) 2021, Advanced Micro Devices, Inc.
  */
 #ifndef SELFTEST_KVM_UCALL_COMMON_H
 #define SELFTEST_KVM_UCALL_COMMON_H
@@ -14,6 +18,7 @@ enum {
 	UCALL_ABORT,
 	UCALL_DONE,
 	UCALL_UNHANDLED,
+	UCALL_NOT_IMPLEMENTED,
 };
 
 #define UCALL_MAX_ARGS 6
@@ -23,8 +28,18 @@ struct ucall {
 	uint64_t args[UCALL_MAX_ARGS];
 };
 
+struct ucall_ops {
+	const char *name;
+	void (*init)(struct kvm_vm *vm, void *arg);
+	void (*uninit)(struct kvm_vm *vm);
+	void (*send_cmd)(struct ucall *uc);
+	uint64_t (*recv_cmd)(struct kvm_vm *vm, uint32_t vcpu_id, struct ucall *uc);
+};
+
 void ucall_init(struct kvm_vm *vm, void *arg);
 void ucall_uninit(struct kvm_vm *vm);
+void ucall_init_ops(struct kvm_vm *vm, void *arg, const struct ucall_ops *ops);
+void ucall_uninit_ops(struct kvm_vm *vm);
 void ucall(uint64_t cmd, int nargs, ...);
 uint64_t get_ucall(struct kvm_vm *vm, uint32_t vcpu_id, struct ucall *uc);
 
diff --git a/tools/testing/selftests/kvm/include/x86_64/ucall.h b/tools/testing/selftests/kvm/include/x86_64/ucall.h
new file mode 100644
index 000000000000..8366bdc9c04e
--- /dev/null
+++ b/tools/testing/selftests/kvm/include/x86_64/ucall.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Arch-specific ucall implementations.
+ *
+ * A ucall is a "hypercall to userspace".
+ *
+ * Copyright (C) 2021 Advanced Micro Devices
+ */
+#ifndef SELFTEST_KVM_UCALL_H
+#define SELFTEST_KVM_UCALL_H
+
+#include "ucall_common.h"
+
+extern const struct ucall_ops ucall_ops_pio;
+
+extern const struct ucall_ops ucall_ops_default;
+
+#endif /* SELFTEST_KVM_UCALL_H */
diff --git a/tools/testing/selftests/kvm/lib/ucall_common.c b/tools/testing/selftests/kvm/lib/ucall_common.c
new file mode 100644
index 000000000000..db0129edcbc1
--- /dev/null
+++ b/tools/testing/selftests/kvm/lib/ucall_common.c
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Common interfaces related to ucall support. A ucall is a hypercall to
+ * userspace.
+ *
+ * Copyright (C) 2018, Red Hat, Inc.
+ * Copyright (C) 2021, Advanced Micro Devices, Inc.
+ */
+#include "kvm_util_base.h"
+#include "ucall_common.h"
+
+extern const struct ucall_ops ucall_ops_default;
+
+/* Some archs rely on a default that is available even without ucall_init(). */
+#if defined(__x86_64__) || defined(__s390x__)
+static const struct ucall_ops *ucall_ops = &ucall_ops_default;
+#else
+static const struct ucall_ops *ucall_ops;
+#endif
+
+void ucall_init_ops(struct kvm_vm *vm, void *arg, const struct ucall_ops *ops)
+{
+	TEST_ASSERT(ops, "ucall ops must be specified");
+	ucall_ops = ops;
+	sync_global_to_guest(vm, ucall_ops);
+
+	if (ucall_ops->init)
+		ucall_ops->init(vm, arg);
+}
+
+void ucall_init(struct kvm_vm *vm, void *arg)
+{
+	ucall_init_ops(vm, arg, &ucall_ops_default);
+}
+
+void ucall_uninit_ops(struct kvm_vm *vm)
+{
+	if (ucall_ops && ucall_ops->uninit)
+		ucall_ops->uninit(vm);
+
+	ucall_ops = NULL;
+	sync_global_to_guest(vm, ucall_ops);
+}
+
+void ucall_uninit(struct kvm_vm *vm)
+{
+	ucall_uninit_ops(vm);
+}
+
+static void ucall_process_args(struct ucall *uc, uint64_t cmd, int nargs, va_list va_args)
+{
+	int i;
+
+	nargs = nargs <= UCALL_MAX_ARGS ? nargs : UCALL_MAX_ARGS;
+	uc->cmd = cmd;
+
+	for (i = 0; i < nargs; ++i)
+		uc->args[i] = va_arg(va_args, uint64_t);
+}
+
+/*
+ * Allocate/populate a ucall buffer from the guest's stack and then generate an
+ * exit to host userspace. ucall_ops->send_cmd should have some way of
+ * communicating the address of the ucall buffer to the host.
+ */
+void ucall(uint64_t cmd, int nargs, ...)
+{
+	struct ucall uc;
+	va_list va;
+
+	if (!ucall_ops->send_cmd)
+		return;
+
+	va_start(va, nargs);
+	ucall_process_args(&uc, cmd, nargs, va);
+	va_end(va);
+
+	ucall_ops->send_cmd(&uc);
+}
+
+/*
+ * Parse the ucall buffer allocated by the guest via ucall() to determine what
+ * ucall message/command was sent by the guest. If 'uc' is provided, copy the
+ * contents of the guest's ucall buffer into it.
+ */
+uint64_t get_ucall(struct kvm_vm *vm, uint32_t vcpu_id, struct ucall *uc)
+{
+	if (!ucall_ops->recv_cmd)
+		return UCALL_NOT_IMPLEMENTED;
+
+	if (uc)
+		memset(uc, 0, sizeof(*uc));
+
+	return ucall_ops->recv_cmd(vm, vcpu_id, uc);
+}
diff --git a/tools/testing/selftests/kvm/lib/x86_64/ucall.c b/tools/testing/selftests/kvm/lib/x86_64/ucall.c
index a3489973e290..f5d9aba0d803 100644
--- a/tools/testing/selftests/kvm/lib/x86_64/ucall.c
+++ b/tools/testing/selftests/kvm/lib/x86_64/ucall.c
@@ -1,48 +1,28 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * ucall support. A ucall is a "hypercall to userspace".
+ * Arch-specific ucall implementations.
+ *
+ * A ucall is a "hypercall to userspace".
  *
  * Copyright (C) 2018, Red Hat, Inc.
  */
-#include "kvm_util.h"
+#include "kvm_util_base.h"
+#include "ucall.h"
 
 #define UCALL_PIO_PORT ((uint16_t)0x1000)
 
-void ucall_init(struct kvm_vm *vm, void *arg)
-{
-}
-
-void ucall_uninit(struct kvm_vm *vm)
-{
-}
-
-void ucall(uint64_t cmd, int nargs, ...)
+static void ucall_ops_pio_send_cmd(struct ucall *uc)
 {
-	struct ucall uc = {
-		.cmd = cmd,
-	};
-	va_list va;
-	int i;
-
-	nargs = nargs <= UCALL_MAX_ARGS ? nargs : UCALL_MAX_ARGS;
-
-	va_start(va, nargs);
-	for (i = 0; i < nargs; ++i)
-		uc.args[i] = va_arg(va, uint64_t);
-	va_end(va);
-
 	asm volatile("in %[port], %%al"
-		: : [port] "d" (UCALL_PIO_PORT), "D" (&uc) : "rax", "memory");
+		: : [port] "d" (UCALL_PIO_PORT), "D" (uc) : "rax", "memory");
 }
 
-uint64_t get_ucall(struct kvm_vm *vm, uint32_t vcpu_id, struct ucall *uc)
+static uint64_t ucall_ops_pio_recv_cmd(struct kvm_vm *vm, uint32_t vcpu_id,
+				       struct ucall *uc)
 {
 	struct kvm_run *run = vcpu_state(vm, vcpu_id);
 	struct ucall ucall = {};
 
-	if (uc)
-		memset(uc, 0, sizeof(*uc));
-
 	if (run->exit_reason == KVM_EXIT_IO && run->io.port == UCALL_PIO_PORT) {
 		struct kvm_regs regs;
 
@@ -57,3 +37,11 @@ uint64_t get_ucall(struct kvm_vm *vm, uint32_t vcpu_id, struct ucall *uc)
 
 	return ucall.cmd;
 }
+
+const struct ucall_ops ucall_ops_pio = {
+	.name = "PIO",
+	.send_cmd = ucall_ops_pio_send_cmd,
+	.recv_cmd = ucall_ops_pio_recv_cmd,
+};
+
+const struct ucall_ops ucall_ops_default = ucall_ops_pio;
-- 
2.25.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

  parent reply	other threads:[~2021-12-10 16:49 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-12-10 16:46 [RFC PATCH 00/10] KVM: selftests: Add support for test-selectable ucall implementations Michael Roth
2021-12-10 16:46 ` Michael Roth
2021-12-10 16:46 ` [PATCH RFC 01/10] kvm: selftests: move base kvm_util.h declarations to kvm_util_base.h Michael Roth
2021-12-10 16:46   ` Michael Roth
2021-12-10 16:46 ` [PATCH RFC 02/10] kvm: selftests: move ucall declarations into ucall_common.h Michael Roth
2021-12-10 16:46   ` Michael Roth
2021-12-25  9:11   ` Andrew Jones
2021-12-25  9:11     ` Andrew Jones
2021-12-10 16:46 ` Michael Roth [this message]
2021-12-10 16:46   ` [PATCH RFC 03/10] kvm: selftests: introduce ucall_ops for test/arch-specific ucall implementations Michael Roth
2021-12-10 16:46 ` [PATCH RFC 04/10] kvm: arm64: selftests: use ucall_ops to define default ucall implementation Michael Roth
2021-12-10 16:46   ` Michael Roth
2021-12-10 16:46 ` [PATCH RFC 05/10] kvm: s390: " Michael Roth
2021-12-10 16:46   ` Michael Roth
2021-12-10 16:46 ` [PATCH RFC 06/10] kvm: selftests: add ucall interfaces based around shared memory Michael Roth
2021-12-10 16:46   ` Michael Roth
2021-12-10 16:46 ` [PATCH RFC 07/10] kvm: selftests: add ucall_shared ops for PIO Michael Roth
2021-12-10 16:46   ` Michael Roth
2021-12-10 16:46 ` [PATCH RFC 08/10] kvm: selftests: introduce ucall implementation based on halt instructions Michael Roth
2021-12-10 16:46   ` Michael Roth
2021-12-10 16:46 ` [PATCH RFC 09/10] kvm: selftests: add GUEST_SHARED_* macros for shared ucall implementations Michael Roth
2021-12-10 16:46   ` Michael Roth
2021-12-10 16:46 ` [PATCH RFC 10/10] kvm: selftests: add ucall_test to test various ucall functionality Michael Roth
2021-12-10 16:46   ` Michael Roth
2021-12-22 14:46 ` [RFC PATCH 00/10] KVM: selftests: Add support for test-selectable ucall implementations Paolo Bonzini
2021-12-22 14:46   ` Paolo Bonzini
2021-12-30 21:11 ` Sean Christopherson
2021-12-30 21:11   ` Sean Christopherson
2022-01-04 23:35   ` Michael Roth
2022-01-04 23:35     ` Michael Roth
2022-01-05  0:17     ` Sean Christopherson
2022-01-05  0:17       ` Sean Christopherson
2022-01-05 17:02       ` Michael Roth
2022-01-05 17:02         ` Michael Roth
2022-01-05 17:43         ` Sean Christopherson
2022-01-05 17:43           ` Sean Christopherson
2022-01-05 19:11           ` Michael Roth
2022-01-05 19:11             ` Michael Roth
2022-01-05 19:40             ` Sean Christopherson
2022-01-05 19:40               ` Sean Christopherson
2022-01-05 21:35               ` Michael Roth
2022-01-05 21:35                 ` Michael Roth
2022-01-05 22:02                 ` Sean Christopherson
2022-01-05 22:02                   ` Sean Christopherson
2022-01-05 22:32                   ` Michael Roth
2022-01-05 22:32                     ` Michael Roth

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20211210164620.11636-4-michael.roth@amd.com \
    --to=michael.roth@amd.com \
    --cc=alexandru.elisei@arm.com \
    --cc=borntraeger@linux.ibm.com \
    --cc=bp@alien8.de \
    --cc=brijesh.singh@amd.com \
    --cc=david@redhat.com \
    --cc=dwmw@amazon.co.uk \
    --cc=frankja@linux.ibm.com \
    --cc=hpa@zytor.com \
    --cc=imbrenda@linux.ibm.com \
    --cc=james.morse@arm.com \
    --cc=jmattson@google.com \
    --cc=joro@8bytes.org \
    --cc=kvm@vger.kernel.org \
    --cc=kvmarm@lists.cs.columbia.edu \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=marcorr@google.com \
    --cc=maz@kernel.org \
    --cc=mingo@redhat.com \
    --cc=mizhang@google.com \
    --cc=natet@google.com \
    --cc=ricarkol@google.com \
    --cc=seanjc@google.com \
    --cc=shuah@kernel.org \
    --cc=srutherford@google.com \
    --cc=suzuki.poulose@arm.com \
    --cc=tglx@linutronix.de \
    --cc=thomas.lendacky@amd.com \
    --cc=varad.gautam@suse.com \
    --cc=vkuznets@redhat.com \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.