return virtio_queue_get_addr(vdev, vdev->queue_sel)
>> proxy->guest_page_shift;
case VIRTIO_MMIO_INTERRUPTSTATUS:
- return vdev->isr;
+ return atomic_read(&vdev->isr);
case VIRTIO_MMIO_STATUS:
return vdev->status;
case VIRTIO_MMIO_HOSTFEATURESSEL:
}
break;
case VIRTIO_MMIO_INTERRUPTACK:
- vdev->isr &= ~value;
+ atomic_and(&vdev->isr, ~value);
virtio_update_irq(vdev);
break;
case VIRTIO_MMIO_STATUS:
if (!vdev) {
return;
}
- level = (vdev->isr != 0);
+ level = (atomic_read(&vdev->isr) != 0);
DPRINTF("virtio_mmio setting IRQ %d\n", level);
qemu_set_irq(proxy->irq, level);
}
msix_notify(&proxy->pci_dev, vector);
else {
VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
- pci_set_irq(&proxy->pci_dev, vdev->isr & 1);
+ pci_set_irq(&proxy->pci_dev, atomic_read(&vdev->isr) & 1);
}
}
break;
case VIRTIO_PCI_ISR:
/* reading from the ISR also clears it. */
- ret = vdev->isr;
- vdev->isr = 0;
+ ret = atomic_xchg(&vdev->isr, 0);
pci_irq_deassert(&proxy->pci_dev);
break;
case VIRTIO_MSI_CONFIG_VECTOR:
{
VirtIOPCIProxy *proxy = opaque;
VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
- uint64_t val = vdev->isr;
-
- vdev->isr = 0;
+ uint64_t val = atomic_xchg(&vdev->isr, 0);
pci_irq_deassert(&proxy->pci_dev);
return val;
vdev->guest_features = 0;
vdev->queue_sel = 0;
vdev->status = 0;
- vdev->isr = 0;
+ atomic_set(&vdev->isr, 0);
vdev->config_vector = VIRTIO_NO_VECTOR;
virtio_notify_vector(vdev, vdev->config_vector);
vdev->vq[n].vring.num_default = 0;
}
+static void virtio_set_isr(VirtIODevice *vdev, int value)
+{
+ uint8_t old = atomic_read(&vdev->isr);
+
+ /* Do not write ISR if it does not change, so that its cacheline remains
+ * shared in the common case where the guest does not read it.
+ */
+ if ((old & value) != value) {
+ atomic_or(&vdev->isr, value);
+ }
+}
+
void virtio_irq(VirtQueue *vq)
{
trace_virtio_irq(vq);
- vq->vdev->isr |= 0x01;
+ virtio_set_isr(vq->vdev, 0x1);
virtio_notify_vector(vq->vdev, vq->vector);
}
}
trace_virtio_notify(vdev, vq);
- vdev->isr |= 0x01;
+ virtio_set_isr(vq->vdev, 0x1);
virtio_notify_vector(vdev, vq->vector);
}
if (!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK))
return;
- vdev->isr |= 0x03;
+ virtio_set_isr(vdev, 0x3);
vdev->generation++;
virtio_notify_vector(vdev, vdev->config_vector);
}
vdev->device_id = device_id;
vdev->status = 0;
- vdev->isr = 0;
+ atomic_set(&vdev->isr, 0);
vdev->queue_sel = 0;
vdev->config_vector = VIRTIO_NO_VECTOR;
vdev->vq = g_malloc0(sizeof(VirtQueue) * VIRTIO_QUEUE_MAX);