xen_pvdev.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  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_pvdev.h"
  25. /* private */
  26. static int debug;
  27. struct xs_dirs {
  28. char *xs_dir;
  29. QTAILQ_ENTRY(xs_dirs) list;
  30. };
  31. static QTAILQ_HEAD(, xs_dirs) xs_cleanup =
  32. QTAILQ_HEAD_INITIALIZER(xs_cleanup);
  33. static QTAILQ_HEAD(, XenLegacyDevice) xendevs =
  34. QTAILQ_HEAD_INITIALIZER(xendevs);
  35. /* ------------------------------------------------------------- */
  36. static void xenstore_cleanup_dir(char *dir)
  37. {
  38. struct xs_dirs *d;
  39. d = g_malloc(sizeof(*d));
  40. d->xs_dir = dir;
  41. QTAILQ_INSERT_TAIL(&xs_cleanup, d, list);
  42. }
  43. void xen_config_cleanup(void)
  44. {
  45. struct xs_dirs *d;
  46. QTAILQ_FOREACH(d, &xs_cleanup, list) {
  47. qemu_xen_xs_destroy(xenstore, 0, d->xs_dir);
  48. }
  49. }
  50. int xenstore_mkdir(char *path, int p)
  51. {
  52. if (!qemu_xen_xs_create(xenstore, 0, 0, xen_domid, p, path)) {
  53. xen_pv_printf(NULL, 0, "xs_mkdir %s: failed\n", path);
  54. return -1;
  55. }
  56. xenstore_cleanup_dir(g_strdup(path));
  57. return 0;
  58. }
  59. int xenstore_write_str(const char *base, const char *node, const char *val)
  60. {
  61. char abspath[XEN_BUFSIZE];
  62. snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
  63. if (!qemu_xen_xs_write(xenstore, 0, abspath, val, strlen(val))) {
  64. return -1;
  65. }
  66. return 0;
  67. }
  68. char *xenstore_read_str(const char *base, const char *node)
  69. {
  70. char abspath[XEN_BUFSIZE];
  71. unsigned int len;
  72. char *str, *ret = NULL;
  73. snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
  74. str = qemu_xen_xs_read(xenstore, 0, abspath, &len);
  75. if (str != NULL) {
  76. /* move to qemu-allocated memory to make sure
  77. * callers can savely g_free() stuff. */
  78. ret = g_strdup(str);
  79. free(str);
  80. }
  81. return ret;
  82. }
  83. int xenstore_write_int(const char *base, const char *node, int ival)
  84. {
  85. char val[12];
  86. snprintf(val, sizeof(val), "%d", ival);
  87. return xenstore_write_str(base, node, val);
  88. }
  89. int xenstore_write_int64(const char *base, const char *node, int64_t ival)
  90. {
  91. char val[21];
  92. snprintf(val, sizeof(val), "%"PRId64, ival);
  93. return xenstore_write_str(base, node, val);
  94. }
  95. int xenstore_read_int(const char *base, const char *node, int *ival)
  96. {
  97. char *val;
  98. int rc = -1;
  99. val = xenstore_read_str(base, node);
  100. if (val && 1 == sscanf(val, "%d", ival)) {
  101. rc = 0;
  102. }
  103. g_free(val);
  104. return rc;
  105. }
  106. int xenstore_read_uint64(const char *base, const char *node, uint64_t *uval)
  107. {
  108. char *val;
  109. int rc = -1;
  110. val = xenstore_read_str(base, node);
  111. if (val && 1 == sscanf(val, "%"SCNu64, uval)) {
  112. rc = 0;
  113. }
  114. g_free(val);
  115. return rc;
  116. }
  117. const char *xenbus_strstate(enum xenbus_state state)
  118. {
  119. static const char *const name[] = {
  120. [XenbusStateUnknown] = "Unknown",
  121. [XenbusStateInitialising] = "Initialising",
  122. [XenbusStateInitWait] = "InitWait",
  123. [XenbusStateInitialised] = "Initialised",
  124. [XenbusStateConnected] = "Connected",
  125. [XenbusStateClosing] = "Closing",
  126. [XenbusStateClosed] = "Closed",
  127. };
  128. return (state < ARRAY_SIZE(name)) ? name[state] : "INVALID";
  129. }
  130. /*
  131. * msg_level:
  132. * 0 == errors (stderr + logfile).
  133. * 1 == informative debug messages (logfile only).
  134. * 2 == noisy debug messages (logfile only).
  135. * 3 == will flood your log (logfile only).
  136. */
  137. G_GNUC_PRINTF(3, 0)
  138. static void xen_pv_output_msg(struct XenLegacyDevice *xendev,
  139. FILE *f, const char *fmt, va_list args)
  140. {
  141. if (xendev) {
  142. fprintf(f, "xen be: %s: ", xendev->name);
  143. } else {
  144. fprintf(f, "xen be core: ");
  145. }
  146. vfprintf(f, fmt, args);
  147. }
  148. void xen_pv_printf(struct XenLegacyDevice *xendev, int msg_level,
  149. const char *fmt, ...)
  150. {
  151. FILE *logfile;
  152. va_list args;
  153. if (msg_level > (xendev ? xendev->debug : debug)) {
  154. return;
  155. }
  156. logfile = qemu_log_trylock();
  157. if (logfile) {
  158. va_start(args, fmt);
  159. xen_pv_output_msg(xendev, logfile, fmt, args);
  160. va_end(args);
  161. qemu_log_unlock(logfile);
  162. }
  163. if (msg_level == 0) {
  164. va_start(args, fmt);
  165. xen_pv_output_msg(xendev, stderr, fmt, args);
  166. va_end(args);
  167. }
  168. }
  169. void xen_pv_evtchn_event(void *opaque)
  170. {
  171. struct XenLegacyDevice *xendev = opaque;
  172. evtchn_port_t port;
  173. port = qemu_xen_evtchn_pending(xendev->evtchndev);
  174. if (port != xendev->local_port) {
  175. xen_pv_printf(xendev, 0,
  176. "xenevtchn_pending returned %d (expected %d)\n",
  177. port, xendev->local_port);
  178. return;
  179. }
  180. qemu_xen_evtchn_unmask(xendev->evtchndev, port);
  181. if (xendev->ops->event) {
  182. xendev->ops->event(xendev);
  183. }
  184. }
  185. void xen_pv_unbind_evtchn(struct XenLegacyDevice *xendev)
  186. {
  187. if (xendev->local_port == -1) {
  188. return;
  189. }
  190. qemu_set_fd_handler(qemu_xen_evtchn_fd(xendev->evtchndev), NULL, NULL, NULL);
  191. qemu_xen_evtchn_unbind(xendev->evtchndev, xendev->local_port);
  192. xen_pv_printf(xendev, 2, "unbind evtchn port %d\n", xendev->local_port);
  193. xendev->local_port = -1;
  194. }
  195. int xen_pv_send_notify(struct XenLegacyDevice *xendev)
  196. {
  197. return qemu_xen_evtchn_notify(xendev->evtchndev, xendev->local_port);
  198. }
  199. /* ------------------------------------------------------------- */
  200. struct XenLegacyDevice *xen_pv_find_xendev(const char *type, int dom, int dev)
  201. {
  202. struct XenLegacyDevice *xendev;
  203. QTAILQ_FOREACH(xendev, &xendevs, next) {
  204. if (xendev->dom != dom) {
  205. continue;
  206. }
  207. if (xendev->dev != dev) {
  208. continue;
  209. }
  210. if (strcmp(xendev->type, type) != 0) {
  211. continue;
  212. }
  213. return xendev;
  214. }
  215. return NULL;
  216. }
  217. /*
  218. * release xen backend device.
  219. */
  220. void xen_pv_del_xendev(struct XenLegacyDevice *xendev)
  221. {
  222. if (xendev->ops->free) {
  223. xendev->ops->free(xendev);
  224. }
  225. if (xendev->fe) {
  226. qemu_xen_xs_unwatch(xenstore, xendev->watch);
  227. g_free(xendev->fe);
  228. }
  229. if (xendev->evtchndev != NULL) {
  230. qemu_xen_evtchn_close(xendev->evtchndev);
  231. }
  232. if (xendev->gnttabdev != NULL) {
  233. qemu_xen_gnttab_close(xendev->gnttabdev);
  234. }
  235. QTAILQ_REMOVE(&xendevs, xendev, next);
  236. qdev_unplug(&xendev->qdev, NULL);
  237. }
  238. void xen_pv_insert_xendev(struct XenLegacyDevice *xendev)
  239. {
  240. QTAILQ_INSERT_TAIL(&xendevs, xendev, next);
  241. }