Date: Wed, 27 Nov 2013 23:08:01 +0800 From: Julian Elischer <julian@freebsd.org> To: Peter Grehan <grehan@FreeBSD.org>, svn-src-head@freebsd.org Subject: Re: svn commit: r258668 - in head/usr.sbin: bhyve bhyveload Message-ID: <52960AD1.5020604@freebsd.org> In-Reply-To: <201311270021.rAR0LcX4009601@svn.freebsd.org> References: <201311270021.rAR0LcX4009601@svn.freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
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()); >
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?52960AD1.5020604>