All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V2 0/3] virtio: Add vhost-user-i2c device's support
@ 2021-07-09  5:00 Viresh Kumar
  2021-07-09  5:00 ` [PATCH V2 1/3] hw/virtio: add boilerplate for vhost-user-i2c device Viresh Kumar
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Viresh Kumar @ 2021-07-09  5:00 UTC (permalink / raw)
  To: qemu-devel, Alex Bennée, Michael S. Tsirkin, Viresh Kumar
  Cc: Vincent Guittot, Jie Deng, Bill Mills, Arnd Bergmann,
	Mike Holmes, stratos-dev

Hello,

This patchset adds vhost-user-i2c device's support in Qemu. Initially I tried to
add the backend implementation as well into Qemu, but as I was looking for a
hypervisor agnostic backend implementation, I decided to keep it outside of
Qemu. Eventually I implemented it in Rust and it works very well with this
patchset, and it is under review [1] to be merged in common rust vhost devices
crate.

The kernel virtio I2C driver [2] is fully reviewed and is ready to be merged soon.

V1->V2:
- Dropped the backend support from qemu and minor cleanups.

I2C Testing:
------------

I didn't have access to a real hardware where I can play with a I2C
client device (like RTC, eeprom, etc) to verify the working of the
backend daemon, so I decided to test it on my x86 box itself with
hierarchy of two ARM64 guests.

The first ARM64 guest was passed "-device ds1338,address=0x20" option,
so it could emulate a ds1338 RTC device, which connects to an I2C bus.
Once the guest came up, ds1338 device instance was created within the
guest kernel by doing:

  echo ds1338 0x20 > /sys/bus/i2c/devices/i2c-0/new_device

[
  Note that this may end up binding the ds1338 device to its driver,
  which won't let our i2c daemon talk to the device. For that we need to
  manually unbind the device from the driver:

  echo 0-0020 > /sys/bus/i2c/devices/0-0020/driver/unbind
]

After this is done, you will get /dev/rtc1. This is the device we wanted
to emulate, which will be accessed by the vhost-user-i2c backend daemon
via the /dev/i2c-0 file present in the guest VM.

At this point we need to start the backend daemon and give it a
socket-path to talk to from qemu (you can pass -v to it to get more
detailed messages):

  vhost-user-i2c --socket-path=vi2c.sock -l 0:32

[ Here, 0:32 is the bus/device mapping, 0 for /dev/i2c-0 and 32 (i.e.
0x20) is client address of ds1338 that we used while creating the
device. ]

Now we need to start the second level ARM64 guest (from within the first
guest) to get the i2c-virtio.c Linux driver up. The second level guest
is passed the following options to connect to the same socket:

  -chardev socket,path=vi2c.sock0,id=vi2c \
  -device vhost-user-i2c-pci,chardev=vi2c,id=i2c

Once the second level guest boots up, we will see the i2c-virtio bus at
/sys/bus/i2c/devices/i2c-X/. From there we can now make it emulate the
ds1338 device again by doing:


  echo ds1338 0x20 > /sys/bus/i2c/devices/i2c-0/new_device

[ This time we want ds1338's driver to be bound to the device, so it
should be enabled in the kernel as well. ]

And we will get /dev/rtc1 device again here in the second level guest.
Now we can play with the rtc device with help of hwclock utility and we
can see the following sequence of transfers happening if we try to
update rtc's time from system time.

hwclock -w -f /dev/rtc1 (in guest2) ->
  Reaches i2c-virtio.c (Linux bus driver in guest2) ->
    transfer over virtio ->
      Reaches the qemu's vhost-i2c device emulation (running over guest1) ->
        Reaches the backend daemon vhost-user-i2c started earlier (in guest1) ->
          ioctl(/dev/i2c-0, I2C_RDWR, ..); (in guest1) ->
            reaches qemu's hw/rtc/ds1338.c (running over host)


SMBUS Testing:
--------------

I wasn't required to have such a tedious setup for testing out with
SMBUS devices. I was able to emulate a SMBUS device on my x86 machine
using i2c-stub driver.

$ modprobe i2c-stub chip_addr=0x20
//Boot the arm64 guest now with i2c-virtio driver and then do:
$ echo al3320a 0x20 > /sys/class/i2c-adapter/i2c-0/new_device
$ cat /sys/bus/iio/devices/iio:device0/in_illuminance_raw

That's it.

I hope I was able to give a clear picture of my test setup here :)

--
Viresh

Viresh Kumar (3):
  hw/virtio: add boilerplate for vhost-user-i2c device
  hw/virtio: add vhost-user-i2c-pci boilerplate
  MAINTAINERS: Add entry for virtio-i2c

 MAINTAINERS                        |   7 +
 hw/virtio/Kconfig                  |   5 +
 hw/virtio/meson.build              |   2 +
 hw/virtio/vhost-user-i2c-pci.c     |  69 +++++++
 hw/virtio/vhost-user-i2c.c         | 288 +++++++++++++++++++++++++++++
 include/hw/virtio/vhost-user-i2c.h |  28 +++
 6 files changed, 399 insertions(+)
 create mode 100644 hw/virtio/vhost-user-i2c-pci.c
 create mode 100644 hw/virtio/vhost-user-i2c.c
 create mode 100644 include/hw/virtio/vhost-user-i2c.h

-- 
2.31.1.272.g89b43f80a514



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

* [PATCH V2 1/3] hw/virtio: add boilerplate for vhost-user-i2c device
  2021-07-09  5:00 [PATCH V2 0/3] virtio: Add vhost-user-i2c device's support Viresh Kumar
@ 2021-07-09  5:00 ` Viresh Kumar
  2021-07-09  5:00 ` [PATCH V2 2/3] hw/virtio: add vhost-user-i2c-pci boilerplate Viresh Kumar
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Viresh Kumar @ 2021-07-09  5:00 UTC (permalink / raw)
  To: qemu-devel, Alex Bennée, Michael S. Tsirkin, Viresh Kumar
  Cc: Vincent Guittot, Jie Deng, Bill Mills, Arnd Bergmann,
	Mike Holmes, stratos-dev

This creates the QEMU side of the vhost-user-i2c device which connects
to the remote daemon. It is based of vhost-user-fs code.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 hw/virtio/Kconfig                  |   5 +
 hw/virtio/meson.build              |   1 +
 hw/virtio/vhost-user-i2c.c         | 288 +++++++++++++++++++++++++++++
 include/hw/virtio/vhost-user-i2c.h |  28 +++
 4 files changed, 322 insertions(+)
 create mode 100644 hw/virtio/vhost-user-i2c.c
 create mode 100644 include/hw/virtio/vhost-user-i2c.h

diff --git a/hw/virtio/Kconfig b/hw/virtio/Kconfig
index 0eda25c4e1bf..35ab45e2095c 100644
--- a/hw/virtio/Kconfig
+++ b/hw/virtio/Kconfig
@@ -58,3 +58,8 @@ config VIRTIO_MEM
     depends on LINUX
     depends on VIRTIO_MEM_SUPPORTED
     select MEM_DEVICE
+
+config VHOST_USER_I2C
+    bool
+    default y
+    depends on VIRTIO && VHOST_USER
diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build
index fbff9bc9d4de..1a0d736a0db5 100644
--- a/hw/virtio/meson.build
+++ b/hw/virtio/meson.build
@@ -25,6 +25,7 @@ virtio_ss.add(when: 'CONFIG_VHOST_USER_VSOCK', if_true: files('vhost-user-vsock.
 virtio_ss.add(when: 'CONFIG_VIRTIO_RNG', if_true: files('virtio-rng.c'))
 virtio_ss.add(when: 'CONFIG_VIRTIO_IOMMU', if_true: files('virtio-iommu.c'))
 virtio_ss.add(when: 'CONFIG_VIRTIO_MEM', if_true: files('virtio-mem.c'))
+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'))
diff --git a/hw/virtio/vhost-user-i2c.c b/hw/virtio/vhost-user-i2c.c
new file mode 100644
index 000000000000..d172632bb0cd
--- /dev/null
+++ b/hw/virtio/vhost-user-i2c.c
@@ -0,0 +1,288 @@
+/*
+ * Vhost-user i2c virtio device
+ *
+ * Copyright (c) 2021 Viresh Kumar <viresh.kumar@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-i2c.h"
+#include "qemu/error-report.h"
+#include "standard-headers/linux/virtio_ids.h"
+
+/* Remove this once the header is updated in Linux kernel */
+#ifndef VIRTIO_ID_I2C_ADAPTER
+#define VIRTIO_ID_I2C_ADAPTER                34
+#endif
+
+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);
+    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);
+
+    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 = status & VIRTIO_CONFIG_S_DRIVER_OK;
+
+    if (!vdev->vm_running) {
+        should_start = false;
+    }
+
+    if (i2c->vhost_dev.started == 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)
+{
+    /* No feature bits used yet */
+    return 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);
+
+    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);
+
+    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);
+    g_free(i2c->vhost_dev.vqs);
+    i2c->vhost_dev.vqs = NULL;
+}
+
+static int vu_i2c_connect(DeviceState *dev)
+{
+    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+    VHostUserI2C *i2c = VHOST_USER_I2C(vdev);
+
+    if (i2c->connected) {
+        return 0;
+    }
+    i2c->connected = true;
+
+    /* 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 (i2c->vhost_dev.started) {
+        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, "vhost-user-i2c", 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) {
+        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);
+
+    /* This will stop vhost backend if appropriate. */
+    vu_i2c_set_status(vdev, 0);
+    vhost_dev_cleanup(&i2c->vhost_dev);
+    do_vhost_user_cleanup(vdev, i2c);
+}
+
+static const VMStateDescription vu_i2c_vmstate = {
+    .name = "vhost-user-i2c",
+    .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);
+
+    device_class_set_props(dc, vu_i2c_properties);
+    dc->vmsd = &vu_i2c_vmstate;
+    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,
+    .instance_size = sizeof(VHostUserI2C),
+    .class_init = vu_i2c_class_init,
+};
+
+static void vu_i2c_register_types(void)
+{
+    type_register_static(&vu_i2c_info);
+}
+
+type_init(vu_i2c_register_types)
diff --git a/include/hw/virtio/vhost-user-i2c.h b/include/hw/virtio/vhost-user-i2c.h
new file mode 100644
index 000000000000..deae47a76d55
--- /dev/null
+++ b/include/hw/virtio/vhost-user-i2c.h
@@ -0,0 +1,28 @@
+/*
+ * Vhost-user i2c virtio device
+ *
+ * Copyright (c) 2021 Viresh Kumar <viresh.kumar@linaro.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef _QEMU_VHOST_USER_I2C_H
+#define _QEMU_VHOST_USER_I2C_H
+
+#include "hw/virtio/vhost.h"
+#include "hw/virtio/vhost-user.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;
+};
+
+#endif /* _QEMU_VHOST_USER_I2C_H */
-- 
2.31.1.272.g89b43f80a514



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

* [PATCH V2 2/3] hw/virtio: add vhost-user-i2c-pci boilerplate
  2021-07-09  5:00 [PATCH V2 0/3] virtio: Add vhost-user-i2c device's support Viresh Kumar
  2021-07-09  5:00 ` [PATCH V2 1/3] hw/virtio: add boilerplate for vhost-user-i2c device Viresh Kumar
@ 2021-07-09  5:00 ` Viresh Kumar
  2021-07-09  5:00 ` [PATCH V2 3/3] MAINTAINERS: Add entry for virtio-i2c Viresh Kumar
  2021-09-04 19:44 ` [PATCH V2 0/3] virtio: Add vhost-user-i2c device's support Michael S. Tsirkin
  3 siblings, 0 replies; 6+ messages in thread
From: Viresh Kumar @ 2021-07-09  5:00 UTC (permalink / raw)
  To: qemu-devel, Alex Bennée, Michael S. Tsirkin, Viresh Kumar
  Cc: Vincent Guittot, Jie Deng, Bill Mills, Arnd Bergmann,
	Mike Holmes, stratos-dev

This allows is to instantiate a vhost-user-i2c device as part of a PCI
bus. It is mostly boilerplate which looks pretty similar to the
vhost-user-fs-pci device.

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 hw/virtio/meson.build          |  1 +
 hw/virtio/vhost-user-i2c-pci.c | 69 ++++++++++++++++++++++++++++++++++
 2 files changed, 70 insertions(+)
 create mode 100644 hw/virtio/vhost-user-i2c-pci.c

diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build
index 1a0d736a0db5..bc352a600911 100644
--- a/hw/virtio/meson.build
+++ b/hw/virtio/meson.build
@@ -26,6 +26,7 @@ virtio_ss.add(when: 'CONFIG_VIRTIO_RNG', if_true: files('virtio-rng.c'))
 virtio_ss.add(when: 'CONFIG_VIRTIO_IOMMU', if_true: files('virtio-iommu.c'))
 virtio_ss.add(when: 'CONFIG_VIRTIO_MEM', if_true: files('virtio-mem.c'))
 virtio_ss.add(when: 'CONFIG_VHOST_USER_I2C', if_true: files('vhost-user-i2c.c'))
+virtio_ss.add(when: ['CONFIG_VIRTIO_PCI', 'CONFIG_VHOST_USER_I2C'], if_true: files('vhost-user-i2c-pci.c'))
 
 virtio_pci_ss = ss.source_set()
 virtio_pci_ss.add(when: 'CONFIG_VHOST_VSOCK', if_true: files('vhost-vsock-pci.c'))
diff --git a/hw/virtio/vhost-user-i2c-pci.c b/hw/virtio/vhost-user-i2c-pci.c
new file mode 100644
index 000000000000..70b7b65fd970
--- /dev/null
+++ b/hw/virtio/vhost-user-i2c-pci.c
@@ -0,0 +1,69 @@
+/*
+ * Vhost-user i2c virtio device PCI glue
+ *
+ * Copyright (c) 2021 Viresh Kumar <viresh.kumar@linaro.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "hw/qdev-properties.h"
+#include "hw/virtio/vhost-user-i2c.h"
+#include "virtio-pci.h"
+
+struct VHostUserI2CPCI {
+    VirtIOPCIProxy parent_obj;
+    VHostUserI2C vdev;
+};
+
+typedef struct VHostUserI2CPCI VHostUserI2CPCI;
+
+#define TYPE_VHOST_USER_I2C_PCI "vhost-user-i2c-pci-base"
+
+DECLARE_INSTANCE_CHECKER(VHostUserI2CPCI, VHOST_USER_I2C_PCI,
+                         TYPE_VHOST_USER_I2C_PCI)
+
+static void vhost_user_i2c_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
+{
+    VHostUserI2CPCI *dev = VHOST_USER_I2C_PCI(vpci_dev);
+    DeviceState *vdev = DEVICE(&dev->vdev);
+
+    vpci_dev->nvectors = 1;
+    qdev_realize(vdev, BUS(&vpci_dev->bus), errp);
+}
+
+static void vhost_user_i2c_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_i2c_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_i2c_pci_instance_init(Object *obj)
+{
+    VHostUserI2CPCI *dev = VHOST_USER_I2C_PCI(obj);
+
+    virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
+                                TYPE_VHOST_USER_I2C);
+}
+
+static const VirtioPCIDeviceTypeInfo vhost_user_i2c_pci_info = {
+    .base_name = TYPE_VHOST_USER_I2C_PCI,
+    .non_transitional_name = "vhost-user-i2c-pci",
+    .instance_size = sizeof(VHostUserI2CPCI),
+    .instance_init = vhost_user_i2c_pci_instance_init,
+    .class_init = vhost_user_i2c_pci_class_init,
+};
+
+static void vhost_user_i2c_pci_register(void)
+{
+    virtio_pci_types_register(&vhost_user_i2c_pci_info);
+}
+
+type_init(vhost_user_i2c_pci_register);
-- 
2.31.1.272.g89b43f80a514



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

* [PATCH V2 3/3] MAINTAINERS: Add entry for virtio-i2c
  2021-07-09  5:00 [PATCH V2 0/3] virtio: Add vhost-user-i2c device's support Viresh Kumar
  2021-07-09  5:00 ` [PATCH V2 1/3] hw/virtio: add boilerplate for vhost-user-i2c device Viresh Kumar
  2021-07-09  5:00 ` [PATCH V2 2/3] hw/virtio: add vhost-user-i2c-pci boilerplate Viresh Kumar
@ 2021-07-09  5:00 ` Viresh Kumar
  2021-09-04 19:44 ` [PATCH V2 0/3] virtio: Add vhost-user-i2c device's support Michael S. Tsirkin
  3 siblings, 0 replies; 6+ messages in thread
From: Viresh Kumar @ 2021-07-09  5:00 UTC (permalink / raw)
  To: qemu-devel, Alex Bennée
  Cc: Vincent Guittot, Jie Deng, Viresh Kumar, Bill Mills,
	Arnd Bergmann, Mike Holmes, stratos-dev

This patch adds entry for virtio-i2c related files in MAINTAINERS.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 MAINTAINERS | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 684142e12eaa..2869fb185253 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2143,6 +2143,13 @@ F: docs/interop/vhost-user-gpu.rst
 F: contrib/vhost-user-gpu
 F: hw/display/vhost-user-*
 
+vhost-user-i2c
+M: Viresh Kumar <viresh.kumar@linaro.org>
+S: Supported
+F: hw/virtio/vhost-user-i2c.c
+F: hw/virtio/vhost-user-i2c-pci.c
+F: include/hw/virtio/vhost-user-i2c.h
+
 Cirrus VGA
 M: Gerd Hoffmann <kraxel@redhat.com>
 S: Odd Fixes
-- 
2.31.1.272.g89b43f80a514



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

* Re: [PATCH V2 0/3] virtio: Add vhost-user-i2c device's support
  2021-07-09  5:00 [PATCH V2 0/3] virtio: Add vhost-user-i2c device's support Viresh Kumar
                   ` (2 preceding siblings ...)
  2021-07-09  5:00 ` [PATCH V2 3/3] MAINTAINERS: Add entry for virtio-i2c Viresh Kumar
@ 2021-09-04 19:44 ` Michael S. Tsirkin
  2021-09-06  4:37   ` Viresh Kumar
  3 siblings, 1 reply; 6+ messages in thread
From: Michael S. Tsirkin @ 2021-09-04 19:44 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Vincent Guittot, Jie Deng, Bill Mills, qemu-devel, Arnd Bergmann,
	Mike Holmes, Alex Bennée, stratos-dev

On Fri, Jul 09, 2021 at 10:30:15AM +0530, Viresh Kumar wrote:
> Hello,
> 
> This patchset adds vhost-user-i2c device's support in Qemu. Initially I tried to
> add the backend implementation as well into Qemu, but as I was looking for a
> hypervisor agnostic backend implementation, I decided to keep it outside of
> Qemu. Eventually I implemented it in Rust and it works very well with this
> patchset, and it is under review [1] to be merged in common rust vhost devices
> crate.


So I'm not sure whether it's appropriate to merge this right now.
There are several spec change proposals before the virtio TC
and I did not investigate whether this code reflects the
spec before or after these changes. It seems prudent to wait
until the spec changes are finalized and voted on, in any case.

Pls ping me to merge once that has taken place. Thanks!

> The kernel virtio I2C driver [2] is fully reviewed and is ready to be merged soon.
> 
> V1->V2:
> - Dropped the backend support from qemu and minor cleanups.
> 
> I2C Testing:
> ------------
> 
> I didn't have access to a real hardware where I can play with a I2C
> client device (like RTC, eeprom, etc) to verify the working of the
> backend daemon, so I decided to test it on my x86 box itself with
> hierarchy of two ARM64 guests.
> 
> The first ARM64 guest was passed "-device ds1338,address=0x20" option,
> so it could emulate a ds1338 RTC device, which connects to an I2C bus.
> Once the guest came up, ds1338 device instance was created within the
> guest kernel by doing:
> 
>   echo ds1338 0x20 > /sys/bus/i2c/devices/i2c-0/new_device
> 
> [
>   Note that this may end up binding the ds1338 device to its driver,
>   which won't let our i2c daemon talk to the device. For that we need to
>   manually unbind the device from the driver:
> 
>   echo 0-0020 > /sys/bus/i2c/devices/0-0020/driver/unbind
> ]
> 
> After this is done, you will get /dev/rtc1. This is the device we wanted
> to emulate, which will be accessed by the vhost-user-i2c backend daemon
> via the /dev/i2c-0 file present in the guest VM.
> 
> At this point we need to start the backend daemon and give it a
> socket-path to talk to from qemu (you can pass -v to it to get more
> detailed messages):
> 
>   vhost-user-i2c --socket-path=vi2c.sock -l 0:32
> 
> [ Here, 0:32 is the bus/device mapping, 0 for /dev/i2c-0 and 32 (i.e.
> 0x20) is client address of ds1338 that we used while creating the
> device. ]
> 
> Now we need to start the second level ARM64 guest (from within the first
> guest) to get the i2c-virtio.c Linux driver up. The second level guest
> is passed the following options to connect to the same socket:
> 
>   -chardev socket,path=vi2c.sock0,id=vi2c \
>   -device vhost-user-i2c-pci,chardev=vi2c,id=i2c
> 
> Once the second level guest boots up, we will see the i2c-virtio bus at
> /sys/bus/i2c/devices/i2c-X/. From there we can now make it emulate the
> ds1338 device again by doing:
> 
> 
>   echo ds1338 0x20 > /sys/bus/i2c/devices/i2c-0/new_device
> 
> [ This time we want ds1338's driver to be bound to the device, so it
> should be enabled in the kernel as well. ]
> 
> And we will get /dev/rtc1 device again here in the second level guest.
> Now we can play with the rtc device with help of hwclock utility and we
> can see the following sequence of transfers happening if we try to
> update rtc's time from system time.
> 
> hwclock -w -f /dev/rtc1 (in guest2) ->
>   Reaches i2c-virtio.c (Linux bus driver in guest2) ->
>     transfer over virtio ->
>       Reaches the qemu's vhost-i2c device emulation (running over guest1) ->
>         Reaches the backend daemon vhost-user-i2c started earlier (in guest1) ->
>           ioctl(/dev/i2c-0, I2C_RDWR, ..); (in guest1) ->
>             reaches qemu's hw/rtc/ds1338.c (running over host)
> 
> 
> SMBUS Testing:
> --------------
> 
> I wasn't required to have such a tedious setup for testing out with
> SMBUS devices. I was able to emulate a SMBUS device on my x86 machine
> using i2c-stub driver.
> 
> $ modprobe i2c-stub chip_addr=0x20
> //Boot the arm64 guest now with i2c-virtio driver and then do:
> $ echo al3320a 0x20 > /sys/class/i2c-adapter/i2c-0/new_device
> $ cat /sys/bus/iio/devices/iio:device0/in_illuminance_raw
> 
> That's it.
> 
> I hope I was able to give a clear picture of my test setup here :)
> 
> --
> Viresh
> 
> Viresh Kumar (3):
>   hw/virtio: add boilerplate for vhost-user-i2c device
>   hw/virtio: add vhost-user-i2c-pci boilerplate
>   MAINTAINERS: Add entry for virtio-i2c
> 
>  MAINTAINERS                        |   7 +
>  hw/virtio/Kconfig                  |   5 +
>  hw/virtio/meson.build              |   2 +
>  hw/virtio/vhost-user-i2c-pci.c     |  69 +++++++
>  hw/virtio/vhost-user-i2c.c         | 288 +++++++++++++++++++++++++++++
>  include/hw/virtio/vhost-user-i2c.h |  28 +++
>  6 files changed, 399 insertions(+)
>  create mode 100644 hw/virtio/vhost-user-i2c-pci.c
>  create mode 100644 hw/virtio/vhost-user-i2c.c
>  create mode 100644 include/hw/virtio/vhost-user-i2c.h
> 
> -- 
> 2.31.1.272.g89b43f80a514



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

* Re: [PATCH V2 0/3] virtio: Add vhost-user-i2c device's support
  2021-09-04 19:44 ` [PATCH V2 0/3] virtio: Add vhost-user-i2c device's support Michael S. Tsirkin
@ 2021-09-06  4:37   ` Viresh Kumar
  0 siblings, 0 replies; 6+ messages in thread
From: Viresh Kumar @ 2021-09-06  4:37 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Vincent Guittot, Jie Deng, Bill Mills, qemu-devel, Arnd Bergmann,
	Mike Holmes, Alex Bennée, stratos-dev

On 04-09-21, 15:44, Michael S. Tsirkin wrote:
> So I'm not sure whether it's appropriate to merge this right now.

This is already merged.

> There are several spec change proposals before the virtio TC
> and I did not investigate whether this code reflects the
> spec before or after these changes.

I believe you are talking about the zero-length stuff, right ?

This patchset doesn't depend on that and won't change with or without
those patches. The backend is implemented separately in Rust.

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

> It seems prudent to wait
> until the spec changes are finalized and voted on, in any case.

I will update both the Linux driver and Rust implementation once we
accept the changes for spec.

-- 
viresh


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

end of thread, other threads:[~2021-09-06  4:39 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-09  5:00 [PATCH V2 0/3] virtio: Add vhost-user-i2c device's support Viresh Kumar
2021-07-09  5:00 ` [PATCH V2 1/3] hw/virtio: add boilerplate for vhost-user-i2c device Viresh Kumar
2021-07-09  5:00 ` [PATCH V2 2/3] hw/virtio: add vhost-user-i2c-pci boilerplate Viresh Kumar
2021-07-09  5:00 ` [PATCH V2 3/3] MAINTAINERS: Add entry for virtio-i2c Viresh Kumar
2021-09-04 19:44 ` [PATCH V2 0/3] virtio: Add vhost-user-i2c device's support Michael S. Tsirkin
2021-09-06  4:37   ` Viresh Kumar

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.