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, ...) \ 32 do { 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 78 typedef 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 92 static 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 181 static 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 289 static const MemoryRegionOps virtio_mem_ops = { 290 .read = virtio_mmio_read, 291 .write = virtio_mmio_write, 292 .endianness = DEVICE_NATIVE_ENDIAN, 293 }; 294 295 static 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 309 static unsigned int virtio_mmio_get_features(DeviceState *opaque) 310 { 311 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque); 312 313 return proxy->host_features; 314 } 315 316 static 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 326 static 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 335 static 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. */ 348 static 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 357 static 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 370 static Property virtio_mmio_properties[] = { 371 DEFINE_VIRTIO_COMMON_FEATURES(VirtIOMMIOProxy, host_features), 372 DEFINE_PROP_END_OF_LIST(), 373 }; 374 375 static 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 385 static 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 394 static 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 408 static 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 415 static void virtio_mmio_register_types(void) 416 { 417 type_register_static(&virtio_mmio_bus_info); 418 type_register_static(&virtio_mmio_info); 419 } 420 421 type_init(virtio_mmio_register_types) 422