virtio: access ISR atomically
This will be needed once dataplane will be able to set it outside the big QEMU lock. Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Tested-by: Farhan Ali <alifm@linux.vnet.ibm.com> Tested-by: Alex Williamson <alex.williamson@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
		
							parent
							
								
									310837de6c
								
							
						
					
					
						commit
						0687c37c5e
					
				@ -191,7 +191,7 @@ static uint64_t virtio_mmio_read(void *opaque, hwaddr offset, unsigned size)
 | 
				
			|||||||
        return virtio_queue_get_addr(vdev, vdev->queue_sel)
 | 
					        return virtio_queue_get_addr(vdev, vdev->queue_sel)
 | 
				
			||||||
            >> proxy->guest_page_shift;
 | 
					            >> proxy->guest_page_shift;
 | 
				
			||||||
    case VIRTIO_MMIO_INTERRUPTSTATUS:
 | 
					    case VIRTIO_MMIO_INTERRUPTSTATUS:
 | 
				
			||||||
        return vdev->isr;
 | 
					        return atomic_read(&vdev->isr);
 | 
				
			||||||
    case VIRTIO_MMIO_STATUS:
 | 
					    case VIRTIO_MMIO_STATUS:
 | 
				
			||||||
        return vdev->status;
 | 
					        return vdev->status;
 | 
				
			||||||
    case VIRTIO_MMIO_HOSTFEATURESSEL:
 | 
					    case VIRTIO_MMIO_HOSTFEATURESSEL:
 | 
				
			||||||
@ -299,7 +299,7 @@ static void virtio_mmio_write(void *opaque, hwaddr offset, uint64_t value,
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case VIRTIO_MMIO_INTERRUPTACK:
 | 
					    case VIRTIO_MMIO_INTERRUPTACK:
 | 
				
			||||||
        vdev->isr &= ~value;
 | 
					        atomic_and(&vdev->isr, ~value);
 | 
				
			||||||
        virtio_update_irq(vdev);
 | 
					        virtio_update_irq(vdev);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case VIRTIO_MMIO_STATUS:
 | 
					    case VIRTIO_MMIO_STATUS:
 | 
				
			||||||
@ -347,7 +347,7 @@ static void virtio_mmio_update_irq(DeviceState *opaque, uint16_t vector)
 | 
				
			|||||||
    if (!vdev) {
 | 
					    if (!vdev) {
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    level = (vdev->isr != 0);
 | 
					    level = (atomic_read(&vdev->isr) != 0);
 | 
				
			||||||
    DPRINTF("virtio_mmio setting IRQ %d\n", level);
 | 
					    DPRINTF("virtio_mmio setting IRQ %d\n", level);
 | 
				
			||||||
    qemu_set_irq(proxy->irq, level);
 | 
					    qemu_set_irq(proxy->irq, level);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -73,7 +73,7 @@ static void virtio_pci_notify(DeviceState *d, uint16_t vector)
 | 
				
			|||||||
        msix_notify(&proxy->pci_dev, vector);
 | 
					        msix_notify(&proxy->pci_dev, vector);
 | 
				
			||||||
    else {
 | 
					    else {
 | 
				
			||||||
        VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
 | 
					        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);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -449,8 +449,7 @@ static uint32_t virtio_ioport_read(VirtIOPCIProxy *proxy, uint32_t addr)
 | 
				
			|||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case VIRTIO_PCI_ISR:
 | 
					    case VIRTIO_PCI_ISR:
 | 
				
			||||||
        /* reading from the ISR also clears it. */
 | 
					        /* reading from the ISR also clears it. */
 | 
				
			||||||
        ret = vdev->isr;
 | 
					        ret = atomic_xchg(&vdev->isr, 0);
 | 
				
			||||||
        vdev->isr = 0;
 | 
					 | 
				
			||||||
        pci_irq_deassert(&proxy->pci_dev);
 | 
					        pci_irq_deassert(&proxy->pci_dev);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case VIRTIO_MSI_CONFIG_VECTOR:
 | 
					    case VIRTIO_MSI_CONFIG_VECTOR:
 | 
				
			||||||
@ -1379,9 +1378,7 @@ static uint64_t virtio_pci_isr_read(void *opaque, hwaddr addr,
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    VirtIOPCIProxy *proxy = opaque;
 | 
					    VirtIOPCIProxy *proxy = opaque;
 | 
				
			||||||
    VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
 | 
					    VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
 | 
				
			||||||
    uint64_t val = vdev->isr;
 | 
					    uint64_t val = atomic_xchg(&vdev->isr, 0);
 | 
				
			||||||
 | 
					 | 
				
			||||||
    vdev->isr = 0;
 | 
					 | 
				
			||||||
    pci_irq_deassert(&proxy->pci_dev);
 | 
					    pci_irq_deassert(&proxy->pci_dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return val;
 | 
					    return val;
 | 
				
			||||||
 | 
				
			|||||||
@ -945,7 +945,7 @@ void virtio_reset(void *opaque)
 | 
				
			|||||||
    vdev->guest_features = 0;
 | 
					    vdev->guest_features = 0;
 | 
				
			||||||
    vdev->queue_sel = 0;
 | 
					    vdev->queue_sel = 0;
 | 
				
			||||||
    vdev->status = 0;
 | 
					    vdev->status = 0;
 | 
				
			||||||
    vdev->isr = 0;
 | 
					    atomic_set(&vdev->isr, 0);
 | 
				
			||||||
    vdev->config_vector = VIRTIO_NO_VECTOR;
 | 
					    vdev->config_vector = VIRTIO_NO_VECTOR;
 | 
				
			||||||
    virtio_notify_vector(vdev, vdev->config_vector);
 | 
					    virtio_notify_vector(vdev, vdev->config_vector);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1318,10 +1318,22 @@ void virtio_del_queue(VirtIODevice *vdev, int n)
 | 
				
			|||||||
    vdev->vq[n].vring.num_default = 0;
 | 
					    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)
 | 
					void virtio_irq(VirtQueue *vq)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    trace_virtio_irq(vq);
 | 
					    trace_virtio_irq(vq);
 | 
				
			||||||
    vq->vdev->isr |= 0x01;
 | 
					    virtio_set_isr(vq->vdev, 0x1);
 | 
				
			||||||
    virtio_notify_vector(vq->vdev, vq->vector);
 | 
					    virtio_notify_vector(vq->vdev, vq->vector);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1355,7 +1367,7 @@ void virtio_notify(VirtIODevice *vdev, VirtQueue *vq)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    trace_virtio_notify(vdev, vq);
 | 
					    trace_virtio_notify(vdev, vq);
 | 
				
			||||||
    vdev->isr |= 0x01;
 | 
					    virtio_set_isr(vq->vdev, 0x1);
 | 
				
			||||||
    virtio_notify_vector(vdev, vq->vector);
 | 
					    virtio_notify_vector(vdev, vq->vector);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1364,7 +1376,7 @@ void virtio_notify_config(VirtIODevice *vdev)
 | 
				
			|||||||
    if (!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK))
 | 
					    if (!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK))
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    vdev->isr |= 0x03;
 | 
					    virtio_set_isr(vdev, 0x3);
 | 
				
			||||||
    vdev->generation++;
 | 
					    vdev->generation++;
 | 
				
			||||||
    virtio_notify_vector(vdev, vdev->config_vector);
 | 
					    virtio_notify_vector(vdev, vdev->config_vector);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -1895,7 +1907,7 @@ void virtio_init(VirtIODevice *vdev, const char *name,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    vdev->device_id = device_id;
 | 
					    vdev->device_id = device_id;
 | 
				
			||||||
    vdev->status = 0;
 | 
					    vdev->status = 0;
 | 
				
			||||||
    vdev->isr = 0;
 | 
					    atomic_set(&vdev->isr, 0);
 | 
				
			||||||
    vdev->queue_sel = 0;
 | 
					    vdev->queue_sel = 0;
 | 
				
			||||||
    vdev->config_vector = VIRTIO_NO_VECTOR;
 | 
					    vdev->config_vector = VIRTIO_NO_VECTOR;
 | 
				
			||||||
    vdev->vq = g_malloc0(sizeof(VirtQueue) * VIRTIO_QUEUE_MAX);
 | 
					    vdev->vq = g_malloc0(sizeof(VirtQueue) * VIRTIO_QUEUE_MAX);
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user