aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/virtio/vhost-backend.c86
-rw-r--r--hw/virtio/vhost.c10
-rw-r--r--include/hw/virtio/vhost-backend.h2
-rw-r--r--include/hw/virtio/vhost.h1
4 files changed, 83 insertions, 16 deletions
diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c
index 782b1d6..88c8ecc 100644
--- a/hw/virtio/vhost-backend.c
+++ b/hw/virtio/vhost-backend.c
@@ -156,6 +156,28 @@ static int vhost_kernel_set_features(struct vhost_dev *dev,
return vhost_kernel_call(dev, VHOST_SET_FEATURES, &features);
}
+static int vhost_kernel_set_backend_cap(struct vhost_dev *dev)
+{
+ uint64_t features;
+ uint64_t f = 0x1ULL << VHOST_BACKEND_F_IOTLB_MSG_V2;
+ int r;
+
+ if (vhost_kernel_call(dev, VHOST_GET_BACKEND_FEATURES, &features)) {
+ return 0;
+ }
+
+ features &= f;
+ r = vhost_kernel_call(dev, VHOST_SET_BACKEND_FEATURES,
+ &features);
+ if (r) {
+ return 0;
+ }
+
+ dev->backend_cap = features;
+
+ return 0;
+}
+
static int vhost_kernel_get_features(struct vhost_dev *dev,
uint64_t *features)
{
@@ -195,34 +217,65 @@ static int vhost_kernel_vsock_set_running(struct vhost_dev *dev, int start)
static void vhost_kernel_iotlb_read(void *opaque)
{
struct vhost_dev *dev = opaque;
- struct vhost_msg msg;
ssize_t len;
- while ((len = read((uintptr_t)dev->opaque, &msg, sizeof msg)) > 0) {
- if (len < sizeof msg) {
- error_report("Wrong vhost message len: %d", (int)len);
- break;
+ if (dev->backend_cap &
+ (0x1ULL << VHOST_BACKEND_F_IOTLB_MSG_V2)) {
+ struct vhost_msg_v2 msg;
+
+ while ((len = read((uintptr_t)dev->opaque, &msg, sizeof msg)) > 0) {
+ if (len < sizeof msg) {
+ error_report("Wrong vhost message len: %d", (int)len);
+ break;
+ }
+ if (msg.type != VHOST_IOTLB_MSG_V2) {
+ error_report("Unknown vhost iotlb message type");
+ break;
+ }
+
+ vhost_backend_handle_iotlb_msg(dev, &msg.iotlb);
}
- if (msg.type != VHOST_IOTLB_MSG) {
- error_report("Unknown vhost iotlb message type");
- break;
+ } else {
+ struct vhost_msg msg;
+
+ while ((len = read((uintptr_t)dev->opaque, &msg, sizeof msg)) > 0) {
+ if (len < sizeof msg) {
+ error_report("Wrong vhost message len: %d", (int)len);
+ break;
+ }
+ if (msg.type != VHOST_IOTLB_MSG) {
+ error_report("Unknown vhost iotlb message type");
+ break;
+ }
+
+ vhost_backend_handle_iotlb_msg(dev, &msg.iotlb);
}
-
- vhost_backend_handle_iotlb_msg(dev, &msg.iotlb);
}
}
static int vhost_kernel_send_device_iotlb_msg(struct vhost_dev *dev,
struct vhost_iotlb_msg *imsg)
{
- struct vhost_msg msg;
+ if (dev->backend_cap & (1ULL << VHOST_BACKEND_F_IOTLB_MSG_V2)) {
+ struct vhost_msg_v2 msg;
- msg.type = VHOST_IOTLB_MSG;
- msg.iotlb = *imsg;
+ msg.type = VHOST_IOTLB_MSG_V2;
+ msg.iotlb = *imsg;
- if (write((uintptr_t)dev->opaque, &msg, sizeof msg) != sizeof msg) {
- error_report("Fail to update device iotlb");
- return -EFAULT;
+ if (write((uintptr_t)dev->opaque, &msg, sizeof msg) != sizeof msg) {
+ error_report("Fail to update device iotlb");
+ return -EFAULT;
+ }
+ } else {
+ struct vhost_msg msg;
+
+ msg.type = VHOST_IOTLB_MSG;
+ msg.iotlb = *imsg;
+
+ if (write((uintptr_t)dev->opaque, &msg, sizeof msg) != sizeof msg) {
+ error_report("Fail to update device iotlb");
+ return -EFAULT;
+ }
}
return 0;
@@ -260,6 +313,7 @@ static const VhostOps kernel_ops = {
vhost_kernel_set_vring_busyloop_timeout,
.vhost_set_features = vhost_kernel_set_features,
.vhost_get_features = vhost_kernel_get_features,
+ .vhost_set_backend_cap = vhost_kernel_set_backend_cap,
.vhost_set_owner = vhost_kernel_set_owner,
.vhost_reset_device = vhost_kernel_reset_device,
.vhost_get_vq_index = vhost_kernel_get_vq_index,
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 0119516..8087f20 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -818,7 +818,17 @@ static int vhost_dev_set_features(struct vhost_dev *dev,
r = dev->vhost_ops->vhost_set_features(dev, features);
if (r < 0) {
VHOST_OPS_DEBUG("vhost_set_features failed");
+ goto out;
}
+ if (dev->vhost_ops->vhost_set_backend_cap) {
+ r = dev->vhost_ops->vhost_set_backend_cap(dev);
+ if (r < 0) {
+ VHOST_OPS_DEBUG("vhost_set_backend_cap failed");
+ goto out;
+ }
+ }
+
+out:
return r < 0 ? -errno : 0;
}
diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h
index 8825bd2..8a6f8e2 100644
--- a/include/hw/virtio/vhost-backend.h
+++ b/include/hw/virtio/vhost-backend.h
@@ -74,6 +74,7 @@ typedef int (*vhost_set_features_op)(struct vhost_dev *dev,
uint64_t features);
typedef int (*vhost_get_features_op)(struct vhost_dev *dev,
uint64_t *features);
+typedef int (*vhost_set_backend_cap_op)(struct vhost_dev *dev);
typedef int (*vhost_set_owner_op)(struct vhost_dev *dev);
typedef int (*vhost_reset_device_op)(struct vhost_dev *dev);
typedef int (*vhost_get_vq_index_op)(struct vhost_dev *dev, int idx);
@@ -146,6 +147,7 @@ typedef struct VhostOps {
vhost_set_vring_busyloop_timeout_op vhost_set_vring_busyloop_timeout;
vhost_set_features_op vhost_set_features;
vhost_get_features_op vhost_get_features;
+ vhost_set_backend_cap_op vhost_set_backend_cap;
vhost_set_owner_op vhost_set_owner;
vhost_reset_device_op vhost_reset_device;
vhost_get_vq_index_op vhost_get_vq_index;
diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
index 767a95e..9458506 100644
--- a/include/hw/virtio/vhost.h
+++ b/include/hw/virtio/vhost.h
@@ -79,6 +79,7 @@ struct vhost_dev {
uint64_t backend_features;
uint64_t protocol_features;
uint64_t max_queues;
+ uint64_t backend_cap;
bool started;
bool log_enabled;
uint64_t log_size;