aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean-Philippe Brucker <jean-philippe@linaro.org>2023-06-06 14:04:13 +0100
committerWill Deacon <will@kernel.org>2023-06-08 22:39:03 +0100
commit029cd2bb789837641aad4b43b6370ff0fecfca28 (patch)
tree84ff2a12fd68f5f10960b777386fff0015049d2d
parent676c0c8ad95bff2f1aa77f2899aa9ee13f66c7a1 (diff)
downloadkvmtool-029cd2bb789837641aad4b43b6370ff0fecfca28.tar.gz
virtio/vhost: Factor notify_vq_gsi()
All vhost devices should perform the same operations when initializing the IRQFD. Move it to virtio/vhost.c This fixes vsock, which didn't go through the irq__add_irqfd() helper and couldn't be used on systems that require GSI translation (GICv2m). Also correct notify_vq_gsi() in net.c, to check which virtqueue is being configured. Since vhost only manages the data queues, we shouldn't try to setup GSI routing for the control queue. This hasn't been a problem so far because the Linux guest doesn't use IRQs for the control queue. Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> Link: https://lore.kernel.org/r/20230606130426.978945-5-jean-philippe@linaro.org Signed-off-by: Will Deacon <will@kernel.org>
-rw-r--r--include/kvm/virtio.h8
-rw-r--r--virtio/net.c32
-rw-r--r--virtio/scsi.c15
-rw-r--r--virtio/vhost.c35
-rw-r--r--virtio/vsock.c26
5 files changed, 53 insertions, 63 deletions
diff --git a/include/kvm/virtio.h b/include/kvm/virtio.h
index 6912875e..a2f8355a 100644
--- a/include/kvm/virtio.h
+++ b/include/kvm/virtio.h
@@ -77,6 +77,10 @@ struct virt_queue {
u16 endian;
bool use_event_idx;
bool enabled;
+
+ /* vhost IRQ handling */
+ int gsi;
+ int irqfd;
};
/*
@@ -263,6 +267,10 @@ void virtio_vhost_set_vring(struct kvm *kvm, int vhost_fd, u32 index,
struct virt_queue *queue);
void virtio_vhost_set_vring_kick(struct kvm *kvm, int vhost_fd,
u32 index, int event_fd);
+void virtio_vhost_set_vring_call(struct kvm *kvm, int vhost_fd, u32 index,
+ u32 gsi, struct virt_queue *queue);
+void virtio_vhost_reset_vring(struct kvm *kvm, int vhost_fd, u32 index,
+ struct virt_queue *queue);
int virtio_transport_parser(const struct option *opt, const char *arg, int unset);
diff --git a/virtio/net.c b/virtio/net.c
index c0871163..3e1aedf7 100644
--- a/virtio/net.c
+++ b/virtio/net.c
@@ -4,12 +4,12 @@
#include "kvm/mutex.h"
#include "kvm/util.h"
#include "kvm/kvm.h"
-#include "kvm/irq.h"
#include "kvm/uip.h"
#include "kvm/guest_compat.h"
#include "kvm/iovec.h"
#include "kvm/strbuf.h"
+#include <linux/list.h>
#include <linux/vhost.h>
#include <linux/virtio_net.h>
#include <linux/if_tun.h>
@@ -25,7 +25,6 @@
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/wait.h>
-#include <sys/eventfd.h>
#define VIRTIO_NET_QUEUE_SIZE 256
#define VIRTIO_NET_NUM_QUEUES 8
@@ -44,8 +43,6 @@ struct net_dev_queue {
pthread_t thread;
struct mutex lock;
pthread_cond_t cond;
- int gsi;
- int irqfd;
};
struct net_dev {
@@ -647,11 +644,7 @@ static void exit_vq(struct kvm *kvm, void *dev, u32 vq)
struct net_dev *ndev = dev;
struct net_dev_queue *queue = &ndev->queues[vq];
- if (!is_ctrl_vq(ndev, vq) && queue->gsi) {
- irq__del_irqfd(kvm, queue->gsi, queue->irqfd);
- close(queue->irqfd);
- queue->gsi = queue->irqfd = 0;
- }
+ virtio_vhost_reset_vring(kvm, ndev->vhost_fd, vq, &queue->vq);
/*
* TODO: vhost reset owner. It's the only way to cleanly stop vhost, but
@@ -675,27 +668,12 @@ static void notify_vq_gsi(struct kvm *kvm, void *dev, u32 vq, u32 gsi)
{
struct net_dev *ndev = dev;
struct net_dev_queue *queue = &ndev->queues[vq];
- struct vhost_vring_file file;
- int r;
- if (ndev->vhost_fd == 0)
+ if (ndev->vhost_fd == 0 || is_ctrl_vq(ndev, vq))
return;
- file = (struct vhost_vring_file) {
- .index = vq,
- .fd = eventfd(0, 0),
- };
-
- r = irq__add_irqfd(kvm, gsi, file.fd, -1);
- if (r < 0)
- die_perror("KVM_IRQFD failed");
-
- queue->irqfd = file.fd;
- queue->gsi = gsi;
-
- r = ioctl(ndev->vhost_fd, VHOST_SET_VRING_CALL, &file);
- if (r < 0)
- die_perror("VHOST_SET_VRING_CALL failed");
+ virtio_vhost_set_vring_call(kvm, ndev->vhost_fd, vq, gsi,
+ &queue->vq);
}
static void notify_vq_eventfd(struct kvm *kvm, void *dev, u32 vq, u32 efd)
diff --git a/virtio/scsi.c b/virtio/scsi.c
index ebddec36..708fb23a 100644
--- a/virtio/scsi.c
+++ b/virtio/scsi.c
@@ -90,25 +90,14 @@ static int init_vq(struct kvm *kvm, void *dev, u32 vq)
static void notify_vq_gsi(struct kvm *kvm, void *dev, u32 vq, u32 gsi)
{
- struct vhost_vring_file file;
struct scsi_dev *sdev = dev;
int r;
if (sdev->vhost_fd == 0)
return;
- file = (struct vhost_vring_file) {
- .index = vq,
- .fd = eventfd(0, 0),
- };
-
- r = irq__add_irqfd(kvm, gsi, file.fd, -1);
- if (r < 0)
- die_perror("KVM_IRQFD failed");
-
- r = ioctl(sdev->vhost_fd, VHOST_SET_VRING_CALL, &file);
- if (r < 0)
- die_perror("VHOST_SET_VRING_CALL failed");
+ virtio_vhost_set_vring_call(kvm, sdev->vhost_fd, vq, gsi,
+ &sdev->vqs[vq]);
if (vq > 0)
return;
diff --git a/virtio/vhost.c b/virtio/vhost.c
index 3acfd30a..cd83645c 100644
--- a/virtio/vhost.c
+++ b/virtio/vhost.c
@@ -1,9 +1,12 @@
+#include "kvm/irq.h"
#include "kvm/virtio.h"
#include <linux/kvm.h>
#include <linux/vhost.h>
#include <linux/list.h>
+#include <sys/eventfd.h>
+
void virtio_vhost_init(struct kvm *kvm, int vhost_fd)
{
struct kvm_mem_bank *bank;
@@ -79,3 +82,35 @@ void virtio_vhost_set_vring_kick(struct kvm *kvm, int vhost_fd,
if (r < 0)
die_perror("VHOST_SET_VRING_KICK failed");
}
+
+void virtio_vhost_set_vring_call(struct kvm *kvm, int vhost_fd, u32 index,
+ u32 gsi, struct virt_queue *queue)
+{
+ int r;
+ struct vhost_vring_file file = {
+ .index = index,
+ .fd = eventfd(0, 0),
+ };
+
+ r = irq__add_irqfd(kvm, gsi, file.fd, -1);
+ if (r < 0)
+ die_perror("KVM_IRQFD failed");
+
+ r = ioctl(vhost_fd, VHOST_SET_VRING_CALL, &file);
+ if (r < 0)
+ die_perror("VHOST_SET_VRING_CALL failed");
+
+ queue->irqfd = file.fd;
+ queue->gsi = gsi;
+}
+
+void virtio_vhost_reset_vring(struct kvm *kvm, int vhost_fd, u32 index,
+ struct virt_queue *queue)
+
+{
+ if (queue->gsi) {
+ irq__del_irqfd(kvm, queue->gsi, queue->irqfd);
+ close(queue->irqfd);
+ queue->gsi = queue->irqfd = 0;
+ }
+}
diff --git a/virtio/vsock.c b/virtio/vsock.c
index 0ada9e09..559fbaba 100644
--- a/virtio/vsock.c
+++ b/virtio/vsock.c
@@ -131,33 +131,13 @@ static int set_size_vq(struct kvm *kvm, void *dev, u32 vq, int size)
static void notify_vq_gsi(struct kvm *kvm, void *dev, u32 vq, u32 gsi)
{
- struct vhost_vring_file file;
struct vsock_dev *vdev = dev;
- struct kvm_irqfd irq;
- int r;
-
- if (vdev->vhost_fd == -1)
- return;
- if (is_event_vq(vq))
+ if (vdev->vhost_fd == -1 || is_event_vq(vq))
return;
- irq = (struct kvm_irqfd) {
- .gsi = gsi,
- .fd = eventfd(0, 0),
- };
- file = (struct vhost_vring_file) {
- .index = vq,
- .fd = irq.fd,
- };
-
- r = ioctl(kvm->vm_fd, KVM_IRQFD, &irq);
- if (r < 0)
- die_perror("KVM_IRQFD failed");
-
- r = ioctl(vdev->vhost_fd, VHOST_SET_VRING_CALL, &file);
- if (r < 0)
- die_perror("VHOST_SET_VRING_CALL failed");
+ virtio_vhost_set_vring_call(kvm, vdev->vhost_fd, vq, gsi,
+ &vdev->vqs[vq]);
}
static unsigned int get_vq_count(struct kvm *kvm, void *dev)