aboutsummaryrefslogtreecommitdiff
path: root/hw/virtio
diff options
context:
space:
mode:
authorJason Wang <jasowang@redhat.com>2020-09-07 18:49:02 +0800
committerMichael S. Tsirkin <mst@redhat.com>2020-09-29 02:14:29 -0400
commitb37556edec8372bef83959901fc142a272a7e1fa (patch)
treefe0fc6c5fccfeff5a2ede0bcc43f35cf2412f9ea /hw/virtio
parente6546342a830e520d14ef03aa95677611de0d90c (diff)
vhost: switch to use IOTLB v2 format
This patch tries to switch to use new kernel IOTLB format V2. Previous version may have inconsistent ABI between 32bit and 64bit machines because of the hole after type field. Refer kernel commit ("429711aec282 vhost: switch to use new message format") for more information. To enable this feature, qemu need to use a new ioctl VHOST_SET_BACKEND_FEATURE with VHOST_BACKEND_F_IOTLB_MSG_V2 bit. A new vhost setting backend features ops was introduced. And when we try to set features for vhost dev, we will examine the support of new IOTLB format and enable it. This process is total transparent to guest, which means we can have different IOTLB message type in src and dst during migration. The conversion of IOTLB message is straightforward, just check the type and behave accordingly. Signed-off-by: Jason Wang <jasowang@redhat.com> Message-Id: <20200907104903.31551-3-jasowang@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'hw/virtio')
-rw-r--r--hw/virtio/vhost-backend.c86
-rw-r--r--hw/virtio/vhost.c10
2 files changed, 80 insertions, 16 deletions
diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c
index 782b1d67d9..88c8ecc9e0 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 0119516254..8087f200e9 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;
}