Thread (2 messages) 2 messages, 2 authors, 2018-11-27

Re: [PATCH v5 5/7] iommu: Add virtio-iommu driver

From: Jean-Philippe Brucker <hidden>
Date: 2018-11-27 18:10:46

On 27/11/2018 18:04, Michael S. Tsirkin wrote:
On Tue, Nov 27, 2018 at 05:50:50PM +0000, Jean-Philippe Brucker wrote:
quoted
On 23/11/2018 22:02, Michael S. Tsirkin wrote:
quoted
quoted
+/*
+ * __viommu_sync_req - Complete all in-flight requests
+ *
+ * Wait for all added requests to complete. When this function returns, all
+ * requests that were in-flight at the time of the call have completed.
+ */
+static int __viommu_sync_req(struct viommu_dev *viommu)
+{
+	int ret = 0;
+	unsigned int len;
+	size_t write_len;
+	struct viommu_request *req;
+	struct virtqueue *vq = viommu->vqs[VIOMMU_REQUEST_VQ];
+
+	assert_spin_locked(&viommu->request_lock);
+
+	virtqueue_kick(vq);
+
+	while (!list_empty(&viommu->requests)) {
+		len = 0;
+		req = virtqueue_get_buf(vq, &len);
+		if (!req)
+			continue;
+
+		if (!len)
+			viommu_set_req_status(req->buf, req->len,
+					      VIRTIO_IOMMU_S_IOERR);
+
+		write_len = req->len - req->write_offset;
+		if (req->writeback && len == write_len)
+			memcpy(req->writeback, req->buf + req->write_offset,
+			       write_len);
+
+		list_del(&req->list);
+		kfree(req);
+	}
I didn't notice this in the past but it seems this will spin
with interrupts disabled until host handles the request.
Please do not do this - host execution can be another
task that needs the same host CPU. This will then disable
interrupts for a very very long time.
In the guest yes, but that doesn't prevent the host from running another
task right?
Doesn't prevent it but it will delay it significantly
until scheduler decides to kick the VCPU task out.
quoted
My tests run fine when QEMU is bound to a single CPU, even
though vcpu and viommu run in different threads
quoted
What to do then? Queue in software and wake up task.
Unfortunately I can't do anything here, because IOMMU drivers can't
sleep in the iommu_map() or iommu_unmap() path.

The problem is the same
for all IOMMU drivers. That's because the DMA API allows drivers to call
some functions with interrupts disabled. For example
Documentation/DMA-API-HOWTO.txt allows dma_alloc_coherent() and
dma_unmap_single() to be called in interrupt context.
In fact I don't really understand how it's supposed to
work at all: you only sync when ring is full.
So host may not have seen your map request if ring
is not full.
Why is it safe to use the address with a device then?
viommu_map() calls viommu_send_req_sync(), which does the sync
immediately after adding the MAP request.

Thanks,
Jean
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help