2 * Copyright (C) International Business Machines Corp., 2005
3 * Author(s): Anthony Liguori <aliguori@us.ibm.com>
5 * Copyright (C) Red Hat 2007
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; under version 2 of the License.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "qemu/osdep.h"
23 #include "qemu/cutils.h"
24 #include <sys/select.h>
27 #include "qapi/error.h"
28 #include "sysemu/sysemu.h"
29 #include "chardev/char-fe.h"
30 #include "hw/xen/xen-backend.h"
31 #include "hw/xen/xen-bus-helper.h"
32 #include "hw/qdev-properties.h"
33 #include "hw/qdev-properties-system.h"
34 #include "hw/xen/interface/io/console.h"
35 #include "hw/xen/interface/io/xs_wire.h"
36 #include "hw/xen/interface/grant_table.h"
37 #include "hw/i386/kvm/xen_primary_console.h"
49 struct XenDevice xendev
; /* must be first */
50 XenEventChannel
*event_channel
;
54 unsigned int ring_ref
;
59 typedef struct XenConsole XenConsole
;
61 #define TYPE_XEN_CONSOLE_DEVICE "xen-console"
62 OBJECT_DECLARE_SIMPLE_TYPE(XenConsole
, XEN_CONSOLE_DEVICE
)
64 static bool buffer_append(XenConsole
*con
)
66 struct buffer
*buffer
= &con
->buffer
;
67 XENCONS_RING_IDX cons
, prod
, size
;
68 struct xencons_interface
*intf
= con
->sring
;
70 cons
= intf
->out_cons
;
71 prod
= intf
->out_prod
;
75 if ((size
== 0) || (size
> sizeof(intf
->out
)))
78 if ((buffer
->capacity
- buffer
->size
) < size
) {
79 buffer
->capacity
+= (size
+ 1024);
80 buffer
->data
= g_realloc(buffer
->data
, buffer
->capacity
);
84 buffer
->data
[buffer
->size
++] = intf
->out
[
85 MASK_XENCONS_IDX(cons
++, intf
->out
)];
88 intf
->out_cons
= cons
;
89 xen_device_notify_event_channel(XEN_DEVICE(con
), con
->event_channel
, NULL
);
91 if (buffer
->max_capacity
&&
92 buffer
->size
> buffer
->max_capacity
) {
93 /* Discard the middle of the data. */
95 size_t over
= buffer
->size
- buffer
->max_capacity
;
96 uint8_t *maxpos
= buffer
->data
+ buffer
->max_capacity
;
98 memmove(maxpos
- over
, maxpos
, over
);
99 buffer
->data
= g_realloc(buffer
->data
, buffer
->max_capacity
);
100 buffer
->size
= buffer
->capacity
= buffer
->max_capacity
;
102 if (buffer
->consumed
> buffer
->max_capacity
- over
)
103 buffer
->consumed
= buffer
->max_capacity
- over
;
108 static void buffer_advance(struct buffer
*buffer
, size_t len
)
110 buffer
->consumed
+= len
;
111 if (buffer
->consumed
== buffer
->size
) {
112 buffer
->consumed
= 0;
117 static int ring_free_bytes(XenConsole
*con
)
119 struct xencons_interface
*intf
= con
->sring
;
120 XENCONS_RING_IDX cons
, prod
, space
;
122 cons
= intf
->in_cons
;
123 prod
= intf
->in_prod
;
127 if (space
> sizeof(intf
->in
))
128 return 0; /* ring is screwed: ignore it */
130 return (sizeof(intf
->in
) - space
);
133 static int xencons_can_receive(void *opaque
)
135 XenConsole
*con
= opaque
;
136 return ring_free_bytes(con
);
139 static void xencons_receive(void *opaque
, const uint8_t *buf
, int len
)
141 XenConsole
*con
= opaque
;
142 struct xencons_interface
*intf
= con
->sring
;
143 XENCONS_RING_IDX prod
;
146 max
= ring_free_bytes(con
);
147 /* The can_receive() func limits this, but check again anyway */
151 prod
= intf
->in_prod
;
152 for (i
= 0; i
< len
; i
++) {
153 intf
->in
[MASK_XENCONS_IDX(prod
++, intf
->in
)] =
157 intf
->in_prod
= prod
;
158 xen_device_notify_event_channel(XEN_DEVICE(con
), con
->event_channel
, NULL
);
161 static bool xencons_send(XenConsole
*con
)
165 size
= con
->buffer
.size
- con
->buffer
.consumed
;
166 if (qemu_chr_fe_backend_connected(&con
->chr
)) {
167 len
= qemu_chr_fe_write(&con
->chr
,
168 con
->buffer
.data
+ con
->buffer
.consumed
,
178 buffer_advance(&con
->buffer
, len
);
179 if (con
->backlog
&& len
== size
) {
186 /* -------------------------------------------------------------------- */
188 static bool con_event(void *_xendev
)
190 XenConsole
*con
= XEN_CONSOLE_DEVICE(_xendev
);
193 if (xen_device_backend_get_state(&con
->xendev
) != XenbusStateConnected
) {
197 done_something
= buffer_append(con
);
199 if (con
->buffer
.size
- con
->buffer
.consumed
) {
200 done_something
|= xencons_send(con
);
202 return done_something
;
205 /* -------------------------------------------------------------------- */
207 static bool xen_console_connect(XenDevice
*xendev
, Error
**errp
)
209 XenConsole
*con
= XEN_CONSOLE_DEVICE(xendev
);
210 unsigned int port
, limit
;
212 if (xen_device_frontend_scanf(xendev
, "ring-ref", "%u",
213 &con
->ring_ref
) != 1) {
214 error_setg(errp
, "failed to read ring-ref");
218 if (xen_device_frontend_scanf(xendev
, "port", "%u", &port
) != 1) {
219 error_setg(errp
, "failed to read remote port");
223 if (xen_device_frontend_scanf(xendev
, "limit", "%u", &limit
) == 1) {
224 con
->buffer
.max_capacity
= limit
;
227 con
->event_channel
= xen_device_bind_event_channel(xendev
, port
,
231 if (!con
->event_channel
) {
238 * The primary console is special. For real Xen the ring-ref is
239 * actually a GFN which needs to be mapped as foreignmem.
241 if (xen_mode
!= XEN_EMULATE
) {
242 xen_pfn_t mfn
= (xen_pfn_t
)con
->ring_ref
;
243 con
->sring
= qemu_xen_foreignmem_map(xendev
->frontend_id
, NULL
,
244 PROT_READ
| PROT_WRITE
,
247 error_setg(errp
, "failed to map console page");
254 * For Xen emulation, we still follow the convention of ring-ref
255 * holding the GFN, but we map the fixed GNTTAB_RESERVED_CONSOLE
256 * grant ref because there is no implementation of foreignmem
257 * operations for emulated mode. The emulation code which handles
258 * the guest-side page and event channel also needs to be informed
259 * of the backend event channel port, in order to reconnect to it
260 * after a soft reset.
262 xen_primary_console_set_be_port(
263 xen_event_channel_get_local_port(con
->event_channel
));
264 con
->ring_ref
= GNTTAB_RESERVED_CONSOLE
;
267 con
->sring
= xen_device_map_grant_refs(xendev
,
269 PROT_READ
| PROT_WRITE
,
272 error_prepend(errp
, "failed to map console grant ref: ");
278 trace_xen_console_connect(con
->dev
, con
->ring_ref
, port
,
279 con
->buffer
.max_capacity
);
281 qemu_chr_fe_set_handlers(&con
->chr
, xencons_can_receive
,
282 xencons_receive
, NULL
, NULL
, con
, NULL
,
287 static void xen_console_disconnect(XenDevice
*xendev
, Error
**errp
)
289 XenConsole
*con
= XEN_CONSOLE_DEVICE(xendev
);
291 trace_xen_console_disconnect(con
->dev
);
293 qemu_chr_fe_set_handlers(&con
->chr
, NULL
, NULL
, NULL
, NULL
,
296 if (con
->event_channel
) {
297 xen_device_unbind_event_channel(xendev
, con
->event_channel
,
299 con
->event_channel
= NULL
;
301 if (xen_mode
== XEN_EMULATE
&& !con
->dev
) {
302 xen_primary_console_set_be_port(0);
307 if (!con
->dev
&& xen_mode
!= XEN_EMULATE
) {
308 qemu_xen_foreignmem_unmap(con
->sring
, 1);
310 xen_device_unmap_grant_refs(xendev
, con
->sring
,
311 &con
->ring_ref
, 1, errp
);
317 static void xen_console_frontend_changed(XenDevice
*xendev
,
318 enum xenbus_state frontend_state
,
322 enum xenbus_state backend_state
= xen_device_backend_get_state(xendev
);
324 switch (frontend_state
) {
325 case XenbusStateInitialised
:
326 case XenbusStateConnected
:
327 if (backend_state
== XenbusStateConnected
) {
331 xen_console_disconnect(xendev
, errp
);
336 if (!xen_console_connect(xendev
, errp
)) {
337 xen_device_backend_set_state(xendev
, XenbusStateClosing
);
341 xen_device_backend_set_state(xendev
, XenbusStateConnected
);
344 case XenbusStateClosing
:
345 xen_device_backend_set_state(xendev
, XenbusStateClosing
);
348 case XenbusStateClosed
:
349 case XenbusStateUnknown
:
350 xen_console_disconnect(xendev
, errp
);
355 xen_device_backend_set_state(xendev
, XenbusStateClosed
);
363 static char *xen_console_get_name(XenDevice
*xendev
, Error
**errp
)
365 XenConsole
*con
= XEN_CONSOLE_DEVICE(xendev
);
367 if (con
->dev
== -1) {
368 XenBus
*xenbus
= XEN_BUS(qdev_get_parent_bus(DEVICE(xendev
)));
369 char fe_path
[XENSTORE_ABS_PATH_MAX
+ 1];
370 int idx
= (xen_mode
== XEN_EMULATE
) ? 0 : 1;
373 /* Theoretically we could go up to INT_MAX here but that's overkill */
376 snprintf(fe_path
, sizeof(fe_path
),
377 "/local/domain/%u/console", xendev
->frontend_id
);
379 snprintf(fe_path
, sizeof(fe_path
),
380 "/local/domain/%u/device/console/%u",
381 xendev
->frontend_id
, idx
);
383 value
= qemu_xen_xs_read(xenbus
->xsh
, XBT_NULL
, fe_path
, NULL
);
385 if (errno
== ENOENT
) {
389 error_setg(errp
, "cannot read %s: %s", fe_path
,
396 error_setg(errp
, "cannot find device index for console device");
400 return g_strdup_printf("%u", con
->dev
);
403 static void xen_console_unrealize(XenDevice
*xendev
)
405 XenConsole
*con
= XEN_CONSOLE_DEVICE(xendev
);
407 trace_xen_console_unrealize(con
->dev
);
409 /* Disconnect from the frontend in case this has not already happened */
410 xen_console_disconnect(xendev
, NULL
);
412 qemu_chr_fe_deinit(&con
->chr
, false);
415 static void xen_console_realize(XenDevice
*xendev
, Error
**errp
)
418 XenConsole
*con
= XEN_CONSOLE_DEVICE(xendev
);
419 Chardev
*cs
= qemu_chr_fe_get_driver(&con
->chr
);
423 error_setg(errp
, "no backing character device");
427 if (con
->dev
== -1) {
428 error_setg(errp
, "no device index provided");
433 * The Xen primary console is special. The ring-ref is actually a GFN to
434 * be mapped directly as foreignmem (not a grant ref), and the guest port
435 * was allocated *for* the guest by the toolstack. The guest gets these
436 * through HVMOP_get_param and can use the console long before it's got
437 * XenStore up and running. We cannot create those for a true Xen guest,
438 * but we can for Xen emulation.
441 if (xen_mode
== XEN_EMULATE
) {
442 xen_primary_console_create();
443 } else if (xen_device_frontend_scanf(xendev
, "ring-ref", "%u", &u
)
445 xen_device_frontend_scanf(xendev
, "port", "%u", &u
) != 1) {
446 error_setg(errp
, "cannot create primary Xen console");
451 trace_xen_console_realize(con
->dev
, object_get_typename(OBJECT(cs
)));
453 if (CHARDEV_IS_PTY(cs
)) {
454 /* Strip the leading 'pty:' */
455 xen_device_frontend_printf(xendev
, "tty", "%s", cs
->filename
+ 4);
458 /* No normal PV driver initialization for the primary console under Xen */
459 if (!con
->dev
&& xen_mode
!= XEN_EMULATE
) {
460 xen_console_connect(xendev
, errp
);
464 static char *console_frontend_path(struct qemu_xs_handle
*xenstore
,
465 unsigned int dom_id
, unsigned int dev
)
468 return g_strdup_printf("/local/domain/%u/console", dom_id
);
470 return g_strdup_printf("/local/domain/%u/device/console/%u", dom_id
,
475 static char *xen_console_get_frontend_path(XenDevice
*xendev
, Error
**errp
)
477 XenConsole
*con
= XEN_CONSOLE_DEVICE(xendev
);
478 XenBus
*xenbus
= XEN_BUS(qdev_get_parent_bus(DEVICE(xendev
)));
479 char *ret
= console_frontend_path(xenbus
->xsh
, xendev
->frontend_id
,
483 error_setg(errp
, "failed to create frontend path");
489 static Property xen_console_properties
[] = {
490 DEFINE_PROP_CHR("chardev", XenConsole
, chr
),
491 DEFINE_PROP_INT32("idx", XenConsole
, dev
, -1),
492 DEFINE_PROP_END_OF_LIST(),
495 static void xen_console_class_init(ObjectClass
*class, void *data
)
497 DeviceClass
*dev_class
= DEVICE_CLASS(class);
498 XenDeviceClass
*xendev_class
= XEN_DEVICE_CLASS(class);
500 xendev_class
->backend
= "console";
501 xendev_class
->device
= "console";
502 xendev_class
->get_name
= xen_console_get_name
;
503 xendev_class
->realize
= xen_console_realize
;
504 xendev_class
->frontend_changed
= xen_console_frontend_changed
;
505 xendev_class
->unrealize
= xen_console_unrealize
;
506 xendev_class
->get_frontend_path
= xen_console_get_frontend_path
;
508 device_class_set_props(dev_class
, xen_console_properties
);
511 static const TypeInfo xen_console_type_info
= {
512 .name
= TYPE_XEN_CONSOLE_DEVICE
,
513 .parent
= TYPE_XEN_DEVICE
,
514 .instance_size
= sizeof(XenConsole
),
515 .class_init
= xen_console_class_init
,
518 static void xen_console_register_types(void)
520 type_register_static(&xen_console_type_info
);
523 type_init(xen_console_register_types
)
525 /* Called to instantiate a XenConsole when the backend is detected. */
526 static void xen_console_device_create(XenBackendInstance
*backend
,
527 QDict
*opts
, Error
**errp
)
530 XenBus
*xenbus
= xen_backend_get_bus(backend
);
531 const char *name
= xen_backend_get_name(backend
);
532 unsigned long number
;
533 char *fe
= NULL
, *type
= NULL
, *output
= NULL
;
535 XenDevice
*xendev
= NULL
;
538 struct qemu_xs_handle
*xsh
= xenbus
->xsh
;
540 if (qemu_strtoul(name
, NULL
, 10, &number
) || number
> INT_MAX
) {
541 error_setg(errp
, "failed to parse name '%s'", name
);
545 trace_xen_console_device_create(number
);
547 fe
= console_frontend_path(xsh
, xen_domid
, number
);
549 error_setg(errp
, "failed to generate frontend path");
553 if (xs_node_scanf(xsh
, XBT_NULL
, fe
, "type", errp
, "%ms", &type
) != 1) {
554 error_prepend(errp
, "failed to read console device type: ");
558 if (strcmp(type
, "ioemu")) {
559 error_setg(errp
, "declining to handle console type '%s'",
564 xendev
= XEN_DEVICE(qdev_new(TYPE_XEN_CONSOLE_DEVICE
));
565 con
= XEN_CONSOLE_DEVICE(xendev
);
569 snprintf(label
, sizeof(label
), "xencons%ld", number
);
571 if (xs_node_scanf(xsh
, XBT_NULL
, fe
, "output", NULL
, "%ms", &output
) == 1) {
573 * FIXME: sure we want to support implicit
574 * muxed monitors here?
576 cd
= qemu_chr_new_mux_mon(label
, output
, NULL
);
578 error_setg(errp
, "console: No valid chardev found at '%s': ",
583 cd
= serial_hd(number
);
585 error_prepend(errp
, "console: No serial device #%ld found: ",
590 /* No 'output' node on primary console: use null. */
591 cd
= qemu_chr_new(label
, "null", NULL
);
593 error_setg(errp
, "console: failed to create null device");
598 if (!qemu_chr_fe_init(&con
->chr
, cd
, errp
)) {
599 error_prepend(errp
, "console: failed to initialize backing chardev: ");
603 if (qdev_realize_and_unref(DEVICE(xendev
), BUS(xenbus
), errp
)) {
604 xen_backend_set_device(backend
, xendev
);
608 error_prepend(errp
, "realization of console device %lu failed: ",
613 object_unparent(OBJECT(xendev
));
621 static void xen_console_device_destroy(XenBackendInstance
*backend
,
625 XenDevice
*xendev
= xen_backend_get_device(backend
);
626 XenConsole
*con
= XEN_CONSOLE_DEVICE(xendev
);
628 trace_xen_console_device_destroy(con
->dev
);
630 object_unparent(OBJECT(xendev
));
633 static const XenBackendInfo xen_console_backend_info
= {
635 .create
= xen_console_device_create
,
636 .destroy
= xen_console_device_destroy
,
639 static void xen_console_register_backend(void)
641 xen_backend_register(&xen_console_backend_info
);
644 xen_backend_init(xen_console_register_backend
);