summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgrehan <grehan@FreeBSD.org>2013-01-07 07:33:48 +0000
committergrehan <grehan@FreeBSD.org>2013-01-07 07:33:48 +0000
commit6b4735f33a04654288e66e77e13b9ec13c620488 (patch)
treefbf26081eca0dc491cca8ed1bed8fcbd81013abb
parent89556fd0ba3250c2723106cab75be15a87b0d650 (diff)
downloadFreeBSD-src-6b4735f33a04654288e66e77e13b9ec13c620488.zip
FreeBSD-src-6b4735f33a04654288e66e77e13b9ec13c620488.tar.gz
Don't completely drain the read file descriptor. Instead, only
fill up to the uart's rx fifo size, and leave any remaining input for when the rx fifo is read. This allows cut'n'paste of long lines to be done into the bhyve console without truncation. Also, introduce a mutex since the file input will run in the mevent thread context and may corrupt state accessed by a vCPU thread. Reviewed by: neel Approved by: NetApp
-rw-r--r--usr.sbin/bhyve/pci_uart.c44
1 files changed, 34 insertions, 10 deletions
diff --git a/usr.sbin/bhyve/pci_uart.c b/usr.sbin/bhyve/pci_uart.c
index 3f192e1..dd30551 100644
--- a/usr.sbin/bhyve/pci_uart.c
+++ b/usr.sbin/bhyve/pci_uart.c
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include <unistd.h>
#include <stdbool.h>
#include <string.h>
+#include <pthread.h>
#include "bhyverun.h"
#include "pci_emul.h"
@@ -97,6 +98,7 @@ struct fifo {
struct pci_uart_softc {
struct pci_devinst *pi;
+ pthread_mutex_t mtx; /* protects all softc elements */
uint8_t data; /* Data register (R/W) */
uint8_t ier; /* Interrupt enable register (R/W) */
uint8_t lcr; /* Line control register (R/W) */
@@ -214,6 +216,13 @@ fifo_numchars(struct fifo *fifo)
return (fifo->num);
}
+static int
+fifo_available(struct fifo *fifo)
+{
+
+ return (fifo->num < fifo->size);
+}
+
static void
pci_uart_opentty(struct pci_uart_softc *sc)
{
@@ -304,19 +313,25 @@ pci_uart_drain(int fd, enum ev_type ev, void *arg)
assert(fd == STDIN_FILENO);
assert(ev == EVF_READ);
+
+ /*
+ * This routine is called in the context of the mevent thread
+ * to take out the softc lock to protect against concurrent
+ * access from a vCPU i/o exit
+ */
+ pthread_mutex_lock(&sc->mtx);
- while ((ch = ttyread()) != -1) {
- /*
- * If we are in loopback mode then drop this character.
- */
- if ((sc->mcr & MCR_LOOPBACK) != 0)
- continue;
-
- if (fifo_putchar(&sc->rxfifo, ch) != 0)
- sc->lsr |= LSR_OE;
+ if ((sc->mcr & MCR_LOOPBACK) != 0) {
+ (void) ttyread();
+ } else {
+ while (fifo_available(&sc->rxfifo) &&
+ ((ch = ttyread()) != -1)) {
+ fifo_putchar(&sc->rxfifo, ch);
+ }
+ pci_uart_toggle_intr(sc);
}
- pci_uart_toggle_intr(sc);
+ pthread_mutex_unlock(&sc->mtx);
}
static void
@@ -337,6 +352,8 @@ pci_uart_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
pci_uart_opentty(sc);
sc->opened = 1;
}
+
+ pthread_mutex_lock(&sc->mtx);
/*
* Take care of the special case DLAB accesses first
@@ -458,6 +475,7 @@ pci_uart_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
done:
pci_uart_toggle_intr(sc);
+ pthread_mutex_unlock(&sc->mtx);
}
uint64_t
@@ -479,6 +497,8 @@ pci_uart_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
sc->opened = 1;
}
+ pthread_mutex_lock(&sc->mtx);
+
/*
* Take care of the special case DLAB accesses first
*/
@@ -554,6 +574,8 @@ pci_uart_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
done:
pci_uart_toggle_intr(sc);
+ pthread_mutex_unlock(&sc->mtx);
+
return (reg);
}
@@ -570,6 +592,8 @@ pci_uart_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
pi->pi_arg = sc;
sc->pi = pi;
+ pthread_mutex_init(&sc->mtx, NULL);
+
/* initialize config space */
pci_set_cfgdata16(pi, PCIR_DEVICE, COM_DEV);
pci_set_cfgdata16(pi, PCIR_VENDOR, COM_VENDOR);
OpenPOWER on IntegriCloud