2
0

xen-legacy-backend.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737
  1. /*
  2. * xen backend driver infrastructure
  3. * (c) 2008 Gerd Hoffmann <kraxel@redhat.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; under version 2 of the License.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along
  15. * with this program; if not, see <http://www.gnu.org/licenses/>.
  16. *
  17. * Contributions after 2012-01-13 are licensed under the terms of the
  18. * GNU GPL, version 2 or (at your option) any later version.
  19. */
  20. /*
  21. * TODO: add some xenbus / xenstore concepts overview here.
  22. */
  23. #include "qemu/osdep.h"
  24. #include "hw/sysbus.h"
  25. #include "hw/boards.h"
  26. #include "hw/qdev-properties.h"
  27. #include "qemu/main-loop.h"
  28. #include "qapi/error.h"
  29. #include "hw/xen/xen-legacy-backend.h"
  30. #include "hw/xen/xen_pvdev.h"
  31. #include "monitor/qdev.h"
  32. DeviceState *xen_sysdev;
  33. BusState *xen_sysbus;
  34. /* ------------------------------------------------------------- */
  35. /* public */
  36. struct qemu_xs_handle *xenstore;
  37. const char *xen_protocol;
  38. /* private */
  39. static int debug;
  40. int xenstore_write_be_str(struct XenLegacyDevice *xendev, const char *node,
  41. const char *val)
  42. {
  43. return xenstore_write_str(xendev->be, node, val);
  44. }
  45. int xenstore_write_be_int(struct XenLegacyDevice *xendev, const char *node,
  46. int ival)
  47. {
  48. return xenstore_write_int(xendev->be, node, ival);
  49. }
  50. int xenstore_write_be_int64(struct XenLegacyDevice *xendev, const char *node,
  51. int64_t ival)
  52. {
  53. return xenstore_write_int64(xendev->be, node, ival);
  54. }
  55. char *xenstore_read_be_str(struct XenLegacyDevice *xendev, const char *node)
  56. {
  57. return xenstore_read_str(xendev->be, node);
  58. }
  59. int xenstore_read_be_int(struct XenLegacyDevice *xendev, const char *node,
  60. int *ival)
  61. {
  62. return xenstore_read_int(xendev->be, node, ival);
  63. }
  64. char *xenstore_read_fe_str(struct XenLegacyDevice *xendev, const char *node)
  65. {
  66. return xenstore_read_str(xendev->fe, node);
  67. }
  68. int xenstore_read_fe_int(struct XenLegacyDevice *xendev, const char *node,
  69. int *ival)
  70. {
  71. return xenstore_read_int(xendev->fe, node, ival);
  72. }
  73. int xenstore_read_fe_uint64(struct XenLegacyDevice *xendev, const char *node,
  74. uint64_t *uval)
  75. {
  76. return xenstore_read_uint64(xendev->fe, node, uval);
  77. }
  78. /* ------------------------------------------------------------- */
  79. int xen_be_set_state(struct XenLegacyDevice *xendev, enum xenbus_state state)
  80. {
  81. int rc;
  82. rc = xenstore_write_be_int(xendev, "state", state);
  83. if (rc < 0) {
  84. return rc;
  85. }
  86. xen_pv_printf(xendev, 1, "backend state: %s -> %s\n",
  87. xenbus_strstate(xendev->be_state), xenbus_strstate(state));
  88. xendev->be_state = state;
  89. return 0;
  90. }
  91. void xen_be_set_max_grant_refs(struct XenLegacyDevice *xendev,
  92. unsigned int nr_refs)
  93. {
  94. assert(xendev->ops->flags & DEVOPS_FLAG_NEED_GNTDEV);
  95. if (qemu_xen_gnttab_set_max_grants(xendev->gnttabdev, nr_refs)) {
  96. xen_pv_printf(xendev, 0, "xengnttab_set_max_grants failed: %s\n",
  97. strerror(errno));
  98. }
  99. }
  100. void *xen_be_map_grant_refs(struct XenLegacyDevice *xendev, uint32_t *refs,
  101. unsigned int nr_refs, int prot)
  102. {
  103. void *ptr;
  104. assert(xendev->ops->flags & DEVOPS_FLAG_NEED_GNTDEV);
  105. ptr = qemu_xen_gnttab_map_refs(xendev->gnttabdev, nr_refs, xen_domid, refs,
  106. prot);
  107. if (!ptr) {
  108. xen_pv_printf(xendev, 0,
  109. "xengnttab_map_domain_grant_refs failed: %s\n",
  110. strerror(errno));
  111. }
  112. return ptr;
  113. }
  114. void xen_be_unmap_grant_refs(struct XenLegacyDevice *xendev, void *ptr,
  115. uint32_t *refs, unsigned int nr_refs)
  116. {
  117. assert(xendev->ops->flags & DEVOPS_FLAG_NEED_GNTDEV);
  118. if (qemu_xen_gnttab_unmap(xendev->gnttabdev, ptr, refs, nr_refs)) {
  119. xen_pv_printf(xendev, 0, "xengnttab_unmap failed: %s\n",
  120. strerror(errno));
  121. }
  122. }
  123. int xen_be_copy_grant_refs(struct XenLegacyDevice *xendev,
  124. bool to_domain,
  125. XenGrantCopySegment segs[],
  126. unsigned int nr_segs)
  127. {
  128. int rc;
  129. assert(xendev->ops->flags & DEVOPS_FLAG_NEED_GNTDEV);
  130. rc = qemu_xen_gnttab_grant_copy(xendev->gnttabdev, to_domain, xen_domid,
  131. segs, nr_segs, NULL);
  132. if (rc) {
  133. xen_pv_printf(xendev, 0, "xengnttab_grant_copy failed: %s\n",
  134. strerror(-rc));
  135. }
  136. return rc;
  137. }
  138. /*
  139. * get xen backend device, allocate a new one if it doesn't exist.
  140. */
  141. static struct XenLegacyDevice *xen_be_get_xendev(const char *type, int dom,
  142. int dev,
  143. struct XenDevOps *ops)
  144. {
  145. struct XenLegacyDevice *xendev;
  146. xendev = xen_pv_find_xendev(type, dom, dev);
  147. if (xendev) {
  148. return xendev;
  149. }
  150. /* init new xendev */
  151. xendev = g_malloc0(ops->size);
  152. object_initialize(&xendev->qdev, ops->size, TYPE_XENBACKEND);
  153. OBJECT(xendev)->free = g_free;
  154. qdev_set_id(DEVICE(xendev), g_strdup_printf("xen-%s-%d", type, dev),
  155. &error_fatal);
  156. qdev_realize(DEVICE(xendev), xen_sysbus, &error_fatal);
  157. object_unref(OBJECT(xendev));
  158. xendev->type = type;
  159. xendev->dom = dom;
  160. xendev->dev = dev;
  161. xendev->ops = ops;
  162. snprintf(xendev->be, sizeof(xendev->be), "backend/%s/%d/%d",
  163. xendev->type, xendev->dom, xendev->dev);
  164. snprintf(xendev->name, sizeof(xendev->name), "%s-%d",
  165. xendev->type, xendev->dev);
  166. xendev->debug = debug;
  167. xendev->local_port = -1;
  168. xendev->evtchndev = qemu_xen_evtchn_open();
  169. if (xendev->evtchndev == NULL) {
  170. xen_pv_printf(NULL, 0, "can't open evtchn device\n");
  171. qdev_unplug(DEVICE(xendev), NULL);
  172. return NULL;
  173. }
  174. qemu_set_cloexec(qemu_xen_evtchn_fd(xendev->evtchndev));
  175. xen_pv_insert_xendev(xendev);
  176. if (xendev->ops->alloc) {
  177. xendev->ops->alloc(xendev);
  178. }
  179. return xendev;
  180. }
  181. /*
  182. * Sync internal data structures on xenstore updates.
  183. * Node specifies the changed field. node = NULL means
  184. * update all fields (used for initialization).
  185. */
  186. static void xen_be_backend_changed(struct XenLegacyDevice *xendev,
  187. const char *node)
  188. {
  189. if (node == NULL || strcmp(node, "online") == 0) {
  190. if (xenstore_read_be_int(xendev, "online", &xendev->online) == -1) {
  191. xendev->online = 0;
  192. }
  193. }
  194. if (node) {
  195. xen_pv_printf(xendev, 2, "backend update: %s\n", node);
  196. if (xendev->ops->backend_changed) {
  197. xendev->ops->backend_changed(xendev, node);
  198. }
  199. }
  200. }
  201. static void xen_be_frontend_changed(struct XenLegacyDevice *xendev,
  202. const char *node)
  203. {
  204. int fe_state;
  205. if (node == NULL || strcmp(node, "state") == 0) {
  206. if (xenstore_read_fe_int(xendev, "state", &fe_state) == -1) {
  207. fe_state = XenbusStateUnknown;
  208. }
  209. if (xendev->fe_state != fe_state) {
  210. xen_pv_printf(xendev, 1, "frontend state: %s -> %s\n",
  211. xenbus_strstate(xendev->fe_state),
  212. xenbus_strstate(fe_state));
  213. }
  214. xendev->fe_state = fe_state;
  215. }
  216. if (node == NULL || strcmp(node, "protocol") == 0) {
  217. g_free(xendev->protocol);
  218. xendev->protocol = xenstore_read_fe_str(xendev, "protocol");
  219. if (xendev->protocol) {
  220. xen_pv_printf(xendev, 1, "frontend protocol: %s\n",
  221. xendev->protocol);
  222. }
  223. }
  224. if (node) {
  225. xen_pv_printf(xendev, 2, "frontend update: %s\n", node);
  226. if (xendev->ops->frontend_changed) {
  227. xendev->ops->frontend_changed(xendev, node);
  228. }
  229. }
  230. }
  231. static void xenstore_update_fe(void *opaque, const char *watch)
  232. {
  233. struct XenLegacyDevice *xendev = opaque;
  234. const char *node;
  235. unsigned int len;
  236. len = strlen(xendev->fe);
  237. if (strncmp(xendev->fe, watch, len) != 0) {
  238. return;
  239. }
  240. if (watch[len] != '/') {
  241. return;
  242. }
  243. node = watch + len + 1;
  244. xen_be_frontend_changed(xendev, node);
  245. xen_be_check_state(xendev);
  246. }
  247. /* ------------------------------------------------------------- */
  248. /* Check for possible state transitions and perform them. */
  249. /*
  250. * Initial xendev setup. Read frontend path, register watch for it.
  251. * Should succeed once xend finished setting up the backend device.
  252. *
  253. * Also sets initial state (-> Initializing) when done. Which
  254. * only affects the xendev->be_state variable as xenbus should
  255. * already be put into that state by xend.
  256. */
  257. static int xen_be_try_setup(struct XenLegacyDevice *xendev)
  258. {
  259. int be_state;
  260. if (xenstore_read_be_int(xendev, "state", &be_state) == -1) {
  261. xen_pv_printf(xendev, 0, "reading backend state failed\n");
  262. return -1;
  263. }
  264. if (be_state != XenbusStateInitialising) {
  265. xen_pv_printf(xendev, 0, "initial backend state is wrong (%s)\n",
  266. xenbus_strstate(be_state));
  267. return -1;
  268. }
  269. xendev->fe = xenstore_read_be_str(xendev, "frontend");
  270. if (xendev->fe == NULL) {
  271. xen_pv_printf(xendev, 0, "reading frontend path failed\n");
  272. return -1;
  273. }
  274. /* setup frontend watch */
  275. xendev->watch = qemu_xen_xs_watch(xenstore, xendev->fe, xenstore_update_fe,
  276. xendev);
  277. if (!xendev->watch) {
  278. xen_pv_printf(xendev, 0, "watching frontend path (%s) failed\n",
  279. xendev->fe);
  280. return -1;
  281. }
  282. xen_be_set_state(xendev, XenbusStateInitialising);
  283. xen_be_backend_changed(xendev, NULL);
  284. xen_be_frontend_changed(xendev, NULL);
  285. return 0;
  286. }
  287. /*
  288. * Try initialize xendev. Prepare everything the backend can do
  289. * without synchronizing with the frontend. Fakes hotplug-status. No
  290. * hotplug involved here because this is about userspace drivers, thus
  291. * there are kernel backend devices which could invoke hotplug.
  292. *
  293. * Goes to InitWait on success.
  294. */
  295. static int xen_be_try_init(struct XenLegacyDevice *xendev)
  296. {
  297. int rc = 0;
  298. if (!xendev->online) {
  299. xen_pv_printf(xendev, 1, "not online\n");
  300. return -1;
  301. }
  302. if (xendev->ops->init) {
  303. rc = xendev->ops->init(xendev);
  304. }
  305. if (rc != 0) {
  306. xen_pv_printf(xendev, 1, "init() failed\n");
  307. return rc;
  308. }
  309. xenstore_write_be_str(xendev, "hotplug-status", "connected");
  310. xen_be_set_state(xendev, XenbusStateInitWait);
  311. return 0;
  312. }
  313. /*
  314. * Try to initialise xendev. Depends on the frontend being ready
  315. * for it (shared ring and evtchn info in xenstore, state being
  316. * Initialised or Connected).
  317. *
  318. * Goes to Connected on success.
  319. */
  320. static int xen_be_try_initialise(struct XenLegacyDevice *xendev)
  321. {
  322. int rc = 0;
  323. if (xendev->fe_state != XenbusStateInitialised &&
  324. xendev->fe_state != XenbusStateConnected) {
  325. if (xendev->ops->flags & DEVOPS_FLAG_IGNORE_STATE) {
  326. xen_pv_printf(xendev, 2, "frontend not ready, ignoring\n");
  327. } else {
  328. xen_pv_printf(xendev, 2, "frontend not ready (yet)\n");
  329. return -1;
  330. }
  331. }
  332. if (xendev->ops->flags & DEVOPS_FLAG_NEED_GNTDEV) {
  333. xendev->gnttabdev = qemu_xen_gnttab_open();
  334. if (xendev->gnttabdev == NULL) {
  335. xen_pv_printf(NULL, 0, "can't open gnttab device\n");
  336. return -1;
  337. }
  338. } else {
  339. xendev->gnttabdev = NULL;
  340. }
  341. if (xendev->ops->initialise) {
  342. rc = xendev->ops->initialise(xendev);
  343. }
  344. if (rc != 0) {
  345. xen_pv_printf(xendev, 0, "initialise() failed\n");
  346. return rc;
  347. }
  348. xen_be_set_state(xendev, XenbusStateConnected);
  349. return 0;
  350. }
  351. /*
  352. * Try to let xendev know that it is connected. Depends on the
  353. * frontend being Connected. Note that this may be called more
  354. * than once since the backend state is not modified.
  355. */
  356. static void xen_be_try_connected(struct XenLegacyDevice *xendev)
  357. {
  358. if (!xendev->ops->connected) {
  359. return;
  360. }
  361. if (xendev->fe_state != XenbusStateConnected) {
  362. if (xendev->ops->flags & DEVOPS_FLAG_IGNORE_STATE) {
  363. xen_pv_printf(xendev, 2, "frontend not ready, ignoring\n");
  364. } else {
  365. xen_pv_printf(xendev, 2, "frontend not ready (yet)\n");
  366. return;
  367. }
  368. }
  369. xendev->ops->connected(xendev);
  370. }
  371. /*
  372. * Teardown connection.
  373. *
  374. * Goes to Closed when done.
  375. */
  376. static void xen_be_disconnect(struct XenLegacyDevice *xendev,
  377. enum xenbus_state state)
  378. {
  379. if (xendev->be_state != XenbusStateClosing &&
  380. xendev->be_state != XenbusStateClosed &&
  381. xendev->ops->disconnect) {
  382. xendev->ops->disconnect(xendev);
  383. }
  384. if (xendev->gnttabdev) {
  385. qemu_xen_gnttab_close(xendev->gnttabdev);
  386. xendev->gnttabdev = NULL;
  387. }
  388. if (xendev->be_state != state) {
  389. xen_be_set_state(xendev, state);
  390. }
  391. }
  392. /*
  393. * Try to reset xendev, for reconnection by another frontend instance.
  394. */
  395. static int xen_be_try_reset(struct XenLegacyDevice *xendev)
  396. {
  397. if (xendev->fe_state != XenbusStateInitialising) {
  398. return -1;
  399. }
  400. xen_pv_printf(xendev, 1, "device reset (for re-connect)\n");
  401. xen_be_set_state(xendev, XenbusStateInitialising);
  402. return 0;
  403. }
  404. /*
  405. * state change dispatcher function
  406. */
  407. void xen_be_check_state(struct XenLegacyDevice *xendev)
  408. {
  409. int rc = 0;
  410. /* frontend may request shutdown from almost anywhere */
  411. if (xendev->fe_state == XenbusStateClosing ||
  412. xendev->fe_state == XenbusStateClosed) {
  413. xen_be_disconnect(xendev, xendev->fe_state);
  414. return;
  415. }
  416. /* check for possible backend state transitions */
  417. for (;;) {
  418. switch (xendev->be_state) {
  419. case XenbusStateUnknown:
  420. rc = xen_be_try_setup(xendev);
  421. break;
  422. case XenbusStateInitialising:
  423. rc = xen_be_try_init(xendev);
  424. break;
  425. case XenbusStateInitWait:
  426. rc = xen_be_try_initialise(xendev);
  427. break;
  428. case XenbusStateConnected:
  429. /* xendev->be_state doesn't change */
  430. xen_be_try_connected(xendev);
  431. rc = -1;
  432. break;
  433. case XenbusStateClosed:
  434. rc = xen_be_try_reset(xendev);
  435. break;
  436. default:
  437. rc = -1;
  438. }
  439. if (rc != 0) {
  440. break;
  441. }
  442. }
  443. }
  444. /* ------------------------------------------------------------- */
  445. struct xenstore_be {
  446. const char *type;
  447. int dom;
  448. struct XenDevOps *ops;
  449. };
  450. static void xenstore_update_be(void *opaque, const char *watch)
  451. {
  452. struct xenstore_be *be = opaque;
  453. struct XenLegacyDevice *xendev;
  454. char path[XEN_BUFSIZE], *bepath;
  455. unsigned int len, dev;
  456. len = snprintf(path, sizeof(path), "backend/%s/%d", be->type, be->dom);
  457. if (strncmp(path, watch, len) != 0) {
  458. return;
  459. }
  460. if (sscanf(watch + len, "/%u/%255s", &dev, path) != 2) {
  461. strcpy(path, "");
  462. if (sscanf(watch + len, "/%u", &dev) != 1) {
  463. dev = -1;
  464. }
  465. }
  466. if (dev == -1) {
  467. return;
  468. }
  469. xendev = xen_be_get_xendev(be->type, be->dom, dev, be->ops);
  470. if (xendev != NULL) {
  471. bepath = qemu_xen_xs_read(xenstore, 0, xendev->be, &len);
  472. if (bepath == NULL) {
  473. xen_pv_del_xendev(xendev);
  474. } else {
  475. free(bepath);
  476. xen_be_backend_changed(xendev, path);
  477. xen_be_check_state(xendev);
  478. }
  479. }
  480. }
  481. static int xenstore_scan(const char *type, int dom, struct XenDevOps *ops)
  482. {
  483. struct XenLegacyDevice *xendev;
  484. char path[XEN_BUFSIZE];
  485. struct xenstore_be *be = g_new0(struct xenstore_be, 1);
  486. char **dev = NULL;
  487. unsigned int cdev, j;
  488. /* setup watch */
  489. be->type = type;
  490. be->dom = dom;
  491. be->ops = ops;
  492. snprintf(path, sizeof(path), "backend/%s/%d", type, dom);
  493. if (!qemu_xen_xs_watch(xenstore, path, xenstore_update_be, be)) {
  494. xen_pv_printf(NULL, 0, "xen be: watching backend path (%s) failed\n",
  495. path);
  496. return -1;
  497. }
  498. /* look for backends */
  499. dev = qemu_xen_xs_directory(xenstore, 0, path, &cdev);
  500. if (!dev) {
  501. return 0;
  502. }
  503. for (j = 0; j < cdev; j++) {
  504. xendev = xen_be_get_xendev(type, dom, atoi(dev[j]), ops);
  505. if (xendev == NULL) {
  506. continue;
  507. }
  508. xen_be_check_state(xendev);
  509. }
  510. free(dev);
  511. return 0;
  512. }
  513. /* -------------------------------------------------------------------- */
  514. static void xen_set_dynamic_sysbus(void)
  515. {
  516. Object *machine = qdev_get_machine();
  517. ObjectClass *oc = object_get_class(machine);
  518. MachineClass *mc = MACHINE_CLASS(oc);
  519. machine_class_allow_dynamic_sysbus_dev(mc, TYPE_XENSYSDEV);
  520. }
  521. void xen_be_init(void)
  522. {
  523. xenstore = qemu_xen_xs_open();
  524. if (!xenstore) {
  525. xen_pv_printf(NULL, 0, "can't connect to xenstored\n");
  526. exit(1);
  527. }
  528. if (xen_evtchn_ops == NULL || xen_gnttab_ops == NULL) {
  529. xen_pv_printf(NULL, 0, "Xen operations not set up\n");
  530. exit(1);
  531. }
  532. xen_sysdev = qdev_new(TYPE_XENSYSDEV);
  533. sysbus_realize_and_unref(SYS_BUS_DEVICE(xen_sysdev), &error_fatal);
  534. xen_sysbus = qbus_new(TYPE_XENSYSBUS, xen_sysdev, "xen-sysbus");
  535. qbus_set_bus_hotplug_handler(xen_sysbus);
  536. xen_set_dynamic_sysbus();
  537. xen_be_register("console", &xen_console_ops);
  538. xen_be_register("vkbd", &xen_kbdmouse_ops);
  539. #ifdef CONFIG_VIRTFS
  540. xen_be_register("9pfs", &xen_9pfs_ops);
  541. #endif
  542. #ifdef CONFIG_USB_LIBUSB
  543. xen_be_register("qusb", &xen_usb_ops);
  544. #endif
  545. }
  546. int xen_be_register(const char *type, struct XenDevOps *ops)
  547. {
  548. char path[50];
  549. int rc;
  550. if (ops->backend_register) {
  551. rc = ops->backend_register();
  552. if (rc) {
  553. return rc;
  554. }
  555. }
  556. snprintf(path, sizeof(path), "device-model/%u/backends/%s", xen_domid,
  557. type);
  558. xenstore_mkdir(path, XS_PERM_NONE);
  559. return xenstore_scan(type, xen_domid, ops);
  560. }
  561. int xen_be_bind_evtchn(struct XenLegacyDevice *xendev)
  562. {
  563. if (xendev->local_port != -1) {
  564. return 0;
  565. }
  566. xendev->local_port = qemu_xen_evtchn_bind_interdomain
  567. (xendev->evtchndev, xendev->dom, xendev->remote_port);
  568. if (xendev->local_port == -1) {
  569. xen_pv_printf(xendev, 0, "xenevtchn_bind_interdomain failed\n");
  570. return -1;
  571. }
  572. xen_pv_printf(xendev, 2, "bind evtchn port %d\n", xendev->local_port);
  573. qemu_set_fd_handler(qemu_xen_evtchn_fd(xendev->evtchndev),
  574. xen_pv_evtchn_event, NULL, xendev);
  575. return 0;
  576. }
  577. static Property xendev_properties[] = {
  578. DEFINE_PROP_END_OF_LIST(),
  579. };
  580. static void xendev_class_init(ObjectClass *klass, void *data)
  581. {
  582. DeviceClass *dc = DEVICE_CLASS(klass);
  583. device_class_set_props(dc, xendev_properties);
  584. set_bit(DEVICE_CATEGORY_MISC, dc->categories);
  585. /* xen-backend devices can be plugged/unplugged dynamically */
  586. dc->user_creatable = true;
  587. dc->bus_type = TYPE_XENSYSBUS;
  588. }
  589. static const TypeInfo xendev_type_info = {
  590. .name = TYPE_XENBACKEND,
  591. .parent = TYPE_DEVICE,
  592. .class_init = xendev_class_init,
  593. .instance_size = sizeof(struct XenLegacyDevice),
  594. };
  595. static void xen_sysbus_class_init(ObjectClass *klass, void *data)
  596. {
  597. HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
  598. hc->unplug = qdev_simple_device_unplug_cb;
  599. }
  600. static const TypeInfo xensysbus_info = {
  601. .name = TYPE_XENSYSBUS,
  602. .parent = TYPE_BUS,
  603. .class_init = xen_sysbus_class_init,
  604. .interfaces = (InterfaceInfo[]) {
  605. { TYPE_HOTPLUG_HANDLER },
  606. { }
  607. }
  608. };
  609. static Property xen_sysdev_properties[] = {
  610. {/* end of property list */},
  611. };
  612. static void xen_sysdev_class_init(ObjectClass *klass, void *data)
  613. {
  614. DeviceClass *dc = DEVICE_CLASS(klass);
  615. device_class_set_props(dc, xen_sysdev_properties);
  616. }
  617. static const TypeInfo xensysdev_info = {
  618. .name = TYPE_XENSYSDEV,
  619. .parent = TYPE_SYS_BUS_DEVICE,
  620. .instance_size = sizeof(SysBusDevice),
  621. .class_init = xen_sysdev_class_init,
  622. };
  623. static void xenbe_register_types(void)
  624. {
  625. type_register_static(&xensysbus_info);
  626. type_register_static(&xensysdev_info);
  627. type_register_static(&xendev_type_info);
  628. }
  629. type_init(xenbe_register_types)