1 /* 2 * Copyright (c) 2015 Julien Grall <julien.grall@citrix.com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 #include <sys/param.h> 31 #include <sys/module.h> 32 #include <sys/systm.h> 33 #include <sys/consio.h> 34 #include <sys/priv.h> 35 #include <sys/proc.h> 36 #include <sys/uio.h> 37 #include <sys/tty.h> 38 #include <sys/systm.h> 39 #include <sys/taskqueue.h> 40 #include <sys/conf.h> 41 #include <sys/kernel.h> 42 #include <sys/bus.h> 43 #include <sys/cons.h> 44 #include <sys/kdb.h> 45 #include <sys/proc.h> 46 47 #include <machine/stdarg.h> 48 49 #include <xen/xen-os.h> 50 #include <xen/hypervisor.h> 51 #include <xen/xen_intr.h> 52 #include <xen/interface/io/console.h> 53 54 #include "opt_ddb.h" 55 #include "opt_printf.h" 56 57 #ifdef DDB 58 #include <ddb/ddb.h> 59 #endif 60 61 static char driver_name[] = "xc"; 62 63 struct xencons_priv; 64 65 typedef void xencons_early_init_t(struct xencons_priv *cons); 66 typedef int xencons_init_t(device_t dev, struct tty *tp, 67 driver_intr_t intr_handler); 68 typedef int xencons_read_t(struct xencons_priv *cons, char *buffer, 69 unsigned int size); 70 typedef int xencons_write_t(struct xencons_priv *cons, const char *buffer, 71 unsigned int size); 72 73 struct xencons_ops { 74 /* 75 * Called by the low-level driver during early boot. 76 * Only the minimal set up to get a console should be done here. 77 */ 78 xencons_early_init_t *early_init; 79 /* Prepare the console to be fully use */ 80 xencons_init_t *init; 81 /* Read/write helpers */ 82 xencons_read_t *read; 83 xencons_write_t *write; 84 }; 85 86 struct xencons_priv { 87 /* Mutex to protect the shared ring and the internal buffers */ 88 struct mtx mtx; 89 /* Interrupt handler used for notify the backend */ 90 xen_intr_handle_t intr_handle; 91 /* KDB internal state */ 92 #ifdef KDB 93 int altbrk; 94 #endif 95 /* Status of the tty */ 96 bool opened; 97 /* Callout used when the write buffer is full */ 98 struct callout callout; 99 100 /* Internal buffers must be used with mtx locked */ 101 #define WBUF_SIZE 4096 102 #define WBUF_MASK(_i) ((_i)&(WBUF_SIZE-1)) 103 char wbuf[WBUF_SIZE]; 104 unsigned int wc, wp; /* Consumer/producer wbuf */ 105 106 #define RBUF_SIZE 1024 107 #define RBUF_MASK(_i) ((_i)&(RBUF_SIZE-1)) 108 char rbuf[RBUF_SIZE]; 109 unsigned int rc, rp; /* Consumer/producer rbuf */ 110 111 /* Pointer to the console operations */ 112 const struct xencons_ops *ops; 113 114 /* 115 * Ring specific fields 116 * XXX: make an union? 117 */ 118 /* Event channel number for early notification (PV only) */ 119 uint32_t evtchn; 120 /* Console shared page */ 121 struct xencons_interface *intf; 122 }; 123 124 /* 125 * Data for the main console 126 * Necessary to support low-level console driver 127 */ 128 static struct xencons_priv main_cons; 129 130 #define XC_POLLTIME (hz/10) 131 132 /* 133 * Virtual address of the shared console page (only for PV guest) 134 * TODO: Introduce a function to set it 135 */ 136 char *console_page; 137 138 /*----------------------------- Debug function ------------------------------*/ 139 struct putchar_arg { 140 char *buf; 141 size_t size; 142 size_t n_next; 143 }; 144 145 static void 146 putchar(int c, void *arg) 147 { 148 struct putchar_arg *pca; 149 150 pca = (struct putchar_arg *)arg; 151 152 if (pca->buf == NULL) { 153 /* 154 * We have no buffer, output directly to the 155 * console char by char. 156 */ 157 HYPERVISOR_console_write((char *)&c, 1); 158 } else { 159 pca->buf[pca->n_next++] = c; 160 if ((pca->size == pca->n_next) || (c = '\0')) { 161 /* Flush the buffer */ 162 HYPERVISOR_console_write(pca->buf, pca->n_next); 163 pca->n_next = 0; 164 } 165 } 166 } 167 168 void 169 xc_printf(const char *fmt, ...) 170 { 171 va_list ap; 172 struct putchar_arg pca; 173 #ifdef PRINTF_BUFR_SIZE 174 char buf[PRINTF_BUFR_SIZE]; 175 176 pca.buf = buf; 177 pca.size = sizeof(buf); 178 pca.n_next = 0; 179 #else 180 pca.buf = NULL; 181 pca.size = 0; 182 #endif 183 184 KASSERT((xen_domain()), ("call to xc_printf from non Xen guest")); 185 186 va_start(ap, fmt); 187 kvprintf(fmt, putchar, &pca, 10, ap); 188 va_end(ap); 189 190 #ifdef PRINTF_BUFR_SIZE 191 if (pca.n_next != 0) 192 HYPERVISOR_console_write(buf, pca.n_next); 193 #endif 194 } 195 196 /*---------------------- Helpers for the console lock -----------------------*/ 197 /* 198 * The lock is not used when the kernel is panicing as it will never recover 199 * and we want to output no matter what it costs. 200 */ 201 static inline void xencons_lock(struct xencons_priv *cons) 202 { 203 204 if (panicstr == NULL) 205 mtx_lock_spin(&cons->mtx); 206 207 } 208 209 static inline void xencons_unlock(struct xencons_priv *cons) 210 { 211 212 if (panicstr == NULL) 213 mtx_unlock_spin(&cons->mtx); 214 } 215 216 #define xencons_lock_assert(cons) mtx_assert(&(cons)->mtx, MA_OWNED) 217 218 /*------------------ Helpers for the hypervisor console ---------------------*/ 219 static void 220 xencons_early_init_hypervisor(struct xencons_priv *cons) 221 { 222 /* 223 * Nothing to setup for the low-level console when using 224 * the hypervisor console. 225 */ 226 } 227 228 static int 229 xencons_init_hypervisor(device_t dev, struct tty *tp, 230 driver_intr_t intr_handler) 231 { 232 struct xencons_priv *cons; 233 int err; 234 235 cons = tty_softc(tp); 236 237 err = xen_intr_bind_virq(dev, VIRQ_CONSOLE, 0, NULL, 238 intr_handler, tp, INTR_TYPE_TTY | INTR_MPSAFE, &cons->intr_handle); 239 if (err != 0) 240 device_printf(dev, "Can't register console interrupt\n"); 241 242 return (err); 243 } 244 245 static int 246 xencons_write_hypervisor(struct xencons_priv *cons, const char *buffer, 247 unsigned int size) 248 { 249 250 HYPERVISOR_console_io(CONSOLEIO_write, size, buffer); 251 252 return (size); 253 } 254 255 static int 256 xencons_read_hypervisor(struct xencons_priv *cons, char *buffer, 257 unsigned int size) 258 { 259 260 xencons_lock_assert(cons); 261 262 return (HYPERVISOR_console_io(CONSOLEIO_read, size, buffer)); 263 } 264 265 static const struct xencons_ops xencons_hypervisor_ops = { 266 .early_init = xencons_early_init_hypervisor, 267 .init = xencons_init_hypervisor, 268 .read = xencons_read_hypervisor, 269 .write = xencons_write_hypervisor, 270 }; 271 272 /*------------------ Helpers for the ring console ---------------------------*/ 273 static void 274 xencons_early_init_ring(struct xencons_priv *cons) 275 { 276 /* The shared page for PV is already mapped by the boot code */ 277 cons->intf = (struct xencons_interface *)console_page; 278 cons->evtchn = HYPERVISOR_start_info->console.domU.evtchn; 279 } 280 281 static int 282 xencons_init_ring(device_t dev, struct tty *tp, driver_intr_t intr_handler) 283 { 284 struct xencons_priv *cons; 285 int err; 286 287 cons = tty_softc(tp); 288 289 if (cons->evtchn == 0) 290 return (ENODEV); 291 292 err = xen_intr_bind_local_port(dev, cons->evtchn, NULL, 293 intr_handler, tp, INTR_TYPE_TTY | INTR_MPSAFE, &cons->intr_handle); 294 if (err != 0) 295 return (err); 296 297 return (0); 298 } 299 300 static void 301 xencons_notify_ring(struct xencons_priv *cons) 302 { 303 /* 304 * The console may be used before the ring interrupt is properly 305 * initialized. 306 * If so, fallback to directly use the event channel hypercall. 307 */ 308 if (__predict_true(cons->intr_handle != NULL)) 309 xen_intr_signal(cons->intr_handle); 310 else { 311 struct evtchn_send send = { 312 .port = cons->evtchn 313 }; 314 315 HYPERVISOR_event_channel_op(EVTCHNOP_send, &send); 316 } 317 } 318 319 static int 320 xencons_write_ring(struct xencons_priv *cons, const char *buffer, 321 unsigned int size) 322 { 323 struct xencons_interface *intf; 324 XENCONS_RING_IDX wcons, wprod; 325 int sent; 326 327 intf = cons->intf; 328 329 xencons_lock_assert(cons); 330 331 wcons = intf->out_cons; 332 wprod = intf->out_prod; 333 334 mb(); 335 KASSERT((wprod - wcons) <= sizeof(intf->out), 336 ("console send ring inconsistent")); 337 338 for (sent = 0; sent < size; sent++, wprod++) { 339 if ((wprod - wcons) >= sizeof(intf->out)) 340 break; 341 intf->out[MASK_XENCONS_IDX(wprod, intf->out)] = buffer[sent]; 342 } 343 344 wmb(); 345 intf->out_prod = wprod; 346 347 xencons_notify_ring(cons); 348 349 return (sent); 350 } 351 352 static int 353 xencons_read_ring(struct xencons_priv *cons, char *buffer, unsigned int size) 354 { 355 struct xencons_interface *intf; 356 XENCONS_RING_IDX rcons, rprod; 357 unsigned int rsz; 358 359 intf = cons->intf; 360 361 xencons_lock_assert(cons); 362 363 rcons = intf->in_cons; 364 rprod = intf->in_prod; 365 rmb(); 366 367 for (rsz = 0; rsz < size; rsz++, rcons++) { 368 if (rprod == rcons) 369 break; 370 buffer[rsz] = intf->in[MASK_XENCONS_IDX(rcons, intf->in)]; 371 } 372 373 wmb(); 374 intf->in_cons = rcons; 375 376 /* No need to notify the backend if nothing has been read */ 377 if (rsz != 0) 378 xencons_notify_ring(cons); 379 380 return (rsz); 381 } 382 383 static const struct xencons_ops xencons_ring_ops = { 384 .early_init = xencons_early_init_ring, 385 .init = xencons_init_ring, 386 .read = xencons_read_ring, 387 .write = xencons_write_ring, 388 }; 389 390 /*------------------ Common implementation of the console -------------------*/ 391 392 /* 393 * Called by the low-level driver during early boot to initialize the 394 * main console driver. 395 * Only the minimal set up to get a console should be done here. 396 */ 397 static void 398 xencons_early_init(void) 399 { 400 401 mtx_init(&main_cons.mtx, "XCONS LOCK", NULL, MTX_SPIN); 402 403 if (xen_initial_domain()) 404 main_cons.ops = &xencons_hypervisor_ops; 405 else 406 main_cons.ops = &xencons_ring_ops; 407 408 main_cons.ops->early_init(&main_cons); 409 } 410 411 /* 412 * Receive character from the console and put them in the internal buffer 413 * XXX: Handle overflow of the internal buffer 414 */ 415 static void 416 xencons_rx(struct xencons_priv *cons) 417 { 418 char buf[16]; 419 int sz; 420 421 xencons_lock(cons); 422 while ((sz = cons->ops->read(cons, buf, sizeof(buf))) > 0) { 423 int i; 424 425 for (i = 0; i < sz; i++) 426 cons->rbuf[RBUF_MASK(cons->rp++)] = buf[i]; 427 } 428 xencons_unlock(cons); 429 } 430 431 /* Return true if the write buffer is full */ 432 static bool 433 xencons_tx_full(struct xencons_priv *cons) 434 { 435 unsigned int used; 436 437 xencons_lock(cons); 438 used = cons->wp - cons->wc; 439 xencons_unlock(cons); 440 441 return (used >= WBUF_SIZE); 442 } 443 444 static void 445 xencons_tx_flush(struct xencons_priv *cons, int force) 446 { 447 int sz; 448 449 xencons_lock(cons); 450 while (cons->wc != cons->wp) { 451 int sent; 452 sz = cons->wp - cons->wc; 453 if (sz > (WBUF_SIZE - WBUF_MASK(cons->wc))) 454 sz = WBUF_SIZE - WBUF_MASK(cons->wc); 455 sent = cons->ops->write(cons, &cons->wbuf[WBUF_MASK(cons->wc)], 456 sz); 457 458 /* 459 * The other end may not have been initialized. Ignore 460 * the force. 461 */ 462 if (__predict_false(sent < 0)) 463 break; 464 465 /* 466 * If force is set, spin until the console data is 467 * flushed through the domain controller. 468 */ 469 if (sent == 0 && __predict_true(!force)) 470 break; 471 472 cons->wc += sent; 473 } 474 xencons_unlock(cons); 475 } 476 477 static bool 478 xencons_putc(struct xencons_priv *cons, int c, bool force_flush) 479 { 480 481 xencons_lock(cons); 482 if ((cons->wp - cons->wc) < WBUF_SIZE) 483 cons->wbuf[WBUF_MASK(cons->wp++)] = c; 484 xencons_unlock(cons); 485 486 xencons_tx_flush(cons, force_flush); 487 488 return (xencons_tx_full(cons)); 489 } 490 491 static int 492 xencons_getc(struct xencons_priv *cons) 493 { 494 int ret; 495 496 xencons_lock(cons); 497 if (cons->rp != cons->rc) { 498 /* We need to return only one char */ 499 ret = (int)cons->rbuf[RBUF_MASK(cons->rc)]; 500 cons->rc++; 501 } else { 502 ret = -1; 503 } 504 505 xencons_unlock(cons); 506 507 return (ret); 508 } 509 510 static bool 511 xencons_tx(struct tty *tp) 512 { 513 bool cons_full; 514 char c; 515 struct xencons_priv *cons; 516 517 cons = tty_softc(tp); 518 519 tty_lock_assert(tp, MA_OWNED); 520 521 /* 522 * Don't transmit any character if the buffer is full. Otherwise, 523 * characters may be lost 524 */ 525 if (xencons_tx_full(cons)) 526 return (false); 527 528 cons_full = false; 529 while (!cons_full && ttydisc_getc(tp, &c, 1) == 1) 530 cons_full = xencons_putc(cons, c, false); 531 532 return (!cons_full); 533 } 534 535 static void 536 xencons_intr(void *arg) 537 { 538 struct tty *tp; 539 struct xencons_priv *cons; 540 int ret; 541 542 tp = arg; 543 cons = tty_softc(tp); 544 545 /* 546 * The input will be used by the low-level console when KDB is active 547 */ 548 if (kdb_active) 549 return; 550 551 /* 552 * It's not necessary to retrieve input when the tty is not opened 553 */ 554 if (!cons->opened) 555 return; 556 557 xencons_rx(cons); 558 559 tty_lock(tp); 560 while ((ret = xencons_getc(cons)) != -1) { 561 #ifdef KDB 562 kdb_alt_break(ret, &cons->altbrk); 563 #endif 564 ttydisc_rint(tp, ret, 0); 565 } 566 ttydisc_rint_done(tp); 567 tty_unlock(tp); 568 569 /* Try to flush remaining characters if necessary */ 570 xencons_tx_flush(cons, 0); 571 } 572 573 /* 574 * Helpers to call while shutting down: 575 * - Force flush all output 576 */ 577 static void 578 xencons_shutdown(void *arg, int howto) 579 { 580 struct tty *tp; 581 582 tp = arg; 583 584 xencons_tx_flush(tty_softc(tp), 1); 585 } 586 587 /*---------------------- Low-level console driver ---------------------------*/ 588 static void 589 xencons_cnprobe(struct consdev *cp) 590 { 591 592 if (!xen_pv_domain()) 593 return; 594 595 cp->cn_pri = CN_REMOTE; 596 sprintf(cp->cn_name, "%s0", driver_name); 597 } 598 599 static void 600 xencons_cninit(struct consdev *cp) 601 { 602 603 xencons_early_init(); 604 } 605 606 static void 607 xencons_cnterm(struct consdev *cp) 608 { 609 } 610 611 static void 612 xencons_cngrab(struct consdev *cp) 613 { 614 } 615 616 static void 617 xencons_cnungrab(struct consdev *cp) 618 { 619 } 620 621 static int 622 xencons_cngetc(struct consdev *dev) 623 { 624 625 xencons_rx(&main_cons); 626 627 return (xencons_getc(&main_cons)); 628 } 629 630 static void 631 xencons_cnputc(struct consdev *dev, int c) 632 { 633 /* 634 * The low-level console is used by KDB and panic. We have to ensure 635 * that any character sent will be seen by the backend. 636 */ 637 xencons_putc(&main_cons, c, true); 638 } 639 640 CONSOLE_DRIVER(xencons); 641 642 /*----------------------------- TTY driver ---------------------------------*/ 643 644 static int 645 xencons_tty_open(struct tty *tp) 646 { 647 struct xencons_priv *cons; 648 649 cons = tty_softc(tp); 650 651 cons->opened = true; 652 653 return (0); 654 } 655 656 static void 657 xencons_tty_close(struct tty *tp) 658 { 659 struct xencons_priv *cons; 660 661 cons = tty_softc(tp); 662 663 cons->opened = false; 664 } 665 666 static void 667 xencons_timeout(void *v) 668 { 669 struct tty *tp; 670 struct xencons_priv *cons; 671 672 tp = v; 673 cons = tty_softc(tp); 674 675 if (!xencons_tx(tp)) 676 callout_reset(&cons->callout, XC_POLLTIME, 677 xencons_timeout, tp); 678 } 679 680 static void 681 xencons_tty_outwakeup(struct tty *tp) 682 { 683 struct xencons_priv *cons; 684 685 cons = tty_softc(tp); 686 687 callout_stop(&cons->callout); 688 689 if (!xencons_tx(tp)) 690 callout_reset(&cons->callout, XC_POLLTIME, 691 xencons_timeout, tp); 692 } 693 694 static struct ttydevsw xencons_ttydevsw = { 695 .tsw_flags = TF_NOPREFIX, 696 .tsw_open = xencons_tty_open, 697 .tsw_close = xencons_tty_close, 698 .tsw_outwakeup = xencons_tty_outwakeup, 699 }; 700 701 /*------------------------ Main console driver ------------------------------*/ 702 static void 703 xencons_identify(driver_t *driver, device_t parent) 704 { 705 device_t child; 706 707 #if defined(__arm__) || defined(__aarch64__) 708 if (!xen_domain()) 709 return; 710 #else 711 if (!xen_pv_domain()) 712 return; 713 #endif 714 715 child = BUS_ADD_CHILD(parent, 0, driver_name, 0); 716 } 717 718 static int 719 xencons_probe(device_t dev) 720 { 721 722 device_set_desc(dev, "Xen Console"); 723 return (BUS_PROBE_NOWILDCARD); 724 } 725 726 static int 727 xencons_attach(device_t dev) 728 { 729 struct tty *tp; 730 /* 731 * The main console is already allocated statically in order to 732 * support low-level console 733 */ 734 struct xencons_priv *cons; 735 int err; 736 737 cons = &main_cons; 738 739 tp = tty_alloc(&xencons_ttydevsw, cons); 740 tty_makedev(tp, NULL, "%s%r", driver_name, 0); 741 device_set_softc(dev, tp); 742 743 callout_init_mtx(&cons->callout, tty_getlock(tp), 0); 744 745 err = cons->ops->init(dev, tp, xencons_intr); 746 if (err != 0) { 747 device_printf(dev, "Unable to initialize the console (%d)\n", 748 err); 749 return (err); 750 } 751 752 /* register handler to flush console on shutdown */ 753 if ((EVENTHANDLER_REGISTER(shutdown_post_sync, xencons_shutdown, 754 tp, SHUTDOWN_PRI_DEFAULT)) == NULL) 755 device_printf(dev, "shutdown event registration failed!\n"); 756 757 return (0); 758 } 759 760 static int 761 xencons_resume(device_t dev) 762 { 763 struct xencons_priv *cons; 764 struct tty *tp; 765 int err; 766 767 tp = device_get_softc(dev); 768 cons = tty_softc(tp); 769 xen_intr_unbind(&cons->intr_handle); 770 771 err = cons->ops->init(dev, tp, xencons_intr); 772 if (err != 0) { 773 device_printf(dev, "Unable to resume the console (%d)\n", err); 774 return (err); 775 } 776 777 return (0); 778 } 779 780 static devclass_t xencons_devclass; 781 782 static device_method_t xencons_methods[] = { 783 DEVMETHOD(device_identify, xencons_identify), 784 DEVMETHOD(device_probe, xencons_probe), 785 DEVMETHOD(device_attach, xencons_attach), 786 DEVMETHOD(device_resume, xencons_resume), 787 788 DEVMETHOD_END 789 }; 790 791 static driver_t xencons_driver = { 792 driver_name, 793 xencons_methods, 794 0, 795 }; 796 797 DRIVER_MODULE(xc, xenpv, xencons_driver, xencons_devclass, 0, 0); 798