]> git.proxmox.com Git - mirror_qemu.git/blame - hw/virtio/virtio-mmio.c
virtio-pmem-pci: force virtio version 1
[mirror_qemu.git] / hw / virtio / virtio-mmio.c
CommitLineData
4b52530b
PM
1/*
2 * Virtio MMIO bindings
3 *
4 * Copyright (c) 2011 Linaro Limited
5 *
6 * Author:
7 * Peter Maydell <peter.maydell@linaro.org>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, see <http://www.gnu.org/licenses/>.
20 */
21
9b8bfe21 22#include "qemu/osdep.h"
7e71da7f 23#include "standard-headers/linux/virtio_mmio.h"
64552b6b 24#include "hw/irq.h"
a27bd6c7 25#include "hw/qdev-properties.h"
4b52530b
PM
26#include "hw/sysbus.h"
27#include "hw/virtio/virtio.h"
ca77ee28 28#include "migration/qemu-file-types.h"
4b52530b 29#include "qemu/host-utils.h"
0b8fa32f 30#include "qemu/module.h"
434027ba 31#include "sysemu/kvm.h"
bca964bc 32#include "hw/virtio/virtio-mmio.h"
434027ba 33#include "qemu/error-report.h"
da1804d1
BL
34#include "qemu/log.h"
35#include "trace.h"
4b52530b 36
8e93cef1 37static bool virtio_mmio_ioeventfd_enabled(DeviceState *d)
c0971bcb 38{
8e93cef1 39 return kvm_eventfds_enabled();
434027ba
YSP
40}
41
c0971bcb
CH
42static int virtio_mmio_ioeventfd_assign(DeviceState *d,
43 EventNotifier *notifier,
44 int n, bool assign)
434027ba 45{
c0971bcb 46 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
434027ba 47
c0971bcb 48 if (assign) {
7e71da7f 49 memory_region_add_eventfd(&proxy->iomem, VIRTIO_MMIO_QUEUE_NOTIFY, 4,
c0971bcb
CH
50 true, n, notifier);
51 } else {
7e71da7f 52 memory_region_del_eventfd(&proxy->iomem, VIRTIO_MMIO_QUEUE_NOTIFY, 4,
c0971bcb 53 true, n, notifier);
434027ba 54 }
c0971bcb
CH
55 return 0;
56}
434027ba 57
c0971bcb
CH
58static void virtio_mmio_start_ioeventfd(VirtIOMMIOProxy *proxy)
59{
60 virtio_bus_start_ioeventfd(&proxy->bus);
61}
434027ba 62
c0971bcb
CH
63static void virtio_mmio_stop_ioeventfd(VirtIOMMIOProxy *proxy)
64{
65 virtio_bus_stop_ioeventfd(&proxy->bus);
434027ba
YSP
66}
67
351da832
JPB
68static void virtio_mmio_soft_reset(VirtIOMMIOProxy *proxy)
69{
70 int i;
71
72 if (proxy->legacy) {
73 return;
74 }
75
76 for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
77 proxy->vqs[i].enabled = 0;
78 }
79}
80
4b52530b
PM
81static uint64_t virtio_mmio_read(void *opaque, hwaddr offset, unsigned size)
82{
83 VirtIOMMIOProxy *proxy = (VirtIOMMIOProxy *)opaque;
06d3dff0 84 VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
4b52530b 85
da1804d1 86 trace_virtio_mmio_read(offset);
4b52530b
PM
87
88 if (!vdev) {
89 /* If no backend is present, we treat most registers as
90 * read-as-zero, except for the magic number, version and
91 * vendor ID. This is not strictly sanctioned by the virtio
92 * spec, but it allows us to provide transports with no backend
93 * plugged in which don't confuse Linux's virtio code: the
94 * probe won't complain about the bad magic number, but the
95 * device ID of zero means no backend will claim it.
96 */
97 switch (offset) {
7e71da7f 98 case VIRTIO_MMIO_MAGIC_VALUE:
4b52530b
PM
99 return VIRT_MAGIC;
100 case VIRTIO_MMIO_VERSION:
44e687a4
SL
101 if (proxy->legacy) {
102 return VIRT_VERSION_LEGACY;
103 } else {
104 return VIRT_VERSION;
105 }
7e71da7f 106 case VIRTIO_MMIO_VENDOR_ID:
4b52530b
PM
107 return VIRT_VENDOR;
108 default:
109 return 0;
110 }
111 }
112
113 if (offset >= VIRTIO_MMIO_CONFIG) {
114 offset -= VIRTIO_MMIO_CONFIG;
115 switch (size) {
116 case 1:
117 return virtio_config_readb(vdev, offset);
118 case 2:
119 return virtio_config_readw(vdev, offset);
120 case 4:
121 return virtio_config_readl(vdev, offset);
122 default:
123 abort();
124 }
125 }
126 if (size != 4) {
da1804d1
BL
127 qemu_log_mask(LOG_GUEST_ERROR,
128 "%s: wrong size access to register!\n",
129 __func__);
4b52530b
PM
130 return 0;
131 }
132 switch (offset) {
7e71da7f 133 case VIRTIO_MMIO_MAGIC_VALUE:
4b52530b
PM
134 return VIRT_MAGIC;
135 case VIRTIO_MMIO_VERSION:
44e687a4
SL
136 if (proxy->legacy) {
137 return VIRT_VERSION_LEGACY;
138 } else {
139 return VIRT_VERSION;
140 }
7e71da7f 141 case VIRTIO_MMIO_DEVICE_ID:
4b52530b 142 return vdev->device_id;
7e71da7f 143 case VIRTIO_MMIO_VENDOR_ID:
4b52530b 144 return VIRT_VENDOR;
7e71da7f 145 case VIRTIO_MMIO_DEVICE_FEATURES:
44e687a4
SL
146 if (proxy->legacy) {
147 if (proxy->host_features_sel) {
148 return 0;
149 } else {
150 return vdev->host_features;
151 }
152 } else {
153 VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
154 return (vdev->host_features & ~vdc->legacy_features)
155 >> (32 * proxy->host_features_sel);
4b52530b 156 }
7e71da7f 157 case VIRTIO_MMIO_QUEUE_NUM_MAX:
f7b803b3
PM
158 if (!virtio_queue_get_num(vdev, vdev->queue_sel)) {
159 return 0;
160 }
4b52530b 161 return VIRTQUEUE_MAX_SIZE;
7e71da7f 162 case VIRTIO_MMIO_QUEUE_PFN:
44e687a4
SL
163 if (!proxy->legacy) {
164 qemu_log_mask(LOG_GUEST_ERROR,
165 "%s: read from legacy register (0x%"
166 HWADDR_PRIx ") in non-legacy mode\n",
167 __func__, offset);
168 return 0;
169 }
4b52530b
PM
170 return virtio_queue_get_addr(vdev, vdev->queue_sel)
171 >> proxy->guest_page_shift;
44e687a4
SL
172 case VIRTIO_MMIO_QUEUE_READY:
173 if (proxy->legacy) {
174 qemu_log_mask(LOG_GUEST_ERROR,
175 "%s: read from non-legacy register (0x%"
176 HWADDR_PRIx ") in legacy mode\n",
177 __func__, offset);
178 return 0;
179 }
180 return proxy->vqs[vdev->queue_sel].enabled;
7e71da7f 181 case VIRTIO_MMIO_INTERRUPT_STATUS:
d73415a3 182 return qatomic_read(&vdev->isr);
4b52530b
PM
183 case VIRTIO_MMIO_STATUS:
184 return vdev->status;
44e687a4
SL
185 case VIRTIO_MMIO_CONFIG_GENERATION:
186 if (proxy->legacy) {
187 qemu_log_mask(LOG_GUEST_ERROR,
188 "%s: read from non-legacy register (0x%"
189 HWADDR_PRIx ") in legacy mode\n",
190 __func__, offset);
191 return 0;
192 }
193 return vdev->generation;
7e71da7f
MT
194 case VIRTIO_MMIO_DEVICE_FEATURES_SEL:
195 case VIRTIO_MMIO_DRIVER_FEATURES:
196 case VIRTIO_MMIO_DRIVER_FEATURES_SEL:
197 case VIRTIO_MMIO_GUEST_PAGE_SIZE:
198 case VIRTIO_MMIO_QUEUE_SEL:
199 case VIRTIO_MMIO_QUEUE_NUM:
200 case VIRTIO_MMIO_QUEUE_ALIGN:
201 case VIRTIO_MMIO_QUEUE_NOTIFY:
202 case VIRTIO_MMIO_INTERRUPT_ACK:
44e687a4
SL
203 case VIRTIO_MMIO_QUEUE_DESC_LOW:
204 case VIRTIO_MMIO_QUEUE_DESC_HIGH:
205 case VIRTIO_MMIO_QUEUE_AVAIL_LOW:
206 case VIRTIO_MMIO_QUEUE_AVAIL_HIGH:
207 case VIRTIO_MMIO_QUEUE_USED_LOW:
208 case VIRTIO_MMIO_QUEUE_USED_HIGH:
da1804d1 209 qemu_log_mask(LOG_GUEST_ERROR,
44e687a4
SL
210 "%s: read of write-only register (0x%" HWADDR_PRIx ")\n",
211 __func__, offset);
4b52530b
PM
212 return 0;
213 default:
44e687a4
SL
214 qemu_log_mask(LOG_GUEST_ERROR,
215 "%s: bad register offset (0x%" HWADDR_PRIx ")\n",
216 __func__, offset);
4b52530b
PM
217 return 0;
218 }
219 return 0;
220}
221
222static void virtio_mmio_write(void *opaque, hwaddr offset, uint64_t value,
223 unsigned size)
224{
225 VirtIOMMIOProxy *proxy = (VirtIOMMIOProxy *)opaque;
06d3dff0 226 VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
4b52530b 227
da1804d1 228 trace_virtio_mmio_write_offset(offset, value);
4b52530b
PM
229
230 if (!vdev) {
231 /* If no backend is present, we just make all registers
232 * write-ignored. This allows us to provide transports with
233 * no backend plugged in.
234 */
235 return;
236 }
237
238 if (offset >= VIRTIO_MMIO_CONFIG) {
239 offset -= VIRTIO_MMIO_CONFIG;
240 switch (size) {
241 case 1:
242 virtio_config_writeb(vdev, offset, value);
243 break;
244 case 2:
245 virtio_config_writew(vdev, offset, value);
246 break;
247 case 4:
248 virtio_config_writel(vdev, offset, value);
249 break;
250 default:
251 abort();
252 }
253 return;
254 }
255 if (size != 4) {
da1804d1
BL
256 qemu_log_mask(LOG_GUEST_ERROR,
257 "%s: wrong size access to register!\n",
258 __func__);
4b52530b
PM
259 return;
260 }
261 switch (offset) {
7e71da7f 262 case VIRTIO_MMIO_DEVICE_FEATURES_SEL:
44e687a4
SL
263 if (value) {
264 proxy->host_features_sel = 1;
265 } else {
266 proxy->host_features_sel = 0;
267 }
4b52530b 268 break;
7e71da7f 269 case VIRTIO_MMIO_DRIVER_FEATURES:
44e687a4
SL
270 if (proxy->legacy) {
271 if (proxy->guest_features_sel) {
272 qemu_log_mask(LOG_GUEST_ERROR,
273 "%s: attempt to write guest features with "
274 "guest_features_sel > 0 in legacy mode\n",
275 __func__);
276 } else {
277 virtio_set_features(vdev, value);
278 }
279 } else {
280 proxy->guest_features[proxy->guest_features_sel] = value;
4b52530b
PM
281 }
282 break;
7e71da7f 283 case VIRTIO_MMIO_DRIVER_FEATURES_SEL:
44e687a4
SL
284 if (value) {
285 proxy->guest_features_sel = 1;
286 } else {
287 proxy->guest_features_sel = 0;
288 }
4b52530b 289 break;
7e71da7f 290 case VIRTIO_MMIO_GUEST_PAGE_SIZE:
44e687a4
SL
291 if (!proxy->legacy) {
292 qemu_log_mask(LOG_GUEST_ERROR,
293 "%s: write to legacy register (0x%"
294 HWADDR_PRIx ") in non-legacy mode\n",
295 __func__, offset);
296 return;
297 }
4b52530b
PM
298 proxy->guest_page_shift = ctz32(value);
299 if (proxy->guest_page_shift > 31) {
300 proxy->guest_page_shift = 0;
301 }
da1804d1 302 trace_virtio_mmio_guest_page(value, proxy->guest_page_shift);
4b52530b 303 break;
7e71da7f 304 case VIRTIO_MMIO_QUEUE_SEL:
87b3bd1c 305 if (value < VIRTIO_QUEUE_MAX) {
4b52530b
PM
306 vdev->queue_sel = value;
307 }
308 break;
7e71da7f 309 case VIRTIO_MMIO_QUEUE_NUM:
da1804d1 310 trace_virtio_mmio_queue_write(value, VIRTQUEUE_MAX_SIZE);
1049f4c6
DP
311 virtio_queue_set_num(vdev, vdev->queue_sel, value);
312
44e687a4 313 if (proxy->legacy) {
44e687a4
SL
314 virtio_queue_update_rings(vdev, vdev->queue_sel);
315 } else {
316 proxy->vqs[vdev->queue_sel].num = value;
317 }
4b52530b 318 break;
7e71da7f 319 case VIRTIO_MMIO_QUEUE_ALIGN:
44e687a4
SL
320 if (!proxy->legacy) {
321 qemu_log_mask(LOG_GUEST_ERROR,
322 "%s: write to legacy register (0x%"
323 HWADDR_PRIx ") in non-legacy mode\n",
324 __func__, offset);
325 return;
326 }
4b52530b
PM
327 virtio_queue_set_align(vdev, vdev->queue_sel, value);
328 break;
7e71da7f 329 case VIRTIO_MMIO_QUEUE_PFN:
44e687a4
SL
330 if (!proxy->legacy) {
331 qemu_log_mask(LOG_GUEST_ERROR,
332 "%s: write to legacy register (0x%"
333 HWADDR_PRIx ") in non-legacy mode\n",
334 __func__, offset);
335 return;
336 }
4b52530b
PM
337 if (value == 0) {
338 virtio_reset(vdev);
339 } else {
340 virtio_queue_set_addr(vdev, vdev->queue_sel,
341 value << proxy->guest_page_shift);
342 }
343 break;
44e687a4
SL
344 case VIRTIO_MMIO_QUEUE_READY:
345 if (proxy->legacy) {
346 qemu_log_mask(LOG_GUEST_ERROR,
347 "%s: write to non-legacy register (0x%"
348 HWADDR_PRIx ") in legacy mode\n",
349 __func__, offset);
350 return;
351 }
352 if (value) {
353 virtio_queue_set_num(vdev, vdev->queue_sel,
354 proxy->vqs[vdev->queue_sel].num);
355 virtio_queue_set_rings(vdev, vdev->queue_sel,
356 ((uint64_t)proxy->vqs[vdev->queue_sel].desc[1]) << 32 |
357 proxy->vqs[vdev->queue_sel].desc[0],
358 ((uint64_t)proxy->vqs[vdev->queue_sel].avail[1]) << 32 |
359 proxy->vqs[vdev->queue_sel].avail[0],
360 ((uint64_t)proxy->vqs[vdev->queue_sel].used[1]) << 32 |
361 proxy->vqs[vdev->queue_sel].used[0]);
362 proxy->vqs[vdev->queue_sel].enabled = 1;
363 } else {
364 proxy->vqs[vdev->queue_sel].enabled = 0;
365 }
366 break;
7e71da7f 367 case VIRTIO_MMIO_QUEUE_NOTIFY:
87b3bd1c 368 if (value < VIRTIO_QUEUE_MAX) {
4b52530b
PM
369 virtio_queue_notify(vdev, value);
370 }
371 break;
7e71da7f 372 case VIRTIO_MMIO_INTERRUPT_ACK:
d73415a3 373 qatomic_and(&vdev->isr, ~value);
4b52530b
PM
374 virtio_update_irq(vdev);
375 break;
376 case VIRTIO_MMIO_STATUS:
434027ba
YSP
377 if (!(value & VIRTIO_CONFIG_S_DRIVER_OK)) {
378 virtio_mmio_stop_ioeventfd(proxy);
379 }
380
44e687a4
SL
381 if (!proxy->legacy && (value & VIRTIO_CONFIG_S_FEATURES_OK)) {
382 virtio_set_features(vdev,
383 ((uint64_t)proxy->guest_features[1]) << 32 |
384 proxy->guest_features[0]);
385 }
386
4b52530b 387 virtio_set_status(vdev, value & 0xff);
434027ba
YSP
388
389 if (value & VIRTIO_CONFIG_S_DRIVER_OK) {
390 virtio_mmio_start_ioeventfd(proxy);
391 }
392
4b52530b
PM
393 if (vdev->status == 0) {
394 virtio_reset(vdev);
351da832 395 virtio_mmio_soft_reset(proxy);
4b52530b
PM
396 }
397 break;
44e687a4
SL
398 case VIRTIO_MMIO_QUEUE_DESC_LOW:
399 if (proxy->legacy) {
400 qemu_log_mask(LOG_GUEST_ERROR,
401 "%s: write to non-legacy register (0x%"
402 HWADDR_PRIx ") in legacy mode\n",
403 __func__, offset);
404 return;
405 }
406 proxy->vqs[vdev->queue_sel].desc[0] = value;
407 break;
408 case VIRTIO_MMIO_QUEUE_DESC_HIGH:
409 if (proxy->legacy) {
410 qemu_log_mask(LOG_GUEST_ERROR,
411 "%s: write to non-legacy register (0x%"
412 HWADDR_PRIx ") in legacy mode\n",
413 __func__, offset);
414 return;
415 }
416 proxy->vqs[vdev->queue_sel].desc[1] = value;
417 break;
418 case VIRTIO_MMIO_QUEUE_AVAIL_LOW:
419 if (proxy->legacy) {
420 qemu_log_mask(LOG_GUEST_ERROR,
421 "%s: write to non-legacy register (0x%"
422 HWADDR_PRIx ") in legacy mode\n",
423 __func__, offset);
424 return;
425 }
426 proxy->vqs[vdev->queue_sel].avail[0] = value;
427 break;
428 case VIRTIO_MMIO_QUEUE_AVAIL_HIGH:
429 if (proxy->legacy) {
430 qemu_log_mask(LOG_GUEST_ERROR,
431 "%s: write to non-legacy register (0x%"
432 HWADDR_PRIx ") in legacy mode\n",
433 __func__, offset);
434 return;
435 }
436 proxy->vqs[vdev->queue_sel].avail[1] = value;
437 break;
438 case VIRTIO_MMIO_QUEUE_USED_LOW:
439 if (proxy->legacy) {
440 qemu_log_mask(LOG_GUEST_ERROR,
441 "%s: write to non-legacy register (0x%"
442 HWADDR_PRIx ") in legacy mode\n",
443 __func__, offset);
444 return;
445 }
446 proxy->vqs[vdev->queue_sel].used[0] = value;
447 break;
448 case VIRTIO_MMIO_QUEUE_USED_HIGH:
449 if (proxy->legacy) {
450 qemu_log_mask(LOG_GUEST_ERROR,
451 "%s: write to non-legacy register (0x%"
452 HWADDR_PRIx ") in legacy mode\n",
453 __func__, offset);
454 return;
455 }
456 proxy->vqs[vdev->queue_sel].used[1] = value;
457 break;
7e71da7f 458 case VIRTIO_MMIO_MAGIC_VALUE:
4b52530b 459 case VIRTIO_MMIO_VERSION:
7e71da7f
MT
460 case VIRTIO_MMIO_DEVICE_ID:
461 case VIRTIO_MMIO_VENDOR_ID:
462 case VIRTIO_MMIO_DEVICE_FEATURES:
463 case VIRTIO_MMIO_QUEUE_NUM_MAX:
464 case VIRTIO_MMIO_INTERRUPT_STATUS:
44e687a4 465 case VIRTIO_MMIO_CONFIG_GENERATION:
da1804d1 466 qemu_log_mask(LOG_GUEST_ERROR,
44e687a4
SL
467 "%s: write to read-only register (0x%" HWADDR_PRIx ")\n",
468 __func__, offset);
4b52530b
PM
469 break;
470
471 default:
44e687a4
SL
472 qemu_log_mask(LOG_GUEST_ERROR,
473 "%s: bad register offset (0x%" HWADDR_PRIx ")\n",
474 __func__, offset);
4b52530b
PM
475 }
476}
477
44e687a4 478static const MemoryRegionOps virtio_legacy_mem_ops = {
4b52530b
PM
479 .read = virtio_mmio_read,
480 .write = virtio_mmio_write,
481 .endianness = DEVICE_NATIVE_ENDIAN,
482};
483
44e687a4
SL
484static const MemoryRegionOps virtio_mem_ops = {
485 .read = virtio_mmio_read,
486 .write = virtio_mmio_write,
487 .endianness = DEVICE_LITTLE_ENDIAN,
488};
489
4b52530b
PM
490static void virtio_mmio_update_irq(DeviceState *opaque, uint16_t vector)
491{
492 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
06d3dff0 493 VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
4b52530b
PM
494 int level;
495
06d3dff0 496 if (!vdev) {
4b52530b
PM
497 return;
498 }
d73415a3 499 level = (qatomic_read(&vdev->isr) != 0);
da1804d1 500 trace_virtio_mmio_setting_irq(level);
4b52530b
PM
501 qemu_set_irq(proxy->irq, level);
502}
503
4b52530b
PM
504static int virtio_mmio_load_config(DeviceState *opaque, QEMUFile *f)
505{
506 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
507
508 proxy->host_features_sel = qemu_get_be32(f);
509 proxy->guest_features_sel = qemu_get_be32(f);
510 proxy->guest_page_shift = qemu_get_be32(f);
511 return 0;
512}
513
514static void virtio_mmio_save_config(DeviceState *opaque, QEMUFile *f)
515{
516 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
517
518 qemu_put_be32(f, proxy->host_features_sel);
519 qemu_put_be32(f, proxy->guest_features_sel);
520 qemu_put_be32(f, proxy->guest_page_shift);
521}
522
44e687a4
SL
523static const VMStateDescription vmstate_virtio_mmio_queue_state = {
524 .name = "virtio_mmio/queue_state",
525 .version_id = 1,
526 .minimum_version_id = 1,
527 .fields = (VMStateField[]) {
528 VMSTATE_UINT16(num, VirtIOMMIOQueue),
529 VMSTATE_BOOL(enabled, VirtIOMMIOQueue),
530 VMSTATE_UINT32_ARRAY(desc, VirtIOMMIOQueue, 2),
531 VMSTATE_UINT32_ARRAY(avail, VirtIOMMIOQueue, 2),
532 VMSTATE_UINT32_ARRAY(used, VirtIOMMIOQueue, 2),
533 VMSTATE_END_OF_LIST()
534 }
535};
536
537static const VMStateDescription vmstate_virtio_mmio_state_sub = {
538 .name = "virtio_mmio/state",
539 .version_id = 1,
540 .minimum_version_id = 1,
541 .fields = (VMStateField[]) {
542 VMSTATE_UINT32_ARRAY(guest_features, VirtIOMMIOProxy, 2),
543 VMSTATE_STRUCT_ARRAY(vqs, VirtIOMMIOProxy, VIRTIO_QUEUE_MAX, 0,
544 vmstate_virtio_mmio_queue_state,
545 VirtIOMMIOQueue),
546 VMSTATE_END_OF_LIST()
547 }
548};
549
550static const VMStateDescription vmstate_virtio_mmio = {
551 .name = "virtio_mmio",
552 .version_id = 1,
553 .minimum_version_id = 1,
554 .minimum_version_id_old = 1,
555 .fields = (VMStateField[]) {
556 VMSTATE_END_OF_LIST()
557 },
558 .subsections = (const VMStateDescription * []) {
559 &vmstate_virtio_mmio_state_sub,
560 NULL
561 }
562};
563
564static void virtio_mmio_save_extra_state(DeviceState *opaque, QEMUFile *f)
565{
566 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
567
568 vmstate_save_state(f, &vmstate_virtio_mmio, proxy, NULL);
569}
570
571static int virtio_mmio_load_extra_state(DeviceState *opaque, QEMUFile *f)
572{
573 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
574
575 return vmstate_load_state(f, &vmstate_virtio_mmio, proxy, 1);
576}
577
578static bool virtio_mmio_has_extra_state(DeviceState *opaque)
579{
580 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
581
582 return !proxy->legacy;
583}
584
4b52530b
PM
585static void virtio_mmio_reset(DeviceState *d)
586{
587 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
44e687a4 588 int i;
4b52530b 589
434027ba 590 virtio_mmio_stop_ioeventfd(proxy);
4b52530b
PM
591 virtio_bus_reset(&proxy->bus);
592 proxy->host_features_sel = 0;
593 proxy->guest_features_sel = 0;
594 proxy->guest_page_shift = 0;
44e687a4
SL
595
596 if (!proxy->legacy) {
597 proxy->guest_features[0] = proxy->guest_features[1] = 0;
598
599 for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
600 proxy->vqs[i].enabled = 0;
601 proxy->vqs[i].num = 0;
602 proxy->vqs[i].desc[0] = proxy->vqs[i].desc[1] = 0;
603 proxy->vqs[i].avail[0] = proxy->vqs[i].avail[1] = 0;
604 proxy->vqs[i].used[0] = proxy->vqs[i].used[1] = 0;
605 }
606 }
4b52530b
PM
607}
608
434027ba
YSP
609static int virtio_mmio_set_guest_notifier(DeviceState *d, int n, bool assign,
610 bool with_irqfd)
611{
612 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
613 VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
614 VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
615 VirtQueue *vq = virtio_get_queue(vdev, n);
616 EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
617
618 if (assign) {
619 int r = event_notifier_init(notifier, 0);
620 if (r < 0) {
621 return r;
622 }
623 virtio_queue_set_guest_notifier_fd_handler(vq, true, with_irqfd);
624 } else {
625 virtio_queue_set_guest_notifier_fd_handler(vq, false, with_irqfd);
626 event_notifier_cleanup(notifier);
627 }
628
2858bc68 629 if (vdc->guest_notifier_mask && vdev->use_guest_notifier_mask) {
434027ba
YSP
630 vdc->guest_notifier_mask(vdev, n, !assign);
631 }
632
633 return 0;
634}
635
636static int virtio_mmio_set_guest_notifiers(DeviceState *d, int nvqs,
637 bool assign)
638{
639 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
640 VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
641 /* TODO: need to check if kvm-arm supports irqfd */
642 bool with_irqfd = false;
643 int r, n;
644
645 nvqs = MIN(nvqs, VIRTIO_QUEUE_MAX);
646
647 for (n = 0; n < nvqs; n++) {
648 if (!virtio_queue_get_num(vdev, n)) {
649 break;
650 }
651
652 r = virtio_mmio_set_guest_notifier(d, n, assign, with_irqfd);
653 if (r < 0) {
654 goto assign_error;
655 }
656 }
657
658 return 0;
659
660assign_error:
661 /* We get here on assignment failure. Recover by undoing for VQs 0 .. n. */
662 assert(assign);
663 while (--n >= 0) {
664 virtio_mmio_set_guest_notifier(d, n, !assign, false);
665 }
666 return r;
667}
668
44e687a4
SL
669static void virtio_mmio_pre_plugged(DeviceState *d, Error **errp)
670{
671 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
672 VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
673
674 if (!proxy->legacy) {
675 virtio_add_feature(&vdev->host_features, VIRTIO_F_VERSION_1);
676 }
677}
678
4b52530b
PM
679/* virtio-mmio device */
680
f58b39d2
LE
681static Property virtio_mmio_properties[] = {
682 DEFINE_PROP_BOOL("format_transport_address", VirtIOMMIOProxy,
683 format_transport_address, true),
44e687a4 684 DEFINE_PROP_BOOL("force-legacy", VirtIOMMIOProxy, legacy, true),
f58b39d2
LE
685 DEFINE_PROP_END_OF_LIST(),
686};
687
4b52530b
PM
688static void virtio_mmio_realizefn(DeviceState *d, Error **errp)
689{
690 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
691 SysBusDevice *sbd = SYS_BUS_DEVICE(d);
692
2f4f6035
IM
693 qbus_create_inplace(&proxy->bus, sizeof(proxy->bus), TYPE_VIRTIO_MMIO_BUS,
694 d, NULL);
4b52530b 695 sysbus_init_irq(sbd, &proxy->irq);
44e687a4
SL
696 if (proxy->legacy) {
697 memory_region_init_io(&proxy->iomem, OBJECT(d),
698 &virtio_legacy_mem_ops, proxy,
699 TYPE_VIRTIO_MMIO, 0x200);
700 } else {
701 memory_region_init_io(&proxy->iomem, OBJECT(d),
702 &virtio_mem_ops, proxy,
703 TYPE_VIRTIO_MMIO, 0x200);
704 }
4b52530b
PM
705 sysbus_init_mmio(sbd, &proxy->iomem);
706}
707
708static void virtio_mmio_class_init(ObjectClass *klass, void *data)
709{
710 DeviceClass *dc = DEVICE_CLASS(klass);
711
712 dc->realize = virtio_mmio_realizefn;
713 dc->reset = virtio_mmio_reset;
125ee0ed 714 set_bit(DEVICE_CATEGORY_MISC, dc->categories);
4f67d30b 715 device_class_set_props(dc, virtio_mmio_properties);
4b52530b
PM
716}
717
718static const TypeInfo virtio_mmio_info = {
719 .name = TYPE_VIRTIO_MMIO,
720 .parent = TYPE_SYS_BUS_DEVICE,
721 .instance_size = sizeof(VirtIOMMIOProxy),
722 .class_init = virtio_mmio_class_init,
723};
724
725/* virtio-mmio-bus. */
726
f58b39d2
LE
727static char *virtio_mmio_bus_get_dev_path(DeviceState *dev)
728{
729 BusState *virtio_mmio_bus;
730 VirtIOMMIOProxy *virtio_mmio_proxy;
731 char *proxy_path;
732 SysBusDevice *proxy_sbd;
733 char *path;
734
735 virtio_mmio_bus = qdev_get_parent_bus(dev);
736 virtio_mmio_proxy = VIRTIO_MMIO(virtio_mmio_bus->parent);
737 proxy_path = qdev_get_dev_path(DEVICE(virtio_mmio_proxy));
738
739 /*
740 * If @format_transport_address is false, then we just perform the same as
741 * virtio_bus_get_dev_path(): we delegate the address formatting for the
742 * device on the virtio-mmio bus to the bus that the virtio-mmio proxy
743 * (i.e., the device that implements the virtio-mmio bus) resides on. In
744 * this case the base address of the virtio-mmio transport will be
745 * invisible.
746 */
747 if (!virtio_mmio_proxy->format_transport_address) {
748 return proxy_path;
749 }
750
751 /* Otherwise, we append the base address of the transport. */
752 proxy_sbd = SYS_BUS_DEVICE(virtio_mmio_proxy);
753 assert(proxy_sbd->num_mmio == 1);
754 assert(proxy_sbd->mmio[0].memory == &virtio_mmio_proxy->iomem);
755
756 if (proxy_path) {
757 path = g_strdup_printf("%s/virtio-mmio@" TARGET_FMT_plx, proxy_path,
758 proxy_sbd->mmio[0].addr);
759 } else {
760 path = g_strdup_printf("virtio-mmio@" TARGET_FMT_plx,
761 proxy_sbd->mmio[0].addr);
762 }
763 g_free(proxy_path);
764 return path;
765}
766
4b52530b
PM
767static void virtio_mmio_bus_class_init(ObjectClass *klass, void *data)
768{
769 BusClass *bus_class = BUS_CLASS(klass);
770 VirtioBusClass *k = VIRTIO_BUS_CLASS(klass);
771
772 k->notify = virtio_mmio_update_irq;
773 k->save_config = virtio_mmio_save_config;
774 k->load_config = virtio_mmio_load_config;
44e687a4
SL
775 k->save_extra_state = virtio_mmio_save_extra_state;
776 k->load_extra_state = virtio_mmio_load_extra_state;
777 k->has_extra_state = virtio_mmio_has_extra_state;
434027ba 778 k->set_guest_notifiers = virtio_mmio_set_guest_notifiers;
8e93cef1 779 k->ioeventfd_enabled = virtio_mmio_ioeventfd_enabled;
c0971bcb 780 k->ioeventfd_assign = virtio_mmio_ioeventfd_assign;
44e687a4 781 k->pre_plugged = virtio_mmio_pre_plugged;
4b52530b
PM
782 k->has_variable_vring_alignment = true;
783 bus_class->max_dev = 1;
f58b39d2 784 bus_class->get_dev_path = virtio_mmio_bus_get_dev_path;
4b52530b
PM
785}
786
787static const TypeInfo virtio_mmio_bus_info = {
788 .name = TYPE_VIRTIO_MMIO_BUS,
789 .parent = TYPE_VIRTIO_BUS,
790 .instance_size = sizeof(VirtioBusState),
791 .class_init = virtio_mmio_bus_class_init,
792};
793
794static void virtio_mmio_register_types(void)
795{
796 type_register_static(&virtio_mmio_bus_info);
797 type_register_static(&virtio_mmio_info);
798}
799
800type_init(virtio_mmio_register_types)