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 uint64_t virtio_mmio_read(void *opaque, hwaddr offset, unsigned size)
  93{
  94    VirtIOMMIOProxy *proxy = (VirtIOMMIOProxy *)opaque;
  95    VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
  96
  97    DPRINTF("virtio_mmio_read offset 0x%x\n", (int)offset);
  98
  99    if (!vdev) {
 100        /* If no backend is present, we treat most registers as
 101         * read-as-zero, except for the magic number, version and
 102         * vendor ID. This is not strictly sanctioned by the virtio
 103         * spec, but it allows us to provide transports with no backend
 104         * plugged in which don't confuse Linux's virtio code: the
 105         * probe won't complain about the bad magic number, but the
 106         * device ID of zero means no backend will claim it.
 107         */
 108        switch (offset) {
 109        case VIRTIO_MMIO_MAGIC:
 110            return VIRT_MAGIC;
 111        case VIRTIO_MMIO_VERSION:
 112            return VIRT_VERSION;
 113        case VIRTIO_MMIO_VENDORID:
 114            return VIRT_VENDOR;
 115        default:
 116            return 0;
 117        }
 118    }
 119
 120    if (offset >= VIRTIO_MMIO_CONFIG) {
 121        offset -= VIRTIO_MMIO_CONFIG;
 122        switch (size) {
 123        case 1:
 124            return virtio_config_readb(vdev, offset);
 125        case 2:
 126            return virtio_config_readw(vdev, offset);
 127        case 4:
 128            return virtio_config_readl(vdev, offset);
 129        default:
 130            abort();
 131        }
 132    }
 133    if (size != 4) {
 134        DPRINTF("wrong size access to register!\n");
 135        return 0;
 136    }
 137    switch (offset) {
 138    case VIRTIO_MMIO_MAGIC:
 139        return VIRT_MAGIC;
 140    case VIRTIO_MMIO_VERSION:
 141        return VIRT_VERSION;
 142    case VIRTIO_MMIO_DEVICEID:
 143        return vdev->device_id;
 144    case VIRTIO_MMIO_VENDORID:
 145        return VIRT_VENDOR;
 146    case VIRTIO_MMIO_HOSTFEATURES:
 147        if (proxy->host_features_sel) {
 148            return 0;
 149        }
 150        return proxy->host_features;
 151    case VIRTIO_MMIO_QUEUENUMMAX:
 152        if (!virtio_queue_get_num(vdev, vdev->queue_sel)) {
 153            return 0;
 154        }
 155        return VIRTQUEUE_MAX_SIZE;
 156    case VIRTIO_MMIO_QUEUEPFN:
 157        return virtio_queue_get_addr(vdev, vdev->queue_sel)
 158            >> proxy->guest_page_shift;
 159    case VIRTIO_MMIO_INTERRUPTSTATUS:
 160        return vdev->isr;
 161    case VIRTIO_MMIO_STATUS:
 162        return vdev->status;
 163    case VIRTIO_MMIO_HOSTFEATURESSEL:
 164    case VIRTIO_MMIO_GUESTFEATURES:
 165    case VIRTIO_MMIO_GUESTFEATURESSEL:
 166    case VIRTIO_MMIO_GUESTPAGESIZE:
 167    case VIRTIO_MMIO_QUEUESEL:
 168    case VIRTIO_MMIO_QUEUENUM:
 169    case VIRTIO_MMIO_QUEUEALIGN:
 170    case VIRTIO_MMIO_QUEUENOTIFY:
 171    case VIRTIO_MMIO_INTERRUPTACK:
 172        DPRINTF("read of write-only register\n");
 173        return 0;
 174    default:
 175        DPRINTF("bad register offset\n");
 176        return 0;
 177    }
 178    return 0;
 179}
 180
 181static void virtio_mmio_write(void *opaque, hwaddr offset, uint64_t value,
 182                              unsigned size)
 183{
 184    VirtIOMMIOProxy *proxy = (VirtIOMMIOProxy *)opaque;
 185    VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
 186
 187    DPRINTF("virtio_mmio_write offset 0x%x value 0x%" PRIx64 "\n",
 188            (int)offset, value);
 189
 190    if (!vdev) {
 191        /* If no backend is present, we just make all registers
 192         * write-ignored. This allows us to provide transports with
 193         * no backend plugged in.
 194         */
 195        return;
 196    }
 197
 198    if (offset >= VIRTIO_MMIO_CONFIG) {
 199        offset -= VIRTIO_MMIO_CONFIG;
 200        switch (size) {
 201        case 1:
 202            virtio_config_writeb(vdev, offset, value);
 203            break;
 204        case 2:
 205            virtio_config_writew(vdev, offset, value);
 206            break;
 207        case 4:
 208            virtio_config_writel(vdev, offset, value);
 209            break;
 210        default:
 211            abort();
 212        }
 213        return;
 214    }
 215    if (size != 4) {
 216        DPRINTF("wrong size access to register!\n");
 217        return;
 218    }
 219    switch (offset) {
 220    case VIRTIO_MMIO_HOSTFEATURESSEL:
 221        proxy->host_features_sel = value;
 222        break;
 223    case VIRTIO_MMIO_GUESTFEATURES:
 224        if (!proxy->guest_features_sel) {
 225            virtio_set_features(vdev, value);
 226        }
 227        break;
 228    case VIRTIO_MMIO_GUESTFEATURESSEL:
 229        proxy->guest_features_sel = value;
 230        break;
 231    case VIRTIO_MMIO_GUESTPAGESIZE:
 232        proxy->guest_page_shift = ctz32(value);
 233        if (proxy->guest_page_shift > 31) {
 234            proxy->guest_page_shift = 0;
 235        }
 236        DPRINTF("guest page size %" PRIx64 " shift %d\n", value,
 237                proxy->guest_page_shift);
 238        break;
 239    case VIRTIO_MMIO_QUEUESEL:
 240        if (value < VIRTIO_PCI_QUEUE_MAX) {
 241            vdev->queue_sel = value;
 242        }
 243        break;
 244    case VIRTIO_MMIO_QUEUENUM:
 245        DPRINTF("mmio_queue write %d max %d\n", (int)value, VIRTQUEUE_MAX_SIZE);
 246        virtio_queue_set_num(vdev, vdev->queue_sel, value);
 247        break;
 248    case VIRTIO_MMIO_QUEUEALIGN:
 249        virtio_queue_set_align(vdev, vdev->queue_sel, value);
 250        break;
 251    case VIRTIO_MMIO_QUEUEPFN:
 252        if (value == 0) {
 253            virtio_reset(vdev);
 254        } else {
 255            virtio_queue_set_addr(vdev, vdev->queue_sel,
 256                                  value << proxy->guest_page_shift);
 257        }
 258        break;
 259    case VIRTIO_MMIO_QUEUENOTIFY:
 260        if (value < VIRTIO_PCI_QUEUE_MAX) {
 261            virtio_queue_notify(vdev, value);
 262        }
 263        break;
 264    case VIRTIO_MMIO_INTERRUPTACK:
 265        vdev->isr &= ~value;
 266        virtio_update_irq(vdev);
 267        break;
 268    case VIRTIO_MMIO_STATUS:
 269        virtio_set_status(vdev, value & 0xff);
 270        if (vdev->status == 0) {
 271            virtio_reset(vdev);
 272        }
 273        break;
 274    case VIRTIO_MMIO_MAGIC:
 275    case VIRTIO_MMIO_VERSION:
 276    case VIRTIO_MMIO_DEVICEID:
 277    case VIRTIO_MMIO_VENDORID:
 278    case VIRTIO_MMIO_HOSTFEATURES:
 279    case VIRTIO_MMIO_QUEUENUMMAX:
 280    case VIRTIO_MMIO_INTERRUPTSTATUS:
 281        DPRINTF("write to readonly register\n");
 282        break;
 283
 284    default:
 285        DPRINTF("bad register offset\n");
 286    }
 287}
 288
 289static const MemoryRegionOps virtio_mem_ops = {
 290    .read = virtio_mmio_read,
 291    .write = virtio_mmio_write,
 292    .endianness = DEVICE_NATIVE_ENDIAN,
 293};
 294
 295static void virtio_mmio_update_irq(DeviceState *opaque, uint16_t vector)
 296{
 297    VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
 298    VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
 299    int level;
 300
 301    if (!vdev) {
 302        return;
 303    }
 304    level = (vdev->isr != 0);
 305    DPRINTF("virtio_mmio setting IRQ %d\n", level);
 306    qemu_set_irq(proxy->irq, level);
 307}
 308
 309static unsigned int virtio_mmio_get_features(DeviceState *opaque)
 310{
 311    VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
 312
 313    return proxy->host_features;
 314}
 315
 316static int virtio_mmio_load_config(DeviceState *opaque, QEMUFile *f)
 317{
 318    VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
 319
 320    proxy->host_features_sel = qemu_get_be32(f);
 321    proxy->guest_features_sel = qemu_get_be32(f);
 322    proxy->guest_page_shift = qemu_get_be32(f);
 323    return 0;
 324}
 325
 326static void virtio_mmio_save_config(DeviceState *opaque, QEMUFile *f)
 327{
 328    VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
 329
 330    qemu_put_be32(f, proxy->host_features_sel);
 331    qemu_put_be32(f, proxy->guest_features_sel);
 332    qemu_put_be32(f, proxy->guest_page_shift);
 333}
 334
 335static void virtio_mmio_reset(DeviceState *d)
 336{
 337    VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
 338
 339    virtio_bus_reset(&proxy->bus);
 340    proxy->host_features_sel = 0;
 341    proxy->guest_features_sel = 0;
 342    proxy->guest_page_shift = 0;
 343}
 344
 345/* virtio-mmio device */
 346
 347/* This is called by virtio-bus just after the device is plugged. */
 348static void virtio_mmio_device_plugged(DeviceState *opaque)
 349{
 350    VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
 351
 352    virtio_add_feature(&proxy->host_features, VIRTIO_F_NOTIFY_ON_EMPTY);
 353    proxy->host_features = virtio_bus_get_vdev_features(&proxy->bus,
 354                                                        proxy->host_features);
 355}
 356
 357static void virtio_mmio_realizefn(DeviceState *d, Error **errp)
 358{
 359    VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
 360    SysBusDevice *sbd = SYS_BUS_DEVICE(d);
 361
 362    qbus_create_inplace(&proxy->bus, sizeof(proxy->bus), TYPE_VIRTIO_MMIO_BUS,
 363                        d, NULL);
 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 Property virtio_mmio_properties[] = {
 371    DEFINE_VIRTIO_COMMON_FEATURES(VirtIOMMIOProxy, host_features),
 372    DEFINE_PROP_END_OF_LIST(),
 373};
 374
 375static void virtio_mmio_class_init(ObjectClass *klass, void *data)
 376{
 377    DeviceClass *dc = DEVICE_CLASS(klass);
 378
 379    dc->props = virtio_mmio_properties;
 380    dc->realize = virtio_mmio_realizefn;
 381    dc->reset = virtio_mmio_reset;
 382    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
 383}
 384
 385static const TypeInfo virtio_mmio_info = {
 386    .name          = TYPE_VIRTIO_MMIO,
 387    .parent        = TYPE_SYS_BUS_DEVICE,
 388    .instance_size = sizeof(VirtIOMMIOProxy),
 389    .class_init    = virtio_mmio_class_init,
 390};
 391
 392/* virtio-mmio-bus. */
 393
 394static void virtio_mmio_bus_class_init(ObjectClass *klass, void *data)
 395{
 396    BusClass *bus_class = BUS_CLASS(klass);
 397    VirtioBusClass *k = VIRTIO_BUS_CLASS(klass);
 398
 399    k->notify = virtio_mmio_update_irq;
 400    k->save_config = virtio_mmio_save_config;
 401    k->load_config = virtio_mmio_load_config;
 402    k->get_features = virtio_mmio_get_features;
 403    k->device_plugged = virtio_mmio_device_plugged;
 404    k->has_variable_vring_alignment = true;
 405    bus_class->max_dev = 1;
 406}
 407
 408static const TypeInfo virtio_mmio_bus_info = {
 409    .name          = TYPE_VIRTIO_MMIO_BUS,
 410    .parent        = TYPE_VIRTIO_BUS,
 411    .instance_size = sizeof(VirtioBusState),
 412    .class_init    = virtio_mmio_bus_class_init,
 413};
 414
 415static void virtio_mmio_register_types(void)
 416{
 417    type_register_static(&virtio_mmio_bus_info);
 418    type_register_static(&virtio_mmio_info);
 419}
 420
 421type_init(virtio_mmio_register_types)
 422