Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

virtio-mmio: Update the device to OASIS spec version

This patch add a support for second version of the virtio-mmio device,
which follows OASIS "Virtual I/O Device (VIRTIO) Version 1.0"
specification.

Main changes:

1. The control register symbolic names use the new device/driver
nomenclature rather than the old guest/host one.

2. The driver detect the device version (version 1 is the pre-OASIS
spec, version 2 is compatible with fist revision of the OASIS spec)
and drives the device accordingly.

3. New version uses direct addressing (64 bit address split into two
low/high register) instead of the guest page size based one,
and addresses each part of the queue (descriptors, available, used)
separately.

4. The device activity is now explicitly triggered by writing to the
"queue ready" register.

5. Whole 64 bit features are properly handled now (both ways).

Signed-off-by: Pawel Moll <pawel.moll@arm.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>

authored by

Pawel Moll and committed by
Rusty Russell
1862ee22 76545f06

+118 -57
+81 -50
drivers/virtio/virtio_mmio.c
··· 1 1 /* 2 2 * Virtio memory mapped device driver 3 3 * 4 - * Copyright 2011, ARM Ltd. 4 + * Copyright 2011-2014, ARM Ltd. 5 5 * 6 6 * This module allows virtio devices to be used over a virtual, memory mapped 7 7 * platform device. ··· 49 49 * virtio_mmio.device=1K@0x1001e000:74 50 50 * 51 51 * 52 - * 53 - * Registers layout (all 32-bit wide): 54 - * 55 - * offset d. name description 56 - * ------ -- ---------------- ----------------- 57 - * 58 - * 0x000 R MagicValue Magic value "virt" 59 - * 0x004 R Version Device version (current max. 1) 60 - * 0x008 R DeviceID Virtio device ID 61 - * 0x00c R VendorID Virtio vendor ID 62 - * 63 - * 0x010 R HostFeatures Features supported by the host 64 - * 0x014 W HostFeaturesSel Set of host features to access via HostFeatures 65 - * 66 - * 0x020 W GuestFeatures Features activated by the guest 67 - * 0x024 W GuestFeaturesSel Set of activated features to set via GuestFeatures 68 - * 0x028 W GuestPageSize Size of guest's memory page in bytes 69 - * 70 - * 0x030 W QueueSel Queue selector 71 - * 0x034 R QueueNumMax Maximum size of the currently selected queue 72 - * 0x038 W QueueNum Queue size for the currently selected queue 73 - * 0x03c W QueueAlign Used Ring alignment for the current queue 74 - * 0x040 RW QueuePFN PFN for the currently selected queue 75 - * 76 - * 0x050 W QueueNotify Queue notifier 77 - * 0x060 R InterruptStatus Interrupt status register 78 - * 0x064 W InterruptACK Interrupt acknowledge register 79 - * 0x070 RW Status Device status register 80 - * 81 - * 0x100+ RW Device-specific configuration space 82 52 * 83 53 * Based on Virtio PCI driver by Anthony Liguori, copyright IBM Corp. 2007 84 54 * ··· 115 145 static u64 vm_get_features(struct virtio_device *vdev) 116 146 { 117 147 struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); 148 + u64 features; 118 149 119 - /* TODO: Features > 32 bits */ 120 - writel(0, vm_dev->base + VIRTIO_MMIO_HOST_FEATURES_SEL); 150 + writel(1, vm_dev->base + VIRTIO_MMIO_DEVICE_FEATURES_SEL); 151 + features = readl(vm_dev->base + VIRTIO_MMIO_DEVICE_FEATURES); 152 + features <<= 32; 121 153 122 - return readl(vm_dev->base + VIRTIO_MMIO_HOST_FEATURES); 154 + writel(0, vm_dev->base + VIRTIO_MMIO_DEVICE_FEATURES_SEL); 155 + features |= readl(vm_dev->base + VIRTIO_MMIO_DEVICE_FEATURES); 156 + 157 + return features; 123 158 } 124 159 125 160 static int vm_finalize_features(struct virtio_device *vdev) ··· 134 159 /* Give virtio_ring a chance to accept features. */ 135 160 vring_transport_features(vdev); 136 161 137 - /* Make sure we don't have any features > 32 bits! */ 138 - BUG_ON((u32)vdev->features != vdev->features); 162 + /* Make sure there is are no mixed devices */ 163 + if (vm_dev->version == 2 && 164 + !__virtio_test_bit(vdev, VIRTIO_F_VERSION_1)) { 165 + dev_err(&vdev->dev, "New virtio-mmio devices (version 2) must provide VIRTIO_F_VERSION_1 feature!\n"); 166 + return -EINVAL; 167 + } 139 168 140 - writel(0, vm_dev->base + VIRTIO_MMIO_GUEST_FEATURES_SEL); 141 - writel(vdev->features, vm_dev->base + VIRTIO_MMIO_GUEST_FEATURES); 169 + writel(1, vm_dev->base + VIRTIO_MMIO_DRIVER_FEATURES_SEL); 170 + writel((u32)(vdev->features >> 32), 171 + vm_dev->base + VIRTIO_MMIO_DRIVER_FEATURES); 172 + 173 + writel(0, vm_dev->base + VIRTIO_MMIO_DRIVER_FEATURES_SEL); 174 + writel((u32)vdev->features, 175 + vm_dev->base + VIRTIO_MMIO_DRIVER_FEATURES); 142 176 143 177 return 0; 144 178 } ··· 259 275 260 276 /* Select and deactivate the queue */ 261 277 writel(index, vm_dev->base + VIRTIO_MMIO_QUEUE_SEL); 262 - writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN); 278 + if (vm_dev->version == 1) { 279 + writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN); 280 + } else { 281 + writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_READY); 282 + WARN_ON(readl(vm_dev->base + VIRTIO_MMIO_QUEUE_READY)); 283 + } 263 284 264 285 size = PAGE_ALIGN(vring_size(info->num, VIRTIO_MMIO_VRING_ALIGN)); 265 286 free_pages_exact(info->queue, size); ··· 301 312 writel(index, vm_dev->base + VIRTIO_MMIO_QUEUE_SEL); 302 313 303 314 /* Queue shouldn't already be set up. */ 304 - if (readl(vm_dev->base + VIRTIO_MMIO_QUEUE_PFN)) { 315 + if (readl(vm_dev->base + (vm_dev->version == 1 ? 316 + VIRTIO_MMIO_QUEUE_PFN : VIRTIO_MMIO_QUEUE_READY))) { 305 317 err = -ENOENT; 306 318 goto error_available; 307 319 } ··· 346 356 info->num /= 2; 347 357 } 348 358 349 - /* Activate the queue */ 350 - writel(info->num, vm_dev->base + VIRTIO_MMIO_QUEUE_NUM); 351 - writel(VIRTIO_MMIO_VRING_ALIGN, 352 - vm_dev->base + VIRTIO_MMIO_QUEUE_ALIGN); 353 - writel(virt_to_phys(info->queue) >> PAGE_SHIFT, 354 - vm_dev->base + VIRTIO_MMIO_QUEUE_PFN); 355 - 356 359 /* Create the vring */ 357 360 vq = vring_new_virtqueue(index, info->num, VIRTIO_MMIO_VRING_ALIGN, vdev, 358 361 true, info->queue, vm_notify, callback, name); 359 362 if (!vq) { 360 363 err = -ENOMEM; 361 364 goto error_new_virtqueue; 365 + } 366 + 367 + /* Activate the queue */ 368 + writel(info->num, vm_dev->base + VIRTIO_MMIO_QUEUE_NUM); 369 + if (vm_dev->version == 1) { 370 + writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_QUEUE_ALIGN); 371 + writel(virt_to_phys(info->queue) >> PAGE_SHIFT, 372 + vm_dev->base + VIRTIO_MMIO_QUEUE_PFN); 373 + } else { 374 + u64 addr; 375 + 376 + addr = virt_to_phys(info->queue); 377 + writel((u32)addr, vm_dev->base + VIRTIO_MMIO_QUEUE_DESC_LOW); 378 + writel((u32)(addr >> 32), 379 + vm_dev->base + VIRTIO_MMIO_QUEUE_DESC_HIGH); 380 + 381 + addr = virt_to_phys(virtqueue_get_avail(vq)); 382 + writel((u32)addr, vm_dev->base + VIRTIO_MMIO_QUEUE_AVAIL_LOW); 383 + writel((u32)(addr >> 32), 384 + vm_dev->base + VIRTIO_MMIO_QUEUE_AVAIL_HIGH); 385 + 386 + addr = virt_to_phys(virtqueue_get_used(vq)); 387 + writel((u32)addr, vm_dev->base + VIRTIO_MMIO_QUEUE_USED_LOW); 388 + writel((u32)(addr >> 32), 389 + vm_dev->base + VIRTIO_MMIO_QUEUE_USED_HIGH); 390 + 391 + writel(1, vm_dev->base + VIRTIO_MMIO_QUEUE_READY); 362 392 } 363 393 364 394 vq->priv = info; ··· 391 381 return vq; 392 382 393 383 error_new_virtqueue: 394 - writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN); 384 + if (vm_dev->version == 1) { 385 + writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN); 386 + } else { 387 + writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_READY); 388 + WARN_ON(readl(vm_dev->base + VIRTIO_MMIO_QUEUE_READY)); 389 + } 395 390 free_pages_exact(info->queue, size); 396 391 error_alloc_pages: 397 392 kfree(info); ··· 491 476 492 477 /* Check device version */ 493 478 vm_dev->version = readl(vm_dev->base + VIRTIO_MMIO_VERSION); 494 - if (vm_dev->version != 1) { 479 + if (vm_dev->version < 1 || vm_dev->version > 2) { 495 480 dev_err(&pdev->dev, "Version %ld not supported!\n", 496 481 vm_dev->version); 497 482 return -ENXIO; 498 483 } 499 484 500 485 vm_dev->vdev.id.device = readl(vm_dev->base + VIRTIO_MMIO_DEVICE_ID); 486 + if (vm_dev->vdev.id.device == 0) { 487 + /* 488 + * virtio-mmio device with an ID 0 is a (dummy) placeholder 489 + * with no function. End probing now with no error reported. 490 + */ 491 + return -ENODEV; 492 + } 501 493 vm_dev->vdev.id.vendor = readl(vm_dev->base + VIRTIO_MMIO_VENDOR_ID); 502 494 503 - writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_GUEST_PAGE_SIZE); 495 + /* Reject legacy-only IDs for version 2 devices */ 496 + if (vm_dev->version == 2 && 497 + virtio_device_is_legacy_only(vm_dev->vdev.id)) { 498 + dev_err(&pdev->dev, "Version 2 not supported for devices %u!\n", 499 + vm_dev->vdev.id.device); 500 + return -ENODEV; 501 + } 502 + 503 + if (vm_dev->version == 1) 504 + writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_GUEST_PAGE_SIZE); 504 505 505 506 platform_set_drvdata(pdev, vm_dev); 506 507
+37 -7
include/linux/virtio_mmio.h
··· 51 51 /* Virtio vendor ID - Read Only */ 52 52 #define VIRTIO_MMIO_VENDOR_ID 0x00c 53 53 54 - /* Bitmask of the features supported by the host 54 + /* Bitmask of the features supported by the device (host) 55 55 * (32 bits per set) - Read Only */ 56 - #define VIRTIO_MMIO_HOST_FEATURES 0x010 56 + #define VIRTIO_MMIO_DEVICE_FEATURES 0x010 57 57 58 - /* Host features set selector - Write Only */ 59 - #define VIRTIO_MMIO_HOST_FEATURES_SEL 0x014 58 + /* Device (host) features set selector - Write Only */ 59 + #define VIRTIO_MMIO_DEVICE_FEATURES_SEL 0x014 60 60 61 - /* Bitmask of features activated by the guest 61 + /* Bitmask of features activated by the driver (guest) 62 62 * (32 bits per set) - Write Only */ 63 - #define VIRTIO_MMIO_GUEST_FEATURES 0x020 63 + #define VIRTIO_MMIO_DRIVER_FEATURES 0x020 64 64 65 65 /* Activated features set selector - Write Only */ 66 - #define VIRTIO_MMIO_GUEST_FEATURES_SEL 0x024 66 + #define VIRTIO_MMIO_DRIVER_FEATURES_SEL 0x024 67 + 68 + 69 + #ifndef VIRTIO_MMIO_NO_LEGACY /* LEGACY DEVICES ONLY! */ 67 70 68 71 /* Guest's memory page size in bytes - Write Only */ 69 72 #define VIRTIO_MMIO_GUEST_PAGE_SIZE 0x028 73 + 74 + #endif 75 + 70 76 71 77 /* Queue selector - Write Only */ 72 78 #define VIRTIO_MMIO_QUEUE_SEL 0x030 ··· 83 77 /* Queue size for the currently selected queue - Write Only */ 84 78 #define VIRTIO_MMIO_QUEUE_NUM 0x038 85 79 80 + 81 + #ifndef VIRTIO_MMIO_NO_LEGACY /* LEGACY DEVICES ONLY! */ 82 + 86 83 /* Used Ring alignment for the currently selected queue - Write Only */ 87 84 #define VIRTIO_MMIO_QUEUE_ALIGN 0x03c 88 85 89 86 /* Guest's PFN for the currently selected queue - Read Write */ 90 87 #define VIRTIO_MMIO_QUEUE_PFN 0x040 88 + 89 + #endif 90 + 91 + 92 + /* Ready bit for the currently selected queue - Read Write */ 93 + #define VIRTIO_MMIO_QUEUE_READY 0x044 91 94 92 95 /* Queue notifier - Write Only */ 93 96 #define VIRTIO_MMIO_QUEUE_NOTIFY 0x050 ··· 109 94 110 95 /* Device status register - Read Write */ 111 96 #define VIRTIO_MMIO_STATUS 0x070 97 + 98 + /* Selected queue's Descriptor Table address, 64 bits in two halves */ 99 + #define VIRTIO_MMIO_QUEUE_DESC_LOW 0x080 100 + #define VIRTIO_MMIO_QUEUE_DESC_HIGH 0x084 101 + 102 + /* Selected queue's Available Ring address, 64 bits in two halves */ 103 + #define VIRTIO_MMIO_QUEUE_AVAIL_LOW 0x090 104 + #define VIRTIO_MMIO_QUEUE_AVAIL_HIGH 0x094 105 + 106 + /* Selected queue's Used Ring address, 64 bits in two halves */ 107 + #define VIRTIO_MMIO_QUEUE_USED_LOW 0x0a0 108 + #define VIRTIO_MMIO_QUEUE_USED_HIGH 0x0a4 109 + 110 + /* Configuration atomicity value */ 111 + #define VIRTIO_MMIO_CONFIG_GENERATION 0x0fc 112 112 113 113 /* The config space is defined by each driver as 114 114 * the per-driver configuration space - Read Write */