xen_pvdev.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  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 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. xs_rm(xenstore, 0, d->xs_dir);
  48. }
  49. }
  50. int xenstore_mkdir(char *path, int p)
  51. {
  52. struct xs_permissions perms[2] = {
  53. {
  54. .id = 0, /* set owner: dom0 */
  55. }, {
  56. .id = xen_domid,
  57. .perms = p,
  58. }
  59. };
  60. if (!xs_mkdir(xenstore, 0, path)) {
  61. xen_pv_printf(NULL, 0, "xs_mkdir %s: failed\n", path);
  62. return -1;
  63. }
  64. xenstore_cleanup_dir(g_strdup(path));
  65. if (!xs_set_permissions(xenstore, 0, path, perms, 2)) {
  66. xen_pv_printf(NULL, 0, "xs_set_permissions %s: failed\n", path);
  67. return -1;
  68. }
  69. return 0;
  70. }
  71. int xenstore_write_str(const char *base, const char *node, const char *val)
  72. {
  73. char abspath[XEN_BUFSIZE];
  74. snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
  75. if (!xs_write(xenstore, 0, abspath, val, strlen(val))) {
  76. return -1;
  77. }
  78. return 0;
  79. }
  80. char *xenstore_read_str(const char *base, const char *node)
  81. {
  82. char abspath[XEN_BUFSIZE];
  83. unsigned int len;
  84. char *str, *ret = NULL;
  85. snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
  86. str = xs_read(xenstore, 0, abspath, &len);
  87. if (str != NULL) {
  88. /* move to qemu-allocated memory to make sure
  89. * callers can savely g_free() stuff. */
  90. ret = g_strdup(str);
  91. free(str);
  92. }
  93. return ret;
  94. }
  95. int xenstore_write_int(const char *base, const char *node, int ival)
  96. {
  97. char val[12];
  98. snprintf(val, sizeof(val), "%d", ival);
  99. return xenstore_write_str(base, node, val);
  100. }
  101. int xenstore_write_int64(const char *base, const char *node, int64_t ival)
  102. {
  103. char val[21];
  104. snprintf(val, sizeof(val), "%"PRId64, ival);
  105. return xenstore_write_str(base, node, val);
  106. }
  107. int xenstore_read_int(const char *base, const char *node, int *ival)
  108. {
  109. char *val;
  110. int rc = -1;
  111. val = xenstore_read_str(base, node);
  112. if (val && 1 == sscanf(val, "%d", ival)) {
  113. rc = 0;
  114. }
  115. g_free(val);
  116. return rc;
  117. }
  118. int xenstore_read_uint64(const char *base, const char *node, uint64_t *uval)
  119. {
  120. char *val;
  121. int rc = -1;
  122. val = xenstore_read_str(base, node);
  123. if (val && 1 == sscanf(val, "%"SCNu64, uval)) {
  124. rc = 0;
  125. }
  126. g_free(val);
  127. return rc;
  128. }
  129. void xenstore_update(void *unused)
  130. {
  131. char **vec = NULL;
  132. intptr_t type, ops, ptr;
  133. unsigned int dom, count;
  134. vec = xs_read_watch(xenstore, &count);
  135. if (vec == NULL) {
  136. goto cleanup;
  137. }
  138. if (sscanf(vec[XS_WATCH_TOKEN], "be:%" PRIxPTR ":%d:%" PRIxPTR,
  139. &type, &dom, &ops) == 3) {
  140. xenstore_update_be(vec[XS_WATCH_PATH], (void *)type, dom, (void*)ops);
  141. }
  142. if (sscanf(vec[XS_WATCH_TOKEN], "fe:%" PRIxPTR, &ptr) == 1) {
  143. xenstore_update_fe(vec[XS_WATCH_PATH], (void *)ptr);
  144. }
  145. cleanup:
  146. free(vec);
  147. }
  148. const char *xenbus_strstate(enum xenbus_state state)
  149. {
  150. static const char *const name[] = {
  151. [XenbusStateUnknown] = "Unknown",
  152. [XenbusStateInitialising] = "Initialising",
  153. [XenbusStateInitWait] = "InitWait",
  154. [XenbusStateInitialised] = "Initialised",
  155. [XenbusStateConnected] = "Connected",
  156. [XenbusStateClosing] = "Closing",
  157. [XenbusStateClosed] = "Closed",
  158. };
  159. return (state < ARRAY_SIZE(name)) ? name[state] : "INVALID";
  160. }
  161. /*
  162. * msg_level:
  163. * 0 == errors (stderr + logfile).
  164. * 1 == informative debug messages (logfile only).
  165. * 2 == noisy debug messages (logfile only).
  166. * 3 == will flood your log (logfile only).
  167. */
  168. void xen_pv_printf(struct XenLegacyDevice *xendev, int msg_level,
  169. const char *fmt, ...)
  170. {
  171. va_list args;
  172. if (xendev) {
  173. if (msg_level > xendev->debug) {
  174. return;
  175. }
  176. qemu_log("xen be: %s: ", xendev->name);
  177. if (msg_level == 0) {
  178. fprintf(stderr, "xen be: %s: ", xendev->name);
  179. }
  180. } else {
  181. if (msg_level > debug) {
  182. return;
  183. }
  184. qemu_log("xen be core: ");
  185. if (msg_level == 0) {
  186. fprintf(stderr, "xen be core: ");
  187. }
  188. }
  189. va_start(args, fmt);
  190. qemu_log_vprintf(fmt, args);
  191. va_end(args);
  192. if (msg_level == 0) {
  193. va_start(args, fmt);
  194. vfprintf(stderr, fmt, args);
  195. va_end(args);
  196. }
  197. qemu_log_flush();
  198. }
  199. void xen_pv_evtchn_event(void *opaque)
  200. {
  201. struct XenLegacyDevice *xendev = opaque;
  202. evtchn_port_t port;
  203. port = xenevtchn_pending(xendev->evtchndev);
  204. if (port != xendev->local_port) {
  205. xen_pv_printf(xendev, 0,
  206. "xenevtchn_pending returned %d (expected %d)\n",
  207. port, xendev->local_port);
  208. return;
  209. }
  210. xenevtchn_unmask(xendev->evtchndev, port);
  211. if (xendev->ops->event) {
  212. xendev->ops->event(xendev);
  213. }
  214. }
  215. void xen_pv_unbind_evtchn(struct XenLegacyDevice *xendev)
  216. {
  217. if (xendev->local_port == -1) {
  218. return;
  219. }
  220. qemu_set_fd_handler(xenevtchn_fd(xendev->evtchndev), NULL, NULL, NULL);
  221. xenevtchn_unbind(xendev->evtchndev, xendev->local_port);
  222. xen_pv_printf(xendev, 2, "unbind evtchn port %d\n", xendev->local_port);
  223. xendev->local_port = -1;
  224. }
  225. int xen_pv_send_notify(struct XenLegacyDevice *xendev)
  226. {
  227. return xenevtchn_notify(xendev->evtchndev, xendev->local_port);
  228. }
  229. /* ------------------------------------------------------------- */
  230. struct XenLegacyDevice *xen_pv_find_xendev(const char *type, int dom, int dev)
  231. {
  232. struct XenLegacyDevice *xendev;
  233. QTAILQ_FOREACH(xendev, &xendevs, next) {
  234. if (xendev->dom != dom) {
  235. continue;
  236. }
  237. if (xendev->dev != dev) {
  238. continue;
  239. }
  240. if (strcmp(xendev->type, type) != 0) {
  241. continue;
  242. }
  243. return xendev;
  244. }
  245. return NULL;
  246. }
  247. /*
  248. * release xen backend device.
  249. */
  250. void xen_pv_del_xendev(struct XenLegacyDevice *xendev)
  251. {
  252. if (xendev->ops->free) {
  253. xendev->ops->free(xendev);
  254. }
  255. if (xendev->fe) {
  256. char token[XEN_BUFSIZE];
  257. snprintf(token, sizeof(token), "fe:%p", xendev);
  258. xs_unwatch(xenstore, xendev->fe, token);
  259. g_free(xendev->fe);
  260. }
  261. if (xendev->evtchndev != NULL) {
  262. xenevtchn_close(xendev->evtchndev);
  263. }
  264. if (xendev->gnttabdev != NULL) {
  265. xengnttab_close(xendev->gnttabdev);
  266. }
  267. QTAILQ_REMOVE(&xendevs, xendev, next);
  268. qdev_unplug(&xendev->qdev, NULL);
  269. }
  270. void xen_pv_insert_xendev(struct XenLegacyDevice *xendev)
  271. {
  272. QTAILQ_INSERT_TAIL(&xendevs, xendev, next);
  273. }