2 * QEMU Cryptodev backend for QEMU cipher APIs
4 * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
7 * Gonglei <arei.gonglei@huawei.com>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
24 #include "qemu/osdep.h"
25 #include "hw/boards.h"
26 #include "qapi/error.h"
27 #include "qapi/qmp/qerror.h"
28 #include "qemu/error-report.h"
29 #include "standard-headers/linux/virtio_crypto.h"
30 #include "sysemu/cryptodev-vhost.h"
31 #include "chardev/char-fe.h"
35 * @TYPE_CRYPTODEV_BACKEND_VHOST_USER:
36 * name of backend that uses vhost user server
38 #define TYPE_CRYPTODEV_BACKEND_VHOST_USER "cryptodev-vhost-user"
40 #define CRYPTODEV_BACKEND_VHOST_USER(obj) \
41 OBJECT_CHECK(CryptoDevBackendVhostUser, \
42 (obj), TYPE_CRYPTODEV_BACKEND_VHOST_USER)
45 typedef struct CryptoDevBackendVhostUser
{
46 CryptoDevBackend parent_obj
;
51 CryptoDevBackendVhost
*vhost_crypto
[MAX_CRYPTO_QUEUE_NUM
];
52 } CryptoDevBackendVhostUser
;
55 cryptodev_vhost_user_running(
56 CryptoDevBackendVhost
*crypto
)
58 return crypto
? 1 : 0;
61 static void cryptodev_vhost_user_stop(int queues
,
62 CryptoDevBackendVhostUser
*s
)
66 for (i
= 0; i
< queues
; i
++) {
67 if (!cryptodev_vhost_user_running(s
->vhost_crypto
[i
])) {
71 cryptodev_vhost_cleanup(s
->vhost_crypto
[i
]);
72 s
->vhost_crypto
[i
] = NULL
;
77 cryptodev_vhost_user_start(int queues
,
78 CryptoDevBackendVhostUser
*s
)
80 CryptoDevBackendVhostOptions options
;
81 CryptoDevBackend
*b
= CRYPTODEV_BACKEND(s
);
85 for (i
= 0; i
< queues
; i
++) {
86 if (cryptodev_vhost_user_running(s
->vhost_crypto
[i
])) {
90 options
.opaque
= &s
->chr
;
91 options
.backend_type
= VHOST_BACKEND_TYPE_USER
;
92 options
.cc
= b
->conf
.peers
.ccs
[i
];
93 s
->vhost_crypto
[i
] = cryptodev_vhost_init(&options
);
94 if (!s
->vhost_crypto
[i
]) {
95 error_report("failed to init vhost_crypto for queue %zu", i
);
101 cryptodev_vhost_get_max_queues(s
->vhost_crypto
[i
]);
102 if (queues
> max_queues
) {
103 error_report("you are asking more queues than supported: %d",
113 cryptodev_vhost_user_stop(i
+ 1, s
);
118 cryptodev_vhost_claim_chardev(CryptoDevBackendVhostUser
*s
,
123 if (s
->chr_name
== NULL
) {
124 error_setg(errp
, QERR_INVALID_PARAMETER_VALUE
,
125 "chardev", "a valid character device");
129 chr
= qemu_chr_find(s
->chr_name
);
131 error_set(errp
, ERROR_CLASS_DEVICE_NOT_FOUND
,
132 "Device '%s' not found", s
->chr_name
);
139 static void cryptodev_vhost_user_event(void *opaque
, int event
)
141 CryptoDevBackendVhostUser
*s
= opaque
;
142 CryptoDevBackend
*b
= CRYPTODEV_BACKEND(s
);
144 int queues
= b
->conf
.peers
.queues
;
146 assert(queues
< MAX_CRYPTO_QUEUE_NUM
);
149 case CHR_EVENT_OPENED
:
150 if (cryptodev_vhost_user_start(queues
, s
) < 0) {
155 case CHR_EVENT_CLOSED
:
157 cryptodev_vhost_user_stop(queues
, s
);
162 error_report_err(err
);
166 static void cryptodev_vhost_user_init(
167 CryptoDevBackend
*backend
, Error
**errp
)
169 int queues
= backend
->conf
.peers
.queues
;
171 Error
*local_err
= NULL
;
173 CryptoDevBackendClient
*cc
;
174 CryptoDevBackendVhostUser
*s
=
175 CRYPTODEV_BACKEND_VHOST_USER(backend
);
177 chr
= cryptodev_vhost_claim_chardev(s
, &local_err
);
179 error_propagate(errp
, local_err
);
185 for (i
= 0; i
< queues
; i
++) {
186 cc
= cryptodev_backend_new_client(
187 "cryptodev-vhost-user", NULL
);
188 cc
->info_str
= g_strdup_printf("cryptodev-vhost-user%zu to %s ",
192 backend
->conf
.peers
.ccs
[i
] = cc
;
195 if (!qemu_chr_fe_init(&s
->chr
, chr
, &local_err
)) {
196 error_propagate(errp
, local_err
);
202 qemu_chr_fe_set_handlers(&s
->chr
, NULL
, NULL
,
203 cryptodev_vhost_user_event
, NULL
, s
, NULL
, true);
205 backend
->conf
.crypto_services
=
206 1u << VIRTIO_CRYPTO_SERVICE_CIPHER
|
207 1u << VIRTIO_CRYPTO_SERVICE_HASH
|
208 1u << VIRTIO_CRYPTO_SERVICE_MAC
;
209 backend
->conf
.cipher_algo_l
= 1u << VIRTIO_CRYPTO_CIPHER_AES_CBC
;
210 backend
->conf
.hash_algo
= 1u << VIRTIO_CRYPTO_HASH_SHA1
;
213 static int64_t cryptodev_vhost_user_sym_create_session(
214 CryptoDevBackend
*backend
,
215 CryptoDevBackendSymSessionInfo
*sess_info
,
216 uint32_t queue_index
, Error
**errp
)
221 static int cryptodev_vhost_user_sym_close_session(
222 CryptoDevBackend
*backend
,
224 uint32_t queue_index
, Error
**errp
)
229 static int cryptodev_vhost_user_sym_operation(
230 CryptoDevBackend
*backend
,
231 CryptoDevBackendSymOpInfo
*op_info
,
232 uint32_t queue_index
, Error
**errp
)
234 return VIRTIO_CRYPTO_OK
;
237 static void cryptodev_vhost_user_cleanup(
238 CryptoDevBackend
*backend
,
241 CryptoDevBackendVhostUser
*s
=
242 CRYPTODEV_BACKEND_VHOST_USER(backend
);
244 int queues
= backend
->conf
.peers
.queues
;
245 CryptoDevBackendClient
*cc
;
247 cryptodev_vhost_user_stop(queues
, s
);
249 for (i
= 0; i
< queues
; i
++) {
250 cc
= backend
->conf
.peers
.ccs
[i
];
252 cryptodev_backend_free_client(cc
);
253 backend
->conf
.peers
.ccs
[i
] = NULL
;
258 static void cryptodev_vhost_user_set_chardev(Object
*obj
,
259 const char *value
, Error
**errp
)
261 CryptoDevBackendVhostUser
*s
=
262 CRYPTODEV_BACKEND_VHOST_USER(obj
);
265 error_setg(errp
, QERR_PERMISSION_DENIED
);
268 s
->chr_name
= g_strdup(value
);
273 cryptodev_vhost_user_get_chardev(Object
*obj
, Error
**errp
)
275 CryptoDevBackendVhostUser
*s
=
276 CRYPTODEV_BACKEND_VHOST_USER(obj
);
277 Chardev
*chr
= qemu_chr_fe_get_driver(&s
->chr
);
279 if (chr
&& chr
->label
) {
280 return g_strdup(chr
->label
);
286 static void cryptodev_vhost_user_instance_int(Object
*obj
)
288 object_property_add_str(obj
, "chardev",
289 cryptodev_vhost_user_get_chardev
,
290 cryptodev_vhost_user_set_chardev
,
294 static void cryptodev_vhost_user_finalize(Object
*obj
)
296 CryptoDevBackendVhostUser
*s
=
297 CRYPTODEV_BACKEND_VHOST_USER(obj
);
299 qemu_chr_fe_deinit(&s
->chr
, false);
305 cryptodev_vhost_user_class_init(ObjectClass
*oc
, void *data
)
307 CryptoDevBackendClass
*bc
= CRYPTODEV_BACKEND_CLASS(oc
);
309 bc
->init
= cryptodev_vhost_user_init
;
310 bc
->cleanup
= cryptodev_vhost_user_cleanup
;
311 bc
->create_session
= cryptodev_vhost_user_sym_create_session
;
312 bc
->close_session
= cryptodev_vhost_user_sym_close_session
;
313 bc
->do_sym_op
= cryptodev_vhost_user_sym_operation
;
316 static const TypeInfo cryptodev_vhost_user_info
= {
317 .name
= TYPE_CRYPTODEV_BACKEND_VHOST_USER
,
318 .parent
= TYPE_CRYPTODEV_BACKEND
,
319 .class_init
= cryptodev_vhost_user_class_init
,
320 .instance_init
= cryptodev_vhost_user_instance_int
,
321 .instance_finalize
= cryptodev_vhost_user_finalize
,
322 .instance_size
= sizeof(CryptoDevBackendVhostUser
),
326 cryptodev_vhost_user_register_types(void)
328 type_register_static(&cryptodev_vhost_user_info
);
331 type_init(cryptodev_vhost_user_register_types
);