1d0ee7a13SGonglei /* 2d0ee7a13SGonglei * QEMU Crypto Device Implementation 3d0ee7a13SGonglei * 4d0ee7a13SGonglei * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD. 5d0ee7a13SGonglei * 6d0ee7a13SGonglei * Authors: 7d0ee7a13SGonglei * Gonglei <arei.gonglei@huawei.com> 8d0ee7a13SGonglei * 9d0ee7a13SGonglei * This library is free software; you can redistribute it and/or 10d0ee7a13SGonglei * modify it under the terms of the GNU Lesser General Public 11d0ee7a13SGonglei * License as published by the Free Software Foundation; either 120dda001bSChetan Pant * version 2.1 of the License, or (at your option) any later version. 13d0ee7a13SGonglei * 14d0ee7a13SGonglei * This library is distributed in the hope that it will be useful, 15d0ee7a13SGonglei * but WITHOUT ANY WARRANTY; without even the implied warranty of 16d0ee7a13SGonglei * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17d0ee7a13SGonglei * Lesser General Public License for more details. 18d0ee7a13SGonglei * 19d0ee7a13SGonglei * You should have received a copy of the GNU Lesser General Public 20d0ee7a13SGonglei * License along with this library; if not, see <http://www.gnu.org/licenses/>. 21d0ee7a13SGonglei * 22d0ee7a13SGonglei */ 23d0ee7a13SGonglei 24d0ee7a13SGonglei #include "qemu/osdep.h" 25d0ee7a13SGonglei #include "sysemu/cryptodev.h" 26f2b90109Szhenwei pi #include "sysemu/stats.h" 27d0ee7a13SGonglei #include "qapi/error.h" 285dcb0198Szhenwei pi #include "qapi/qapi-commands-cryptodev.h" 29f2b90109Szhenwei pi #include "qapi/qapi-types-stats.h" 30d0ee7a13SGonglei #include "qapi/visitor.h" 31d0ee7a13SGonglei #include "qemu/config-file.h" 322fda101dSLei He #include "qemu/error-report.h" 332580b452Szhenwei pi #include "qemu/main-loop.h" 34d0ee7a13SGonglei #include "qom/object_interfaces.h" 35d6634ac0SGonglei #include "hw/virtio/virtio-crypto.h" 36d6634ac0SGonglei 37f2b90109Szhenwei pi #define SYM_ENCRYPT_OPS_STR "sym-encrypt-ops" 38f2b90109Szhenwei pi #define SYM_DECRYPT_OPS_STR "sym-decrypt-ops" 39f2b90109Szhenwei pi #define SYM_ENCRYPT_BYTES_STR "sym-encrypt-bytes" 40f2b90109Szhenwei pi #define SYM_DECRYPT_BYTES_STR "sym-decrypt-bytes" 41f2b90109Szhenwei pi 42f2b90109Szhenwei pi #define ASYM_ENCRYPT_OPS_STR "asym-encrypt-ops" 43f2b90109Szhenwei pi #define ASYM_DECRYPT_OPS_STR "asym-decrypt-ops" 44f2b90109Szhenwei pi #define ASYM_SIGN_OPS_STR "asym-sign-ops" 45f2b90109Szhenwei pi #define ASYM_VERIFY_OPS_STR "asym-verify-ops" 46f2b90109Szhenwei pi #define ASYM_ENCRYPT_BYTES_STR "asym-encrypt-bytes" 47f2b90109Szhenwei pi #define ASYM_DECRYPT_BYTES_STR "asym-decrypt-bytes" 48f2b90109Szhenwei pi #define ASYM_SIGN_BYTES_STR "asym-sign-bytes" 49f2b90109Szhenwei pi #define ASYM_VERIFY_BYTES_STR "asym-verify-bytes" 50f2b90109Szhenwei pi 51f2b90109Szhenwei pi typedef struct StatsArgs { 52f2b90109Szhenwei pi union StatsResultsType { 53f2b90109Szhenwei pi StatsResultList **stats; 54f2b90109Szhenwei pi StatsSchemaList **schema; 55f2b90109Szhenwei pi } result; 56f2b90109Szhenwei pi strList *names; 57f2b90109Szhenwei pi Error **errp; 58f2b90109Szhenwei pi } StatsArgs; 59d0ee7a13SGonglei 60d0ee7a13SGonglei static QTAILQ_HEAD(, CryptoDevBackendClient) crypto_clients; 61d0ee7a13SGonglei 625dcb0198Szhenwei pi static int qmp_query_cryptodev_foreach(Object *obj, void *data) 635dcb0198Szhenwei pi { 645dcb0198Szhenwei pi CryptoDevBackend *backend; 655dcb0198Szhenwei pi QCryptodevInfoList **infolist = data; 665dcb0198Szhenwei pi uint32_t services, i; 675dcb0198Szhenwei pi 685dcb0198Szhenwei pi if (!object_dynamic_cast(obj, TYPE_CRYPTODEV_BACKEND)) { 695dcb0198Szhenwei pi return 0; 705dcb0198Szhenwei pi } 715dcb0198Szhenwei pi 725dcb0198Szhenwei pi QCryptodevInfo *info = g_new0(QCryptodevInfo, 1); 735dcb0198Szhenwei pi info->id = g_strdup(object_get_canonical_path_component(obj)); 745dcb0198Szhenwei pi 755dcb0198Szhenwei pi backend = CRYPTODEV_BACKEND(obj); 765dcb0198Szhenwei pi services = backend->conf.crypto_services; 77*d0917d79SMarkus Armbruster for (i = 0; i < QCRYPTODEV_BACKEND_SERVICE_TYPE__MAX; i++) { 785dcb0198Szhenwei pi if (services & (1 << i)) { 795dcb0198Szhenwei pi QAPI_LIST_PREPEND(info->service, i); 805dcb0198Szhenwei pi } 815dcb0198Szhenwei pi } 825dcb0198Szhenwei pi 835dcb0198Szhenwei pi for (i = 0; i < backend->conf.peers.queues; i++) { 845dcb0198Szhenwei pi CryptoDevBackendClient *cc = backend->conf.peers.ccs[i]; 855dcb0198Szhenwei pi QCryptodevBackendClient *client = g_new0(QCryptodevBackendClient, 1); 865dcb0198Szhenwei pi 875dcb0198Szhenwei pi client->queue = cc->queue_index; 885dcb0198Szhenwei pi client->type = cc->type; 895dcb0198Szhenwei pi QAPI_LIST_PREPEND(info->client, client); 905dcb0198Szhenwei pi } 915dcb0198Szhenwei pi 925dcb0198Szhenwei pi QAPI_LIST_PREPEND(*infolist, info); 935dcb0198Szhenwei pi 945dcb0198Szhenwei pi return 0; 955dcb0198Szhenwei pi } 965dcb0198Szhenwei pi 975dcb0198Szhenwei pi QCryptodevInfoList *qmp_query_cryptodev(Error **errp) 985dcb0198Szhenwei pi { 995dcb0198Szhenwei pi QCryptodevInfoList *list = NULL; 1005dcb0198Szhenwei pi Object *objs = container_get(object_get_root(), "/objects"); 1015dcb0198Szhenwei pi 1025dcb0198Szhenwei pi object_child_foreach(objs, qmp_query_cryptodev_foreach, &list); 1035dcb0198Szhenwei pi 1045dcb0198Szhenwei pi return list; 1055dcb0198Szhenwei pi } 106d0ee7a13SGonglei 1073f478371Szhenwei pi CryptoDevBackendClient *cryptodev_backend_new_client(void) 108d0ee7a13SGonglei { 109d0ee7a13SGonglei CryptoDevBackendClient *cc; 110d0ee7a13SGonglei 111b21e2380SMarkus Armbruster cc = g_new0(CryptoDevBackendClient, 1); 112d0ee7a13SGonglei QTAILQ_INSERT_TAIL(&crypto_clients, cc, next); 113d0ee7a13SGonglei 114d0ee7a13SGonglei return cc; 115d0ee7a13SGonglei } 116d0ee7a13SGonglei 117d0ee7a13SGonglei void cryptodev_backend_free_client( 118d0ee7a13SGonglei CryptoDevBackendClient *cc) 119d0ee7a13SGonglei { 120d0ee7a13SGonglei QTAILQ_REMOVE(&crypto_clients, cc, next); 121d0ee7a13SGonglei g_free(cc->info_str); 122d0ee7a13SGonglei g_free(cc); 123d0ee7a13SGonglei } 124d0ee7a13SGonglei 125d0ee7a13SGonglei void cryptodev_backend_cleanup( 126d0ee7a13SGonglei CryptoDevBackend *backend, 127d0ee7a13SGonglei Error **errp) 128d0ee7a13SGonglei { 129d0ee7a13SGonglei CryptoDevBackendClass *bc = 130d0ee7a13SGonglei CRYPTODEV_BACKEND_GET_CLASS(backend); 131d0ee7a13SGonglei 132d0ee7a13SGonglei if (bc->cleanup) { 133d0ee7a13SGonglei bc->cleanup(backend, errp); 134d0ee7a13SGonglei } 135e7a775fdSzhenwei pi 136e7a775fdSzhenwei pi g_free(backend->sym_stat); 137e7a775fdSzhenwei pi g_free(backend->asym_stat); 138d0ee7a13SGonglei } 139d0ee7a13SGonglei 1402fda101dSLei He int cryptodev_backend_create_session( 1419e4f86a8SGonglei CryptoDevBackend *backend, 1420e660a6fSzhenwei pi CryptoDevBackendSessionInfo *sess_info, 1432fda101dSLei He uint32_t queue_index, 1442fda101dSLei He CryptoDevCompletionFunc cb, 1452fda101dSLei He void *opaque) 1469e4f86a8SGonglei { 1479e4f86a8SGonglei CryptoDevBackendClass *bc = 1489e4f86a8SGonglei CRYPTODEV_BACKEND_GET_CLASS(backend); 1499e4f86a8SGonglei 1509e4f86a8SGonglei if (bc->create_session) { 1512fda101dSLei He return bc->create_session(backend, sess_info, queue_index, cb, opaque); 1529e4f86a8SGonglei } 1532fda101dSLei He return -VIRTIO_CRYPTO_NOTSUPP; 1549e4f86a8SGonglei } 1559e4f86a8SGonglei 1560e660a6fSzhenwei pi int cryptodev_backend_close_session( 1579e4f86a8SGonglei CryptoDevBackend *backend, 1589e4f86a8SGonglei uint64_t session_id, 1592fda101dSLei He uint32_t queue_index, 1602fda101dSLei He CryptoDevCompletionFunc cb, 1612fda101dSLei He void *opaque) 1629e4f86a8SGonglei { 1639e4f86a8SGonglei CryptoDevBackendClass *bc = 1649e4f86a8SGonglei CRYPTODEV_BACKEND_GET_CLASS(backend); 1659e4f86a8SGonglei 1669e4f86a8SGonglei if (bc->close_session) { 1672fda101dSLei He return bc->close_session(backend, session_id, queue_index, cb, opaque); 1689e4f86a8SGonglei } 1692fda101dSLei He return -VIRTIO_CRYPTO_NOTSUPP; 1709e4f86a8SGonglei } 1719e4f86a8SGonglei 1720e660a6fSzhenwei pi static int cryptodev_backend_operation( 1739e4f86a8SGonglei CryptoDevBackend *backend, 1742cb06927Szhenwei pi CryptoDevBackendOpInfo *op_info) 1759e4f86a8SGonglei { 1769e4f86a8SGonglei CryptoDevBackendClass *bc = 1779e4f86a8SGonglei CRYPTODEV_BACKEND_GET_CLASS(backend); 1789e4f86a8SGonglei 1790e660a6fSzhenwei pi if (bc->do_op) { 1802cb06927Szhenwei pi return bc->do_op(backend, op_info); 1819e4f86a8SGonglei } 1822fda101dSLei He return -VIRTIO_CRYPTO_NOTSUPP; 183d6634ac0SGonglei } 184d6634ac0SGonglei 185e7a775fdSzhenwei pi static int cryptodev_backend_account(CryptoDevBackend *backend, 186e7a775fdSzhenwei pi CryptoDevBackendOpInfo *op_info) 187e7a775fdSzhenwei pi { 188e7a775fdSzhenwei pi enum QCryptodevBackendAlgType algtype = op_info->algtype; 189e7a775fdSzhenwei pi int len; 190e7a775fdSzhenwei pi 191e7a775fdSzhenwei pi if (algtype == QCRYPTODEV_BACKEND_ALG_ASYM) { 192e7a775fdSzhenwei pi CryptoDevBackendAsymOpInfo *asym_op_info = op_info->u.asym_op_info; 193e7a775fdSzhenwei pi len = asym_op_info->src_len; 19415b11a1dSzhenwei pi 19515b11a1dSzhenwei pi if (unlikely(!backend->asym_stat)) { 19615b11a1dSzhenwei pi error_report("cryptodev: Unexpected asym operation"); 19715b11a1dSzhenwei pi return -VIRTIO_CRYPTO_NOTSUPP; 19815b11a1dSzhenwei pi } 199e7a775fdSzhenwei pi switch (op_info->op_code) { 200e7a775fdSzhenwei pi case VIRTIO_CRYPTO_AKCIPHER_ENCRYPT: 201e7a775fdSzhenwei pi CryptodevAsymStatIncEncrypt(backend, len); 202e7a775fdSzhenwei pi break; 203e7a775fdSzhenwei pi case VIRTIO_CRYPTO_AKCIPHER_DECRYPT: 204e7a775fdSzhenwei pi CryptodevAsymStatIncDecrypt(backend, len); 205e7a775fdSzhenwei pi break; 206e7a775fdSzhenwei pi case VIRTIO_CRYPTO_AKCIPHER_SIGN: 207e7a775fdSzhenwei pi CryptodevAsymStatIncSign(backend, len); 208e7a775fdSzhenwei pi break; 209e7a775fdSzhenwei pi case VIRTIO_CRYPTO_AKCIPHER_VERIFY: 210e7a775fdSzhenwei pi CryptodevAsymStatIncVerify(backend, len); 211e7a775fdSzhenwei pi break; 212e7a775fdSzhenwei pi default: 213e7a775fdSzhenwei pi return -VIRTIO_CRYPTO_NOTSUPP; 214e7a775fdSzhenwei pi } 215e7a775fdSzhenwei pi } else if (algtype == QCRYPTODEV_BACKEND_ALG_SYM) { 216e7a775fdSzhenwei pi CryptoDevBackendSymOpInfo *sym_op_info = op_info->u.sym_op_info; 217e7a775fdSzhenwei pi len = sym_op_info->src_len; 21815b11a1dSzhenwei pi 21915b11a1dSzhenwei pi if (unlikely(!backend->sym_stat)) { 22015b11a1dSzhenwei pi error_report("cryptodev: Unexpected sym operation"); 22115b11a1dSzhenwei pi return -VIRTIO_CRYPTO_NOTSUPP; 22215b11a1dSzhenwei pi } 223e7a775fdSzhenwei pi switch (op_info->op_code) { 224e7a775fdSzhenwei pi case VIRTIO_CRYPTO_CIPHER_ENCRYPT: 225e7a775fdSzhenwei pi CryptodevSymStatIncEncrypt(backend, len); 226e7a775fdSzhenwei pi break; 227e7a775fdSzhenwei pi case VIRTIO_CRYPTO_CIPHER_DECRYPT: 228e7a775fdSzhenwei pi CryptodevSymStatIncDecrypt(backend, len); 229e7a775fdSzhenwei pi break; 230e7a775fdSzhenwei pi default: 231e7a775fdSzhenwei pi return -VIRTIO_CRYPTO_NOTSUPP; 232e7a775fdSzhenwei pi } 233e7a775fdSzhenwei pi } else { 234e7a775fdSzhenwei pi error_report("Unsupported cryptodev alg type: %" PRIu32 "", algtype); 235e7a775fdSzhenwei pi return -VIRTIO_CRYPTO_NOTSUPP; 236e7a775fdSzhenwei pi } 237e7a775fdSzhenwei pi 238e7a775fdSzhenwei pi return len; 239e7a775fdSzhenwei pi } 240e7a775fdSzhenwei pi 2412580b452Szhenwei pi static void cryptodev_backend_throttle_timer_cb(void *opaque) 2422580b452Szhenwei pi { 2432580b452Szhenwei pi CryptoDevBackend *backend = (CryptoDevBackend *)opaque; 2442580b452Szhenwei pi CryptoDevBackendOpInfo *op_info, *tmpop; 2452580b452Szhenwei pi int ret; 2462580b452Szhenwei pi 2472580b452Szhenwei pi QTAILQ_FOREACH_SAFE(op_info, &backend->opinfos, next, tmpop) { 2482580b452Szhenwei pi QTAILQ_REMOVE(&backend->opinfos, op_info, next); 2492580b452Szhenwei pi ret = cryptodev_backend_account(backend, op_info); 2502580b452Szhenwei pi if (ret < 0) { 2512580b452Szhenwei pi op_info->cb(op_info->opaque, ret); 2522580b452Szhenwei pi continue; 2532580b452Szhenwei pi } 2542580b452Szhenwei pi 255e76f201fSzhenwei pi throttle_account(&backend->ts, THROTTLE_WRITE, ret); 2562580b452Szhenwei pi cryptodev_backend_operation(backend, op_info); 2572580b452Szhenwei pi if (throttle_enabled(&backend->tc) && 258e76f201fSzhenwei pi throttle_schedule_timer(&backend->ts, &backend->tt, 259e76f201fSzhenwei pi THROTTLE_WRITE)) { 2602580b452Szhenwei pi break; 2612580b452Szhenwei pi } 2622580b452Szhenwei pi } 2632580b452Szhenwei pi } 2642580b452Szhenwei pi 265d6634ac0SGonglei int cryptodev_backend_crypto_operation( 266d6634ac0SGonglei CryptoDevBackend *backend, 2672cb06927Szhenwei pi CryptoDevBackendOpInfo *op_info) 268d6634ac0SGonglei { 269e7a775fdSzhenwei pi int ret; 270d6634ac0SGonglei 2712580b452Szhenwei pi if (!throttle_enabled(&backend->tc)) { 2722580b452Szhenwei pi goto do_account; 2732580b452Szhenwei pi } 2742580b452Szhenwei pi 275e76f201fSzhenwei pi if (throttle_schedule_timer(&backend->ts, &backend->tt, THROTTLE_WRITE) || 2762580b452Szhenwei pi !QTAILQ_EMPTY(&backend->opinfos)) { 2772580b452Szhenwei pi QTAILQ_INSERT_TAIL(&backend->opinfos, op_info, next); 2782580b452Szhenwei pi return 0; 2792580b452Szhenwei pi } 2802580b452Szhenwei pi 2812580b452Szhenwei pi do_account: 282e7a775fdSzhenwei pi ret = cryptodev_backend_account(backend, op_info); 283e7a775fdSzhenwei pi if (ret < 0) { 284e7a775fdSzhenwei pi return ret; 285d6634ac0SGonglei } 286d6634ac0SGonglei 287e76f201fSzhenwei pi throttle_account(&backend->ts, THROTTLE_WRITE, ret); 2882580b452Szhenwei pi 2892cb06927Szhenwei pi return cryptodev_backend_operation(backend, op_info); 2909e4f86a8SGonglei } 2919e4f86a8SGonglei 292d0ee7a13SGonglei static void 293d0ee7a13SGonglei cryptodev_backend_get_queues(Object *obj, Visitor *v, const char *name, 294d0ee7a13SGonglei void *opaque, Error **errp) 295d0ee7a13SGonglei { 296d0ee7a13SGonglei CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj); 297d0ee7a13SGonglei uint32_t value = backend->conf.peers.queues; 298d0ee7a13SGonglei 299d0ee7a13SGonglei visit_type_uint32(v, name, &value, errp); 300d0ee7a13SGonglei } 301d0ee7a13SGonglei 302d0ee7a13SGonglei static void 303d0ee7a13SGonglei cryptodev_backend_set_queues(Object *obj, Visitor *v, const char *name, 304d0ee7a13SGonglei void *opaque, Error **errp) 305d0ee7a13SGonglei { 306d0ee7a13SGonglei CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj); 307d0ee7a13SGonglei uint32_t value; 308d0ee7a13SGonglei 309668f62ecSMarkus Armbruster if (!visit_type_uint32(v, name, &value, errp)) { 310dcfe4805SMarkus Armbruster return; 311d0ee7a13SGonglei } 312d0ee7a13SGonglei if (!value) { 313dcfe4805SMarkus Armbruster error_setg(errp, "Property '%s.%s' doesn't take value '%" PRIu32 "'", 314dcfe4805SMarkus Armbruster object_get_typename(obj), name, value); 315dcfe4805SMarkus Armbruster return; 316d0ee7a13SGonglei } 317d0ee7a13SGonglei backend->conf.peers.queues = value; 318d0ee7a13SGonglei } 319d0ee7a13SGonglei 3202580b452Szhenwei pi static void cryptodev_backend_set_throttle(CryptoDevBackend *backend, int field, 3212580b452Szhenwei pi uint64_t value, Error **errp) 3222580b452Szhenwei pi { 3232580b452Szhenwei pi uint64_t orig = backend->tc.buckets[field].avg; 3242580b452Szhenwei pi bool enabled = throttle_enabled(&backend->tc); 3252580b452Szhenwei pi 3262580b452Szhenwei pi if (orig == value) { 3272580b452Szhenwei pi return; 3282580b452Szhenwei pi } 3292580b452Szhenwei pi 3302580b452Szhenwei pi backend->tc.buckets[field].avg = value; 3312580b452Szhenwei pi if (!throttle_enabled(&backend->tc)) { 3322580b452Szhenwei pi throttle_timers_destroy(&backend->tt); 3332580b452Szhenwei pi cryptodev_backend_throttle_timer_cb(backend); /* drain opinfos */ 3342580b452Szhenwei pi return; 3352580b452Szhenwei pi } 3362580b452Szhenwei pi 3372580b452Szhenwei pi if (!throttle_is_valid(&backend->tc, errp)) { 3382580b452Szhenwei pi backend->tc.buckets[field].avg = orig; /* revert change */ 3392580b452Szhenwei pi return; 3402580b452Szhenwei pi } 3412580b452Szhenwei pi 3422580b452Szhenwei pi if (!enabled) { 3432580b452Szhenwei pi throttle_init(&backend->ts); 3442580b452Szhenwei pi throttle_timers_init(&backend->tt, qemu_get_aio_context(), 34527cf1229Szhenwei pi QEMU_CLOCK_REALTIME, NULL, 3462580b452Szhenwei pi cryptodev_backend_throttle_timer_cb, backend); 3472580b452Szhenwei pi } 3482580b452Szhenwei pi 3492580b452Szhenwei pi throttle_config(&backend->ts, QEMU_CLOCK_REALTIME, &backend->tc); 3502580b452Szhenwei pi } 3512580b452Szhenwei pi 3522580b452Szhenwei pi static void cryptodev_backend_get_bps(Object *obj, Visitor *v, 3532580b452Szhenwei pi const char *name, void *opaque, 3542580b452Szhenwei pi Error **errp) 3552580b452Szhenwei pi { 3562580b452Szhenwei pi CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj); 3572580b452Szhenwei pi uint64_t value = backend->tc.buckets[THROTTLE_BPS_TOTAL].avg; 3582580b452Szhenwei pi 3592580b452Szhenwei pi visit_type_uint64(v, name, &value, errp); 3602580b452Szhenwei pi } 3612580b452Szhenwei pi 3622580b452Szhenwei pi static void cryptodev_backend_set_bps(Object *obj, Visitor *v, const char *name, 3632580b452Szhenwei pi void *opaque, Error **errp) 3642580b452Szhenwei pi { 3652580b452Szhenwei pi CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj); 3662580b452Szhenwei pi uint64_t value; 3672580b452Szhenwei pi 3682580b452Szhenwei pi if (!visit_type_uint64(v, name, &value, errp)) { 3692580b452Szhenwei pi return; 3702580b452Szhenwei pi } 3712580b452Szhenwei pi 3722580b452Szhenwei pi cryptodev_backend_set_throttle(backend, THROTTLE_BPS_TOTAL, value, errp); 3732580b452Szhenwei pi } 3742580b452Szhenwei pi 3752580b452Szhenwei pi static void cryptodev_backend_get_ops(Object *obj, Visitor *v, const char *name, 3762580b452Szhenwei pi void *opaque, Error **errp) 3772580b452Szhenwei pi { 3782580b452Szhenwei pi CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj); 3792580b452Szhenwei pi uint64_t value = backend->tc.buckets[THROTTLE_OPS_TOTAL].avg; 3802580b452Szhenwei pi 3812580b452Szhenwei pi visit_type_uint64(v, name, &value, errp); 3822580b452Szhenwei pi } 3832580b452Szhenwei pi 3842580b452Szhenwei pi static void cryptodev_backend_set_ops(Object *obj, Visitor *v, 3852580b452Szhenwei pi const char *name, void *opaque, 3862580b452Szhenwei pi Error **errp) 3872580b452Szhenwei pi { 3882580b452Szhenwei pi CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj); 3892580b452Szhenwei pi uint64_t value; 3902580b452Szhenwei pi 3912580b452Szhenwei pi if (!visit_type_uint64(v, name, &value, errp)) { 3922580b452Szhenwei pi return; 3932580b452Szhenwei pi } 3942580b452Szhenwei pi 3952580b452Szhenwei pi cryptodev_backend_set_throttle(backend, THROTTLE_OPS_TOTAL, value, errp); 3962580b452Szhenwei pi } 3972580b452Szhenwei pi 398d0ee7a13SGonglei static void 399d0ee7a13SGonglei cryptodev_backend_complete(UserCreatable *uc, Error **errp) 400d0ee7a13SGonglei { 401484aecf2SPhilippe Mathieu-Daudé ERRP_GUARD(); 402d0ee7a13SGonglei CryptoDevBackend *backend = CRYPTODEV_BACKEND(uc); 403d0ee7a13SGonglei CryptoDevBackendClass *bc = CRYPTODEV_BACKEND_GET_CLASS(uc); 404e7a775fdSzhenwei pi uint32_t services; 4052580b452Szhenwei pi uint64_t value; 4062580b452Szhenwei pi 4072580b452Szhenwei pi QTAILQ_INIT(&backend->opinfos); 4082580b452Szhenwei pi value = backend->tc.buckets[THROTTLE_OPS_TOTAL].avg; 4092580b452Szhenwei pi cryptodev_backend_set_throttle(backend, THROTTLE_OPS_TOTAL, value, errp); 410484aecf2SPhilippe Mathieu-Daudé if (*errp) { 411484aecf2SPhilippe Mathieu-Daudé return; 412484aecf2SPhilippe Mathieu-Daudé } 4132580b452Szhenwei pi value = backend->tc.buckets[THROTTLE_BPS_TOTAL].avg; 4142580b452Szhenwei pi cryptodev_backend_set_throttle(backend, THROTTLE_BPS_TOTAL, value, errp); 415484aecf2SPhilippe Mathieu-Daudé if (*errp) { 416484aecf2SPhilippe Mathieu-Daudé return; 417484aecf2SPhilippe Mathieu-Daudé } 418d0ee7a13SGonglei 419d0ee7a13SGonglei if (bc->init) { 4207dc75edbSVladimir Sementsov-Ogievskiy bc->init(backend, errp); 421484aecf2SPhilippe Mathieu-Daudé if (*errp) { 422484aecf2SPhilippe Mathieu-Daudé return; 423484aecf2SPhilippe Mathieu-Daudé } 424d0ee7a13SGonglei } 425e7a775fdSzhenwei pi 426e7a775fdSzhenwei pi services = backend->conf.crypto_services; 427*d0917d79SMarkus Armbruster if (services & (1 << QCRYPTODEV_BACKEND_SERVICE_TYPE_CIPHER)) { 428e7a775fdSzhenwei pi backend->sym_stat = g_new0(CryptodevBackendSymStat, 1); 429e7a775fdSzhenwei pi } 430e7a775fdSzhenwei pi 431*d0917d79SMarkus Armbruster if (services & (1 << QCRYPTODEV_BACKEND_SERVICE_TYPE_AKCIPHER)) { 432e7a775fdSzhenwei pi backend->asym_stat = g_new0(CryptodevBackendAsymStat, 1); 433e7a775fdSzhenwei pi } 434d0ee7a13SGonglei } 4356138dbdaSGonglei 43646fd1705SGonglei void cryptodev_backend_set_used(CryptoDevBackend *backend, bool used) 43746fd1705SGonglei { 43846fd1705SGonglei backend->is_used = used; 43946fd1705SGonglei } 44046fd1705SGonglei 44146fd1705SGonglei bool cryptodev_backend_is_used(CryptoDevBackend *backend) 44246fd1705SGonglei { 44346fd1705SGonglei return backend->is_used; 44446fd1705SGonglei } 44546fd1705SGonglei 4466138dbdaSGonglei void cryptodev_backend_set_ready(CryptoDevBackend *backend, bool ready) 4476138dbdaSGonglei { 4486138dbdaSGonglei backend->ready = ready; 4496138dbdaSGonglei } 4506138dbdaSGonglei 4516138dbdaSGonglei bool cryptodev_backend_is_ready(CryptoDevBackend *backend) 4526138dbdaSGonglei { 4536138dbdaSGonglei return backend->ready; 4546138dbdaSGonglei } 4556138dbdaSGonglei 45646fd1705SGonglei static bool 4573beacfb9SEduardo Habkost cryptodev_backend_can_be_deleted(UserCreatable *uc) 45846fd1705SGonglei { 45946fd1705SGonglei return !cryptodev_backend_is_used(CRYPTODEV_BACKEND(uc)); 46046fd1705SGonglei } 46146fd1705SGonglei 462d0ee7a13SGonglei static void cryptodev_backend_instance_init(Object *obj) 463d0ee7a13SGonglei { 4642580b452Szhenwei pi CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj); 4652580b452Szhenwei pi 466d0ee7a13SGonglei /* Initialize devices' queues property to 1 */ 4675325cc34SMarkus Armbruster object_property_set_int(obj, "queues", 1, NULL); 4682580b452Szhenwei pi 4692580b452Szhenwei pi throttle_config_init(&backend->tc); 470d0ee7a13SGonglei } 471d0ee7a13SGonglei 472d0ee7a13SGonglei static void cryptodev_backend_finalize(Object *obj) 473d0ee7a13SGonglei { 47446fd1705SGonglei CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj); 475d0ee7a13SGonglei 47646fd1705SGonglei cryptodev_backend_cleanup(backend, NULL); 4772580b452Szhenwei pi if (throttle_enabled(&backend->tc)) { 4782580b452Szhenwei pi throttle_timers_destroy(&backend->tt); 4792580b452Szhenwei pi } 480d0ee7a13SGonglei } 481d0ee7a13SGonglei 482f2b90109Szhenwei pi static StatsList *cryptodev_backend_stats_add(const char *name, int64_t *val, 483f2b90109Szhenwei pi StatsList *stats_list) 484f2b90109Szhenwei pi { 485f2b90109Szhenwei pi Stats *stats = g_new0(Stats, 1); 486f2b90109Szhenwei pi 487f2b90109Szhenwei pi stats->name = g_strdup(name); 488f2b90109Szhenwei pi stats->value = g_new0(StatsValue, 1); 489f2b90109Szhenwei pi stats->value->type = QTYPE_QNUM; 490f2b90109Szhenwei pi stats->value->u.scalar = *val; 491f2b90109Szhenwei pi 492f2b90109Szhenwei pi QAPI_LIST_PREPEND(stats_list, stats); 493f2b90109Szhenwei pi return stats_list; 494f2b90109Szhenwei pi } 495f2b90109Szhenwei pi 496f2b90109Szhenwei pi static int cryptodev_backend_stats_query(Object *obj, void *data) 497f2b90109Szhenwei pi { 498f2b90109Szhenwei pi StatsArgs *stats_args = data; 499f2b90109Szhenwei pi StatsResultList **stats_results = stats_args->result.stats; 500f2b90109Szhenwei pi StatsList *stats_list = NULL; 501f2b90109Szhenwei pi StatsResult *entry; 502f2b90109Szhenwei pi CryptoDevBackend *backend; 503f2b90109Szhenwei pi CryptodevBackendSymStat *sym_stat; 504f2b90109Szhenwei pi CryptodevBackendAsymStat *asym_stat; 505f2b90109Szhenwei pi 506f2b90109Szhenwei pi if (!object_dynamic_cast(obj, TYPE_CRYPTODEV_BACKEND)) { 507f2b90109Szhenwei pi return 0; 508f2b90109Szhenwei pi } 509f2b90109Szhenwei pi 510f2b90109Szhenwei pi backend = CRYPTODEV_BACKEND(obj); 511f2b90109Szhenwei pi sym_stat = backend->sym_stat; 512f2b90109Szhenwei pi if (sym_stat) { 513f2b90109Szhenwei pi stats_list = cryptodev_backend_stats_add(SYM_ENCRYPT_OPS_STR, 514f2b90109Szhenwei pi &sym_stat->encrypt_ops, stats_list); 515f2b90109Szhenwei pi stats_list = cryptodev_backend_stats_add(SYM_DECRYPT_OPS_STR, 516f2b90109Szhenwei pi &sym_stat->decrypt_ops, stats_list); 517f2b90109Szhenwei pi stats_list = cryptodev_backend_stats_add(SYM_ENCRYPT_BYTES_STR, 518f2b90109Szhenwei pi &sym_stat->encrypt_bytes, stats_list); 519f2b90109Szhenwei pi stats_list = cryptodev_backend_stats_add(SYM_DECRYPT_BYTES_STR, 520f2b90109Szhenwei pi &sym_stat->decrypt_bytes, stats_list); 521f2b90109Szhenwei pi } 522f2b90109Szhenwei pi 523f2b90109Szhenwei pi asym_stat = backend->asym_stat; 524f2b90109Szhenwei pi if (asym_stat) { 525f2b90109Szhenwei pi stats_list = cryptodev_backend_stats_add(ASYM_ENCRYPT_OPS_STR, 526f2b90109Szhenwei pi &asym_stat->encrypt_ops, stats_list); 527f2b90109Szhenwei pi stats_list = cryptodev_backend_stats_add(ASYM_DECRYPT_OPS_STR, 528f2b90109Szhenwei pi &asym_stat->decrypt_ops, stats_list); 529f2b90109Szhenwei pi stats_list = cryptodev_backend_stats_add(ASYM_SIGN_OPS_STR, 530f2b90109Szhenwei pi &asym_stat->sign_ops, stats_list); 531f2b90109Szhenwei pi stats_list = cryptodev_backend_stats_add(ASYM_VERIFY_OPS_STR, 532f2b90109Szhenwei pi &asym_stat->verify_ops, stats_list); 533f2b90109Szhenwei pi stats_list = cryptodev_backend_stats_add(ASYM_ENCRYPT_BYTES_STR, 534f2b90109Szhenwei pi &asym_stat->encrypt_bytes, stats_list); 535f2b90109Szhenwei pi stats_list = cryptodev_backend_stats_add(ASYM_DECRYPT_BYTES_STR, 536f2b90109Szhenwei pi &asym_stat->decrypt_bytes, stats_list); 537f2b90109Szhenwei pi stats_list = cryptodev_backend_stats_add(ASYM_SIGN_BYTES_STR, 538f2b90109Szhenwei pi &asym_stat->sign_bytes, stats_list); 539f2b90109Szhenwei pi stats_list = cryptodev_backend_stats_add(ASYM_VERIFY_BYTES_STR, 540f2b90109Szhenwei pi &asym_stat->verify_bytes, stats_list); 541f2b90109Szhenwei pi } 542f2b90109Szhenwei pi 543f2b90109Szhenwei pi entry = g_new0(StatsResult, 1); 544f2b90109Szhenwei pi entry->provider = STATS_PROVIDER_CRYPTODEV; 545a1f85cffSzhenwei pi entry->qom_path = object_get_canonical_path(obj); 546f2b90109Szhenwei pi entry->stats = stats_list; 547f2b90109Szhenwei pi QAPI_LIST_PREPEND(*stats_results, entry); 548f2b90109Szhenwei pi 549f2b90109Szhenwei pi return 0; 550f2b90109Szhenwei pi } 551f2b90109Szhenwei pi 552f2b90109Szhenwei pi static void cryptodev_backend_stats_cb(StatsResultList **result, 553f2b90109Szhenwei pi StatsTarget target, 554f2b90109Szhenwei pi strList *names, strList *targets, 555f2b90109Szhenwei pi Error **errp) 556f2b90109Szhenwei pi { 557f2b90109Szhenwei pi switch (target) { 558f2b90109Szhenwei pi case STATS_TARGET_CRYPTODEV: 559f2b90109Szhenwei pi { 560f2b90109Szhenwei pi Object *objs = container_get(object_get_root(), "/objects"); 561f2b90109Szhenwei pi StatsArgs stats_args; 562f2b90109Szhenwei pi stats_args.result.stats = result; 563f2b90109Szhenwei pi stats_args.names = names; 564f2b90109Szhenwei pi stats_args.errp = errp; 565f2b90109Szhenwei pi 566f2b90109Szhenwei pi object_child_foreach(objs, cryptodev_backend_stats_query, &stats_args); 567f2b90109Szhenwei pi break; 568f2b90109Szhenwei pi } 569f2b90109Szhenwei pi default: 570f2b90109Szhenwei pi break; 571f2b90109Szhenwei pi } 572f2b90109Szhenwei pi } 573f2b90109Szhenwei pi 574f2b90109Szhenwei pi static StatsSchemaValueList *cryptodev_backend_schemas_add(const char *name, 575f2b90109Szhenwei pi StatsSchemaValueList *list) 576f2b90109Szhenwei pi { 577f2b90109Szhenwei pi StatsSchemaValueList *schema_entry = g_new0(StatsSchemaValueList, 1); 578f2b90109Szhenwei pi 579f2b90109Szhenwei pi schema_entry->value = g_new0(StatsSchemaValue, 1); 580f2b90109Szhenwei pi schema_entry->value->type = STATS_TYPE_CUMULATIVE; 581f2b90109Szhenwei pi schema_entry->value->name = g_strdup(name); 582f2b90109Szhenwei pi schema_entry->next = list; 583f2b90109Szhenwei pi 584f2b90109Szhenwei pi return schema_entry; 585f2b90109Szhenwei pi } 586f2b90109Szhenwei pi 587f2b90109Szhenwei pi static void cryptodev_backend_schemas_cb(StatsSchemaList **result, 588f2b90109Szhenwei pi Error **errp) 589f2b90109Szhenwei pi { 590f2b90109Szhenwei pi StatsSchemaValueList *stats_list = NULL; 591f2b90109Szhenwei pi const char *sym_stats[] = { SYM_ENCRYPT_OPS_STR, SYM_DECRYPT_OPS_STR, 592f2b90109Szhenwei pi SYM_ENCRYPT_BYTES_STR, SYM_DECRYPT_BYTES_STR }; 593f2b90109Szhenwei pi const char *asym_stats[] = { ASYM_ENCRYPT_OPS_STR, ASYM_DECRYPT_OPS_STR, 594f2b90109Szhenwei pi ASYM_SIGN_OPS_STR, ASYM_VERIFY_OPS_STR, 595f2b90109Szhenwei pi ASYM_ENCRYPT_BYTES_STR, ASYM_DECRYPT_BYTES_STR, 596f2b90109Szhenwei pi ASYM_SIGN_BYTES_STR, ASYM_VERIFY_BYTES_STR }; 597f2b90109Szhenwei pi 598f2b90109Szhenwei pi for (int i = 0; i < ARRAY_SIZE(sym_stats); i++) { 599f2b90109Szhenwei pi stats_list = cryptodev_backend_schemas_add(sym_stats[i], stats_list); 600f2b90109Szhenwei pi } 601f2b90109Szhenwei pi 602f2b90109Szhenwei pi for (int i = 0; i < ARRAY_SIZE(asym_stats); i++) { 603f2b90109Szhenwei pi stats_list = cryptodev_backend_schemas_add(asym_stats[i], stats_list); 604f2b90109Szhenwei pi } 605f2b90109Szhenwei pi 606f2b90109Szhenwei pi add_stats_schema(result, STATS_PROVIDER_CRYPTODEV, STATS_TARGET_CRYPTODEV, 607f2b90109Szhenwei pi stats_list); 608f2b90109Szhenwei pi } 609f2b90109Szhenwei pi 610d0ee7a13SGonglei static void 611d0ee7a13SGonglei cryptodev_backend_class_init(ObjectClass *oc, void *data) 612d0ee7a13SGonglei { 613d0ee7a13SGonglei UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc); 614d0ee7a13SGonglei 615d0ee7a13SGonglei ucc->complete = cryptodev_backend_complete; 61646fd1705SGonglei ucc->can_be_deleted = cryptodev_backend_can_be_deleted; 617d0ee7a13SGonglei 618d0ee7a13SGonglei QTAILQ_INIT(&crypto_clients); 6191f14e388SEduardo Habkost object_class_property_add(oc, "queues", "uint32", 6201f14e388SEduardo Habkost cryptodev_backend_get_queues, 6211f14e388SEduardo Habkost cryptodev_backend_set_queues, 6221f14e388SEduardo Habkost NULL, NULL); 6232580b452Szhenwei pi object_class_property_add(oc, "throttle-bps", "uint64", 6242580b452Szhenwei pi cryptodev_backend_get_bps, 6252580b452Szhenwei pi cryptodev_backend_set_bps, 6262580b452Szhenwei pi NULL, NULL); 6272580b452Szhenwei pi object_class_property_add(oc, "throttle-ops", "uint64", 6282580b452Szhenwei pi cryptodev_backend_get_ops, 6292580b452Szhenwei pi cryptodev_backend_set_ops, 6302580b452Szhenwei pi NULL, NULL); 631f2b90109Szhenwei pi 632f2b90109Szhenwei pi add_stats_callbacks(STATS_PROVIDER_CRYPTODEV, cryptodev_backend_stats_cb, 633f2b90109Szhenwei pi cryptodev_backend_schemas_cb); 634d0ee7a13SGonglei } 635d0ee7a13SGonglei 636d0ee7a13SGonglei static const TypeInfo cryptodev_backend_info = { 637d0ee7a13SGonglei .name = TYPE_CRYPTODEV_BACKEND, 638d0ee7a13SGonglei .parent = TYPE_OBJECT, 639d0ee7a13SGonglei .instance_size = sizeof(CryptoDevBackend), 640d0ee7a13SGonglei .instance_init = cryptodev_backend_instance_init, 641d0ee7a13SGonglei .instance_finalize = cryptodev_backend_finalize, 642d0ee7a13SGonglei .class_size = sizeof(CryptoDevBackendClass), 643d0ee7a13SGonglei .class_init = cryptodev_backend_class_init, 644d0ee7a13SGonglei .interfaces = (InterfaceInfo[]) { 645d0ee7a13SGonglei { TYPE_USER_CREATABLE }, 646d0ee7a13SGonglei { } 647d0ee7a13SGonglei } 648d0ee7a13SGonglei }; 649d0ee7a13SGonglei 650d0ee7a13SGonglei static void 651d0ee7a13SGonglei cryptodev_backend_register_types(void) 652d0ee7a13SGonglei { 653d0ee7a13SGonglei type_register_static(&cryptodev_backend_info); 654d0ee7a13SGonglei } 655d0ee7a13SGonglei 656d0ee7a13SGonglei type_init(cryptodev_backend_register_types); 657