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