2
0

cryptodev-vhost.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. /*
  2. * QEMU Cryptodev backend for QEMU cipher APIs
  3. *
  4. * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
  5. *
  6. * Authors:
  7. * Gonglei <arei.gonglei@huawei.com>
  8. * Jay Zhou <jianjay.zhou@huawei.com>
  9. *
  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 of the License, or (at your option) any later version.
  14. *
  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.
  19. *
  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/>.
  22. *
  23. */
  24. #include "qemu/osdep.h"
  25. #include "hw/virtio/virtio-bus.h"
  26. #include "sysemu/cryptodev-vhost.h"
  27. #ifdef CONFIG_VHOST_CRYPTO
  28. #include "qapi/error.h"
  29. #include "qapi/qmp/qerror.h"
  30. #include "qemu/error-report.h"
  31. #include "hw/virtio/virtio-crypto.h"
  32. #include "sysemu/cryptodev-vhost-user.h"
  33. uint64_t
  34. cryptodev_vhost_get_max_queues(
  35. CryptoDevBackendVhost *crypto)
  36. {
  37. return crypto->dev.max_queues;
  38. }
  39. void cryptodev_vhost_cleanup(CryptoDevBackendVhost *crypto)
  40. {
  41. vhost_dev_cleanup(&crypto->dev);
  42. g_free(crypto);
  43. }
  44. struct CryptoDevBackendVhost *
  45. cryptodev_vhost_init(
  46. CryptoDevBackendVhostOptions *options)
  47. {
  48. int r;
  49. CryptoDevBackendVhost *crypto;
  50. crypto = g_new(CryptoDevBackendVhost, 1);
  51. crypto->dev.max_queues = 1;
  52. crypto->dev.nvqs = 1;
  53. crypto->dev.vqs = crypto->vqs;
  54. crypto->cc = options->cc;
  55. crypto->dev.protocol_features = 0;
  56. crypto->backend = -1;
  57. /* vhost-user needs vq_index to initiate a specific queue pair */
  58. crypto->dev.vq_index = crypto->cc->queue_index * crypto->dev.nvqs;
  59. r = vhost_dev_init(&crypto->dev, options->opaque, options->backend_type, 0);
  60. if (r < 0) {
  61. goto fail;
  62. }
  63. return crypto;
  64. fail:
  65. g_free(crypto);
  66. return NULL;
  67. }
  68. static int
  69. cryptodev_vhost_start_one(CryptoDevBackendVhost *crypto,
  70. VirtIODevice *dev)
  71. {
  72. int r;
  73. crypto->dev.nvqs = 1;
  74. crypto->dev.vqs = crypto->vqs;
  75. r = vhost_dev_enable_notifiers(&crypto->dev, dev);
  76. if (r < 0) {
  77. goto fail_notifiers;
  78. }
  79. r = vhost_dev_start(&crypto->dev, dev);
  80. if (r < 0) {
  81. goto fail_start;
  82. }
  83. return 0;
  84. fail_start:
  85. vhost_dev_disable_notifiers(&crypto->dev, dev);
  86. fail_notifiers:
  87. return r;
  88. }
  89. static void
  90. cryptodev_vhost_stop_one(CryptoDevBackendVhost *crypto,
  91. VirtIODevice *dev)
  92. {
  93. vhost_dev_stop(&crypto->dev, dev);
  94. vhost_dev_disable_notifiers(&crypto->dev, dev);
  95. }
  96. CryptoDevBackendVhost *
  97. cryptodev_get_vhost(CryptoDevBackendClient *cc,
  98. CryptoDevBackend *b,
  99. uint16_t queue)
  100. {
  101. CryptoDevBackendVhost *vhost_crypto = NULL;
  102. if (!cc) {
  103. return NULL;
  104. }
  105. switch (cc->type) {
  106. #if defined(CONFIG_VHOST_USER) && defined(CONFIG_LINUX)
  107. case CRYPTODEV_BACKEND_TYPE_VHOST_USER:
  108. vhost_crypto = cryptodev_vhost_user_get_vhost(cc, b, queue);
  109. break;
  110. #endif
  111. default:
  112. break;
  113. }
  114. return vhost_crypto;
  115. }
  116. static void
  117. cryptodev_vhost_set_vq_index(CryptoDevBackendVhost *crypto,
  118. int vq_index)
  119. {
  120. crypto->dev.vq_index = vq_index;
  121. }
  122. static int
  123. vhost_set_vring_enable(CryptoDevBackendClient *cc,
  124. CryptoDevBackend *b,
  125. uint16_t queue, int enable)
  126. {
  127. CryptoDevBackendVhost *crypto =
  128. cryptodev_get_vhost(cc, b, queue);
  129. const VhostOps *vhost_ops;
  130. cc->vring_enable = enable;
  131. if (!crypto) {
  132. return 0;
  133. }
  134. vhost_ops = crypto->dev.vhost_ops;
  135. if (vhost_ops->vhost_set_vring_enable) {
  136. return vhost_ops->vhost_set_vring_enable(&crypto->dev, enable);
  137. }
  138. return 0;
  139. }
  140. int cryptodev_vhost_start(VirtIODevice *dev, int total_queues)
  141. {
  142. VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(dev);
  143. BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev)));
  144. VirtioBusState *vbus = VIRTIO_BUS(qbus);
  145. VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
  146. int r, e;
  147. int i;
  148. CryptoDevBackend *b = vcrypto->cryptodev;
  149. CryptoDevBackendVhost *vhost_crypto;
  150. CryptoDevBackendClient *cc;
  151. if (!k->set_guest_notifiers) {
  152. error_report("binding does not support guest notifiers");
  153. return -ENOSYS;
  154. }
  155. for (i = 0; i < total_queues; i++) {
  156. cc = b->conf.peers.ccs[i];
  157. vhost_crypto = cryptodev_get_vhost(cc, b, i);
  158. cryptodev_vhost_set_vq_index(vhost_crypto, i);
  159. /* Suppress the masking guest notifiers on vhost user
  160. * because vhost user doesn't interrupt masking/unmasking
  161. * properly.
  162. */
  163. if (cc->type == CRYPTODEV_BACKEND_TYPE_VHOST_USER) {
  164. dev->use_guest_notifier_mask = false;
  165. }
  166. }
  167. r = k->set_guest_notifiers(qbus->parent, total_queues, true);
  168. if (r < 0) {
  169. error_report("error binding guest notifier: %d", -r);
  170. goto err;
  171. }
  172. for (i = 0; i < total_queues; i++) {
  173. cc = b->conf.peers.ccs[i];
  174. vhost_crypto = cryptodev_get_vhost(cc, b, i);
  175. r = cryptodev_vhost_start_one(vhost_crypto, dev);
  176. if (r < 0) {
  177. goto err_start;
  178. }
  179. if (cc->vring_enable) {
  180. /* restore vring enable state */
  181. r = vhost_set_vring_enable(cc, b, i, cc->vring_enable);
  182. if (r < 0) {
  183. goto err_start;
  184. }
  185. }
  186. }
  187. return 0;
  188. err_start:
  189. while (--i >= 0) {
  190. cc = b->conf.peers.ccs[i];
  191. vhost_crypto = cryptodev_get_vhost(cc, b, i);
  192. cryptodev_vhost_stop_one(vhost_crypto, dev);
  193. }
  194. e = k->set_guest_notifiers(qbus->parent, total_queues, false);
  195. if (e < 0) {
  196. error_report("vhost guest notifier cleanup failed: %d", e);
  197. }
  198. err:
  199. return r;
  200. }
  201. void cryptodev_vhost_stop(VirtIODevice *dev, int total_queues)
  202. {
  203. BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev)));
  204. VirtioBusState *vbus = VIRTIO_BUS(qbus);
  205. VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus);
  206. VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(dev);
  207. CryptoDevBackend *b = vcrypto->cryptodev;
  208. CryptoDevBackendVhost *vhost_crypto;
  209. CryptoDevBackendClient *cc;
  210. size_t i;
  211. int r;
  212. for (i = 0; i < total_queues; i++) {
  213. cc = b->conf.peers.ccs[i];
  214. vhost_crypto = cryptodev_get_vhost(cc, b, i);
  215. cryptodev_vhost_stop_one(vhost_crypto, dev);
  216. }
  217. r = k->set_guest_notifiers(qbus->parent, total_queues, false);
  218. if (r < 0) {
  219. error_report("vhost guest notifier cleanup failed: %d", r);
  220. }
  221. assert(r >= 0);
  222. }
  223. void cryptodev_vhost_virtqueue_mask(VirtIODevice *dev,
  224. int queue,
  225. int idx, bool mask)
  226. {
  227. VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(dev);
  228. CryptoDevBackend *b = vcrypto->cryptodev;
  229. CryptoDevBackendVhost *vhost_crypto;
  230. CryptoDevBackendClient *cc;
  231. assert(queue < MAX_CRYPTO_QUEUE_NUM);
  232. cc = b->conf.peers.ccs[queue];
  233. vhost_crypto = cryptodev_get_vhost(cc, b, queue);
  234. vhost_virtqueue_mask(&vhost_crypto->dev, dev, idx, mask);
  235. }
  236. bool cryptodev_vhost_virtqueue_pending(VirtIODevice *dev,
  237. int queue, int idx)
  238. {
  239. VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(dev);
  240. CryptoDevBackend *b = vcrypto->cryptodev;
  241. CryptoDevBackendVhost *vhost_crypto;
  242. CryptoDevBackendClient *cc;
  243. assert(queue < MAX_CRYPTO_QUEUE_NUM);
  244. cc = b->conf.peers.ccs[queue];
  245. vhost_crypto = cryptodev_get_vhost(cc, b, queue);
  246. return vhost_virtqueue_pending(&vhost_crypto->dev, idx);
  247. }
  248. #else
  249. uint64_t
  250. cryptodev_vhost_get_max_queues(CryptoDevBackendVhost *crypto)
  251. {
  252. return 0;
  253. }
  254. void cryptodev_vhost_cleanup(CryptoDevBackendVhost *crypto)
  255. {
  256. }
  257. struct CryptoDevBackendVhost *
  258. cryptodev_vhost_init(CryptoDevBackendVhostOptions *options)
  259. {
  260. return NULL;
  261. }
  262. CryptoDevBackendVhost *
  263. cryptodev_get_vhost(CryptoDevBackendClient *cc,
  264. CryptoDevBackend *b,
  265. uint16_t queue)
  266. {
  267. return NULL;
  268. }
  269. int cryptodev_vhost_start(VirtIODevice *dev, int total_queues)
  270. {
  271. return -1;
  272. }
  273. void cryptodev_vhost_stop(VirtIODevice *dev, int total_queues)
  274. {
  275. }
  276. void cryptodev_vhost_virtqueue_mask(VirtIODevice *dev,
  277. int queue,
  278. int idx, bool mask)
  279. {
  280. }
  281. bool cryptodev_vhost_virtqueue_pending(VirtIODevice *dev,
  282. int queue, int idx)
  283. {
  284. return false;
  285. }
  286. #endif