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 "qemu/error-report.h"
32 #include "hw/virtio/virtio-crypto.h"
33 #include "sysemu/cryptodev-vhost-user.h"
36 cryptodev_vhost_get_max_queues(
37 CryptoDevBackendVhost
*crypto
)
39 return crypto
->dev
.max_queues
;
42 void cryptodev_vhost_cleanup(CryptoDevBackendVhost
*crypto
)
44 vhost_dev_cleanup(&crypto
->dev
);
48 struct CryptoDevBackendVhost
*
50 CryptoDevBackendVhostOptions
*options
)
53 CryptoDevBackendVhost
*crypto
;
54 Error
*local_err
= NULL
;
56 crypto
= g_new(CryptoDevBackendVhost
, 1);
57 crypto
->dev
.max_queues
= 1;
59 crypto
->dev
.vqs
= crypto
->vqs
;
61 crypto
->cc
= options
->cc
;
63 crypto
->dev
.protocol_features
= 0;
66 /* vhost-user needs vq_index to initiate a specific queue pair */
67 crypto
->dev
.vq_index
= crypto
->cc
->queue_index
* crypto
->dev
.nvqs
;
69 r
= vhost_dev_init(&crypto
->dev
, options
->opaque
, options
->backend_type
, 0,
72 error_report_err(local_err
);
83 cryptodev_vhost_start_one(CryptoDevBackendVhost
*crypto
,
89 crypto
->dev
.vqs
= crypto
->vqs
;
91 r
= vhost_dev_enable_notifiers(&crypto
->dev
, dev
);
96 r
= vhost_dev_start(&crypto
->dev
, dev
, false);
104 vhost_dev_disable_notifiers(&crypto
->dev
, dev
);
110 cryptodev_vhost_stop_one(CryptoDevBackendVhost
*crypto
,
113 vhost_dev_stop(&crypto
->dev
, dev
, false);
114 vhost_dev_disable_notifiers(&crypto
->dev
, dev
);
117 CryptoDevBackendVhost
*
118 cryptodev_get_vhost(CryptoDevBackendClient
*cc
,
122 CryptoDevBackendVhost
*vhost_crypto
= NULL
;
129 #if defined(CONFIG_VHOST_USER) && defined(CONFIG_LINUX)
130 case QCRYPTODEV_BACKEND_TYPE_VHOST_USER
:
131 vhost_crypto
= cryptodev_vhost_user_get_vhost(cc
, b
, queue
);
142 cryptodev_vhost_set_vq_index(CryptoDevBackendVhost
*crypto
,
145 crypto
->dev
.vq_index
= vq_index
;
149 vhost_set_vring_enable(CryptoDevBackendClient
*cc
,
151 uint16_t queue
, int enable
)
153 CryptoDevBackendVhost
*crypto
=
154 cryptodev_get_vhost(cc
, b
, queue
);
155 const VhostOps
*vhost_ops
;
157 cc
->vring_enable
= enable
;
163 vhost_ops
= crypto
->dev
.vhost_ops
;
164 if (vhost_ops
->vhost_set_vring_enable
) {
165 return vhost_ops
->vhost_set_vring_enable(&crypto
->dev
, enable
);
171 int cryptodev_vhost_start(VirtIODevice
*dev
, int total_queues
)
173 VirtIOCrypto
*vcrypto
= VIRTIO_CRYPTO(dev
);
174 BusState
*qbus
= BUS(qdev_get_parent_bus(DEVICE(dev
)));
175 VirtioBusState
*vbus
= VIRTIO_BUS(qbus
);
176 VirtioBusClass
*k
= VIRTIO_BUS_GET_CLASS(vbus
);
179 CryptoDevBackend
*b
= vcrypto
->cryptodev
;
180 CryptoDevBackendVhost
*vhost_crypto
;
181 CryptoDevBackendClient
*cc
;
183 if (!k
->set_guest_notifiers
) {
184 error_report("binding does not support guest notifiers");
188 for (i
= 0; i
< total_queues
; i
++) {
189 cc
= b
->conf
.peers
.ccs
[i
];
191 vhost_crypto
= cryptodev_get_vhost(cc
, b
, i
);
192 cryptodev_vhost_set_vq_index(vhost_crypto
, i
);
194 /* Suppress the masking guest notifiers on vhost user
195 * because vhost user doesn't interrupt masking/unmasking
198 if (cc
->type
== QCRYPTODEV_BACKEND_TYPE_VHOST_USER
) {
199 dev
->use_guest_notifier_mask
= false;
203 r
= k
->set_guest_notifiers(qbus
->parent
, total_queues
, true);
205 error_report("error binding guest notifier: %d", -r
);
209 for (i
= 0; i
< total_queues
; i
++) {
210 cc
= b
->conf
.peers
.ccs
[i
];
212 vhost_crypto
= cryptodev_get_vhost(cc
, b
, i
);
213 r
= cryptodev_vhost_start_one(vhost_crypto
, dev
);
219 if (cc
->vring_enable
) {
220 /* restore vring enable state */
221 r
= vhost_set_vring_enable(cc
, b
, i
, cc
->vring_enable
);
233 cc
= b
->conf
.peers
.ccs
[i
];
234 vhost_crypto
= cryptodev_get_vhost(cc
, b
, i
);
235 cryptodev_vhost_stop_one(vhost_crypto
, dev
);
237 e
= k
->set_guest_notifiers(qbus
->parent
, total_queues
, false);
239 error_report("vhost guest notifier cleanup failed: %d", e
);
245 void cryptodev_vhost_stop(VirtIODevice
*dev
, int total_queues
)
247 BusState
*qbus
= BUS(qdev_get_parent_bus(DEVICE(dev
)));
248 VirtioBusState
*vbus
= VIRTIO_BUS(qbus
);
249 VirtioBusClass
*k
= VIRTIO_BUS_GET_CLASS(vbus
);
250 VirtIOCrypto
*vcrypto
= VIRTIO_CRYPTO(dev
);
251 CryptoDevBackend
*b
= vcrypto
->cryptodev
;
252 CryptoDevBackendVhost
*vhost_crypto
;
253 CryptoDevBackendClient
*cc
;
257 for (i
= 0; i
< total_queues
; i
++) {
258 cc
= b
->conf
.peers
.ccs
[i
];
260 vhost_crypto
= cryptodev_get_vhost(cc
, b
, i
);
261 cryptodev_vhost_stop_one(vhost_crypto
, dev
);
264 r
= k
->set_guest_notifiers(qbus
->parent
, total_queues
, false);
266 error_report("vhost guest notifier cleanup failed: %d", r
);
271 void cryptodev_vhost_virtqueue_mask(VirtIODevice
*dev
,
275 VirtIOCrypto
*vcrypto
= VIRTIO_CRYPTO(dev
);
276 CryptoDevBackend
*b
= vcrypto
->cryptodev
;
277 CryptoDevBackendVhost
*vhost_crypto
;
278 CryptoDevBackendClient
*cc
;
280 assert(queue
< MAX_CRYPTO_QUEUE_NUM
);
282 cc
= b
->conf
.peers
.ccs
[queue
];
283 vhost_crypto
= cryptodev_get_vhost(cc
, b
, queue
);
285 vhost_virtqueue_mask(&vhost_crypto
->dev
, dev
, idx
, mask
);
288 bool cryptodev_vhost_virtqueue_pending(VirtIODevice
*dev
,
291 VirtIOCrypto
*vcrypto
= VIRTIO_CRYPTO(dev
);
292 CryptoDevBackend
*b
= vcrypto
->cryptodev
;
293 CryptoDevBackendVhost
*vhost_crypto
;
294 CryptoDevBackendClient
*cc
;
296 assert(queue
< MAX_CRYPTO_QUEUE_NUM
);
298 cc
= b
->conf
.peers
.ccs
[queue
];
299 vhost_crypto
= cryptodev_get_vhost(cc
, b
, queue
);
301 return vhost_virtqueue_pending(&vhost_crypto
->dev
, idx
);
306 cryptodev_vhost_get_max_queues(CryptoDevBackendVhost
*crypto
)
311 void cryptodev_vhost_cleanup(CryptoDevBackendVhost
*crypto
)
315 struct CryptoDevBackendVhost
*
316 cryptodev_vhost_init(CryptoDevBackendVhostOptions
*options
)
321 CryptoDevBackendVhost
*
322 cryptodev_get_vhost(CryptoDevBackendClient
*cc
,
329 int cryptodev_vhost_start(VirtIODevice
*dev
, int total_queues
)
334 void cryptodev_vhost_stop(VirtIODevice
*dev
, int total_queues
)
338 void cryptodev_vhost_virtqueue_mask(VirtIODevice
*dev
,
344 bool cryptodev_vhost_virtqueue_pending(VirtIODevice
*dev
,