aboutsummaryrefslogtreecommitdiff
path: root/hw/virtio/vhost-backend.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/virtio/vhost-backend.c')
-rw-r--r--hw/virtio/vhost-backend.c86
1 files changed, 70 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,