virtio-console.c 9.4 KB

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