diff options
30 files changed, 1022 insertions, 794 deletions
diff --git a/usr/src/boot/sys/boot/common/gfx_fb.c b/usr/src/boot/sys/boot/common/gfx_fb.c index 361076fc2b..6331a28ab7 100644 --- a/usr/src/boot/sys/boot/common/gfx_fb.c +++ b/usr/src/boot/sys/boot/common/gfx_fb.c @@ -16,13 +16,64 @@ */ /* - * Common functions to implement graphical framebuffer support for console. + * The workhorse here is gfxfb_blt(). It is implemented to mimic UEFI + * GOP Blt, and allows us to fill the rectangle on screen, copy + * rectangle from video to buffer and buffer to video and video to video. + * Such implementation does allow us to have almost identical implementation + * for both BIOS VBE and UEFI. + * + * ALL pixel data is assumed to be 32-bit BGRA (byte order Blue, Green, Red, + * Alpha) format, this allows us to only handle RGB data and not to worry + * about mixing RGB with indexed colors. + * Data exchange between memory buffer and video will translate BGRA + * and native format as following: + * + * 32-bit to/from 32-bit is trivial case. + * 32-bit to/from 24-bit is also simple - we just drop the alpha channel. + * 32-bit to/from 16-bit is more complicated, because we nee to handle + * data loss from 32-bit to 16-bit. While reading/writing from/to video, we + * need to apply masks of 16-bit color components. This will preserve + * colors for terminal text. For 32-bit truecolor PMG images, we need to + * translate 32-bit colors to 15/16 bit colors and this means data loss. + * There are different algorithms how to perform such color space reduction, + * we are currently using bitwise right shift to reduce color space and so far + * this technique seems to be sufficient (see also gfx_fb_putimage(), the + * end of for loop). + * 32-bit to/from 8-bit is the most troublesome because 8-bit colors are + * indexed. From video, we do get color indexes, and we do translate + * color index values to RGB. To write to video, we again need to translate + * RGB to color index. Additionally, we need to translate between VGA and + * Sun colors. + * + * Our internal color data is represented using BGRA format. But the hardware + * used indexed colors for 8-bit colors (0-255) and for this mode we do + * need to perform translation to/from BGRA and index values. + * + * - paletteentry RGB <-> index - + * BGRA BUFFER <----/ \ - VIDEO + * \ / + * - RGB (16/24/32) - + * + * To perform index to RGB translation, we use palette table generated + * from when we set up 8-bit mode video. We cannot read palette data from + * the hardware, because not all hardware supports reading it. + * + * BGRA to index is implemented in rgb_to_color_index() by searching + * palette array for closest match of RBG values. + * + * Note: In 8-bit mode, We do store first 16 colors to palette registers + * in VGA color order, this serves two purposes; firstly, + * if palette update is not supported, we still have correct 16 colors. + * Secondly, the kernel does get correct 16 colors when some other boot + * loader is used. However, the palette map for 8-bit colors is using + * Sun color ordering - this does allow us to skip translation + * from VGA colors to Sun colors, while we are reading RGB data. */ #include <sys/cdefs.h> #include <sys/param.h> #include <stand.h> -#if defined(EFI) +#if defined(EFI) #include <efi.h> #include <efilib.h> #else @@ -59,25 +110,16 @@ 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) +#if defined(EFI) static EFI_GRAPHICS_OUTPUT_BLT_PIXEL *GlyphBuffer; -static size_t GlyphBufferSize; +#else +static struct paletteentry *GlyphBuffer; #endif +static size_t GlyphBufferSize; -static int gfx_fb_cons_clear(struct vis_consclear *); -static void gfx_fb_cons_copy(struct vis_conscopy *); -static void gfx_fb_cons_display(struct vis_consdisplay *); - -#if defined(EFI) -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 *); +int gfx_fb_cons_clear(struct vis_consclear *); +void gfx_fb_cons_copy(struct vis_conscopy *); +void gfx_fb_cons_display(struct vis_consdisplay *); static bool insert_font(char *, FONT_FLAGS); @@ -90,17 +132,6 @@ static bool insert_font(char *, FONT_FLAGS); * Task Priority Level (TPL) to TPL_NOTIFY, which is highest priority * usable in application. */ -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_cursor = gfx_bm_display_cursor -}; /* * Translate platform specific FB address. @@ -108,7 +139,7 @@ struct gfx_fb_ops { static uint8_t * gfx_get_fb_address(void) { -#if defined(EFI) +#if defined(EFI) return ((uint8_t *)(uintptr_t) gfx_fb.framebuffer_common.framebuffer_addr); #else @@ -174,28 +205,35 @@ gfx_parse_mode_str(char *str, int *x, int *y, int *depth) /* * Support for color mapping. + * For 8, 24 and 32 bit depth, use mask size 8. + * 15/16 bit depth needs to use mask size from mode, + * or we will lose color information from 32-bit to 15/16 bit translation. */ uint32_t gfx_fb_color_map(uint8_t index) { rgb_t rgb; + int bpp; - if (gfx_fb.framebuffer_common.framebuffer_type != - MULTIBOOT_FRAMEBUFFER_TYPE_RGB) { - if (index < nitems(solaris_color_to_pc_color)) - return (solaris_color_to_pc_color[index]); - else - return (index); - } + bpp = roundup2(gfx_fb.framebuffer_common.framebuffer_bpp, 8) >> 3; - rgb.red.pos = gfx_fb.u.fb2.framebuffer_red_field_position; - rgb.red.size = gfx_fb.u.fb2.framebuffer_red_mask_size; + rgb.red.pos = 16; + if (bpp == 2) + rgb.red.size = gfx_fb.u.fb2.framebuffer_red_mask_size; + else + rgb.red.size = 8; - rgb.green.pos = gfx_fb.u.fb2.framebuffer_green_field_position; - rgb.green.size = gfx_fb.u.fb2.framebuffer_green_mask_size; + rgb.green.pos = 8; + if (bpp == 2) + rgb.green.size = gfx_fb.u.fb2.framebuffer_green_mask_size; + else + rgb.green.size = 8; - rgb.blue.pos = gfx_fb.u.fb2.framebuffer_blue_field_position; - rgb.blue.size = gfx_fb.u.fb2.framebuffer_blue_mask_size; + rgb.blue.pos = 0; + if (bpp == 2) + rgb.blue.size = gfx_fb.u.fb2.framebuffer_blue_mask_size; + else + rgb.blue.size = 8; return (rgb_color_map(&rgb, index)); } @@ -328,31 +366,16 @@ gfx_set_inverses(struct env_var *ev, int flags, const void *value) * Initialize gfx framework. */ void -gfx_framework_init(struct visual_ops *fb_ops) +gfx_framework_init(void) { int rc, limit; char *env, buf[2]; -#if defined(EFI) - extern EFI_GRAPHICS_OUTPUT *gop; - - if (gop != NULL) { - 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 if (gfx_fb.framebuffer_common.framebuffer_bpp < 24) limit = 7; else limit = 255; - /* Add visual io callbacks */ - fb_ops->cons_clear = gfx_fb_cons_clear; - fb_ops->cons_copy = gfx_fb_cons_copy; - fb_ops->cons_display = gfx_fb_cons_display; - /* set up tem inverse controls */ env = getenv("tem.inverse"); if (env != NULL) { @@ -415,159 +438,562 @@ gfx_framework_init(struct visual_ops *fb_ops) } /* - * visual io callbacks. + * Get indexed color from RGB. This function is used to write data to video + * memory when the adapter is set to use indexed colors. + * Since UEFI does only support 32-bit colors, we do not implement it for + * UEFI because there is no need for it and we do not have palette array + * for UEFI. */ +static uint8_t +rgb_to_color_index(uint8_t r, uint8_t g, uint8_t b) +{ +#if !defined(EFI) + uint32_t color, best, dist, k; + int diff; + + color = 0; + best = 255 * 255 * 255; + for (k = 0; k < NCMAP; k++) { + diff = r - pe8[k].Red; + dist = diff * diff; + diff = g - pe8[k].Green; + dist += diff * diff; + diff = b - pe8[k].Blue; + dist += diff * diff; + + /* Exact match, exit the loop */ + if (dist == 0) + break; -#if defined(EFI) -static int -gfx_gop_cons_clear(uint32_t data, uint32_t width, uint32_t height) + if (dist < best) { + color = k; + best = dist; + } + } + if (k == NCMAP) + k = color; + return (k); +#else + (void) r; + (void) g; + (void) b; + return (0); +#endif +} + +static void +gfx_mem_wr1(uint8_t *base, size_t size, uint32_t o, uint8_t v) { - EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer; - EFI_STATUS status; - extern EFI_GRAPHICS_OUTPUT *gop; - BltBuffer = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)&data; + if (o >= size) + return; + *(uint8_t *)(base + o) = v; +} - status = gop->Blt(gop, BltBuffer, EfiBltVideoFill, 0, 0, - 0, 0, width, height, 0); +static void +gfx_mem_wr2(uint8_t *base, size_t size, uint32_t o, uint16_t v) +{ - if (EFI_ERROR(status)) - return (1); - else - return (0); + if (o >= size) + return; + *(uint16_t *)(base + o) = v; +} + +static void +gfx_mem_wr4(uint8_t *base, size_t size, uint32_t o, uint32_t v) +{ + + if (o >= size) + return; + *(uint32_t *)(base + o) = v; } -#endif static int -gfx_bm_cons_clear(uint32_t data, uint32_t width, uint32_t height) +gfxfb_blt_fill(void *BltBuffer, + uint32_t DestinationX, uint32_t DestinationY, + uint32_t Width, uint32_t Height) { - uint8_t *fb, *fb8; - uint32_t *fb32, pitch; - uint16_t *fb16; - uint32_t i, j; +#if defined(EFI) + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *p; +#else + struct paletteentry *p; +#endif + uint32_t data, bpp, pitch, y, x; + size_t size; + off_t off; + uint8_t *destination; - fb = gfx_get_fb_address(); - pitch = gfx_fb.framebuffer_common.framebuffer_pitch; + if (BltBuffer == NULL) + return (EINVAL); - switch (gfx_fb.framebuffer_common.framebuffer_bpp) { - case 8: /* 8 bit */ - for (i = 0; i < height; i++) { - (void) memset(fb + i * pitch, data, pitch); - } - break; - case 15: - case 16: /* 16 bit */ - for (i = 0; i < height; i++) { - fb16 = (uint16_t *)(fb + i * pitch); - for (j = 0; j < width; j++) - fb16[j] = (uint16_t)(data & 0xffff); - } - break; - case 24: /* 24 bit */ - for (i = 0; i < height; i++) { - fb8 = fb + i * pitch; - for (j = 0; j < pitch; j += 3) { - fb8[j] = (data >> 16) & 0xff; - fb8[j+1] = (data >> 8) & 0xff; - fb8[j+2] = data & 0xff; + if (DestinationY + Height > + gfx_fb.framebuffer_common.framebuffer_height) + return (EINVAL); + + if (DestinationX + Width > gfx_fb.framebuffer_common.framebuffer_width) + return (EINVAL); + + if (Width == 0 || Height == 0) + return (EINVAL); + + p = BltBuffer; + if (gfx_fb.framebuffer_common.framebuffer_bpp == 8) { + data = rgb_to_color_index(p->Red, p->Green, p->Blue); + } else { + data = (p->Red & + ((1 << gfx_fb.u.fb2.framebuffer_red_mask_size) - 1)) << + gfx_fb.u.fb2.framebuffer_red_field_position; + data |= (p->Green & + ((1 << gfx_fb.u.fb2.framebuffer_green_mask_size) - 1)) << + gfx_fb.u.fb2.framebuffer_green_field_position; + data |= (p->Blue & + ((1 << gfx_fb.u.fb2.framebuffer_blue_mask_size) - 1)) << + gfx_fb.u.fb2.framebuffer_blue_field_position; + } + + bpp = roundup2(gfx_fb.framebuffer_common.framebuffer_bpp, 8) >> 3; + pitch = gfx_fb.framebuffer_common.framebuffer_pitch; + destination = gfx_get_fb_address(); + size = gfx_fb.framebuffer_common.framebuffer_height * pitch; + + for (y = DestinationY; y < Height + DestinationY; y++) { + off = y * pitch + DestinationX * bpp; + for (x = 0; x < Width; x++) { + switch (bpp) { + case 1: + gfx_mem_wr1(destination, size, off, + (data < NCOLORS) ? + solaris_color_to_pc_color[data] : data); + break; + case 2: + gfx_mem_wr2(destination, size, off, data); + break; + case 3: + gfx_mem_wr1(destination, size, off, + (data >> 16) & 0xff); + gfx_mem_wr1(destination, size, off + 1, + (data >> 8) & 0xff); + gfx_mem_wr1(destination, size, off + 2, + data & 0xff); + break; + case 4: + gfx_mem_wr4(destination, size, off, data); + break; + default: + return (EINVAL); } + off += bpp; } - break; - case 32: /* 32 bit */ - for (i = 0; i < height; i++) { - fb32 = (uint32_t *)(fb + i * pitch); - for (j = 0; j < width; j++) - fb32[j] = data; - } - break; - default: - return (1); } return (0); } static int -gfx_fb_cons_clear(struct vis_consclear *ca) +gfxfb_blt_video_to_buffer(void *BltBuffer, uint32_t SourceX, uint32_t SourceY, + uint32_t DestinationX, uint32_t DestinationY, + uint32_t Width, uint32_t Height, uint32_t Delta) { - uint32_t data, width, height; - int ret; -#if defined(EFI) - EFI_TPL tpl; +#if defined(EFI) + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *p; +#else + struct paletteentry *p; #endif + uint32_t x, sy, dy; + uint32_t bpp, pitch, copybytes; + off_t off; + uint8_t *source, *destination, *sb; + uint8_t rm, rp, gm, gp, bm, bp; + bool bgra; + + if (BltBuffer == NULL) + return (EINVAL); - data = gfx_fb_color_map(ca->bg_color); - width = gfx_fb.framebuffer_common.framebuffer_width; - height = gfx_fb.framebuffer_common.framebuffer_height; + if (SourceY + Height > + gfx_fb.framebuffer_common.framebuffer_height) + return (EINVAL); -#if defined(EFI) - tpl = BS->RaiseTPL(TPL_NOTIFY); -#endif - ret = gfx_fb_ops.gfx_cons_clear(data, width, height); -#if defined(EFI) - BS->RestoreTPL(tpl); -#endif - return (ret); + if (SourceX + Width > gfx_fb.framebuffer_common.framebuffer_width) + return (EINVAL); + + if (Width == 0 || Height == 0) + return (EINVAL); + + if (Delta == 0) + Delta = Width * sizeof (*p); + + bpp = roundup2(gfx_fb.framebuffer_common.framebuffer_bpp, 8) >> 3; + pitch = gfx_fb.framebuffer_common.framebuffer_pitch; + + copybytes = Width * bpp; + + rm = (1 << gfx_fb.u.fb2.framebuffer_red_mask_size) - 1; + rp = gfx_fb.u.fb2.framebuffer_red_field_position; + gm = (1 << gfx_fb.u.fb2.framebuffer_green_mask_size) - 1; + gp = gfx_fb.u.fb2.framebuffer_green_field_position; + bm = (1 << gfx_fb.u.fb2.framebuffer_blue_mask_size) - 1; + bp = gfx_fb.u.fb2.framebuffer_blue_field_position; + /* If FB pixel format is BGRA, we can use direct copy. */ + bgra = bpp == 4 && + gfx_fb.u.fb2.framebuffer_red_mask_size == 8 && + gfx_fb.u.fb2.framebuffer_red_field_position == 16 && + gfx_fb.u.fb2.framebuffer_green_mask_size == 8 && + gfx_fb.u.fb2.framebuffer_green_field_position == 8 && + gfx_fb.u.fb2.framebuffer_blue_mask_size == 8 && + gfx_fb.u.fb2.framebuffer_blue_field_position == 0; + + for (sy = SourceY, dy = DestinationY; dy < Height + DestinationY; + sy++, dy++) { + off = sy * pitch + SourceX * bpp; + source = gfx_get_fb_address() + off; + destination = (uint8_t *)BltBuffer + dy * Delta + + DestinationX * sizeof (*p); + + if (bgra) { + bcopy(source, destination, copybytes); + } else { + for (x = 0; x < Width; x++) { + uint32_t c = 0; + + p = (void *)(destination + x * sizeof (*p)); + sb = source + x * bpp; + switch (bpp) { + case 1: + c = *sb; + break; + case 2: + c = *(uint16_t *)sb; + break; + case 3: + c = sb[0] << 16 | sb[1] << 8 | sb[2]; + break; + case 4: + c = *(uint32_t *)sb; + break; + default: + return (EINVAL); + } + + if (bpp == 1) { + *(uint32_t *)p = gfx_fb_color_map( + (c < NCOLORS) ? + pc_color_to_solaris_color[c] : c); + } else { + p->Red = (c >> rp) & rm; + p->Green = (c >> gp) & gm; + p->Blue = (c >> bp) & bm; + p->Reserved = 0; + } + } + } + } + + return (0); } -#if defined(EFI) -static void -gfx_gop_cons_copy(struct vis_conscopy *ma) +static int +gfxfb_blt_buffer_to_video(void *BltBuffer, uint32_t SourceX, uint32_t SourceY, + uint32_t DestinationX, uint32_t DestinationY, + uint32_t Width, uint32_t Height, uint32_t Delta) { - UINTN width, height; - extern EFI_GRAPHICS_OUTPUT *gop; +#if defined(EFI) + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *p; +#else + struct paletteentry *p; +#endif + uint32_t x, sy, dy; + uint32_t bpp, pitch, copybytes; + off_t off; + uint8_t *source, *destination; + uint8_t rm, rp, gm, gp, bm, bp; + bool bgra; + + if (BltBuffer == NULL) + return (EINVAL); - width = ma->e_col - ma->s_col + 1; - height = ma->e_row - ma->s_row + 1; + if (DestinationY + Height > + gfx_fb.framebuffer_common.framebuffer_height) + return (EINVAL); - (void) gop->Blt(gop, NULL, EfiBltVideoToVideo, ma->s_col, ma->s_row, - ma->t_col, ma->t_row, width, height, 0); + if (DestinationX + Width > gfx_fb.framebuffer_common.framebuffer_width) + return (EINVAL); + + if (Width == 0 || Height == 0) + return (EINVAL); + + if (Delta == 0) + Delta = Width * sizeof (*p); + + bpp = roundup2(gfx_fb.framebuffer_common.framebuffer_bpp, 8) >> 3; + pitch = gfx_fb.framebuffer_common.framebuffer_pitch; + + copybytes = Width * bpp; + + rm = (1 << gfx_fb.u.fb2.framebuffer_red_mask_size) - 1; + rp = gfx_fb.u.fb2.framebuffer_red_field_position; + gm = (1 << gfx_fb.u.fb2.framebuffer_green_mask_size) - 1; + gp = gfx_fb.u.fb2.framebuffer_green_field_position; + bm = (1 << gfx_fb.u.fb2.framebuffer_blue_mask_size) - 1; + bp = gfx_fb.u.fb2.framebuffer_blue_field_position; + /* If FB pixel format is BGRA, we can use direct copy. */ + bgra = bpp == 4 && + gfx_fb.u.fb2.framebuffer_red_mask_size == 8 && + gfx_fb.u.fb2.framebuffer_red_field_position == 16 && + gfx_fb.u.fb2.framebuffer_green_mask_size == 8 && + gfx_fb.u.fb2.framebuffer_green_field_position == 8 && + gfx_fb.u.fb2.framebuffer_blue_mask_size == 8 && + gfx_fb.u.fb2.framebuffer_blue_field_position == 0; + + for (sy = SourceY, dy = DestinationY; sy < Height + SourceY; + sy++, dy++) { + off = dy * pitch + DestinationX * bpp; + destination = gfx_get_fb_address() + off; + + if (bgra) { + source = (uint8_t *)BltBuffer + sy * Delta + + SourceX * sizeof (*p); + bcopy(source, destination, copybytes); + } else { + for (x = 0; x < Width; x++) { + uint32_t c; + + p = (void *)((uint8_t *)BltBuffer + + sy * Delta + + (SourceX + x) * sizeof (*p)); + if (bpp == 1) { + c = rgb_to_color_index(p->Red, + p->Green, p->Blue); + } else { + c = (p->Red & rm) << rp | + (p->Green & gm) << gp | + (p->Blue & bm) << bp; + } + off = x * bpp; + switch (bpp) { + case 1: + gfx_mem_wr1(destination, copybytes, + off, (c < NCOLORS) ? + solaris_color_to_pc_color[c] : c); + break; + case 2: + gfx_mem_wr2(destination, copybytes, + off, c); + break; + case 3: + gfx_mem_wr1(destination, copybytes, + off, (c >> 16) & 0xff); + gfx_mem_wr1(destination, copybytes, + off + 1, (c >> 8) & 0xff); + gfx_mem_wr1(destination, copybytes, + off + 2, c & 0xff); + break; + case 4: + gfx_mem_wr4(destination, copybytes, + off, c); + break; + default: + return (EINVAL); + } + } + } + } + + return (0); } -#endif -static void -gfx_bm_cons_copy(struct vis_conscopy *ma) +static int +gfxfb_blt_video_to_video(uint32_t SourceX, uint32_t SourceY, + uint32_t DestinationX, uint32_t DestinationY, + uint32_t Width, uint32_t Height) { - uint32_t soffset, toffset; - uint32_t width, height; - uint8_t *src, *dst, *fb; - uint32_t bpp, pitch; + uint32_t bpp, copybytes; + int pitch; + uint8_t *source, *destination; + off_t off; + + if (SourceY + Height > + gfx_fb.framebuffer_common.framebuffer_height) + return (EINVAL); + + if (SourceX + Width > gfx_fb.framebuffer_common.framebuffer_width) + return (EINVAL); + + if (DestinationY + Height > + gfx_fb.framebuffer_common.framebuffer_height) + return (EINVAL); + + if (DestinationX + Width > gfx_fb.framebuffer_common.framebuffer_width) + return (EINVAL); + + if (Width == 0 || Height == 0) + return (EINVAL); - fb = gfx_get_fb_address(); bpp = roundup2(gfx_fb.framebuffer_common.framebuffer_bpp, 8) >> 3; pitch = gfx_fb.framebuffer_common.framebuffer_pitch; - soffset = ma->s_col * bpp + ma->s_row * pitch; - toffset = ma->t_col * bpp + ma->t_row * pitch; - src = fb + soffset; - dst = fb + toffset; - width = (ma->e_col - ma->s_col + 1) * bpp; - height = ma->e_row - ma->s_row + 1; + copybytes = Width * bpp; - if (toffset <= soffset) { - for (uint32_t i = 0; i < height; i++) { - uint32_t increment = i * pitch; - (void) memmove(dst + increment, src + increment, width); + off = SourceY * pitch + SourceX * bpp; + source = gfx_get_fb_address() + off; + off = DestinationY * pitch + DestinationX * bpp; + destination = gfx_get_fb_address() + off; + + /* + * To handle overlapping areas, set up reverse copy here. + */ + if ((uintptr_t)destination > (uintptr_t)source) { + source += Height * pitch; + destination += Height * pitch; + pitch = -pitch; + } + + while (Height-- > 0) { + bcopy(source, destination, copybytes); + source += pitch; + destination += pitch; + } + + return (0); +} + +int +gfxfb_blt(void *BltBuffer, GFXFB_BLT_OPERATION BltOperation, + uint32_t SourceX, uint32_t SourceY, + uint32_t DestinationX, uint32_t DestinationY, + uint32_t Width, uint32_t Height, uint32_t Delta) +{ + int rv; +#if defined(EFI) + EFI_STATUS status; + extern EFI_GRAPHICS_OUTPUT *gop; + + /* + * We assume Blt() does work, if not, we will need to build + * exception list case by case. + */ + if (gop != NULL) { + switch (BltOperation) { + case GfxFbBltVideoFill: + status = gop->Blt(gop, BltBuffer, EfiBltVideoFill, + SourceX, SourceY, DestinationX, DestinationY, + Width, Height, Delta); + break; + + case GfxFbBltVideoToBltBuffer: + status = gop->Blt(gop, BltBuffer, + EfiBltVideoToBltBuffer, + SourceX, SourceY, DestinationX, DestinationY, + Width, Height, Delta); + break; + + case GfxFbBltBufferToVideo: + status = gop->Blt(gop, BltBuffer, EfiBltBufferToVideo, + SourceX, SourceY, DestinationX, DestinationY, + Width, Height, Delta); + break; + + case GfxFbBltVideoToVideo: + status = gop->Blt(gop, BltBuffer, EfiBltVideoToVideo, + SourceX, SourceY, DestinationX, DestinationY, + Width, Height, Delta); + break; + + default: + status = EFI_INVALID_PARAMETER; + break; } - } else { - for (int i = height - 1; i >= 0; i--) { - uint32_t increment = i * pitch; - (void) memmove(dst + increment, src + increment, width); + + switch (status) { + case EFI_SUCCESS: + rv = 0; + break; + + case EFI_INVALID_PARAMETER: + rv = EINVAL; + break; + + case EFI_DEVICE_ERROR: + default: + rv = EIO; + break; } + + return (rv); } +#endif + + switch (BltOperation) { + case GfxFbBltVideoFill: + rv = gfxfb_blt_fill(BltBuffer, DestinationX, DestinationY, + Width, Height); + break; + + case GfxFbBltVideoToBltBuffer: + rv = gfxfb_blt_video_to_buffer(BltBuffer, SourceX, SourceY, + DestinationX, DestinationY, Width, Height, Delta); + break; + + case GfxFbBltBufferToVideo: + rv = gfxfb_blt_buffer_to_video(BltBuffer, SourceX, SourceY, + DestinationX, DestinationY, Width, Height, Delta); + break; + + case GfxFbBltVideoToVideo: + rv = gfxfb_blt_video_to_video(SourceX, SourceY, + DestinationX, DestinationY, Width, Height); + break; + + default: + rv = EINVAL; + break; + } + return (rv); } -static void +/* + * visual io callbacks. + */ +int +gfx_fb_cons_clear(struct vis_consclear *ca) +{ + int rv; + uint32_t data, width, height; +#if defined(EFI) + EFI_TPL tpl; +#endif + + data = gfx_fb_color_map(ca->bg_color); + width = gfx_fb.framebuffer_common.framebuffer_width; + height = gfx_fb.framebuffer_common.framebuffer_height; + +#if defined(EFI) + tpl = BS->RaiseTPL(TPL_NOTIFY); +#endif + rv = gfxfb_blt(&data, GfxFbBltVideoFill, 0, 0, + 0, 0, width, height, 0); +#if defined(EFI) + BS->RestoreTPL(tpl); +#endif + + return (rv); +} + +void gfx_fb_cons_copy(struct vis_conscopy *ma) { -#if defined(EFI) + uint32_t width, height; +#if defined(EFI) EFI_TPL tpl; tpl = BS->RaiseTPL(TPL_NOTIFY); #endif - gfx_fb_ops.gfx_cons_copy(ma); -#if defined(EFI) + width = ma->e_col - ma->s_col + 1; + height = ma->e_row - ma->s_row + 1; + + (void) gfxfb_blt(NULL, GfxFbBltVideoToVideo, ma->s_col, ma->s_row, + ma->t_col, ma->t_row, width, height, 0); +#if defined(EFI) BS->RestoreTPL(tpl); #endif } @@ -600,103 +1026,57 @@ alpha_blend(uint8_t fg, uint8_t bg, uint8_t alpha) /* Copy memory to framebuffer or to memory. */ static void -bitmap_cpy(uint8_t *dst, uint8_t *src, uint32_t len, int bpp) +bitmap_cpy(void *dst, void *src, size_t size) { +#if defined(EFI) + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *ps, *pd; +#else + struct paletteentry *ps, *pd; +#endif uint32_t i; uint8_t a; - switch (bpp) { - case 4: - /* - * we only implement alpha blending for depth 32, - * use memcpy for other cases. - */ - for (i = 0; i < len; i += bpp) { - a = src[i+3]; - dst[i] = alpha_blend(src[i], dst[i], a); - dst[i+1] = alpha_blend(src[i+1], dst[i+1], a); - dst[i+2] = alpha_blend(src[i+2], dst[i+2], a); - dst[i+3] = a; - } - break; - default: - (void) memcpy(dst, src, len); - break; - } -} - -#if defined(EFI) -static void -gfx_gop_cons_display(struct vis_consdisplay *da) -{ - EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer; - uint32_t size; - int bpp; - extern EFI_GRAPHICS_OUTPUT *gop; - - bpp = roundup2(gfx_fb.framebuffer_common.framebuffer_bpp, 8) >> 3; - size = sizeof (*BltBuffer) * da->width * da->height; + ps = src; + pd = dst; /* - * Common data to display is glyph, use preallocated - * glyph buffer. + * we only implement alpha blending for depth 32. */ - if (size == GlyphBufferSize) { - BltBuffer = GlyphBuffer; - } else { - BltBuffer = malloc(size); + for (i = 0; i < size; i++) { + a = ps[i].Reserved; + pd[i].Red = alpha_blend(ps[i].Red, pd[i].Red, a); + pd[i].Green = alpha_blend(ps[i].Green, pd[i].Green, a); + pd[i].Blue = alpha_blend(ps[i].Blue, pd[i].Blue, a); + pd[i].Reserved = a; } - 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; - } - - (void) gop->Blt(gop, BltBuffer, EfiBltVideoToBltBuffer, - da->col, da->row, 0, 0, da->width, da->height, 0); - 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); - - if (BltBuffer != GlyphBuffer) - free(BltBuffer); } -#endif -static void -gfx_bm_cons_display(struct vis_consdisplay *da) +static void * +allocate_glyphbuffer(uint32_t width, uint32_t height) { - uint32_t size; /* write size per scanline */ - uint8_t *fbp; /* fb + calculated offset */ - int i, bpp, pitch; - - bpp = roundup2(gfx_fb.framebuffer_common.framebuffer_bpp, 8) >> 3; - pitch = gfx_fb.framebuffer_common.framebuffer_pitch; - - size = da->width * bpp; - fbp = gfx_get_fb_address(); - fbp += da->col * bpp + da->row * pitch; + size_t size; - /* write all scanlines in rectangle */ - for (i = 0; i < da->height; i++) { - uint8_t *dest = fbp + i * pitch; - uint8_t *src = da->data + i * size; - bitmap_cpy(dest, src, size, bpp); + size = sizeof (*GlyphBuffer) * width * height; + if (size != GlyphBufferSize) { + free(GlyphBuffer); + GlyphBuffer = malloc(size); + if (GlyphBuffer == NULL) + return (NULL); + GlyphBufferSize = size; } + return (GlyphBuffer); } -static void +void gfx_fb_cons_display(struct vis_consdisplay *da) { -#if defined(EFI) +#if defined(EFI) + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer; EFI_TPL tpl; +#else + struct paletteentry *BltBuffer; #endif + uint32_t size; /* make sure we will not write past FB */ if ((uint32_t)da->col >= gfx_fb.framebuffer_common.framebuffer_width || @@ -707,74 +1087,51 @@ gfx_fb_cons_display(struct vis_consdisplay *da) gfx_fb.framebuffer_common.framebuffer_height) return; -#if defined(EFI) - tpl = BS->RaiseTPL(TPL_NOTIFY); -#endif - gfx_fb_ops.gfx_cons_display(da); -#if defined(EFI) - BS->RestoreTPL(tpl); -#endif -} + size = sizeof (*BltBuffer) * da->width * da->height; -void -gfx_fb_display_cursor(struct vis_conscursor *ca) -{ -#if defined(EFI) - EFI_TPL tpl; + /* + * Common data to display is glyph, use preallocated + * glyph buffer. + */ + if (tems.ts_pix_data_size != GlyphBufferSize) + (void) allocate_glyphbuffer(da->width, da->height); + + if (size == GlyphBufferSize) { + BltBuffer = GlyphBuffer; + } else { + BltBuffer = malloc(size); + } + if (BltBuffer == NULL) + return; +#if defined(EFI) tpl = BS->RaiseTPL(TPL_NOTIFY); #endif - gfx_fb_ops.gfx_cons_display_cursor(ca); -#if defined(EFI) + if (gfxfb_blt(BltBuffer, GfxFbBltVideoToBltBuffer, + da->col, da->row, 0, 0, da->width, da->height, 0) == 0) { + bitmap_cpy(BltBuffer, da->data, da->width * da->height); + (void) gfxfb_blt(BltBuffer, GfxFbBltBufferToVideo, + 0, 0, da->col, da->row, da->width, da->height, 0); + } + +#if defined(EFI) BS->RestoreTPL(tpl); #endif + if (BltBuffer != GlyphBuffer) + free(BltBuffer); } -#if defined(EFI) static void -gfx_gop_display_cursor(struct vis_conscursor *ca) +gfx_fb_cursor_impl(uint32_t fg, uint32_t bg, struct vis_conscursor *ca) { union pixel { +#if defined(EFI) EFI_GRAPHICS_OUTPUT_BLT_PIXEL p; +#else + struct paletteentry p; +#endif 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]; + } *row; /* * Build inverse image of the glyph. @@ -784,94 +1141,49 @@ gfx_gop_display_cursor(struct vis_conscursor *ca) 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; + row[j].p32 = (row[j].p32 ^ fg) ^ bg; } } - - (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) +void +gfx_fb_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; + union pixel { +#if defined(EFI) + EFI_GRAPHICS_OUTPUT_BLT_PIXEL p; +#else + struct paletteentry p; +#endif + uint32_t p32; + } fg, bg; +#if defined(EFI) + EFI_TPL tpl; - fb = gfx_get_fb_address(); - bpp = roundup2(gfx_fb.framebuffer_common.framebuffer_bpp, 8) >> 3; - pitch = gfx_fb.framebuffer_common.framebuffer_pitch; + tpl = BS->RaiseTPL(TPL_NOTIFY); +#endif + + 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]; - size = ca->width * bpp; + if (allocate_glyphbuffer(ca->width, ca->height) != NULL) { + if (gfxfb_blt(GlyphBuffer, GfxFbBltVideoToBltBuffer, + ca->col, ca->row, 0, 0, ca->width, ca->height, 0) == 0) + gfx_fb_cursor_impl(fg.p32, bg.p32, ca); - /* - * Build cursor image. We are building mirror image of data on - * frame buffer by (D xor FG) xor BG. - */ - offset = ca->col * bpp + ca->row * pitch; - switch (gfx_fb.framebuffer_common.framebuffer_bpp) { - case 8: /* 8 bit */ - fg = ca->fg_color.mono; - bg = ca->bg_color.mono; - for (int i = 0; i < ca->height; i++) { - fb8 = fb + offset + i * pitch; - for (uint32_t j = 0; j < size; j += 1) { - fb8[j] = (fb8[j] ^ (fg & 0xff)) ^ (bg & 0xff); - } - } - break; - case 15: - case 16: /* 16 bit */ - fg = ca->fg_color.sixteen[0] << 8; - fg |= ca->fg_color.sixteen[1]; - bg = ca->bg_color.sixteen[0] << 8; - bg |= ca->bg_color.sixteen[1]; - for (int i = 0; i < ca->height; i++) { - fb16 = (uint16_t *)(fb + offset + i * pitch); - for (int j = 0; j < ca->width; j++) { - fb16[j] = (fb16[j] ^ (fg & 0xffff)) ^ - (bg & 0xffff); - } - } - break; - case 24: /* 24 bit */ - fg = ca->fg_color.twentyfour[0] << 16; - fg |= ca->fg_color.twentyfour[1] << 8; - fg |= ca->fg_color.twentyfour[2]; - bg = ca->bg_color.twentyfour[0] << 16; - bg |= ca->bg_color.twentyfour[1] << 8; - bg |= ca->bg_color.twentyfour[2]; - - for (int i = 0; i < ca->height; i++) { - fb8 = fb + offset + i * pitch; - for (uint32_t j = 0; j < size; j += 3) { - fb8[j] = (fb8[j] ^ ((fg >> 16) & 0xff)) ^ - ((bg >> 16) & 0xff); - fb8[j+1] = (fb8[j+1] ^ ((fg >> 8) & 0xff)) ^ - ((bg >> 8) & 0xff); - fb8[j+2] = (fb8[j+2] ^ (fg & 0xff)) ^ - (bg & 0xff); - } - } - break; - case 32: /* 32 bit */ - fg = ca->fg_color.twentyfour[0] << 16; - fg |= ca->fg_color.twentyfour[1] << 8; - fg |= ca->fg_color.twentyfour[2]; - bg = ca->bg_color.twentyfour[0] << 16; - bg |= ca->bg_color.twentyfour[1] << 8; - bg |= ca->bg_color.twentyfour[2]; - for (int i = 0; i < ca->height; i++) { - fb32 = (uint32_t *)(fb + offset + i * pitch); - for (int j = 0; j < ca->width; j++) - fb32[j] = (fb32[j] ^ fg) ^ bg; - } - break; + (void) gfxfb_blt(GlyphBuffer, GfxFbBltBufferToVideo, 0, 0, + ca->col, ca->row, ca->width, ca->height, 0); } + +#if defined(EFI) + BS->RestoreTPL(tpl); +#endif } /* @@ -903,13 +1215,8 @@ isqrt(int num) void gfx_fb_setpixel(uint32_t x, uint32_t y) { - uint32_t c, offset, pitch, bpp; - uint8_t *fb; + uint32_t c; 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; @@ -921,38 +1228,7 @@ gfx_fb_setpixel(uint32_t x, uint32_t y) y >= gfx_fb.framebuffer_common.framebuffer_height) return; - fb = gfx_get_fb_address(); - pitch = gfx_fb.framebuffer_common.framebuffer_pitch; - bpp = roundup2(gfx_fb.framebuffer_common.framebuffer_bpp, 8) >> 3; - - offset = y * pitch + x * bpp; - switch (gfx_fb.framebuffer_common.framebuffer_bpp) { - case 8: - fb[offset] = c & 0xff; - break; - case 15: - case 16: - *(uint16_t *)(fb + offset) = c & 0xffff; - break; - case 24: - fb[offset] = (c >> 16) & 0xff; - fb[offset + 1] = (c >> 8) & 0xff; - 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; - } + gfxfb_blt(&c, GfxFbBltVideoFill, 0, 0, x, y, 1, 1, 0); } /* @@ -1203,9 +1479,13 @@ int gfx_fb_putimage(png_t *png, uint32_t ux1, uint32_t uy1, uint32_t ux2, uint32_t uy2, uint32_t flags) { +#if defined(EFI) + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *p; +#else + struct paletteentry *p; +#endif struct vis_consdisplay da; - uint32_t i, j, x, y, fheight, fwidth, color; - int fbpp; + uint32_t i, j, x, y, fheight, fwidth; uint8_t r, g, b, a; bool scale = false; bool trace = false; @@ -1333,9 +1613,8 @@ gfx_fb_putimage(png_t *png, uint32_t ux1, uint32_t uy1, uint32_t ux2, if ((flags & FL_PUTIMAGE_BORDER)) gfx_fb_drawrect(ux1, uy1, ux2, uy2, 0); - fbpp = roundup2(gfx_fb.framebuffer_common.framebuffer_bpp, 8) >> 3; - - da.data = malloc(fwidth * fheight * fbpp); + da.data = malloc(fwidth * fheight * sizeof (*p)); + p = (void *)da.data; if (da.data == NULL) { if (trace) printf("Out of memory.\n"); @@ -1375,7 +1654,7 @@ gfx_fb_putimage(png_t *png, uint32_t ux1, uint32_t uy1, uint32_t ux2, uint32_t offset_x1 = offset_x + 1; /* Target pixel index */ - j = (y * fwidth + x) * fbpp; + j = y * fwidth + x; if (!scale) { i = GETPIXEL(x, y); @@ -1425,88 +1704,19 @@ gfx_fb_putimage(png_t *png, uint32_t ux1, uint32_t uy1, uint32_t ux2, a = pixel[3]; } - color = - r >> (8 - gfx_fb.u.fb2.framebuffer_red_mask_size) - << gfx_fb.u.fb2.framebuffer_red_field_position | - g >> (8 - gfx_fb.u.fb2.framebuffer_green_mask_size) - << gfx_fb.u.fb2.framebuffer_green_field_position | - b >> (8 - gfx_fb.u.fb2.framebuffer_blue_mask_size) - << gfx_fb.u.fb2.framebuffer_blue_field_position; - - switch (gfx_fb.framebuffer_common.framebuffer_bpp) { -#if !defined(EFI) - case 8: { - uint32_t best, dist, k; - int diff; - - /* if alpha is 0, use screen bg color */ - if (a == 0) { - text_color_t fg, bg; - - tem_get_colors( - (tem_vt_state_t)tems.ts_active, - &fg, &bg); - da.data[j] = gfx_fb_color_map(bg); - break; - } + if (trace) + printf("r/g/b: %x/%x/%x\n", r, g, b); + /* + * Rough colorspace reduction for 15/16 bit colors. + */ + p[j].Red = r >> + (8 - gfx_fb.u.fb2.framebuffer_red_mask_size); + p[j].Green = g >> + (8 - gfx_fb.u.fb2.framebuffer_green_mask_size); + p[j].Blue = b >> + (8 - gfx_fb.u.fb2.framebuffer_blue_mask_size); + p[j].Reserved = a; - color = 0; - best = CMAP_SIZE * CMAP_SIZE * CMAP_SIZE; - for (k = 0; k < CMAP_SIZE; k++) { - diff = r - pe8[k].Red; - dist = diff * diff; - diff = g - pe8[k].Green; - dist += diff * diff; - diff = b - pe8[k].Blue; - dist += diff * diff; - - if (dist == 0) - break; - - if (dist < best) { - color = k; - best = dist; - } - } - if (k == CMAP_SIZE) - k = color; - da.data[j] = (k < 16) ? - solaris_color_to_pc_color[k] : k; - break; - } - case 15: - case 16: - /* if alpha is 0, use screen bg color */ - if (a == 0) { - text_color_t fg, bg; - - tem_get_colors( - (tem_vt_state_t)tems.ts_active, - &fg, &bg); - color = gfx_fb_color_map(bg); - } - *(uint16_t *)(da.data+j) = color; - break; - case 24: - /* if alpha is 0, use screen bg color */ - if (a == 0) { - text_color_t fg, bg; - - tem_get_colors( - (tem_vt_state_t)tems.ts_active, - &fg, &bg); - color = gfx_fb_color_map(bg); - } - da.data[j] = ((uint8_t *)&color)[0]; - da.data[j + 1] = ((uint8_t *)&color)[1]; - da.data[j + 2] = ((uint8_t *)&color)[2]; - break; -#endif - case 32: - color |= a << 24; - *(uint32_t *)(da.data+j) = color; - break; - } wc += wcstep; } hc += hcstep; diff --git a/usr/src/boot/sys/boot/common/gfx_fb.h b/usr/src/boot/sys/boot/common/gfx_fb.h index 04bbd91121..3fb7fcc3af 100644 --- a/usr/src/boot/sys/boot/common/gfx_fb.h +++ b/usr/src/boot/sys/boot/common/gfx_fb.h @@ -133,10 +133,24 @@ typedef TAILQ_HEAD(edid_resolution, resolution) edid_res_list_t; extern multiboot_tag_framebuffer_t gfx_fb; +typedef enum { + GfxFbBltVideoFill, + GfxFbBltVideoToBltBuffer, + GfxFbBltBufferToVideo, + GfxFbBltVideoToVideo, + GfxFbBltOperationMax, +} GFXFB_BLT_OPERATION; + +int gfxfb_blt(void *, GFXFB_BLT_OPERATION, uint32_t, uint32_t, + uint32_t, uint32_t, uint32_t, uint32_t, uint32_t); + void bios_text_font(bool); bool gfx_get_edid_resolution(struct vesa_edid_info *, edid_res_list_t *); -void gfx_framework_init(struct visual_ops *); +void gfx_framework_init(void); uint32_t gfx_fb_color_map(uint8_t); +int gfx_fb_cons_clear(struct vis_consclear *); +void gfx_fb_cons_copy(struct vis_conscopy *); +void gfx_fb_cons_display(struct vis_consdisplay *); void gfx_fb_display_cursor(struct vis_conscursor *); void gfx_fb_setpixel(uint32_t, uint32_t); void gfx_fb_drawrect(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t); diff --git a/usr/src/boot/sys/boot/common/tem.c b/usr/src/boot/sys/boot/common/tem.c index 561be4e28d..ebb3ae48f8 100644 --- a/usr/src/boot/sys/boot/common/tem.c +++ b/usr/src/boot/sys/boot/common/tem.c @@ -143,14 +143,6 @@ static void tem_pix_cls_range(struct tem_vt_state *, screen_pos_t, int, static void tem_pix_cls(struct tem_vt_state *, int, screen_pos_t, screen_pos_t); -static void bit_to_pix4(struct tem_vt_state *tem, tem_char_t c, - text_color_t fg_color, text_color_t bg_color); -static void bit_to_pix8(struct tem_vt_state *tem, tem_char_t c, - text_color_t fg_color, text_color_t bg_color); -static void bit_to_pix16(struct tem_vt_state *tem, tem_char_t c, - text_color_t fg_color, text_color_t bg_color); -static void bit_to_pix24(struct tem_vt_state *tem, tem_char_t c, - text_color_t fg_color, text_color_t bg_color); static void bit_to_pix32(struct tem_vt_state *tem, tem_char_t c, text_color_t fg_color, text_color_t bg_color); @@ -2291,35 +2283,12 @@ static void tem_pix_bit2pix(struct tem_vt_state *tem, term_char_t c) { text_color_t fg, bg; - void (*fp)(struct tem_vt_state *, tem_char_t, - unsigned char, unsigned char); fg = DEFAULT_ANSI_FOREGROUND; bg = DEFAULT_ANSI_BACKGROUND; tem_get_color(&fg, &bg, c); - switch (tems.ts_pdepth) { - case 4: - fp = bit_to_pix4; - break; - case 8: - fp = bit_to_pix8; - break; - case 15: - case 16: - fp = bit_to_pix16; - break; - case 24: - fp = bit_to_pix24; - break; - case 32: - fp = bit_to_pix32; - break; - default: - return; - } - - fp(tem, c.tc_char, fg, bg); + bit_to_pix32(tem, c.tc_char, fg, bg); } @@ -2657,36 +2626,14 @@ tem_pix_cursor(struct tem_vt_state *tem, short action) bg = DEFAULT_ANSI_BACKGROUND; tem_get_color(&fg, &bg, c); - switch (tems.ts_pdepth) { - case 4: - ca.fg_color.mono = fg; - ca.bg_color.mono = bg; - break; - case 8: - ca.fg_color.mono = tems.ts_color_map(fg); - ca.bg_color.mono = tems.ts_color_map(bg); - break; - case 15: - case 16: - color = tems.ts_color_map(fg); - ca.fg_color.sixteen[0] = (color >> 8) & 0xFF; - ca.fg_color.sixteen[1] = color & 0xFF; - color = tems.ts_color_map(bg); - ca.bg_color.sixteen[0] = (color >> 8) & 0xFF; - ca.bg_color.sixteen[1] = color & 0xFF; - break; - case 24: - case 32: - color = tems.ts_color_map(fg); - ca.fg_color.twentyfour[0] = (color >> 16) & 0xFF; - ca.fg_color.twentyfour[1] = (color >> 8) & 0xFF; - ca.fg_color.twentyfour[2] = color & 0xFF; - color = tems.ts_color_map(bg); - ca.bg_color.twentyfour[0] = (color >> 16) & 0xFF; - ca.bg_color.twentyfour[1] = (color >> 8) & 0xFF; - ca.bg_color.twentyfour[2] = color & 0xFF; - break; - } + color = tems.ts_color_map(fg); + ca.fg_color.twentyfour[0] = (color >> 16) & 0xFF; + ca.fg_color.twentyfour[1] = (color >> 8) & 0xFF; + ca.fg_color.twentyfour[2] = color & 0xFF; + color = tems.ts_color_map(bg); + ca.bg_color.twentyfour[0] = (color >> 16) & 0xFF; + ca.bg_color.twentyfour[1] = (color >> 8) & 0xFF; + ca.bg_color.twentyfour[2] = color & 0xFF; ca.action = action; @@ -2708,61 +2655,6 @@ tem_pix_cursor(struct tem_vt_state *tem, short action) } static void -bit_to_pix4(struct tem_vt_state *tem, - tem_char_t c, - text_color_t fg_color, - text_color_t bg_color) -{ - uint8_t *dest = (uint8_t *)tem->tvs_pix_data; - font_bit_to_pix4(&tems.ts_font, dest, c, fg_color, bg_color); -} - -static void -bit_to_pix8(struct tem_vt_state *tem, - tem_char_t c, - text_color_t fg_color, - text_color_t bg_color) -{ - uint8_t *dest = (uint8_t *)tem->tvs_pix_data; - - fg_color = (text_color_t)tems.ts_color_map(fg_color); - bg_color = (text_color_t)tems.ts_color_map(bg_color); - font_bit_to_pix8(&tems.ts_font, dest, c, fg_color, bg_color); -} - -static void -bit_to_pix16(struct tem_vt_state *tem, - tem_char_t c, - text_color_t fg_color4, - text_color_t bg_color4) -{ - uint16_t fg_color16, bg_color16; - uint16_t *dest; - - fg_color16 = (uint16_t)tems.ts_color_map(fg_color4); - bg_color16 = (uint16_t)tems.ts_color_map(bg_color4); - - dest = (uint16_t *)tem->tvs_pix_data; - font_bit_to_pix16(&tems.ts_font, dest, c, fg_color16, bg_color16); -} - -static void -bit_to_pix24(struct tem_vt_state *tem, - tem_char_t c, - text_color_t fg_color4, - text_color_t bg_color4) -{ - uint32_t fg_color32, bg_color32; - uint8_t *dest; - - fg_color32 = tems.ts_color_map(fg_color4); - bg_color32 = tems.ts_color_map(bg_color4); - - dest = (uint8_t *)tem->tvs_pix_data; - font_bit_to_pix24(&tems.ts_font, dest, c, fg_color32, bg_color32); -} - -static void bit_to_pix32(struct tem_vt_state *tem, tem_char_t c, text_color_t fg_color4, diff --git a/usr/src/boot/sys/boot/efi/libefi/efi_console.c b/usr/src/boot/sys/boot/efi/libefi/efi_console.c index 37d07a8802..13c2ad0635 100644 --- a/usr/src/boot/sys/boot/efi/libefi/efi_console.c +++ b/usr/src/boot/sys/boot/efi/libefi/efi_console.c @@ -124,10 +124,10 @@ struct visual_ops fb_ops = { .ident = &fb_ident, .kdsetmode = NULL, .devinit = efi_fb_devinit, - .cons_copy = NULL, - .cons_display = NULL, + .cons_copy = gfx_fb_cons_copy, + .cons_display = gfx_fb_cons_display, .cons_cursor = efi_cons_cursor, - .cons_clear = NULL, + .cons_clear = gfx_fb_cons_clear, .cons_put_cmap = NULL }; @@ -539,7 +539,7 @@ efi_cons_init(struct console *cp, int arg __unused) if (status == EFI_SUCCESS) ecd->ecd_coninex = coninex; - gfx_framework_init(&fb_ops); + gfx_framework_init(); if (tem_info_init(cp) == 0 && tem == NULL) { tem = tem_init(); diff --git a/usr/src/boot/sys/boot/i386/libi386/vbe.c b/usr/src/boot/sys/boot/i386/libi386/vbe.c index c660367bdf..4f98cdf747 100644 --- a/usr/src/boot/sys/boot/i386/libi386/vbe.c +++ b/usr/src/boot/sys/boot/i386/libi386/vbe.c @@ -333,7 +333,7 @@ vbe_set_palette(const struct paletteentry *entry, size_t slot) pe.Blue = entry->Blue; pe.Green = entry->Green; pe.Red = entry->Red; - pe.Alignment = entry->Alignment; + pe.Reserved = entry->Reserved; if (vbe->Capabilities & VBE_CAP_SNOW) mode = 0x80; diff --git a/usr/src/boot/sys/boot/i386/libi386/vbe.h b/usr/src/boot/sys/boot/i386/libi386/vbe.h index c775b13012..e049af1e42 100644 --- a/usr/src/boot/sys/boot/i386/libi386/vbe.h +++ b/usr/src/boot/sys/boot/i386/libi386/vbe.h @@ -111,7 +111,7 @@ struct paletteentry { uint8_t Blue; uint8_t Green; uint8_t Red; - uint8_t Alignment; + uint8_t Reserved; } __packed; struct flatpanelinfo diff --git a/usr/src/boot/sys/boot/i386/libi386/vidconsole.c b/usr/src/boot/sys/boot/i386/libi386/vidconsole.c index 9dff446903..dbdbcbc699 100644 --- a/usr/src/boot/sys/boot/i386/libi386/vidconsole.c +++ b/usr/src/boot/sys/boot/i386/libi386/vidconsole.c @@ -108,10 +108,10 @@ struct visual_ops fb_ops = { .ident = &fb_ident, .kdsetmode = NULL, .devinit = vidc_vbe_devinit, - .cons_copy = NULL, - .cons_display = NULL, + .cons_copy = gfx_fb_cons_copy, + .cons_display = gfx_fb_cons_display, .cons_cursor = vidc_cons_cursor, - .cons_clear = NULL, + .cons_clear = gfx_fb_cons_clear, .cons_put_cmap = vidc_vbe_cons_put_cmap }; @@ -570,24 +570,24 @@ vidc_vbe_cons_put_cmap(struct vis_cmap *cm) rgb.blue.pos = gfx_fb.u.fb2.framebuffer_blue_field_position; rgb.blue.size = gfx_fb.u.fb2.framebuffer_blue_mask_size; - /* - * The first 16 colors need to be in VGA color order. - */ - for (i = cm->index; i < 256 && rc == 0; i++) { - if (i < 16) { - if (i < 15) - c = rgb_color_map(&rgb, i + 1); - else - c = rgb_color_map(&rgb, 0); - } else { - c = rgb_color_map(&rgb, i); - } + for (i = cm->index; i < NCMAP && rc == 0; i++) { + int idx; + + /* Pick RGB from cmap4_to_24 */ + c = rgb_color_map(&rgb, i); + /* The first 16 colors need to be in VGA color order. */ + if (i < NCOLORS) + idx = solaris_color_to_pc_color[i]; + else + idx = i; + pe8[i].Red = (c >> rgb.red.pos) & ((1 << rgb.red.size) - 1); pe8[i].Green = (c >> rgb.green.pos) & ((1 << rgb.green.size) - 1); - pe8[i].Blue = (c >> rgb.blue.pos) & ((1 << rgb.blue.size) - 1); - pe8[i].Alignment = 0; - rc = vbe_set_palette(&pe8[i], i); + pe8[i].Blue = + (c >> rgb.blue.pos) & ((1 << rgb.blue.size) - 1); + pe8[i].Reserved = 0; + rc = vbe_set_palette(&pe8[i], idx); } return (rc); } @@ -869,7 +869,7 @@ vidc_init(struct console *cp, int arg) } } - gfx_framework_init(&fb_ops); + gfx_framework_init(); /* set up callback before calling tem_info_init(). */ tem_register_modechg_cb(vidc_install_font, (tem_modechg_cb_arg_t)cp); rc = tem_info_init(cp); diff --git a/usr/src/boot/sys/sys/tem_impl.h b/usr/src/boot/sys/sys/tem_impl.h index ee0dcbb28f..6764475695 100644 --- a/usr/src/boot/sys/sys/tem_impl.h +++ b/usr/src/boot/sys/sys/tem_impl.h @@ -183,7 +183,7 @@ struct tem_vt_state { term_char_t *tvs_outbuf; /* place to keep incomplete lines */ int tvs_outindex; /* index into a_outbuf */ void *tvs_pix_data; /* pointer to tmp bitmap area */ - int tvs_pix_data_size; + unsigned tvs_pix_data_size; text_color_t tvs_fg_color; text_color_t tvs_bg_color; int tvs_first_line; /* kernel console output begins */ @@ -226,7 +226,7 @@ typedef struct tem_state { struct tem_size ts_p_dimension; /* screen dimensions in pixels */ struct tem_pix_pos ts_p_offset; /* pix offset to center the display */ - int ts_pix_data_size; /* size of bitmap data areas */ + unsigned ts_pix_data_size; /* size of bitmap data areas */ int ts_pdepth; /* pixel depth */ struct font ts_font; /* font table */ bool update_font; /* flag the font change */ diff --git a/usr/src/cmd/svc/svccfg/svccfg_libscf.c b/usr/src/cmd/svc/svccfg/svccfg_libscf.c index 38dd45c75c..629d7817f7 100644 --- a/usr/src/cmd/svc/svccfg/svccfg_libscf.c +++ b/usr/src/cmd/svc/svccfg/svccfg_libscf.c @@ -16470,7 +16470,7 @@ find_add_svc_mfst(const char *svnbuf, const char *mfst) * Create the service to manifest avl tree. * * Walk each of the manifests currently installed in the supported - * directories, /lib/svc/manifests and /var/svc/manifests. For + * directories, /lib/svc/manifest and /var/svc/manifest. For * each of the manifests, inventory the services and add them to * the tree. * diff --git a/usr/src/common/font/font.c b/usr/src/common/font/font.c index 81d5b4ae53..35e2e12eca 100644 --- a/usr/src/common/font/font.c +++ b/usr/src/common/font/font.c @@ -62,7 +62,7 @@ const uint8_t solaris_color_to_pc_color[16] = { pc_magenta, /* 6 - magenta */ pc_brown, /* 7 - brown */ pc_white, /* 8 - white */ - pc_grey, /* 9 - gery */ + pc_grey, /* 9 - grey */ pc_brt_blue, /* 10 - brt_blue */ pc_brt_green, /* 11 - brt_green */ pc_brt_cyan, /* 12 - brt_cyan */ @@ -71,6 +71,25 @@ const uint8_t solaris_color_to_pc_color[16] = { pc_yellow /* 15 - yellow */ }; +const uint8_t pc_color_to_solaris_color[16] = { + sun_black, /* 0 - black */ + sun_blue, /* 1 - blue */ + sun_green, /* 2 - green */ + sun_cyan, /* 3 - cyan */ + sun_red, /* 4 - red */ + sun_magenta, /* 5 - magenta */ + sun_brown, /* 6 - brown */ + sun_white, /* 7 - white */ + sun_grey, /* 8 - grey */ + sun_brt_blue, /* 9 - brt_blue */ + sun_brt_green, /* 10 - brt_green */ + sun_brt_cyan, /* 11 - brt_cyan */ + sun_brt_red, /* 12 - brt_red */ + sun_brt_magenta, /* 13 - brt_magenta */ + sun_yellow, /* 14 - yellow */ + sun_brt_white /* 15 - brt_white */ +}; + /* 4-bit to 24-bit color translation. */ const text_cmap_t cmap4_to_24 = { /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 diff --git a/usr/src/lib/commpage/amd64/cp_subr.s b/usr/src/lib/commpage/amd64/cp_subr.s index 09b8deaf8d..ebae0ed307 100644 --- a/usr/src/lib/commpage/amd64/cp_subr.s +++ b/usr/src/lib/commpage/amd64/cp_subr.s @@ -11,6 +11,7 @@ /* * Copyright 2019 Joyent, Inc. + * Copyright 2020 Oxide Computer Company */ #include <sys/asm_linkage.h> @@ -110,11 +111,11 @@ movl %edx, %r10d 3: - cmpl $TSC_RDTSC_MFENCE, %esi - jne 4f - mfence - rdtsc - jmp 7f + /* + * TSC_RDTSC_MFENCE was used in the past for AMD chips, but has been + * supplanted by TSC_RDTSC_LFENCE, which works on Intel and AMD (when + * lfence can be confirmed as serializing). + */ 4: cmpl $TSC_RDTSC_LFENCE, %esi diff --git a/usr/src/lib/commpage/common/cp_main.c b/usr/src/lib/commpage/common/cp_main.c index 13a9aea3d7..42cc37d6b8 100644 --- a/usr/src/lib/commpage/common/cp_main.c +++ b/usr/src/lib/commpage/common/cp_main.c @@ -25,7 +25,6 @@ __cp_can_gettime(comm_page_t *cp) { switch (cp->cp_tsc_type) { case TSC_TSCP: - case TSC_RDTSC_MFENCE: case TSC_RDTSC_LFENCE: case TSC_RDTSC_CPUID: return (1); diff --git a/usr/src/lib/commpage/i386/cp_subr.s b/usr/src/lib/commpage/i386/cp_subr.s index d1e07008c4..83b7dcff56 100644 --- a/usr/src/lib/commpage/i386/cp_subr.s +++ b/usr/src/lib/commpage/i386/cp_subr.s @@ -11,6 +11,7 @@ /* * Copyright 2019 Joyent, Inc. + * Copyright 2020 Oxide Computer Company */ #include <sys/asm_linkage.h> @@ -88,11 +89,11 @@ movl CP_TSC_TYPE(%edi), %eax 4: - cmpl $TSC_RDTSC_MFENCE, %eax - jne 5f - mfence - rdtsc - jmp 8f + /* + * TSC_RDTSC_MFENCE was used in the past for AMD chips, but has been + * supplanted by TSC_RDTSC_LFENCE, which works on Intel and AMD (when + * lfence can be confirmed as serializing). + */ 5: cmpl $TSC_RDTSC_LFENCE, %eax diff --git a/usr/src/test/test-runner/cmd/run b/usr/src/test/test-runner/cmd/run index 127de5c35e..db3f33a1a8 100644 --- a/usr/src/test/test-runner/cmd/run +++ b/usr/src/test/test-runner/cmd/run @@ -31,6 +31,7 @@ import io import os import logging import platform +import re from logging.handlers import WatchedFileHandler from datetime import datetime from optparse import OptionParser @@ -102,8 +103,8 @@ class Result(object): def done(self, proc, killed): """ Finalize the results of this Cmd. - Report SKIP for return codes 3,4 (NOTINUSE, UNSUPPORTED) - as defined in ../stf/include/stf.shlib + Report SKIP for return codes 3,4 (NOTINUSE, UNSUPPORTED) + as defined in ../stf/include/stf.shlib """ global retcode @@ -468,6 +469,9 @@ class TestGroup(Test): (self.pathname, self.outputdir, self.tests, self.timeout, self.pre, pre_user, self.post, post_user, self.user) + def filter(self, keeplist): + self.tests = [ x for x in self.tests if x in keeplist ] + def verify(self, logger): """ Check the pre/post scripts, user and tests in this TestGroup. Omit @@ -609,6 +613,24 @@ class TestRun(object): testgroup.verify(self.logger) + def filter(self, keeplist): + for group in list(self.testgroups.keys()): + if group not in keeplist: + del self.testgroups[group] + continue + + g = self.testgroups[group] + + if g.pre and os.path.basename(g.pre) in keeplist[group]: + continue + + g.filter(keeplist[group]) + + for test in list(self.tests.keys()): + directory, base = os.path.split(test) + if directory not in keeplist or base not in keeplist[directory]: + del self.tests[test] + def read(self, logger, options): """ Read in the specified runfile, and apply the TestRun properties @@ -620,7 +642,7 @@ class TestRun(object): """ config = configparser.RawConfigParser() if not len(config.read(options.runfile)): - fail("Coulnd't read config file %s" % options.runfile) + fail("Couldn't read config file %s" % options.runfile) for opt in TestRun.props: if config.has_option('DEFAULT', opt): @@ -686,10 +708,18 @@ class TestRun(object): for test in sorted(self.tests.keys()): config.add_section(test) + for prop in Test.props: + if prop not in self.props: + config.set(testgroup, prop, + getattr(self.testgroups[testgroup], prop)) for testgroup in sorted(self.testgroups.keys()): config.add_section(testgroup) config.set(testgroup, 'tests', self.testgroups[testgroup].tests) + for prop in TestGroup.props: + if prop not in self.props: + config.set(testgroup, prop, + getattr(self.testgroups[testgroup], prop)) try: with open(options.template, 'w') as f: @@ -743,7 +773,7 @@ class TestRun(object): testlogger = logging.getLogger(__name__) testlogger.setLevel(logging.DEBUG) - if options.cmd != 'wrconfig': + if not options.template: try: old = os.umask(0) os.makedirs(self.outputdir, mode=0o777) @@ -870,29 +900,45 @@ def find_tests(testrun, options): testrun.addtest(p, options) +def filter_tests(testrun, options): + try: + fh = open(options.logfile, "r") + except Exception as e: + fail('%s' % e) + + failed = {} + while True: + line = fh.readline() + if not line: + break + m = re.match(r'Test: (.*)/(\S+).*\[FAIL\]', line) + if not m: + continue + group, test = m.group(1, 2) + try: + failed[group].append(test) + except KeyError: + failed[group] = [ test ] + fh.close() + + testrun.filter(failed) + + def fail(retstr, ret=1): print('%s: %s' % (argv[0], retstr)) exit(ret) def options_cb(option, opt_str, value, parser): - path_options = ['runfile', 'outputdir', 'template'] - - if option.dest == 'runfile' and '-w' in parser.rargs or \ - option.dest == 'template' and '-c' in parser.rargs: - fail('-c and -w are mutually exclusive.') + path_options = ['runfile', 'outputdir', 'template', 'logfile'] if opt_str in parser.rargs: fail('%s may only be specified once.' % opt_str) - if option.dest == 'runfile': - parser.values.cmd = 'rdconfig' - if option.dest == 'template': - parser.values.cmd = 'wrconfig' - - setattr(parser.values, option.dest, value) if option.dest in path_options: setattr(parser.values, option.dest, os.path.abspath(value)) + else: + setattr(parser.values, option.dest, value) def parse_args(): @@ -902,6 +948,10 @@ def parse_args(): help='Specify tests to run via config file.') parser.add_option('-d', action='store_true', default=False, dest='dryrun', help='Dry run. Print tests, but take no other action.') + parser.add_option('-l', action='callback', callback=options_cb, + default=None, dest='logfile', metavar='logfile', + type='string', + help='Read logfile and re-run tests which failed.') parser.add_option('-g', action='store_true', default=False, dest='do_groups', help='Make directories TestGroups.') parser.add_option('-o', action='callback', callback=options_cb, @@ -932,9 +982,6 @@ def parse_args(): help='Specify a user to execute the post script.') (options, pathnames) = parser.parse_args() - if not options.runfile and not options.template: - options.cmd = 'runtests' - if options.runfile and len(pathnames): fail('Extraneous arguments.') @@ -945,18 +992,20 @@ def parse_args(): def main(): options = parse_args() + testrun = TestRun(options) - if options.cmd == 'runtests': - find_tests(testrun, options) - elif options.cmd == 'rdconfig': + if options.runfile: testrun.read(testrun.logger, options) - elif options.cmd == 'wrconfig': + else: find_tests(testrun, options) + + if options.logfile: + filter_tests(testrun, options) + + if options.template: testrun.write(options) exit(0) - else: - fail('Unknown command specified') testrun.complete_outputdirs() testrun.run(options) diff --git a/usr/src/test/zfs-tests/cmd/scripts/zfstest.ksh b/usr/src/test/zfs-tests/cmd/scripts/zfstest.ksh index e38b5a34a1..4df97de7a5 100644 --- a/usr/src/test/zfs-tests/cmd/scripts/zfstest.ksh +++ b/usr/src/test/zfs-tests/cmd/scripts/zfstest.ksh @@ -16,6 +16,7 @@ # Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved. # Copyright 2016 Nexenta Systems, Inc. # Copyright 2019 Joyent, Inc. +# Copyright 2020 OmniOS Community Edition (OmniOSce) Association. # export PATH="/usr/bin" @@ -147,7 +148,7 @@ constrain_path export PATH=$PATHDIR verify_id -while getopts ac:q c; do +while getopts ac:l:q c; do case $c in 'a') auto_detect=true @@ -156,8 +157,13 @@ while getopts ac:q c; do runfile=$OPTARG [[ -f $runfile ]] || fail "Cannot read file: $runfile" ;; + 'l') + logfile=$OPTARG + [[ -f $logfile ]] || fail "Cannot read file: $logfile" + xargs+=" -l $logfile" + ;; 'q') - quiet='-q' + xargs+=" -q" ;; esac done @@ -192,7 +198,7 @@ num_disks=$(echo $DISKS | awk '{print NF}') [[ $num_disks -lt 3 ]] && fail "Not enough disks to run ZFS Test Suite" # Ensure user has only basic privileges. -ppriv -s EIP=basic -e $runner $quiet -c $runfile +ppriv -s EIP=basic -e $runner -c $runfile $xargs ret=$? rm -rf $PATHDIR || fail "Couldn't remove $PATHDIR" diff --git a/usr/src/uts/common/io/ib/clients/rds/rdsib.c b/usr/src/uts/common/io/ib/clients/rds/rdsib.c index ebfa352ac0..b80b385d75 100644 --- a/usr/src/uts/common/io/ib/clients/rds/rdsib.c +++ b/usr/src/uts/common/io/ib/clients/rds/rdsib.c @@ -71,6 +71,10 @@ rds_transport_ops_t rds_ib_transport_ops = { rds_if_lookup_by_name }; +/* Global pools of buffers */ +rds_bufpool_t rds_dpool; /* data pool */ +rds_bufpool_t rds_cpool; /* ctrl pool */ + /* global */ rds_state_t *rdsib_statep = NULL; krwlock_t rds_loopback_portmap_lock; diff --git a/usr/src/uts/common/io/ib/clients/rdsv3/rdsv3_impl.c b/usr/src/uts/common/io/ib/clients/rdsv3/rdsv3_impl.c index 5cc3160b3a..028ceb9937 100644 --- a/usr/src/uts/common/io/ib/clients/rdsv3/rdsv3_impl.c +++ b/usr/src/uts/common/io/ib/clients/rdsv3/rdsv3_impl.c @@ -66,6 +66,7 @@ #include <sys/mac_provider.h> #include <sys/mac_client_priv.h> +uint_t rdsv3_one_sec_in_hz; ddi_taskq_t *rdsv3_taskq = NULL; extern kmem_cache_t *rdsv3_alloc_cache; diff --git a/usr/src/uts/common/io/idm/idm.c b/usr/src/uts/common/io/idm/idm.c index 1361b8dfb9..ade553dabd 100644 --- a/usr/src/uts/common/io/idm/idm.c +++ b/usr/src/uts/common/io/idm/idm.c @@ -107,6 +107,8 @@ idm_transport_t idm_transport_list[] = { }; +idm_global_t idm; /* Global state */ + int _init(void) { diff --git a/usr/src/uts/common/io/nge/nge_chip.h b/usr/src/uts/common/io/nge/nge_chip.h index 089f77320a..1d1e85be08 100644 --- a/usr/src/uts/common/io/nge/nge_chip.h +++ b/usr/src/uts/common/io/nge/nge_chip.h @@ -522,7 +522,7 @@ typedef union _nge_rx_cntrl0 { uint32_t crcm:1; uint32_t ofolm:1; uint32_t framerm:1; - uint32_t resv23_31:9; + uint32_t resv23_31:9; } cntl_bits; } nge_rx_cntrl0; @@ -627,7 +627,7 @@ typedef union _nge_rx_def { * Low 32 bit unicast address */ #define NGE_UNI_ADDR0 0x0a8 -union { +typedef union _nge_uni_addr0 { uint32_t addr_val; struct { uint32_t addr; @@ -655,12 +655,12 @@ typedef union _nge_uni_addr1 { * Low 32 bit multicast address */ #define NGE_MUL_ADDR0 0x0b0 -union { +typedef union _nge_mul_addr0 { uint32_t addr_val; struct { uint32_t addr; }addr_bits; -}nge_mul_addr0; +} nge_mul_addr0; /* * High 32 bit multicast address @@ -672,13 +672,13 @@ typedef union _nge_mul_addr1 { uint32_t addr:16; uint32_t resv16_31:16; }addr_bits; -}nge_mul_addr1; +} nge_mul_addr1; /* * Low 32 bit multicast mask */ #define NGE_MUL_MASK 0x0b8 -union { +typedef union _nge_mul_mask0 { uint32_t mask_val; struct { uint32_t mask; @@ -689,7 +689,7 @@ union { * High 32 bit multicast mask */ #define NGE_MUL_MASK1 0x0bc -union { +typedef union _nge_mul_mask1 { uint32_t mask_val; struct { uint32_t mask:16; @@ -800,7 +800,7 @@ typedef union _nge_rx_poll { * Transmit polling count */ #define NGE_TX_PCNT 0x114 -union { +typedef union _nge_tx_pcnt { uint32_t cnt_val; struct { uint32_t pcnt:32; @@ -811,7 +811,7 @@ union { * Receive polling count */ #define NGE_RX_PCNT 0x118 -union { +typedef union _nge_rx_pcnt { uint32_t cnt_val; struct { uint32_t pcnt:32; @@ -823,7 +823,7 @@ union { * Current tx's descriptor address */ #define NGE_TX_CUR_DADR 0x11c -union { +typedef union _nge_tx_cur_addr { uint32_t addr_val; struct { uint32_t resv0_2:3; @@ -835,7 +835,7 @@ union { * Current rx's descriptor address */ #define NGE_RX_CUR_DADR 0x120 -union { +typedef union _nge_rx_cur_addr { uint32_t addr_val; struct { uint32_t resv0_2:3; @@ -847,7 +847,7 @@ union { * Current tx's data buffer address */ #define NGE_TX_CUR_PRD0 0x124 -union { +typedef union _nge_tx_cur_prd0 { uint32_t prd0_val; struct { uint32_t prd0:32; @@ -858,7 +858,7 @@ union { * Current tx's data buffer status */ #define NGE_TX_CUR_PRD1 0x128 -union { +typedef union _nge_tx_cur_prd1 { uint32_t prd1_val; struct { uint32_t rebytes:16; @@ -870,12 +870,12 @@ union { * Current rx's data buffer address */ #define NGE_RX_CUR_PRD0 0x12c -union { +typedef union _nge_rx_cur_prd0 { uint32_t prd0_val; struct { uint32_t prd0:32; }prd0_bits; -}nge_rx_cur_prd0; +} nge_rx_cur_prd0; /* * Current rx's data buffer status @@ -886,18 +886,18 @@ union { * Next tx's descriptor address */ #define NGE_TX_NXT_DADR 0x134 -union { +typedef union _nge_tx_nxt_dadr { uint32_t dadr_val; struct { uint32_t addr:32; }addr_bits; -}nge_tx_nxt_dadr; +} nge_tx_nxt_dadr; /* * Next rx's descriptor address */ #define NGE_RX_NXT_DADR 0x138 -union { +typedef union _nge_rx_nxt_dadr { uint32_t dadr_val; struct { uint32_t addr:32; @@ -1362,7 +1362,7 @@ typedef union { #define MII_CICADA_DISABLE_ECHO_MODE 0x2000 #define MII_CICADA_EXT_CONTROL MII_VENDOR(7) -#define MII_CICADA_MODE_SELECT_BITS 0xf000 +#define MII_CICADA_MODE_SELECT_BITS 0xf000 #define MII_CICADA_MODE_SELECT_RGMII 0x1000 #define MII_CICADA_POWER_SUPPLY_BITS 0x0e00 #define MII_CICADA_POWER_SUPPLY_3_3V 0x0000 diff --git a/usr/src/uts/common/sys/ib/clients/rds/rdsib_buf.h b/usr/src/uts/common/sys/ib/clients/rds/rdsib_buf.h index 5e2f419600..164af2aa7a 100644 --- a/usr/src/uts/common/sys/ib/clients/rds/rdsib_buf.h +++ b/usr/src/uts/common/sys/ib/clients/rds/rdsib_buf.h @@ -75,8 +75,6 @@ #ifndef _RDSIB_BUF_H #define _RDSIB_BUF_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif @@ -149,8 +147,8 @@ typedef struct rds_bufpool_s { } rds_bufpool_t; /* Global pools of buffers */ -rds_bufpool_t rds_dpool; /* data pool */ -rds_bufpool_t rds_cpool; /* ctrl pool */ +extern rds_bufpool_t rds_dpool; /* data pool */ +extern rds_bufpool_t rds_cpool; /* ctrl pool */ /* defined in rds_buf.c */ int rds_init_recv_caches(rds_state_t *statep); diff --git a/usr/src/uts/common/sys/ib/clients/rdsv3/rdsv3_impl.h b/usr/src/uts/common/sys/ib/clients/rdsv3/rdsv3_impl.h index 56b92f8037..c462306418 100644 --- a/usr/src/uts/common/sys/ib/clients/rdsv3/rdsv3_impl.h +++ b/usr/src/uts/common/sys/ib/clients/rdsv3/rdsv3_impl.h @@ -117,7 +117,7 @@ typedef unsigned int atomic_t; #define clear_le_bit(b, p) clear_bit(b ^ LE_BIT_XOR, p) #define test_le_bit(b, p) test_bit(b ^ LE_BIT_XOR, p) -uint_t rdsv3_one_sec_in_hz; +extern uint_t rdsv3_one_sec_in_hz; #define jiffies 100 #define HZ (drv_hztousec(1)) diff --git a/usr/src/uts/common/sys/idm/idm_impl.h b/usr/src/uts/common/sys/idm/idm_impl.h index 346611719d..1e816ee211 100644 --- a/usr/src/uts/common/sys/idm/idm_impl.h +++ b/usr/src/uts/common/sys/idm/idm_impl.h @@ -472,7 +472,7 @@ typedef struct { kmem_cache_t *idm_so_128k_buf_cache; } idm_global_t; -idm_global_t idm; /* Global state */ +extern idm_global_t idm; /* Global state */ int idm_idpool_create(idm_idpool_t *pool); diff --git a/usr/src/uts/common/sys/mhd.h b/usr/src/uts/common/sys/mhd.h index 66d57266ad..3d7e0d5d5a 100644 --- a/usr/src/uts/common/sys/mhd.h +++ b/usr/src/uts/common/sys/mhd.h @@ -27,8 +27,6 @@ #ifndef _SYS_MHD_H #define _SYS_MHD_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif @@ -41,8 +39,8 @@ extern "C" { #define MHIOCTKOWN (MHIOC|2) #define MHIOCRELEASE (MHIOC|3) #define MHIOCSTATUS (MHIOC|4) -#define MHIOCGRP_INKEYS (MHIOC|5) -#define MHIOCGRP_INRESV (MHIOC|6) +#define MHIOCGRP_INKEYS (MHIOC|5) +#define MHIOCGRP_INRESV (MHIOC|6) #define MHIOCGRP_REGISTER (MHIOC|7) #define MHIOCGRP_RESERVE (MHIOC|8) #define MHIOCGRP_PREEMPTANDABORT (MHIOC|9) @@ -79,13 +77,13 @@ typedef struct mhioc_inkeys { } mhioc_inkeys_t; #if defined(_SYSCALL32) -struct mhioc_key_list32 { +typedef struct mhioc_key_list32 { uint32_t listsize; uint32_t listlen; caddr32_t list; } mhioc_key_list32_t; -struct mhioc_inkeys32 { +typedef struct mhioc_inkeys32 { uint32_t generation; caddr32_t li; } mhioc_inkeys32_t; @@ -110,7 +108,7 @@ typedef struct mhioc_inresvs { } mhioc_inresvs_t; #if defined(_SYSCALL32) -struct mhioc_resv_desc_list32 { +typedef struct mhioc_resv_desc_list32 { uint32_t listsize; uint32_t listlen; caddr32_t list; diff --git a/usr/src/uts/common/sys/rgb.h b/usr/src/uts/common/sys/rgb.h index 9ddfaa9e3f..6e0ba29af2 100644 --- a/usr/src/uts/common/sys/rgb.h +++ b/usr/src/uts/common/sys/rgb.h @@ -23,6 +23,13 @@ extern "C" { #endif /* + * Number of "base" colors is 16, 8 dark and 8 bright/light. + * Color map size for indexed colors is 256, to support VGA 256-color modes. + */ +#define NCOLORS 16 +#define NCMAP 256 + +/* * Color data from bootloader. */ typedef struct rgb_color { @@ -37,9 +44,9 @@ typedef struct rgb { } rgb_t; typedef struct { - uint8_t red[16]; - uint8_t green[16]; - uint8_t blue[16]; + uint8_t red[NCOLORS]; + uint8_t green[NCOLORS]; + uint8_t blue[NCOLORS]; } text_cmap_t; extern const text_cmap_t cmap4_to_24; @@ -67,10 +74,30 @@ typedef enum pc_colors { pc_brt_white = 15 } pc_colors_t; +typedef enum sun_colors { + sun_brt_white = 0, + sun_black = 1, + sun_blue = 2, + sun_green = 3, + sun_cyan = 4, + sun_red = 5, + sun_magenta = 6, + sun_brown = 7, + sun_white = 8, + sun_grey = 9, + sun_brt_blue = 10, + sun_brt_green = 11, + sun_brt_cyan = 12, + sun_brt_red = 13, + sun_brt_magenta = 14, + sun_yellow = 15, +} sun_colors_t; + #define XLATE_NCOLORS 8 extern const uint8_t dim_xlate[XLATE_NCOLORS]; extern const uint8_t brt_xlate[XLATE_NCOLORS]; -extern const uint8_t solaris_color_to_pc_color[16]; +extern const uint8_t solaris_color_to_pc_color[NCOLORS]; +extern const uint8_t pc_color_to_solaris_color[NCOLORS]; extern uint32_t rgb_color_map(const rgb_t *, uint8_t); diff --git a/usr/src/uts/i86pc/io/vmm/amd/svm_msr.c b/usr/src/uts/i86pc/io/vmm/amd/svm_msr.c index 234631def4..f453692855 100644 --- a/usr/src/uts/i86pc/io/vmm/amd/svm_msr.c +++ b/usr/src/uts/i86pc/io/vmm/amd/svm_msr.c @@ -44,6 +44,8 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/errno.h> #include <sys/systm.h> +#include <sys/x86_archext.h> +#include <sys/privregs.h> #include <machine/cpufunc.h> #include <machine/specialreg.h> @@ -162,13 +164,17 @@ svm_rdmsr(struct svm_softc *sc, int vcpu, uint_t num, uint64_t *result) case MSR_EXTFEATURES: *result = 0; break; - case MSR_DE_CFG: + case MSR_AMD_DE_CFG: + *result = 0; /* - * MSR_DE_CFG is used for a vast array of AMD errata, spanning - * from family 10h to 17h. In the future, it might make sense - * to more thoroughly emulate its contents. + * Bit 1 of DE_CFG is defined by AMD to control whether the + * lfence instruction is serializing. Practically all CPUs + * supported by bhyve also contain this MSR, making it safe to + * expose unconditionally. */ - *result = 0; + if (is_x86_feature(x86_featureset, X86FSET_LFENCE_SER)) { + *result |= AMD_DE_CFG_LFENCE_DISPATCH; + } break; default: error = EINVAL; @@ -197,8 +203,8 @@ svm_wrmsr(struct svm_softc *sc, int vcpu, uint_t num, uint64_t val) case MSR_SYSCFG: /* Ignore writes */ break; - case MSR_DE_CFG: - /* Ignore writes for now. (See: svm_rdmsr) */ + case MSR_AMD_DE_CFG: + /* Ignore writes */ break; case MSR_AMDK8_IPM: /* diff --git a/usr/src/uts/i86pc/os/cpuid.c b/usr/src/uts/i86pc/os/cpuid.c index c40173d4c8..ff01bd1308 100644 --- a/usr/src/uts/i86pc/os/cpuid.c +++ b/usr/src/uts/i86pc/os/cpuid.c @@ -24,6 +24,7 @@ * Copyright 2013 Nexenta Systems, Inc. All rights reserved. * Copyright 2014 Josef "Jeff" Sipek <jeffpc@josefsipek.net> * Copyright 2020 Joyent, Inc. + * Copyright 2020 Oxide Computer Company */ /* * Copyright (c) 2010, Intel Corporation. @@ -1439,7 +1440,8 @@ static char *x86_feature_names[NUM_X86_FEATURES] = { "taa_no", "ppin", "vaes", - "vpclmulqdq" + "vpclmulqdq", + "lfence_serializing" }; boolean_t @@ -2732,7 +2734,6 @@ cpuid_enable_enhanced_ibrs(void) wrmsr(MSR_IA32_SPEC_CTRL, val); } -#ifndef __xpv /* * Determine whether or not we can use the AMD optimized retpoline * functionality. We use this when we know we're on an AMD system and we can @@ -2741,46 +2742,12 @@ cpuid_enable_enhanced_ibrs(void) static boolean_t cpuid_use_amd_retpoline(struct cpuid_info *cpi) { - uint64_t val; - on_trap_data_t otd; - if (cpi->cpi_vendor != X86_VENDOR_AMD && cpi->cpi_vendor != X86_VENDOR_HYGON) return (B_FALSE); - /* - * We need to determine whether or not lfence is serializing. It always - * is on families 0xf and 0x11. On others, it's controlled by - * MSR_AMD_DE_CFG (MSRC001_1029). If some hypervisor gives us a crazy - * old family, don't try and do anything. - */ - if (cpi->cpi_family < 0xf) - return (B_FALSE); - if (cpi->cpi_family == 0xf || cpi->cpi_family == 0x11) - return (B_TRUE); - - /* - * While it may be tempting to use get_hwenv(), there are no promises - * that a hypervisor will actually declare themselves to be so in a - * friendly way. As such, try to read and set the MSR. If we can then - * read back the value we set (it wasn't just set to zero), then we go - * for it. - */ - if (!on_trap(&otd, OT_DATA_ACCESS)) { - val = rdmsr(MSR_AMD_DE_CFG); - val |= AMD_DE_CFG_LFENCE_DISPATCH; - wrmsr(MSR_AMD_DE_CFG, val); - val = rdmsr(MSR_AMD_DE_CFG); - } else { - val = 0; - } - no_trap(); - - if ((val & AMD_DE_CFG_LFENCE_DISPATCH) != 0) - return (B_TRUE); - return (B_FALSE); + return (is_x86_feature(x86_featureset, X86FSET_LFENCE_SER)); } -#endif /* !__xpv */ /* * Determine how we should mitigate TAA or if we need to. Regardless of TAA, if @@ -3019,10 +2986,8 @@ cpuid_scan_security(cpu_t *cpu, uchar_t *featureset) } else if (is_x86_feature(featureset, X86FSET_IBRS_ALL)) { cpuid_enable_enhanced_ibrs(); v2mit = X86_SPECTREV2_ENHANCED_IBRS; -#ifndef __xpv } else if (cpuid_use_amd_retpoline(cpi)) { v2mit = X86_SPECTREV2_RETPOLINE_AMD; -#endif /* !__xpv */ } else { v2mit = X86_SPECTREV2_RETPOLINE; } @@ -4186,6 +4151,59 @@ cpuid_pass1(cpu_t *cpu, uchar_t *featureset) } /* + * Check (and potentially set) if lfence is serializing. + * This is useful for accurate rdtsc measurements and AMD retpolines. + */ + if ((cpi->cpi_vendor == X86_VENDOR_AMD || + cpi->cpi_vendor == X86_VENDOR_HYGON) && + is_x86_feature(featureset, X86FSET_SSE2)) { + /* + * The AMD white paper Software Techniques For Managing + * Speculation on AMD Processors details circumstances for when + * lfence instructions are serializing. + * + * On family 0xf and 0x11, it is inherently so. On family 0x10 + * and later (excluding 0x11), a bit in the DE_CFG MSR + * determines the lfence behavior. Per that whitepaper, AMD has + * committed to supporting that MSR on all later CPUs. + */ + if (cpi->cpi_family == 0xf || cpi->cpi_family == 0x11) { + add_x86_feature(featureset, X86FSET_LFENCE_SER); + } else if (cpi->cpi_family >= 0x10) { + uint64_t val = 0; + +#if !defined(__xpv) + /* + * Be careful when attempting to enable the bit, and + * verify that it was actually set in case we are + * running in a hypervisor which is less than faithful + * about its emulation of this feature. + */ + on_trap_data_t otd; + if (!on_trap(&otd, OT_DATA_ACCESS)) { + val = rdmsr(MSR_AMD_DE_CFG); + val |= AMD_DE_CFG_LFENCE_DISPATCH; + wrmsr(MSR_AMD_DE_CFG, val); + val = rdmsr(MSR_AMD_DE_CFG); + } + no_trap(); +#endif + + if ((val & AMD_DE_CFG_LFENCE_DISPATCH) != 0) { + add_x86_feature(featureset, X86FSET_LFENCE_SER); + } + } + } else if (cpi->cpi_vendor == X86_VENDOR_Intel && + is_x86_feature(featureset, X86FSET_SSE2)) { + /* + * Documentation and other OSes indicate that lfence is always + * serializing on Intel CPUs. + */ + add_x86_feature(featureset, X86FSET_LFENCE_SER); + } + + + /* * Check the processor leaves that are used for security features. */ cpuid_scan_security(cpu, featureset); @@ -7263,11 +7281,6 @@ patch_tsc_read(int flag) cnt = &_no_rdtsc_end - &_no_rdtsc_start; (void) memcpy((void *)tsc_read, (void *)&_no_rdtsc_start, cnt); break; - case TSC_RDTSC_MFENCE: - cnt = &_tsc_mfence_end - &_tsc_mfence_start; - (void) memcpy((void *)tsc_read, - (void *)&_tsc_mfence_start, cnt); - break; case TSC_RDTSC_LFENCE: cnt = &_tsc_lfence_end - &_tsc_lfence_start; (void) memcpy((void *)tsc_read, diff --git a/usr/src/uts/i86pc/os/fakebop.c b/usr/src/uts/i86pc/os/fakebop.c index 75c4c618a7..933411606e 100644 --- a/usr/src/uts/i86pc/os/fakebop.c +++ b/usr/src/uts/i86pc/os/fakebop.c @@ -130,8 +130,8 @@ static char *curr_page = NULL; /* ptr to avail bprop memory */ static int curr_space = 0; /* amount of memory at curr_page */ #ifdef __xpv -start_info_t *xen_info; -shared_info_t *HYPERVISOR_shared_info; +extern start_info_t *xen_info; +extern shared_info_t *HYPERVISOR_shared_info; #endif /* diff --git a/usr/src/uts/i86pc/os/mlsetup.c b/usr/src/uts/i86pc/os/mlsetup.c index 9487552564..e1fd081cfa 100644 --- a/usr/src/uts/i86pc/os/mlsetup.c +++ b/usr/src/uts/i86pc/os/mlsetup.c @@ -24,6 +24,7 @@ * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011 by Delphix. All rights reserved. * Copyright 2019 Joyent, Inc. + * Copyright 2020 Oxide Computer Company */ /* * Copyright (c) 2010, Intel Corporation. @@ -265,30 +266,16 @@ mlsetup(struct regs *rp) * time-stamp counter while ensuring no out-of-order execution. * Patch it while the kernel text is still writable. * - * Note: tsc_read is not patched for intel processors whose family - * is >6 and for amd whose family >f (in case they don't support rdtscp - * instruction, unlikely). By default tsc_read will use cpuid for - * serialization in such cases. The following code needs to be - * revisited if intel processors of family >= f retains the - * instruction serialization nature of mfence instruction. - * Note: tsc_read is not patched for x86 processors which do - * not support "mfence". By default tsc_read will use cpuid for - * serialization in such cases. - * * The Xen hypervisor does not correctly report whether rdtscp is * supported or not, so we must assume that it is not. */ if ((get_hwenv() & HW_XEN_HVM) == 0 && - is_x86_feature(x86_featureset, X86FSET_TSCP)) + is_x86_feature(x86_featureset, X86FSET_TSCP)) { patch_tsc_read(TSC_TSCP); - else if (cpuid_getvendor(CPU) == X86_VENDOR_AMD && - cpuid_getfamily(CPU) <= 0xf && - is_x86_feature(x86_featureset, X86FSET_SSE2)) - patch_tsc_read(TSC_RDTSC_MFENCE); - else if (cpuid_getvendor(CPU) == X86_VENDOR_Intel && - cpuid_getfamily(CPU) <= 6 && - is_x86_feature(x86_featureset, X86FSET_SSE2)) + } else if (is_x86_feature(x86_featureset, X86FSET_LFENCE_SER)) { + ASSERT(is_x86_feature(x86_featureset, X86FSET_SSE2)); patch_tsc_read(TSC_RDTSC_LFENCE); + } #endif /* !__xpv */ diff --git a/usr/src/uts/i86pc/sys/tsc.h b/usr/src/uts/i86pc/sys/tsc.h index d4090381c4..82a1557bd0 100644 --- a/usr/src/uts/i86pc/sys/tsc.h +++ b/usr/src/uts/i86pc/sys/tsc.h @@ -21,7 +21,7 @@ */ #define TSC_NONE 0x0 #define TSC_RDTSC_CPUID 0x1 -#define TSC_RDTSC_MFENCE 0x2 +/* formerly TSC_RDTSC_MFENCE 0x2 */ #define TSC_RDTSC_LFENCE 0x3 #define TSC_TSCP 0x4 diff --git a/usr/src/uts/intel/sys/x86_archext.h b/usr/src/uts/intel/sys/x86_archext.h index 689ed9cc76..241ce2820b 100644 --- a/usr/src/uts/intel/sys/x86_archext.h +++ b/usr/src/uts/intel/sys/x86_archext.h @@ -738,6 +738,7 @@ extern "C" { #define X86FSET_PPIN 99 #define X86FSET_VAES 100 #define X86FSET_VPCLMULQDQ 101 +#define X86FSET_LFENCE_SER 102 /* * Intel Deep C-State invariant TSC in leaf 0x80000007. @@ -1138,7 +1139,7 @@ extern "C" { #if defined(_KERNEL) || defined(_KMEMUSER) -#define NUM_X86_FEATURES 102 +#define NUM_X86_FEATURES 103 extern uchar_t x86_featureset[]; extern void free_x86_featureset(void *featureset); |