summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJerry Jelinek <jerry.jelinek@joyent.com>2020-08-11 11:26:16 +0000
committerJerry Jelinek <jerry.jelinek@joyent.com>2020-08-11 11:26:16 +0000
commit6cf46b2989d19f4276d4e941f35d7daff371ad9b (patch)
tree01332e1d9a905b8dbbdcee8c0736f48f18a0e3b1
parent11f7a743c7e9060689d86f78f89fe0e9efe92932 (diff)
parentf7eeebb7a51b880fb7920f443b9774532d3efea6 (diff)
downloadillumos-joyent-6cf46b2989d19f4276d4e941f35d7daff371ad9b.tar.gz
[illumos-gate merge]
commit f7eeebb7a51b880fb7920f443b9774532d3efea6 13019 loader.efi: cursor and pixel draw should use Blt() if possible commit c3d209cab1511045e9bb1a521f1bd85995d4fd7e 13008 bhyve devmem could match better 13009 mdb-bhyve mishandles memseg offsets 13010 bhyve should not exit when VM debugged commit 40ae3b8f7394f061252c31a21b854ae328f6f269 13024 Add omitted word in sed man page
-rw-r--r--usr/src/boot/Makefile.version2
-rw-r--r--usr/src/boot/sys/boot/common/gfx_fb.c138
-rw-r--r--usr/src/cmd/bhyve/bhyverun.c12
-rw-r--r--usr/src/cmd/bhyve/gdb.c36
-rw-r--r--usr/src/cmd/bhyve/gdb.h3
-rw-r--r--usr/src/lib/libvmm/libvmm.c30
-rw-r--r--usr/src/man/man1/sed.14
-rw-r--r--usr/src/uts/i86pc/io/vmm/vm/vm_glue.h5
-rw-r--r--usr/src/uts/i86pc/io/vmm/vmm_sol_dev.c32
-rw-r--r--usr/src/uts/i86pc/io/vmm/vmm_sol_vm.c10
10 files changed, 232 insertions, 40 deletions
diff --git a/usr/src/boot/Makefile.version b/usr/src/boot/Makefile.version
index f0fd4aed50..5d93ec0e76 100644
--- a/usr/src/boot/Makefile.version
+++ b/usr/src/boot/Makefile.version
@@ -33,4 +33,4 @@ LOADER_VERSION = 1.1
# Use date like formatting here, YYYY.MM.DD.XX, without leading zeroes.
# The version is processed from left to right, the version number can only
# be increased.
-BOOT_VERSION = $(LOADER_VERSION)-2020.07.07.1
+BOOT_VERSION = $(LOADER_VERSION)-2020.08.05.1
diff --git a/usr/src/boot/sys/boot/common/gfx_fb.c b/usr/src/boot/sys/boot/common/gfx_fb.c
index 12ef4579fa..9389856ba8 100644
--- a/usr/src/boot/sys/boot/common/gfx_fb.c
+++ b/usr/src/boot/sys/boot/common/gfx_fb.c
@@ -48,6 +48,10 @@ static int gfx_inverse = 0;
static int gfx_inverse_screen = 0;
static uint8_t gfx_fg = DEFAULT_ANSI_FOREGROUND;
static uint8_t gfx_bg = DEFAULT_ANSI_BACKGROUND;
+#if defined(EFI)
+static EFI_GRAPHICS_OUTPUT_BLT_PIXEL *GlyphBuffer;
+static size_t GlyphBufferSize;
+#endif
static int gfx_fb_cons_clear(struct vis_consclear *);
static void gfx_fb_cons_copy(struct vis_conscopy *);
@@ -57,10 +61,12 @@ static void gfx_fb_cons_display(struct vis_consdisplay *);
static int gfx_gop_cons_clear(uint32_t data, uint32_t width, uint32_t height);
static void gfx_gop_cons_copy(struct vis_conscopy *);
static void gfx_gop_cons_display(struct vis_consdisplay *);
+static void gfx_gop_display_cursor(struct vis_conscursor *);
#endif
static int gfx_bm_cons_clear(uint32_t data, uint32_t width, uint32_t height);
static void gfx_bm_cons_copy(struct vis_conscopy *);
static void gfx_bm_cons_display(struct vis_consdisplay *);
+static void gfx_bm_display_cursor(struct vis_conscursor *);
/*
* Set default operations to use bitmap based implementation.
@@ -75,10 +81,12 @@ struct gfx_fb_ops {
int (*gfx_cons_clear)(uint32_t, uint32_t, uint32_t);
void (*gfx_cons_copy)(struct vis_conscopy *);
void (*gfx_cons_display)(struct vis_consdisplay *);
+ void (*gfx_cons_display_cursor)(struct vis_conscursor *);
} gfx_fb_ops = {
.gfx_cons_clear = gfx_bm_cons_clear,
.gfx_cons_copy = gfx_bm_cons_copy,
- .gfx_cons_display = gfx_bm_cons_display
+ .gfx_cons_display = gfx_bm_cons_display,
+ .gfx_cons_display_cursor = gfx_bm_display_cursor
};
/*
@@ -323,6 +331,7 @@ gfx_framework_init(struct visual_ops *fb_ops)
gfx_fb_ops.gfx_cons_clear = gfx_gop_cons_clear;
gfx_fb_ops.gfx_cons_copy = gfx_gop_cons_copy;
gfx_fb_ops.gfx_cons_display = gfx_gop_cons_display;
+ gfx_fb_ops.gfx_cons_display_cursor = gfx_gop_display_cursor;
}
#endif
@@ -614,10 +623,25 @@ gfx_gop_cons_display(struct vis_consdisplay *da)
bpp = roundup2(gfx_fb.framebuffer_common.framebuffer_bpp, 8) >> 3;
size = sizeof (*BltBuffer) * da->width * da->height;
- BltBuffer = malloc(size);
- if (BltBuffer == NULL && gfx_get_fb_address() != NULL) {
- /* Fall back to bitmap implementation */
- gfx_bm_cons_display(da);
+
+ /*
+ * Common data to display is glyph, use preallocated
+ * glyph buffer.
+ */
+ if (size == GlyphBufferSize) {
+ BltBuffer = GlyphBuffer;
+ } else {
+ BltBuffer = malloc(size);
+ }
+ if (BltBuffer == NULL) {
+ if (gfx_get_fb_address() != NULL) {
+ /* Fall back to bitmap implementation */
+ gfx_bm_cons_display(da);
+ }
+ /*
+ * We can not use Blt() and we have no address
+ * to write data to FB.
+ */
return;
}
@@ -626,7 +650,9 @@ gfx_gop_cons_display(struct vis_consdisplay *da)
bitmap_cpy((void *)BltBuffer, da->data, size, bpp);
(void) gop->Blt(gop, BltBuffer, EfiBltBufferToVideo,
0, 0, da->col, da->row, da->width, da->height, 0);
- free(BltBuffer);
+
+ if (BltBuffer != GlyphBuffer)
+ free(BltBuffer);
}
#endif
@@ -680,14 +706,88 @@ gfx_fb_cons_display(struct vis_consdisplay *da)
void
gfx_fb_display_cursor(struct vis_conscursor *ca)
{
+#if defined(EFI)
+ EFI_TPL tpl;
+
+ tpl = BS->RaiseTPL(TPL_NOTIFY);
+#endif
+ gfx_fb_ops.gfx_cons_display_cursor(ca);
+#if defined(EFI)
+ BS->RestoreTPL(tpl);
+#endif
+}
+
+#if defined(EFI)
+static void
+gfx_gop_display_cursor(struct vis_conscursor *ca)
+{
+ union pixel {
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL p;
+ uint32_t p32;
+ } *row, fg, bg;
+ size_t size;
+ extern EFI_GRAPHICS_OUTPUT *gop;
+
+ size = sizeof (*GlyphBuffer) * ca->width * ca->height;
+ if (size != GlyphBufferSize) {
+ free(GlyphBuffer);
+ GlyphBuffer = malloc(size);
+ if (GlyphBuffer == NULL) {
+ if (gfx_get_fb_address() != NULL) {
+ /* Fall back to bitmap implementation */
+ gfx_bm_display_cursor(ca);
+ }
+ /*
+ * We can not use Blt() and we have no address
+ * to write data to FB.
+ */
+ return;
+ }
+ GlyphBufferSize = size;
+ }
+
+ /*
+ * Since EfiBltVideoToBltBuffer is valid, Blt() can fail only
+ * due to device error.
+ */
+ if (gop->Blt(gop, GlyphBuffer, EfiBltVideoToBltBuffer,
+ ca->col, ca->row, 0, 0, ca->width, ca->height, 0) != EFI_SUCCESS)
+ return;
+
+ fg.p.Reserved = 0;
+ fg.p.Red = ca->fg_color.twentyfour[0];
+ fg.p.Green = ca->fg_color.twentyfour[1];
+ fg.p.Blue = ca->fg_color.twentyfour[2];
+ bg.p.Reserved = 0;
+ bg.p.Red = ca->bg_color.twentyfour[0];
+ bg.p.Green = ca->bg_color.twentyfour[1];
+ bg.p.Blue = ca->bg_color.twentyfour[2];
+
+ /*
+ * Build inverse image of the glyph.
+ * Since xor has self-inverse property, drawing cursor
+ * second time on the same spot, will restore the original content.
+ */
+ for (screen_size_t i = 0; i < ca->height; i++) {
+ row = (union pixel *)(GlyphBuffer + i * ca->width);
+ for (screen_size_t j = 0; j < ca->width; j++) {
+ row[j].p32 = (row[j].p32 ^ fg.p32) ^ bg.p32;
+ }
+ }
+
+ (void) gop->Blt(gop, GlyphBuffer, EfiBltBufferToVideo,
+ 0, 0, ca->col, ca->row, ca->width, ca->height, 0);
+}
+#endif
+
+static void
+gfx_bm_display_cursor(struct vis_conscursor *ca)
+{
uint32_t fg, bg;
uint32_t offset, size, *fb32;
uint16_t *fb16;
uint8_t *fb8, *fb;
uint32_t bpp, pitch;
-#if defined(EFI)
- EFI_TPL tpl;
-#endif
fb = gfx_get_fb_address();
bpp = roundup2(gfx_fb.framebuffer_common.framebuffer_bpp, 8) >> 3;
@@ -700,9 +800,6 @@ gfx_fb_display_cursor(struct vis_conscursor *ca)
* frame buffer by (D xor FG) xor BG.
*/
offset = ca->col * bpp + ca->row * pitch;
-#if defined(EFI)
- tpl = BS->RaiseTPL(TPL_NOTIFY);
-#endif
switch (gfx_fb.framebuffer_common.framebuffer_bpp) {
case 8: /* 8 bit */
fg = ca->fg_color.mono;
@@ -762,9 +859,6 @@ gfx_fb_display_cursor(struct vis_conscursor *ca)
}
break;
}
-#if defined(EFI)
- BS->RestoreTPL(tpl);
-#endif
}
/*
@@ -799,6 +893,10 @@ gfx_fb_setpixel(uint32_t x, uint32_t y)
uint32_t c, offset, pitch, bpp;
uint8_t *fb;
text_color_t fg, bg;
+#if defined(EFI)
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL p;
+ extern EFI_GRAPHICS_OUTPUT *gop;
+#endif
if (plat_stdout_is_framebuffer() == 0)
return;
@@ -829,6 +927,16 @@ gfx_fb_setpixel(uint32_t x, uint32_t y)
fb[offset + 2] = c & 0xff;
break;
case 32:
+#if defined(EFI)
+ if (gop != NULL) {
+ p.Reserved = 0;
+ p.Red = (c >> 16) & 0xff;
+ p.Green = (c >> 8) & 0xff;
+ p.Blue = c & 0xff;
+ gop->Blt(gop, &p, EfiBltBufferToVideo, 0, 0,
+ x, y, 1, 1, 0);
+ } else
+#endif
*(uint32_t *)(fb + offset) = c;
break;
}
diff --git a/usr/src/cmd/bhyve/bhyverun.c b/usr/src/cmd/bhyve/bhyverun.c
index e3c56bdbd0..18bfda76f0 100644
--- a/usr/src/cmd/bhyve/bhyverun.c
+++ b/usr/src/cmd/bhyve/bhyverun.c
@@ -1337,8 +1337,20 @@ main(int argc, char *argv[])
if (dbg_port != 0)
init_dbgport(dbg_port);
+#ifdef __FreeBSD__
if (gdb_port != 0)
init_gdb(ctx, gdb_port, gdb_stop);
+#else
+ if (gdb_port < 0) {
+ /*
+ * Set up the internal gdb state needed for basic debugging, but
+ * skip the step of listening on a port for the GDB server.
+ */
+ init_mdb(ctx, gdb_stop);
+ } else if (gdb_port != 0) {
+ init_gdb(ctx, gdb_port, gdb_stop);
+ }
+#endif
if (bvmcons)
init_bvmcons();
diff --git a/usr/src/cmd/bhyve/gdb.c b/usr/src/cmd/bhyve/gdb.c
index 6f6884eee8..720a55c58b 100644
--- a/usr/src/cmd/bhyve/gdb.c
+++ b/usr/src/cmd/bhyve/gdb.c
@@ -1840,6 +1840,42 @@ limit_gdb_socket(int s)
}
#endif
+
+#ifndef __FreeBSD__
+/*
+ * Equivalent to init_gdb() below, but without configuring the listening socket.
+ * This will allow the bhyve process to tolerate mdb attaching/detaching from
+ * the instance while it is running.
+ */
+void
+init_mdb(struct vmctx *_ctx, bool wait)
+{
+ int error;
+
+ error = pthread_mutex_init(&gdb_lock, NULL);
+ if (error != 0)
+ errc(1, error, "gdb mutex init");
+ error = pthread_cond_init(&idle_vcpus, NULL);
+ if (error != 0)
+ errc(1, error, "gdb cv init");
+
+ ctx = _ctx;
+ stopped_vcpu = -1;
+ TAILQ_INIT(&breakpoints);
+ vcpu_state = calloc(guest_ncpus, sizeof(*vcpu_state));
+ if (wait) {
+ /*
+ * Set vcpu 0 in vcpus_suspended. This will trigger the
+ * logic in gdb_cpu_add() to suspend the first vcpu before
+ * it starts execution. The vcpu will remain suspended
+ * until a debugger connects.
+ */
+ CPU_SET(0, &vcpus_suspended);
+ stopped_vcpu = 0;
+ }
+}
+#endif
+
void
init_gdb(struct vmctx *_ctx, int sport, bool wait)
{
diff --git a/usr/src/cmd/bhyve/gdb.h b/usr/src/cmd/bhyve/gdb.h
index 93396c1c67..95afee7ac2 100644
--- a/usr/src/cmd/bhyve/gdb.h
+++ b/usr/src/cmd/bhyve/gdb.h
@@ -35,5 +35,8 @@ void gdb_cpu_breakpoint(int vcpu, struct vm_exit *vmexit);
void gdb_cpu_mtrap(int vcpu);
void gdb_cpu_suspend(int vcpu);
void init_gdb(struct vmctx *ctx, int sport, bool wait);
+#ifndef __FreeBSD__
+void init_mdb(struct vmctx *ctx, bool wait);
+#endif
#endif /* !__GDB_H__ */
diff --git a/usr/src/lib/libvmm/libvmm.c b/usr/src/lib/libvmm/libvmm.c
index dc552a8de0..df3d8ec99f 100644
--- a/usr/src/lib/libvmm/libvmm.c
+++ b/usr/src/lib/libvmm/libvmm.c
@@ -11,6 +11,7 @@
/*
* Copyright 2019 Joyent, Inc.
+ * Copyright 2020 Oxide Computer Company
*/
/*
@@ -199,12 +200,31 @@ vmm_map(vmm_t *vmm, boolean_t writable)
for (ms = list_head(&vmm->vmm_memlist);
ms != NULL;
ms = list_next(&vmm->vmm_memlist, ms)) {
- off_t mapoff = ms->vms_gpa;
+ off_t mapoff;
+
+ if ((ms->vms_flags & VMM_MEMSEG_DEVMEM) == 0) {
+ /*
+ * sysmem segments will be located at an offset
+ * equivalent to their GPA.
+ */
+ mapoff = ms->vms_gpa;
+ } else {
+ /*
+ * devmem segments are located in a special region away
+ * from the normal GPA space.
+ */
+ if (vm_get_devmem_offset(vmm->vmm_ctx, ms->vms_segid,
+ &mapoff) != 0) {
+ goto fail;
+ }
+ }
- if ((ms->vms_flags & VMM_MEMSEG_DEVMEM) &&
- vm_get_devmem_offset(vmm->vmm_ctx, ms->vms_segid, &mapoff)
- != 0)
- goto fail;
+ /*
+ * While 'mapoff' points to the front of the segment, the actual
+ * mapping may be at some offset beyond that.
+ */
+ VERIFY(ms->vms_segoff >= 0);
+ mapoff += ms->vms_segoff;
vmm->vmm_memsize += ms->vms_maplen;
diff --git a/usr/src/man/man1/sed.1 b/usr/src/man/man1/sed.1
index 688d11ae41..441f877919 100644
--- a/usr/src/man/man1/sed.1
+++ b/usr/src/man/man1/sed.1
@@ -28,7 +28,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.TH SED 1 "Feb 14, 2015"
+.TH SED 1 "Aug 7, 2020"
.SH NAME
\fBsed\fP
\- stream editor
@@ -53,7 +53,7 @@ are specified, modifying the input as specified by a list of commands.
The input is then written to the standard output.
A single command may be specified as the first argument to
-\fB.\fP
+\fBsed\fP.
Multiple commands may be specified by using the
\fB\-e\fP
or
diff --git a/usr/src/uts/i86pc/io/vmm/vm/vm_glue.h b/usr/src/uts/i86pc/io/vmm/vm/vm_glue.h
index f894fcaf68..436b8e9691 100644
--- a/usr/src/uts/i86pc/io/vmm/vm/vm_glue.h
+++ b/usr/src/uts/i86pc/io/vmm/vm/vm_glue.h
@@ -12,6 +12,7 @@
/*
* Copyright 2019 Joyent, Inc.
+ * Copyright 2020 Oxide Computer Company
*/
#ifndef _VM_GLUE_
@@ -76,8 +77,8 @@ struct vm_page {
};
/* Illumos-specific functions for setup and operation */
-int vm_segmap_obj(struct vmspace *, vm_object_t, struct as *, caddr_t *,
- uint_t, uint_t, uint_t);
+int vm_segmap_obj(vm_object_t, off_t, size_t, struct as *, caddr_t *, uint_t,
+ uint_t, uint_t);
int vm_segmap_space(struct vmspace *, off_t, struct as *, caddr_t *, off_t,
uint_t, uint_t, uint_t);
void *vmspace_find_kva(struct vmspace *, uintptr_t, size_t);
diff --git a/usr/src/uts/i86pc/io/vmm/vmm_sol_dev.c b/usr/src/uts/i86pc/io/vmm/vmm_sol_dev.c
index 95a146661c..2f84ac5e95 100644
--- a/usr/src/uts/i86pc/io/vmm/vmm_sol_dev.c
+++ b/usr/src/uts/i86pc/io/vmm/vmm_sol_dev.c
@@ -14,6 +14,7 @@
* Copyright 2015 Pluribus Networks Inc.
* Copyright 2019 Joyent, Inc.
* Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
+ * Copyright 2020 Oxide Computer Company
*/
#include <sys/types.h>
@@ -184,25 +185,30 @@ vmmdev_devmem_create(vmm_softc_t *sc, struct vm_memseg *mseg, const char *name)
}
static boolean_t
-vmmdev_devmem_segid(vmm_softc_t *sc, off_t off, off_t len, int *segidp)
+vmmdev_devmem_segid(vmm_softc_t *sc, off_t off, off_t len, int *segidp,
+ off_t *map_offp)
{
list_t *dl = &sc->vmm_devmem_list;
vmm_devmem_entry_t *de = NULL;
+ const off_t map_end = off + len;
VERIFY(off >= VM_DEVMEM_START);
- for (de = list_head(dl); de != NULL; de = list_next(dl, de)) {
- /* XXX: Only hit on direct offset/length matches for now */
- if (de->vde_off == off && de->vde_len == len) {
- break;
- }
- }
- if (de == NULL) {
+ if (map_end < off) {
+ /* No match on overflow */
return (B_FALSE);
}
- *segidp = de->vde_segid;
- return (B_TRUE);
+ for (de = list_head(dl); de != NULL; de = list_next(dl, de)) {
+ const off_t item_end = de->vde_off + de->vde_len;
+
+ if (de->vde_off <= off && item_end >= map_end) {
+ *segidp = de->vde_segid;
+ *map_offp = off - de->vde_off;
+ return (B_TRUE);
+ }
+ }
+ return (B_FALSE);
}
static void
@@ -2076,9 +2082,10 @@ vmm_segmap(dev_t dev, off_t off, struct as *as, caddr_t *addrp, off_t len,
vms = vm_get_vmspace(vm);
if (off >= VM_DEVMEM_START) {
int segid;
+ off_t map_off = 0;
/* Mapping a devmem "device" */
- if (!vmmdev_devmem_segid(sc, off, len, &segid)) {
+ if (!vmmdev_devmem_segid(sc, off, len, &segid, &map_off)) {
err = ENODEV;
goto out;
}
@@ -2086,7 +2093,8 @@ vmm_segmap(dev_t dev, off_t off, struct as *as, caddr_t *addrp, off_t len,
if (err != 0) {
goto out;
}
- err = vm_segmap_obj(vms, vmo, as, addrp, prot, maxprot, flags);
+ err = vm_segmap_obj(vmo, map_off, len, as, addrp, prot, maxprot,
+ flags);
} else {
/* Mapping a part of the guest physical space */
err = vm_segmap_space(vms, off, as, addrp, len, prot, maxprot,
diff --git a/usr/src/uts/i86pc/io/vmm/vmm_sol_vm.c b/usr/src/uts/i86pc/io/vmm/vmm_sol_vm.c
index 9bd55c41f2..bedc338474 100644
--- a/usr/src/uts/i86pc/io/vmm/vmm_sol_vm.c
+++ b/usr/src/uts/i86pc/io/vmm/vmm_sol_vm.c
@@ -12,6 +12,7 @@
/*
* Copyright 2019 Joyent, Inc.
+ * Copyright 2020 Oxide Computer Company
*/
#include <sys/param.h>
@@ -894,12 +895,15 @@ vm_map_wire(vm_map_t map, vm_offset_t start, vm_offset_t end, int flags)
/* Provided custom for bhyve 'devmem' segment mapping */
int
-vm_segmap_obj(struct vmspace *vms, vm_object_t vmo, struct as *as,
+vm_segmap_obj(vm_object_t vmo, off_t map_off, size_t size, struct as *as,
caddr_t *addrp, uint_t prot, uint_t maxprot, uint_t flags)
{
- const size_t size = vmo->vmo_size;
int err;
+ VERIFY(map_off >= 0);
+ VERIFY(size <= vmo->vmo_size);
+ VERIFY((size + map_off) <= vmo->vmo_size);
+
if (vmo->vmo_type != OBJT_DEFAULT) {
/* Only support default objects for now */
return (ENOTSUP);
@@ -911,7 +915,7 @@ vm_segmap_obj(struct vmspace *vms, vm_object_t vmo, struct as *as,
if (err == 0) {
segvmm_crargs_t svma;
- svma.kaddr = vmo->vmo_data;
+ svma.kaddr = (caddr_t)vmo->vmo_data + map_off;
svma.prot = prot;
svma.cookie = vmo;
svma.hold = (segvmm_holdfn_t)vm_object_reference;