vhost-user.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931
  1. /*
  2. * vhost-user
  3. *
  4. * Copyright (c) 2013 Virtual Open Systems Sarl.
  5. *
  6. * This work is licensed under the terms of the GNU GPL, version 2 or later.
  7. * See the COPYING file in the top-level directory.
  8. *
  9. */
  10. #include "qemu/osdep.h"
  11. #include "qapi/error.h"
  12. #include "hw/virtio/vhost.h"
  13. #include "hw/virtio/vhost-backend.h"
  14. #include "hw/virtio/virtio-net.h"
  15. #include "chardev/char-fe.h"
  16. #include "sysemu/kvm.h"
  17. #include "qemu/error-report.h"
  18. #include "qemu/sockets.h"
  19. #include <sys/ioctl.h>
  20. #include <sys/socket.h>
  21. #include <sys/un.h>
  22. #include <linux/vhost.h>
  23. #define VHOST_MEMORY_MAX_NREGIONS 8
  24. #define VHOST_USER_F_PROTOCOL_FEATURES 30
  25. enum VhostUserProtocolFeature {
  26. VHOST_USER_PROTOCOL_F_MQ = 0,
  27. VHOST_USER_PROTOCOL_F_LOG_SHMFD = 1,
  28. VHOST_USER_PROTOCOL_F_RARP = 2,
  29. VHOST_USER_PROTOCOL_F_REPLY_ACK = 3,
  30. VHOST_USER_PROTOCOL_F_NET_MTU = 4,
  31. VHOST_USER_PROTOCOL_F_SLAVE_REQ = 5,
  32. VHOST_USER_PROTOCOL_F_MAX
  33. };
  34. #define VHOST_USER_PROTOCOL_FEATURE_MASK ((1 << VHOST_USER_PROTOCOL_F_MAX) - 1)
  35. typedef enum VhostUserRequest {
  36. VHOST_USER_NONE = 0,
  37. VHOST_USER_GET_FEATURES = 1,
  38. VHOST_USER_SET_FEATURES = 2,
  39. VHOST_USER_SET_OWNER = 3,
  40. VHOST_USER_RESET_OWNER = 4,
  41. VHOST_USER_SET_MEM_TABLE = 5,
  42. VHOST_USER_SET_LOG_BASE = 6,
  43. VHOST_USER_SET_LOG_FD = 7,
  44. VHOST_USER_SET_VRING_NUM = 8,
  45. VHOST_USER_SET_VRING_ADDR = 9,
  46. VHOST_USER_SET_VRING_BASE = 10,
  47. VHOST_USER_GET_VRING_BASE = 11,
  48. VHOST_USER_SET_VRING_KICK = 12,
  49. VHOST_USER_SET_VRING_CALL = 13,
  50. VHOST_USER_SET_VRING_ERR = 14,
  51. VHOST_USER_GET_PROTOCOL_FEATURES = 15,
  52. VHOST_USER_SET_PROTOCOL_FEATURES = 16,
  53. VHOST_USER_GET_QUEUE_NUM = 17,
  54. VHOST_USER_SET_VRING_ENABLE = 18,
  55. VHOST_USER_SEND_RARP = 19,
  56. VHOST_USER_NET_SET_MTU = 20,
  57. VHOST_USER_SET_SLAVE_REQ_FD = 21,
  58. VHOST_USER_IOTLB_MSG = 22,
  59. VHOST_USER_MAX
  60. } VhostUserRequest;
  61. typedef enum VhostUserSlaveRequest {
  62. VHOST_USER_SLAVE_NONE = 0,
  63. VHOST_USER_SLAVE_IOTLB_MSG = 1,
  64. VHOST_USER_SLAVE_MAX
  65. } VhostUserSlaveRequest;
  66. typedef struct VhostUserMemoryRegion {
  67. uint64_t guest_phys_addr;
  68. uint64_t memory_size;
  69. uint64_t userspace_addr;
  70. uint64_t mmap_offset;
  71. } VhostUserMemoryRegion;
  72. typedef struct VhostUserMemory {
  73. uint32_t nregions;
  74. uint32_t padding;
  75. VhostUserMemoryRegion regions[VHOST_MEMORY_MAX_NREGIONS];
  76. } VhostUserMemory;
  77. typedef struct VhostUserLog {
  78. uint64_t mmap_size;
  79. uint64_t mmap_offset;
  80. } VhostUserLog;
  81. typedef struct VhostUserMsg {
  82. VhostUserRequest request;
  83. #define VHOST_USER_VERSION_MASK (0x3)
  84. #define VHOST_USER_REPLY_MASK (0x1<<2)
  85. #define VHOST_USER_NEED_REPLY_MASK (0x1 << 3)
  86. uint32_t flags;
  87. uint32_t size; /* the following payload size */
  88. union {
  89. #define VHOST_USER_VRING_IDX_MASK (0xff)
  90. #define VHOST_USER_VRING_NOFD_MASK (0x1<<8)
  91. uint64_t u64;
  92. struct vhost_vring_state state;
  93. struct vhost_vring_addr addr;
  94. VhostUserMemory memory;
  95. VhostUserLog log;
  96. struct vhost_iotlb_msg iotlb;
  97. } payload;
  98. } QEMU_PACKED VhostUserMsg;
  99. static VhostUserMsg m __attribute__ ((unused));
  100. #define VHOST_USER_HDR_SIZE (sizeof(m.request) \
  101. + sizeof(m.flags) \
  102. + sizeof(m.size))
  103. #define VHOST_USER_PAYLOAD_SIZE (sizeof(m) - VHOST_USER_HDR_SIZE)
  104. /* The version of the protocol we support */
  105. #define VHOST_USER_VERSION (0x1)
  106. struct vhost_user {
  107. CharBackend *chr;
  108. int slave_fd;
  109. };
  110. static bool ioeventfd_enabled(void)
  111. {
  112. return kvm_enabled() && kvm_eventfds_enabled();
  113. }
  114. static int vhost_user_read(struct vhost_dev *dev, VhostUserMsg *msg)
  115. {
  116. struct vhost_user *u = dev->opaque;
  117. CharBackend *chr = u->chr;
  118. uint8_t *p = (uint8_t *) msg;
  119. int r, size = VHOST_USER_HDR_SIZE;
  120. r = qemu_chr_fe_read_all(chr, p, size);
  121. if (r != size) {
  122. error_report("Failed to read msg header. Read %d instead of %d."
  123. " Original request %d.", r, size, msg->request);
  124. goto fail;
  125. }
  126. /* validate received flags */
  127. if (msg->flags != (VHOST_USER_REPLY_MASK | VHOST_USER_VERSION)) {
  128. error_report("Failed to read msg header."
  129. " Flags 0x%x instead of 0x%x.", msg->flags,
  130. VHOST_USER_REPLY_MASK | VHOST_USER_VERSION);
  131. goto fail;
  132. }
  133. /* validate message size is sane */
  134. if (msg->size > VHOST_USER_PAYLOAD_SIZE) {
  135. error_report("Failed to read msg header."
  136. " Size %d exceeds the maximum %zu.", msg->size,
  137. VHOST_USER_PAYLOAD_SIZE);
  138. goto fail;
  139. }
  140. if (msg->size) {
  141. p += VHOST_USER_HDR_SIZE;
  142. size = msg->size;
  143. r = qemu_chr_fe_read_all(chr, p, size);
  144. if (r != size) {
  145. error_report("Failed to read msg payload."
  146. " Read %d instead of %d.", r, msg->size);
  147. goto fail;
  148. }
  149. }
  150. return 0;
  151. fail:
  152. return -1;
  153. }
  154. static int process_message_reply(struct vhost_dev *dev,
  155. const VhostUserMsg *msg)
  156. {
  157. VhostUserMsg msg_reply;
  158. if ((msg->flags & VHOST_USER_NEED_REPLY_MASK) == 0) {
  159. return 0;
  160. }
  161. if (vhost_user_read(dev, &msg_reply) < 0) {
  162. return -1;
  163. }
  164. if (msg_reply.request != msg->request) {
  165. error_report("Received unexpected msg type."
  166. "Expected %d received %d",
  167. msg->request, msg_reply.request);
  168. return -1;
  169. }
  170. return msg_reply.payload.u64 ? -1 : 0;
  171. }
  172. static bool vhost_user_one_time_request(VhostUserRequest request)
  173. {
  174. switch (request) {
  175. case VHOST_USER_SET_OWNER:
  176. case VHOST_USER_RESET_OWNER:
  177. case VHOST_USER_SET_MEM_TABLE:
  178. case VHOST_USER_GET_QUEUE_NUM:
  179. case VHOST_USER_NET_SET_MTU:
  180. return true;
  181. default:
  182. return false;
  183. }
  184. }
  185. /* most non-init callers ignore the error */
  186. static int vhost_user_write(struct vhost_dev *dev, VhostUserMsg *msg,
  187. int *fds, int fd_num)
  188. {
  189. struct vhost_user *u = dev->opaque;
  190. CharBackend *chr = u->chr;
  191. int ret, size = VHOST_USER_HDR_SIZE + msg->size;
  192. /*
  193. * For non-vring specific requests, like VHOST_USER_SET_MEM_TABLE,
  194. * we just need send it once in the first time. For later such
  195. * request, we just ignore it.
  196. */
  197. if (vhost_user_one_time_request(msg->request) && dev->vq_index != 0) {
  198. msg->flags &= ~VHOST_USER_NEED_REPLY_MASK;
  199. return 0;
  200. }
  201. if (qemu_chr_fe_set_msgfds(chr, fds, fd_num) < 0) {
  202. error_report("Failed to set msg fds.");
  203. return -1;
  204. }
  205. ret = qemu_chr_fe_write_all(chr, (const uint8_t *) msg, size);
  206. if (ret != size) {
  207. error_report("Failed to write msg."
  208. " Wrote %d instead of %d.", ret, size);
  209. return -1;
  210. }
  211. return 0;
  212. }
  213. static int vhost_user_set_log_base(struct vhost_dev *dev, uint64_t base,
  214. struct vhost_log *log)
  215. {
  216. int fds[VHOST_MEMORY_MAX_NREGIONS];
  217. size_t fd_num = 0;
  218. bool shmfd = virtio_has_feature(dev->protocol_features,
  219. VHOST_USER_PROTOCOL_F_LOG_SHMFD);
  220. VhostUserMsg msg = {
  221. .request = VHOST_USER_SET_LOG_BASE,
  222. .flags = VHOST_USER_VERSION,
  223. .payload.log.mmap_size = log->size * sizeof(*(log->log)),
  224. .payload.log.mmap_offset = 0,
  225. .size = sizeof(msg.payload.log),
  226. };
  227. if (shmfd && log->fd != -1) {
  228. fds[fd_num++] = log->fd;
  229. }
  230. if (vhost_user_write(dev, &msg, fds, fd_num) < 0) {
  231. return -1;
  232. }
  233. if (shmfd) {
  234. msg.size = 0;
  235. if (vhost_user_read(dev, &msg) < 0) {
  236. return -1;
  237. }
  238. if (msg.request != VHOST_USER_SET_LOG_BASE) {
  239. error_report("Received unexpected msg type. "
  240. "Expected %d received %d",
  241. VHOST_USER_SET_LOG_BASE, msg.request);
  242. return -1;
  243. }
  244. }
  245. return 0;
  246. }
  247. static int vhost_user_set_mem_table(struct vhost_dev *dev,
  248. struct vhost_memory *mem)
  249. {
  250. int fds[VHOST_MEMORY_MAX_NREGIONS];
  251. int i, fd;
  252. size_t fd_num = 0;
  253. bool reply_supported = virtio_has_feature(dev->protocol_features,
  254. VHOST_USER_PROTOCOL_F_REPLY_ACK);
  255. VhostUserMsg msg = {
  256. .request = VHOST_USER_SET_MEM_TABLE,
  257. .flags = VHOST_USER_VERSION,
  258. };
  259. if (reply_supported) {
  260. msg.flags |= VHOST_USER_NEED_REPLY_MASK;
  261. }
  262. for (i = 0; i < dev->mem->nregions; ++i) {
  263. struct vhost_memory_region *reg = dev->mem->regions + i;
  264. ram_addr_t offset;
  265. MemoryRegion *mr;
  266. assert((uintptr_t)reg->userspace_addr == reg->userspace_addr);
  267. mr = memory_region_from_host((void *)(uintptr_t)reg->userspace_addr,
  268. &offset);
  269. fd = memory_region_get_fd(mr);
  270. if (fd > 0) {
  271. msg.payload.memory.regions[fd_num].userspace_addr = reg->userspace_addr;
  272. msg.payload.memory.regions[fd_num].memory_size = reg->memory_size;
  273. msg.payload.memory.regions[fd_num].guest_phys_addr = reg->guest_phys_addr;
  274. msg.payload.memory.regions[fd_num].mmap_offset = offset;
  275. assert(fd_num < VHOST_MEMORY_MAX_NREGIONS);
  276. fds[fd_num++] = fd;
  277. }
  278. }
  279. msg.payload.memory.nregions = fd_num;
  280. if (!fd_num) {
  281. error_report("Failed initializing vhost-user memory map, "
  282. "consider using -object memory-backend-file share=on");
  283. return -1;
  284. }
  285. msg.size = sizeof(msg.payload.memory.nregions);
  286. msg.size += sizeof(msg.payload.memory.padding);
  287. msg.size += fd_num * sizeof(VhostUserMemoryRegion);
  288. if (vhost_user_write(dev, &msg, fds, fd_num) < 0) {
  289. return -1;
  290. }
  291. if (reply_supported) {
  292. return process_message_reply(dev, &msg);
  293. }
  294. return 0;
  295. }
  296. static int vhost_user_set_vring_addr(struct vhost_dev *dev,
  297. struct vhost_vring_addr *addr)
  298. {
  299. VhostUserMsg msg = {
  300. .request = VHOST_USER_SET_VRING_ADDR,
  301. .flags = VHOST_USER_VERSION,
  302. .payload.addr = *addr,
  303. .size = sizeof(msg.payload.addr),
  304. };
  305. if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
  306. return -1;
  307. }
  308. return 0;
  309. }
  310. static int vhost_user_set_vring_endian(struct vhost_dev *dev,
  311. struct vhost_vring_state *ring)
  312. {
  313. error_report("vhost-user trying to send unhandled ioctl");
  314. return -1;
  315. }
  316. static int vhost_set_vring(struct vhost_dev *dev,
  317. unsigned long int request,
  318. struct vhost_vring_state *ring)
  319. {
  320. VhostUserMsg msg = {
  321. .request = request,
  322. .flags = VHOST_USER_VERSION,
  323. .payload.state = *ring,
  324. .size = sizeof(msg.payload.state),
  325. };
  326. if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
  327. return -1;
  328. }
  329. return 0;
  330. }
  331. static int vhost_user_set_vring_num(struct vhost_dev *dev,
  332. struct vhost_vring_state *ring)
  333. {
  334. return vhost_set_vring(dev, VHOST_USER_SET_VRING_NUM, ring);
  335. }
  336. static int vhost_user_set_vring_base(struct vhost_dev *dev,
  337. struct vhost_vring_state *ring)
  338. {
  339. return vhost_set_vring(dev, VHOST_USER_SET_VRING_BASE, ring);
  340. }
  341. static int vhost_user_set_vring_enable(struct vhost_dev *dev, int enable)
  342. {
  343. int i;
  344. if (!virtio_has_feature(dev->features, VHOST_USER_F_PROTOCOL_FEATURES)) {
  345. return -1;
  346. }
  347. for (i = 0; i < dev->nvqs; ++i) {
  348. struct vhost_vring_state state = {
  349. .index = dev->vq_index + i,
  350. .num = enable,
  351. };
  352. vhost_set_vring(dev, VHOST_USER_SET_VRING_ENABLE, &state);
  353. }
  354. return 0;
  355. }
  356. static int vhost_user_get_vring_base(struct vhost_dev *dev,
  357. struct vhost_vring_state *ring)
  358. {
  359. VhostUserMsg msg = {
  360. .request = VHOST_USER_GET_VRING_BASE,
  361. .flags = VHOST_USER_VERSION,
  362. .payload.state = *ring,
  363. .size = sizeof(msg.payload.state),
  364. };
  365. if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
  366. return -1;
  367. }
  368. if (vhost_user_read(dev, &msg) < 0) {
  369. return -1;
  370. }
  371. if (msg.request != VHOST_USER_GET_VRING_BASE) {
  372. error_report("Received unexpected msg type. Expected %d received %d",
  373. VHOST_USER_GET_VRING_BASE, msg.request);
  374. return -1;
  375. }
  376. if (msg.size != sizeof(msg.payload.state)) {
  377. error_report("Received bad msg size.");
  378. return -1;
  379. }
  380. *ring = msg.payload.state;
  381. return 0;
  382. }
  383. static int vhost_set_vring_file(struct vhost_dev *dev,
  384. VhostUserRequest request,
  385. struct vhost_vring_file *file)
  386. {
  387. int fds[VHOST_MEMORY_MAX_NREGIONS];
  388. size_t fd_num = 0;
  389. VhostUserMsg msg = {
  390. .request = request,
  391. .flags = VHOST_USER_VERSION,
  392. .payload.u64 = file->index & VHOST_USER_VRING_IDX_MASK,
  393. .size = sizeof(msg.payload.u64),
  394. };
  395. if (ioeventfd_enabled() && file->fd > 0) {
  396. fds[fd_num++] = file->fd;
  397. } else {
  398. msg.payload.u64 |= VHOST_USER_VRING_NOFD_MASK;
  399. }
  400. if (vhost_user_write(dev, &msg, fds, fd_num) < 0) {
  401. return -1;
  402. }
  403. return 0;
  404. }
  405. static int vhost_user_set_vring_kick(struct vhost_dev *dev,
  406. struct vhost_vring_file *file)
  407. {
  408. return vhost_set_vring_file(dev, VHOST_USER_SET_VRING_KICK, file);
  409. }
  410. static int vhost_user_set_vring_call(struct vhost_dev *dev,
  411. struct vhost_vring_file *file)
  412. {
  413. return vhost_set_vring_file(dev, VHOST_USER_SET_VRING_CALL, file);
  414. }
  415. static int vhost_user_set_u64(struct vhost_dev *dev, int request, uint64_t u64)
  416. {
  417. VhostUserMsg msg = {
  418. .request = request,
  419. .flags = VHOST_USER_VERSION,
  420. .payload.u64 = u64,
  421. .size = sizeof(msg.payload.u64),
  422. };
  423. if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
  424. return -1;
  425. }
  426. return 0;
  427. }
  428. static int vhost_user_set_features(struct vhost_dev *dev,
  429. uint64_t features)
  430. {
  431. return vhost_user_set_u64(dev, VHOST_USER_SET_FEATURES, features);
  432. }
  433. static int vhost_user_set_protocol_features(struct vhost_dev *dev,
  434. uint64_t features)
  435. {
  436. return vhost_user_set_u64(dev, VHOST_USER_SET_PROTOCOL_FEATURES, features);
  437. }
  438. static int vhost_user_get_u64(struct vhost_dev *dev, int request, uint64_t *u64)
  439. {
  440. VhostUserMsg msg = {
  441. .request = request,
  442. .flags = VHOST_USER_VERSION,
  443. };
  444. if (vhost_user_one_time_request(request) && dev->vq_index != 0) {
  445. return 0;
  446. }
  447. if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
  448. return -1;
  449. }
  450. if (vhost_user_read(dev, &msg) < 0) {
  451. return -1;
  452. }
  453. if (msg.request != request) {
  454. error_report("Received unexpected msg type. Expected %d received %d",
  455. request, msg.request);
  456. return -1;
  457. }
  458. if (msg.size != sizeof(msg.payload.u64)) {
  459. error_report("Received bad msg size.");
  460. return -1;
  461. }
  462. *u64 = msg.payload.u64;
  463. return 0;
  464. }
  465. static int vhost_user_get_features(struct vhost_dev *dev, uint64_t *features)
  466. {
  467. return vhost_user_get_u64(dev, VHOST_USER_GET_FEATURES, features);
  468. }
  469. static int vhost_user_set_owner(struct vhost_dev *dev)
  470. {
  471. VhostUserMsg msg = {
  472. .request = VHOST_USER_SET_OWNER,
  473. .flags = VHOST_USER_VERSION,
  474. };
  475. if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
  476. return -1;
  477. }
  478. return 0;
  479. }
  480. static int vhost_user_reset_device(struct vhost_dev *dev)
  481. {
  482. VhostUserMsg msg = {
  483. .request = VHOST_USER_RESET_OWNER,
  484. .flags = VHOST_USER_VERSION,
  485. };
  486. if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
  487. return -1;
  488. }
  489. return 0;
  490. }
  491. static void slave_read(void *opaque)
  492. {
  493. struct vhost_dev *dev = opaque;
  494. struct vhost_user *u = dev->opaque;
  495. VhostUserMsg msg = { 0, };
  496. int size, ret = 0;
  497. /* Read header */
  498. size = read(u->slave_fd, &msg, VHOST_USER_HDR_SIZE);
  499. if (size != VHOST_USER_HDR_SIZE) {
  500. error_report("Failed to read from slave.");
  501. goto err;
  502. }
  503. if (msg.size > VHOST_USER_PAYLOAD_SIZE) {
  504. error_report("Failed to read msg header."
  505. " Size %d exceeds the maximum %zu.", msg.size,
  506. VHOST_USER_PAYLOAD_SIZE);
  507. goto err;
  508. }
  509. /* Read payload */
  510. size = read(u->slave_fd, &msg.payload, msg.size);
  511. if (size != msg.size) {
  512. error_report("Failed to read payload from slave.");
  513. goto err;
  514. }
  515. switch (msg.request) {
  516. case VHOST_USER_SLAVE_IOTLB_MSG:
  517. ret = vhost_backend_handle_iotlb_msg(dev, &msg.payload.iotlb);
  518. break;
  519. default:
  520. error_report("Received unexpected msg type.");
  521. ret = -EINVAL;
  522. }
  523. /*
  524. * REPLY_ACK feature handling. Other reply types has to be managed
  525. * directly in their request handlers.
  526. */
  527. if (msg.flags & VHOST_USER_NEED_REPLY_MASK) {
  528. msg.flags &= ~VHOST_USER_NEED_REPLY_MASK;
  529. msg.flags |= VHOST_USER_REPLY_MASK;
  530. msg.payload.u64 = !!ret;
  531. msg.size = sizeof(msg.payload.u64);
  532. size = write(u->slave_fd, &msg, VHOST_USER_HDR_SIZE + msg.size);
  533. if (size != VHOST_USER_HDR_SIZE + msg.size) {
  534. error_report("Failed to send msg reply to slave.");
  535. goto err;
  536. }
  537. }
  538. return;
  539. err:
  540. qemu_set_fd_handler(u->slave_fd, NULL, NULL, NULL);
  541. close(u->slave_fd);
  542. u->slave_fd = -1;
  543. return;
  544. }
  545. static int vhost_setup_slave_channel(struct vhost_dev *dev)
  546. {
  547. VhostUserMsg msg = {
  548. .request = VHOST_USER_SET_SLAVE_REQ_FD,
  549. .flags = VHOST_USER_VERSION,
  550. };
  551. struct vhost_user *u = dev->opaque;
  552. int sv[2], ret = 0;
  553. bool reply_supported = virtio_has_feature(dev->protocol_features,
  554. VHOST_USER_PROTOCOL_F_REPLY_ACK);
  555. if (!virtio_has_feature(dev->protocol_features,
  556. VHOST_USER_PROTOCOL_F_SLAVE_REQ)) {
  557. return 0;
  558. }
  559. if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1) {
  560. error_report("socketpair() failed");
  561. return -1;
  562. }
  563. u->slave_fd = sv[0];
  564. qemu_set_fd_handler(u->slave_fd, slave_read, NULL, dev);
  565. if (reply_supported) {
  566. msg.flags |= VHOST_USER_NEED_REPLY_MASK;
  567. }
  568. ret = vhost_user_write(dev, &msg, &sv[1], 1);
  569. if (ret) {
  570. goto out;
  571. }
  572. if (reply_supported) {
  573. ret = process_message_reply(dev, &msg);
  574. }
  575. out:
  576. close(sv[1]);
  577. if (ret) {
  578. qemu_set_fd_handler(u->slave_fd, NULL, NULL, NULL);
  579. close(u->slave_fd);
  580. u->slave_fd = -1;
  581. }
  582. return ret;
  583. }
  584. static int vhost_user_init(struct vhost_dev *dev, void *opaque)
  585. {
  586. uint64_t features, protocol_features;
  587. struct vhost_user *u;
  588. int err;
  589. assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
  590. u = g_new0(struct vhost_user, 1);
  591. u->chr = opaque;
  592. u->slave_fd = -1;
  593. dev->opaque = u;
  594. err = vhost_user_get_features(dev, &features);
  595. if (err < 0) {
  596. return err;
  597. }
  598. if (virtio_has_feature(features, VHOST_USER_F_PROTOCOL_FEATURES)) {
  599. dev->backend_features |= 1ULL << VHOST_USER_F_PROTOCOL_FEATURES;
  600. err = vhost_user_get_u64(dev, VHOST_USER_GET_PROTOCOL_FEATURES,
  601. &protocol_features);
  602. if (err < 0) {
  603. return err;
  604. }
  605. dev->protocol_features =
  606. protocol_features & VHOST_USER_PROTOCOL_FEATURE_MASK;
  607. err = vhost_user_set_protocol_features(dev, dev->protocol_features);
  608. if (err < 0) {
  609. return err;
  610. }
  611. /* query the max queues we support if backend supports Multiple Queue */
  612. if (dev->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_MQ)) {
  613. err = vhost_user_get_u64(dev, VHOST_USER_GET_QUEUE_NUM,
  614. &dev->max_queues);
  615. if (err < 0) {
  616. return err;
  617. }
  618. }
  619. if (virtio_has_feature(features, VIRTIO_F_IOMMU_PLATFORM) &&
  620. !(virtio_has_feature(dev->protocol_features,
  621. VHOST_USER_PROTOCOL_F_SLAVE_REQ) &&
  622. virtio_has_feature(dev->protocol_features,
  623. VHOST_USER_PROTOCOL_F_REPLY_ACK))) {
  624. error_report("IOMMU support requires reply-ack and "
  625. "slave-req protocol features.");
  626. return -1;
  627. }
  628. }
  629. if (dev->migration_blocker == NULL &&
  630. !virtio_has_feature(dev->protocol_features,
  631. VHOST_USER_PROTOCOL_F_LOG_SHMFD)) {
  632. error_setg(&dev->migration_blocker,
  633. "Migration disabled: vhost-user backend lacks "
  634. "VHOST_USER_PROTOCOL_F_LOG_SHMFD feature.");
  635. }
  636. err = vhost_setup_slave_channel(dev);
  637. if (err < 0) {
  638. return err;
  639. }
  640. return 0;
  641. }
  642. static int vhost_user_cleanup(struct vhost_dev *dev)
  643. {
  644. struct vhost_user *u;
  645. assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
  646. u = dev->opaque;
  647. if (u->slave_fd >= 0) {
  648. close(u->slave_fd);
  649. u->slave_fd = -1;
  650. }
  651. g_free(u);
  652. dev->opaque = 0;
  653. return 0;
  654. }
  655. static int vhost_user_get_vq_index(struct vhost_dev *dev, int idx)
  656. {
  657. assert(idx >= dev->vq_index && idx < dev->vq_index + dev->nvqs);
  658. return idx;
  659. }
  660. static int vhost_user_memslots_limit(struct vhost_dev *dev)
  661. {
  662. return VHOST_MEMORY_MAX_NREGIONS;
  663. }
  664. static bool vhost_user_requires_shm_log(struct vhost_dev *dev)
  665. {
  666. assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
  667. return virtio_has_feature(dev->protocol_features,
  668. VHOST_USER_PROTOCOL_F_LOG_SHMFD);
  669. }
  670. static int vhost_user_migration_done(struct vhost_dev *dev, char* mac_addr)
  671. {
  672. VhostUserMsg msg = { 0 };
  673. assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
  674. /* If guest supports GUEST_ANNOUNCE do nothing */
  675. if (virtio_has_feature(dev->acked_features, VIRTIO_NET_F_GUEST_ANNOUNCE)) {
  676. return 0;
  677. }
  678. /* if backend supports VHOST_USER_PROTOCOL_F_RARP ask it to send the RARP */
  679. if (virtio_has_feature(dev->protocol_features,
  680. VHOST_USER_PROTOCOL_F_RARP)) {
  681. msg.request = VHOST_USER_SEND_RARP;
  682. msg.flags = VHOST_USER_VERSION;
  683. memcpy((char *)&msg.payload.u64, mac_addr, 6);
  684. msg.size = sizeof(msg.payload.u64);
  685. return vhost_user_write(dev, &msg, NULL, 0);
  686. }
  687. return -1;
  688. }
  689. static bool vhost_user_can_merge(struct vhost_dev *dev,
  690. uint64_t start1, uint64_t size1,
  691. uint64_t start2, uint64_t size2)
  692. {
  693. ram_addr_t offset;
  694. int mfd, rfd;
  695. MemoryRegion *mr;
  696. mr = memory_region_from_host((void *)(uintptr_t)start1, &offset);
  697. mfd = memory_region_get_fd(mr);
  698. mr = memory_region_from_host((void *)(uintptr_t)start2, &offset);
  699. rfd = memory_region_get_fd(mr);
  700. return mfd == rfd;
  701. }
  702. static int vhost_user_net_set_mtu(struct vhost_dev *dev, uint16_t mtu)
  703. {
  704. VhostUserMsg msg;
  705. bool reply_supported = virtio_has_feature(dev->protocol_features,
  706. VHOST_USER_PROTOCOL_F_REPLY_ACK);
  707. if (!(dev->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_NET_MTU))) {
  708. return 0;
  709. }
  710. msg.request = VHOST_USER_NET_SET_MTU;
  711. msg.payload.u64 = mtu;
  712. msg.size = sizeof(msg.payload.u64);
  713. msg.flags = VHOST_USER_VERSION;
  714. if (reply_supported) {
  715. msg.flags |= VHOST_USER_NEED_REPLY_MASK;
  716. }
  717. if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
  718. return -1;
  719. }
  720. /* If reply_ack supported, slave has to ack specified MTU is valid */
  721. if (reply_supported) {
  722. return process_message_reply(dev, &msg);
  723. }
  724. return 0;
  725. }
  726. static int vhost_user_send_device_iotlb_msg(struct vhost_dev *dev,
  727. struct vhost_iotlb_msg *imsg)
  728. {
  729. VhostUserMsg msg = {
  730. .request = VHOST_USER_IOTLB_MSG,
  731. .size = sizeof(msg.payload.iotlb),
  732. .flags = VHOST_USER_VERSION | VHOST_USER_NEED_REPLY_MASK,
  733. .payload.iotlb = *imsg,
  734. };
  735. if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
  736. return -EFAULT;
  737. }
  738. return process_message_reply(dev, &msg);
  739. }
  740. static void vhost_user_set_iotlb_callback(struct vhost_dev *dev, int enabled)
  741. {
  742. /* No-op as the receive channel is not dedicated to IOTLB messages. */
  743. }
  744. const VhostOps user_ops = {
  745. .backend_type = VHOST_BACKEND_TYPE_USER,
  746. .vhost_backend_init = vhost_user_init,
  747. .vhost_backend_cleanup = vhost_user_cleanup,
  748. .vhost_backend_memslots_limit = vhost_user_memslots_limit,
  749. .vhost_set_log_base = vhost_user_set_log_base,
  750. .vhost_set_mem_table = vhost_user_set_mem_table,
  751. .vhost_set_vring_addr = vhost_user_set_vring_addr,
  752. .vhost_set_vring_endian = vhost_user_set_vring_endian,
  753. .vhost_set_vring_num = vhost_user_set_vring_num,
  754. .vhost_set_vring_base = vhost_user_set_vring_base,
  755. .vhost_get_vring_base = vhost_user_get_vring_base,
  756. .vhost_set_vring_kick = vhost_user_set_vring_kick,
  757. .vhost_set_vring_call = vhost_user_set_vring_call,
  758. .vhost_set_features = vhost_user_set_features,
  759. .vhost_get_features = vhost_user_get_features,
  760. .vhost_set_owner = vhost_user_set_owner,
  761. .vhost_reset_device = vhost_user_reset_device,
  762. .vhost_get_vq_index = vhost_user_get_vq_index,
  763. .vhost_set_vring_enable = vhost_user_set_vring_enable,
  764. .vhost_requires_shm_log = vhost_user_requires_shm_log,
  765. .vhost_migration_done = vhost_user_migration_done,
  766. .vhost_backend_can_merge = vhost_user_can_merge,
  767. .vhost_net_set_mtu = vhost_user_net_set_mtu,
  768. .vhost_set_iotlb_callback = vhost_user_set_iotlb_callback,
  769. .vhost_send_device_iotlb_msg = vhost_user_send_device_iotlb_msg,
  770. };