xref: /qemu/backends/cryptodev.c (revision b1019999)
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 
qmp_query_cryptodev_foreach(Object * obj,void * data)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;
77d0917d79SMarkus 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 
qmp_query_cryptodev(Error ** errp)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 
cryptodev_backend_new_client(void)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 
cryptodev_backend_free_client(CryptoDevBackendClient * cc)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 
cryptodev_backend_cleanup(CryptoDevBackend * backend,Error ** errp)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 
cryptodev_backend_create_session(CryptoDevBackend * backend,CryptoDevBackendSessionInfo * sess_info,uint32_t queue_index,CryptoDevCompletionFunc cb,void * opaque)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 
cryptodev_backend_close_session(CryptoDevBackend * backend,uint64_t session_id,uint32_t queue_index,CryptoDevCompletionFunc cb,void * opaque)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 
cryptodev_backend_operation(CryptoDevBackend * backend,CryptoDevBackendOpInfo * op_info)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 
cryptodev_backend_account(CryptoDevBackend * backend,CryptoDevBackendOpInfo * op_info)185e7a775fdSzhenwei pi static int cryptodev_backend_account(CryptoDevBackend *backend,
186e7a775fdSzhenwei pi                  CryptoDevBackendOpInfo *op_info)
187e7a775fdSzhenwei pi {
188*b1019999SMarkus Armbruster     enum QCryptodevBackendAlgoType algtype = op_info->algtype;
189e7a775fdSzhenwei pi     int len;
190e7a775fdSzhenwei pi 
191*b1019999SMarkus Armbruster     if (algtype == QCRYPTODEV_BACKEND_ALGO_TYPE_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         }
215*b1019999SMarkus Armbruster     } else if (algtype == QCRYPTODEV_BACKEND_ALGO_TYPE_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 
cryptodev_backend_throttle_timer_cb(void * opaque)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 
cryptodev_backend_crypto_operation(CryptoDevBackend * backend,CryptoDevBackendOpInfo * op_info)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
cryptodev_backend_get_queues(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)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
cryptodev_backend_set_queues(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)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 
cryptodev_backend_set_throttle(CryptoDevBackend * backend,int field,uint64_t value,Error ** errp)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 
cryptodev_backend_get_bps(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)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 
cryptodev_backend_set_bps(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)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 
cryptodev_backend_get_ops(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)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 
cryptodev_backend_set_ops(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)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
cryptodev_backend_complete(UserCreatable * uc,Error ** errp)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;
427d0917d79SMarkus Armbruster     if (services & (1 << QCRYPTODEV_BACKEND_SERVICE_TYPE_CIPHER)) {
428e7a775fdSzhenwei pi         backend->sym_stat = g_new0(CryptodevBackendSymStat, 1);
429e7a775fdSzhenwei pi     }
430e7a775fdSzhenwei pi 
431d0917d79SMarkus Armbruster     if (services & (1 << QCRYPTODEV_BACKEND_SERVICE_TYPE_AKCIPHER)) {
432e7a775fdSzhenwei pi         backend->asym_stat = g_new0(CryptodevBackendAsymStat, 1);
433e7a775fdSzhenwei pi     }
434d0ee7a13SGonglei }
4356138dbdaSGonglei 
cryptodev_backend_set_used(CryptoDevBackend * backend,bool used)43646fd1705SGonglei void cryptodev_backend_set_used(CryptoDevBackend *backend, bool used)
43746fd1705SGonglei {
43846fd1705SGonglei     backend->is_used = used;
43946fd1705SGonglei }
44046fd1705SGonglei 
cryptodev_backend_is_used(CryptoDevBackend * backend)44146fd1705SGonglei bool cryptodev_backend_is_used(CryptoDevBackend *backend)
44246fd1705SGonglei {
44346fd1705SGonglei     return backend->is_used;
44446fd1705SGonglei }
44546fd1705SGonglei 
cryptodev_backend_set_ready(CryptoDevBackend * backend,bool ready)4466138dbdaSGonglei void cryptodev_backend_set_ready(CryptoDevBackend *backend, bool ready)
4476138dbdaSGonglei {
4486138dbdaSGonglei     backend->ready = ready;
4496138dbdaSGonglei }
4506138dbdaSGonglei 
cryptodev_backend_is_ready(CryptoDevBackend * backend)4516138dbdaSGonglei bool cryptodev_backend_is_ready(CryptoDevBackend *backend)
4526138dbdaSGonglei {
4536138dbdaSGonglei     return backend->ready;
4546138dbdaSGonglei }
4556138dbdaSGonglei 
45646fd1705SGonglei static bool
cryptodev_backend_can_be_deleted(UserCreatable * uc)4573beacfb9SEduardo Habkost cryptodev_backend_can_be_deleted(UserCreatable *uc)
45846fd1705SGonglei {
45946fd1705SGonglei     return !cryptodev_backend_is_used(CRYPTODEV_BACKEND(uc));
46046fd1705SGonglei }
46146fd1705SGonglei 
cryptodev_backend_instance_init(Object * obj)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 
cryptodev_backend_finalize(Object * obj)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 
cryptodev_backend_stats_add(const char * name,int64_t * val,StatsList * stats_list)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 
cryptodev_backend_stats_query(Object * obj,void * data)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 
cryptodev_backend_stats_cb(StatsResultList ** result,StatsTarget target,strList * names,strList * targets,Error ** errp)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 
cryptodev_backend_schemas_add(const char * name,StatsSchemaValueList * list)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 
cryptodev_backend_schemas_cb(StatsSchemaList ** result,Error ** errp)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
cryptodev_backend_class_init(ObjectClass * oc,void * data)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
cryptodev_backend_register_types(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