2
0

virtio-console.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  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, int 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. }
  143. }
  144. static int chr_be_change(void *opaque)
  145. {
  146. VirtConsole *vcon = opaque;
  147. VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(vcon);
  148. VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(port);
  149. if (k->is_console) {
  150. qemu_chr_fe_set_handlers(&vcon->chr, chr_can_read, chr_read,
  151. NULL, chr_be_change, vcon, NULL, true);
  152. } else {
  153. qemu_chr_fe_set_handlers(&vcon->chr, chr_can_read, chr_read,
  154. chr_event, chr_be_change, vcon, NULL, false);
  155. }
  156. if (vcon->watch) {
  157. g_source_remove(vcon->watch);
  158. vcon->watch = qemu_chr_fe_add_watch(&vcon->chr,
  159. G_IO_OUT | G_IO_HUP,
  160. chr_write_unblocked, vcon);
  161. }
  162. return 0;
  163. }
  164. static void virtconsole_enable_backend(VirtIOSerialPort *port, bool enable)
  165. {
  166. VirtConsole *vcon = VIRTIO_CONSOLE(port);
  167. if (!qemu_chr_fe_backend_connected(&vcon->chr)) {
  168. return;
  169. }
  170. if (enable) {
  171. VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(port);
  172. qemu_chr_fe_set_handlers(&vcon->chr, chr_can_read, chr_read,
  173. k->is_console ? NULL : chr_event,
  174. chr_be_change, vcon, NULL, false);
  175. } else {
  176. qemu_chr_fe_set_handlers(&vcon->chr, NULL, NULL, NULL,
  177. NULL, NULL, NULL, false);
  178. }
  179. }
  180. static void virtconsole_realize(DeviceState *dev, Error **errp)
  181. {
  182. VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(dev);
  183. VirtConsole *vcon = VIRTIO_CONSOLE(dev);
  184. VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(dev);
  185. if (port->id == 0 && !k->is_console) {
  186. error_setg(errp, "Port number 0 on virtio-serial devices reserved "
  187. "for virtconsole devices for backward compatibility.");
  188. return;
  189. }
  190. if (qemu_chr_fe_backend_connected(&vcon->chr)) {
  191. /*
  192. * For consoles we don't block guest data transfer just
  193. * because nothing is connected - we'll just let it go
  194. * whetherever the chardev wants - /dev/null probably.
  195. *
  196. * For serial ports we need 100% reliable data transfer
  197. * so we use the opened/closed signals from chardev to
  198. * trigger open/close of the device
  199. */
  200. if (k->is_console) {
  201. qemu_chr_fe_set_handlers(&vcon->chr, chr_can_read, chr_read,
  202. NULL, chr_be_change,
  203. vcon, NULL, true);
  204. virtio_serial_open(port);
  205. } else {
  206. qemu_chr_fe_set_handlers(&vcon->chr, chr_can_read, chr_read,
  207. chr_event, chr_be_change,
  208. vcon, NULL, false);
  209. }
  210. }
  211. }
  212. static void virtconsole_unrealize(DeviceState *dev, Error **errp)
  213. {
  214. VirtConsole *vcon = VIRTIO_CONSOLE(dev);
  215. if (vcon->watch) {
  216. g_source_remove(vcon->watch);
  217. }
  218. }
  219. static void virtconsole_class_init(ObjectClass *klass, void *data)
  220. {
  221. VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_CLASS(klass);
  222. k->is_console = true;
  223. }
  224. static const TypeInfo virtconsole_info = {
  225. .name = "virtconsole",
  226. .parent = TYPE_VIRTIO_CONSOLE_SERIAL_PORT,
  227. .class_init = virtconsole_class_init,
  228. };
  229. static Property virtserialport_properties[] = {
  230. DEFINE_PROP_CHR("chardev", VirtConsole, chr),
  231. DEFINE_PROP_END_OF_LIST(),
  232. };
  233. static void virtserialport_class_init(ObjectClass *klass, void *data)
  234. {
  235. DeviceClass *dc = DEVICE_CLASS(klass);
  236. VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_CLASS(klass);
  237. k->realize = virtconsole_realize;
  238. k->unrealize = virtconsole_unrealize;
  239. k->have_data = flush_buf;
  240. k->set_guest_connected = set_guest_connected;
  241. k->enable_backend = virtconsole_enable_backend;
  242. k->guest_writable = guest_writable;
  243. dc->props = virtserialport_properties;
  244. }
  245. static const TypeInfo virtserialport_info = {
  246. .name = TYPE_VIRTIO_CONSOLE_SERIAL_PORT,
  247. .parent = TYPE_VIRTIO_SERIAL_PORT,
  248. .instance_size = sizeof(VirtConsole),
  249. .class_init = virtserialport_class_init,
  250. };
  251. static void virtconsole_register_types(void)
  252. {
  253. type_register_static(&virtserialport_info);
  254. type_register_static(&virtconsole_info);
  255. }
  256. type_init(virtconsole_register_types)