Statistics
| Branch: | Revision:

root / hw / virtio-pci.c @ 15239b2e

History | View | Annotate | Download (16.1 kB)

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
#include "msix.h"
22

    
23
/* from Linux's linux/virtio_pci.h */
24

    
25
/* A 32-bit r/o bitmask of the features supported by the host */
26
#define VIRTIO_PCI_HOST_FEATURES        0
27

    
28
/* A 32-bit r/w bitmask of features activated by the guest */
29
#define VIRTIO_PCI_GUEST_FEATURES       4
30

    
31
/* A 32-bit r/w PFN for the currently selected queue */
32
#define VIRTIO_PCI_QUEUE_PFN            8
33

    
34
/* A 16-bit r/o queue size for the currently selected queue */
35
#define VIRTIO_PCI_QUEUE_NUM            12
36

    
37
/* A 16-bit r/w queue selector */
38
#define VIRTIO_PCI_QUEUE_SEL            14
39

    
40
/* A 16-bit r/w queue notifier */
41
#define VIRTIO_PCI_QUEUE_NOTIFY         16
42

    
43
/* An 8-bit device status register.  */
44
#define VIRTIO_PCI_STATUS               18
45

    
46
/* An 8-bit r/o interrupt status register.  Reading the value will return the
47
 * current contents of the ISR and will also clear it.  This is effectively
48
 * a read-and-acknowledge. */
49
#define VIRTIO_PCI_ISR                  19
50

    
51
/* MSI-X registers: only enabled if MSI-X is enabled. */
52
/* A 16-bit vector for configuration changes. */
53
#define VIRTIO_MSI_CONFIG_VECTOR        20
54
/* A 16-bit vector for selected queue notifications. */
55
#define VIRTIO_MSI_QUEUE_VECTOR         22
56

    
57
/* Config space size */
58
#define VIRTIO_PCI_CONFIG_NOMSI         20
59
#define VIRTIO_PCI_CONFIG_MSI           24
60
#define VIRTIO_PCI_REGION_SIZE(dev)     (msix_present(dev) ? \
61
                                         VIRTIO_PCI_CONFIG_MSI : \
62
                                         VIRTIO_PCI_CONFIG_NOMSI)
63

    
64
/* The remaining space is defined by each driver as the per-driver
65
 * configuration space */
66
#define VIRTIO_PCI_CONFIG(dev)          (msix_enabled(dev) ? \
67
                                         VIRTIO_PCI_CONFIG_MSI : \
68
                                         VIRTIO_PCI_CONFIG_NOMSI)
69

    
70
/* Virtio ABI version, if we increment this, we break the guest driver. */
71
#define VIRTIO_PCI_ABI_VERSION          0
72

    
73
/* How many bits to shift physical queue address written to QUEUE_PFN.
74
 * 12 is historical, and due to x86 page size. */
75
#define VIRTIO_PCI_QUEUE_ADDR_SHIFT    12
76

    
77
/* QEMU doesn't strictly need write barriers since everything runs in
78
 * lock-step.  We'll leave the calls to wmb() in though to make it obvious for
79
 * KVM or if kqemu gets SMP support.
80
 */
81
#define wmb() do { } while (0)
82

    
83
/* PCI bindings.  */
84

    
85
typedef struct {
86
    PCIDevice pci_dev;
87
    VirtIODevice *vdev;
88
    uint32_t addr;
89
} VirtIOPCIProxy;
90

    
91
/* virtio device */
92

    
93
static void virtio_pci_notify(void *opaque, uint16_t vector)
94
{
95
    VirtIOPCIProxy *proxy = opaque;
96
    if (msix_enabled(&proxy->pci_dev))
97
        msix_notify(&proxy->pci_dev, vector);
98
    else
99
        qemu_set_irq(proxy->pci_dev.irq[0], proxy->vdev->isr & 1);
100
}
101

    
102
static void virtio_pci_save_config(void * opaque, QEMUFile *f)
103
{
104
    VirtIOPCIProxy *proxy = opaque;
105
    pci_device_save(&proxy->pci_dev, f);
106
    msix_save(&proxy->pci_dev, f);
107
    if (msix_present(&proxy->pci_dev))
108
        qemu_put_be16(f, proxy->vdev->config_vector);
109
}
110

    
111
static void virtio_pci_save_queue(void * opaque, int n, QEMUFile *f)
112
{
113
    VirtIOPCIProxy *proxy = opaque;
114
    if (msix_present(&proxy->pci_dev))
115
        qemu_put_be16(f, virtio_queue_vector(proxy->vdev, n));
116
}
117

    
118
static int virtio_pci_load_config(void * opaque, QEMUFile *f)
119
{
120
    VirtIOPCIProxy *proxy = opaque;
121
    int ret;
122
    ret = pci_device_load(&proxy->pci_dev, f);
123
    if (ret) {
124
        return ret;
125
    }
126
    msix_load(&proxy->pci_dev, f);
127
    if (msix_present(&proxy->pci_dev)) {
128
        qemu_get_be16s(f, &proxy->vdev->config_vector);
129
    } else {
130
        proxy->vdev->config_vector = VIRTIO_NO_VECTOR;
131
    }
132
    if (proxy->vdev->config_vector != VIRTIO_NO_VECTOR) {
133
        return msix_vector_use(&proxy->pci_dev, proxy->vdev->config_vector);
134
    }
135
    return 0;
136
}
137

    
138
static int virtio_pci_load_queue(void * opaque, int n, QEMUFile *f)
139
{
140
    VirtIOPCIProxy *proxy = opaque;
141
    uint16_t vector;
142
    if (msix_present(&proxy->pci_dev)) {
143
        qemu_get_be16s(f, &vector);
144
    } else {
145
        vector = VIRTIO_NO_VECTOR;
146
    }
147
    virtio_queue_set_vector(proxy->vdev, n, vector);
148
    if (vector != VIRTIO_NO_VECTOR) {
149
        return msix_vector_use(&proxy->pci_dev, vector);
150
    }
151
    return 0;
152
}
153

    
154
static void virtio_pci_reset(void *opaque)
155
{
156
    VirtIOPCIProxy *proxy = opaque;
157
    virtio_reset(proxy->vdev);
158
    msix_reset(&proxy->pci_dev);
159
}
160

    
161
static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
162
{
163
    VirtIOPCIProxy *proxy = opaque;
164
    VirtIODevice *vdev = proxy->vdev;
165
    target_phys_addr_t pa;
166

    
167
    switch (addr) {
168
    case VIRTIO_PCI_GUEST_FEATURES:
169
        /* Guest does not negotiate properly?  We have to assume nothing. */
170
        if (val & (1 << VIRTIO_F_BAD_FEATURE)) {
171
            if (vdev->bad_features)
172
                val = vdev->bad_features(vdev);
173
            else
174
                val = 0;
175
        }
176
        if (vdev->set_features)
177
            vdev->set_features(vdev, val);
178
        vdev->features = val;
179
        break;
180
    case VIRTIO_PCI_QUEUE_PFN:
181
        pa = (target_phys_addr_t)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT;
182
        if (pa == 0)
183
            virtio_pci_reset(proxy);
184
        else
185
            virtio_queue_set_addr(vdev, vdev->queue_sel, pa);
186
        break;
187
    case VIRTIO_PCI_QUEUE_SEL:
188
        if (val < VIRTIO_PCI_QUEUE_MAX)
189
            vdev->queue_sel = val;
190
        break;
191
    case VIRTIO_PCI_QUEUE_NOTIFY:
192
        virtio_queue_notify(vdev, val);
193
        break;
194
    case VIRTIO_PCI_STATUS:
195
        vdev->status = val & 0xFF;
196
        if (vdev->status == 0)
197
            virtio_pci_reset(proxy);
198
        break;
199
    case VIRTIO_MSI_CONFIG_VECTOR:
200
        msix_vector_unuse(&proxy->pci_dev, vdev->config_vector);
201
        /* Make it possible for guest to discover an error took place. */
202
        if (msix_vector_use(&proxy->pci_dev, val) < 0)
203
            val = VIRTIO_NO_VECTOR;
204
        vdev->config_vector = val;
205
        break;
206
    case VIRTIO_MSI_QUEUE_VECTOR:
207
        msix_vector_unuse(&proxy->pci_dev,
208
                          virtio_queue_vector(vdev, vdev->queue_sel));
209
        /* Make it possible for guest to discover an error took place. */
210
        if (msix_vector_use(&proxy->pci_dev, val) < 0)
211
            val = VIRTIO_NO_VECTOR;
212
        virtio_queue_set_vector(vdev, vdev->queue_sel, val);
213
        break;
214
    default:
215
        fprintf(stderr, "%s: unexpected address 0x%x value 0x%x\n",
216
                __func__, addr, val);
217
        break;
218
    }
219
}
220

    
221
static uint32_t virtio_ioport_read(VirtIOPCIProxy *proxy, uint32_t addr)
222
{
223
    VirtIODevice *vdev = proxy->vdev;
224
    uint32_t ret = 0xFFFFFFFF;
225

    
226
    switch (addr) {
227
    case VIRTIO_PCI_HOST_FEATURES:
228
        ret = vdev->get_features(vdev);
229
        ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY);
230
        ret |= (1 << VIRTIO_RING_F_INDIRECT_DESC);
231
        ret |= (1 << VIRTIO_F_BAD_FEATURE);
232
        break;
233
    case VIRTIO_PCI_GUEST_FEATURES:
234
        ret = vdev->features;
235
        break;
236
    case VIRTIO_PCI_QUEUE_PFN:
237
        ret = virtio_queue_get_addr(vdev, vdev->queue_sel)
238
              >> VIRTIO_PCI_QUEUE_ADDR_SHIFT;
239
        break;
240
    case VIRTIO_PCI_QUEUE_NUM:
241
        ret = virtio_queue_get_num(vdev, vdev->queue_sel);
242
        break;
243
    case VIRTIO_PCI_QUEUE_SEL:
244
        ret = vdev->queue_sel;
245
        break;
246
    case VIRTIO_PCI_STATUS:
247
        ret = vdev->status;
248
        break;
249
    case VIRTIO_PCI_ISR:
250
        /* reading from the ISR also clears it. */
251
        ret = vdev->isr;
252
        vdev->isr = 0;
253
        qemu_set_irq(proxy->pci_dev.irq[0], 0);
254
        break;
255
    case VIRTIO_MSI_CONFIG_VECTOR:
256
        ret = vdev->config_vector;
257
        break;
258
    case VIRTIO_MSI_QUEUE_VECTOR:
259
        ret = virtio_queue_vector(vdev, vdev->queue_sel);
260
        break;
261
    default:
262
        break;
263
    }
264

    
265
    return ret;
266
}
267

    
268
static uint32_t virtio_pci_config_readb(void *opaque, uint32_t addr)
269
{
270
    VirtIOPCIProxy *proxy = opaque;
271
    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
272
    addr -= proxy->addr;
273
    if (addr < config)
274
        return virtio_ioport_read(proxy, addr);
275
    addr -= config;
276
    return virtio_config_readb(proxy->vdev, addr);
277
}
278

    
279
static uint32_t virtio_pci_config_readw(void *opaque, uint32_t addr)
280
{
281
    VirtIOPCIProxy *proxy = opaque;
282
    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
283
    addr -= proxy->addr;
284
    if (addr < config)
285
        return virtio_ioport_read(proxy, addr);
286
    addr -= config;
287
    return virtio_config_readw(proxy->vdev, addr);
288
}
289

    
290
static uint32_t virtio_pci_config_readl(void *opaque, uint32_t addr)
291
{
292
    VirtIOPCIProxy *proxy = opaque;
293
    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
294
    addr -= proxy->addr;
295
    if (addr < config)
296
        return virtio_ioport_read(proxy, addr);
297
    addr -= config;
298
    return virtio_config_readl(proxy->vdev, addr);
299
}
300

    
301
static void virtio_pci_config_writeb(void *opaque, uint32_t addr, uint32_t val)
302
{
303
    VirtIOPCIProxy *proxy = opaque;
304
    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
305
    addr -= proxy->addr;
306
    if (addr < config) {
307
        virtio_ioport_write(proxy, addr, val);
308
        return;
309
    }
310
    addr -= config;
311
    virtio_config_writeb(proxy->vdev, addr, val);
312
}
313

    
314
static void virtio_pci_config_writew(void *opaque, uint32_t addr, uint32_t val)
315
{
316
    VirtIOPCIProxy *proxy = opaque;
317
    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
318
    addr -= proxy->addr;
319
    if (addr < config) {
320
        virtio_ioport_write(proxy, addr, val);
321
        return;
322
    }
323
    addr -= config;
324
    virtio_config_writew(proxy->vdev, addr, val);
325
}
326

    
327
static void virtio_pci_config_writel(void *opaque, uint32_t addr, uint32_t val)
328
{
329
    VirtIOPCIProxy *proxy = opaque;
330
    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
331
    addr -= proxy->addr;
332
    if (addr < config) {
333
        virtio_ioport_write(proxy, addr, val);
334
        return;
335
    }
336
    addr -= config;
337
    virtio_config_writel(proxy->vdev, addr, val);
338
}
339

    
340
static void virtio_map(PCIDevice *pci_dev, int region_num,
341
                       uint32_t addr, uint32_t size, int type)
342
{
343
    VirtIOPCIProxy *proxy = container_of(pci_dev, VirtIOPCIProxy, pci_dev);
344
    VirtIODevice *vdev = proxy->vdev;
345
    unsigned config_len = VIRTIO_PCI_REGION_SIZE(pci_dev) + vdev->config_len;
346

    
347
    proxy->addr = addr;
348

    
349
    register_ioport_write(addr, config_len, 1, virtio_pci_config_writeb, proxy);
350
    register_ioport_write(addr, config_len, 2, virtio_pci_config_writew, proxy);
351
    register_ioport_write(addr, config_len, 4, virtio_pci_config_writel, proxy);
352
    register_ioport_read(addr, config_len, 1, virtio_pci_config_readb, proxy);
353
    register_ioport_read(addr, config_len, 2, virtio_pci_config_readw, proxy);
354
    register_ioport_read(addr, config_len, 4, virtio_pci_config_readl, proxy);
355

    
356
    if (vdev->config_len)
357
        vdev->get_config(vdev, vdev->config);
358
}
359

    
360
static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
361
                                uint32_t val, int len)
362
{
363
    pci_default_write_config(pci_dev, address, val, len);
364
    msix_write_config(pci_dev, address, val, len);
365
}
366

    
367
static const VirtIOBindings virtio_pci_bindings = {
368
    .notify = virtio_pci_notify,
369
    .save_config = virtio_pci_save_config,
370
    .load_config = virtio_pci_load_config,
371
    .save_queue = virtio_pci_save_queue,
372
    .load_queue = virtio_pci_load_queue,
373
};
374

    
375
static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,
376
                            uint16_t vendor, uint16_t device,
377
                            uint16_t class_code, uint8_t pif)
378
{
379
    uint8_t *config;
380
    uint32_t size;
381

    
382
    proxy->vdev = vdev;
383

    
384
    config = proxy->pci_dev.config;
385
    pci_config_set_vendor_id(config, vendor);
386
    pci_config_set_device_id(config, device);
387

    
388
    config[0x08] = VIRTIO_PCI_ABI_VERSION;
389

    
390
    config[0x09] = pif;
391
    pci_config_set_class(config, class_code);
392
    config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL;
393

    
394
    config[0x2c] = vendor & 0xFF;
395
    config[0x2d] = (vendor >> 8) & 0xFF;
396
    config[0x2e] = vdev->device_id & 0xFF;
397
    config[0x2f] = (vdev->device_id >> 8) & 0xFF;
398

    
399
    config[0x3d] = 1;
400

    
401
    if (vdev->nvectors && !msix_init(&proxy->pci_dev, vdev->nvectors, 1, 0)) {
402
        pci_register_bar(&proxy->pci_dev, 1,
403
                         msix_bar_size(&proxy->pci_dev),
404
                         PCI_ADDRESS_SPACE_MEM,
405
                         msix_mmio_map);
406
        proxy->pci_dev.config_write = virtio_write_config;
407
        proxy->pci_dev.unregister = msix_uninit;
408
    } else
409
        vdev->nvectors = 0;
410

    
411
    size = VIRTIO_PCI_REGION_SIZE(&proxy->pci_dev) + vdev->config_len;
412
    if (size & (size-1))
413
        size = 1 << qemu_fls(size);
414

    
415
    pci_register_bar(&proxy->pci_dev, 0, size, PCI_ADDRESS_SPACE_IO,
416
                           virtio_map);
417

    
418
    qemu_register_reset(virtio_pci_reset, proxy);
419

    
420
    virtio_bind_device(vdev, &virtio_pci_bindings, proxy);
421
}
422

    
423
static void virtio_blk_init_pci_with_class(PCIDevice *pci_dev,
424
                                           uint16_t class_code)
425
{
426
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
427
    VirtIODevice *vdev;
428

    
429
    vdev = virtio_blk_init(&pci_dev->qdev);
430
    virtio_init_pci(proxy, vdev,
431
                    PCI_VENDOR_ID_REDHAT_QUMRANET,
432
                    PCI_DEVICE_ID_VIRTIO_BLOCK,
433
                    class_code, 0x00);
434
}
435

    
436
static void virtio_blk_init_pci(PCIDevice *pci_dev)
437
{
438
    virtio_blk_init_pci_with_class(pci_dev, PCI_CLASS_STORAGE_SCSI);
439
}
440

    
441
static void virtio_blk_init_pci_0_10(PCIDevice *pci_dev)
442
{
443
    virtio_blk_init_pci_with_class(pci_dev, PCI_CLASS_STORAGE_OTHER);
444
}
445

    
446
static void virtio_console_init_pci_with_class(PCIDevice *pci_dev,
447
                                               uint16_t class_code)
448
{
449
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
450
    VirtIODevice *vdev;
451

    
452
    vdev = virtio_console_init(&pci_dev->qdev);
453
    virtio_init_pci(proxy, vdev,
454
                    PCI_VENDOR_ID_REDHAT_QUMRANET,
455
                    PCI_DEVICE_ID_VIRTIO_CONSOLE,
456
                    class_code, 0x00);
457
}
458

    
459
static void virtio_console_init_pci(PCIDevice *pci_dev)
460
{
461
    virtio_console_init_pci_with_class(pci_dev, PCI_CLASS_SERIAL_OTHER);
462
}
463

    
464
static void virtio_console_init_pci_0_10(PCIDevice *pci_dev)
465
{
466
    virtio_console_init_pci_with_class(pci_dev, PCI_CLASS_DISPLAY_OTHER);
467
}
468

    
469
static void virtio_net_init_pci(PCIDevice *pci_dev)
470
{
471
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
472
    VirtIODevice *vdev;
473

    
474
    vdev = virtio_net_init(&pci_dev->qdev);
475
    virtio_init_pci(proxy, vdev,
476
                    PCI_VENDOR_ID_REDHAT_QUMRANET,
477
                    PCI_DEVICE_ID_VIRTIO_NET,
478
                    PCI_CLASS_NETWORK_ETHERNET,
479
                    0x00);
480
}
481

    
482
static void virtio_balloon_init_pci(PCIDevice *pci_dev)
483
{
484
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
485
    VirtIODevice *vdev;
486

    
487
    vdev = virtio_balloon_init(&pci_dev->qdev);
488
    virtio_init_pci(proxy, vdev,
489
                    PCI_VENDOR_ID_REDHAT_QUMRANET,
490
                    PCI_DEVICE_ID_VIRTIO_BALLOON,
491
                    PCI_CLASS_MEMORY_RAM,
492
                    0x00);
493
}
494

    
495
static PCIDeviceInfo virtio_info[] = {
496
    {
497
        .qdev.name = "virtio-blk-pci",
498
        .qdev.size = sizeof(VirtIOPCIProxy),
499
        .init      = virtio_blk_init_pci,
500
    },{
501
        .qdev.name = "virtio-net-pci",
502
        .qdev.size = sizeof(VirtIOPCIProxy),
503
        .init      = virtio_net_init_pci,
504
    },{
505
        .qdev.name = "virtio-console-pci",
506
        .qdev.size = sizeof(VirtIOPCIProxy),
507
        .init      = virtio_console_init_pci,
508
    },{
509
        .qdev.name = "virtio-balloon-pci",
510
        .qdev.size = sizeof(VirtIOPCIProxy),
511
        .init      = virtio_balloon_init_pci,
512
    },{
513
        /* For compatibility with 0.10 */
514
        .qdev.name = "virtio-blk-pci-0-10",
515
        .qdev.size = sizeof(VirtIOPCIProxy),
516
        .init      = virtio_blk_init_pci_0_10,
517
    },{
518
        .qdev.name = "virtio-console-pci-0-10",
519
        .qdev.size = sizeof(VirtIOPCIProxy),
520
        .init      = virtio_console_init_pci_0_10,
521
    },{
522
        /* end of list */
523
    }
524
};
525

    
526
static void virtio_pci_register_devices(void)
527
{
528
    pci_qdev_register_many(virtio_info);
529
}
530

    
531
device_init(virtio_pci_register_devices)