diff mbox

[RFC,v2,4/6] hw/misc: sdm virtio device

Message ID 1458292385-13802-5-git-send-email-b.reynal@virtualopensystems.com
State New
Headers show

Commit Message

Baptiste Reynal March 18, 2016, 9:13 a.m. UTC
This is the virtio implementation for an SDM device.

Parameters are:
comm=[sdm_communication_id] specifies the communication channel
master=[true/false] - configure the SDM device as master or slave
num_slaves=[slave_number] - if master is true, specifies the number
of slaves
len-signals=[signals_number] - specifies the number of signals
signals[x]=[signal_id] - add a signal to the device, with the ID x

Signed-off-by: Christian Pinto <c.pinto@virtualopensystems.com>
Signed-off-by: Baptiste Reynal <b.reynal@virtualopensystems.com>
---
 hw/virtio/Makefile.objs          |   1 +
 hw/virtio/virtio-sdm.c           | 262 +++++++++++++++++++++++++++++++++++++++
 include/hw/virtio/virtio-sdm.h   |  60 +++++++++
 linux-headers/linux/virtio_sdm.h |  52 ++++++++
 4 files changed, 375 insertions(+)
 create mode 100644 hw/virtio/virtio-sdm.c
 create mode 100644 include/hw/virtio/virtio-sdm.h
 create mode 100644 linux-headers/linux/virtio_sdm.h

Comments

Stefan Hajnoczi March 31, 2016, 9:12 a.m. UTC | #1
On Fri, Mar 18, 2016 at 10:13:03AM +0100, Baptiste Reynal wrote:
> This is the virtio implementation for an SDM device.
> 
> Parameters are:
> comm=[sdm_communication_id] specifies the communication channel
> master=[true/false] - configure the SDM device as master or slave
> num_slaves=[slave_number] - if master is true, specifies the number
> of slaves
> len-signals=[signals_number] - specifies the number of signals
> signals[x]=[signal_id] - add a signal to the device, with the ID x
> 
> Signed-off-by: Christian Pinto <c.pinto@virtualopensystems.com>
> Signed-off-by: Baptiste Reynal <b.reynal@virtualopensystems.com>
> ---
>  hw/virtio/Makefile.objs          |   1 +
>  hw/virtio/virtio-sdm.c           | 262 +++++++++++++++++++++++++++++++++++++++
>  include/hw/virtio/virtio-sdm.h   |  60 +++++++++
>  linux-headers/linux/virtio_sdm.h |  52 ++++++++
>  4 files changed, 375 insertions(+)
>  create mode 100644 hw/virtio/virtio-sdm.c
>  create mode 100644 include/hw/virtio/virtio-sdm.h
>  create mode 100644 linux-headers/linux/virtio_sdm.h

Have you posted a draft specification for this device to the VIRTIO
Technical Committee?
https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=virtio

Normally the spec should be accepted into VIRTIO before patches can be
merged.

Stefan
Baptiste Reynal April 5, 2016, 12:54 p.m. UTC | #2
On Thu, Mar 31, 2016 at 11:12 AM, Stefan Hajnoczi <stefanha@gmail.com> wrote:
> On Fri, Mar 18, 2016 at 10:13:03AM +0100, Baptiste Reynal wrote:
>> This is the virtio implementation for an SDM device.
>>
>> Parameters are:
>> comm=[sdm_communication_id] specifies the communication channel
>> master=[true/false] - configure the SDM device as master or slave
>> num_slaves=[slave_number] - if master is true, specifies the number
>> of slaves
>> len-signals=[signals_number] - specifies the number of signals
>> signals[x]=[signal_id] - add a signal to the device, with the ID x
>>
>> Signed-off-by: Christian Pinto <c.pinto@virtualopensystems.com>
>> Signed-off-by: Baptiste Reynal <b.reynal@virtualopensystems.com>
>> ---
>>  hw/virtio/Makefile.objs          |   1 +
>>  hw/virtio/virtio-sdm.c           | 262 +++++++++++++++++++++++++++++++++++++++
>>  include/hw/virtio/virtio-sdm.h   |  60 +++++++++
>>  linux-headers/linux/virtio_sdm.h |  52 ++++++++
>>  4 files changed, 375 insertions(+)
>>  create mode 100644 hw/virtio/virtio-sdm.c
>>  create mode 100644 include/hw/virtio/virtio-sdm.h
>>  create mode 100644 linux-headers/linux/virtio_sdm.h
>
> Have you posted a draft specification for this device to the VIRTIO
> Technical Committee?
> https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=virtio
>
> Normally the spec should be accepted into VIRTIO before patches can be
> merged.
Thanks for the comment, I wasn't aware of such process.
I'll wait for some comments on the SDM in general, then I'll send a
draft spec to virtio.
Maybe this patchs should be dropped and reintroduced in a future patch series ?
>
> Stefan
Stefan Hajnoczi April 6, 2016, 8:55 a.m. UTC | #3
On Tue, Apr 05, 2016 at 02:54:56PM +0200, Baptiste Reynal wrote:
> On Thu, Mar 31, 2016 at 11:12 AM, Stefan Hajnoczi <stefanha@gmail.com> wrote:
> > On Fri, Mar 18, 2016 at 10:13:03AM +0100, Baptiste Reynal wrote:
> >> This is the virtio implementation for an SDM device.
> >>
> >> Parameters are:
> >> comm=[sdm_communication_id] specifies the communication channel
> >> master=[true/false] - configure the SDM device as master or slave
> >> num_slaves=[slave_number] - if master is true, specifies the number
> >> of slaves
> >> len-signals=[signals_number] - specifies the number of signals
> >> signals[x]=[signal_id] - add a signal to the device, with the ID x
> >>
> >> Signed-off-by: Christian Pinto <c.pinto@virtualopensystems.com>
> >> Signed-off-by: Baptiste Reynal <b.reynal@virtualopensystems.com>
> >> ---
> >>  hw/virtio/Makefile.objs          |   1 +
> >>  hw/virtio/virtio-sdm.c           | 262 +++++++++++++++++++++++++++++++++++++++
> >>  include/hw/virtio/virtio-sdm.h   |  60 +++++++++
> >>  linux-headers/linux/virtio_sdm.h |  52 ++++++++
> >>  4 files changed, 375 insertions(+)
> >>  create mode 100644 hw/virtio/virtio-sdm.c
> >>  create mode 100644 include/hw/virtio/virtio-sdm.h
> >>  create mode 100644 linux-headers/linux/virtio_sdm.h
> >
> > Have you posted a draft specification for this device to the VIRTIO
> > Technical Committee?
> > https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=virtio
> >
> > Normally the spec should be accepted into VIRTIO before patches can be
> > merged.
> Thanks for the comment, I wasn't aware of such process.
> I'll wait for some comments on the SDM in general, then I'll send a
> draft spec to virtio.
> Maybe this patchs should be dropped and reintroduced in a future patch series ?

These things tend to take time so I suggest doing it in parallel:
publish your QEMU patches while also trying to get your virtio spec
change merged.
diff mbox

Patch

diff --git a/hw/virtio/Makefile.objs b/hw/virtio/Makefile.objs
index 19b224a..7e44bc4 100644
--- a/hw/virtio/Makefile.objs
+++ b/hw/virtio/Makefile.objs
@@ -2,6 +2,7 @@  common-obj-y += virtio-rng.o
 common-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
 common-obj-y += virtio-bus.o
 common-obj-y += virtio-mmio.o
+obj-$(CONFIG_SDM) += virtio-sdm.o
 obj-$(CONFIG_VIRTIO) += dataplane/
 
 obj-y += virtio.o virtio-balloon.o 
diff --git a/hw/virtio/virtio-sdm.c b/hw/virtio/virtio-sdm.c
new file mode 100644
index 0000000..66986c7
--- /dev/null
+++ b/hw/virtio/virtio-sdm.c
@@ -0,0 +1,262 @@ 
+/*
+ * Copyright (C) 2016 - Virtual Open Systems
+ * Authors: Christian Pinto <c.pinto@virtualopensystems.com>
+ *          Baptiste Reynal <b.reynal@virtualopensystems.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/virtio_sdm.h>
+
+#include "qemu/iov.h"
+#include "qemu/error-report.h"
+#include "hw/virtio/virtio.h"
+#include "hw/virtio/virtio-sdm.h"
+
+typedef void (*cmd_handler)(VirtIOSdm *sdm, union sdm_cmd_params);
+/**
+ * Command handler for signal type commands.
+ * Invoked when the command is received from the guest
+ */
+static void handler_signal(VirtIOSdm *sdm, union sdm_cmd_params params)
+{
+    SDMSignalData signal;
+    DEBUG_PRINT("handler_signal: SIGNAL %d, SLAVE_ID %d\n", params.sig.type,
+            params.sig.slave_id);
+
+    signal.type = params.sig.type;
+    signal.slave = params.sig.slave_id;
+    memcpy(&signal.payload, &params.sig.payload, 2 * sizeof(uint32_t));
+
+    sdm_communication_signal(sdm->sdmc, SDM_DEVICE(sdm),  &signal);
+}
+
+static cmd_handler sdm_cmd_handlers[] = {
+    [SDM_SIGNAL_CMD]    = handler_signal,
+};
+
+/**
+ * Send a command to the guest virtio-driver
+ */
+static void send_cmd_to_guest(VirtIOSdm *sdm,
+        struct sdm_cmd cmd)
+{
+    VirtQueueElement elem;
+    VirtIODevice *vdev = VIRTIO_DEVICE(sdm);
+
+    if (!virtqueue_pop(sdm->hg_vq, &elem)) {
+        return;
+    }
+
+    if (iov_from_buf(elem.in_sg, elem.in_num, 0, &cmd, sizeof(cmd))) {
+        virtqueue_push(sdm->hg_vq, &elem, sizeof(cmd));
+        virtio_notify(vdev, sdm->hg_vq);
+        DEBUG_PRINT("Sending command %d of type %d\n",
+                cmd.cmd, cmd.params.sig.type);
+    } else {
+        error_report("virtio-idm - Failed to issue command id 0x%x\n", cmd.cmd);
+    }
+}
+
+/**
+ * guest -> host virtqueue handler.
+ * Calls the handler assoociated to the command received over the virtqueue
+ */
+static void handle_guest_host_queue(VirtIODevice *vdev, VirtQueue *vq)
+{
+    VirtQueueElement elem;
+    struct sdm_cmd cmd;
+
+    if (!virtqueue_pop(vq, &elem)) {
+        return;
+    }
+
+    if (!iov_to_buf(elem.out_sg, elem.out_num, 0, &cmd, sizeof(cmd))) {
+        return;
+    }
+
+    DEBUG_PRINT("Command received 0x%x\n", cmd.cmd);
+
+    if (cmd.cmd >= ARRAY_SIZE(sdm_cmd_handlers) ||
+            !sdm_cmd_handlers[cmd.params.sig.type]) {
+        error_report("virtio-idm - unrecognized command %x\n", cmd.cmd);
+        return;
+    }
+
+    sdm_cmd_handlers[cmd.params.sig.type](VIRTIO_SDM(vdev), cmd.params);
+}
+
+/**
+ * Guest sends commands over this virtqueue only to add an empty
+ * buffer to be later used by the host.
+ */
+static void handle_host_guest_queue(VirtIODevice *vdev, VirtQueue *vq)
+{
+    VirtIOSdm *sdm = VIRTIO_SDM(vdev);
+
+    sdm->busy = false;
+}
+
+static uint64_t get_features(VirtIODevice *vdev, uint64_t requested_features,
+        Error **errp)
+{
+    return requested_features;
+}
+
+static void virtio_sdm_device_realize(DeviceState *dev, Error **errp)
+{
+    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+    VirtIOSdm *sdm = VIRTIO_SDM(dev);
+    int i;
+
+    virtio_init(vdev, "virtio-sdm", VIRTIO_ID_SDM, 0);
+
+    sdm->hg_vq = virtio_add_queue(vdev, 128, handle_host_guest_queue);
+    sdm->gh_vq = virtio_add_queue(vdev, 128, handle_guest_host_queue);
+
+    sdm->signals = calloc(sdm->num_signals, sizeof(SDMSignal));
+    for (i = 0; i < sdm->num_signals; i++) {
+        sdm->signals[i] = (SDMSignal *) object_resolve_path_type(
+                sdm->signals_name[i],
+                TYPE_SDM_SIGNAL, false);
+        if (!sdm->signals[i]) {
+            error_report("virtio-sdm: Cannot find signal %s",
+                    sdm->signals_name[i]);;
+        }
+    }
+
+    sdm_communication_connect(sdm->sdmc, SDM_DEVICE(sdm));
+}
+
+static void virtio_sdm_device_unrealize(DeviceState *dev, Error **errp)
+{
+    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+    virtio_cleanup(vdev);
+}
+
+static int virtio_sdm_accept(SDMDevice *sdm)
+{
+    VirtIOSdm *sdmv = VIRTIO_SDM(sdm);
+
+    if (sdmv->last_slave >= sdmv->num_slaves) {
+        return -1;
+    }
+
+    return ++sdmv->last_slave;
+}
+
+static int virtio_sdm_notify(SDMDevice *sdm, SDMSignalData *signal)
+{
+    VirtIOSdm *sdmv = VIRTIO_SDM(sdm);
+    SDMSignal *hw_signal ;
+    struct sdm_cmd cmd;
+
+    if (signal->type > sdmv->num_signals) {
+        return 0;
+    }
+
+    hw_signal = sdmv->signals[signal->type];
+
+    if (!hw_signal) {
+        return 0;
+    }
+
+    sdm_signal_hw_ops(hw_signal, signal);
+
+    if (!sdm_signal_hw_only(hw_signal)) {
+        if (sdmv->busy) {
+            return -1;
+        }
+
+        sdmv->busy = true;
+
+        cmd.cmd = SDM_SIGNAL_CMD;
+        cmd.params.sig.type = signal->type;
+        cmd.params.sig.slave_id = signal->slave;
+        memcpy(cmd.params.sig.payload, signal->payload, 2 * sizeof(uint32_t));
+
+        printf("Forward %d %d\n", cmd.params.sig.type, cmd.params.sig.slave_id);
+        send_cmd_to_guest(sdmv, cmd);
+    }
+
+    return 0;
+}
+
+static int virtio_sdm_get_num_slaves(SDMDevice *sdm)
+{
+    VirtIOSdm *sdmv = VIRTIO_SDM(sdm);
+
+    return sdmv->num_slaves;
+}
+
+static bool virtio_sdm_is_master(SDMDevice *sdm)
+{
+    VirtIOSdm *sdmv = VIRTIO_SDM(sdm);
+
+    return sdmv->master;
+}
+
+static Property sdm_virtio_properties[] = {
+    DEFINE_PROP_UINT32("num-slaves", VirtIOSdm, num_slaves, 1),
+    DEFINE_PROP_BOOL("master", VirtIOSdm, master, false),
+    DEFINE_PROP_ARRAY("signals", VirtIOSdm, num_signals, signals_name,
+            qdev_prop_string, char *),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_sdm_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
+    SDMDeviceClass *sdmc = SDM_DEVICE_CLASS(klass);
+
+    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+    vdc->realize = virtio_sdm_device_realize;
+    vdc->unrealize = virtio_sdm_device_unrealize;
+    vdc->get_features = get_features;
+
+    sdmc->accept = virtio_sdm_accept;
+    sdmc->notify = virtio_sdm_notify;
+    sdmc->get_num_slaves = virtio_sdm_get_num_slaves;
+    sdmc->is_master = virtio_sdm_is_master;
+
+    dc->props = sdm_virtio_properties;
+}
+
+static void virtio_sdm_init(Object *obj)
+{
+    VirtIOSdm *sdm = VIRTIO_SDM(obj);
+
+    object_property_add_link(obj, "comm", TYPE_SDM_COMMUNICATION,
+            (Object **)&sdm->sdmc,
+            qdev_prop_allow_set_link_before_realize,
+            OBJ_PROP_LINK_UNREF_ON_RELEASE, &error_abort);
+
+    sdm->busy = false;
+}
+
+static const TypeInfo virtio_sdm_info = {
+    .name = TYPE_VIRTIO_SDM,
+    .parent = TYPE_VIRTIO_DEVICE,
+    .instance_size = sizeof(VirtIOSdm),
+    .class_init = virtio_sdm_class_init,
+    .instance_init = virtio_sdm_init,
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_SDM_DEVICE },
+        { }
+    }
+};
+
+static void virtio_register_types(void)
+{
+    type_register_static(&virtio_sdm_info);
+}
+
+type_init(virtio_register_types)
diff --git a/include/hw/virtio/virtio-sdm.h b/include/hw/virtio/virtio-sdm.h
new file mode 100644
index 0000000..601e083
--- /dev/null
+++ b/include/hw/virtio/virtio-sdm.h
@@ -0,0 +1,60 @@ 
+/*
+ * Copyright (C) 2016 - Virtual Open Systems
+ * Author: Christian Pinto <c.pinto@virtualopensystems.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _QEMU_VIRTIO_SDM_H
+#define _QEMU_VIRTIO_SDM_H
+
+#include "hw/virtio/virtio.h"
+#include "hw/misc/sdm-device.h"
+#include "hw/misc/sdm-communication.h"
+
+#define DEBUG
+#ifdef DEBUG
+#define DEBUG_PRINT(fmt, ...) \
+    do {printf("virtio-idm - " fmt, ## __VA_ARGS__); } while (0)
+#else
+#define DEBUG_PRINT(fmt, ...)
+#endif
+
+#define TYPE_VIRTIO_SDM "virtio-sdm-device"
+#define VIRTIO_SDM(obj) \
+        OBJECT_CHECK(VirtIOSdm, (obj), TYPE_VIRTIO_SDM)
+#define VIRTIO_SDM_GET_PARENT_CLASS(obj) \
+        OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_SDM)
+
+/* The Virtio ID for the virtio SDM device */
+#define VIRTIO_ID_SDM 65000
+
+typedef struct VirtIOSdm VirtIOSdm;
+
+struct VirtIOSdm {
+    VirtIODevice parent_obj;
+
+    SDMCommunication *sdmc;
+
+    bool master;
+    bool busy;
+
+    uint32_t num_slaves;
+    uint32_t last_slave;
+
+    uint32_t num_signals;
+    char **signals_name;
+    SDMSignal **signals;
+
+    VirtQueue *hg_vq;
+    VirtQueue *gh_vq;
+};
+
+#endif /*_QEMU_VIRTIO_SDM_H*/
diff --git a/linux-headers/linux/virtio_sdm.h b/linux-headers/linux/virtio_sdm.h
new file mode 100644
index 0000000..db786b0
--- /dev/null
+++ b/linux-headers/linux/virtio_sdm.h
@@ -0,0 +1,52 @@ 
+/*
+ * Copyright (C) 2016 - Virtual Open Systems
+ * Author: Christian Pinto <c.pinto@virtualopensystems.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _LINUX_VIRTIO_SDM_H
+#define _LINUX_VIRTIO_SDM_H
+#include <linux/virtio_ids.h>
+#include <linux/virtio_config.h>
+#include <linux/types.h>
+/* the commands the host can issue to a virtio-sdm guest */
+enum sdm_cmd_type {
+    SDM_SIGNAL_CMD,
+};
+
+enum sdm_signal_type {
+    SDM_IRQ,
+    SDM_BOOT,
+};
+
+union sdm_cmd_params {
+    /**
+    * This command is used to communicate signals between
+    * guest and host.
+    * The slave_id to which signal triggering/reception is
+    * associated, the type and signal and 2 32-bits registers
+    * for payload are transmitted.
+    */
+    struct {
+        __u16 type;
+        __u16 slave_id;
+
+        __u32 payload[2];
+    } sig;
+        __u32 padding[4];
+};
+
+struct sdm_cmd {
+    enum sdm_cmd_type       cmd;
+    union sdm_cmd_params    params;
+};
+
+#endif /* _LINUX_VIRTIO_SDM_H */