@@ -22,6 +22,8 @@
#include "qapi/visitor.h"
#include "sysemu/char.h"
#include "sysemu/iothread.h"
+#include "crypto/crypto.h"
+
static void get_pointer(Object *obj, Visitor *v, Property *prop,
char *(*print)(void *ptr),
@@ -430,3 +432,87 @@ void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
}
nd->instantiated = 1;
}
+
+/* --- cryptodev device --- */
+static void get_cryptodev(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ DeviceState *dev = DEVICE(obj);
+ Property *prop = opaque;
+ CryptoLegacyHWPeers *peers_ptr = qdev_get_prop_ptr(dev, prop);
+ char *p = g_strdup(peers_ptr->ccs[0] ? peers_ptr->ccs[0]->name : "");
+ visit_type_str(v, name, &p, errp);
+ g_free(p);
+}
+
+static void set_cryptodev(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ DeviceState *dev = DEVICE(obj);
+ Property *prop = opaque;
+ CryptoLegacyHWPeers *peers_ptr = qdev_get_prop_ptr(dev, prop);
+ CryptoClientState **ccs = peers_ptr->ccs;
+ CryptoClientState *peers[MAX_CRYPTO_QUEUE_NUM];
+ Error *local_err = NULL;
+ int queues, err = 0, i = 0;
+ char *str;
+
+ if (dev->realized) {
+ qdev_prop_set_after_realize(dev, name, errp);
+ return;
+ }
+
+ visit_type_str(v, name, &str, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
+ queues = qemu_find_crypto_clients_except(str, peers,
+ CRYPTO_CLIENT_OPTIONS_KIND_LEGACY_HW,
+ MAX_CRYPTO_QUEUE_NUM);
+ if (queues == 0) {
+ err = -ENOENT;
+ goto out;
+ }
+
+ if (queues > MAX_CRYPTO_QUEUE_NUM) {
+ error_setg(errp,
+ "queues of backend '%s'(%d) exceeds QEMU limitation(%d)",
+ str, queues, MAX_CRYPTO_QUEUE_NUM);
+ goto out;
+ }
+
+ for (i = 0; i < queues; i++) {
+ if (peers[i] == NULL) {
+ err = -ENOENT;
+ goto out;
+ }
+
+ if (peers[i]->peer) {
+ err = -EEXIST;
+ goto out;
+ }
+
+ if (ccs[i]) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ ccs[i] = peers[i];
+ ccs[i]->queue_index = i;
+ }
+
+ peers_ptr->queues = queues;
+
+out:
+ error_set_from_qdev_prop_error(errp, err, dev, prop, str);
+ g_free(str);
+}
+
+PropertyInfo qdev_prop_cryptodev = {
+ .name = "str",
+ .description = "ID of a cryptodev to use as a backend",
+ .get = get_cryptodev,
+ .set = set_cryptodev,
+};
@@ -6,3 +6,4 @@ common-obj-y += virtio-mmio.o
obj-y += virtio.o virtio-balloon.o
obj-$(CONFIG_LINUX) += vhost.o vhost-backend.o vhost-user.o
obj-$(CONFIG_VIRTIO_PCI) += virtio-crypto-pci.o
+obj-y += virtio-crypto.o
new file mode 100644
@@ -0,0 +1,250 @@
+/*
+ * Virtio crypto Support
+ *
+ * Based on virtio-net.c
+ *
+ * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
+ *
+ * Authors:
+ * Gonglei <arei.gonglei@huawei.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version. See the COPYING file in the
+ * top-level directory.
+ */
+#include "qemu/osdep.h"
+#include "qemu/iov.h"
+#include "hw/qdev.h"
+#include "qapi/error.h"
+#include "qemu/error-report.h"
+
+#include "hw/virtio/virtio.h"
+#include "hw/virtio/virtio-crypto.h"
+#include "hw/virtio/virtio-access.h"
+
+static void virtio_crypto_process(VirtIOCrypto *vcrypto)
+{
+}
+
+static void virtio_crypto_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
+{
+}
+
+static void virtio_crypto_handle_dataq_bh(VirtIODevice *vdev, VirtQueue *vq)
+{
+}
+
+static void virtio_crypto_dataq_bh(void *opaque)
+{
+}
+
+static void virtio_crypto_add_queue(VirtIOCrypto *vcrypto, int index)
+{
+ VirtIODevice *vdev = VIRTIO_DEVICE(vcrypto);
+
+ vcrypto->vqs[index].dataq = virtio_add_queue(vdev, 1024,
+ virtio_crypto_handle_dataq_bh);
+ vcrypto->vqs[index].tx_bh = qemu_bh_new(virtio_crypto_dataq_bh,
+ &vcrypto->vqs[index]);
+
+ vcrypto->vqs[index].tx_waiting = 0;
+ vcrypto->vqs[index].vcrypto = vcrypto;
+}
+
+static void virtio_crypto_del_queue(VirtIOCrypto *vcrypto, int index)
+{
+ VirtIODevice *vdev = VIRTIO_DEVICE(vcrypto);
+ VirtIOCryptoQueue *q = &vcrypto->vqs[index];
+
+ virtio_del_queue(vdev, index);
+ qemu_bh_delete(q->tx_bh);
+}
+
+static uint64_t virtio_crypto_get_features(VirtIODevice *vdev,
+ uint64_t features,
+ Error **errp)
+{
+ return features;
+}
+
+static void virtio_crypto_set_features(VirtIODevice *vdev, uint64_t features)
+{
+
+}
+
+static void virtio_crypto_save(QEMUFile *f, void *opaque)
+{
+ VirtIODevice *vdev = opaque;
+
+ virtio_save(vdev, f);
+}
+
+static int virtio_crypto_load(QEMUFile *f, void *opaque, int version_id)
+{
+ VirtIOCrypto *vcrypto = opaque;
+ int ret;
+
+ if (version_id != 1) {
+ return -EINVAL;
+ }
+ ret = virtio_load(VIRTIO_DEVICE(vcrypto), f, version_id);
+ if (ret != 0) {
+ return ret;
+ }
+
+ /* We may have an element ready but couldn't process it due to a quota
+ * limit. Make sure to try again after live migration when the quota may
+ * have been reset.
+ */
+ virtio_crypto_process(vcrypto);
+
+ return 0;
+}
+
+static void virtio_crypto_set_status(VirtIODevice *vdev, uint8_t status)
+{
+}
+
+static void virtio_crypto_reset(VirtIODevice *vdev)
+{
+ /*
+ * This should cancel pending requests, but can't do nicely until there
+ * are per-device request lists.
+ */
+}
+
+static void virtio_crypto_set_hw_status(CryptoClientState *cc)
+{
+ VirtIOCrypto *vcrypto = qemu_get_crypto_legacy_hw_opaque(cc);
+ VirtIODevice *vdev = VIRTIO_DEVICE(vcrypto);
+ uint16_t old_status = vcrypto->status;
+
+ if (!cc->ready) {
+ vcrypto->status &= ~VIRTIO_CRYPTO_S_HW_READY;
+ } else {
+ vcrypto->status |= VIRTIO_CRYPTO_S_HW_READY;
+ }
+ if (vcrypto->status != old_status) {
+ virtio_notify_config(vdev);
+ }
+
+ virtio_crypto_set_status(vdev, vdev->status);
+}
+
+static CryptoClientInfo crypto_virtio_info = {
+ .type = CRYPTO_CLIENT_OPTIONS_KIND_LEGACY_HW,
+ .size = sizeof(CryptoLegacyHWState),
+ .hw_status_changed = virtio_crypto_set_hw_status,
+};
+
+static void virtio_crypto_device_realize(DeviceState *dev, Error **errp)
+{
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(dev);
+ int i;
+
+ vcrypto->max_queues = MAX(vcrypto->legacy_conf.peers.queues, 1);
+ if (vcrypto->max_queues + 1 > VIRTIO_QUEUE_MAX) {
+ error_setg(errp, "Invalid number of queues (= %" PRIu16 "), "
+ "must be a postive integer less than %d.",
+ vcrypto->max_queues, VIRTIO_QUEUE_MAX - 1);
+ return;
+ }
+
+ virtio_init(vdev, "virtio-crypto", VIRTIO_ID_CRYPTO, vcrypto->config_size);
+ vcrypto->vqs = g_new0(VirtIOCryptoQueue, vcrypto->max_queues);
+ vcrypto->curr_queues = 1;
+
+ for (i = 0; i < vcrypto->max_queues; i++) {
+ virtio_crypto_add_queue(vcrypto, i);
+ }
+
+ vcrypto->ctrl_vq = virtio_add_queue(vdev, 64, virtio_crypto_handle_ctrl);
+ vcrypto->tx_burst = vcrypto->conf.txburst;
+ vcrypto->crypto = qemu_new_crypto_legacy_hw(&crypto_virtio_info,
+ &vcrypto->legacy_conf,
+ object_get_typename(OBJECT(dev)),
+ dev->id, vcrypto);
+ vcrypto->status = VIRTIO_CRYPTO_S_HW_READY;
+ register_savevm(dev, "virtio-crypto", -1, 1, virtio_crypto_save,
+ virtio_crypto_load, vcrypto);
+}
+
+static void virtio_crypto_device_unrealize(DeviceState *dev, Error **errp)
+{
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(dev);
+ int i, max_queues;
+
+ unregister_savevm(dev, "virtio-crypto", vcrypto);
+
+ max_queues = vcrypto->multiqueue ? vcrypto->max_queues : 1;
+ for (i = 0; i < max_queues; i++) {
+ virtio_crypto_del_queue(vcrypto, i);
+ }
+ g_free(vcrypto->vqs);
+ qemu_del_crypto_legacy_hw(vcrypto->crypto);
+
+ virtio_cleanup(vdev);
+}
+
+static Property virtio_crypto_properties[] = {
+ DEFINE_PROP_CRYPTODEV("cryptodev", VirtIOCrypto, legacy_conf.peers),
+ DEFINE_PROP_INT32("x-txburst", VirtIOCrypto, conf.txburst,
+ VIRTIO_CRYPTO_TX_BURST),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_crypto_get_config(VirtIODevice *vdev, uint8_t *config)
+{
+
+}
+
+static void virtio_crypto_set_config(VirtIODevice *vdev, const uint8_t *config)
+{
+
+}
+
+static void virtio_crypto_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
+
+ dc->props = virtio_crypto_properties;
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+ vdc->realize = virtio_crypto_device_realize;
+ vdc->unrealize = virtio_crypto_device_unrealize;
+ vdc->get_config = virtio_crypto_get_config;
+ vdc->set_config = virtio_crypto_set_config;
+ vdc->get_features = virtio_crypto_get_features;
+ vdc->set_features = virtio_crypto_set_features;
+ vdc->set_status = virtio_crypto_set_status;
+ vdc->reset = virtio_crypto_reset;
+}
+
+static void virtio_crypto_instance_init(Object *obj)
+{
+ VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(obj);
+
+ /*
+ * The default config_size is sizeof(struct virtio_crypto_config).
+ * Can be overriden with virtio_crypto_set_config_size.
+ */
+ vcrypto->config_size = sizeof(struct virtio_crypto_config);
+}
+
+
+static const TypeInfo virtio_crypto_info = {
+ .name = TYPE_VIRTIO_CRYPTO,
+ .parent = TYPE_VIRTIO_DEVICE,
+ .instance_size = sizeof(VirtIOCrypto),
+ .instance_init = virtio_crypto_instance_init,
+ .class_init = virtio_crypto_class_init,
+};
+
+static void virtio_register_types(void)
+{
+ type_register_static(&virtio_crypto_info);
+}
+
+type_init(virtio_register_types)
@@ -30,6 +30,7 @@ extern PropertyInfo qdev_prop_pci_devfn;
extern PropertyInfo qdev_prop_blocksize;
extern PropertyInfo qdev_prop_pci_host_devaddr;
extern PropertyInfo qdev_prop_arraylen;
+extern PropertyInfo qdev_prop_cryptodev;
#define DEFINE_PROP(_name, _state, _field, _prop, _type) { \
.name = (_name), \
@@ -171,6 +172,8 @@ extern PropertyInfo qdev_prop_arraylen;
DEFINE_PROP_DEFAULT(_n, _s, _f, 0, qdev_prop_blocksize, uint16_t)
#define DEFINE_PROP_PCI_HOST_DEVADDR(_n, _s, _f) \
DEFINE_PROP(_n, _s, _f, qdev_prop_pci_host_devaddr, PCIHostDeviceAddress)
+#define DEFINE_PROP_CRYPTODEV(_n, _s, _f) \
+ DEFINE_PROP(_n, _s, _f, qdev_prop_cryptodev, CryptoLegacyHWPeers)
#define DEFINE_PROP_END_OF_LIST() \
{}
Introduce the virtio crypto realization modle, I'll finish the core code in the following patches. The thoughts came from virtio net realization. Signed-off-by: Gonglei <arei.gonglei@huawei.com> --- hw/core/qdev-properties-system.c | 86 ++++++++++++++ hw/virtio/Makefile.objs | 1 + hw/virtio/virtio-crypto.c | 250 +++++++++++++++++++++++++++++++++++++++ include/hw/qdev-properties.h | 3 + 4 files changed, 340 insertions(+) create mode 100644 hw/virtio/virtio-crypto.c