diff options
author | Jerry Jelinek <jerry.jelinek@joyent.com> | 2020-08-11 11:26:16 +0000 |
---|---|---|
committer | Jerry Jelinek <jerry.jelinek@joyent.com> | 2020-08-11 11:26:16 +0000 |
commit | 6cf46b2989d19f4276d4e941f35d7daff371ad9b (patch) | |
tree | 01332e1d9a905b8dbbdcee8c0736f48f18a0e3b1 | |
parent | 11f7a743c7e9060689d86f78f89fe0e9efe92932 (diff) | |
parent | f7eeebb7a51b880fb7920f443b9774532d3efea6 (diff) | |
download | illumos-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.version | 2 | ||||
-rw-r--r-- | usr/src/boot/sys/boot/common/gfx_fb.c | 138 | ||||
-rw-r--r-- | usr/src/cmd/bhyve/bhyverun.c | 12 | ||||
-rw-r--r-- | usr/src/cmd/bhyve/gdb.c | 36 | ||||
-rw-r--r-- | usr/src/cmd/bhyve/gdb.h | 3 | ||||
-rw-r--r-- | usr/src/lib/libvmm/libvmm.c | 30 | ||||
-rw-r--r-- | usr/src/man/man1/sed.1 | 4 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/vmm/vm/vm_glue.h | 5 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/vmm/vmm_sol_dev.c | 32 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/vmm/vmm_sol_vm.c | 10 |
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; |