svn commit: r258668 - in head/usr.sbin: bhyve bhyveload
Julian Elischer
julian at freebsd.org
Wed Nov 27 15:08:19 UTC 2013
On 11/27/13, 8:21 AM, Peter Grehan wrote:
> Author: grehan
> Date: Wed Nov 27 00:21:37 2013
> New Revision: 258668
> URL: http://svnweb.freebsd.org/changeset/base/258668
>
> Log:
> Allow bhyve and bhyveload to attach to tty devices.
>
> bhyveload: introduce the -c <device> parameter
> to select a tty for output (or "stdio")
>
> bhyve: allow the puc and lpc-com backends to
> accept a tty in addition to "stdio"
>
> When used in conjunction with the null-modem device,
> nmdm(4), this allows attach/detach to the guest console
> and multiple concurrent serial ports. kgdb on a serial
> port is now functional.
>
I wrote nmdm for exactly this purpose for the old vmware port...
> Reviewed by: neel
> Requested by: Almost everyone that has used bhyve
> MFC after: 10.0
>
> Modified:
> head/usr.sbin/bhyve/uart_emul.c
> head/usr.sbin/bhyveload/bhyveload.8
> head/usr.sbin/bhyveload/bhyveload.c
>
> Modified: head/usr.sbin/bhyve/uart_emul.c
> ==============================================================================
> --- head/usr.sbin/bhyve/uart_emul.c Tue Nov 26 22:41:40 2013 (r258667)
> +++ head/usr.sbin/bhyve/uart_emul.c Wed Nov 27 00:21:37 2013 (r258668)
> @@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$");
> #include <stdio.h>
> #include <stdlib.h>
> #include <assert.h>
> +#include <fcntl.h>
> #include <termios.h>
> #include <unistd.h>
> #include <stdbool.h>
> @@ -67,6 +68,7 @@ __FBSDID("$FreeBSD$");
> #define FIFOSZ 16
>
> static bool uart_stdio; /* stdio in use for i/o */
> +static struct termios tio_stdio_orig;
>
> static struct {
> int baseaddr;
> @@ -87,6 +89,12 @@ struct fifo {
> int size; /* size of the fifo */
> };
>
> +struct ttyfd {
> + bool opened;
> + int fd; /* tty device file descriptor */
> + struct termios tio_orig, tio_new; /* I/O Terminals */
> +};
> +
> struct uart_softc {
> pthread_mutex_t mtx; /* protects all softc elements */
> uint8_t data; /* Data register (R/W) */
> @@ -103,8 +111,7 @@ struct uart_softc {
>
> struct fifo rxfifo;
>
> - bool opened;
> - bool stdio;
> + struct ttyfd tty;
> bool thre_int_pending; /* THRE interrupt pending */
>
> void *arg;
> @@ -114,38 +121,41 @@ struct uart_softc {
>
> static void uart_drain(int fd, enum ev_type ev, void *arg);
>
> -static struct termios tio_orig, tio_new; /* I/O Terminals */
> -
> static void
> ttyclose(void)
> {
>
> - tcsetattr(STDIN_FILENO, TCSANOW, &tio_orig);
> + tcsetattr(STDIN_FILENO, TCSANOW, &tio_stdio_orig);
> }
>
> static void
> -ttyopen(void)
> +ttyopen(struct ttyfd *tf)
> {
>
> - tcgetattr(STDIN_FILENO, &tio_orig);
> + tcgetattr(tf->fd, &tf->tio_orig);
>
> - cfmakeraw(&tio_new);
> - tcsetattr(STDIN_FILENO, TCSANOW, &tio_new);
> + tf->tio_new = tf->tio_orig;
> + cfmakeraw(&tf->tio_new);
> + tf->tio_new.c_cflag |= CLOCAL;
> + tcsetattr(tf->fd, TCSANOW, &tf->tio_new);
>
> - atexit(ttyclose);
> + if (tf->fd == STDIN_FILENO) {
> + tio_stdio_orig = tf->tio_orig;
> + atexit(ttyclose);
> + }
> }
>
> static bool
> -tty_char_available(void)
> +tty_char_available(struct ttyfd *tf)
> {
> fd_set rfds;
> struct timeval tv;
>
> FD_ZERO(&rfds);
> - FD_SET(STDIN_FILENO, &rfds);
> + FD_SET(tf->fd, &rfds);
> tv.tv_sec = 0;
> tv.tv_usec = 0;
> - if (select(STDIN_FILENO + 1, &rfds, NULL, NULL, &tv) > 0 ) {
> + if (select(tf->fd + 1, &rfds, NULL, NULL, &tv) > 0 ) {
> return (true);
> } else {
> return (false);
> @@ -153,12 +163,12 @@ tty_char_available(void)
> }
>
> static int
> -ttyread(void)
> +ttyread(struct ttyfd *tf)
> {
> char rb;
>
> - if (tty_char_available()) {
> - read(STDIN_FILENO, &rb, 1);
> + if (tty_char_available(tf)) {
> + read(tf->fd, &rb, 1);
> return (rb & 0xff);
> } else {
> return (-1);
> @@ -166,10 +176,10 @@ ttyread(void)
> }
>
> static void
> -ttywrite(unsigned char wb)
> +ttywrite(struct ttyfd *tf, unsigned char wb)
> {
>
> - (void)write(STDIN_FILENO, &wb, 1);
> + (void)write(tf->fd, &wb, 1);
> }
>
> static void
> @@ -226,10 +236,8 @@ uart_opentty(struct uart_softc *sc)
> {
> struct mevent *mev;
>
> - assert(!sc->opened && sc->stdio);
> -
> - ttyopen();
> - mev = mevent_add(STDIN_FILENO, EVF_READ, uart_drain, sc);
> + ttyopen(&sc->tty);
> + mev = mevent_add(sc->tty.fd, EVF_READ, uart_drain, sc);
> assert(mev);
> }
>
> @@ -294,7 +302,7 @@ uart_drain(int fd, enum ev_type ev, void
>
> sc = arg;
>
> - assert(fd == STDIN_FILENO);
> + assert(fd == sc->tty.fd);
> assert(ev == EVF_READ);
>
> /*
> @@ -305,10 +313,10 @@ uart_drain(int fd, enum ev_type ev, void
> pthread_mutex_lock(&sc->mtx);
>
> if ((sc->mcr & MCR_LOOPBACK) != 0) {
> - (void) ttyread();
> + (void) ttyread(&sc->tty);
> } else {
> while (fifo_available(&sc->rxfifo) &&
> - ((ch = ttyread()) != -1)) {
> + ((ch = ttyread(&sc->tty)) != -1)) {
> fifo_putchar(&sc->rxfifo, ch);
> }
> uart_toggle_intr(sc);
> @@ -323,12 +331,6 @@ uart_write(struct uart_softc *sc, int of
> int fifosz;
> uint8_t msr;
>
> - /* Open terminal */
> - if (!sc->opened && sc->stdio) {
> - uart_opentty(sc);
> - sc->opened = true;
> - }
> -
> pthread_mutex_lock(&sc->mtx);
>
> /*
> @@ -351,8 +353,8 @@ uart_write(struct uart_softc *sc, int of
> if (sc->mcr & MCR_LOOPBACK) {
> if (fifo_putchar(&sc->rxfifo, value) != 0)
> sc->lsr |= LSR_OE;
> - } else if (sc->stdio) {
> - ttywrite(value);
> + } else if (sc->tty.opened) {
> + ttywrite(&sc->tty, value);
> } /* else drop on floor */
> sc->thre_int_pending = true;
> break;
> @@ -459,12 +461,6 @@ uart_read(struct uart_softc *sc, int off
> {
> uint8_t iir, intr_reason, reg;
>
> - /* Open terminal */
> - if (!sc->opened && sc->stdio) {
> - uart_opentty(sc);
> - sc->opened = true;
> - }
> -
> pthread_mutex_lock(&sc->mtx);
>
> /*
> @@ -581,19 +577,47 @@ uart_init(uart_intr_func_t intr_assert,
> return (sc);
> }
>
> +static int
> +uart_tty_backend(struct uart_softc *sc, const char *opts)
> +{
> + int fd;
> + int retval;
> +
> + retval = -1;
> +
> + fd = open(opts, O_RDWR);
> + if (fd > 0 && isatty(fd)) {
> + sc->tty.fd = fd;
> + sc->tty.opened = true;
> + retval = 0;
> + }
> +
> + return (retval);
> +}
> +
> int
> uart_set_backend(struct uart_softc *sc, const char *opts)
> {
> - /*
> - * XXX one stdio backend supported at this time.
> - */
> + int retval;
> +
> + retval = -1;
> +
> if (opts == NULL)
> return (0);
>
> - if (strcmp("stdio", opts) == 0 && !uart_stdio) {
> - sc->stdio = true;
> - uart_stdio = true;
> - return (0);
> - } else
> - return (-1);
> + if (strcmp("stdio", opts) == 0) {
> + if (!uart_stdio) {
> + sc->tty.fd = STDIN_FILENO;
> + sc->tty.opened = true;
> + uart_stdio = true;
> + retval = 0;
> + }
> + } else if (uart_tty_backend(sc, opts) == 0) {
> + retval = 0;
> + }
> +
> + if (retval == 0)
> + uart_opentty(sc);
> +
> + return (retval);
> }
>
> Modified: head/usr.sbin/bhyveload/bhyveload.8
> ==============================================================================
> --- head/usr.sbin/bhyveload/bhyveload.8 Tue Nov 26 22:41:40 2013 (r258667)
> +++ head/usr.sbin/bhyveload/bhyveload.8 Wed Nov 27 00:21:37 2013 (r258668)
> @@ -39,6 +39,7 @@ guest inside a bhyve virtual machine
> .Op Fl d Ar disk-path
> .Op Fl h Ar host-path
> .Op Fl e Ar name=value
> +.Op Fl c Ar cons-dev
> .Ar vmname
> .Sh DESCRIPTION
> .Nm
> @@ -100,6 +101,16 @@ to
> .Pp
> The option may be used more than once to set more than one environment
> variable.
> +.It Fl c Ar cons-dev
> +.Ar cons-dev
> +is a
> +.Xr tty 4
> +device to use for
> +.Nm
> +terminal I/O.
> +.Pp
> +The text string "stdio" is also accepted and selects the use of
> +unbuffered standard I/O. This is the default value.
> .El
> .Sh EXAMPLES
> To create a virtual machine named
> @@ -109,10 +120,23 @@ that boots off the ISO image
> and has 1GB memory allocated to it:
> .Pp
> .Dl "bhyveload -m 1G -d /freebsd/release.iso freebsd-vm"
> +.Pp
> +To create a virtual machine named
> +.Ar test-vm
> +with 256MB of memory allocated, the guest root filesystem under the host
> +directory
> +.Pa /user/images/test
> +and terminal I/O sent to the
> +.Xr nmdm 4
> +device
> +.Pa /dev/nmdm1B
> +.Pp
> +.Dl "bhyveload -m 256MB -h /usr/images/test -c /dev/nmdm1B test-vm
> .Sh SEE ALSO
> .Xr bhyve 4 ,
> .Xr bhyve 8 ,
> .Xr loader 8 ,
> +.Xr nmdm 4,
> .Xr vmm 4
> .Sh HISTORY
> .Nm
>
> Modified: head/usr.sbin/bhyveload/bhyveload.c
> ==============================================================================
> --- head/usr.sbin/bhyveload/bhyveload.c Tue Nov 26 22:41:40 2013 (r258667)
> +++ head/usr.sbin/bhyveload/bhyveload.c Wed Nov 27 00:21:37 2013 (r258668)
> @@ -91,6 +91,7 @@ __FBSDID("$FreeBSD$");
> static char *host_base = "/";
> static struct termios term, oldterm;
> static int disk_fd = -1;
> +static int consin_fd, consout_fd;
>
> static char *vmname, *progname;
> static struct vmctx *ctx;
> @@ -108,7 +109,7 @@ cb_putc(void *arg, int ch)
> {
> char c = ch;
>
> - write(1, &c, 1);
> + (void) write(consout_fd, &c, 1);
> }
>
> static int
> @@ -116,7 +117,7 @@ cb_getc(void *arg)
> {
> char c;
>
> - if (read(0, &c, 1) == 1)
> + if (read(consin_fd, &c, 1) == 1)
> return (c);
> return (-1);
> }
> @@ -126,7 +127,7 @@ cb_poll(void *arg)
> {
> int n;
>
> - if (ioctl(0, FIONREAD, &n) >= 0)
> + if (ioctl(consin_fd, FIONREAD, &n) >= 0)
> return (n > 0);
> return (0);
> }
> @@ -488,7 +489,7 @@ static void
> cb_exit(void *arg, int v)
> {
>
> - tcsetattr(0, TCSAFLUSH, &oldterm);
> + tcsetattr(consout_fd, TCSAFLUSH, &oldterm);
> exit(v);
> }
>
> @@ -564,13 +565,45 @@ static struct loader_callbacks cb = {
> .getenv = cb_getenv,
> };
>
> +static int
> +altcons_open(char *path)
> +{
> + struct stat sb;
> + int err;
> + int fd;
> +
> + /*
> + * Allow stdio to be passed in so that the same string
> + * can be used for the bhyveload console and bhyve com-port
> + * parameters
> + */
> + if (!strcmp(path, "stdio"))
> + return (0);
> +
> + err = stat(path, &sb);
> + if (err == 0) {
> + if (!S_ISCHR(sb.st_mode))
> + err = ENOTSUP;
> + else {
> + fd = open(path, O_RDWR | O_NONBLOCK);
> + if (fd < 0)
> + err = errno;
> + else
> + consin_fd = consout_fd = fd;
> + }
> + }
> +
> + return (err);
> +}
> +
> static void
> usage(void)
> {
>
> fprintf(stderr,
> "usage: %s [-m mem-size] [-d <disk-path>] [-h <host-path>]\n"
> - " %*s [-e <name=value>] <vmname>\n", progname,
> + " %*s [-e <name=value>] [-c <console-device>] <vmname>\n",
> + progname,
> (int)strlen(progname), "");
> exit(1);
> }
> @@ -589,8 +622,16 @@ main(int argc, char** argv)
> mem_size = 256 * MB;
> disk_image = NULL;
>
> - while ((opt = getopt(argc, argv, "d:e:h:m:")) != -1) {
> + consin_fd = STDIN_FILENO;
> + consout_fd = STDOUT_FILENO;
> +
> + while ((opt = getopt(argc, argv, "c:d:e:h:m:")) != -1) {
> switch (opt) {
> + case 'c':
> + error = altcons_open(optarg);
> + if (error != 0)
> + errx(EX_USAGE, "Could not open '%s'", optarg);
> + break;
> case 'd':
> disk_image = optarg;
> break;
> @@ -640,11 +681,13 @@ main(int argc, char** argv)
> exit(1);
> }
>
> - tcgetattr(0, &term);
> + tcgetattr(consout_fd, &term);
> oldterm = term;
> - term.c_lflag &= ~(ICANON|ECHO);
> - term.c_iflag &= ~ICRNL;
> - tcsetattr(0, TCSAFLUSH, &term);
> + cfmakeraw(&term);
> + term.c_cflag |= CLOCAL;
> +
> + tcsetattr(consout_fd, TCSAFLUSH, &term);
> +
> h = dlopen("/boot/userboot.so", RTLD_LOCAL);
> if (!h) {
> printf("%s\n", dlerror());
>
More information about the svn-src-head
mailing list