196c1a628SMichael Roth /* SPDX-License-Identifier: GPL-2.0-only */ 296c1a628SMichael Roth /* 396c1a628SMichael Roth * Copyright (C) 2018, Google LLC. 496c1a628SMichael Roth */ 596c1a628SMichael Roth #ifndef SELFTEST_KVM_UCALL_COMMON_H 696c1a628SMichael Roth #define SELFTEST_KVM_UCALL_COMMON_H 7ddcb57afSColton Lewis #include "test_util.h" 8*b35f4c73SSean Christopherson #include "ucall.h" 996c1a628SMichael Roth 1096c1a628SMichael Roth /* Common ucalls */ 1196c1a628SMichael Roth enum { 1296c1a628SMichael Roth UCALL_NONE, 1396c1a628SMichael Roth UCALL_SYNC, 1496c1a628SMichael Roth UCALL_ABORT, 1557e5c1feSAaron Lewis UCALL_PRINTF, 1696c1a628SMichael Roth UCALL_DONE, 1796c1a628SMichael Roth UCALL_UNHANDLED, 1896c1a628SMichael Roth }; 1996c1a628SMichael Roth 20fc573fa4SColton Lewis #define UCALL_MAX_ARGS 7 2157e5c1feSAaron Lewis #define UCALL_BUFFER_LEN 1024 2296c1a628SMichael Roth 2396c1a628SMichael Roth struct ucall { 2496c1a628SMichael Roth uint64_t cmd; 2596c1a628SMichael Roth uint64_t args[UCALL_MAX_ARGS]; 2657e5c1feSAaron Lewis char buffer[UCALL_BUFFER_LEN]; 27426729b2SPeter Gonda 28426729b2SPeter Gonda /* Host virtual address of this struct. */ 29426729b2SPeter Gonda struct ucall *hva; 3096c1a628SMichael Roth }; 3196c1a628SMichael Roth 32dc88244bSSean Christopherson void ucall_arch_init(struct kvm_vm *vm, vm_paddr_t mmio_gpa); 3370466381SSean Christopherson void ucall_arch_do_ucall(vm_vaddr_t uc); 34ef38871eSSean Christopherson void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu); 3570466381SSean Christopherson 3696c1a628SMichael Roth void ucall(uint64_t cmd, int nargs, ...); 3757e5c1feSAaron Lewis void ucall_fmt(uint64_t cmd, const char *fmt, ...); 38289c2b4dSSean Christopherson void ucall_assert(uint64_t cmd, const char *exp, const char *file, 39289c2b4dSSean Christopherson unsigned int line, const char *fmt, ...); 40ef38871eSSean Christopherson uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc); 41426729b2SPeter Gonda void ucall_init(struct kvm_vm *vm, vm_paddr_t mmio_gpa); 42215a6817SAaron Lewis int ucall_nr_pages_required(uint64_t page_size); 4370466381SSean Christopherson 44ef16b2dfSSean Christopherson /* 45ef16b2dfSSean Christopherson * Perform userspace call without any associated data. This bare call avoids 46ef16b2dfSSean Christopherson * allocating a ucall struct, which can be useful if the atomic operations in 47ef16b2dfSSean Christopherson * the full ucall() are problematic and/or unwanted. Note, this will come out 48ef16b2dfSSean Christopherson * as UCALL_NONE on the backend. 49ef16b2dfSSean Christopherson */ 50ef16b2dfSSean Christopherson #define GUEST_UCALL_NONE() ucall_arch_do_ucall((vm_vaddr_t)NULL) 51ef16b2dfSSean Christopherson 5296c1a628SMichael Roth #define GUEST_SYNC_ARGS(stage, arg1, arg2, arg3, arg4) \ 5396c1a628SMichael Roth ucall(UCALL_SYNC, 6, "hello", stage, arg1, arg2, arg3, arg4) 5496c1a628SMichael Roth #define GUEST_SYNC(stage) ucall(UCALL_SYNC, 2, "hello", stage) 5557e5c1feSAaron Lewis #define GUEST_PRINTF(_fmt, _args...) ucall_fmt(UCALL_PRINTF, _fmt, ##_args) 5696c1a628SMichael Roth #define GUEST_DONE() ucall(UCALL_DONE, 0) 578fb2638aSColton Lewis 5857e5c1feSAaron Lewis #define REPORT_GUEST_PRINTF(ucall) pr_info("%s", (ucall).buffer) 5957e5c1feSAaron Lewis 608fb2638aSColton Lewis enum guest_assert_builtin_args { 618fb2638aSColton Lewis GUEST_ERROR_STRING, 628fb2638aSColton Lewis GUEST_FILE, 638fb2638aSColton Lewis GUEST_LINE, 648fb2638aSColton Lewis GUEST_ASSERT_BUILTIN_NARGS 658fb2638aSColton Lewis }; 668fb2638aSColton Lewis 67289c2b4dSSean Christopherson #define ____GUEST_ASSERT(_condition, _exp, _fmt, _args...) \ 68289c2b4dSSean Christopherson do { \ 69289c2b4dSSean Christopherson if (!(_condition)) \ 70289c2b4dSSean Christopherson ucall_assert(UCALL_ABORT, _exp, __FILE__, __LINE__, _fmt, ##_args); \ 71289c2b4dSSean Christopherson } while (0) 72289c2b4dSSean Christopherson 73289c2b4dSSean Christopherson #define __GUEST_ASSERT(_condition, _fmt, _args...) \ 74289c2b4dSSean Christopherson ____GUEST_ASSERT(_condition, #_condition, _fmt, ##_args) 75289c2b4dSSean Christopherson 76289c2b4dSSean Christopherson #define GUEST_ASSERT(_condition) \ 77289c2b4dSSean Christopherson __GUEST_ASSERT(_condition, #_condition) 78289c2b4dSSean Christopherson 79289c2b4dSSean Christopherson #define GUEST_FAIL(_fmt, _args...) \ 80289c2b4dSSean Christopherson ucall_assert(UCALL_ABORT, "Unconditional guest failure", \ 81289c2b4dSSean Christopherson __FILE__, __LINE__, _fmt, ##_args) 82289c2b4dSSean Christopherson 83289c2b4dSSean Christopherson #define GUEST_ASSERT_EQ(a, b) \ 84289c2b4dSSean Christopherson do { \ 85289c2b4dSSean Christopherson typeof(a) __a = (a); \ 86289c2b4dSSean Christopherson typeof(b) __b = (b); \ 87289c2b4dSSean Christopherson ____GUEST_ASSERT(__a == __b, #a " == " #b, "%#lx != %#lx (%s != %s)", \ 88289c2b4dSSean Christopherson (unsigned long)(__a), (unsigned long)(__b), #a, #b); \ 89289c2b4dSSean Christopherson } while (0) 90289c2b4dSSean Christopherson 91289c2b4dSSean Christopherson #define GUEST_ASSERT_NE(a, b) \ 92289c2b4dSSean Christopherson do { \ 93289c2b4dSSean Christopherson typeof(a) __a = (a); \ 94289c2b4dSSean Christopherson typeof(b) __b = (b); \ 95289c2b4dSSean Christopherson ____GUEST_ASSERT(__a != __b, #a " != " #b, "%#lx == %#lx (%s == %s)", \ 96289c2b4dSSean Christopherson (unsigned long)(__a), (unsigned long)(__b), #a, #b); \ 97289c2b4dSSean Christopherson } while (0) 98289c2b4dSSean Christopherson 99289c2b4dSSean Christopherson #define REPORT_GUEST_ASSERT(ucall) \ 100289c2b4dSSean Christopherson test_assert(false, (const char *)(ucall).args[GUEST_ERROR_STRING], \ 101289c2b4dSSean Christopherson (const char *)(ucall).args[GUEST_FILE], \ 102289c2b4dSSean Christopherson (ucall).args[GUEST_LINE], "%s", (ucall).buffer) 103289c2b4dSSean Christopherson 10496c1a628SMichael Roth #endif /* SELFTEST_KVM_UCALL_COMMON_H */ 105