1 // SPDX-License-Identifier: GPL-2.0-only
3 #include "linux/types.h"
4 #include "linux/bitmap.h"
5 #include "linux/atomic.h"
7 #define GUEST_UCALL_FAILED -1
10 DECLARE_BITMAP(in_use, KVM_MAX_VCPUS);
11 struct ucall ucalls[KVM_MAX_VCPUS];
14 int ucall_nr_pages_required(uint64_t page_size)
16 return align_up(sizeof(struct ucall_header), page_size) / page_size;
20 * ucall_pool holds per-VM values (global data is duplicated by each VM), it
21 * must not be accessed from host code.
23 static struct ucall_header *ucall_pool;
25 void ucall_init(struct kvm_vm *vm, vm_paddr_t mmio_gpa)
27 struct ucall_header *hdr;
32 vaddr = __vm_vaddr_alloc(vm, sizeof(*hdr), KVM_UTIL_MIN_VADDR, MEM_REGION_DATA);
33 hdr = (struct ucall_header *)addr_gva2hva(vm, vaddr);
34 memset(hdr, 0, sizeof(*hdr));
36 for (i = 0; i < KVM_MAX_VCPUS; ++i) {
41 write_guest_global(vm, ucall_pool, (struct ucall_header *)vaddr);
43 ucall_arch_init(vm, mmio_gpa);
46 static struct ucall *ucall_alloc(void)
54 for (i = 0; i < KVM_MAX_VCPUS; ++i) {
55 if (!test_and_set_bit(i, ucall_pool->in_use)) {
56 uc = &ucall_pool->ucalls[i];
57 memset(uc->args, 0, sizeof(uc->args));
64 * If the vCPU cannot grab a ucall structure, make a bare ucall with a
65 * magic value to signal to get_ucall() that things went sideways.
66 * GUEST_ASSERT() depends on ucall_alloc() and so cannot be used here.
68 ucall_arch_do_ucall(GUEST_UCALL_FAILED);
72 static void ucall_free(struct ucall *uc)
74 /* Beware, here be pointer arithmetic. */
75 clear_bit(uc - ucall_pool->ucalls, ucall_pool->in_use);
78 void ucall_assert(uint64_t cmd, const char *exp, const char *file,
79 unsigned int line, const char *fmt, ...)
87 WRITE_ONCE(uc->args[GUEST_ERROR_STRING], (uint64_t)(exp));
88 WRITE_ONCE(uc->args[GUEST_FILE], (uint64_t)(file));
89 WRITE_ONCE(uc->args[GUEST_LINE], line);
92 guest_vsnprintf(uc->buffer, UCALL_BUFFER_LEN, fmt, va);
95 ucall_arch_do_ucall((vm_vaddr_t)uc->hva);
100 void ucall_fmt(uint64_t cmd, const char *fmt, ...)
109 guest_vsnprintf(uc->buffer, UCALL_BUFFER_LEN, fmt, va);
112 ucall_arch_do_ucall((vm_vaddr_t)uc->hva);
117 void ucall(uint64_t cmd, int nargs, ...)
125 WRITE_ONCE(uc->cmd, cmd);
127 nargs = min(nargs, UCALL_MAX_ARGS);
130 for (i = 0; i < nargs; ++i)
131 WRITE_ONCE(uc->args[i], va_arg(va, uint64_t));
134 ucall_arch_do_ucall((vm_vaddr_t)uc->hva);
139 uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc)
147 addr = ucall_arch_get_ucall(vcpu);
149 TEST_ASSERT(addr != (void *)GUEST_UCALL_FAILED,
150 "Guest failed to allocate ucall struct");
152 memcpy(uc, addr, sizeof(*uc));
153 vcpu_run_complete_io(vcpu);
155 memset(uc, 0, sizeof(*uc));