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