All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 00/20] virtio: add vhost-user-generic, reduce c&p and support standalone
@ 2023-07-10 15:35 ` Alex Bennée
  0 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

A lot of our vhost-user stubs are large chunks of boilerplate that do
(mostly) the same thing. This series attempts to fix that by defining
a new base class (vhost-user-base) which is used by a generic
vhost-user-device implementation. Then the rng, gpio and i2c
vhost-user devices become simple specialisations of the common base
defining the ID, number of queues and potentially the config handling.

However as of v3 we go a bit further and introduce a new protocol
feature called F_STANDALONE which adds some messages to vhost-user
that allow the daemon to fully advertise its capabilities.

Example
=======

Using the vhost-device-rng built from this branch (draft PR):

  https://github.com/rust-vmm/vhost-device/pull/394

You can start QEMU with an even simpler command line:

  -chardev socket,id=vus,path=/tmp/vus.sock0 \
  -device vhost-user-device-pci,chardev=vus \
  -d trace:vhost_\*,trace:vhost_user\*

which doesn't specify any queues or config space but gets it from the
daemon as it starts up. This does involve a bit of shuffling around in
the guts of the vhost code so currently it is RFC status.

Anything for 8.1?
=================

mst,

I don't know if you want to cherry pick anything up to and including:

  hw/virtio: derive vhost-user-i2c from vhost-user-base

which is at least a cleanup. However I'm on holiday for the next 3 or
so weeks so it's perfectly ok to leave this as 8.2 material if you
want.

Alex.

Alex Bennée (20):
  include: attempt to document device_class_set_props
  include/hw: document the device_class_set_parent_* fns
  hw/virtio: fix typo in VIRTIO_CONFIG_IRQ_IDX comments
  include/hw/virtio: document virtio_notify_config
  include/hw/virtio: add kerneldoc for virtio_init
  include/hw/virtio: document some more usage of notifiers
  virtio: add vhost-user-base and a generic vhost-user-device
  virtio: add PCI stub for vhost-user-device
  hw/virtio: derive vhost-user-rng from vhost-user-device
  hw/virtio: add config support to vhost-user-device
  hw/virtio: derive vhost-user-gpio from vhost-user-device
  hw/virtio: derive vhost-user-i2c from vhost-user-base
  docs/system: add a basic enumeration of vhost-user devices
  docs/interop: define STANDALONE protocol feature for vhost-user
  hw/virtio: move vhost_user_init earlier
  hw/virtio: move virtq initialisation into internal helper
  hw/virtio: push down allocation responsibility for vhost_dev->vqs
  hw/virtio: validate F_STANDALONE also supports other protocol features
  hw/virtio: probe backend for specs if it supports it
  hw/virtio: allow vhost-user-device to be driven by backend

 docs/interop/vhost-user.rst            |  39 +++
 docs/system/devices/vhost-user-rng.rst |   2 +
 docs/system/devices/vhost-user.rst     |  41 +++
 include/hw/qdev-core.h                 |  36 +++
 include/hw/virtio/vhost-user-blk.h     |   1 -
 include/hw/virtio/vhost-user-device.h  |  46 +++
 include/hw/virtio/vhost-user-gpio.h    |  23 +-
 include/hw/virtio/vhost-user-i2c.h     |  18 +-
 include/hw/virtio/vhost-user-rng.h     |  11 +-
 include/hw/virtio/vhost.h              |  21 ++
 include/hw/virtio/virtio.h             |  21 ++
 backends/vhost-user.c                  |   1 -
 hw/block/vhost-user-blk.c              |   7 +-
 hw/display/vhost-user-gpu.c            |   4 +-
 hw/net/virtio-net.c                    |   4 +-
 hw/scsi/vhost-scsi.c                   |   2 -
 hw/scsi/vhost-user-scsi.c              |   6 -
 hw/virtio/vdpa-dev.c                   |   9 +-
 hw/virtio/vhost-user-device-pci.c      |  71 +++++
 hw/virtio/vhost-user-device.c          | 396 ++++++++++++++++++++++++
 hw/virtio/vhost-user-fs.c              |   5 +-
 hw/virtio/vhost-user-gpio.c            | 400 ++-----------------------
 hw/virtio/vhost-user-i2c.c             | 271 +----------------
 hw/virtio/vhost-user-rng.c             | 277 ++---------------
 hw/virtio/vhost-user.c                 |  84 ++++++
 hw/virtio/vhost-vsock-common.c         |   4 +-
 hw/virtio/vhost.c                      |  70 +++--
 hw/virtio/virtio-crypto.c              |   4 +-
 hw/virtio/meson.build                  |  20 +-
 29 files changed, 898 insertions(+), 996 deletions(-)
 create mode 100644 include/hw/virtio/vhost-user-device.h
 create mode 100644 hw/virtio/vhost-user-device-pci.c
 create mode 100644 hw/virtio/vhost-user-device.c

-- 
2.39.2



^ permalink raw reply	[flat|nested] 66+ messages in thread

* [Virtio-fs] [PATCH v3 00/20] virtio: add vhost-user-generic, reduce c&p and support standalone
@ 2023-07-10 15:35 ` Alex Bennée
  0 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

A lot of our vhost-user stubs are large chunks of boilerplate that do
(mostly) the same thing. This series attempts to fix that by defining
a new base class (vhost-user-base) which is used by a generic
vhost-user-device implementation. Then the rng, gpio and i2c
vhost-user devices become simple specialisations of the common base
defining the ID, number of queues and potentially the config handling.

However as of v3 we go a bit further and introduce a new protocol
feature called F_STANDALONE which adds some messages to vhost-user
that allow the daemon to fully advertise its capabilities.

Example
=======

Using the vhost-device-rng built from this branch (draft PR):

  https://github.com/rust-vmm/vhost-device/pull/394

You can start QEMU with an even simpler command line:

  -chardev socket,id=vus,path=/tmp/vus.sock0 \
  -device vhost-user-device-pci,chardev=vus \
  -d trace:vhost_\*,trace:vhost_user\*

which doesn't specify any queues or config space but gets it from the
daemon as it starts up. This does involve a bit of shuffling around in
the guts of the vhost code so currently it is RFC status.

Anything for 8.1?
=================

mst,

I don't know if you want to cherry pick anything up to and including:

  hw/virtio: derive vhost-user-i2c from vhost-user-base

which is at least a cleanup. However I'm on holiday for the next 3 or
so weeks so it's perfectly ok to leave this as 8.2 material if you
want.

Alex.

Alex Bennée (20):
  include: attempt to document device_class_set_props
  include/hw: document the device_class_set_parent_* fns
  hw/virtio: fix typo in VIRTIO_CONFIG_IRQ_IDX comments
  include/hw/virtio: document virtio_notify_config
  include/hw/virtio: add kerneldoc for virtio_init
  include/hw/virtio: document some more usage of notifiers
  virtio: add vhost-user-base and a generic vhost-user-device
  virtio: add PCI stub for vhost-user-device
  hw/virtio: derive vhost-user-rng from vhost-user-device
  hw/virtio: add config support to vhost-user-device
  hw/virtio: derive vhost-user-gpio from vhost-user-device
  hw/virtio: derive vhost-user-i2c from vhost-user-base
  docs/system: add a basic enumeration of vhost-user devices
  docs/interop: define STANDALONE protocol feature for vhost-user
  hw/virtio: move vhost_user_init earlier
  hw/virtio: move virtq initialisation into internal helper
  hw/virtio: push down allocation responsibility for vhost_dev->vqs
  hw/virtio: validate F_STANDALONE also supports other protocol features
  hw/virtio: probe backend for specs if it supports it
  hw/virtio: allow vhost-user-device to be driven by backend

 docs/interop/vhost-user.rst            |  39 +++
 docs/system/devices/vhost-user-rng.rst |   2 +
 docs/system/devices/vhost-user.rst     |  41 +++
 include/hw/qdev-core.h                 |  36 +++
 include/hw/virtio/vhost-user-blk.h     |   1 -
 include/hw/virtio/vhost-user-device.h  |  46 +++
 include/hw/virtio/vhost-user-gpio.h    |  23 +-
 include/hw/virtio/vhost-user-i2c.h     |  18 +-
 include/hw/virtio/vhost-user-rng.h     |  11 +-
 include/hw/virtio/vhost.h              |  21 ++
 include/hw/virtio/virtio.h             |  21 ++
 backends/vhost-user.c                  |   1 -
 hw/block/vhost-user-blk.c              |   7 +-
 hw/display/vhost-user-gpu.c            |   4 +-
 hw/net/virtio-net.c                    |   4 +-
 hw/scsi/vhost-scsi.c                   |   2 -
 hw/scsi/vhost-user-scsi.c              |   6 -
 hw/virtio/vdpa-dev.c                   |   9 +-
 hw/virtio/vhost-user-device-pci.c      |  71 +++++
 hw/virtio/vhost-user-device.c          | 396 ++++++++++++++++++++++++
 hw/virtio/vhost-user-fs.c              |   5 +-
 hw/virtio/vhost-user-gpio.c            | 400 ++-----------------------
 hw/virtio/vhost-user-i2c.c             | 271 +----------------
 hw/virtio/vhost-user-rng.c             | 277 ++---------------
 hw/virtio/vhost-user.c                 |  84 ++++++
 hw/virtio/vhost-vsock-common.c         |   4 +-
 hw/virtio/vhost.c                      |  70 +++--
 hw/virtio/virtio-crypto.c              |   4 +-
 hw/virtio/meson.build                  |  20 +-
 29 files changed, 898 insertions(+), 996 deletions(-)
 create mode 100644 include/hw/virtio/vhost-user-device.h
 create mode 100644 hw/virtio/vhost-user-device-pci.c
 create mode 100644 hw/virtio/vhost-user-device.c

-- 
2.39.2


^ permalink raw reply	[flat|nested] 66+ messages in thread

* [PATCH v3 01/20] include: attempt to document device_class_set_props
  2023-07-10 15:35 ` [Virtio-fs] " Alex Bennée
@ 2023-07-10 15:35   ` Alex Bennée
  -1 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

I'm still not sure how I achieve by use case of the parent class
defining the following properties:

  static Property vud_properties[] = {
      DEFINE_PROP_CHR("chardev", VHostUserDevice, chardev),
      DEFINE_PROP_UINT16("id", VHostUserDevice, id, 0),
      DEFINE_PROP_UINT32("num_vqs", VHostUserDevice, num_vqs, 1),
      DEFINE_PROP_END_OF_LIST(),
  };

But for the specialisation of the class I want the id to default to
the actual device id, e.g.:

  static Property vu_rng_properties[] = {
      DEFINE_PROP_UINT16("id", VHostUserDevice, id, VIRTIO_ID_RNG),
      DEFINE_PROP_UINT32("num_vqs", VHostUserDevice, num_vqs, 1),
      DEFINE_PROP_END_OF_LIST(),
  };

And so far the API for doing that isn't super clear.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
 include/hw/qdev-core.h | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 06cadfc492..196ebf6d91 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -926,6 +926,15 @@ BusState *sysbus_get_default(void);
 char *qdev_get_fw_dev_path(DeviceState *dev);
 char *qdev_get_own_fw_dev_path_from_handler(BusState *bus, DeviceState *dev);
 
+/**
+ * device_class_set_props(): add a set of properties to an device
+ * @dc: the parent DeviceClass all devices inherit
+ * @props: an array of properties, terminate by DEFINE_PROP_END_OF_LIST()
+ *
+ * This will add a set of properties to the object. It will fault if
+ * you attempt to add an existing property defined by a parent class.
+ * To modify an inherited property you need to use????
+ */
 void device_class_set_props(DeviceClass *dc, Property *props);
 
 /**
-- 
2.39.2



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Virtio-fs] [PATCH v3 01/20] include: attempt to document device_class_set_props
@ 2023-07-10 15:35   ` Alex Bennée
  0 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

I'm still not sure how I achieve by use case of the parent class
defining the following properties:

  static Property vud_properties[] = {
      DEFINE_PROP_CHR("chardev", VHostUserDevice, chardev),
      DEFINE_PROP_UINT16("id", VHostUserDevice, id, 0),
      DEFINE_PROP_UINT32("num_vqs", VHostUserDevice, num_vqs, 1),
      DEFINE_PROP_END_OF_LIST(),
  };

But for the specialisation of the class I want the id to default to
the actual device id, e.g.:

  static Property vu_rng_properties[] = {
      DEFINE_PROP_UINT16("id", VHostUserDevice, id, VIRTIO_ID_RNG),
      DEFINE_PROP_UINT32("num_vqs", VHostUserDevice, num_vqs, 1),
      DEFINE_PROP_END_OF_LIST(),
  };

And so far the API for doing that isn't super clear.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
 include/hw/qdev-core.h | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 06cadfc492..196ebf6d91 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -926,6 +926,15 @@ BusState *sysbus_get_default(void);
 char *qdev_get_fw_dev_path(DeviceState *dev);
 char *qdev_get_own_fw_dev_path_from_handler(BusState *bus, DeviceState *dev);
 
+/**
+ * device_class_set_props(): add a set of properties to an device
+ * @dc: the parent DeviceClass all devices inherit
+ * @props: an array of properties, terminate by DEFINE_PROP_END_OF_LIST()
+ *
+ * This will add a set of properties to the object. It will fault if
+ * you attempt to add an existing property defined by a parent class.
+ * To modify an inherited property you need to use????
+ */
 void device_class_set_props(DeviceClass *dc, Property *props);
 
 /**
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v3 02/20] include/hw: document the device_class_set_parent_* fns
  2023-07-10 15:35 ` [Virtio-fs] " Alex Bennée
@ 2023-07-10 15:35   ` Alex Bennée
  -1 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

These are useful functions for when you want proper inheritance of
functionality across realize/unrealize calls.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
 include/hw/qdev-core.h | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 196ebf6d91..884c726a87 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -952,9 +952,36 @@ void device_class_set_props(DeviceClass *dc, Property *props);
 void device_class_set_parent_reset(DeviceClass *dc,
                                    DeviceReset dev_reset,
                                    DeviceReset *parent_reset);
+
+/**
+ * device_class_set_parent_realize() - set up for chaining realize fns
+ * @dc: The device class
+ * @dev_realize: the device realize function
+ * @parent_realize: somewhere to save the parents realize function
+ *
+ * This is intended to be used when the new realize function will
+ * eventually call its parent realization function during creation.
+ * This requires storing the function call somewhere (usually in the
+ * instance structure) so you can eventually call
+ * dc->parent_realize(dev, errp)
+ */
 void device_class_set_parent_realize(DeviceClass *dc,
                                      DeviceRealize dev_realize,
                                      DeviceRealize *parent_realize);
+
+
+/**
+ * device_class_set_parent_unrealize() - set up for chaining unrealize fns
+ * @dc: The device class
+ * @dev_unrealize: the device realize function
+ * @parent_unrealize: somewhere to save the parents unrealize function
+ *
+ * This is intended to be used when the new unrealize function will
+ * eventually call its parent unrealization function during the
+ * unrealize phase. This requires storing the function call somewhere
+ * (usually in the instance structure) so you can eventually call
+ * dc->parent_unrealize(dev);
+ */
 void device_class_set_parent_unrealize(DeviceClass *dc,
                                        DeviceUnrealize dev_unrealize,
                                        DeviceUnrealize *parent_unrealize);
-- 
2.39.2



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Virtio-fs] [PATCH v3 02/20] include/hw: document the device_class_set_parent_* fns
@ 2023-07-10 15:35   ` Alex Bennée
  0 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

These are useful functions for when you want proper inheritance of
functionality across realize/unrealize calls.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
 include/hw/qdev-core.h | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 196ebf6d91..884c726a87 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -952,9 +952,36 @@ void device_class_set_props(DeviceClass *dc, Property *props);
 void device_class_set_parent_reset(DeviceClass *dc,
                                    DeviceReset dev_reset,
                                    DeviceReset *parent_reset);
+
+/**
+ * device_class_set_parent_realize() - set up for chaining realize fns
+ * @dc: The device class
+ * @dev_realize: the device realize function
+ * @parent_realize: somewhere to save the parents realize function
+ *
+ * This is intended to be used when the new realize function will
+ * eventually call its parent realization function during creation.
+ * This requires storing the function call somewhere (usually in the
+ * instance structure) so you can eventually call
+ * dc->parent_realize(dev, errp)
+ */
 void device_class_set_parent_realize(DeviceClass *dc,
                                      DeviceRealize dev_realize,
                                      DeviceRealize *parent_realize);
+
+
+/**
+ * device_class_set_parent_unrealize() - set up for chaining unrealize fns
+ * @dc: The device class
+ * @dev_unrealize: the device realize function
+ * @parent_unrealize: somewhere to save the parents unrealize function
+ *
+ * This is intended to be used when the new unrealize function will
+ * eventually call its parent unrealization function during the
+ * unrealize phase. This requires storing the function call somewhere
+ * (usually in the instance structure) so you can eventually call
+ * dc->parent_unrealize(dev);
+ */
 void device_class_set_parent_unrealize(DeviceClass *dc,
                                        DeviceUnrealize dev_unrealize,
                                        DeviceUnrealize *parent_unrealize);
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v3 03/20] hw/virtio: fix typo in VIRTIO_CONFIG_IRQ_IDX comments
  2023-07-10 15:35 ` [Virtio-fs] " Alex Bennée
@ 2023-07-10 15:35   ` Alex Bennée
  -1 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

Fixes: 544f0278af (virtio: introduce macro VIRTIO_CONFIG_IRQ_IDX)
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
 hw/display/vhost-user-gpu.c    | 4 ++--
 hw/net/virtio-net.c            | 4 ++--
 hw/virtio/vhost-user-fs.c      | 4 ++--
 hw/virtio/vhost-user-gpio.c    | 2 +-
 hw/virtio/vhost-vsock-common.c | 4 ++--
 hw/virtio/virtio-crypto.c      | 4 ++--
 6 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c
index 15f9d99d09..1791797bd7 100644
--- a/hw/display/vhost-user-gpu.c
+++ b/hw/display/vhost-user-gpu.c
@@ -489,7 +489,7 @@ vhost_user_gpu_guest_notifier_pending(VirtIODevice *vdev, int idx)
 
     /*
      * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1
-     * as the Marco of configure interrupt's IDX, If this driver does not
+     * as the macro of configure interrupt's IDX, If this driver does not
      * support, the function will return
      */
 
@@ -506,7 +506,7 @@ vhost_user_gpu_guest_notifier_mask(VirtIODevice *vdev, int idx, bool mask)
 
     /*
      * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1
-     * as the Marco of configure interrupt's IDX, If this driver does not
+     * as the macro of configure interrupt's IDX, If this driver does not
      * support, the function will return
      */
 
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 04783f5b94..493afdd96b 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -3362,7 +3362,7 @@ static bool virtio_net_guest_notifier_pending(VirtIODevice *vdev, int idx)
     }
     /*
      * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1
-     * as the Marco of configure interrupt's IDX, If this driver does not
+     * as the macro of configure interrupt's IDX, If this driver does not
      * support, the function will return false
      */
 
@@ -3394,7 +3394,7 @@ static void virtio_net_guest_notifier_mask(VirtIODevice *vdev, int idx,
     }
     /*
      *Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1
-     * as the Marco of configure interrupt's IDX, If this driver does not
+     * as the macro of configure interrupt's IDX, If this driver does not
      * support, the function will return
      */
 
diff --git a/hw/virtio/vhost-user-fs.c b/hw/virtio/vhost-user-fs.c
index 83fc20e49e..49d699ffc2 100644
--- a/hw/virtio/vhost-user-fs.c
+++ b/hw/virtio/vhost-user-fs.c
@@ -161,7 +161,7 @@ static void vuf_guest_notifier_mask(VirtIODevice *vdev, int idx,
 
     /*
      * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1
-     * as the Marco of configure interrupt's IDX, If this driver does not
+     * as the macro of configure interrupt's IDX, If this driver does not
      * support, the function will return
      */
 
@@ -177,7 +177,7 @@ static bool vuf_guest_notifier_pending(VirtIODevice *vdev, int idx)
 
     /*
      * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1
-     * as the Marco of configure interrupt's IDX, If this driver does not
+     * as the macro of configure interrupt's IDX, If this driver does not
      * support, the function will return
      */
 
diff --git a/hw/virtio/vhost-user-gpio.c b/hw/virtio/vhost-user-gpio.c
index d6927b610a..3b013f2d0f 100644
--- a/hw/virtio/vhost-user-gpio.c
+++ b/hw/virtio/vhost-user-gpio.c
@@ -194,7 +194,7 @@ static void vu_gpio_guest_notifier_mask(VirtIODevice *vdev, int idx, bool mask)
 
     /*
      * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1
-     * as the Marco of configure interrupt's IDX, If this driver does not
+     * as the macro of configure interrupt's IDX, If this driver does not
      * support, the function will return
      */
 
diff --git a/hw/virtio/vhost-vsock-common.c b/hw/virtio/vhost-vsock-common.c
index 321262f6b3..12ea87d7a7 100644
--- a/hw/virtio/vhost-vsock-common.c
+++ b/hw/virtio/vhost-vsock-common.c
@@ -129,7 +129,7 @@ static void vhost_vsock_common_guest_notifier_mask(VirtIODevice *vdev, int idx,
 
     /*
      * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1
-     * as the Marco of configure interrupt's IDX, If this driver does not
+     * as the macro of configure interrupt's IDX, If this driver does not
      * support, the function will return
      */
 
@@ -146,7 +146,7 @@ static bool vhost_vsock_common_guest_notifier_pending(VirtIODevice *vdev,
 
     /*
      * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1
-     * as the Marco of configure interrupt's IDX, If this driver does not
+     * as the macro of configure interrupt's IDX, If this driver does not
      * support, the function will return
      */
 
diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c
index a6d7e1e8ec..44faf5a522 100644
--- a/hw/virtio/virtio-crypto.c
+++ b/hw/virtio/virtio-crypto.c
@@ -1210,7 +1210,7 @@ static void virtio_crypto_guest_notifier_mask(VirtIODevice *vdev, int idx,
 
     /*
      * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1
-     * as the Marco of configure interrupt's IDX, If this driver does not
+     * as the macro of configure interrupt's IDX, If this driver does not
      * support, the function will return
      */
 
@@ -1229,7 +1229,7 @@ static bool virtio_crypto_guest_notifier_pending(VirtIODevice *vdev, int idx)
 
     /*
      * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1
-     * as the Marco of configure interrupt's IDX, If this driver does not
+     * as the macro of configure interrupt's IDX, If this driver does not
      * support, the function will return
      */
 
-- 
2.39.2



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Virtio-fs] [PATCH v3 03/20] hw/virtio: fix typo in VIRTIO_CONFIG_IRQ_IDX comments
@ 2023-07-10 15:35   ` Alex Bennée
  0 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

Fixes: 544f0278af (virtio: introduce macro VIRTIO_CONFIG_IRQ_IDX)
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
 hw/display/vhost-user-gpu.c    | 4 ++--
 hw/net/virtio-net.c            | 4 ++--
 hw/virtio/vhost-user-fs.c      | 4 ++--
 hw/virtio/vhost-user-gpio.c    | 2 +-
 hw/virtio/vhost-vsock-common.c | 4 ++--
 hw/virtio/virtio-crypto.c      | 4 ++--
 6 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c
index 15f9d99d09..1791797bd7 100644
--- a/hw/display/vhost-user-gpu.c
+++ b/hw/display/vhost-user-gpu.c
@@ -489,7 +489,7 @@ vhost_user_gpu_guest_notifier_pending(VirtIODevice *vdev, int idx)
 
     /*
      * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1
-     * as the Marco of configure interrupt's IDX, If this driver does not
+     * as the macro of configure interrupt's IDX, If this driver does not
      * support, the function will return
      */
 
@@ -506,7 +506,7 @@ vhost_user_gpu_guest_notifier_mask(VirtIODevice *vdev, int idx, bool mask)
 
     /*
      * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1
-     * as the Marco of configure interrupt's IDX, If this driver does not
+     * as the macro of configure interrupt's IDX, If this driver does not
      * support, the function will return
      */
 
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 04783f5b94..493afdd96b 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -3362,7 +3362,7 @@ static bool virtio_net_guest_notifier_pending(VirtIODevice *vdev, int idx)
     }
     /*
      * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1
-     * as the Marco of configure interrupt's IDX, If this driver does not
+     * as the macro of configure interrupt's IDX, If this driver does not
      * support, the function will return false
      */
 
@@ -3394,7 +3394,7 @@ static void virtio_net_guest_notifier_mask(VirtIODevice *vdev, int idx,
     }
     /*
      *Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1
-     * as the Marco of configure interrupt's IDX, If this driver does not
+     * as the macro of configure interrupt's IDX, If this driver does not
      * support, the function will return
      */
 
diff --git a/hw/virtio/vhost-user-fs.c b/hw/virtio/vhost-user-fs.c
index 83fc20e49e..49d699ffc2 100644
--- a/hw/virtio/vhost-user-fs.c
+++ b/hw/virtio/vhost-user-fs.c
@@ -161,7 +161,7 @@ static void vuf_guest_notifier_mask(VirtIODevice *vdev, int idx,
 
     /*
      * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1
-     * as the Marco of configure interrupt's IDX, If this driver does not
+     * as the macro of configure interrupt's IDX, If this driver does not
      * support, the function will return
      */
 
@@ -177,7 +177,7 @@ static bool vuf_guest_notifier_pending(VirtIODevice *vdev, int idx)
 
     /*
      * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1
-     * as the Marco of configure interrupt's IDX, If this driver does not
+     * as the macro of configure interrupt's IDX, If this driver does not
      * support, the function will return
      */
 
diff --git a/hw/virtio/vhost-user-gpio.c b/hw/virtio/vhost-user-gpio.c
index d6927b610a..3b013f2d0f 100644
--- a/hw/virtio/vhost-user-gpio.c
+++ b/hw/virtio/vhost-user-gpio.c
@@ -194,7 +194,7 @@ static void vu_gpio_guest_notifier_mask(VirtIODevice *vdev, int idx, bool mask)
 
     /*
      * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1
-     * as the Marco of configure interrupt's IDX, If this driver does not
+     * as the macro of configure interrupt's IDX, If this driver does not
      * support, the function will return
      */
 
diff --git a/hw/virtio/vhost-vsock-common.c b/hw/virtio/vhost-vsock-common.c
index 321262f6b3..12ea87d7a7 100644
--- a/hw/virtio/vhost-vsock-common.c
+++ b/hw/virtio/vhost-vsock-common.c
@@ -129,7 +129,7 @@ static void vhost_vsock_common_guest_notifier_mask(VirtIODevice *vdev, int idx,
 
     /*
      * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1
-     * as the Marco of configure interrupt's IDX, If this driver does not
+     * as the macro of configure interrupt's IDX, If this driver does not
      * support, the function will return
      */
 
@@ -146,7 +146,7 @@ static bool vhost_vsock_common_guest_notifier_pending(VirtIODevice *vdev,
 
     /*
      * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1
-     * as the Marco of configure interrupt's IDX, If this driver does not
+     * as the macro of configure interrupt's IDX, If this driver does not
      * support, the function will return
      */
 
diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c
index a6d7e1e8ec..44faf5a522 100644
--- a/hw/virtio/virtio-crypto.c
+++ b/hw/virtio/virtio-crypto.c
@@ -1210,7 +1210,7 @@ static void virtio_crypto_guest_notifier_mask(VirtIODevice *vdev, int idx,
 
     /*
      * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1
-     * as the Marco of configure interrupt's IDX, If this driver does not
+     * as the macro of configure interrupt's IDX, If this driver does not
      * support, the function will return
      */
 
@@ -1229,7 +1229,7 @@ static bool virtio_crypto_guest_notifier_pending(VirtIODevice *vdev, int idx)
 
     /*
      * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1
-     * as the Marco of configure interrupt's IDX, If this driver does not
+     * as the macro of configure interrupt's IDX, If this driver does not
      * support, the function will return
      */
 
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v3 04/20] include/hw/virtio: document virtio_notify_config
  2023-07-10 15:35 ` [Virtio-fs] " Alex Bennée
@ 2023-07-10 15:35   ` Alex Bennée
  -1 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
 include/hw/virtio/virtio.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index 0492d26900..0671989383 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -276,6 +276,13 @@ extern const VMStateInfo virtio_vmstate_info;
 
 int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id);
 
+/**
+ * virtio_notify_config() - signal a change to device config
+ * @vdev: the virtio device
+ *
+ * Assuming the virtio device is up (VIRTIO_CONFIG_S_DRIVER_OK) this
+ * will trigger a guest interrupt and update the config version.
+ */
 void virtio_notify_config(VirtIODevice *vdev);
 
 bool virtio_queue_get_notification(VirtQueue *vq);
-- 
2.39.2



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Virtio-fs] [PATCH v3 04/20] include/hw/virtio: document virtio_notify_config
@ 2023-07-10 15:35   ` Alex Bennée
  0 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
 include/hw/virtio/virtio.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index 0492d26900..0671989383 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -276,6 +276,13 @@ extern const VMStateInfo virtio_vmstate_info;
 
 int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id);
 
+/**
+ * virtio_notify_config() - signal a change to device config
+ * @vdev: the virtio device
+ *
+ * Assuming the virtio device is up (VIRTIO_CONFIG_S_DRIVER_OK) this
+ * will trigger a guest interrupt and update the config version.
+ */
 void virtio_notify_config(VirtIODevice *vdev);
 
 bool virtio_queue_get_notification(VirtQueue *vq);
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v3 05/20] include/hw/virtio: add kerneldoc for virtio_init
  2023-07-10 15:35 ` [Virtio-fs] " Alex Bennée
@ 2023-07-10 15:35   ` Alex Bennée
  -1 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
 include/hw/virtio/virtio.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index 0671989383..631490bda4 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -219,6 +219,12 @@ struct VirtioDeviceClass {
 void virtio_instance_init_common(Object *proxy_obj, void *data,
                                  size_t vdev_size, const char *vdev_name);
 
+/**
+ * virtio_init() - initialise the common VirtIODevice structure
+ * @vdev: pointer to VirtIODevice
+ * @device_id: the VirtIO device ID (see virtio_ids.h)
+ * @config_size: size of the config space
+ */
 void virtio_init(VirtIODevice *vdev, uint16_t device_id, size_t config_size);
 
 void virtio_cleanup(VirtIODevice *vdev);
-- 
2.39.2



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Virtio-fs] [PATCH v3 05/20] include/hw/virtio: add kerneldoc for virtio_init
@ 2023-07-10 15:35   ` Alex Bennée
  0 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
 include/hw/virtio/virtio.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index 0671989383..631490bda4 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -219,6 +219,12 @@ struct VirtioDeviceClass {
 void virtio_instance_init_common(Object *proxy_obj, void *data,
                                  size_t vdev_size, const char *vdev_name);
 
+/**
+ * virtio_init() - initialise the common VirtIODevice structure
+ * @vdev: pointer to VirtIODevice
+ * @device_id: the VirtIO device ID (see virtio_ids.h)
+ * @config_size: size of the config space
+ */
 void virtio_init(VirtIODevice *vdev, uint16_t device_id, size_t config_size);
 
 void virtio_cleanup(VirtIODevice *vdev);
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v3 06/20] include/hw/virtio: document some more usage of notifiers
  2023-07-10 15:35 ` [Virtio-fs] " Alex Bennée
@ 2023-07-10 15:35   ` Alex Bennée
  -1 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

Lets document some more of the core VirtIODevice structure.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
 include/hw/virtio/virtio.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index 631490bda4..c8f72850bc 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -150,10 +150,18 @@ struct VirtIODevice
     VMChangeStateEntry *vmstate;
     char *bus_name;
     uint8_t device_endian;
+    /**
+     * @user_guest_notifier_mask: gate usage of ->guest_notifier_mask() callback.
+     * This is used to suppress the masking of guest updates for
+     * vhost-user devices which are asynchronous by design.
+     */
     bool use_guest_notifier_mask;
     AddressSpace *dma_as;
     QLIST_HEAD(, VirtQueue) *vector_queues;
     QTAILQ_ENTRY(VirtIODevice) next;
+    /**
+     * @config_notifier: the event notifier that handles config events
+     */
     EventNotifier config_notifier;
     bool device_iotlb_enabled;
 };
-- 
2.39.2



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Virtio-fs] [PATCH v3 06/20] include/hw/virtio: document some more usage of notifiers
@ 2023-07-10 15:35   ` Alex Bennée
  0 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

Lets document some more of the core VirtIODevice structure.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
 include/hw/virtio/virtio.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index 631490bda4..c8f72850bc 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -150,10 +150,18 @@ struct VirtIODevice
     VMChangeStateEntry *vmstate;
     char *bus_name;
     uint8_t device_endian;
+    /**
+     * @user_guest_notifier_mask: gate usage of ->guest_notifier_mask() callback.
+     * This is used to suppress the masking of guest updates for
+     * vhost-user devices which are asynchronous by design.
+     */
     bool use_guest_notifier_mask;
     AddressSpace *dma_as;
     QLIST_HEAD(, VirtQueue) *vector_queues;
     QTAILQ_ENTRY(VirtIODevice) next;
+    /**
+     * @config_notifier: the event notifier that handles config events
+     */
     EventNotifier config_notifier;
     bool device_iotlb_enabled;
 };
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v3 07/20] virtio: add vhost-user-base and a generic vhost-user-device
  2023-07-10 15:35 ` [Virtio-fs] " Alex Bennée
@ 2023-07-10 15:35   ` Alex Bennée
  -1 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

In theory we shouldn't need to repeat so much boilerplate to support
vhost-user backends. This provides a generic vhost-user-base QOM
object and a derived vhost-user-device for which the user needs to
provide the few bits of information that aren't currently provided by
the vhost-user protocol. This should provide a baseline implementation
from which the other vhost-user stub can specialise.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>

---
v2
  - split into vub and vud
---
 include/hw/virtio/vhost-user-device.h |  45 ++++
 hw/virtio/vhost-user-device.c         | 324 ++++++++++++++++++++++++++
 hw/virtio/meson.build                 |   2 +
 3 files changed, 371 insertions(+)
 create mode 100644 include/hw/virtio/vhost-user-device.h
 create mode 100644 hw/virtio/vhost-user-device.c

diff --git a/include/hw/virtio/vhost-user-device.h b/include/hw/virtio/vhost-user-device.h
new file mode 100644
index 0000000000..9105011e25
--- /dev/null
+++ b/include/hw/virtio/vhost-user-device.h
@@ -0,0 +1,45 @@
+/*
+ * Vhost-user generic virtio device
+ *
+ * Copyright (c) 2023 Linaro Ltd
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef QEMU_VHOST_USER_DEVICE_H
+#define QEMU_VHOST_USER_DEVICE_H
+
+#include "hw/virtio/vhost.h"
+#include "hw/virtio/vhost-user.h"
+
+#define TYPE_VHOST_USER_BASE "vhost-user-base"
+
+OBJECT_DECLARE_TYPE(VHostUserBase, VHostUserBaseClass, VHOST_USER_BASE)
+
+struct VHostUserBase {
+    VirtIODevice parent;
+    /* Properties */
+    CharBackend chardev;
+    uint16_t virtio_id;
+    uint32_t num_vqs;
+    /* State tracking */
+    VhostUserState vhost_user;
+    struct vhost_virtqueue *vhost_vq;
+    struct vhost_dev vhost_dev;
+    GPtrArray *vqs;
+    bool connected;
+};
+
+    /* needed so we can use the base realize after specialisation
+       tweaks */
+struct VHostUserBaseClass {
+    /*< private >*/
+    VirtioDeviceClass parent_class;
+    /*< public >*/
+    DeviceRealize parent_realize;
+};
+
+/* shared for the benefit of the derived pci class */
+#define TYPE_VHOST_USER_DEVICE "vhost-user-device"
+
+#endif /* QEMU_VHOST_USER_DEVICE_H */
diff --git a/hw/virtio/vhost-user-device.c b/hw/virtio/vhost-user-device.c
new file mode 100644
index 0000000000..b0239fa033
--- /dev/null
+++ b/hw/virtio/vhost-user-device.c
@@ -0,0 +1,324 @@
+/*
+ * Generic vhost-user stub. This can be used to connect to any
+ * vhost-user backend. All configuration details must be handled by
+ * the vhost-user daemon itself
+ *
+ * Copyright (c) 2023 Linaro Ltd
+ * Author: Alex Bennée <alex.bennee@linaro.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/qdev-properties.h"
+#include "hw/virtio/virtio-bus.h"
+#include "hw/virtio/vhost-user-device.h"
+#include "qemu/error-report.h"
+
+static void vub_start(VirtIODevice *vdev)
+{
+    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
+    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
+    VHostUserBase *vub = VHOST_USER_BASE(vdev);
+    int ret, i;
+
+    if (!k->set_guest_notifiers) {
+        error_report("binding does not support guest notifiers");
+        return;
+    }
+
+    ret = vhost_dev_enable_notifiers(&vub->vhost_dev, vdev);
+    if (ret < 0) {
+        error_report("Error enabling host notifiers: %d", -ret);
+        return;
+    }
+
+    ret = k->set_guest_notifiers(qbus->parent, vub->vhost_dev.nvqs, true);
+    if (ret < 0) {
+        error_report("Error binding guest notifier: %d", -ret);
+        goto err_host_notifiers;
+    }
+
+    vub->vhost_dev.acked_features = vdev->guest_features;
+
+    ret = vhost_dev_start(&vub->vhost_dev, vdev, true);
+    if (ret < 0) {
+        error_report("Error starting vhost-user-device: %d", -ret);
+        goto err_guest_notifiers;
+    }
+
+    /*
+     * guest_notifier_mask/pending not used yet, so just unmask
+     * everything here. virtio-pci will do the right thing by
+     * enabling/disabling irqfd.
+     */
+    for (i = 0; i < vub->vhost_dev.nvqs; i++) {
+        vhost_virtqueue_mask(&vub->vhost_dev, vdev, i, false);
+    }
+
+    return;
+
+err_guest_notifiers:
+    k->set_guest_notifiers(qbus->parent, vub->vhost_dev.nvqs, false);
+err_host_notifiers:
+    vhost_dev_disable_notifiers(&vub->vhost_dev, vdev);
+}
+
+static void vub_stop(VirtIODevice *vdev)
+{
+    VHostUserBase *vub = VHOST_USER_BASE(vdev);
+    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
+    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
+    int ret;
+
+    if (!k->set_guest_notifiers) {
+        return;
+    }
+
+    vhost_dev_stop(&vub->vhost_dev, vdev, true);
+
+    ret = k->set_guest_notifiers(qbus->parent, vub->vhost_dev.nvqs, false);
+    if (ret < 0) {
+        error_report("vhost guest notifier cleanup failed: %d", ret);
+        return;
+    }
+
+    vhost_dev_disable_notifiers(&vub->vhost_dev, vdev);
+}
+
+static void vub_set_status(VirtIODevice *vdev, uint8_t status)
+{
+    VHostUserBase *vub = VHOST_USER_BASE(vdev);
+    bool should_start = virtio_device_should_start(vdev, status);
+
+    if (vhost_dev_is_started(&vub->vhost_dev) == should_start) {
+        return;
+    }
+
+    if (should_start) {
+        vub_start(vdev);
+    } else {
+        vub_stop(vdev);
+    }
+}
+
+/*
+ * For an implementation where everything is delegated to the backend
+ * we don't do anything other than return the full feature set offered
+ * by the daemon (module the reserved feature bit).
+ */
+static uint64_t vub_get_features(VirtIODevice *vdev,
+                                 uint64_t requested_features, Error **errp)
+{
+    VHostUserBase *vub = VHOST_USER_BASE(vdev);
+    /* This should be set when the vhost connection initialises */
+    g_assert(vub->vhost_dev.features);
+    return vub->vhost_dev.features & ~(1ULL << VHOST_USER_F_PROTOCOL_FEATURES);
+}
+
+static void vub_handle_output(VirtIODevice *vdev, VirtQueue *vq)
+{
+    /*
+     * Not normally called; it's the daemon that handles the queue;
+     * however virtio's cleanup path can call this.
+     */
+}
+
+static void do_vhost_user_cleanup(VirtIODevice *vdev, VHostUserBase *vub)
+{
+    vhost_user_cleanup(&vub->vhost_user);
+
+    for (int i = 0; i < vub->num_vqs; i++) {
+        VirtQueue *vq = g_ptr_array_index(vub->vqs, i);
+        virtio_delete_queue(vq);
+    }
+
+    virtio_cleanup(vdev);
+}
+
+static int vub_connect(DeviceState *dev)
+{
+    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+    VHostUserBase *vub = VHOST_USER_BASE(vdev);
+
+    if (vub->connected) {
+        return 0;
+    }
+    vub->connected = true;
+
+    /* restore vhost state */
+    if (virtio_device_started(vdev, vdev->status)) {
+        vub_start(vdev);
+    }
+
+    return 0;
+}
+
+static void vub_disconnect(DeviceState *dev)
+{
+    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+    VHostUserBase *vub = VHOST_USER_BASE(vdev);
+
+    if (!vub->connected) {
+        return;
+    }
+    vub->connected = false;
+
+    if (vhost_dev_is_started(&vub->vhost_dev)) {
+        vub_stop(vdev);
+    }
+}
+
+static void vub_event(void *opaque, QEMUChrEvent event)
+{
+    DeviceState *dev = opaque;
+    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+    VHostUserBase *vub = VHOST_USER_BASE(vdev);
+
+    switch (event) {
+    case CHR_EVENT_OPENED:
+        if (vub_connect(dev) < 0) {
+            qemu_chr_fe_disconnect(&vub->chardev);
+            return;
+        }
+        break;
+    case CHR_EVENT_CLOSED:
+        vub_disconnect(dev);
+        break;
+    case CHR_EVENT_BREAK:
+    case CHR_EVENT_MUX_IN:
+    case CHR_EVENT_MUX_OUT:
+        /* Ignore */
+        break;
+    }
+}
+
+static void vub_device_realize(DeviceState *dev, Error **errp)
+{
+    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+    VHostUserBase *vub = VHOST_USER_BASE(dev);
+    int ret;
+
+    if (!vub->chardev.chr) {
+        error_setg(errp, "vhost-user-device: missing chardev");
+        return;
+    }
+
+    if (!vub->virtio_id) {
+        error_setg(errp, "vhost-user-device: need to define device id");
+        return;
+    }
+
+    if (!vub->num_vqs) {
+        vub->num_vqs = 1; /* reasonable default? */
+    }
+
+    if (!vhost_user_init(&vub->vhost_user, &vub->chardev, errp)) {
+        return;
+    }
+
+    virtio_init(vdev, vub->virtio_id, 0);
+
+    /*
+     * Disable guest notifiers, by default all notifications will be via the
+     * asynchronous vhost-user socket.
+     */
+    vdev->use_guest_notifier_mask = false;
+
+    /* Allocate queues */
+    vub->vqs = g_ptr_array_sized_new(vub->num_vqs);
+    for (int i = 0; i < vub->num_vqs; i++) {
+        g_ptr_array_add(vub->vqs,
+                        virtio_add_queue(vdev, 4, vub_handle_output));
+    }
+
+    vub->vhost_dev.nvqs = vub->num_vqs;
+    vub->vhost_dev.vqs = g_new0(struct vhost_virtqueue, vub->vhost_dev.nvqs);
+
+    /* connect to backend */
+    ret = vhost_dev_init(&vub->vhost_dev, &vub->vhost_user,
+                         VHOST_BACKEND_TYPE_USER, 0, errp);
+
+    if (ret < 0) {
+        do_vhost_user_cleanup(vdev, vub);
+    }
+
+    qemu_chr_fe_set_handlers(&vub->chardev, NULL, NULL, vub_event, NULL,
+                             dev, NULL, true);
+}
+
+static void vub_device_unrealize(DeviceState *dev)
+{
+    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+    VHostUserBase *vub = VHOST_USER_BASE(dev);
+    struct vhost_virtqueue *vhost_vqs = vub->vhost_dev.vqs;
+
+    /* This will stop vhost backend if appropriate. */
+    vub_set_status(vdev, 0);
+    vhost_dev_cleanup(&vub->vhost_dev);
+    g_free(vhost_vqs);
+    do_vhost_user_cleanup(vdev, vub);
+}
+
+static void vub_class_init(ObjectClass *klass, void *data)
+{
+    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
+
+    vdc->realize = vub_device_realize;
+    vdc->unrealize = vub_device_unrealize;
+    vdc->get_features = vub_get_features;
+    vdc->set_status = vub_set_status;
+}
+
+static const TypeInfo vub_info = {
+    .name = TYPE_VHOST_USER_BASE,
+    .parent = TYPE_VIRTIO_DEVICE,
+    .instance_size = sizeof(VHostUserBase),
+    .class_init = vub_class_init,
+    .class_size = sizeof(VHostUserBaseClass),
+    .abstract = true
+};
+
+
+/*
+ * The following is a concrete implementation of the base class which
+ * allows the user to define the key parameters via the command line.
+ */
+
+static const VMStateDescription vud_vmstate = {
+    .name = "vhost-user-device",
+    .unmigratable = 1,
+};
+
+static Property vud_properties[] = {
+    DEFINE_PROP_CHR("chardev", VHostUserBase, chardev),
+    DEFINE_PROP_UINT16("virtio-id", VHostUserBase, virtio_id, 0),
+    DEFINE_PROP_UINT32("num_vqs", VHostUserBase, num_vqs, 1),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void vud_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    device_class_set_props(dc, vud_properties);
+    dc->vmsd = &vud_vmstate;
+    set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
+}
+
+static const TypeInfo vud_info = {
+    .name = TYPE_VHOST_USER_DEVICE,
+    .parent = TYPE_VHOST_USER_BASE,
+    .instance_size = sizeof(VHostUserBase),
+    .class_init = vud_class_init,
+    .class_size = sizeof(VHostUserBaseClass),
+};
+
+static void vu_register_types(void)
+{
+    type_register_static(&vub_info);
+    type_register_static(&vud_info);
+}
+
+type_init(vu_register_types)
diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build
index f32b22f61b..b87c5523e7 100644
--- a/hw/virtio/meson.build
+++ b/hw/virtio/meson.build
@@ -15,7 +15,9 @@ if have_vhost
   softmmu_virtio_ss.add(files('vhost.c'))
   specific_virtio_ss.add(files('vhost-backend.c', 'vhost-iova-tree.c'))
   if have_vhost_user
+    # fixme - this really should be generic
     specific_virtio_ss.add(files('vhost-user.c'))
+    softmmu_virtio_ss.add(files('vhost-user-device.c'))
   endif
   if have_vhost_vdpa
     specific_virtio_ss.add(files('vhost-vdpa.c', 'vhost-shadow-virtqueue.c'))
-- 
2.39.2



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Virtio-fs] [PATCH v3 07/20] virtio: add vhost-user-base and a generic vhost-user-device
@ 2023-07-10 15:35   ` Alex Bennée
  0 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

In theory we shouldn't need to repeat so much boilerplate to support
vhost-user backends. This provides a generic vhost-user-base QOM
object and a derived vhost-user-device for which the user needs to
provide the few bits of information that aren't currently provided by
the vhost-user protocol. This should provide a baseline implementation
from which the other vhost-user stub can specialise.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>

---
v2
  - split into vub and vud
---
 include/hw/virtio/vhost-user-device.h |  45 ++++
 hw/virtio/vhost-user-device.c         | 324 ++++++++++++++++++++++++++
 hw/virtio/meson.build                 |   2 +
 3 files changed, 371 insertions(+)
 create mode 100644 include/hw/virtio/vhost-user-device.h
 create mode 100644 hw/virtio/vhost-user-device.c

diff --git a/include/hw/virtio/vhost-user-device.h b/include/hw/virtio/vhost-user-device.h
new file mode 100644
index 0000000000..9105011e25
--- /dev/null
+++ b/include/hw/virtio/vhost-user-device.h
@@ -0,0 +1,45 @@
+/*
+ * Vhost-user generic virtio device
+ *
+ * Copyright (c) 2023 Linaro Ltd
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef QEMU_VHOST_USER_DEVICE_H
+#define QEMU_VHOST_USER_DEVICE_H
+
+#include "hw/virtio/vhost.h"
+#include "hw/virtio/vhost-user.h"
+
+#define TYPE_VHOST_USER_BASE "vhost-user-base"
+
+OBJECT_DECLARE_TYPE(VHostUserBase, VHostUserBaseClass, VHOST_USER_BASE)
+
+struct VHostUserBase {
+    VirtIODevice parent;
+    /* Properties */
+    CharBackend chardev;
+    uint16_t virtio_id;
+    uint32_t num_vqs;
+    /* State tracking */
+    VhostUserState vhost_user;
+    struct vhost_virtqueue *vhost_vq;
+    struct vhost_dev vhost_dev;
+    GPtrArray *vqs;
+    bool connected;
+};
+
+    /* needed so we can use the base realize after specialisation
+       tweaks */
+struct VHostUserBaseClass {
+    /*< private >*/
+    VirtioDeviceClass parent_class;
+    /*< public >*/
+    DeviceRealize parent_realize;
+};
+
+/* shared for the benefit of the derived pci class */
+#define TYPE_VHOST_USER_DEVICE "vhost-user-device"
+
+#endif /* QEMU_VHOST_USER_DEVICE_H */
diff --git a/hw/virtio/vhost-user-device.c b/hw/virtio/vhost-user-device.c
new file mode 100644
index 0000000000..b0239fa033
--- /dev/null
+++ b/hw/virtio/vhost-user-device.c
@@ -0,0 +1,324 @@
+/*
+ * Generic vhost-user stub. This can be used to connect to any
+ * vhost-user backend. All configuration details must be handled by
+ * the vhost-user daemon itself
+ *
+ * Copyright (c) 2023 Linaro Ltd
+ * Author: Alex Bennée <alex.bennee@linaro.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/qdev-properties.h"
+#include "hw/virtio/virtio-bus.h"
+#include "hw/virtio/vhost-user-device.h"
+#include "qemu/error-report.h"
+
+static void vub_start(VirtIODevice *vdev)
+{
+    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
+    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
+    VHostUserBase *vub = VHOST_USER_BASE(vdev);
+    int ret, i;
+
+    if (!k->set_guest_notifiers) {
+        error_report("binding does not support guest notifiers");
+        return;
+    }
+
+    ret = vhost_dev_enable_notifiers(&vub->vhost_dev, vdev);
+    if (ret < 0) {
+        error_report("Error enabling host notifiers: %d", -ret);
+        return;
+    }
+
+    ret = k->set_guest_notifiers(qbus->parent, vub->vhost_dev.nvqs, true);
+    if (ret < 0) {
+        error_report("Error binding guest notifier: %d", -ret);
+        goto err_host_notifiers;
+    }
+
+    vub->vhost_dev.acked_features = vdev->guest_features;
+
+    ret = vhost_dev_start(&vub->vhost_dev, vdev, true);
+    if (ret < 0) {
+        error_report("Error starting vhost-user-device: %d", -ret);
+        goto err_guest_notifiers;
+    }
+
+    /*
+     * guest_notifier_mask/pending not used yet, so just unmask
+     * everything here. virtio-pci will do the right thing by
+     * enabling/disabling irqfd.
+     */
+    for (i = 0; i < vub->vhost_dev.nvqs; i++) {
+        vhost_virtqueue_mask(&vub->vhost_dev, vdev, i, false);
+    }
+
+    return;
+
+err_guest_notifiers:
+    k->set_guest_notifiers(qbus->parent, vub->vhost_dev.nvqs, false);
+err_host_notifiers:
+    vhost_dev_disable_notifiers(&vub->vhost_dev, vdev);
+}
+
+static void vub_stop(VirtIODevice *vdev)
+{
+    VHostUserBase *vub = VHOST_USER_BASE(vdev);
+    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
+    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
+    int ret;
+
+    if (!k->set_guest_notifiers) {
+        return;
+    }
+
+    vhost_dev_stop(&vub->vhost_dev, vdev, true);
+
+    ret = k->set_guest_notifiers(qbus->parent, vub->vhost_dev.nvqs, false);
+    if (ret < 0) {
+        error_report("vhost guest notifier cleanup failed: %d", ret);
+        return;
+    }
+
+    vhost_dev_disable_notifiers(&vub->vhost_dev, vdev);
+}
+
+static void vub_set_status(VirtIODevice *vdev, uint8_t status)
+{
+    VHostUserBase *vub = VHOST_USER_BASE(vdev);
+    bool should_start = virtio_device_should_start(vdev, status);
+
+    if (vhost_dev_is_started(&vub->vhost_dev) == should_start) {
+        return;
+    }
+
+    if (should_start) {
+        vub_start(vdev);
+    } else {
+        vub_stop(vdev);
+    }
+}
+
+/*
+ * For an implementation where everything is delegated to the backend
+ * we don't do anything other than return the full feature set offered
+ * by the daemon (module the reserved feature bit).
+ */
+static uint64_t vub_get_features(VirtIODevice *vdev,
+                                 uint64_t requested_features, Error **errp)
+{
+    VHostUserBase *vub = VHOST_USER_BASE(vdev);
+    /* This should be set when the vhost connection initialises */
+    g_assert(vub->vhost_dev.features);
+    return vub->vhost_dev.features & ~(1ULL << VHOST_USER_F_PROTOCOL_FEATURES);
+}
+
+static void vub_handle_output(VirtIODevice *vdev, VirtQueue *vq)
+{
+    /*
+     * Not normally called; it's the daemon that handles the queue;
+     * however virtio's cleanup path can call this.
+     */
+}
+
+static void do_vhost_user_cleanup(VirtIODevice *vdev, VHostUserBase *vub)
+{
+    vhost_user_cleanup(&vub->vhost_user);
+
+    for (int i = 0; i < vub->num_vqs; i++) {
+        VirtQueue *vq = g_ptr_array_index(vub->vqs, i);
+        virtio_delete_queue(vq);
+    }
+
+    virtio_cleanup(vdev);
+}
+
+static int vub_connect(DeviceState *dev)
+{
+    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+    VHostUserBase *vub = VHOST_USER_BASE(vdev);
+
+    if (vub->connected) {
+        return 0;
+    }
+    vub->connected = true;
+
+    /* restore vhost state */
+    if (virtio_device_started(vdev, vdev->status)) {
+        vub_start(vdev);
+    }
+
+    return 0;
+}
+
+static void vub_disconnect(DeviceState *dev)
+{
+    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+    VHostUserBase *vub = VHOST_USER_BASE(vdev);
+
+    if (!vub->connected) {
+        return;
+    }
+    vub->connected = false;
+
+    if (vhost_dev_is_started(&vub->vhost_dev)) {
+        vub_stop(vdev);
+    }
+}
+
+static void vub_event(void *opaque, QEMUChrEvent event)
+{
+    DeviceState *dev = opaque;
+    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+    VHostUserBase *vub = VHOST_USER_BASE(vdev);
+
+    switch (event) {
+    case CHR_EVENT_OPENED:
+        if (vub_connect(dev) < 0) {
+            qemu_chr_fe_disconnect(&vub->chardev);
+            return;
+        }
+        break;
+    case CHR_EVENT_CLOSED:
+        vub_disconnect(dev);
+        break;
+    case CHR_EVENT_BREAK:
+    case CHR_EVENT_MUX_IN:
+    case CHR_EVENT_MUX_OUT:
+        /* Ignore */
+        break;
+    }
+}
+
+static void vub_device_realize(DeviceState *dev, Error **errp)
+{
+    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+    VHostUserBase *vub = VHOST_USER_BASE(dev);
+    int ret;
+
+    if (!vub->chardev.chr) {
+        error_setg(errp, "vhost-user-device: missing chardev");
+        return;
+    }
+
+    if (!vub->virtio_id) {
+        error_setg(errp, "vhost-user-device: need to define device id");
+        return;
+    }
+
+    if (!vub->num_vqs) {
+        vub->num_vqs = 1; /* reasonable default? */
+    }
+
+    if (!vhost_user_init(&vub->vhost_user, &vub->chardev, errp)) {
+        return;
+    }
+
+    virtio_init(vdev, vub->virtio_id, 0);
+
+    /*
+     * Disable guest notifiers, by default all notifications will be via the
+     * asynchronous vhost-user socket.
+     */
+    vdev->use_guest_notifier_mask = false;
+
+    /* Allocate queues */
+    vub->vqs = g_ptr_array_sized_new(vub->num_vqs);
+    for (int i = 0; i < vub->num_vqs; i++) {
+        g_ptr_array_add(vub->vqs,
+                        virtio_add_queue(vdev, 4, vub_handle_output));
+    }
+
+    vub->vhost_dev.nvqs = vub->num_vqs;
+    vub->vhost_dev.vqs = g_new0(struct vhost_virtqueue, vub->vhost_dev.nvqs);
+
+    /* connect to backend */
+    ret = vhost_dev_init(&vub->vhost_dev, &vub->vhost_user,
+                         VHOST_BACKEND_TYPE_USER, 0, errp);
+
+    if (ret < 0) {
+        do_vhost_user_cleanup(vdev, vub);
+    }
+
+    qemu_chr_fe_set_handlers(&vub->chardev, NULL, NULL, vub_event, NULL,
+                             dev, NULL, true);
+}
+
+static void vub_device_unrealize(DeviceState *dev)
+{
+    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+    VHostUserBase *vub = VHOST_USER_BASE(dev);
+    struct vhost_virtqueue *vhost_vqs = vub->vhost_dev.vqs;
+
+    /* This will stop vhost backend if appropriate. */
+    vub_set_status(vdev, 0);
+    vhost_dev_cleanup(&vub->vhost_dev);
+    g_free(vhost_vqs);
+    do_vhost_user_cleanup(vdev, vub);
+}
+
+static void vub_class_init(ObjectClass *klass, void *data)
+{
+    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
+
+    vdc->realize = vub_device_realize;
+    vdc->unrealize = vub_device_unrealize;
+    vdc->get_features = vub_get_features;
+    vdc->set_status = vub_set_status;
+}
+
+static const TypeInfo vub_info = {
+    .name = TYPE_VHOST_USER_BASE,
+    .parent = TYPE_VIRTIO_DEVICE,
+    .instance_size = sizeof(VHostUserBase),
+    .class_init = vub_class_init,
+    .class_size = sizeof(VHostUserBaseClass),
+    .abstract = true
+};
+
+
+/*
+ * The following is a concrete implementation of the base class which
+ * allows the user to define the key parameters via the command line.
+ */
+
+static const VMStateDescription vud_vmstate = {
+    .name = "vhost-user-device",
+    .unmigratable = 1,
+};
+
+static Property vud_properties[] = {
+    DEFINE_PROP_CHR("chardev", VHostUserBase, chardev),
+    DEFINE_PROP_UINT16("virtio-id", VHostUserBase, virtio_id, 0),
+    DEFINE_PROP_UINT32("num_vqs", VHostUserBase, num_vqs, 1),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void vud_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    device_class_set_props(dc, vud_properties);
+    dc->vmsd = &vud_vmstate;
+    set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
+}
+
+static const TypeInfo vud_info = {
+    .name = TYPE_VHOST_USER_DEVICE,
+    .parent = TYPE_VHOST_USER_BASE,
+    .instance_size = sizeof(VHostUserBase),
+    .class_init = vud_class_init,
+    .class_size = sizeof(VHostUserBaseClass),
+};
+
+static void vu_register_types(void)
+{
+    type_register_static(&vub_info);
+    type_register_static(&vud_info);
+}
+
+type_init(vu_register_types)
diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build
index f32b22f61b..b87c5523e7 100644
--- a/hw/virtio/meson.build
+++ b/hw/virtio/meson.build
@@ -15,7 +15,9 @@ if have_vhost
   softmmu_virtio_ss.add(files('vhost.c'))
   specific_virtio_ss.add(files('vhost-backend.c', 'vhost-iova-tree.c'))
   if have_vhost_user
+    # fixme - this really should be generic
     specific_virtio_ss.add(files('vhost-user.c'))
+    softmmu_virtio_ss.add(files('vhost-user-device.c'))
   endif
   if have_vhost_vdpa
     specific_virtio_ss.add(files('vhost-vdpa.c', 'vhost-shadow-virtqueue.c'))
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v3 08/20] virtio: add PCI stub for vhost-user-device
  2023-07-10 15:35 ` [Virtio-fs] " Alex Bennée
@ 2023-07-10 15:35   ` Alex Bennée
  -1 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

This is all pretty much boilerplate.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Tested-by: Erik Schilling <erik.schilling@linaro.org>
---
 hw/virtio/vhost-user-device-pci.c | 71 +++++++++++++++++++++++++++++++
 hw/virtio/meson.build             |  1 +
 2 files changed, 72 insertions(+)
 create mode 100644 hw/virtio/vhost-user-device-pci.c

diff --git a/hw/virtio/vhost-user-device-pci.c b/hw/virtio/vhost-user-device-pci.c
new file mode 100644
index 0000000000..41f9b7905b
--- /dev/null
+++ b/hw/virtio/vhost-user-device-pci.c
@@ -0,0 +1,71 @@
+/*
+ * Vhost-user generic virtio device PCI glue
+ *
+ * Copyright (c) 2023 Linaro Ltd
+ * Author: Alex Bennée <alex.bennee@linaro.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "hw/qdev-properties.h"
+#include "hw/virtio/vhost-user-device.h"
+#include "hw/virtio/virtio-pci.h"
+
+struct VHostUserDevicePCI {
+    VirtIOPCIProxy parent_obj;
+    VHostUserBase vub;
+};
+
+typedef struct VHostUserDevicePCI VHostUserDevicePCI;
+
+#define TYPE_VHOST_USER_DEVICE_PCI "vhost-user-device-pci-base"
+
+DECLARE_INSTANCE_CHECKER(VHostUserDevicePCI,
+                         VHOST_USER_DEVICE_PCI,
+                         TYPE_VHOST_USER_DEVICE_PCI)
+
+static void vhost_user_device_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
+{
+    VHostUserDevicePCI *dev = VHOST_USER_DEVICE_PCI(vpci_dev);
+    DeviceState *vdev = DEVICE(&dev->vub);
+
+    vpci_dev->nvectors = 1;
+    qdev_realize(vdev, BUS(&vpci_dev->bus), errp);
+}
+
+static void vhost_user_device_pci_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
+    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
+    k->realize = vhost_user_device_pci_realize;
+    set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
+    pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+    pcidev_k->device_id = 0; /* Set by virtio-pci based on virtio id */
+    pcidev_k->revision = 0x00;
+    pcidev_k->class_id = PCI_CLASS_COMMUNICATION_OTHER;
+}
+
+static void vhost_user_device_pci_instance_init(Object *obj)
+{
+    VHostUserDevicePCI *dev = VHOST_USER_DEVICE_PCI(obj);
+
+    virtio_instance_init_common(obj, &dev->vub, sizeof(dev->vub),
+                                TYPE_VHOST_USER_DEVICE);
+}
+
+static const VirtioPCIDeviceTypeInfo vhost_user_device_pci_info = {
+    .base_name = TYPE_VHOST_USER_DEVICE_PCI,
+    .non_transitional_name = "vhost-user-device-pci",
+    .instance_size = sizeof(VHostUserDevicePCI),
+    .instance_init = vhost_user_device_pci_instance_init,
+    .class_init = vhost_user_device_pci_class_init,
+};
+
+static void vhost_user_device_pci_register(void)
+{
+    virtio_pci_types_register(&vhost_user_device_pci_info);
+}
+
+type_init(vhost_user_device_pci_register);
diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build
index b87c5523e7..1e1df77783 100644
--- a/hw/virtio/meson.build
+++ b/hw/virtio/meson.build
@@ -18,6 +18,7 @@ if have_vhost
     # fixme - this really should be generic
     specific_virtio_ss.add(files('vhost-user.c'))
     softmmu_virtio_ss.add(files('vhost-user-device.c'))
+    softmmu_virtio_ss.add(when: 'CONFIG_VIRTIO_PCI', if_true: files('vhost-user-device-pci.c'))
   endif
   if have_vhost_vdpa
     specific_virtio_ss.add(files('vhost-vdpa.c', 'vhost-shadow-virtqueue.c'))
-- 
2.39.2



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Virtio-fs] [PATCH v3 08/20] virtio: add PCI stub for vhost-user-device
@ 2023-07-10 15:35   ` Alex Bennée
  0 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

This is all pretty much boilerplate.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Tested-by: Erik Schilling <erik.schilling@linaro.org>
---
 hw/virtio/vhost-user-device-pci.c | 71 +++++++++++++++++++++++++++++++
 hw/virtio/meson.build             |  1 +
 2 files changed, 72 insertions(+)
 create mode 100644 hw/virtio/vhost-user-device-pci.c

diff --git a/hw/virtio/vhost-user-device-pci.c b/hw/virtio/vhost-user-device-pci.c
new file mode 100644
index 0000000000..41f9b7905b
--- /dev/null
+++ b/hw/virtio/vhost-user-device-pci.c
@@ -0,0 +1,71 @@
+/*
+ * Vhost-user generic virtio device PCI glue
+ *
+ * Copyright (c) 2023 Linaro Ltd
+ * Author: Alex Bennée <alex.bennee@linaro.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "hw/qdev-properties.h"
+#include "hw/virtio/vhost-user-device.h"
+#include "hw/virtio/virtio-pci.h"
+
+struct VHostUserDevicePCI {
+    VirtIOPCIProxy parent_obj;
+    VHostUserBase vub;
+};
+
+typedef struct VHostUserDevicePCI VHostUserDevicePCI;
+
+#define TYPE_VHOST_USER_DEVICE_PCI "vhost-user-device-pci-base"
+
+DECLARE_INSTANCE_CHECKER(VHostUserDevicePCI,
+                         VHOST_USER_DEVICE_PCI,
+                         TYPE_VHOST_USER_DEVICE_PCI)
+
+static void vhost_user_device_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
+{
+    VHostUserDevicePCI *dev = VHOST_USER_DEVICE_PCI(vpci_dev);
+    DeviceState *vdev = DEVICE(&dev->vub);
+
+    vpci_dev->nvectors = 1;
+    qdev_realize(vdev, BUS(&vpci_dev->bus), errp);
+}
+
+static void vhost_user_device_pci_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
+    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
+    k->realize = vhost_user_device_pci_realize;
+    set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
+    pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+    pcidev_k->device_id = 0; /* Set by virtio-pci based on virtio id */
+    pcidev_k->revision = 0x00;
+    pcidev_k->class_id = PCI_CLASS_COMMUNICATION_OTHER;
+}
+
+static void vhost_user_device_pci_instance_init(Object *obj)
+{
+    VHostUserDevicePCI *dev = VHOST_USER_DEVICE_PCI(obj);
+
+    virtio_instance_init_common(obj, &dev->vub, sizeof(dev->vub),
+                                TYPE_VHOST_USER_DEVICE);
+}
+
+static const VirtioPCIDeviceTypeInfo vhost_user_device_pci_info = {
+    .base_name = TYPE_VHOST_USER_DEVICE_PCI,
+    .non_transitional_name = "vhost-user-device-pci",
+    .instance_size = sizeof(VHostUserDevicePCI),
+    .instance_init = vhost_user_device_pci_instance_init,
+    .class_init = vhost_user_device_pci_class_init,
+};
+
+static void vhost_user_device_pci_register(void)
+{
+    virtio_pci_types_register(&vhost_user_device_pci_info);
+}
+
+type_init(vhost_user_device_pci_register);
diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build
index b87c5523e7..1e1df77783 100644
--- a/hw/virtio/meson.build
+++ b/hw/virtio/meson.build
@@ -18,6 +18,7 @@ if have_vhost
     # fixme - this really should be generic
     specific_virtio_ss.add(files('vhost-user.c'))
     softmmu_virtio_ss.add(files('vhost-user-device.c'))
+    softmmu_virtio_ss.add(when: 'CONFIG_VIRTIO_PCI', if_true: files('vhost-user-device-pci.c'))
   endif
   if have_vhost_vdpa
     specific_virtio_ss.add(files('vhost-vdpa.c', 'vhost-shadow-virtqueue.c'))
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v3 09/20] hw/virtio: derive vhost-user-rng from vhost-user-device
  2023-07-10 15:35 ` [Virtio-fs] " Alex Bennée
@ 2023-07-10 15:35   ` Alex Bennée
  -1 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

Now we can take advantage of our new base class and make
vhost-user-rng a much simpler boilerplate wrapper. Also as this
doesn't require any target specific hacks we only need to build the
stubs once.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>

---
v2
  - new derivation layout
  - move directly to softmmu_virtio_ss
---
 include/hw/virtio/vhost-user-rng.h |  11 +-
 hw/virtio/vhost-user-rng.c         | 277 +++--------------------------
 hw/virtio/meson.build              |   7 +-
 3 files changed, 28 insertions(+), 267 deletions(-)

diff --git a/include/hw/virtio/vhost-user-rng.h b/include/hw/virtio/vhost-user-rng.h
index ddd9f01eea..13139c0d9d 100644
--- a/include/hw/virtio/vhost-user-rng.h
+++ b/include/hw/virtio/vhost-user-rng.h
@@ -12,21 +12,14 @@
 #include "hw/virtio/virtio.h"
 #include "hw/virtio/vhost.h"
 #include "hw/virtio/vhost-user.h"
-#include "chardev/char-fe.h"
+#include "hw/virtio/vhost-user-device.h"
 
 #define TYPE_VHOST_USER_RNG "vhost-user-rng"
 OBJECT_DECLARE_SIMPLE_TYPE(VHostUserRNG, VHOST_USER_RNG)
 
 struct VHostUserRNG {
     /*< private >*/
-    VirtIODevice parent;
-    CharBackend chardev;
-    struct vhost_virtqueue *vhost_vq;
-    struct vhost_dev vhost_dev;
-    VhostUserState vhost_user;
-    VirtQueue *req_vq;
-    bool connected;
-
+    VHostUserBase parent;
     /*< public >*/
 };
 
diff --git a/hw/virtio/vhost-user-rng.c b/hw/virtio/vhost-user-rng.c
index efc54cd3fb..71d3991f93 100644
--- a/hw/virtio/vhost-user-rng.c
+++ b/hw/virtio/vhost-user-rng.c
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2021 Mathieu Poirier <mathieu.poirier@linaro.org>
  *
- * Implementation seriously tailored on vhost-user-i2c.c
+ * Simple wrapper of the generic vhost-user-device.
  *
  * SPDX-License-Identifier: GPL-2.0-or-later
  */
@@ -13,281 +13,46 @@
 #include "hw/qdev-properties.h"
 #include "hw/virtio/virtio-bus.h"
 #include "hw/virtio/vhost-user-rng.h"
-#include "qemu/error-report.h"
 #include "standard-headers/linux/virtio_ids.h"
 
-static const int feature_bits[] = {
-    VIRTIO_F_RING_RESET,
-    VHOST_INVALID_FEATURE_BIT
-};
-
-static void vu_rng_start(VirtIODevice *vdev)
-{
-    VHostUserRNG *rng = VHOST_USER_RNG(vdev);
-    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
-    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
-    int ret;
-    int i;
-
-    if (!k->set_guest_notifiers) {
-        error_report("binding does not support guest notifiers");
-        return;
-    }
-
-    ret = vhost_dev_enable_notifiers(&rng->vhost_dev, vdev);
-    if (ret < 0) {
-        error_report("Error enabling host notifiers: %d", -ret);
-        return;
-    }
-
-    ret = k->set_guest_notifiers(qbus->parent, rng->vhost_dev.nvqs, true);
-    if (ret < 0) {
-        error_report("Error binding guest notifier: %d", -ret);
-        goto err_host_notifiers;
-    }
-
-    rng->vhost_dev.acked_features = vdev->guest_features;
-    ret = vhost_dev_start(&rng->vhost_dev, vdev, true);
-    if (ret < 0) {
-        error_report("Error starting vhost-user-rng: %d", -ret);
-        goto err_guest_notifiers;
-    }
-
-    /*
-     * guest_notifier_mask/pending not used yet, so just unmask
-     * everything here. virtio-pci will do the right thing by
-     * enabling/disabling irqfd.
-     */
-    for (i = 0; i < rng->vhost_dev.nvqs; i++) {
-        vhost_virtqueue_mask(&rng->vhost_dev, vdev, i, false);
-    }
-
-    return;
-
-err_guest_notifiers:
-    k->set_guest_notifiers(qbus->parent, rng->vhost_dev.nvqs, false);
-err_host_notifiers:
-    vhost_dev_disable_notifiers(&rng->vhost_dev, vdev);
-}
-
-static void vu_rng_stop(VirtIODevice *vdev)
-{
-    VHostUserRNG *rng = VHOST_USER_RNG(vdev);
-    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
-    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
-    int ret;
-
-    if (!k->set_guest_notifiers) {
-        return;
-    }
-
-    vhost_dev_stop(&rng->vhost_dev, vdev, true);
-
-    ret = k->set_guest_notifiers(qbus->parent, rng->vhost_dev.nvqs, false);
-    if (ret < 0) {
-        error_report("vhost guest notifier cleanup failed: %d", ret);
-        return;
-    }
-
-    vhost_dev_disable_notifiers(&rng->vhost_dev, vdev);
-}
-
-static void vu_rng_set_status(VirtIODevice *vdev, uint8_t status)
-{
-    VHostUserRNG *rng = VHOST_USER_RNG(vdev);
-    bool should_start = virtio_device_should_start(vdev, status);
-
-    if (vhost_dev_is_started(&rng->vhost_dev) == should_start) {
-        return;
-    }
-
-    if (should_start) {
-        vu_rng_start(vdev);
-    } else {
-        vu_rng_stop(vdev);
-    }
-}
-
-static uint64_t vu_rng_get_features(VirtIODevice *vdev,
-                                    uint64_t requested_features, Error **errp)
-{
-    VHostUserRNG *rng = VHOST_USER_RNG(vdev);
-
-    return vhost_get_features(&rng->vhost_dev, feature_bits,
-                              requested_features);
-}
-
-static void vu_rng_handle_output(VirtIODevice *vdev, VirtQueue *vq)
-{
-    /*
-     * Not normally called; it's the daemon that handles the queue;
-     * however virtio's cleanup path can call this.
-     */
-}
-
-static void vu_rng_guest_notifier_mask(VirtIODevice *vdev, int idx, bool mask)
-{
-    VHostUserRNG *rng = VHOST_USER_RNG(vdev);
-
-    vhost_virtqueue_mask(&rng->vhost_dev, vdev, idx, mask);
-}
-
-static bool vu_rng_guest_notifier_pending(VirtIODevice *vdev, int idx)
-{
-    VHostUserRNG *rng = VHOST_USER_RNG(vdev);
-
-    return vhost_virtqueue_pending(&rng->vhost_dev, idx);
-}
-
-static void vu_rng_connect(DeviceState *dev)
-{
-    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
-    VHostUserRNG *rng = VHOST_USER_RNG(vdev);
-
-    if (rng->connected) {
-        return;
-    }
-
-    rng->connected = true;
-
-    /* restore vhost state */
-    if (virtio_device_started(vdev, vdev->status)) {
-        vu_rng_start(vdev);
-    }
-}
-
-static void vu_rng_disconnect(DeviceState *dev)
-{
-    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
-    VHostUserRNG *rng = VHOST_USER_RNG(vdev);
-
-    if (!rng->connected) {
-        return;
-    }
-
-    rng->connected = false;
-
-    if (vhost_dev_is_started(&rng->vhost_dev)) {
-        vu_rng_stop(vdev);
-    }
-}
-
-static void vu_rng_event(void *opaque, QEMUChrEvent event)
-{
-    DeviceState *dev = opaque;
-
-    switch (event) {
-    case CHR_EVENT_OPENED:
-        vu_rng_connect(dev);
-        break;
-    case CHR_EVENT_CLOSED:
-        vu_rng_disconnect(dev);
-        break;
-    case CHR_EVENT_BREAK:
-    case CHR_EVENT_MUX_IN:
-    case CHR_EVENT_MUX_OUT:
-        /* Ignore */
-        break;
-    }
-}
-
-static void vu_rng_device_realize(DeviceState *dev, Error **errp)
-{
-    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
-    VHostUserRNG *rng = VHOST_USER_RNG(dev);
-    int ret;
-
-    if (!rng->chardev.chr) {
-        error_setg(errp, "missing chardev");
-        return;
-    }
-
-    if (!vhost_user_init(&rng->vhost_user, &rng->chardev, errp)) {
-        return;
-    }
-
-    virtio_init(vdev, VIRTIO_ID_RNG, 0);
-
-    rng->req_vq = virtio_add_queue(vdev, 4, vu_rng_handle_output);
-    if (!rng->req_vq) {
-        error_setg_errno(errp, -1, "virtio_add_queue() failed");
-        goto virtio_add_queue_failed;
-    }
-
-    rng->vhost_dev.nvqs = 1;
-    rng->vhost_dev.vqs = g_new0(struct vhost_virtqueue, rng->vhost_dev.nvqs);
-    ret = vhost_dev_init(&rng->vhost_dev, &rng->vhost_user,
-                         VHOST_BACKEND_TYPE_USER, 0, errp);
-    if (ret < 0) {
-        error_setg_errno(errp, -ret, "vhost_dev_init() failed");
-        goto vhost_dev_init_failed;
-    }
-
-    qemu_chr_fe_set_handlers(&rng->chardev, NULL, NULL, vu_rng_event, NULL,
-                             dev, NULL, true);
-
-    return;
-
-vhost_dev_init_failed:
-    g_free(rng->vhost_dev.vqs);
-    virtio_delete_queue(rng->req_vq);
-virtio_add_queue_failed:
-    virtio_cleanup(vdev);
-    vhost_user_cleanup(&rng->vhost_user);
-}
-
-static void vu_rng_device_unrealize(DeviceState *dev)
-{
-    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
-    VHostUserRNG *rng = VHOST_USER_RNG(dev);
-    struct vhost_virtqueue *vhost_vqs = rng->vhost_dev.vqs;
-
-    vu_rng_set_status(vdev, 0);
-
-    vhost_dev_cleanup(&rng->vhost_dev);
-    g_free(vhost_vqs);
-    virtio_delete_queue(rng->req_vq);
-    virtio_cleanup(vdev);
-    vhost_user_cleanup(&rng->vhost_user);
-}
-
-static struct vhost_dev *vu_rng_get_vhost(VirtIODevice *vdev)
-{
-    VHostUserRNG *rng = VHOST_USER_RNG(vdev);
-    return &rng->vhost_dev;
-}
-
 static const VMStateDescription vu_rng_vmstate = {
     .name = "vhost-user-rng",
     .unmigratable = 1,
 };
 
-static Property vu_rng_properties[] = {
-    DEFINE_PROP_CHR("chardev", VHostUserRNG, chardev),
+static Property vrng_properties[] = {
+    DEFINE_PROP_CHR("chardev", VHostUserBase, chardev),
     DEFINE_PROP_END_OF_LIST(),
 };
 
+static void vu_rng_base_realize(DeviceState *dev, Error **errp)
+{
+    VHostUserBase *vub = VHOST_USER_BASE(dev);
+    VHostUserBaseClass *vubs = VHOST_USER_BASE_GET_CLASS(dev);
+
+    /* Fixed for RNG */
+    vub->virtio_id = VIRTIO_ID_RNG;
+    vub->num_vqs = 1;
+
+    vubs->parent_realize(dev, errp);
+}
+
 static void vu_rng_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
+    VHostUserBaseClass *vubc = VHOST_USER_BASE_CLASS(klass);
 
-    device_class_set_props(dc, vu_rng_properties);
     dc->vmsd = &vu_rng_vmstate;
-    set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
+    device_class_set_props(dc, vrng_properties);
+    device_class_set_parent_realize(dc, vu_rng_base_realize,
+                                    &vubc->parent_realize);
 
-    vdc->realize = vu_rng_device_realize;
-    vdc->unrealize = vu_rng_device_unrealize;
-    vdc->get_features = vu_rng_get_features;
-    vdc->set_status = vu_rng_set_status;
-    vdc->guest_notifier_mask = vu_rng_guest_notifier_mask;
-    vdc->guest_notifier_pending = vu_rng_guest_notifier_pending;
-    vdc->get_vhost = vu_rng_get_vhost;
+    set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
 }
 
 static const TypeInfo vu_rng_info = {
     .name = TYPE_VHOST_USER_RNG,
-    .parent = TYPE_VIRTIO_DEVICE,
+    .parent = TYPE_VHOST_USER_BASE,
     .instance_size = sizeof(VHostUserRNG),
     .class_init = vu_rng_class_init,
 };
diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build
index 1e1df77783..fb80587d5b 100644
--- a/hw/virtio/meson.build
+++ b/hw/virtio/meson.build
@@ -7,6 +7,11 @@ softmmu_virtio_ss.add(when: 'CONFIG_VHOST_VSOCK_COMMON', if_true: files('vhost-v
 softmmu_virtio_ss.add(when: 'CONFIG_VIRTIO_IOMMU', if_true: files('virtio-iommu.c'))
 softmmu_virtio_ss.add(when: 'CONFIG_VHOST_VDPA_DEV', if_true: files('vdpa-dev.c'))
 
+# VirtIO stubs which don't need building per-guest
+softmmu_virtio_ss.add(when: 'CONFIG_VHOST_USER_RNG', if_true: files('vhost-user-rng.c'))
+softmmu_virtio_ss.add(when: ['CONFIG_VIRTIO_PCI', 'CONFIG_VHOST_USER_RNG'],
+                      if_true: files('vhost-user-rng-pci.c'))
+
 specific_virtio_ss = ss.source_set()
 specific_virtio_ss.add(files('virtio.c'))
 specific_virtio_ss.add(files('virtio-config-io.c', 'virtio-qmp.c'))
@@ -35,7 +40,6 @@ specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_VSOCK', if_true: files('vhost-us
 specific_virtio_ss.add(when: 'CONFIG_VIRTIO_RNG', if_true: files('virtio-rng.c'))
 specific_virtio_ss.add(when: 'CONFIG_VIRTIO_MEM', if_true: files('virtio-mem.c'))
 specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_I2C', if_true: files('vhost-user-i2c.c'))
-specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_RNG', if_true: files('vhost-user-rng.c'))
 specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_GPIO', if_true: files('vhost-user-gpio.c'))
 specific_virtio_ss.add(when: ['CONFIG_VIRTIO_PCI', 'CONFIG_VHOST_USER_GPIO'], if_true: files('vhost-user-gpio-pci.c'))
 
@@ -45,7 +49,6 @@ virtio_pci_ss.add(when: 'CONFIG_VHOST_USER_VSOCK', if_true: files('vhost-user-vs
 virtio_pci_ss.add(when: 'CONFIG_VHOST_USER_BLK', if_true: files('vhost-user-blk-pci.c'))
 virtio_pci_ss.add(when: 'CONFIG_VHOST_USER_I2C', if_true: files('vhost-user-i2c-pci.c'))
 virtio_pci_ss.add(when: 'CONFIG_VHOST_USER_INPUT', if_true: files('vhost-user-input-pci.c'))
-virtio_pci_ss.add(when: 'CONFIG_VHOST_USER_RNG', if_true: files('vhost-user-rng-pci.c'))
 virtio_pci_ss.add(when: 'CONFIG_VHOST_USER_SCSI', if_true: files('vhost-user-scsi-pci.c'))
 virtio_pci_ss.add(when: 'CONFIG_VHOST_SCSI', if_true: files('vhost-scsi-pci.c'))
 virtio_pci_ss.add(when: 'CONFIG_VHOST_USER_FS', if_true: files('vhost-user-fs-pci.c'))
-- 
2.39.2



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Virtio-fs] [PATCH v3 09/20] hw/virtio: derive vhost-user-rng from vhost-user-device
@ 2023-07-10 15:35   ` Alex Bennée
  0 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

Now we can take advantage of our new base class and make
vhost-user-rng a much simpler boilerplate wrapper. Also as this
doesn't require any target specific hacks we only need to build the
stubs once.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>

---
v2
  - new derivation layout
  - move directly to softmmu_virtio_ss
---
 include/hw/virtio/vhost-user-rng.h |  11 +-
 hw/virtio/vhost-user-rng.c         | 277 +++--------------------------
 hw/virtio/meson.build              |   7 +-
 3 files changed, 28 insertions(+), 267 deletions(-)

diff --git a/include/hw/virtio/vhost-user-rng.h b/include/hw/virtio/vhost-user-rng.h
index ddd9f01eea..13139c0d9d 100644
--- a/include/hw/virtio/vhost-user-rng.h
+++ b/include/hw/virtio/vhost-user-rng.h
@@ -12,21 +12,14 @@
 #include "hw/virtio/virtio.h"
 #include "hw/virtio/vhost.h"
 #include "hw/virtio/vhost-user.h"
-#include "chardev/char-fe.h"
+#include "hw/virtio/vhost-user-device.h"
 
 #define TYPE_VHOST_USER_RNG "vhost-user-rng"
 OBJECT_DECLARE_SIMPLE_TYPE(VHostUserRNG, VHOST_USER_RNG)
 
 struct VHostUserRNG {
     /*< private >*/
-    VirtIODevice parent;
-    CharBackend chardev;
-    struct vhost_virtqueue *vhost_vq;
-    struct vhost_dev vhost_dev;
-    VhostUserState vhost_user;
-    VirtQueue *req_vq;
-    bool connected;
-
+    VHostUserBase parent;
     /*< public >*/
 };
 
diff --git a/hw/virtio/vhost-user-rng.c b/hw/virtio/vhost-user-rng.c
index efc54cd3fb..71d3991f93 100644
--- a/hw/virtio/vhost-user-rng.c
+++ b/hw/virtio/vhost-user-rng.c
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2021 Mathieu Poirier <mathieu.poirier@linaro.org>
  *
- * Implementation seriously tailored on vhost-user-i2c.c
+ * Simple wrapper of the generic vhost-user-device.
  *
  * SPDX-License-Identifier: GPL-2.0-or-later
  */
@@ -13,281 +13,46 @@
 #include "hw/qdev-properties.h"
 #include "hw/virtio/virtio-bus.h"
 #include "hw/virtio/vhost-user-rng.h"
-#include "qemu/error-report.h"
 #include "standard-headers/linux/virtio_ids.h"
 
-static const int feature_bits[] = {
-    VIRTIO_F_RING_RESET,
-    VHOST_INVALID_FEATURE_BIT
-};
-
-static void vu_rng_start(VirtIODevice *vdev)
-{
-    VHostUserRNG *rng = VHOST_USER_RNG(vdev);
-    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
-    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
-    int ret;
-    int i;
-
-    if (!k->set_guest_notifiers) {
-        error_report("binding does not support guest notifiers");
-        return;
-    }
-
-    ret = vhost_dev_enable_notifiers(&rng->vhost_dev, vdev);
-    if (ret < 0) {
-        error_report("Error enabling host notifiers: %d", -ret);
-        return;
-    }
-
-    ret = k->set_guest_notifiers(qbus->parent, rng->vhost_dev.nvqs, true);
-    if (ret < 0) {
-        error_report("Error binding guest notifier: %d", -ret);
-        goto err_host_notifiers;
-    }
-
-    rng->vhost_dev.acked_features = vdev->guest_features;
-    ret = vhost_dev_start(&rng->vhost_dev, vdev, true);
-    if (ret < 0) {
-        error_report("Error starting vhost-user-rng: %d", -ret);
-        goto err_guest_notifiers;
-    }
-
-    /*
-     * guest_notifier_mask/pending not used yet, so just unmask
-     * everything here. virtio-pci will do the right thing by
-     * enabling/disabling irqfd.
-     */
-    for (i = 0; i < rng->vhost_dev.nvqs; i++) {
-        vhost_virtqueue_mask(&rng->vhost_dev, vdev, i, false);
-    }
-
-    return;
-
-err_guest_notifiers:
-    k->set_guest_notifiers(qbus->parent, rng->vhost_dev.nvqs, false);
-err_host_notifiers:
-    vhost_dev_disable_notifiers(&rng->vhost_dev, vdev);
-}
-
-static void vu_rng_stop(VirtIODevice *vdev)
-{
-    VHostUserRNG *rng = VHOST_USER_RNG(vdev);
-    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
-    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
-    int ret;
-
-    if (!k->set_guest_notifiers) {
-        return;
-    }
-
-    vhost_dev_stop(&rng->vhost_dev, vdev, true);
-
-    ret = k->set_guest_notifiers(qbus->parent, rng->vhost_dev.nvqs, false);
-    if (ret < 0) {
-        error_report("vhost guest notifier cleanup failed: %d", ret);
-        return;
-    }
-
-    vhost_dev_disable_notifiers(&rng->vhost_dev, vdev);
-}
-
-static void vu_rng_set_status(VirtIODevice *vdev, uint8_t status)
-{
-    VHostUserRNG *rng = VHOST_USER_RNG(vdev);
-    bool should_start = virtio_device_should_start(vdev, status);
-
-    if (vhost_dev_is_started(&rng->vhost_dev) == should_start) {
-        return;
-    }
-
-    if (should_start) {
-        vu_rng_start(vdev);
-    } else {
-        vu_rng_stop(vdev);
-    }
-}
-
-static uint64_t vu_rng_get_features(VirtIODevice *vdev,
-                                    uint64_t requested_features, Error **errp)
-{
-    VHostUserRNG *rng = VHOST_USER_RNG(vdev);
-
-    return vhost_get_features(&rng->vhost_dev, feature_bits,
-                              requested_features);
-}
-
-static void vu_rng_handle_output(VirtIODevice *vdev, VirtQueue *vq)
-{
-    /*
-     * Not normally called; it's the daemon that handles the queue;
-     * however virtio's cleanup path can call this.
-     */
-}
-
-static void vu_rng_guest_notifier_mask(VirtIODevice *vdev, int idx, bool mask)
-{
-    VHostUserRNG *rng = VHOST_USER_RNG(vdev);
-
-    vhost_virtqueue_mask(&rng->vhost_dev, vdev, idx, mask);
-}
-
-static bool vu_rng_guest_notifier_pending(VirtIODevice *vdev, int idx)
-{
-    VHostUserRNG *rng = VHOST_USER_RNG(vdev);
-
-    return vhost_virtqueue_pending(&rng->vhost_dev, idx);
-}
-
-static void vu_rng_connect(DeviceState *dev)
-{
-    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
-    VHostUserRNG *rng = VHOST_USER_RNG(vdev);
-
-    if (rng->connected) {
-        return;
-    }
-
-    rng->connected = true;
-
-    /* restore vhost state */
-    if (virtio_device_started(vdev, vdev->status)) {
-        vu_rng_start(vdev);
-    }
-}
-
-static void vu_rng_disconnect(DeviceState *dev)
-{
-    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
-    VHostUserRNG *rng = VHOST_USER_RNG(vdev);
-
-    if (!rng->connected) {
-        return;
-    }
-
-    rng->connected = false;
-
-    if (vhost_dev_is_started(&rng->vhost_dev)) {
-        vu_rng_stop(vdev);
-    }
-}
-
-static void vu_rng_event(void *opaque, QEMUChrEvent event)
-{
-    DeviceState *dev = opaque;
-
-    switch (event) {
-    case CHR_EVENT_OPENED:
-        vu_rng_connect(dev);
-        break;
-    case CHR_EVENT_CLOSED:
-        vu_rng_disconnect(dev);
-        break;
-    case CHR_EVENT_BREAK:
-    case CHR_EVENT_MUX_IN:
-    case CHR_EVENT_MUX_OUT:
-        /* Ignore */
-        break;
-    }
-}
-
-static void vu_rng_device_realize(DeviceState *dev, Error **errp)
-{
-    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
-    VHostUserRNG *rng = VHOST_USER_RNG(dev);
-    int ret;
-
-    if (!rng->chardev.chr) {
-        error_setg(errp, "missing chardev");
-        return;
-    }
-
-    if (!vhost_user_init(&rng->vhost_user, &rng->chardev, errp)) {
-        return;
-    }
-
-    virtio_init(vdev, VIRTIO_ID_RNG, 0);
-
-    rng->req_vq = virtio_add_queue(vdev, 4, vu_rng_handle_output);
-    if (!rng->req_vq) {
-        error_setg_errno(errp, -1, "virtio_add_queue() failed");
-        goto virtio_add_queue_failed;
-    }
-
-    rng->vhost_dev.nvqs = 1;
-    rng->vhost_dev.vqs = g_new0(struct vhost_virtqueue, rng->vhost_dev.nvqs);
-    ret = vhost_dev_init(&rng->vhost_dev, &rng->vhost_user,
-                         VHOST_BACKEND_TYPE_USER, 0, errp);
-    if (ret < 0) {
-        error_setg_errno(errp, -ret, "vhost_dev_init() failed");
-        goto vhost_dev_init_failed;
-    }
-
-    qemu_chr_fe_set_handlers(&rng->chardev, NULL, NULL, vu_rng_event, NULL,
-                             dev, NULL, true);
-
-    return;
-
-vhost_dev_init_failed:
-    g_free(rng->vhost_dev.vqs);
-    virtio_delete_queue(rng->req_vq);
-virtio_add_queue_failed:
-    virtio_cleanup(vdev);
-    vhost_user_cleanup(&rng->vhost_user);
-}
-
-static void vu_rng_device_unrealize(DeviceState *dev)
-{
-    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
-    VHostUserRNG *rng = VHOST_USER_RNG(dev);
-    struct vhost_virtqueue *vhost_vqs = rng->vhost_dev.vqs;
-
-    vu_rng_set_status(vdev, 0);
-
-    vhost_dev_cleanup(&rng->vhost_dev);
-    g_free(vhost_vqs);
-    virtio_delete_queue(rng->req_vq);
-    virtio_cleanup(vdev);
-    vhost_user_cleanup(&rng->vhost_user);
-}
-
-static struct vhost_dev *vu_rng_get_vhost(VirtIODevice *vdev)
-{
-    VHostUserRNG *rng = VHOST_USER_RNG(vdev);
-    return &rng->vhost_dev;
-}
-
 static const VMStateDescription vu_rng_vmstate = {
     .name = "vhost-user-rng",
     .unmigratable = 1,
 };
 
-static Property vu_rng_properties[] = {
-    DEFINE_PROP_CHR("chardev", VHostUserRNG, chardev),
+static Property vrng_properties[] = {
+    DEFINE_PROP_CHR("chardev", VHostUserBase, chardev),
     DEFINE_PROP_END_OF_LIST(),
 };
 
+static void vu_rng_base_realize(DeviceState *dev, Error **errp)
+{
+    VHostUserBase *vub = VHOST_USER_BASE(dev);
+    VHostUserBaseClass *vubs = VHOST_USER_BASE_GET_CLASS(dev);
+
+    /* Fixed for RNG */
+    vub->virtio_id = VIRTIO_ID_RNG;
+    vub->num_vqs = 1;
+
+    vubs->parent_realize(dev, errp);
+}
+
 static void vu_rng_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
+    VHostUserBaseClass *vubc = VHOST_USER_BASE_CLASS(klass);
 
-    device_class_set_props(dc, vu_rng_properties);
     dc->vmsd = &vu_rng_vmstate;
-    set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
+    device_class_set_props(dc, vrng_properties);
+    device_class_set_parent_realize(dc, vu_rng_base_realize,
+                                    &vubc->parent_realize);
 
-    vdc->realize = vu_rng_device_realize;
-    vdc->unrealize = vu_rng_device_unrealize;
-    vdc->get_features = vu_rng_get_features;
-    vdc->set_status = vu_rng_set_status;
-    vdc->guest_notifier_mask = vu_rng_guest_notifier_mask;
-    vdc->guest_notifier_pending = vu_rng_guest_notifier_pending;
-    vdc->get_vhost = vu_rng_get_vhost;
+    set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
 }
 
 static const TypeInfo vu_rng_info = {
     .name = TYPE_VHOST_USER_RNG,
-    .parent = TYPE_VIRTIO_DEVICE,
+    .parent = TYPE_VHOST_USER_BASE,
     .instance_size = sizeof(VHostUserRNG),
     .class_init = vu_rng_class_init,
 };
diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build
index 1e1df77783..fb80587d5b 100644
--- a/hw/virtio/meson.build
+++ b/hw/virtio/meson.build
@@ -7,6 +7,11 @@ softmmu_virtio_ss.add(when: 'CONFIG_VHOST_VSOCK_COMMON', if_true: files('vhost-v
 softmmu_virtio_ss.add(when: 'CONFIG_VIRTIO_IOMMU', if_true: files('virtio-iommu.c'))
 softmmu_virtio_ss.add(when: 'CONFIG_VHOST_VDPA_DEV', if_true: files('vdpa-dev.c'))
 
+# VirtIO stubs which don't need building per-guest
+softmmu_virtio_ss.add(when: 'CONFIG_VHOST_USER_RNG', if_true: files('vhost-user-rng.c'))
+softmmu_virtio_ss.add(when: ['CONFIG_VIRTIO_PCI', 'CONFIG_VHOST_USER_RNG'],
+                      if_true: files('vhost-user-rng-pci.c'))
+
 specific_virtio_ss = ss.source_set()
 specific_virtio_ss.add(files('virtio.c'))
 specific_virtio_ss.add(files('virtio-config-io.c', 'virtio-qmp.c'))
@@ -35,7 +40,6 @@ specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_VSOCK', if_true: files('vhost-us
 specific_virtio_ss.add(when: 'CONFIG_VIRTIO_RNG', if_true: files('virtio-rng.c'))
 specific_virtio_ss.add(when: 'CONFIG_VIRTIO_MEM', if_true: files('virtio-mem.c'))
 specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_I2C', if_true: files('vhost-user-i2c.c'))
-specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_RNG', if_true: files('vhost-user-rng.c'))
 specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_GPIO', if_true: files('vhost-user-gpio.c'))
 specific_virtio_ss.add(when: ['CONFIG_VIRTIO_PCI', 'CONFIG_VHOST_USER_GPIO'], if_true: files('vhost-user-gpio-pci.c'))
 
@@ -45,7 +49,6 @@ virtio_pci_ss.add(when: 'CONFIG_VHOST_USER_VSOCK', if_true: files('vhost-user-vs
 virtio_pci_ss.add(when: 'CONFIG_VHOST_USER_BLK', if_true: files('vhost-user-blk-pci.c'))
 virtio_pci_ss.add(when: 'CONFIG_VHOST_USER_I2C', if_true: files('vhost-user-i2c-pci.c'))
 virtio_pci_ss.add(when: 'CONFIG_VHOST_USER_INPUT', if_true: files('vhost-user-input-pci.c'))
-virtio_pci_ss.add(when: 'CONFIG_VHOST_USER_RNG', if_true: files('vhost-user-rng-pci.c'))
 virtio_pci_ss.add(when: 'CONFIG_VHOST_USER_SCSI', if_true: files('vhost-user-scsi-pci.c'))
 virtio_pci_ss.add(when: 'CONFIG_VHOST_SCSI', if_true: files('vhost-scsi-pci.c'))
 virtio_pci_ss.add(when: 'CONFIG_VHOST_USER_FS', if_true: files('vhost-user-fs-pci.c'))
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v3 10/20] hw/virtio: add config support to vhost-user-device
  2023-07-10 15:35 ` [Virtio-fs] " Alex Bennée
@ 2023-07-10 15:35   ` Alex Bennée
  -1 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

To use the generic device the user will need to provide the config
region size via the command line. We also add a notifier so the guest
can be pinged if the remote daemon updates the config.

With these changes:

  -device vhost-user-device-pci,virtio-id=41,num_vqs=2,config_size=8

is equivalent to:

  -device vhost-user-gpio-pci

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
 include/hw/virtio/vhost-user-device.h |  1 +
 hw/virtio/vhost-user-device.c         | 58 ++++++++++++++++++++++++++-
 2 files changed, 58 insertions(+), 1 deletion(-)

diff --git a/include/hw/virtio/vhost-user-device.h b/include/hw/virtio/vhost-user-device.h
index 9105011e25..3ddf88a146 100644
--- a/include/hw/virtio/vhost-user-device.h
+++ b/include/hw/virtio/vhost-user-device.h
@@ -22,6 +22,7 @@ struct VHostUserBase {
     CharBackend chardev;
     uint16_t virtio_id;
     uint32_t num_vqs;
+    uint32_t config_size;
     /* State tracking */
     VhostUserState vhost_user;
     struct vhost_virtqueue *vhost_vq;
diff --git a/hw/virtio/vhost-user-device.c b/hw/virtio/vhost-user-device.c
index b0239fa033..2b028cae08 100644
--- a/hw/virtio/vhost-user-device.c
+++ b/hw/virtio/vhost-user-device.c
@@ -117,6 +117,42 @@ static uint64_t vub_get_features(VirtIODevice *vdev,
     return vub->vhost_dev.features & ~(1ULL << VHOST_USER_F_PROTOCOL_FEATURES);
 }
 
+/*
+ * To handle VirtIO config we need to know the size of the config
+ * space. We don't cache the config but re-fetch it from the guest
+ * every time in case something has changed.
+ */
+static void vub_get_config(VirtIODevice *vdev, uint8_t *config)
+{
+    VHostUserBase *vub = VHOST_USER_BASE(vdev);
+    Error *local_err = NULL;
+
+    /*
+     * There will have been a warning during vhost_dev_init, but lets
+     * assert here as nothing will go right now.
+     */
+    g_assert(vub->config_size && vub->vhost_user.supports_config == true);
+
+    if (vhost_dev_get_config(&vub->vhost_dev, config,
+                             vub->config_size, &local_err)) {
+        error_report_err(local_err);
+    }
+}
+
+/*
+ * When the daemon signals an update to the config we just need to
+ * signal the guest as we re-read the config on demand above.
+ */
+static int vub_config_notifier(struct vhost_dev *dev)
+{
+    virtio_notify_config(dev->vdev);
+    return 0;
+}
+
+const VhostDevConfigOps vub_config_ops = {
+    .vhost_dev_config_notifier = vub_config_notifier,
+};
+
 static void vub_handle_output(VirtIODevice *vdev, VirtQueue *vq)
 {
     /*
@@ -141,12 +177,21 @@ static int vub_connect(DeviceState *dev)
 {
     VirtIODevice *vdev = VIRTIO_DEVICE(dev);
     VHostUserBase *vub = VHOST_USER_BASE(vdev);
+    struct vhost_dev *vhost_dev = &vub->vhost_dev;
 
     if (vub->connected) {
         return 0;
     }
     vub->connected = true;
 
+    /*
+     * If we support VHOST_USER_GET_CONFIG we must enable the notifier
+     * so we can ping the guest when it updates.
+     */
+    if (vub->vhost_user.supports_config) {
+        vhost_dev_set_config_notifier(vhost_dev, &vub_config_ops);
+    }
+
     /* restore vhost state */
     if (virtio_device_started(vdev, vdev->status)) {
         vub_start(vdev);
@@ -214,11 +259,20 @@ static void vub_device_realize(DeviceState *dev, Error **errp)
         vub->num_vqs = 1; /* reasonable default? */
     }
 
+    /*
+     * We can't handle config requests unless we know the size of the
+     * config region, specialisations of the vhost-user-device will be
+     * able to set this.
+     */
+    if (vub->config_size) {
+        vub->vhost_user.supports_config = true;
+    }
+
     if (!vhost_user_init(&vub->vhost_user, &vub->chardev, errp)) {
         return;
     }
 
-    virtio_init(vdev, vub->virtio_id, 0);
+    virtio_init(vdev, vub->virtio_id, vub->config_size);
 
     /*
      * Disable guest notifiers, by default all notifications will be via the
@@ -268,6 +322,7 @@ static void vub_class_init(ObjectClass *klass, void *data)
     vdc->realize = vub_device_realize;
     vdc->unrealize = vub_device_unrealize;
     vdc->get_features = vub_get_features;
+    vdc->get_config = vub_get_config;
     vdc->set_status = vub_set_status;
 }
 
@@ -295,6 +350,7 @@ static Property vud_properties[] = {
     DEFINE_PROP_CHR("chardev", VHostUserBase, chardev),
     DEFINE_PROP_UINT16("virtio-id", VHostUserBase, virtio_id, 0),
     DEFINE_PROP_UINT32("num_vqs", VHostUserBase, num_vqs, 1),
+    DEFINE_PROP_UINT32("config_size", VHostUserBase, config_size, 0),
     DEFINE_PROP_END_OF_LIST(),
 };
 
-- 
2.39.2



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Virtio-fs] [PATCH v3 10/20] hw/virtio: add config support to vhost-user-device
@ 2023-07-10 15:35   ` Alex Bennée
  0 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

To use the generic device the user will need to provide the config
region size via the command line. We also add a notifier so the guest
can be pinged if the remote daemon updates the config.

With these changes:

  -device vhost-user-device-pci,virtio-id=41,num_vqs=2,config_size=8

is equivalent to:

  -device vhost-user-gpio-pci

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
 include/hw/virtio/vhost-user-device.h |  1 +
 hw/virtio/vhost-user-device.c         | 58 ++++++++++++++++++++++++++-
 2 files changed, 58 insertions(+), 1 deletion(-)

diff --git a/include/hw/virtio/vhost-user-device.h b/include/hw/virtio/vhost-user-device.h
index 9105011e25..3ddf88a146 100644
--- a/include/hw/virtio/vhost-user-device.h
+++ b/include/hw/virtio/vhost-user-device.h
@@ -22,6 +22,7 @@ struct VHostUserBase {
     CharBackend chardev;
     uint16_t virtio_id;
     uint32_t num_vqs;
+    uint32_t config_size;
     /* State tracking */
     VhostUserState vhost_user;
     struct vhost_virtqueue *vhost_vq;
diff --git a/hw/virtio/vhost-user-device.c b/hw/virtio/vhost-user-device.c
index b0239fa033..2b028cae08 100644
--- a/hw/virtio/vhost-user-device.c
+++ b/hw/virtio/vhost-user-device.c
@@ -117,6 +117,42 @@ static uint64_t vub_get_features(VirtIODevice *vdev,
     return vub->vhost_dev.features & ~(1ULL << VHOST_USER_F_PROTOCOL_FEATURES);
 }
 
+/*
+ * To handle VirtIO config we need to know the size of the config
+ * space. We don't cache the config but re-fetch it from the guest
+ * every time in case something has changed.
+ */
+static void vub_get_config(VirtIODevice *vdev, uint8_t *config)
+{
+    VHostUserBase *vub = VHOST_USER_BASE(vdev);
+    Error *local_err = NULL;
+
+    /*
+     * There will have been a warning during vhost_dev_init, but lets
+     * assert here as nothing will go right now.
+     */
+    g_assert(vub->config_size && vub->vhost_user.supports_config == true);
+
+    if (vhost_dev_get_config(&vub->vhost_dev, config,
+                             vub->config_size, &local_err)) {
+        error_report_err(local_err);
+    }
+}
+
+/*
+ * When the daemon signals an update to the config we just need to
+ * signal the guest as we re-read the config on demand above.
+ */
+static int vub_config_notifier(struct vhost_dev *dev)
+{
+    virtio_notify_config(dev->vdev);
+    return 0;
+}
+
+const VhostDevConfigOps vub_config_ops = {
+    .vhost_dev_config_notifier = vub_config_notifier,
+};
+
 static void vub_handle_output(VirtIODevice *vdev, VirtQueue *vq)
 {
     /*
@@ -141,12 +177,21 @@ static int vub_connect(DeviceState *dev)
 {
     VirtIODevice *vdev = VIRTIO_DEVICE(dev);
     VHostUserBase *vub = VHOST_USER_BASE(vdev);
+    struct vhost_dev *vhost_dev = &vub->vhost_dev;
 
     if (vub->connected) {
         return 0;
     }
     vub->connected = true;
 
+    /*
+     * If we support VHOST_USER_GET_CONFIG we must enable the notifier
+     * so we can ping the guest when it updates.
+     */
+    if (vub->vhost_user.supports_config) {
+        vhost_dev_set_config_notifier(vhost_dev, &vub_config_ops);
+    }
+
     /* restore vhost state */
     if (virtio_device_started(vdev, vdev->status)) {
         vub_start(vdev);
@@ -214,11 +259,20 @@ static void vub_device_realize(DeviceState *dev, Error **errp)
         vub->num_vqs = 1; /* reasonable default? */
     }
 
+    /*
+     * We can't handle config requests unless we know the size of the
+     * config region, specialisations of the vhost-user-device will be
+     * able to set this.
+     */
+    if (vub->config_size) {
+        vub->vhost_user.supports_config = true;
+    }
+
     if (!vhost_user_init(&vub->vhost_user, &vub->chardev, errp)) {
         return;
     }
 
-    virtio_init(vdev, vub->virtio_id, 0);
+    virtio_init(vdev, vub->virtio_id, vub->config_size);
 
     /*
      * Disable guest notifiers, by default all notifications will be via the
@@ -268,6 +322,7 @@ static void vub_class_init(ObjectClass *klass, void *data)
     vdc->realize = vub_device_realize;
     vdc->unrealize = vub_device_unrealize;
     vdc->get_features = vub_get_features;
+    vdc->get_config = vub_get_config;
     vdc->set_status = vub_set_status;
 }
 
@@ -295,6 +350,7 @@ static Property vud_properties[] = {
     DEFINE_PROP_CHR("chardev", VHostUserBase, chardev),
     DEFINE_PROP_UINT16("virtio-id", VHostUserBase, virtio_id, 0),
     DEFINE_PROP_UINT32("num_vqs", VHostUserBase, num_vqs, 1),
+    DEFINE_PROP_UINT32("config_size", VHostUserBase, config_size, 0),
     DEFINE_PROP_END_OF_LIST(),
 };
 
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v3 11/20] hw/virtio: derive vhost-user-gpio from vhost-user-device
  2023-07-10 15:35 ` [Virtio-fs] " Alex Bennée
@ 2023-07-10 15:35   ` Alex Bennée
  -1 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

Now the new base class supports config handling we can take advantage
and make vhost-user-gpio a much simpler boilerplate wrapper. Also as
this doesn't require any target specific hacks we only need to build
the stubs once.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>

---
v2
  - use new vhost-user-base
  - move build to common code
v3
  - fix inadvertent double link
---
 include/hw/virtio/vhost-user-gpio.h |  23 +-
 hw/virtio/vhost-user-gpio.c         | 400 ++--------------------------
 hw/virtio/meson.build               |   5 +-
 3 files changed, 22 insertions(+), 406 deletions(-)

diff --git a/include/hw/virtio/vhost-user-gpio.h b/include/hw/virtio/vhost-user-gpio.h
index a9d3f9b049..0948654dec 100644
--- a/include/hw/virtio/vhost-user-gpio.h
+++ b/include/hw/virtio/vhost-user-gpio.h
@@ -12,33 +12,14 @@
 #include "hw/virtio/virtio.h"
 #include "hw/virtio/vhost.h"
 #include "hw/virtio/vhost-user.h"
-#include "standard-headers/linux/virtio_gpio.h"
-#include "chardev/char-fe.h"
+#include "hw/virtio/vhost-user-device.h"
 
 #define TYPE_VHOST_USER_GPIO "vhost-user-gpio-device"
 OBJECT_DECLARE_SIMPLE_TYPE(VHostUserGPIO, VHOST_USER_GPIO);
 
 struct VHostUserGPIO {
     /*< private >*/
-    VirtIODevice parent_obj;
-    CharBackend chardev;
-    struct virtio_gpio_config config;
-    struct vhost_virtqueue *vhost_vqs;
-    struct vhost_dev vhost_dev;
-    VhostUserState vhost_user;
-    VirtQueue *command_vq;
-    VirtQueue *interrupt_vq;
-    /**
-     * There are at least two steps of initialization of the
-     * vhost-user device. The first is a "connect" step and
-     * second is a "start" step. Make a separation between
-     * those initialization phases by using two fields.
-     *
-     * @connected: see vu_gpio_connect()/vu_gpio_disconnect()
-     * @started_vu: see vu_gpio_start()/vu_gpio_stop()
-     */
-    bool connected;
-    bool started_vu;
+    VHostUserBase parent;
     /*< public >*/
 };
 
diff --git a/hw/virtio/vhost-user-gpio.c b/hw/virtio/vhost-user-gpio.c
index 3b013f2d0f..9f37c25415 100644
--- a/hw/virtio/vhost-user-gpio.c
+++ b/hw/virtio/vhost-user-gpio.c
@@ -11,382 +11,25 @@
 #include "hw/qdev-properties.h"
 #include "hw/virtio/virtio-bus.h"
 #include "hw/virtio/vhost-user-gpio.h"
-#include "qemu/error-report.h"
 #include "standard-headers/linux/virtio_ids.h"
-#include "trace.h"
+#include "standard-headers/linux/virtio_gpio.h"
 
-#define REALIZE_CONNECTION_RETRIES 3
-#define VHOST_NVQS 2
-
-/* Features required from VirtIO */
-static const int feature_bits[] = {
-    VIRTIO_F_VERSION_1,
-    VIRTIO_F_NOTIFY_ON_EMPTY,
-    VIRTIO_RING_F_INDIRECT_DESC,
-    VIRTIO_RING_F_EVENT_IDX,
-    VIRTIO_GPIO_F_IRQ,
-    VIRTIO_F_RING_RESET,
-    VHOST_INVALID_FEATURE_BIT
-};
-
-static void vu_gpio_get_config(VirtIODevice *vdev, uint8_t *config)
-{
-    VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev);
-
-    memcpy(config, &gpio->config, sizeof(gpio->config));
-}
-
-static int vu_gpio_config_notifier(struct vhost_dev *dev)
-{
-    VHostUserGPIO *gpio = VHOST_USER_GPIO(dev->vdev);
-
-    memcpy(dev->vdev->config, &gpio->config, sizeof(gpio->config));
-    virtio_notify_config(dev->vdev);
-
-    return 0;
-}
-
-const VhostDevConfigOps gpio_ops = {
-    .vhost_dev_config_notifier = vu_gpio_config_notifier,
+static Property vgpio_properties[] = {
+    DEFINE_PROP_CHR("chardev", VHostUserBase, chardev),
+    DEFINE_PROP_END_OF_LIST(),
 };
 
-static int vu_gpio_start(VirtIODevice *vdev)
+static void vgpio_realize(DeviceState *dev, Error **errp)
 {
-    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
-    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
-    VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev);
-    struct vhost_dev *vhost_dev = &gpio->vhost_dev;
-    int ret, i;
+    VHostUserBase *vub = VHOST_USER_BASE(dev);
+    VHostUserBaseClass *vubc = VHOST_USER_BASE_GET_CLASS(dev);
 
-    if (!k->set_guest_notifiers) {
-        error_report("binding does not support guest notifiers");
-        return -ENOSYS;
-    }
+    /* Fixed for GPIO */
+    vub->virtio_id = VIRTIO_ID_GPIO;
+    vub->num_vqs = 2;
+    vub->config_size = sizeof(struct virtio_gpio_config);
 
-    ret = vhost_dev_enable_notifiers(vhost_dev, vdev);
-    if (ret < 0) {
-        error_report("Error enabling host notifiers: %d", ret);
-        return ret;
-    }
-
-    ret = k->set_guest_notifiers(qbus->parent, vhost_dev->nvqs, true);
-    if (ret < 0) {
-        error_report("Error binding guest notifier: %d", ret);
-        goto err_host_notifiers;
-    }
-
-    /*
-     * Before we start up we need to ensure we have the final feature
-     * set needed for the vhost configuration. The backend may also
-     * apply backend_features when the feature set is sent.
-     */
-    vhost_ack_features(&gpio->vhost_dev, feature_bits, vdev->guest_features);
-
-    ret = vhost_dev_start(&gpio->vhost_dev, vdev, false);
-    if (ret < 0) {
-        error_report("Error starting vhost-user-gpio: %d", ret);
-        goto err_guest_notifiers;
-    }
-    gpio->started_vu = true;
-
-    /*
-     * guest_notifier_mask/pending not used yet, so just unmask
-     * everything here. virtio-pci will do the right thing by
-     * enabling/disabling irqfd.
-     */
-    for (i = 0; i < gpio->vhost_dev.nvqs; i++) {
-        vhost_virtqueue_mask(&gpio->vhost_dev, vdev, i, false);
-    }
-
-    /*
-     * As we must have VHOST_USER_F_PROTOCOL_FEATURES (because
-     * VHOST_USER_GET_CONFIG requires it) we need to explicitly enable
-     * the vrings.
-     */
-    g_assert(vhost_dev->vhost_ops &&
-             vhost_dev->vhost_ops->vhost_set_vring_enable);
-    ret = vhost_dev->vhost_ops->vhost_set_vring_enable(vhost_dev, true);
-    if (ret == 0) {
-        return 0;
-    }
-
-    error_report("Failed to start vrings for vhost-user-gpio: %d", ret);
-
-err_guest_notifiers:
-    k->set_guest_notifiers(qbus->parent, gpio->vhost_dev.nvqs, false);
-err_host_notifiers:
-    vhost_dev_disable_notifiers(&gpio->vhost_dev, vdev);
-
-    return ret;
-}
-
-static void vu_gpio_stop(VirtIODevice *vdev)
-{
-    VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev);
-    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
-    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
-    struct vhost_dev *vhost_dev = &gpio->vhost_dev;
-    int ret;
-
-    if (!gpio->started_vu) {
-        return;
-    }
-    gpio->started_vu = false;
-
-    if (!k->set_guest_notifiers) {
-        return;
-    }
-
-    vhost_dev_stop(vhost_dev, vdev, false);
-
-    ret = k->set_guest_notifiers(qbus->parent, vhost_dev->nvqs, false);
-    if (ret < 0) {
-        error_report("vhost guest notifier cleanup failed: %d", ret);
-        return;
-    }
-
-    vhost_dev_disable_notifiers(vhost_dev, vdev);
-}
-
-static void vu_gpio_set_status(VirtIODevice *vdev, uint8_t status)
-{
-    VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev);
-    bool should_start = virtio_device_should_start(vdev, status);
-
-    trace_virtio_gpio_set_status(status);
-
-    if (!gpio->connected) {
-        return;
-    }
-
-    if (vhost_dev_is_started(&gpio->vhost_dev) == should_start) {
-        return;
-    }
-
-    if (should_start) {
-        if (vu_gpio_start(vdev)) {
-            qemu_chr_fe_disconnect(&gpio->chardev);
-        }
-    } else {
-        vu_gpio_stop(vdev);
-    }
-}
-
-static uint64_t vu_gpio_get_features(VirtIODevice *vdev, uint64_t features,
-                                     Error **errp)
-{
-    VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev);
-
-    return vhost_get_features(&gpio->vhost_dev, feature_bits, features);
-}
-
-static void vu_gpio_handle_output(VirtIODevice *vdev, VirtQueue *vq)
-{
-    /*
-     * Not normally called; it's the daemon that handles the queue;
-     * however virtio's cleanup path can call this.
-     */
-}
-
-static void vu_gpio_guest_notifier_mask(VirtIODevice *vdev, int idx, bool mask)
-{
-    VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev);
-
-    /*
-     * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1
-     * as the macro of configure interrupt's IDX, If this driver does not
-     * support, the function will return
-     */
-
-    if (idx == VIRTIO_CONFIG_IRQ_IDX) {
-        return;
-    }
-
-    vhost_virtqueue_mask(&gpio->vhost_dev, vdev, idx, mask);
-}
-
-static void do_vhost_user_cleanup(VirtIODevice *vdev, VHostUserGPIO *gpio)
-{
-    virtio_delete_queue(gpio->command_vq);
-    virtio_delete_queue(gpio->interrupt_vq);
-    g_free(gpio->vhost_vqs);
-    virtio_cleanup(vdev);
-    vhost_user_cleanup(&gpio->vhost_user);
-}
-
-static int vu_gpio_connect(DeviceState *dev, Error **errp)
-{
-    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
-    VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev);
-    struct vhost_dev *vhost_dev = &gpio->vhost_dev;
-    int ret;
-
-    if (gpio->connected) {
-        return 0;
-    }
-    gpio->connected = true;
-
-    vhost_dev_set_config_notifier(vhost_dev, &gpio_ops);
-    gpio->vhost_user.supports_config = true;
-
-    gpio->vhost_dev.nvqs = VHOST_NVQS;
-    gpio->vhost_dev.vqs = gpio->vhost_vqs;
-
-    ret = vhost_dev_init(vhost_dev, &gpio->vhost_user,
-                         VHOST_BACKEND_TYPE_USER, 0, errp);
-    if (ret < 0) {
-        return ret;
-    }
-
-    /* restore vhost state */
-    if (virtio_device_started(vdev, vdev->status)) {
-        vu_gpio_start(vdev);
-    }
-
-    return 0;
-}
-
-static void vu_gpio_event(void *opaque, QEMUChrEvent event);
-
-static void vu_gpio_disconnect(DeviceState *dev)
-{
-    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
-    VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev);
-
-    if (!gpio->connected) {
-        return;
-    }
-    gpio->connected = false;
-
-    vu_gpio_stop(vdev);
-    vhost_dev_cleanup(&gpio->vhost_dev);
-
-    /* Re-instate the event handler for new connections */
-    qemu_chr_fe_set_handlers(&gpio->chardev,
-                             NULL, NULL, vu_gpio_event,
-                             NULL, dev, NULL, true);
-}
-
-static void vu_gpio_event(void *opaque, QEMUChrEvent event)
-{
-    DeviceState *dev = opaque;
-    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
-    VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev);
-    Error *local_err = NULL;
-
-    switch (event) {
-    case CHR_EVENT_OPENED:
-        if (vu_gpio_connect(dev, &local_err) < 0) {
-            qemu_chr_fe_disconnect(&gpio->chardev);
-            return;
-        }
-        break;
-    case CHR_EVENT_CLOSED:
-        /* defer close until later to avoid circular close */
-        vhost_user_async_close(dev, &gpio->chardev, &gpio->vhost_dev,
-                               vu_gpio_disconnect);
-        break;
-    case CHR_EVENT_BREAK:
-    case CHR_EVENT_MUX_IN:
-    case CHR_EVENT_MUX_OUT:
-        /* Ignore */
-        break;
-    }
-}
-
-static int vu_gpio_realize_connect(VHostUserGPIO *gpio, Error **errp)
-{
-    VirtIODevice *vdev = &gpio->parent_obj;
-    DeviceState *dev = &vdev->parent_obj;
-    struct vhost_dev *vhost_dev = &gpio->vhost_dev;
-    int ret;
-
-    ret = qemu_chr_fe_wait_connected(&gpio->chardev, errp);
-    if (ret < 0) {
-        return ret;
-    }
-
-    /*
-     * vu_gpio_connect() may have already connected (via the event
-     * callback) in which case it will just report success.
-     */
-    ret = vu_gpio_connect(dev, errp);
-    if (ret < 0) {
-        qemu_chr_fe_disconnect(&gpio->chardev);
-        return ret;
-    }
-    g_assert(gpio->connected);
-
-    ret = vhost_dev_get_config(vhost_dev, (uint8_t *)&gpio->config,
-                               sizeof(gpio->config), errp);
-
-    if (ret < 0) {
-        error_report("vhost-user-gpio: get config failed");
-
-        qemu_chr_fe_disconnect(&gpio->chardev);
-        vhost_dev_cleanup(vhost_dev);
-        return ret;
-    }
-
-    return 0;
-}
-
-static void vu_gpio_device_realize(DeviceState *dev, Error **errp)
-{
-    ERRP_GUARD();
-
-    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
-    VHostUserGPIO *gpio = VHOST_USER_GPIO(dev);
-    int retries, ret;
-
-    if (!gpio->chardev.chr) {
-        error_setg(errp, "vhost-user-gpio: chardev is mandatory");
-        return;
-    }
-
-    if (!vhost_user_init(&gpio->vhost_user, &gpio->chardev, errp)) {
-        return;
-    }
-
-    virtio_init(vdev, VIRTIO_ID_GPIO, sizeof(gpio->config));
-
-    gpio->command_vq = virtio_add_queue(vdev, 256, vu_gpio_handle_output);
-    gpio->interrupt_vq = virtio_add_queue(vdev, 256, vu_gpio_handle_output);
-    gpio->vhost_vqs = g_new0(struct vhost_virtqueue, VHOST_NVQS);
-
-    gpio->connected = false;
-
-    qemu_chr_fe_set_handlers(&gpio->chardev, NULL, NULL, vu_gpio_event, NULL,
-                             dev, NULL, true);
-
-    retries = REALIZE_CONNECTION_RETRIES;
-    g_assert(!*errp);
-    do {
-        if (*errp) {
-            error_prepend(errp, "Reconnecting after error: ");
-            error_report_err(*errp);
-            *errp = NULL;
-        }
-        ret = vu_gpio_realize_connect(gpio, errp);
-    } while (ret < 0 && retries--);
-
-    if (ret < 0) {
-        do_vhost_user_cleanup(vdev, gpio);
-    }
-
-    return;
-}
-
-static void vu_gpio_device_unrealize(DeviceState *dev)
-{
-    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
-    VHostUserGPIO *gpio = VHOST_USER_GPIO(dev);
-
-    vu_gpio_set_status(vdev, 0);
-    qemu_chr_fe_set_handlers(&gpio->chardev, NULL, NULL, NULL, NULL, NULL, NULL,
-                             false);
-    vhost_dev_cleanup(&gpio->vhost_dev);
-    do_vhost_user_cleanup(vdev, gpio);
+    vubc->parent_realize(dev, errp);
 }
 
 static const VMStateDescription vu_gpio_vmstate = {
@@ -394,30 +37,21 @@ static const VMStateDescription vu_gpio_vmstate = {
     .unmigratable = 1,
 };
 
-static Property vu_gpio_properties[] = {
-    DEFINE_PROP_CHR("chardev", VHostUserGPIO, chardev),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
 static void vu_gpio_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
+    VHostUserBaseClass *vubc = VHOST_USER_BASE_CLASS(klass);
 
-    device_class_set_props(dc, vu_gpio_properties);
     dc->vmsd = &vu_gpio_vmstate;
+    device_class_set_props(dc, vgpio_properties);
+    device_class_set_parent_realize(dc, vgpio_realize,
+                                    &vubc->parent_realize);
     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
-    vdc->realize = vu_gpio_device_realize;
-    vdc->unrealize = vu_gpio_device_unrealize;
-    vdc->get_features = vu_gpio_get_features;
-    vdc->get_config = vu_gpio_get_config;
-    vdc->set_status = vu_gpio_set_status;
-    vdc->guest_notifier_mask = vu_gpio_guest_notifier_mask;
 }
 
 static const TypeInfo vu_gpio_info = {
     .name = TYPE_VHOST_USER_GPIO,
-    .parent = TYPE_VIRTIO_DEVICE,
+    .parent = TYPE_VHOST_USER_BASE,
     .instance_size = sizeof(VHostUserGPIO),
     .class_init = vu_gpio_class_init,
 };
diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build
index fb80587d5b..62ab2d82e0 100644
--- a/hw/virtio/meson.build
+++ b/hw/virtio/meson.build
@@ -11,6 +11,9 @@ softmmu_virtio_ss.add(when: 'CONFIG_VHOST_VDPA_DEV', if_true: files('vdpa-dev.c'
 softmmu_virtio_ss.add(when: 'CONFIG_VHOST_USER_RNG', if_true: files('vhost-user-rng.c'))
 softmmu_virtio_ss.add(when: ['CONFIG_VIRTIO_PCI', 'CONFIG_VHOST_USER_RNG'],
                       if_true: files('vhost-user-rng-pci.c'))
+softmmu_virtio_ss.add(when: 'CONFIG_VHOST_USER_GPIO', if_true: files('vhost-user-gpio.c'))
+softmmu_virtio_ss.add(when: ['CONFIG_VIRTIO_PCI', 'CONFIG_VHOST_USER_GPIO'],
+                      if_true: files('vhost-user-gpio-pci.c'))
 
 specific_virtio_ss = ss.source_set()
 specific_virtio_ss.add(files('virtio.c'))
@@ -40,8 +43,6 @@ specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_VSOCK', if_true: files('vhost-us
 specific_virtio_ss.add(when: 'CONFIG_VIRTIO_RNG', if_true: files('virtio-rng.c'))
 specific_virtio_ss.add(when: 'CONFIG_VIRTIO_MEM', if_true: files('virtio-mem.c'))
 specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_I2C', if_true: files('vhost-user-i2c.c'))
-specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_GPIO', if_true: files('vhost-user-gpio.c'))
-specific_virtio_ss.add(when: ['CONFIG_VIRTIO_PCI', 'CONFIG_VHOST_USER_GPIO'], if_true: files('vhost-user-gpio-pci.c'))
 
 virtio_pci_ss = ss.source_set()
 virtio_pci_ss.add(when: 'CONFIG_VHOST_VSOCK', if_true: files('vhost-vsock-pci.c'))
-- 
2.39.2



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Virtio-fs] [PATCH v3 11/20] hw/virtio: derive vhost-user-gpio from vhost-user-device
@ 2023-07-10 15:35   ` Alex Bennée
  0 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

Now the new base class supports config handling we can take advantage
and make vhost-user-gpio a much simpler boilerplate wrapper. Also as
this doesn't require any target specific hacks we only need to build
the stubs once.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>

---
v2
  - use new vhost-user-base
  - move build to common code
v3
  - fix inadvertent double link
---
 include/hw/virtio/vhost-user-gpio.h |  23 +-
 hw/virtio/vhost-user-gpio.c         | 400 ++--------------------------
 hw/virtio/meson.build               |   5 +-
 3 files changed, 22 insertions(+), 406 deletions(-)

diff --git a/include/hw/virtio/vhost-user-gpio.h b/include/hw/virtio/vhost-user-gpio.h
index a9d3f9b049..0948654dec 100644
--- a/include/hw/virtio/vhost-user-gpio.h
+++ b/include/hw/virtio/vhost-user-gpio.h
@@ -12,33 +12,14 @@
 #include "hw/virtio/virtio.h"
 #include "hw/virtio/vhost.h"
 #include "hw/virtio/vhost-user.h"
-#include "standard-headers/linux/virtio_gpio.h"
-#include "chardev/char-fe.h"
+#include "hw/virtio/vhost-user-device.h"
 
 #define TYPE_VHOST_USER_GPIO "vhost-user-gpio-device"
 OBJECT_DECLARE_SIMPLE_TYPE(VHostUserGPIO, VHOST_USER_GPIO);
 
 struct VHostUserGPIO {
     /*< private >*/
-    VirtIODevice parent_obj;
-    CharBackend chardev;
-    struct virtio_gpio_config config;
-    struct vhost_virtqueue *vhost_vqs;
-    struct vhost_dev vhost_dev;
-    VhostUserState vhost_user;
-    VirtQueue *command_vq;
-    VirtQueue *interrupt_vq;
-    /**
-     * There are at least two steps of initialization of the
-     * vhost-user device. The first is a "connect" step and
-     * second is a "start" step. Make a separation between
-     * those initialization phases by using two fields.
-     *
-     * @connected: see vu_gpio_connect()/vu_gpio_disconnect()
-     * @started_vu: see vu_gpio_start()/vu_gpio_stop()
-     */
-    bool connected;
-    bool started_vu;
+    VHostUserBase parent;
     /*< public >*/
 };
 
diff --git a/hw/virtio/vhost-user-gpio.c b/hw/virtio/vhost-user-gpio.c
index 3b013f2d0f..9f37c25415 100644
--- a/hw/virtio/vhost-user-gpio.c
+++ b/hw/virtio/vhost-user-gpio.c
@@ -11,382 +11,25 @@
 #include "hw/qdev-properties.h"
 #include "hw/virtio/virtio-bus.h"
 #include "hw/virtio/vhost-user-gpio.h"
-#include "qemu/error-report.h"
 #include "standard-headers/linux/virtio_ids.h"
-#include "trace.h"
+#include "standard-headers/linux/virtio_gpio.h"
 
-#define REALIZE_CONNECTION_RETRIES 3
-#define VHOST_NVQS 2
-
-/* Features required from VirtIO */
-static const int feature_bits[] = {
-    VIRTIO_F_VERSION_1,
-    VIRTIO_F_NOTIFY_ON_EMPTY,
-    VIRTIO_RING_F_INDIRECT_DESC,
-    VIRTIO_RING_F_EVENT_IDX,
-    VIRTIO_GPIO_F_IRQ,
-    VIRTIO_F_RING_RESET,
-    VHOST_INVALID_FEATURE_BIT
-};
-
-static void vu_gpio_get_config(VirtIODevice *vdev, uint8_t *config)
-{
-    VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev);
-
-    memcpy(config, &gpio->config, sizeof(gpio->config));
-}
-
-static int vu_gpio_config_notifier(struct vhost_dev *dev)
-{
-    VHostUserGPIO *gpio = VHOST_USER_GPIO(dev->vdev);
-
-    memcpy(dev->vdev->config, &gpio->config, sizeof(gpio->config));
-    virtio_notify_config(dev->vdev);
-
-    return 0;
-}
-
-const VhostDevConfigOps gpio_ops = {
-    .vhost_dev_config_notifier = vu_gpio_config_notifier,
+static Property vgpio_properties[] = {
+    DEFINE_PROP_CHR("chardev", VHostUserBase, chardev),
+    DEFINE_PROP_END_OF_LIST(),
 };
 
-static int vu_gpio_start(VirtIODevice *vdev)
+static void vgpio_realize(DeviceState *dev, Error **errp)
 {
-    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
-    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
-    VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev);
-    struct vhost_dev *vhost_dev = &gpio->vhost_dev;
-    int ret, i;
+    VHostUserBase *vub = VHOST_USER_BASE(dev);
+    VHostUserBaseClass *vubc = VHOST_USER_BASE_GET_CLASS(dev);
 
-    if (!k->set_guest_notifiers) {
-        error_report("binding does not support guest notifiers");
-        return -ENOSYS;
-    }
+    /* Fixed for GPIO */
+    vub->virtio_id = VIRTIO_ID_GPIO;
+    vub->num_vqs = 2;
+    vub->config_size = sizeof(struct virtio_gpio_config);
 
-    ret = vhost_dev_enable_notifiers(vhost_dev, vdev);
-    if (ret < 0) {
-        error_report("Error enabling host notifiers: %d", ret);
-        return ret;
-    }
-
-    ret = k->set_guest_notifiers(qbus->parent, vhost_dev->nvqs, true);
-    if (ret < 0) {
-        error_report("Error binding guest notifier: %d", ret);
-        goto err_host_notifiers;
-    }
-
-    /*
-     * Before we start up we need to ensure we have the final feature
-     * set needed for the vhost configuration. The backend may also
-     * apply backend_features when the feature set is sent.
-     */
-    vhost_ack_features(&gpio->vhost_dev, feature_bits, vdev->guest_features);
-
-    ret = vhost_dev_start(&gpio->vhost_dev, vdev, false);
-    if (ret < 0) {
-        error_report("Error starting vhost-user-gpio: %d", ret);
-        goto err_guest_notifiers;
-    }
-    gpio->started_vu = true;
-
-    /*
-     * guest_notifier_mask/pending not used yet, so just unmask
-     * everything here. virtio-pci will do the right thing by
-     * enabling/disabling irqfd.
-     */
-    for (i = 0; i < gpio->vhost_dev.nvqs; i++) {
-        vhost_virtqueue_mask(&gpio->vhost_dev, vdev, i, false);
-    }
-
-    /*
-     * As we must have VHOST_USER_F_PROTOCOL_FEATURES (because
-     * VHOST_USER_GET_CONFIG requires it) we need to explicitly enable
-     * the vrings.
-     */
-    g_assert(vhost_dev->vhost_ops &&
-             vhost_dev->vhost_ops->vhost_set_vring_enable);
-    ret = vhost_dev->vhost_ops->vhost_set_vring_enable(vhost_dev, true);
-    if (ret == 0) {
-        return 0;
-    }
-
-    error_report("Failed to start vrings for vhost-user-gpio: %d", ret);
-
-err_guest_notifiers:
-    k->set_guest_notifiers(qbus->parent, gpio->vhost_dev.nvqs, false);
-err_host_notifiers:
-    vhost_dev_disable_notifiers(&gpio->vhost_dev, vdev);
-
-    return ret;
-}
-
-static void vu_gpio_stop(VirtIODevice *vdev)
-{
-    VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev);
-    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
-    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
-    struct vhost_dev *vhost_dev = &gpio->vhost_dev;
-    int ret;
-
-    if (!gpio->started_vu) {
-        return;
-    }
-    gpio->started_vu = false;
-
-    if (!k->set_guest_notifiers) {
-        return;
-    }
-
-    vhost_dev_stop(vhost_dev, vdev, false);
-
-    ret = k->set_guest_notifiers(qbus->parent, vhost_dev->nvqs, false);
-    if (ret < 0) {
-        error_report("vhost guest notifier cleanup failed: %d", ret);
-        return;
-    }
-
-    vhost_dev_disable_notifiers(vhost_dev, vdev);
-}
-
-static void vu_gpio_set_status(VirtIODevice *vdev, uint8_t status)
-{
-    VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev);
-    bool should_start = virtio_device_should_start(vdev, status);
-
-    trace_virtio_gpio_set_status(status);
-
-    if (!gpio->connected) {
-        return;
-    }
-
-    if (vhost_dev_is_started(&gpio->vhost_dev) == should_start) {
-        return;
-    }
-
-    if (should_start) {
-        if (vu_gpio_start(vdev)) {
-            qemu_chr_fe_disconnect(&gpio->chardev);
-        }
-    } else {
-        vu_gpio_stop(vdev);
-    }
-}
-
-static uint64_t vu_gpio_get_features(VirtIODevice *vdev, uint64_t features,
-                                     Error **errp)
-{
-    VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev);
-
-    return vhost_get_features(&gpio->vhost_dev, feature_bits, features);
-}
-
-static void vu_gpio_handle_output(VirtIODevice *vdev, VirtQueue *vq)
-{
-    /*
-     * Not normally called; it's the daemon that handles the queue;
-     * however virtio's cleanup path can call this.
-     */
-}
-
-static void vu_gpio_guest_notifier_mask(VirtIODevice *vdev, int idx, bool mask)
-{
-    VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev);
-
-    /*
-     * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1
-     * as the macro of configure interrupt's IDX, If this driver does not
-     * support, the function will return
-     */
-
-    if (idx == VIRTIO_CONFIG_IRQ_IDX) {
-        return;
-    }
-
-    vhost_virtqueue_mask(&gpio->vhost_dev, vdev, idx, mask);
-}
-
-static void do_vhost_user_cleanup(VirtIODevice *vdev, VHostUserGPIO *gpio)
-{
-    virtio_delete_queue(gpio->command_vq);
-    virtio_delete_queue(gpio->interrupt_vq);
-    g_free(gpio->vhost_vqs);
-    virtio_cleanup(vdev);
-    vhost_user_cleanup(&gpio->vhost_user);
-}
-
-static int vu_gpio_connect(DeviceState *dev, Error **errp)
-{
-    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
-    VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev);
-    struct vhost_dev *vhost_dev = &gpio->vhost_dev;
-    int ret;
-
-    if (gpio->connected) {
-        return 0;
-    }
-    gpio->connected = true;
-
-    vhost_dev_set_config_notifier(vhost_dev, &gpio_ops);
-    gpio->vhost_user.supports_config = true;
-
-    gpio->vhost_dev.nvqs = VHOST_NVQS;
-    gpio->vhost_dev.vqs = gpio->vhost_vqs;
-
-    ret = vhost_dev_init(vhost_dev, &gpio->vhost_user,
-                         VHOST_BACKEND_TYPE_USER, 0, errp);
-    if (ret < 0) {
-        return ret;
-    }
-
-    /* restore vhost state */
-    if (virtio_device_started(vdev, vdev->status)) {
-        vu_gpio_start(vdev);
-    }
-
-    return 0;
-}
-
-static void vu_gpio_event(void *opaque, QEMUChrEvent event);
-
-static void vu_gpio_disconnect(DeviceState *dev)
-{
-    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
-    VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev);
-
-    if (!gpio->connected) {
-        return;
-    }
-    gpio->connected = false;
-
-    vu_gpio_stop(vdev);
-    vhost_dev_cleanup(&gpio->vhost_dev);
-
-    /* Re-instate the event handler for new connections */
-    qemu_chr_fe_set_handlers(&gpio->chardev,
-                             NULL, NULL, vu_gpio_event,
-                             NULL, dev, NULL, true);
-}
-
-static void vu_gpio_event(void *opaque, QEMUChrEvent event)
-{
-    DeviceState *dev = opaque;
-    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
-    VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev);
-    Error *local_err = NULL;
-
-    switch (event) {
-    case CHR_EVENT_OPENED:
-        if (vu_gpio_connect(dev, &local_err) < 0) {
-            qemu_chr_fe_disconnect(&gpio->chardev);
-            return;
-        }
-        break;
-    case CHR_EVENT_CLOSED:
-        /* defer close until later to avoid circular close */
-        vhost_user_async_close(dev, &gpio->chardev, &gpio->vhost_dev,
-                               vu_gpio_disconnect);
-        break;
-    case CHR_EVENT_BREAK:
-    case CHR_EVENT_MUX_IN:
-    case CHR_EVENT_MUX_OUT:
-        /* Ignore */
-        break;
-    }
-}
-
-static int vu_gpio_realize_connect(VHostUserGPIO *gpio, Error **errp)
-{
-    VirtIODevice *vdev = &gpio->parent_obj;
-    DeviceState *dev = &vdev->parent_obj;
-    struct vhost_dev *vhost_dev = &gpio->vhost_dev;
-    int ret;
-
-    ret = qemu_chr_fe_wait_connected(&gpio->chardev, errp);
-    if (ret < 0) {
-        return ret;
-    }
-
-    /*
-     * vu_gpio_connect() may have already connected (via the event
-     * callback) in which case it will just report success.
-     */
-    ret = vu_gpio_connect(dev, errp);
-    if (ret < 0) {
-        qemu_chr_fe_disconnect(&gpio->chardev);
-        return ret;
-    }
-    g_assert(gpio->connected);
-
-    ret = vhost_dev_get_config(vhost_dev, (uint8_t *)&gpio->config,
-                               sizeof(gpio->config), errp);
-
-    if (ret < 0) {
-        error_report("vhost-user-gpio: get config failed");
-
-        qemu_chr_fe_disconnect(&gpio->chardev);
-        vhost_dev_cleanup(vhost_dev);
-        return ret;
-    }
-
-    return 0;
-}
-
-static void vu_gpio_device_realize(DeviceState *dev, Error **errp)
-{
-    ERRP_GUARD();
-
-    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
-    VHostUserGPIO *gpio = VHOST_USER_GPIO(dev);
-    int retries, ret;
-
-    if (!gpio->chardev.chr) {
-        error_setg(errp, "vhost-user-gpio: chardev is mandatory");
-        return;
-    }
-
-    if (!vhost_user_init(&gpio->vhost_user, &gpio->chardev, errp)) {
-        return;
-    }
-
-    virtio_init(vdev, VIRTIO_ID_GPIO, sizeof(gpio->config));
-
-    gpio->command_vq = virtio_add_queue(vdev, 256, vu_gpio_handle_output);
-    gpio->interrupt_vq = virtio_add_queue(vdev, 256, vu_gpio_handle_output);
-    gpio->vhost_vqs = g_new0(struct vhost_virtqueue, VHOST_NVQS);
-
-    gpio->connected = false;
-
-    qemu_chr_fe_set_handlers(&gpio->chardev, NULL, NULL, vu_gpio_event, NULL,
-                             dev, NULL, true);
-
-    retries = REALIZE_CONNECTION_RETRIES;
-    g_assert(!*errp);
-    do {
-        if (*errp) {
-            error_prepend(errp, "Reconnecting after error: ");
-            error_report_err(*errp);
-            *errp = NULL;
-        }
-        ret = vu_gpio_realize_connect(gpio, errp);
-    } while (ret < 0 && retries--);
-
-    if (ret < 0) {
-        do_vhost_user_cleanup(vdev, gpio);
-    }
-
-    return;
-}
-
-static void vu_gpio_device_unrealize(DeviceState *dev)
-{
-    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
-    VHostUserGPIO *gpio = VHOST_USER_GPIO(dev);
-
-    vu_gpio_set_status(vdev, 0);
-    qemu_chr_fe_set_handlers(&gpio->chardev, NULL, NULL, NULL, NULL, NULL, NULL,
-                             false);
-    vhost_dev_cleanup(&gpio->vhost_dev);
-    do_vhost_user_cleanup(vdev, gpio);
+    vubc->parent_realize(dev, errp);
 }
 
 static const VMStateDescription vu_gpio_vmstate = {
@@ -394,30 +37,21 @@ static const VMStateDescription vu_gpio_vmstate = {
     .unmigratable = 1,
 };
 
-static Property vu_gpio_properties[] = {
-    DEFINE_PROP_CHR("chardev", VHostUserGPIO, chardev),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
 static void vu_gpio_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
+    VHostUserBaseClass *vubc = VHOST_USER_BASE_CLASS(klass);
 
-    device_class_set_props(dc, vu_gpio_properties);
     dc->vmsd = &vu_gpio_vmstate;
+    device_class_set_props(dc, vgpio_properties);
+    device_class_set_parent_realize(dc, vgpio_realize,
+                                    &vubc->parent_realize);
     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
-    vdc->realize = vu_gpio_device_realize;
-    vdc->unrealize = vu_gpio_device_unrealize;
-    vdc->get_features = vu_gpio_get_features;
-    vdc->get_config = vu_gpio_get_config;
-    vdc->set_status = vu_gpio_set_status;
-    vdc->guest_notifier_mask = vu_gpio_guest_notifier_mask;
 }
 
 static const TypeInfo vu_gpio_info = {
     .name = TYPE_VHOST_USER_GPIO,
-    .parent = TYPE_VIRTIO_DEVICE,
+    .parent = TYPE_VHOST_USER_BASE,
     .instance_size = sizeof(VHostUserGPIO),
     .class_init = vu_gpio_class_init,
 };
diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build
index fb80587d5b..62ab2d82e0 100644
--- a/hw/virtio/meson.build
+++ b/hw/virtio/meson.build
@@ -11,6 +11,9 @@ softmmu_virtio_ss.add(when: 'CONFIG_VHOST_VDPA_DEV', if_true: files('vdpa-dev.c'
 softmmu_virtio_ss.add(when: 'CONFIG_VHOST_USER_RNG', if_true: files('vhost-user-rng.c'))
 softmmu_virtio_ss.add(when: ['CONFIG_VIRTIO_PCI', 'CONFIG_VHOST_USER_RNG'],
                       if_true: files('vhost-user-rng-pci.c'))
+softmmu_virtio_ss.add(when: 'CONFIG_VHOST_USER_GPIO', if_true: files('vhost-user-gpio.c'))
+softmmu_virtio_ss.add(when: ['CONFIG_VIRTIO_PCI', 'CONFIG_VHOST_USER_GPIO'],
+                      if_true: files('vhost-user-gpio-pci.c'))
 
 specific_virtio_ss = ss.source_set()
 specific_virtio_ss.add(files('virtio.c'))
@@ -40,8 +43,6 @@ specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_VSOCK', if_true: files('vhost-us
 specific_virtio_ss.add(when: 'CONFIG_VIRTIO_RNG', if_true: files('virtio-rng.c'))
 specific_virtio_ss.add(when: 'CONFIG_VIRTIO_MEM', if_true: files('virtio-mem.c'))
 specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_I2C', if_true: files('vhost-user-i2c.c'))
-specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_GPIO', if_true: files('vhost-user-gpio.c'))
-specific_virtio_ss.add(when: ['CONFIG_VIRTIO_PCI', 'CONFIG_VHOST_USER_GPIO'], if_true: files('vhost-user-gpio-pci.c'))
 
 virtio_pci_ss = ss.source_set()
 virtio_pci_ss.add(when: 'CONFIG_VHOST_VSOCK', if_true: files('vhost-vsock-pci.c'))
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [PATCH v3 12/20] hw/virtio: derive vhost-user-i2c from vhost-user-base
  2023-07-10 15:35 ` [Virtio-fs] " Alex Bennée
@ 2023-07-10 15:35   ` Alex Bennée
  -1 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

Now we can take advantage of the new base class and make
vhost-user-i2c a much simpler boilerplate wrapper. Also as this
doesn't require any target specific hacks we only need to build the
stubs once.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>

---
v2
  - update to new inheritance scheme
  - move build to common code
v3
  - fix merge conflict in meson
---
 include/hw/virtio/vhost-user-i2c.h |  18 +-
 hw/virtio/vhost-user-i2c.c         | 271 ++---------------------------
 hw/virtio/meson.build              |   5 +-
 3 files changed, 26 insertions(+), 268 deletions(-)

diff --git a/include/hw/virtio/vhost-user-i2c.h b/include/hw/virtio/vhost-user-i2c.h
index 0f7acd40e3..47153782d1 100644
--- a/include/hw/virtio/vhost-user-i2c.h
+++ b/include/hw/virtio/vhost-user-i2c.h
@@ -12,20 +12,18 @@
 #include "hw/virtio/vhost.h"
 #include "hw/virtio/vhost-user.h"
 
+#include "hw/virtio/virtio.h"
+#include "hw/virtio/vhost.h"
+#include "hw/virtio/vhost-user.h"
+#include "hw/virtio/vhost-user-device.h"
+
 #define TYPE_VHOST_USER_I2C "vhost-user-i2c-device"
 OBJECT_DECLARE_SIMPLE_TYPE(VHostUserI2C, VHOST_USER_I2C)
 
 struct VHostUserI2C {
-    VirtIODevice parent;
-    CharBackend chardev;
-    struct vhost_virtqueue *vhost_vq;
-    struct vhost_dev vhost_dev;
-    VhostUserState vhost_user;
-    VirtQueue *vq;
-    bool connected;
+    /*< private >*/
+    VHostUserBase parent;
+    /*< public >*/
 };
 
-/* Virtio Feature bits */
-#define VIRTIO_I2C_F_ZERO_LENGTH_REQUEST		0
-
 #endif /* QEMU_VHOST_USER_I2C_H */
diff --git a/hw/virtio/vhost-user-i2c.c b/hw/virtio/vhost-user-i2c.c
index 4eef3f0633..4a1f644a87 100644
--- a/hw/virtio/vhost-user-i2c.c
+++ b/hw/virtio/vhost-user-i2c.c
@@ -14,253 +14,21 @@
 #include "qemu/error-report.h"
 #include "standard-headers/linux/virtio_ids.h"
 
-static const int feature_bits[] = {
-    VIRTIO_I2C_F_ZERO_LENGTH_REQUEST,
-    VIRTIO_F_RING_RESET,
-    VHOST_INVALID_FEATURE_BIT
+static Property vi2c_properties[] = {
+    DEFINE_PROP_CHR("chardev", VHostUserBase, chardev),
+    DEFINE_PROP_END_OF_LIST(),
 };
 
-static void vu_i2c_start(VirtIODevice *vdev)
-{
-    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
-    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
-    VHostUserI2C *i2c = VHOST_USER_I2C(vdev);
-    int ret, i;
-
-    if (!k->set_guest_notifiers) {
-        error_report("binding does not support guest notifiers");
-        return;
-    }
-
-    ret = vhost_dev_enable_notifiers(&i2c->vhost_dev, vdev);
-    if (ret < 0) {
-        error_report("Error enabling host notifiers: %d", -ret);
-        return;
-    }
-
-    ret = k->set_guest_notifiers(qbus->parent, i2c->vhost_dev.nvqs, true);
-    if (ret < 0) {
-        error_report("Error binding guest notifier: %d", -ret);
-        goto err_host_notifiers;
-    }
-
-    i2c->vhost_dev.acked_features = vdev->guest_features;
-
-    ret = vhost_dev_start(&i2c->vhost_dev, vdev, true);
-    if (ret < 0) {
-        error_report("Error starting vhost-user-i2c: %d", -ret);
-        goto err_guest_notifiers;
-    }
-
-    /*
-     * guest_notifier_mask/pending not used yet, so just unmask
-     * everything here. virtio-pci will do the right thing by
-     * enabling/disabling irqfd.
-     */
-    for (i = 0; i < i2c->vhost_dev.nvqs; i++) {
-        vhost_virtqueue_mask(&i2c->vhost_dev, vdev, i, false);
-    }
-
-    return;
-
-err_guest_notifiers:
-    k->set_guest_notifiers(qbus->parent, i2c->vhost_dev.nvqs, false);
-err_host_notifiers:
-    vhost_dev_disable_notifiers(&i2c->vhost_dev, vdev);
-}
-
-static void vu_i2c_stop(VirtIODevice *vdev)
-{
-    VHostUserI2C *i2c = VHOST_USER_I2C(vdev);
-    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
-    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
-    int ret;
-
-    if (!k->set_guest_notifiers) {
-        return;
-    }
-
-    vhost_dev_stop(&i2c->vhost_dev, vdev, true);
-
-    ret = k->set_guest_notifiers(qbus->parent, i2c->vhost_dev.nvqs, false);
-    if (ret < 0) {
-        error_report("vhost guest notifier cleanup failed: %d", ret);
-        return;
-    }
-
-    vhost_dev_disable_notifiers(&i2c->vhost_dev, vdev);
-}
-
-static void vu_i2c_set_status(VirtIODevice *vdev, uint8_t status)
-{
-    VHostUserI2C *i2c = VHOST_USER_I2C(vdev);
-    bool should_start = virtio_device_should_start(vdev, status);
-
-    if (vhost_dev_is_started(&i2c->vhost_dev) == should_start) {
-        return;
-    }
-
-    if (should_start) {
-        vu_i2c_start(vdev);
-    } else {
-        vu_i2c_stop(vdev);
-    }
-}
-
-static uint64_t vu_i2c_get_features(VirtIODevice *vdev,
-                                    uint64_t requested_features, Error **errp)
-{
-    VHostUserI2C *i2c = VHOST_USER_I2C(vdev);
-
-    virtio_add_feature(&requested_features, VIRTIO_I2C_F_ZERO_LENGTH_REQUEST);
-    return vhost_get_features(&i2c->vhost_dev, feature_bits, requested_features);
-}
-
-static void vu_i2c_handle_output(VirtIODevice *vdev, VirtQueue *vq)
-{
-    /*
-     * Not normally called; it's the daemon that handles the queue;
-     * however virtio's cleanup path can call this.
-     */
-}
-
-static void vu_i2c_guest_notifier_mask(VirtIODevice *vdev, int idx, bool mask)
-{
-    VHostUserI2C *i2c = VHOST_USER_I2C(vdev);
-
-    /*
-     * We don't support interrupts, return early if index is set to
-     * VIRTIO_CONFIG_IRQ_IDX.
-     */
-    if (idx == VIRTIO_CONFIG_IRQ_IDX) {
-        return;
-    }
-
-    vhost_virtqueue_mask(&i2c->vhost_dev, vdev, idx, mask);
-}
-
-static bool vu_i2c_guest_notifier_pending(VirtIODevice *vdev, int idx)
-{
-    VHostUserI2C *i2c = VHOST_USER_I2C(vdev);
-
-    /*
-     * We don't support interrupts, return early if index is set to
-     * VIRTIO_CONFIG_IRQ_IDX.
-     */
-    if (idx == VIRTIO_CONFIG_IRQ_IDX) {
-        return false;
-    }
-
-    return vhost_virtqueue_pending(&i2c->vhost_dev, idx);
-}
-
-static void do_vhost_user_cleanup(VirtIODevice *vdev, VHostUserI2C *i2c)
-{
-    vhost_user_cleanup(&i2c->vhost_user);
-    virtio_delete_queue(i2c->vq);
-    virtio_cleanup(vdev);
-}
-
-static int vu_i2c_connect(DeviceState *dev)
+static void vi2c_realize(DeviceState *dev, Error **errp)
 {
-    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
-    VHostUserI2C *i2c = VHOST_USER_I2C(vdev);
+    VHostUserBase *vub = VHOST_USER_BASE(dev);
+    VHostUserBaseClass *vubc = VHOST_USER_BASE_GET_CLASS(dev);
 
-    if (i2c->connected) {
-        return 0;
-    }
-    i2c->connected = true;
+    /* Fixed for I2C */
+    vub->virtio_id = VIRTIO_ID_I2C_ADAPTER;
+    vub->num_vqs = 1;
 
-    /* restore vhost state */
-    if (virtio_device_started(vdev, vdev->status)) {
-        vu_i2c_start(vdev);
-    }
-
-    return 0;
-}
-
-static void vu_i2c_disconnect(DeviceState *dev)
-{
-    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
-    VHostUserI2C *i2c = VHOST_USER_I2C(vdev);
-
-    if (!i2c->connected) {
-        return;
-    }
-    i2c->connected = false;
-
-    if (vhost_dev_is_started(&i2c->vhost_dev)) {
-        vu_i2c_stop(vdev);
-    }
-}
-
-static void vu_i2c_event(void *opaque, QEMUChrEvent event)
-{
-    DeviceState *dev = opaque;
-    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
-    VHostUserI2C *i2c = VHOST_USER_I2C(vdev);
-
-    switch (event) {
-    case CHR_EVENT_OPENED:
-        if (vu_i2c_connect(dev) < 0) {
-            qemu_chr_fe_disconnect(&i2c->chardev);
-            return;
-        }
-        break;
-    case CHR_EVENT_CLOSED:
-        vu_i2c_disconnect(dev);
-        break;
-    case CHR_EVENT_BREAK:
-    case CHR_EVENT_MUX_IN:
-    case CHR_EVENT_MUX_OUT:
-        /* Ignore */
-        break;
-    }
-}
-
-static void vu_i2c_device_realize(DeviceState *dev, Error **errp)
-{
-    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
-    VHostUserI2C *i2c = VHOST_USER_I2C(dev);
-    int ret;
-
-    if (!i2c->chardev.chr) {
-        error_setg(errp, "vhost-user-i2c: missing chardev");
-        return;
-    }
-
-    if (!vhost_user_init(&i2c->vhost_user, &i2c->chardev, errp)) {
-        return;
-    }
-
-    virtio_init(vdev, VIRTIO_ID_I2C_ADAPTER, 0);
-
-    i2c->vhost_dev.nvqs = 1;
-    i2c->vq = virtio_add_queue(vdev, 4, vu_i2c_handle_output);
-    i2c->vhost_dev.vqs = g_new0(struct vhost_virtqueue, i2c->vhost_dev.nvqs);
-
-    ret = vhost_dev_init(&i2c->vhost_dev, &i2c->vhost_user,
-                         VHOST_BACKEND_TYPE_USER, 0, errp);
-    if (ret < 0) {
-        g_free(i2c->vhost_dev.vqs);
-        do_vhost_user_cleanup(vdev, i2c);
-    }
-
-    qemu_chr_fe_set_handlers(&i2c->chardev, NULL, NULL, vu_i2c_event, NULL,
-                             dev, NULL, true);
-}
-
-static void vu_i2c_device_unrealize(DeviceState *dev)
-{
-    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
-    VHostUserI2C *i2c = VHOST_USER_I2C(dev);
-    struct vhost_virtqueue *vhost_vqs = i2c->vhost_dev.vqs;
-
-    /* This will stop vhost backend if appropriate. */
-    vu_i2c_set_status(vdev, 0);
-    vhost_dev_cleanup(&i2c->vhost_dev);
-    g_free(vhost_vqs);
-    do_vhost_user_cleanup(vdev, i2c);
+    vubc->parent_realize(dev, errp);
 }
 
 static const VMStateDescription vu_i2c_vmstate = {
@@ -268,30 +36,21 @@ static const VMStateDescription vu_i2c_vmstate = {
     .unmigratable = 1,
 };
 
-static Property vu_i2c_properties[] = {
-    DEFINE_PROP_CHR("chardev", VHostUserI2C, chardev),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
 static void vu_i2c_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
+    VHostUserBaseClass *vubc = VHOST_USER_BASE_CLASS(klass);
 
-    device_class_set_props(dc, vu_i2c_properties);
     dc->vmsd = &vu_i2c_vmstate;
+    device_class_set_props(dc, vi2c_properties);
+    device_class_set_parent_realize(dc, vi2c_realize,
+                                    &vubc->parent_realize);
     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
-    vdc->realize = vu_i2c_device_realize;
-    vdc->unrealize = vu_i2c_device_unrealize;
-    vdc->get_features = vu_i2c_get_features;
-    vdc->set_status = vu_i2c_set_status;
-    vdc->guest_notifier_mask = vu_i2c_guest_notifier_mask;
-    vdc->guest_notifier_pending = vu_i2c_guest_notifier_pending;
 }
 
 static const TypeInfo vu_i2c_info = {
     .name = TYPE_VHOST_USER_I2C,
-    .parent = TYPE_VIRTIO_DEVICE,
+    .parent = TYPE_VHOST_USER_BASE,
     .instance_size = sizeof(VHostUserI2C),
     .class_init = vu_i2c_class_init,
 };
diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build
index 62ab2d82e0..d1d6892068 100644
--- a/hw/virtio/meson.build
+++ b/hw/virtio/meson.build
@@ -14,6 +14,9 @@ softmmu_virtio_ss.add(when: ['CONFIG_VIRTIO_PCI', 'CONFIG_VHOST_USER_RNG'],
 softmmu_virtio_ss.add(when: 'CONFIG_VHOST_USER_GPIO', if_true: files('vhost-user-gpio.c'))
 softmmu_virtio_ss.add(when: ['CONFIG_VIRTIO_PCI', 'CONFIG_VHOST_USER_GPIO'],
                       if_true: files('vhost-user-gpio-pci.c'))
+softmmu_virtio_ss.add(when: 'CONFIG_VHOST_USER_I2C', if_true: files('vhost-user-i2c.c'))
+softmmu_virtio_ss.add(when: ['CONFIG_VIRTIO_PCI', 'CONFIG_VHOST_USER_I2C'],
+                       if_true: files('vhost-user-i2c-pci.c'))
 
 specific_virtio_ss = ss.source_set()
 specific_virtio_ss.add(files('virtio.c'))
@@ -42,13 +45,11 @@ specific_virtio_ss.add(when: 'CONFIG_VHOST_VSOCK', if_true: files('vhost-vsock.c
 specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_VSOCK', if_true: files('vhost-user-vsock.c'))
 specific_virtio_ss.add(when: 'CONFIG_VIRTIO_RNG', if_true: files('virtio-rng.c'))
 specific_virtio_ss.add(when: 'CONFIG_VIRTIO_MEM', if_true: files('virtio-mem.c'))
-specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_I2C', if_true: files('vhost-user-i2c.c'))
 
 virtio_pci_ss = ss.source_set()
 virtio_pci_ss.add(when: 'CONFIG_VHOST_VSOCK', if_true: files('vhost-vsock-pci.c'))
 virtio_pci_ss.add(when: 'CONFIG_VHOST_USER_VSOCK', if_true: files('vhost-user-vsock-pci.c'))
 virtio_pci_ss.add(when: 'CONFIG_VHOST_USER_BLK', if_true: files('vhost-user-blk-pci.c'))
-virtio_pci_ss.add(when: 'CONFIG_VHOST_USER_I2C', if_true: files('vhost-user-i2c-pci.c'))
 virtio_pci_ss.add(when: 'CONFIG_VHOST_USER_INPUT', if_true: files('vhost-user-input-pci.c'))
 virtio_pci_ss.add(when: 'CONFIG_VHOST_USER_SCSI', if_true: files('vhost-user-scsi-pci.c'))
 virtio_pci_ss.add(when: 'CONFIG_VHOST_SCSI', if_true: files('vhost-scsi-pci.c'))
-- 
2.39.2



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Virtio-fs] [PATCH v3 12/20] hw/virtio: derive vhost-user-i2c from vhost-user-base
@ 2023-07-10 15:35   ` Alex Bennée
  0 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

Now we can take advantage of the new base class and make
vhost-user-i2c a much simpler boilerplate wrapper. Also as this
doesn't require any target specific hacks we only need to build the
stubs once.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>

---
v2
  - update to new inheritance scheme
  - move build to common code
v3
  - fix merge conflict in meson
---
 include/hw/virtio/vhost-user-i2c.h |  18 +-
 hw/virtio/vhost-user-i2c.c         | 271 ++---------------------------
 hw/virtio/meson.build              |   5 +-
 3 files changed, 26 insertions(+), 268 deletions(-)

diff --git a/include/hw/virtio/vhost-user-i2c.h b/include/hw/virtio/vhost-user-i2c.h
index 0f7acd40e3..47153782d1 100644
--- a/include/hw/virtio/vhost-user-i2c.h
+++ b/include/hw/virtio/vhost-user-i2c.h
@@ -12,20 +12,18 @@
 #include "hw/virtio/vhost.h"
 #include "hw/virtio/vhost-user.h"
 
+#include "hw/virtio/virtio.h"
+#include "hw/virtio/vhost.h"
+#include "hw/virtio/vhost-user.h"
+#include "hw/virtio/vhost-user-device.h"
+
 #define TYPE_VHOST_USER_I2C "vhost-user-i2c-device"
 OBJECT_DECLARE_SIMPLE_TYPE(VHostUserI2C, VHOST_USER_I2C)
 
 struct VHostUserI2C {
-    VirtIODevice parent;
-    CharBackend chardev;
-    struct vhost_virtqueue *vhost_vq;
-    struct vhost_dev vhost_dev;
-    VhostUserState vhost_user;
-    VirtQueue *vq;
-    bool connected;
+    /*< private >*/
+    VHostUserBase parent;
+    /*< public >*/
 };
 
-/* Virtio Feature bits */
-#define VIRTIO_I2C_F_ZERO_LENGTH_REQUEST		0
-
 #endif /* QEMU_VHOST_USER_I2C_H */
diff --git a/hw/virtio/vhost-user-i2c.c b/hw/virtio/vhost-user-i2c.c
index 4eef3f0633..4a1f644a87 100644
--- a/hw/virtio/vhost-user-i2c.c
+++ b/hw/virtio/vhost-user-i2c.c
@@ -14,253 +14,21 @@
 #include "qemu/error-report.h"
 #include "standard-headers/linux/virtio_ids.h"
 
-static const int feature_bits[] = {
-    VIRTIO_I2C_F_ZERO_LENGTH_REQUEST,
-    VIRTIO_F_RING_RESET,
-    VHOST_INVALID_FEATURE_BIT
+static Property vi2c_properties[] = {
+    DEFINE_PROP_CHR("chardev", VHostUserBase, chardev),
+    DEFINE_PROP_END_OF_LIST(),
 };
 
-static void vu_i2c_start(VirtIODevice *vdev)
-{
-    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
-    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
-    VHostUserI2C *i2c = VHOST_USER_I2C(vdev);
-    int ret, i;
-
-    if (!k->set_guest_notifiers) {
-        error_report("binding does not support guest notifiers");
-        return;
-    }
-
-    ret = vhost_dev_enable_notifiers(&i2c->vhost_dev, vdev);
-    if (ret < 0) {
-        error_report("Error enabling host notifiers: %d", -ret);
-        return;
-    }
-
-    ret = k->set_guest_notifiers(qbus->parent, i2c->vhost_dev.nvqs, true);
-    if (ret < 0) {
-        error_report("Error binding guest notifier: %d", -ret);
-        goto err_host_notifiers;
-    }
-
-    i2c->vhost_dev.acked_features = vdev->guest_features;
-
-    ret = vhost_dev_start(&i2c->vhost_dev, vdev, true);
-    if (ret < 0) {
-        error_report("Error starting vhost-user-i2c: %d", -ret);
-        goto err_guest_notifiers;
-    }
-
-    /*
-     * guest_notifier_mask/pending not used yet, so just unmask
-     * everything here. virtio-pci will do the right thing by
-     * enabling/disabling irqfd.
-     */
-    for (i = 0; i < i2c->vhost_dev.nvqs; i++) {
-        vhost_virtqueue_mask(&i2c->vhost_dev, vdev, i, false);
-    }
-
-    return;
-
-err_guest_notifiers:
-    k->set_guest_notifiers(qbus->parent, i2c->vhost_dev.nvqs, false);
-err_host_notifiers:
-    vhost_dev_disable_notifiers(&i2c->vhost_dev, vdev);
-}
-
-static void vu_i2c_stop(VirtIODevice *vdev)
-{
-    VHostUserI2C *i2c = VHOST_USER_I2C(vdev);
-    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
-    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
-    int ret;
-
-    if (!k->set_guest_notifiers) {
-        return;
-    }
-
-    vhost_dev_stop(&i2c->vhost_dev, vdev, true);
-
-    ret = k->set_guest_notifiers(qbus->parent, i2c->vhost_dev.nvqs, false);
-    if (ret < 0) {
-        error_report("vhost guest notifier cleanup failed: %d", ret);
-        return;
-    }
-
-    vhost_dev_disable_notifiers(&i2c->vhost_dev, vdev);
-}
-
-static void vu_i2c_set_status(VirtIODevice *vdev, uint8_t status)
-{
-    VHostUserI2C *i2c = VHOST_USER_I2C(vdev);
-    bool should_start = virtio_device_should_start(vdev, status);
-
-    if (vhost_dev_is_started(&i2c->vhost_dev) == should_start) {
-        return;
-    }
-
-    if (should_start) {
-        vu_i2c_start(vdev);
-    } else {
-        vu_i2c_stop(vdev);
-    }
-}
-
-static uint64_t vu_i2c_get_features(VirtIODevice *vdev,
-                                    uint64_t requested_features, Error **errp)
-{
-    VHostUserI2C *i2c = VHOST_USER_I2C(vdev);
-
-    virtio_add_feature(&requested_features, VIRTIO_I2C_F_ZERO_LENGTH_REQUEST);
-    return vhost_get_features(&i2c->vhost_dev, feature_bits, requested_features);
-}
-
-static void vu_i2c_handle_output(VirtIODevice *vdev, VirtQueue *vq)
-{
-    /*
-     * Not normally called; it's the daemon that handles the queue;
-     * however virtio's cleanup path can call this.
-     */
-}
-
-static void vu_i2c_guest_notifier_mask(VirtIODevice *vdev, int idx, bool mask)
-{
-    VHostUserI2C *i2c = VHOST_USER_I2C(vdev);
-
-    /*
-     * We don't support interrupts, return early if index is set to
-     * VIRTIO_CONFIG_IRQ_IDX.
-     */
-    if (idx == VIRTIO_CONFIG_IRQ_IDX) {
-        return;
-    }
-
-    vhost_virtqueue_mask(&i2c->vhost_dev, vdev, idx, mask);
-}
-
-static bool vu_i2c_guest_notifier_pending(VirtIODevice *vdev, int idx)
-{
-    VHostUserI2C *i2c = VHOST_USER_I2C(vdev);
-
-    /*
-     * We don't support interrupts, return early if index is set to
-     * VIRTIO_CONFIG_IRQ_IDX.
-     */
-    if (idx == VIRTIO_CONFIG_IRQ_IDX) {
-        return false;
-    }
-
-    return vhost_virtqueue_pending(&i2c->vhost_dev, idx);
-}
-
-static void do_vhost_user_cleanup(VirtIODevice *vdev, VHostUserI2C *i2c)
-{
-    vhost_user_cleanup(&i2c->vhost_user);
-    virtio_delete_queue(i2c->vq);
-    virtio_cleanup(vdev);
-}
-
-static int vu_i2c_connect(DeviceState *dev)
+static void vi2c_realize(DeviceState *dev, Error **errp)
 {
-    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
-    VHostUserI2C *i2c = VHOST_USER_I2C(vdev);
+    VHostUserBase *vub = VHOST_USER_BASE(dev);
+    VHostUserBaseClass *vubc = VHOST_USER_BASE_GET_CLASS(dev);
 
-    if (i2c->connected) {
-        return 0;
-    }
-    i2c->connected = true;
+    /* Fixed for I2C */
+    vub->virtio_id = VIRTIO_ID_I2C_ADAPTER;
+    vub->num_vqs = 1;
 
-    /* restore vhost state */
-    if (virtio_device_started(vdev, vdev->status)) {
-        vu_i2c_start(vdev);
-    }
-
-    return 0;
-}
-
-static void vu_i2c_disconnect(DeviceState *dev)
-{
-    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
-    VHostUserI2C *i2c = VHOST_USER_I2C(vdev);
-
-    if (!i2c->connected) {
-        return;
-    }
-    i2c->connected = false;
-
-    if (vhost_dev_is_started(&i2c->vhost_dev)) {
-        vu_i2c_stop(vdev);
-    }
-}
-
-static void vu_i2c_event(void *opaque, QEMUChrEvent event)
-{
-    DeviceState *dev = opaque;
-    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
-    VHostUserI2C *i2c = VHOST_USER_I2C(vdev);
-
-    switch (event) {
-    case CHR_EVENT_OPENED:
-        if (vu_i2c_connect(dev) < 0) {
-            qemu_chr_fe_disconnect(&i2c->chardev);
-            return;
-        }
-        break;
-    case CHR_EVENT_CLOSED:
-        vu_i2c_disconnect(dev);
-        break;
-    case CHR_EVENT_BREAK:
-    case CHR_EVENT_MUX_IN:
-    case CHR_EVENT_MUX_OUT:
-        /* Ignore */
-        break;
-    }
-}
-
-static void vu_i2c_device_realize(DeviceState *dev, Error **errp)
-{
-    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
-    VHostUserI2C *i2c = VHOST_USER_I2C(dev);
-    int ret;
-
-    if (!i2c->chardev.chr) {
-        error_setg(errp, "vhost-user-i2c: missing chardev");
-        return;
-    }
-
-    if (!vhost_user_init(&i2c->vhost_user, &i2c->chardev, errp)) {
-        return;
-    }
-
-    virtio_init(vdev, VIRTIO_ID_I2C_ADAPTER, 0);
-
-    i2c->vhost_dev.nvqs = 1;
-    i2c->vq = virtio_add_queue(vdev, 4, vu_i2c_handle_output);
-    i2c->vhost_dev.vqs = g_new0(struct vhost_virtqueue, i2c->vhost_dev.nvqs);
-
-    ret = vhost_dev_init(&i2c->vhost_dev, &i2c->vhost_user,
-                         VHOST_BACKEND_TYPE_USER, 0, errp);
-    if (ret < 0) {
-        g_free(i2c->vhost_dev.vqs);
-        do_vhost_user_cleanup(vdev, i2c);
-    }
-
-    qemu_chr_fe_set_handlers(&i2c->chardev, NULL, NULL, vu_i2c_event, NULL,
-                             dev, NULL, true);
-}
-
-static void vu_i2c_device_unrealize(DeviceState *dev)
-{
-    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
-    VHostUserI2C *i2c = VHOST_USER_I2C(dev);
-    struct vhost_virtqueue *vhost_vqs = i2c->vhost_dev.vqs;
-
-    /* This will stop vhost backend if appropriate. */
-    vu_i2c_set_status(vdev, 0);
-    vhost_dev_cleanup(&i2c->vhost_dev);
-    g_free(vhost_vqs);
-    do_vhost_user_cleanup(vdev, i2c);
+    vubc->parent_realize(dev, errp);
 }
 
 static const VMStateDescription vu_i2c_vmstate = {
@@ -268,30 +36,21 @@ static const VMStateDescription vu_i2c_vmstate = {
     .unmigratable = 1,
 };
 
-static Property vu_i2c_properties[] = {
-    DEFINE_PROP_CHR("chardev", VHostUserI2C, chardev),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
 static void vu_i2c_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
+    VHostUserBaseClass *vubc = VHOST_USER_BASE_CLASS(klass);
 
-    device_class_set_props(dc, vu_i2c_properties);
     dc->vmsd = &vu_i2c_vmstate;
+    device_class_set_props(dc, vi2c_properties);
+    device_class_set_parent_realize(dc, vi2c_realize,
+                                    &vubc->parent_realize);
     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
-    vdc->realize = vu_i2c_device_realize;
-    vdc->unrealize = vu_i2c_device_unrealize;
-    vdc->get_features = vu_i2c_get_features;
-    vdc->set_status = vu_i2c_set_status;
-    vdc->guest_notifier_mask = vu_i2c_guest_notifier_mask;
-    vdc->guest_notifier_pending = vu_i2c_guest_notifier_pending;
 }
 
 static const TypeInfo vu_i2c_info = {
     .name = TYPE_VHOST_USER_I2C,
-    .parent = TYPE_VIRTIO_DEVICE,
+    .parent = TYPE_VHOST_USER_BASE,
     .instance_size = sizeof(VHostUserI2C),
     .class_init = vu_i2c_class_init,
 };
diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build
index 62ab2d82e0..d1d6892068 100644
--- a/hw/virtio/meson.build
+++ b/hw/virtio/meson.build
@@ -14,6 +14,9 @@ softmmu_virtio_ss.add(when: ['CONFIG_VIRTIO_PCI', 'CONFIG_VHOST_USER_RNG'],
 softmmu_virtio_ss.add(when: 'CONFIG_VHOST_USER_GPIO', if_true: files('vhost-user-gpio.c'))
 softmmu_virtio_ss.add(when: ['CONFIG_VIRTIO_PCI', 'CONFIG_VHOST_USER_GPIO'],
                       if_true: files('vhost-user-gpio-pci.c'))
+softmmu_virtio_ss.add(when: 'CONFIG_VHOST_USER_I2C', if_true: files('vhost-user-i2c.c'))
+softmmu_virtio_ss.add(when: ['CONFIG_VIRTIO_PCI', 'CONFIG_VHOST_USER_I2C'],
+                       if_true: files('vhost-user-i2c-pci.c'))
 
 specific_virtio_ss = ss.source_set()
 specific_virtio_ss.add(files('virtio.c'))
@@ -42,13 +45,11 @@ specific_virtio_ss.add(when: 'CONFIG_VHOST_VSOCK', if_true: files('vhost-vsock.c
 specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_VSOCK', if_true: files('vhost-user-vsock.c'))
 specific_virtio_ss.add(when: 'CONFIG_VIRTIO_RNG', if_true: files('virtio-rng.c'))
 specific_virtio_ss.add(when: 'CONFIG_VIRTIO_MEM', if_true: files('virtio-mem.c'))
-specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_I2C', if_true: files('vhost-user-i2c.c'))
 
 virtio_pci_ss = ss.source_set()
 virtio_pci_ss.add(when: 'CONFIG_VHOST_VSOCK', if_true: files('vhost-vsock-pci.c'))
 virtio_pci_ss.add(when: 'CONFIG_VHOST_USER_VSOCK', if_true: files('vhost-user-vsock-pci.c'))
 virtio_pci_ss.add(when: 'CONFIG_VHOST_USER_BLK', if_true: files('vhost-user-blk-pci.c'))
-virtio_pci_ss.add(when: 'CONFIG_VHOST_USER_I2C', if_true: files('vhost-user-i2c-pci.c'))
 virtio_pci_ss.add(when: 'CONFIG_VHOST_USER_INPUT', if_true: files('vhost-user-input-pci.c'))
 virtio_pci_ss.add(when: 'CONFIG_VHOST_USER_SCSI', if_true: files('vhost-user-scsi-pci.c'))
 virtio_pci_ss.add(when: 'CONFIG_VHOST_SCSI', if_true: files('vhost-scsi-pci.c'))
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [RFC PATCH v3 13/20] docs/system: add a basic enumeration of vhost-user devices
  2023-07-10 15:35 ` [Virtio-fs] " Alex Bennée
@ 2023-07-10 15:35   ` Alex Bennée
  -1 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

Make it clear the vhost-user-device is intended for expert use only.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>

---
v2
  - make clear vhost-user-device for expert use
---
 docs/system/devices/vhost-user-rng.rst |  2 ++
 docs/system/devices/vhost-user.rst     | 41 ++++++++++++++++++++++++++
 2 files changed, 43 insertions(+)

diff --git a/docs/system/devices/vhost-user-rng.rst b/docs/system/devices/vhost-user-rng.rst
index a145d4105c..ead1405326 100644
--- a/docs/system/devices/vhost-user-rng.rst
+++ b/docs/system/devices/vhost-user-rng.rst
@@ -1,3 +1,5 @@
+.. _vhost_user_rng:
+
 QEMU vhost-user-rng - RNG emulation
 ===================================
 
diff --git a/docs/system/devices/vhost-user.rst b/docs/system/devices/vhost-user.rst
index a80e95a48a..0f9eec3f00 100644
--- a/docs/system/devices/vhost-user.rst
+++ b/docs/system/devices/vhost-user.rst
@@ -15,6 +15,47 @@ to the guest. The code is mostly boilerplate although each device has
 a ``chardev`` option which specifies the ID of the ``--chardev``
 device that connects via a socket to the vhost-user *daemon*.
 
+Each device will have an virtio-mmio and virtio-pci variant. See your
+platform details for what sort of virtio bus to use.
+
+.. list-table:: vhost-user devices
+  :widths: 20 20 60
+  :header-rows: 1
+
+  * - Device
+    - Type
+    - Notes
+  * - vhost-user-device
+    - Generic Development Device
+    - You must manually specify ``virtio-id`` and the correct ``num_vqs``. Intended for expert use.
+  * - vhost-user-blk
+    - Block storage
+    -
+  * - vhost-user-fs
+    - File based storage driver
+    - See https://gitlab.com/virtio-fs/virtiofsd
+  * - vhost-user-scsi
+    - SCSI based storage
+    - See contrib/vhost-user/scsi
+  * - vhost-user-gpio
+    - Proxy gpio pins to host
+    - See https://github.com/rust-vmm/vhost-device
+  * - vhost-user-i2c
+    - Proxy i2c devices to host
+    - See https://github.com/rust-vmm/vhost-device
+  * - vhost-user-input
+    - Generic input driver
+    - See contrib/vhost-user-input
+  * - vhost-user-rng
+    - Entropy driver
+    - :ref:`vhost_user_rng`
+  * - vhost-user-gpu
+    - GPU driver
+    -
+  * - vhost-user-vsock
+    - Socket based communication
+    - See https://github.com/rust-vmm/vhost-device
+
 vhost-user daemon
 =================
 
-- 
2.39.2



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Virtio-fs] [RFC PATCH v3 13/20] docs/system: add a basic enumeration of vhost-user devices
@ 2023-07-10 15:35   ` Alex Bennée
  0 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

Make it clear the vhost-user-device is intended for expert use only.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>

---
v2
  - make clear vhost-user-device for expert use
---
 docs/system/devices/vhost-user-rng.rst |  2 ++
 docs/system/devices/vhost-user.rst     | 41 ++++++++++++++++++++++++++
 2 files changed, 43 insertions(+)

diff --git a/docs/system/devices/vhost-user-rng.rst b/docs/system/devices/vhost-user-rng.rst
index a145d4105c..ead1405326 100644
--- a/docs/system/devices/vhost-user-rng.rst
+++ b/docs/system/devices/vhost-user-rng.rst
@@ -1,3 +1,5 @@
+.. _vhost_user_rng:
+
 QEMU vhost-user-rng - RNG emulation
 ===================================
 
diff --git a/docs/system/devices/vhost-user.rst b/docs/system/devices/vhost-user.rst
index a80e95a48a..0f9eec3f00 100644
--- a/docs/system/devices/vhost-user.rst
+++ b/docs/system/devices/vhost-user.rst
@@ -15,6 +15,47 @@ to the guest. The code is mostly boilerplate although each device has
 a ``chardev`` option which specifies the ID of the ``--chardev``
 device that connects via a socket to the vhost-user *daemon*.
 
+Each device will have an virtio-mmio and virtio-pci variant. See your
+platform details for what sort of virtio bus to use.
+
+.. list-table:: vhost-user devices
+  :widths: 20 20 60
+  :header-rows: 1
+
+  * - Device
+    - Type
+    - Notes
+  * - vhost-user-device
+    - Generic Development Device
+    - You must manually specify ``virtio-id`` and the correct ``num_vqs``. Intended for expert use.
+  * - vhost-user-blk
+    - Block storage
+    -
+  * - vhost-user-fs
+    - File based storage driver
+    - See https://gitlab.com/virtio-fs/virtiofsd
+  * - vhost-user-scsi
+    - SCSI based storage
+    - See contrib/vhost-user/scsi
+  * - vhost-user-gpio
+    - Proxy gpio pins to host
+    - See https://github.com/rust-vmm/vhost-device
+  * - vhost-user-i2c
+    - Proxy i2c devices to host
+    - See https://github.com/rust-vmm/vhost-device
+  * - vhost-user-input
+    - Generic input driver
+    - See contrib/vhost-user-input
+  * - vhost-user-rng
+    - Entropy driver
+    - :ref:`vhost_user_rng`
+  * - vhost-user-gpu
+    - GPU driver
+    -
+  * - vhost-user-vsock
+    - Socket based communication
+    - See https://github.com/rust-vmm/vhost-device
+
 vhost-user daemon
 =================
 
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [RFC PATCH v3 14/20] docs/interop: define STANDALONE protocol feature for vhost-user
  2023-07-10 15:35 ` [Virtio-fs] " Alex Bennée
@ 2023-07-10 15:35   ` Alex Bennée
  -1 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

Currently QEMU has to know some details about the back-end to be able
to setup the guest. While various parts of the setup can be delegated
to the backend (for example config handling) this is a very piecemeal
approach.

This patch suggests a new feature flag (VHOST_USER_PROTOCOL_F_STANDALONE)
which the back-end can advertise which allows a probe message to be
sent to get all the details QEMU needs to know in one message.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>

---
Initial RFC for discussion. I intend to prototype this work with QEMU
and one of the rust-vmm vhost-user daemons.
---
 docs/interop/vhost-user.rst | 39 +++++++++++++++++++++++++++++++++++++
 hw/virtio/vhost-user.c      |  8 ++++++++
 2 files changed, 47 insertions(+)

diff --git a/docs/interop/vhost-user.rst b/docs/interop/vhost-user.rst
index 5a070adbc1..a2080f56f3 100644
--- a/docs/interop/vhost-user.rst
+++ b/docs/interop/vhost-user.rst
@@ -275,6 +275,21 @@ Inflight description
 
 :queue size: a 16-bit size of virtqueues
 
+Backend specifications
+^^^^^^^^^^^^^^^^^^^^^^
+
++-----------+-------------+------------+------------+
+| device id | config size |   min_vqs  |   max_vqs  |
++-----------+-------------+------------+------------+
+
+:device id: a 32-bit value holding the VirtIO device ID
+
+:config size: a 32-bit value holding the config size (see ``VHOST_USER_GET_CONFIG``)
+
+:min_vqs: a 32-bit value holding the minimum number of vqs supported
+
+:max_vqs: a 32-bit value holding the maximum number of vqs supported, must be >= min_vqs
+
 C structure
 -----------
 
@@ -296,6 +311,7 @@ In QEMU the vhost-user message is implemented with the following struct:
           VhostUserConfig config;
           VhostUserVringArea area;
           VhostUserInflight inflight;
+          VhostUserBackendSpecs specs;
       };
   } QEMU_PACKED VhostUserMsg;
 
@@ -316,6 +332,7 @@ replies. Here is a list of the ones that do:
 * ``VHOST_USER_GET_VRING_BASE``
 * ``VHOST_USER_SET_LOG_BASE`` (if ``VHOST_USER_PROTOCOL_F_LOG_SHMFD``)
 * ``VHOST_USER_GET_INFLIGHT_FD`` (if ``VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD``)
+* ``VHOST_USER_GET_BACKEND_SPECS`` (if ``VHOST_USER_PROTOCOL_F_STANDALONE``)
 
 .. seealso::
 
@@ -885,6 +902,15 @@ Protocol features
   #define VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS  15
   #define VHOST_USER_PROTOCOL_F_STATUS               16
   #define VHOST_USER_PROTOCOL_F_XEN_MMAP             17
+  #define VHOST_USER_PROTOCOL_F_STANDALONE           18
+
+Some features depend on others to be supported:
+
+* ``VHOST_USER_PROTOCOL_F_STANDALONE`` depends on:
+
+  * ``VHOST_USER_PROTOCOL_F_STATUS``
+  * ``VHOST_USER_PROTOCOL_F_CONFIG`` (if there is a config space)
+
 
 Front-end message types
 -----------------------
@@ -1440,6 +1466,19 @@ Front-end message types
   query the back-end for its device status as defined in the Virtio
   specification.
 
+``VHOST_USER_GET_BACKEND_SPECS``
+  :id: 41
+  :request payload: N/A
+  :reply payload: ``Backend specifications``
+
+  When the ``VHOST_USER_PROTOCOL_F_STANDALONE`` protocol feature has been
+  successfully negotiated, this message is submitted by the front-end to
+  query the back-end for its capabilities. This is intended to remove
+  the need for the front-end to know ahead of time what the VirtIO
+  device the backend emulates is.
+
+  The reply contains the device id, size of the config space and the
+  range of VirtQueues the backend supports.
 
 Back-end message types
 ----------------------
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index c4e0cbd702..28b021d5d3 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -202,6 +202,13 @@ typedef struct VhostUserInflight {
     uint16_t queue_size;
 } VhostUserInflight;
 
+typedef struct VhostUserBackendSpecs {
+    uint32_t device_id;
+    uint32_t config_size;
+    uint32_t min_vqs;
+    uint32_t max_vqs;
+} VhostUserBackendSpecs;
+
 typedef struct {
     VhostUserRequest request;
 
@@ -226,6 +233,7 @@ typedef union {
         VhostUserCryptoSession session;
         VhostUserVringArea area;
         VhostUserInflight inflight;
+        VhostUserBackendSpecs specs;
 } VhostUserPayload;
 
 typedef struct VhostUserMsg {
-- 
2.39.2



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Virtio-fs] [RFC PATCH v3 14/20] docs/interop: define STANDALONE protocol feature for vhost-user
@ 2023-07-10 15:35   ` Alex Bennée
  0 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

Currently QEMU has to know some details about the back-end to be able
to setup the guest. While various parts of the setup can be delegated
to the backend (for example config handling) this is a very piecemeal
approach.

This patch suggests a new feature flag (VHOST_USER_PROTOCOL_F_STANDALONE)
which the back-end can advertise which allows a probe message to be
sent to get all the details QEMU needs to know in one message.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>

---
Initial RFC for discussion. I intend to prototype this work with QEMU
and one of the rust-vmm vhost-user daemons.
---
 docs/interop/vhost-user.rst | 39 +++++++++++++++++++++++++++++++++++++
 hw/virtio/vhost-user.c      |  8 ++++++++
 2 files changed, 47 insertions(+)

diff --git a/docs/interop/vhost-user.rst b/docs/interop/vhost-user.rst
index 5a070adbc1..a2080f56f3 100644
--- a/docs/interop/vhost-user.rst
+++ b/docs/interop/vhost-user.rst
@@ -275,6 +275,21 @@ Inflight description
 
 :queue size: a 16-bit size of virtqueues
 
+Backend specifications
+^^^^^^^^^^^^^^^^^^^^^^
+
++-----------+-------------+------------+------------+
+| device id | config size |   min_vqs  |   max_vqs  |
++-----------+-------------+------------+------------+
+
+:device id: a 32-bit value holding the VirtIO device ID
+
+:config size: a 32-bit value holding the config size (see ``VHOST_USER_GET_CONFIG``)
+
+:min_vqs: a 32-bit value holding the minimum number of vqs supported
+
+:max_vqs: a 32-bit value holding the maximum number of vqs supported, must be >= min_vqs
+
 C structure
 -----------
 
@@ -296,6 +311,7 @@ In QEMU the vhost-user message is implemented with the following struct:
           VhostUserConfig config;
           VhostUserVringArea area;
           VhostUserInflight inflight;
+          VhostUserBackendSpecs specs;
       };
   } QEMU_PACKED VhostUserMsg;
 
@@ -316,6 +332,7 @@ replies. Here is a list of the ones that do:
 * ``VHOST_USER_GET_VRING_BASE``
 * ``VHOST_USER_SET_LOG_BASE`` (if ``VHOST_USER_PROTOCOL_F_LOG_SHMFD``)
 * ``VHOST_USER_GET_INFLIGHT_FD`` (if ``VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD``)
+* ``VHOST_USER_GET_BACKEND_SPECS`` (if ``VHOST_USER_PROTOCOL_F_STANDALONE``)
 
 .. seealso::
 
@@ -885,6 +902,15 @@ Protocol features
   #define VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS  15
   #define VHOST_USER_PROTOCOL_F_STATUS               16
   #define VHOST_USER_PROTOCOL_F_XEN_MMAP             17
+  #define VHOST_USER_PROTOCOL_F_STANDALONE           18
+
+Some features depend on others to be supported:
+
+* ``VHOST_USER_PROTOCOL_F_STANDALONE`` depends on:
+
+  * ``VHOST_USER_PROTOCOL_F_STATUS``
+  * ``VHOST_USER_PROTOCOL_F_CONFIG`` (if there is a config space)
+
 
 Front-end message types
 -----------------------
@@ -1440,6 +1466,19 @@ Front-end message types
   query the back-end for its device status as defined in the Virtio
   specification.
 
+``VHOST_USER_GET_BACKEND_SPECS``
+  :id: 41
+  :request payload: N/A
+  :reply payload: ``Backend specifications``
+
+  When the ``VHOST_USER_PROTOCOL_F_STANDALONE`` protocol feature has been
+  successfully negotiated, this message is submitted by the front-end to
+  query the back-end for its capabilities. This is intended to remove
+  the need for the front-end to know ahead of time what the VirtIO
+  device the backend emulates is.
+
+  The reply contains the device id, size of the config space and the
+  range of VirtQueues the backend supports.
 
 Back-end message types
 ----------------------
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index c4e0cbd702..28b021d5d3 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -202,6 +202,13 @@ typedef struct VhostUserInflight {
     uint16_t queue_size;
 } VhostUserInflight;
 
+typedef struct VhostUserBackendSpecs {
+    uint32_t device_id;
+    uint32_t config_size;
+    uint32_t min_vqs;
+    uint32_t max_vqs;
+} VhostUserBackendSpecs;
+
 typedef struct {
     VhostUserRequest request;
 
@@ -226,6 +233,7 @@ typedef union {
         VhostUserCryptoSession session;
         VhostUserVringArea area;
         VhostUserInflight inflight;
+        VhostUserBackendSpecs specs;
 } VhostUserPayload;
 
 typedef struct VhostUserMsg {
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [RFC PATCH v3 15/20] hw/virtio: move vhost_user_init earlier
  2023-07-10 15:35 ` [Virtio-fs] " Alex Bennée
@ 2023-07-10 15:35   ` Alex Bennée
  -1 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

In preparation for getting the details of the VirtIO device directly
from the vhost-user daemon we should connect once we have validated
the chardev. We will actually move the connection in the next patch to
keep the changes small and bisectable.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
 hw/virtio/vhost-user-device.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/hw/virtio/vhost-user-device.c b/hw/virtio/vhost-user-device.c
index 2b028cae08..d787f52364 100644
--- a/hw/virtio/vhost-user-device.c
+++ b/hw/virtio/vhost-user-device.c
@@ -250,6 +250,10 @@ static void vub_device_realize(DeviceState *dev, Error **errp)
         return;
     }
 
+    if (!vhost_user_init(&vub->vhost_user, &vub->chardev, errp)) {
+        return;
+    }
+
     if (!vub->virtio_id) {
         error_setg(errp, "vhost-user-device: need to define device id");
         return;
@@ -268,10 +272,6 @@ static void vub_device_realize(DeviceState *dev, Error **errp)
         vub->vhost_user.supports_config = true;
     }
 
-    if (!vhost_user_init(&vub->vhost_user, &vub->chardev, errp)) {
-        return;
-    }
-
     virtio_init(vdev, vub->virtio_id, vub->config_size);
 
     /*
-- 
2.39.2



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Virtio-fs] [RFC PATCH v3 15/20] hw/virtio: move vhost_user_init earlier
@ 2023-07-10 15:35   ` Alex Bennée
  0 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

In preparation for getting the details of the VirtIO device directly
from the vhost-user daemon we should connect once we have validated
the chardev. We will actually move the connection in the next patch to
keep the changes small and bisectable.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
 hw/virtio/vhost-user-device.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/hw/virtio/vhost-user-device.c b/hw/virtio/vhost-user-device.c
index 2b028cae08..d787f52364 100644
--- a/hw/virtio/vhost-user-device.c
+++ b/hw/virtio/vhost-user-device.c
@@ -250,6 +250,10 @@ static void vub_device_realize(DeviceState *dev, Error **errp)
         return;
     }
 
+    if (!vhost_user_init(&vub->vhost_user, &vub->chardev, errp)) {
+        return;
+    }
+
     if (!vub->virtio_id) {
         error_setg(errp, "vhost-user-device: need to define device id");
         return;
@@ -268,10 +272,6 @@ static void vub_device_realize(DeviceState *dev, Error **errp)
         vub->vhost_user.supports_config = true;
     }
 
-    if (!vhost_user_init(&vub->vhost_user, &vub->chardev, errp)) {
-        return;
-    }
-
     virtio_init(vdev, vub->virtio_id, vub->config_size);
 
     /*
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [RFC PATCH v3 16/20] hw/virtio: move virtq initialisation into internal helper
  2023-07-10 15:35 ` [Virtio-fs] " Alex Bennée
@ 2023-07-10 15:35   ` Alex Bennée
  -1 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

This will be useful if we end up having to consider initialising the
virtqs at a seperate time.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
 hw/virtio/vhost.c | 60 ++++++++++++++++++++++++++++++++---------------
 1 file changed, 41 insertions(+), 19 deletions(-)

diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 82394331bf..971df8ccc5 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1382,12 +1382,47 @@ static void vhost_virtqueue_cleanup(struct vhost_virtqueue *vq)
     }
 }
 
+/*
+ * Initialise the virtqs. This can happen soon after the initial
+ * connection if we have all the details we need or be deferred until
+ * later.
+ */
+static bool vhost_init_virtqs(struct vhost_dev *hdev, uint32_t busyloop_timeout,
+                              Error **errp)
+{
+    int i, r, n_initialized_vqs = 0;
+
+    for (i = 0; i < hdev->nvqs; ++i, ++n_initialized_vqs) {
+        r = vhost_virtqueue_init(hdev, hdev->vqs + i, hdev->vq_index + i);
+        if (r < 0) {
+            error_setg_errno(errp, -r, "Failed to initialize virtqueue %d", i);
+            /* not sure what the point of this is if we have failed... */
+            hdev->nvqs = n_initialized_vqs;
+            return false;
+        }
+    }
+
+    if (busyloop_timeout) {
+        for (i = 0; i < hdev->nvqs; ++i) {
+            r = vhost_virtqueue_set_busyloop_timeout(hdev, hdev->vq_index + i,
+                                                     busyloop_timeout);
+            if (r < 0) {
+                error_setg_errno(errp, -r, "Failed to set busyloop timeout");
+                return false;
+            }
+        }
+    }
+
+    g_assert(hdev->nvqs == n_initialized_vqs);
+    return true;
+}
+
 int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
                    VhostBackendType backend_type, uint32_t busyloop_timeout,
                    Error **errp)
 {
     uint64_t features;
-    int i, r, n_initialized_vqs = 0;
+    int i, r;
 
     hdev->vdev = NULL;
     hdev->migration_blocker = NULL;
@@ -1412,22 +1447,10 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
         goto fail;
     }
 
-    for (i = 0; i < hdev->nvqs; ++i, ++n_initialized_vqs) {
-        r = vhost_virtqueue_init(hdev, hdev->vqs + i, hdev->vq_index + i);
-        if (r < 0) {
-            error_setg_errno(errp, -r, "Failed to initialize virtqueue %d", i);
-            goto fail;
-        }
-    }
-
-    if (busyloop_timeout) {
-        for (i = 0; i < hdev->nvqs; ++i) {
-            r = vhost_virtqueue_set_busyloop_timeout(hdev, hdev->vq_index + i,
-                                                     busyloop_timeout);
-            if (r < 0) {
-                error_setg_errno(errp, -r, "Failed to set busyloop timeout");
-                goto fail_busyloop;
-            }
+    /* Skip if we don't yet have number of vqs */
+    if (hdev->vqs && hdev->nvqs) {
+        if (!vhost_init_virtqs(hdev, busyloop_timeout, errp)) {
+            goto fail_busyloop;
         }
     }
 
@@ -1492,12 +1515,11 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
 
 fail_busyloop:
     if (busyloop_timeout) {
-        while (--i >= 0) {
+        for (i = 0; i < hdev->nvqs; ++i) {
             vhost_virtqueue_set_busyloop_timeout(hdev, hdev->vq_index + i, 0);
         }
     }
 fail:
-    hdev->nvqs = n_initialized_vqs;
     vhost_dev_cleanup(hdev);
     return r;
 }
-- 
2.39.2



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Virtio-fs] [RFC PATCH v3 16/20] hw/virtio: move virtq initialisation into internal helper
@ 2023-07-10 15:35   ` Alex Bennée
  0 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

This will be useful if we end up having to consider initialising the
virtqs at a seperate time.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
 hw/virtio/vhost.c | 60 ++++++++++++++++++++++++++++++++---------------
 1 file changed, 41 insertions(+), 19 deletions(-)

diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 82394331bf..971df8ccc5 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1382,12 +1382,47 @@ static void vhost_virtqueue_cleanup(struct vhost_virtqueue *vq)
     }
 }
 
+/*
+ * Initialise the virtqs. This can happen soon after the initial
+ * connection if we have all the details we need or be deferred until
+ * later.
+ */
+static bool vhost_init_virtqs(struct vhost_dev *hdev, uint32_t busyloop_timeout,
+                              Error **errp)
+{
+    int i, r, n_initialized_vqs = 0;
+
+    for (i = 0; i < hdev->nvqs; ++i, ++n_initialized_vqs) {
+        r = vhost_virtqueue_init(hdev, hdev->vqs + i, hdev->vq_index + i);
+        if (r < 0) {
+            error_setg_errno(errp, -r, "Failed to initialize virtqueue %d", i);
+            /* not sure what the point of this is if we have failed... */
+            hdev->nvqs = n_initialized_vqs;
+            return false;
+        }
+    }
+
+    if (busyloop_timeout) {
+        for (i = 0; i < hdev->nvqs; ++i) {
+            r = vhost_virtqueue_set_busyloop_timeout(hdev, hdev->vq_index + i,
+                                                     busyloop_timeout);
+            if (r < 0) {
+                error_setg_errno(errp, -r, "Failed to set busyloop timeout");
+                return false;
+            }
+        }
+    }
+
+    g_assert(hdev->nvqs == n_initialized_vqs);
+    return true;
+}
+
 int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
                    VhostBackendType backend_type, uint32_t busyloop_timeout,
                    Error **errp)
 {
     uint64_t features;
-    int i, r, n_initialized_vqs = 0;
+    int i, r;
 
     hdev->vdev = NULL;
     hdev->migration_blocker = NULL;
@@ -1412,22 +1447,10 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
         goto fail;
     }
 
-    for (i = 0; i < hdev->nvqs; ++i, ++n_initialized_vqs) {
-        r = vhost_virtqueue_init(hdev, hdev->vqs + i, hdev->vq_index + i);
-        if (r < 0) {
-            error_setg_errno(errp, -r, "Failed to initialize virtqueue %d", i);
-            goto fail;
-        }
-    }
-
-    if (busyloop_timeout) {
-        for (i = 0; i < hdev->nvqs; ++i) {
-            r = vhost_virtqueue_set_busyloop_timeout(hdev, hdev->vq_index + i,
-                                                     busyloop_timeout);
-            if (r < 0) {
-                error_setg_errno(errp, -r, "Failed to set busyloop timeout");
-                goto fail_busyloop;
-            }
+    /* Skip if we don't yet have number of vqs */
+    if (hdev->vqs && hdev->nvqs) {
+        if (!vhost_init_virtqs(hdev, busyloop_timeout, errp)) {
+            goto fail_busyloop;
         }
     }
 
@@ -1492,12 +1515,11 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
 
 fail_busyloop:
     if (busyloop_timeout) {
-        while (--i >= 0) {
+        for (i = 0; i < hdev->nvqs; ++i) {
             vhost_virtqueue_set_busyloop_timeout(hdev, hdev->vq_index + i, 0);
         }
     }
 fail:
-    hdev->nvqs = n_initialized_vqs;
     vhost_dev_cleanup(hdev);
     return r;
 }
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [RFC PATCH v3 17/20] hw/virtio: push down allocation responsibility for vhost_dev->vqs
  2023-07-10 15:35 ` [Virtio-fs] " Alex Bennée
@ 2023-07-10 15:35   ` Alex Bennée
  -1 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

All the allocations are a function the number of vqs we are allocating
so let the vhost code deal with it directly. This allows to eliminate
some complexity of the clean-up code (because vhost_dev_init cleanups
after itself if it fails). We can also places where we store copies of
@vqs in child objects.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
 include/hw/virtio/vhost-user-blk.h |  1 -
 include/hw/virtio/vhost.h          |  9 +++++++++
 backends/vhost-user.c              |  1 -
 hw/block/vhost-user-blk.c          |  7 +------
 hw/scsi/vhost-scsi.c               |  2 --
 hw/scsi/vhost-user-scsi.c          |  6 ------
 hw/virtio/vdpa-dev.c               |  9 ++-------
 hw/virtio/vhost-user-device.c      |  3 ---
 hw/virtio/vhost-user-fs.c          |  1 -
 hw/virtio/vhost.c                  | 10 ++++++++--
 10 files changed, 20 insertions(+), 29 deletions(-)

diff --git a/include/hw/virtio/vhost-user-blk.h b/include/hw/virtio/vhost-user-blk.h
index ea085ee1ed..479fcc2a82 100644
--- a/include/hw/virtio/vhost-user-blk.h
+++ b/include/hw/virtio/vhost-user-blk.h
@@ -37,7 +37,6 @@ struct VHostUserBlk {
     struct vhost_dev dev;
     struct vhost_inflight *inflight;
     VhostUserState vhost_user;
-    struct vhost_virtqueue *vhost_vqs;
     VirtQueue **virtqs;
 
     /*
diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
index f7f10c8fb7..912706668a 100644
--- a/include/hw/virtio/vhost.h
+++ b/include/hw/virtio/vhost.h
@@ -82,6 +82,10 @@ struct vhost_dev {
     MemoryRegionSection *mem_sections;
     int n_tmp_sections;
     MemoryRegionSection *tmp_sections;
+    /**
+     * @vqs - internal to vhost_dev, allocated based on @nvqs
+     * @nvqs - number of @vqs to allocate.
+     */
     struct vhost_virtqueue *vqs;
     unsigned int nvqs;
     /* the first virtqueue which would be used by this vhost dev */
@@ -156,6 +160,9 @@ struct vhost_net {
  * negotiation of backend interface. Configuration of the VirtIO
  * itself won't happen until the interface is started.
  *
+ * If the initialisation fails it will call vhost_dev_cleanup() to
+ * tear down the interface and free memory.
+ *
  * Return: 0 on success, non-zero on error while setting errp.
  */
 int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
@@ -165,6 +172,8 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
 /**
  * vhost_dev_cleanup() - tear down and cleanup vhost interface
  * @hdev: the common vhost_dev structure
+ *
+ * This includes freeing internals such as @vqs
  */
 void vhost_dev_cleanup(struct vhost_dev *hdev);
 
diff --git a/backends/vhost-user.c b/backends/vhost-user.c
index 94c6a82d52..05a3cf77d0 100644
--- a/backends/vhost-user.c
+++ b/backends/vhost-user.c
@@ -34,7 +34,6 @@ vhost_user_backend_dev_init(VhostUserBackend *b, VirtIODevice *vdev,
 
     b->vdev = vdev;
     b->dev.nvqs = nvqs;
-    b->dev.vqs = g_new0(struct vhost_virtqueue, nvqs);
 
     ret = vhost_dev_init(&b->dev, &b->vhost_user, VHOST_BACKEND_TYPE_USER, 0,
                          errp);
diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c
index eecf3f7a81..9221f159ec 100644
--- a/hw/block/vhost-user-blk.c
+++ b/hw/block/vhost-user-blk.c
@@ -332,7 +332,6 @@ static int vhost_user_blk_connect(DeviceState *dev, Error **errp)
 
     s->dev.num_queues = s->num_queues;
     s->dev.nvqs = s->num_queues;
-    s->dev.vqs = s->vhost_vqs;
     s->dev.vq_index = 0;
     s->dev.backend_features = 0;
 
@@ -480,7 +479,6 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp)
     }
 
     s->inflight = g_new0(struct vhost_inflight, 1);
-    s->vhost_vqs = g_new0(struct vhost_virtqueue, s->num_queues);
 
     retries = REALIZE_CONNECTION_RETRIES;
     assert(!*errp);
@@ -504,8 +502,7 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp)
     return;
 
 virtio_err:
-    g_free(s->vhost_vqs);
-    s->vhost_vqs = NULL;
+    vhost_dev_cleanup(&s->dev);
     g_free(s->inflight);
     s->inflight = NULL;
     for (i = 0; i < s->num_queues; i++) {
@@ -527,8 +524,6 @@ static void vhost_user_blk_device_unrealize(DeviceState *dev)
                              NULL, NULL, NULL, false);
     vhost_dev_cleanup(&s->dev);
     vhost_dev_free_inflight(s->inflight);
-    g_free(s->vhost_vqs);
-    s->vhost_vqs = NULL;
     g_free(s->inflight);
     s->inflight = NULL;
 
diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c
index 443f67daa4..aa25cdfcdc 100644
--- a/hw/scsi/vhost-scsi.c
+++ b/hw/scsi/vhost-scsi.c
@@ -214,8 +214,6 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp)
     }
 
     vsc->dev.nvqs = VHOST_SCSI_VQ_NUM_FIXED + vs->conf.num_queues;
-    vqs = g_new0(struct vhost_virtqueue, vsc->dev.nvqs);
-    vsc->dev.vqs = vqs;
     vsc->dev.vq_index = 0;
     vsc->dev.backend_features = 0;
 
diff --git a/hw/scsi/vhost-user-scsi.c b/hw/scsi/vhost-user-scsi.c
index ee99b19e7a..7e4c20ba42 100644
--- a/hw/scsi/vhost-user-scsi.c
+++ b/hw/scsi/vhost-user-scsi.c
@@ -94,7 +94,6 @@ static void vhost_user_scsi_realize(DeviceState *dev, Error **errp)
     VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev);
     VHostUserSCSI *s = VHOST_USER_SCSI(dev);
     VHostSCSICommon *vsc = VHOST_SCSI_COMMON(s);
-    struct vhost_virtqueue *vqs = NULL;
     Error *err = NULL;
     int ret;
 
@@ -116,10 +115,8 @@ static void vhost_user_scsi_realize(DeviceState *dev, Error **errp)
     }
 
     vsc->dev.nvqs = VIRTIO_SCSI_VQ_NUM_FIXED + vs->conf.num_queues;
-    vsc->dev.vqs = g_new0(struct vhost_virtqueue, vsc->dev.nvqs);
     vsc->dev.vq_index = 0;
     vsc->dev.backend_features = 0;
-    vqs = vsc->dev.vqs;
 
     ret = vhost_dev_init(&vsc->dev, &s->vhost_user,
                          VHOST_BACKEND_TYPE_USER, 0, errp);
@@ -136,7 +133,6 @@ static void vhost_user_scsi_realize(DeviceState *dev, Error **errp)
 
 free_vhost:
     vhost_user_cleanup(&s->vhost_user);
-    g_free(vqs);
 free_virtio:
     virtio_scsi_common_unrealize(dev);
 }
@@ -146,13 +142,11 @@ static void vhost_user_scsi_unrealize(DeviceState *dev)
     VirtIODevice *vdev = VIRTIO_DEVICE(dev);
     VHostUserSCSI *s = VHOST_USER_SCSI(dev);
     VHostSCSICommon *vsc = VHOST_SCSI_COMMON(s);
-    struct vhost_virtqueue *vqs = vsc->dev.vqs;
 
     /* This will stop the vhost backend. */
     vhost_user_scsi_set_status(vdev, 0);
 
     vhost_dev_cleanup(&vsc->dev);
-    g_free(vqs);
 
     virtio_scsi_common_unrealize(dev);
     vhost_user_cleanup(&s->vhost_user);
diff --git a/hw/virtio/vdpa-dev.c b/hw/virtio/vdpa-dev.c
index 363b625243..c537c0d5f5 100644
--- a/hw/virtio/vdpa-dev.c
+++ b/hw/virtio/vdpa-dev.c
@@ -54,7 +54,6 @@ static void vhost_vdpa_device_realize(DeviceState *dev, Error **errp)
     VhostVdpaDevice *v = VHOST_VDPA_DEVICE(vdev);
     struct vhost_vdpa_iova_range iova_range;
     uint16_t max_queue_size;
-    struct vhost_virtqueue *vqs;
     int i, ret;
 
     if (!v->vhostdev) {
@@ -101,8 +100,6 @@ static void vhost_vdpa_device_realize(DeviceState *dev, Error **errp)
     }
 
     v->dev.nvqs = v->num_queues;
-    vqs = g_new0(struct vhost_virtqueue, v->dev.nvqs);
-    v->dev.vqs = vqs;
     v->dev.vq_index = 0;
     v->dev.vq_index_end = v->dev.nvqs;
     v->dev.backend_features = 0;
@@ -112,7 +109,7 @@ static void vhost_vdpa_device_realize(DeviceState *dev, Error **errp)
     if (ret < 0) {
         error_setg(errp, "vhost-vdpa-device: get iova range failed: %s",
                    strerror(-ret));
-        goto free_vqs;
+        goto out;
     }
     v->vdpa.iova_range = iova_range;
 
@@ -120,7 +117,7 @@ static void vhost_vdpa_device_realize(DeviceState *dev, Error **errp)
     if (ret < 0) {
         error_setg(errp, "vhost-vdpa-device: vhost initialization failed: %s",
                    strerror(-ret));
-        goto free_vqs;
+        goto out;
     }
 
     v->config_size = vhost_vdpa_device_get_u32(v->vhostfd,
@@ -160,8 +157,6 @@ free_config:
     g_free(v->config);
 vhost_cleanup:
     vhost_dev_cleanup(&v->dev);
-free_vqs:
-    g_free(vqs);
 out:
     qemu_close(v->vhostfd);
     v->vhostfd = -1;
diff --git a/hw/virtio/vhost-user-device.c b/hw/virtio/vhost-user-device.c
index d787f52364..0109d4829d 100644
--- a/hw/virtio/vhost-user-device.c
+++ b/hw/virtio/vhost-user-device.c
@@ -288,7 +288,6 @@ static void vub_device_realize(DeviceState *dev, Error **errp)
     }
 
     vub->vhost_dev.nvqs = vub->num_vqs;
-    vub->vhost_dev.vqs = g_new0(struct vhost_virtqueue, vub->vhost_dev.nvqs);
 
     /* connect to backend */
     ret = vhost_dev_init(&vub->vhost_dev, &vub->vhost_user,
@@ -306,12 +305,10 @@ static void vub_device_unrealize(DeviceState *dev)
 {
     VirtIODevice *vdev = VIRTIO_DEVICE(dev);
     VHostUserBase *vub = VHOST_USER_BASE(dev);
-    struct vhost_virtqueue *vhost_vqs = vub->vhost_dev.vqs;
 
     /* This will stop vhost backend if appropriate. */
     vub_set_status(vdev, 0);
     vhost_dev_cleanup(&vub->vhost_dev);
-    g_free(vhost_vqs);
     do_vhost_user_cleanup(vdev, vub);
 }
 
diff --git a/hw/virtio/vhost-user-fs.c b/hw/virtio/vhost-user-fs.c
index 49d699ffc2..b6667f08b0 100644
--- a/hw/virtio/vhost-user-fs.c
+++ b/hw/virtio/vhost-user-fs.c
@@ -248,7 +248,6 @@ static void vuf_device_realize(DeviceState *dev, Error **errp)
 
     /* 1 high prio queue, plus the number configured */
     fs->vhost_dev.nvqs = 1 + fs->conf.num_request_queues;
-    fs->vhost_dev.vqs = g_new0(struct vhost_virtqueue, fs->vhost_dev.nvqs);
     ret = vhost_dev_init(&fs->vhost_dev, &fs->vhost_user,
                          VHOST_BACKEND_TYPE_USER, 0, errp);
     if (ret < 0) {
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 971df8ccc5..4c73ced3b7 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1392,6 +1392,8 @@ static bool vhost_init_virtqs(struct vhost_dev *hdev, uint32_t busyloop_timeout,
 {
     int i, r, n_initialized_vqs = 0;
 
+    hdev->vqs = g_new0(struct vhost_virtqueue, hdev->nvqs);
+
     for (i = 0; i < hdev->nvqs; ++i, ++n_initialized_vqs) {
         r = vhost_virtqueue_init(hdev, hdev->vqs + i, hdev->vq_index + i);
         if (r < 0) {
@@ -1530,9 +1532,13 @@ void vhost_dev_cleanup(struct vhost_dev *hdev)
 
     trace_vhost_dev_cleanup(hdev);
 
-    for (i = 0; i < hdev->nvqs; ++i) {
-        vhost_virtqueue_cleanup(hdev->vqs + i);
+    if (hdev->vqs) {
+        for (i = 0; i < hdev->nvqs; ++i) {
+            vhost_virtqueue_cleanup(hdev->vqs + i);
+        }
+        g_free(hdev->vqs);
     }
+
     if (hdev->mem) {
         /* those are only safe after successful init */
         memory_listener_unregister(&hdev->memory_listener);
-- 
2.39.2



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Virtio-fs] [RFC PATCH v3 17/20] hw/virtio: push down allocation responsibility for vhost_dev->vqs
@ 2023-07-10 15:35   ` Alex Bennée
  0 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

All the allocations are a function the number of vqs we are allocating
so let the vhost code deal with it directly. This allows to eliminate
some complexity of the clean-up code (because vhost_dev_init cleanups
after itself if it fails). We can also places where we store copies of
@vqs in child objects.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
 include/hw/virtio/vhost-user-blk.h |  1 -
 include/hw/virtio/vhost.h          |  9 +++++++++
 backends/vhost-user.c              |  1 -
 hw/block/vhost-user-blk.c          |  7 +------
 hw/scsi/vhost-scsi.c               |  2 --
 hw/scsi/vhost-user-scsi.c          |  6 ------
 hw/virtio/vdpa-dev.c               |  9 ++-------
 hw/virtio/vhost-user-device.c      |  3 ---
 hw/virtio/vhost-user-fs.c          |  1 -
 hw/virtio/vhost.c                  | 10 ++++++++--
 10 files changed, 20 insertions(+), 29 deletions(-)

diff --git a/include/hw/virtio/vhost-user-blk.h b/include/hw/virtio/vhost-user-blk.h
index ea085ee1ed..479fcc2a82 100644
--- a/include/hw/virtio/vhost-user-blk.h
+++ b/include/hw/virtio/vhost-user-blk.h
@@ -37,7 +37,6 @@ struct VHostUserBlk {
     struct vhost_dev dev;
     struct vhost_inflight *inflight;
     VhostUserState vhost_user;
-    struct vhost_virtqueue *vhost_vqs;
     VirtQueue **virtqs;
 
     /*
diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
index f7f10c8fb7..912706668a 100644
--- a/include/hw/virtio/vhost.h
+++ b/include/hw/virtio/vhost.h
@@ -82,6 +82,10 @@ struct vhost_dev {
     MemoryRegionSection *mem_sections;
     int n_tmp_sections;
     MemoryRegionSection *tmp_sections;
+    /**
+     * @vqs - internal to vhost_dev, allocated based on @nvqs
+     * @nvqs - number of @vqs to allocate.
+     */
     struct vhost_virtqueue *vqs;
     unsigned int nvqs;
     /* the first virtqueue which would be used by this vhost dev */
@@ -156,6 +160,9 @@ struct vhost_net {
  * negotiation of backend interface. Configuration of the VirtIO
  * itself won't happen until the interface is started.
  *
+ * If the initialisation fails it will call vhost_dev_cleanup() to
+ * tear down the interface and free memory.
+ *
  * Return: 0 on success, non-zero on error while setting errp.
  */
 int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
@@ -165,6 +172,8 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
 /**
  * vhost_dev_cleanup() - tear down and cleanup vhost interface
  * @hdev: the common vhost_dev structure
+ *
+ * This includes freeing internals such as @vqs
  */
 void vhost_dev_cleanup(struct vhost_dev *hdev);
 
diff --git a/backends/vhost-user.c b/backends/vhost-user.c
index 94c6a82d52..05a3cf77d0 100644
--- a/backends/vhost-user.c
+++ b/backends/vhost-user.c
@@ -34,7 +34,6 @@ vhost_user_backend_dev_init(VhostUserBackend *b, VirtIODevice *vdev,
 
     b->vdev = vdev;
     b->dev.nvqs = nvqs;
-    b->dev.vqs = g_new0(struct vhost_virtqueue, nvqs);
 
     ret = vhost_dev_init(&b->dev, &b->vhost_user, VHOST_BACKEND_TYPE_USER, 0,
                          errp);
diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c
index eecf3f7a81..9221f159ec 100644
--- a/hw/block/vhost-user-blk.c
+++ b/hw/block/vhost-user-blk.c
@@ -332,7 +332,6 @@ static int vhost_user_blk_connect(DeviceState *dev, Error **errp)
 
     s->dev.num_queues = s->num_queues;
     s->dev.nvqs = s->num_queues;
-    s->dev.vqs = s->vhost_vqs;
     s->dev.vq_index = 0;
     s->dev.backend_features = 0;
 
@@ -480,7 +479,6 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp)
     }
 
     s->inflight = g_new0(struct vhost_inflight, 1);
-    s->vhost_vqs = g_new0(struct vhost_virtqueue, s->num_queues);
 
     retries = REALIZE_CONNECTION_RETRIES;
     assert(!*errp);
@@ -504,8 +502,7 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp)
     return;
 
 virtio_err:
-    g_free(s->vhost_vqs);
-    s->vhost_vqs = NULL;
+    vhost_dev_cleanup(&s->dev);
     g_free(s->inflight);
     s->inflight = NULL;
     for (i = 0; i < s->num_queues; i++) {
@@ -527,8 +524,6 @@ static void vhost_user_blk_device_unrealize(DeviceState *dev)
                              NULL, NULL, NULL, false);
     vhost_dev_cleanup(&s->dev);
     vhost_dev_free_inflight(s->inflight);
-    g_free(s->vhost_vqs);
-    s->vhost_vqs = NULL;
     g_free(s->inflight);
     s->inflight = NULL;
 
diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c
index 443f67daa4..aa25cdfcdc 100644
--- a/hw/scsi/vhost-scsi.c
+++ b/hw/scsi/vhost-scsi.c
@@ -214,8 +214,6 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp)
     }
 
     vsc->dev.nvqs = VHOST_SCSI_VQ_NUM_FIXED + vs->conf.num_queues;
-    vqs = g_new0(struct vhost_virtqueue, vsc->dev.nvqs);
-    vsc->dev.vqs = vqs;
     vsc->dev.vq_index = 0;
     vsc->dev.backend_features = 0;
 
diff --git a/hw/scsi/vhost-user-scsi.c b/hw/scsi/vhost-user-scsi.c
index ee99b19e7a..7e4c20ba42 100644
--- a/hw/scsi/vhost-user-scsi.c
+++ b/hw/scsi/vhost-user-scsi.c
@@ -94,7 +94,6 @@ static void vhost_user_scsi_realize(DeviceState *dev, Error **errp)
     VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev);
     VHostUserSCSI *s = VHOST_USER_SCSI(dev);
     VHostSCSICommon *vsc = VHOST_SCSI_COMMON(s);
-    struct vhost_virtqueue *vqs = NULL;
     Error *err = NULL;
     int ret;
 
@@ -116,10 +115,8 @@ static void vhost_user_scsi_realize(DeviceState *dev, Error **errp)
     }
 
     vsc->dev.nvqs = VIRTIO_SCSI_VQ_NUM_FIXED + vs->conf.num_queues;
-    vsc->dev.vqs = g_new0(struct vhost_virtqueue, vsc->dev.nvqs);
     vsc->dev.vq_index = 0;
     vsc->dev.backend_features = 0;
-    vqs = vsc->dev.vqs;
 
     ret = vhost_dev_init(&vsc->dev, &s->vhost_user,
                          VHOST_BACKEND_TYPE_USER, 0, errp);
@@ -136,7 +133,6 @@ static void vhost_user_scsi_realize(DeviceState *dev, Error **errp)
 
 free_vhost:
     vhost_user_cleanup(&s->vhost_user);
-    g_free(vqs);
 free_virtio:
     virtio_scsi_common_unrealize(dev);
 }
@@ -146,13 +142,11 @@ static void vhost_user_scsi_unrealize(DeviceState *dev)
     VirtIODevice *vdev = VIRTIO_DEVICE(dev);
     VHostUserSCSI *s = VHOST_USER_SCSI(dev);
     VHostSCSICommon *vsc = VHOST_SCSI_COMMON(s);
-    struct vhost_virtqueue *vqs = vsc->dev.vqs;
 
     /* This will stop the vhost backend. */
     vhost_user_scsi_set_status(vdev, 0);
 
     vhost_dev_cleanup(&vsc->dev);
-    g_free(vqs);
 
     virtio_scsi_common_unrealize(dev);
     vhost_user_cleanup(&s->vhost_user);
diff --git a/hw/virtio/vdpa-dev.c b/hw/virtio/vdpa-dev.c
index 363b625243..c537c0d5f5 100644
--- a/hw/virtio/vdpa-dev.c
+++ b/hw/virtio/vdpa-dev.c
@@ -54,7 +54,6 @@ static void vhost_vdpa_device_realize(DeviceState *dev, Error **errp)
     VhostVdpaDevice *v = VHOST_VDPA_DEVICE(vdev);
     struct vhost_vdpa_iova_range iova_range;
     uint16_t max_queue_size;
-    struct vhost_virtqueue *vqs;
     int i, ret;
 
     if (!v->vhostdev) {
@@ -101,8 +100,6 @@ static void vhost_vdpa_device_realize(DeviceState *dev, Error **errp)
     }
 
     v->dev.nvqs = v->num_queues;
-    vqs = g_new0(struct vhost_virtqueue, v->dev.nvqs);
-    v->dev.vqs = vqs;
     v->dev.vq_index = 0;
     v->dev.vq_index_end = v->dev.nvqs;
     v->dev.backend_features = 0;
@@ -112,7 +109,7 @@ static void vhost_vdpa_device_realize(DeviceState *dev, Error **errp)
     if (ret < 0) {
         error_setg(errp, "vhost-vdpa-device: get iova range failed: %s",
                    strerror(-ret));
-        goto free_vqs;
+        goto out;
     }
     v->vdpa.iova_range = iova_range;
 
@@ -120,7 +117,7 @@ static void vhost_vdpa_device_realize(DeviceState *dev, Error **errp)
     if (ret < 0) {
         error_setg(errp, "vhost-vdpa-device: vhost initialization failed: %s",
                    strerror(-ret));
-        goto free_vqs;
+        goto out;
     }
 
     v->config_size = vhost_vdpa_device_get_u32(v->vhostfd,
@@ -160,8 +157,6 @@ free_config:
     g_free(v->config);
 vhost_cleanup:
     vhost_dev_cleanup(&v->dev);
-free_vqs:
-    g_free(vqs);
 out:
     qemu_close(v->vhostfd);
     v->vhostfd = -1;
diff --git a/hw/virtio/vhost-user-device.c b/hw/virtio/vhost-user-device.c
index d787f52364..0109d4829d 100644
--- a/hw/virtio/vhost-user-device.c
+++ b/hw/virtio/vhost-user-device.c
@@ -288,7 +288,6 @@ static void vub_device_realize(DeviceState *dev, Error **errp)
     }
 
     vub->vhost_dev.nvqs = vub->num_vqs;
-    vub->vhost_dev.vqs = g_new0(struct vhost_virtqueue, vub->vhost_dev.nvqs);
 
     /* connect to backend */
     ret = vhost_dev_init(&vub->vhost_dev, &vub->vhost_user,
@@ -306,12 +305,10 @@ static void vub_device_unrealize(DeviceState *dev)
 {
     VirtIODevice *vdev = VIRTIO_DEVICE(dev);
     VHostUserBase *vub = VHOST_USER_BASE(dev);
-    struct vhost_virtqueue *vhost_vqs = vub->vhost_dev.vqs;
 
     /* This will stop vhost backend if appropriate. */
     vub_set_status(vdev, 0);
     vhost_dev_cleanup(&vub->vhost_dev);
-    g_free(vhost_vqs);
     do_vhost_user_cleanup(vdev, vub);
 }
 
diff --git a/hw/virtio/vhost-user-fs.c b/hw/virtio/vhost-user-fs.c
index 49d699ffc2..b6667f08b0 100644
--- a/hw/virtio/vhost-user-fs.c
+++ b/hw/virtio/vhost-user-fs.c
@@ -248,7 +248,6 @@ static void vuf_device_realize(DeviceState *dev, Error **errp)
 
     /* 1 high prio queue, plus the number configured */
     fs->vhost_dev.nvqs = 1 + fs->conf.num_request_queues;
-    fs->vhost_dev.vqs = g_new0(struct vhost_virtqueue, fs->vhost_dev.nvqs);
     ret = vhost_dev_init(&fs->vhost_dev, &fs->vhost_user,
                          VHOST_BACKEND_TYPE_USER, 0, errp);
     if (ret < 0) {
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 971df8ccc5..4c73ced3b7 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1392,6 +1392,8 @@ static bool vhost_init_virtqs(struct vhost_dev *hdev, uint32_t busyloop_timeout,
 {
     int i, r, n_initialized_vqs = 0;
 
+    hdev->vqs = g_new0(struct vhost_virtqueue, hdev->nvqs);
+
     for (i = 0; i < hdev->nvqs; ++i, ++n_initialized_vqs) {
         r = vhost_virtqueue_init(hdev, hdev->vqs + i, hdev->vq_index + i);
         if (r < 0) {
@@ -1530,9 +1532,13 @@ void vhost_dev_cleanup(struct vhost_dev *hdev)
 
     trace_vhost_dev_cleanup(hdev);
 
-    for (i = 0; i < hdev->nvqs; ++i) {
-        vhost_virtqueue_cleanup(hdev->vqs + i);
+    if (hdev->vqs) {
+        for (i = 0; i < hdev->nvqs; ++i) {
+            vhost_virtqueue_cleanup(hdev->vqs + i);
+        }
+        g_free(hdev->vqs);
     }
+
     if (hdev->mem) {
         /* those are only safe after successful init */
         memory_listener_unregister(&hdev->memory_listener);
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [RFC PATCH v3 18/20] hw/virtio: validate F_STANDALONE also supports other protocol features
  2023-07-10 15:35 ` [Virtio-fs] " Alex Bennée
@ 2023-07-10 15:35   ` Alex Bennée
  -1 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

If the backend advertises F_STANDALONE validate that it supports the
other mandatory features or error out.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
 hw/virtio/vhost-user.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 28b021d5d3..3116b3e46a 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -74,6 +74,8 @@ enum VhostUserProtocolFeature {
     /* Feature 14 reserved for VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS. */
     VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS = 15,
     VHOST_USER_PROTOCOL_F_STATUS = 16,
+    VHOST_USER_PROTOCOL_F_XEN_MMAP = 17,
+    VHOST_USER_PROTOCOL_F_STANDALONE = 18,
     VHOST_USER_PROTOCOL_F_MAX
 };
 
@@ -2048,6 +2050,21 @@ static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque,
             }
         }
 
+        /*
+         * If the backend supports F_STANDALONE we should validate it
+         * supports the other features we expect. We can't check for
+         * F_CONFIG support until we know if there is a config space
+         * to manage.
+         */
+        if (virtio_has_feature(protocol_features,
+                               VHOST_USER_PROTOCOL_F_STANDALONE)) {
+            if (!virtio_has_feature(protocol_features, VHOST_USER_PROTOCOL_F_STATUS)) {
+                error_setg(errp, "vhost-user device expecting F_STANDALONE device to also "
+                           "support F_STATUS but it does not.");
+                return -EPROTO;
+            }
+        }
+
         /* final set of protocol features */
         dev->protocol_features = protocol_features;
         err = vhost_user_set_protocol_features(dev, dev->protocol_features);
-- 
2.39.2



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Virtio-fs] [RFC PATCH v3 18/20] hw/virtio: validate F_STANDALONE also supports other protocol features
@ 2023-07-10 15:35   ` Alex Bennée
  0 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

If the backend advertises F_STANDALONE validate that it supports the
other mandatory features or error out.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
 hw/virtio/vhost-user.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 28b021d5d3..3116b3e46a 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -74,6 +74,8 @@ enum VhostUserProtocolFeature {
     /* Feature 14 reserved for VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS. */
     VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS = 15,
     VHOST_USER_PROTOCOL_F_STATUS = 16,
+    VHOST_USER_PROTOCOL_F_XEN_MMAP = 17,
+    VHOST_USER_PROTOCOL_F_STANDALONE = 18,
     VHOST_USER_PROTOCOL_F_MAX
 };
 
@@ -2048,6 +2050,21 @@ static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque,
             }
         }
 
+        /*
+         * If the backend supports F_STANDALONE we should validate it
+         * supports the other features we expect. We can't check for
+         * F_CONFIG support until we know if there is a config space
+         * to manage.
+         */
+        if (virtio_has_feature(protocol_features,
+                               VHOST_USER_PROTOCOL_F_STANDALONE)) {
+            if (!virtio_has_feature(protocol_features, VHOST_USER_PROTOCOL_F_STATUS)) {
+                error_setg(errp, "vhost-user device expecting F_STANDALONE device to also "
+                           "support F_STATUS but it does not.");
+                return -EPROTO;
+            }
+        }
+
         /* final set of protocol features */
         dev->protocol_features = protocol_features;
         err = vhost_user_set_protocol_features(dev, dev->protocol_features);
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [RFC PATCH v3 19/20] hw/virtio: probe backend for specs if it supports it
  2023-07-10 15:35 ` [Virtio-fs] " Alex Bennée
@ 2023-07-10 15:35   ` Alex Bennée
  -1 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

Now we have detected and validated the protocol support lets do the
probe. The empty state indicates no probe took place.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
 include/hw/virtio/vhost.h | 12 +++++++
 hw/virtio/vhost-user.c    | 73 +++++++++++++++++++++++++++++++++++----
 hw/virtio/vhost.c         |  2 +-
 3 files changed, 79 insertions(+), 8 deletions(-)

diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
index 912706668a..1d8de1c558 100644
--- a/include/hw/virtio/vhost.h
+++ b/include/hw/virtio/vhost.h
@@ -68,6 +68,13 @@ typedef struct VhostDevConfigOps {
 
 struct vhost_memory;
 
+typedef struct VhostUserBackendSpecs {
+    uint32_t device_id;
+    uint32_t config_size;
+    uint32_t min_vqs;
+    uint32_t max_vqs;
+} VhostUserBackendSpecs;
+
 /**
  * struct vhost_dev - common vhost_dev structure
  * @vhost_ops: backend specific ops
@@ -107,11 +114,15 @@ struct vhost_dev {
      * VHOST_USER_SET_FEATURES or VHOST_NET_F_VIRTIO_NET_HDR. Its
      * future use should be discouraged and the variable retired as
      * its easy to confuse with the VirtIO backend_features.
+     *
+     * @specs: the results of a GET_BACKEND_SPECS probe.
      */
     uint64_t features;
     uint64_t acked_features;
     uint64_t backend_features;
 
+    VhostUserBackendSpecs specs;
+
     /**
      * @protocol_features: is the vhost-user only feature set by
      * VHOST_USER_SET_PROTOCOL_FEATURES. Protocol features are only
@@ -134,6 +145,7 @@ struct vhost_dev {
     QLIST_HEAD(, vhost_iommu) iommu_list;
     IOMMUNotifier n;
     const VhostDevConfigOps *config_ops;
+
 };
 
 extern const VhostOps kernel_ops;
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 3116b3e46a..36aa4ec2d5 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -123,6 +123,7 @@ typedef enum VhostUserRequest {
     VHOST_USER_REM_MEM_REG = 38,
     VHOST_USER_SET_STATUS = 39,
     VHOST_USER_GET_STATUS = 40,
+    VHOST_USER_GET_BACKEND_SPECS = 41,
     VHOST_USER_MAX
 } VhostUserRequest;
 
@@ -204,13 +205,6 @@ typedef struct VhostUserInflight {
     uint16_t queue_size;
 } VhostUserInflight;
 
-typedef struct VhostUserBackendSpecs {
-    uint32_t device_id;
-    uint32_t config_size;
-    uint32_t min_vqs;
-    uint32_t max_vqs;
-} VhostUserBackendSpecs;
-
 typedef struct {
     VhostUserRequest request;
 
@@ -1991,6 +1985,56 @@ static int vhost_user_postcopy_notifier(NotifierWithReturn *notifier,
     return 0;
 }
 
+static bool vhost_user_get_backend_specs(struct vhost_dev *dev, Error **errp)
+{
+    int ret;
+    VhostUserMsg msg = {
+        .hdr.request = VHOST_USER_GET_BACKEND_SPECS,
+        .hdr.flags = VHOST_USER_VERSION,
+        .hdr.size = VHOST_USER_HDR_SIZE,
+    };
+
+    if (!virtio_has_feature(dev->protocol_features,
+                VHOST_USER_PROTOCOL_F_STANDALONE)) {
+        error_setg(errp, "VHOST_USER_PROTOCOL_F_STANDALONE not supported");
+        return -EINVAL;
+    }
+
+    ret = vhost_user_write(dev, &msg, NULL, 0);
+    if (ret < 0) {
+        error_setg_errno(errp, -ret, "vhost_get_backend send failed");
+        return ret;
+    }
+
+    ret = vhost_user_read(dev, &msg);
+    if (ret < 0) {
+        error_setg_errno(errp, -ret, "vhost_get_backend recv failed");
+        return ret;
+    }
+
+    if (msg.hdr.request != VHOST_USER_GET_BACKEND_SPECS) {
+        error_setg(errp,
+                   "Received unexpected msg type. Expected %d received %d",
+                   VHOST_USER_GET_BACKEND_SPECS, msg.hdr.request);
+        return -EPROTO;
+    }
+
+    if (msg.hdr.size != sizeof(msg.payload.specs)) {
+        error_setg(errp, "Received bad msg size.");
+        return -EPROTO;
+    }
+
+    if (msg.payload.specs.config_size && !virtio_has_feature(dev->protocol_features,
+                                                             VHOST_USER_PROTOCOL_F_CONFIG)) {
+        error_setg(errp, "VHOST_USER_PROTOCOL_F_CONFIG not supported");
+        return -EPROTO;
+    }
+
+    dev->specs = msg.payload.specs;
+
+    return 0;
+}
+
 static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque,
                                    Error **errp)
 {
@@ -2073,6 +2117,21 @@ static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque,
             return -EPROTO;
         }
 
+        if (dev->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_STANDALONE)) {
+            err = vhost_user_get_backend_specs(dev, errp);
+            if (err < 0) {
+                error_setg_errno(errp, EPROTO, "vhost_get_backend_specs failed");
+                return -EPROTO;
+            }
+            /*
+             * If this was never set by the user we can now fill it in
+             * so we can continue the initialisation
+             */
+            if (!dev->nvqs) {
+                dev->nvqs = dev->specs.min_vqs;
+            }
+        }
+
         /* query the max queues we support if backend supports Multiple Queue */
         if (dev->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_MQ)) {
             err = vhost_user_get_u64(dev, VHOST_USER_GET_QUEUE_NUM,
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 4c73ced3b7..d14467aa1c 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1450,7 +1450,7 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
     }
 
     /* Skip if we don't yet have number of vqs */
-    if (hdev->vqs && hdev->nvqs) {
+    if (hdev->nvqs) {
         if (!vhost_init_virtqs(hdev, busyloop_timeout, errp)) {
             goto fail_busyloop;
         }
-- 
2.39.2



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Virtio-fs] [RFC PATCH v3 19/20] hw/virtio: probe backend for specs if it supports it
@ 2023-07-10 15:35   ` Alex Bennée
  0 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

Now we have detected and validated the protocol support lets do the
probe. The empty state indicates no probe took place.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
 include/hw/virtio/vhost.h | 12 +++++++
 hw/virtio/vhost-user.c    | 73 +++++++++++++++++++++++++++++++++++----
 hw/virtio/vhost.c         |  2 +-
 3 files changed, 79 insertions(+), 8 deletions(-)

diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
index 912706668a..1d8de1c558 100644
--- a/include/hw/virtio/vhost.h
+++ b/include/hw/virtio/vhost.h
@@ -68,6 +68,13 @@ typedef struct VhostDevConfigOps {
 
 struct vhost_memory;
 
+typedef struct VhostUserBackendSpecs {
+    uint32_t device_id;
+    uint32_t config_size;
+    uint32_t min_vqs;
+    uint32_t max_vqs;
+} VhostUserBackendSpecs;
+
 /**
  * struct vhost_dev - common vhost_dev structure
  * @vhost_ops: backend specific ops
@@ -107,11 +114,15 @@ struct vhost_dev {
      * VHOST_USER_SET_FEATURES or VHOST_NET_F_VIRTIO_NET_HDR. Its
      * future use should be discouraged and the variable retired as
      * its easy to confuse with the VirtIO backend_features.
+     *
+     * @specs: the results of a GET_BACKEND_SPECS probe.
      */
     uint64_t features;
     uint64_t acked_features;
     uint64_t backend_features;
 
+    VhostUserBackendSpecs specs;
+
     /**
      * @protocol_features: is the vhost-user only feature set by
      * VHOST_USER_SET_PROTOCOL_FEATURES. Protocol features are only
@@ -134,6 +145,7 @@ struct vhost_dev {
     QLIST_HEAD(, vhost_iommu) iommu_list;
     IOMMUNotifier n;
     const VhostDevConfigOps *config_ops;
+
 };
 
 extern const VhostOps kernel_ops;
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 3116b3e46a..36aa4ec2d5 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -123,6 +123,7 @@ typedef enum VhostUserRequest {
     VHOST_USER_REM_MEM_REG = 38,
     VHOST_USER_SET_STATUS = 39,
     VHOST_USER_GET_STATUS = 40,
+    VHOST_USER_GET_BACKEND_SPECS = 41,
     VHOST_USER_MAX
 } VhostUserRequest;
 
@@ -204,13 +205,6 @@ typedef struct VhostUserInflight {
     uint16_t queue_size;
 } VhostUserInflight;
 
-typedef struct VhostUserBackendSpecs {
-    uint32_t device_id;
-    uint32_t config_size;
-    uint32_t min_vqs;
-    uint32_t max_vqs;
-} VhostUserBackendSpecs;
-
 typedef struct {
     VhostUserRequest request;
 
@@ -1991,6 +1985,56 @@ static int vhost_user_postcopy_notifier(NotifierWithReturn *notifier,
     return 0;
 }
 
+static bool vhost_user_get_backend_specs(struct vhost_dev *dev, Error **errp)
+{
+    int ret;
+    VhostUserMsg msg = {
+        .hdr.request = VHOST_USER_GET_BACKEND_SPECS,
+        .hdr.flags = VHOST_USER_VERSION,
+        .hdr.size = VHOST_USER_HDR_SIZE,
+    };
+
+    if (!virtio_has_feature(dev->protocol_features,
+                VHOST_USER_PROTOCOL_F_STANDALONE)) {
+        error_setg(errp, "VHOST_USER_PROTOCOL_F_STANDALONE not supported");
+        return -EINVAL;
+    }
+
+    ret = vhost_user_write(dev, &msg, NULL, 0);
+    if (ret < 0) {
+        error_setg_errno(errp, -ret, "vhost_get_backend send failed");
+        return ret;
+    }
+
+    ret = vhost_user_read(dev, &msg);
+    if (ret < 0) {
+        error_setg_errno(errp, -ret, "vhost_get_backend recv failed");
+        return ret;
+    }
+
+    if (msg.hdr.request != VHOST_USER_GET_BACKEND_SPECS) {
+        error_setg(errp,
+                   "Received unexpected msg type. Expected %d received %d",
+                   VHOST_USER_GET_BACKEND_SPECS, msg.hdr.request);
+        return -EPROTO;
+    }
+
+    if (msg.hdr.size != sizeof(msg.payload.specs)) {
+        error_setg(errp, "Received bad msg size.");
+        return -EPROTO;
+    }
+
+    if (msg.payload.specs.config_size && !virtio_has_feature(dev->protocol_features,
+                                                             VHOST_USER_PROTOCOL_F_CONFIG)) {
+        error_setg(errp, "VHOST_USER_PROTOCOL_F_CONFIG not supported");
+        return -EPROTO;
+    }
+
+    dev->specs = msg.payload.specs;
+
+    return 0;
+}
+
 static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque,
                                    Error **errp)
 {
@@ -2073,6 +2117,21 @@ static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque,
             return -EPROTO;
         }
 
+        if (dev->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_STANDALONE)) {
+            err = vhost_user_get_backend_specs(dev, errp);
+            if (err < 0) {
+                error_setg_errno(errp, EPROTO, "vhost_get_backend_specs failed");
+                return -EPROTO;
+            }
+            /*
+             * If this was never set by the user we can now fill it in
+             * so we can continue the initialisation
+             */
+            if (!dev->nvqs) {
+                dev->nvqs = dev->specs.min_vqs;
+            }
+        }
+
         /* query the max queues we support if backend supports Multiple Queue */
         if (dev->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_MQ)) {
             err = vhost_user_get_u64(dev, VHOST_USER_GET_QUEUE_NUM,
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 4c73ced3b7..d14467aa1c 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1450,7 +1450,7 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
     }
 
     /* Skip if we don't yet have number of vqs */
-    if (hdev->vqs && hdev->nvqs) {
+    if (hdev->nvqs) {
         if (!vhost_init_virtqs(hdev, busyloop_timeout, errp)) {
             goto fail_busyloop;
         }
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [RFC PATCH v3 20/20] hw/virtio: allow vhost-user-device to be driven by backend
  2023-07-10 15:35 ` [Virtio-fs] " Alex Bennée
@ 2023-07-10 15:35   ` Alex Bennée
  -1 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

Instead of requiring all the information up front allow the
vhost_dev_init to complete and then see what information we have from
the backend.

This does change the order around somewhat.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
 hw/virtio/vhost-user-device.c | 45 +++++++++++++++++++++++++----------
 1 file changed, 32 insertions(+), 13 deletions(-)

diff --git a/hw/virtio/vhost-user-device.c b/hw/virtio/vhost-user-device.c
index 0109d4829d..b30b6265fb 100644
--- a/hw/virtio/vhost-user-device.c
+++ b/hw/virtio/vhost-user-device.c
@@ -243,7 +243,6 @@ static void vub_device_realize(DeviceState *dev, Error **errp)
 {
     VirtIODevice *vdev = VIRTIO_DEVICE(dev);
     VHostUserBase *vub = VHOST_USER_BASE(dev);
-    int ret;
 
     if (!vub->chardev.chr) {
         error_setg(errp, "vhost-user-device: missing chardev");
@@ -254,13 +253,43 @@ static void vub_device_realize(DeviceState *dev, Error **errp)
         return;
     }
 
+    if (vhost_dev_init(&vub->vhost_dev, &vub->vhost_user,
+                       VHOST_BACKEND_TYPE_USER, 0, errp)!=0) {
+        error_setg(errp, "vhost-user-device: unable to start connection");
+        return;
+    }
+
+    if (vub->vhost_dev.specs.device_id) {
+        if (vub->virtio_id && vub->virtio_id != vub->vhost_dev.specs.device_id) {
+            error_setg(errp, "vhost-user-device: backend id %d doesn't match cli %d",
+                       vub->vhost_dev.specs.device_id, vub->virtio_id);
+            return;
+        }
+        vub->virtio_id = vub->vhost_dev.specs.device_id;
+    }
+
     if (!vub->virtio_id) {
-        error_setg(errp, "vhost-user-device: need to define device id");
+        error_setg(errp, "vhost-user-device: need to define or be told device id");
         return;
     }
 
+    if (vub->vhost_dev.specs.min_vqs) {
+        if (vub->num_vqs) {
+            if (vub->num_vqs < vub->vhost_dev.specs.min_vqs ||
+                vub->num_vqs > vub->vhost_dev.specs.max_vqs) {
+                error_setg(errp,
+                           "vhost-user-device: selected nvqs (%d) out of bounds (%d->%d)",
+                           vub->num_vqs,
+                           vub->vhost_dev.specs.min_vqs, vub->vhost_dev.specs.max_vqs);
+                return;
+            }
+        } else {
+            vub->num_vqs = vub->vhost_dev.specs.min_vqs;
+        }
+    }
+
     if (!vub->num_vqs) {
-        vub->num_vqs = 1; /* reasonable default? */
+        error_setg(errp, "vhost-user-device: need to define number of vqs");
     }
 
     /*
@@ -287,16 +316,6 @@ static void vub_device_realize(DeviceState *dev, Error **errp)
                         virtio_add_queue(vdev, 4, vub_handle_output));
     }
 
-    vub->vhost_dev.nvqs = vub->num_vqs;
-
-    /* connect to backend */
-    ret = vhost_dev_init(&vub->vhost_dev, &vub->vhost_user,
-                         VHOST_BACKEND_TYPE_USER, 0, errp);
-
-    if (ret < 0) {
-        do_vhost_user_cleanup(vdev, vub);
-    }
-
     qemu_chr_fe_set_handlers(&vub->chardev, NULL, NULL, vub_event, NULL,
                              dev, NULL, true);
 }
-- 
2.39.2



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Virtio-fs] [RFC PATCH v3 20/20] hw/virtio: allow vhost-user-device to be driven by backend
@ 2023-07-10 15:35   ` Alex Bennée
  0 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-07-10 15:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Alex Bennée, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

Instead of requiring all the information up front allow the
vhost_dev_init to complete and then see what information we have from
the backend.

This does change the order around somewhat.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
 hw/virtio/vhost-user-device.c | 45 +++++++++++++++++++++++++----------
 1 file changed, 32 insertions(+), 13 deletions(-)

diff --git a/hw/virtio/vhost-user-device.c b/hw/virtio/vhost-user-device.c
index 0109d4829d..b30b6265fb 100644
--- a/hw/virtio/vhost-user-device.c
+++ b/hw/virtio/vhost-user-device.c
@@ -243,7 +243,6 @@ static void vub_device_realize(DeviceState *dev, Error **errp)
 {
     VirtIODevice *vdev = VIRTIO_DEVICE(dev);
     VHostUserBase *vub = VHOST_USER_BASE(dev);
-    int ret;
 
     if (!vub->chardev.chr) {
         error_setg(errp, "vhost-user-device: missing chardev");
@@ -254,13 +253,43 @@ static void vub_device_realize(DeviceState *dev, Error **errp)
         return;
     }
 
+    if (vhost_dev_init(&vub->vhost_dev, &vub->vhost_user,
+                       VHOST_BACKEND_TYPE_USER, 0, errp)!=0) {
+        error_setg(errp, "vhost-user-device: unable to start connection");
+        return;
+    }
+
+    if (vub->vhost_dev.specs.device_id) {
+        if (vub->virtio_id && vub->virtio_id != vub->vhost_dev.specs.device_id) {
+            error_setg(errp, "vhost-user-device: backend id %d doesn't match cli %d",
+                       vub->vhost_dev.specs.device_id, vub->virtio_id);
+            return;
+        }
+        vub->virtio_id = vub->vhost_dev.specs.device_id;
+    }
+
     if (!vub->virtio_id) {
-        error_setg(errp, "vhost-user-device: need to define device id");
+        error_setg(errp, "vhost-user-device: need to define or be told device id");
         return;
     }
 
+    if (vub->vhost_dev.specs.min_vqs) {
+        if (vub->num_vqs) {
+            if (vub->num_vqs < vub->vhost_dev.specs.min_vqs ||
+                vub->num_vqs > vub->vhost_dev.specs.max_vqs) {
+                error_setg(errp,
+                           "vhost-user-device: selected nvqs (%d) out of bounds (%d->%d)",
+                           vub->num_vqs,
+                           vub->vhost_dev.specs.min_vqs, vub->vhost_dev.specs.max_vqs);
+                return;
+            }
+        } else {
+            vub->num_vqs = vub->vhost_dev.specs.min_vqs;
+        }
+    }
+
     if (!vub->num_vqs) {
-        vub->num_vqs = 1; /* reasonable default? */
+        error_setg(errp, "vhost-user-device: need to define number of vqs");
     }
 
     /*
@@ -287,16 +316,6 @@ static void vub_device_realize(DeviceState *dev, Error **errp)
                         virtio_add_queue(vdev, 4, vub_handle_output));
     }
 
-    vub->vhost_dev.nvqs = vub->num_vqs;
-
-    /* connect to backend */
-    ret = vhost_dev_init(&vub->vhost_dev, &vub->vhost_user,
-                         VHOST_BACKEND_TYPE_USER, 0, errp);
-
-    if (ret < 0) {
-        do_vhost_user_cleanup(vdev, vub);
-    }
-
     qemu_chr_fe_set_handlers(&vub->chardev, NULL, NULL, vub_event, NULL,
                              dev, NULL, true);
 }
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 66+ messages in thread

* Re: [PATCH v3 10/20] hw/virtio: add config support to vhost-user-device
  2023-07-10 15:35   ` [Virtio-fs] " Alex Bennée
@ 2023-07-10 19:58     ` Michael S. Tsirkin
  -1 siblings, 0 replies; 66+ messages in thread
From: Michael S. Tsirkin @ 2023-07-10 19:58 UTC (permalink / raw)
  To: Alex Bennée
  Cc: qemu-devel, Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Mark Cave-Ayland, Kevin Wolf,
	Markus Armbruster, Gerd Hoffmann, Mathieu Poirier, Hanna Reitz,
	Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

On Mon, Jul 10, 2023 at 04:35:12PM +0100, Alex Bennée wrote:
> To use the generic device the user will need to provide the config
> region size via the command line. We also add a notifier so the guest
> can be pinged if the remote daemon updates the config.
> 
> With these changes:
> 
>   -device vhost-user-device-pci,virtio-id=41,num_vqs=2,config_size=8
> 
> is equivalent to:
> 
>   -device vhost-user-gpio-pci
> 
> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>


This one I think it's best to defer until we get a better
handle on how we want the configuration to look.


> ---
>  include/hw/virtio/vhost-user-device.h |  1 +
>  hw/virtio/vhost-user-device.c         | 58 ++++++++++++++++++++++++++-
>  2 files changed, 58 insertions(+), 1 deletion(-)
> 
> diff --git a/include/hw/virtio/vhost-user-device.h b/include/hw/virtio/vhost-user-device.h
> index 9105011e25..3ddf88a146 100644
> --- a/include/hw/virtio/vhost-user-device.h
> +++ b/include/hw/virtio/vhost-user-device.h
> @@ -22,6 +22,7 @@ struct VHostUserBase {
>      CharBackend chardev;
>      uint16_t virtio_id;
>      uint32_t num_vqs;
> +    uint32_t config_size;
>      /* State tracking */
>      VhostUserState vhost_user;
>      struct vhost_virtqueue *vhost_vq;
> diff --git a/hw/virtio/vhost-user-device.c b/hw/virtio/vhost-user-device.c
> index b0239fa033..2b028cae08 100644
> --- a/hw/virtio/vhost-user-device.c
> +++ b/hw/virtio/vhost-user-device.c
> @@ -117,6 +117,42 @@ static uint64_t vub_get_features(VirtIODevice *vdev,
>      return vub->vhost_dev.features & ~(1ULL << VHOST_USER_F_PROTOCOL_FEATURES);
>  }
>  
> +/*
> + * To handle VirtIO config we need to know the size of the config
> + * space. We don't cache the config but re-fetch it from the guest
> + * every time in case something has changed.
> + */
> +static void vub_get_config(VirtIODevice *vdev, uint8_t *config)
> +{
> +    VHostUserBase *vub = VHOST_USER_BASE(vdev);
> +    Error *local_err = NULL;
> +
> +    /*
> +     * There will have been a warning during vhost_dev_init, but lets
> +     * assert here as nothing will go right now.
> +     */
> +    g_assert(vub->config_size && vub->vhost_user.supports_config == true);
> +
> +    if (vhost_dev_get_config(&vub->vhost_dev, config,
> +                             vub->config_size, &local_err)) {
> +        error_report_err(local_err);
> +    }
> +}
> +
> +/*
> + * When the daemon signals an update to the config we just need to
> + * signal the guest as we re-read the config on demand above.
> + */
> +static int vub_config_notifier(struct vhost_dev *dev)
> +{
> +    virtio_notify_config(dev->vdev);
> +    return 0;
> +}
> +
> +const VhostDevConfigOps vub_config_ops = {
> +    .vhost_dev_config_notifier = vub_config_notifier,
> +};
> +
>  static void vub_handle_output(VirtIODevice *vdev, VirtQueue *vq)
>  {
>      /*
> @@ -141,12 +177,21 @@ static int vub_connect(DeviceState *dev)
>  {
>      VirtIODevice *vdev = VIRTIO_DEVICE(dev);
>      VHostUserBase *vub = VHOST_USER_BASE(vdev);
> +    struct vhost_dev *vhost_dev = &vub->vhost_dev;
>  
>      if (vub->connected) {
>          return 0;
>      }
>      vub->connected = true;
>  
> +    /*
> +     * If we support VHOST_USER_GET_CONFIG we must enable the notifier
> +     * so we can ping the guest when it updates.
> +     */
> +    if (vub->vhost_user.supports_config) {
> +        vhost_dev_set_config_notifier(vhost_dev, &vub_config_ops);
> +    }
> +
>      /* restore vhost state */
>      if (virtio_device_started(vdev, vdev->status)) {
>          vub_start(vdev);
> @@ -214,11 +259,20 @@ static void vub_device_realize(DeviceState *dev, Error **errp)
>          vub->num_vqs = 1; /* reasonable default? */
>      }
>  
> +    /*
> +     * We can't handle config requests unless we know the size of the
> +     * config region, specialisations of the vhost-user-device will be
> +     * able to set this.
> +     */
> +    if (vub->config_size) {
> +        vub->vhost_user.supports_config = true;
> +    }
> +
>      if (!vhost_user_init(&vub->vhost_user, &vub->chardev, errp)) {
>          return;
>      }
>  
> -    virtio_init(vdev, vub->virtio_id, 0);
> +    virtio_init(vdev, vub->virtio_id, vub->config_size);
>  
>      /*
>       * Disable guest notifiers, by default all notifications will be via the
> @@ -268,6 +322,7 @@ static void vub_class_init(ObjectClass *klass, void *data)
>      vdc->realize = vub_device_realize;
>      vdc->unrealize = vub_device_unrealize;
>      vdc->get_features = vub_get_features;
> +    vdc->get_config = vub_get_config;
>      vdc->set_status = vub_set_status;
>  }
>  
> @@ -295,6 +350,7 @@ static Property vud_properties[] = {
>      DEFINE_PROP_CHR("chardev", VHostUserBase, chardev),
>      DEFINE_PROP_UINT16("virtio-id", VHostUserBase, virtio_id, 0),
>      DEFINE_PROP_UINT32("num_vqs", VHostUserBase, num_vqs, 1),
> +    DEFINE_PROP_UINT32("config_size", VHostUserBase, config_size, 0),
>      DEFINE_PROP_END_OF_LIST(),
>  };
>  
> -- 
> 2.39.2



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Virtio-fs] [PATCH v3 10/20] hw/virtio: add config support to vhost-user-device
@ 2023-07-10 19:58     ` Michael S. Tsirkin
  0 siblings, 0 replies; 66+ messages in thread
From: Michael S. Tsirkin @ 2023-07-10 19:58 UTC (permalink / raw)
  To: Alex Bennée
  Cc: qemu-devel, Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Mark Cave-Ayland, Kevin Wolf,
	Markus Armbruster, Gerd Hoffmann, Mathieu Poirier, Hanna Reitz,
	Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

On Mon, Jul 10, 2023 at 04:35:12PM +0100, Alex Bennée wrote:
> To use the generic device the user will need to provide the config
> region size via the command line. We also add a notifier so the guest
> can be pinged if the remote daemon updates the config.
> 
> With these changes:
> 
>   -device vhost-user-device-pci,virtio-id=41,num_vqs=2,config_size=8
> 
> is equivalent to:
> 
>   -device vhost-user-gpio-pci
> 
> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>


This one I think it's best to defer until we get a better
handle on how we want the configuration to look.


> ---
>  include/hw/virtio/vhost-user-device.h |  1 +
>  hw/virtio/vhost-user-device.c         | 58 ++++++++++++++++++++++++++-
>  2 files changed, 58 insertions(+), 1 deletion(-)
> 
> diff --git a/include/hw/virtio/vhost-user-device.h b/include/hw/virtio/vhost-user-device.h
> index 9105011e25..3ddf88a146 100644
> --- a/include/hw/virtio/vhost-user-device.h
> +++ b/include/hw/virtio/vhost-user-device.h
> @@ -22,6 +22,7 @@ struct VHostUserBase {
>      CharBackend chardev;
>      uint16_t virtio_id;
>      uint32_t num_vqs;
> +    uint32_t config_size;
>      /* State tracking */
>      VhostUserState vhost_user;
>      struct vhost_virtqueue *vhost_vq;
> diff --git a/hw/virtio/vhost-user-device.c b/hw/virtio/vhost-user-device.c
> index b0239fa033..2b028cae08 100644
> --- a/hw/virtio/vhost-user-device.c
> +++ b/hw/virtio/vhost-user-device.c
> @@ -117,6 +117,42 @@ static uint64_t vub_get_features(VirtIODevice *vdev,
>      return vub->vhost_dev.features & ~(1ULL << VHOST_USER_F_PROTOCOL_FEATURES);
>  }
>  
> +/*
> + * To handle VirtIO config we need to know the size of the config
> + * space. We don't cache the config but re-fetch it from the guest
> + * every time in case something has changed.
> + */
> +static void vub_get_config(VirtIODevice *vdev, uint8_t *config)
> +{
> +    VHostUserBase *vub = VHOST_USER_BASE(vdev);
> +    Error *local_err = NULL;
> +
> +    /*
> +     * There will have been a warning during vhost_dev_init, but lets
> +     * assert here as nothing will go right now.
> +     */
> +    g_assert(vub->config_size && vub->vhost_user.supports_config == true);
> +
> +    if (vhost_dev_get_config(&vub->vhost_dev, config,
> +                             vub->config_size, &local_err)) {
> +        error_report_err(local_err);
> +    }
> +}
> +
> +/*
> + * When the daemon signals an update to the config we just need to
> + * signal the guest as we re-read the config on demand above.
> + */
> +static int vub_config_notifier(struct vhost_dev *dev)
> +{
> +    virtio_notify_config(dev->vdev);
> +    return 0;
> +}
> +
> +const VhostDevConfigOps vub_config_ops = {
> +    .vhost_dev_config_notifier = vub_config_notifier,
> +};
> +
>  static void vub_handle_output(VirtIODevice *vdev, VirtQueue *vq)
>  {
>      /*
> @@ -141,12 +177,21 @@ static int vub_connect(DeviceState *dev)
>  {
>      VirtIODevice *vdev = VIRTIO_DEVICE(dev);
>      VHostUserBase *vub = VHOST_USER_BASE(vdev);
> +    struct vhost_dev *vhost_dev = &vub->vhost_dev;
>  
>      if (vub->connected) {
>          return 0;
>      }
>      vub->connected = true;
>  
> +    /*
> +     * If we support VHOST_USER_GET_CONFIG we must enable the notifier
> +     * so we can ping the guest when it updates.
> +     */
> +    if (vub->vhost_user.supports_config) {
> +        vhost_dev_set_config_notifier(vhost_dev, &vub_config_ops);
> +    }
> +
>      /* restore vhost state */
>      if (virtio_device_started(vdev, vdev->status)) {
>          vub_start(vdev);
> @@ -214,11 +259,20 @@ static void vub_device_realize(DeviceState *dev, Error **errp)
>          vub->num_vqs = 1; /* reasonable default? */
>      }
>  
> +    /*
> +     * We can't handle config requests unless we know the size of the
> +     * config region, specialisations of the vhost-user-device will be
> +     * able to set this.
> +     */
> +    if (vub->config_size) {
> +        vub->vhost_user.supports_config = true;
> +    }
> +
>      if (!vhost_user_init(&vub->vhost_user, &vub->chardev, errp)) {
>          return;
>      }
>  
> -    virtio_init(vdev, vub->virtio_id, 0);
> +    virtio_init(vdev, vub->virtio_id, vub->config_size);
>  
>      /*
>       * Disable guest notifiers, by default all notifications will be via the
> @@ -268,6 +322,7 @@ static void vub_class_init(ObjectClass *klass, void *data)
>      vdc->realize = vub_device_realize;
>      vdc->unrealize = vub_device_unrealize;
>      vdc->get_features = vub_get_features;
> +    vdc->get_config = vub_get_config;
>      vdc->set_status = vub_set_status;
>  }
>  
> @@ -295,6 +350,7 @@ static Property vud_properties[] = {
>      DEFINE_PROP_CHR("chardev", VHostUserBase, chardev),
>      DEFINE_PROP_UINT16("virtio-id", VHostUserBase, virtio_id, 0),
>      DEFINE_PROP_UINT32("num_vqs", VHostUserBase, num_vqs, 1),
> +    DEFINE_PROP_UINT32("config_size", VHostUserBase, config_size, 0),
>      DEFINE_PROP_END_OF_LIST(),
>  };
>  
> -- 
> 2.39.2


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v3 07/20] virtio: add vhost-user-base and a generic vhost-user-device
  2023-07-10 15:35   ` [Virtio-fs] " Alex Bennée
@ 2023-07-10 20:15     ` Michael S. Tsirkin
  -1 siblings, 0 replies; 66+ messages in thread
From: Michael S. Tsirkin @ 2023-07-10 20:15 UTC (permalink / raw)
  To: Alex Bennée
  Cc: qemu-devel, Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Mark Cave-Ayland, Kevin Wolf,
	Markus Armbruster, Gerd Hoffmann, Mathieu Poirier, Hanna Reitz,
	Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

> +static const TypeInfo vud_info = {
> +    .name = TYPE_VHOST_USER_DEVICE,
> +    .parent = TYPE_VHOST_USER_BASE,
> +    .instance_size = sizeof(VHostUserBase),
> +    .class_init = vud_class_init,
> +    .class_size = sizeof(VHostUserBaseClass),

I wish you didn't tie the refactoring in with new functionality.
I applied but blocked creating these for now with:

Subject: [PATCH] vhost-user-device: block creating instances
Message-Id: <b10d1e585adf8a5348bd886333a8c55dcdef6048.1689020067.git.mst@redhat.com>

block this until we are ready to commit to this command line.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 hw/virtio/vhost-user-device.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/virtio/vhost-user-device.c b/hw/virtio/vhost-user-device.c
index 2b028cae08..ded97b6d70 100644
--- a/hw/virtio/vhost-user-device.c
+++ b/hw/virtio/vhost-user-device.c
@@ -369,6 +369,7 @@ static const TypeInfo vud_info = {
     .instance_size = sizeof(VHostUserBase),
     .class_init = vud_class_init,
     .class_size = sizeof(VHostUserBaseClass),
+    .abstract = true
 };

 static void vu_register_types(void)

-- 
MST



^ permalink raw reply related	[flat|nested] 66+ messages in thread

* Re: [Virtio-fs] [PATCH v3 07/20] virtio: add vhost-user-base and a generic vhost-user-device
@ 2023-07-10 20:15     ` Michael S. Tsirkin
  0 siblings, 0 replies; 66+ messages in thread
From: Michael S. Tsirkin @ 2023-07-10 20:15 UTC (permalink / raw)
  To: Alex Bennée
  Cc: qemu-devel, Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Mark Cave-Ayland, Kevin Wolf,
	Markus Armbruster, Gerd Hoffmann, Mathieu Poirier, Hanna Reitz,
	Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

> +static const TypeInfo vud_info = {
> +    .name = TYPE_VHOST_USER_DEVICE,
> +    .parent = TYPE_VHOST_USER_BASE,
> +    .instance_size = sizeof(VHostUserBase),
> +    .class_init = vud_class_init,
> +    .class_size = sizeof(VHostUserBaseClass),

I wish you didn't tie the refactoring in with new functionality.
I applied but blocked creating these for now with:

Subject: [PATCH] vhost-user-device: block creating instances
Message-Id: <b10d1e585adf8a5348bd886333a8c55dcdef6048.1689020067.git.mst@redhat.com>

block this until we are ready to commit to this command line.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 hw/virtio/vhost-user-device.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/virtio/vhost-user-device.c b/hw/virtio/vhost-user-device.c
index 2b028cae08..ded97b6d70 100644
--- a/hw/virtio/vhost-user-device.c
+++ b/hw/virtio/vhost-user-device.c
@@ -369,6 +369,7 @@ static const TypeInfo vud_info = {
     .instance_size = sizeof(VHostUserBase),
     .class_init = vud_class_init,
     .class_size = sizeof(VHostUserBaseClass),
+    .abstract = true
 };

 static void vu_register_types(void)

-- 
MST


^ permalink raw reply related	[flat|nested] 66+ messages in thread

* Re: [PATCH v3 03/20] hw/virtio: fix typo in VIRTIO_CONFIG_IRQ_IDX comments
  2023-07-10 15:35   ` [Virtio-fs] " Alex Bennée
@ 2023-07-10 21:56     ` Philippe Mathieu-Daudé
  -1 siblings, 0 replies; 66+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-10 21:56 UTC (permalink / raw)
  To: Alex Bennée, qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

On 10/7/23 17:35, Alex Bennée wrote:
> Fixes: 544f0278af (virtio: introduce macro VIRTIO_CONFIG_IRQ_IDX)
> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
> ---
>   hw/display/vhost-user-gpu.c    | 4 ++--
>   hw/net/virtio-net.c            | 4 ++--
>   hw/virtio/vhost-user-fs.c      | 4 ++--
>   hw/virtio/vhost-user-gpio.c    | 2 +-
>   hw/virtio/vhost-vsock-common.c | 4 ++--
>   hw/virtio/virtio-crypto.c      | 4 ++--
>   6 files changed, 11 insertions(+), 11 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Virtio-fs] [PATCH v3 03/20] hw/virtio: fix typo in VIRTIO_CONFIG_IRQ_IDX comments
@ 2023-07-10 21:56     ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 66+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-10 21:56 UTC (permalink / raw)
  To: Alex Bennée, qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

On 10/7/23 17:35, Alex Bennée wrote:
> Fixes: 544f0278af (virtio: introduce macro VIRTIO_CONFIG_IRQ_IDX)
> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
> ---
>   hw/display/vhost-user-gpu.c    | 4 ++--
>   hw/net/virtio-net.c            | 4 ++--
>   hw/virtio/vhost-user-fs.c      | 4 ++--
>   hw/virtio/vhost-user-gpio.c    | 2 +-
>   hw/virtio/vhost-vsock-common.c | 4 ++--
>   hw/virtio/virtio-crypto.c      | 4 ++--
>   6 files changed, 11 insertions(+), 11 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v3 05/20] include/hw/virtio: add kerneldoc for virtio_init
  2023-07-10 15:35   ` [Virtio-fs] " Alex Bennée
@ 2023-07-10 21:58     ` Philippe Mathieu-Daudé
  -1 siblings, 0 replies; 66+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-10 21:58 UTC (permalink / raw)
  To: Alex Bennée, qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

On 10/7/23 17:35, Alex Bennée wrote:
> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
> ---
>   include/hw/virtio/virtio.h | 6 ++++++
>   1 file changed, 6 insertions(+)

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Virtio-fs] [PATCH v3 05/20] include/hw/virtio: add kerneldoc for virtio_init
@ 2023-07-10 21:58     ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 66+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-10 21:58 UTC (permalink / raw)
  To: Alex Bennée, qemu-devel
  Cc: Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

On 10/7/23 17:35, Alex Bennée wrote:
> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
> ---
>   include/hw/virtio/virtio.h | 6 ++++++
>   1 file changed, 6 insertions(+)

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v3 10/20] hw/virtio: add config support to vhost-user-device
  2023-07-10 19:58     ` [Virtio-fs] " Michael S. Tsirkin
@ 2023-08-31 14:23       ` Albert Esteve
  -1 siblings, 0 replies; 66+ messages in thread
From: Albert Esteve @ 2023-08-31 14:23 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Alex Bennée, qemu-devel, Marc-André Lureau, Jason Wang,
	Viresh Kumar, Raphael Norwitz, Paolo Bonzini,
	Daniel P. Berrangé,
	qemu-block, Eric Blake, Mark Cave-Ayland, Kevin Wolf,
	Markus Armbruster, Gerd Hoffmann, Mathieu Poirier, Hanna Reitz,
	Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

[-- Attachment #1: Type: text/plain, Size: 6108 bytes --]

Sorry to bring up this post, it's been a while since you posted.
But I have been testing the patch the last couple of days.

On Mon, Jul 10, 2023 at 9:58 PM Michael S. Tsirkin <mst@redhat.com> wrote:

> On Mon, Jul 10, 2023 at 04:35:12PM +0100, Alex Bennée wrote:
> > To use the generic device the user will need to provide the config
> > region size via the command line. We also add a notifier so the guest
> > can be pinged if the remote daemon updates the config.
> >
> > With these changes:
> >
> >   -device vhost-user-device-pci,virtio-id=41,num_vqs=2,config_size=8
> >
> > is equivalent to:
> >
> >   -device vhost-user-gpio-pci
> >
> > Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
>
>
> This one I think it's best to defer until we get a better
> handle on how we want the configuration to look.
>
>
> > ---
> >  include/hw/virtio/vhost-user-device.h |  1 +
> >  hw/virtio/vhost-user-device.c         | 58 ++++++++++++++++++++++++++-
> >  2 files changed, 58 insertions(+), 1 deletion(-)
> >
> > diff --git a/include/hw/virtio/vhost-user-device.h
> b/include/hw/virtio/vhost-user-device.h
> > index 9105011e25..3ddf88a146 100644
> > --- a/include/hw/virtio/vhost-user-device.h
> > +++ b/include/hw/virtio/vhost-user-device.h
> > @@ -22,6 +22,7 @@ struct VHostUserBase {
> >      CharBackend chardev;
> >      uint16_t virtio_id;
> >      uint32_t num_vqs;
> > +    uint32_t config_size;
> >      /* State tracking */
> >      VhostUserState vhost_user;
> >      struct vhost_virtqueue *vhost_vq;
> > diff --git a/hw/virtio/vhost-user-device.c
> b/hw/virtio/vhost-user-device.c
> > index b0239fa033..2b028cae08 100644
> > --- a/hw/virtio/vhost-user-device.c
> > +++ b/hw/virtio/vhost-user-device.c
> > @@ -117,6 +117,42 @@ static uint64_t vub_get_features(VirtIODevice *vdev,
> >      return vub->vhost_dev.features & ~(1ULL <<
> VHOST_USER_F_PROTOCOL_FEATURES);
> >  }
> >
> > +/*
> > + * To handle VirtIO config we need to know the size of the config
> > + * space. We don't cache the config but re-fetch it from the guest
> > + * every time in case something has changed.
> > + */
> > +static void vub_get_config(VirtIODevice *vdev, uint8_t *config)
> > +{
> > +    VHostUserBase *vub = VHOST_USER_BASE(vdev);
> > +    Error *local_err = NULL;
> > +
> > +    /*
> > +     * There will have been a warning during vhost_dev_init, but lets
> > +     * assert here as nothing will go right now.
> > +     */
> > +    g_assert(vub->config_size && vub->vhost_user.supports_config ==
> true);
> > +
> > +    if (vhost_dev_get_config(&vub->vhost_dev, config,
> > +                             vub->config_size, &local_err)) {
> > +        error_report_err(local_err);
> > +    }
> > +}
> > +
> > +/*
> > + * When the daemon signals an update to the config we just need to
> > + * signal the guest as we re-read the config on demand above.
> > + */
> > +static int vub_config_notifier(struct vhost_dev *dev)
> > +{
> > +    virtio_notify_config(dev->vdev);
> > +    return 0;
> > +}
> > +
> > +const VhostDevConfigOps vub_config_ops = {
> > +    .vhost_dev_config_notifier = vub_config_notifier,
> > +};
> > +
> >  static void vub_handle_output(VirtIODevice *vdev, VirtQueue *vq)
> >  {
> >      /*
> > @@ -141,12 +177,21 @@ static int vub_connect(DeviceState *dev)
> >  {
> >      VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> >      VHostUserBase *vub = VHOST_USER_BASE(vdev);
> > +    struct vhost_dev *vhost_dev = &vub->vhost_dev;
> >
> >      if (vub->connected) {
> >          return 0;
> >      }
> >      vub->connected = true;
> >
> > +    /*
> > +     * If we support VHOST_USER_GET_CONFIG we must enable the notifier
> > +     * so we can ping the guest when it updates.
> > +     */
> > +    if (vub->vhost_user.supports_config) {
> > +        vhost_dev_set_config_notifier(vhost_dev, &vub_config_ops);
> > +    }
> > +
> >      /* restore vhost state */
> >      if (virtio_device_started(vdev, vdev->status)) {
> >          vub_start(vdev);
> > @@ -214,11 +259,20 @@ static void vub_device_realize(DeviceState *dev,
> Error **errp)
> >          vub->num_vqs = 1; /* reasonable default? */
> >      }
> >
> > +    /*
> > +     * We can't handle config requests unless we know the size of the
> > +     * config region, specialisations of the vhost-user-device will be
> > +     * able to set this.
> > +     */
> > +    if (vub->config_size) {
> > +        vub->vhost_user.supports_config = true;
> > +    }
>

Shouldn't the `supports_config = true' be set before we
call vhost_dev_init() a few lines above?
Otherwise, we end up checking the `supports_config` attribute from within
`vhost_user_backend_init()` (in vhost_user source file)
before the VhostUserState is set, causing this warning to pop if the
backend supports the CONFIG feature:
```
qemu-system-x86_64: warning: vhost-user backend supports
VHOST_USER_PROTOCOL_F_CONFIG but QEMU does not.
```


> > +
> >      if (!vhost_user_init(&vub->vhost_user, &vub->chardev, errp)) {
> >          return;
> >      }
> >
> > -    virtio_init(vdev, vub->virtio_id, 0);
> > +    virtio_init(vdev, vub->virtio_id, vub->config_size);
> >
> >      /*
> >       * Disable guest notifiers, by default all notifications will be
> via the
> > @@ -268,6 +322,7 @@ static void vub_class_init(ObjectClass *klass, void
> *data)
> >      vdc->realize = vub_device_realize;
> >      vdc->unrealize = vub_device_unrealize;
> >      vdc->get_features = vub_get_features;
> > +    vdc->get_config = vub_get_config;
> >      vdc->set_status = vub_set_status;
> >  }
> >
> > @@ -295,6 +350,7 @@ static Property vud_properties[] = {
> >      DEFINE_PROP_CHR("chardev", VHostUserBase, chardev),
> >      DEFINE_PROP_UINT16("virtio-id", VHostUserBase, virtio_id, 0),
> >      DEFINE_PROP_UINT32("num_vqs", VHostUserBase, num_vqs, 1),
> > +    DEFINE_PROP_UINT32("config_size", VHostUserBase, config_size, 0),
> >      DEFINE_PROP_END_OF_LIST(),
> >  };
> >
> > --
> > 2.39.2
>
>
>

[-- Attachment #2: Type: text/html, Size: 7895 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Virtio-fs] [PATCH v3 10/20] hw/virtio: add config support to vhost-user-device
@ 2023-08-31 14:23       ` Albert Esteve
  0 siblings, 0 replies; 66+ messages in thread
From: Albert Esteve @ 2023-08-31 14:23 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Alex Bennée, qemu-devel, Marc-André Lureau, Jason Wang,
	Viresh Kumar, Raphael Norwitz, Paolo Bonzini,
	Daniel P. Berrangé,
	qemu-block, Eric Blake, Mark Cave-Ayland, Kevin Wolf,
	Markus Armbruster, Gerd Hoffmann, Mathieu Poirier, Hanna Reitz,
	Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

[-- Attachment #1: Type: text/plain, Size: 6108 bytes --]

Sorry to bring up this post, it's been a while since you posted.
But I have been testing the patch the last couple of days.

On Mon, Jul 10, 2023 at 9:58 PM Michael S. Tsirkin <mst@redhat.com> wrote:

> On Mon, Jul 10, 2023 at 04:35:12PM +0100, Alex Bennée wrote:
> > To use the generic device the user will need to provide the config
> > region size via the command line. We also add a notifier so the guest
> > can be pinged if the remote daemon updates the config.
> >
> > With these changes:
> >
> >   -device vhost-user-device-pci,virtio-id=41,num_vqs=2,config_size=8
> >
> > is equivalent to:
> >
> >   -device vhost-user-gpio-pci
> >
> > Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
>
>
> This one I think it's best to defer until we get a better
> handle on how we want the configuration to look.
>
>
> > ---
> >  include/hw/virtio/vhost-user-device.h |  1 +
> >  hw/virtio/vhost-user-device.c         | 58 ++++++++++++++++++++++++++-
> >  2 files changed, 58 insertions(+), 1 deletion(-)
> >
> > diff --git a/include/hw/virtio/vhost-user-device.h
> b/include/hw/virtio/vhost-user-device.h
> > index 9105011e25..3ddf88a146 100644
> > --- a/include/hw/virtio/vhost-user-device.h
> > +++ b/include/hw/virtio/vhost-user-device.h
> > @@ -22,6 +22,7 @@ struct VHostUserBase {
> >      CharBackend chardev;
> >      uint16_t virtio_id;
> >      uint32_t num_vqs;
> > +    uint32_t config_size;
> >      /* State tracking */
> >      VhostUserState vhost_user;
> >      struct vhost_virtqueue *vhost_vq;
> > diff --git a/hw/virtio/vhost-user-device.c
> b/hw/virtio/vhost-user-device.c
> > index b0239fa033..2b028cae08 100644
> > --- a/hw/virtio/vhost-user-device.c
> > +++ b/hw/virtio/vhost-user-device.c
> > @@ -117,6 +117,42 @@ static uint64_t vub_get_features(VirtIODevice *vdev,
> >      return vub->vhost_dev.features & ~(1ULL <<
> VHOST_USER_F_PROTOCOL_FEATURES);
> >  }
> >
> > +/*
> > + * To handle VirtIO config we need to know the size of the config
> > + * space. We don't cache the config but re-fetch it from the guest
> > + * every time in case something has changed.
> > + */
> > +static void vub_get_config(VirtIODevice *vdev, uint8_t *config)
> > +{
> > +    VHostUserBase *vub = VHOST_USER_BASE(vdev);
> > +    Error *local_err = NULL;
> > +
> > +    /*
> > +     * There will have been a warning during vhost_dev_init, but lets
> > +     * assert here as nothing will go right now.
> > +     */
> > +    g_assert(vub->config_size && vub->vhost_user.supports_config ==
> true);
> > +
> > +    if (vhost_dev_get_config(&vub->vhost_dev, config,
> > +                             vub->config_size, &local_err)) {
> > +        error_report_err(local_err);
> > +    }
> > +}
> > +
> > +/*
> > + * When the daemon signals an update to the config we just need to
> > + * signal the guest as we re-read the config on demand above.
> > + */
> > +static int vub_config_notifier(struct vhost_dev *dev)
> > +{
> > +    virtio_notify_config(dev->vdev);
> > +    return 0;
> > +}
> > +
> > +const VhostDevConfigOps vub_config_ops = {
> > +    .vhost_dev_config_notifier = vub_config_notifier,
> > +};
> > +
> >  static void vub_handle_output(VirtIODevice *vdev, VirtQueue *vq)
> >  {
> >      /*
> > @@ -141,12 +177,21 @@ static int vub_connect(DeviceState *dev)
> >  {
> >      VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> >      VHostUserBase *vub = VHOST_USER_BASE(vdev);
> > +    struct vhost_dev *vhost_dev = &vub->vhost_dev;
> >
> >      if (vub->connected) {
> >          return 0;
> >      }
> >      vub->connected = true;
> >
> > +    /*
> > +     * If we support VHOST_USER_GET_CONFIG we must enable the notifier
> > +     * so we can ping the guest when it updates.
> > +     */
> > +    if (vub->vhost_user.supports_config) {
> > +        vhost_dev_set_config_notifier(vhost_dev, &vub_config_ops);
> > +    }
> > +
> >      /* restore vhost state */
> >      if (virtio_device_started(vdev, vdev->status)) {
> >          vub_start(vdev);
> > @@ -214,11 +259,20 @@ static void vub_device_realize(DeviceState *dev,
> Error **errp)
> >          vub->num_vqs = 1; /* reasonable default? */
> >      }
> >
> > +    /*
> > +     * We can't handle config requests unless we know the size of the
> > +     * config region, specialisations of the vhost-user-device will be
> > +     * able to set this.
> > +     */
> > +    if (vub->config_size) {
> > +        vub->vhost_user.supports_config = true;
> > +    }
>

Shouldn't the `supports_config = true' be set before we
call vhost_dev_init() a few lines above?
Otherwise, we end up checking the `supports_config` attribute from within
`vhost_user_backend_init()` (in vhost_user source file)
before the VhostUserState is set, causing this warning to pop if the
backend supports the CONFIG feature:
```
qemu-system-x86_64: warning: vhost-user backend supports
VHOST_USER_PROTOCOL_F_CONFIG but QEMU does not.
```


> > +
> >      if (!vhost_user_init(&vub->vhost_user, &vub->chardev, errp)) {
> >          return;
> >      }
> >
> > -    virtio_init(vdev, vub->virtio_id, 0);
> > +    virtio_init(vdev, vub->virtio_id, vub->config_size);
> >
> >      /*
> >       * Disable guest notifiers, by default all notifications will be
> via the
> > @@ -268,6 +322,7 @@ static void vub_class_init(ObjectClass *klass, void
> *data)
> >      vdc->realize = vub_device_realize;
> >      vdc->unrealize = vub_device_unrealize;
> >      vdc->get_features = vub_get_features;
> > +    vdc->get_config = vub_get_config;
> >      vdc->set_status = vub_set_status;
> >  }
> >
> > @@ -295,6 +350,7 @@ static Property vud_properties[] = {
> >      DEFINE_PROP_CHR("chardev", VHostUserBase, chardev),
> >      DEFINE_PROP_UINT16("virtio-id", VHostUserBase, virtio_id, 0),
> >      DEFINE_PROP_UINT32("num_vqs", VHostUserBase, num_vqs, 1),
> > +    DEFINE_PROP_UINT32("config_size", VHostUserBase, config_size, 0),
> >      DEFINE_PROP_END_OF_LIST(),
> >  };
> >
> > --
> > 2.39.2
>
>
>

[-- Attachment #2: Type: text/html, Size: 7895 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v3 10/20] hw/virtio: add config support to vhost-user-device
  2023-08-31 14:23       ` [Virtio-fs] " Albert Esteve
@ 2023-08-31 15:47         ` Alex Bennée
  -1 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-08-31 15:47 UTC (permalink / raw)
  To: Albert Esteve
  Cc: Michael S. Tsirkin, qemu-devel, Marc-André Lureau,
	Jason Wang, Viresh Kumar, Raphael Norwitz, Paolo Bonzini,
	Daniel P. Berrangé,
	qemu-block, Eric Blake, Mark Cave-Ayland, Kevin Wolf,
	Markus Armbruster, Gerd Hoffmann, Mathieu Poirier, Hanna Reitz,
	Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi


Albert Esteve <aesteve@redhat.com> writes:

> Sorry to bring up this post, it's been a while since you posted.
> But I have been testing the patch the last couple of days.
>
> On Mon, Jul 10, 2023 at 9:58 PM Michael S. Tsirkin <mst@redhat.com> wrote:
>
>  On Mon, Jul 10, 2023 at 04:35:12PM +0100, Alex Bennée wrote:
>  > To use the generic device the user will need to provide the config
>  > region size via the command line. We also add a notifier so the guest
>  > can be pinged if the remote daemon updates the config.
>  > 
>  > With these changes:
>  > 
>  >   -device vhost-user-device-pci,virtio-id=41,num_vqs=2,config_size=8
>  > 
>  > is equivalent to:
>  > 
>  >   -device vhost-user-gpio-pci
>  > 
>  > Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
>
>  This one I think it's best to defer until we get a better
>  handle on how we want the configuration to look.
>
>  > ---
>  >  include/hw/virtio/vhost-user-device.h |  1 +
>  >  hw/virtio/vhost-user-device.c         | 58 ++++++++++++++++++++++++++-
>  >  2 files changed, 58 insertions(+), 1 deletion(-)
>  > 
>  > diff --git a/include/hw/virtio/vhost-user-device.h b/include/hw/virtio/vhost-user-device.h
>  > index 9105011e25..3ddf88a146 100644
>  > --- a/include/hw/virtio/vhost-user-device.h
>  > +++ b/include/hw/virtio/vhost-user-device.h
>  > @@ -22,6 +22,7 @@ struct VHostUserBase {
>  >      CharBackend chardev;
>  >      uint16_t virtio_id;
>  >      uint32_t num_vqs;
>  > +    uint32_t config_size;
>  >      /* State tracking */
>  >      VhostUserState vhost_user;
>  >      struct vhost_virtqueue *vhost_vq;
>  > diff --git a/hw/virtio/vhost-user-device.c b/hw/virtio/vhost-user-device.c
>  > index b0239fa033..2b028cae08 100644
>  > --- a/hw/virtio/vhost-user-device.c
>  > +++ b/hw/virtio/vhost-user-device.c
>  > @@ -117,6 +117,42 @@ static uint64_t vub_get_features(VirtIODevice *vdev,
>  >      return vub->vhost_dev.features & ~(1ULL << VHOST_USER_F_PROTOCOL_FEATURES);
>  >  }
>  >  
>  > +/*
>  > + * To handle VirtIO config we need to know the size of the config
>  > + * space. We don't cache the config but re-fetch it from the guest
>  > + * every time in case something has changed.
>  > + */
>  > +static void vub_get_config(VirtIODevice *vdev, uint8_t *config)
>  > +{
>  > +    VHostUserBase *vub = VHOST_USER_BASE(vdev);
>  > +    Error *local_err = NULL;
>  > +
>  > +    /*
>  > +     * There will have been a warning during vhost_dev_init, but lets
>  > +     * assert here as nothing will go right now.
>  > +     */
>  > +    g_assert(vub->config_size && vub->vhost_user.supports_config == true);
>  > +
>  > +    if (vhost_dev_get_config(&vub->vhost_dev, config,
>  > +                             vub->config_size, &local_err)) {
>  > +        error_report_err(local_err);
>  > +    }
>  > +}
>  > +
>  > +/*
>  > + * When the daemon signals an update to the config we just need to
>  > + * signal the guest as we re-read the config on demand above.
>  > + */
>  > +static int vub_config_notifier(struct vhost_dev *dev)
>  > +{
>  > +    virtio_notify_config(dev->vdev);
>  > +    return 0;
>  > +}
>  > +
>  > +const VhostDevConfigOps vub_config_ops = {
>  > +    .vhost_dev_config_notifier = vub_config_notifier,
>  > +};
>  > +
>  >  static void vub_handle_output(VirtIODevice *vdev, VirtQueue *vq)
>  >  {
>  >      /*
>  > @@ -141,12 +177,21 @@ static int vub_connect(DeviceState *dev)
>  >  {
>  >      VirtIODevice *vdev = VIRTIO_DEVICE(dev);
>  >      VHostUserBase *vub = VHOST_USER_BASE(vdev);
>  > +    struct vhost_dev *vhost_dev = &vub->vhost_dev;
>  >  
>  >      if (vub->connected) {
>  >          return 0;
>  >      }
>  >      vub->connected = true;
>  >  
>  > +    /*
>  > +     * If we support VHOST_USER_GET_CONFIG we must enable the notifier
>  > +     * so we can ping the guest when it updates.
>  > +     */
>  > +    if (vub->vhost_user.supports_config) {
>  > +        vhost_dev_set_config_notifier(vhost_dev, &vub_config_ops);
>  > +    }
>  > +
>  >      /* restore vhost state */
>  >      if (virtio_device_started(vdev, vdev->status)) {
>  >          vub_start(vdev);
>  > @@ -214,11 +259,20 @@ static void vub_device_realize(DeviceState *dev, Error **errp)
>  >          vub->num_vqs = 1; /* reasonable default? */
>  >      }
>  >  
>  > +    /*
>  > +     * We can't handle config requests unless we know the size of the
>  > +     * config region, specialisations of the vhost-user-device will be
>  > +     * able to set this.
>  > +     */
>  > +    if (vub->config_size) {
>  > +        vub->vhost_user.supports_config = true;
>  > +    }
>
> Shouldn't the `supports_config = true' be set before we call vhost_dev_init() a few lines above?
> Otherwise, we end up checking the `supports_config` attribute from within `vhost_user_backend_init()` (in vhost_user
> source file)
> before the VhostUserState is set, causing this warning to pop if the backend supports the CONFIG feature:
> ```
> qemu-system-x86_64: warning: vhost-user backend supports VHOST_USER_PROTOCOL_F_CONFIG but QEMU does
> not.
> ```

I allude to that in the comments for vub_get_config() further up.
However the more I look at this the more confused I am about the
original intention of the flag I added (*blush*). I think we need to
handle the following cases:

 - the virtio device has no config space
 - the virtio device has config space, emulated inside qemu
 - the virtio vhost device has config space, emulated inside qemu
 - the virtio vhost device has config space, handled by vhost

for the final case the qemu internals need to be able to handle the
signalling of updates to the config by the vhost device by way of the
notifier.

In the case of a "standalone" vhost-user daemon we won't even know if
there is a config space until we have connected to it and queried its
size via protocol messages.

Maybe we need two fields?

  - supports_remote_config (device is capable of handling remote config)
  - config_location one of { NONE, LOCAL, REMOTE }
  
>  
>  > +
>  >      if (!vhost_user_init(&vub->vhost_user, &vub->chardev, errp)) {
>  >          return;
>  >      }
>  >  
>  > -    virtio_init(vdev, vub->virtio_id, 0);
>  > +    virtio_init(vdev, vub->virtio_id, vub->config_size);
>  >  
>  >      /*
>  >       * Disable guest notifiers, by default all notifications will be via the
>  > @@ -268,6 +322,7 @@ static void vub_class_init(ObjectClass *klass, void *data)
>  >      vdc->realize = vub_device_realize;
>  >      vdc->unrealize = vub_device_unrealize;
>  >      vdc->get_features = vub_get_features;
>  > +    vdc->get_config = vub_get_config;
>  >      vdc->set_status = vub_set_status;
>  >  }
>  >  
>  > @@ -295,6 +350,7 @@ static Property vud_properties[] = {
>  >      DEFINE_PROP_CHR("chardev", VHostUserBase, chardev),
>  >      DEFINE_PROP_UINT16("virtio-id", VHostUserBase, virtio_id, 0),
>  >      DEFINE_PROP_UINT32("num_vqs", VHostUserBase, num_vqs, 1),
>  > +    DEFINE_PROP_UINT32("config_size", VHostUserBase, config_size, 0),
>  >      DEFINE_PROP_END_OF_LIST(),
>  >  };
>  >  
>  > -- 
>  > 2.39.2


-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Virtio-fs] [PATCH v3 10/20] hw/virtio: add config support to vhost-user-device
@ 2023-08-31 15:47         ` Alex Bennée
  0 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-08-31 15:47 UTC (permalink / raw)
  To: Albert Esteve
  Cc: Michael S. Tsirkin, qemu-devel, Marc-André Lureau,
	Jason Wang, Viresh Kumar, Raphael Norwitz, Paolo Bonzini,
	Daniel P. Berrangé,
	qemu-block, Eric Blake, Mark Cave-Ayland, Kevin Wolf,
	Markus Armbruster, Gerd Hoffmann, Mathieu Poirier, Hanna Reitz,
	Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi


Albert Esteve <aesteve@redhat.com> writes:

> Sorry to bring up this post, it's been a while since you posted.
> But I have been testing the patch the last couple of days.
>
> On Mon, Jul 10, 2023 at 9:58 PM Michael S. Tsirkin <mst@redhat.com> wrote:
>
>  On Mon, Jul 10, 2023 at 04:35:12PM +0100, Alex Bennée wrote:
>  > To use the generic device the user will need to provide the config
>  > region size via the command line. We also add a notifier so the guest
>  > can be pinged if the remote daemon updates the config.
>  > 
>  > With these changes:
>  > 
>  >   -device vhost-user-device-pci,virtio-id=41,num_vqs=2,config_size=8
>  > 
>  > is equivalent to:
>  > 
>  >   -device vhost-user-gpio-pci
>  > 
>  > Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
>
>  This one I think it's best to defer until we get a better
>  handle on how we want the configuration to look.
>
>  > ---
>  >  include/hw/virtio/vhost-user-device.h |  1 +
>  >  hw/virtio/vhost-user-device.c         | 58 ++++++++++++++++++++++++++-
>  >  2 files changed, 58 insertions(+), 1 deletion(-)
>  > 
>  > diff --git a/include/hw/virtio/vhost-user-device.h b/include/hw/virtio/vhost-user-device.h
>  > index 9105011e25..3ddf88a146 100644
>  > --- a/include/hw/virtio/vhost-user-device.h
>  > +++ b/include/hw/virtio/vhost-user-device.h
>  > @@ -22,6 +22,7 @@ struct VHostUserBase {
>  >      CharBackend chardev;
>  >      uint16_t virtio_id;
>  >      uint32_t num_vqs;
>  > +    uint32_t config_size;
>  >      /* State tracking */
>  >      VhostUserState vhost_user;
>  >      struct vhost_virtqueue *vhost_vq;
>  > diff --git a/hw/virtio/vhost-user-device.c b/hw/virtio/vhost-user-device.c
>  > index b0239fa033..2b028cae08 100644
>  > --- a/hw/virtio/vhost-user-device.c
>  > +++ b/hw/virtio/vhost-user-device.c
>  > @@ -117,6 +117,42 @@ static uint64_t vub_get_features(VirtIODevice *vdev,
>  >      return vub->vhost_dev.features & ~(1ULL << VHOST_USER_F_PROTOCOL_FEATURES);
>  >  }
>  >  
>  > +/*
>  > + * To handle VirtIO config we need to know the size of the config
>  > + * space. We don't cache the config but re-fetch it from the guest
>  > + * every time in case something has changed.
>  > + */
>  > +static void vub_get_config(VirtIODevice *vdev, uint8_t *config)
>  > +{
>  > +    VHostUserBase *vub = VHOST_USER_BASE(vdev);
>  > +    Error *local_err = NULL;
>  > +
>  > +    /*
>  > +     * There will have been a warning during vhost_dev_init, but lets
>  > +     * assert here as nothing will go right now.
>  > +     */
>  > +    g_assert(vub->config_size && vub->vhost_user.supports_config == true);
>  > +
>  > +    if (vhost_dev_get_config(&vub->vhost_dev, config,
>  > +                             vub->config_size, &local_err)) {
>  > +        error_report_err(local_err);
>  > +    }
>  > +}
>  > +
>  > +/*
>  > + * When the daemon signals an update to the config we just need to
>  > + * signal the guest as we re-read the config on demand above.
>  > + */
>  > +static int vub_config_notifier(struct vhost_dev *dev)
>  > +{
>  > +    virtio_notify_config(dev->vdev);
>  > +    return 0;
>  > +}
>  > +
>  > +const VhostDevConfigOps vub_config_ops = {
>  > +    .vhost_dev_config_notifier = vub_config_notifier,
>  > +};
>  > +
>  >  static void vub_handle_output(VirtIODevice *vdev, VirtQueue *vq)
>  >  {
>  >      /*
>  > @@ -141,12 +177,21 @@ static int vub_connect(DeviceState *dev)
>  >  {
>  >      VirtIODevice *vdev = VIRTIO_DEVICE(dev);
>  >      VHostUserBase *vub = VHOST_USER_BASE(vdev);
>  > +    struct vhost_dev *vhost_dev = &vub->vhost_dev;
>  >  
>  >      if (vub->connected) {
>  >          return 0;
>  >      }
>  >      vub->connected = true;
>  >  
>  > +    /*
>  > +     * If we support VHOST_USER_GET_CONFIG we must enable the notifier
>  > +     * so we can ping the guest when it updates.
>  > +     */
>  > +    if (vub->vhost_user.supports_config) {
>  > +        vhost_dev_set_config_notifier(vhost_dev, &vub_config_ops);
>  > +    }
>  > +
>  >      /* restore vhost state */
>  >      if (virtio_device_started(vdev, vdev->status)) {
>  >          vub_start(vdev);
>  > @@ -214,11 +259,20 @@ static void vub_device_realize(DeviceState *dev, Error **errp)
>  >          vub->num_vqs = 1; /* reasonable default? */
>  >      }
>  >  
>  > +    /*
>  > +     * We can't handle config requests unless we know the size of the
>  > +     * config region, specialisations of the vhost-user-device will be
>  > +     * able to set this.
>  > +     */
>  > +    if (vub->config_size) {
>  > +        vub->vhost_user.supports_config = true;
>  > +    }
>
> Shouldn't the `supports_config = true' be set before we call vhost_dev_init() a few lines above?
> Otherwise, we end up checking the `supports_config` attribute from within `vhost_user_backend_init()` (in vhost_user
> source file)
> before the VhostUserState is set, causing this warning to pop if the backend supports the CONFIG feature:
> ```
> qemu-system-x86_64: warning: vhost-user backend supports VHOST_USER_PROTOCOL_F_CONFIG but QEMU does
> not.
> ```

I allude to that in the comments for vub_get_config() further up.
However the more I look at this the more confused I am about the
original intention of the flag I added (*blush*). I think we need to
handle the following cases:

 - the virtio device has no config space
 - the virtio device has config space, emulated inside qemu
 - the virtio vhost device has config space, emulated inside qemu
 - the virtio vhost device has config space, handled by vhost

for the final case the qemu internals need to be able to handle the
signalling of updates to the config by the vhost device by way of the
notifier.

In the case of a "standalone" vhost-user daemon we won't even know if
there is a config space until we have connected to it and queried its
size via protocol messages.

Maybe we need two fields?

  - supports_remote_config (device is capable of handling remote config)
  - config_location one of { NONE, LOCAL, REMOTE }
  
>  
>  > +
>  >      if (!vhost_user_init(&vub->vhost_user, &vub->chardev, errp)) {
>  >          return;
>  >      }
>  >  
>  > -    virtio_init(vdev, vub->virtio_id, 0);
>  > +    virtio_init(vdev, vub->virtio_id, vub->config_size);
>  >  
>  >      /*
>  >       * Disable guest notifiers, by default all notifications will be via the
>  > @@ -268,6 +322,7 @@ static void vub_class_init(ObjectClass *klass, void *data)
>  >      vdc->realize = vub_device_realize;
>  >      vdc->unrealize = vub_device_unrealize;
>  >      vdc->get_features = vub_get_features;
>  > +    vdc->get_config = vub_get_config;
>  >      vdc->set_status = vub_set_status;
>  >  }
>  >  
>  > @@ -295,6 +350,7 @@ static Property vud_properties[] = {
>  >      DEFINE_PROP_CHR("chardev", VHostUserBase, chardev),
>  >      DEFINE_PROP_UINT16("virtio-id", VHostUserBase, virtio_id, 0),
>  >      DEFINE_PROP_UINT32("num_vqs", VHostUserBase, num_vqs, 1),
>  > +    DEFINE_PROP_UINT32("config_size", VHostUserBase, config_size, 0),
>  >      DEFINE_PROP_END_OF_LIST(),
>  >  };
>  >  
>  > -- 
>  > 2.39.2


-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v3 10/20] hw/virtio: add config support to vhost-user-device
  2023-08-31 15:47         ` [Virtio-fs] " Alex Bennée
@ 2023-09-01  5:56           ` Erik Schilling
  -1 siblings, 0 replies; 66+ messages in thread
From: Erik Schilling @ 2023-09-01  5:56 UTC (permalink / raw)
  To: Alex Bennée, Albert Esteve
  Cc: Michael S. Tsirkin, qemu-devel, Marc-André Lureau,
	Jason Wang, Viresh Kumar, Raphael Norwitz, Paolo Bonzini,
	Daniel P. Berrangé,
	qemu-block, Eric Blake, Mark Cave-Ayland, Kevin Wolf,
	Markus Armbruster, Gerd Hoffmann, Mathieu Poirier, Hanna Reitz,
	Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

On Thu Aug 31, 2023 at 5:47 PM CEST, Alex Bennée wrote:
>
> Albert Esteve <aesteve@redhat.com> writes:
>
> > Sorry to bring up this post, it's been a while since you posted.
> > But I have been testing the patch the last couple of days.
> >
> > On Mon, Jul 10, 2023 at 9:58 PM Michael S. Tsirkin <mst@redhat.com> wrote:
> >
> >  On Mon, Jul 10, 2023 at 04:35:12PM +0100, Alex Bennée wrote:
> >  > To use the generic device the user will need to provide the config
> >  > region size via the command line. We also add a notifier so the guest
> >  > can be pinged if the remote daemon updates the config.
> >  > 
> >  > With these changes:
> >  > 
> >  >   -device vhost-user-device-pci,virtio-id=41,num_vqs=2,config_size=8
> >  > 
> >  > is equivalent to:
> >  > 
> >  >   -device vhost-user-gpio-pci
> >  > 
> >  > Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
> >
> >  This one I think it's best to defer until we get a better
> >  handle on how we want the configuration to look.
> >
> >  > ---
> >  >  include/hw/virtio/vhost-user-device.h |  1 +
> >  >  hw/virtio/vhost-user-device.c         | 58 ++++++++++++++++++++++++++-
> >  >  2 files changed, 58 insertions(+), 1 deletion(-)
> >  > 
> >  > diff --git a/include/hw/virtio/vhost-user-device.h b/include/hw/virtio/vhost-user-device.h
> >  > index 9105011e25..3ddf88a146 100644
> >  > --- a/include/hw/virtio/vhost-user-device.h
> >  > +++ b/include/hw/virtio/vhost-user-device.h
> >  > @@ -22,6 +22,7 @@ struct VHostUserBase {
> >  >      CharBackend chardev;
> >  >      uint16_t virtio_id;
> >  >      uint32_t num_vqs;
> >  > +    uint32_t config_size;
> >  >      /* State tracking */
> >  >      VhostUserState vhost_user;
> >  >      struct vhost_virtqueue *vhost_vq;
> >  > diff --git a/hw/virtio/vhost-user-device.c b/hw/virtio/vhost-user-device.c
> >  > index b0239fa033..2b028cae08 100644
> >  > --- a/hw/virtio/vhost-user-device.c
> >  > +++ b/hw/virtio/vhost-user-device.c
> >  > @@ -117,6 +117,42 @@ static uint64_t vub_get_features(VirtIODevice *vdev,
> >  >      return vub->vhost_dev.features & ~(1ULL << VHOST_USER_F_PROTOCOL_FEATURES);
> >  >  }
> >  >  
> >  > +/*
> >  > + * To handle VirtIO config we need to know the size of the config
> >  > + * space. We don't cache the config but re-fetch it from the guest
> >  > + * every time in case something has changed.
> >  > + */
> >  > +static void vub_get_config(VirtIODevice *vdev, uint8_t *config)
> >  > +{
> >  > +    VHostUserBase *vub = VHOST_USER_BASE(vdev);
> >  > +    Error *local_err = NULL;
> >  > +
> >  > +    /*
> >  > +     * There will have been a warning during vhost_dev_init, but lets
> >  > +     * assert here as nothing will go right now.
> >  > +     */
> >  > +    g_assert(vub->config_size && vub->vhost_user.supports_config == true);
> >  > +
> >  > +    if (vhost_dev_get_config(&vub->vhost_dev, config,
> >  > +                             vub->config_size, &local_err)) {
> >  > +        error_report_err(local_err);
> >  > +    }
> >  > +}
> >  > +
> >  > +/*
> >  > + * When the daemon signals an update to the config we just need to
> >  > + * signal the guest as we re-read the config on demand above.
> >  > + */
> >  > +static int vub_config_notifier(struct vhost_dev *dev)
> >  > +{
> >  > +    virtio_notify_config(dev->vdev);
> >  > +    return 0;
> >  > +}
> >  > +
> >  > +const VhostDevConfigOps vub_config_ops = {
> >  > +    .vhost_dev_config_notifier = vub_config_notifier,
> >  > +};
> >  > +
> >  >  static void vub_handle_output(VirtIODevice *vdev, VirtQueue *vq)
> >  >  {
> >  >      /*
> >  > @@ -141,12 +177,21 @@ static int vub_connect(DeviceState *dev)
> >  >  {
> >  >      VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> >  >      VHostUserBase *vub = VHOST_USER_BASE(vdev);
> >  > +    struct vhost_dev *vhost_dev = &vub->vhost_dev;
> >  >  
> >  >      if (vub->connected) {
> >  >          return 0;
> >  >      }
> >  >      vub->connected = true;
> >  >  
> >  > +    /*
> >  > +     * If we support VHOST_USER_GET_CONFIG we must enable the notifier
> >  > +     * so we can ping the guest when it updates.
> >  > +     */
> >  > +    if (vub->vhost_user.supports_config) {
> >  > +        vhost_dev_set_config_notifier(vhost_dev, &vub_config_ops);
> >  > +    }
> >  > +
> >  >      /* restore vhost state */
> >  >      if (virtio_device_started(vdev, vdev->status)) {
> >  >          vub_start(vdev);
> >  > @@ -214,11 +259,20 @@ static void vub_device_realize(DeviceState *dev, Error **errp)
> >  >          vub->num_vqs = 1; /* reasonable default? */
> >  >      }
> >  >  
> >  > +    /*
> >  > +     * We can't handle config requests unless we know the size of the
> >  > +     * config region, specialisations of the vhost-user-device will be
> >  > +     * able to set this.
> >  > +     */
> >  > +    if (vub->config_size) {
> >  > +        vub->vhost_user.supports_config = true;
> >  > +    }
> >
> > Shouldn't the `supports_config = true' be set before we call vhost_dev_init() a few lines above?
> > Otherwise, we end up checking the `supports_config` attribute from within `vhost_user_backend_init()` (in vhost_user
> > source file)
> > before the VhostUserState is set, causing this warning to pop if the backend supports the CONFIG feature:
> > ```
> > qemu-system-x86_64: warning: vhost-user backend supports VHOST_USER_PROTOCOL_F_CONFIG but QEMU does
> > not.
> > ```
>
> I allude to that in the comments for vub_get_config() further up.
> However the more I look at this the more confused I am about the
> original intention of the flag I added (*blush*). I think we need to
> handle the following cases:
>
>  - the virtio device has no config space
>  - the virtio device has config space, emulated inside qemu
>  - the virtio vhost device has config space, emulated inside qemu
>  - the virtio vhost device has config space, handled by vhost
>
> for the final case the qemu internals need to be able to handle the
> signalling of updates to the config by the vhost device by way of the
> notifier.
>
> In the case of a "standalone" vhost-user daemon we won't even know if
> there is a config space until we have connected to it and queried its
> size via protocol messages.
>
> Maybe we need two fields?
>
>   - supports_remote_config (device is capable of handling remote config)
>   - config_location one of { NONE, LOCAL, REMOTE }

Hm... Shouldn't the F_CONFIG flag already indicate
`supports_remote_config` (you mean "backend-handled" config, right?) and
the negotiation of the flag would clarify the location?

Of course, there would be a disambiguity between case 3 and 4. But
wouldn't that be decidable by the configured QEMU device? The new
standalone device could default to just forwarding the backend config
while the existing devices could continue providing their proxies where
required?

- Erik

>   
> >  
> >  > +
> >  >      if (!vhost_user_init(&vub->vhost_user, &vub->chardev, errp)) {
> >  >          return;
> >  >      }
> >  >  
> >  > -    virtio_init(vdev, vub->virtio_id, 0);
> >  > +    virtio_init(vdev, vub->virtio_id, vub->config_size);
> >  >  
> >  >      /*
> >  >       * Disable guest notifiers, by default all notifications will be via the
> >  > @@ -268,6 +322,7 @@ static void vub_class_init(ObjectClass *klass, void *data)
> >  >      vdc->realize = vub_device_realize;
> >  >      vdc->unrealize = vub_device_unrealize;
> >  >      vdc->get_features = vub_get_features;
> >  > +    vdc->get_config = vub_get_config;
> >  >      vdc->set_status = vub_set_status;
> >  >  }
> >  >  
> >  > @@ -295,6 +350,7 @@ static Property vud_properties[] = {
> >  >      DEFINE_PROP_CHR("chardev", VHostUserBase, chardev),
> >  >      DEFINE_PROP_UINT16("virtio-id", VHostUserBase, virtio_id, 0),
> >  >      DEFINE_PROP_UINT32("num_vqs", VHostUserBase, num_vqs, 1),
> >  > +    DEFINE_PROP_UINT32("config_size", VHostUserBase, config_size, 0),
> >  >      DEFINE_PROP_END_OF_LIST(),
> >  >  };
> >  >  
> >  > -- 
> >  > 2.39.2



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Virtio-fs] [PATCH v3 10/20] hw/virtio: add config support to vhost-user-device
@ 2023-09-01  5:56           ` Erik Schilling
  0 siblings, 0 replies; 66+ messages in thread
From: Erik Schilling @ 2023-09-01  5:56 UTC (permalink / raw)
  To: Alex Bennée, Albert Esteve
  Cc: Michael S. Tsirkin, qemu-devel, Marc-André Lureau,
	Jason Wang, Viresh Kumar, Raphael Norwitz, Paolo Bonzini,
	Daniel P. Berrangé,
	qemu-block, Eric Blake, Mark Cave-Ayland, Kevin Wolf,
	Markus Armbruster, Gerd Hoffmann, Mathieu Poirier, Hanna Reitz,
	Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

On Thu Aug 31, 2023 at 5:47 PM CEST, Alex Bennée wrote:
>
> Albert Esteve <aesteve@redhat.com> writes:
>
> > Sorry to bring up this post, it's been a while since you posted.
> > But I have been testing the patch the last couple of days.
> >
> > On Mon, Jul 10, 2023 at 9:58 PM Michael S. Tsirkin <mst@redhat.com> wrote:
> >
> >  On Mon, Jul 10, 2023 at 04:35:12PM +0100, Alex Bennée wrote:
> >  > To use the generic device the user will need to provide the config
> >  > region size via the command line. We also add a notifier so the guest
> >  > can be pinged if the remote daemon updates the config.
> >  > 
> >  > With these changes:
> >  > 
> >  >   -device vhost-user-device-pci,virtio-id=41,num_vqs=2,config_size=8
> >  > 
> >  > is equivalent to:
> >  > 
> >  >   -device vhost-user-gpio-pci
> >  > 
> >  > Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
> >
> >  This one I think it's best to defer until we get a better
> >  handle on how we want the configuration to look.
> >
> >  > ---
> >  >  include/hw/virtio/vhost-user-device.h |  1 +
> >  >  hw/virtio/vhost-user-device.c         | 58 ++++++++++++++++++++++++++-
> >  >  2 files changed, 58 insertions(+), 1 deletion(-)
> >  > 
> >  > diff --git a/include/hw/virtio/vhost-user-device.h b/include/hw/virtio/vhost-user-device.h
> >  > index 9105011e25..3ddf88a146 100644
> >  > --- a/include/hw/virtio/vhost-user-device.h
> >  > +++ b/include/hw/virtio/vhost-user-device.h
> >  > @@ -22,6 +22,7 @@ struct VHostUserBase {
> >  >      CharBackend chardev;
> >  >      uint16_t virtio_id;
> >  >      uint32_t num_vqs;
> >  > +    uint32_t config_size;
> >  >      /* State tracking */
> >  >      VhostUserState vhost_user;
> >  >      struct vhost_virtqueue *vhost_vq;
> >  > diff --git a/hw/virtio/vhost-user-device.c b/hw/virtio/vhost-user-device.c
> >  > index b0239fa033..2b028cae08 100644
> >  > --- a/hw/virtio/vhost-user-device.c
> >  > +++ b/hw/virtio/vhost-user-device.c
> >  > @@ -117,6 +117,42 @@ static uint64_t vub_get_features(VirtIODevice *vdev,
> >  >      return vub->vhost_dev.features & ~(1ULL << VHOST_USER_F_PROTOCOL_FEATURES);
> >  >  }
> >  >  
> >  > +/*
> >  > + * To handle VirtIO config we need to know the size of the config
> >  > + * space. We don't cache the config but re-fetch it from the guest
> >  > + * every time in case something has changed.
> >  > + */
> >  > +static void vub_get_config(VirtIODevice *vdev, uint8_t *config)
> >  > +{
> >  > +    VHostUserBase *vub = VHOST_USER_BASE(vdev);
> >  > +    Error *local_err = NULL;
> >  > +
> >  > +    /*
> >  > +     * There will have been a warning during vhost_dev_init, but lets
> >  > +     * assert here as nothing will go right now.
> >  > +     */
> >  > +    g_assert(vub->config_size && vub->vhost_user.supports_config == true);
> >  > +
> >  > +    if (vhost_dev_get_config(&vub->vhost_dev, config,
> >  > +                             vub->config_size, &local_err)) {
> >  > +        error_report_err(local_err);
> >  > +    }
> >  > +}
> >  > +
> >  > +/*
> >  > + * When the daemon signals an update to the config we just need to
> >  > + * signal the guest as we re-read the config on demand above.
> >  > + */
> >  > +static int vub_config_notifier(struct vhost_dev *dev)
> >  > +{
> >  > +    virtio_notify_config(dev->vdev);
> >  > +    return 0;
> >  > +}
> >  > +
> >  > +const VhostDevConfigOps vub_config_ops = {
> >  > +    .vhost_dev_config_notifier = vub_config_notifier,
> >  > +};
> >  > +
> >  >  static void vub_handle_output(VirtIODevice *vdev, VirtQueue *vq)
> >  >  {
> >  >      /*
> >  > @@ -141,12 +177,21 @@ static int vub_connect(DeviceState *dev)
> >  >  {
> >  >      VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> >  >      VHostUserBase *vub = VHOST_USER_BASE(vdev);
> >  > +    struct vhost_dev *vhost_dev = &vub->vhost_dev;
> >  >  
> >  >      if (vub->connected) {
> >  >          return 0;
> >  >      }
> >  >      vub->connected = true;
> >  >  
> >  > +    /*
> >  > +     * If we support VHOST_USER_GET_CONFIG we must enable the notifier
> >  > +     * so we can ping the guest when it updates.
> >  > +     */
> >  > +    if (vub->vhost_user.supports_config) {
> >  > +        vhost_dev_set_config_notifier(vhost_dev, &vub_config_ops);
> >  > +    }
> >  > +
> >  >      /* restore vhost state */
> >  >      if (virtio_device_started(vdev, vdev->status)) {
> >  >          vub_start(vdev);
> >  > @@ -214,11 +259,20 @@ static void vub_device_realize(DeviceState *dev, Error **errp)
> >  >          vub->num_vqs = 1; /* reasonable default? */
> >  >      }
> >  >  
> >  > +    /*
> >  > +     * We can't handle config requests unless we know the size of the
> >  > +     * config region, specialisations of the vhost-user-device will be
> >  > +     * able to set this.
> >  > +     */
> >  > +    if (vub->config_size) {
> >  > +        vub->vhost_user.supports_config = true;
> >  > +    }
> >
> > Shouldn't the `supports_config = true' be set before we call vhost_dev_init() a few lines above?
> > Otherwise, we end up checking the `supports_config` attribute from within `vhost_user_backend_init()` (in vhost_user
> > source file)
> > before the VhostUserState is set, causing this warning to pop if the backend supports the CONFIG feature:
> > ```
> > qemu-system-x86_64: warning: vhost-user backend supports VHOST_USER_PROTOCOL_F_CONFIG but QEMU does
> > not.
> > ```
>
> I allude to that in the comments for vub_get_config() further up.
> However the more I look at this the more confused I am about the
> original intention of the flag I added (*blush*). I think we need to
> handle the following cases:
>
>  - the virtio device has no config space
>  - the virtio device has config space, emulated inside qemu
>  - the virtio vhost device has config space, emulated inside qemu
>  - the virtio vhost device has config space, handled by vhost
>
> for the final case the qemu internals need to be able to handle the
> signalling of updates to the config by the vhost device by way of the
> notifier.
>
> In the case of a "standalone" vhost-user daemon we won't even know if
> there is a config space until we have connected to it and queried its
> size via protocol messages.
>
> Maybe we need two fields?
>
>   - supports_remote_config (device is capable of handling remote config)
>   - config_location one of { NONE, LOCAL, REMOTE }

Hm... Shouldn't the F_CONFIG flag already indicate
`supports_remote_config` (you mean "backend-handled" config, right?) and
the negotiation of the flag would clarify the location?

Of course, there would be a disambiguity between case 3 and 4. But
wouldn't that be decidable by the configured QEMU device? The new
standalone device could default to just forwarding the backend config
while the existing devices could continue providing their proxies where
required?

- Erik

>   
> >  
> >  > +
> >  >      if (!vhost_user_init(&vub->vhost_user, &vub->chardev, errp)) {
> >  >          return;
> >  >      }
> >  >  
> >  > -    virtio_init(vdev, vub->virtio_id, 0);
> >  > +    virtio_init(vdev, vub->virtio_id, vub->config_size);
> >  >  
> >  >      /*
> >  >       * Disable guest notifiers, by default all notifications will be via the
> >  > @@ -268,6 +322,7 @@ static void vub_class_init(ObjectClass *klass, void *data)
> >  >      vdc->realize = vub_device_realize;
> >  >      vdc->unrealize = vub_device_unrealize;
> >  >      vdc->get_features = vub_get_features;
> >  > +    vdc->get_config = vub_get_config;
> >  >      vdc->set_status = vub_set_status;
> >  >  }
> >  >  
> >  > @@ -295,6 +350,7 @@ static Property vud_properties[] = {
> >  >      DEFINE_PROP_CHR("chardev", VHostUserBase, chardev),
> >  >      DEFINE_PROP_UINT16("virtio-id", VHostUserBase, virtio_id, 0),
> >  >      DEFINE_PROP_UINT32("num_vqs", VHostUserBase, num_vqs, 1),
> >  > +    DEFINE_PROP_UINT32("config_size", VHostUserBase, config_size, 0),
> >  >      DEFINE_PROP_END_OF_LIST(),
> >  >  };
> >  >  
> >  > -- 
> >  > 2.39.2


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v3 10/20] hw/virtio: add config support to vhost-user-device
  2023-08-31 15:47         ` [Virtio-fs] " Alex Bennée
@ 2023-09-01  8:34           ` Albert Esteve
  -1 siblings, 0 replies; 66+ messages in thread
From: Albert Esteve @ 2023-09-01  8:34 UTC (permalink / raw)
  To: Alex Bennée
  Cc: Michael S. Tsirkin, qemu-devel, Marc-André Lureau,
	Jason Wang, Viresh Kumar, Raphael Norwitz, Paolo Bonzini,
	Daniel P. Berrangé,
	qemu-block, Eric Blake, Mark Cave-Ayland, Kevin Wolf,
	Markus Armbruster, Gerd Hoffmann, Mathieu Poirier, Hanna Reitz,
	Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

[-- Attachment #1: Type: text/plain, Size: 8559 bytes --]

On Thu, Aug 31, 2023 at 6:03 PM Alex Bennée <alex.bennee@linaro.org> wrote:

>
> Albert Esteve <aesteve@redhat.com> writes:
>
> > Sorry to bring up this post, it's been a while since you posted.
> > But I have been testing the patch the last couple of days.
> >
> > On Mon, Jul 10, 2023 at 9:58 PM Michael S. Tsirkin <mst@redhat.com>
> wrote:
> >
> >  On Mon, Jul 10, 2023 at 04:35:12PM +0100, Alex Bennée wrote:
> >  > To use the generic device the user will need to provide the config
> >  > region size via the command line. We also add a notifier so the guest
> >  > can be pinged if the remote daemon updates the config.
> >  >
> >  > With these changes:
> >  >
> >  >   -device vhost-user-device-pci,virtio-id=41,num_vqs=2,config_size=8
> >  >
> >  > is equivalent to:
> >  >
> >  >   -device vhost-user-gpio-pci
> >  >
> >  > Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
> >
> >  This one I think it's best to defer until we get a better
> >  handle on how we want the configuration to look.
> >
> >  > ---
> >  >  include/hw/virtio/vhost-user-device.h |  1 +
> >  >  hw/virtio/vhost-user-device.c         | 58
> ++++++++++++++++++++++++++-
> >  >  2 files changed, 58 insertions(+), 1 deletion(-)
> >  >
> >  > diff --git a/include/hw/virtio/vhost-user-device.h
> b/include/hw/virtio/vhost-user-device.h
> >  > index 9105011e25..3ddf88a146 100644
> >  > --- a/include/hw/virtio/vhost-user-device.h
> >  > +++ b/include/hw/virtio/vhost-user-device.h
> >  > @@ -22,6 +22,7 @@ struct VHostUserBase {
> >  >      CharBackend chardev;
> >  >      uint16_t virtio_id;
> >  >      uint32_t num_vqs;
> >  > +    uint32_t config_size;
> >  >      /* State tracking */
> >  >      VhostUserState vhost_user;
> >  >      struct vhost_virtqueue *vhost_vq;
> >  > diff --git a/hw/virtio/vhost-user-device.c
> b/hw/virtio/vhost-user-device.c
> >  > index b0239fa033..2b028cae08 100644
> >  > --- a/hw/virtio/vhost-user-device.c
> >  > +++ b/hw/virtio/vhost-user-device.c
> >  > @@ -117,6 +117,42 @@ static uint64_t vub_get_features(VirtIODevice
> *vdev,
> >  >      return vub->vhost_dev.features & ~(1ULL <<
> VHOST_USER_F_PROTOCOL_FEATURES);
> >  >  }
> >  >
> >  > +/*
> >  > + * To handle VirtIO config we need to know the size of the config
> >  > + * space. We don't cache the config but re-fetch it from the guest
> >  > + * every time in case something has changed.
> >  > + */
> >  > +static void vub_get_config(VirtIODevice *vdev, uint8_t *config)
> >  > +{
> >  > +    VHostUserBase *vub = VHOST_USER_BASE(vdev);
> >  > +    Error *local_err = NULL;
> >  > +
> >  > +    /*
> >  > +     * There will have been a warning during vhost_dev_init, but lets
> >  > +     * assert here as nothing will go right now.
> >  > +     */
> >  > +    g_assert(vub->config_size && vub->vhost_user.supports_config ==
> true);
> >  > +
> >  > +    if (vhost_dev_get_config(&vub->vhost_dev, config,
> >  > +                             vub->config_size, &local_err)) {
> >  > +        error_report_err(local_err);
> >  > +    }
> >  > +}
> >  > +
> >  > +/*
> >  > + * When the daemon signals an update to the config we just need to
> >  > + * signal the guest as we re-read the config on demand above.
> >  > + */
> >  > +static int vub_config_notifier(struct vhost_dev *dev)
> >  > +{
> >  > +    virtio_notify_config(dev->vdev);
> >  > +    return 0;
> >  > +}
> >  > +
> >  > +const VhostDevConfigOps vub_config_ops = {
> >  > +    .vhost_dev_config_notifier = vub_config_notifier,
> >  > +};
> >  > +
> >  >  static void vub_handle_output(VirtIODevice *vdev, VirtQueue *vq)
> >  >  {
> >  >      /*
> >  > @@ -141,12 +177,21 @@ static int vub_connect(DeviceState *dev)
> >  >  {
> >  >      VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> >  >      VHostUserBase *vub = VHOST_USER_BASE(vdev);
> >  > +    struct vhost_dev *vhost_dev = &vub->vhost_dev;
> >  >
> >  >      if (vub->connected) {
> >  >          return 0;
> >  >      }
> >  >      vub->connected = true;
> >  >
> >  > +    /*
> >  > +     * If we support VHOST_USER_GET_CONFIG we must enable the
> notifier
> >  > +     * so we can ping the guest when it updates.
> >  > +     */
> >  > +    if (vub->vhost_user.supports_config) {
> >  > +        vhost_dev_set_config_notifier(vhost_dev, &vub_config_ops);
> >  > +    }
> >  > +
> >  >      /* restore vhost state */
> >  >      if (virtio_device_started(vdev, vdev->status)) {
> >  >          vub_start(vdev);
> >  > @@ -214,11 +259,20 @@ static void vub_device_realize(DeviceState
> *dev, Error **errp)
> >  >          vub->num_vqs = 1; /* reasonable default? */
> >  >      }
> >  >
> >  > +    /*
> >  > +     * We can't handle config requests unless we know the size of the
> >  > +     * config region, specialisations of the vhost-user-device will
> be
> >  > +     * able to set this.
> >  > +     */
> >  > +    if (vub->config_size) {
> >  > +        vub->vhost_user.supports_config = true;
> >  > +    }
> >
> > Shouldn't the `supports_config = true' be set before we call
> vhost_dev_init() a few lines above?
> > Otherwise, we end up checking the `supports_config` attribute from
> within `vhost_user_backend_init()` (in vhost_user
> > source file)
> > before the VhostUserState is set, causing this warning to pop if the
> backend supports the CONFIG feature:
> > ```
> > qemu-system-x86_64: warning: vhost-user backend supports
> VHOST_USER_PROTOCOL_F_CONFIG but QEMU does
> > not.
> > ```
>
> I allude to that in the comments for vub_get_config() further up.
>

Ah, true. Sorry I missed it. Still not sure that allowing the warning is a
good idea.
Either the warning is not relevant anymore or the logic is not correct.
In my case the connection was breaking because the driver was receiving
a wrong configuration, even though the backend was sending correct data.
Qemu disables the F_CONFIG bit from the backend features when the
warning is printed, and I assume that was causing the issue that the
config fields were all 0'd when the driver asked for it.


> However the more I look at this the more confused I am about the
> original intention of the flag I added (*blush*). I think we need to
> handle the following cases:
>
>  - the virtio device has no config space
>  - the virtio device has config space, emulated inside qemu
>  - the virtio vhost device has config space, emulated inside qemu
>  - the virtio vhost device has config space, handled by vhost
>
> for the final case the qemu internals need to be able to handle the
> signalling of updates to the config by the vhost device by way of the
> notifier.
>
> In the case of a "standalone" vhost-user daemon we won't even know if
> there is a config space until we have connected to it and queried its
> size via protocol messages.
>
> Maybe we need two fields?
>
>   - supports_remote_config (device is capable of handling remote config)
>   - config_location one of { NONE, LOCAL, REMOTE }
>
>
Mmh, when setting the config location, if remote config is not supported
and the location
is remote, we could force the flag to NONE, and then we only need the
`config_location`.
It already tells us both if supported, and where to find it.

>
> >  > +
> >  >      if (!vhost_user_init(&vub->vhost_user, &vub->chardev, errp)) {
> >  >          return;
> >  >      }
> >  >
> >  > -    virtio_init(vdev, vub->virtio_id, 0);
> >  > +    virtio_init(vdev, vub->virtio_id, vub->config_size);
> >  >
> >  >      /*
> >  >       * Disable guest notifiers, by default all notifications will be
> via the
> >  > @@ -268,6 +322,7 @@ static void vub_class_init(ObjectClass *klass,
> void *data)
> >  >      vdc->realize = vub_device_realize;
> >  >      vdc->unrealize = vub_device_unrealize;
> >  >      vdc->get_features = vub_get_features;
> >  > +    vdc->get_config = vub_get_config;
> >  >      vdc->set_status = vub_set_status;
> >  >  }
> >  >
> >  > @@ -295,6 +350,7 @@ static Property vud_properties[] = {
> >  >      DEFINE_PROP_CHR("chardev", VHostUserBase, chardev),
> >  >      DEFINE_PROP_UINT16("virtio-id", VHostUserBase, virtio_id, 0),
> >  >      DEFINE_PROP_UINT32("num_vqs", VHostUserBase, num_vqs, 1),
> >  > +    DEFINE_PROP_UINT32("config_size", VHostUserBase, config_size, 0),
> >  >      DEFINE_PROP_END_OF_LIST(),
> >  >  };
> >  >
> >  > --
> >  > 2.39.2
>
>
> --
> Alex Bennée
> Virtualisation Tech Lead @ Linaro
>
>

[-- Attachment #2: Type: text/html, Size: 11373 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Virtio-fs] [PATCH v3 10/20] hw/virtio: add config support to vhost-user-device
@ 2023-09-01  8:34           ` Albert Esteve
  0 siblings, 0 replies; 66+ messages in thread
From: Albert Esteve @ 2023-09-01  8:34 UTC (permalink / raw)
  To: Alex Bennée
  Cc: Michael S. Tsirkin, qemu-devel, Marc-André Lureau,
	Jason Wang, Viresh Kumar, Raphael Norwitz, Paolo Bonzini,
	Daniel P. Berrangé,
	qemu-block, Eric Blake, Mark Cave-Ayland, Kevin Wolf,
	Markus Armbruster, Gerd Hoffmann, Mathieu Poirier, Hanna Reitz,
	Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

[-- Attachment #1: Type: text/plain, Size: 8559 bytes --]

On Thu, Aug 31, 2023 at 6:03 PM Alex Bennée <alex.bennee@linaro.org> wrote:

>
> Albert Esteve <aesteve@redhat.com> writes:
>
> > Sorry to bring up this post, it's been a while since you posted.
> > But I have been testing the patch the last couple of days.
> >
> > On Mon, Jul 10, 2023 at 9:58 PM Michael S. Tsirkin <mst@redhat.com>
> wrote:
> >
> >  On Mon, Jul 10, 2023 at 04:35:12PM +0100, Alex Bennée wrote:
> >  > To use the generic device the user will need to provide the config
> >  > region size via the command line. We also add a notifier so the guest
> >  > can be pinged if the remote daemon updates the config.
> >  >
> >  > With these changes:
> >  >
> >  >   -device vhost-user-device-pci,virtio-id=41,num_vqs=2,config_size=8
> >  >
> >  > is equivalent to:
> >  >
> >  >   -device vhost-user-gpio-pci
> >  >
> >  > Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
> >
> >  This one I think it's best to defer until we get a better
> >  handle on how we want the configuration to look.
> >
> >  > ---
> >  >  include/hw/virtio/vhost-user-device.h |  1 +
> >  >  hw/virtio/vhost-user-device.c         | 58
> ++++++++++++++++++++++++++-
> >  >  2 files changed, 58 insertions(+), 1 deletion(-)
> >  >
> >  > diff --git a/include/hw/virtio/vhost-user-device.h
> b/include/hw/virtio/vhost-user-device.h
> >  > index 9105011e25..3ddf88a146 100644
> >  > --- a/include/hw/virtio/vhost-user-device.h
> >  > +++ b/include/hw/virtio/vhost-user-device.h
> >  > @@ -22,6 +22,7 @@ struct VHostUserBase {
> >  >      CharBackend chardev;
> >  >      uint16_t virtio_id;
> >  >      uint32_t num_vqs;
> >  > +    uint32_t config_size;
> >  >      /* State tracking */
> >  >      VhostUserState vhost_user;
> >  >      struct vhost_virtqueue *vhost_vq;
> >  > diff --git a/hw/virtio/vhost-user-device.c
> b/hw/virtio/vhost-user-device.c
> >  > index b0239fa033..2b028cae08 100644
> >  > --- a/hw/virtio/vhost-user-device.c
> >  > +++ b/hw/virtio/vhost-user-device.c
> >  > @@ -117,6 +117,42 @@ static uint64_t vub_get_features(VirtIODevice
> *vdev,
> >  >      return vub->vhost_dev.features & ~(1ULL <<
> VHOST_USER_F_PROTOCOL_FEATURES);
> >  >  }
> >  >
> >  > +/*
> >  > + * To handle VirtIO config we need to know the size of the config
> >  > + * space. We don't cache the config but re-fetch it from the guest
> >  > + * every time in case something has changed.
> >  > + */
> >  > +static void vub_get_config(VirtIODevice *vdev, uint8_t *config)
> >  > +{
> >  > +    VHostUserBase *vub = VHOST_USER_BASE(vdev);
> >  > +    Error *local_err = NULL;
> >  > +
> >  > +    /*
> >  > +     * There will have been a warning during vhost_dev_init, but lets
> >  > +     * assert here as nothing will go right now.
> >  > +     */
> >  > +    g_assert(vub->config_size && vub->vhost_user.supports_config ==
> true);
> >  > +
> >  > +    if (vhost_dev_get_config(&vub->vhost_dev, config,
> >  > +                             vub->config_size, &local_err)) {
> >  > +        error_report_err(local_err);
> >  > +    }
> >  > +}
> >  > +
> >  > +/*
> >  > + * When the daemon signals an update to the config we just need to
> >  > + * signal the guest as we re-read the config on demand above.
> >  > + */
> >  > +static int vub_config_notifier(struct vhost_dev *dev)
> >  > +{
> >  > +    virtio_notify_config(dev->vdev);
> >  > +    return 0;
> >  > +}
> >  > +
> >  > +const VhostDevConfigOps vub_config_ops = {
> >  > +    .vhost_dev_config_notifier = vub_config_notifier,
> >  > +};
> >  > +
> >  >  static void vub_handle_output(VirtIODevice *vdev, VirtQueue *vq)
> >  >  {
> >  >      /*
> >  > @@ -141,12 +177,21 @@ static int vub_connect(DeviceState *dev)
> >  >  {
> >  >      VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> >  >      VHostUserBase *vub = VHOST_USER_BASE(vdev);
> >  > +    struct vhost_dev *vhost_dev = &vub->vhost_dev;
> >  >
> >  >      if (vub->connected) {
> >  >          return 0;
> >  >      }
> >  >      vub->connected = true;
> >  >
> >  > +    /*
> >  > +     * If we support VHOST_USER_GET_CONFIG we must enable the
> notifier
> >  > +     * so we can ping the guest when it updates.
> >  > +     */
> >  > +    if (vub->vhost_user.supports_config) {
> >  > +        vhost_dev_set_config_notifier(vhost_dev, &vub_config_ops);
> >  > +    }
> >  > +
> >  >      /* restore vhost state */
> >  >      if (virtio_device_started(vdev, vdev->status)) {
> >  >          vub_start(vdev);
> >  > @@ -214,11 +259,20 @@ static void vub_device_realize(DeviceState
> *dev, Error **errp)
> >  >          vub->num_vqs = 1; /* reasonable default? */
> >  >      }
> >  >
> >  > +    /*
> >  > +     * We can't handle config requests unless we know the size of the
> >  > +     * config region, specialisations of the vhost-user-device will
> be
> >  > +     * able to set this.
> >  > +     */
> >  > +    if (vub->config_size) {
> >  > +        vub->vhost_user.supports_config = true;
> >  > +    }
> >
> > Shouldn't the `supports_config = true' be set before we call
> vhost_dev_init() a few lines above?
> > Otherwise, we end up checking the `supports_config` attribute from
> within `vhost_user_backend_init()` (in vhost_user
> > source file)
> > before the VhostUserState is set, causing this warning to pop if the
> backend supports the CONFIG feature:
> > ```
> > qemu-system-x86_64: warning: vhost-user backend supports
> VHOST_USER_PROTOCOL_F_CONFIG but QEMU does
> > not.
> > ```
>
> I allude to that in the comments for vub_get_config() further up.
>

Ah, true. Sorry I missed it. Still not sure that allowing the warning is a
good idea.
Either the warning is not relevant anymore or the logic is not correct.
In my case the connection was breaking because the driver was receiving
a wrong configuration, even though the backend was sending correct data.
Qemu disables the F_CONFIG bit from the backend features when the
warning is printed, and I assume that was causing the issue that the
config fields were all 0'd when the driver asked for it.


> However the more I look at this the more confused I am about the
> original intention of the flag I added (*blush*). I think we need to
> handle the following cases:
>
>  - the virtio device has no config space
>  - the virtio device has config space, emulated inside qemu
>  - the virtio vhost device has config space, emulated inside qemu
>  - the virtio vhost device has config space, handled by vhost
>
> for the final case the qemu internals need to be able to handle the
> signalling of updates to the config by the vhost device by way of the
> notifier.
>
> In the case of a "standalone" vhost-user daemon we won't even know if
> there is a config space until we have connected to it and queried its
> size via protocol messages.
>
> Maybe we need two fields?
>
>   - supports_remote_config (device is capable of handling remote config)
>   - config_location one of { NONE, LOCAL, REMOTE }
>
>
Mmh, when setting the config location, if remote config is not supported
and the location
is remote, we could force the flag to NONE, and then we only need the
`config_location`.
It already tells us both if supported, and where to find it.

>
> >  > +
> >  >      if (!vhost_user_init(&vub->vhost_user, &vub->chardev, errp)) {
> >  >          return;
> >  >      }
> >  >
> >  > -    virtio_init(vdev, vub->virtio_id, 0);
> >  > +    virtio_init(vdev, vub->virtio_id, vub->config_size);
> >  >
> >  >      /*
> >  >       * Disable guest notifiers, by default all notifications will be
> via the
> >  > @@ -268,6 +322,7 @@ static void vub_class_init(ObjectClass *klass,
> void *data)
> >  >      vdc->realize = vub_device_realize;
> >  >      vdc->unrealize = vub_device_unrealize;
> >  >      vdc->get_features = vub_get_features;
> >  > +    vdc->get_config = vub_get_config;
> >  >      vdc->set_status = vub_set_status;
> >  >  }
> >  >
> >  > @@ -295,6 +350,7 @@ static Property vud_properties[] = {
> >  >      DEFINE_PROP_CHR("chardev", VHostUserBase, chardev),
> >  >      DEFINE_PROP_UINT16("virtio-id", VHostUserBase, virtio_id, 0),
> >  >      DEFINE_PROP_UINT32("num_vqs", VHostUserBase, num_vqs, 1),
> >  > +    DEFINE_PROP_UINT32("config_size", VHostUserBase, config_size, 0),
> >  >      DEFINE_PROP_END_OF_LIST(),
> >  >  };
> >  >
> >  > --
> >  > 2.39.2
>
>
> --
> Alex Bennée
> Virtualisation Tech Lead @ Linaro
>
>

[-- Attachment #2: Type: text/html, Size: 11373 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [RFC PATCH v3 20/20] hw/virtio: allow vhost-user-device to be driven by backend
  2023-07-10 15:35   ` [Virtio-fs] " Alex Bennée
@ 2023-09-01 10:00     ` Albert Esteve
  -1 siblings, 0 replies; 66+ messages in thread
From: Albert Esteve @ 2023-09-01 10:00 UTC (permalink / raw)
  To: Alex Bennée
  Cc: qemu-devel, Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

[-- Attachment #1: Type: text/plain, Size: 4255 bytes --]

On Mon, Jul 10, 2023 at 6:44 PM Alex Bennée <alex.bennee@linaro.org> wrote:

> Instead of requiring all the information up front allow the
> vhost_dev_init to complete and then see what information we have from
> the backend.
>
> This does change the order around somewhat.
>
> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
> ---
>  hw/virtio/vhost-user-device.c | 45 +++++++++++++++++++++++++----------
>  1 file changed, 32 insertions(+), 13 deletions(-)
>
> diff --git a/hw/virtio/vhost-user-device.c b/hw/virtio/vhost-user-device.c
> index 0109d4829d..b30b6265fb 100644
> --- a/hw/virtio/vhost-user-device.c
> +++ b/hw/virtio/vhost-user-device.c
> @@ -243,7 +243,6 @@ static void vub_device_realize(DeviceState *dev, Error
> **errp)
>  {
>      VirtIODevice *vdev = VIRTIO_DEVICE(dev);
>      VHostUserBase *vub = VHOST_USER_BASE(dev);
> -    int ret;
>
>      if (!vub->chardev.chr) {
>          error_setg(errp, "vhost-user-device: missing chardev");
> @@ -254,13 +253,43 @@ static void vub_device_realize(DeviceState *dev,
> Error **errp)
>          return;
>      }
>
> +    if (vhost_dev_init(&vub->vhost_dev, &vub->vhost_user,
> +                       VHOST_BACKEND_TYPE_USER, 0, errp)!=0) {
> +        error_setg(errp, "vhost-user-device: unable to start connection");
> +        return;
> +    }
> +
> +    if (vub->vhost_dev.specs.device_id) {
> +        if (vub->virtio_id && vub->virtio_id !=
> vub->vhost_dev.specs.device_id) {
> +            error_setg(errp, "vhost-user-device: backend id %d doesn't
> match cli %d",
> +                       vub->vhost_dev.specs.device_id, vub->virtio_id);
> +            return;
> +        }
> +        vub->virtio_id = vub->vhost_dev.specs.device_id;
> +    }
> +
>      if (!vub->virtio_id) {
> -        error_setg(errp, "vhost-user-device: need to define device id");
> +        error_setg(errp, "vhost-user-device: need to define or be told
> device id");
>          return;
>      }
>
> +    if (vub->vhost_dev.specs.min_vqs) {
> +        if (vub->num_vqs) {
> +            if (vub->num_vqs < vub->vhost_dev.specs.min_vqs ||
> +                vub->num_vqs > vub->vhost_dev.specs.max_vqs) {
> +                error_setg(errp,
> +                           "vhost-user-device: selected nvqs (%d) out of
> bounds (%d->%d)",
> +                           vub->num_vqs,
> +                           vub->vhost_dev.specs.min_vqs,
> vub->vhost_dev.specs.max_vqs);
> +                return;
> +            }
> +        } else {
> +            vub->num_vqs = vub->vhost_dev.specs.min_vqs;
> +        }
> +    }
> +
>      if (!vub->num_vqs) {
> -        vub->num_vqs = 1; /* reasonable default? */
> +        error_setg(errp, "vhost-user-device: need to define number of
> vqs");
>      }
>
>      /*
> @@ -287,16 +316,6 @@ static void vub_device_realize(DeviceState *dev,
> Error **errp)
>                          virtio_add_queue(vdev, 4, vub_handle_output));
>      }
>
> -    vub->vhost_dev.nvqs = vub->num_vqs;
>

Who sets `vub->vhost_dev.nvqs` after removing this line?
Why having `vub->num_vqs` in the first place? In vub_start for example we
still
use `vub->vhost_dev.nvqs`, and we pass `vhost_dev` to other functions that
use its `nvqs`, so `num_vqs` is redundant and requires a logic to
copy/initialise `vhost_dev.nvqs`.

Maybe it would be better to initialse `nvqs` through a function, in the
device file, instead of doing:
`vub->num_vqs = 2;`
We could have:
`vub_set_nvqs(vub, 2);`
Or something along those lines. And the function will have all the internal
logic in this commit, i.e.,
checking the boundaries, setting the `vhost_dev.nvqs` value, printing the
error, etc.
So we can save the extra variable, and the logic to copy the value to the
device.


> -
> -    /* connect to backend */
> -    ret = vhost_dev_init(&vub->vhost_dev, &vub->vhost_user,
> -                         VHOST_BACKEND_TYPE_USER, 0, errp);
> -
> -    if (ret < 0) {
> -        do_vhost_user_cleanup(vdev, vub);
> -    }
> -
>      qemu_chr_fe_set_handlers(&vub->chardev, NULL, NULL, vub_event, NULL,
>                               dev, NULL, true);
>  }
> --
> 2.39.2
>
>
>

[-- Attachment #2: Type: text/html, Size: 5643 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Virtio-fs] [RFC PATCH v3 20/20] hw/virtio: allow vhost-user-device to be driven by backend
@ 2023-09-01 10:00     ` Albert Esteve
  0 siblings, 0 replies; 66+ messages in thread
From: Albert Esteve @ 2023-09-01 10:00 UTC (permalink / raw)
  To: Alex Bennée
  Cc: qemu-devel, Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

[-- Attachment #1: Type: text/plain, Size: 4255 bytes --]

On Mon, Jul 10, 2023 at 6:44 PM Alex Bennée <alex.bennee@linaro.org> wrote:

> Instead of requiring all the information up front allow the
> vhost_dev_init to complete and then see what information we have from
> the backend.
>
> This does change the order around somewhat.
>
> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
> ---
>  hw/virtio/vhost-user-device.c | 45 +++++++++++++++++++++++++----------
>  1 file changed, 32 insertions(+), 13 deletions(-)
>
> diff --git a/hw/virtio/vhost-user-device.c b/hw/virtio/vhost-user-device.c
> index 0109d4829d..b30b6265fb 100644
> --- a/hw/virtio/vhost-user-device.c
> +++ b/hw/virtio/vhost-user-device.c
> @@ -243,7 +243,6 @@ static void vub_device_realize(DeviceState *dev, Error
> **errp)
>  {
>      VirtIODevice *vdev = VIRTIO_DEVICE(dev);
>      VHostUserBase *vub = VHOST_USER_BASE(dev);
> -    int ret;
>
>      if (!vub->chardev.chr) {
>          error_setg(errp, "vhost-user-device: missing chardev");
> @@ -254,13 +253,43 @@ static void vub_device_realize(DeviceState *dev,
> Error **errp)
>          return;
>      }
>
> +    if (vhost_dev_init(&vub->vhost_dev, &vub->vhost_user,
> +                       VHOST_BACKEND_TYPE_USER, 0, errp)!=0) {
> +        error_setg(errp, "vhost-user-device: unable to start connection");
> +        return;
> +    }
> +
> +    if (vub->vhost_dev.specs.device_id) {
> +        if (vub->virtio_id && vub->virtio_id !=
> vub->vhost_dev.specs.device_id) {
> +            error_setg(errp, "vhost-user-device: backend id %d doesn't
> match cli %d",
> +                       vub->vhost_dev.specs.device_id, vub->virtio_id);
> +            return;
> +        }
> +        vub->virtio_id = vub->vhost_dev.specs.device_id;
> +    }
> +
>      if (!vub->virtio_id) {
> -        error_setg(errp, "vhost-user-device: need to define device id");
> +        error_setg(errp, "vhost-user-device: need to define or be told
> device id");
>          return;
>      }
>
> +    if (vub->vhost_dev.specs.min_vqs) {
> +        if (vub->num_vqs) {
> +            if (vub->num_vqs < vub->vhost_dev.specs.min_vqs ||
> +                vub->num_vqs > vub->vhost_dev.specs.max_vqs) {
> +                error_setg(errp,
> +                           "vhost-user-device: selected nvqs (%d) out of
> bounds (%d->%d)",
> +                           vub->num_vqs,
> +                           vub->vhost_dev.specs.min_vqs,
> vub->vhost_dev.specs.max_vqs);
> +                return;
> +            }
> +        } else {
> +            vub->num_vqs = vub->vhost_dev.specs.min_vqs;
> +        }
> +    }
> +
>      if (!vub->num_vqs) {
> -        vub->num_vqs = 1; /* reasonable default? */
> +        error_setg(errp, "vhost-user-device: need to define number of
> vqs");
>      }
>
>      /*
> @@ -287,16 +316,6 @@ static void vub_device_realize(DeviceState *dev,
> Error **errp)
>                          virtio_add_queue(vdev, 4, vub_handle_output));
>      }
>
> -    vub->vhost_dev.nvqs = vub->num_vqs;
>

Who sets `vub->vhost_dev.nvqs` after removing this line?
Why having `vub->num_vqs` in the first place? In vub_start for example we
still
use `vub->vhost_dev.nvqs`, and we pass `vhost_dev` to other functions that
use its `nvqs`, so `num_vqs` is redundant and requires a logic to
copy/initialise `vhost_dev.nvqs`.

Maybe it would be better to initialse `nvqs` through a function, in the
device file, instead of doing:
`vub->num_vqs = 2;`
We could have:
`vub_set_nvqs(vub, 2);`
Or something along those lines. And the function will have all the internal
logic in this commit, i.e.,
checking the boundaries, setting the `vhost_dev.nvqs` value, printing the
error, etc.
So we can save the extra variable, and the logic to copy the value to the
device.


> -
> -    /* connect to backend */
> -    ret = vhost_dev_init(&vub->vhost_dev, &vub->vhost_user,
> -                         VHOST_BACKEND_TYPE_USER, 0, errp);
> -
> -    if (ret < 0) {
> -        do_vhost_user_cleanup(vdev, vub);
> -    }
> -
>      qemu_chr_fe_set_handlers(&vub->chardev, NULL, NULL, vub_event, NULL,
>                               dev, NULL, true);
>  }
> --
> 2.39.2
>
>
>

[-- Attachment #2: Type: text/html, Size: 5643 bytes --]

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v3 07/20] virtio: add vhost-user-base and a generic vhost-user-device
  2023-07-10 15:35   ` [Virtio-fs] " Alex Bennée
@ 2023-09-05 14:19     ` Matias Ezequiel Vara Larsen
  -1 siblings, 0 replies; 66+ messages in thread
From: Matias Ezequiel Vara Larsen @ 2023-09-05 14:19 UTC (permalink / raw)
  To: Alex Bennée
  Cc: qemu-devel, Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

On Mon, Jul 10, 2023 at 04:35:09PM +0100, Alex Bennée wrote:
> In theory we shouldn't need to repeat so much boilerplate to support
> vhost-user backends. This provides a generic vhost-user-base QOM
> object and a derived vhost-user-device for which the user needs to
> provide the few bits of information that aren't currently provided by
> the vhost-user protocol. This should provide a baseline implementation
> from which the other vhost-user stub can specialise.
> 
> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
> 
> ---
> v2
>   - split into vub and vud
> ---
>  include/hw/virtio/vhost-user-device.h |  45 ++++
>  hw/virtio/vhost-user-device.c         | 324 ++++++++++++++++++++++++++
>  hw/virtio/meson.build                 |   2 +
>  3 files changed, 371 insertions(+)
>  create mode 100644 include/hw/virtio/vhost-user-device.h
>  create mode 100644 hw/virtio/vhost-user-device.c
> 
> diff --git a/include/hw/virtio/vhost-user-device.h b/include/hw/virtio/vhost-user-device.h
> new file mode 100644
> index 0000000000..9105011e25
> --- /dev/null
> +++ b/include/hw/virtio/vhost-user-device.h
> @@ -0,0 +1,45 @@
> +/*
> + * Vhost-user generic virtio device
> + *
> + * Copyright (c) 2023 Linaro Ltd
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#ifndef QEMU_VHOST_USER_DEVICE_H
> +#define QEMU_VHOST_USER_DEVICE_H
> +
> +#include "hw/virtio/vhost.h"
> +#include "hw/virtio/vhost-user.h"
> +
> +#define TYPE_VHOST_USER_BASE "vhost-user-base"
> +
> +OBJECT_DECLARE_TYPE(VHostUserBase, VHostUserBaseClass, VHOST_USER_BASE)
> +
> +struct VHostUserBase {
> +    VirtIODevice parent;
> +    /* Properties */
> +    CharBackend chardev;
> +    uint16_t virtio_id;
> +    uint32_t num_vqs;
> +    /* State tracking */
> +    VhostUserState vhost_user;
> +    struct vhost_virtqueue *vhost_vq;
> +    struct vhost_dev vhost_dev;
> +    GPtrArray *vqs;
> +    bool connected;
> +};
> +
> +    /* needed so we can use the base realize after specialisation
> +       tweaks */
> +struct VHostUserBaseClass {
> +    /*< private >*/
> +    VirtioDeviceClass parent_class;
> +    /*< public >*/
> +    DeviceRealize parent_realize;
> +};
> +
> +/* shared for the benefit of the derived pci class */
> +#define TYPE_VHOST_USER_DEVICE "vhost-user-device"
> +
> +#endif /* QEMU_VHOST_USER_DEVICE_H */
> diff --git a/hw/virtio/vhost-user-device.c b/hw/virtio/vhost-user-device.c
> new file mode 100644
> index 0000000000..b0239fa033
> --- /dev/null
> +++ b/hw/virtio/vhost-user-device.c
> @@ -0,0 +1,324 @@
> +/*
> + * Generic vhost-user stub. This can be used to connect to any
> + * vhost-user backend. All configuration details must be handled by
> + * the vhost-user daemon itself
> + *
> + * Copyright (c) 2023 Linaro Ltd
> + * Author: Alex Bennée <alex.bennee@linaro.org>
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qapi/error.h"
> +#include "hw/qdev-properties.h"
> +#include "hw/virtio/virtio-bus.h"
> +#include "hw/virtio/vhost-user-device.h"
> +#include "qemu/error-report.h"
> +
> +static void vub_start(VirtIODevice *vdev)
> +{
> +    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
> +    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
> +    VHostUserBase *vub = VHOST_USER_BASE(vdev);
> +    int ret, i;
> +
> +    if (!k->set_guest_notifiers) {
> +        error_report("binding does not support guest notifiers");
> +        return;
> +    }
> +
> +    ret = vhost_dev_enable_notifiers(&vub->vhost_dev, vdev);
> +    if (ret < 0) {
> +        error_report("Error enabling host notifiers: %d", -ret);
> +        return;
> +    }
> +
> +    ret = k->set_guest_notifiers(qbus->parent, vub->vhost_dev.nvqs, true);
> +    if (ret < 0) {
> +        error_report("Error binding guest notifier: %d", -ret);
> +        goto err_host_notifiers;
> +    }
> +
> +    vub->vhost_dev.acked_features = vdev->guest_features;
> +
> +    ret = vhost_dev_start(&vub->vhost_dev, vdev, true);
> +    if (ret < 0) {
> +        error_report("Error starting vhost-user-device: %d", -ret);
> +        goto err_guest_notifiers;
> +    }
> +
> +    /*
> +     * guest_notifier_mask/pending not used yet, so just unmask
> +     * everything here. virtio-pci will do the right thing by
> +     * enabling/disabling irqfd.
> +     */
> +    for (i = 0; i < vub->vhost_dev.nvqs; i++) {
> +        vhost_virtqueue_mask(&vub->vhost_dev, vdev, i, false);
> +    }
> +
> +    return;
> +
> +err_guest_notifiers:
> +    k->set_guest_notifiers(qbus->parent, vub->vhost_dev.nvqs, false);
> +err_host_notifiers:
> +    vhost_dev_disable_notifiers(&vub->vhost_dev, vdev);
> +}
> +
> +static void vub_stop(VirtIODevice *vdev)
> +{
> +    VHostUserBase *vub = VHOST_USER_BASE(vdev);
> +    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
> +    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
> +    int ret;
> +
> +    if (!k->set_guest_notifiers) {
> +        return;
> +    }
> +
> +    vhost_dev_stop(&vub->vhost_dev, vdev, true);
> +
> +    ret = k->set_guest_notifiers(qbus->parent, vub->vhost_dev.nvqs, false);
> +    if (ret < 0) {
> +        error_report("vhost guest notifier cleanup failed: %d", ret);
> +        return;
> +    }
> +
> +    vhost_dev_disable_notifiers(&vub->vhost_dev, vdev);
> +}
> +
> +static void vub_set_status(VirtIODevice *vdev, uint8_t status)
> +{
> +    VHostUserBase *vub = VHOST_USER_BASE(vdev);
> +    bool should_start = virtio_device_should_start(vdev, status);
> +
> +    if (vhost_dev_is_started(&vub->vhost_dev) == should_start) {
> +        return;
> +    }
> +
> +    if (should_start) {
> +        vub_start(vdev);
> +    } else {
> +        vub_stop(vdev);
> +    }
> +}
> +
> +/*
> + * For an implementation where everything is delegated to the backend
> + * we don't do anything other than return the full feature set offered
> + * by the daemon (module the reserved feature bit).
> + */
> +static uint64_t vub_get_features(VirtIODevice *vdev,
> +                                 uint64_t requested_features, Error **errp)
> +{
> +    VHostUserBase *vub = VHOST_USER_BASE(vdev);
> +    /* This should be set when the vhost connection initialises */
> +    g_assert(vub->vhost_dev.features);
> +    return vub->vhost_dev.features & ~(1ULL << VHOST_USER_F_PROTOCOL_FEATURES);
> +}
> +
> +static void vub_handle_output(VirtIODevice *vdev, VirtQueue *vq)
> +{
> +    /*
> +     * Not normally called; it's the daemon that handles the queue;
> +     * however virtio's cleanup path can call this.
> +     */
> +}
> +
> +static void do_vhost_user_cleanup(VirtIODevice *vdev, VHostUserBase *vub)
> +{
> +    vhost_user_cleanup(&vub->vhost_user);
> +
> +    for (int i = 0; i < vub->num_vqs; i++) {
> +        VirtQueue *vq = g_ptr_array_index(vub->vqs, i);
> +        virtio_delete_queue(vq);
> +    }
> +
> +    virtio_cleanup(vdev);
> +}
> +
> +static int vub_connect(DeviceState *dev)
> +{
> +    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> +    VHostUserBase *vub = VHOST_USER_BASE(vdev);
> +
> +    if (vub->connected) {
> +        return 0;
> +    }
> +    vub->connected = true;
> +
> +    /* restore vhost state */
> +    if (virtio_device_started(vdev, vdev->status)) {
> +        vub_start(vdev);
> +    }
> +
> +    return 0;
> +}
> +
> +static void vub_disconnect(DeviceState *dev)
> +{
> +    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> +    VHostUserBase *vub = VHOST_USER_BASE(vdev);
> +
> +    if (!vub->connected) {
> +        return;
> +    }
> +    vub->connected = false;
> +
> +    if (vhost_dev_is_started(&vub->vhost_dev)) {
> +        vub_stop(vdev);
> +    }
> +}
> +
> +static void vub_event(void *opaque, QEMUChrEvent event)
> +{
> +    DeviceState *dev = opaque;
> +    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> +    VHostUserBase *vub = VHOST_USER_BASE(vdev);
> +
> +    switch (event) {
> +    case CHR_EVENT_OPENED:
> +        if (vub_connect(dev) < 0) {
> +            qemu_chr_fe_disconnect(&vub->chardev);
> +            return;
> +        }
> +        break;
> +    case CHR_EVENT_CLOSED:
> +        vub_disconnect(dev);
> +        break;
> +    case CHR_EVENT_BREAK:
> +    case CHR_EVENT_MUX_IN:
> +    case CHR_EVENT_MUX_OUT:
> +        /* Ignore */
> +        break;
> +    }
> +}
> +
> +static void vub_device_realize(DeviceState *dev, Error **errp)
> +{
> +    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> +    VHostUserBase *vub = VHOST_USER_BASE(dev);
> +    int ret;
> +
> +    if (!vub->chardev.chr) {
> +        error_setg(errp, "vhost-user-device: missing chardev");
> +        return;
> +    }
> +
> +    if (!vub->virtio_id) {
> +        error_setg(errp, "vhost-user-device: need to define device id");
> +        return;
> +    }
> +
> +    if (!vub->num_vqs) {
> +        vub->num_vqs = 1; /* reasonable default? */
> +    }
> +
> +    if (!vhost_user_init(&vub->vhost_user, &vub->chardev, errp)) {
> +        return;
> +    }
> +
> +    virtio_init(vdev, vub->virtio_id, 0);
> +
> +    /*
> +     * Disable guest notifiers, by default all notifications will be via the
> +     * asynchronous vhost-user socket.
> +     */
> +    vdev->use_guest_notifier_mask = false;
> +
> +    /* Allocate queues */
> +    vub->vqs = g_ptr_array_sized_new(vub->num_vqs);
> +    for (int i = 0; i < vub->num_vqs; i++) {
> +        g_ptr_array_add(vub->vqs,
> +                        virtio_add_queue(vdev, 4, vub_handle_output));
> +    }
> +

Hello Alex, apologies if someone already asked this. If I understand
correctly, the second parameter of virtio_add_queue() is the len of the
queue. Why have you chosen "4" as its value? Shall qemu query the len of
the queue from the vhost-user device instead?

Matias



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Virtio-fs] [PATCH v3 07/20] virtio: add vhost-user-base and a generic vhost-user-device
@ 2023-09-05 14:19     ` Matias Ezequiel Vara Larsen
  0 siblings, 0 replies; 66+ messages in thread
From: Matias Ezequiel Vara Larsen @ 2023-09-05 14:19 UTC (permalink / raw)
  To: Alex Bennée
  Cc: qemu-devel, Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

On Mon, Jul 10, 2023 at 04:35:09PM +0100, Alex Bennée wrote:
> In theory we shouldn't need to repeat so much boilerplate to support
> vhost-user backends. This provides a generic vhost-user-base QOM
> object and a derived vhost-user-device for which the user needs to
> provide the few bits of information that aren't currently provided by
> the vhost-user protocol. This should provide a baseline implementation
> from which the other vhost-user stub can specialise.
> 
> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
> 
> ---
> v2
>   - split into vub and vud
> ---
>  include/hw/virtio/vhost-user-device.h |  45 ++++
>  hw/virtio/vhost-user-device.c         | 324 ++++++++++++++++++++++++++
>  hw/virtio/meson.build                 |   2 +
>  3 files changed, 371 insertions(+)
>  create mode 100644 include/hw/virtio/vhost-user-device.h
>  create mode 100644 hw/virtio/vhost-user-device.c
> 
> diff --git a/include/hw/virtio/vhost-user-device.h b/include/hw/virtio/vhost-user-device.h
> new file mode 100644
> index 0000000000..9105011e25
> --- /dev/null
> +++ b/include/hw/virtio/vhost-user-device.h
> @@ -0,0 +1,45 @@
> +/*
> + * Vhost-user generic virtio device
> + *
> + * Copyright (c) 2023 Linaro Ltd
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#ifndef QEMU_VHOST_USER_DEVICE_H
> +#define QEMU_VHOST_USER_DEVICE_H
> +
> +#include "hw/virtio/vhost.h"
> +#include "hw/virtio/vhost-user.h"
> +
> +#define TYPE_VHOST_USER_BASE "vhost-user-base"
> +
> +OBJECT_DECLARE_TYPE(VHostUserBase, VHostUserBaseClass, VHOST_USER_BASE)
> +
> +struct VHostUserBase {
> +    VirtIODevice parent;
> +    /* Properties */
> +    CharBackend chardev;
> +    uint16_t virtio_id;
> +    uint32_t num_vqs;
> +    /* State tracking */
> +    VhostUserState vhost_user;
> +    struct vhost_virtqueue *vhost_vq;
> +    struct vhost_dev vhost_dev;
> +    GPtrArray *vqs;
> +    bool connected;
> +};
> +
> +    /* needed so we can use the base realize after specialisation
> +       tweaks */
> +struct VHostUserBaseClass {
> +    /*< private >*/
> +    VirtioDeviceClass parent_class;
> +    /*< public >*/
> +    DeviceRealize parent_realize;
> +};
> +
> +/* shared for the benefit of the derived pci class */
> +#define TYPE_VHOST_USER_DEVICE "vhost-user-device"
> +
> +#endif /* QEMU_VHOST_USER_DEVICE_H */
> diff --git a/hw/virtio/vhost-user-device.c b/hw/virtio/vhost-user-device.c
> new file mode 100644
> index 0000000000..b0239fa033
> --- /dev/null
> +++ b/hw/virtio/vhost-user-device.c
> @@ -0,0 +1,324 @@
> +/*
> + * Generic vhost-user stub. This can be used to connect to any
> + * vhost-user backend. All configuration details must be handled by
> + * the vhost-user daemon itself
> + *
> + * Copyright (c) 2023 Linaro Ltd
> + * Author: Alex Bennée <alex.bennee@linaro.org>
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qapi/error.h"
> +#include "hw/qdev-properties.h"
> +#include "hw/virtio/virtio-bus.h"
> +#include "hw/virtio/vhost-user-device.h"
> +#include "qemu/error-report.h"
> +
> +static void vub_start(VirtIODevice *vdev)
> +{
> +    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
> +    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
> +    VHostUserBase *vub = VHOST_USER_BASE(vdev);
> +    int ret, i;
> +
> +    if (!k->set_guest_notifiers) {
> +        error_report("binding does not support guest notifiers");
> +        return;
> +    }
> +
> +    ret = vhost_dev_enable_notifiers(&vub->vhost_dev, vdev);
> +    if (ret < 0) {
> +        error_report("Error enabling host notifiers: %d", -ret);
> +        return;
> +    }
> +
> +    ret = k->set_guest_notifiers(qbus->parent, vub->vhost_dev.nvqs, true);
> +    if (ret < 0) {
> +        error_report("Error binding guest notifier: %d", -ret);
> +        goto err_host_notifiers;
> +    }
> +
> +    vub->vhost_dev.acked_features = vdev->guest_features;
> +
> +    ret = vhost_dev_start(&vub->vhost_dev, vdev, true);
> +    if (ret < 0) {
> +        error_report("Error starting vhost-user-device: %d", -ret);
> +        goto err_guest_notifiers;
> +    }
> +
> +    /*
> +     * guest_notifier_mask/pending not used yet, so just unmask
> +     * everything here. virtio-pci will do the right thing by
> +     * enabling/disabling irqfd.
> +     */
> +    for (i = 0; i < vub->vhost_dev.nvqs; i++) {
> +        vhost_virtqueue_mask(&vub->vhost_dev, vdev, i, false);
> +    }
> +
> +    return;
> +
> +err_guest_notifiers:
> +    k->set_guest_notifiers(qbus->parent, vub->vhost_dev.nvqs, false);
> +err_host_notifiers:
> +    vhost_dev_disable_notifiers(&vub->vhost_dev, vdev);
> +}
> +
> +static void vub_stop(VirtIODevice *vdev)
> +{
> +    VHostUserBase *vub = VHOST_USER_BASE(vdev);
> +    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
> +    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
> +    int ret;
> +
> +    if (!k->set_guest_notifiers) {
> +        return;
> +    }
> +
> +    vhost_dev_stop(&vub->vhost_dev, vdev, true);
> +
> +    ret = k->set_guest_notifiers(qbus->parent, vub->vhost_dev.nvqs, false);
> +    if (ret < 0) {
> +        error_report("vhost guest notifier cleanup failed: %d", ret);
> +        return;
> +    }
> +
> +    vhost_dev_disable_notifiers(&vub->vhost_dev, vdev);
> +}
> +
> +static void vub_set_status(VirtIODevice *vdev, uint8_t status)
> +{
> +    VHostUserBase *vub = VHOST_USER_BASE(vdev);
> +    bool should_start = virtio_device_should_start(vdev, status);
> +
> +    if (vhost_dev_is_started(&vub->vhost_dev) == should_start) {
> +        return;
> +    }
> +
> +    if (should_start) {
> +        vub_start(vdev);
> +    } else {
> +        vub_stop(vdev);
> +    }
> +}
> +
> +/*
> + * For an implementation where everything is delegated to the backend
> + * we don't do anything other than return the full feature set offered
> + * by the daemon (module the reserved feature bit).
> + */
> +static uint64_t vub_get_features(VirtIODevice *vdev,
> +                                 uint64_t requested_features, Error **errp)
> +{
> +    VHostUserBase *vub = VHOST_USER_BASE(vdev);
> +    /* This should be set when the vhost connection initialises */
> +    g_assert(vub->vhost_dev.features);
> +    return vub->vhost_dev.features & ~(1ULL << VHOST_USER_F_PROTOCOL_FEATURES);
> +}
> +
> +static void vub_handle_output(VirtIODevice *vdev, VirtQueue *vq)
> +{
> +    /*
> +     * Not normally called; it's the daemon that handles the queue;
> +     * however virtio's cleanup path can call this.
> +     */
> +}
> +
> +static void do_vhost_user_cleanup(VirtIODevice *vdev, VHostUserBase *vub)
> +{
> +    vhost_user_cleanup(&vub->vhost_user);
> +
> +    for (int i = 0; i < vub->num_vqs; i++) {
> +        VirtQueue *vq = g_ptr_array_index(vub->vqs, i);
> +        virtio_delete_queue(vq);
> +    }
> +
> +    virtio_cleanup(vdev);
> +}
> +
> +static int vub_connect(DeviceState *dev)
> +{
> +    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> +    VHostUserBase *vub = VHOST_USER_BASE(vdev);
> +
> +    if (vub->connected) {
> +        return 0;
> +    }
> +    vub->connected = true;
> +
> +    /* restore vhost state */
> +    if (virtio_device_started(vdev, vdev->status)) {
> +        vub_start(vdev);
> +    }
> +
> +    return 0;
> +}
> +
> +static void vub_disconnect(DeviceState *dev)
> +{
> +    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> +    VHostUserBase *vub = VHOST_USER_BASE(vdev);
> +
> +    if (!vub->connected) {
> +        return;
> +    }
> +    vub->connected = false;
> +
> +    if (vhost_dev_is_started(&vub->vhost_dev)) {
> +        vub_stop(vdev);
> +    }
> +}
> +
> +static void vub_event(void *opaque, QEMUChrEvent event)
> +{
> +    DeviceState *dev = opaque;
> +    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> +    VHostUserBase *vub = VHOST_USER_BASE(vdev);
> +
> +    switch (event) {
> +    case CHR_EVENT_OPENED:
> +        if (vub_connect(dev) < 0) {
> +            qemu_chr_fe_disconnect(&vub->chardev);
> +            return;
> +        }
> +        break;
> +    case CHR_EVENT_CLOSED:
> +        vub_disconnect(dev);
> +        break;
> +    case CHR_EVENT_BREAK:
> +    case CHR_EVENT_MUX_IN:
> +    case CHR_EVENT_MUX_OUT:
> +        /* Ignore */
> +        break;
> +    }
> +}
> +
> +static void vub_device_realize(DeviceState *dev, Error **errp)
> +{
> +    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> +    VHostUserBase *vub = VHOST_USER_BASE(dev);
> +    int ret;
> +
> +    if (!vub->chardev.chr) {
> +        error_setg(errp, "vhost-user-device: missing chardev");
> +        return;
> +    }
> +
> +    if (!vub->virtio_id) {
> +        error_setg(errp, "vhost-user-device: need to define device id");
> +        return;
> +    }
> +
> +    if (!vub->num_vqs) {
> +        vub->num_vqs = 1; /* reasonable default? */
> +    }
> +
> +    if (!vhost_user_init(&vub->vhost_user, &vub->chardev, errp)) {
> +        return;
> +    }
> +
> +    virtio_init(vdev, vub->virtio_id, 0);
> +
> +    /*
> +     * Disable guest notifiers, by default all notifications will be via the
> +     * asynchronous vhost-user socket.
> +     */
> +    vdev->use_guest_notifier_mask = false;
> +
> +    /* Allocate queues */
> +    vub->vqs = g_ptr_array_sized_new(vub->num_vqs);
> +    for (int i = 0; i < vub->num_vqs; i++) {
> +        g_ptr_array_add(vub->vqs,
> +                        virtio_add_queue(vdev, 4, vub_handle_output));
> +    }
> +

Hello Alex, apologies if someone already asked this. If I understand
correctly, the second parameter of virtio_add_queue() is the len of the
queue. Why have you chosen "4" as its value? Shall qemu query the len of
the queue from the vhost-user device instead?

Matias


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v3 07/20] virtio: add vhost-user-base and a generic vhost-user-device
  2023-09-05 14:19     ` [Virtio-fs] " Matias Ezequiel Vara Larsen
@ 2023-09-05 17:01       ` Alex Bennée
  -1 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-09-05 17:01 UTC (permalink / raw)
  To: Matias Ezequiel Vara Larsen
  Cc: qemu-devel, Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi


Matias Ezequiel Vara Larsen <mvaralar@redhat.com> writes:

> On Mon, Jul 10, 2023 at 04:35:09PM +0100, Alex Bennée wrote:
>> In theory we shouldn't need to repeat so much boilerplate to support
>> vhost-user backends. This provides a generic vhost-user-base QOM
>> object and a derived vhost-user-device for which the user needs to
>> provide the few bits of information that aren't currently provided by
>> the vhost-user protocol. This should provide a baseline implementation
>> from which the other vhost-user stub can specialise.
>> 
>> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
>> 
>> ---
>> v2
>>   - split into vub and vud
<snip>
>> +
>> +    /*
>> +     * Disable guest notifiers, by default all notifications will be via the
>> +     * asynchronous vhost-user socket.
>> +     */
>> +    vdev->use_guest_notifier_mask = false;
>> +
>> +    /* Allocate queues */
>> +    vub->vqs = g_ptr_array_sized_new(vub->num_vqs);
>> +    for (int i = 0; i < vub->num_vqs; i++) {
>> +        g_ptr_array_add(vub->vqs,
>> +                        virtio_add_queue(vdev, 4, vub_handle_output));
>> +    }
>> +
>
> Hello Alex, apologies if someone already asked this. If I understand
> correctly, the second parameter of virtio_add_queue() is the len of the
> queue. Why have you chosen "4" as its value? Shall qemu query the len of
> the queue from the vhost-user device instead?

Hmm yeah that is inherited from the virtio-rng backend which has a
pretty short queue. I don't think it is intrinsic to the device
implementation (although I guess that depends if a device will have
multiple requests in flight).

I propose making is some useful ^2 (like 64) and adding a config knob to
increase it if needed.

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Virtio-fs] [PATCH v3 07/20] virtio: add vhost-user-base and a generic vhost-user-device
@ 2023-09-05 17:01       ` Alex Bennée
  0 siblings, 0 replies; 66+ messages in thread
From: Alex Bennée @ 2023-09-05 17:01 UTC (permalink / raw)
  To: Matias Ezequiel Vara Larsen
  Cc: qemu-devel, Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi


Matias Ezequiel Vara Larsen <mvaralar@redhat.com> writes:

> On Mon, Jul 10, 2023 at 04:35:09PM +0100, Alex Bennée wrote:
>> In theory we shouldn't need to repeat so much boilerplate to support
>> vhost-user backends. This provides a generic vhost-user-base QOM
>> object and a derived vhost-user-device for which the user needs to
>> provide the few bits of information that aren't currently provided by
>> the vhost-user protocol. This should provide a baseline implementation
>> from which the other vhost-user stub can specialise.
>> 
>> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
>> 
>> ---
>> v2
>>   - split into vub and vud
<snip>
>> +
>> +    /*
>> +     * Disable guest notifiers, by default all notifications will be via the
>> +     * asynchronous vhost-user socket.
>> +     */
>> +    vdev->use_guest_notifier_mask = false;
>> +
>> +    /* Allocate queues */
>> +    vub->vqs = g_ptr_array_sized_new(vub->num_vqs);
>> +    for (int i = 0; i < vub->num_vqs; i++) {
>> +        g_ptr_array_add(vub->vqs,
>> +                        virtio_add_queue(vdev, 4, vub_handle_output));
>> +    }
>> +
>
> Hello Alex, apologies if someone already asked this. If I understand
> correctly, the second parameter of virtio_add_queue() is the len of the
> queue. Why have you chosen "4" as its value? Shall qemu query the len of
> the queue from the vhost-user device instead?

Hmm yeah that is inherited from the virtio-rng backend which has a
pretty short queue. I don't think it is intrinsic to the device
implementation (although I guess that depends if a device will have
multiple requests in flight).

I propose making is some useful ^2 (like 64) and adding a config knob to
increase it if needed.

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [PATCH v3 07/20] virtio: add vhost-user-base and a generic vhost-user-device
  2023-09-05 17:01       ` [Virtio-fs] " Alex Bennée
@ 2023-09-06  9:21         ` Matias Ezequiel Vara Larsen
  -1 siblings, 0 replies; 66+ messages in thread
From: Matias Ezequiel Vara Larsen @ 2023-09-06  9:21 UTC (permalink / raw)
  To: Alex Bennée
  Cc: qemu-devel, Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

On Tue, Sep 05, 2023 at 06:01:56PM +0100, Alex Bennée wrote:
> 
> Matias Ezequiel Vara Larsen <mvaralar@redhat.com> writes:
> 
> > On Mon, Jul 10, 2023 at 04:35:09PM +0100, Alex Bennée wrote:
> >> In theory we shouldn't need to repeat so much boilerplate to support
> >> vhost-user backends. This provides a generic vhost-user-base QOM
> >> object and a derived vhost-user-device for which the user needs to
> >> provide the few bits of information that aren't currently provided by
> >> the vhost-user protocol. This should provide a baseline implementation
> >> from which the other vhost-user stub can specialise.
> >> 
> >> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
> >> 
> >> ---
> >> v2
> >>   - split into vub and vud
> <snip>
> >> +
> >> +    /*
> >> +     * Disable guest notifiers, by default all notifications will be via the
> >> +     * asynchronous vhost-user socket.
> >> +     */
> >> +    vdev->use_guest_notifier_mask = false;
> >> +
> >> +    /* Allocate queues */
> >> +    vub->vqs = g_ptr_array_sized_new(vub->num_vqs);
> >> +    for (int i = 0; i < vub->num_vqs; i++) {
> >> +        g_ptr_array_add(vub->vqs,
> >> +                        virtio_add_queue(vdev, 4, vub_handle_output));
> >> +    }
> >> +
> >
> > Hello Alex, apologies if someone already asked this. If I understand
> > correctly, the second parameter of virtio_add_queue() is the len of the
> > queue. Why have you chosen "4" as its value? Shall qemu query the len of
> > the queue from the vhost-user device instead?
> 
> Hmm yeah that is inherited from the virtio-rng backend which has a
> pretty short queue. I don't think it is intrinsic to the device
> implementation (although I guess that depends if a device will have
> multiple requests in flight).
> 
> I propose making is some useful ^2 (like 64) and adding a config knob to
> increase it if needed.
> 

LGTM.  

Matias



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Virtio-fs] [PATCH v3 07/20] virtio: add vhost-user-base and a generic vhost-user-device
@ 2023-09-06  9:21         ` Matias Ezequiel Vara Larsen
  0 siblings, 0 replies; 66+ messages in thread
From: Matias Ezequiel Vara Larsen @ 2023-09-06  9:21 UTC (permalink / raw)
  To: Alex Bennée
  Cc: qemu-devel, Marc-André Lureau, Jason Wang, Viresh Kumar,
	Raphael Norwitz, Paolo Bonzini, Daniel P. Berrangé,
	qemu-block, Eric Blake, Michael S. Tsirkin, Mark Cave-Ayland,
	Kevin Wolf, Markus Armbruster, Gerd Hoffmann, Mathieu Poirier,
	Hanna Reitz, Erik Schilling, Gonglei (Arei),
	Eduardo Habkost, Fam Zheng, virtio-fs, Stefan Hajnoczi

On Tue, Sep 05, 2023 at 06:01:56PM +0100, Alex Bennée wrote:
> 
> Matias Ezequiel Vara Larsen <mvaralar@redhat.com> writes:
> 
> > On Mon, Jul 10, 2023 at 04:35:09PM +0100, Alex Bennée wrote:
> >> In theory we shouldn't need to repeat so much boilerplate to support
> >> vhost-user backends. This provides a generic vhost-user-base QOM
> >> object and a derived vhost-user-device for which the user needs to
> >> provide the few bits of information that aren't currently provided by
> >> the vhost-user protocol. This should provide a baseline implementation
> >> from which the other vhost-user stub can specialise.
> >> 
> >> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
> >> 
> >> ---
> >> v2
> >>   - split into vub and vud
> <snip>
> >> +
> >> +    /*
> >> +     * Disable guest notifiers, by default all notifications will be via the
> >> +     * asynchronous vhost-user socket.
> >> +     */
> >> +    vdev->use_guest_notifier_mask = false;
> >> +
> >> +    /* Allocate queues */
> >> +    vub->vqs = g_ptr_array_sized_new(vub->num_vqs);
> >> +    for (int i = 0; i < vub->num_vqs; i++) {
> >> +        g_ptr_array_add(vub->vqs,
> >> +                        virtio_add_queue(vdev, 4, vub_handle_output));
> >> +    }
> >> +
> >
> > Hello Alex, apologies if someone already asked this. If I understand
> > correctly, the second parameter of virtio_add_queue() is the len of the
> > queue. Why have you chosen "4" as its value? Shall qemu query the len of
> > the queue from the vhost-user device instead?
> 
> Hmm yeah that is inherited from the virtio-rng backend which has a
> pretty short queue. I don't think it is intrinsic to the device
> implementation (although I guess that depends if a device will have
> multiple requests in flight).
> 
> I propose making is some useful ^2 (like 64) and adding a config knob to
> increase it if needed.
> 

LGTM.  

Matias


^ permalink raw reply	[flat|nested] 66+ messages in thread

end of thread, other threads:[~2023-09-06  9:23 UTC | newest]

Thread overview: 66+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-10 15:35 [PATCH v3 00/20] virtio: add vhost-user-generic, reduce c&p and support standalone Alex Bennée
2023-07-10 15:35 ` [Virtio-fs] " Alex Bennée
2023-07-10 15:35 ` [PATCH v3 01/20] include: attempt to document device_class_set_props Alex Bennée
2023-07-10 15:35   ` [Virtio-fs] " Alex Bennée
2023-07-10 15:35 ` [PATCH v3 02/20] include/hw: document the device_class_set_parent_* fns Alex Bennée
2023-07-10 15:35   ` [Virtio-fs] " Alex Bennée
2023-07-10 15:35 ` [PATCH v3 03/20] hw/virtio: fix typo in VIRTIO_CONFIG_IRQ_IDX comments Alex Bennée
2023-07-10 15:35   ` [Virtio-fs] " Alex Bennée
2023-07-10 21:56   ` Philippe Mathieu-Daudé
2023-07-10 21:56     ` [Virtio-fs] " Philippe Mathieu-Daudé
2023-07-10 15:35 ` [PATCH v3 04/20] include/hw/virtio: document virtio_notify_config Alex Bennée
2023-07-10 15:35   ` [Virtio-fs] " Alex Bennée
2023-07-10 15:35 ` [PATCH v3 05/20] include/hw/virtio: add kerneldoc for virtio_init Alex Bennée
2023-07-10 15:35   ` [Virtio-fs] " Alex Bennée
2023-07-10 21:58   ` Philippe Mathieu-Daudé
2023-07-10 21:58     ` [Virtio-fs] " Philippe Mathieu-Daudé
2023-07-10 15:35 ` [PATCH v3 06/20] include/hw/virtio: document some more usage of notifiers Alex Bennée
2023-07-10 15:35   ` [Virtio-fs] " Alex Bennée
2023-07-10 15:35 ` [PATCH v3 07/20] virtio: add vhost-user-base and a generic vhost-user-device Alex Bennée
2023-07-10 15:35   ` [Virtio-fs] " Alex Bennée
2023-07-10 20:15   ` Michael S. Tsirkin
2023-07-10 20:15     ` [Virtio-fs] " Michael S. Tsirkin
2023-09-05 14:19   ` Matias Ezequiel Vara Larsen
2023-09-05 14:19     ` [Virtio-fs] " Matias Ezequiel Vara Larsen
2023-09-05 17:01     ` Alex Bennée
2023-09-05 17:01       ` [Virtio-fs] " Alex Bennée
2023-09-06  9:21       ` Matias Ezequiel Vara Larsen
2023-09-06  9:21         ` [Virtio-fs] " Matias Ezequiel Vara Larsen
2023-07-10 15:35 ` [PATCH v3 08/20] virtio: add PCI stub for vhost-user-device Alex Bennée
2023-07-10 15:35   ` [Virtio-fs] " Alex Bennée
2023-07-10 15:35 ` [PATCH v3 09/20] hw/virtio: derive vhost-user-rng from vhost-user-device Alex Bennée
2023-07-10 15:35   ` [Virtio-fs] " Alex Bennée
2023-07-10 15:35 ` [PATCH v3 10/20] hw/virtio: add config support to vhost-user-device Alex Bennée
2023-07-10 15:35   ` [Virtio-fs] " Alex Bennée
2023-07-10 19:58   ` Michael S. Tsirkin
2023-07-10 19:58     ` [Virtio-fs] " Michael S. Tsirkin
2023-08-31 14:23     ` Albert Esteve
2023-08-31 14:23       ` [Virtio-fs] " Albert Esteve
2023-08-31 15:47       ` Alex Bennée
2023-08-31 15:47         ` [Virtio-fs] " Alex Bennée
2023-09-01  5:56         ` Erik Schilling
2023-09-01  5:56           ` [Virtio-fs] " Erik Schilling
2023-09-01  8:34         ` Albert Esteve
2023-09-01  8:34           ` [Virtio-fs] " Albert Esteve
2023-07-10 15:35 ` [PATCH v3 11/20] hw/virtio: derive vhost-user-gpio from vhost-user-device Alex Bennée
2023-07-10 15:35   ` [Virtio-fs] " Alex Bennée
2023-07-10 15:35 ` [PATCH v3 12/20] hw/virtio: derive vhost-user-i2c from vhost-user-base Alex Bennée
2023-07-10 15:35   ` [Virtio-fs] " Alex Bennée
2023-07-10 15:35 ` [RFC PATCH v3 13/20] docs/system: add a basic enumeration of vhost-user devices Alex Bennée
2023-07-10 15:35   ` [Virtio-fs] " Alex Bennée
2023-07-10 15:35 ` [RFC PATCH v3 14/20] docs/interop: define STANDALONE protocol feature for vhost-user Alex Bennée
2023-07-10 15:35   ` [Virtio-fs] " Alex Bennée
2023-07-10 15:35 ` [RFC PATCH v3 15/20] hw/virtio: move vhost_user_init earlier Alex Bennée
2023-07-10 15:35   ` [Virtio-fs] " Alex Bennée
2023-07-10 15:35 ` [RFC PATCH v3 16/20] hw/virtio: move virtq initialisation into internal helper Alex Bennée
2023-07-10 15:35   ` [Virtio-fs] " Alex Bennée
2023-07-10 15:35 ` [RFC PATCH v3 17/20] hw/virtio: push down allocation responsibility for vhost_dev->vqs Alex Bennée
2023-07-10 15:35   ` [Virtio-fs] " Alex Bennée
2023-07-10 15:35 ` [RFC PATCH v3 18/20] hw/virtio: validate F_STANDALONE also supports other protocol features Alex Bennée
2023-07-10 15:35   ` [Virtio-fs] " Alex Bennée
2023-07-10 15:35 ` [RFC PATCH v3 19/20] hw/virtio: probe backend for specs if it supports it Alex Bennée
2023-07-10 15:35   ` [Virtio-fs] " Alex Bennée
2023-07-10 15:35 ` [RFC PATCH v3 20/20] hw/virtio: allow vhost-user-device to be driven by backend Alex Bennée
2023-07-10 15:35   ` [Virtio-fs] " Alex Bennée
2023-09-01 10:00   ` Albert Esteve
2023-09-01 10:00     ` [Virtio-fs] " Albert Esteve

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.