2 * QEMU Cryptodev backend for QEMU cipher APIs
4 * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
7 * Gonglei <arei.gonglei@huawei.com>
8 * Jay Zhou <jianjay.zhou@huawei.com>
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
25 #include "qemu/osdep.h"
26 #include "hw/virtio/virtio-bus.h"
27 #include "sysemu/cryptodev-vhost.h"
29 #ifdef CONFIG_VHOST_CRYPTO
30 #include "qapi/error.h"
31 #include "qapi/qmp/qerror.h"
32 #include "qemu/error-report.h"
33 #include "hw/virtio/virtio-crypto.h"
34 #include "sysemu/cryptodev-vhost-user.h"
37 cryptodev_vhost_get_max_queues(
38 CryptoDevBackendVhost
*crypto
)
40 return crypto
->dev
.max_queues
;
43 void cryptodev_vhost_cleanup(CryptoDevBackendVhost
*crypto
)
45 vhost_dev_cleanup(&crypto
->dev
);
49 struct CryptoDevBackendVhost
*
51 CryptoDevBackendVhostOptions
*options
)
54 CryptoDevBackendVhost
*crypto
;
55 Error
*local_err
= NULL
;
57 crypto
= g_new(CryptoDevBackendVhost
, 1);
58 crypto
->dev
.max_queues
= 1;
60 crypto
->dev
.vqs
= crypto
->vqs
;
62 crypto
->cc
= options
->cc
;
64 crypto
->dev
.protocol_features
= 0;
67 /* vhost-user needs vq_index to initiate a specific queue pair */
68 crypto
->dev
.vq_index
= crypto
->cc
->queue_index
* crypto
->dev
.nvqs
;
70 r
= vhost_dev_init(&crypto
->dev
, options
->opaque
, options
->backend_type
, 0,
73 error_report_err(local_err
);
84 cryptodev_vhost_start_one(CryptoDevBackendVhost
*crypto
,
90 crypto
->dev
.vqs
= crypto
->vqs
;
92 r
= vhost_dev_enable_notifiers(&crypto
->dev
, dev
);
97 r
= vhost_dev_start(&crypto
->dev
, dev
, false);
105 vhost_dev_disable_notifiers(&crypto
->dev
, dev
);
111 cryptodev_vhost_stop_one(CryptoDevBackendVhost
*crypto
,
114 vhost_dev_stop(&crypto
->dev
, dev
, false);
115 vhost_dev_disable_notifiers(&crypto
->dev
, dev
);
118 CryptoDevBackendVhost
*
119 cryptodev_get_vhost(CryptoDevBackendClient
*cc
,
123 CryptoDevBackendVhost
*vhost_crypto
= NULL
;
130 #if defined(CONFIG_VHOST_USER) && defined(CONFIG_LINUX)
131 case CRYPTODEV_BACKEND_TYPE_VHOST_USER
:
132 vhost_crypto
= cryptodev_vhost_user_get_vhost(cc
, b
, queue
);
143 cryptodev_vhost_set_vq_index(CryptoDevBackendVhost
*crypto
,
146 crypto
->dev
.vq_index
= vq_index
;
150 vhost_set_vring_enable(CryptoDevBackendClient
*cc
,
152 uint16_t queue
, int enable
)
154 CryptoDevBackendVhost
*crypto
=
155 cryptodev_get_vhost(cc
, b
, queue
);
156 const VhostOps
*vhost_ops
;
158 cc
->vring_enable
= enable
;
164 vhost_ops
= crypto
->dev
.vhost_ops
;
165 if (vhost_ops
->vhost_set_vring_enable
) {
166 return vhost_ops
->vhost_set_vring_enable(&crypto
->dev
, enable
);
172 int cryptodev_vhost_start(VirtIODevice
*dev
, int total_queues
)
174 VirtIOCrypto
*vcrypto
= VIRTIO_CRYPTO(dev
);
175 BusState
*qbus
= BUS(qdev_get_parent_bus(DEVICE(dev
)));
176 VirtioBusState
*vbus
= VIRTIO_BUS(qbus
);
177 VirtioBusClass
*k
= VIRTIO_BUS_GET_CLASS(vbus
);
180 CryptoDevBackend
*b
= vcrypto
->cryptodev
;
181 CryptoDevBackendVhost
*vhost_crypto
;
182 CryptoDevBackendClient
*cc
;
184 if (!k
->set_guest_notifiers
) {
185 error_report("binding does not support guest notifiers");
189 for (i
= 0; i
< total_queues
; i
++) {
190 cc
= b
->conf
.peers
.ccs
[i
];
192 vhost_crypto
= cryptodev_get_vhost(cc
, b
, i
);
193 cryptodev_vhost_set_vq_index(vhost_crypto
, i
);
195 /* Suppress the masking guest notifiers on vhost user
196 * because vhost user doesn't interrupt masking/unmasking
199 if (cc
->type
== CRYPTODEV_BACKEND_TYPE_VHOST_USER
) {
200 dev
->use_guest_notifier_mask
= false;
204 r
= k
->set_guest_notifiers(qbus
->parent
, total_queues
, true);
206 error_report("error binding guest notifier: %d", -r
);
210 for (i
= 0; i
< total_queues
; i
++) {
211 cc
= b
->conf
.peers
.ccs
[i
];
213 vhost_crypto
= cryptodev_get_vhost(cc
, b
, i
);
214 r
= cryptodev_vhost_start_one(vhost_crypto
, dev
);
220 if (cc
->vring_enable
) {
221 /* restore vring enable state */
222 r
= vhost_set_vring_enable(cc
, b
, i
, cc
->vring_enable
);
234 cc
= b
->conf
.peers
.ccs
[i
];
235 vhost_crypto
= cryptodev_get_vhost(cc
, b
, i
);
236 cryptodev_vhost_stop_one(vhost_crypto
, dev
);
238 e
= k
->set_guest_notifiers(qbus
->parent
, total_queues
, false);
240 error_report("vhost guest notifier cleanup failed: %d", e
);
246 void cryptodev_vhost_stop(VirtIODevice
*dev
, int total_queues
)
248 BusState
*qbus
= BUS(qdev_get_parent_bus(DEVICE(dev
)));
249 VirtioBusState
*vbus
= VIRTIO_BUS(qbus
);
250 VirtioBusClass
*k
= VIRTIO_BUS_GET_CLASS(vbus
);
251 VirtIOCrypto
*vcrypto
= VIRTIO_CRYPTO(dev
);
252 CryptoDevBackend
*b
= vcrypto
->cryptodev
;
253 CryptoDevBackendVhost
*vhost_crypto
;
254 CryptoDevBackendClient
*cc
;
258 for (i
= 0; i
< total_queues
; i
++) {
259 cc
= b
->conf
.peers
.ccs
[i
];
261 vhost_crypto
= cryptodev_get_vhost(cc
, b
, i
);
262 cryptodev_vhost_stop_one(vhost_crypto
, dev
);
265 r
= k
->set_guest_notifiers(qbus
->parent
, total_queues
, false);
267 error_report("vhost guest notifier cleanup failed: %d", r
);
272 void cryptodev_vhost_virtqueue_mask(VirtIODevice
*dev
,
276 VirtIOCrypto
*vcrypto
= VIRTIO_CRYPTO(dev
);
277 CryptoDevBackend
*b
= vcrypto
->cryptodev
;
278 CryptoDevBackendVhost
*vhost_crypto
;
279 CryptoDevBackendClient
*cc
;
281 assert(queue
< MAX_CRYPTO_QUEUE_NUM
);
283 cc
= b
->conf
.peers
.ccs
[queue
];
284 vhost_crypto
= cryptodev_get_vhost(cc
, b
, queue
);
286 vhost_virtqueue_mask(&vhost_crypto
->dev
, dev
, idx
, mask
);
289 bool cryptodev_vhost_virtqueue_pending(VirtIODevice
*dev
,
292 VirtIOCrypto
*vcrypto
= VIRTIO_CRYPTO(dev
);
293 CryptoDevBackend
*b
= vcrypto
->cryptodev
;
294 CryptoDevBackendVhost
*vhost_crypto
;
295 CryptoDevBackendClient
*cc
;
297 assert(queue
< MAX_CRYPTO_QUEUE_NUM
);
299 cc
= b
->conf
.peers
.ccs
[queue
];
300 vhost_crypto
= cryptodev_get_vhost(cc
, b
, queue
);
302 return vhost_virtqueue_pending(&vhost_crypto
->dev
, idx
);
307 cryptodev_vhost_get_max_queues(CryptoDevBackendVhost
*crypto
)
312 void cryptodev_vhost_cleanup(CryptoDevBackendVhost
*crypto
)
316 struct CryptoDevBackendVhost
*
317 cryptodev_vhost_init(CryptoDevBackendVhostOptions
*options
)
322 CryptoDevBackendVhost
*
323 cryptodev_get_vhost(CryptoDevBackendClient
*cc
,
330 int cryptodev_vhost_start(VirtIODevice
*dev
, int total_queues
)
335 void cryptodev_vhost_stop(VirtIODevice
*dev
, int total_queues
)
339 void cryptodev_vhost_virtqueue_mask(VirtIODevice
*dev
,
345 bool cryptodev_vhost_virtqueue_pending(VirtIODevice
*dev
,