qemu/hw/virtio/virtio-mmio.c
<<
>>
Prefs
   1/*
   2 * Virtio MMIO bindings
   3 *
   4 * Copyright (c) 2011 Linaro Limited
   5 *
   6 * Author:
   7 *  Peter Maydell <peter.maydell@linaro.org>
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License; either version 2
  11 * of the License, or (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License along
  19 * with this program; if not, see <http://www.gnu.org/licenses/>.
  20 */
  21
  22#include "hw/sysbus.h"
  23#include "hw/virtio/virtio.h"
  24#include "qemu/host-utils.h"
  25#include "hw/virtio/virtio-bus.h"
  26
  27/* #define DEBUG_VIRTIO_MMIO */
  28
  29#ifdef DEBUG_VIRTIO_MMIO
  30
  31#define DPRINTF(fmt, ...) \
  32do { printf("virtio_mmio: " fmt , ## __VA_ARGS__); } while (0)
  33#else
  34#define DPRINTF(fmt, ...) do {} while (0)
  35#endif
  36
  37/* QOM macros */
  38/* virtio-mmio-bus */
  39#define TYPE_VIRTIO_MMIO_BUS "virtio-mmio-bus"
  40#define VIRTIO_MMIO_BUS(obj) \
  41        OBJECT_CHECK(VirtioBusState, (obj), TYPE_VIRTIO_MMIO_BUS)
  42#define VIRTIO_MMIO_BUS_GET_CLASS(obj) \
  43        OBJECT_GET_CLASS(VirtioBusClass, (obj), TYPE_VIRTIO_MMIO_BUS)
  44#define VIRTIO_MMIO_BUS_CLASS(klass) \
  45        OBJECT_CLASS_CHECK(VirtioBusClass, (klass), TYPE_VIRTIO_MMIO_BUS)
  46
  47/* virtio-mmio */
  48#define TYPE_VIRTIO_MMIO "virtio-mmio"
  49#define VIRTIO_MMIO(obj) \
  50        OBJECT_CHECK(VirtIOMMIOProxy, (obj), TYPE_VIRTIO_MMIO)
  51
  52/* Memory mapped register offsets */
  53#define VIRTIO_MMIO_MAGIC 0x0
  54#define VIRTIO_MMIO_VERSION 0x4
  55#define VIRTIO_MMIO_DEVICEID 0x8
  56#define VIRTIO_MMIO_VENDORID 0xc
  57#define VIRTIO_MMIO_HOSTFEATURES 0x10
  58#define VIRTIO_MMIO_HOSTFEATURESSEL 0x14
  59#define VIRTIO_MMIO_GUESTFEATURES 0x20
  60#define VIRTIO_MMIO_GUESTFEATURESSEL 0x24
  61#define VIRTIO_MMIO_GUESTPAGESIZE 0x28
  62#define VIRTIO_MMIO_QUEUESEL 0x30
  63#define VIRTIO_MMIO_QUEUENUMMAX 0x34
  64#define VIRTIO_MMIO_QUEUENUM 0x38
  65#define VIRTIO_MMIO_QUEUEALIGN 0x3c
  66#define VIRTIO_MMIO_QUEUEPFN 0x40
  67#define VIRTIO_MMIO_QUEUENOTIFY 0x50
  68#define VIRTIO_MMIO_INTERRUPTSTATUS 0x60
  69#define VIRTIO_MMIO_INTERRUPTACK 0x64
  70#define VIRTIO_MMIO_STATUS 0x70
  71/* Device specific config space starts here */
  72#define VIRTIO_MMIO_CONFIG 0x100
  73
  74#define VIRT_MAGIC 0x74726976 /* 'virt' */
  75#define VIRT_VERSION 1
  76#define VIRT_VENDOR 0x554D4551 /* 'QEMU' */
  77
  78typedef struct {
  79    /* Generic */
  80    SysBusDevice parent_obj;
  81    MemoryRegion iomem;
  82    qemu_irq irq;
  83    uint32_t host_features;
  84    /* Guest accessible state needing migration and reset */
  85    uint32_t host_features_sel;
  86    uint32_t guest_features_sel;
  87    uint32_t guest_page_shift;
  88    /* virtio-bus */
  89    VirtioBusState bus;
  90} VirtIOMMIOProxy;
  91
  92static void virtio_mmio_bus_new(VirtioBusState *bus, VirtIOMMIOProxy *dev);
  93
  94static uint64_t virtio_mmio_read(void *opaque, hwaddr offset, unsigned size)
  95{
  96    VirtIOMMIOProxy *proxy = (VirtIOMMIOProxy *)opaque;
  97    VirtIODevice *vdev = proxy->bus.vdev;
  98
  99    DPRINTF("virtio_mmio_read offset 0x%x\n", (int)offset);
 100
 101    if (!vdev) {
 102        /* If no backend is present, we treat most registers as
 103         * read-as-zero, except for the magic number, version and
 104         * vendor ID. This is not strictly sanctioned by the virtio
 105         * spec, but it allows us to provide transports with no backend
 106         * plugged in which don't confuse Linux's virtio code: the
 107         * probe won't complain about the bad magic number, but the
 108         * device ID of zero means no backend will claim it.
 109         */
 110        switch (offset) {
 111        case VIRTIO_MMIO_MAGIC:
 112            return VIRT_MAGIC;
 113        case VIRTIO_MMIO_VERSION:
 114            return VIRT_VERSION;
 115        case VIRTIO_MMIO_VENDORID:
 116            return VIRT_VENDOR;
 117        default:
 118            return 0;
 119        }
 120    }
 121
 122    if (offset >= VIRTIO_MMIO_CONFIG) {
 123        offset -= VIRTIO_MMIO_CONFIG;
 124        switch (size) {
 125        case 1:
 126            return virtio_config_readb(vdev, offset);
 127        case 2:
 128            return virtio_config_readw(vdev, offset);
 129        case 4:
 130            return virtio_config_readl(vdev, offset);
 131        default:
 132            abort();
 133        }
 134    }
 135    if (size != 4) {
 136        DPRINTF("wrong size access to register!\n");
 137        return 0;
 138    }
 139    switch (offset) {
 140    case VIRTIO_MMIO_MAGIC:
 141        return VIRT_MAGIC;
 142    case VIRTIO_MMIO_VERSION:
 143        return VIRT_VERSION;
 144    case VIRTIO_MMIO_DEVICEID:
 145        return vdev->device_id;
 146    case VIRTIO_MMIO_VENDORID:
 147        return VIRT_VENDOR;
 148    case VIRTIO_MMIO_HOSTFEATURES:
 149        if (proxy->host_features_sel) {
 150            return 0;
 151        }
 152        return proxy->host_features;
 153    case VIRTIO_MMIO_QUEUENUMMAX:
 154        if (!virtio_queue_get_num(vdev, vdev->queue_sel)) {
 155            return 0;
 156        }
 157        return VIRTQUEUE_MAX_SIZE;
 158    case VIRTIO_MMIO_QUEUEPFN:
 159        return virtio_queue_get_addr(vdev, vdev->queue_sel)
 160            >> proxy->guest_page_shift;
 161    case VIRTIO_MMIO_INTERRUPTSTATUS:
 162        return vdev->isr;
 163    case VIRTIO_MMIO_STATUS:
 164        return vdev->status;
 165    case VIRTIO_MMIO_HOSTFEATURESSEL:
 166    case VIRTIO_MMIO_GUESTFEATURES:
 167    case VIRTIO_MMIO_GUESTFEATURESSEL:
 168    case VIRTIO_MMIO_GUESTPAGESIZE:
 169    case VIRTIO_MMIO_QUEUESEL:
 170    case VIRTIO_MMIO_QUEUENUM:
 171    case VIRTIO_MMIO_QUEUEALIGN:
 172    case VIRTIO_MMIO_QUEUENOTIFY:
 173    case VIRTIO_MMIO_INTERRUPTACK:
 174        DPRINTF("read of write-only register\n");
 175        return 0;
 176    default:
 177        DPRINTF("bad register offset\n");
 178        return 0;
 179    }
 180    return 0;
 181}
 182
 183static void virtio_mmio_write(void *opaque, hwaddr offset, uint64_t value,
 184                              unsigned size)
 185{
 186    VirtIOMMIOProxy *proxy = (VirtIOMMIOProxy *)opaque;
 187    VirtIODevice *vdev = proxy->bus.vdev;
 188
 189    DPRINTF("virtio_mmio_write offset 0x%x value 0x%" PRIx64 "\n",
 190            (int)offset, value);
 191
 192    if (!vdev) {
 193        /* If no backend is present, we just make all registers
 194         * write-ignored. This allows us to provide transports with
 195         * no backend plugged in.
 196         */
 197        return;
 198    }
 199
 200    if (offset >= VIRTIO_MMIO_CONFIG) {
 201        offset -= VIRTIO_MMIO_CONFIG;
 202        switch (size) {
 203        case 1:
 204            virtio_config_writeb(vdev, offset, value);
 205            break;
 206        case 2:
 207            virtio_config_writew(vdev, offset, value);
 208            break;
 209        case 4:
 210            virtio_config_writel(vdev, offset, value);
 211            break;
 212        default:
 213            abort();
 214        }
 215        return;
 216    }
 217    if (size != 4) {
 218        DPRINTF("wrong size access to register!\n");
 219        return;
 220    }
 221    switch (offset) {
 222    case VIRTIO_MMIO_HOSTFEATURESSEL:
 223        proxy->host_features_sel = value;
 224        break;
 225    case VIRTIO_MMIO_GUESTFEATURES:
 226        if (!proxy->guest_features_sel) {
 227            virtio_set_features(vdev, value);
 228        }
 229        break;
 230    case VIRTIO_MMIO_GUESTFEATURESSEL:
 231        proxy->guest_features_sel = value;
 232        break;
 233    case VIRTIO_MMIO_GUESTPAGESIZE:
 234        proxy->guest_page_shift = ctz32(value);
 235        if (proxy->guest_page_shift > 31) {
 236            proxy->guest_page_shift = 0;
 237        }
 238        DPRINTF("guest page size %" PRIx64 " shift %d\n", value,
 239                proxy->guest_page_shift);
 240        break;
 241    case VIRTIO_MMIO_QUEUESEL:
 242        if (value < VIRTIO_PCI_QUEUE_MAX) {
 243            vdev->queue_sel = value;
 244        }
 245        break;
 246    case VIRTIO_MMIO_QUEUENUM:
 247        DPRINTF("mmio_queue write %d max %d\n", (int)value, VIRTQUEUE_MAX_SIZE);
 248        virtio_queue_set_num(vdev, vdev->queue_sel, value);
 249        break;
 250    case VIRTIO_MMIO_QUEUEALIGN:
 251        virtio_queue_set_align(vdev, vdev->queue_sel, value);
 252        break;
 253    case VIRTIO_MMIO_QUEUEPFN:
 254        if (value == 0) {
 255            virtio_reset(vdev);
 256        } else {
 257            virtio_queue_set_addr(vdev, vdev->queue_sel,
 258                                  value << proxy->guest_page_shift);
 259        }
 260        break;
 261    case VIRTIO_MMIO_QUEUENOTIFY:
 262        if (value < VIRTIO_PCI_QUEUE_MAX) {
 263            virtio_queue_notify(vdev, value);
 264        }
 265        break;
 266    case VIRTIO_MMIO_INTERRUPTACK:
 267        vdev->isr &= ~value;
 268        virtio_update_irq(vdev);
 269        break;
 270    case VIRTIO_MMIO_STATUS:
 271        virtio_set_status(vdev, value & 0xff);
 272        if (vdev->status == 0) {
 273            virtio_reset(vdev);
 274        }
 275        break;
 276    case VIRTIO_MMIO_MAGIC:
 277    case VIRTIO_MMIO_VERSION:
 278    case VIRTIO_MMIO_DEVICEID:
 279    case VIRTIO_MMIO_VENDORID:
 280    case VIRTIO_MMIO_HOSTFEATURES:
 281    case VIRTIO_MMIO_QUEUENUMMAX:
 282    case VIRTIO_MMIO_INTERRUPTSTATUS:
 283        DPRINTF("write to readonly register\n");
 284        break;
 285
 286    default:
 287        DPRINTF("bad register offset\n");
 288    }
 289}
 290
 291static const MemoryRegionOps virtio_mem_ops = {
 292    .read = virtio_mmio_read,
 293    .write = virtio_mmio_write,
 294    .endianness = DEVICE_NATIVE_ENDIAN,
 295};
 296
 297static void virtio_mmio_update_irq(DeviceState *opaque, uint16_t vector)
 298{
 299    VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
 300    int level;
 301
 302    if (!proxy->bus.vdev) {
 303        return;
 304    }
 305    level = (proxy->bus.vdev->isr != 0);
 306    DPRINTF("virtio_mmio setting IRQ %d\n", level);
 307    qemu_set_irq(proxy->irq, level);
 308}
 309
 310static unsigned int virtio_mmio_get_features(DeviceState *opaque)
 311{
 312    VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
 313
 314    return proxy->host_features;
 315}
 316
 317static int virtio_mmio_load_config(DeviceState *opaque, QEMUFile *f)
 318{
 319    VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
 320
 321    proxy->host_features_sel = qemu_get_be32(f);
 322    proxy->guest_features_sel = qemu_get_be32(f);
 323    proxy->guest_page_shift = qemu_get_be32(f);
 324    return 0;
 325}
 326
 327static void virtio_mmio_save_config(DeviceState *opaque, QEMUFile *f)
 328{
 329    VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
 330
 331    qemu_put_be32(f, proxy->host_features_sel);
 332    qemu_put_be32(f, proxy->guest_features_sel);
 333    qemu_put_be32(f, proxy->guest_page_shift);
 334}
 335
 336static void virtio_mmio_reset(DeviceState *d)
 337{
 338    VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
 339
 340    virtio_bus_reset(&proxy->bus);
 341    proxy->host_features_sel = 0;
 342    proxy->guest_features_sel = 0;
 343    proxy->guest_page_shift = 0;
 344}
 345
 346/* virtio-mmio device */
 347
 348/* This is called by virtio-bus just after the device is plugged. */
 349static void virtio_mmio_device_plugged(DeviceState *opaque)
 350{
 351    VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
 352
 353    proxy->host_features |= (0x1 << VIRTIO_F_NOTIFY_ON_EMPTY);
 354    proxy->host_features = virtio_bus_get_vdev_features(&proxy->bus,
 355                                                        proxy->host_features);
 356}
 357
 358static void virtio_mmio_realizefn(DeviceState *d, Error **errp)
 359{
 360    VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
 361    SysBusDevice *sbd = SYS_BUS_DEVICE(d);
 362
 363    virtio_mmio_bus_new(&proxy->bus, proxy);
 364    sysbus_init_irq(sbd, &proxy->irq);
 365    memory_region_init_io(&proxy->iomem, OBJECT(d), &virtio_mem_ops, proxy,
 366                          TYPE_VIRTIO_MMIO, 0x200);
 367    sysbus_init_mmio(sbd, &proxy->iomem);
 368}
 369
 370static void virtio_mmio_class_init(ObjectClass *klass, void *data)
 371{
 372    DeviceClass *dc = DEVICE_CLASS(klass);
 373
 374    dc->realize = virtio_mmio_realizefn;
 375    dc->reset = virtio_mmio_reset;
 376    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
 377}
 378
 379static const TypeInfo virtio_mmio_info = {
 380    .name          = TYPE_VIRTIO_MMIO,
 381    .parent        = TYPE_SYS_BUS_DEVICE,
 382    .instance_size = sizeof(VirtIOMMIOProxy),
 383    .class_init    = virtio_mmio_class_init,
 384};
 385
 386/* virtio-mmio-bus. */
 387
 388static void virtio_mmio_bus_new(VirtioBusState *bus, VirtIOMMIOProxy *dev)
 389{
 390    DeviceState *qdev = DEVICE(dev);
 391    BusState *qbus;
 392
 393    qbus_create_inplace((BusState *)bus, TYPE_VIRTIO_MMIO_BUS, qdev, NULL);
 394    qbus = BUS(bus);
 395    qbus->allow_hotplug = 0;
 396}
 397
 398static void virtio_mmio_bus_class_init(ObjectClass *klass, void *data)
 399{
 400    BusClass *bus_class = BUS_CLASS(klass);
 401    VirtioBusClass *k = VIRTIO_BUS_CLASS(klass);
 402
 403    k->notify = virtio_mmio_update_irq;
 404    k->save_config = virtio_mmio_save_config;
 405    k->load_config = virtio_mmio_load_config;
 406    k->get_features = virtio_mmio_get_features;
 407    k->device_plugged = virtio_mmio_device_plugged;
 408    k->has_variable_vring_alignment = true;
 409    bus_class->max_dev = 1;
 410}
 411
 412static const TypeInfo virtio_mmio_bus_info = {
 413    .name          = TYPE_VIRTIO_MMIO_BUS,
 414    .parent        = TYPE_VIRTIO_BUS,
 415    .instance_size = sizeof(VirtioBusState),
 416    .class_init    = virtio_mmio_bus_class_init,
 417};
 418
 419static void virtio_mmio_register_types(void)
 420{
 421    type_register_static(&virtio_mmio_bus_info);
 422    type_register_static(&virtio_mmio_info);
 423}
 424
 425type_init(virtio_mmio_register_types)
 426