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 | 489 | gdbstub.o gdbstub-xml.o sysbus.o |
490 | 490 | # virtio has to be here due to weird dependency between PCI and virtio-net. |
491 | 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 | 494 | OBJS+=fw_cfg.o |
494 | 495 | ifdef CONFIG_KVM |
495 | 496 | OBJS+=kvm.o kvm-all.o | ... | ... |
hw/pc.c
... | ... | @@ -1137,21 +1137,21 @@ static void pc_init1(ram_addr_t ram_size, |
1137 | 1137 | int unit_id = 0; |
1138 | 1138 | |
1139 | 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 | 1141 | unit_id++; |
1142 | 1142 | } |
1143 | 1143 | } |
1144 | 1144 | |
1145 | 1145 | /* Add virtio balloon device */ |
1146 | 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 | 1150 | /* Add virtio console devices */ |
1151 | 1151 | if (pci_enabled) { |
1152 | 1152 | for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) { |
1153 | 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 | 120 | opaque = pci_create_simple(pci_bus, -1, "lsi53c895a"); |
121 | 121 | break; |
122 | 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 | 124 | qdev_init(opaque); |
125 | 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 | 111 | |
112 | 112 | /* Add virtio block devices. */ |
113 | 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 | 115 | unit_id++; |
116 | 116 | } |
117 | 117 | |
118 | 118 | /* Add virtio console devices */ |
119 | 119 | for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) { |
120 | 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 | 220 | |
221 | 221 | /* Add virtio block devices. */ |
222 | 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 | 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 | 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 | 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 | 180 | s->vdev.get_config = virtio_balloon_get_config; |
185 | 181 | s->vdev.set_config = virtio_balloon_set_config; |
... | ... | @@ -191,12 +187,6 @@ static void virtio_balloon_init(PCIDevice *pci_dev) |
191 | 187 | qemu_add_balloon_handler(virtio_balloon_to_target, s); |
192 | 188 | |
193 | 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 | 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 | 353 | VirtIOBlock *s; |
354 | 354 | int cylinders, heads, secs; |
355 | 355 | static int virtio_blk_id; |
356 | 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 | 363 | s->vdev.get_config = virtio_blk_update_config; |
368 | 364 | s->vdev.get_features = virtio_blk_get_features; |
369 | 365 | s->vdev.reset = virtio_blk_reset; |
370 | 366 | s->bs = bs; |
371 | 367 | s->rq = NULL; |
372 | - bs->private = &s->vdev.pci_dev; | |
368 | + bs->private = dev; | |
373 | 369 | bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs); |
374 | 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 | 374 | qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s); |
379 | 375 | register_savevm("virtio-blk", virtio_blk_id++, 2, |
380 | 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 | 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 | 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 | 132 | s->vdev.get_features = virtio_console_get_features; |
137 | 133 | |
138 | 134 | s->ivq = virtio_add_queue(&s->vdev, 128, virtio_console_handle_input); |
139 | 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 | 138 | qemu_chr_add_handlers(s->chr, vcon_can_read, vcon_read, vcon_event, s); |
143 | 139 | |
144 | 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 | 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 | 590 | VirtIONet *n; |
591 | 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 | 597 | n->vdev.get_config = virtio_net_get_config; |
602 | 598 | n->vdev.set_config = virtio_net_set_config; |
... | ... | @@ -607,9 +603,9 @@ static void virtio_net_init(PCIDevice *pci_dev) |
607 | 603 | n->rx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_rx); |
608 | 604 | n->tx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_tx); |
609 | 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 | 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 | 609 | virtio_net_receive, |
614 | 610 | virtio_net_can_receive, |
615 | 611 | virtio_net_cleanup, n); |
... | ... | @@ -628,11 +624,6 @@ static void virtio_net_init(PCIDevice *pci_dev) |
628 | 624 | |
629 | 625 | register_savevm("virtio-net", virtio_net_id++, VIRTIO_NET_VM_VERSION, |
630 | 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 | 16 | #include "virtio.h" |
17 | 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 | 19 | /* The alignment to use between consumer and producer parts of vring. |
57 | 20 | * x86 pagesize again. */ |
58 | 21 | #define VIRTIO_PCI_VRING_ALIGN 4096 |
... | ... | @@ -102,7 +65,7 @@ typedef struct VRing |
102 | 65 | struct VirtQueue |
103 | 66 | { |
104 | 67 | VRing vring; |
105 | - uint32_t pfn; | |
68 | + target_phys_addr_t pa; | |
106 | 69 | uint16_t last_avail_idx; |
107 | 70 | int inuse; |
108 | 71 | void (*handle_output)(VirtIODevice *vdev, VirtQueue *vq); |
... | ... | @@ -111,8 +74,10 @@ struct VirtQueue |
111 | 74 | #define VIRTIO_PCI_QUEUE_MAX 16 |
112 | 75 | |
113 | 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 | 81 | vq->vring.desc = pa; |
117 | 82 | vq->vring.avail = pa + vq->vring.num * sizeof(VRingDesc); |
118 | 83 | vq->vring.used = vring_align(vq->vring.avail + |
... | ... | @@ -409,17 +374,14 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem) |
409 | 374 | |
410 | 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 | 386 | VirtIODevice *vdev = opaque; |
425 | 387 | int i; |
... | ... | @@ -438,103 +400,16 @@ static void virtio_reset(void *opaque) |
438 | 400 | vdev->vq[i].vring.avail = 0; |
439 | 401 | vdev->vq[i].vring.used = 0; |
440 | 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 | 409 | uint8_t val; |
534 | 410 | |
535 | 411 | vdev->get_config(vdev, vdev->config); |
536 | 412 | |
537 | - addr -= vdev->addr + VIRTIO_PCI_CONFIG; | |
538 | 413 | if (addr > (vdev->config_len - sizeof(val))) |
539 | 414 | return (uint32_t)-1; |
540 | 415 | |
... | ... | @@ -542,14 +417,12 @@ static uint32_t virtio_config_readb(void *opaque, uint32_t addr) |
542 | 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 | 422 | uint16_t val; |
549 | 423 | |
550 | 424 | vdev->get_config(vdev, vdev->config); |
551 | 425 | |
552 | - addr -= vdev->addr + VIRTIO_PCI_CONFIG; | |
553 | 426 | if (addr > (vdev->config_len - sizeof(val))) |
554 | 427 | return (uint32_t)-1; |
555 | 428 | |
... | ... | @@ -557,14 +430,12 @@ static uint32_t virtio_config_readw(void *opaque, uint32_t addr) |
557 | 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 | 435 | uint32_t val; |
564 | 436 | |
565 | 437 | vdev->get_config(vdev, vdev->config); |
566 | 438 | |
567 | - addr -= vdev->addr + VIRTIO_PCI_CONFIG; | |
568 | 439 | if (addr > (vdev->config_len - sizeof(val))) |
569 | 440 | return (uint32_t)-1; |
570 | 441 | |
... | ... | @@ -572,12 +443,10 @@ static uint32_t virtio_config_readl(void *opaque, uint32_t addr) |
572 | 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 | 448 | uint8_t val = data; |
579 | 449 | |
580 | - addr -= vdev->addr + VIRTIO_PCI_CONFIG; | |
581 | 450 | if (addr > (vdev->config_len - sizeof(val))) |
582 | 451 | return; |
583 | 452 | |
... | ... | @@ -587,12 +456,10 @@ static void virtio_config_writeb(void *opaque, uint32_t addr, uint32_t data) |
587 | 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 | 461 | uint16_t val = data; |
594 | 462 | |
595 | - addr -= vdev->addr + VIRTIO_PCI_CONFIG; | |
596 | 463 | if (addr > (vdev->config_len - sizeof(val))) |
597 | 464 | return; |
598 | 465 | |
... | ... | @@ -602,12 +469,10 @@ static void virtio_config_writew(void *opaque, uint32_t addr, uint32_t data) |
602 | 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 | 474 | uint32_t val = data; |
609 | 475 | |
610 | - addr -= vdev->addr + VIRTIO_PCI_CONFIG; | |
611 | 476 | if (addr > (vdev->config_len - sizeof(val))) |
612 | 477 | return; |
613 | 478 | |
... | ... | @@ -617,33 +482,30 @@ static void virtio_config_writel(void *opaque, uint32_t addr, uint32_t data) |
617 | 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 | 553 | { |
692 | 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 | 559 | qemu_put_8s(f, &vdev->status); |
698 | 560 | qemu_put_8s(f, &vdev->isr); |
699 | 561 | qemu_put_be16s(f, &vdev->queue_sel); |
... | ... | @@ -713,7 +575,7 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f) |
713 | 575 | break; |
714 | 576 | |
715 | 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 | 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 | 584 | { |
723 | 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 | 590 | qemu_get_8s(f, &vdev->status); |
729 | 591 | qemu_get_8s(f, &vdev->isr); |
730 | 592 | qemu_get_be16s(f, &vdev->queue_sel); |
... | ... | @@ -736,14 +598,11 @@ void virtio_load(VirtIODevice *vdev, QEMUFile *f) |
736 | 598 | |
737 | 599 | for (i = 0; i < num; i++) { |
738 | 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 | 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 | 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 | 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 | 627 | vdev->status = 0; |
773 | 628 | vdev->isr = 0; |
774 | 629 | vdev->queue_sel = 0; |
775 | 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 | 632 | vdev->name = name; |
795 | 633 | vdev->config_len = config_size; |
796 | 634 | if (vdev->config_len) |
... | ... | @@ -798,13 +636,13 @@ VirtIODevice *virtio_init_pci(PCIDevice *pci_dev, const char *name, |
798 | 636 | else |
799 | 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 | 639 | qemu_register_reset(virtio_reset, vdev); |
808 | - | |
809 | 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 | 15 | #define _QEMU_VIRTIO_H |
16 | 16 | |
17 | 17 | #include "hw.h" |
18 | -#include "pci.h" | |
18 | +#include "qdev.h" | |
19 | 19 | |
20 | 20 | /* from Linux's linux/virtio_config.h */ |
21 | 21 | |
... | ... | @@ -70,13 +70,15 @@ typedef struct VirtQueueElement |
70 | 70 | struct iovec out_sg[VIRTQUEUE_MAX_SIZE]; |
71 | 71 | } VirtQueueElement; |
72 | 72 | |
73 | +typedef struct { | |
74 | + void (*update_irq)(void * opaque); | |
75 | +} VirtIOBindings; | |
76 | + | |
73 | 77 | #define VIRTIO_PCI_QUEUE_MAX 16 |
74 | 78 | |
75 | 79 | struct VirtIODevice |
76 | 80 | { |
77 | - PCIDevice pci_dev; | |
78 | 81 | const char *name; |
79 | - uint32_t addr; | |
80 | 82 | uint8_t status; |
81 | 83 | uint8_t isr; |
82 | 84 | uint16_t queue_sel; |
... | ... | @@ -90,14 +92,11 @@ struct VirtIODevice |
90 | 92 | void (*set_config)(VirtIODevice *vdev, const uint8_t *config); |
91 | 93 | void (*reset)(VirtIODevice *vdev); |
92 | 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 | 100 | VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size, |
102 | 101 | void (*handle_output)(VirtIODevice *, |
103 | 102 | VirtQueue *)); |
... | ... | @@ -127,4 +126,30 @@ int virtio_queue_ready(VirtQueue *vq); |
127 | 126 | |
128 | 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 | 155 | #endif | ... | ... |