summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/bhyve/acpi.c21
-rw-r--r--usr.sbin/bhyve/acpi.h2
-rw-r--r--usr.sbin/bhyve/bhyverun.c26
-rw-r--r--usr.sbin/bhyve/block_if.c2
-rw-r--r--usr.sbin/bhyve/mevent.c4
-rw-r--r--usr.sbin/bhyve/mptbl.c14
-rw-r--r--usr.sbin/bhyve/mptbl.h2
-rw-r--r--usr.sbin/bhyve/pci_ahci.c38
-rw-r--r--usr.sbin/bhyve/pci_emul.c2
-rw-r--r--usr.sbin/bhyve/pci_virtio_net.c5
-rw-r--r--usr.sbin/bhyve/pit_8254.c4
-rw-r--r--usr.sbin/bhyve/uart_emul.c120
-rw-r--r--usr.sbin/bhyveload/bhyveload.833
-rw-r--r--usr.sbin/bhyveload/bhyveload.c120
14 files changed, 268 insertions, 125 deletions
diff --git a/usr.sbin/bhyve/acpi.c b/usr.sbin/bhyve/acpi.c
index 89c11bc..6824330 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 fec6c9d..12d1ee0 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 6e8ea59..8263602 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,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);
diff --git a/usr.sbin/bhyve/block_if.c b/usr.sbin/bhyve/block_if.c
index 9228b9a..ba7cfcd 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 eff0610..82e5edd 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 5687d90..794ccc7 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 3c4c527..e9e1c42 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 68d9bc1..0109975 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 bbaac23..3820b04 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 ae20231..57ab041 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 3987da3..88c2d22 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 981607b..2fbbd15 100644
--- a/usr.sbin/bhyve/uart_emul.c
+++ b/usr.sbin/bhyve/uart_emul.c
@@ -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 *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 2efcad0..eed1f1a 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 6e541e8..94cb1b1 100644
--- a/usr.sbin/bhyveload/bhyveload.c
+++ b/usr.sbin/bhyveload/bhyveload.c
@@ -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_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 <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);
}
OpenPOWER on IntegriCloud