Skip to content

Commit

Permalink
virtio: support setting memory region based host notifier
Browse files Browse the repository at this point in the history
This patch introduces the support for setting memory region
based host notifiers for virtio device. This is helpful when
using a hardware accelerator for a virtio device, because
hardware heavily depends on the notification, this will allow
the guest driver in the VM to notify the hardware directly.

Signed-off-by: Tiwei Bie <tiwei.bie@intel.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
  • Loading branch information
Tiwei Bie authored and mstsirkin committed May 23, 2018
1 parent 1f3a451 commit 6f80e61
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 0 deletions.
22 changes: 22 additions & 0 deletions hw/virtio/virtio-pci.c
Expand Up @@ -1037,6 +1037,27 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign)
return r;
}

static int virtio_pci_set_host_notifier_mr(DeviceState *d, int n,
MemoryRegion *mr, bool assign)
{
VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
int offset;

if (n >= VIRTIO_QUEUE_MAX || !virtio_pci_modern(proxy) ||
virtio_pci_queue_mem_mult(proxy) != memory_region_size(mr)) {
return -1;
}

if (assign) {
offset = virtio_pci_queue_mem_mult(proxy) * n;
memory_region_add_subregion_overlap(&proxy->notify.mr, offset, mr, 1);
} else {
memory_region_del_subregion(&proxy->notify.mr, mr);
}

return 0;
}

static void virtio_pci_vmstate_change(DeviceState *d, bool running)
{
VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
Expand Down Expand Up @@ -2652,6 +2673,7 @@ static void virtio_pci_bus_class_init(ObjectClass *klass, void *data)
k->has_extra_state = virtio_pci_has_extra_state;
k->query_guest_notifiers = virtio_pci_query_guest_notifiers;
k->set_guest_notifiers = virtio_pci_set_guest_notifiers;
k->set_host_notifier_mr = virtio_pci_set_host_notifier_mr;
k->vmstate_change = virtio_pci_vmstate_change;
k->pre_plugged = virtio_pci_pre_plugged;
k->device_plugged = virtio_pci_device_plugged;
Expand Down
13 changes: 13 additions & 0 deletions hw/virtio/virtio.c
Expand Up @@ -2454,6 +2454,19 @@ EventNotifier *virtio_queue_get_host_notifier(VirtQueue *vq)
return &vq->host_notifier;
}

int virtio_queue_set_host_notifier_mr(VirtIODevice *vdev, int n,
MemoryRegion *mr, bool assign)
{
BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);

if (k->set_host_notifier_mr) {
return k->set_host_notifier_mr(qbus->parent, n, mr, assign);
}

return -1;
}

void virtio_device_set_child_bus_name(VirtIODevice *vdev, char *bus_name)
{
g_free(vdev->bus_name);
Expand Down
2 changes: 2 additions & 0 deletions include/hw/virtio/virtio-bus.h
Expand Up @@ -52,6 +52,8 @@ typedef struct VirtioBusClass {
bool (*has_extra_state)(DeviceState *d);
bool (*query_guest_notifiers)(DeviceState *d);
int (*set_guest_notifiers)(DeviceState *d, int nvqs, bool assign);
int (*set_host_notifier_mr)(DeviceState *d, int n,
MemoryRegion *mr, bool assign);
void (*vmstate_change)(DeviceState *d, bool running);
/*
* Expose the features the transport layer supports before
Expand Down
2 changes: 2 additions & 0 deletions include/hw/virtio/virtio.h
Expand Up @@ -239,6 +239,8 @@ void virtio_queue_set_align(VirtIODevice *vdev, int n, int align);
void virtio_queue_notify(VirtIODevice *vdev, int n);
uint16_t virtio_queue_vector(VirtIODevice *vdev, int n);
void virtio_queue_set_vector(VirtIODevice *vdev, int n, uint16_t vector);
int virtio_queue_set_host_notifier_mr(VirtIODevice *vdev, int n,
MemoryRegion *mr, bool assign);
int virtio_set_status(VirtIODevice *vdev, uint8_t val);
void virtio_reset(void *opaque);
void virtio_update_irq(VirtIODevice *vdev);
Expand Down

0 comments on commit 6f80e61

Please sign in to comment.