162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2018, Google LLC.
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci#ifndef SELFTEST_KVM_UCALL_COMMON_H
662306a36Sopenharmony_ci#define SELFTEST_KVM_UCALL_COMMON_H
762306a36Sopenharmony_ci#include "test_util.h"
862306a36Sopenharmony_ci#include "ucall.h"
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci/* Common ucalls */
1162306a36Sopenharmony_cienum {
1262306a36Sopenharmony_ci	UCALL_NONE,
1362306a36Sopenharmony_ci	UCALL_SYNC,
1462306a36Sopenharmony_ci	UCALL_ABORT,
1562306a36Sopenharmony_ci	UCALL_PRINTF,
1662306a36Sopenharmony_ci	UCALL_DONE,
1762306a36Sopenharmony_ci	UCALL_UNHANDLED,
1862306a36Sopenharmony_ci};
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci#define UCALL_MAX_ARGS 7
2162306a36Sopenharmony_ci#define UCALL_BUFFER_LEN 1024
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_cistruct ucall {
2462306a36Sopenharmony_ci	uint64_t cmd;
2562306a36Sopenharmony_ci	uint64_t args[UCALL_MAX_ARGS];
2662306a36Sopenharmony_ci	char buffer[UCALL_BUFFER_LEN];
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci	/* Host virtual address of this struct. */
2962306a36Sopenharmony_ci	struct ucall *hva;
3062306a36Sopenharmony_ci};
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_civoid ucall_arch_init(struct kvm_vm *vm, vm_paddr_t mmio_gpa);
3362306a36Sopenharmony_civoid ucall_arch_do_ucall(vm_vaddr_t uc);
3462306a36Sopenharmony_civoid *ucall_arch_get_ucall(struct kvm_vcpu *vcpu);
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_civoid ucall(uint64_t cmd, int nargs, ...);
3762306a36Sopenharmony_civoid ucall_fmt(uint64_t cmd, const char *fmt, ...);
3862306a36Sopenharmony_civoid ucall_assert(uint64_t cmd, const char *exp, const char *file,
3962306a36Sopenharmony_ci		  unsigned int line, const char *fmt, ...);
4062306a36Sopenharmony_ciuint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc);
4162306a36Sopenharmony_civoid ucall_init(struct kvm_vm *vm, vm_paddr_t mmio_gpa);
4262306a36Sopenharmony_ciint ucall_nr_pages_required(uint64_t page_size);
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci/*
4562306a36Sopenharmony_ci * Perform userspace call without any associated data.  This bare call avoids
4662306a36Sopenharmony_ci * allocating a ucall struct, which can be useful if the atomic operations in
4762306a36Sopenharmony_ci * the full ucall() are problematic and/or unwanted.  Note, this will come out
4862306a36Sopenharmony_ci * as UCALL_NONE on the backend.
4962306a36Sopenharmony_ci */
5062306a36Sopenharmony_ci#define GUEST_UCALL_NONE()	ucall_arch_do_ucall((vm_vaddr_t)NULL)
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci#define GUEST_SYNC_ARGS(stage, arg1, arg2, arg3, arg4)	\
5362306a36Sopenharmony_ci				ucall(UCALL_SYNC, 6, "hello", stage, arg1, arg2, arg3, arg4)
5462306a36Sopenharmony_ci#define GUEST_SYNC(stage)	ucall(UCALL_SYNC, 2, "hello", stage)
5562306a36Sopenharmony_ci#define GUEST_PRINTF(_fmt, _args...) ucall_fmt(UCALL_PRINTF, _fmt, ##_args)
5662306a36Sopenharmony_ci#define GUEST_DONE()		ucall(UCALL_DONE, 0)
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci#define REPORT_GUEST_PRINTF(ucall) pr_info("%s", (ucall).buffer)
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_cienum guest_assert_builtin_args {
6162306a36Sopenharmony_ci	GUEST_ERROR_STRING,
6262306a36Sopenharmony_ci	GUEST_FILE,
6362306a36Sopenharmony_ci	GUEST_LINE,
6462306a36Sopenharmony_ci	GUEST_ASSERT_BUILTIN_NARGS
6562306a36Sopenharmony_ci};
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci#define ____GUEST_ASSERT(_condition, _exp, _fmt, _args...)				\
6862306a36Sopenharmony_cido {											\
6962306a36Sopenharmony_ci	if (!(_condition))								\
7062306a36Sopenharmony_ci		ucall_assert(UCALL_ABORT, _exp, __FILE__, __LINE__, _fmt, ##_args);	\
7162306a36Sopenharmony_ci} while (0)
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci#define __GUEST_ASSERT(_condition, _fmt, _args...)				\
7462306a36Sopenharmony_ci	____GUEST_ASSERT(_condition, #_condition, _fmt, ##_args)
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci#define GUEST_ASSERT(_condition)						\
7762306a36Sopenharmony_ci	__GUEST_ASSERT(_condition, #_condition)
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci#define GUEST_FAIL(_fmt, _args...)						\
8062306a36Sopenharmony_ci	ucall_assert(UCALL_ABORT, "Unconditional guest failure",		\
8162306a36Sopenharmony_ci		     __FILE__, __LINE__, _fmt, ##_args)
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci#define GUEST_ASSERT_EQ(a, b)							\
8462306a36Sopenharmony_cido {										\
8562306a36Sopenharmony_ci	typeof(a) __a = (a);							\
8662306a36Sopenharmony_ci	typeof(b) __b = (b);							\
8762306a36Sopenharmony_ci	____GUEST_ASSERT(__a == __b, #a " == " #b, "%#lx != %#lx (%s != %s)",	\
8862306a36Sopenharmony_ci			 (unsigned long)(__a), (unsigned long)(__b), #a, #b);	\
8962306a36Sopenharmony_ci} while (0)
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci#define GUEST_ASSERT_NE(a, b)							\
9262306a36Sopenharmony_cido {										\
9362306a36Sopenharmony_ci	typeof(a) __a = (a);							\
9462306a36Sopenharmony_ci	typeof(b) __b = (b);							\
9562306a36Sopenharmony_ci	____GUEST_ASSERT(__a != __b, #a " != " #b, "%#lx == %#lx (%s == %s)",	\
9662306a36Sopenharmony_ci			 (unsigned long)(__a), (unsigned long)(__b), #a, #b);	\
9762306a36Sopenharmony_ci} while (0)
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci#define REPORT_GUEST_ASSERT(ucall)						\
10062306a36Sopenharmony_ci	test_assert(false, (const char *)(ucall).args[GUEST_ERROR_STRING],	\
10162306a36Sopenharmony_ci		    (const char *)(ucall).args[GUEST_FILE],			\
10262306a36Sopenharmony_ci		    (ucall).args[GUEST_LINE], "%s", (ucall).buffer)
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci#endif /* SELFTEST_KVM_UCALL_COMMON_H */
105