1 /*- 2 * Copyright (c) 2014, Bryan Venteicher <bryanv@FreeBSD.org> 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 unmodified, this list of conditions, and the following 10 * disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 /* Driver for VirtIO console devices. */ 28 29 #include <sys/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/kernel.h> 35 #include <sys/malloc.h> 36 #include <sys/module.h> 37 #include <sys/kdb.h> 38 #include <sys/lock.h> 39 #include <sys/mutex.h> 40 #include <sys/sglist.h> 41 #include <sys/sysctl.h> 42 #include <sys/taskqueue.h> 43 #include <sys/queue.h> 44 45 #include <sys/conf.h> 46 #include <sys/cons.h> 47 #include <sys/tty.h> 48 49 #include <machine/bus.h> 50 #include <machine/resource.h> 51 #include <sys/bus.h> 52 53 #include <dev/virtio/virtio.h> 54 #include <dev/virtio/virtqueue.h> 55 #include <dev/virtio/console/virtio_console.h> 56 57 #include "virtio_if.h" 58 59 #define VTCON_MAX_PORTS 32 60 #define VTCON_TTY_PREFIX "V" 61 #define VTCON_BULK_BUFSZ 128 62 63 /* 64 * The buffer cannot cross more than one page boundary due to the 65 * size of the sglist segment array used. 66 */ 67 CTASSERT(VTCON_BULK_BUFSZ <= PAGE_SIZE); 68 69 struct vtcon_softc; 70 struct vtcon_softc_port; 71 72 struct vtcon_port { 73 struct mtx vtcport_mtx; 74 struct vtcon_softc *vtcport_sc; 75 struct vtcon_softc_port *vtcport_scport; 76 struct tty *vtcport_tty; 77 struct virtqueue *vtcport_invq; 78 struct virtqueue *vtcport_outvq; 79 int vtcport_id; 80 int vtcport_flags; 81 #define VTCON_PORT_FLAG_GONE 0x01 82 #define VTCON_PORT_FLAG_CONSOLE 0x02 83 84 #if defined(KDB) 85 int vtcport_alt_break_state; 86 #endif 87 }; 88 89 #define VTCON_PORT_LOCK(_port) mtx_lock(&(_port)->vtcport_mtx) 90 #define VTCON_PORT_UNLOCK(_port) mtx_unlock(&(_port)->vtcport_mtx) 91 92 struct vtcon_softc_port { 93 struct vtcon_softc *vcsp_sc; 94 struct vtcon_port *vcsp_port; 95 struct virtqueue *vcsp_invq; 96 struct virtqueue *vcsp_outvq; 97 }; 98 99 struct vtcon_softc { 100 device_t vtcon_dev; 101 struct mtx vtcon_mtx; 102 uint64_t vtcon_features; 103 uint32_t vtcon_max_ports; 104 uint32_t vtcon_flags; 105 #define VTCON_FLAG_DETACHED 0x01 106 #define VTCON_FLAG_SIZE 0x02 107 #define VTCON_FLAG_MULTIPORT 0x04 108 109 /* 110 * Ports can be added and removed during runtime, but we have 111 * to allocate all the virtqueues during attach. This array is 112 * indexed by the port ID. 113 */ 114 struct vtcon_softc_port *vtcon_ports; 115 116 struct task vtcon_ctrl_task; 117 struct virtqueue *vtcon_ctrl_rxvq; 118 struct virtqueue *vtcon_ctrl_txvq; 119 struct mtx vtcon_ctrl_tx_mtx; 120 }; 121 122 #define VTCON_LOCK(_sc) mtx_lock(&(_sc)->vtcon_mtx) 123 #define VTCON_UNLOCK(_sc) mtx_unlock(&(_sc)->vtcon_mtx) 124 #define VTCON_LOCK_ASSERT(_sc) \ 125 mtx_assert(&(_sc)->vtcon_mtx, MA_OWNED) 126 #define VTCON_LOCK_ASSERT_NOTOWNED(_sc) \ 127 mtx_assert(&(_sc)->vtcon_mtx, MA_NOTOWNED) 128 129 #define VTCON_CTRL_TX_LOCK(_sc) mtx_lock(&(_sc)->vtcon_ctrl_tx_mtx) 130 #define VTCON_CTRL_TX_UNLOCK(_sc) mtx_unlock(&(_sc)->vtcon_ctrl_tx_mtx) 131 132 #define VTCON_ASSERT_VALID_PORTID(_sc, _id) \ 133 KASSERT((_id) >= 0 && (_id) < (_sc)->vtcon_max_ports, \ 134 ("%s: port ID %d out of range", __func__, _id)) 135 136 #define VTCON_FEATURES VIRTIO_CONSOLE_F_MULTIPORT 137 138 static struct virtio_feature_desc vtcon_feature_desc[] = { 139 { VIRTIO_CONSOLE_F_SIZE, "ConsoleSize" }, 140 { VIRTIO_CONSOLE_F_MULTIPORT, "MultiplePorts" }, 141 { VIRTIO_CONSOLE_F_EMERG_WRITE, "EmergencyWrite" }, 142 143 { 0, NULL } 144 }; 145 146 static int vtcon_modevent(module_t, int, void *); 147 static void vtcon_drain_all(void); 148 149 static int vtcon_probe(device_t); 150 static int vtcon_attach(device_t); 151 static int vtcon_detach(device_t); 152 static int vtcon_config_change(device_t); 153 154 static void vtcon_setup_features(struct vtcon_softc *); 155 static void vtcon_negotiate_features(struct vtcon_softc *); 156 static int vtcon_alloc_scports(struct vtcon_softc *); 157 static int vtcon_alloc_virtqueues(struct vtcon_softc *); 158 static void vtcon_read_config(struct vtcon_softc *, 159 struct virtio_console_config *); 160 161 static void vtcon_determine_max_ports(struct vtcon_softc *, 162 struct virtio_console_config *); 163 static void vtcon_destroy_ports(struct vtcon_softc *); 164 static void vtcon_stop(struct vtcon_softc *); 165 166 static int vtcon_ctrl_event_enqueue(struct vtcon_softc *, 167 struct virtio_console_control *); 168 static int vtcon_ctrl_event_create(struct vtcon_softc *); 169 static void vtcon_ctrl_event_requeue(struct vtcon_softc *, 170 struct virtio_console_control *); 171 static int vtcon_ctrl_event_populate(struct vtcon_softc *); 172 static void vtcon_ctrl_event_drain(struct vtcon_softc *); 173 static int vtcon_ctrl_init(struct vtcon_softc *); 174 static void vtcon_ctrl_deinit(struct vtcon_softc *); 175 static void vtcon_ctrl_port_add_event(struct vtcon_softc *, int); 176 static void vtcon_ctrl_port_remove_event(struct vtcon_softc *, int); 177 static void vtcon_ctrl_port_console_event(struct vtcon_softc *, int); 178 static void vtcon_ctrl_port_open_event(struct vtcon_softc *, int); 179 static void vtcon_ctrl_process_event(struct vtcon_softc *, 180 struct virtio_console_control *); 181 static void vtcon_ctrl_task_cb(void *, int); 182 static void vtcon_ctrl_event_intr(void *); 183 static void vtcon_ctrl_poll(struct vtcon_softc *, 184 struct virtio_console_control *control); 185 static void vtcon_ctrl_send_control(struct vtcon_softc *, uint32_t, 186 uint16_t, uint16_t); 187 188 static int vtcon_port_enqueue_buf(struct vtcon_port *, void *, size_t); 189 static int vtcon_port_create_buf(struct vtcon_port *); 190 static void vtcon_port_requeue_buf(struct vtcon_port *, void *); 191 static int vtcon_port_populate(struct vtcon_port *); 192 static void vtcon_port_destroy(struct vtcon_port *); 193 static int vtcon_port_create(struct vtcon_softc *, int); 194 static void vtcon_port_drain_bufs(struct virtqueue *); 195 static void vtcon_port_drain(struct vtcon_port *); 196 static void vtcon_port_teardown(struct vtcon_port *); 197 static void vtcon_port_change_size(struct vtcon_port *, uint16_t, 198 uint16_t); 199 static void vtcon_port_update_console_size(struct vtcon_softc *); 200 static void vtcon_port_enable_intr(struct vtcon_port *); 201 static void vtcon_port_disable_intr(struct vtcon_port *); 202 static void vtcon_port_in(struct vtcon_port *); 203 static void vtcon_port_intr(void *); 204 static void vtcon_port_out(struct vtcon_port *, void *, int); 205 static void vtcon_port_submit_event(struct vtcon_port *, uint16_t, 206 uint16_t); 207 208 static int vtcon_tty_open(struct tty *); 209 static void vtcon_tty_close(struct tty *); 210 static void vtcon_tty_outwakeup(struct tty *); 211 static void vtcon_tty_free(void *); 212 213 static void vtcon_get_console_size(struct vtcon_softc *, uint16_t *, 214 uint16_t *); 215 216 static void vtcon_enable_interrupts(struct vtcon_softc *); 217 static void vtcon_disable_interrupts(struct vtcon_softc *); 218 219 static int vtcon_pending_free; 220 221 static struct ttydevsw vtcon_tty_class = { 222 .tsw_flags = 0, 223 .tsw_open = vtcon_tty_open, 224 .tsw_close = vtcon_tty_close, 225 .tsw_outwakeup = vtcon_tty_outwakeup, 226 .tsw_free = vtcon_tty_free, 227 }; 228 229 static device_method_t vtcon_methods[] = { 230 /* Device methods. */ 231 DEVMETHOD(device_probe, vtcon_probe), 232 DEVMETHOD(device_attach, vtcon_attach), 233 DEVMETHOD(device_detach, vtcon_detach), 234 235 /* VirtIO methods. */ 236 DEVMETHOD(virtio_config_change, vtcon_config_change), 237 238 DEVMETHOD_END 239 }; 240 241 static driver_t vtcon_driver = { 242 "vtcon", 243 vtcon_methods, 244 sizeof(struct vtcon_softc) 245 }; 246 static devclass_t vtcon_devclass; 247 248 DRIVER_MODULE(virtio_console, virtio_pci, vtcon_driver, vtcon_devclass, 249 vtcon_modevent, 0); 250 MODULE_VERSION(virtio_console, 1); 251 MODULE_DEPEND(virtio_console, virtio, 1, 1, 1); 252 253 static int 254 vtcon_modevent(module_t mod, int type, void *unused) 255 { 256 int error; 257 258 switch (type) { 259 case MOD_LOAD: 260 error = 0; 261 break; 262 case MOD_QUIESCE: 263 error = 0; 264 break; 265 case MOD_UNLOAD: 266 vtcon_drain_all(); 267 error = 0; 268 break; 269 case MOD_SHUTDOWN: 270 error = 0; 271 break; 272 default: 273 error = EOPNOTSUPP; 274 break; 275 } 276 277 return (error); 278 } 279 280 static void 281 vtcon_drain_all(void) 282 { 283 int first; 284 285 for (first = 1; vtcon_pending_free != 0; first = 0) { 286 if (first != 0) { 287 printf("virtio_console: Waiting for all detached TTY " 288 "devices to have open fds closed.\n"); 289 } 290 pause("vtcondra", hz); 291 } 292 } 293 294 static int 295 vtcon_probe(device_t dev) 296 { 297 298 if (virtio_get_device_type(dev) != VIRTIO_ID_CONSOLE) 299 return (ENXIO); 300 301 device_set_desc(dev, "VirtIO Console Adapter"); 302 303 return (BUS_PROBE_DEFAULT); 304 } 305 306 static int 307 vtcon_attach(device_t dev) 308 { 309 struct vtcon_softc *sc; 310 struct virtio_console_config concfg; 311 int error; 312 313 sc = device_get_softc(dev); 314 sc->vtcon_dev = dev; 315 316 mtx_init(&sc->vtcon_mtx, "vtconmtx", NULL, MTX_DEF); 317 mtx_init(&sc->vtcon_ctrl_tx_mtx, "vtconctrlmtx", NULL, MTX_DEF); 318 319 virtio_set_feature_desc(dev, vtcon_feature_desc); 320 vtcon_setup_features(sc); 321 322 vtcon_read_config(sc, &concfg); 323 vtcon_determine_max_ports(sc, &concfg); 324 325 error = vtcon_alloc_scports(sc); 326 if (error) { 327 device_printf(dev, "cannot allocate softc port structures\n"); 328 goto fail; 329 } 330 331 error = vtcon_alloc_virtqueues(sc); 332 if (error) { 333 device_printf(dev, "cannot allocate virtqueues\n"); 334 goto fail; 335 } 336 337 if (sc->vtcon_flags & VTCON_FLAG_MULTIPORT) { 338 TASK_INIT(&sc->vtcon_ctrl_task, 0, vtcon_ctrl_task_cb, sc); 339 error = vtcon_ctrl_init(sc); 340 if (error) 341 goto fail; 342 } else { 343 error = vtcon_port_create(sc, 0); 344 if (error) 345 goto fail; 346 if (sc->vtcon_flags & VTCON_FLAG_SIZE) 347 vtcon_port_update_console_size(sc); 348 } 349 350 error = virtio_setup_intr(dev, INTR_TYPE_TTY); 351 if (error) { 352 device_printf(dev, "cannot setup virtqueue interrupts\n"); 353 goto fail; 354 } 355 356 vtcon_enable_interrupts(sc); 357 358 vtcon_ctrl_send_control(sc, VIRTIO_CONSOLE_BAD_ID, 359 VIRTIO_CONSOLE_DEVICE_READY, 1); 360 361 fail: 362 if (error) 363 vtcon_detach(dev); 364 365 return (error); 366 } 367 368 static int 369 vtcon_detach(device_t dev) 370 { 371 struct vtcon_softc *sc; 372 373 sc = device_get_softc(dev); 374 375 VTCON_LOCK(sc); 376 sc->vtcon_flags |= VTCON_FLAG_DETACHED; 377 if (device_is_attached(dev)) 378 vtcon_stop(sc); 379 VTCON_UNLOCK(sc); 380 381 if (sc->vtcon_flags & VTCON_FLAG_MULTIPORT) { 382 taskqueue_drain(taskqueue_thread, &sc->vtcon_ctrl_task); 383 vtcon_ctrl_deinit(sc); 384 } 385 386 vtcon_destroy_ports(sc); 387 mtx_destroy(&sc->vtcon_mtx); 388 mtx_destroy(&sc->vtcon_ctrl_tx_mtx); 389 390 return (0); 391 } 392 393 static int 394 vtcon_config_change(device_t dev) 395 { 396 struct vtcon_softc *sc; 397 398 sc = device_get_softc(dev); 399 400 /* 401 * When the multiport feature is negotiated, all configuration 402 * changes are done through control virtqueue events. 403 */ 404 if ((sc->vtcon_flags & VTCON_FLAG_MULTIPORT) == 0) { 405 if (sc->vtcon_flags & VTCON_FLAG_SIZE) 406 vtcon_port_update_console_size(sc); 407 } 408 409 return (0); 410 } 411 412 static void 413 vtcon_negotiate_features(struct vtcon_softc *sc) 414 { 415 device_t dev; 416 uint64_t features; 417 418 dev = sc->vtcon_dev; 419 features = VTCON_FEATURES; 420 421 sc->vtcon_features = virtio_negotiate_features(dev, features); 422 } 423 424 static void 425 vtcon_setup_features(struct vtcon_softc *sc) 426 { 427 device_t dev; 428 429 dev = sc->vtcon_dev; 430 431 vtcon_negotiate_features(sc); 432 433 if (virtio_with_feature(dev, VIRTIO_CONSOLE_F_SIZE)) 434 sc->vtcon_flags |= VTCON_FLAG_SIZE; 435 if (virtio_with_feature(dev, VIRTIO_CONSOLE_F_MULTIPORT)) 436 sc->vtcon_flags |= VTCON_FLAG_MULTIPORT; 437 } 438 439 #define VTCON_GET_CONFIG(_dev, _feature, _field, _cfg) \ 440 if (virtio_with_feature(_dev, _feature)) { \ 441 virtio_read_device_config(_dev, \ 442 offsetof(struct virtio_console_config, _field), \ 443 &(_cfg)->_field, sizeof((_cfg)->_field)); \ 444 } 445 446 static void 447 vtcon_read_config(struct vtcon_softc *sc, struct virtio_console_config *concfg) 448 { 449 device_t dev; 450 451 dev = sc->vtcon_dev; 452 453 bzero(concfg, sizeof(struct virtio_console_config)); 454 455 VTCON_GET_CONFIG(dev, VIRTIO_CONSOLE_F_SIZE, cols, concfg); 456 VTCON_GET_CONFIG(dev, VIRTIO_CONSOLE_F_SIZE, rows, concfg); 457 VTCON_GET_CONFIG(dev, VIRTIO_CONSOLE_F_MULTIPORT, max_nr_ports, concfg); 458 } 459 460 #undef VTCON_GET_CONFIG 461 462 static int 463 vtcon_alloc_scports(struct vtcon_softc *sc) 464 { 465 struct vtcon_softc_port *scport; 466 int max, i; 467 468 max = sc->vtcon_max_ports; 469 470 sc->vtcon_ports = malloc(sizeof(struct vtcon_softc_port) * max, 471 M_DEVBUF, M_NOWAIT | M_ZERO); 472 if (sc->vtcon_ports == NULL) 473 return (ENOMEM); 474 475 for (i = 0; i < max; i++) { 476 scport = &sc->vtcon_ports[i]; 477 scport->vcsp_sc = sc; 478 } 479 480 return (0); 481 } 482 483 static int 484 vtcon_alloc_virtqueues(struct vtcon_softc *sc) 485 { 486 device_t dev; 487 struct vq_alloc_info *info; 488 struct vtcon_softc_port *scport; 489 int i, idx, portidx, nvqs, error; 490 491 dev = sc->vtcon_dev; 492 493 nvqs = sc->vtcon_max_ports * 2; 494 if (sc->vtcon_flags & VTCON_FLAG_MULTIPORT) 495 nvqs += 2; 496 497 info = malloc(sizeof(struct vq_alloc_info) * nvqs, M_TEMP, M_NOWAIT); 498 if (info == NULL) 499 return (ENOMEM); 500 501 for (i = 0, idx = 0, portidx = 0; i < nvqs / 2; i++, idx += 2) { 502 503 if (i == 1) { 504 /* The control virtqueues are after the first port. */ 505 VQ_ALLOC_INFO_INIT(&info[idx], 0, 506 vtcon_ctrl_event_intr, sc, &sc->vtcon_ctrl_rxvq, 507 "%s-control rx", device_get_nameunit(dev)); 508 VQ_ALLOC_INFO_INIT(&info[idx+1], 0, 509 NULL, sc, &sc->vtcon_ctrl_txvq, 510 "%s-control tx", device_get_nameunit(dev)); 511 continue; 512 } 513 514 scport = &sc->vtcon_ports[portidx]; 515 516 VQ_ALLOC_INFO_INIT(&info[idx], 0, vtcon_port_intr, 517 scport, &scport->vcsp_invq, "%s-port%d in", 518 device_get_nameunit(dev), i); 519 VQ_ALLOC_INFO_INIT(&info[idx+1], 0, NULL, 520 NULL, &scport->vcsp_outvq, "%s-port%d out", 521 device_get_nameunit(dev), i); 522 523 portidx++; 524 } 525 526 error = virtio_alloc_virtqueues(dev, 0, nvqs, info); 527 free(info, M_TEMP); 528 529 return (error); 530 } 531 532 static void 533 vtcon_determine_max_ports(struct vtcon_softc *sc, 534 struct virtio_console_config *concfg) 535 { 536 537 if (sc->vtcon_flags & VTCON_FLAG_MULTIPORT) { 538 sc->vtcon_max_ports = 539 min(concfg->max_nr_ports, VTCON_MAX_PORTS); 540 if (sc->vtcon_max_ports == 0) 541 sc->vtcon_max_ports = 1; 542 } else 543 sc->vtcon_max_ports = 1; 544 } 545 546 static void 547 vtcon_destroy_ports(struct vtcon_softc *sc) 548 { 549 struct vtcon_softc_port *scport; 550 struct vtcon_port *port; 551 struct virtqueue *vq; 552 int i; 553 554 if (sc->vtcon_ports == NULL) 555 return; 556 557 VTCON_LOCK(sc); 558 for (i = 0; i < sc->vtcon_max_ports; i++) { 559 scport = &sc->vtcon_ports[i]; 560 561 port = scport->vcsp_port; 562 if (port != NULL) { 563 scport->vcsp_port = NULL; 564 VTCON_PORT_LOCK(port); 565 VTCON_UNLOCK(sc); 566 vtcon_port_teardown(port); 567 VTCON_LOCK(sc); 568 } 569 570 vq = scport->vcsp_invq; 571 if (vq != NULL) 572 vtcon_port_drain_bufs(vq); 573 } 574 VTCON_UNLOCK(sc); 575 576 free(sc->vtcon_ports, M_DEVBUF); 577 sc->vtcon_ports = NULL; 578 } 579 580 static void 581 vtcon_stop(struct vtcon_softc *sc) 582 { 583 584 vtcon_disable_interrupts(sc); 585 virtio_stop(sc->vtcon_dev); 586 } 587 588 static int 589 vtcon_ctrl_event_enqueue(struct vtcon_softc *sc, 590 struct virtio_console_control *control) 591 { 592 struct sglist_seg segs[2]; 593 struct sglist sg; 594 struct virtqueue *vq; 595 int error; 596 597 vq = sc->vtcon_ctrl_rxvq; 598 599 sglist_init(&sg, 2, segs); 600 error = sglist_append(&sg, control, 601 sizeof(struct virtio_console_control)); 602 KASSERT(error == 0, ("%s: error %d adding control to sglist", 603 __func__, error)); 604 605 return (virtqueue_enqueue(vq, control, &sg, 0, sg.sg_nseg)); 606 } 607 608 static int 609 vtcon_ctrl_event_create(struct vtcon_softc *sc) 610 { 611 struct virtio_console_control *control; 612 int error; 613 614 control = malloc(sizeof(struct virtio_console_control), M_DEVBUF, 615 M_ZERO | M_NOWAIT); 616 if (control == NULL) 617 return (ENOMEM); 618 619 error = vtcon_ctrl_event_enqueue(sc, control); 620 if (error) 621 free(control, M_DEVBUF); 622 623 return (error); 624 } 625 626 static void 627 vtcon_ctrl_event_requeue(struct vtcon_softc *sc, 628 struct virtio_console_control *control) 629 { 630 int error; 631 632 bzero(control, sizeof(struct virtio_console_control)); 633 634 error = vtcon_ctrl_event_enqueue(sc, control); 635 KASSERT(error == 0, 636 ("%s: cannot requeue control buffer %d", __func__, error)); 637 } 638 639 static int 640 vtcon_ctrl_event_populate(struct vtcon_softc *sc) 641 { 642 struct virtqueue *vq; 643 int nbufs, error; 644 645 vq = sc->vtcon_ctrl_rxvq; 646 error = ENOSPC; 647 648 for (nbufs = 0; !virtqueue_full(vq); nbufs++) { 649 error = vtcon_ctrl_event_create(sc); 650 if (error) 651 break; 652 } 653 654 if (nbufs > 0) { 655 virtqueue_notify(vq); 656 error = 0; 657 } 658 659 return (error); 660 } 661 662 static void 663 vtcon_ctrl_event_drain(struct vtcon_softc *sc) 664 { 665 struct virtio_console_control *control; 666 struct virtqueue *vq; 667 int last; 668 669 vq = sc->vtcon_ctrl_rxvq; 670 last = 0; 671 672 if (vq == NULL) 673 return; 674 675 VTCON_LOCK(sc); 676 while ((control = virtqueue_drain(vq, &last)) != NULL) 677 free(control, M_DEVBUF); 678 VTCON_UNLOCK(sc); 679 } 680 681 static int 682 vtcon_ctrl_init(struct vtcon_softc *sc) 683 { 684 int error; 685 686 error = vtcon_ctrl_event_populate(sc); 687 688 return (error); 689 } 690 691 static void 692 vtcon_ctrl_deinit(struct vtcon_softc *sc) 693 { 694 695 vtcon_ctrl_event_drain(sc); 696 } 697 698 static void 699 vtcon_ctrl_port_add_event(struct vtcon_softc *sc, int id) 700 { 701 device_t dev; 702 int error; 703 704 dev = sc->vtcon_dev; 705 706 /* This single thread only way for ports to be created. */ 707 if (sc->vtcon_ports[id].vcsp_port != NULL) { 708 device_printf(dev, "%s: adding port %d, but already exists\n", 709 __func__, id); 710 return; 711 } 712 713 error = vtcon_port_create(sc, id); 714 if (error) { 715 device_printf(dev, "%s: cannot create port %d: %d\n", 716 __func__, id, error); 717 vtcon_ctrl_send_control(sc, id, VIRTIO_CONSOLE_PORT_READY, 0); 718 return; 719 } 720 } 721 722 static void 723 vtcon_ctrl_port_remove_event(struct vtcon_softc *sc, int id) 724 { 725 device_t dev; 726 struct vtcon_softc_port *scport; 727 struct vtcon_port *port; 728 729 dev = sc->vtcon_dev; 730 scport = &sc->vtcon_ports[id]; 731 732 VTCON_LOCK(sc); 733 port = scport->vcsp_port; 734 if (port == NULL) { 735 VTCON_UNLOCK(sc); 736 device_printf(dev, "%s: remove port %d, but does not exist\n", 737 __func__, id); 738 return; 739 } 740 741 scport->vcsp_port = NULL; 742 VTCON_PORT_LOCK(port); 743 VTCON_UNLOCK(sc); 744 vtcon_port_teardown(port); 745 } 746 747 static void 748 vtcon_ctrl_port_console_event(struct vtcon_softc *sc, int id) 749 { 750 device_t dev; 751 struct vtcon_softc_port *scport; 752 struct vtcon_port *port; 753 754 dev = sc->vtcon_dev; 755 scport = &sc->vtcon_ports[id]; 756 757 VTCON_LOCK(sc); 758 port = scport->vcsp_port; 759 if (port == NULL) { 760 VTCON_UNLOCK(sc); 761 device_printf(dev, "%s: console port %d, but does not exist\n", 762 __func__, id); 763 return; 764 } 765 766 VTCON_PORT_LOCK(port); 767 VTCON_UNLOCK(sc); 768 port->vtcport_flags |= VTCON_PORT_FLAG_CONSOLE; 769 vtcon_port_submit_event(port, VIRTIO_CONSOLE_PORT_OPEN, 1); 770 VTCON_PORT_UNLOCK(port); 771 } 772 773 static void 774 vtcon_ctrl_port_open_event(struct vtcon_softc *sc, int id) 775 { 776 device_t dev; 777 struct vtcon_softc_port *scport; 778 struct vtcon_port *port; 779 780 dev = sc->vtcon_dev; 781 scport = &sc->vtcon_ports[id]; 782 783 VTCON_LOCK(sc); 784 port = scport->vcsp_port; 785 if (port == NULL) { 786 VTCON_UNLOCK(sc); 787 device_printf(dev, "%s: open port %d, but does not exist\n", 788 __func__, id); 789 return; 790 } 791 792 VTCON_PORT_LOCK(port); 793 VTCON_UNLOCK(sc); 794 vtcon_port_enable_intr(port); 795 VTCON_PORT_UNLOCK(port); 796 } 797 798 static void 799 vtcon_ctrl_process_event(struct vtcon_softc *sc, 800 struct virtio_console_control *control) 801 { 802 device_t dev; 803 int id; 804 805 dev = sc->vtcon_dev; 806 id = control->id; 807 808 if (id < 0 || id >= sc->vtcon_max_ports) { 809 device_printf(dev, "%s: invalid port ID %d\n", __func__, id); 810 return; 811 } 812 813 switch (control->event) { 814 case VIRTIO_CONSOLE_PORT_ADD: 815 vtcon_ctrl_port_add_event(sc, id); 816 break; 817 818 case VIRTIO_CONSOLE_PORT_REMOVE: 819 vtcon_ctrl_port_remove_event(sc, id); 820 break; 821 822 case VIRTIO_CONSOLE_CONSOLE_PORT: 823 vtcon_ctrl_port_console_event(sc, id); 824 break; 825 826 case VIRTIO_CONSOLE_RESIZE: 827 break; 828 829 case VIRTIO_CONSOLE_PORT_OPEN: 830 vtcon_ctrl_port_open_event(sc, id); 831 break; 832 833 case VIRTIO_CONSOLE_PORT_NAME: 834 break; 835 } 836 } 837 838 static void 839 vtcon_ctrl_task_cb(void *xsc, int pending) 840 { 841 struct vtcon_softc *sc; 842 struct virtqueue *vq; 843 struct virtio_console_control *control; 844 int detached; 845 846 sc = xsc; 847 vq = sc->vtcon_ctrl_rxvq; 848 849 VTCON_LOCK(sc); 850 851 while ((detached = (sc->vtcon_flags & VTCON_FLAG_DETACHED)) == 0) { 852 control = virtqueue_dequeue(vq, NULL); 853 if (control == NULL) 854 break; 855 856 VTCON_UNLOCK(sc); 857 vtcon_ctrl_process_event(sc, control); 858 VTCON_LOCK(sc); 859 vtcon_ctrl_event_requeue(sc, control); 860 } 861 862 if (!detached) { 863 virtqueue_notify(vq); 864 if (virtqueue_enable_intr(vq) != 0) 865 taskqueue_enqueue(taskqueue_thread, 866 &sc->vtcon_ctrl_task); 867 } 868 869 VTCON_UNLOCK(sc); 870 } 871 872 static void 873 vtcon_ctrl_event_intr(void *xsc) 874 { 875 struct vtcon_softc *sc; 876 877 sc = xsc; 878 879 /* 880 * Only some events require us to potentially block, but it 881 * easier to just defer all event handling to the taskqueue. 882 */ 883 taskqueue_enqueue(taskqueue_thread, &sc->vtcon_ctrl_task); 884 } 885 886 static void 887 vtcon_ctrl_poll(struct vtcon_softc *sc, 888 struct virtio_console_control *control) 889 { 890 struct sglist_seg segs[2]; 891 struct sglist sg; 892 struct virtqueue *vq; 893 int error; 894 895 vq = sc->vtcon_ctrl_txvq; 896 897 sglist_init(&sg, 2, segs); 898 error = sglist_append(&sg, control, 899 sizeof(struct virtio_console_control)); 900 KASSERT(error == 0, ("%s: error %d adding control to sglist", 901 __func__, error)); 902 903 /* 904 * We cannot use the softc lock to serialize access to this 905 * virtqueue since this is called from the tty layer with the 906 * port lock held. Acquiring the softc would violate our lock 907 * ordering. 908 */ 909 VTCON_CTRL_TX_LOCK(sc); 910 KASSERT(virtqueue_empty(vq), 911 ("%s: virtqueue is not emtpy", __func__)); 912 error = virtqueue_enqueue(vq, control, &sg, sg.sg_nseg, 0); 913 if (error == 0) { 914 virtqueue_notify(vq); 915 virtqueue_poll(vq, NULL); 916 } 917 VTCON_CTRL_TX_UNLOCK(sc); 918 } 919 920 static void 921 vtcon_ctrl_send_control(struct vtcon_softc *sc, uint32_t portid, 922 uint16_t event, uint16_t value) 923 { 924 struct virtio_console_control control; 925 926 if ((sc->vtcon_flags & VTCON_FLAG_MULTIPORT) == 0) 927 return; 928 929 control.id = portid; 930 control.event = event; 931 control.value = value; 932 933 vtcon_ctrl_poll(sc, &control); 934 } 935 936 static int 937 vtcon_port_enqueue_buf(struct vtcon_port *port, void *buf, size_t len) 938 { 939 struct sglist_seg segs[2]; 940 struct sglist sg; 941 struct virtqueue *vq; 942 int error; 943 944 vq = port->vtcport_invq; 945 946 sglist_init(&sg, 2, segs); 947 error = sglist_append(&sg, buf, len); 948 KASSERT(error == 0, 949 ("%s: error %d adding buffer to sglist", __func__, error)); 950 951 error = virtqueue_enqueue(vq, buf, &sg, 0, sg.sg_nseg); 952 953 return (error); 954 } 955 956 static int 957 vtcon_port_create_buf(struct vtcon_port *port) 958 { 959 void *buf; 960 int error; 961 962 buf = malloc(VTCON_BULK_BUFSZ, M_DEVBUF, M_ZERO | M_NOWAIT); 963 if (buf == NULL) 964 return (ENOMEM); 965 966 error = vtcon_port_enqueue_buf(port, buf, VTCON_BULK_BUFSZ); 967 if (error) 968 free(buf, M_DEVBUF); 969 970 return (error); 971 } 972 973 static void 974 vtcon_port_requeue_buf(struct vtcon_port *port, void *buf) 975 { 976 int error; 977 978 error = vtcon_port_enqueue_buf(port, buf, VTCON_BULK_BUFSZ); 979 KASSERT(error == 0, 980 ("%s: cannot requeue input buffer %d", __func__, error)); 981 } 982 983 static int 984 vtcon_port_populate(struct vtcon_port *port) 985 { 986 struct virtqueue *vq; 987 int nbufs, error; 988 989 vq = port->vtcport_invq; 990 error = ENOSPC; 991 992 for (nbufs = 0; !virtqueue_full(vq); nbufs++) { 993 error = vtcon_port_create_buf(port); 994 if (error) 995 break; 996 } 997 998 if (nbufs > 0) { 999 virtqueue_notify(vq); 1000 error = 0; 1001 } 1002 1003 return (error); 1004 } 1005 1006 static void 1007 vtcon_port_destroy(struct vtcon_port *port) 1008 { 1009 1010 port->vtcport_sc = NULL; 1011 port->vtcport_scport = NULL; 1012 port->vtcport_invq = NULL; 1013 port->vtcport_outvq = NULL; 1014 port->vtcport_id = -1; 1015 mtx_destroy(&port->vtcport_mtx); 1016 free(port, M_DEVBUF); 1017 } 1018 1019 static int 1020 vtcon_port_init_vqs(struct vtcon_port *port) 1021 { 1022 struct vtcon_softc_port *scport; 1023 int error; 1024 1025 scport = port->vtcport_scport; 1026 1027 port->vtcport_invq = scport->vcsp_invq; 1028 port->vtcport_outvq = scport->vcsp_outvq; 1029 1030 /* 1031 * Free any data left over from when this virtqueue was in use by a 1032 * prior port. We have not yet notified the host that the port is 1033 * ready, so assume nothing in the virtqueue can be for us. 1034 */ 1035 vtcon_port_drain(port); 1036 1037 KASSERT(virtqueue_empty(port->vtcport_invq), 1038 ("%s: in virtqueue is not empty", __func__)); 1039 KASSERT(virtqueue_empty(port->vtcport_outvq), 1040 ("%s: out virtqueue is not empty", __func__)); 1041 1042 error = vtcon_port_populate(port); 1043 if (error) 1044 return (error); 1045 1046 return (0); 1047 } 1048 1049 static int 1050 vtcon_port_create(struct vtcon_softc *sc, int id) 1051 { 1052 device_t dev; 1053 struct vtcon_softc_port *scport; 1054 struct vtcon_port *port; 1055 int error; 1056 1057 dev = sc->vtcon_dev; 1058 scport = &sc->vtcon_ports[id]; 1059 1060 VTCON_ASSERT_VALID_PORTID(sc, id); 1061 MPASS(scport->vcsp_port == NULL); 1062 1063 port = malloc(sizeof(struct vtcon_port), M_DEVBUF, M_NOWAIT | M_ZERO); 1064 if (port == NULL) 1065 return (ENOMEM); 1066 1067 port->vtcport_sc = sc; 1068 port->vtcport_scport = scport; 1069 port->vtcport_id = id; 1070 mtx_init(&port->vtcport_mtx, "vtcpmtx", NULL, MTX_DEF); 1071 port->vtcport_tty = tty_alloc_mutex(&vtcon_tty_class, port, 1072 &port->vtcport_mtx); 1073 1074 error = vtcon_port_init_vqs(port); 1075 if (error) { 1076 VTCON_PORT_LOCK(port); 1077 vtcon_port_teardown(port); 1078 return (error); 1079 } 1080 1081 VTCON_LOCK(sc); 1082 VTCON_PORT_LOCK(port); 1083 scport->vcsp_port = port; 1084 vtcon_port_enable_intr(port); 1085 vtcon_port_submit_event(port, VIRTIO_CONSOLE_PORT_READY, 1); 1086 VTCON_PORT_UNLOCK(port); 1087 VTCON_UNLOCK(sc); 1088 1089 tty_makedev(port->vtcport_tty, NULL, "%s%r.%r", VTCON_TTY_PREFIX, 1090 device_get_unit(dev), id); 1091 1092 return (0); 1093 } 1094 1095 static void 1096 vtcon_port_drain_bufs(struct virtqueue *vq) 1097 { 1098 void *buf; 1099 int last; 1100 1101 last = 0; 1102 1103 while ((buf = virtqueue_drain(vq, &last)) != NULL) 1104 free(buf, M_DEVBUF); 1105 } 1106 1107 static void 1108 vtcon_port_drain(struct vtcon_port *port) 1109 { 1110 1111 vtcon_port_drain_bufs(port->vtcport_invq); 1112 } 1113 1114 static void 1115 vtcon_port_teardown(struct vtcon_port *port) 1116 { 1117 struct tty *tp; 1118 1119 tp = port->vtcport_tty; 1120 1121 port->vtcport_flags |= VTCON_PORT_FLAG_GONE; 1122 1123 if (tp != NULL) { 1124 atomic_add_int(&vtcon_pending_free, 1); 1125 tty_rel_gone(tp); 1126 } else 1127 vtcon_port_destroy(port); 1128 } 1129 1130 static void 1131 vtcon_port_change_size(struct vtcon_port *port, uint16_t cols, uint16_t rows) 1132 { 1133 struct tty *tp; 1134 struct winsize sz; 1135 1136 tp = port->vtcport_tty; 1137 1138 if (tp == NULL) 1139 return; 1140 1141 bzero(&sz, sizeof(struct winsize)); 1142 sz.ws_col = cols; 1143 sz.ws_row = rows; 1144 1145 tty_set_winsize(tp, &sz); 1146 } 1147 1148 static void 1149 vtcon_port_update_console_size(struct vtcon_softc *sc) 1150 { 1151 struct vtcon_port *port; 1152 struct vtcon_softc_port *scport; 1153 uint16_t cols, rows; 1154 1155 vtcon_get_console_size(sc, &cols, &rows); 1156 1157 /* 1158 * For now, assume the first (only) port is the console. Note 1159 * QEMU does not implement this feature yet. 1160 */ 1161 scport = &sc->vtcon_ports[0]; 1162 1163 VTCON_LOCK(sc); 1164 port = scport->vcsp_port; 1165 1166 if (port != NULL) { 1167 VTCON_PORT_LOCK(port); 1168 VTCON_UNLOCK(sc); 1169 vtcon_port_change_size(port, cols, rows); 1170 VTCON_PORT_UNLOCK(port); 1171 } else 1172 VTCON_UNLOCK(sc); 1173 } 1174 1175 static void 1176 vtcon_port_enable_intr(struct vtcon_port *port) 1177 { 1178 1179 /* 1180 * NOTE: The out virtqueue is always polled, so its interupt 1181 * kept disabled. 1182 */ 1183 virtqueue_enable_intr(port->vtcport_invq); 1184 } 1185 1186 static void 1187 vtcon_port_disable_intr(struct vtcon_port *port) 1188 { 1189 1190 if (port->vtcport_invq != NULL) 1191 virtqueue_disable_intr(port->vtcport_invq); 1192 if (port->vtcport_outvq != NULL) 1193 virtqueue_disable_intr(port->vtcport_outvq); 1194 } 1195 1196 static void 1197 vtcon_port_in(struct vtcon_port *port) 1198 { 1199 struct virtqueue *vq; 1200 struct tty *tp; 1201 char *buf; 1202 uint32_t len; 1203 int i, deq; 1204 1205 tp = port->vtcport_tty; 1206 vq = port->vtcport_invq; 1207 1208 again: 1209 deq = 0; 1210 1211 while ((buf = virtqueue_dequeue(vq, &len)) != NULL) { 1212 for (i = 0; i < len; i++) { 1213 #if defined(KDB) 1214 if (port->vtcport_flags & VTCON_PORT_FLAG_CONSOLE) 1215 kdb_alt_break(buf[i], 1216 &port->vtcport_alt_break_state); 1217 #endif 1218 ttydisc_rint(tp, buf[i], 0); 1219 } 1220 vtcon_port_requeue_buf(port, buf); 1221 deq++; 1222 } 1223 ttydisc_rint_done(tp); 1224 1225 if (deq > 0) 1226 virtqueue_notify(vq); 1227 1228 if (virtqueue_enable_intr(vq) != 0) 1229 goto again; 1230 } 1231 1232 static void 1233 vtcon_port_intr(void *scportx) 1234 { 1235 struct vtcon_softc_port *scport; 1236 struct vtcon_softc *sc; 1237 struct vtcon_port *port; 1238 1239 scport = scportx; 1240 sc = scport->vcsp_sc; 1241 1242 VTCON_LOCK(sc); 1243 port = scport->vcsp_port; 1244 if (port == NULL) { 1245 VTCON_UNLOCK(sc); 1246 return; 1247 } 1248 VTCON_PORT_LOCK(port); 1249 VTCON_UNLOCK(sc); 1250 if ((port->vtcport_flags & VTCON_PORT_FLAG_GONE) == 0) 1251 vtcon_port_in(port); 1252 VTCON_PORT_UNLOCK(port); 1253 } 1254 1255 static void 1256 vtcon_port_out(struct vtcon_port *port, void *buf, int bufsize) 1257 { 1258 struct sglist_seg segs[2]; 1259 struct sglist sg; 1260 struct virtqueue *vq; 1261 int error; 1262 1263 vq = port->vtcport_outvq; 1264 KASSERT(virtqueue_empty(vq), 1265 ("%s: port %p out virtqueue not emtpy", __func__, port)); 1266 1267 sglist_init(&sg, 2, segs); 1268 error = sglist_append(&sg, buf, bufsize); 1269 KASSERT(error == 0, ("%s: error %d adding buffer to sglist", 1270 __func__, error)); 1271 1272 error = virtqueue_enqueue(vq, buf, &sg, sg.sg_nseg, 0); 1273 if (error == 0) { 1274 virtqueue_notify(vq); 1275 virtqueue_poll(vq, NULL); 1276 } 1277 } 1278 1279 static void 1280 vtcon_port_submit_event(struct vtcon_port *port, uint16_t event, 1281 uint16_t value) 1282 { 1283 struct vtcon_softc *sc; 1284 1285 sc = port->vtcport_sc; 1286 1287 vtcon_ctrl_send_control(sc, port->vtcport_id, event, value); 1288 } 1289 1290 static int 1291 vtcon_tty_open(struct tty *tp) 1292 { 1293 struct vtcon_port *port; 1294 1295 port = tty_softc(tp); 1296 1297 if (port->vtcport_flags & VTCON_PORT_FLAG_GONE) 1298 return (ENXIO); 1299 1300 vtcon_port_submit_event(port, VIRTIO_CONSOLE_PORT_OPEN, 1); 1301 1302 return (0); 1303 } 1304 1305 static void 1306 vtcon_tty_close(struct tty *tp) 1307 { 1308 struct vtcon_port *port; 1309 1310 port = tty_softc(tp); 1311 1312 if (port->vtcport_flags & VTCON_PORT_FLAG_GONE) 1313 return; 1314 1315 vtcon_port_submit_event(port, VIRTIO_CONSOLE_PORT_OPEN, 0); 1316 } 1317 1318 static void 1319 vtcon_tty_outwakeup(struct tty *tp) 1320 { 1321 struct vtcon_port *port; 1322 char buf[VTCON_BULK_BUFSZ]; 1323 int len; 1324 1325 port = tty_softc(tp); 1326 1327 if (port->vtcport_flags & VTCON_PORT_FLAG_GONE) 1328 return; 1329 1330 while ((len = ttydisc_getc(tp, buf, sizeof(buf))) != 0) 1331 vtcon_port_out(port, buf, len); 1332 } 1333 1334 static void 1335 vtcon_tty_free(void *xport) 1336 { 1337 struct vtcon_port *port; 1338 1339 port = xport; 1340 1341 vtcon_port_destroy(port); 1342 atomic_subtract_int(&vtcon_pending_free, 1); 1343 } 1344 1345 static void 1346 vtcon_get_console_size(struct vtcon_softc *sc, uint16_t *cols, uint16_t *rows) 1347 { 1348 struct virtio_console_config concfg; 1349 1350 KASSERT(sc->vtcon_flags & VTCON_FLAG_SIZE, 1351 ("%s: size feature not negotiated", __func__)); 1352 1353 vtcon_read_config(sc, &concfg); 1354 1355 *cols = concfg.cols; 1356 *rows = concfg.rows; 1357 } 1358 1359 static void 1360 vtcon_enable_interrupts(struct vtcon_softc *sc) 1361 { 1362 struct vtcon_softc_port *scport; 1363 struct vtcon_port *port; 1364 int i; 1365 1366 VTCON_LOCK(sc); 1367 1368 if (sc->vtcon_flags & VTCON_FLAG_MULTIPORT) 1369 virtqueue_enable_intr(sc->vtcon_ctrl_rxvq); 1370 1371 for (i = 0; i < sc->vtcon_max_ports; i++) { 1372 scport = &sc->vtcon_ports[i]; 1373 1374 port = scport->vcsp_port; 1375 if (port == NULL) 1376 continue; 1377 1378 VTCON_PORT_LOCK(port); 1379 vtcon_port_enable_intr(port); 1380 VTCON_PORT_UNLOCK(port); 1381 } 1382 1383 VTCON_UNLOCK(sc); 1384 } 1385 1386 static void 1387 vtcon_disable_interrupts(struct vtcon_softc *sc) 1388 { 1389 struct vtcon_softc_port *scport; 1390 struct vtcon_port *port; 1391 int i; 1392 1393 VTCON_LOCK_ASSERT(sc); 1394 1395 if (sc->vtcon_flags & VTCON_FLAG_MULTIPORT) 1396 virtqueue_disable_intr(sc->vtcon_ctrl_rxvq); 1397 1398 for (i = 0; i < sc->vtcon_max_ports; i++) { 1399 scport = &sc->vtcon_ports[i]; 1400 1401 port = scport->vcsp_port; 1402 if (port == NULL) 1403 continue; 1404 1405 VTCON_PORT_LOCK(port); 1406 vtcon_port_disable_intr(port); 1407 VTCON_PORT_UNLOCK(port); 1408 } 1409 } 1410