diff options
| author | Jerry Jelinek <jerry.jelinek@joyent.com> | 2020-10-12 13:55:36 +0000 |
|---|---|---|
| committer | Jerry Jelinek <jerry.jelinek@joyent.com> | 2020-10-12 13:55:36 +0000 |
| commit | 3be601817c5683fd48fab3620618f0589357f226 (patch) | |
| tree | 3195e417e2e354e403813f1ce419bc2f428722cb /usr/src | |
| parent | 47660a03a1bef9bb5e314c4cb6a9a255a6cc95e6 (diff) | |
| parent | aefb332f5664b51526fd3e7d0b3cb6bdda1e1758 (diff) | |
| download | illumos-joyent-3be601817c5683fd48fab3620618f0589357f226.tar.gz | |
[illumos-gate merge]
commit aefb332f5664b51526fd3e7d0b3cb6bdda1e1758
13206 Fix open(2) man page
commit d0caeb890c33e30d7a9addcbccdda2343401d3e7
13200 fmtopo could display CPU socket
commit a41862fc9ba4a637c7ae5da1e5edd176416f7990
13198 Add AMD Dali, Renoir, and Banded Kestrel socket info
13199 AMD Socket info shouldn't require revision
commit d06ea0b9fb5d1989b39a245c5e79324b2c8db398
13153 loader: before falling back to default, also use EDID standard timings
Diffstat (limited to 'usr/src')
| -rw-r--r-- | usr/src/boot/Makefile.version | 2 | ||||
| -rw-r--r-- | usr/src/boot/sys/boot/common/gfx_fb.c | 82 | ||||
| -rw-r--r-- | usr/src/boot/sys/boot/common/gfx_fb.h | 22 | ||||
| -rw-r--r-- | usr/src/boot/sys/boot/efi/loader/framebuffer.c | 100 | ||||
| -rw-r--r-- | usr/src/boot/sys/boot/i386/libi386/vbe.c | 48 | ||||
| -rw-r--r-- | usr/src/lib/fm/topo/modules/i86pc/chip/chip.c | 20 | ||||
| -rw-r--r-- | usr/src/lib/fm/topo/modules/i86pc/chip/chip.h | 5 | ||||
| -rw-r--r-- | usr/src/lib/fm/topo/modules/i86pc/chip/chip_subr.c | 42 | ||||
| -rw-r--r-- | usr/src/man/man2/open.2 | 18 | ||||
| -rw-r--r-- | usr/src/uts/i86pc/os/cpuid_subr.c | 175 | ||||
| -rw-r--r-- | usr/src/uts/intel/sys/x86_archext.h | 6 |
11 files changed, 378 insertions, 142 deletions
diff --git a/usr/src/boot/Makefile.version b/usr/src/boot/Makefile.version index 8644947a6e..76b7a4056d 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.09.24.1 +BOOT_VERSION = $(LOADER_VERSION)-2020.09.25.1 diff --git a/usr/src/boot/sys/boot/common/gfx_fb.c b/usr/src/boot/sys/boot/common/gfx_fb.c index 84d5e50fe2..78d3910e39 100644 --- a/usr/src/boot/sys/boot/common/gfx_fb.c +++ b/usr/src/boot/sys/boot/common/gfx_fb.c @@ -2011,3 +2011,85 @@ command_font(int argc, char *argv[]) } return (rc); } + +bool +gfx_get_edid_resolution(struct vesa_edid_info *edid, edid_res_list_t *res) +{ + struct resolution *rp, *p; + + /* + * Walk detailed timings tables (4). + */ + if ((edid->display.supported_features + & EDID_FEATURE_PREFERRED_TIMING_MODE) != 0) { + /* Walk detailed timing descriptors (4) */ + for (int i = 0; i < DET_TIMINGS; i++) { + /* + * Reserved value 0 is not used for display decriptor. + */ + if (edid->detailed_timings[i].pixel_clock == 0) + continue; + if ((rp = malloc(sizeof (*rp))) == NULL) + continue; + rp->width = GET_EDID_INFO_WIDTH(edid, i); + rp->height = GET_EDID_INFO_HEIGHT(edid, i); + if (rp->width > 0 && rp->width <= EDID_MAX_PIXELS && + rp->height > 0 && rp->height <= EDID_MAX_LINES) + TAILQ_INSERT_TAIL(res, rp, next); + else + free(rp); + } + } + + /* + * Walk standard timings list (8). + */ + for (int i = 0; i < STD_TIMINGS; i++) { + /* Is this field unused? */ + if (edid->standard_timings[i] == 0x0101) + continue; + + if ((rp = malloc(sizeof (*rp))) == NULL) + continue; + + rp->width = HSIZE(edid->standard_timings[i]); + switch (RATIO(edid->standard_timings[i])) { + case RATIO1_1: + rp->height = HSIZE(edid->standard_timings[i]); + if (edid->header.version > 1 || + edid->header.revision > 2) { + rp->height = rp->height * 10 / 16; + } + break; + case RATIO4_3: + rp->height = HSIZE(edid->standard_timings[i]) * 3 / 4; + break; + case RATIO5_4: + rp->height = HSIZE(edid->standard_timings[i]) * 4 / 5; + break; + case RATIO16_9: + rp->height = HSIZE(edid->standard_timings[i]) * 9 / 16; + break; + } + + /* + * Create resolution list in decreasing order, except keep + * first entry (preferred timing mode). + */ + TAILQ_FOREACH(p, res, next) { + if (p->width * p->height < rp->width * rp->height) { + /* Keep preferred mode first */ + if (TAILQ_FIRST(res) == p) + TAILQ_INSERT_AFTER(res, p, rp, next); + else + TAILQ_INSERT_BEFORE(p, rp, next); + break; + } + if (TAILQ_NEXT(p, next) == NULL) { + TAILQ_INSERT_TAIL(res, rp, next); + break; + } + } + } + return (!TAILQ_EMPTY(res)); +} diff --git a/usr/src/boot/sys/boot/common/gfx_fb.h b/usr/src/boot/sys/boot/common/gfx_fb.h index cb2d37042d..e242931a44 100644 --- a/usr/src/boot/sys/boot/common/gfx_fb.h +++ b/usr/src/boot/sys/boot/common/gfx_fb.h @@ -19,6 +19,7 @@ #include <stdbool.h> #include <sys/visual_io.h> #include <sys/multiboot2.h> +#include <sys/queue.h> #include <pnglite.h> #ifdef __cplusplus @@ -93,6 +94,18 @@ struct vesa_edid_info { uint8_t checksum; } __packed; +#define STD_TIMINGS 8 +#define DET_TIMINGS 4 + +#define HSIZE(x) (((x & 0xff) + 31) * 8) +#define RATIO(x) ((x & 0xC000) >> 14) +#define RATIO1_1 0 +/* EDID Ver. 1.3 redefined this */ +#define RATIO16_10 RATIO1_1 +#define RATIO4_3 1 +#define RATIO5_4 2 +#define RATIO16_9 3 + /* * Number of pixels and lines is 12-bit int, valid values 0-4095. */ @@ -109,9 +122,18 @@ struct vesa_edid_info { (((uint_t)(edid_info)->detailed_timings[(timings_num)].vertical_hi & \ 0xf0) << 4)) +struct resolution { + uint32_t width; + uint32_t height; + TAILQ_ENTRY(resolution) next; +}; + +typedef TAILQ_HEAD(edid_resolution, resolution) edid_res_list_t; + extern multiboot_tag_framebuffer_t gfx_fb; 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 *); uint32_t gfx_fb_color_map(uint8_t); void gfx_fb_display_cursor(struct vis_conscursor *); diff --git a/usr/src/boot/sys/boot/efi/loader/framebuffer.c b/usr/src/boot/sys/boot/efi/loader/framebuffer.c index f063cc1639..534e00cf9c 100644 --- a/usr/src/boot/sys/boot/efi/loader/framebuffer.c +++ b/usr/src/boot/sys/boot/efi/loader/framebuffer.c @@ -50,10 +50,11 @@ EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; static EFI_GUID pciio_guid = EFI_PCI_IO_PROTOCOL_GUID; EFI_GUID uga_guid = EFI_UGA_DRAW_PROTOCOL_GUID; static EFI_GUID active_edid_guid = EFI_EDID_ACTIVE_PROTOCOL_GUID; -static EFI_GUID discovered_edid_guid = EFI_EDID_DISCOVERED_PROTOCOL_GUID; /* Saved initial GOP mode. */ static uint32_t default_mode = UINT32_MAX; +/* Cached EDID. */ +static struct vesa_edid_info *edid_info; static uint32_t gop_default_mode(void); static int efifb_set_mode(EFI_GRAPHICS_OUTPUT *, uint_t); @@ -451,63 +452,54 @@ efifb_gop_get_edid(EFI_HANDLE gop) { const uint8_t magic[] = EDID_MAGIC; EFI_EDID_ACTIVE_PROTOCOL *edid; - struct vesa_edid_info *edid_info; + struct vesa_edid_info *edid_infop; EFI_GUID *guid; EFI_STATUS status; size_t size; - edid_info = calloc(1, sizeof (*edid_info)); - if (edid_info == NULL) - return (NULL); - guid = &active_edid_guid; - status = BS->OpenProtocol(gop, guid, (void **)&edid, IH, NULL, - EFI_OPEN_PROTOCOL_GET_PROTOCOL); - if (status != EFI_SUCCESS) { - guid = &discovered_edid_guid; - status = BS->OpenProtocol(gop, guid, (void **)&edid, IH, NULL, - EFI_OPEN_PROTOCOL_GET_PROTOCOL); - } + status = OpenProtocolByHandle(gop, guid, (void **)&edid); if (status != EFI_SUCCESS) - goto error; + return (NULL); + + size = sizeof (*edid_infop); + if (size < edid->SizeOfEdid) + size = edid->SizeOfEdid; - size = edid->SizeOfEdid; - if (size > sizeof (*edid_info)) - size = sizeof (*edid_info); + edid_infop = calloc(1, size); + if (edid_infop == NULL) { + status = BS->CloseProtocol(gop, guid, IH, NULL); + return (NULL); + } - memcpy(edid_info, edid->Edid, size); + memcpy(edid_infop, edid->Edid, edid->SizeOfEdid); status = BS->CloseProtocol(gop, guid, IH, NULL); /* Validate EDID */ - if (memcmp(edid_info, magic, sizeof (magic)) != 0) + if (memcmp(edid_infop, magic, sizeof (magic)) != 0) goto error; - if (edid_info->header.version == 1 && - (edid_info->display.supported_features - & EDID_FEATURE_PREFERRED_TIMING_MODE) && - edid_info->detailed_timings[0].pixel_clock) { - return (edid_info); - } + if (edid_infop->header.version != 1) + goto error; + return (edid_infop); error: - free(edid_info); + free(edid_infop); return (NULL); } -static int -efifb_get_edid(UINT32 *pwidth, UINT32 *pheight) +static bool +efifb_get_edid(edid_res_list_t *res) { extern EFI_GRAPHICS_OUTPUT *gop; - struct vesa_edid_info *edid_info; - int rv = 1; - - edid_info = efifb_gop_get_edid(gop); - if (edid_info != NULL) { - *pwidth = GET_EDID_INFO_WIDTH(edid_info, 0); - *pheight = GET_EDID_INFO_HEIGHT(edid_info, 0); - rv = 0; - } - free(edid_info); + bool rv = false; + + if (edid_info == NULL) + edid_info = efifb_gop_get_edid(gop); + + if (edid_info != NULL) + rv = gfx_get_edid_resolution(edid_info, res); + return (rv); } @@ -548,13 +540,22 @@ static void print_efifb(int mode, struct efi_fb *efifb, int verbose) { uint_t depth; - UINT32 width, height; + edid_res_list_t res; + struct resolution *rp; + TAILQ_INIT(&res); if (verbose == 1) { printf("Framebuffer mode: %s\n", plat_stdout_is_framebuffer() ? "on" : "off"); - if (efifb_get_edid(&width, &height) == 0) - printf("EDID mode: %dx%d\n\n", width, height); + if (efifb_get_edid(&res)) { + printf("EDID"); + while ((rp = TAILQ_FIRST(&res)) != NULL) { + printf(" %dx%d", rp->width, rp->height); + TAILQ_REMOVE(&res, rp, next); + free(rp); + } + printf("\n"); + } } if (mode >= 0) { @@ -665,12 +666,23 @@ efifb_find_mode(char *str) static uint32_t gop_default_mode(void) { + edid_res_list_t res; + struct resolution *rp; extern EFI_GRAPHICS_OUTPUT *gop; - UINT32 mode, width = 0, height = 0; + UINT32 mode; mode = gop->Mode->MaxMode; - if (efifb_get_edid(&width, &height) == 0) - mode = efifb_find_mode_xydm(width, height, -1, -1); + TAILQ_INIT(&res); + if (efifb_get_edid(&res)) { + while ((rp = TAILQ_FIRST(&res)) != NULL) { + if (mode == gop->Mode->MaxMode) { + mode = efifb_find_mode_xydm( + rp->width, rp->height, -1, -1); + } + TAILQ_REMOVE(&res, rp, next); + free(rp); + } + } if (mode == gop->Mode->MaxMode) mode = default_mode; diff --git a/usr/src/boot/sys/boot/i386/libi386/vbe.c b/usr/src/boot/sys/boot/i386/libi386/vbe.c index c3cc09dd53..d0831d1599 100644 --- a/usr/src/boot/sys/boot/i386/libi386/vbe.c +++ b/usr/src/boot/sys/boot/i386/libi386/vbe.c @@ -494,7 +494,7 @@ vbe_dump_mode(int modenum, struct modeinfoblock *mi) } static bool -vbe_get_edid(uint_t *pwidth, uint_t *pheight) +vbe_get_edid(edid_res_list_t *res) { struct vesa_edid_info *edid_info; const uint8_t magic[] = EDID_MAGIC; @@ -517,18 +517,11 @@ vbe_get_edid(uint_t *pwidth, uint_t *pheight) if (memcmp(edid_info, magic, sizeof (magic)) != 0) goto done; - if (!(edid_info->header.version == 1 && - (edid_info->display.supported_features - & EDID_FEATURE_PREFERRED_TIMING_MODE) && - edid_info->detailed_timings[0].pixel_clock)) + /* Unknown EDID version. */ + if (edid_info->header.version != 1) goto done; - *pwidth = GET_EDID_INFO_WIDTH(edid_info, 0); - *pheight = GET_EDID_INFO_HEIGHT(edid_info, 0); - - if (*pwidth > 0 && *pwidth <= EDID_MAX_PIXELS && - *pheight > 0 && *pheight <= EDID_MAX_LINES) - ret = true; + ret = gfx_get_edid_resolution(edid_info, res); done: bio_free(edid_info, sizeof (*edid_info)); return (ret); @@ -596,6 +589,8 @@ vbe_modelist(int depth) int ddc_caps; uint_t width, height; bool edid = false; + edid_res_list_t res; + struct resolution *rp; if (!vbe_check()) return; @@ -608,11 +603,19 @@ vbe_modelist(int depth) if (ddc_caps & 2) printf(" [DDC2]"); - edid = vbe_get_edid(&width, &height); - if (edid) - printf(": EDID %dx%d\n", width, height); - else + TAILQ_INIT(&res); + edid = vbe_get_edid(&res); + if (edid) { + printf(": EDID"); + while ((rp = TAILQ_FIRST(&res)) != NULL) { + printf(" %dx%d", rp->width, rp->height); + TAILQ_REMOVE(&res, rp, next); + free(rp); + } + printf("\n"); + } else { printf(": no EDID information\n"); + } } if (!edid) if (vbe_get_flatpanel(&width, &height)) @@ -744,12 +747,23 @@ vbe_print_mode(void) int vbe_default_mode(void) { + edid_res_list_t res; + struct resolution *rp; int modenum; uint_t width, height; modenum = 0; - if (vbe_get_edid(&width, &height)) - modenum = vbe_find_mode_xydm(width, height, -1, -1); + TAILQ_INIT(&res); + if (vbe_get_edid(&res)) { + while ((rp = TAILQ_FIRST(&res)) != NULL) { + if (modenum == 0) { + modenum = vbe_find_mode_xydm( + rp->width, rp->height, -1, -1); + } + TAILQ_REMOVE(&res, rp, next); + free(rp); + } + } if (modenum == 0 && vbe_get_flatpanel(&width, &height)) { diff --git a/usr/src/lib/fm/topo/modules/i86pc/chip/chip.c b/usr/src/lib/fm/topo/modules/i86pc/chip/chip.c index c81f01c3e9..183bace316 100644 --- a/usr/src/lib/fm/topo/modules/i86pc/chip/chip.c +++ b/usr/src/lib/fm/topo/modules/i86pc/chip/chip.c @@ -23,6 +23,7 @@ * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * Copyright 2019, Joyent, Inc. + * Copyright 2020 Oxide Computer Company */ #include <unistd.h> @@ -482,7 +483,8 @@ create_chip(topo_mod_t *mod, tnode_t *pnode, topo_instance_t min, nvlist_t *fmri = NULL; int err, perr, nerr = 0; int32_t chipid, procnodeid, procnodes_per_pkg; - const char *vendor, *brand; + const char *vendor; + char *brand, *socket; int32_t family, model; boolean_t create_mc = B_FALSE; uint16_t smbios_id; @@ -549,16 +551,24 @@ create_chip(topo_mod_t *mod, tnode_t *pnode, topo_instance_t min, NULL, CHIP_FAMILY, CHIP_MODEL, CHIP_STEPPING, NULL); /* - * Attempt to lookup the processor brand string in kstats. - * and add it as a prop, if found. + * Attempt to lookup the processor brand and socket string in + * kstats and add it as a prop, if found. */ - brand = get_chip_brand(mod, kc, chipid); + brand = socket = NULL; + get_chip_kstat_strs(mod, kc, chipid, &brand, &socket); if (brand != NULL && topo_prop_set_string(chip, PGNAME(CHIP), CHIP_BRAND, TOPO_PROP_IMMUTABLE, brand, &perr) != 0) { whinge(mod, &nerr, "failed to set prop %s/%s", PGNAME(CHIP), CHIP_BRAND); } - topo_mod_strfree(mod, (char *)brand); + topo_mod_strfree(mod, brand); + + if (socket != NULL && topo_prop_set_string(chip, PGNAME(CHIP), + CHIP_SOCKET, TOPO_PROP_IMMUTABLE, socket, &perr) != 0) { + whinge(mod, &nerr, "failed to set prop %s/%s", + PGNAME(CHIP), CHIP_SOCKET); + } + topo_mod_strfree(mod, socket); if (FM_AWARE_SMBIOS(mod)) { int fru = 0; diff --git a/usr/src/lib/fm/topo/modules/i86pc/chip/chip.h b/usr/src/lib/fm/topo/modules/i86pc/chip/chip.h index b4fd850996..efabfbc6d9 100644 --- a/usr/src/lib/fm/topo/modules/i86pc/chip/chip.h +++ b/usr/src/lib/fm/topo/modules/i86pc/chip/chip.h @@ -21,6 +21,7 @@ /* * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2019, Joyent, Inc. + * Copyright 2020 Oxide Computer Company */ #ifndef _CHIP_H @@ -74,6 +75,7 @@ extern "C" { #define CHIP_FAMILY "family" #define CHIP_MODEL "model" #define CHIP_NCORE "ncore_per_chip" +#define CHIP_SOCKET "socket" #define CHIP_STEPPING "stepping" #define CHIP_VENDOR_ID "vendor_id" @@ -158,7 +160,8 @@ extern int mkrsrc(topo_mod_t *, tnode_t *, const char *, int, nvlist_t *, nvlist_t **); extern nvlist_t *cpu_fmri_create(topo_mod_t *, uint32_t, char *, uint8_t); extern boolean_t is_xpv(); -extern const char *get_chip_brand(topo_mod_t *, kstat_ctl_t *, int32_t); +extern void get_chip_kstat_strs(topo_mod_t *, kstat_ctl_t *, int32_t, char **, + char **); /* * topo methods diff --git a/usr/src/lib/fm/topo/modules/i86pc/chip/chip_subr.c b/usr/src/lib/fm/topo/modules/i86pc/chip/chip_subr.c index 53fd7852ef..90be5dca92 100644 --- a/usr/src/lib/fm/topo/modules/i86pc/chip/chip_subr.c +++ b/usr/src/lib/fm/topo/modules/i86pc/chip/chip_subr.c @@ -23,6 +23,7 @@ * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * Copyright 2019, Joyent, Inc. + * Copyright 2020 Oxide Computer Company */ /* @@ -865,18 +866,41 @@ out: return (set_retnvl(mod, out, TOPO_METH_REPLACED_RET, ret)); } -const char * -get_chip_brand(topo_mod_t *mod, kstat_ctl_t *kc, int32_t chipid) +void +get_chip_kstat_strs(topo_mod_t *mod, kstat_ctl_t *kc, int32_t chipid, + char **brandp, char **sktp) { kstat_t *ksp; kstat_named_t *ks; + uint_t i; - if ((ksp = kstat_lookup(kc, "cpu_info", chipid, NULL)) == NULL || - kstat_read(kc, ksp, NULL) == -1 || - (ks = kstat_data_lookup(ksp, "brand")) == NULL) { - topo_mod_dprintf(mod, "failed to read stat cpu_info:%d:brand", - chipid); - return (NULL); + for (i = 0, ksp = kc->kc_chain; ksp != NULL; ksp = ksp->ks_next, i++) { + if (strcmp(ksp->ks_module, "cpu_info") != 0) + continue; + + if (kstat_read(kc, ksp, NULL) == -1) { + topo_mod_dprintf(mod, "failed to read stat cpu_info:%u", + i); + continue; + } + + if ((ks = kstat_data_lookup(ksp, "chip_id")) == NULL || + chipid != ks->value.i32) { + continue; + } + + if ((ks = kstat_data_lookup(ksp, "brand")) != NULL) { + *brandp = topo_mod_strdup(mod, ks->value.str.addr.ptr); + + } + + if ((ks = kstat_data_lookup(ksp, "socket_type")) != NULL) { + if (strcmp(ks->value.str.addr.ptr, "Unknown") != 0) { + *sktp = topo_mod_strdup(mod, + ks->value.str.addr.ptr); + } + } + + return; } - return (topo_mod_strdup(mod, ks->value.str.addr.ptr)); } diff --git a/usr/src/man/man2/open.2 b/usr/src/man/man2/open.2 index 0e13f5af79..aa9048c660 100644 --- a/usr/src/man/man2/open.2 +++ b/usr/src/man/man2/open.2 @@ -52,7 +52,6 @@ .SH NAME open, openat \- open a file .SH SYNOPSIS -.LP .nf #include <sys/types.h> #include <sys/stat.h> @@ -68,7 +67,6 @@ open, openat \- open a file .fi .SH DESCRIPTION -.LP The \fBopen()\fR function establishes the connection between a file and a file descriptor. It creates an open file description that refers to a file and a file descriptor that refers to that open file description. The file descriptor @@ -526,13 +524,11 @@ Certain flag values can be set following \fBopen()\fR as described in The largest value that can be represented correctly in an object of type \fBoff_t\fR is established as the offset maximum in the open file description. .SH RETURN VALUES -.LP Upon successful completion, both \fBopen()\fR and \fBopenat()\fR functions open the file and return a non-negative integer representing the lowest numbered unused file descriptor. Otherwise, \fB\(mi1\fR is returned, \fBerrno\fR is set to indicate the error, and no files are created or modified. .SH ERRORS -.LP The \fBopen()\fR and \fBopenat()\fR functions will fail if: .sp .ne 2 @@ -570,15 +566,6 @@ conflicts with an existing \fBf_deny\fR share reservation. .sp .ne 2 .na -\fB\fBEBADF\fR\fR -.ad -.RS 16n -The file descriptor provided to \fBopenat()\fR is invalid. -.RE - -.sp -.ne 2 -.na \fB\fBEDQUOT\fR\fR .ad .RS 16n @@ -917,7 +904,6 @@ The file is a pure procedure (shared text) file that is being executed and .RE .SH EXAMPLES -.LP \fBExample 1 \fROpen a file for writing by the owner. .sp .LP @@ -1004,12 +990,10 @@ if ((pfd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, .in -2 .SH USAGE -.LP The \fBopen()\fR function has a transitional interface for 64-bit file offsets. See \fBlf64\fR(5). Note that using \fBopen64()\fR is equivalent to using \fBopen()\fR with \fBO_LARGEFILE\fR set in \fIoflag\fR. .SH ATTRIBUTES -.LP See \fBattributes\fR(5) for descriptions of the following attributes: .sp @@ -1028,7 +1012,6 @@ Standard For \fBopen()\fR, see \fBstandards\fR(5). .TE .SH SEE ALSO -.LP \fBIntro\fR(2), \fBchmod\fR(2), \fBclose\fR(2), \fBcreat\fR(2), \fBdup\fR(2), \fBexec\fR(2), \fBfcntl\fR(2), \fBgetmsg\fR(2), \fBgetrlimit\fR(2), \fBlseek\fR(2), \fBputmsg\fR(2), \fBread\fR(2), \fBstat\fR(2), \fBumask\fR(2), @@ -1037,7 +1020,6 @@ Standard For \fBopen()\fR, see \fBstandards\fR(5). \fBunlockpt\fR(3C), \fBattributes\fR(5), \fBlf64\fR(5), \fBprivileges\fR(5), \fBstandards\fR(5), \fBconnld\fR(7M), \fBstreamio\fR(7I) .SH NOTES -.LP Hierarchical Storage Management (HSM) file systems can sometimes cause long delays when opening a file, since HSM files must be recalled from secondary storage. diff --git a/usr/src/uts/i86pc/os/cpuid_subr.c b/usr/src/uts/i86pc/os/cpuid_subr.c index 6343051ef2..83b3e115eb 100644 --- a/usr/src/uts/i86pc/os/cpuid_subr.c +++ b/usr/src/uts/i86pc/os/cpuid_subr.c @@ -34,6 +34,7 @@ * Copyright 2012 Jens Elkner <jel+illumos@cs.uni-magdeburg.de> * Copyright 2012 Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org> * Copyright 2019 Joyent, Inc. + * Copyright 2020 Oxide Computer Company */ /* @@ -61,6 +62,7 @@ #include <sys/bitmap.h> #include <sys/x86_archext.h> #include <sys/pci_cfgspace.h> +#include <sys/sysmacros.h> #ifdef __xpv #include <sys/hypervisor.h> #endif @@ -82,13 +84,14 @@ * 11 for family 0x16, models 00 - 0f * 12 for family 0x16, models 30 - 3f * 13 for family 0x17, models 00 - 0f - * 14 for family 0x17, models 10 - 1f + * 14 for family 0x17, models 10 - 2f * 15 for family 0x17, models 30 - 3f - * 16 for family 0x17, models 70 - 7f + * 16 for family 0x17, models 60 - 6f + * 17 for family 0x17, models 70 - 7f * Second index by (model & 0x3) for family 0fh, * CPUID pkg bits (Fn8000_0001_EBX[31:28]) for later families. */ -static uint32_t amd_skts[17][8] = { +static uint32_t amd_skts[18][8] = { /* * Family 0xf revisions B through E */ @@ -298,7 +301,9 @@ static uint32_t amd_skts[17][8] = { }, /* - * Family 0x17 models 10-1f (Zen 1 - APU: Raven Ridge) + * Family 0x17 models 10-2f (Zen 1 - APU: Raven Ridge) + * (Zen 1 - APU: Banded Kestrel) + * (Zen 1 - APU: Dali) */ #define A_SKTS_14 14 { @@ -328,10 +333,25 @@ static uint32_t amd_skts[17][8] = { }, /* - * Family 0x17 models 70-7f (Zen 2 - Matisse) + * Family 0x17 models 60-6f (Zen 2 - Renoir) */ #define A_SKTS_16 16 { + X86_SOCKET_FP6, /* 0b000 */ + X86_SOCKET_UNKNOWN, /* 0b001 */ + X86_SOCKET_AM4, /* 0b010 */ + X86_SOCKET_UNKNOWN, /* 0b011 */ + X86_SOCKET_UNKNOWN, /* 0b100 */ + X86_SOCKET_UNKNOWN, /* 0b101 */ + X86_SOCKET_UNKNOWN, /* 0b110 */ + X86_SOCKET_UNKNOWN /* 0b111 */ + }, + + /* + * Family 0x17 models 70-7f (Zen 2 - Matisse) + */ +#define A_SKTS_17 17 + { X86_SOCKET_UNKNOWN, /* 0b000 */ X86_SOCKET_UNKNOWN, /* 0b001 */ X86_SOCKET_AM4, /* 0b010 */ @@ -347,7 +367,7 @@ struct amd_sktmap_s { uint32_t skt_code; char sktstr[16]; }; -static struct amd_sktmap_s amd_sktmap[X86_NUM_SOCKETS_AMD + 1] = { +static struct amd_sktmap_s amd_sktmap_strs[X86_NUM_SOCKETS_AMD + 1] = { { X86_SOCKET_754, "754" }, { X86_SOCKET_939, "939" }, { X86_SOCKET_940, "940" }, @@ -380,9 +400,34 @@ static struct amd_sktmap_s amd_sktmap[X86_NUM_SOCKETS_AMD + 1] = { { X86_SOCKET_SP3, "SP3" }, { X86_SOCKET_SP3R2, "SP3r2" }, { X86_SOCKET_FP5, "FP5" }, + { X86_SOCKET_FP6, "FP6" }, { X86_SOCKET_UNKNOWN, "Unknown" } }; +static const struct amd_skt_mapent { + uint_t sm_family; + uint_t sm_modello; + uint_t sm_modelhi; + uint_t sm_sktidx; +} amd_sktmap[] = { + { 0x10, 0x00, 0xff, A_SKTS_2 }, + { 0x11, 0x00, 0xff, A_SKTS_3 }, + { 0x12, 0x00, 0xff, A_SKTS_4 }, + { 0x14, 0x00, 0x0f, A_SKTS_5 }, + { 0x15, 0x00, 0x0f, A_SKTS_6 }, + { 0x15, 0x10, 0x1f, A_SKTS_7 }, + { 0x15, 0x30, 0x3f, A_SKTS_8 }, + { 0x15, 0x60, 0x6f, A_SKTS_9 }, + { 0x15, 0x70, 0x7f, A_SKTS_10 }, + { 0x16, 0x00, 0x0f, A_SKTS_11 }, + { 0x16, 0x30, 0x3f, A_SKTS_12 }, + { 0x17, 0x00, 0x0f, A_SKTS_13 }, + { 0x17, 0x10, 0x2f, A_SKTS_14 }, + { 0x17, 0x30, 0x3f, A_SKTS_15 }, + { 0x17, 0x60, 0x6f, A_SKTS_16 }, + { 0x17, 0x70, 0x7f, A_SKTS_17 } +}; + /* * Table for mapping AMD Family 0xf and AMD Family 0x10 model/stepping * combination to chip "revision" and socket type. @@ -398,7 +443,7 @@ static const struct amd_rev_mapent { uint_t rm_stephi; uint32_t rm_chiprev; const char *rm_chiprevstr; - int rm_sktidx; + uint_t rm_sktidx; } amd_revmap[] = { /* * =============== AuthenticAMD Family 0xf =============== @@ -547,8 +592,79 @@ static const struct amd_rev_mapent { A_SKTS_15 }, { 0x17, 0x31, 0x31, 0x0, 0x0, X86_CHIPREV_AMD_17_SSP_B0, "SSP-B0", A_SKTS_15 }, + + { 0x17, 0x71, 0x71, 0x0, 0x0, X86_CHIPREV_AMD_17_MTS_B0, "MTS-B0", + A_SKTS_17 } }; +/* + * AMD keeps the socket type in CPUID Fn8000_0001_EBX, bits 31:28. + */ +static uint32_t +synth_amd_skt_cpuid(uint_t family, uint_t sktid) +{ + struct cpuid_regs cp; + uint_t idx; + + cp.cp_eax = 0x80000001; + (void) __cpuid_insn(&cp); + + /* PkgType bits */ + idx = BITX(cp.cp_ebx, 31, 28); + + if (idx > 7) { + return (X86_SOCKET_UNKNOWN); + } + + if (family == 0x10) { + uint32_t val; + + val = pci_getl_func(0, 24, 2, 0x94); + if (BITX(val, 8, 8)) { + if (amd_skts[sktid][idx] == X86_SOCKET_AM2R2) { + return (X86_SOCKET_AM3); + } else if (amd_skts[sktid][idx] == X86_SOCKET_S1g3) { + return (X86_SOCKET_S1g4); + } + } + } + + return (amd_skts[sktid][idx]); +} + +static void +synth_amd_skt(uint_t family, uint_t model, uint32_t *skt_p) +{ + int platform; + const struct amd_skt_mapent *skt; + uint_t i; + + if (skt_p == NULL || family < 0xf) + return; + +#ifdef __xpv + /* PV guest */ + if (!is_controldom()) { + *skt_p = X86_SOCKET_UNKNOWN; + return; + } +#endif + platform = get_hwenv(); + + if ((platform & HW_VIRTUAL) != 0) { + *skt_p = X86_SOCKET_UNKNOWN; + return; + } + + for (i = 0, skt = amd_sktmap; i < ARRAY_SIZE(amd_sktmap); + i++, skt++) { + if (family == skt->sm_family && + model >= skt->sm_modello && model <= skt->sm_modelhi) { + *skt_p = synth_amd_skt_cpuid(family, skt->sm_sktidx); + } + } +} + static void synth_amd_info(uint_t family, uint_t model, uint_t step, uint32_t *skt_p, uint32_t *chiprev_p, const char **chiprevstr_p) @@ -560,8 +676,7 @@ synth_amd_info(uint_t family, uint_t model, uint_t step, if (family < 0xf) return; - for (i = 0, rmp = amd_revmap; i < sizeof (amd_revmap) / sizeof (*rmp); - i++, rmp++) { + for (i = 0, rmp = amd_revmap; i < ARRAY_SIZE(amd_revmap); i++, rmp++) { if (family == rmp->rm_family && model >= rmp->rm_modello && model <= rmp->rm_modelhi && step >= rmp->rm_steplo && step <= rmp->rm_stephi) { @@ -570,8 +685,10 @@ synth_amd_info(uint_t family, uint_t model, uint_t step, } } - if (!found) + if (!found) { + synth_amd_skt(family, model, skt_p); return; + } if (chiprev_p != NULL) *chiprev_p = rmp->rm_chiprev; @@ -595,41 +712,7 @@ synth_amd_info(uint_t family, uint_t model, uint_t step, } else if (family == 0xf) { *skt_p = amd_skts[rmp->rm_sktidx][model & 0x3]; } else { - /* - * Starting with family 10h, socket type is stored in - * CPUID Fn8000_0001_EBX - */ - struct cpuid_regs cp; - int idx; - - cp.cp_eax = 0x80000001; - (void) __cpuid_insn(&cp); - - /* PkgType bits */ - idx = BITX(cp.cp_ebx, 31, 28); - - if (idx > 7) { - /* Reserved bits */ - *skt_p = X86_SOCKET_UNKNOWN; - } else { - *skt_p = amd_skts[rmp->rm_sktidx][idx]; - } - if (family == 0x10) { - /* - * Look at Ddr3Mode bit of DRAM Configuration - * High Register to decide whether this is - * actually AM3 or S1g4. - */ - uint32_t val; - - val = pci_getl_func(0, 24, 2, 0x94); - if (BITX(val, 8, 8)) { - if (*skt_p == X86_SOCKET_AM2R2) - *skt_p = X86_SOCKET_AM3; - else if (*skt_p == X86_SOCKET_S1g3) - *skt_p = X86_SOCKET_S1g4; - } - } + *skt_p = synth_amd_skt_cpuid(family, rmp->rm_sktidx); } } } @@ -663,7 +746,7 @@ _cpuid_sktstr(uint_t vendor, uint_t family, uint_t model, uint_t step) case X86_VENDOR_AMD: synth_amd_info(family, model, step, &skt, NULL, NULL); - sktmapp = amd_sktmap; + sktmapp = amd_sktmap_strs; while (sktmapp->skt_code != X86_SOCKET_UNKNOWN) { if (sktmapp->skt_code == skt) break; diff --git a/usr/src/uts/intel/sys/x86_archext.h b/usr/src/uts/intel/sys/x86_archext.h index f5e4a4b153..eed3c5fd4e 100644 --- a/usr/src/uts/intel/sys/x86_archext.h +++ b/usr/src/uts/intel/sys/x86_archext.h @@ -962,6 +962,9 @@ extern "C" { #define X86_CHIPREV_AMD_17_SSP_B0 \ _X86_CHIPREV_MKREV(X86_VENDOR_AMD, 0x17, 0x0008) +#define X86_CHIPREV_AMD_17_MTS_B0 \ + _X86_CHIPREV_MKREV(X86_VENDOR_AMD, 0x17, 0x0009) + /* * Various socket/package types, extended as the need to distinguish * a new type arises. The top 8 byte identfies the vendor and the @@ -1017,7 +1020,8 @@ extern "C" { #define X86_SOCKET_SP3 _X86_SOCKET_MKVAL(X86_VENDOR_AMD, 0x1f) #define X86_SOCKET_SP3R2 _X86_SOCKET_MKVAL(X86_VENDOR_AMD, 0x20) #define X86_SOCKET_FP5 _X86_SOCKET_MKVAL(X86_VENDOR_AMD, 0x21) -#define X86_NUM_SOCKETS_AMD 0x22 +#define X86_SOCKET_FP6 _X86_SOCKET_MKVAL(X86_VENDOR_AMD, 0x22) +#define X86_NUM_SOCKETS_AMD 0x23 /* |
