1 // SPDX-License-Identifier: GPL-2.0
2 #include <signal.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <sys/ioctl.h>
7
8 #include <linux/sizes.h>
9
10 #include <kvm_util.h>
11 #include <processor.h>
12
13 #include "ucall_common.h"
14
15 struct kvm_coalesced_io {
16 struct kvm_coalesced_mmio_ring *ring;
17 uint32_t ring_size;
18 uint64_t mmio_gpa;
19 uint64_t *mmio;
20
21 /*
22 * x86-only, but define pio_port for all architectures to minimize the
23 * amount of #ifdeffery and complexity, without having to sacrifice
24 * verbose error messages.
25 */
26 uint8_t pio_port;
27 };
28
29 static struct kvm_coalesced_io kvm_builtin_io_ring;
30
31 #ifdef __x86_64__
32 static const int has_pio = 1;
33 #else
34 static const int has_pio = 0;
35 #endif
36
guest_code(struct kvm_coalesced_io * io)37 static void guest_code(struct kvm_coalesced_io *io)
38 {
39 int i, j;
40
41 for (;;) {
42 for (j = 0; j < 1 + has_pio; j++) {
43 /*
44 * KVM always leaves one free entry, i.e. exits to
45 * userspace before the last entry is filled.
46 */
47 for (i = 0; i < io->ring_size - 1; i++) {
48 #ifdef __x86_64__
49 if (i & 1)
50 outl(io->pio_port, io->pio_port + i);
51 else
52 #endif
53 WRITE_ONCE(*io->mmio, io->mmio_gpa + i);
54 }
55 #ifdef __x86_64__
56 if (j & 1)
57 outl(io->pio_port, io->pio_port + i);
58 else
59 #endif
60 WRITE_ONCE(*io->mmio, io->mmio_gpa + i);
61 }
62 GUEST_SYNC(0);
63
64 WRITE_ONCE(*io->mmio, io->mmio_gpa + i);
65 #ifdef __x86_64__
66 outl(io->pio_port, io->pio_port + i);
67 #endif
68 }
69 }
70
vcpu_run_and_verify_io_exit(struct kvm_vcpu * vcpu,struct kvm_coalesced_io * io,uint32_t ring_start,uint32_t expected_exit)71 static void vcpu_run_and_verify_io_exit(struct kvm_vcpu *vcpu,
72 struct kvm_coalesced_io *io,
73 uint32_t ring_start,
74 uint32_t expected_exit)
75 {
76 const bool want_pio = expected_exit == KVM_EXIT_IO;
77 struct kvm_coalesced_mmio_ring *ring = io->ring;
78 struct kvm_run *run = vcpu->run;
79 uint32_t pio_value;
80
81 WRITE_ONCE(ring->first, ring_start);
82 WRITE_ONCE(ring->last, ring_start);
83
84 vcpu_run(vcpu);
85
86 /*
87 * Annoyingly, reading PIO data is safe only for PIO exits, otherwise
88 * data_offset is garbage, e.g. an MMIO gpa.
89 */
90 if (run->exit_reason == KVM_EXIT_IO)
91 pio_value = *(uint32_t *)((void *)run + run->io.data_offset);
92 else
93 pio_value = 0;
94
95 TEST_ASSERT((!want_pio && (run->exit_reason == KVM_EXIT_MMIO && run->mmio.is_write &&
96 run->mmio.phys_addr == io->mmio_gpa && run->mmio.len == 8 &&
97 *(uint64_t *)run->mmio.data == io->mmio_gpa + io->ring_size - 1)) ||
98 (want_pio && (run->exit_reason == KVM_EXIT_IO && run->io.port == io->pio_port &&
99 run->io.direction == KVM_EXIT_IO_OUT && run->io.count == 1 &&
100 pio_value == io->pio_port + io->ring_size - 1)),
101 "For start = %u, expected exit on %u-byte %s write 0x%llx = %lx, got exit_reason = %u (%s)\n "
102 "(MMIO addr = 0x%llx, write = %u, len = %u, data = %lx)\n "
103 "(PIO port = 0x%x, write = %u, len = %u, count = %u, data = %x",
104 ring_start, want_pio ? 4 : 8, want_pio ? "PIO" : "MMIO",
105 want_pio ? (unsigned long long)io->pio_port : io->mmio_gpa,
106 (want_pio ? io->pio_port : io->mmio_gpa) + io->ring_size - 1, run->exit_reason,
107 run->exit_reason == KVM_EXIT_MMIO ? "MMIO" : run->exit_reason == KVM_EXIT_IO ? "PIO" : "other",
108 run->mmio.phys_addr, run->mmio.is_write, run->mmio.len, *(uint64_t *)run->mmio.data,
109 run->io.port, run->io.direction, run->io.size, run->io.count, pio_value);
110 }
111
vcpu_run_and_verify_coalesced_io(struct kvm_vcpu * vcpu,struct kvm_coalesced_io * io,uint32_t ring_start,uint32_t expected_exit)112 static void vcpu_run_and_verify_coalesced_io(struct kvm_vcpu *vcpu,
113 struct kvm_coalesced_io *io,
114 uint32_t ring_start,
115 uint32_t expected_exit)
116 {
117 struct kvm_coalesced_mmio_ring *ring = io->ring;
118 int i;
119
120 vcpu_run_and_verify_io_exit(vcpu, io, ring_start, expected_exit);
121
122 TEST_ASSERT((ring->last + 1) % io->ring_size == ring->first,
123 "Expected ring to be full (minus 1), first = %u, last = %u, max = %u, start = %u",
124 ring->first, ring->last, io->ring_size, ring_start);
125
126 for (i = 0; i < io->ring_size - 1; i++) {
127 uint32_t idx = (ring->first + i) % io->ring_size;
128 struct kvm_coalesced_mmio *entry = &ring->coalesced_mmio[idx];
129
130 #ifdef __x86_64__
131 if (i & 1)
132 TEST_ASSERT(entry->phys_addr == io->pio_port &&
133 entry->len == 4 && entry->pio &&
134 *(uint32_t *)entry->data == io->pio_port + i,
135 "Wanted 4-byte port I/O 0x%x = 0x%x in entry %u, got %u-byte %s 0x%llx = 0x%x",
136 io->pio_port, io->pio_port + i, i,
137 entry->len, entry->pio ? "PIO" : "MMIO",
138 entry->phys_addr, *(uint32_t *)entry->data);
139 else
140 #endif
141 TEST_ASSERT(entry->phys_addr == io->mmio_gpa &&
142 entry->len == 8 && !entry->pio,
143 "Wanted 8-byte MMIO to 0x%lx = %lx in entry %u, got %u-byte %s 0x%llx = 0x%lx",
144 io->mmio_gpa, io->mmio_gpa + i, i,
145 entry->len, entry->pio ? "PIO" : "MMIO",
146 entry->phys_addr, *(uint64_t *)entry->data);
147 }
148 }
149
test_coalesced_io(struct kvm_vcpu * vcpu,struct kvm_coalesced_io * io,uint32_t ring_start)150 static void test_coalesced_io(struct kvm_vcpu *vcpu,
151 struct kvm_coalesced_io *io, uint32_t ring_start)
152 {
153 struct kvm_coalesced_mmio_ring *ring = io->ring;
154
155 kvm_vm_register_coalesced_io(vcpu->vm, io->mmio_gpa, 8, false /* pio */);
156 #ifdef __x86_64__
157 kvm_vm_register_coalesced_io(vcpu->vm, io->pio_port, 8, true /* pio */);
158 #endif
159
160 vcpu_run_and_verify_coalesced_io(vcpu, io, ring_start, KVM_EXIT_MMIO);
161 #ifdef __x86_64__
162 vcpu_run_and_verify_coalesced_io(vcpu, io, ring_start, KVM_EXIT_IO);
163 #endif
164
165 /*
166 * Verify ucall, which may use non-coalesced MMIO or PIO, generates an
167 * immediate exit.
168 */
169 WRITE_ONCE(ring->first, ring_start);
170 WRITE_ONCE(ring->last, ring_start);
171 vcpu_run(vcpu);
172 TEST_ASSERT_EQ(get_ucall(vcpu, NULL), UCALL_SYNC);
173 TEST_ASSERT_EQ(ring->first, ring_start);
174 TEST_ASSERT_EQ(ring->last, ring_start);
175
176 /* Verify that non-coalesced MMIO/PIO generates an exit to userspace. */
177 kvm_vm_unregister_coalesced_io(vcpu->vm, io->mmio_gpa, 8, false /* pio */);
178 vcpu_run_and_verify_io_exit(vcpu, io, ring_start, KVM_EXIT_MMIO);
179
180 #ifdef __x86_64__
181 kvm_vm_unregister_coalesced_io(vcpu->vm, io->pio_port, 8, true /* pio */);
182 vcpu_run_and_verify_io_exit(vcpu, io, ring_start, KVM_EXIT_IO);
183 #endif
184 }
185
main(int argc,char * argv[])186 int main(int argc, char *argv[])
187 {
188 struct kvm_vcpu *vcpu;
189 struct kvm_vm *vm;
190 int i;
191
192 TEST_REQUIRE(kvm_has_cap(KVM_CAP_COALESCED_MMIO));
193
194 #ifdef __x86_64__
195 TEST_REQUIRE(kvm_has_cap(KVM_CAP_COALESCED_PIO));
196 #endif
197
198 vm = vm_create_with_one_vcpu(&vcpu, guest_code);
199
200 kvm_builtin_io_ring = (struct kvm_coalesced_io) {
201 /*
202 * The I/O ring is a kernel-allocated page whose address is
203 * relative to each vCPU's run page, with the page offset
204 * provided by KVM in the return of KVM_CAP_COALESCED_MMIO.
205 */
206 .ring = (void *)vcpu->run +
207 (kvm_check_cap(KVM_CAP_COALESCED_MMIO) * getpagesize()),
208
209 /*
210 * The size of the I/O ring is fixed, but KVM defines the sized
211 * based on the kernel's PAGE_SIZE. Thus, userspace must query
212 * the host's page size at runtime to compute the ring size.
213 */
214 .ring_size = (getpagesize() - sizeof(struct kvm_coalesced_mmio_ring)) /
215 sizeof(struct kvm_coalesced_mmio),
216
217 /*
218 * Arbitrary address+port (MMIO mustn't overlap memslots), with
219 * the MMIO GPA identity mapped in the guest.
220 */
221 .mmio_gpa = 4ull * SZ_1G,
222 .mmio = (uint64_t *)(4ull * SZ_1G),
223 .pio_port = 0x80,
224 };
225
226 virt_map(vm, (uint64_t)kvm_builtin_io_ring.mmio, kvm_builtin_io_ring.mmio_gpa, 1);
227
228 sync_global_to_guest(vm, kvm_builtin_io_ring);
229 vcpu_args_set(vcpu, 1, &kvm_builtin_io_ring);
230
231 for (i = 0; i < kvm_builtin_io_ring.ring_size; i++)
232 test_coalesced_io(vcpu, &kvm_builtin_io_ring, i);
233
234 kvm_vm_free(vm);
235 return 0;
236 }
237