xref: /linux/tools/testing/selftests/kvm/lib/ucall_common.c (revision 71dfa617ea9f18e4585fe78364217cd32b1fc382)
1 // SPDX-License-Identifier: GPL-2.0-only
2 #include "kvm_util.h"
3 #include "linux/types.h"
4 #include "linux/bitmap.h"
5 #include "linux/atomic.h"
6 
7 #define GUEST_UCALL_FAILED -1
8 
9 struct ucall_header {
10 	DECLARE_BITMAP(in_use, KVM_MAX_VCPUS);
11 	struct ucall ucalls[KVM_MAX_VCPUS];
12 };
13 
14 int ucall_nr_pages_required(uint64_t page_size)
15 {
16 	return align_up(sizeof(struct ucall_header), page_size) / page_size;
17 }
18 
19 /*
20  * ucall_pool holds per-VM values (global data is duplicated by each VM), it
21  * must not be accessed from host code.
22  */
23 static struct ucall_header *ucall_pool;
24 
25 void ucall_init(struct kvm_vm *vm, vm_paddr_t mmio_gpa)
26 {
27 	struct ucall_header *hdr;
28 	struct ucall *uc;
29 	vm_vaddr_t vaddr;
30 	int i;
31 
32 	vaddr = vm_vaddr_alloc_shared(vm, sizeof(*hdr), KVM_UTIL_MIN_VADDR,
33 				      MEM_REGION_DATA);
34 	hdr = (struct ucall_header *)addr_gva2hva(vm, vaddr);
35 	memset(hdr, 0, sizeof(*hdr));
36 
37 	for (i = 0; i < KVM_MAX_VCPUS; ++i) {
38 		uc = &hdr->ucalls[i];
39 		uc->hva = uc;
40 	}
41 
42 	write_guest_global(vm, ucall_pool, (struct ucall_header *)vaddr);
43 
44 	ucall_arch_init(vm, mmio_gpa);
45 }
46 
47 static struct ucall *ucall_alloc(void)
48 {
49 	struct ucall *uc;
50 	int i;
51 
52 	if (!ucall_pool)
53 		goto ucall_failed;
54 
55 	for (i = 0; i < KVM_MAX_VCPUS; ++i) {
56 		if (!test_and_set_bit(i, ucall_pool->in_use)) {
57 			uc = &ucall_pool->ucalls[i];
58 			memset(uc->args, 0, sizeof(uc->args));
59 			return uc;
60 		}
61 	}
62 
63 ucall_failed:
64 	/*
65 	 * If the vCPU cannot grab a ucall structure, make a bare ucall with a
66 	 * magic value to signal to get_ucall() that things went sideways.
67 	 * GUEST_ASSERT() depends on ucall_alloc() and so cannot be used here.
68 	 */
69 	ucall_arch_do_ucall(GUEST_UCALL_FAILED);
70 	return NULL;
71 }
72 
73 static void ucall_free(struct ucall *uc)
74 {
75 	/* Beware, here be pointer arithmetic.  */
76 	clear_bit(uc - ucall_pool->ucalls, ucall_pool->in_use);
77 }
78 
79 void ucall_assert(uint64_t cmd, const char *exp, const char *file,
80 		  unsigned int line, const char *fmt, ...)
81 {
82 	struct ucall *uc;
83 	va_list va;
84 
85 	uc = ucall_alloc();
86 	uc->cmd = cmd;
87 
88 	WRITE_ONCE(uc->args[GUEST_ERROR_STRING], (uint64_t)(exp));
89 	WRITE_ONCE(uc->args[GUEST_FILE], (uint64_t)(file));
90 	WRITE_ONCE(uc->args[GUEST_LINE], line);
91 
92 	va_start(va, fmt);
93 	guest_vsnprintf(uc->buffer, UCALL_BUFFER_LEN, fmt, va);
94 	va_end(va);
95 
96 	ucall_arch_do_ucall((vm_vaddr_t)uc->hva);
97 
98 	ucall_free(uc);
99 }
100 
101 void ucall_fmt(uint64_t cmd, const char *fmt, ...)
102 {
103 	struct ucall *uc;
104 	va_list va;
105 
106 	uc = ucall_alloc();
107 	uc->cmd = cmd;
108 
109 	va_start(va, fmt);
110 	guest_vsnprintf(uc->buffer, UCALL_BUFFER_LEN, fmt, va);
111 	va_end(va);
112 
113 	ucall_arch_do_ucall((vm_vaddr_t)uc->hva);
114 
115 	ucall_free(uc);
116 }
117 
118 void ucall(uint64_t cmd, int nargs, ...)
119 {
120 	struct ucall *uc;
121 	va_list va;
122 	int i;
123 
124 	uc = ucall_alloc();
125 
126 	WRITE_ONCE(uc->cmd, cmd);
127 
128 	nargs = min(nargs, UCALL_MAX_ARGS);
129 
130 	va_start(va, nargs);
131 	for (i = 0; i < nargs; ++i)
132 		WRITE_ONCE(uc->args[i], va_arg(va, uint64_t));
133 	va_end(va);
134 
135 	ucall_arch_do_ucall((vm_vaddr_t)uc->hva);
136 
137 	ucall_free(uc);
138 }
139 
140 uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc)
141 {
142 	struct ucall ucall;
143 	void *addr;
144 
145 	if (!uc)
146 		uc = &ucall;
147 
148 	addr = ucall_arch_get_ucall(vcpu);
149 	if (addr) {
150 		TEST_ASSERT(addr != (void *)GUEST_UCALL_FAILED,
151 			    "Guest failed to allocate ucall struct");
152 
153 		memcpy(uc, addr, sizeof(*uc));
154 		vcpu_run_complete_io(vcpu);
155 	} else {
156 		memset(uc, 0, sizeof(*uc));
157 	}
158 
159 	return uc->cmd;
160 }
161