Commit 53c25cea7d59525ca9aa3fb01cc6947bafbbfb61
1 parent
d8ee7665
Separate virtio PCI code
Split the PCI host bindings from the VRing transport implementation. Signed-off-by: Paul Brook <paul@codesourcery.com>
Showing
14 changed files
with
474 additions
and
300 deletions
Makefile.target
@@ -489,7 +489,8 @@ OBJS=vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o machine.o dma-helpers.o \ | @@ -489,7 +489,8 @@ OBJS=vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o machine.o dma-helpers.o \ | ||
489 | gdbstub.o gdbstub-xml.o sysbus.o | 489 | gdbstub.o gdbstub-xml.o sysbus.o |
490 | # virtio has to be here due to weird dependency between PCI and virtio-net. | 490 | # virtio has to be here due to weird dependency between PCI and virtio-net. |
491 | # need to fix this properly | 491 | # need to fix this properly |
492 | -OBJS+=virtio.o virtio-blk.o virtio-balloon.o virtio-net.o virtio-console.o | 492 | +OBJS+=virtio.o virtio-pci.o |
493 | +OBJS+=virtio-blk.o virtio-balloon.o virtio-net.o virtio-console.o | ||
493 | OBJS+=fw_cfg.o | 494 | OBJS+=fw_cfg.o |
494 | ifdef CONFIG_KVM | 495 | ifdef CONFIG_KVM |
495 | OBJS+=kvm.o kvm-all.o | 496 | OBJS+=kvm.o kvm-all.o |
hw/pc.c
@@ -1137,21 +1137,21 @@ static void pc_init1(ram_addr_t ram_size, | @@ -1137,21 +1137,21 @@ static void pc_init1(ram_addr_t ram_size, | ||
1137 | int unit_id = 0; | 1137 | int unit_id = 0; |
1138 | 1138 | ||
1139 | while ((index = drive_get_index(IF_VIRTIO, 0, unit_id)) != -1) { | 1139 | while ((index = drive_get_index(IF_VIRTIO, 0, unit_id)) != -1) { |
1140 | - pci_create_simple(pci_bus, -1, "virtio-blk"); | 1140 | + pci_create_simple(pci_bus, -1, "virtio-blk-pci"); |
1141 | unit_id++; | 1141 | unit_id++; |
1142 | } | 1142 | } |
1143 | } | 1143 | } |
1144 | 1144 | ||
1145 | /* Add virtio balloon device */ | 1145 | /* Add virtio balloon device */ |
1146 | if (pci_enabled) { | 1146 | if (pci_enabled) { |
1147 | - pci_create_simple(pci_bus, -1, "virtio-balloon"); | 1147 | + pci_create_simple(pci_bus, -1, "virtio-balloon-pci"); |
1148 | } | 1148 | } |
1149 | 1149 | ||
1150 | /* Add virtio console devices */ | 1150 | /* Add virtio console devices */ |
1151 | if (pci_enabled) { | 1151 | if (pci_enabled) { |
1152 | for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) { | 1152 | for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) { |
1153 | if (virtcon_hds[i]) { | 1153 | if (virtcon_hds[i]) { |
1154 | - pci_create_simple(pci_bus, -1, "virtio-console"); | 1154 | + pci_create_simple(pci_bus, -1, "virtio-console-pci"); |
1155 | } | 1155 | } |
1156 | } | 1156 | } |
1157 | } | 1157 | } |
hw/pci-hotplug.c
@@ -120,7 +120,7 @@ static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon, PCIBus *pci_bus, | @@ -120,7 +120,7 @@ static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon, PCIBus *pci_bus, | ||
120 | opaque = pci_create_simple(pci_bus, -1, "lsi53c895a"); | 120 | opaque = pci_create_simple(pci_bus, -1, "lsi53c895a"); |
121 | break; | 121 | break; |
122 | case IF_VIRTIO: | 122 | case IF_VIRTIO: |
123 | - opaque = pci_create_simple(pci_bus, -1, "virtio-blk"); | 123 | + opaque = pci_create_simple(pci_bus, -1, "virtio-blk-pci"); |
124 | qdev_init(opaque); | 124 | qdev_init(opaque); |
125 | break; | 125 | break; |
126 | } | 126 | } |
hw/pci.c
hw/ppc440_bamboo.c
@@ -111,14 +111,14 @@ static void bamboo_init(ram_addr_t ram_size, | @@ -111,14 +111,14 @@ static void bamboo_init(ram_addr_t ram_size, | ||
111 | 111 | ||
112 | /* Add virtio block devices. */ | 112 | /* Add virtio block devices. */ |
113 | while ((i = drive_get_index(IF_VIRTIO, 0, unit_id)) != -1) { | 113 | while ((i = drive_get_index(IF_VIRTIO, 0, unit_id)) != -1) { |
114 | - pci_create_simple(pcibus, -1, "virtio-blk"); | 114 | + pci_create_simple(pcibus, -1, "virtio-blk-pci"); |
115 | unit_id++; | 115 | unit_id++; |
116 | } | 116 | } |
117 | 117 | ||
118 | /* Add virtio console devices */ | 118 | /* Add virtio console devices */ |
119 | for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) { | 119 | for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) { |
120 | if (virtcon_hds[i]) { | 120 | if (virtcon_hds[i]) { |
121 | - pci_create_simple(pcibus, -1, "virtio-console"); | 121 | + pci_create_simple(pcibus, -1, "virtio-console-pci"); |
122 | } | 122 | } |
123 | } | 123 | } |
124 | 124 |
hw/ppce500_mpc8544ds.c
@@ -220,7 +220,7 @@ static void mpc8544ds_init(ram_addr_t ram_size, | @@ -220,7 +220,7 @@ static void mpc8544ds_init(ram_addr_t ram_size, | ||
220 | 220 | ||
221 | /* Add virtio block devices. */ | 221 | /* Add virtio block devices. */ |
222 | while ((i = drive_get_index(IF_VIRTIO, 0, unit_id)) != -1) { | 222 | while ((i = drive_get_index(IF_VIRTIO, 0, unit_id)) != -1) { |
223 | - pci_create_simple(pci_bus, -1, "virtio-blk"); | 223 | + pci_create_simple(pci_bus, -1, "virtio-blk-pci"); |
224 | unit_id++; | 224 | unit_id++; |
225 | } | 225 | } |
226 | 226 |
hw/virtio-balloon.c
@@ -169,17 +169,13 @@ static int virtio_balloon_load(QEMUFile *f, void *opaque, int version_id) | @@ -169,17 +169,13 @@ static int virtio_balloon_load(QEMUFile *f, void *opaque, int version_id) | ||
169 | return 0; | 169 | return 0; |
170 | } | 170 | } |
171 | 171 | ||
172 | -static void virtio_balloon_init(PCIDevice *pci_dev) | 172 | +VirtIODevice *virtio_balloon_init(DeviceState *dev) |
173 | { | 173 | { |
174 | VirtIOBalloon *s; | 174 | VirtIOBalloon *s; |
175 | 175 | ||
176 | - s = (VirtIOBalloon *)virtio_init_pci(pci_dev, "virtio-balloon", | ||
177 | - PCI_VENDOR_ID_REDHAT_QUMRANET, | ||
178 | - PCI_DEVICE_ID_VIRTIO_BALLOON, | ||
179 | - PCI_VENDOR_ID_REDHAT_QUMRANET, | ||
180 | - VIRTIO_ID_BALLOON, | ||
181 | - PCI_CLASS_MEMORY_RAM, 0x00, | ||
182 | - 8); | 176 | + s = (VirtIOBalloon *)virtio_common_init("virtio-balloon", |
177 | + VIRTIO_ID_BALLOON, | ||
178 | + 8, sizeof(VirtIOBalloon)); | ||
183 | 179 | ||
184 | s->vdev.get_config = virtio_balloon_get_config; | 180 | s->vdev.get_config = virtio_balloon_get_config; |
185 | s->vdev.set_config = virtio_balloon_set_config; | 181 | s->vdev.set_config = virtio_balloon_set_config; |
@@ -191,12 +187,6 @@ static void virtio_balloon_init(PCIDevice *pci_dev) | @@ -191,12 +187,6 @@ static void virtio_balloon_init(PCIDevice *pci_dev) | ||
191 | qemu_add_balloon_handler(virtio_balloon_to_target, s); | 187 | qemu_add_balloon_handler(virtio_balloon_to_target, s); |
192 | 188 | ||
193 | register_savevm("virtio-balloon", -1, 1, virtio_balloon_save, virtio_balloon_load, s); | 189 | register_savevm("virtio-balloon", -1, 1, virtio_balloon_save, virtio_balloon_load, s); |
194 | -} | ||
195 | 190 | ||
196 | -static void virtio_balloon_register_devices(void) | ||
197 | -{ | ||
198 | - pci_qdev_register("virtio-balloon", sizeof(VirtIOBalloon), | ||
199 | - virtio_balloon_init); | 191 | + return &s->vdev; |
200 | } | 192 | } |
201 | - | ||
202 | -device_init(virtio_balloon_register_devices) |
hw/virtio-blk.c
@@ -348,28 +348,24 @@ static int virtio_blk_load(QEMUFile *f, void *opaque, int version_id) | @@ -348,28 +348,24 @@ static int virtio_blk_load(QEMUFile *f, void *opaque, int version_id) | ||
348 | return 0; | 348 | return 0; |
349 | } | 349 | } |
350 | 350 | ||
351 | -static void virtio_blk_init(PCIDevice *pci_dev) | 351 | +VirtIODevice *virtio_blk_init(DeviceState *dev) |
352 | { | 352 | { |
353 | VirtIOBlock *s; | 353 | VirtIOBlock *s; |
354 | int cylinders, heads, secs; | 354 | int cylinders, heads, secs; |
355 | static int virtio_blk_id; | 355 | static int virtio_blk_id; |
356 | BlockDriverState *bs; | 356 | BlockDriverState *bs; |
357 | 357 | ||
358 | - s = (VirtIOBlock *)virtio_init_pci(pci_dev, "virtio-blk", | ||
359 | - PCI_VENDOR_ID_REDHAT_QUMRANET, | ||
360 | - PCI_DEVICE_ID_VIRTIO_BLOCK, | ||
361 | - PCI_VENDOR_ID_REDHAT_QUMRANET, | ||
362 | - VIRTIO_ID_BLOCK, | ||
363 | - PCI_CLASS_STORAGE_OTHER, 0x00, | ||
364 | - sizeof(struct virtio_blk_config)); | 358 | + s = (VirtIOBlock *)virtio_common_init("virtio-blk", VIRTIO_ID_BLOCK, |
359 | + sizeof(struct virtio_blk_config), | ||
360 | + sizeof(VirtIOBlock)); | ||
365 | 361 | ||
366 | - bs = qdev_init_bdrv(&pci_dev->qdev, IF_VIRTIO); | 362 | + bs = qdev_init_bdrv(dev, IF_VIRTIO); |
367 | s->vdev.get_config = virtio_blk_update_config; | 363 | s->vdev.get_config = virtio_blk_update_config; |
368 | s->vdev.get_features = virtio_blk_get_features; | 364 | s->vdev.get_features = virtio_blk_get_features; |
369 | s->vdev.reset = virtio_blk_reset; | 365 | s->vdev.reset = virtio_blk_reset; |
370 | s->bs = bs; | 366 | s->bs = bs; |
371 | s->rq = NULL; | 367 | s->rq = NULL; |
372 | - bs->private = &s->vdev.pci_dev; | 368 | + bs->private = dev; |
373 | bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs); | 369 | bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs); |
374 | bdrv_set_geometry_hint(s->bs, cylinders, heads, secs); | 370 | bdrv_set_geometry_hint(s->bs, cylinders, heads, secs); |
375 | 371 | ||
@@ -378,11 +374,6 @@ static void virtio_blk_init(PCIDevice *pci_dev) | @@ -378,11 +374,6 @@ static void virtio_blk_init(PCIDevice *pci_dev) | ||
378 | qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s); | 374 | qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s); |
379 | register_savevm("virtio-blk", virtio_blk_id++, 2, | 375 | register_savevm("virtio-blk", virtio_blk_id++, 2, |
380 | virtio_blk_save, virtio_blk_load, s); | 376 | virtio_blk_save, virtio_blk_load, s); |
381 | -} | ||
382 | 377 | ||
383 | -static void virtio_blk_register_devices(void) | ||
384 | -{ | ||
385 | - pci_qdev_register("virtio-blk", sizeof(VirtIOBlock), virtio_blk_init); | 378 | + return &s->vdev; |
386 | } | 379 | } |
387 | - | ||
388 | -device_init(virtio_blk_register_devices) |
hw/virtio-blk.h
hw/virtio-console.c
@@ -123,31 +123,21 @@ static int virtio_console_load(QEMUFile *f, void *opaque, int version_id) | @@ -123,31 +123,21 @@ static int virtio_console_load(QEMUFile *f, void *opaque, int version_id) | ||
123 | return 0; | 123 | return 0; |
124 | } | 124 | } |
125 | 125 | ||
126 | -static void virtio_console_init(PCIDevice *pci_dev) | 126 | +VirtIODevice *virtio_console_init(DeviceState *dev) |
127 | { | 127 | { |
128 | VirtIOConsole *s; | 128 | VirtIOConsole *s; |
129 | - s = (VirtIOConsole *)virtio_init_pci(pci_dev, "virtio-console", | ||
130 | - PCI_VENDOR_ID_REDHAT_QUMRANET, | ||
131 | - PCI_DEVICE_ID_VIRTIO_CONSOLE, | ||
132 | - PCI_VENDOR_ID_REDHAT_QUMRANET, | ||
133 | - VIRTIO_ID_CONSOLE, | ||
134 | - PCI_CLASS_DISPLAY_OTHER, 0x00, | ||
135 | - 0); | 129 | + s = (VirtIOConsole *)virtio_common_init("virtio-console", |
130 | + VIRTIO_ID_CONSOLE, | ||
131 | + 0, sizeof(VirtIOConsole)); | ||
136 | s->vdev.get_features = virtio_console_get_features; | 132 | s->vdev.get_features = virtio_console_get_features; |
137 | 133 | ||
138 | s->ivq = virtio_add_queue(&s->vdev, 128, virtio_console_handle_input); | 134 | s->ivq = virtio_add_queue(&s->vdev, 128, virtio_console_handle_input); |
139 | s->dvq = virtio_add_queue(&s->vdev, 128, virtio_console_handle_output); | 135 | s->dvq = virtio_add_queue(&s->vdev, 128, virtio_console_handle_output); |
140 | 136 | ||
141 | - s->chr = qdev_init_chardev(&pci_dev->qdev); | 137 | + s->chr = qdev_init_chardev(dev); |
142 | qemu_chr_add_handlers(s->chr, vcon_can_read, vcon_read, vcon_event, s); | 138 | qemu_chr_add_handlers(s->chr, vcon_can_read, vcon_read, vcon_event, s); |
143 | 139 | ||
144 | register_savevm("virtio-console", -1, 1, virtio_console_save, virtio_console_load, s); | 140 | register_savevm("virtio-console", -1, 1, virtio_console_save, virtio_console_load, s); |
145 | -} | ||
146 | 141 | ||
147 | -static void virtio_console_register_devices(void) | ||
148 | -{ | ||
149 | - pci_qdev_register("virtio-console", sizeof(VirtIOConsole), | ||
150 | - virtio_console_init); | 142 | + return &s->vdev; |
151 | } | 143 | } |
152 | - | ||
153 | -device_init(virtio_console_register_devices) |
hw/virtio-net.c
@@ -585,18 +585,14 @@ static void virtio_net_cleanup(VLANClientState *vc) | @@ -585,18 +585,14 @@ static void virtio_net_cleanup(VLANClientState *vc) | ||
585 | virtio_cleanup(&n->vdev); | 585 | virtio_cleanup(&n->vdev); |
586 | } | 586 | } |
587 | 587 | ||
588 | -static void virtio_net_init(PCIDevice *pci_dev) | 588 | +VirtIODevice *virtio_net_init(DeviceState *dev) |
589 | { | 589 | { |
590 | VirtIONet *n; | 590 | VirtIONet *n; |
591 | static int virtio_net_id; | 591 | static int virtio_net_id; |
592 | 592 | ||
593 | - n = (VirtIONet *)virtio_init_pci(pci_dev, "virtio-net", | ||
594 | - PCI_VENDOR_ID_REDHAT_QUMRANET, | ||
595 | - PCI_DEVICE_ID_VIRTIO_NET, | ||
596 | - PCI_VENDOR_ID_REDHAT_QUMRANET, | ||
597 | - VIRTIO_ID_NET, | ||
598 | - PCI_CLASS_NETWORK_ETHERNET, 0x00, | ||
599 | - sizeof(struct virtio_net_config)); | 593 | + n = (VirtIONet *)virtio_common_init("virtio-net", VIRTIO_ID_NET, |
594 | + sizeof(struct virtio_net_config), | ||
595 | + sizeof(VirtIONet)); | ||
600 | 596 | ||
601 | n->vdev.get_config = virtio_net_get_config; | 597 | n->vdev.get_config = virtio_net_get_config; |
602 | n->vdev.set_config = virtio_net_set_config; | 598 | n->vdev.set_config = virtio_net_set_config; |
@@ -607,9 +603,9 @@ static void virtio_net_init(PCIDevice *pci_dev) | @@ -607,9 +603,9 @@ static void virtio_net_init(PCIDevice *pci_dev) | ||
607 | n->rx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_rx); | 603 | n->rx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_rx); |
608 | n->tx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_tx); | 604 | n->tx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_tx); |
609 | n->ctrl_vq = virtio_add_queue(&n->vdev, 16, virtio_net_handle_ctrl); | 605 | n->ctrl_vq = virtio_add_queue(&n->vdev, 16, virtio_net_handle_ctrl); |
610 | - qdev_get_macaddr(&pci_dev->qdev, n->mac); | 606 | + qdev_get_macaddr(dev, n->mac); |
611 | n->status = VIRTIO_NET_S_LINK_UP; | 607 | n->status = VIRTIO_NET_S_LINK_UP; |
612 | - n->vc = qdev_get_vlan_client(&pci_dev->qdev, | 608 | + n->vc = qdev_get_vlan_client(dev, |
613 | virtio_net_receive, | 609 | virtio_net_receive, |
614 | virtio_net_can_receive, | 610 | virtio_net_can_receive, |
615 | virtio_net_cleanup, n); | 611 | virtio_net_cleanup, n); |
@@ -628,11 +624,6 @@ static void virtio_net_init(PCIDevice *pci_dev) | @@ -628,11 +624,6 @@ static void virtio_net_init(PCIDevice *pci_dev) | ||
628 | 624 | ||
629 | register_savevm("virtio-net", virtio_net_id++, VIRTIO_NET_VM_VERSION, | 625 | register_savevm("virtio-net", virtio_net_id++, VIRTIO_NET_VM_VERSION, |
630 | virtio_net_save, virtio_net_load, n); | 626 | virtio_net_save, virtio_net_load, n); |
631 | -} | ||
632 | 627 | ||
633 | -static void virtio_net_register_devices(void) | ||
634 | -{ | ||
635 | - pci_qdev_register("virtio_net", sizeof(VirtIONet), virtio_net_init); | 628 | + return &n->vdev; |
636 | } | 629 | } |
637 | - | ||
638 | -device_init(virtio_net_register_devices) |
hw/virtio-pci.c
0 โ 100644
1 | +/* | ||
2 | + * Virtio PCI Bindings | ||
3 | + * | ||
4 | + * Copyright IBM, Corp. 2007 | ||
5 | + * Copyright (c) 2009 CodeSourcery | ||
6 | + * | ||
7 | + * Authors: | ||
8 | + * Anthony Liguori <aliguori@us.ibm.com> | ||
9 | + * Paul Brook <paul@codesourcery.com> | ||
10 | + * | ||
11 | + * This work is licensed under the terms of the GNU GPL, version 2. See | ||
12 | + * the COPYING file in the top-level directory. | ||
13 | + * | ||
14 | + */ | ||
15 | + | ||
16 | +#include <inttypes.h> | ||
17 | + | ||
18 | +#include "virtio.h" | ||
19 | +#include "pci.h" | ||
20 | +#include "sysemu.h" | ||
21 | + | ||
22 | +/* from Linux's linux/virtio_pci.h */ | ||
23 | + | ||
24 | +/* A 32-bit r/o bitmask of the features supported by the host */ | ||
25 | +#define VIRTIO_PCI_HOST_FEATURES 0 | ||
26 | + | ||
27 | +/* A 32-bit r/w bitmask of features activated by the guest */ | ||
28 | +#define VIRTIO_PCI_GUEST_FEATURES 4 | ||
29 | + | ||
30 | +/* A 32-bit r/w PFN for the currently selected queue */ | ||
31 | +#define VIRTIO_PCI_QUEUE_PFN 8 | ||
32 | + | ||
33 | +/* A 16-bit r/o queue size for the currently selected queue */ | ||
34 | +#define VIRTIO_PCI_QUEUE_NUM 12 | ||
35 | + | ||
36 | +/* A 16-bit r/w queue selector */ | ||
37 | +#define VIRTIO_PCI_QUEUE_SEL 14 | ||
38 | + | ||
39 | +/* A 16-bit r/w queue notifier */ | ||
40 | +#define VIRTIO_PCI_QUEUE_NOTIFY 16 | ||
41 | + | ||
42 | +/* An 8-bit device status register. */ | ||
43 | +#define VIRTIO_PCI_STATUS 18 | ||
44 | + | ||
45 | +/* An 8-bit r/o interrupt status register. Reading the value will return the | ||
46 | + * current contents of the ISR and will also clear it. This is effectively | ||
47 | + * a read-and-acknowledge. */ | ||
48 | +#define VIRTIO_PCI_ISR 19 | ||
49 | + | ||
50 | +#define VIRTIO_PCI_CONFIG 20 | ||
51 | + | ||
52 | +/* Virtio ABI version, if we increment this, we break the guest driver. */ | ||
53 | +#define VIRTIO_PCI_ABI_VERSION 0 | ||
54 | + | ||
55 | +/* How many bits to shift physical queue address written to QUEUE_PFN. | ||
56 | + * 12 is historical, and due to x86 page size. */ | ||
57 | +#define VIRTIO_PCI_QUEUE_ADDR_SHIFT 12 | ||
58 | + | ||
59 | +/* QEMU doesn't strictly need write barriers since everything runs in | ||
60 | + * lock-step. We'll leave the calls to wmb() in though to make it obvious for | ||
61 | + * KVM or if kqemu gets SMP support. | ||
62 | + */ | ||
63 | +#define wmb() do { } while (0) | ||
64 | + | ||
65 | +/* PCI bindings. */ | ||
66 | + | ||
67 | +typedef struct { | ||
68 | + PCIDevice pci_dev; | ||
69 | + VirtIODevice *vdev; | ||
70 | + uint32_t addr; | ||
71 | + | ||
72 | + uint16_t vendor; | ||
73 | + uint16_t device; | ||
74 | + uint16_t subvendor; | ||
75 | + uint16_t class_code; | ||
76 | + uint8_t pif; | ||
77 | +} VirtIOPCIProxy; | ||
78 | + | ||
79 | +/* virtio device */ | ||
80 | + | ||
81 | +static void virtio_pci_update_irq(void *opaque) | ||
82 | +{ | ||
83 | + VirtIOPCIProxy *proxy = opaque; | ||
84 | + | ||
85 | + qemu_set_irq(proxy->pci_dev.irq[0], proxy->vdev->isr & 1); | ||
86 | +} | ||
87 | + | ||
88 | +static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val) | ||
89 | +{ | ||
90 | + VirtIOPCIProxy *proxy = opaque; | ||
91 | + VirtIODevice *vdev = proxy->vdev; | ||
92 | + target_phys_addr_t pa; | ||
93 | + | ||
94 | + addr -= proxy->addr; | ||
95 | + | ||
96 | + switch (addr) { | ||
97 | + case VIRTIO_PCI_GUEST_FEATURES: | ||
98 | + /* Guest does not negotiate properly? We have to assume nothing. */ | ||
99 | + if (val & (1 << VIRTIO_F_BAD_FEATURE)) { | ||
100 | + if (vdev->bad_features) | ||
101 | + val = vdev->bad_features(vdev); | ||
102 | + else | ||
103 | + val = 0; | ||
104 | + } | ||
105 | + if (vdev->set_features) | ||
106 | + vdev->set_features(vdev, val); | ||
107 | + vdev->features = val; | ||
108 | + break; | ||
109 | + case VIRTIO_PCI_QUEUE_PFN: | ||
110 | + pa = (target_phys_addr_t)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT; | ||
111 | + virtio_queue_set_addr(vdev, vdev->queue_sel, pa); | ||
112 | + break; | ||
113 | + case VIRTIO_PCI_QUEUE_SEL: | ||
114 | + if (val < VIRTIO_PCI_QUEUE_MAX) | ||
115 | + vdev->queue_sel = val; | ||
116 | + break; | ||
117 | + case VIRTIO_PCI_QUEUE_NOTIFY: | ||
118 | + virtio_queue_notify(vdev, val); | ||
119 | + break; | ||
120 | + case VIRTIO_PCI_STATUS: | ||
121 | + vdev->status = val & 0xFF; | ||
122 | + if (vdev->status == 0) | ||
123 | + virtio_reset(vdev); | ||
124 | + break; | ||
125 | + } | ||
126 | +} | ||
127 | + | ||
128 | +static uint32_t virtio_ioport_read(void *opaque, uint32_t addr) | ||
129 | +{ | ||
130 | + VirtIOPCIProxy *proxy = opaque; | ||
131 | + VirtIODevice *vdev = proxy->vdev; | ||
132 | + uint32_t ret = 0xFFFFFFFF; | ||
133 | + | ||
134 | + addr -= proxy->addr; | ||
135 | + | ||
136 | + switch (addr) { | ||
137 | + case VIRTIO_PCI_HOST_FEATURES: | ||
138 | + ret = vdev->get_features(vdev); | ||
139 | + ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY) | (1 << VIRTIO_F_BAD_FEATURE); | ||
140 | + break; | ||
141 | + case VIRTIO_PCI_GUEST_FEATURES: | ||
142 | + ret = vdev->features; | ||
143 | + break; | ||
144 | + case VIRTIO_PCI_QUEUE_PFN: | ||
145 | + ret = virtio_queue_get_addr(vdev, vdev->queue_sel) | ||
146 | + >> VIRTIO_PCI_QUEUE_ADDR_SHIFT; | ||
147 | + break; | ||
148 | + case VIRTIO_PCI_QUEUE_NUM: | ||
149 | + ret = virtio_queue_get_num(vdev, vdev->queue_sel); | ||
150 | + break; | ||
151 | + case VIRTIO_PCI_QUEUE_SEL: | ||
152 | + ret = vdev->queue_sel; | ||
153 | + break; | ||
154 | + case VIRTIO_PCI_STATUS: | ||
155 | + ret = vdev->status; | ||
156 | + break; | ||
157 | + case VIRTIO_PCI_ISR: | ||
158 | + /* reading from the ISR also clears it. */ | ||
159 | + ret = vdev->isr; | ||
160 | + vdev->isr = 0; | ||
161 | + virtio_update_irq(vdev); | ||
162 | + break; | ||
163 | + default: | ||
164 | + break; | ||
165 | + } | ||
166 | + | ||
167 | + return ret; | ||
168 | +} | ||
169 | + | ||
170 | +static uint32_t virtio_pci_config_readb(void *opaque, uint32_t addr) | ||
171 | +{ | ||
172 | + VirtIOPCIProxy *proxy = opaque; | ||
173 | + addr -= proxy->addr + VIRTIO_PCI_CONFIG; | ||
174 | + return virtio_config_readb(proxy->vdev, addr); | ||
175 | +} | ||
176 | + | ||
177 | +static uint32_t virtio_pci_config_readw(void *opaque, uint32_t addr) | ||
178 | +{ | ||
179 | + VirtIOPCIProxy *proxy = opaque; | ||
180 | + addr -= proxy->addr + VIRTIO_PCI_CONFIG; | ||
181 | + return virtio_config_readw(proxy->vdev, addr); | ||
182 | +} | ||
183 | + | ||
184 | +static uint32_t virtio_pci_config_readl(void *opaque, uint32_t addr) | ||
185 | +{ | ||
186 | + VirtIOPCIProxy *proxy = opaque; | ||
187 | + addr -= proxy->addr + VIRTIO_PCI_CONFIG; | ||
188 | + return virtio_config_readl(proxy->vdev, addr); | ||
189 | +} | ||
190 | + | ||
191 | +static void virtio_pci_config_writeb(void *opaque, uint32_t addr, uint32_t val) | ||
192 | +{ | ||
193 | + VirtIOPCIProxy *proxy = opaque; | ||
194 | + addr -= proxy->addr + VIRTIO_PCI_CONFIG; | ||
195 | + virtio_config_writeb(proxy->vdev, addr, val); | ||
196 | +} | ||
197 | + | ||
198 | +static void virtio_pci_config_writew(void *opaque, uint32_t addr, uint32_t val) | ||
199 | +{ | ||
200 | + VirtIOPCIProxy *proxy = opaque; | ||
201 | + addr -= proxy->addr + VIRTIO_PCI_CONFIG; | ||
202 | + virtio_config_writew(proxy->vdev, addr, val); | ||
203 | +} | ||
204 | + | ||
205 | +static void virtio_pci_config_writel(void *opaque, uint32_t addr, uint32_t val) | ||
206 | +{ | ||
207 | + VirtIOPCIProxy *proxy = opaque; | ||
208 | + addr -= proxy->addr + VIRTIO_PCI_CONFIG; | ||
209 | + virtio_config_writel(proxy->vdev, addr, val); | ||
210 | +} | ||
211 | + | ||
212 | +static void virtio_map(PCIDevice *pci_dev, int region_num, | ||
213 | + uint32_t addr, uint32_t size, int type) | ||
214 | +{ | ||
215 | + VirtIOPCIProxy *proxy = container_of(pci_dev, VirtIOPCIProxy, pci_dev); | ||
216 | + VirtIODevice *vdev = proxy->vdev; | ||
217 | + int i; | ||
218 | + | ||
219 | + proxy->addr = addr; | ||
220 | + for (i = 0; i < 3; i++) { | ||
221 | + register_ioport_write(addr, VIRTIO_PCI_CONFIG, 1 << i, | ||
222 | + virtio_ioport_write, proxy); | ||
223 | + register_ioport_read(addr, VIRTIO_PCI_CONFIG, 1 << i, | ||
224 | + virtio_ioport_read, proxy); | ||
225 | + } | ||
226 | + | ||
227 | + if (vdev->config_len) { | ||
228 | + register_ioport_write(addr + VIRTIO_PCI_CONFIG, vdev->config_len, 1, | ||
229 | + virtio_pci_config_writeb, proxy); | ||
230 | + register_ioport_write(addr + VIRTIO_PCI_CONFIG, vdev->config_len, 2, | ||
231 | + virtio_pci_config_writew, proxy); | ||
232 | + register_ioport_write(addr + VIRTIO_PCI_CONFIG, vdev->config_len, 4, | ||
233 | + virtio_pci_config_writel, proxy); | ||
234 | + register_ioport_read(addr + VIRTIO_PCI_CONFIG, vdev->config_len, 1, | ||
235 | + virtio_pci_config_readb, proxy); | ||
236 | + register_ioport_read(addr + VIRTIO_PCI_CONFIG, vdev->config_len, 2, | ||
237 | + virtio_pci_config_readw, proxy); | ||
238 | + register_ioport_read(addr + VIRTIO_PCI_CONFIG, vdev->config_len, 4, | ||
239 | + virtio_pci_config_readl, proxy); | ||
240 | + | ||
241 | + vdev->get_config(vdev, vdev->config); | ||
242 | + } | ||
243 | +} | ||
244 | + | ||
245 | +static const VirtIOBindings virtio_pci_bindings = { | ||
246 | + .update_irq = virtio_pci_update_irq | ||
247 | +}; | ||
248 | + | ||
249 | +static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev, | ||
250 | + uint16_t vendor, uint16_t device, | ||
251 | + uint16_t class_code, uint8_t pif) | ||
252 | +{ | ||
253 | + uint8_t *config; | ||
254 | + uint32_t size; | ||
255 | + | ||
256 | + proxy->vdev = vdev; | ||
257 | + | ||
258 | + config = proxy->pci_dev.config; | ||
259 | + pci_config_set_vendor_id(config, vendor); | ||
260 | + pci_config_set_device_id(config, device); | ||
261 | + | ||
262 | + config[0x08] = VIRTIO_PCI_ABI_VERSION; | ||
263 | + | ||
264 | + config[0x09] = pif; | ||
265 | + pci_config_set_class(config, class_code); | ||
266 | + config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; | ||
267 | + | ||
268 | + config[0x2c] = vendor & 0xFF; | ||
269 | + config[0x2d] = (vendor >> 8) & 0xFF; | ||
270 | + config[0x2e] = vdev->device_id & 0xFF; | ||
271 | + config[0x2f] = (vdev->device_id >> 8) & 0xFF; | ||
272 | + | ||
273 | + config[0x3d] = 1; | ||
274 | + | ||
275 | + size = 20 + vdev->config_len; | ||
276 | + if (size & (size-1)) | ||
277 | + size = 1 << qemu_fls(size); | ||
278 | + | ||
279 | + pci_register_io_region(&proxy->pci_dev, 0, size, PCI_ADDRESS_SPACE_IO, | ||
280 | + virtio_map); | ||
281 | + | ||
282 | + virtio_bind_device(vdev, &virtio_pci_bindings, proxy); | ||
283 | +} | ||
284 | + | ||
285 | +static void virtio_blk_init_pci(PCIDevice *pci_dev) | ||
286 | +{ | ||
287 | + VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev); | ||
288 | + VirtIODevice *vdev; | ||
289 | + | ||
290 | + vdev = virtio_blk_init(&pci_dev->qdev); | ||
291 | + virtio_init_pci(proxy, vdev, | ||
292 | + PCI_VENDOR_ID_REDHAT_QUMRANET, | ||
293 | + PCI_DEVICE_ID_VIRTIO_BLOCK, | ||
294 | + PCI_CLASS_STORAGE_OTHER, | ||
295 | + 0x00); | ||
296 | +} | ||
297 | + | ||
298 | +static void virtio_console_init_pci(PCIDevice *pci_dev) | ||
299 | +{ | ||
300 | + VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev); | ||
301 | + VirtIODevice *vdev; | ||
302 | + | ||
303 | + vdev = virtio_console_init(&pci_dev->qdev); | ||
304 | + virtio_init_pci(proxy, vdev, | ||
305 | + PCI_VENDOR_ID_REDHAT_QUMRANET, | ||
306 | + PCI_DEVICE_ID_VIRTIO_CONSOLE, | ||
307 | + PCI_CLASS_DISPLAY_OTHER, | ||
308 | + 0x00); | ||
309 | +} | ||
310 | + | ||
311 | +static void virtio_net_init_pci(PCIDevice *pci_dev) | ||
312 | +{ | ||
313 | + VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev); | ||
314 | + VirtIODevice *vdev; | ||
315 | + | ||
316 | + vdev = virtio_net_init(&pci_dev->qdev); | ||
317 | + virtio_init_pci(proxy, vdev, | ||
318 | + PCI_VENDOR_ID_REDHAT_QUMRANET, | ||
319 | + PCI_DEVICE_ID_VIRTIO_NET, | ||
320 | + PCI_CLASS_NETWORK_ETHERNET, | ||
321 | + 0x00); | ||
322 | +} | ||
323 | + | ||
324 | +static void virtio_balloon_init_pci(PCIDevice *pci_dev) | ||
325 | +{ | ||
326 | + VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev); | ||
327 | + VirtIODevice *vdev; | ||
328 | + | ||
329 | + vdev = virtio_balloon_init(&pci_dev->qdev); | ||
330 | + virtio_init_pci(proxy, vdev, | ||
331 | + PCI_VENDOR_ID_REDHAT_QUMRANET, | ||
332 | + PCI_DEVICE_ID_VIRTIO_BALLOON, | ||
333 | + PCI_CLASS_MEMORY_RAM, | ||
334 | + 0x00); | ||
335 | +} | ||
336 | + | ||
337 | +static void virtio_pci_register_devices(void) | ||
338 | +{ | ||
339 | + pci_qdev_register("virtio-blk-pci", sizeof(VirtIOPCIProxy), | ||
340 | + virtio_blk_init_pci); | ||
341 | + pci_qdev_register("virtio-net-pci", sizeof(VirtIOPCIProxy), | ||
342 | + virtio_net_init_pci); | ||
343 | + pci_qdev_register("virtio-console-pci", sizeof(VirtIOPCIProxy), | ||
344 | + virtio_console_init_pci); | ||
345 | + pci_qdev_register("virtio-balloon-pci", sizeof(VirtIOPCIProxy), | ||
346 | + virtio_balloon_init_pci); | ||
347 | +} | ||
348 | + | ||
349 | +device_init(virtio_pci_register_devices) |
hw/virtio.c
@@ -16,43 +16,6 @@ | @@ -16,43 +16,6 @@ | ||
16 | #include "virtio.h" | 16 | #include "virtio.h" |
17 | #include "sysemu.h" | 17 | #include "sysemu.h" |
18 | 18 | ||
19 | -/* from Linux's linux/virtio_pci.h */ | ||
20 | - | ||
21 | -/* A 32-bit r/o bitmask of the features supported by the host */ | ||
22 | -#define VIRTIO_PCI_HOST_FEATURES 0 | ||
23 | - | ||
24 | -/* A 32-bit r/w bitmask of features activated by the guest */ | ||
25 | -#define VIRTIO_PCI_GUEST_FEATURES 4 | ||
26 | - | ||
27 | -/* A 32-bit r/w PFN for the currently selected queue */ | ||
28 | -#define VIRTIO_PCI_QUEUE_PFN 8 | ||
29 | - | ||
30 | -/* A 16-bit r/o queue size for the currently selected queue */ | ||
31 | -#define VIRTIO_PCI_QUEUE_NUM 12 | ||
32 | - | ||
33 | -/* A 16-bit r/w queue selector */ | ||
34 | -#define VIRTIO_PCI_QUEUE_SEL 14 | ||
35 | - | ||
36 | -/* A 16-bit r/w queue notifier */ | ||
37 | -#define VIRTIO_PCI_QUEUE_NOTIFY 16 | ||
38 | - | ||
39 | -/* An 8-bit device status register. */ | ||
40 | -#define VIRTIO_PCI_STATUS 18 | ||
41 | - | ||
42 | -/* An 8-bit r/o interrupt status register. Reading the value will return the | ||
43 | - * current contents of the ISR and will also clear it. This is effectively | ||
44 | - * a read-and-acknowledge. */ | ||
45 | -#define VIRTIO_PCI_ISR 19 | ||
46 | - | ||
47 | -#define VIRTIO_PCI_CONFIG 20 | ||
48 | - | ||
49 | -/* Virtio ABI version, if we increment this, we break the guest driver. */ | ||
50 | -#define VIRTIO_PCI_ABI_VERSION 0 | ||
51 | - | ||
52 | -/* How many bits to shift physical queue address written to QUEUE_PFN. | ||
53 | - * 12 is historical, and due to x86 page size. */ | ||
54 | -#define VIRTIO_PCI_QUEUE_ADDR_SHIFT 12 | ||
55 | - | ||
56 | /* The alignment to use between consumer and producer parts of vring. | 19 | /* The alignment to use between consumer and producer parts of vring. |
57 | * x86 pagesize again. */ | 20 | * x86 pagesize again. */ |
58 | #define VIRTIO_PCI_VRING_ALIGN 4096 | 21 | #define VIRTIO_PCI_VRING_ALIGN 4096 |
@@ -102,7 +65,7 @@ typedef struct VRing | @@ -102,7 +65,7 @@ typedef struct VRing | ||
102 | struct VirtQueue | 65 | struct VirtQueue |
103 | { | 66 | { |
104 | VRing vring; | 67 | VRing vring; |
105 | - uint32_t pfn; | 68 | + target_phys_addr_t pa; |
106 | uint16_t last_avail_idx; | 69 | uint16_t last_avail_idx; |
107 | int inuse; | 70 | int inuse; |
108 | void (*handle_output)(VirtIODevice *vdev, VirtQueue *vq); | 71 | void (*handle_output)(VirtIODevice *vdev, VirtQueue *vq); |
@@ -111,8 +74,10 @@ struct VirtQueue | @@ -111,8 +74,10 @@ struct VirtQueue | ||
111 | #define VIRTIO_PCI_QUEUE_MAX 16 | 74 | #define VIRTIO_PCI_QUEUE_MAX 16 |
112 | 75 | ||
113 | /* virt queue functions */ | 76 | /* virt queue functions */ |
114 | -static void virtqueue_init(VirtQueue *vq, target_phys_addr_t pa) | 77 | +static void virtqueue_init(VirtQueue *vq) |
115 | { | 78 | { |
79 | + target_phys_addr_t pa = vq->pa; | ||
80 | + | ||
116 | vq->vring.desc = pa; | 81 | vq->vring.desc = pa; |
117 | vq->vring.avail = pa + vq->vring.num * sizeof(VRingDesc); | 82 | vq->vring.avail = pa + vq->vring.num * sizeof(VRingDesc); |
118 | vq->vring.used = vring_align(vq->vring.avail + | 83 | vq->vring.used = vring_align(vq->vring.avail + |
@@ -409,17 +374,14 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem) | @@ -409,17 +374,14 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem) | ||
409 | 374 | ||
410 | /* virtio device */ | 375 | /* virtio device */ |
411 | 376 | ||
412 | -static VirtIODevice *to_virtio_device(PCIDevice *pci_dev) | 377 | +void virtio_update_irq(VirtIODevice *vdev) |
413 | { | 378 | { |
414 | - return (VirtIODevice *)pci_dev; | ||
415 | -} | ||
416 | - | ||
417 | -static void virtio_update_irq(VirtIODevice *vdev) | ||
418 | -{ | ||
419 | - qemu_set_irq(vdev->pci_dev.irq[0], vdev->isr & 1); | 379 | + if (vdev->binding->update_irq) { |
380 | + vdev->binding->update_irq(vdev->binding_opaque); | ||
381 | + } | ||
420 | } | 382 | } |
421 | 383 | ||
422 | -static void virtio_reset(void *opaque) | 384 | +void virtio_reset(void *opaque) |
423 | { | 385 | { |
424 | VirtIODevice *vdev = opaque; | 386 | VirtIODevice *vdev = opaque; |
425 | int i; | 387 | int i; |
@@ -438,103 +400,16 @@ static void virtio_reset(void *opaque) | @@ -438,103 +400,16 @@ static void virtio_reset(void *opaque) | ||
438 | vdev->vq[i].vring.avail = 0; | 400 | vdev->vq[i].vring.avail = 0; |
439 | vdev->vq[i].vring.used = 0; | 401 | vdev->vq[i].vring.used = 0; |
440 | vdev->vq[i].last_avail_idx = 0; | 402 | vdev->vq[i].last_avail_idx = 0; |
441 | - vdev->vq[i].pfn = 0; | 403 | + vdev->vq[i].pa = 0; |
442 | } | 404 | } |
443 | } | 405 | } |
444 | 406 | ||
445 | -static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val) | ||
446 | -{ | ||
447 | - VirtIODevice *vdev = to_virtio_device(opaque); | ||
448 | - ram_addr_t pa; | ||
449 | - | ||
450 | - addr -= vdev->addr; | ||
451 | - | ||
452 | - switch (addr) { | ||
453 | - case VIRTIO_PCI_GUEST_FEATURES: | ||
454 | - /* Guest does not negotiate properly? We have to assume nothing. */ | ||
455 | - if (val & (1 << VIRTIO_F_BAD_FEATURE)) { | ||
456 | - if (vdev->bad_features) | ||
457 | - val = vdev->bad_features(vdev); | ||
458 | - else | ||
459 | - val = 0; | ||
460 | - } | ||
461 | - if (vdev->set_features) | ||
462 | - vdev->set_features(vdev, val); | ||
463 | - vdev->features = val; | ||
464 | - break; | ||
465 | - case VIRTIO_PCI_QUEUE_PFN: | ||
466 | - pa = (ram_addr_t)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT; | ||
467 | - vdev->vq[vdev->queue_sel].pfn = val; | ||
468 | - if (pa == 0) { | ||
469 | - virtio_reset(vdev); | ||
470 | - } else { | ||
471 | - virtqueue_init(&vdev->vq[vdev->queue_sel], pa); | ||
472 | - } | ||
473 | - break; | ||
474 | - case VIRTIO_PCI_QUEUE_SEL: | ||
475 | - if (val < VIRTIO_PCI_QUEUE_MAX) | ||
476 | - vdev->queue_sel = val; | ||
477 | - break; | ||
478 | - case VIRTIO_PCI_QUEUE_NOTIFY: | ||
479 | - if (val < VIRTIO_PCI_QUEUE_MAX && vdev->vq[val].vring.desc) | ||
480 | - vdev->vq[val].handle_output(vdev, &vdev->vq[val]); | ||
481 | - break; | ||
482 | - case VIRTIO_PCI_STATUS: | ||
483 | - vdev->status = val & 0xFF; | ||
484 | - if (vdev->status == 0) | ||
485 | - virtio_reset(vdev); | ||
486 | - break; | ||
487 | - } | ||
488 | -} | ||
489 | - | ||
490 | -static uint32_t virtio_ioport_read(void *opaque, uint32_t addr) | ||
491 | -{ | ||
492 | - VirtIODevice *vdev = to_virtio_device(opaque); | ||
493 | - uint32_t ret = 0xFFFFFFFF; | ||
494 | - | ||
495 | - addr -= vdev->addr; | ||
496 | - | ||
497 | - switch (addr) { | ||
498 | - case VIRTIO_PCI_HOST_FEATURES: | ||
499 | - ret = vdev->get_features(vdev); | ||
500 | - ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY) | (1 << VIRTIO_F_BAD_FEATURE); | ||
501 | - break; | ||
502 | - case VIRTIO_PCI_GUEST_FEATURES: | ||
503 | - ret = vdev->features; | ||
504 | - break; | ||
505 | - case VIRTIO_PCI_QUEUE_PFN: | ||
506 | - ret = vdev->vq[vdev->queue_sel].pfn; | ||
507 | - break; | ||
508 | - case VIRTIO_PCI_QUEUE_NUM: | ||
509 | - ret = vdev->vq[vdev->queue_sel].vring.num; | ||
510 | - break; | ||
511 | - case VIRTIO_PCI_QUEUE_SEL: | ||
512 | - ret = vdev->queue_sel; | ||
513 | - break; | ||
514 | - case VIRTIO_PCI_STATUS: | ||
515 | - ret = vdev->status; | ||
516 | - break; | ||
517 | - case VIRTIO_PCI_ISR: | ||
518 | - /* reading from the ISR also clears it. */ | ||
519 | - ret = vdev->isr; | ||
520 | - vdev->isr = 0; | ||
521 | - virtio_update_irq(vdev); | ||
522 | - break; | ||
523 | - default: | ||
524 | - break; | ||
525 | - } | ||
526 | - | ||
527 | - return ret; | ||
528 | -} | ||
529 | - | ||
530 | -static uint32_t virtio_config_readb(void *opaque, uint32_t addr) | 407 | +uint32_t virtio_config_readb(VirtIODevice *vdev, uint32_t addr) |
531 | { | 408 | { |
532 | - VirtIODevice *vdev = opaque; | ||
533 | uint8_t val; | 409 | uint8_t val; |
534 | 410 | ||
535 | vdev->get_config(vdev, vdev->config); | 411 | vdev->get_config(vdev, vdev->config); |
536 | 412 | ||
537 | - addr -= vdev->addr + VIRTIO_PCI_CONFIG; | ||
538 | if (addr > (vdev->config_len - sizeof(val))) | 413 | if (addr > (vdev->config_len - sizeof(val))) |
539 | return (uint32_t)-1; | 414 | return (uint32_t)-1; |
540 | 415 | ||
@@ -542,14 +417,12 @@ static uint32_t virtio_config_readb(void *opaque, uint32_t addr) | @@ -542,14 +417,12 @@ static uint32_t virtio_config_readb(void *opaque, uint32_t addr) | ||
542 | return val; | 417 | return val; |
543 | } | 418 | } |
544 | 419 | ||
545 | -static uint32_t virtio_config_readw(void *opaque, uint32_t addr) | 420 | +uint32_t virtio_config_readw(VirtIODevice *vdev, uint32_t addr) |
546 | { | 421 | { |
547 | - VirtIODevice *vdev = opaque; | ||
548 | uint16_t val; | 422 | uint16_t val; |
549 | 423 | ||
550 | vdev->get_config(vdev, vdev->config); | 424 | vdev->get_config(vdev, vdev->config); |
551 | 425 | ||
552 | - addr -= vdev->addr + VIRTIO_PCI_CONFIG; | ||
553 | if (addr > (vdev->config_len - sizeof(val))) | 426 | if (addr > (vdev->config_len - sizeof(val))) |
554 | return (uint32_t)-1; | 427 | return (uint32_t)-1; |
555 | 428 | ||
@@ -557,14 +430,12 @@ static uint32_t virtio_config_readw(void *opaque, uint32_t addr) | @@ -557,14 +430,12 @@ static uint32_t virtio_config_readw(void *opaque, uint32_t addr) | ||
557 | return val; | 430 | return val; |
558 | } | 431 | } |
559 | 432 | ||
560 | -static uint32_t virtio_config_readl(void *opaque, uint32_t addr) | 433 | +uint32_t virtio_config_readl(VirtIODevice *vdev, uint32_t addr) |
561 | { | 434 | { |
562 | - VirtIODevice *vdev = opaque; | ||
563 | uint32_t val; | 435 | uint32_t val; |
564 | 436 | ||
565 | vdev->get_config(vdev, vdev->config); | 437 | vdev->get_config(vdev, vdev->config); |
566 | 438 | ||
567 | - addr -= vdev->addr + VIRTIO_PCI_CONFIG; | ||
568 | if (addr > (vdev->config_len - sizeof(val))) | 439 | if (addr > (vdev->config_len - sizeof(val))) |
569 | return (uint32_t)-1; | 440 | return (uint32_t)-1; |
570 | 441 | ||
@@ -572,12 +443,10 @@ static uint32_t virtio_config_readl(void *opaque, uint32_t addr) | @@ -572,12 +443,10 @@ static uint32_t virtio_config_readl(void *opaque, uint32_t addr) | ||
572 | return val; | 443 | return val; |
573 | } | 444 | } |
574 | 445 | ||
575 | -static void virtio_config_writeb(void *opaque, uint32_t addr, uint32_t data) | 446 | +void virtio_config_writeb(VirtIODevice *vdev, uint32_t addr, uint32_t data) |
576 | { | 447 | { |
577 | - VirtIODevice *vdev = opaque; | ||
578 | uint8_t val = data; | 448 | uint8_t val = data; |
579 | 449 | ||
580 | - addr -= vdev->addr + VIRTIO_PCI_CONFIG; | ||
581 | if (addr > (vdev->config_len - sizeof(val))) | 450 | if (addr > (vdev->config_len - sizeof(val))) |
582 | return; | 451 | return; |
583 | 452 | ||
@@ -587,12 +456,10 @@ static void virtio_config_writeb(void *opaque, uint32_t addr, uint32_t data) | @@ -587,12 +456,10 @@ static void virtio_config_writeb(void *opaque, uint32_t addr, uint32_t data) | ||
587 | vdev->set_config(vdev, vdev->config); | 456 | vdev->set_config(vdev, vdev->config); |
588 | } | 457 | } |
589 | 458 | ||
590 | -static void virtio_config_writew(void *opaque, uint32_t addr, uint32_t data) | 459 | +void virtio_config_writew(VirtIODevice *vdev, uint32_t addr, uint32_t data) |
591 | { | 460 | { |
592 | - VirtIODevice *vdev = opaque; | ||
593 | uint16_t val = data; | 461 | uint16_t val = data; |
594 | 462 | ||
595 | - addr -= vdev->addr + VIRTIO_PCI_CONFIG; | ||
596 | if (addr > (vdev->config_len - sizeof(val))) | 463 | if (addr > (vdev->config_len - sizeof(val))) |
597 | return; | 464 | return; |
598 | 465 | ||
@@ -602,12 +469,10 @@ static void virtio_config_writew(void *opaque, uint32_t addr, uint32_t data) | @@ -602,12 +469,10 @@ static void virtio_config_writew(void *opaque, uint32_t addr, uint32_t data) | ||
602 | vdev->set_config(vdev, vdev->config); | 469 | vdev->set_config(vdev, vdev->config); |
603 | } | 470 | } |
604 | 471 | ||
605 | -static void virtio_config_writel(void *opaque, uint32_t addr, uint32_t data) | 472 | +void virtio_config_writel(VirtIODevice *vdev, uint32_t addr, uint32_t data) |
606 | { | 473 | { |
607 | - VirtIODevice *vdev = opaque; | ||
608 | uint32_t val = data; | 474 | uint32_t val = data; |
609 | 475 | ||
610 | - addr -= vdev->addr + VIRTIO_PCI_CONFIG; | ||
611 | if (addr > (vdev->config_len - sizeof(val))) | 476 | if (addr > (vdev->config_len - sizeof(val))) |
612 | return; | 477 | return; |
613 | 478 | ||
@@ -617,33 +482,30 @@ static void virtio_config_writel(void *opaque, uint32_t addr, uint32_t data) | @@ -617,33 +482,30 @@ static void virtio_config_writel(void *opaque, uint32_t addr, uint32_t data) | ||
617 | vdev->set_config(vdev, vdev->config); | 482 | vdev->set_config(vdev, vdev->config); |
618 | } | 483 | } |
619 | 484 | ||
620 | -static void virtio_map(PCIDevice *pci_dev, int region_num, | ||
621 | - uint32_t addr, uint32_t size, int type) | 485 | +void virtio_queue_set_addr(VirtIODevice *vdev, int n, target_phys_addr_t addr) |
622 | { | 486 | { |
623 | - VirtIODevice *vdev = to_virtio_device(pci_dev); | ||
624 | - int i; | ||
625 | - | ||
626 | - vdev->addr = addr; | ||
627 | - for (i = 0; i < 3; i++) { | ||
628 | - register_ioport_write(addr, 20, 1 << i, virtio_ioport_write, vdev); | ||
629 | - register_ioport_read(addr, 20, 1 << i, virtio_ioport_read, vdev); | 487 | + if (addr == 0) { |
488 | + virtio_reset(vdev); | ||
489 | + } else { | ||
490 | + vdev->vq[n].pa = addr; | ||
491 | + virtqueue_init(&vdev->vq[n]); | ||
630 | } | 492 | } |
493 | +} | ||
494 | + | ||
495 | +target_phys_addr_t virtio_queue_get_addr(VirtIODevice *vdev, int n) | ||
496 | +{ | ||
497 | + return vdev->vq[n].pa; | ||
498 | +} | ||
499 | + | ||
500 | +int virtio_queue_get_num(VirtIODevice *vdev, int n) | ||
501 | +{ | ||
502 | + return vdev->vq[n].vring.num; | ||
503 | +} | ||
631 | 504 | ||
632 | - if (vdev->config_len) { | ||
633 | - register_ioport_write(addr + 20, vdev->config_len, 1, | ||
634 | - virtio_config_writeb, vdev); | ||
635 | - register_ioport_write(addr + 20, vdev->config_len, 2, | ||
636 | - virtio_config_writew, vdev); | ||
637 | - register_ioport_write(addr + 20, vdev->config_len, 4, | ||
638 | - virtio_config_writel, vdev); | ||
639 | - register_ioport_read(addr + 20, vdev->config_len, 1, | ||
640 | - virtio_config_readb, vdev); | ||
641 | - register_ioport_read(addr + 20, vdev->config_len, 2, | ||
642 | - virtio_config_readw, vdev); | ||
643 | - register_ioport_read(addr + 20, vdev->config_len, 4, | ||
644 | - virtio_config_readl, vdev); | ||
645 | - | ||
646 | - vdev->get_config(vdev, vdev->config); | 505 | +void virtio_queue_notify(VirtIODevice *vdev, int n) |
506 | +{ | ||
507 | + if (n < VIRTIO_PCI_QUEUE_MAX && vdev->vq[n].vring.desc) { | ||
508 | + vdev->vq[n].handle_output(vdev, &vdev->vq[n]); | ||
647 | } | 509 | } |
648 | } | 510 | } |
649 | 511 | ||
@@ -691,9 +553,9 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f) | @@ -691,9 +553,9 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f) | ||
691 | { | 553 | { |
692 | int i; | 554 | int i; |
693 | 555 | ||
694 | - pci_device_save(&vdev->pci_dev, f); | 556 | + /* FIXME: load/save binding. */ |
557 | + //pci_device_save(&vdev->pci_dev, f); | ||
695 | 558 | ||
696 | - qemu_put_be32s(f, &vdev->addr); | ||
697 | qemu_put_8s(f, &vdev->status); | 559 | qemu_put_8s(f, &vdev->status); |
698 | qemu_put_8s(f, &vdev->isr); | 560 | qemu_put_8s(f, &vdev->isr); |
699 | qemu_put_be16s(f, &vdev->queue_sel); | 561 | qemu_put_be16s(f, &vdev->queue_sel); |
@@ -713,7 +575,7 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f) | @@ -713,7 +575,7 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f) | ||
713 | break; | 575 | break; |
714 | 576 | ||
715 | qemu_put_be32(f, vdev->vq[i].vring.num); | 577 | qemu_put_be32(f, vdev->vq[i].vring.num); |
716 | - qemu_put_be32s(f, &vdev->vq[i].pfn); | 578 | + qemu_put_be64(f, vdev->vq[i].pa); |
717 | qemu_put_be16s(f, &vdev->vq[i].last_avail_idx); | 579 | qemu_put_be16s(f, &vdev->vq[i].last_avail_idx); |
718 | } | 580 | } |
719 | } | 581 | } |
@@ -722,9 +584,9 @@ void virtio_load(VirtIODevice *vdev, QEMUFile *f) | @@ -722,9 +584,9 @@ void virtio_load(VirtIODevice *vdev, QEMUFile *f) | ||
722 | { | 584 | { |
723 | int num, i; | 585 | int num, i; |
724 | 586 | ||
725 | - pci_device_load(&vdev->pci_dev, f); | 587 | + /* FIXME: load/save binding. */ |
588 | + //pci_device_load(&vdev->pci_dev, f); | ||
726 | 589 | ||
727 | - qemu_get_be32s(f, &vdev->addr); | ||
728 | qemu_get_8s(f, &vdev->status); | 590 | qemu_get_8s(f, &vdev->status); |
729 | qemu_get_8s(f, &vdev->isr); | 591 | qemu_get_8s(f, &vdev->isr); |
730 | qemu_get_be16s(f, &vdev->queue_sel); | 592 | qemu_get_be16s(f, &vdev->queue_sel); |
@@ -736,14 +598,11 @@ void virtio_load(VirtIODevice *vdev, QEMUFile *f) | @@ -736,14 +598,11 @@ void virtio_load(VirtIODevice *vdev, QEMUFile *f) | ||
736 | 598 | ||
737 | for (i = 0; i < num; i++) { | 599 | for (i = 0; i < num; i++) { |
738 | vdev->vq[i].vring.num = qemu_get_be32(f); | 600 | vdev->vq[i].vring.num = qemu_get_be32(f); |
739 | - qemu_get_be32s(f, &vdev->vq[i].pfn); | 601 | + vdev->vq[i].pa = qemu_get_be64(f); |
740 | qemu_get_be16s(f, &vdev->vq[i].last_avail_idx); | 602 | qemu_get_be16s(f, &vdev->vq[i].last_avail_idx); |
741 | 603 | ||
742 | - if (vdev->vq[i].pfn) { | ||
743 | - target_phys_addr_t pa; | ||
744 | - | ||
745 | - pa = (ram_addr_t)vdev->vq[i].pfn << VIRTIO_PCI_QUEUE_ADDR_SHIFT; | ||
746 | - virtqueue_init(&vdev->vq[i], pa); | 604 | + if (vdev->vq[i].pa) { |
605 | + virtqueue_init(&vdev->vq[i]); | ||
747 | } | 606 | } |
748 | } | 607 | } |
749 | 608 | ||
@@ -757,40 +616,19 @@ void virtio_cleanup(VirtIODevice *vdev) | @@ -757,40 +616,19 @@ void virtio_cleanup(VirtIODevice *vdev) | ||
757 | qemu_free(vdev->vq); | 616 | qemu_free(vdev->vq); |
758 | } | 617 | } |
759 | 618 | ||
760 | -VirtIODevice *virtio_init_pci(PCIDevice *pci_dev, const char *name, | ||
761 | - uint16_t vendor, uint16_t device, | ||
762 | - uint16_t subvendor, uint16_t subdevice, | ||
763 | - uint16_t class_code, uint8_t pif, | ||
764 | - size_t config_size) | 619 | +VirtIODevice *virtio_common_init(const char *name, uint16_t device_id, |
620 | + size_t config_size, size_t struct_size) | ||
765 | { | 621 | { |
766 | VirtIODevice *vdev; | 622 | VirtIODevice *vdev; |
767 | - uint8_t *config; | ||
768 | - uint32_t size; | ||
769 | 623 | ||
770 | - vdev = to_virtio_device(pci_dev); | 624 | + vdev = qemu_mallocz(struct_size); |
771 | 625 | ||
626 | + vdev->device_id = device_id; | ||
772 | vdev->status = 0; | 627 | vdev->status = 0; |
773 | vdev->isr = 0; | 628 | vdev->isr = 0; |
774 | vdev->queue_sel = 0; | 629 | vdev->queue_sel = 0; |
775 | vdev->vq = qemu_mallocz(sizeof(VirtQueue) * VIRTIO_PCI_QUEUE_MAX); | 630 | vdev->vq = qemu_mallocz(sizeof(VirtQueue) * VIRTIO_PCI_QUEUE_MAX); |
776 | 631 | ||
777 | - config = pci_dev->config; | ||
778 | - pci_config_set_vendor_id(config, vendor); | ||
779 | - pci_config_set_device_id(config, device); | ||
780 | - | ||
781 | - config[0x08] = VIRTIO_PCI_ABI_VERSION; | ||
782 | - | ||
783 | - config[0x09] = pif; | ||
784 | - pci_config_set_class(config, class_code); | ||
785 | - config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; | ||
786 | - | ||
787 | - config[0x2c] = subvendor & 0xFF; | ||
788 | - config[0x2d] = (subvendor >> 8) & 0xFF; | ||
789 | - config[0x2e] = subdevice & 0xFF; | ||
790 | - config[0x2f] = (subdevice >> 8) & 0xFF; | ||
791 | - | ||
792 | - config[0x3d] = 1; | ||
793 | - | ||
794 | vdev->name = name; | 632 | vdev->name = name; |
795 | vdev->config_len = config_size; | 633 | vdev->config_len = config_size; |
796 | if (vdev->config_len) | 634 | if (vdev->config_len) |
@@ -798,13 +636,13 @@ VirtIODevice *virtio_init_pci(PCIDevice *pci_dev, const char *name, | @@ -798,13 +636,13 @@ VirtIODevice *virtio_init_pci(PCIDevice *pci_dev, const char *name, | ||
798 | else | 636 | else |
799 | vdev->config = NULL; | 637 | vdev->config = NULL; |
800 | 638 | ||
801 | - size = 20 + config_size; | ||
802 | - if (size & (size-1)) | ||
803 | - size = 1 << qemu_fls(size); | ||
804 | - | ||
805 | - pci_register_io_region(pci_dev, 0, size, PCI_ADDRESS_SPACE_IO, | ||
806 | - virtio_map); | ||
807 | qemu_register_reset(virtio_reset, vdev); | 639 | qemu_register_reset(virtio_reset, vdev); |
808 | - | ||
809 | return vdev; | 640 | return vdev; |
810 | } | 641 | } |
642 | + | ||
643 | +void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding, | ||
644 | + void *opaque) | ||
645 | +{ | ||
646 | + vdev->binding = binding; | ||
647 | + vdev->binding_opaque = opaque; | ||
648 | +} |
hw/virtio.h
@@ -15,7 +15,7 @@ | @@ -15,7 +15,7 @@ | ||
15 | #define _QEMU_VIRTIO_H | 15 | #define _QEMU_VIRTIO_H |
16 | 16 | ||
17 | #include "hw.h" | 17 | #include "hw.h" |
18 | -#include "pci.h" | 18 | +#include "qdev.h" |
19 | 19 | ||
20 | /* from Linux's linux/virtio_config.h */ | 20 | /* from Linux's linux/virtio_config.h */ |
21 | 21 | ||
@@ -70,13 +70,15 @@ typedef struct VirtQueueElement | @@ -70,13 +70,15 @@ typedef struct VirtQueueElement | ||
70 | struct iovec out_sg[VIRTQUEUE_MAX_SIZE]; | 70 | struct iovec out_sg[VIRTQUEUE_MAX_SIZE]; |
71 | } VirtQueueElement; | 71 | } VirtQueueElement; |
72 | 72 | ||
73 | +typedef struct { | ||
74 | + void (*update_irq)(void * opaque); | ||
75 | +} VirtIOBindings; | ||
76 | + | ||
73 | #define VIRTIO_PCI_QUEUE_MAX 16 | 77 | #define VIRTIO_PCI_QUEUE_MAX 16 |
74 | 78 | ||
75 | struct VirtIODevice | 79 | struct VirtIODevice |
76 | { | 80 | { |
77 | - PCIDevice pci_dev; | ||
78 | const char *name; | 81 | const char *name; |
79 | - uint32_t addr; | ||
80 | uint8_t status; | 82 | uint8_t status; |
81 | uint8_t isr; | 83 | uint8_t isr; |
82 | uint16_t queue_sel; | 84 | uint16_t queue_sel; |
@@ -90,14 +92,11 @@ struct VirtIODevice | @@ -90,14 +92,11 @@ struct VirtIODevice | ||
90 | void (*set_config)(VirtIODevice *vdev, const uint8_t *config); | 92 | void (*set_config)(VirtIODevice *vdev, const uint8_t *config); |
91 | void (*reset)(VirtIODevice *vdev); | 93 | void (*reset)(VirtIODevice *vdev); |
92 | VirtQueue *vq; | 94 | VirtQueue *vq; |
95 | + const VirtIOBindings *binding; | ||
96 | + void *binding_opaque; | ||
97 | + uint16_t device_id; | ||
93 | }; | 98 | }; |
94 | 99 | ||
95 | -VirtIODevice *virtio_init_pci(PCIDevice *pci_dev, const char *name, | ||
96 | - uint16_t vendor, uint16_t device, | ||
97 | - uint16_t subvendor, uint16_t subdevice, | ||
98 | - uint16_t class_code, uint8_t pif, | ||
99 | - size_t config_size); | ||
100 | - | ||
101 | VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size, | 100 | VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size, |
102 | void (*handle_output)(VirtIODevice *, | 101 | void (*handle_output)(VirtIODevice *, |
103 | VirtQueue *)); | 102 | VirtQueue *)); |
@@ -127,4 +126,30 @@ int virtio_queue_ready(VirtQueue *vq); | @@ -127,4 +126,30 @@ int virtio_queue_ready(VirtQueue *vq); | ||
127 | 126 | ||
128 | int virtio_queue_empty(VirtQueue *vq); | 127 | int virtio_queue_empty(VirtQueue *vq); |
129 | 128 | ||
129 | +/* Host binding interface. */ | ||
130 | + | ||
131 | +VirtIODevice *virtio_common_init(const char *name, uint16_t device_id, | ||
132 | + size_t config_size, size_t struct_size); | ||
133 | +uint32_t virtio_config_readb(VirtIODevice *vdev, uint32_t addr); | ||
134 | +uint32_t virtio_config_readw(VirtIODevice *vdev, uint32_t addr); | ||
135 | +uint32_t virtio_config_readl(VirtIODevice *vdev, uint32_t addr); | ||
136 | +void virtio_config_writeb(VirtIODevice *vdev, uint32_t addr, uint32_t data); | ||
137 | +void virtio_config_writew(VirtIODevice *vdev, uint32_t addr, uint32_t data); | ||
138 | +void virtio_config_writel(VirtIODevice *vdev, uint32_t addr, uint32_t data); | ||
139 | +void virtio_queue_set_addr(VirtIODevice *vdev, int n, target_phys_addr_t addr); | ||
140 | +target_phys_addr_t virtio_queue_get_addr(VirtIODevice *vdev, int n); | ||
141 | +int virtio_queue_get_num(VirtIODevice *vdev, int n); | ||
142 | +void virtio_queue_notify(VirtIODevice *vdev, int n); | ||
143 | +void virtio_reset(void *opaque); | ||
144 | +void virtio_update_irq(VirtIODevice *vdev); | ||
145 | + | ||
146 | +void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding, | ||
147 | + void *opaque); | ||
148 | + | ||
149 | +/* Base devices. */ | ||
150 | +VirtIODevice *virtio_blk_init(DeviceState *dev); | ||
151 | +VirtIODevice *virtio_net_init(DeviceState *dev); | ||
152 | +VirtIODevice *virtio_console_init(DeviceState *dev); | ||
153 | +VirtIODevice *virtio_balloon_init(DeviceState *dev); | ||
154 | + | ||
130 | #endif | 155 | #endif |