qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Michael S. Tsirkin" <mst@redhat.com>
To: qemu-devel@nongnu.org
Cc: "Peter Maydell" <peter.maydell@linaro.org>,
	"Changpeng Liu" <changpeng.liu@intel.com>,
	"Marc-André Lureau" <marcandre.lureau@redhat.com>
Subject: [Qemu-devel] [PULL 02/33] vhost-user: add new vhost user messages to support virtio config space
Date: Tue, 16 Jan 2018 06:46:25 +0200	[thread overview]
Message-ID: <1516077852-7974-3-git-send-email-mst@redhat.com> (raw)
In-Reply-To: <1516077852-7974-1-git-send-email-mst@redhat.com>

From: Changpeng Liu <changpeng.liu@intel.com>

Add VHOST_USER_GET_CONFIG/VHOST_USER_SET_CONFIG messages which can be
used for live migration of vhost user devices, also vhost user devices
can benefit from the messages to get/set virtio config space from/to the
I/O target. For the purpose to support virtio config space change,
VHOST_USER_SLAVE_CONFIG_CHANGE_MSG message is added as the event notifier
in case virtio config space change in the slave I/O target.

Signed-off-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 docs/interop/vhost-user.txt       |  55 ++++++++++++++++++
 include/hw/virtio/vhost-backend.h |  12 ++++
 include/hw/virtio/vhost.h         |  15 +++++
 hw/virtio/vhost-user.c            | 118 ++++++++++++++++++++++++++++++++++++++
 hw/virtio/vhost.c                 |  32 +++++++++++
 5 files changed, 232 insertions(+)

diff --git a/docs/interop/vhost-user.txt b/docs/interop/vhost-user.txt
index d49444e..0875ef4 100644
--- a/docs/interop/vhost-user.txt
+++ b/docs/interop/vhost-user.txt
@@ -119,6 +119,19 @@ Depending on the request type, payload can be:
     - 3: IOTLB invalidate
     - 4: IOTLB access fail
 
+ * Virtio device config space
+   -----------------------------------
+   | offset | size | flags | payload |
+   -----------------------------------
+
+   Offset: a 32-bit offset of virtio device's configuration space
+   Size: a 32-bit configuration space access size in bytes
+   Flags: a 32-bit value:
+    - 0: Vhost master messages used for writeable fields
+    - 1: Vhost master messages used for live migration
+   Payload: Size bytes array holding the contents of the virtio
+       device's configuration space
+
 In QEMU the vhost-user message is implemented with the following struct:
 
 typedef struct VhostUserMsg {
@@ -132,6 +145,7 @@ typedef struct VhostUserMsg {
         VhostUserMemory memory;
         VhostUserLog log;
         struct vhost_iotlb_msg iotlb;
+        VhostUserConfig config;
     };
 } QEMU_PACKED VhostUserMsg;
 
@@ -623,6 +637,32 @@ Master message types
       and expect this message once (per VQ) during device configuration
       (ie. before the master starts the VQ).
 
+ * VHOST_USER_GET_CONFIG
+
+      Id: 24
+      Equivalent ioctl: N/A
+      Master payload: virtio device config space
+      Slave payload: virtio device config space
+
+      Submitted by the vhost-user master to fetch the contents of the virtio
+      device configuration space, vhost-user slave's payload size MUST match
+      master's request, vhost-user slave uses zero length of payload to
+      indicate an error to vhost-user master. The vhost-user master may
+      cache the contents to avoid repeated VHOST_USER_GET_CONFIG calls.
+
+* VHOST_USER_SET_CONFIG
+
+      Id: 25
+      Equivalent ioctl: N/A
+      Master payload: virtio device config space
+      Slave payload: N/A
+
+      Submitted by the vhost-user master when the Guest changes the virtio
+      device configuration space and also can be used for live migration
+      on the destination host. The vhost-user slave must check the flags
+      field, and slaves MUST NOT accept SET_CONFIG for read-only
+      configuration space fields unless the live migration bit is set.
+
 Slave message types
 -------------------
 
@@ -641,6 +681,21 @@ Slave message types
       This request should be send only when VIRTIO_F_IOMMU_PLATFORM feature
       has been successfully negotiated.
 
+* VHOST_USER_SLAVE_CONFIG_CHANGE_MSG
+
+     Id: 2
+     Equivalent ioctl: N/A
+     Slave payload: N/A
+     Master payload: N/A
+
+     Vhost-user slave sends such messages to notify that the virtio device's
+     configuration space has changed, for those host devices which can support
+     such feature, host driver can send VHOST_USER_GET_CONFIG message to slave
+     to get the latest content. If VHOST_USER_PROTOCOL_F_REPLY_ACK is
+     negotiated, and slave set the VHOST_USER_NEED_REPLY flag, master must
+     respond with zero when operation is successfully completed, or non-zero
+     otherwise.
+
 VHOST_USER_PROTOCOL_F_REPLY_ACK:
 -------------------------------
 The original vhost-user specification only demands replies for certain
diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h
index a7a5f22..592254f 100644
--- a/include/hw/virtio/vhost-backend.h
+++ b/include/hw/virtio/vhost-backend.h
@@ -20,6 +20,11 @@ typedef enum VhostBackendType {
     VHOST_BACKEND_TYPE_MAX = 3,
 } VhostBackendType;
 
+typedef enum VhostSetConfigType {
+    VHOST_SET_CONFIG_TYPE_MASTER = 0,
+    VHOST_SET_CONFIG_TYPE_MIGRATION = 1,
+} VhostSetConfigType;
+
 struct vhost_dev;
 struct vhost_log;
 struct vhost_memory;
@@ -84,6 +89,11 @@ typedef void (*vhost_set_iotlb_callback_op)(struct vhost_dev *dev,
                                            int enabled);
 typedef int (*vhost_send_device_iotlb_msg_op)(struct vhost_dev *dev,
                                               struct vhost_iotlb_msg *imsg);
+typedef int (*vhost_set_config_op)(struct vhost_dev *dev, const uint8_t *data,
+                                   uint32_t offset, uint32_t size,
+                                   uint32_t flags);
+typedef int (*vhost_get_config_op)(struct vhost_dev *dev, uint8_t *config,
+                                   uint32_t config_len);
 
 typedef struct VhostOps {
     VhostBackendType backend_type;
@@ -118,6 +128,8 @@ typedef struct VhostOps {
     vhost_vsock_set_running_op vhost_vsock_set_running;
     vhost_set_iotlb_callback_op vhost_set_iotlb_callback;
     vhost_send_device_iotlb_msg_op vhost_send_device_iotlb_msg;
+    vhost_get_config_op vhost_get_config;
+    vhost_set_config_op vhost_set_config;
 } VhostOps;
 
 extern const VhostOps user_ops;
diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
index 467dc77..1dc2d73 100644
--- a/include/hw/virtio/vhost.h
+++ b/include/hw/virtio/vhost.h
@@ -46,6 +46,12 @@ struct vhost_iommu {
     QLIST_ENTRY(vhost_iommu) iommu_next;
 };
 
+typedef struct VhostDevConfigOps {
+    /* Vhost device config space changed callback
+     */
+    int (*vhost_dev_config_notifier)(struct vhost_dev *dev);
+} VhostDevConfigOps;
+
 struct vhost_memory;
 struct vhost_dev {
     VirtIODevice *vdev;
@@ -76,6 +82,7 @@ struct vhost_dev {
     QLIST_ENTRY(vhost_dev) entry;
     QLIST_HEAD(, vhost_iommu) iommu_list;
     IOMMUNotifier n;
+    const VhostDevConfigOps *config_ops;
 };
 
 int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
@@ -106,4 +113,12 @@ int vhost_net_set_backend(struct vhost_dev *hdev,
                           struct vhost_vring_file *file);
 
 int vhost_device_iotlb_miss(struct vhost_dev *dev, uint64_t iova, int write);
+int vhost_dev_get_config(struct vhost_dev *dev, uint8_t *config,
+                         uint32_t config_len);
+int vhost_dev_set_config(struct vhost_dev *dev, const uint8_t *data,
+                         uint32_t offset, uint32_t size, uint32_t flags);
+/* notifier callback in case vhost device config space changed
+ */
+void vhost_dev_set_config_notifier(struct vhost_dev *dev,
+                                   const VhostDevConfigOps *ops);
 #endif
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 093675e..8b94688 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -26,6 +26,11 @@
 #define VHOST_MEMORY_MAX_NREGIONS    8
 #define VHOST_USER_F_PROTOCOL_FEATURES 30
 
+/*
+ * Maximum size of virtio device config space
+ */
+#define VHOST_USER_MAX_CONFIG_SIZE 256
+
 enum VhostUserProtocolFeature {
     VHOST_USER_PROTOCOL_F_MQ = 0,
     VHOST_USER_PROTOCOL_F_LOG_SHMFD = 1,
@@ -65,12 +70,15 @@ typedef enum VhostUserRequest {
     VHOST_USER_SET_SLAVE_REQ_FD = 21,
     VHOST_USER_IOTLB_MSG = 22,
     VHOST_USER_SET_VRING_ENDIAN = 23,
+    VHOST_USER_GET_CONFIG = 24,
+    VHOST_USER_SET_CONFIG = 25,
     VHOST_USER_MAX
 } VhostUserRequest;
 
 typedef enum VhostUserSlaveRequest {
     VHOST_USER_SLAVE_NONE = 0,
     VHOST_USER_SLAVE_IOTLB_MSG = 1,
+    VHOST_USER_SLAVE_CONFIG_CHANGE_MSG = 2,
     VHOST_USER_SLAVE_MAX
 }  VhostUserSlaveRequest;
 
@@ -92,6 +100,18 @@ typedef struct VhostUserLog {
     uint64_t mmap_offset;
 } VhostUserLog;
 
+typedef struct VhostUserConfig {
+    uint32_t offset;
+    uint32_t size;
+    uint32_t flags;
+    uint8_t region[VHOST_USER_MAX_CONFIG_SIZE];
+} VhostUserConfig;
+
+static VhostUserConfig c __attribute__ ((unused));
+#define VHOST_USER_CONFIG_HDR_SIZE (sizeof(c.offset) \
+                                   + sizeof(c.size) \
+                                   + sizeof(c.flags))
+
 typedef struct VhostUserMsg {
     VhostUserRequest request;
 
@@ -109,6 +129,7 @@ typedef struct VhostUserMsg {
         VhostUserMemory memory;
         VhostUserLog log;
         struct vhost_iotlb_msg iotlb;
+        VhostUserConfig config;
     } payload;
 } QEMU_PACKED VhostUserMsg;
 
@@ -608,6 +629,21 @@ static int vhost_user_reset_device(struct vhost_dev *dev)
     return 0;
 }
 
+static int vhost_user_slave_handle_config_change(struct vhost_dev *dev)
+{
+    int ret = -1;
+
+    if (!dev->config_ops) {
+        return -1;
+    }
+
+    if (dev->config_ops->vhost_dev_config_notifier) {
+        ret = dev->config_ops->vhost_dev_config_notifier(dev);
+    }
+
+    return ret;
+}
+
 static void slave_read(void *opaque)
 {
     struct vhost_dev *dev = opaque;
@@ -640,6 +676,9 @@ static void slave_read(void *opaque)
     case VHOST_USER_SLAVE_IOTLB_MSG:
         ret = vhost_backend_handle_iotlb_msg(dev, &msg.payload.iotlb);
         break;
+    case VHOST_USER_SLAVE_CONFIG_CHANGE_MSG :
+        ret = vhost_user_slave_handle_config_change(dev);
+        break;
     default:
         error_report("Received unexpected msg type.");
         ret = -EINVAL;
@@ -922,6 +961,83 @@ static void vhost_user_set_iotlb_callback(struct vhost_dev *dev, int enabled)
     /* No-op as the receive channel is not dedicated to IOTLB messages. */
 }
 
+static int vhost_user_get_config(struct vhost_dev *dev, uint8_t *config,
+                                 uint32_t config_len)
+{
+    VhostUserMsg msg = {
+        msg.request = VHOST_USER_GET_CONFIG,
+        msg.flags = VHOST_USER_VERSION,
+        msg.size = VHOST_USER_CONFIG_HDR_SIZE + config_len,
+    };
+
+    if (config_len > VHOST_USER_MAX_CONFIG_SIZE) {
+        return -1;
+    }
+
+    msg.payload.config.offset = 0;
+    msg.payload.config.size = config_len;
+    if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
+        return -1;
+    }
+
+    if (vhost_user_read(dev, &msg) < 0) {
+        return -1;
+    }
+
+    if (msg.request != VHOST_USER_GET_CONFIG) {
+        error_report("Received unexpected msg type. Expected %d received %d",
+                     VHOST_USER_GET_CONFIG, msg.request);
+        return -1;
+    }
+
+    if (msg.size != VHOST_USER_CONFIG_HDR_SIZE + config_len) {
+        error_report("Received bad msg size.");
+        return -1;
+    }
+
+    memcpy(config, msg.payload.config.region, config_len);
+
+    return 0;
+}
+
+static int vhost_user_set_config(struct vhost_dev *dev, const uint8_t *data,
+                                 uint32_t offset, uint32_t size, uint32_t flags)
+{
+    uint8_t *p;
+    bool reply_supported = virtio_has_feature(dev->protocol_features,
+                                              VHOST_USER_PROTOCOL_F_REPLY_ACK);
+
+    VhostUserMsg msg = {
+        msg.request = VHOST_USER_SET_CONFIG,
+        msg.flags = VHOST_USER_VERSION,
+        msg.size = VHOST_USER_CONFIG_HDR_SIZE + size,
+    };
+
+    if (reply_supported) {
+        msg.flags |= VHOST_USER_NEED_REPLY_MASK;
+    }
+
+    if (size > VHOST_USER_MAX_CONFIG_SIZE) {
+        return -1;
+    }
+
+    msg.payload.config.offset = offset,
+    msg.payload.config.size = size,
+    msg.payload.config.flags = flags,
+    p = msg.payload.config.region;
+    memcpy(p, data, size);
+
+    if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
+        return -1;
+    }
+
+    if (reply_supported) {
+        return process_message_reply(dev, &msg);
+    }
+
+    return 0;
+}
+
 const VhostOps user_ops = {
         .backend_type = VHOST_BACKEND_TYPE_USER,
         .vhost_backend_init = vhost_user_init,
@@ -948,4 +1064,6 @@ const VhostOps user_ops = {
         .vhost_net_set_mtu = vhost_user_net_set_mtu,
         .vhost_set_iotlb_callback = vhost_user_set_iotlb_callback,
         .vhost_send_device_iotlb_msg = vhost_user_send_device_iotlb_msg,
+        .vhost_get_config = vhost_user_get_config,
+        .vhost_set_config = vhost_user_set_config,
 };
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index e4290ce..386aef8 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1505,6 +1505,38 @@ void vhost_ack_features(struct vhost_dev *hdev, const int *feature_bits,
     }
 }
 
+int vhost_dev_get_config(struct vhost_dev *hdev, uint8_t *config,
+                         uint32_t config_len)
+{
+    assert(hdev->vhost_ops);
+
+    if (hdev->vhost_ops->vhost_get_config) {
+        return hdev->vhost_ops->vhost_get_config(hdev, config, config_len);
+    }
+
+    return -1;
+}
+
+int vhost_dev_set_config(struct vhost_dev *hdev, const uint8_t *data,
+                         uint32_t offset, uint32_t size, uint32_t flags)
+{
+    assert(hdev->vhost_ops);
+
+    if (hdev->vhost_ops->vhost_set_config) {
+        return hdev->vhost_ops->vhost_set_config(hdev, data, offset,
+                                                 size, flags);
+    }
+
+    return -1;
+}
+
+void vhost_dev_set_config_notifier(struct vhost_dev *hdev,
+                                   const VhostDevConfigOps *ops)
+{
+    assert(hdev->vhost_ops);
+    hdev->config_ops = ops;
+}
+
 /* Host notifiers must be enabled at this point. */
 int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev)
 {
-- 
MST

  parent reply	other threads:[~2018-01-16  4:46 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-01-16  4:46 [Qemu-devel] [PULL 00/33] pc, pci, virtio: features, fixes, cleanups Michael S. Tsirkin
2018-01-16  4:46 ` [Qemu-devel] [PULL 01/33] MAINTAINERS: Add myself as maintainer to X86 machines Michael S. Tsirkin
2018-01-16  5:55   ` Thomas Huth
2018-01-16  4:46 ` Michael S. Tsirkin [this message]
2018-01-16  4:46 ` [Qemu-devel] [PULL 03/33] vhost-user-blk: introduce a new vhost-user-blk host device Michael S. Tsirkin
2018-01-16  4:46 ` [Qemu-devel] [PULL 04/33] contrib/libvhost-user: enable virtio config space messages Michael S. Tsirkin
2018-01-16  4:46 ` [Qemu-devel] [PULL 05/33] contrib/vhost-user-blk: introduce a vhost-user-blk sample application Michael S. Tsirkin
2018-01-16  4:46 ` [Qemu-devel] [PULL 06/33] qemu: add a cleanup callback function to EventNotifier Michael S. Tsirkin
2018-01-16  4:46 ` [Qemu-devel] [PULL 07/33] virtio: postpone the execution of event_notifier_cleanup function Michael S. Tsirkin
2018-01-16  4:46 ` [Qemu-devel] [PULL 08/33] virtio: improve virtio devices initialization time Michael S. Tsirkin
2018-01-16  4:47 ` [Qemu-devel] [PULL 09/33] pci/shpc: Move function to generic header file Michael S. Tsirkin
2018-01-16  4:47 ` [Qemu-devel] [PULL 10/33] vhost-user: fix multiple queue specification Michael S. Tsirkin
2018-01-16  4:47 ` [Qemu-devel] [PULL 11/33] intel-iommu: Redefine macros to enable supporting 48 bit address width Michael S. Tsirkin
2018-01-16  4:47 ` [Qemu-devel] [PULL 12/33] intel-iommu: Extend address width to 48 bits Michael S. Tsirkin
2018-01-16  4:47 ` [Qemu-devel] [PULL 13/33] hw/pci-bridge: fix QEMU crash because of pcie-root-port Michael S. Tsirkin
2018-01-16  4:47 ` [Qemu-devel] [PULL 14/33] ACPI/unit-test: Add a testcase for RAM allocation in numa node Michael S. Tsirkin
2018-01-16  4:47 ` [Qemu-devel] [PULL 15/33] hw/acpi-build: Make next_base easy to follow Michael S. Tsirkin
2018-01-16  4:47 ` [Qemu-devel] [PULL 16/33] vhost-user-test: fix features mask Michael S. Tsirkin
2018-01-16  4:47 ` [Qemu-devel] [PULL 17/33] vhost-user-test: extract read-guest-mem test from main loop Michael S. Tsirkin
2018-01-16  4:47 ` [Qemu-devel] [PULL 18/33] vhost-user-test: setup virtqueues in all tests Michael S. Tsirkin
2018-01-16  4:47 ` [Qemu-devel] [PULL 19/33] vhost-user-test: make features mask an init_virtio_dev() argument Michael S. Tsirkin
2018-01-16  4:47 ` [Qemu-devel] [PULL 20/33] vhost-user-test: use init_virtio_dev in multiqueue test Michael S. Tsirkin
2018-01-16  4:48 ` [Qemu-devel] [PULL 21/33] vhost: Build temporary section list and deref after commit Michael S. Tsirkin
2018-01-16  4:48 ` [Qemu-devel] [PULL 22/33] vhost: Move log_dirty check Michael S. Tsirkin
2018-01-16 13:27   ` Igor Mammedov
2018-01-16  4:48 ` [Qemu-devel] [PULL 23/33] vhost: Simplify ring verification checks Michael S. Tsirkin
2018-01-16  4:48 ` [Qemu-devel] [PULL 24/33] vhost: Merge sections added to temporary list Michael S. Tsirkin
2018-01-16  4:48 ` [Qemu-devel] [PULL 25/33] x86_iommu: Move machine check to x86_iommu_realize() Michael S. Tsirkin
2018-01-16  4:48 ` [Qemu-devel] [PULL 26/33] x86_iommu: check if machine has PCI bus Michael S. Tsirkin
2018-01-16  4:48 ` [Qemu-devel] [PULL 27/33] tests: acpi: move tested tables array allocation outside of test_acpi_dsdt_table() Michael S. Tsirkin
2018-01-16  4:48 ` [Qemu-devel] [PULL 28/33] tests: acpi: init table descriptor in test_dst_table() Michael S. Tsirkin
2018-01-16  4:48 ` [Qemu-devel] [PULL 29/33] tests: acpi: rename test_acpi_tables()/test_dst_table() to reflect its usage Michael S. Tsirkin
2018-01-16  4:48 ` [Qemu-devel] [PULL 30/33] tests: acpi: add comments to fetch_rsdt_referenced_tables/data->tables usage Michael S. Tsirkin
2018-01-16  4:48 ` [Qemu-devel] [PULL 31/33] vhost-user: factor out msg head and payload Michael S. Tsirkin
2018-01-16  4:48 ` [Qemu-devel] [PULL 32/33] vhost-user: fix misaligned access to payload Michael S. Tsirkin
2018-01-16  4:48 ` [Qemu-devel] [PULL 33/33] vhost: remove assertion to prevent crash Michael S. Tsirkin
2018-01-16 12:24 ` [Qemu-devel] [PULL 00/33] pc, pci, virtio: features, fixes, cleanups Peter Maydell
2018-01-16 12:58   ` Peter Maydell
2018-01-16 12:59   ` Dr. David Alan Gilbert

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1516077852-7974-3-git-send-email-mst@redhat.com \
    --to=mst@redhat.com \
    --cc=changpeng.liu@intel.com \
    --cc=marcandre.lureau@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).