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
)
210 XenConsole
*con
= XEN_CONSOLE_DEVICE(xendev
);
211 unsigned int port
, limit
;
213 if (xen_device_frontend_scanf(xendev
, "ring-ref", "%u",
214 &con
->ring_ref
) != 1) {
215 error_setg(errp
, "failed to read ring-ref");
219 if (xen_device_frontend_scanf(xendev
, "port", "%u", &port
) != 1) {
220 error_setg(errp
, "failed to read remote port");
224 if (xen_device_frontend_scanf(xendev
, "limit", "%u", &limit
) == 1) {
225 con
->buffer
.max_capacity
= limit
;
228 con
->event_channel
= xen_device_bind_event_channel(xendev
, port
,
232 if (!con
->event_channel
) {
239 * The primary console is special. For real Xen the ring-ref is
240 * actually a GFN which needs to be mapped as foreignmem.
242 if (xen_mode
!= XEN_EMULATE
) {
243 xen_pfn_t mfn
= (xen_pfn_t
)con
->ring_ref
;
244 con
->sring
= qemu_xen_foreignmem_map(xendev
->frontend_id
, NULL
,
245 PROT_READ
| PROT_WRITE
,
248 error_setg(errp
, "failed to map console page");
255 * For Xen emulation, we still follow the convention of ring-ref
256 * holding the GFN, but we map the fixed GNTTAB_RESERVED_CONSOLE
257 * grant ref because there is no implementation of foreignmem
258 * operations for emulated mode. The emulation code which handles
259 * the guest-side page and event channel also needs to be informed
260 * of the backend event channel port, in order to reconnect to it
261 * after a soft reset.
263 xen_primary_console_set_be_port(
264 xen_event_channel_get_local_port(con
->event_channel
));
265 con
->ring_ref
= GNTTAB_RESERVED_CONSOLE
;
268 con
->sring
= xen_device_map_grant_refs(xendev
,
270 PROT_READ
| PROT_WRITE
,
273 error_prepend(errp
, "failed to map console grant ref: ");
279 trace_xen_console_connect(con
->dev
, con
->ring_ref
, port
,
280 con
->buffer
.max_capacity
);
282 qemu_chr_fe_set_handlers(&con
->chr
, xencons_can_receive
,
283 xencons_receive
, NULL
, NULL
, con
, NULL
,
288 static void xen_console_disconnect(XenDevice
*xendev
, Error
**errp
)
290 XenConsole
*con
= XEN_CONSOLE_DEVICE(xendev
);
292 trace_xen_console_disconnect(con
->dev
);
294 qemu_chr_fe_set_handlers(&con
->chr
, NULL
, NULL
, NULL
, NULL
,
297 if (con
->event_channel
) {
298 xen_device_unbind_event_channel(xendev
, con
->event_channel
,
300 con
->event_channel
= NULL
;
302 if (xen_mode
== XEN_EMULATE
&& !con
->dev
) {
303 xen_primary_console_set_be_port(0);
308 if (!con
->dev
&& xen_mode
!= XEN_EMULATE
) {
309 qemu_xen_foreignmem_unmap(con
->sring
, 1);
311 xen_device_unmap_grant_refs(xendev
, con
->sring
,
312 &con
->ring_ref
, 1, errp
);
318 static void xen_console_frontend_changed(XenDevice
*xendev
,
319 enum xenbus_state frontend_state
,
323 enum xenbus_state backend_state
= xen_device_backend_get_state(xendev
);
325 switch (frontend_state
) {
326 case XenbusStateInitialised
:
327 case XenbusStateConnected
:
328 if (backend_state
== XenbusStateConnected
) {
332 xen_console_disconnect(xendev
, errp
);
337 if (!xen_console_connect(xendev
, errp
)) {
338 xen_device_backend_set_state(xendev
, XenbusStateClosing
);
342 xen_device_backend_set_state(xendev
, XenbusStateConnected
);
345 case XenbusStateClosing
:
346 xen_device_backend_set_state(xendev
, XenbusStateClosing
);
349 case XenbusStateClosed
:
350 case XenbusStateUnknown
:
351 xen_console_disconnect(xendev
, errp
);
356 xen_device_backend_set_state(xendev
, XenbusStateClosed
);
364 static char *xen_console_get_name(XenDevice
*xendev
, Error
**errp
)
366 XenConsole
*con
= XEN_CONSOLE_DEVICE(xendev
);
368 if (con
->dev
== -1) {
369 XenBus
*xenbus
= XEN_BUS(qdev_get_parent_bus(DEVICE(xendev
)));
370 char fe_path
[XENSTORE_ABS_PATH_MAX
+ 1];
371 int idx
= (xen_mode
== XEN_EMULATE
) ? 0 : 1;
374 /* Theoretically we could go up to INT_MAX here but that's overkill */
377 snprintf(fe_path
, sizeof(fe_path
),
378 "/local/domain/%u/console", xendev
->frontend_id
);
380 snprintf(fe_path
, sizeof(fe_path
),
381 "/local/domain/%u/device/console/%u",
382 xendev
->frontend_id
, idx
);
384 value
= qemu_xen_xs_read(xenbus
->xsh
, XBT_NULL
, fe_path
, NULL
);
386 if (errno
== ENOENT
) {
390 error_setg(errp
, "cannot read %s: %s", fe_path
,
397 error_setg(errp
, "cannot find device index for console device");
401 return g_strdup_printf("%u", con
->dev
);
404 static void xen_console_unrealize(XenDevice
*xendev
)
406 XenConsole
*con
= XEN_CONSOLE_DEVICE(xendev
);
408 trace_xen_console_unrealize(con
->dev
);
410 /* Disconnect from the frontend in case this has not already happened */
411 xen_console_disconnect(xendev
, NULL
);
413 qemu_chr_fe_deinit(&con
->chr
, false);
416 static void xen_console_realize(XenDevice
*xendev
, Error
**errp
)
419 XenConsole
*con
= XEN_CONSOLE_DEVICE(xendev
);
420 Chardev
*cs
= qemu_chr_fe_get_driver(&con
->chr
);
424 error_setg(errp
, "no backing character device");
428 if (con
->dev
== -1) {
429 error_setg(errp
, "no device index provided");
434 * The Xen primary console is special. The ring-ref is actually a GFN to
435 * be mapped directly as foreignmem (not a grant ref), and the guest port
436 * was allocated *for* the guest by the toolstack. The guest gets these
437 * through HVMOP_get_param and can use the console long before it's got
438 * XenStore up and running. We cannot create those for a true Xen guest,
439 * but we can for Xen emulation.
442 if (xen_mode
== XEN_EMULATE
) {
443 xen_primary_console_create();
444 } else if (xen_device_frontend_scanf(xendev
, "ring-ref", "%u", &u
)
446 xen_device_frontend_scanf(xendev
, "port", "%u", &u
) != 1) {
447 error_setg(errp
, "cannot create primary Xen console");
452 trace_xen_console_realize(con
->dev
, object_get_typename(OBJECT(cs
)));
454 if (CHARDEV_IS_PTY(cs
)) {
455 /* Strip the leading 'pty:' */
456 xen_device_frontend_printf(xendev
, "tty", "%s", cs
->filename
+ 4);
459 /* No normal PV driver initialization for the primary console under Xen */
460 if (!con
->dev
&& xen_mode
!= XEN_EMULATE
) {
461 xen_console_connect(xendev
, errp
);
465 static char *console_frontend_path(struct qemu_xs_handle
*xenstore
,
466 unsigned int dom_id
, unsigned int dev
)
469 return g_strdup_printf("/local/domain/%u/console", dom_id
);
471 return g_strdup_printf("/local/domain/%u/device/console/%u", dom_id
,
476 static char *xen_console_get_frontend_path(XenDevice
*xendev
, Error
**errp
)
478 XenConsole
*con
= XEN_CONSOLE_DEVICE(xendev
);
479 XenBus
*xenbus
= XEN_BUS(qdev_get_parent_bus(DEVICE(xendev
)));
480 char *ret
= console_frontend_path(xenbus
->xsh
, xendev
->frontend_id
,
484 error_setg(errp
, "failed to create frontend path");
490 static Property xen_console_properties
[] = {
491 DEFINE_PROP_CHR("chardev", XenConsole
, chr
),
492 DEFINE_PROP_INT32("idx", XenConsole
, dev
, -1),
493 DEFINE_PROP_END_OF_LIST(),
496 static void xen_console_class_init(ObjectClass
*class, void *data
)
498 DeviceClass
*dev_class
= DEVICE_CLASS(class);
499 XenDeviceClass
*xendev_class
= XEN_DEVICE_CLASS(class);
501 xendev_class
->backend
= "console";
502 xendev_class
->device
= "console";
503 xendev_class
->get_name
= xen_console_get_name
;
504 xendev_class
->realize
= xen_console_realize
;
505 xendev_class
->frontend_changed
= xen_console_frontend_changed
;
506 xendev_class
->unrealize
= xen_console_unrealize
;
507 xendev_class
->get_frontend_path
= xen_console_get_frontend_path
;
509 device_class_set_props(dev_class
, xen_console_properties
);
512 static const TypeInfo xen_console_type_info
= {
513 .name
= TYPE_XEN_CONSOLE_DEVICE
,
514 .parent
= TYPE_XEN_DEVICE
,
515 .instance_size
= sizeof(XenConsole
),
516 .class_init
= xen_console_class_init
,
519 static void xen_console_register_types(void)
521 type_register_static(&xen_console_type_info
);
524 type_init(xen_console_register_types
)
526 /* Called to instantiate a XenConsole when the backend is detected. */
527 static void xen_console_device_create(XenBackendInstance
*backend
,
528 QDict
*opts
, Error
**errp
)
531 XenBus
*xenbus
= xen_backend_get_bus(backend
);
532 const char *name
= xen_backend_get_name(backend
);
533 unsigned long number
;
534 char *fe
= NULL
, *type
= NULL
, *output
= NULL
;
536 XenDevice
*xendev
= NULL
;
539 struct qemu_xs_handle
*xsh
= xenbus
->xsh
;
541 if (qemu_strtoul(name
, NULL
, 10, &number
) || number
> INT_MAX
) {
542 error_setg(errp
, "failed to parse name '%s'", name
);
546 trace_xen_console_device_create(number
);
548 fe
= console_frontend_path(xsh
, xen_domid
, number
);
550 error_setg(errp
, "failed to generate frontend path");
554 if (xs_node_scanf(xsh
, XBT_NULL
, fe
, "type", errp
, "%ms", &type
) != 1) {
555 error_prepend(errp
, "failed to read console device type: ");
559 if (strcmp(type
, "ioemu")) {
560 error_setg(errp
, "declining to handle console type '%s'",
565 xendev
= XEN_DEVICE(qdev_new(TYPE_XEN_CONSOLE_DEVICE
));
566 con
= XEN_CONSOLE_DEVICE(xendev
);
570 snprintf(label
, sizeof(label
), "xencons%ld", number
);
572 if (xs_node_scanf(xsh
, XBT_NULL
, fe
, "output", NULL
, "%ms", &output
) == 1) {
574 * FIXME: sure we want to support implicit
575 * muxed monitors here?
577 cd
= qemu_chr_new_mux_mon(label
, output
, NULL
);
579 error_setg(errp
, "console: No valid chardev found at '%s': ",
584 cd
= serial_hd(number
);
586 error_prepend(errp
, "console: No serial device #%ld found: ",
591 /* No 'output' node on primary console: use null. */
592 cd
= qemu_chr_new(label
, "null", NULL
);
594 error_setg(errp
, "console: failed to create null device");
599 if (!qemu_chr_fe_init(&con
->chr
, cd
, errp
)) {
600 error_prepend(errp
, "console: failed to initialize backing chardev: ");
604 if (qdev_realize_and_unref(DEVICE(xendev
), BUS(xenbus
), errp
)) {
605 xen_backend_set_device(backend
, xendev
);
609 error_prepend(errp
, "realization of console device %lu failed: ",
614 object_unparent(OBJECT(xendev
));
622 static void xen_console_device_destroy(XenBackendInstance
*backend
,
626 XenDevice
*xendev
= xen_backend_get_device(backend
);
627 XenConsole
*con
= XEN_CONSOLE_DEVICE(xendev
);
629 trace_xen_console_device_destroy(con
->dev
);
631 object_unparent(OBJECT(xendev
));
634 static const XenBackendInfo xen_console_backend_info
= {
636 .create
= xen_console_device_create
,
637 .destroy
= xen_console_device_destroy
,
640 static void xen_console_register_backend(void)
642 xen_backend_register(&xen_console_backend_info
);
645 xen_backend_init(xen_console_register_backend
);