|
@@ -397,9 +397,23 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index,
|
|
/* Activate the queue */
|
|
/* Activate the queue */
|
|
writel(virtqueue_get_vring_size(vq), vm_dev->base + VIRTIO_MMIO_QUEUE_NUM);
|
|
writel(virtqueue_get_vring_size(vq), vm_dev->base + VIRTIO_MMIO_QUEUE_NUM);
|
|
if (vm_dev->version == 1) {
|
|
if (vm_dev->version == 1) {
|
|
|
|
+ u64 q_pfn = virtqueue_get_desc_addr(vq) >> PAGE_SHIFT;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * virtio-mmio v1 uses a 32bit QUEUE PFN. If we have something
|
|
|
|
+ * that doesn't fit in 32bit, fail the setup rather than
|
|
|
|
+ * pretending to be successful.
|
|
|
|
+ */
|
|
|
|
+ if (q_pfn >> 32) {
|
|
|
|
+ dev_err(&vdev->dev,
|
|
|
|
+ "platform bug: legacy virtio-mmio must not be used with RAM above 0x%llxGB\n",
|
|
|
|
+ 0x1ULL << (32 + PAGE_SHIFT - 30));
|
|
|
|
+ err = -E2BIG;
|
|
|
|
+ goto error_bad_pfn;
|
|
|
|
+ }
|
|
|
|
+
|
|
writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_QUEUE_ALIGN);
|
|
writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_QUEUE_ALIGN);
|
|
- writel(virtqueue_get_desc_addr(vq) >> PAGE_SHIFT,
|
|
|
|
- vm_dev->base + VIRTIO_MMIO_QUEUE_PFN);
|
|
|
|
|
|
+ writel(q_pfn, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN);
|
|
} else {
|
|
} else {
|
|
u64 addr;
|
|
u64 addr;
|
|
|
|
|
|
@@ -430,6 +444,8 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index,
|
|
|
|
|
|
return vq;
|
|
return vq;
|
|
|
|
|
|
|
|
+error_bad_pfn:
|
|
|
|
+ vring_del_virtqueue(vq);
|
|
error_new_virtqueue:
|
|
error_new_virtqueue:
|
|
if (vm_dev->version == 1) {
|
|
if (vm_dev->version == 1) {
|
|
writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN);
|
|
writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN);
|