xen_pvdev.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. /*
  2. * Xen para-virtualization device
  3. *
  4. * (c) 2008 Gerd Hoffmann <kraxel@redhat.com>
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, see <http://www.gnu.org/licenses/>
  18. */
  19. #include "qemu/osdep.h"
  20. #include "qemu/log.h"
  21. #include "qemu/main-loop.h"
  22. #include "hw/qdev-core.h"
  23. #include "hw/xen/xen-legacy-backend.h"
  24. #include "hw/xen/xen-bus-helper.h"
  25. #include "hw/xen/xen_pvdev.h"
  26. /* private */
  27. static int debug;
  28. struct xs_dirs {
  29. char *xs_dir;
  30. QTAILQ_ENTRY(xs_dirs) list;
  31. };
  32. static QTAILQ_HEAD(, xs_dirs) xs_cleanup =
  33. QTAILQ_HEAD_INITIALIZER(xs_cleanup);
  34. static QTAILQ_HEAD(, XenLegacyDevice) xendevs =
  35. QTAILQ_HEAD_INITIALIZER(xendevs);
  36. /* ------------------------------------------------------------- */
  37. static void xenstore_cleanup_dir(char *dir)
  38. {
  39. struct xs_dirs *d;
  40. d = g_malloc(sizeof(*d));
  41. d->xs_dir = dir;
  42. QTAILQ_INSERT_TAIL(&xs_cleanup, d, list);
  43. }
  44. void xen_config_cleanup(void)
  45. {
  46. struct xs_dirs *d;
  47. QTAILQ_FOREACH(d, &xs_cleanup, list) {
  48. qemu_xen_xs_destroy(xenstore, 0, d->xs_dir);
  49. }
  50. }
  51. int xenstore_mkdir(char *path, int p)
  52. {
  53. if (!qemu_xen_xs_create(xenstore, 0, 0, xen_domid, p, path)) {
  54. xen_pv_printf(NULL, 0, "xs_mkdir %s: failed\n", path);
  55. return -1;
  56. }
  57. xenstore_cleanup_dir(g_strdup(path));
  58. return 0;
  59. }
  60. int xenstore_write_str(const char *base, const char *node, const char *val)
  61. {
  62. char abspath[XEN_BUFSIZE];
  63. snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
  64. if (!qemu_xen_xs_write(xenstore, 0, abspath, val, strlen(val))) {
  65. return -1;
  66. }
  67. return 0;
  68. }
  69. char *xenstore_read_str(const char *base, const char *node)
  70. {
  71. char *str, *ret = NULL;
  72. str = xs_node_read(xenstore, 0, NULL, NULL, "%s/%s", base, node);
  73. if (str != NULL) {
  74. /* move to qemu-allocated memory to make sure
  75. * callers can safely g_free() stuff. */
  76. ret = g_strdup(str);
  77. free(str);
  78. }
  79. return ret;
  80. }
  81. int xenstore_write_int(const char *base, const char *node, int ival)
  82. {
  83. char val[12];
  84. snprintf(val, sizeof(val), "%d", ival);
  85. return xenstore_write_str(base, node, val);
  86. }
  87. int xenstore_write_int64(const char *base, const char *node, int64_t ival)
  88. {
  89. char val[21];
  90. snprintf(val, sizeof(val), "%"PRId64, ival);
  91. return xenstore_write_str(base, node, val);
  92. }
  93. int xenstore_read_int(const char *base, const char *node, int *ival)
  94. {
  95. char *val;
  96. int rc = -1;
  97. val = xenstore_read_str(base, node);
  98. if (val && 1 == sscanf(val, "%d", ival)) {
  99. rc = 0;
  100. }
  101. g_free(val);
  102. return rc;
  103. }
  104. int xenstore_read_uint64(const char *base, const char *node, uint64_t *uval)
  105. {
  106. char *val;
  107. int rc = -1;
  108. val = xenstore_read_str(base, node);
  109. if (val && 1 == sscanf(val, "%"SCNu64, uval)) {
  110. rc = 0;
  111. }
  112. g_free(val);
  113. return rc;
  114. }
  115. const char *xenbus_strstate(enum xenbus_state state)
  116. {
  117. static const char *const name[] = {
  118. [XenbusStateUnknown] = "Unknown",
  119. [XenbusStateInitialising] = "Initialising",
  120. [XenbusStateInitWait] = "InitWait",
  121. [XenbusStateInitialised] = "Initialised",
  122. [XenbusStateConnected] = "Connected",
  123. [XenbusStateClosing] = "Closing",
  124. [XenbusStateClosed] = "Closed",
  125. };
  126. return (state < ARRAY_SIZE(name)) ? name[state] : "INVALID";
  127. }
  128. /*
  129. * msg_level:
  130. * 0 == errors (stderr + logfile).
  131. * 1 == informative debug messages (logfile only).
  132. * 2 == noisy debug messages (logfile only).
  133. * 3 == will flood your log (logfile only).
  134. */
  135. G_GNUC_PRINTF(3, 0)
  136. static void xen_pv_output_msg(struct XenLegacyDevice *xendev,
  137. FILE *f, const char *fmt, va_list args)
  138. {
  139. if (xendev) {
  140. fprintf(f, "xen be: %s: ", xendev->name);
  141. } else {
  142. fprintf(f, "xen be core: ");
  143. }
  144. vfprintf(f, fmt, args);
  145. }
  146. void xen_pv_printf(struct XenLegacyDevice *xendev, int msg_level,
  147. const char *fmt, ...)
  148. {
  149. FILE *logfile;
  150. va_list args;
  151. if (msg_level > (xendev ? xendev->debug : debug)) {
  152. return;
  153. }
  154. logfile = qemu_log_trylock();
  155. if (logfile) {
  156. va_start(args, fmt);
  157. xen_pv_output_msg(xendev, logfile, fmt, args);
  158. va_end(args);
  159. qemu_log_unlock(logfile);
  160. }
  161. if (msg_level == 0) {
  162. va_start(args, fmt);
  163. xen_pv_output_msg(xendev, stderr, fmt, args);
  164. va_end(args);
  165. }
  166. }
  167. void xen_pv_evtchn_event(void *opaque)
  168. {
  169. struct XenLegacyDevice *xendev = opaque;
  170. evtchn_port_t port;
  171. port = qemu_xen_evtchn_pending(xendev->evtchndev);
  172. if (port != xendev->local_port) {
  173. xen_pv_printf(xendev, 0,
  174. "xenevtchn_pending returned %d (expected %d)\n",
  175. port, xendev->local_port);
  176. return;
  177. }
  178. qemu_xen_evtchn_unmask(xendev->evtchndev, port);
  179. if (xendev->ops->event) {
  180. xendev->ops->event(xendev);
  181. }
  182. }
  183. void xen_pv_unbind_evtchn(struct XenLegacyDevice *xendev)
  184. {
  185. if (xendev->local_port == -1) {
  186. return;
  187. }
  188. qemu_set_fd_handler(qemu_xen_evtchn_fd(xendev->evtchndev), NULL, NULL, NULL);
  189. qemu_xen_evtchn_unbind(xendev->evtchndev, xendev->local_port);
  190. xen_pv_printf(xendev, 2, "unbind evtchn port %d\n", xendev->local_port);
  191. xendev->local_port = -1;
  192. }
  193. int xen_pv_send_notify(struct XenLegacyDevice *xendev)
  194. {
  195. return qemu_xen_evtchn_notify(xendev->evtchndev, xendev->local_port);
  196. }
  197. /* ------------------------------------------------------------- */
  198. struct XenLegacyDevice *xen_pv_find_xendev(const char *type, int dom, int dev)
  199. {
  200. struct XenLegacyDevice *xendev;
  201. QTAILQ_FOREACH(xendev, &xendevs, next) {
  202. if (xendev->dom != dom) {
  203. continue;
  204. }
  205. if (xendev->dev != dev) {
  206. continue;
  207. }
  208. if (strcmp(xendev->type, type) != 0) {
  209. continue;
  210. }
  211. return xendev;
  212. }
  213. return NULL;
  214. }
  215. /*
  216. * release xen backend device.
  217. */
  218. void xen_pv_del_xendev(struct XenLegacyDevice *xendev)
  219. {
  220. if (xendev->ops->free) {
  221. xendev->ops->free(xendev);
  222. }
  223. if (xendev->fe) {
  224. qemu_xen_xs_unwatch(xenstore, xendev->watch);
  225. g_free(xendev->fe);
  226. }
  227. if (xendev->evtchndev != NULL) {
  228. qemu_xen_evtchn_close(xendev->evtchndev);
  229. }
  230. if (xendev->gnttabdev != NULL) {
  231. qemu_xen_gnttab_close(xendev->gnttabdev);
  232. }
  233. QTAILQ_REMOVE(&xendevs, xendev, next);
  234. qdev_unplug(&xendev->qdev, NULL);
  235. }
  236. void xen_pv_insert_xendev(struct XenLegacyDevice *xendev)
  237. {
  238. QTAILQ_INSERT_TAIL(&xendevs, xendev, next);
  239. }