Statistics
| Branch: | Revision:

root / hw / virtio.c @ b946a153

History | View | Annotate | Download (21.3 kB)

1 967f97fa aliguori
/*
2 967f97fa aliguori
 * Virtio Support
3 967f97fa aliguori
 *
4 967f97fa aliguori
 * Copyright IBM, Corp. 2007
5 967f97fa aliguori
 *
6 967f97fa aliguori
 * Authors:
7 967f97fa aliguori
 *  Anthony Liguori   <aliguori@us.ibm.com>
8 967f97fa aliguori
 *
9 967f97fa aliguori
 * This work is licensed under the terms of the GNU GPL, version 2.  See
10 967f97fa aliguori
 * the COPYING file in the top-level directory.
11 967f97fa aliguori
 *
12 967f97fa aliguori
 */
13 967f97fa aliguori
14 967f97fa aliguori
#include <inttypes.h>
15 967f97fa aliguori
16 967f97fa aliguori
#include "virtio.h"
17 967f97fa aliguori
#include "sysemu.h"
18 967f97fa aliguori
19 967f97fa aliguori
/* from Linux's linux/virtio_pci.h */
20 967f97fa aliguori
21 967f97fa aliguori
/* A 32-bit r/o bitmask of the features supported by the host */
22 967f97fa aliguori
#define VIRTIO_PCI_HOST_FEATURES        0
23 967f97fa aliguori
24 967f97fa aliguori
/* A 32-bit r/w bitmask of features activated by the guest */
25 967f97fa aliguori
#define VIRTIO_PCI_GUEST_FEATURES       4
26 967f97fa aliguori
27 967f97fa aliguori
/* A 32-bit r/w PFN for the currently selected queue */
28 967f97fa aliguori
#define VIRTIO_PCI_QUEUE_PFN            8
29 967f97fa aliguori
30 967f97fa aliguori
/* A 16-bit r/o queue size for the currently selected queue */
31 967f97fa aliguori
#define VIRTIO_PCI_QUEUE_NUM            12
32 967f97fa aliguori
33 967f97fa aliguori
/* A 16-bit r/w queue selector */
34 967f97fa aliguori
#define VIRTIO_PCI_QUEUE_SEL            14
35 967f97fa aliguori
36 967f97fa aliguori
/* A 16-bit r/w queue notifier */
37 967f97fa aliguori
#define VIRTIO_PCI_QUEUE_NOTIFY         16
38 967f97fa aliguori
39 967f97fa aliguori
/* An 8-bit device status register.  */
40 967f97fa aliguori
#define VIRTIO_PCI_STATUS               18
41 967f97fa aliguori
42 967f97fa aliguori
/* An 8-bit r/o interrupt status register.  Reading the value will return the
43 967f97fa aliguori
 * current contents of the ISR and will also clear it.  This is effectively
44 967f97fa aliguori
 * a read-and-acknowledge. */
45 967f97fa aliguori
#define VIRTIO_PCI_ISR                  19
46 967f97fa aliguori
47 967f97fa aliguori
#define VIRTIO_PCI_CONFIG               20
48 967f97fa aliguori
49 967f97fa aliguori
/* Virtio ABI version, if we increment this, we break the guest driver. */
50 967f97fa aliguori
#define VIRTIO_PCI_ABI_VERSION          0
51 967f97fa aliguori
52 f46f15bc aliguori
/* How many bits to shift physical queue address written to QUEUE_PFN.
53 f46f15bc aliguori
 * 12 is historical, and due to x86 page size. */
54 f46f15bc aliguori
#define VIRTIO_PCI_QUEUE_ADDR_SHIFT    12
55 f46f15bc aliguori
56 f46f15bc aliguori
/* The alignment to use between consumer and producer parts of vring.
57 f46f15bc aliguori
 * x86 pagesize again. */
58 f46f15bc aliguori
#define VIRTIO_PCI_VRING_ALIGN         4096
59 f46f15bc aliguori
60 967f97fa aliguori
/* QEMU doesn't strictly need write barriers since everything runs in
61 967f97fa aliguori
 * lock-step.  We'll leave the calls to wmb() in though to make it obvious for
62 967f97fa aliguori
 * KVM or if kqemu gets SMP support.
63 967f97fa aliguori
 */
64 967f97fa aliguori
#define wmb() do { } while (0)
65 967f97fa aliguori
66 967f97fa aliguori
typedef struct VRingDesc
67 967f97fa aliguori
{
68 967f97fa aliguori
    uint64_t addr;
69 967f97fa aliguori
    uint32_t len;
70 967f97fa aliguori
    uint16_t flags;
71 967f97fa aliguori
    uint16_t next;
72 967f97fa aliguori
} VRingDesc;
73 967f97fa aliguori
74 967f97fa aliguori
typedef struct VRingAvail
75 967f97fa aliguori
{
76 967f97fa aliguori
    uint16_t flags;
77 967f97fa aliguori
    uint16_t idx;
78 967f97fa aliguori
    uint16_t ring[0];
79 967f97fa aliguori
} VRingAvail;
80 967f97fa aliguori
81 967f97fa aliguori
typedef struct VRingUsedElem
82 967f97fa aliguori
{
83 967f97fa aliguori
    uint32_t id;
84 967f97fa aliguori
    uint32_t len;
85 967f97fa aliguori
} VRingUsedElem;
86 967f97fa aliguori
87 967f97fa aliguori
typedef struct VRingUsed
88 967f97fa aliguori
{
89 967f97fa aliguori
    uint16_t flags;
90 967f97fa aliguori
    uint16_t idx;
91 967f97fa aliguori
    VRingUsedElem ring[0];
92 967f97fa aliguori
} VRingUsed;
93 967f97fa aliguori
94 967f97fa aliguori
typedef struct VRing
95 967f97fa aliguori
{
96 967f97fa aliguori
    unsigned int num;
97 967f97fa aliguori
    target_phys_addr_t desc;
98 967f97fa aliguori
    target_phys_addr_t avail;
99 967f97fa aliguori
    target_phys_addr_t used;
100 967f97fa aliguori
} VRing;
101 967f97fa aliguori
102 967f97fa aliguori
struct VirtQueue
103 967f97fa aliguori
{
104 967f97fa aliguori
    VRing vring;
105 967f97fa aliguori
    uint32_t pfn;
106 967f97fa aliguori
    uint16_t last_avail_idx;
107 967f97fa aliguori
    int inuse;
108 967f97fa aliguori
    void (*handle_output)(VirtIODevice *vdev, VirtQueue *vq);
109 967f97fa aliguori
};
110 967f97fa aliguori
111 967f97fa aliguori
#define VIRTIO_PCI_QUEUE_MAX        16
112 967f97fa aliguori
113 967f97fa aliguori
/* virt queue functions */
114 967f97fa aliguori
static void virtqueue_init(VirtQueue *vq, target_phys_addr_t pa)
115 967f97fa aliguori
{
116 967f97fa aliguori
    vq->vring.desc = pa;
117 967f97fa aliguori
    vq->vring.avail = pa + vq->vring.num * sizeof(VRingDesc);
118 f46f15bc aliguori
    vq->vring.used = vring_align(vq->vring.avail +
119 f46f15bc aliguori
                                 offsetof(VRingAvail, ring[vq->vring.num]),
120 f46f15bc aliguori
                                 VIRTIO_PCI_VRING_ALIGN);
121 967f97fa aliguori
}
122 967f97fa aliguori
123 967f97fa aliguori
static inline uint64_t vring_desc_addr(VirtQueue *vq, int i)
124 967f97fa aliguori
{
125 967f97fa aliguori
    target_phys_addr_t pa;
126 967f97fa aliguori
    pa = vq->vring.desc + sizeof(VRingDesc) * i + offsetof(VRingDesc, addr);
127 967f97fa aliguori
    return ldq_phys(pa);
128 967f97fa aliguori
}
129 967f97fa aliguori
130 967f97fa aliguori
static inline uint32_t vring_desc_len(VirtQueue *vq, int i)
131 967f97fa aliguori
{
132 967f97fa aliguori
    target_phys_addr_t pa;
133 967f97fa aliguori
    pa = vq->vring.desc + sizeof(VRingDesc) * i + offsetof(VRingDesc, len);
134 967f97fa aliguori
    return ldl_phys(pa);
135 967f97fa aliguori
}
136 967f97fa aliguori
137 967f97fa aliguori
static inline uint16_t vring_desc_flags(VirtQueue *vq, int i)
138 967f97fa aliguori
{
139 967f97fa aliguori
    target_phys_addr_t pa;
140 967f97fa aliguori
    pa = vq->vring.desc + sizeof(VRingDesc) * i + offsetof(VRingDesc, flags);
141 967f97fa aliguori
    return lduw_phys(pa);
142 967f97fa aliguori
}
143 967f97fa aliguori
144 967f97fa aliguori
static inline uint16_t vring_desc_next(VirtQueue *vq, int i)
145 967f97fa aliguori
{
146 967f97fa aliguori
    target_phys_addr_t pa;
147 967f97fa aliguori
    pa = vq->vring.desc + sizeof(VRingDesc) * i + offsetof(VRingDesc, next);
148 967f97fa aliguori
    return lduw_phys(pa);
149 967f97fa aliguori
}
150 967f97fa aliguori
151 967f97fa aliguori
static inline uint16_t vring_avail_flags(VirtQueue *vq)
152 967f97fa aliguori
{
153 967f97fa aliguori
    target_phys_addr_t pa;
154 967f97fa aliguori
    pa = vq->vring.avail + offsetof(VRingAvail, flags);
155 967f97fa aliguori
    return lduw_phys(pa);
156 967f97fa aliguori
}
157 967f97fa aliguori
158 967f97fa aliguori
static inline uint16_t vring_avail_idx(VirtQueue *vq)
159 967f97fa aliguori
{
160 967f97fa aliguori
    target_phys_addr_t pa;
161 967f97fa aliguori
    pa = vq->vring.avail + offsetof(VRingAvail, idx);
162 967f97fa aliguori
    return lduw_phys(pa);
163 967f97fa aliguori
}
164 967f97fa aliguori
165 967f97fa aliguori
static inline uint16_t vring_avail_ring(VirtQueue *vq, int i)
166 967f97fa aliguori
{
167 967f97fa aliguori
    target_phys_addr_t pa;
168 967f97fa aliguori
    pa = vq->vring.avail + offsetof(VRingAvail, ring[i]);
169 967f97fa aliguori
    return lduw_phys(pa);
170 967f97fa aliguori
}
171 967f97fa aliguori
172 967f97fa aliguori
static inline void vring_used_ring_id(VirtQueue *vq, int i, uint32_t val)
173 967f97fa aliguori
{
174 967f97fa aliguori
    target_phys_addr_t pa;
175 967f97fa aliguori
    pa = vq->vring.used + offsetof(VRingUsed, ring[i].id);
176 967f97fa aliguori
    stl_phys(pa, val);
177 967f97fa aliguori
}
178 967f97fa aliguori
179 967f97fa aliguori
static inline void vring_used_ring_len(VirtQueue *vq, int i, uint32_t val)
180 967f97fa aliguori
{
181 967f97fa aliguori
    target_phys_addr_t pa;
182 967f97fa aliguori
    pa = vq->vring.used + offsetof(VRingUsed, ring[i].len);
183 967f97fa aliguori
    stl_phys(pa, val);
184 967f97fa aliguori
}
185 967f97fa aliguori
186 967f97fa aliguori
static uint16_t vring_used_idx(VirtQueue *vq)
187 967f97fa aliguori
{
188 967f97fa aliguori
    target_phys_addr_t pa;
189 967f97fa aliguori
    pa = vq->vring.used + offsetof(VRingUsed, idx);
190 967f97fa aliguori
    return lduw_phys(pa);
191 967f97fa aliguori
}
192 967f97fa aliguori
193 967f97fa aliguori
static inline void vring_used_idx_increment(VirtQueue *vq, uint16_t val)
194 967f97fa aliguori
{
195 967f97fa aliguori
    target_phys_addr_t pa;
196 967f97fa aliguori
    pa = vq->vring.used + offsetof(VRingUsed, idx);
197 967f97fa aliguori
    stw_phys(pa, vring_used_idx(vq) + val);
198 967f97fa aliguori
}
199 967f97fa aliguori
200 967f97fa aliguori
static inline void vring_used_flags_set_bit(VirtQueue *vq, int mask)
201 967f97fa aliguori
{
202 967f97fa aliguori
    target_phys_addr_t pa;
203 967f97fa aliguori
    pa = vq->vring.used + offsetof(VRingUsed, flags);
204 967f97fa aliguori
    stw_phys(pa, lduw_phys(pa) | mask);
205 967f97fa aliguori
}
206 967f97fa aliguori
207 967f97fa aliguori
static inline void vring_used_flags_unset_bit(VirtQueue *vq, int mask)
208 967f97fa aliguori
{
209 967f97fa aliguori
    target_phys_addr_t pa;
210 967f97fa aliguori
    pa = vq->vring.used + offsetof(VRingUsed, flags);
211 967f97fa aliguori
    stw_phys(pa, lduw_phys(pa) & ~mask);
212 967f97fa aliguori
}
213 967f97fa aliguori
214 967f97fa aliguori
void virtio_queue_set_notification(VirtQueue *vq, int enable)
215 967f97fa aliguori
{
216 967f97fa aliguori
    if (enable)
217 967f97fa aliguori
        vring_used_flags_unset_bit(vq, VRING_USED_F_NO_NOTIFY);
218 967f97fa aliguori
    else
219 967f97fa aliguori
        vring_used_flags_set_bit(vq, VRING_USED_F_NO_NOTIFY);
220 967f97fa aliguori
}
221 967f97fa aliguori
222 967f97fa aliguori
int virtio_queue_ready(VirtQueue *vq)
223 967f97fa aliguori
{
224 967f97fa aliguori
    return vq->vring.avail != 0;
225 967f97fa aliguori
}
226 967f97fa aliguori
227 967f97fa aliguori
int virtio_queue_empty(VirtQueue *vq)
228 967f97fa aliguori
{
229 967f97fa aliguori
    return vring_avail_idx(vq) == vq->last_avail_idx;
230 967f97fa aliguori
}
231 967f97fa aliguori
232 967f97fa aliguori
void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
233 967f97fa aliguori
                    unsigned int len, unsigned int idx)
234 967f97fa aliguori
{
235 967f97fa aliguori
    unsigned int offset;
236 967f97fa aliguori
    int i;
237 967f97fa aliguori
238 967f97fa aliguori
    offset = 0;
239 967f97fa aliguori
    for (i = 0; i < elem->in_num; i++) {
240 967f97fa aliguori
        size_t size = MIN(len - offset, elem->in_sg[i].iov_len);
241 967f97fa aliguori
242 26b258e1 aliguori
        cpu_physical_memory_unmap(elem->in_sg[i].iov_base,
243 26b258e1 aliguori
                                  elem->in_sg[i].iov_len,
244 26b258e1 aliguori
                                  1, size);
245 967f97fa aliguori
246 26b258e1 aliguori
        offset += elem->in_sg[i].iov_len;
247 967f97fa aliguori
    }
248 967f97fa aliguori
249 26b258e1 aliguori
    for (i = 0; i < elem->out_num; i++)
250 26b258e1 aliguori
        cpu_physical_memory_unmap(elem->out_sg[i].iov_base,
251 26b258e1 aliguori
                                  elem->out_sg[i].iov_len,
252 26b258e1 aliguori
                                  0, elem->out_sg[i].iov_len);
253 26b258e1 aliguori
254 967f97fa aliguori
    idx = (idx + vring_used_idx(vq)) % vq->vring.num;
255 967f97fa aliguori
256 967f97fa aliguori
    /* Get a pointer to the next entry in the used ring. */
257 967f97fa aliguori
    vring_used_ring_id(vq, idx, elem->index);
258 967f97fa aliguori
    vring_used_ring_len(vq, idx, len);
259 967f97fa aliguori
}
260 967f97fa aliguori
261 967f97fa aliguori
void virtqueue_flush(VirtQueue *vq, unsigned int count)
262 967f97fa aliguori
{
263 967f97fa aliguori
    /* Make sure buffer is written before we update index. */
264 967f97fa aliguori
    wmb();
265 967f97fa aliguori
    vring_used_idx_increment(vq, count);
266 967f97fa aliguori
    vq->inuse -= count;
267 967f97fa aliguori
}
268 967f97fa aliguori
269 967f97fa aliguori
void virtqueue_push(VirtQueue *vq, const VirtQueueElement *elem,
270 967f97fa aliguori
                    unsigned int len)
271 967f97fa aliguori
{
272 967f97fa aliguori
    virtqueue_fill(vq, elem, len, 0);
273 967f97fa aliguori
    virtqueue_flush(vq, 1);
274 967f97fa aliguori
}
275 967f97fa aliguori
276 967f97fa aliguori
static int virtqueue_num_heads(VirtQueue *vq, unsigned int idx)
277 967f97fa aliguori
{
278 967f97fa aliguori
    uint16_t num_heads = vring_avail_idx(vq) - idx;
279 967f97fa aliguori
280 967f97fa aliguori
    /* Check it isn't doing very strange things with descriptor numbers. */
281 bb6834cf aliguori
    if (num_heads > vq->vring.num) {
282 bb6834cf aliguori
        fprintf(stderr, "Guest moved used index from %u to %u",
283 bb6834cf aliguori
                idx, vring_avail_idx(vq));
284 bb6834cf aliguori
        exit(1);
285 bb6834cf aliguori
    }
286 967f97fa aliguori
287 967f97fa aliguori
    return num_heads;
288 967f97fa aliguori
}
289 967f97fa aliguori
290 967f97fa aliguori
static unsigned int virtqueue_get_head(VirtQueue *vq, unsigned int idx)
291 967f97fa aliguori
{
292 967f97fa aliguori
    unsigned int head;
293 967f97fa aliguori
294 967f97fa aliguori
    /* Grab the next descriptor number they're advertising, and increment
295 967f97fa aliguori
     * the index we've seen. */
296 967f97fa aliguori
    head = vring_avail_ring(vq, idx % vq->vring.num);
297 967f97fa aliguori
298 967f97fa aliguori
    /* If their number is silly, that's a fatal mistake. */
299 bb6834cf aliguori
    if (head >= vq->vring.num) {
300 bb6834cf aliguori
        fprintf(stderr, "Guest says index %u is available", head);
301 bb6834cf aliguori
        exit(1);
302 bb6834cf aliguori
    }
303 967f97fa aliguori
304 967f97fa aliguori
    return head;
305 967f97fa aliguori
}
306 967f97fa aliguori
307 967f97fa aliguori
static unsigned virtqueue_next_desc(VirtQueue *vq, unsigned int i)
308 967f97fa aliguori
{
309 967f97fa aliguori
    unsigned int next;
310 967f97fa aliguori
311 967f97fa aliguori
    /* If this descriptor says it doesn't chain, we're done. */
312 967f97fa aliguori
    if (!(vring_desc_flags(vq, i) & VRING_DESC_F_NEXT))
313 967f97fa aliguori
        return vq->vring.num;
314 967f97fa aliguori
315 967f97fa aliguori
    /* Check they're not leading us off end of descriptors. */
316 967f97fa aliguori
    next = vring_desc_next(vq, i);
317 967f97fa aliguori
    /* Make sure compiler knows to grab that: we don't want it changing! */
318 967f97fa aliguori
    wmb();
319 967f97fa aliguori
320 bb6834cf aliguori
    if (next >= vq->vring.num) {
321 bb6834cf aliguori
        fprintf(stderr, "Desc next is %u", next);
322 bb6834cf aliguori
        exit(1);
323 bb6834cf aliguori
    }
324 967f97fa aliguori
325 967f97fa aliguori
    return next;
326 967f97fa aliguori
}
327 967f97fa aliguori
328 967f97fa aliguori
int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes)
329 967f97fa aliguori
{
330 967f97fa aliguori
    unsigned int idx;
331 967f97fa aliguori
    int num_bufs, in_total, out_total;
332 967f97fa aliguori
333 967f97fa aliguori
    idx = vq->last_avail_idx;
334 967f97fa aliguori
335 967f97fa aliguori
    num_bufs = in_total = out_total = 0;
336 967f97fa aliguori
    while (virtqueue_num_heads(vq, idx)) {
337 967f97fa aliguori
        int i;
338 967f97fa aliguori
339 967f97fa aliguori
        i = virtqueue_get_head(vq, idx++);
340 967f97fa aliguori
        do {
341 967f97fa aliguori
            /* If we've got too many, that implies a descriptor loop. */
342 bb6834cf aliguori
            if (++num_bufs > vq->vring.num) {
343 bb6834cf aliguori
                fprintf(stderr, "Looped descriptor");
344 bb6834cf aliguori
                exit(1);
345 bb6834cf aliguori
            }
346 967f97fa aliguori
347 967f97fa aliguori
            if (vring_desc_flags(vq, i) & VRING_DESC_F_WRITE) {
348 967f97fa aliguori
                if (in_bytes > 0 &&
349 967f97fa aliguori
                    (in_total += vring_desc_len(vq, i)) >= in_bytes)
350 967f97fa aliguori
                    return 1;
351 967f97fa aliguori
            } else {
352 967f97fa aliguori
                if (out_bytes > 0 &&
353 967f97fa aliguori
                    (out_total += vring_desc_len(vq, i)) >= out_bytes)
354 967f97fa aliguori
                    return 1;
355 967f97fa aliguori
            }
356 967f97fa aliguori
        } while ((i = virtqueue_next_desc(vq, i)) != vq->vring.num);
357 967f97fa aliguori
    }
358 967f97fa aliguori
359 967f97fa aliguori
    return 0;
360 967f97fa aliguori
}
361 967f97fa aliguori
362 967f97fa aliguori
int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
363 967f97fa aliguori
{
364 967f97fa aliguori
    unsigned int i, head;
365 26b258e1 aliguori
    target_phys_addr_t len;
366 967f97fa aliguori
367 967f97fa aliguori
    if (!virtqueue_num_heads(vq, vq->last_avail_idx))
368 967f97fa aliguori
        return 0;
369 967f97fa aliguori
370 967f97fa aliguori
    /* When we start there are none of either input nor output. */
371 967f97fa aliguori
    elem->out_num = elem->in_num = 0;
372 967f97fa aliguori
373 967f97fa aliguori
    i = head = virtqueue_get_head(vq, vq->last_avail_idx++);
374 967f97fa aliguori
    do {
375 967f97fa aliguori
        struct iovec *sg;
376 26b258e1 aliguori
        int is_write = 0;
377 967f97fa aliguori
378 967f97fa aliguori
        if (vring_desc_flags(vq, i) & VRING_DESC_F_WRITE) {
379 967f97fa aliguori
            elem->in_addr[elem->in_num] = vring_desc_addr(vq, i);
380 967f97fa aliguori
            sg = &elem->in_sg[elem->in_num++];
381 26b258e1 aliguori
            is_write = 1;
382 967f97fa aliguori
        } else
383 967f97fa aliguori
            sg = &elem->out_sg[elem->out_num++];
384 967f97fa aliguori
385 967f97fa aliguori
        /* Grab the first descriptor, and check it's OK. */
386 967f97fa aliguori
        sg->iov_len = vring_desc_len(vq, i);
387 26b258e1 aliguori
        len = sg->iov_len;
388 967f97fa aliguori
389 26b258e1 aliguori
        sg->iov_base = cpu_physical_memory_map(vring_desc_addr(vq, i), &len, is_write);
390 26b258e1 aliguori
391 26b258e1 aliguori
        if (sg->iov_base == NULL || len != sg->iov_len) {
392 26b258e1 aliguori
            fprintf(stderr, "virtio: trying to map MMIO memory\n");
393 bb6834cf aliguori
            exit(1);
394 bb6834cf aliguori
        }
395 967f97fa aliguori
396 967f97fa aliguori
        /* If we've got too many, that implies a descriptor loop. */
397 bb6834cf aliguori
        if ((elem->in_num + elem->out_num) > vq->vring.num) {
398 bb6834cf aliguori
            fprintf(stderr, "Looped descriptor");
399 bb6834cf aliguori
            exit(1);
400 bb6834cf aliguori
        }
401 967f97fa aliguori
    } while ((i = virtqueue_next_desc(vq, i)) != vq->vring.num);
402 967f97fa aliguori
403 967f97fa aliguori
    elem->index = head;
404 967f97fa aliguori
405 967f97fa aliguori
    vq->inuse++;
406 967f97fa aliguori
407 967f97fa aliguori
    return elem->in_num + elem->out_num;
408 967f97fa aliguori
}
409 967f97fa aliguori
410 967f97fa aliguori
/* virtio device */
411 967f97fa aliguori
412 967f97fa aliguori
static VirtIODevice *to_virtio_device(PCIDevice *pci_dev)
413 967f97fa aliguori
{
414 967f97fa aliguori
    return (VirtIODevice *)pci_dev;
415 967f97fa aliguori
}
416 967f97fa aliguori
417 967f97fa aliguori
static void virtio_update_irq(VirtIODevice *vdev)
418 967f97fa aliguori
{
419 967f97fa aliguori
    qemu_set_irq(vdev->pci_dev.irq[0], vdev->isr & 1);
420 967f97fa aliguori
}
421 967f97fa aliguori
422 69d6451c blueswir1
static void virtio_reset(void *opaque)
423 967f97fa aliguori
{
424 967f97fa aliguori
    VirtIODevice *vdev = opaque;
425 967f97fa aliguori
    int i;
426 967f97fa aliguori
427 967f97fa aliguori
    if (vdev->reset)
428 967f97fa aliguori
        vdev->reset(vdev);
429 967f97fa aliguori
430 967f97fa aliguori
    vdev->features = 0;
431 967f97fa aliguori
    vdev->queue_sel = 0;
432 967f97fa aliguori
    vdev->status = 0;
433 967f97fa aliguori
    vdev->isr = 0;
434 967f97fa aliguori
    virtio_update_irq(vdev);
435 967f97fa aliguori
436 967f97fa aliguori
    for(i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
437 967f97fa aliguori
        vdev->vq[i].vring.desc = 0;
438 967f97fa aliguori
        vdev->vq[i].vring.avail = 0;
439 967f97fa aliguori
        vdev->vq[i].vring.used = 0;
440 967f97fa aliguori
        vdev->vq[i].last_avail_idx = 0;
441 967f97fa aliguori
        vdev->vq[i].pfn = 0;
442 967f97fa aliguori
    }
443 967f97fa aliguori
}
444 967f97fa aliguori
445 967f97fa aliguori
static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
446 967f97fa aliguori
{
447 967f97fa aliguori
    VirtIODevice *vdev = to_virtio_device(opaque);
448 967f97fa aliguori
    ram_addr_t pa;
449 967f97fa aliguori
450 967f97fa aliguori
    addr -= vdev->addr;
451 967f97fa aliguori
452 967f97fa aliguori
    switch (addr) {
453 967f97fa aliguori
    case VIRTIO_PCI_GUEST_FEATURES:
454 8eca6b1b aliguori
        /* Guest does not negotiate properly?  We have to assume nothing. */
455 8eca6b1b aliguori
        if (val & (1 << VIRTIO_F_BAD_FEATURE)) {
456 8eca6b1b aliguori
            if (vdev->bad_features)
457 8eca6b1b aliguori
                val = vdev->bad_features(vdev);
458 8eca6b1b aliguori
            else
459 8eca6b1b aliguori
                val = 0;
460 8eca6b1b aliguori
        }
461 967f97fa aliguori
        if (vdev->set_features)
462 967f97fa aliguori
            vdev->set_features(vdev, val);
463 967f97fa aliguori
        vdev->features = val;
464 967f97fa aliguori
        break;
465 967f97fa aliguori
    case VIRTIO_PCI_QUEUE_PFN:
466 f46f15bc aliguori
        pa = (ram_addr_t)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT;
467 967f97fa aliguori
        vdev->vq[vdev->queue_sel].pfn = val;
468 967f97fa aliguori
        if (pa == 0) {
469 967f97fa aliguori
            virtio_reset(vdev);
470 967f97fa aliguori
        } else {
471 967f97fa aliguori
            virtqueue_init(&vdev->vq[vdev->queue_sel], pa);
472 967f97fa aliguori
        }
473 967f97fa aliguori
        break;
474 967f97fa aliguori
    case VIRTIO_PCI_QUEUE_SEL:
475 967f97fa aliguori
        if (val < VIRTIO_PCI_QUEUE_MAX)
476 967f97fa aliguori
            vdev->queue_sel = val;
477 967f97fa aliguori
        break;
478 967f97fa aliguori
    case VIRTIO_PCI_QUEUE_NOTIFY:
479 967f97fa aliguori
        if (val < VIRTIO_PCI_QUEUE_MAX && vdev->vq[val].vring.desc)
480 967f97fa aliguori
            vdev->vq[val].handle_output(vdev, &vdev->vq[val]);
481 967f97fa aliguori
        break;
482 967f97fa aliguori
    case VIRTIO_PCI_STATUS:
483 967f97fa aliguori
        vdev->status = val & 0xFF;
484 967f97fa aliguori
        if (vdev->status == 0)
485 967f97fa aliguori
            virtio_reset(vdev);
486 967f97fa aliguori
        break;
487 967f97fa aliguori
    }
488 967f97fa aliguori
}
489 967f97fa aliguori
490 967f97fa aliguori
static uint32_t virtio_ioport_read(void *opaque, uint32_t addr)
491 967f97fa aliguori
{
492 967f97fa aliguori
    VirtIODevice *vdev = to_virtio_device(opaque);
493 967f97fa aliguori
    uint32_t ret = 0xFFFFFFFF;
494 967f97fa aliguori
495 967f97fa aliguori
    addr -= vdev->addr;
496 967f97fa aliguori
497 967f97fa aliguori
    switch (addr) {
498 967f97fa aliguori
    case VIRTIO_PCI_HOST_FEATURES:
499 967f97fa aliguori
        ret = vdev->get_features(vdev);
500 8eca6b1b aliguori
        ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY) | (1 << VIRTIO_F_BAD_FEATURE);
501 967f97fa aliguori
        break;
502 967f97fa aliguori
    case VIRTIO_PCI_GUEST_FEATURES:
503 967f97fa aliguori
        ret = vdev->features;
504 967f97fa aliguori
        break;
505 967f97fa aliguori
    case VIRTIO_PCI_QUEUE_PFN:
506 967f97fa aliguori
        ret = vdev->vq[vdev->queue_sel].pfn;
507 967f97fa aliguori
        break;
508 967f97fa aliguori
    case VIRTIO_PCI_QUEUE_NUM:
509 967f97fa aliguori
        ret = vdev->vq[vdev->queue_sel].vring.num;
510 967f97fa aliguori
        break;
511 967f97fa aliguori
    case VIRTIO_PCI_QUEUE_SEL:
512 967f97fa aliguori
        ret = vdev->queue_sel;
513 967f97fa aliguori
        break;
514 967f97fa aliguori
    case VIRTIO_PCI_STATUS:
515 967f97fa aliguori
        ret = vdev->status;
516 967f97fa aliguori
        break;
517 967f97fa aliguori
    case VIRTIO_PCI_ISR:
518 967f97fa aliguori
        /* reading from the ISR also clears it. */
519 967f97fa aliguori
        ret = vdev->isr;
520 967f97fa aliguori
        vdev->isr = 0;
521 967f97fa aliguori
        virtio_update_irq(vdev);
522 967f97fa aliguori
        break;
523 967f97fa aliguori
    default:
524 967f97fa aliguori
        break;
525 967f97fa aliguori
    }
526 967f97fa aliguori
527 967f97fa aliguori
    return ret;
528 967f97fa aliguori
}
529 967f97fa aliguori
530 967f97fa aliguori
static uint32_t virtio_config_readb(void *opaque, uint32_t addr)
531 967f97fa aliguori
{
532 967f97fa aliguori
    VirtIODevice *vdev = opaque;
533 967f97fa aliguori
    uint8_t val;
534 967f97fa aliguori
535 967f97fa aliguori
    vdev->get_config(vdev, vdev->config);
536 967f97fa aliguori
537 967f97fa aliguori
    addr -= vdev->addr + VIRTIO_PCI_CONFIG;
538 967f97fa aliguori
    if (addr > (vdev->config_len - sizeof(val)))
539 967f97fa aliguori
        return (uint32_t)-1;
540 967f97fa aliguori
541 967f97fa aliguori
    memcpy(&val, vdev->config + addr, sizeof(val));
542 967f97fa aliguori
    return val;
543 967f97fa aliguori
}
544 967f97fa aliguori
545 967f97fa aliguori
static uint32_t virtio_config_readw(void *opaque, uint32_t addr)
546 967f97fa aliguori
{
547 967f97fa aliguori
    VirtIODevice *vdev = opaque;
548 967f97fa aliguori
    uint16_t val;
549 967f97fa aliguori
550 967f97fa aliguori
    vdev->get_config(vdev, vdev->config);
551 967f97fa aliguori
552 967f97fa aliguori
    addr -= vdev->addr + VIRTIO_PCI_CONFIG;
553 967f97fa aliguori
    if (addr > (vdev->config_len - sizeof(val)))
554 967f97fa aliguori
        return (uint32_t)-1;
555 967f97fa aliguori
556 967f97fa aliguori
    memcpy(&val, vdev->config + addr, sizeof(val));
557 967f97fa aliguori
    return val;
558 967f97fa aliguori
}
559 967f97fa aliguori
560 967f97fa aliguori
static uint32_t virtio_config_readl(void *opaque, uint32_t addr)
561 967f97fa aliguori
{
562 967f97fa aliguori
    VirtIODevice *vdev = opaque;
563 967f97fa aliguori
    uint32_t val;
564 967f97fa aliguori
565 967f97fa aliguori
    vdev->get_config(vdev, vdev->config);
566 967f97fa aliguori
567 967f97fa aliguori
    addr -= vdev->addr + VIRTIO_PCI_CONFIG;
568 967f97fa aliguori
    if (addr > (vdev->config_len - sizeof(val)))
569 967f97fa aliguori
        return (uint32_t)-1;
570 967f97fa aliguori
571 967f97fa aliguori
    memcpy(&val, vdev->config + addr, sizeof(val));
572 967f97fa aliguori
    return val;
573 967f97fa aliguori
}
574 967f97fa aliguori
575 967f97fa aliguori
static void virtio_config_writeb(void *opaque, uint32_t addr, uint32_t data)
576 967f97fa aliguori
{
577 967f97fa aliguori
    VirtIODevice *vdev = opaque;
578 967f97fa aliguori
    uint8_t val = data;
579 967f97fa aliguori
580 967f97fa aliguori
    addr -= vdev->addr + VIRTIO_PCI_CONFIG;
581 967f97fa aliguori
    if (addr > (vdev->config_len - sizeof(val)))
582 967f97fa aliguori
        return;
583 967f97fa aliguori
584 967f97fa aliguori
    memcpy(vdev->config + addr, &val, sizeof(val));
585 967f97fa aliguori
586 967f97fa aliguori
    if (vdev->set_config)
587 967f97fa aliguori
        vdev->set_config(vdev, vdev->config);
588 967f97fa aliguori
}
589 967f97fa aliguori
590 967f97fa aliguori
static void virtio_config_writew(void *opaque, uint32_t addr, uint32_t data)
591 967f97fa aliguori
{
592 967f97fa aliguori
    VirtIODevice *vdev = opaque;
593 967f97fa aliguori
    uint16_t val = data;
594 967f97fa aliguori
595 967f97fa aliguori
    addr -= vdev->addr + VIRTIO_PCI_CONFIG;
596 967f97fa aliguori
    if (addr > (vdev->config_len - sizeof(val)))
597 967f97fa aliguori
        return;
598 967f97fa aliguori
599 967f97fa aliguori
    memcpy(vdev->config + addr, &val, sizeof(val));
600 967f97fa aliguori
601 967f97fa aliguori
    if (vdev->set_config)
602 967f97fa aliguori
        vdev->set_config(vdev, vdev->config);
603 967f97fa aliguori
}
604 967f97fa aliguori
605 967f97fa aliguori
static void virtio_config_writel(void *opaque, uint32_t addr, uint32_t data)
606 967f97fa aliguori
{
607 967f97fa aliguori
    VirtIODevice *vdev = opaque;
608 967f97fa aliguori
    uint32_t val = data;
609 967f97fa aliguori
610 967f97fa aliguori
    addr -= vdev->addr + VIRTIO_PCI_CONFIG;
611 967f97fa aliguori
    if (addr > (vdev->config_len - sizeof(val)))
612 967f97fa aliguori
        return;
613 967f97fa aliguori
614 967f97fa aliguori
    memcpy(vdev->config + addr, &val, sizeof(val));
615 967f97fa aliguori
616 967f97fa aliguori
    if (vdev->set_config)
617 967f97fa aliguori
        vdev->set_config(vdev, vdev->config);
618 967f97fa aliguori
}
619 967f97fa aliguori
620 967f97fa aliguori
static void virtio_map(PCIDevice *pci_dev, int region_num,
621 967f97fa aliguori
                       uint32_t addr, uint32_t size, int type)
622 967f97fa aliguori
{
623 967f97fa aliguori
    VirtIODevice *vdev = to_virtio_device(pci_dev);
624 967f97fa aliguori
    int i;
625 967f97fa aliguori
626 967f97fa aliguori
    vdev->addr = addr;
627 967f97fa aliguori
    for (i = 0; i < 3; i++) {
628 967f97fa aliguori
        register_ioport_write(addr, 20, 1 << i, virtio_ioport_write, vdev);
629 967f97fa aliguori
        register_ioport_read(addr, 20, 1 << i, virtio_ioport_read, vdev);
630 967f97fa aliguori
    }
631 967f97fa aliguori
632 967f97fa aliguori
    if (vdev->config_len) {
633 967f97fa aliguori
        register_ioport_write(addr + 20, vdev->config_len, 1,
634 967f97fa aliguori
                              virtio_config_writeb, vdev);
635 967f97fa aliguori
        register_ioport_write(addr + 20, vdev->config_len, 2,
636 967f97fa aliguori
                              virtio_config_writew, vdev);
637 967f97fa aliguori
        register_ioport_write(addr + 20, vdev->config_len, 4,
638 967f97fa aliguori
                              virtio_config_writel, vdev);
639 967f97fa aliguori
        register_ioport_read(addr + 20, vdev->config_len, 1,
640 967f97fa aliguori
                             virtio_config_readb, vdev);
641 967f97fa aliguori
        register_ioport_read(addr + 20, vdev->config_len, 2,
642 967f97fa aliguori
                             virtio_config_readw, vdev);
643 967f97fa aliguori
        register_ioport_read(addr + 20, vdev->config_len, 4,
644 967f97fa aliguori
                             virtio_config_readl, vdev);
645 967f97fa aliguori
646 967f97fa aliguori
        vdev->get_config(vdev, vdev->config);
647 967f97fa aliguori
    }
648 967f97fa aliguori
}
649 967f97fa aliguori
650 967f97fa aliguori
VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size,
651 967f97fa aliguori
                            void (*handle_output)(VirtIODevice *, VirtQueue *))
652 967f97fa aliguori
{
653 967f97fa aliguori
    int i;
654 967f97fa aliguori
655 967f97fa aliguori
    for (i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
656 967f97fa aliguori
        if (vdev->vq[i].vring.num == 0)
657 967f97fa aliguori
            break;
658 967f97fa aliguori
    }
659 967f97fa aliguori
660 967f97fa aliguori
    if (i == VIRTIO_PCI_QUEUE_MAX || queue_size > VIRTQUEUE_MAX_SIZE)
661 967f97fa aliguori
        abort();
662 967f97fa aliguori
663 967f97fa aliguori
    vdev->vq[i].vring.num = queue_size;
664 967f97fa aliguori
    vdev->vq[i].handle_output = handle_output;
665 967f97fa aliguori
666 967f97fa aliguori
    return &vdev->vq[i];
667 967f97fa aliguori
}
668 967f97fa aliguori
669 967f97fa aliguori
void virtio_notify(VirtIODevice *vdev, VirtQueue *vq)
670 967f97fa aliguori
{
671 97b83deb aliguori
    /* Always notify when queue is empty (when feature acknowledge) */
672 97b83deb aliguori
    if ((vring_avail_flags(vq) & VRING_AVAIL_F_NO_INTERRUPT) &&
673 97b83deb aliguori
        (!(vdev->features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY)) ||
674 97b83deb aliguori
         (vq->inuse || vring_avail_idx(vq) != vq->last_avail_idx)))
675 967f97fa aliguori
        return;
676 967f97fa aliguori
677 967f97fa aliguori
    vdev->isr |= 0x01;
678 967f97fa aliguori
    virtio_update_irq(vdev);
679 967f97fa aliguori
}
680 967f97fa aliguori
681 967f97fa aliguori
void virtio_notify_config(VirtIODevice *vdev)
682 967f97fa aliguori
{
683 7625162c aliguori
    if (!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK))
684 7625162c aliguori
        return;
685 7625162c aliguori
686 967f97fa aliguori
    vdev->isr |= 0x03;
687 967f97fa aliguori
    virtio_update_irq(vdev);
688 967f97fa aliguori
}
689 967f97fa aliguori
690 967f97fa aliguori
void virtio_save(VirtIODevice *vdev, QEMUFile *f)
691 967f97fa aliguori
{
692 967f97fa aliguori
    int i;
693 967f97fa aliguori
694 967f97fa aliguori
    pci_device_save(&vdev->pci_dev, f);
695 967f97fa aliguori
696 967f97fa aliguori
    qemu_put_be32s(f, &vdev->addr);
697 967f97fa aliguori
    qemu_put_8s(f, &vdev->status);
698 967f97fa aliguori
    qemu_put_8s(f, &vdev->isr);
699 967f97fa aliguori
    qemu_put_be16s(f, &vdev->queue_sel);
700 967f97fa aliguori
    qemu_put_be32s(f, &vdev->features);
701 967f97fa aliguori
    qemu_put_be32(f, vdev->config_len);
702 967f97fa aliguori
    qemu_put_buffer(f, vdev->config, vdev->config_len);
703 967f97fa aliguori
704 967f97fa aliguori
    for (i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
705 967f97fa aliguori
        if (vdev->vq[i].vring.num == 0)
706 967f97fa aliguori
            break;
707 967f97fa aliguori
    }
708 967f97fa aliguori
709 967f97fa aliguori
    qemu_put_be32(f, i);
710 967f97fa aliguori
711 967f97fa aliguori
    for (i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
712 967f97fa aliguori
        if (vdev->vq[i].vring.num == 0)
713 967f97fa aliguori
            break;
714 967f97fa aliguori
715 967f97fa aliguori
        qemu_put_be32(f, vdev->vq[i].vring.num);
716 967f97fa aliguori
        qemu_put_be32s(f, &vdev->vq[i].pfn);
717 967f97fa aliguori
        qemu_put_be16s(f, &vdev->vq[i].last_avail_idx);
718 967f97fa aliguori
    }
719 967f97fa aliguori
}
720 967f97fa aliguori
721 967f97fa aliguori
void virtio_load(VirtIODevice *vdev, QEMUFile *f)
722 967f97fa aliguori
{
723 967f97fa aliguori
    int num, i;
724 967f97fa aliguori
725 967f97fa aliguori
    pci_device_load(&vdev->pci_dev, f);
726 967f97fa aliguori
727 967f97fa aliguori
    qemu_get_be32s(f, &vdev->addr);
728 967f97fa aliguori
    qemu_get_8s(f, &vdev->status);
729 967f97fa aliguori
    qemu_get_8s(f, &vdev->isr);
730 967f97fa aliguori
    qemu_get_be16s(f, &vdev->queue_sel);
731 967f97fa aliguori
    qemu_get_be32s(f, &vdev->features);
732 967f97fa aliguori
    vdev->config_len = qemu_get_be32(f);
733 967f97fa aliguori
    qemu_get_buffer(f, vdev->config, vdev->config_len);
734 967f97fa aliguori
735 967f97fa aliguori
    num = qemu_get_be32(f);
736 967f97fa aliguori
737 967f97fa aliguori
    for (i = 0; i < num; i++) {
738 967f97fa aliguori
        vdev->vq[i].vring.num = qemu_get_be32(f);
739 967f97fa aliguori
        qemu_get_be32s(f, &vdev->vq[i].pfn);
740 967f97fa aliguori
        qemu_get_be16s(f, &vdev->vq[i].last_avail_idx);
741 967f97fa aliguori
742 967f97fa aliguori
        if (vdev->vq[i].pfn) {
743 967f97fa aliguori
            target_phys_addr_t pa;
744 967f97fa aliguori
745 f46f15bc aliguori
            pa = (ram_addr_t)vdev->vq[i].pfn << VIRTIO_PCI_QUEUE_ADDR_SHIFT;
746 967f97fa aliguori
            virtqueue_init(&vdev->vq[i], pa);
747 967f97fa aliguori
        }
748 967f97fa aliguori
    }
749 967f97fa aliguori
750 967f97fa aliguori
    virtio_update_irq(vdev);
751 967f97fa aliguori
}
752 967f97fa aliguori
753 b946a153 aliguori
void virtio_cleanup(VirtIODevice *vdev)
754 b946a153 aliguori
{
755 b946a153 aliguori
    if (vdev->config)
756 b946a153 aliguori
        qemu_free(vdev->config);
757 b946a153 aliguori
    qemu_free(vdev->vq);
758 b946a153 aliguori
}
759 b946a153 aliguori
760 967f97fa aliguori
VirtIODevice *virtio_init_pci(PCIBus *bus, const char *name,
761 967f97fa aliguori
                              uint16_t vendor, uint16_t device,
762 967f97fa aliguori
                              uint16_t subvendor, uint16_t subdevice,
763 173a543b blueswir1
                              uint16_t class_code, uint8_t pif,
764 173a543b blueswir1
                              size_t config_size, size_t struct_size)
765 967f97fa aliguori
{
766 967f97fa aliguori
    VirtIODevice *vdev;
767 967f97fa aliguori
    PCIDevice *pci_dev;
768 967f97fa aliguori
    uint8_t *config;
769 967f97fa aliguori
    uint32_t size;
770 967f97fa aliguori
771 967f97fa aliguori
    pci_dev = pci_register_device(bus, name, struct_size,
772 967f97fa aliguori
                                  -1, NULL, NULL);
773 967f97fa aliguori
    if (!pci_dev)
774 967f97fa aliguori
        return NULL;
775 967f97fa aliguori
776 967f97fa aliguori
    vdev = to_virtio_device(pci_dev);
777 967f97fa aliguori
778 967f97fa aliguori
    vdev->status = 0;
779 967f97fa aliguori
    vdev->isr = 0;
780 967f97fa aliguori
    vdev->queue_sel = 0;
781 967f97fa aliguori
    vdev->vq = qemu_mallocz(sizeof(VirtQueue) * VIRTIO_PCI_QUEUE_MAX);
782 967f97fa aliguori
783 967f97fa aliguori
    config = pci_dev->config;
784 deb54399 aliguori
    pci_config_set_vendor_id(config, vendor);
785 deb54399 aliguori
    pci_config_set_device_id(config, device);
786 967f97fa aliguori
787 967f97fa aliguori
    config[0x08] = VIRTIO_PCI_ABI_VERSION;
788 967f97fa aliguori
789 967f97fa aliguori
    config[0x09] = pif;
790 173a543b blueswir1
    pci_config_set_class(config, class_code);
791 967f97fa aliguori
    config[0x0e] = 0x00;
792 967f97fa aliguori
793 967f97fa aliguori
    config[0x2c] = subvendor & 0xFF;
794 967f97fa aliguori
    config[0x2d] = (subvendor >> 8) & 0xFF;
795 967f97fa aliguori
    config[0x2e] = subdevice & 0xFF;
796 967f97fa aliguori
    config[0x2f] = (subdevice >> 8) & 0xFF;
797 967f97fa aliguori
798 967f97fa aliguori
    config[0x3d] = 1;
799 967f97fa aliguori
800 967f97fa aliguori
    vdev->name = name;
801 967f97fa aliguori
    vdev->config_len = config_size;
802 967f97fa aliguori
    if (vdev->config_len)
803 967f97fa aliguori
        vdev->config = qemu_mallocz(config_size);
804 967f97fa aliguori
    else
805 967f97fa aliguori
        vdev->config = NULL;
806 967f97fa aliguori
807 967f97fa aliguori
    size = 20 + config_size;
808 967f97fa aliguori
    if (size & (size-1))
809 ad46db9a blueswir1
        size = 1 << qemu_fls(size);
810 967f97fa aliguori
811 967f97fa aliguori
    pci_register_io_region(pci_dev, 0, size, PCI_ADDRESS_SPACE_IO,
812 967f97fa aliguori
                           virtio_map);
813 967f97fa aliguori
    qemu_register_reset(virtio_reset, vdev);
814 967f97fa aliguori
815 967f97fa aliguori
    return vdev;
816 967f97fa aliguori
}