1 /* 2 * Copyright (C) International Business Machines Corp., 2005 3 * Author(s): Anthony Liguori <aliguori@us.ibm.com> 4 * 5 * Copyright (C) Red Hat 2007 6 * 7 * Xen Console 8 * 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. 12 * 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. 17 * 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/>. 20 */ 21 22 #include "qemu/osdep.h" 23 #include "qemu/cutils.h" 24 #include <sys/select.h> 25 #include <termios.h> 26 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 "trace.h" 37 38 struct buffer { 39 uint8_t *data; 40 size_t consumed; 41 size_t size; 42 size_t capacity; 43 size_t max_capacity; 44 }; 45 46 struct XenConsole { 47 struct XenDevice xendev; /* must be first */ 48 XenEventChannel *event_channel; 49 int dev; 50 struct buffer buffer; 51 char *fe_path; 52 unsigned int ring_ref; 53 void *sring; 54 CharBackend chr; 55 int backlog; 56 }; 57 typedef struct XenConsole XenConsole; 58 59 #define TYPE_XEN_CONSOLE_DEVICE "xen-console" 60 OBJECT_DECLARE_SIMPLE_TYPE(XenConsole, XEN_CONSOLE_DEVICE) 61 62 static bool buffer_append(XenConsole *con) 63 { 64 struct buffer *buffer = &con->buffer; 65 XENCONS_RING_IDX cons, prod, size; 66 struct xencons_interface *intf = con->sring; 67 68 cons = intf->out_cons; 69 prod = intf->out_prod; 70 xen_mb(); 71 72 size = prod - cons; 73 if ((size == 0) || (size > sizeof(intf->out))) 74 return false; 75 76 if ((buffer->capacity - buffer->size) < size) { 77 buffer->capacity += (size + 1024); 78 buffer->data = g_realloc(buffer->data, buffer->capacity); 79 } 80 81 while (cons != prod) 82 buffer->data[buffer->size++] = intf->out[ 83 MASK_XENCONS_IDX(cons++, intf->out)]; 84 85 xen_mb(); 86 intf->out_cons = cons; 87 xen_device_notify_event_channel(XEN_DEVICE(con), con->event_channel, NULL); 88 89 if (buffer->max_capacity && 90 buffer->size > buffer->max_capacity) { 91 /* Discard the middle of the data. */ 92 93 size_t over = buffer->size - buffer->max_capacity; 94 uint8_t *maxpos = buffer->data + buffer->max_capacity; 95 96 memmove(maxpos - over, maxpos, over); 97 buffer->data = g_realloc(buffer->data, buffer->max_capacity); 98 buffer->size = buffer->capacity = buffer->max_capacity; 99 100 if (buffer->consumed > buffer->max_capacity - over) 101 buffer->consumed = buffer->max_capacity - over; 102 } 103 return true; 104 } 105 106 static void buffer_advance(struct buffer *buffer, size_t len) 107 { 108 buffer->consumed += len; 109 if (buffer->consumed == buffer->size) { 110 buffer->consumed = 0; 111 buffer->size = 0; 112 } 113 } 114 115 static int ring_free_bytes(XenConsole *con) 116 { 117 struct xencons_interface *intf = con->sring; 118 XENCONS_RING_IDX cons, prod, space; 119 120 cons = intf->in_cons; 121 prod = intf->in_prod; 122 xen_mb(); 123 124 space = prod - cons; 125 if (space > sizeof(intf->in)) 126 return 0; /* ring is screwed: ignore it */ 127 128 return (sizeof(intf->in) - space); 129 } 130 131 static int xencons_can_receive(void *opaque) 132 { 133 XenConsole *con = opaque; 134 return ring_free_bytes(con); 135 } 136 137 static void xencons_receive(void *opaque, const uint8_t *buf, int len) 138 { 139 XenConsole *con = opaque; 140 struct xencons_interface *intf = con->sring; 141 XENCONS_RING_IDX prod; 142 int i, max; 143 144 max = ring_free_bytes(con); 145 /* The can_receive() func limits this, but check again anyway */ 146 if (max < len) 147 len = max; 148 149 prod = intf->in_prod; 150 for (i = 0; i < len; i++) { 151 intf->in[MASK_XENCONS_IDX(prod++, intf->in)] = 152 buf[i]; 153 } 154 xen_wmb(); 155 intf->in_prod = prod; 156 xen_device_notify_event_channel(XEN_DEVICE(con), con->event_channel, NULL); 157 } 158 159 static bool xencons_send(XenConsole *con) 160 { 161 ssize_t len, size; 162 163 size = con->buffer.size - con->buffer.consumed; 164 if (qemu_chr_fe_backend_connected(&con->chr)) { 165 len = qemu_chr_fe_write(&con->chr, 166 con->buffer.data + con->buffer.consumed, 167 size); 168 } else { 169 len = size; 170 } 171 if (len < 1) { 172 if (!con->backlog) { 173 con->backlog = 1; 174 } 175 } else { 176 buffer_advance(&con->buffer, len); 177 if (con->backlog && len == size) { 178 con->backlog = 0; 179 } 180 } 181 return len > 0; 182 } 183 184 /* -------------------------------------------------------------------- */ 185 186 static bool con_event(void *_xendev) 187 { 188 XenConsole *con = XEN_CONSOLE_DEVICE(_xendev); 189 bool done_something; 190 191 if (xen_device_backend_get_state(&con->xendev) != XenbusStateConnected) { 192 return false; 193 } 194 195 done_something = buffer_append(con); 196 197 if (con->buffer.size - con->buffer.consumed) { 198 done_something |= xencons_send(con); 199 } 200 return done_something; 201 } 202 203 /* -------------------------------------------------------------------- */ 204 205 static bool xen_console_connect(XenDevice *xendev, Error **errp) 206 { 207 XenConsole *con = XEN_CONSOLE_DEVICE(xendev); 208 unsigned int port, limit; 209 210 if (xen_device_frontend_scanf(xendev, "ring-ref", "%u", 211 &con->ring_ref) != 1) { 212 error_setg(errp, "failed to read ring-ref"); 213 return false; 214 } 215 216 if (xen_device_frontend_scanf(xendev, "port", "%u", &port) != 1) { 217 error_setg(errp, "failed to read remote port"); 218 return false; 219 } 220 221 if (xen_device_frontend_scanf(xendev, "limit", "%u", &limit) == 1) { 222 con->buffer.max_capacity = limit; 223 } 224 225 con->event_channel = xen_device_bind_event_channel(xendev, port, 226 con_event, 227 con, 228 errp); 229 if (!con->event_channel) { 230 return false; 231 } 232 233 if (!con->dev) { 234 xen_pfn_t mfn = (xen_pfn_t)con->ring_ref; 235 con->sring = qemu_xen_foreignmem_map(xendev->frontend_id, NULL, 236 PROT_READ | PROT_WRITE, 237 1, &mfn, NULL); 238 if (!con->sring) { 239 error_setg(errp, "failed to map console page"); 240 return false; 241 } 242 } else { 243 con->sring = xen_device_map_grant_refs(xendev, 244 &con->ring_ref, 1, 245 PROT_READ | PROT_WRITE, 246 errp); 247 if (!con->sring) { 248 error_prepend(errp, "failed to map grant ref: "); 249 return false; 250 } 251 } 252 253 trace_xen_console_connect(con->dev, con->ring_ref, port, 254 con->buffer.max_capacity); 255 256 qemu_chr_fe_set_handlers(&con->chr, xencons_can_receive, 257 xencons_receive, NULL, NULL, con, NULL, 258 true); 259 return true; 260 } 261 262 static void xen_console_disconnect(XenDevice *xendev, Error **errp) 263 { 264 XenConsole *con = XEN_CONSOLE_DEVICE(xendev); 265 266 trace_xen_console_disconnect(con->dev); 267 268 qemu_chr_fe_set_handlers(&con->chr, NULL, NULL, NULL, NULL, 269 con, NULL, true); 270 271 if (con->event_channel) { 272 xen_device_unbind_event_channel(xendev, con->event_channel, 273 errp); 274 con->event_channel = NULL; 275 } 276 277 if (con->sring) { 278 if (!con->dev) { 279 qemu_xen_foreignmem_unmap(con->sring, 1); 280 } else { 281 xen_device_unmap_grant_refs(xendev, con->sring, 282 &con->ring_ref, 1, errp); 283 } 284 con->sring = NULL; 285 } 286 } 287 288 static void xen_console_frontend_changed(XenDevice *xendev, 289 enum xenbus_state frontend_state, 290 Error **errp) 291 { 292 ERRP_GUARD(); 293 enum xenbus_state backend_state = xen_device_backend_get_state(xendev); 294 295 switch (frontend_state) { 296 case XenbusStateInitialised: 297 case XenbusStateConnected: 298 if (backend_state == XenbusStateConnected) { 299 break; 300 } 301 302 xen_console_disconnect(xendev, errp); 303 if (*errp) { 304 break; 305 } 306 307 if (!xen_console_connect(xendev, errp)) { 308 xen_device_backend_set_state(xendev, XenbusStateClosing); 309 break; 310 } 311 312 xen_device_backend_set_state(xendev, XenbusStateConnected); 313 break; 314 315 case XenbusStateClosing: 316 xen_device_backend_set_state(xendev, XenbusStateClosing); 317 break; 318 319 case XenbusStateClosed: 320 case XenbusStateUnknown: 321 xen_console_disconnect(xendev, errp); 322 if (*errp) { 323 break; 324 } 325 326 xen_device_backend_set_state(xendev, XenbusStateClosed); 327 break; 328 329 default: 330 break; 331 } 332 } 333 334 static char *xen_console_get_name(XenDevice *xendev, Error **errp) 335 { 336 XenConsole *con = XEN_CONSOLE_DEVICE(xendev); 337 338 if (con->dev == -1) { 339 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev))); 340 char fe_path[XENSTORE_ABS_PATH_MAX + 1]; 341 char *value; 342 int idx = 1; 343 344 /* Theoretically we could go up to INT_MAX here but that's overkill */ 345 while (idx < 100) { 346 snprintf(fe_path, sizeof(fe_path), 347 "/local/domain/%u/device/console/%u", 348 xendev->frontend_id, idx); 349 value = qemu_xen_xs_read(xenbus->xsh, XBT_NULL, fe_path, NULL); 350 if (!value) { 351 if (errno == ENOENT) { 352 con->dev = idx; 353 goto found; 354 } 355 error_setg(errp, "cannot read %s: %s", fe_path, 356 strerror(errno)); 357 return NULL; 358 } 359 free(value); 360 idx++; 361 } 362 error_setg(errp, "cannot find device index for console device"); 363 return NULL; 364 } 365 found: 366 return g_strdup_printf("%u", con->dev); 367 } 368 369 static void xen_console_unrealize(XenDevice *xendev) 370 { 371 XenConsole *con = XEN_CONSOLE_DEVICE(xendev); 372 373 trace_xen_console_unrealize(con->dev); 374 375 /* Disconnect from the frontend in case this has not already happened */ 376 xen_console_disconnect(xendev, NULL); 377 378 qemu_chr_fe_deinit(&con->chr, false); 379 } 380 381 static void xen_console_realize(XenDevice *xendev, Error **errp) 382 { 383 ERRP_GUARD(); 384 XenConsole *con = XEN_CONSOLE_DEVICE(xendev); 385 Chardev *cs = qemu_chr_fe_get_driver(&con->chr); 386 unsigned int u; 387 388 if (!cs) { 389 error_setg(errp, "no backing character device"); 390 return; 391 } 392 393 if (con->dev == -1) { 394 error_setg(errp, "no device index provided"); 395 return; 396 } 397 398 /* 399 * The Xen primary console is special. The ring-ref is actually a GFN to 400 * be mapped directly as foreignmem (not a grant ref), and the guest port 401 * was allocated *for* the guest by the toolstack. The guest gets these 402 * through HVMOP_get_param and can use the console long before it's got 403 * XenStore up and running. We cannot create those for a Xen guest. 404 */ 405 if (!con->dev) { 406 if (xen_device_frontend_scanf(xendev, "ring-ref", "%u", &u) != 1 || 407 xen_device_frontend_scanf(xendev, "port", "%u", &u) != 1) { 408 error_setg(errp, "cannot create primary Xen console"); 409 return; 410 } 411 } 412 413 trace_xen_console_realize(con->dev, object_get_typename(OBJECT(cs))); 414 415 if (CHARDEV_IS_PTY(cs)) { 416 /* Strip the leading 'pty:' */ 417 xen_device_frontend_printf(xendev, "tty", "%s", cs->filename + 4); 418 } 419 420 /* No normal PV driver initialization for the primary console */ 421 if (!con->dev) { 422 xen_console_connect(xendev, errp); 423 } 424 } 425 426 static char *console_frontend_path(struct qemu_xs_handle *xenstore, 427 unsigned int dom_id, unsigned int dev) 428 { 429 if (!dev) { 430 return g_strdup_printf("/local/domain/%u/console", dom_id); 431 } else { 432 return g_strdup_printf("/local/domain/%u/device/console/%u", dom_id, 433 dev); 434 } 435 } 436 437 static char *xen_console_get_frontend_path(XenDevice *xendev, Error **errp) 438 { 439 XenConsole *con = XEN_CONSOLE_DEVICE(xendev); 440 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev))); 441 char *ret = console_frontend_path(xenbus->xsh, xendev->frontend_id, 442 con->dev); 443 444 if (!ret) { 445 error_setg(errp, "failed to create frontend path"); 446 } 447 return ret; 448 } 449 450 451 static Property xen_console_properties[] = { 452 DEFINE_PROP_CHR("chardev", XenConsole, chr), 453 DEFINE_PROP_INT32("idx", XenConsole, dev, -1), 454 DEFINE_PROP_END_OF_LIST(), 455 }; 456 457 static void xen_console_class_init(ObjectClass *class, void *data) 458 { 459 DeviceClass *dev_class = DEVICE_CLASS(class); 460 XenDeviceClass *xendev_class = XEN_DEVICE_CLASS(class); 461 462 xendev_class->backend = "console"; 463 xendev_class->device = "console"; 464 xendev_class->get_name = xen_console_get_name; 465 xendev_class->realize = xen_console_realize; 466 xendev_class->frontend_changed = xen_console_frontend_changed; 467 xendev_class->unrealize = xen_console_unrealize; 468 xendev_class->get_frontend_path = xen_console_get_frontend_path; 469 470 device_class_set_props(dev_class, xen_console_properties); 471 } 472 473 static const TypeInfo xen_console_type_info = { 474 .name = TYPE_XEN_CONSOLE_DEVICE, 475 .parent = TYPE_XEN_DEVICE, 476 .instance_size = sizeof(XenConsole), 477 .class_init = xen_console_class_init, 478 }; 479 480 static void xen_console_register_types(void) 481 { 482 type_register_static(&xen_console_type_info); 483 } 484 485 type_init(xen_console_register_types) 486 487 /* Called to instantiate a XenConsole when the backend is detected. */ 488 static void xen_console_device_create(XenBackendInstance *backend, 489 QDict *opts, Error **errp) 490 { 491 ERRP_GUARD(); 492 XenBus *xenbus = xen_backend_get_bus(backend); 493 const char *name = xen_backend_get_name(backend); 494 unsigned long number; 495 char *fe = NULL, *type = NULL, *output = NULL; 496 char label[32]; 497 XenDevice *xendev = NULL; 498 XenConsole *con; 499 Chardev *cd = NULL; 500 struct qemu_xs_handle *xsh = xenbus->xsh; 501 502 if (qemu_strtoul(name, NULL, 10, &number) || number > INT_MAX) { 503 error_setg(errp, "failed to parse name '%s'", name); 504 goto fail; 505 } 506 507 trace_xen_console_device_create(number); 508 509 fe = console_frontend_path(xsh, xen_domid, number); 510 if (fe == NULL) { 511 error_setg(errp, "failed to generate frontend path"); 512 goto fail; 513 } 514 515 if (xs_node_scanf(xsh, XBT_NULL, fe, "type", errp, "%ms", &type) != 1) { 516 error_prepend(errp, "failed to read console device type: "); 517 goto fail; 518 } 519 520 if (strcmp(type, "ioemu")) { 521 error_setg(errp, "declining to handle console type '%s'", 522 type); 523 goto fail; 524 } 525 526 xendev = XEN_DEVICE(qdev_new(TYPE_XEN_CONSOLE_DEVICE)); 527 con = XEN_CONSOLE_DEVICE(xendev); 528 529 con->dev = number; 530 531 snprintf(label, sizeof(label), "xencons%ld", number); 532 533 if (xs_node_scanf(xsh, XBT_NULL, fe, "output", NULL, "%ms", &output) == 1) { 534 /* 535 * FIXME: sure we want to support implicit 536 * muxed monitors here? 537 */ 538 cd = qemu_chr_new_mux_mon(label, output, NULL); 539 if (!cd) { 540 error_setg(errp, "console: No valid chardev found at '%s': ", 541 output); 542 goto fail; 543 } 544 } else if (number) { 545 cd = serial_hd(number); 546 if (!cd) { 547 error_prepend(errp, "console: No serial device #%ld found: ", 548 number); 549 goto fail; 550 } 551 } else { 552 /* No 'output' node on primary console: use null. */ 553 cd = qemu_chr_new(label, "null", NULL); 554 if (!cd) { 555 error_setg(errp, "console: failed to create null device"); 556 goto fail; 557 } 558 } 559 560 if (!qemu_chr_fe_init(&con->chr, cd, errp)) { 561 error_prepend(errp, "console: failed to initialize backing chardev: "); 562 goto fail; 563 } 564 565 if (qdev_realize_and_unref(DEVICE(xendev), BUS(xenbus), errp)) { 566 xen_backend_set_device(backend, xendev); 567 goto done; 568 } 569 570 error_prepend(errp, "realization of console device %lu failed: ", 571 number); 572 573 fail: 574 if (xendev) { 575 object_unparent(OBJECT(xendev)); 576 } 577 done: 578 g_free(fe); 579 free(type); 580 free(output); 581 } 582 583 static void xen_console_device_destroy(XenBackendInstance *backend, 584 Error **errp) 585 { 586 ERRP_GUARD(); 587 XenDevice *xendev = xen_backend_get_device(backend); 588 XenConsole *con = XEN_CONSOLE_DEVICE(xendev); 589 590 trace_xen_console_device_destroy(con->dev); 591 592 object_unparent(OBJECT(xendev)); 593 } 594 595 static const XenBackendInfo xen_console_backend_info = { 596 .type = "console", 597 .create = xen_console_device_create, 598 .destroy = xen_console_device_destroy, 599 }; 600 601 static void xen_console_register_backend(void) 602 { 603 xen_backend_register(&xen_console_backend_info); 604 } 605 606 xen_backend_init(xen_console_register_backend); 607