virtio-console.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. /*
  2. * Virtio Console and Generic Serial Port Devices
  3. *
  4. * Copyright Red Hat, Inc. 2009, 2010
  5. *
  6. * Authors:
  7. * Amit Shah <amit.shah@redhat.com>
  8. *
  9. * This work is licensed under the terms of the GNU GPL, version 2. See
  10. * the COPYING file in the top-level directory.
  11. */
  12. #include "qemu/osdep.h"
  13. #include "chardev/char-fe.h"
  14. #include "qemu/error-report.h"
  15. #include "qemu/module.h"
  16. #include "trace.h"
  17. #include "hw/qdev-properties.h"
  18. #include "hw/qdev-properties-system.h"
  19. #include "hw/virtio/virtio-serial.h"
  20. #include "qapi/error.h"
  21. #include "qapi/qapi-events-char.h"
  22. #include "qom/object.h"
  23. #define TYPE_VIRTIO_CONSOLE_SERIAL_PORT "virtserialport"
  24. typedef struct VirtConsole VirtConsole;
  25. DECLARE_INSTANCE_CHECKER(VirtConsole, VIRTIO_CONSOLE,
  26. TYPE_VIRTIO_CONSOLE_SERIAL_PORT)
  27. struct VirtConsole {
  28. VirtIOSerialPort parent_obj;
  29. CharBackend chr;
  30. guint watch;
  31. };
  32. /*
  33. * Callback function that's called from chardevs when backend becomes
  34. * writable.
  35. */
  36. static gboolean chr_write_unblocked(void *do_not_use, GIOCondition cond,
  37. void *opaque)
  38. {
  39. VirtConsole *vcon = opaque;
  40. vcon->watch = 0;
  41. virtio_serial_throttle_port(VIRTIO_SERIAL_PORT(vcon), false);
  42. return G_SOURCE_REMOVE;
  43. }
  44. /* Callback function that's called when the guest sends us data */
  45. static ssize_t flush_buf(VirtIOSerialPort *port,
  46. const uint8_t *buf, ssize_t len)
  47. {
  48. VirtConsole *vcon = VIRTIO_CONSOLE(port);
  49. ssize_t ret;
  50. if (!qemu_chr_fe_backend_connected(&vcon->chr)) {
  51. /* If there's no backend, we can just say we consumed all data. */
  52. return len;
  53. }
  54. ret = qemu_chr_fe_write(&vcon->chr, buf, len);
  55. trace_virtio_console_flush_buf(port->id, len, ret);
  56. if (ret < len) {
  57. VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(port);
  58. /*
  59. * Ideally we'd get a better error code than just -1, but
  60. * that's what the chardev interface gives us right now. If
  61. * we had a finer-grained message, like -EPIPE, we could close
  62. * this connection.
  63. */
  64. if (ret < 0)
  65. ret = 0;
  66. /* XXX we should be queuing data to send later for the
  67. * console devices too rather than silently dropping
  68. * console data on EAGAIN. The Linux virtio-console
  69. * hvc driver though does sends with spinlocks held,
  70. * so if we enable throttling that'll stall the entire
  71. * guest kernel, not merely the process writing to the
  72. * console.
  73. *
  74. * While we could queue data for later write without
  75. * enabling throttling, this would result in the guest
  76. * being able to trigger arbitrary memory usage in QEMU
  77. * buffering data for later writes.
  78. *
  79. * So fixing this problem likely requires fixing the
  80. * Linux virtio-console hvc driver to not hold spinlocks
  81. * while writing, and instead merely block the process
  82. * that's writing. QEMU would then need some way to detect
  83. * if the guest had the fixed driver too, before we can
  84. * use throttling on host side.
  85. */
  86. if (!k->is_console) {
  87. virtio_serial_throttle_port(port, true);
  88. if (!vcon->watch) {
  89. vcon->watch = qemu_chr_fe_add_watch(&vcon->chr,
  90. G_IO_OUT|G_IO_HUP,
  91. chr_write_unblocked, vcon);
  92. }
  93. }
  94. }
  95. return ret;
  96. }
  97. /* Callback function that's called when the guest opens/closes the port */
  98. static void set_guest_connected(VirtIOSerialPort *port, int guest_connected)
  99. {
  100. VirtConsole *vcon = VIRTIO_CONSOLE(port);
  101. DeviceState *dev = DEVICE(port);
  102. VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(port);
  103. if (!k->is_console) {
  104. qemu_chr_fe_set_open(&vcon->chr, guest_connected);
  105. }
  106. if (dev->id) {
  107. qapi_event_send_vserport_change(dev->id, guest_connected);
  108. }
  109. }
  110. static void guest_writable(VirtIOSerialPort *port)
  111. {
  112. VirtConsole *vcon = VIRTIO_CONSOLE(port);
  113. qemu_chr_fe_accept_input(&vcon->chr);
  114. }
  115. /* Readiness of the guest to accept data on a port */
  116. static int chr_can_read(void *opaque)
  117. {
  118. VirtConsole *vcon = opaque;
  119. return virtio_serial_guest_ready(VIRTIO_SERIAL_PORT(vcon));
  120. }
  121. /* Send data from a char device over to the guest */
  122. static void chr_read(void *opaque, const uint8_t *buf, int size)
  123. {
  124. VirtConsole *vcon = opaque;
  125. VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(vcon);
  126. trace_virtio_console_chr_read(port->id, size);
  127. virtio_serial_write(port, buf, size);
  128. }
  129. static void chr_event(void *opaque, QEMUChrEvent event)
  130. {
  131. VirtConsole *vcon = opaque;
  132. VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(vcon);
  133. trace_virtio_console_chr_event(port->id, event);
  134. switch (event) {
  135. case CHR_EVENT_OPENED:
  136. virtio_serial_open(port);
  137. break;
  138. case CHR_EVENT_CLOSED:
  139. if (vcon->watch) {
  140. g_source_remove(vcon->watch);
  141. vcon->watch = 0;
  142. }
  143. virtio_serial_close(port);
  144. break;
  145. case CHR_EVENT_BREAK:
  146. case CHR_EVENT_MUX_IN:
  147. case CHR_EVENT_MUX_OUT:
  148. /* Ignore */
  149. break;
  150. }
  151. }
  152. static int chr_be_change(void *opaque)
  153. {
  154. VirtConsole *vcon = opaque;
  155. VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(vcon);
  156. VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(port);
  157. if (k->is_console) {
  158. qemu_chr_fe_set_handlers(&vcon->chr, chr_can_read, chr_read,
  159. NULL, chr_be_change, vcon, NULL, true);
  160. } else {
  161. qemu_chr_fe_set_handlers(&vcon->chr, chr_can_read, chr_read,
  162. chr_event, chr_be_change, vcon, NULL, false);
  163. }
  164. if (vcon->watch) {
  165. g_source_remove(vcon->watch);
  166. vcon->watch = qemu_chr_fe_add_watch(&vcon->chr,
  167. G_IO_OUT | G_IO_HUP,
  168. chr_write_unblocked, vcon);
  169. }
  170. return 0;
  171. }
  172. static void virtconsole_enable_backend(VirtIOSerialPort *port, bool enable)
  173. {
  174. VirtConsole *vcon = VIRTIO_CONSOLE(port);
  175. if (!qemu_chr_fe_backend_connected(&vcon->chr)) {
  176. return;
  177. }
  178. if (enable) {
  179. VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(port);
  180. qemu_chr_fe_set_handlers(&vcon->chr, chr_can_read, chr_read,
  181. k->is_console ? NULL : chr_event,
  182. chr_be_change, vcon, NULL, false);
  183. } else {
  184. qemu_chr_fe_set_handlers(&vcon->chr, NULL, NULL, NULL,
  185. NULL, NULL, NULL, false);
  186. }
  187. }
  188. static void virtconsole_realize(DeviceState *dev, Error **errp)
  189. {
  190. VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(dev);
  191. VirtConsole *vcon = VIRTIO_CONSOLE(dev);
  192. VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(dev);
  193. if (port->id == 0 && !k->is_console) {
  194. error_setg(errp, "Port number 0 on virtio-serial devices reserved "
  195. "for virtconsole devices for backward compatibility.");
  196. return;
  197. }
  198. if (qemu_chr_fe_backend_connected(&vcon->chr)) {
  199. /*
  200. * For consoles we don't block guest data transfer just
  201. * because nothing is connected - we'll just let it go
  202. * whetherever the chardev wants - /dev/null probably.
  203. *
  204. * For serial ports we need 100% reliable data transfer
  205. * so we use the opened/closed signals from chardev to
  206. * trigger open/close of the device
  207. */
  208. if (k->is_console) {
  209. qemu_chr_fe_set_handlers(&vcon->chr, chr_can_read, chr_read,
  210. NULL, chr_be_change,
  211. vcon, NULL, true);
  212. virtio_serial_open(port);
  213. } else {
  214. qemu_chr_fe_set_handlers(&vcon->chr, chr_can_read, chr_read,
  215. chr_event, chr_be_change,
  216. vcon, NULL, false);
  217. }
  218. }
  219. }
  220. static void virtconsole_unrealize(DeviceState *dev)
  221. {
  222. VirtConsole *vcon = VIRTIO_CONSOLE(dev);
  223. if (vcon->watch) {
  224. g_source_remove(vcon->watch);
  225. }
  226. }
  227. static void virtconsole_class_init(ObjectClass *klass, void *data)
  228. {
  229. VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_CLASS(klass);
  230. k->is_console = true;
  231. }
  232. static const TypeInfo virtconsole_info = {
  233. .name = "virtconsole",
  234. .parent = TYPE_VIRTIO_CONSOLE_SERIAL_PORT,
  235. .class_init = virtconsole_class_init,
  236. };
  237. static const Property virtserialport_properties[] = {
  238. DEFINE_PROP_CHR("chardev", VirtConsole, chr),
  239. };
  240. static void virtserialport_class_init(ObjectClass *klass, void *data)
  241. {
  242. DeviceClass *dc = DEVICE_CLASS(klass);
  243. VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_CLASS(klass);
  244. k->realize = virtconsole_realize;
  245. k->unrealize = virtconsole_unrealize;
  246. k->have_data = flush_buf;
  247. k->set_guest_connected = set_guest_connected;
  248. k->enable_backend = virtconsole_enable_backend;
  249. k->guest_writable = guest_writable;
  250. device_class_set_props(dc, virtserialport_properties);
  251. }
  252. static const TypeInfo virtserialport_info = {
  253. .name = TYPE_VIRTIO_CONSOLE_SERIAL_PORT,
  254. .parent = TYPE_VIRTIO_SERIAL_PORT,
  255. .instance_size = sizeof(VirtConsole),
  256. .class_init = virtserialport_class_init,
  257. };
  258. static void virtconsole_register_types(void)
  259. {
  260. type_register_static(&virtserialport_info);
  261. type_register_static(&virtconsole_info);
  262. }
  263. type_init(virtconsole_register_types)