diff options
| -rw-r--r-- | usr.sbin/bhyve/bhyvegc.h | 3 | ||||
| -rw-r--r-- | usr.sbin/bhyve/pci_fbuf.c | 53 | ||||
| -rw-r--r-- | usr.sbin/bhyve/rfb.c | 6 |
3 files changed, 42 insertions, 20 deletions
diff --git a/usr.sbin/bhyve/bhyvegc.h b/usr.sbin/bhyve/bhyvegc.h index 5344473a05bd..57c4f048cacf 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 1920 +#define GC_ROWS_MAX 1200 + #endif /* _BHYVEGC_H_ */ diff --git a/usr.sbin/bhyve/pci_fbuf.c b/usr.sbin/bhyve/pci_fbuf.c index e2d34cfef639..99e43a87e6c6 100644 --- a/usr.sbin/bhyve/pci_fbuf.c +++ b/usr.sbin/bhyve/pci_fbuf.c @@ -32,15 +32,16 @@ #include <machine/vmm.h> #include <machine/vmm_snapshot.h> -#include <vmmapi.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" @@ -72,9 +73,8 @@ static int fbuf_debug = 1; #define DMEMSZ 128 #define FB_SIZE (16*MB) - -#define COLS_MAX 1920 -#define ROWS_MAX 1200 +_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 @@ -93,6 +93,8 @@ struct pci_fbuf_softc { uint8_t reserved[116]; } __packed memregs; + pthread_mutex_t mtx; + /* rfb server */ char *rfb_host; char *rfb_password; @@ -134,8 +136,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; @@ -165,6 +167,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 @@ -178,13 +181,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) { @@ -204,6 +207,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", @@ -316,7 +320,7 @@ pci_fbuf_parse_config(struct pci_fbuf_softc *sc, nvlist_t *nvl) value = get_config_value_node(nvl, "w"); if (value != NULL) { sc->memregs.width = atoi(value); - if (sc->memregs.width > COLS_MAX) { + if (sc->memregs.width > GC_COLS_MAX) { EPRINTLN("fbuf: width %d too large", sc->memregs.width); return (-1); } @@ -327,7 +331,7 @@ pci_fbuf_parse_config(struct pci_fbuf_softc *sc, nvlist_t *nvl) value = get_config_value_node(nvl, "h"); if (value != NULL) { sc->memregs.height = atoi(value); - if (sc->memregs.height > ROWS_MAX) { + if (sc->memregs.height > GC_ROWS_MAX) { EPRINTLN("fbuf: height %d too large", sc->memregs.height); return (-1); @@ -347,21 +351,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); } } @@ -380,6 +395,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); @@ -438,8 +455,10 @@ pci_fbuf_init(struct pci_devinst *pi, nvlist_t *nvl) error = rfb_init(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 0b4888483559..737dd197f285 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 |
