svn commit: r259496 - in releng/10.0/usr.sbin: bhyve bhyveload

Peter Grehan grehan at FreeBSD.org
Tue Dec 17 06:39:52 UTC 2013


Author: grehan
Date: Tue Dec 17 06:39:48 2013
New Revision: 259496
URL: http://svnweb.freebsd.org/changeset/base/259496

Log:
  MFStable-10 r259301
  
    MFC r256657,r257018,r257347,r257423,r257729,r257767,
        r257933,r258609,r258614,r258668,r258673,r258855
  
    Pull in some minor bugfixes and functionality enhancements
    from CURRENT. These are candidates to be moved to 10.0-release.
  
    r258855
    mdoc: quote string properly.
  
    r258673
    Don't create an initial value for the host filesystem of "/".
  
    r258668
    Allow bhyve and bhyveload to attach to tty devices.
  
    r258614
    The 22-bit Data Byte Count (DBC) field of a Physical Region Descriptor was
    being read as a 32-bit quantity by the bhyve AHCI driver.
  
    r258609
    Fix discrepancy between the IOAPIC ID advertised by firmware tables and the
    actual value read by the guest.
  
    r257933
    Route the legacy timer interrupt (IRQ0) to pin 2 of the IOAPIC.
  
    r257767
    Fix an off-by-one error when iterating over the emulated PCI BARs.
  
    r257729
    Add the VM name to the process name with setproctitle().
  
    r257423
    Make the virtual ioapic available unconditionally in a bhyve virtual machine.
  
    r257347
    Update copyright to include the author of the LPC bridge emulation code.
  
    hand-merge r257018
    Tidy usage messages for bhyve and bhyveload.
  
    r256657
    Add an option to bhyveload(8) that allows setting a loader environment variable
    from the command line.
  
  Approved by:	re@ (gjb)

Modified:
  releng/10.0/usr.sbin/bhyve/acpi.c
  releng/10.0/usr.sbin/bhyve/acpi.h
  releng/10.0/usr.sbin/bhyve/bhyverun.c
  releng/10.0/usr.sbin/bhyve/block_if.c
  releng/10.0/usr.sbin/bhyve/mevent.c
  releng/10.0/usr.sbin/bhyve/mptbl.c
  releng/10.0/usr.sbin/bhyve/mptbl.h
  releng/10.0/usr.sbin/bhyve/pci_ahci.c
  releng/10.0/usr.sbin/bhyve/pci_emul.c
  releng/10.0/usr.sbin/bhyve/pci_virtio_net.c
  releng/10.0/usr.sbin/bhyve/pit_8254.c
  releng/10.0/usr.sbin/bhyve/uart_emul.c
  releng/10.0/usr.sbin/bhyveload/bhyveload.8
  releng/10.0/usr.sbin/bhyveload/bhyveload.c
Directory Properties:
  releng/10.0/   (props changed)

Modified: releng/10.0/usr.sbin/bhyve/acpi.c
==============================================================================
--- releng/10.0/usr.sbin/bhyve/acpi.c	Tue Dec 17 05:13:37 2013	(r259495)
+++ releng/10.0/usr.sbin/bhyve/acpi.c	Tue Dec 17 06:39:48 2013	(r259496)
@@ -253,13 +253,23 @@ basl_fwrite_madt(FILE *fp)
 	EFPRINTF(fp, "[0001]\t\tSubtable Type : 01\n");
 	EFPRINTF(fp, "[0001]\t\tLength : 0C\n");
 	/* iasl expects a hex value for the i/o apic id */
-	EFPRINTF(fp, "[0001]\t\tI/O Apic ID : %02x\n", basl_ncpu);
+	EFPRINTF(fp, "[0001]\t\tI/O Apic ID : %02x\n", 0);
 	EFPRINTF(fp, "[0001]\t\tReserved : 00\n");
 	EFPRINTF(fp, "[0004]\t\tAddress : fec00000\n");
 	EFPRINTF(fp, "[0004]\t\tInterrupt : 00000000\n");
 	EFPRINTF(fp, "\n");
 
-	/* Override the 8259 chained vector. XXX maybe not needed */
+	/* Legacy IRQ0 is connected to pin 2 of the IOAPIC */
+	EFPRINTF(fp, "[0001]\t\tSubtable Type : 02\n");
+	EFPRINTF(fp, "[0001]\t\tLength : 0A\n");
+	EFPRINTF(fp, "[0001]\t\tBus : 00\n");
+	EFPRINTF(fp, "[0001]\t\tSource : 00\n");
+	EFPRINTF(fp, "[0004]\t\tInterrupt : 00000002\n");
+	EFPRINTF(fp, "[0002]\t\tFlags (decoded below) : 0005\n");
+	EFPRINTF(fp, "\t\t\tPolarity : 1\n");
+	EFPRINTF(fp, "\t\t\tTrigger Mode : 1\n");
+	EFPRINTF(fp, "\n");
+
 	EFPRINTF(fp, "[0001]\t\tSubtable Type : 02\n");
 	EFPRINTF(fp, "[0001]\t\tLength : 0A\n");
 	EFPRINTF(fp, "[0001]\t\tBus : 00\n");
@@ -806,7 +816,7 @@ static struct {
 };
 
 int
-acpi_build(struct vmctx *ctx, int ncpu, int ioapic)
+acpi_build(struct vmctx *ctx, int ncpu)
 {
 	int err;
 	int i;
@@ -814,11 +824,6 @@ acpi_build(struct vmctx *ctx, int ncpu, 
 	err = 0;
 	basl_ncpu = ncpu;
 
-	if (!ioapic) {
-		fprintf(stderr, "ACPI tables require an ioapic\n");
-		return (EINVAL);
-	}
-
 	/*
 	 * For debug, allow the user to have iasl compiler output sent
 	 * to stdout rather than /dev/null

Modified: releng/10.0/usr.sbin/bhyve/acpi.h
==============================================================================
--- releng/10.0/usr.sbin/bhyve/acpi.h	Tue Dec 17 05:13:37 2013	(r259495)
+++ releng/10.0/usr.sbin/bhyve/acpi.h	Tue Dec 17 06:39:48 2013	(r259496)
@@ -29,6 +29,6 @@
 #ifndef _ACPI_H_
 #define _ACPI_H_
 
-int	acpi_build(struct vmctx *ctx, int ncpu, int ioapic);
+int	acpi_build(struct vmctx *ctx, int ncpu);
 
 #endif /* _ACPI_H_ */

Modified: releng/10.0/usr.sbin/bhyve/bhyverun.c
==============================================================================
--- releng/10.0/usr.sbin/bhyve/bhyverun.c	Tue Dec 17 05:13:37 2013	(r259495)
+++ releng/10.0/usr.sbin/bhyve/bhyverun.c	Tue Dec 17 06:39:48 2013	(r259496)
@@ -132,7 +132,6 @@ usage(int code)
 		"       -c: # cpus (default 1)\n"
 		"       -p: pin vcpu 'n' to host cpu 'pincpu + n'\n"
 		"       -H: vmexit from the guest on hlt\n"
-		"       -I: present an ioapic to the guest\n"
 		"       -P: vmexit from the guest on pause\n"
 		"       -W: force virtio to use single-vector MSI\n"
 		"       -e: exit on unhandled I/O access\n"
@@ -191,7 +190,7 @@ fbsdrun_start_thread(void *param)
 	mtp = param;
 	vcpu = mtp->mt_vcpu;
 
-	snprintf(tname, sizeof(tname), "%s vcpu %d", vmname, vcpu);
+	snprintf(tname, sizeof(tname), "vcpu %d", vcpu);
 	pthread_set_name_np(mtp->mt_thr, tname);
 
 	vm_loop(mtp->mt_ctx, vcpu, vmexit[vcpu].rip);
@@ -543,7 +542,7 @@ fbsdrun_set_capabilities(struct vmctx *c
 int
 main(int argc, char *argv[])
 {
-	int c, error, gdb_port, err, ioapic, bvmcons;
+	int c, error, gdb_port, err, bvmcons;
 	int max_vcpus;
 	struct vmctx *ctx;
 	uint64_t rip;
@@ -553,7 +552,6 @@ main(int argc, char *argv[])
 	progname = basename(argv[0]);
 	gdb_port = 0;
 	guest_ncpus = 1;
-	ioapic = 0;
 	memsize = 256 * MB;
 
 	while ((c = getopt(argc, argv, "abehAHIPWp:g:c:s:S:m:l:")) != -1) {
@@ -601,7 +599,13 @@ main(int argc, char *argv[])
 			guest_vmexit_on_hlt = 1;
 			break;
 		case 'I':
-			ioapic = 1;
+			/*
+			 * The "-I" option was used to add an ioapic to the
+			 * virtual machine.
+			 *
+			 * An ioapic is now provided unconditionally for each
+			 * virtual machine and this option is now deprecated.
+			 */
 			break;
 		case 'P':
 			guest_vmexit_on_pause = 1;
@@ -659,8 +663,7 @@ main(int argc, char *argv[])
 	if (init_pci(ctx) != 0)
 		exit(1);
 
-	if (ioapic)
-		ioapic_init(0);
+	ioapic_init(0);
 
 	if (gdb_port != 0)
 		init_dbgport(gdb_port);
@@ -674,14 +677,19 @@ main(int argc, char *argv[])
 	/*
 	 * build the guest tables, MP etc.
 	 */
-	mptable_build(ctx, guest_ncpus, ioapic);
+	mptable_build(ctx, guest_ncpus);
 
 	if (acpi) {
-		error = acpi_build(ctx, guest_ncpus, ioapic);
+		error = acpi_build(ctx, guest_ncpus);
 		assert(error == 0);
 	}
 
 	/*
+	 * Change the proc title to include the VM name.
+	 */
+	setproctitle("%s", vmname); 
+	
+	/*
 	 * Add CPU 0
 	 */
 	fbsdrun_addcpu(ctx, BSP, rip);

Modified: releng/10.0/usr.sbin/bhyve/block_if.c
==============================================================================
--- releng/10.0/usr.sbin/bhyve/block_if.c	Tue Dec 17 05:13:37 2013	(r259495)
+++ releng/10.0/usr.sbin/bhyve/block_if.c	Tue Dec 17 06:39:48 2013	(r259496)
@@ -293,7 +293,7 @@ blockif_open(const char *optstr, const c
 
 	pthread_create(&bc->bc_btid, NULL, blockif_thr, bc);
 
-	snprintf(tname, sizeof(tname), "%s blk-%s", vmname, ident);
+	snprintf(tname, sizeof(tname), "blk-%s", ident);
 	pthread_set_name_np(bc->bc_btid, tname);
 
 	return (bc);

Modified: releng/10.0/usr.sbin/bhyve/mevent.c
==============================================================================
--- releng/10.0/usr.sbin/bhyve/mevent.c	Tue Dec 17 05:13:37 2013	(r259495)
+++ releng/10.0/usr.sbin/bhyve/mevent.c	Tue Dec 17 06:39:48 2013	(r259496)
@@ -381,10 +381,8 @@ mevent_delete_close(struct mevent *evp)
 static void
 mevent_set_name(void)
 {
-	char tname[MAXCOMLEN + 1];
 
-	snprintf(tname, sizeof(tname), "%s mevent", vmname);
-	pthread_set_name_np(mevent_tid, tname);
+	pthread_set_name_np(mevent_tid, "mevent");
 }
 
 void

Modified: releng/10.0/usr.sbin/bhyve/mptbl.c
==============================================================================
--- releng/10.0/usr.sbin/bhyve/mptbl.c	Tue Dec 17 05:13:37 2013	(r259495)
+++ releng/10.0/usr.sbin/bhyve/mptbl.c	Tue Dec 17 06:39:48 2013	(r259496)
@@ -242,7 +242,7 @@ mptable_add_oemtbl(void *tbl, int tblsz)
 }
 
 int
-mptable_build(struct vmctx *ctx, int ncpu, int ioapic)
+mptable_build(struct vmctx *ctx, int ncpu)
 {
 	mpcth_t			mpch;
 	bus_entry_ptr		mpeb;
@@ -278,15 +278,13 @@ mptable_build(struct vmctx *ctx, int ncp
 	curraddr += sizeof(*mpeb) * MPE_NUM_BUSES;
 	mpch->entry_count += MPE_NUM_BUSES;
 
-	if (ioapic) {
-		mpei = (io_apic_entry_ptr)curraddr;
-		mpt_build_ioapic_entries(mpei, ncpu + 1);
-		curraddr += sizeof(*mpei);
-		mpch->entry_count++;
-	}
+	mpei = (io_apic_entry_ptr)curraddr;
+	mpt_build_ioapic_entries(mpei, 0);
+	curraddr += sizeof(*mpei);
+	mpch->entry_count++;
 
 	mpie = (int_entry_ptr) curraddr;
-	mpt_build_ioint_entries(mpie, MPEII_MAX_IRQ, ncpu + 1);
+	mpt_build_ioint_entries(mpie, MPEII_MAX_IRQ, 0);
 	curraddr += sizeof(*mpie) * MPEII_MAX_IRQ;
 	mpch->entry_count += MPEII_MAX_IRQ;
 

Modified: releng/10.0/usr.sbin/bhyve/mptbl.h
==============================================================================
--- releng/10.0/usr.sbin/bhyve/mptbl.h	Tue Dec 17 05:13:37 2013	(r259495)
+++ releng/10.0/usr.sbin/bhyve/mptbl.h	Tue Dec 17 06:39:48 2013	(r259496)
@@ -29,7 +29,7 @@
 #ifndef _MPTBL_H_
 #define _MPTBL_H_
 
-int	mptable_build(struct vmctx *ctx, int ncpu, int ioapic);
+int	mptable_build(struct vmctx *ctx, int ncpu);
 void	mptable_add_oemtbl(void *tbl, int tblsz);
 
 #endif /* _MPTBL_H_ */

Modified: releng/10.0/usr.sbin/bhyve/pci_ahci.c
==============================================================================
--- releng/10.0/usr.sbin/bhyve/pci_ahci.c	Tue Dec 17 05:13:37 2013	(r259495)
+++ releng/10.0/usr.sbin/bhyve/pci_ahci.c	Tue Dec 17 06:39:48 2013	(r259496)
@@ -165,6 +165,7 @@ struct ahci_cmd_hdr {
 struct ahci_prdt_entry {
 	uint64_t dba;
 	uint32_t reserved;
+#define	DBCMASK		0x3fffff
 	uint32_t dbc;
 };
 
@@ -461,10 +462,13 @@ ahci_handle_dma(struct ahci_port *p, int
 	 * Build up the iovec based on the prdt
 	 */
 	for (i = 0; i < iovcnt; i++) {
+		uint32_t dbcsz;
+
+		dbcsz = (prdt->dbc & DBCMASK) + 1;
 		breq->br_iov[i].iov_base = paddr_guest2host(ahci_ctx(sc),
-				prdt->dba, prdt->dbc + 1);
-		breq->br_iov[i].iov_len = prdt->dbc + 1;
-		aior->done += (prdt->dbc + 1);
+		    prdt->dba, dbcsz);
+		breq->br_iov[i].iov_len = dbcsz;
+		aior->done += dbcsz;
 		prdt++;
 	}
 	if (readop)
@@ -513,11 +517,14 @@ write_prdt(struct ahci_port *p, int slot
 	from = buf;
 	prdt = (struct ahci_prdt_entry *)(cfis + 0x80);
 	for (i = 0; i < hdr->prdtl && len; i++) {
-		uint8_t *ptr = paddr_guest2host(ahci_ctx(p->pr_sc),
-				prdt->dba, prdt->dbc + 1);
-		memcpy(ptr, from, prdt->dbc + 1);
-		len -= (prdt->dbc + 1);
-		from += (prdt->dbc + 1);
+		uint8_t *ptr;
+		uint32_t dbcsz;
+
+		dbcsz = (prdt->dbc & DBCMASK) + 1;
+		ptr = paddr_guest2host(ahci_ctx(p->pr_sc), prdt->dba, dbcsz);
+		memcpy(ptr, from, dbcsz);
+		len -= dbcsz;
+		from += dbcsz;
 		prdt++;
 	}
 	hdr->prdbc = size - len;
@@ -908,10 +915,13 @@ atapi_read(struct ahci_port *p, int slot
 	 * Build up the iovec based on the prdt
 	 */
 	for (i = 0; i < iovcnt; i++) {
+		uint32_t dbcsz;
+
+		dbcsz = (prdt->dbc & DBCMASK) + 1;
 		breq->br_iov[i].iov_base = paddr_guest2host(ahci_ctx(sc),
-		    prdt->dba, prdt->dbc + 1);
-		breq->br_iov[i].iov_len = prdt->dbc + 1;
-		aior->done += (prdt->dbc + 1);
+		    prdt->dba, dbcsz);
+		breq->br_iov[i].iov_len = dbcsz;
+		aior->done += dbcsz;
 		prdt++;
 	}
 	err = blockif_read(p->bctx, breq);
@@ -1714,11 +1724,9 @@ pci_ahci_init(struct vmctx *ctx, struct 
 
 	/*
 	 * Attempt to open the backing image. Use the PCI
-	 * slot/func/ahci_port for the identifier string
-	 * since that uniquely identifies a storage device.
+	 * slot/func for the identifier string.
 	 */
-	snprintf(bident, sizeof(bident), "%d:%d:%d", pi->pi_slot, pi->pi_func,
-	    0);
+	snprintf(bident, sizeof(bident), "%d:%d", pi->pi_slot, pi->pi_func);
 	bctxt = blockif_open(opts, bident);
 	if (bctxt == NULL) {       	
 		ret = 1;

Modified: releng/10.0/usr.sbin/bhyve/pci_emul.c
==============================================================================
--- releng/10.0/usr.sbin/bhyve/pci_emul.c	Tue Dec 17 05:13:37 2013	(r259495)
+++ releng/10.0/usr.sbin/bhyve/pci_emul.c	Tue Dec 17 06:39:48 2013	(r259496)
@@ -1252,7 +1252,7 @@ pci_emul_cmdwrite(struct pci_devinst *pi
 	 * If the MMIO or I/O address space decoding has changed then
 	 * register/unregister all BARs that decode that address space.
 	 */
-	for (i = 0; i < PCI_BARMAX; i++) {
+	for (i = 0; i <= PCI_BARMAX; i++) {
 		switch (pi->pi_bar[i].type) {
 			case PCIBAR_NONE:
 			case PCIBAR_MEMHI64:

Modified: releng/10.0/usr.sbin/bhyve/pci_virtio_net.c
==============================================================================
--- releng/10.0/usr.sbin/bhyve/pci_virtio_net.c	Tue Dec 17 05:13:37 2013	(r259495)
+++ releng/10.0/usr.sbin/bhyve/pci_virtio_net.c	Tue Dec 17 06:39:48 2013	(r259496)
@@ -588,7 +588,7 @@ pci_vtnet_init(struct vmctx *ctx, struct
 	 */
 	if (!mac_provided) {
 		snprintf(nstr, sizeof(nstr), "%d-%d-%s", pi->pi_slot,
-	            pi->pi_func, vmname);
+		    pi->pi_func, vmname);
 
 		MD5Init(&mdctx);
 		MD5Update(&mdctx, nstr, strlen(nstr));
@@ -632,7 +632,8 @@ pci_vtnet_init(struct vmctx *ctx, struct
 	pthread_mutex_init(&sc->tx_mtx, NULL);
 	pthread_cond_init(&sc->tx_cond, NULL);
 	pthread_create(&sc->tx_tid, NULL, pci_vtnet_tx_thread, (void *)sc);
-        snprintf(tname, sizeof(tname), "%s vtnet%d tx", vmname, pi->pi_slot);
+	snprintf(tname, sizeof(tname), "vtnet-%d:%d tx", pi->pi_slot,
+	    pi->pi_func);
         pthread_set_name_np(sc->tx_tid, tname);
 
 	return (0);

Modified: releng/10.0/usr.sbin/bhyve/pit_8254.c
==============================================================================
--- releng/10.0/usr.sbin/bhyve/pit_8254.c	Tue Dec 17 05:13:37 2013	(r259495)
+++ releng/10.0/usr.sbin/bhyve/pit_8254.c	Tue Dec 17 06:39:48 2013	(r259496)
@@ -106,8 +106,8 @@ pit_mevent_cb(int fd, enum ev_type type,
 
 	pit_mev_count++;
 
-	ioapic_assert_pin(c->ctx, 0);
-	ioapic_deassert_pin(c->ctx, 0);
+	ioapic_assert_pin(c->ctx, 2);
+	ioapic_deassert_pin(c->ctx, 2);
 
 	/*
 	 * Delete the timer for one-shots

Modified: releng/10.0/usr.sbin/bhyve/uart_emul.c
==============================================================================
--- releng/10.0/usr.sbin/bhyve/uart_emul.c	Tue Dec 17 05:13:37 2013	(r259495)
+++ releng/10.0/usr.sbin/bhyve/uart_emul.c	Tue Dec 17 06:39:48 2013	(r259496)
@@ -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: releng/10.0/usr.sbin/bhyveload/bhyveload.8
==============================================================================
--- releng/10.0/usr.sbin/bhyveload/bhyveload.8	Tue Dec 17 05:13:37 2013	(r259495)
+++ releng/10.0/usr.sbin/bhyveload/bhyveload.8	Tue Dec 17 06:39:48 2013	(r259496)
@@ -38,6 +38,8 @@ guest inside a bhyve virtual machine
 .Op Fl m Ar mem-size
 .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
@@ -91,6 +93,24 @@ is the pathname of the guest's boot disk
 The
 .Ar host-path
 is the directory at the top of the guest's boot filesystem.
+.It Fl e Ar name=value
+Set the FreeBSD loader environment variable
+.Ar name
+to
+.Ar value .
+.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
@@ -100,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: releng/10.0/usr.sbin/bhyveload/bhyveload.c
==============================================================================
--- releng/10.0/usr.sbin/bhyveload/bhyveload.c	Tue Dec 17 05:13:37 2013	(r259495)
+++ releng/10.0/usr.sbin/bhyveload/bhyveload.c	Tue Dec 17 06:39:48 2013	(r259496)
@@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/ioctl.h>
 #include <sys/stat.h>
 #include <sys/disk.h>
+#include <sys/queue.h>
 
 #include <machine/specialreg.h>
 #include <machine/vmm.h>
@@ -70,6 +71,7 @@ __FBSDID("$FreeBSD$");
 #include <err.h>
 #include <fcntl.h>
 #include <getopt.h>
+#include <libgen.h>
 #include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -86,9 +88,10 @@ __FBSDID("$FreeBSD$");
 #define	GB	(1024 * 1024 * 1024UL)
 #define	BSP	0
 
-static char *host_base = "/";
+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;
@@ -106,7 +109,7 @@ cb_putc(void *arg, int ch)
 {
 	char c = ch;
 
-	write(1, &c, 1);
+	(void) write(consout_fd, &c, 1);
 }
 
 static int
@@ -114,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);
 }
@@ -124,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);
 }
@@ -486,7 +489,7 @@ static void
 cb_exit(void *arg, int v)
 {
 
-	tcsetattr(0, TCSAFLUSH, &oldterm);
+	tcsetattr(consout_fd, TCSAFLUSH, &oldterm);
 	exit(v);
 }
 
@@ -498,23 +501,37 @@ cb_getmem(void *arg, uint64_t *ret_lowme
 	vm_get_memory_seg(ctx, 4 * GB, ret_highmem, NULL);
 }
 
+struct env {
+	const char *str;	/* name=value */
+	SLIST_ENTRY(env) next;
+};
+
+static SLIST_HEAD(envhead, env) envhead;
+
+static void
+addenv(const char *str)
+{
+	struct env *env;
+
+	env = malloc(sizeof(struct env));
+	env->str = str;
+	SLIST_INSERT_HEAD(&envhead, env, next);
+}
+
 static const char *
 cb_getenv(void *arg, int num)
 {
-	int max;
-
-	static const char * var[] = {
-		"smbios.bios.vendor=BHYVE",
-		"boot_serial=1",
-		NULL
-	};
+	int i;
+	struct env *env;
 
-	max = sizeof(var) / sizeof(var[0]);
+	i = 0;
+	SLIST_FOREACH(env, &envhead, next) {
+		if (i == num)
+			return (env->str);
+		i++;
+	}
 
-	if (num < max)
-		return (var[num]);
-	else
-		return (NULL);
+	return (NULL);
 }
 
 static struct loader_callbacks cb = {
@@ -548,13 +565,46 @@ 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>] "
-		"<vmname>\n", progname);
+	    "usage: %s [-m mem-size] [-d <disk-path>] [-h <host-path>]\n"
+	    "       %*s [-e <name=value>] [-c <console-device>] <vmname>\n",
+	    progname,
+	    (int)strlen(progname), "");
 	exit(1);
 }
 
@@ -567,17 +617,29 @@ main(int argc, char** argv)
 	int opt, error;
 	char *disk_image;
 
-	progname = argv[0];
+	progname = basename(argv[0]);
 
 	mem_size = 256 * MB;
 	disk_image = NULL;
 
-	while ((opt = getopt(argc, argv, "d: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;
 
+		case 'e':
+			addenv(optarg);
+			break;
+
 		case 'h':
 			host_base = optarg;
 			break;
@@ -619,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());
@@ -638,5 +702,9 @@ main(int argc, char** argv)
 	if (disk_image) {
 		disk_fd = open(disk_image, O_RDONLY);
 	}
+
+	addenv("smbios.bios.vendor=BHYVE");
+	addenv("boot_serial=1");
+
 	func(&cb, NULL, USERBOOT_VERSION_3, disk_fd >= 0);
 }


More information about the svn-src-all mailing list