Re: [PATCH v2 2/3] virtio_ring: Support DMA APIs
Am 28.10.2015 um 15:04 schrieb David Woodhouse: > On Wed, 2015-10-28 at 14:52 +0900, Christian Borntraeger wrote: >>0059b25a: e3201024 lg %r2,32(%r1) >> #0059b260: e310b0a4 lg %r1,160(%r11) >> >0059b266: 4810100c lh %r1,12(%r1) > > Precisely what is that? Is that loading ->archdata.dev_ops (offset 160) > from a device and then trying to find the ->unmap_page method therein? > qemu 2.4 works, and current qemu master has a broken gdb serverI am going to fix this first. What I can tell, that the problem goes away if I disable virtio 1.0 so I assume that things are fine when Andy sends a v4 with the endianess fixes. Christian -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 2/3] virtio_ring: Support DMA APIs
On Wed, 2015-10-28 at 14:52 +0900, Christian Borntraeger wrote: >0059b25a: e3201024 lg %r2,32(%r1) > #0059b260: e310b0a4 lg %r1,160(%r11) > >0059b266: 4810100c lh %r1,12(%r1) Precisely what is that? Is that loading ->archdata.dev_ops (offset 160) from a device and then trying to find the ->unmap_page method therein? -- dwmw2 smime.p7s Description: S/MIME cryptographic signature
[PATCH v2 2/3] virtio_ring: Support DMA APIs
virtio_ring currently sends the device (usually a hypervisor) physical addresses of its I/O buffers. This is okay when DMA addresses and physical addresses are the same thing, but this isn't always the case. For example, this never works on Xen guests, and it is likely to fail if a physical "virtio" device ever ends up behind an IOMMU or swiotlb. The immediate use case for me is to enable virtio on Xen guests. For that to work, we need vring to support DMA address translation as well as a corresponding change to virtio_pci or to another driver. With this patch, if enabled, virtfs survives kmemleak and CONFIG_DMA_API_DEBUG. Signed-off-by: Andy Lutomirski--- drivers/virtio/Kconfig | 2 +- drivers/virtio/virtio_ring.c | 187 +++ tools/virtio/linux/dma-mapping.h | 17 3 files changed, 169 insertions(+), 37 deletions(-) create mode 100644 tools/virtio/linux/dma-mapping.h diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig index cab9f3f63a38..77590320d44c 100644 --- a/drivers/virtio/Kconfig +++ b/drivers/virtio/Kconfig @@ -60,7 +60,7 @@ config VIRTIO_INPUT config VIRTIO_MMIO tristate "Platform bus driver for memory mapped virtio devices" - depends on HAS_IOMEM + depends on HAS_IOMEM && HAS_DMA select VIRTIO ---help--- This drivers provides support for memory mapped virtio diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 096b857e7b75..e71bf0ca59a2 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -24,6 +24,7 @@ #include #include #include +#include #ifdef DEBUG /* For development, we want to crash whenever the ring is screwed. */ @@ -54,7 +55,14 @@ #define END_USE(vq) #endif -struct vring_virtqueue { +struct vring_desc_state +{ + void *data; /* Data for callback. */ + struct vring_desc *indir_desc; /* Indirect descriptor, if any. */ +}; + +struct vring_virtqueue +{ struct virtqueue vq; /* Actual memory layout for this queue */ @@ -92,12 +100,71 @@ struct vring_virtqueue { ktime_t last_add_time; #endif - /* Tokens for callbacks. */ - void *data[]; + /* Per-descriptor state. */ + struct vring_desc_state desc_state[]; }; #define to_vvq(_vq) container_of(_vq, struct vring_virtqueue, vq) +/* + * The DMA ops on various arches are rather gnarly right now, and + * making all of the arch DMA ops work on the vring device itself + * is a mess. For now, we use the parent device for DMA ops. + */ +struct device *vring_dma_dev(const struct vring_virtqueue *vq) +{ + return vq->vq.vdev->dev.parent; +} + +/* Map one sg entry. */ +static dma_addr_t vring_map_one_sg(const struct vring_virtqueue *vq, + struct scatterlist *sg, + enum dma_data_direction direction) +{ + /* +* We can't use dma_map_sg, because we don't use scatterlists in +* the way it expects (we don't guarantee that the scatterlist +* will exist for the lifetime of the mapping). +*/ + return dma_map_page(vring_dma_dev(vq), + sg_page(sg), sg->offset, sg->length, + direction); +} + +static dma_addr_t vring_map_single(const struct vring_virtqueue *vq, + void *cpu_addr, size_t size, + enum dma_data_direction direction) +{ + return dma_map_single(vring_dma_dev(vq), + cpu_addr, size, direction); +} + +static void vring_unmap_one(const struct vring_virtqueue *vq, + struct vring_desc *desc) +{ + u16 flags = virtio16_to_cpu(vq->vq.vdev, desc->flags); + + if (flags & VRING_DESC_F_INDIRECT) { + dma_unmap_single(vring_dma_dev(vq), +virtio64_to_cpu(vq->vq.vdev, desc->addr), +virtio32_to_cpu(vq->vq.vdev, desc->len), +(flags & VRING_DESC_F_WRITE) ? +DMA_FROM_DEVICE : DMA_TO_DEVICE); + } else { + dma_unmap_page(vring_dma_dev(vq), + virtio64_to_cpu(vq->vq.vdev, desc->addr), + virtio32_to_cpu(vq->vq.vdev, desc->len), + (flags & VRING_DESC_F_WRITE) ? + DMA_FROM_DEVICE : DMA_TO_DEVICE); + } +} + +static int vring_mapping_error(const struct vring_virtqueue *vq, + dma_addr_t addr) +{ + return dma_mapping_error(vring_dma_dev(vq), addr); +} + static struct vring_desc *alloc_indirect(struct virtqueue *_vq, unsigned int total_sg, gfp_t gfp) { @@ -131,7 +198,7 @@ static inline int virtqueue_add(struct virtqueue *_vq, struct
Re: [PATCH v2 2/3] virtio_ring: Support DMA APIs
Am 28.10.2015 um 14:30 schrieb Andy Lutomirski: > +static void vring_unmap_one(const struct vring_virtqueue *vq, > + struct vring_desc *desc) > +{ > + u16 flags = virtio16_to_cpu(vq->vq.vdev, desc->flags); > + > + if (flags & VRING_DESC_F_INDIRECT) { > + dma_unmap_single(vring_dma_dev(vq), > + virtio64_to_cpu(vq->vq.vdev, desc->addr), > + virtio32_to_cpu(vq->vq.vdev, desc->len), > + (flags & VRING_DESC_F_WRITE) ? > + DMA_FROM_DEVICE : DMA_TO_DEVICE); > + } else { > + dma_unmap_page(vring_dma_dev(vq), > +virtio64_to_cpu(vq->vq.vdev, desc->addr), > +virtio32_to_cpu(vq->vq.vdev, desc->len), > +(flags & VRING_DESC_F_WRITE) ? > +DMA_FROM_DEVICE : DMA_TO_DEVICE); > + } > +} > + I still have a failure in this: [1.913040] Unable to handle kernel pointer dereference in virtual kernel address space [1.913044] failing address: 0c80 TEID: 0c800803 [1.913045] Fault in home space mode while using kernel ASCE. [1.913048] AS:00d56007 R3:0c7f0007 S:0020 [1.913099] Oops: 0010 ilc:2 [#1] SMP [1.913142] Modules linked in: [1.913144] CPU: 4 PID: 50 Comm: kworker/u18:1 Not tainted 4.3.0-rc3+ #252 [1.913150] Workqueue: events_unbound call_usermodehelper_exec_work [1.913152] task: 0bb8b310 ti: 0bba8000 task.ti: 0bba8000 [1.913154] Krnl PSW : 0404e0018000 0059b266 (vring_unmap_one+0x46/0x8d0) [1.913158]R:0 T:1 IO:0 EX:0 Key:0 M:1 W:0 P:0 AS:3 CC:2 PM:0 EA:3 Krnl GPRS: 0c80 0c036800 0c80 [1.913161]005a21a8 [1.913162]0704c0018000 04000bdbfce8 0c082000 0bdbf6e8 [1.913164]0400 0bdbf988 0bdbf6e8 [1.913170] Krnl Code: 0059b254: e310b0a80004lg %r1,168(%r11) 0059b25a: e3201024 lg %r2,32(%r1) #0059b260: e310b0a4 lg %r1,160(%r11) >0059b266: 4810100c lh %r1,12(%r1) 0059b26a: e320b2a80024 stg %r2,680(%r11) 0059b270: 4010b2a6 sth %r1,678(%r11) 0059b274: e310b2a80004 lg %r1,680(%r11) 0059b27a: e310b2980024 stg %r1,664(%r11) [1.913183] Call Trace: [1.913185] ([<0059b74c>] vring_unmap_one+0x52c/0x8d0) [1.913187] [<005a21a8>] detach_buf+0x720/0x788 [1.913188] [<005a2830>] virtqueue_get_buf+0x620/0x908 [1.913191] [<005e5336>] virtblk_done+0xa6/0x120 [1.913192] [<005a3e46>] vring_interrupt+0x2a6/0x2c0 [1.913224] [<006c9bdc>] virtio_airq_handler+0x7c/0x120 [1.913226] [<0065f88c>] do_airq_interrupt+0xa4/0xc8 [1.913229] [<001b79a0>] handle_irq_event_percpu+0x60/0x1f0 [1.913230] [<001bbbea>] handle_percpu_irq+0x72/0xa0 [1.913232] [<001b6fa4>] generic_handle_irq+0x4c/0x78 [1.913234] [<0010cc7c>] do_IRQ+0x64/0x88 [1.913236] [<00815d42>] io_int_handler+0x10a/0x218 [1.913238] [<00104268>] copy_thread+0x78/0x1a0 [1.913240] ([<001548f8>] copy_process.isra.11+0x750/0x1a80) [1.913242] [<00156122>] _do_fork+0x9a/0x338 [1.913243] [<0015644e>] kernel_thread+0x4e/0x60 [1.913245] [<0016da7a>] call_usermodehelper_exec_work+0x7a/0xf0 [1.913247] [<00171c06>] process_one_work+0x1b6/0x490 [1.913248] [<00171f38>] worker_thread+0x58/0x588 [1.913250] [<001788fa>] kthread+0x10a/0x110 [1.913252] [<00815a8e>] kernel_thread_starter+0x6/0xc [1.913254] [<00815a88>] kernel_thread_starter+0x0/0xc [1.913255] Last Breaking-Event-Address: [1.913256] [<005a21a2>] detach_buf+0x71a/0x788 [1.913258] [1.913263] Kernel panic - not syncing: Fatal exception in interrupt -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html