From f7349214b4b6cc5616c519c2f7b552d90ad7a536 Mon Sep 17 00:00:00 2001 From: grehan Date: Tue, 17 Dec 2013 06:39:48 +0000 Subject: [PATCH] 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) git-svn-id: svn://svn.freebsd.org/base/releng/10.0@259496 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- usr.sbin/bhyve/acpi.c | 21 +++--- usr.sbin/bhyve/acpi.h | 2 +- usr.sbin/bhyve/bhyverun.c | 26 ++++--- usr.sbin/bhyve/block_if.c | 2 +- usr.sbin/bhyve/mevent.c | 4 +- usr.sbin/bhyve/mptbl.c | 14 ++-- usr.sbin/bhyve/mptbl.h | 2 +- usr.sbin/bhyve/pci_ahci.c | 38 ++++++---- usr.sbin/bhyve/pci_emul.c | 2 +- usr.sbin/bhyve/pci_virtio_net.c | 5 +- usr.sbin/bhyve/pit_8254.c | 4 +- usr.sbin/bhyve/uart_emul.c | 120 +++++++++++++++++++------------- usr.sbin/bhyveload/bhyveload.8 | 33 +++++++++ usr.sbin/bhyveload/bhyveload.c | 120 +++++++++++++++++++++++++------- 14 files changed, 268 insertions(+), 125 deletions(-) diff --git a/usr.sbin/bhyve/acpi.c b/usr.sbin/bhyve/acpi.c index 89c11bce..68243308 100644 --- a/usr.sbin/bhyve/acpi.c +++ b/usr.sbin/bhyve/acpi.c @@ -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, int ioapic) 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 diff --git a/usr.sbin/bhyve/acpi.h b/usr.sbin/bhyve/acpi.h index fec6c9d6..12d1ee05 100644 --- a/usr.sbin/bhyve/acpi.h +++ b/usr.sbin/bhyve/acpi.h @@ -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_ */ diff --git a/usr.sbin/bhyve/bhyverun.c b/usr.sbin/bhyve/bhyverun.c index 6e8ea592..82636027 100644 --- a/usr.sbin/bhyve/bhyverun.c +++ b/usr.sbin/bhyve/bhyverun.c @@ -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 *ctx, int cpu) 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,13 +677,18 @@ 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 */ diff --git a/usr.sbin/bhyve/block_if.c b/usr.sbin/bhyve/block_if.c index 9228b9af..ba7cfcdd 100644 --- a/usr.sbin/bhyve/block_if.c +++ b/usr.sbin/bhyve/block_if.c @@ -293,7 +293,7 @@ blockif_open(const char *optstr, const char *ident) 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); diff --git a/usr.sbin/bhyve/mevent.c b/usr.sbin/bhyve/mevent.c index eff06101..82e5edd7 100644 --- a/usr.sbin/bhyve/mevent.c +++ b/usr.sbin/bhyve/mevent.c @@ -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 diff --git a/usr.sbin/bhyve/mptbl.c b/usr.sbin/bhyve/mptbl.c index 5687d90e..794ccc70 100644 --- a/usr.sbin/bhyve/mptbl.c +++ b/usr.sbin/bhyve/mptbl.c @@ -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 ncpu, int ioapic) 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; diff --git a/usr.sbin/bhyve/mptbl.h b/usr.sbin/bhyve/mptbl.h index 3c4c5277..e9e1c426 100644 --- a/usr.sbin/bhyve/mptbl.h +++ b/usr.sbin/bhyve/mptbl.h @@ -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_ */ diff --git a/usr.sbin/bhyve/pci_ahci.c b/usr.sbin/bhyve/pci_ahci.c index 68d9bc1e..0109975d 100644 --- a/usr.sbin/bhyve/pci_ahci.c +++ b/usr.sbin/bhyve/pci_ahci.c @@ -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 slot, uint8_t *cfis, uint32_t done, * 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, uint8_t *cfis, 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, uint8_t *cfis, * 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 pci_devinst *pi, char *opts, int atapi) /* * 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; diff --git a/usr.sbin/bhyve/pci_emul.c b/usr.sbin/bhyve/pci_emul.c index bbaac23f..3820b046 100644 --- a/usr.sbin/bhyve/pci_emul.c +++ b/usr.sbin/bhyve/pci_emul.c @@ -1252,7 +1252,7 @@ pci_emul_cmdwrite(struct pci_devinst *pi, uint32_t new, int bytes) * 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: diff --git a/usr.sbin/bhyve/pci_virtio_net.c b/usr.sbin/bhyve/pci_virtio_net.c index ae20231a..57ab0419 100644 --- a/usr.sbin/bhyve/pci_virtio_net.c +++ b/usr.sbin/bhyve/pci_virtio_net.c @@ -588,7 +588,7 @@ pci_vtnet_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) */ 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 pci_devinst *pi, char *opts) 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); diff --git a/usr.sbin/bhyve/pit_8254.c b/usr.sbin/bhyve/pit_8254.c index 3987da3b..88c2d22d 100644 --- a/usr.sbin/bhyve/pit_8254.c +++ b/usr.sbin/bhyve/pit_8254.c @@ -106,8 +106,8 @@ pit_mevent_cb(int fd, enum ev_type type, void *param) 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 diff --git a/usr.sbin/bhyve/uart_emul.c b/usr.sbin/bhyve/uart_emul.c index 981607b9..2fbbd15e 100644 --- a/usr.sbin/bhyve/uart_emul.c +++ b/usr.sbin/bhyve/uart_emul.c @@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -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 *arg) 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 *arg) 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 offset, uint8_t value) 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 offset, uint8_t value) 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 offset) { 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, uart_intr_func_t intr_deassert, 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); } diff --git a/usr.sbin/bhyveload/bhyveload.8 b/usr.sbin/bhyveload/bhyveload.8 index 2efcad06..eed1f1ad 100644 --- a/usr.sbin/bhyveload/bhyveload.8 +++ b/usr.sbin/bhyveload/bhyveload.8 @@ -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 image. 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 diff --git a/usr.sbin/bhyveload/bhyveload.c b/usr.sbin/bhyveload/bhyveload.c index 6e541e8c..94cb1b19 100644 --- a/usr.sbin/bhyveload/bhyveload.c +++ b/usr.sbin/bhyveload/bhyveload.c @@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -70,6 +71,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -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_lowmem, uint64_t *ret_highmem) vm_get_memory_seg(ctx, 4 * GB, ret_highmem, NULL); } -static const char * -cb_getenv(void *arg, int num) +struct env { + const char *str; /* name=value */ + SLIST_ENTRY(env) next; +}; + +static SLIST_HEAD(envhead, env) envhead; + +static void +addenv(const char *str) { - int max; + struct env *env; - static const char * var[] = { - "smbios.bios.vendor=BHYVE", - "boot_serial=1", - NULL - }; + env = malloc(sizeof(struct env)); + env->str = str; + SLIST_INSERT_HEAD(&envhead, env, next); +} - max = sizeof(var) / sizeof(var[0]); +static const char * +cb_getenv(void *arg, int num) +{ + int i; + struct env *env; + + 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 ] [-h ] " - "\n", progname); + "usage: %s [-m mem-size] [-d ] [-h ]\n" + " %*s [-e ] [-c ] \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); } -- 2.42.0