aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/bhyve/bhyvegc.h3
-rw-r--r--usr.sbin/bhyve/pci_fbuf.c59
-rw-r--r--usr.sbin/bhyve/rfb.c6
3 files changed, 46 insertions, 22 deletions
diff --git a/usr.sbin/bhyve/bhyvegc.h b/usr.sbin/bhyve/bhyvegc.h
index 5344473a05bd..7b2d43d99e32 100644
--- a/usr.sbin/bhyve/bhyvegc.h
+++ b/usr.sbin/bhyve/bhyvegc.h
@@ -43,4 +43,7 @@ void bhyvegc_set_fbaddr(struct bhyvegc *gc, void *fbaddr);
void bhyvegc_resize(struct bhyvegc *gc, int width, int height);
struct bhyvegc_image *bhyvegc_get_image(struct bhyvegc *gc);
+#define GC_COLS_MAX 3840
+#define GC_ROWS_MAX 2160
+
#endif /* _BHYVEGC_H_ */
diff --git a/usr.sbin/bhyve/pci_fbuf.c b/usr.sbin/bhyve/pci_fbuf.c
index 560c2bc839d6..d8cffb7282fc 100644
--- a/usr.sbin/bhyve/pci_fbuf.c
+++ b/usr.sbin/bhyve/pci_fbuf.c
@@ -31,18 +31,20 @@
#include <sys/socket.h>
#include <sys/un.h>
-#include <dev/vmm/vmm_mem.h>
#include <machine/vmm.h>
#include <machine/vmm_snapshot.h>
-#include <vmmapi.h>
+#include <dev/vmm/vmm_mem.h>
+
+#include <errno.h>
+#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-
-#include <errno.h>
#include <unistd.h>
+#include <vmmapi.h>
+
#include "bhyvegc.h"
#include "bhyverun.h"
#include "config.h"
@@ -74,9 +76,8 @@ static int fbuf_debug = 1;
#define DMEMSZ 128
#define FB_SIZE (32*MB)
-
-#define COLS_MAX 3840
-#define ROWS_MAX 2160
+_Static_assert(FB_SIZE >= GC_ROWS_MAX * GC_COLS_MAX * sizeof(uint32_t),
+ "Framebuffer size is too small for maximum resolution");
#define COLS_DEFAULT 1024
#define ROWS_DEFAULT 768
@@ -95,6 +96,8 @@ struct pci_fbuf_softc {
uint8_t reserved[116];
} __packed memregs;
+ pthread_mutex_t mtx;
+
/* rfb server */
sa_family_t rfb_family;
char *rfb_host;
@@ -137,8 +140,8 @@ pci_fbuf_write(struct pci_devinst *pi, int baridx, uint64_t offset, int size,
return;
}
+ pthread_mutex_lock(&sc->mtx);
p = (uint8_t *)&sc->memregs + offset;
-
switch (size) {
case 1:
*p = value;
@@ -168,6 +171,7 @@ pci_fbuf_write(struct pci_devinst *pi, int baridx, uint64_t offset, int size,
DPRINTF(DEBUG_INFO, ("switching to VESA mode"));
sc->gc_image->vgamode = 0;
}
+ pthread_mutex_unlock(&sc->mtx);
}
static uint64_t
@@ -181,13 +185,13 @@ pci_fbuf_read(struct pci_devinst *pi, int baridx, uint64_t offset, int size)
sc = pi->pi_arg;
-
if (offset + size > DMEMSZ) {
printf("fbuf: read too large, offset %ld size %d\n",
offset, size);
return (0);
}
+ pthread_mutex_lock(&sc->mtx);
p = (uint8_t *)&sc->memregs + offset;
value = 0;
switch (size) {
@@ -207,6 +211,7 @@ pci_fbuf_read(struct pci_devinst *pi, int baridx, uint64_t offset, int size)
printf("fbuf: read unknown size %d\n", size);
break;
}
+ pthread_mutex_unlock(&sc->mtx);
DPRINTF(DEBUG_VERBOSE,
("fbuf rd: offset 0x%lx, size: %d, value: 0x%lx",
@@ -340,9 +345,10 @@ pci_fbuf_parse_config(struct pci_fbuf_softc *sc, nvlist_t *nvl)
if (value != NULL)
sc->memregs.height = strtol(value, NULL, 10);
- if (sc->memregs.width > COLS_MAX ||
- sc->memregs.height > ROWS_MAX) {
- EPRINTLN("fbuf: max resolution is %ux%u", COLS_MAX, ROWS_MAX);
+ if (sc->memregs.width > GC_COLS_MAX ||
+ sc->memregs.height > GC_ROWS_MAX) {
+ EPRINTLN("fbuf: max resolution is %ux%u",
+ GC_COLS_MAX, GC_ROWS_MAX);
return (-1);
}
if (sc->memregs.width < COLS_MIN ||
@@ -363,21 +369,32 @@ static void
pci_fbuf_render(struct bhyvegc *gc, void *arg)
{
struct pci_fbuf_softc *sc;
+ uint32_t width, height;
sc = arg;
-
+ pthread_mutex_lock(&sc->mtx);
if (sc->vga_full && sc->gc_image->vgamode) {
/* TODO: mode switching to vga and vesa should use the special
* EFI-bhyve protocol port.
*/
+ pthread_mutex_unlock(&sc->mtx);
vga_render(gc, sc->vgasc);
return;
}
- if (sc->gc_width != sc->memregs.width ||
- sc->gc_height != sc->memregs.height) {
- bhyvegc_resize(gc, sc->memregs.width, sc->memregs.height);
- sc->gc_width = sc->memregs.width;
- sc->gc_height = sc->memregs.height;
+ width = sc->memregs.width;
+ height = sc->memregs.height;
+ if (sc->gc_width != width || sc->gc_height != height) {
+ if (width > GC_COLS_MAX || height > GC_ROWS_MAX) {
+ /* Ignore an invalid resolution. */
+ pthread_mutex_unlock(&sc->mtx);
+ } else {
+ sc->gc_width = width;
+ sc->gc_height = height;
+ pthread_mutex_unlock(&sc->mtx);
+ bhyvegc_resize(gc, width, height);
+ }
+ } else {
+ pthread_mutex_unlock(&sc->mtx);
}
}
@@ -396,6 +413,8 @@ pci_fbuf_init(struct pci_devinst *pi, nvlist_t *nvl)
pi->pi_arg = sc;
+ pthread_mutex_init(&sc->mtx, NULL);
+
/* initialize config space */
pci_set_cfgdata16(pi, PCIR_DEVICE, 0x40FB);
pci_set_cfgdata16(pi, PCIR_VENDOR, 0xFB5D);
@@ -455,8 +474,10 @@ pci_fbuf_init(struct pci_devinst *pi, nvlist_t *nvl)
error = rfb_init(sc->rfb_family, sc->rfb_host, sc->rfb_port,
sc->rfb_wait, sc->rfb_password);
done:
- if (error)
+ if (error) {
+ pthread_mutex_destroy(&sc->mtx);
free(sc);
+ }
return (error);
}
diff --git a/usr.sbin/bhyve/rfb.c b/usr.sbin/bhyve/rfb.c
index c6c048d2b140..265c95ace0a9 100644
--- a/usr.sbin/bhyve/rfb.c
+++ b/usr.sbin/bhyve/rfb.c
@@ -192,9 +192,9 @@ struct rfb_pixfmt_msg {
#define RFB_CLIENTMSG_EXT_KEYEVENT 0
-#define RFB_MAX_WIDTH 2000
-#define RFB_MAX_HEIGHT 1200
-#define RFB_ZLIB_BUFSZ RFB_MAX_WIDTH*RFB_MAX_HEIGHT*4
+#define RFB_MAX_WIDTH GC_COLS_MAX
+#define RFB_MAX_HEIGHT GC_ROWS_MAX
+#define RFB_ZLIB_BUFSZ (RFB_MAX_WIDTH * RFB_MAX_HEIGHT * 4)
#define PIXEL_RED_SHIFT 16
#define PIXEL_GREEN_SHIFT 8