diff options
Diffstat (limited to 'usr/src')
31 files changed, 805 insertions, 582 deletions
diff --git a/usr/src/cmd/prtvtoc/Makefile b/usr/src/cmd/prtvtoc/Makefile index 1a64695fa6..adf9f5396a 100644 --- a/usr/src/cmd/prtvtoc/Makefile +++ b/usr/src/cmd/prtvtoc/Makefile @@ -31,11 +31,7 @@ RELUSRSBIN= ../usr/sbin ROOTSYMLINK= $(ROOTETC)/$(PROG) LDLIBS += -ladm -lefi -CERRWARN += -_gcc=-Wno-parentheses -CERRWARN += $(CNOWARN_UNINIT) - -# not linted -SMATCH=off +CSTD = $(CSTD_GNU99) .KEEP_STATE: diff --git a/usr/src/cmd/prtvtoc/prtvtoc.c b/usr/src/cmd/prtvtoc/prtvtoc.c index 531fd244e8..16a1a5a4c3 100644 --- a/usr/src/cmd/prtvtoc/prtvtoc.c +++ b/usr/src/cmd/prtvtoc/prtvtoc.c @@ -18,12 +18,12 @@ * * CDDL HEADER END */ -/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ -/* All Rights Reserved */ +/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ +/* All Rights Reserved */ -/* Copyright (c) 1984 AT&T */ -/* All Rights Reserved */ +/* Copyright (c) 1984 AT&T */ +/* All Rights Reserved */ /* @@ -42,6 +42,7 @@ #include <string.h> #include <stdio.h> #include <limits.h> +#include <err.h> #include <sys/types.h> #include <sys/stat.h> @@ -56,10 +57,10 @@ * Assumes V_NUMPAR must be a power of 2. * * for V_NUMPAR = 8, we have - * parttn(x)=(x & 0x07) noparttn(x)=(x & 0x3fff8) + * parttn(x)=(x & 0x07) noparttn(x)=(x & 0x3fff8) * * for V_NUMPAR = 16, we have - * parttn(x)=(x & 0x0f) noparttn(x)=(x & 0x3fff0) + * parttn(x)=(x & 0x0f) noparttn(x)=(x & 0x3fff0) */ #define parttn(x) (x % V_NUMPAR) #define noparttn(x) (x & (MAXMIN & ~(V_NUMPAR-1))) @@ -86,8 +87,11 @@ static int readgeom(int, char *, struct dk_geom *); static int readvtoc(int, char *, struct extvtoc *); static int readefi(int, char *, struct dk_gpt **); static void usage(void); -static int warn(char *, char *); -static char *safe_strdup(char *); +static char *safe_strdup(const char *, const char *); +static void *safe_calloc(const char *, size_t, size_t); + +#define SAFE_STRDUP(a) safe_strdup(__func__, (a)) +#define SAFE_CALLOC(a, b) safe_calloc(__func__, (a), (b)) /* * External variables. @@ -101,19 +105,15 @@ static short hflag; /* Omit headers */ static short sflag; /* Omit all but the column header */ static char *fstab = VFSTAB; /* Fstab pathname */ static char *mnttab = MNTTAB; /* mnttab pathname */ -static char *progname; /* Last qualifier of arg0 */ int -main(int ac, char **av) +main(int argc, char *argv[]) { - int idx; + int status = EXIT_SUCCESS; + int c; - if (progname = strrchr(av[0], '/')) - ++progname; - else - progname = av[0]; - while ((idx = getopt(ac, av, "fhst:m:")) != -1) - switch (idx) { + while ((c = getopt(argc, argv, "fhst:m:")) != -1) { + switch (c) { case 'f': ++fflag; break; @@ -132,12 +132,18 @@ main(int ac, char **av) default: usage(); } - if (optind >= ac) + } + + if (optind >= argc) usage(); - idx = 0; - while (optind < ac) - idx |= prtvtoc(av[optind++]); - return (idx == 0 ? 0 : 1); + + for (int i = optind; i < argc; i++) { + if (prtvtoc(argv[i]) != 0) { + status = EXIT_FAILURE; + } + } + + return (status); } static freemap_t *freemap; @@ -147,36 +153,38 @@ static freemap_t *freemap; static freemap_t * findfree(struct dk_geom *geom, struct extvtoc *vtoc) { - struct extpartition *part; - struct extpartition **list; - freemap_t *freeidx; - diskaddr_t fullsize; - ulong_t cylsize; - struct extpartition *sorted[V_NUMPAR + 1]; - - freemap = calloc(sizeof (freemap_t), V_NUMPAR + 1); - cylsize = (geom->dkg_nsect) * (geom->dkg_nhead); - fullsize = (diskaddr_t)(geom->dkg_ncyl) * cylsize; + struct extpartition *part; + struct extpartition **list; + freemap_t *freeidx; + diskaddr_t fullsize; + ulong_t cylsize; + struct extpartition *sorted[V_NUMPAR + 1]; + if (vtoc->v_nparts > V_NUMPAR) { - (void) warn("putfree()", "Too many partitions on disk!"); - exit(1); + errx(EXIT_FAILURE, "putfree(): Too many partitions on disk!"); } + + freemap = SAFE_CALLOC(sizeof (freemap_t), V_NUMPAR + 1); + cylsize = (geom->dkg_nsect) * (geom->dkg_nhead); + fullsize = (diskaddr_t)(geom->dkg_ncyl) * cylsize; list = sorted; - for (part = vtoc->v_part; part < vtoc->v_part + vtoc->v_nparts; ++part) + for (part = vtoc->v_part; part < vtoc->v_part + vtoc->v_nparts; + ++part) { if (part->p_size && part->p_tag != V_BACKUP) *list++ = part; + } *list = 0; - qsort((char *)sorted, (uint_t)(list - sorted), - sizeof (*sorted), partcmp); + qsort(sorted, list - sorted, sizeof (*sorted), partcmp); freeidx = freemap; freeidx->fr_start = 0; - for (list = sorted; (part = *list) != NULL; ++list) - if (part->p_start <= freeidx->fr_start) + for (list = sorted; (part = *list) != NULL; ++list) { + if (part->p_start <= freeidx->fr_start) { freeidx->fr_start += part->p_size; - else { + } else { freeidx->fr_size = part->p_start - freeidx->fr_start; (++freeidx)->fr_start = part->p_start + part->p_size; } + } if (freeidx->fr_start < fullsize) { freeidx->fr_size = fullsize - freeidx->fr_start; ++freeidx; @@ -191,33 +199,33 @@ findfree(struct dk_geom *geom, struct extvtoc *vtoc) static freemap_t * findfree64(struct dk_gpt *efi) { - struct dk_part *part; - struct dk_part **list; - freemap_t *freeidx; - diskaddr_t fullsize; - struct dk_part **sorted; - - freemap = calloc(sizeof (freemap_t), efi->efi_nparts + 1); - sorted = calloc(sizeof (struct dk_part), efi->efi_nparts + 1); + struct dk_part *part; + struct dk_part **list; + freemap_t *freeidx; + diskaddr_t fullsize; + struct dk_part **sorted; + + freemap = SAFE_CALLOC(sizeof (freemap_t), efi->efi_nparts + 1); + sorted = SAFE_CALLOC(sizeof (struct dk_part), efi->efi_nparts + 1); fullsize = efi->efi_last_u_lba; list = sorted; - for (part = efi->efi_parts; - part < efi->efi_parts + efi->efi_nparts; - ++part) + for (part = efi->efi_parts; part < efi->efi_parts + efi->efi_nparts; + ++part) { if (part->p_size && part->p_tag != V_BACKUP) *list++ = part; + } *list = 0; - qsort((char *)sorted, (uint_t)(list - sorted), - sizeof (*sorted), partcmp64); + qsort(sorted, list - sorted, sizeof (*sorted), partcmp64); freeidx = freemap; freeidx->fr_start = efi->efi_first_u_lba; - for (list = sorted; (part = *list) != NULL; ++list) - if (part->p_start == freeidx->fr_start) + for (list = sorted; (part = *list) != NULL; ++list) { + if (part->p_start == freeidx->fr_start) { freeidx->fr_start += part->p_size; - else { + } else { freeidx->fr_size = part->p_start - freeidx->fr_start; (++freeidx)->fr_start = part->p_start + part->p_size; } + } if (freeidx->fr_start < fullsize) { freeidx->fr_size = fullsize - freeidx->fr_start; ++freeidx; @@ -236,7 +244,6 @@ findfree64(struct dk_gpt *efi) static char ** getmntpt(major_t slot, minor_t nopartminor) { - int idx; FILE *file; char devbuf[PATH_MAX], *item; static char *list[V_NUMPAR]; @@ -244,22 +251,22 @@ getmntpt(major_t slot, minor_t nopartminor) struct mnttab mtab; struct vfstab vtab; - for (idx = 0; idx < V_NUMPAR; ++idx) + for (unsigned idx = 0; idx < V_NUMPAR; ++idx) list[idx] = NULL; /* read mnttab for partition mountpoints */ if ((file = fopen(mnttab, "r")) == NULL) { - (void) warn(mnttab, strerror(errno)); + warn("failed to open %s", mnttab); } else { while (getmntent(file, &mtab) == 0) { item = mtab.mnt_special; - if ((item == NULL) || (mtab.mnt_mountp == NULL)) + if (item == NULL || mtab.mnt_mountp == NULL) continue; /* * Is it from /dev? */ - if (strncmp(item, "/dev/", strlen("/dev/") != 0)) + if (strncmp(item, "/dev/", strlen("/dev/")) != 0) continue; /* @@ -268,25 +275,27 @@ getmntpt(major_t slot, minor_t nopartminor) (void) snprintf(devbuf, sizeof (devbuf), "/dev/r%s", item + strlen("/dev/")); - if ((stat(devbuf, &sb) != 0) || - ((sb.st_mode & S_IFMT) != S_IFCHR)) + if (stat(devbuf, &sb) != 0 || + (sb.st_mode & S_IFMT) != S_IFCHR) { continue; + } /* * device must match input slot and nopartminor */ - if ((major(sb.st_rdev) != slot) || - (noparttn(minor(sb.st_rdev)) != nopartminor)) + if (major(sb.st_rdev) != slot || + noparttn(minor(sb.st_rdev)) != nopartminor) { continue; + } list[parttn(minor(sb.st_rdev))] = - safe_strdup(mtab.mnt_mountp); + SAFE_STRDUP(mtab.mnt_mountp); } (void) fclose(file); } if ((file = fopen(fstab, "r")) == NULL) { - (void) warn(fstab, strerror(errno)); + warn("failed to open %s", fstab); return (list); } @@ -296,7 +305,7 @@ getmntpt(major_t slot, minor_t nopartminor) */ while (getvfsent(file, &vtab) == 0) { item = vtab.vfs_special; - if ((item == NULL) || (vtab.vfs_mountp == NULL)) + if (item == NULL || vtab.vfs_mountp == NULL) continue; if (strncmp(item, "/dev/", strlen("/dev/")) != 0) @@ -308,16 +317,18 @@ getmntpt(major_t slot, minor_t nopartminor) (void) snprintf(devbuf, sizeof (devbuf), "/dev/r%s", item + strlen("/dev/")); - if ((stat(devbuf, &sb) != 0) || - ((sb.st_mode & S_IFMT) != S_IFCHR)) + if (stat(devbuf, &sb) != 0 || + (sb.st_mode & S_IFMT) != S_IFCHR) { continue; + } /* * device must match input slot and nopartminor */ - if ((major(sb.st_rdev) != slot) || - (noparttn(minor(sb.st_rdev)) != nopartminor)) + if (major(sb.st_rdev) != slot || + noparttn(minor(sb.st_rdev)) != nopartminor) { continue; + } /* * use mnttab entry if both tables have entries @@ -325,7 +336,7 @@ getmntpt(major_t slot, minor_t nopartminor) if (list[parttn(minor(sb.st_rdev))] != NULL) continue; - list[parttn(minor(sb.st_rdev))] = safe_strdup(vtab.vfs_mountp); + list[parttn(minor(sb.st_rdev))] = SAFE_STRDUP(vtab.vfs_mountp); } (void) fclose(file); @@ -338,22 +349,31 @@ getmntpt(major_t slot, minor_t nopartminor) static int partcmp(const void *one, const void *two) { - return ((*(struct partition **)one)->p_start - - (*(struct partition **)two)->p_start); + struct partition *p1 = *(struct partition **)one; + struct partition *p2 = *(struct partition **)two; + + if (p1->p_start > p2->p_start) { + return (1); + } else if (p1->p_start < p2->p_start) { + return (-1); + } else { + return (0); + } } static int partcmp64(const void *one, const void *two) { - if ((*(struct dk_part **)one)->p_start > - (*(struct dk_part **)two)->p_start) - return (1); - else if ((*(struct dk_part **)one)->p_start < - (*(struct dk_part **)two)->p_start) - return (-1); - else - return (0); + dk_part_t *p1 = *(dk_part_t **)one; + dk_part_t *p2 = *(dk_part_t **)two; + if (p1->p_start > p2->p_start) { + return (1); + } else if (p1->p_start < p2->p_start) { + return (-1); + } else { + return (0); + } } /* @@ -362,37 +382,46 @@ partcmp64(const void *one, const void *two) static int prtvtoc(char *devname) { - int fd; - int idx; - freemap_t *freemap; - struct stat sb; - struct extvtoc vtoc; - int geo; - struct dk_geom geom; - char *name; - int newvtoc = 0; - struct dk_gpt *efi; + int fd; + int idx; + freemap_t *freemap; + struct stat sb; + struct extvtoc vtoc; + int geo; + struct dk_geom geom; + char *name; + int newvtoc = 0; + struct dk_gpt *efi; name = getfullrawname(devname); - if (name == NULL) - return (warn(devname, - "internal administrative call (getfullrawname) failed")); + if (name == NULL) { + warnx("%s: internal administrative call (getfullrawname) " + "failed", devname); + return (-1); + } if (strcmp(name, "") == 0) name = devname; - if ((fd = open(name, O_NONBLOCK|O_RDONLY)) < 0) - return (warn(name, strerror(errno))); - if (fstat(fd, &sb) < 0) - return (warn(name, strerror(errno))); - if ((sb.st_mode & S_IFMT) != S_IFCHR) - return (warn(name, "Not a raw device")); + if ((fd = open(name, O_NONBLOCK|O_RDONLY)) < 0) { + warn("%s: failed to open device", name); + return (-1); + } + if (fstat(fd, &sb) < 0) { + warn("%s: failed to stat device", name); + return (-1); + } + if ((sb.st_mode & S_IFMT) != S_IFCHR) { + warnx("%s: Not a raw device", name); + return (-1); + } geo = (readgeom(fd, name, &geom) == 0); if (geo) { if ((idx = readvtoc(fd, name, &vtoc)) == VT_ENOTSUP) { idx = (readefi(fd, name, &efi) == 0); newvtoc = 1; - } else + } else { idx = (idx == 0); + } } (void) close(fd); if ((!geo) || (!idx)) @@ -407,14 +436,15 @@ prtvtoc(char *devname) else putfree64(efi, freemap); } else { - if (!newvtoc) + if (!newvtoc) { puttable(&geom, &vtoc, freemap, devname, getmntpt(major(sb.st_rdev), noparttn(minor(sb.st_rdev)))); - else + } else { puttable64(efi, freemap, devname, getmntpt(major(sb.st_rdev), noparttn(minor(sb.st_rdev)))); + } } if (newvtoc) efi_free(efi); @@ -468,6 +498,51 @@ putfree64(struct dk_gpt *efi, freemap_t *freemap) (void) printf("\n"); } +static void +print_table_header() +{ + (void) printf("* First Sector" + " Last\n"); + (void) printf("* Partition Tag Flags Sector Count" + " Sector Mount Directory\n"); +} + +static void +print_table_row(uint_t partition, uint_t tag, uint_t flag, + u_longlong_t first_sector, u_longlong_t sector_count, + u_longlong_t last_sector, const char *mount_dir) +{ + (void) printf(" %6u %4u %02x %11llu %11llu %11llu", + partition, tag, flag, first_sector, sector_count, last_sector); + if (mount_dir != NULL) { + (void) printf(" %s", mount_dir); + } + (void) printf("\n"); +} + +static void +print_freemap(freemap_t *freemap) +{ + if (freemap->fr_size == 0) { + /* + * The freemap is completely empty, so do not print the header. + */ + return; + } + + (void) printf("* Unallocated space:\n" + "* First Sector Last\n" + "* Sector Count Sector\n"); + + do { + (void) printf("* %11llu %11llu %11llu\n", + freemap->fr_start, freemap->fr_size, + freemap->fr_size + freemap->fr_start - 1); + } while ((++freemap)->fr_size != 0); + + (void) printf("*\n"); +} + /* * puttable(): Print a human-readable VTOC. */ @@ -475,54 +550,47 @@ static void puttable(struct dk_geom *geom, struct extvtoc *vtoc, freemap_t *freemap, char *name, char **mtab) { - ushort_t idx; - ulong_t cylsize; + ushort_t idx; + ulong_t cylsize; cylsize = (geom->dkg_nsect) * (geom->dkg_nhead); if (!hflag && !sflag) { (void) printf("* %s", name); - if (*vtoc->v_volume) + if (vtoc->v_volume[0] != '\0') (void) printf(" (volume \"%.8s\")", vtoc->v_volume); (void) printf(" partition map\n"); (void) printf("*\n* Dimensions:\n"); - (void) printf("* %7u bytes/sector\n", vtoc->v_sectorsz); - (void) printf("* %7u sectors/track\n", geom->dkg_nsect); - (void) printf("* %7u tracks/cylinder\n", geom->dkg_nhead); - (void) printf("* %7lu sectors/cylinder\n", cylsize); - (void) printf("* %7u cylinders\n", geom->dkg_pcyl); - (void) printf("* %7u accessible cylinders\n", geom->dkg_ncyl); + (void) printf("* %11u bytes/sector\n", vtoc->v_sectorsz); + (void) printf("* %11u sectors/track\n", geom->dkg_nsect); + (void) printf("* %11u tracks/cylinder\n", geom->dkg_nhead); + (void) printf("* %11lu sectors/cylinder\n", cylsize); + (void) printf("* %11u cylinders\n", geom->dkg_pcyl); + (void) printf("* %11u accessible cylinders\n", geom->dkg_ncyl); (void) printf("*\n* Flags:\n"); (void) printf("* 1: unmountable\n"); (void) printf("* 10: read-only\n*\n"); - if (freemap->fr_size) { - (void) printf("* Unallocated space:\n"); - (void) printf("*\tFirst Sector Last\n"); - (void) printf("*\tSector Count Sector \n"); - do { - (void) printf("* %9llu %9llu %9llu\n", - freemap->fr_start, freemap->fr_size, - freemap->fr_size + freemap->fr_start - 1); - } while ((++freemap)->fr_size); - (void) printf("*\n"); - } + print_freemap(freemap); } - if (!hflag) { - (void) printf(\ -"* First Sector Last\n" -"* Partition Tag Flags Sector Count Sector Mount Directory\n"); + + if (!hflag) { + print_table_header(); } + for (idx = 0; idx < vtoc->v_nparts; ++idx) { - if (vtoc->v_part[idx].p_size == 0) + const char *mount_dir = NULL; + struct extpartition *p = &vtoc->v_part[idx]; + + if (p->p_size == 0) continue; - (void) printf(" %2u %5u %02x %9llu %9llu %9llu", - idx, vtoc->v_part[idx].p_tag, vtoc->v_part[idx].p_flag, - vtoc->v_part[idx].p_start, vtoc->v_part[idx].p_size, - vtoc->v_part[idx].p_start + vtoc->v_part[idx].p_size - 1); - if (mtab && mtab[idx]) - (void) printf(" %s", mtab[idx]); - (void) printf("\n"); + + if (mtab != NULL) { + mount_dir = mtab[idx]; + } + + print_table_row(idx, p->p_tag, p->p_flag, p->p_start, + p->p_size, p->p_start + p->p_size - 1, mount_dir); } } @@ -530,55 +598,47 @@ puttable(struct dk_geom *geom, struct extvtoc *vtoc, freemap_t *freemap, * puttable(): Print a human-readable VTOC. */ static void -puttable64(struct dk_gpt *efi, freemap_t *freemap, char *name, - char **mtab) +puttable64(struct dk_gpt *efi, freemap_t *freemap, char *name, char **mtab) { - ushort_t idx; - if (!hflag && !sflag) { (void) printf("* %s", name); - for (idx = 0; idx < efi->efi_nparts; idx++) - if (efi->efi_parts[idx].p_tag == V_RESERVED && - *efi->efi_parts[idx].p_name) - (void) printf(" (volume \"%.8s\")", + for (uint_t idx = 0; idx < efi->efi_nparts; idx++) { + if (efi->efi_parts[idx].p_tag == V_RESERVED && + efi->efi_parts[idx].p_name[0] != '\0') { + (void) printf(" (volume \"%.8s\")", efi->efi_parts[idx].p_name); + } + } (void) printf(" partition map\n"); (void) printf("*\n* Dimensions:\n"); - (void) printf("* %7u bytes/sector\n", efi->efi_lbasize); - (void) printf("* %llu sectors\n", efi->efi_last_lba + 1); - (void) printf("* %llu accessible sectors\n", + (void) printf("* %11u bytes/sector\n", efi->efi_lbasize); + (void) printf("* %11llu sectors\n", efi->efi_last_lba + 1); + (void) printf("* %11llu accessible sectors\n", efi->efi_last_u_lba - efi->efi_first_u_lba + 1); (void) printf("*\n* Flags:\n"); (void) printf("* 1: unmountable\n"); (void) printf("* 10: read-only\n*\n"); - if (freemap->fr_size) { - (void) printf("* Unallocated space:\n"); - (void) printf("*\tFirst Sector Last\n"); - (void) printf("*\tSector Count Sector \n"); - do { - (void) printf("* %9llu %9llu %9llu\n", - freemap->fr_start, freemap->fr_size, - freemap->fr_size + freemap->fr_start - 1); - } while ((++freemap)->fr_size); - (void) printf("*\n"); - } + print_freemap(freemap); } - if (!hflag) { - (void) printf(\ -"* First Sector Last\n" -"* Partition Tag Flags Sector Count Sector Mount Directory\n"); + + if (!hflag) { + print_table_header(); } - for (idx = 0; idx < efi->efi_nparts; ++idx) { - if (efi->efi_parts[idx].p_size == 0) - continue; - (void) printf(" %2u %5u %02x %9llu %9llu %9llu", - idx, efi->efi_parts[idx].p_tag, efi->efi_parts[idx].p_flag, - efi->efi_parts[idx].p_start, efi->efi_parts[idx].p_size, - efi->efi_parts[idx].p_start + efi->efi_parts[idx].p_size - 1); - if ((idx < 7) && mtab && mtab[idx]) - (void) printf(" %s", mtab[idx]); - (void) printf("\n"); + + for (uint_t idx = 0; idx < efi->efi_nparts; ++idx) { + const char *mount_dir = NULL; + dk_part_t *p = &efi->efi_parts[idx]; + + if (p->p_size == 0) + continue; + + if (idx < 7 && mtab != NULL) { + mount_dir = mtab[idx]; + } + + print_table_row(idx, p->p_tag, p->p_flag, p->p_start, + p->p_size, p->p_start + p->p_size - 1, mount_dir); } } @@ -588,16 +648,16 @@ puttable64(struct dk_gpt *efi, freemap_t *freemap, char *name, static int readgeom(int fd, char *name, struct dk_geom *geom) { - char err_string[128]; - - if ((ioctl(fd, DKIOCGGEOM, geom) < 0) && (errno != ENOTSUP)) { - (void) sprintf(err_string, - "Unable to read Disk geometry errno = 0x%x", - errno); - return (warn(name, err_string)); - } else if (errno == ENOTSUP) { + if (ioctl(fd, DKIOCGGEOM, geom) < 0) { + if (errno != ENOTSUP) { + warnx("%s: Unable to read Disk geometry errno = 0x%x", + name, errno); + return (-1); + } + (void) memset(geom, 0, sizeof (struct dk_geom)); } + return (0); } @@ -607,19 +667,23 @@ readgeom(int fd, char *name, struct dk_geom *geom) static int readvtoc(int fd, char *name, struct extvtoc *vtoc) { - int retval; + int retval; if ((retval = read_extvtoc(fd, vtoc)) >= 0) return (0); switch (retval) { - case (VT_EIO): - return (warn(name, "Unable to read VTOC")); - case (VT_EINVAL): - return (warn(name, "Invalid VTOC")); - case (VT_ERROR): - return (warn(name, "Unknown problem reading VTOC")); + case VT_EIO: + warnx("%s: Unable to read VTOC", name); + return (-1); + case VT_EINVAL: + warnx("%s: Invalid VTOC", name); + return (-1); + case VT_ERROR: + warnx("%s: Unknown problem reading VTOC", name); + return (-1); } + return (retval); } @@ -635,25 +699,64 @@ readefi(int fd, char *name, struct dk_gpt **efi) return (0); switch (retval) { - case (VT_EIO): - return (warn(name, "Unable to read VTOC")); - case (VT_EINVAL): - return (warn(name, "Invalid VTOC")); - case (VT_ERROR): - return (warn(name, "Unknown problem reading VTOC")); + case VT_EIO: + warnx("%s: Unable to read VTOC", name); + return (-1); + case VT_EINVAL: + warnx("%s: Invalid VTOC", name); + return (-1); + case VT_ERROR: + warnx("%s: Unknown problem reading VTOC", name); + return (-1); } + return (retval); } +static void +memory_err(size_t l, int e, const char *fname) +{ + const char *reason; + + switch (e) { + case EAGAIN: + reason = "not enough memory was available, please try again"; + break; + case ENOMEM: + reason = "allocation size was too large"; + break; + default: + reason = strerror(e); + break; + } + + errx(EXIT_FAILURE, "%s: failed to allocate %llu bytes of memory: %s", + fname, (u_longlong_t)l, reason); +} + +static void * +safe_calloc(const char *fname, size_t nelem, size_t elsize) +{ + void *r; + + if ((r = calloc(nelem, elsize)) == NULL) { + memory_err(nelem * elsize, errno, fname); + } + + return (r); +} + static char * -safe_strdup(char *str) +safe_strdup(const char *fname, const char *str) { - char *ret; - if ((ret = strdup(str)) == NULL) { - (void) warn("memory allocation", strerror(errno)); - exit(1); + size_t l = strlen(str); + char *r; + + if ((r = strndup(str, l)) == NULL) { + memory_err(l + 1, errno, fname); } - return (ret); + + return (r); } /* @@ -663,16 +766,6 @@ static void usage() { (void) fprintf(stderr, "Usage:\t%s [ -fhs ] [ -t fstab ] [ -m mnttab ] " - "rawdisk ...\n", progname); + "rawdisk ...\n", getprogname()); exit(1); } - -/* - * warn(): Print an error message. Always returns -1. - */ -static int -warn(char *what, char *why) -{ - (void) fprintf(stderr, "%s: %s: %s\n", progname, what, why); - return (-1); -} diff --git a/usr/src/lib/libc/i386/sys/gettimeofday.c b/usr/src/lib/libc/i386/sys/gettimeofday.c index c2396e582a..a4c62aeb68 100644 --- a/usr/src/lib/libc/i386/sys/gettimeofday.c +++ b/usr/src/lib/libc/i386/sys/gettimeofday.c @@ -40,9 +40,10 @@ gettimeofday(struct timeval *tv, void *tz) * and layout of their members, the conversion can be done in-place. */ if (cp != NULL && __cp_can_gettime(cp) != 0) { - __cp_clock_gettime_realtime(cp, (struct timespec *)tv); + (void) __cp_clock_gettime_realtime(cp, (struct timespec *)tv); } else { - __clock_gettime_sys(CLOCK_REALTIME, (struct timespec *)tv); + (void) __clock_gettime_sys(CLOCK_REALTIME, + (struct timespec *)tv); } /* Convert from tv_nsec to tv_usec */ tv->tv_usec /= 1000; diff --git a/usr/src/man/man1m/dispadmin.1m b/usr/src/man/man1m/dispadmin.1m index 91f260bc01..0f7af2d255 100644 --- a/usr/src/man/man1m/dispadmin.1m +++ b/usr/src/man/man1m/dispadmin.1m @@ -127,11 +127,11 @@ Moreover, the values must describe a table that is the same size (has same number of priority levels) as the table being overwritten. Super-user privileges are required in order to use the \fB-s\fR option. .sp -Specify time quantum values for scheduling classes in system clock ticks, and -not in constant-time units. Time quantum values are based on the value of the -kernel's \fBhz\fR variable. If kernel variable \fBhires_tick\fR is set to -\fB1\fR to get higher resolution clock behavior, the actual time quanta will be -reduced by the order of \fB10\fR. +Time quantum values for scheduling classes are specified in system clock ticks +rather than constant-time units. These values are based on the value of the +kernel's \fBhz\fR variable. By default, the system operates at 1000 Hz and +thus with a quantum of 1 millisecond. If the kernel tunable \fBhires_tick\fR +is set to 0, this drops to 100 Hz for a larger quantum of 10 milliseconds. .sp The \fB-g\fR and \fB-s\fR options are mutually exclusive: you may not retrieve the table at the same time you are overwriting it. diff --git a/usr/src/man/man1m/prtvtoc.1m b/usr/src/man/man1m/prtvtoc.1m index 4f883420c1..8b353d750b 100644 --- a/usr/src/man/man1m/prtvtoc.1m +++ b/usr/src/man/man1m/prtvtoc.1m @@ -3,28 +3,23 @@ .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH PRTVTOC 1M "Jul 25, 2002" +.TH PRTVTOC 1M "Apr 14, 2020" .SH NAME prtvtoc \- report information about a disk geometry and partitioning .SH SYNOPSIS -.LP .nf \fBprtvtoc\fR [\fB-fhs\fR] [\fB-t\fR \fIvfstab\fR] [\fB-m\fR \fImnttab\fR] \fIdevice\fR .fi .SH DESCRIPTION -.sp -.LP The \fBprtvtoc\fR command allows the contents of the label to be viewed. The command can be used only by the super-user. .sp .LP The \fIdevice\fR name can be the file name of a raw device in the form of -\fB/dev/rdsk/c?t?d?s2\fR or can be the file name of a block device in the form -of \fB/dev/dsk/c?t?d?s2\fR. +\fB/dev/rdsk/c*t*d*s2\fR or can be the file name of a block device in the form +of \fB/dev/dsk/c*t*d*s2\fR. .SH OPTIONS -.sp -.LP The following options are supported: .sp .ne 2 @@ -75,7 +70,6 @@ Use \fIvfstab\fR as the list of filesystem defaults, in place of .RE .SH EXAMPLES -.LP \fBExample 1 \fRUsing the \fBprtvtoc\fR Command .sp .LP @@ -88,26 +82,25 @@ disk: example# prtvtoc /dev/rdsk/c0t3d0s2 * /dev/rdsk/c0t3d0s2 partition map * -* Dimension: -* 512 bytes/sector -* 80 sectors/track -* 9 tracks/cylinder -* 720 sectors/cylinder -* 2500 cylinders -* 1151 accessible cylinders +* Dimensions: +* 512 bytes/sector +* 80 sectors/track +* 9 tracks/cylinder +* 720 sectors/cylinder +* 2500 cylinders +* 1151 accessible cylinders * * Flags: * 1: unmountable * 10: read-only -* * First Sector Last -* Partition Tag Flags Sector Count Sector Mount Directory - 0 2 00 0 76320 76319 / - 1 3 01 76320 132480 208799 - 2 5 00 0 828720 828719 - 5 6 00 208800 131760 340559 /opt - 6 4 00 340560 447120 787679 /usr - 7 8 00 787680 41040 828719 /export/home -example# +* First Sector Last +* Partition Tag Flags Sector Count Sector Mount Directory + 0 2 00 0 76320 76319 / + 1 3 01 76320 132480 208799 + 2 5 00 0 828720 828719 + 5 6 00 208800 131760 340559 /opt + 6 4 00 340560 447120 787679 /usr + 7 8 00 787680 41040 828719 /export/home .fi .in -2 .sp @@ -133,7 +126,7 @@ BACKUP 0x05 STAND 0x06 VAR 0x07 HOME 0x08 -ALTSCTR 0x09 +ALTSCTR 0x09 CACHE 0x0a RESERVED 0x0b .TE @@ -185,30 +178,26 @@ example# prtvtoc /dev/rdsk/c1t1d0s2 * /dev/rdsk/c1t1d0s2 partition map * * Dimensions: -* 512 bytes/sector -* 3187630080 sectors -* 3187630013 accessible sectors +* 512 bytes/sector +* 3187630080 sectors +* 3187630013 accessible sectors * * Flags: * 1: unmountable * 10: read-only * -* First Sector Last -* Partition Tag Flags Sector Count Sector Mount Directory -0 2 00 34 262144 262177 -1 3 01 262178 262144 524321 -6 4 00 524322 3187089340 3187613661 -8 11 00 3187613662 16384 318763004 +* First Sector Last +* Partition Tag Flags Sector Count Sector Mount Directory + 0 2 00 34 262144 262177 + 1 3 01 262178 262144 524321 + 6 4 00 524322 3187089340 3187613661 + 8 11 00 3187613662 16384 318763004 .fi .in -2 .sp .SH SEE ALSO -.sp -.LP \fBdevinfo\fR(1M), \fBfmthard\fR(1M), \fBformat\fR(1M), \fBmount\fR(1M), \fBattributes\fR(5) .SH WARNINGS -.sp -.LP The \fBmount\fR command does not check the "not mountable" bit. diff --git a/usr/src/man/man4/fx_dptbl.4 b/usr/src/man/man4/fx_dptbl.4 index 4373e7705c..ce2ad1bc3f 100644 --- a/usr/src/man/man4/fx_dptbl.4 +++ b/usr/src/man/man4/fx_dptbl.4 @@ -7,14 +7,11 @@ .SH NAME fx_dptbl \- fixed priority dispatcher parameter table .SH SYNOPSIS -.LP .nf \fBfx_dptbl\fR .fi .SH DESCRIPTION -.sp -.LP The process scheduler or dispatcher is the portion of the kernel that controls allocation of the CPU to processes. The scheduler supports the notion of scheduling classes, where each class defines a scheduling policy used to @@ -67,9 +64,11 @@ processes at a particular level, as the time quantum of a fixed priority process can be changed by the user with the \fBpriocntl\fR(1) command or the \fBpriocntl\fR(2) system call. .sp -In the high resolution clock mode (\fBhires_tick\fR set to \fB1\fR), the value -of \fBhz\fR is set to \fB1000\fR. Increase quantums to maintain the same -absolute time quantums. +In the default high resolution clock mode (\fBhires_tick\fR set to \fB1\fR), +the value of \fBhz\fR is set to \fB1000\fR. If this value is overridden to +\fB0\fR then \fBhz\fR will instead be \fB100\fR; the number of ticks per +quantum must then be decreased to maintain the same length of quantum in +absolute time. .sp An administrator can affect the behavior of the fixed priority portion of the scheduler by reconfiguring the \fBfx_dptbl\fR. There are two methods available @@ -78,8 +77,6 @@ for doing this: reconfigure with a loadable module at boot-time or by using .RE .SS "fx_dptbl Loadable Module" -.sp -.LP The \fBfx_dptbl\fR can be reconfigured with a loadable module that contains a new fixed priority dispatch table. The module containing the dispatch table is separate from the \fBFX\fR loadable module, which contains the rest of the @@ -88,8 +85,6 @@ number of fixed priority priority levels or the set of global scheduling priorities used by the fixed priority class. The relevant procedure and source code is described in Replacing the fx_dptbl Loadable Module below. .SS "dispadmin Configuration File" -.sp -.LP The \fBfx_quantum\fR values in the \fBfx_dptbl\fR can be examined and modified on a running system using the \fBdispadmin\fR(1M) command. Invoking \fBdispadmin\fR for the fixed-priority class allows the administrator to @@ -141,8 +136,6 @@ positive integer specifying the desired time quantum in the resolution given by See Examples for an example of an excerpt of a \fBdispadmin\fR configuration file. .SS "Replacing the fx_dptbl Loadable Module" -.sp -.LP To change the size of the fixed priority dispatch table, you must build the loadable module that contains the dispatch table information. Save the existing module before using the following procedure. @@ -202,7 +195,6 @@ Reboot the system to use the new dispatch table. Exercise great care in using the preceding method to replace the dispatch table. A mistake can result in panics, thus making the system unusable. .SH EXAMPLES -.LP \fBExample 1 \fRConfiguration File Excerpt .sp .LP @@ -395,15 +387,11 @@ fx_getmaxumdpri() .sp .SH SEE ALSO -.sp -.LP \fBpriocntl\fR(1), \fBdispadmin\fR(1M), \fBpriocntl\fR(2), \fBsystem\fR(4) .sp .LP \fISystem Administration Guide, Volume 1, System Interface Guide\fR .SH NOTES -.sp -.LP In order to improve performance under heavy system load, both the \fBnfsd\fR daemon and the \fBlockd\fR daemon utilize the maximum priority in the \fBFX\fR class. Unusual \fBfx_dptbl\fR configurations may have significant negative diff --git a/usr/src/man/man4/rt_dptbl.4 b/usr/src/man/man4/rt_dptbl.4 index b24b3d72f4..bace4ec80b 100644 --- a/usr/src/man/man4/rt_dptbl.4 +++ b/usr/src/man/man4/rt_dptbl.4 @@ -7,8 +7,6 @@ .SH NAME rt_dptbl \- real-time dispatcher parameter table .SH DESCRIPTION -.sp -.LP The process scheduler (or dispatcher) is the portion of the kernel that controls allocation of the \fBCPU\fR to processes. The scheduler supports the notion of scheduling classes where each class defines a scheduling policy, used @@ -59,9 +57,11 @@ processes at a particular level as the time quantum of a real-time process can be changed by the user with the \fBpriocntl\fR command or the \fBpriocntl\fR system call. .sp -In the high resolution clock mode (\fBhires_tick\fR set to \fB1\fR), the value -of \fBhz\fR is set to \fB1000\fR. Increase quantums to maintain the same -absolute time quantums. +In the default high resolution clock mode (\fBhires_tick\fR set to \fB1\fR), +the value of \fBhz\fR is set to \fB1000\fR. If this value is overridden to +\fB0\fR then \fBhz\fR will instead be \fB100\fR; the number of ticks per +quantum must then be decreased to maintain the same length of quantum in +absolute time. .RE .sp @@ -71,8 +71,6 @@ scheduler by reconfiguring the \fBrt_dptbl\fR. There are two methods available for doing this: reconfigure with a loadable module at boot-time or by using \fBdispadmin\fR(1M) at run-time. .SS "rt_dptbl Loadable Module" -.sp -.LP The \fBrt_dptbl\fR can be reconfigured with a loadable module which contains a new real time dispatch table. The module containing the dispatch table is separate from the RT loadable module which contains the rest of the real time @@ -81,8 +79,6 @@ time priority levels or the set of global scheduling priorities used by the real time class. The relevant procedure and source code is described in the Examples section. .SS "dispadmin Configuration File" -.sp -.LP The \fBrt_quantum\fR values in the \fBrt_dptbl\fR can be examined and modified on a running system using the \fBdispadmin\fR(1M) command. Invoking \fBdispadmin\fR for the real-time class allows the administrator to retrieve @@ -120,7 +116,6 @@ level. Each \fBrt_quantum\fR entry must be either a positive integer specifying the desired time quantum (in the resolution given by \fIres\fR), or the value -2 indicating an infinite time quantum for that level. .SH EXAMPLES -.LP \fBExample 1 \fRA Sample \fBdispadmin\fR Configuration File .sp .LP @@ -341,8 +336,6 @@ rtdpent_t config_rt_dptbl[] = { .in -2 .SH SEE ALSO -.sp -.LP \fBpriocntl\fR(1), \fBdispadmin\fR(1M), \fBpriocntl\fR(2), \fBsystem\fR(4) .sp .LP diff --git a/usr/src/man/man4/ts_dptbl.4 b/usr/src/man/man4/ts_dptbl.4 index f6e7db3482..9dbcc11d15 100644 --- a/usr/src/man/man4/ts_dptbl.4 +++ b/usr/src/man/man4/ts_dptbl.4 @@ -7,8 +7,6 @@ .SH NAME ts_dptbl \- time-sharing dispatcher parameter table .SH DESCRIPTION -.sp -.LP The process scheduler (or dispatcher) is the portion of the kernel that controls allocation of the \fBCPU\fR to processes. The scheduler supports the notion of scheduling classes where each class defines a scheduling policy, used @@ -65,9 +63,11 @@ only member of the \fBts_dptbl\fR which cannot be changed with The length of the time quantum allocated to processes at this level in ticks (\fBhz\fR). .sp -In the high resolution clock mode (\fBhires_tick\fR set to \fB1\fR), the value -of \fBhz\fR is set to \fB1000\fR. Increase quantums to maintain the same -absolute time quantums. +In the default high resolution clock mode (\fBhires_tick\fR set to \fB1\fR), +the value of \fBhz\fR is set to \fB1000\fR. If this value is overridden to +\fB0\fR then \fBhz\fR will instead be \fB100\fR; the number of ticks per +quantum must then be decreased to maintain the same length of quantum in +absolute time. .RE .sp @@ -129,8 +129,6 @@ scheduling classes. There are two methods available for doing this: reconfigure with a loadable module at boot-time or by using \fBdispadmin\fR(1M) at run-time. .SS "ts_dptbl Loadable Module" -.sp -.LP The \fBts_dptbl\fR can be reconfigured with a loadable module which contains a new time sharing dispatch table. The module containing the dispatch table is separate from the TS loadable module which contains the rest of the @@ -140,8 +138,6 @@ scheduling priorities used by the time-sharing and inter-active classes. The relevant procedure and source code is described in the \fBREPLACING THE TS_DPTBL LOADABLE MODULE\fR section. .SS "dispadmin Configuration File" -.sp -.LP With the exception of \fBts_globpri\fR all of the members of the \fBts_dptbl\fR can be examined and modified on a running system using the \fBdispadmin\fR(1M) command. Invoking \fBdispadmin\fR for the time-sharing or inter-active class @@ -177,7 +173,6 @@ parameters for time-sharing level 0, the second line specifies the parameters for time-sharing level 1, etc. There must be exactly one line for each configured time-sharing priority level. .SH EXAMPLES -.LP \fBExample 1 \fRA Sample From a Configuration File .sp .LP @@ -435,8 +430,6 @@ ts_getmaxumdpri() .in -2 .SH SEE ALSO -.sp -.LP \fBpriocntl\fR(1), \fBdispadmin\fR(1M), \fBpriocntl\fR(2), \fBsystem\fR(4) .sp .LP @@ -445,8 +438,6 @@ ts_getmaxumdpri() .LP \fIProgramming Interfaces Guide\fR .SH NOTES -.sp -.LP \fBdispadmin\fR does some limited sanity checking on the values supplied in the configuration file. The sanity checking is intended to ensure that the new \fBts_dptbl\fR values do not cause the system to panic. The sanity checking diff --git a/usr/src/test/libc-tests/runfiles/default.run b/usr/src/test/libc-tests/runfiles/default.run index c819079ef6..7c8f5c6738 100644 --- a/usr/src/test/libc-tests/runfiles/default.run +++ b/usr/src/test/libc-tests/runfiles/default.run @@ -45,7 +45,11 @@ outputdir = /var/tmp/test_results [/opt/libc-tests/tests/random/chacha] [/opt/libc-tests/tests/random/inz_child] [/opt/libc-tests/tests/random/inz_inval] +# +# root privs required for mlock privileges +# [/opt/libc-tests/tests/random/inz_mlock] +user = root [/opt/libc-tests/tests/random/inz_region] [/opt/libc-tests/tests/random/inz_split] [/opt/libc-tests/tests/random/inz_split_vpp] @@ -57,7 +61,11 @@ outputdir = /var/tmp/test_results [/opt/libc-tests/tests/random/arc4random_preforkall] [/opt/libc-tests/tests/random/arc4random_forksig] [/opt/libc-tests/tests/random/arc4random_preforksig] +# +# root privs required for DTrace +# [/opt/libc-tests/tests/random/arc4key.ksh] +user = root [/opt/libc-tests/tests/regex/regex_test] @@ -121,7 +129,11 @@ timeout = 600 [/opt/libc-tests/tests/uchar.32] [/opt/libc-tests/tests/uchar.64] +# +# root privs required for priority changes +# [/opt/libc-tests/tests/pthread_attr_get_np] +user=root [/opt/libc-tests/tests/symbols] pre = setup diff --git a/usr/src/uts/common/conf/param.c b/usr/src/uts/common/conf/param.c index 1120748b98..06920c3574 100644 --- a/usr/src/uts/common/conf/param.c +++ b/usr/src/uts/common/conf/param.c @@ -116,7 +116,7 @@ const unsigned int _diskrpm = (unsigned int)DISKRPM; const unsigned long _pgthresh = (unsigned long)PGTHRESH; const unsigned int _maxslp = (unsigned int)MAXSLP; const unsigned long _maxhandspreadpages = (unsigned long)MAXHANDSPREADPAGES; -const int _ncpu = (int)NCPU; +const int _ncpu = (int)NCPU; const int _ncpu_log2 = (int)NCPU_LOG2; const int _ncpu_p2 = (int)NCPU_P2; const unsigned long _defaultstksz = (unsigned long)DEFAULTSTKSZ; @@ -131,9 +131,12 @@ const unsigned int _nbpg = (unsigned int)MMU_PAGESIZE; */ /* - * Default hz is 100, but if we set hires_tick we get higher resolution - * clock behavior (currently defined to be 1000 hz). Higher values seem - * to work, but are not supported. + * hz is 100, but we set hires_tick to get higher resolution clock behavior + * (currently defined to be 1000 hz). Higher values seem to work, but are not + * supported. + * + * This is configured via hires_tick to allow users to explicitly customize it + * to 0 should the need arise. * * If we do decide to play with higher values, remember that hz should * satisfy the following constraints to avoid integer round-off problems: @@ -160,7 +163,7 @@ const unsigned int _nbpg = (unsigned int)MMU_PAGESIZE; int hz = HZ_DEFAULT; int hires_hz = HIRES_HZ_DEFAULT; -int hires_tick = 0; +int hires_tick = 1; int cpu_decay_factor = 10; /* this is no longer tied to clock */ int max_hres_adj; /* maximum adjustment of hrtime per tick */ int tick_per_msec; /* clock ticks per millisecond (zero if hz < 1000) */ diff --git a/usr/src/uts/common/fs/zfs/zvol.c b/usr/src/uts/common/fs/zfs/zvol.c index 19130289e7..2495fb015d 100644 --- a/usr/src/uts/common/fs/zfs/zvol.c +++ b/usr/src/uts/common/fs/zfs/zvol.c @@ -1161,10 +1161,10 @@ zvol_dumpio(zvol_state_t *zv, void *addr, uint64_t offset, uint64_t size, ASSERT(size <= zv->zv_volblocksize); /* Locate the extent this belongs to */ - ze = list_head(&zv->zv_extents); - while (offset >= ze->ze_nblks * zv->zv_volblocksize) { + for (ze = list_head(&zv->zv_extents); + ze != NULL && offset >= ze->ze_nblks * zv->zv_volblocksize; + ze = list_next(&zv->zv_extents, ze)) { offset -= ze->ze_nblks * zv->zv_volblocksize; - ze = list_next(&zv->zv_extents, ze); } if (ze == NULL) diff --git a/usr/src/uts/common/io/usb/usba/hubdi.c b/usr/src/uts/common/io/usb/usba/hubdi.c index 99d75edce3..5207a51490 100644 --- a/usr/src/uts/common/io/usb/usba/hubdi.c +++ b/usr/src/uts/common/io/usb/usba/hubdi.c @@ -55,48 +55,45 @@ extern boolean_t consconfig_console_is_ready(void); /* * Prototypes for static functions */ -static int usba_hubdi_bus_ctl( - dev_info_t *dip, - dev_info_t *rdip, - ddi_ctl_enum_t op, - void *arg, - void *result); - -static int usba_hubdi_map_fault( - dev_info_t *dip, - dev_info_t *rdip, - struct hat *hat, - struct seg *seg, - caddr_t addr, - struct devpage *dp, - pfn_t pfn, - uint_t prot, - uint_t lock); +static int usba_hubdi_bus_ctl(dev_info_t *dip, + dev_info_t *rdip, + ddi_ctl_enum_t op, + void *arg, + void *result); + +static int usba_hubdi_map_fault(dev_info_t *dip, + dev_info_t *rdip, + struct hat *hat, + struct seg *seg, + caddr_t addr, + struct devpage *dp, + pfn_t pfn, + uint_t prot, + uint_t lock); static int hubd_busop_get_eventcookie(dev_info_t *dip, - dev_info_t *rdip, - char *eventname, - ddi_eventcookie_t *cookie); + dev_info_t *rdip, + char *eventname, + ddi_eventcookie_t *cookie); static int hubd_busop_add_eventcall(dev_info_t *dip, - dev_info_t *rdip, - ddi_eventcookie_t cookie, - void (*callback)(dev_info_t *dip, - ddi_eventcookie_t cookie, void *arg, - void *bus_impldata), - void *arg, ddi_callback_id_t *cb_id); + dev_info_t *rdip, + ddi_eventcookie_t cookie, + void (*callback)(dev_info_t *dip, ddi_eventcookie_t cookie, void *arg, + void *bus_impldata), + void *arg, ddi_callback_id_t *cb_id); static int hubd_busop_remove_eventcall(dev_info_t *dip, - ddi_callback_id_t cb_id); + ddi_callback_id_t cb_id); static int hubd_bus_config(dev_info_t *dip, - uint_t flag, - ddi_bus_config_op_t op, - void *arg, - dev_info_t **child); + uint_t flag, + ddi_bus_config_op_t op, + void *arg, + dev_info_t **child); static int hubd_bus_unconfig(dev_info_t *dip, - uint_t flag, - ddi_bus_config_op_t op, - void *arg); + uint_t flag, + ddi_bus_config_op_t op, + void *arg); static int hubd_bus_power(dev_info_t *dip, void *impl_arg, - pm_bus_power_op_t op, void *arg, void *result); + pm_bus_power_op_t op, void *arg, void *result); static usb_port_t hubd_get_port_num(hubd_t *, struct devctl_iocdata *); static dev_info_t *hubd_get_child_dip(hubd_t *, usb_port_t); @@ -251,14 +248,14 @@ usba_hubdi_unregister(dev_info_t *dip) /*ARGSUSED*/ static int usba_hubdi_map_fault(dev_info_t *dip, - dev_info_t *rdip, - struct hat *hat, - struct seg *seg, - caddr_t addr, - struct devpage *dp, - pfn_t pfn, - uint_t prot, - uint_t lock) + dev_info_t *rdip, + struct hat *hat, + struct seg *seg, + caddr_t addr, + struct devpage *dp, + pfn_t pfn, + uint_t prot, + uint_t lock) { return (DDI_FAILURE); } @@ -269,9 +266,9 @@ usba_hubdi_map_fault(dev_info_t *dip, */ int usba_hubdi_bind_root_hub(dev_info_t *dip, - uchar_t *root_hub_config_descriptor, - size_t config_length, - usb_dev_descr_t *root_hub_device_descriptor) + uchar_t *root_hub_config_descriptor, + size_t config_length, + usb_dev_descr_t *root_hub_device_descriptor) { usba_device_t *usba_device; usba_hcdi_t *hcdi = usba_hcdi_get_hcdi(dip); @@ -1145,10 +1142,10 @@ hubd_post_power(hubd_t *hubd, usb_port_t port, pm_bp_child_pwrchg_t *bpc, */ static int usba_hubdi_bus_ctl(dev_info_t *dip, - dev_info_t *rdip, - ddi_ctl_enum_t op, - void *arg, - void *result) + dev_info_t *rdip, + ddi_ctl_enum_t op, + void *arg, + void *result) { usba_device_t *hub_usba_device = usba_get_usba_device(rdip); dev_info_t *root_hub_dip = hub_usba_device->usb_root_hub_dip; @@ -1294,7 +1291,7 @@ usba_hubdi_bus_ctl(dev_info_t *dip, /* * hubd_config_one: - * enumerate one child according to 'port' + * enumerate one child according to 'port' */ static boolean_t @@ -2625,8 +2622,7 @@ hubd_restore_device_state(dev_info_t *dip, hubd_t *hubd) /* * wait at least 3 frames before accessing devices - * (note that delay's minimal time is one clock tick which - * is 10ms unless hires_tick has been changed) + * (note that delay's minimal time is one clock tick). */ mutex_exit(HUBD_MUTEX(hubd)); delay(drv_usectohz(10000)); @@ -3331,8 +3327,8 @@ hubd_set_hub_depth(hubd_t *hubd) int rval; usb_cr_t completion_reason; usb_cb_flags_t cb_flags; - usba_device_t *ud; - uint16_t depth; + usba_device_t *ud; + uint16_t depth; /* * We only need to set the hub depth devices for hubs that are at least @@ -6044,7 +6040,7 @@ hubd_ready_device(hubd_t *hubd, dev_info_t *child_dip, usba_device_t *child_ud, child_ud->usb_active_cfg_ndx = config_index; child_ud->usb_cfg = child_ud->usb_cfg_array[config_index]; child_ud->usb_cfg_length = config_descriptor.wTotalLength; - child_ud->usb_cfg_value = config_descriptor.bConfigurationValue; + child_ud->usb_cfg_value = config_descriptor.bConfigurationValue; child_ud->usb_n_ifs = config_descriptor.bNumInterfaces; child_ud->usb_dip = child_dip; @@ -6089,11 +6085,11 @@ hubd_ready_device(hubd_t *hubd, dev_info_t *child_dip, usba_device_t *child_ud, */ static int hubd_create_child(dev_info_t *dip, - hubd_t *hubd, - usba_device_t *hubd_ud, - usb_port_status_t port_status, - usb_port_t port, - int iteration) + hubd_t *hubd, + usba_device_t *hubd_ud, + usb_port_status_t port_status, + usb_port_t port, + int iteration) { dev_info_t *child_dip = NULL; usb_dev_descr_t usb_dev_descr; @@ -6869,9 +6865,9 @@ hubd_free_usba_device(hubd_t *hubd, usba_device_t *usba_device) */ static int hubd_busop_get_eventcookie(dev_info_t *dip, - dev_info_t *rdip, - char *eventname, - ddi_eventcookie_t *cookie) + dev_info_t *rdip, + char *eventname, + ddi_eventcookie_t *cookie) { hubd_t *hubd = (hubd_t *)hubd_get_soft_state(dip); @@ -6891,12 +6887,11 @@ hubd_busop_get_eventcookie(dev_info_t *dip, static int hubd_busop_add_eventcall(dev_info_t *dip, - dev_info_t *rdip, - ddi_eventcookie_t cookie, - void (*callback)(dev_info_t *dip, - ddi_eventcookie_t cookie, void *arg, - void *bus_impldata), - void *arg, ddi_callback_id_t *cb_id) + dev_info_t *rdip, + ddi_eventcookie_t cookie, + void (*callback)(dev_info_t *dip, ddi_eventcookie_t cookie, void *arg, + void *bus_impldata), + void *arg, ddi_callback_id_t *cb_id) { hubd_t *hubd = (hubd_t *)hubd_get_soft_state(dip); usb_port_t port = hubd_child_dip2port(hubd, rdip); @@ -7671,7 +7666,7 @@ usba_hubdi_open(dev_info_t *dip, dev_t *devp, int flags, int otyp, /* ARGSUSED */ int usba_hubdi_close(dev_info_t *dip, dev_t dev, int flag, int otyp, - cred_t *credp) + cred_t *credp) { hubd_t *hubd; diff --git a/usr/src/uts/common/os/softint.c b/usr/src/uts/common/os/softint.c index ecdb038c79..8801340cf9 100644 --- a/usr/src/uts/common/os/softint.c +++ b/usr/src/uts/common/os/softint.c @@ -58,29 +58,29 @@ * * Starting state is IDLE. * - * softint() + * softint() * * * (c) - * ____________________________________________________ - * | ^ ^ - * v (a) | (b) | - * IDLE--------------------->PEND--------------------->DRAIN - * ^ | | - * | | | - * | | | - * | | | - * | | | - * | d d - * | | | - * | v v - * | PEND DRAIN - * | (e) & & - * |<-----------------------STEAL STEAL - * ^ | - * | | - * | (e) v - * |_________________________<__________________________| + * ____________________________________________________ + * | ^ ^ + * v (a) | (b) | + * IDLE--------------------->PEND--------------------->DRAIN + * ^ | | + * | | | + * | | | + * | | | + * | | | + * | d d + * | | | + * | v v + * | PEND DRAIN + * | (e) & & + * |<-----------------------STEAL STEAL + * ^ | + * | | + * | (e) v + * |_________________________<__________________________| * * * @@ -146,9 +146,9 @@ uint_t softcall_pokemax = 10; /* * This ensures that softcall entries don't get stuck for long. It's expressed - * in 10 milliseconds as 1 unit. When hires_tick is set or other clock frequency - * is used, softcall_init() ensures that it's still expressed as 1 = 10 milli - * seconds. + * in 10 milliseconds as 1 unit. Regardless of the value of hires_tick or + * clock frequency, softcall_init() ensures that it's still expressed as 1 = + * 10 milliseconds. */ unsigned int softcall_delay = 1; diff --git a/usr/src/uts/i86pc/io/hpet_acpi.c b/usr/src/uts/i86pc/io/hpet_acpi.c index ac5a885a38..aace99b18b 100644 --- a/usr/src/uts/i86pc/io/hpet_acpi.c +++ b/usr/src/uts/i86pc/io/hpet_acpi.c @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2020 Oxide Computer Company */ #include <sys/hpet_acpi.h> @@ -34,6 +35,8 @@ #include <sys/clock.h> #include <sys/archsystm.h> #include <sys/cpupart.h> +#include <sys/x86_archext.h> +#include <sys/prom_debug.h> static int hpet_init_proxy(int *hpet_vect, iflag_t *hpet_flags); static boolean_t hpet_install_proxy(void); @@ -140,17 +143,36 @@ hpet_acpi_init(int *hpet_vect, iflag_t *hpet_flags) (void) memset(&hpet_info, 0, sizeof (hpet_info)); hpet.supported = HPET_NO_SUPPORT; - if (idle_cpu_no_deep_c) + if ((get_hwenv() & HW_XEN_HVM) != 0) { + /* + * In some AWS EC2 guests, though the HPET is advertised via + * ACPI, programming the interrupt on the non-legacy timer can + * result in an immediate reset of the instance. It is not + * currently possible to tell whether this is an instance with + * broken HPET emulation or not, so we simply disable it across + * the board. + */ + PRM_POINT("will not program HPET in Xen HVM"); return (DDI_FAILURE); + } - if (!cpuid_deep_cstates_supported()) + if (idle_cpu_no_deep_c || + !cpuid_deep_cstates_supported()) { + /* + * If Deep C-States are disabled or not supported, then we do + * not need to program the HPET at all as it will not + * subsequently be used. + */ + PRM_POINT("no need to program the HPET"); return (DDI_FAILURE); + } hpet_establish_hooks(); /* * Get HPET ACPI table 1. */ + PRM_POINT("AcpiGetTable() HPET #1"); if (ACPI_FAILURE(AcpiGetTable(ACPI_SIG_HPET, HPET_TABLE_1, (ACPI_TABLE_HEADER **)&hpet_table))) { cmn_err(CE_NOTE, "!hpet_acpi: unable to get ACPI HPET table"); @@ -162,14 +184,18 @@ hpet_acpi_init(int *hpet_vect, iflag_t *hpet_flags) return (DDI_FAILURE); } + PRM_POINT("hpet_memory_map()"); la = hpet_memory_map(hpet_table); + PRM_DEBUG(la); if (la == NULL) { cmn_err(CE_NOTE, "!hpet_acpi: memory map HPET failed"); return (DDI_FAILURE); } hpet_info.logical_address = la; + PRM_POINT("hpet_read_gen_cap()"); ret = hpet_read_gen_cap(&hpet_info); + PRM_DEBUG(ret); hpet_info.gen_cap.counter_clk_period = HPET_GCAP_CNTR_CLK_PERIOD(ret); hpet_info.gen_cap.vendor_id = HPET_GCAP_VENDOR_ID(ret); hpet_info.gen_cap.leg_route_cap = HPET_GCAP_LEG_ROUTE_CAP(ret); @@ -189,6 +215,7 @@ hpet_acpi_init(int *hpet_vect, iflag_t *hpet_flags) } num_timers = (uint_t)hpet_info.gen_cap.num_tim_cap; + PRM_DEBUG(num_timers); if ((num_timers < 3) || (num_timers > 32)) { cmn_err(CE_NOTE, "!hpet_acpi: invalid number of HPET timers " "%lx", (long)num_timers); @@ -197,20 +224,23 @@ hpet_acpi_init(int *hpet_vect, iflag_t *hpet_flags) hpet_info.timer_n_config = (hpet_TN_conf_cap_t *)kmem_zalloc( num_timers * sizeof (uint64_t), KM_SLEEP); + PRM_POINT("hpet_read_gen_config()"); ret = hpet_read_gen_config(&hpet_info); hpet_info.gen_config.leg_rt_cnf = HPET_GCFR_LEG_RT_CNF_BITX(ret); hpet_info.gen_config.enable_cnf = HPET_GCFR_ENABLE_CNF_BITX(ret); /* - * Solaris does not use the HPET Legacy Replacement Route capabilities. + * illumos does not use the HPET Legacy Replacement Route capabilities. * This feature has been off by default on test systems. * The HPET spec does not specify if Legacy Replacement Route is - * on or off by default, so we explicitely set it off here. + * on or off by default, so we explicitly set it off here. * It should not matter which mode the HPET is in since we use * the first available non-legacy replacement timer: timer 2. */ + PRM_POINT("hpet_read_gen_config()"); (void) hpet_set_leg_rt_cnf(&hpet_info, 0); + PRM_POINT("hpet_read_gen_config() again"); ret = hpet_read_gen_config(&hpet_info); hpet_info.gen_config.leg_rt_cnf = HPET_GCFR_LEG_RT_CNF_BITX(ret); hpet_info.gen_config.enable_cnf = HPET_GCFR_ENABLE_CNF_BITX(ret); @@ -218,6 +248,7 @@ hpet_acpi_init(int *hpet_vect, iflag_t *hpet_flags) hpet_info.gen_intrpt_stat = hpet_read_gen_intrpt_stat(&hpet_info); hpet_info.main_counter_value = hpet_read_main_counter_value(&hpet_info); + PRM_POINT("disable timer loop..."); for (ti = 0; ti < num_timers; ++ti) { ret = hpet_read_timer_N_config(&hpet_info, ti); /* @@ -231,6 +262,7 @@ hpet_acpi_init(int *hpet_vect, iflag_t *hpet_flags) hpet_info.timer_n_config[ti] = hpet_convert_timer_N_config(ret); } + PRM_POINT("disable timer loop complete"); /* * Be aware the Main Counter may need to be initialized in the future @@ -238,6 +270,7 @@ hpet_acpi_init(int *hpet_vect, iflag_t *hpet_flags) * The HPET's Main Counter does not need to be initialize to a specific * value before starting it for use to wake up CPUs from Deep C-States. */ + PRM_POINT("hpet_start_main_counter()"); if (hpet_start_main_counter(&hpet_info) != AE_OK) { cmn_err(CE_NOTE, "!hpet_acpi: hpet_start_main_counter failed"); return (DDI_FAILURE); @@ -247,6 +280,7 @@ hpet_acpi_init(int *hpet_vect, iflag_t *hpet_flags) /* * Read main counter twice to record HPET latency for debugging. */ + PRM_POINT("TSC and HPET reads:"); hpet_info.tsc[0] = tsc_read(); hpet_info.hpet_main_counter_reads[0] = hpet_read_main_counter_value(&hpet_info); @@ -255,6 +289,12 @@ hpet_acpi_init(int *hpet_vect, iflag_t *hpet_flags) hpet_read_main_counter_value(&hpet_info); hpet_info.tsc[2] = tsc_read(); + PRM_DEBUG(hpet_info.hpet_main_counter_reads[0]); + PRM_DEBUG(hpet_info.hpet_main_counter_reads[1]); + PRM_DEBUG(hpet_info.tsc[0]); + PRM_DEBUG(hpet_info.tsc[1]); + PRM_DEBUG(hpet_info.tsc[2]); + ret = hpet_read_gen_config(&hpet_info); hpet_info.gen_config.leg_rt_cnf = HPET_GCFR_LEG_RT_CNF_BITX(ret); hpet_info.gen_config.enable_cnf = HPET_GCFR_ENABLE_CNF_BITX(ret); @@ -293,6 +333,7 @@ hpet_acpi_fini(void) static int hpet_init_proxy(int *hpet_vect, iflag_t *hpet_flags) { + PRM_POINT("hpet_get_IOAPIC_intr_capable_timer()"); if (hpet_get_IOAPIC_intr_capable_timer(&hpet_info) == -1) { cmn_err(CE_WARN, "!hpet_acpi: get ioapic intr failed."); return (DDI_FAILURE); @@ -300,6 +341,7 @@ hpet_init_proxy(int *hpet_vect, iflag_t *hpet_flags) hpet_init_proxy_data(); + PRM_POINT("hpet_install_interrupt_handler()"); if (hpet_install_interrupt_handler(&hpet_isr, hpet_info.cstate_timer.intr) != AE_OK) { cmn_err(CE_WARN, "!hpet_acpi: install interrupt failed."); @@ -314,13 +356,16 @@ hpet_init_proxy(int *hpet_vect, iflag_t *hpet_flags) * Avoid a possibly stuck interrupt by programing the HPET's timer here * before the I/O APIC is programmed to handle this interrupt. */ + PRM_POINT("hpet_timer_set_up()"); hpet_timer_set_up(&hpet_info, hpet_info.cstate_timer.timer, hpet_info.cstate_timer.intr); + PRM_POINT("back from hpet_timer_set_up()"); /* * All HPET functionality is supported. */ hpet.supported = HPET_FULL_SUPPORT; + PRM_POINT("HPET full support"); return (DDI_SUCCESS); } @@ -564,14 +609,25 @@ hpet_write_gen_intrpt_stat(hpet_info_t *hip, uint64_t l) } static void -hpet_write_timer_N_config(hpet_info_t *hip, uint_t n, uint64_t l) +hpet_write_timer_N_config(hpet_info_t *hip, uint_t n, uint64_t conf) { - if (hip->timer_n_config[n].size_cap == 1) - *(uint64_t *)HPET_TIMER_N_CONF_ADDRESS( - hip->logical_address, n) = l; - else - *(uint32_t *)HPET_TIMER_N_CONF_ADDRESS( - hip->logical_address, n) = (uint32_t)(0xFFFFFFFF & l); + /* + * The configuration register size is not affected by the size + * capability; it is always a 64-bit value. The top 32-bit half of + * this register is always read-only so we constrain our write to the + * bottom half. + */ + uint32_t *confaddr = (uint32_t *)HPET_TIMER_N_CONF_ADDRESS( + hip->logical_address, n); + uint32_t conf32 = 0xFFFFFFFF & conf; + + PRM_DEBUG(n); + PRM_DEBUG(conf); + PRM_DEBUG(conf32); + + *confaddr = conf32; + + PRM_POINT("write done"); } static void @@ -630,16 +686,19 @@ hpet_install_interrupt_handler(avfunc func, int vector) static int hpet_get_IOAPIC_intr_capable_timer(hpet_info_t *hip) { - int timer; - int intr; + int timer; + int intr; for (timer = HPET_FIRST_NON_LEGACY_TIMER; timer < hip->gen_cap.num_tim_cap; ++timer) { - if (!hpet_timer_available(hip->allocated_timers, timer)) continue; intr = lowbit(hip->timer_n_config[timer].int_route_cap) - 1; + + PRM_DEBUG(timer); + PRM_DEBUG(intr); + if (intr >= 0) { hpet_timer_alloc(&hip->allocated_timers, timer); hip->cstate_timer.timer = timer; @@ -678,7 +737,12 @@ hpet_timer_set_up(hpet_info_t *hip, uint32_t timer_n, uint32_t interrupt) { uint64_t conf; + PRM_DEBUG(timer_n); + PRM_DEBUG(interrupt); + + PRM_POINT("hpet_read_timer_N_config()"); conf = hpet_read_timer_N_config(hip, timer_n); + PRM_DEBUG(conf); /* * Caller is required to verify this interrupt route is supported. @@ -691,7 +755,10 @@ hpet_timer_set_up(hpet_info_t *hip, uint32_t timer_n, uint32_t interrupt) conf &= ~HPET_TIMER_N_INT_ENB_CNF_BIT; /* disabled */ conf |= HPET_TIMER_N_INT_TYPE_CNF_BIT; /* Level Triggered */ + PRM_POINT("hpet_write_timer_N_config()"); + PRM_DEBUG(conf); hpet_write_timer_N_config(hip, timer_n, conf); + PRM_POINT("back from hpet_write_timer_N_config()"); } /* diff --git a/usr/src/uts/i86pc/io/mp_platform_common.c b/usr/src/uts/i86pc/io/mp_platform_common.c index aea7f2e856..9b9944fbd0 100644 --- a/usr/src/uts/i86pc/io/mp_platform_common.c +++ b/usr/src/uts/i86pc/io/mp_platform_common.c @@ -25,6 +25,7 @@ * Copyright (c) 2017 by Delphix. All rights reserved. * Copyright (c) 2019, Joyent, Inc. * Copyright 2020 RackTop Systems, Inc. + * Copyright 2020 Oxide Computer Company */ /* * Copyright (c) 2010, Intel Corporation. @@ -72,6 +73,7 @@ #include <sys/note.h> #include <sys/pci_intr_lib.h> #include <sys/sunndi.h> +#include <sys/prom_debug.h> #if !defined(__xpv) #include <sys/hpet.h> #include <sys/clock.h> @@ -334,7 +336,7 @@ apic_probe_common(char *modname) uint32_t mpct_addr, ebda_start = 0, base_mem_end; caddr_t biosdatap; caddr_t mpct = NULL; - caddr_t fptr; + caddr_t fptr = NULL; int i, mpct_size = 0, mapsize, retval = PSM_FAILURE; ushort_t ebda_seg, base_mem_size; struct apic_mpfps_hdr *fpsp; @@ -342,6 +344,8 @@ apic_probe_common(char *modname) int bypass_cpu_and_ioapics_in_mptables; int acpi_user_options; + PRM_POINT("apic_probe_common()"); + if (apic_forceload < 0) return (retval); @@ -359,11 +363,15 @@ apic_probe_common(char *modname) if (!apic_use_acpi) apic_use_acpi_madt_only = 0; + PRM_POINT("acpi_probe()"); retval = acpi_probe(modname); + PRM_DEBUG(retval); /* in UEFI system, there is no BIOS data */ - if (ddi_prop_exists(DDI_DEV_T_ANY, ddi_root_node(), 0, "efi-systab")) + if (ddi_prop_exists(DDI_DEV_T_ANY, ddi_root_node(), 0, "efi-systab")) { + PRM_POINT("UEFI system!"); goto apic_ret; + } /* * mapin the bios data area 40:0 @@ -371,17 +379,21 @@ apic_probe_common(char *modname) * 40:0Eh - two-byte location for the exact starting address of * the EBDA segment for EISA */ + PRM_POINT("psm_map_phys()"); biosdatap = psm_map_phys(0x400, 0x20, PROT_READ); + PRM_DEBUG(biosdatap); if (!biosdatap) goto apic_ret; fpsp = (struct apic_mpfps_hdr *)NULL; mapsize = MPFPS_RAM_WIN_LEN; /*LINTED: pointer cast may result in improper alignment */ ebda_seg = *((ushort_t *)(biosdatap+0xe)); + PRM_DEBUG(ebda_seg); /* check the 1k of EBDA */ if (ebda_seg) { ebda_start = ((uint32_t)ebda_seg) << 4; fptr = psm_map_phys(ebda_start, MPFPS_RAM_WIN_LEN, PROT_READ); + PRM_DEBUG(fptr); if (fptr) { if (!(fpsp = apic_find_fps_sig(fptr, MPFPS_RAM_WIN_LEN))) @@ -389,6 +401,7 @@ apic_probe_common(char *modname) } } /* If not in EBDA, check the last k of system base memory */ + PRM_DEBUG(fpsp); if (!fpsp) { /*LINTED: pointer cast may result in improper alignment */ base_mem_size = *((ushort_t *)(biosdatap + 0x13)); @@ -402,6 +415,7 @@ apic_probe_common(char *modname) fptr = psm_map_phys(base_mem_end, MPFPS_RAM_WIN_LEN, PROT_READ); + PRM_DEBUG(fptr); if (fptr) { if (!(fpsp = apic_find_fps_sig(fptr, @@ -410,13 +424,16 @@ apic_probe_common(char *modname) } } } + PRM_POINT("psm_unmap_phys()"); psm_unmap_phys(biosdatap, 0x20); /* If still cannot find it, check the BIOS ROM space */ + PRM_DEBUG(fpsp); if (!fpsp) { mapsize = MPFPS_ROM_WIN_LEN; fptr = psm_map_phys(MPFPS_ROM_WIN_START, MPFPS_ROM_WIN_LEN, PROT_READ); + PRM_DEBUG(fptr); if (fptr) { if (!(fpsp = apic_find_fps_sig(fptr, MPFPS_ROM_WIN_LEN))) { @@ -426,13 +443,18 @@ apic_probe_common(char *modname) } } + PRM_DEBUG(fptr); + PRM_DEBUG(fpsp); + PRM_POINT("apic_checksum()"); if (apic_checksum((caddr_t)fpsp, fpsp->mpfps_length * 16) != 0) { + PRM_POINT("psm_unmap_phys()"); psm_unmap_phys(fptr, MPFPS_ROM_WIN_LEN); goto apic_ret; } apic_spec_rev = fpsp->mpfps_spec_rev; if ((apic_spec_rev != 04) && (apic_spec_rev != 01)) { + PRM_POINT("psm_unmap_phys()"); psm_unmap_phys(fptr, MPFPS_ROM_WIN_LEN); goto apic_ret; } @@ -442,7 +464,9 @@ apic_probe_common(char *modname) /* check default configuration (dual CPUs) */ if ((apic_defconf = fpsp->mpfps_featinfo1) != 0) { + PRM_POINT("psm_unmap_phys()"); psm_unmap_phys(fptr, mapsize); + PRM_POINT("apic_handle_defconf()"); if ((retval = apic_handle_defconf()) != PSM_SUCCESS) return (retval); @@ -451,6 +475,7 @@ apic_probe_common(char *modname) /* MP Configuration Table */ mpct_addr = (uint32_t)(fpsp->mpfps_mpct_paddr); + PRM_DEBUG(mpct_addr); psm_unmap_phys(fptr, mapsize); /* unmap floating ptr struct */ @@ -472,6 +497,7 @@ apic_probe_common(char *modname) } mpct_size = (int)hdrp->mpcnf_tbl_length; + PRM_POINT("apic_set_pwroff_method_from_mpcnfhdr()"); apic_set_pwroff_method_from_mpcnfhdr(hdrp); psm_unmap_phys((caddr_t)hdrp, sizeof (struct apic_mp_cnf_hdr)); @@ -497,6 +523,8 @@ apic_probe_common(char *modname) hdrp = (struct apic_mp_cnf_hdr *)mpct; apicadr = (uint32_t *)mapin_apic((uint32_t)hdrp->mpcnf_local_apic, APIC_LOCAL_MEMLEN, PROT_READ | PROT_WRITE); + PRM_DEBUG(hdrp); + PRM_DEBUG(apicadr); if (!apicadr) goto apic_fail1; @@ -509,15 +537,20 @@ apic_probe_common(char *modname) } apic_fail1: + PRM_POINT("apic_fail1:"); psm_unmap_phys(mpct, mpct_size); mpct = NULL; apic_ret: + PRM_POINT("apic_ret:"); if (retval == PSM_SUCCESS) { extern int apic_ioapic_method_probe(); - if ((retval = apic_ioapic_method_probe()) == PSM_SUCCESS) + PRM_POINT("apic_ioapic_method_probe()"); + if ((retval = apic_ioapic_method_probe()) == PSM_SUCCESS) { + PRM_POINT("SUCCESS"); return (PSM_SUCCESS); + } } for (i = 0; i < apic_io_max; i++) @@ -533,6 +566,7 @@ apic_ret: if (mpct) psm_unmap_phys(mpct, mpct_size); + PRM_DEBUG(retval); return (retval); } @@ -632,20 +666,24 @@ acpi_probe(char *modname) if (!apic_use_acpi) return (PSM_FAILURE); + PRM_POINT("AcpiGetTable(MADT)"); if (AcpiGetTable(ACPI_SIG_MADT, 1, (ACPI_TABLE_HEADER **) &acpi_mapic_dtp) != AE_OK) { cmn_err(CE_WARN, "!acpi_probe: No MADT found!"); return (PSM_FAILURE); } + PRM_DEBUG((uint32_t)acpi_mapic_dtp->Address); + PRM_POINT("mapin_apic()"); apicadr = mapin_apic((uint32_t)acpi_mapic_dtp->Address, APIC_LOCAL_MEMLEN, PROT_READ | PROT_WRITE); if (!apicadr) return (PSM_FAILURE); if ((local_ids = (uint32_t *)kmem_zalloc(NCPU * sizeof (uint32_t), - KM_NOSLEEP)) == NULL) + KM_NOSLEEP)) == NULL) { return (PSM_FAILURE); + } if ((proc_ids = (uint32_t *)kmem_zalloc(NCPU * sizeof (uint32_t), KM_NOSLEEP)) == NULL) { @@ -653,7 +691,9 @@ acpi_probe(char *modname) return (PSM_FAILURE); } + PRM_POINT("acpi_get_apic_lid()"); local_ids[0] = acpi_get_apic_lid(); + PRM_DEBUG(local_ids[0]); apic_nproc = 1; apic_io_max = 0; @@ -662,6 +702,7 @@ acpi_probe(char *modname) madt_size = acpi_mapic_dtp->Header.Length; madt_seen = sizeof (*acpi_mapic_dtp); + PRM_DEBUG(madt_size); while (madt_seen < madt_size) { switch (ap->Type) { case ACPI_MADT_TYPE_LOCAL_APIC: @@ -812,6 +853,9 @@ acpi_probe(char *modname) ap = (ACPI_SUBTABLE_HEADER *)(((char *)ap) + ap->Length); } + PRM_DEBUG(apic_nproc); + PRM_DEBUG(apic_io_max); + /* We found multiple enabled cpus via MADT */ if ((apic_nproc > 1) && (apic_io_max > 0)) { acpi_found_smp_config = B_TRUE; @@ -826,6 +870,7 @@ acpi_probe(char *modname) if (plat_dr_support_cpu()) { apic_max_nproc = max_ncpus; } + PRM_DEBUG(apic_max_nproc); apic_cpus_size = max(apic_nproc, max_ncpus) * sizeof (*apic_cpus); if ((apic_cpus = kmem_zalloc(apic_cpus_size, KM_NOSLEEP)) == NULL) goto cleanup; @@ -834,15 +879,21 @@ acpi_probe(char *modname) * ACPI doesn't provide the local apic ver, get it directly from the * local apic */ + PRM_POINT("apic_read(APIC_VERS_REG)"); ver = apic_reg_ops->apic_read(APIC_VERS_REG); + PRM_DEBUG(ver); + PRM_DEBUG(apic_nproc); + PRM_DEBUG(boot_ncpus); for (i = 0; i < apic_nproc; i++) { apic_cpus[i].aci_local_id = local_ids[i]; apic_cpus[i].aci_local_ver = (uchar_t)(ver & 0xFF); apic_cpus[i].aci_processor_id = proc_ids[i]; /* Only build mapping info for CPUs present at boot. */ - if (i < boot_ncpus) + if (i < boot_ncpus) { (void) acpica_map_cpu(i, proc_ids[i]); + } } + PRM_POINT("acpica_map_cpu loop complete"); /* * To support CPU dynamic reconfiguration, the apic CPU info structure @@ -881,8 +932,10 @@ acpi_probe(char *modname) apic_cpus[i].aci_status = APIC_CPU_FREE; } + PRM_POINT("ioapic reads"); for (i = 0; i < apic_io_max; i++) { ioapic_ix = i; + PRM_DEBUG(ioapic_ix); /* * need to check Sitka on the following acpi problem @@ -892,16 +945,20 @@ acpi_probe(char *modname) * actual id directly from the ioapic. */ id = ioapic_read(ioapic_ix, APIC_ID_CMD); + PRM_DEBUG(id); hid = (uchar_t)(id >> 24); + PRM_DEBUG(hid); if (hid != apic_io_id[i]) { if (apic_io_id[i] == 0) apic_io_id[i] = hid; else { /* set ioapic id to whatever reported by ACPI */ id = ((uint32_t)apic_io_id[i]) << 24; + PRM_POINT("ioapic_write(ID)"); ioapic_write(ioapic_ix, APIC_ID_CMD, id); } } + PRM_POINT("ioapic_read(VERS)"); ver = ioapic_read(ioapic_ix, APIC_VERS_CMD); apic_io_ver[i] = (uchar_t)(ver & 0xff); intmax = (ver >> 16) & 0xff; @@ -917,6 +974,7 @@ acpi_probe(char *modname) * acpi-user-options specifies legacy mode * (no SCI, no ACPI mode) */ + PRM_POINT("acpica_get_sci()"); if (acpica_get_sci(&sci, &sci_flags) != AE_OK) sci = -1; @@ -925,6 +983,7 @@ acpi_probe(char *modname) * If this fails, we don't attempt to use ACPI * even if we were able to get a MADT above */ + PRM_POINT("acpica_init()"); if (acpica_init() != AE_OK) { cmn_err(CE_WARN, "!apic: Failed to initialize acpica!"); goto cleanup; @@ -934,6 +993,7 @@ acpi_probe(char *modname) * Call acpica_build_processor_map() now that we have * ACPI namesspace access */ + PRM_POINT("acpica_build_processor_map()"); (void) acpica_build_processor_map(); /* @@ -952,15 +1012,19 @@ acpi_probe(char *modname) if (apic_verbose & APIC_VERBOSE_POWEROFF_PAUSE_FLAG) acpi_verboseflags |= PSM_VERBOSE_POWEROFF_PAUSE_FLAG; + PRM_POINT("acpi_psm_init()"); if (acpi_psm_init(modname, acpi_verboseflags) == ACPI_PSM_FAILURE) goto cleanup; /* Enable ACPI APIC interrupt routing */ + PRM_POINT("apic_acpi_enter_apicmode()"); if (apic_acpi_enter_apicmode() != PSM_FAILURE) { cmn_err(CE_NOTE, "!apic: Using APIC interrupt routing mode"); + PRM_POINT("build_reserved_irqlist()"); build_reserved_irqlist((uchar_t *)apic_reserved_irqlist); apic_enable_acpi = 1; if (apic_sci_vect > 0) { + PRM_POINT("acpica_set_core_feature()"); acpica_set_core_feature(ACPI_FEATURE_SCI_EVENT); } if (apic_use_acpi_madt_only) { @@ -970,16 +1034,18 @@ acpi_probe(char *modname) #if !defined(__xpv) /* - * probe ACPI for hpet information here which is used later - * in apic_picinit(). + * Probe ACPI for HPET information here which is used later in + * apic_picinit(). Note that we do not need to use the HPET at + * all on most modern systems, but if there is an actionable + * failure message it will be logged by the routine itself. */ - if (hpet_acpi_init(&apic_hpet_vect, &apic_hpet_flags) < 0) { - cmn_err(CE_NOTE, "!ACPI HPET table query failed\n"); - } + PRM_POINT("hpet_acpi_init()"); + (void) hpet_acpi_init(&apic_hpet_vect, &apic_hpet_flags); #endif kmem_free(local_ids, NCPU * sizeof (uint32_t)); kmem_free(proc_ids, NCPU * sizeof (uint32_t)); + PRM_POINT("SUCCESS"); return (PSM_SUCCESS); } /* if setting APIC mode failed above, we fall through to cleanup */ diff --git a/usr/src/uts/i86pc/io/pcplusmp/apic.c b/usr/src/uts/i86pc/io/pcplusmp/apic.c index efca63c814..c987391435 100644 --- a/usr/src/uts/i86pc/io/pcplusmp/apic.c +++ b/usr/src/uts/i86pc/io/pcplusmp/apic.c @@ -26,6 +26,7 @@ * Copyright (c) 2010, Intel Corporation. * All rights reserved. * Copyright 2019 Joyent, Inc. + * Copyright 2020 Oxide Computer Company */ /* @@ -58,6 +59,7 @@ #include <sys/ddi_impldefs.h> #include <sys/pci.h> #include <sys/promif.h> +#include <sys/prom_debug.h> #include <sys/x86_archext.h> #include <sys/cpc_impl.h> #include <sys/uadmin.h> @@ -249,16 +251,23 @@ _info(struct modinfo *modinfop) static int apic_probe(void) { + PRM_POINT("apic_probe()"); + /* check if apix is initialized */ - if (apix_enable && apix_loaded()) + if (apix_enable && apix_loaded()) { + PRM_POINT("apic_probe FAILURE: apix is loaded"); return (PSM_FAILURE); + } /* * Check whether x2APIC mode was activated by BIOS. We don't support * that in pcplusmp as apix normally handles that. */ - if (apic_local_mode() == LOCAL_X2APIC) + PRM_POINT("apic_local_mode()"); + if (apic_local_mode() == LOCAL_X2APIC) { + PRM_POINT("apic_probe FAILURE: in x2apic mode"); return (PSM_FAILURE); + } /* continue using pcplusmp PSM */ apix_enable = 0; diff --git a/usr/src/uts/i86pc/io/vmm/amd/svm.c b/usr/src/uts/i86pc/io/vmm/amd/svm.c index 46106e9094..41afc97cfd 100644 --- a/usr/src/uts/i86pc/io/vmm/amd/svm.c +++ b/usr/src/uts/i86pc/io/vmm/amd/svm.c @@ -1937,7 +1937,7 @@ svm_dr_leave_guest(struct svm_regctx *gctx) * Start vcpu with specified RIP. */ static int -svm_vmrun(void *arg, int vcpu, register_t rip, pmap_t pmap, +svm_vmrun(void *arg, int vcpu, uint64_t rip, pmap_t pmap, struct vm_eventinfo *evinfo) { struct svm_regctx *gctx; @@ -2121,7 +2121,7 @@ svm_vmcleanup(void *arg) free(sc, M_SVM); } -static register_t * +static uint64_t * swctx_regptr(struct svm_regctx *regctx, int reg) { switch (reg) { @@ -2171,7 +2171,7 @@ svm_getreg(void *arg, int vcpu, int ident, uint64_t *val) { struct svm_softc *sc; struct vmcb *vmcb; - register_t *regp; + uint64_t *regp; uint64_t *fieldp; struct vmcb_segment *seg; @@ -2233,7 +2233,7 @@ svm_setreg(void *arg, int vcpu, int ident, uint64_t val) { struct svm_softc *sc; struct vmcb *vmcb; - register_t *regp; + uint64_t *regp; uint64_t *fieldp; uint32_t dirty; struct vmcb_segment *seg; diff --git a/usr/src/uts/i86pc/io/vmm/amd/svm.h b/usr/src/uts/i86pc/io/vmm/amd/svm.h index c78f7eb067..19739884c2 100644 --- a/usr/src/uts/i86pc/io/vmm/amd/svm.h +++ b/usr/src/uts/i86pc/io/vmm/amd/svm.h @@ -35,31 +35,31 @@ * Guest register state that is saved outside the VMCB. */ struct svm_regctx { - register_t sctx_rbp; - register_t sctx_rbx; - register_t sctx_rcx; - register_t sctx_rdx; - register_t sctx_rdi; - register_t sctx_rsi; - register_t sctx_r8; - register_t sctx_r9; - register_t sctx_r10; - register_t sctx_r11; - register_t sctx_r12; - register_t sctx_r13; - register_t sctx_r14; - register_t sctx_r15; - register_t sctx_dr0; - register_t sctx_dr1; - register_t sctx_dr2; - register_t sctx_dr3; + uint64_t sctx_rbp; + uint64_t sctx_rbx; + uint64_t sctx_rcx; + uint64_t sctx_rdx; + uint64_t sctx_rdi; + uint64_t sctx_rsi; + uint64_t sctx_r8; + uint64_t sctx_r9; + uint64_t sctx_r10; + uint64_t sctx_r11; + uint64_t sctx_r12; + uint64_t sctx_r13; + uint64_t sctx_r14; + uint64_t sctx_r15; + uint64_t sctx_dr0; + uint64_t sctx_dr1; + uint64_t sctx_dr2; + uint64_t sctx_dr3; - register_t host_dr0; - register_t host_dr1; - register_t host_dr2; - register_t host_dr3; - register_t host_dr6; - register_t host_dr7; + uint64_t host_dr0; + uint64_t host_dr1; + uint64_t host_dr2; + uint64_t host_dr3; + uint64_t host_dr6; + uint64_t host_dr7; uint64_t host_debugctl; }; diff --git a/usr/src/uts/i86pc/io/vmm/intel/vmx.c b/usr/src/uts/i86pc/io/vmm/intel/vmx.c index cb8409f5df..39f211b9e6 100644 --- a/usr/src/uts/i86pc/io/vmm/intel/vmx.c +++ b/usr/src/uts/i86pc/io/vmm/intel/vmx.c @@ -2248,7 +2248,7 @@ vmx_exit_process(struct vmx *vmx, int vcpu, struct vm_exit *vmexit) struct vie *vie; struct vlapic *vlapic; struct vm_task_switch *ts; - uint32_t eax, ecx, edx, idtvec_info, idtvec_err, intr_info, inst_info; + uint32_t eax, ecx, edx, idtvec_info, idtvec_err, intr_info; uint32_t intr_type, intr_vec, reason; uint64_t exitintinfo, qual, gpa; bool retu; @@ -2793,7 +2793,7 @@ vmx_exit_handle_nmi(struct vmx *vmx, int vcpuid, struct vm_exit *vmexit) static __inline void vmx_dr_enter_guest(struct vmxctx *vmxctx) { - register_t rflags; + uint64_t rflags; /* Save host control debug registers. */ vmxctx->host_dr7 = rdr7(); @@ -2858,7 +2858,7 @@ vmx_dr_leave_guest(struct vmxctx *vmxctx) } static int -vmx_run(void *arg, int vcpu, register_t rip, pmap_t pmap, +vmx_run(void *arg, int vcpu, uint64_t rip, pmap_t pmap, struct vm_eventinfo *evinfo) { int rc, handled, launched; @@ -3131,7 +3131,7 @@ vmx_vmcleanup(void *arg) return; } -static register_t * +static uint64_t * vmxctx_regptr(struct vmxctx *vmxctx, int reg) { switch (reg) { @@ -3188,7 +3188,7 @@ vmx_getreg(void *arg, int vcpu, int reg, uint64_t *retval) { int running, hostcpu, err; struct vmx *vmx = arg; - register_t *regp; + uint64_t *regp; running = vcpu_is_running(vmx->vm, vcpu, &hostcpu); if (running && hostcpu != curcpu) @@ -3231,7 +3231,7 @@ vmx_setreg(void *arg, int vcpu, int reg, uint64_t val) { int running, hostcpu, error; struct vmx *vmx = arg; - register_t *regp; + uint64_t *regp; running = vcpu_is_running(vmx->vm, vcpu, &hostcpu); if (running && hostcpu != curcpu) diff --git a/usr/src/uts/i86pc/io/vmm/intel/vmx.h b/usr/src/uts/i86pc/io/vmm/intel/vmx.h index a5647e0b87..7943c1fd0e 100644 --- a/usr/src/uts/i86pc/io/vmm/intel/vmx.h +++ b/usr/src/uts/i86pc/io/vmm/intel/vmx.h @@ -50,44 +50,34 @@ struct pmap; struct vmxctx { - register_t guest_rdi; /* Guest state */ - register_t guest_rsi; - register_t guest_rdx; - register_t guest_rcx; - register_t guest_r8; - register_t guest_r9; - register_t guest_rax; - register_t guest_rbx; - register_t guest_rbp; - register_t guest_r10; - register_t guest_r11; - register_t guest_r12; - register_t guest_r13; - register_t guest_r14; - register_t guest_r15; - register_t guest_cr2; - register_t guest_dr0; - register_t guest_dr1; - register_t guest_dr2; - register_t guest_dr3; - register_t guest_dr6; - -#ifdef __FreeBSD__ - register_t host_r15; /* Host state */ - register_t host_r14; - register_t host_r13; - register_t host_r12; - register_t host_rbp; - register_t host_rsp; - register_t host_rbx; -#endif /* __FreeBSD__ */ - - register_t host_dr0; - register_t host_dr1; - register_t host_dr2; - register_t host_dr3; - register_t host_dr6; - register_t host_dr7; + uint64_t guest_rdi; /* Guest state */ + uint64_t guest_rsi; + uint64_t guest_rdx; + uint64_t guest_rcx; + uint64_t guest_r8; + uint64_t guest_r9; + uint64_t guest_rax; + uint64_t guest_rbx; + uint64_t guest_rbp; + uint64_t guest_r10; + uint64_t guest_r11; + uint64_t guest_r12; + uint64_t guest_r13; + uint64_t guest_r14; + uint64_t guest_r15; + uint64_t guest_cr2; + uint64_t guest_dr0; + uint64_t guest_dr1; + uint64_t guest_dr2; + uint64_t guest_dr3; + uint64_t guest_dr6; + + uint64_t host_dr0; + uint64_t host_dr1; + uint64_t host_dr2; + uint64_t host_dr3; + uint64_t host_dr6; + uint64_t host_dr7; uint64_t host_debugctl; int host_tf; diff --git a/usr/src/uts/i86pc/io/vmm/io/iommu.c b/usr/src/uts/i86pc/io/vmm/io/iommu.c index 918a9ec3e4..2e5fc9df32 100644 --- a/usr/src/uts/i86pc/io/vmm/io/iommu.c +++ b/usr/src/uts/i86pc/io/vmm/io/iommu.c @@ -204,12 +204,8 @@ iommu_find_device(dev_info_t *dip, void *arg) static void iommu_init(void) { - int error, bus, slot, func; + int error; vm_paddr_t maxaddr; -#ifdef __FreeBSD__ - devclass_t dc; -#endif - device_t dev; if (!iommu_enable) return; @@ -246,35 +242,7 @@ iommu_init(void) */ iommu_create_mapping(host_domain, 0, 0, maxaddr); -#ifdef __FreeBSD__ - add_tag = EVENTHANDLER_REGISTER(pci_add_device, iommu_pci_add, NULL, 0); - delete_tag = EVENTHANDLER_REGISTER(pci_delete_device, iommu_pci_delete, - NULL, 0); - dc = devclass_find("ppt"); - for (bus = 0; bus <= PCI_BUSMAX; bus++) { - for (slot = 0; slot <= PCI_SLOTMAX; slot++) { - for (func = 0; func <= PCI_FUNCMAX; func++) { - dev = pci_find_dbsf(0, bus, slot, func); - if (dev == NULL) - continue; - - /* Skip passthrough devices. */ - if (dc != NULL && - device_get_devclass(dev) == dc) - continue; - - /* - * Everything else belongs to the host - * domain. - */ - iommu_add_device(host_domain, - pci_get_rid(dev)); - } - } - } -#else ddi_walk_devs(ddi_root_node(), iommu_find_device, (void *)B_TRUE); -#endif IOMMU_ENABLE(); } diff --git a/usr/src/uts/i86pc/io/vmm/io/vlapic.c b/usr/src/uts/i86pc/io/vmm/io/vlapic.c index 1288f69321..f7a05254ec 100644 --- a/usr/src/uts/i86pc/io/vmm/io/vlapic.c +++ b/usr/src/uts/i86pc/io/vmm/io/vlapic.c @@ -140,12 +140,14 @@ vlapic_dfr_write_handler(struct vlapic *vlapic) lapic->dfr &= APIC_DFR_MODEL_MASK; lapic->dfr |= APIC_DFR_RESERVED; +#ifdef __FreeBSD__ if ((lapic->dfr & APIC_DFR_MODEL_MASK) == APIC_DFR_MODEL_FLAT) VLAPIC_CTR0(vlapic, "vlapic DFR in Flat Model"); else if ((lapic->dfr & APIC_DFR_MODEL_MASK) == APIC_DFR_MODEL_CLUSTER) VLAPIC_CTR0(vlapic, "vlapic DFR in Cluster Model"); else VLAPIC_CTR1(vlapic, "DFR in Unknown Model %#x", lapic->dfr); +#endif } void diff --git a/usr/src/uts/i86pc/io/vmm/sys/vmm_kernel.h b/usr/src/uts/i86pc/io/vmm/sys/vmm_kernel.h index fbd2884b84..9501850dfc 100644 --- a/usr/src/uts/i86pc/io/vmm/sys/vmm_kernel.h +++ b/usr/src/uts/i86pc/io/vmm/sys/vmm_kernel.h @@ -74,7 +74,7 @@ typedef int (*vmm_init_func_t)(int ipinum); typedef int (*vmm_cleanup_func_t)(void); typedef void (*vmm_resume_func_t)(void); typedef void * (*vmi_init_func_t)(struct vm *vm, struct pmap *pmap); -typedef int (*vmi_run_func_t)(void *vmi, int vcpu, register_t rip, +typedef int (*vmi_run_func_t)(void *vmi, int vcpu, uint64_t rip, struct pmap *pmap, struct vm_eventinfo *info); typedef void (*vmi_cleanup_func_t)(void *vmi); typedef int (*vmi_get_register_t)(void *vmi, int vcpu, int num, diff --git a/usr/src/uts/i86pc/io/vmm/vmm.c b/usr/src/uts/i86pc/io/vmm/vmm.c index 302af0670e..4eb967fd89 100644 --- a/usr/src/uts/i86pc/io/vmm/vmm.c +++ b/usr/src/uts/i86pc/io/vmm/vmm.c @@ -1915,7 +1915,7 @@ vm_suspend(struct vm *vm, enum vm_suspend_how how) if (how <= VM_SUSPEND_NONE || how >= VM_SUSPEND_LAST) return (EINVAL); - if (atomic_cmpset_int(&vm->suspend, 0, how) == 0) { + if (atomic_cmpset_int((uint_t *)&vm->suspend, 0, how) == 0) { VM_CTR2(vm, "virtual machine already suspended %d/%d", vm->suspend, how); return (EALREADY); diff --git a/usr/src/uts/i86pc/os/mp_implfuncs.c b/usr/src/uts/i86pc/os/mp_implfuncs.c index 2d0bd3eb53..c61e6216b0 100644 --- a/usr/src/uts/i86pc/os/mp_implfuncs.c +++ b/usr/src/uts/i86pc/os/mp_implfuncs.c @@ -21,6 +21,7 @@ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2020 Oxide Computer Company */ #define PSMI_1_7 @@ -32,6 +33,7 @@ #include <sys/psm_modctl.h> #include <sys/smp_impldefs.h> #include <sys/reboot.h> +#include <sys/prom_debug.h> #if defined(__xpv) #include <sys/hypervisor.h> #include <vm/kboot_mmu.h> @@ -390,12 +392,6 @@ psm_modload(void) close_mach_list(); } -#if defined(__xpv) -#define NOTSUP_MSG "This version of Solaris xVM does not support this hardware" -#else -#define NOTSUP_MSG "This version of Solaris does not support this hardware" -#endif /* __xpv */ - void psm_install(void) { @@ -406,14 +402,18 @@ psm_install(void) mutex_enter(&psmsw_lock); for (swp = psmsw->psw_forw; swp != psmsw; ) { + PRM_DEBUGS(swp->psw_infop->p_mach_idstring); opsp = swp->psw_infop->p_ops; if (opsp->psm_probe) { + PRM_POINT("psm_probe()"); if ((*opsp->psm_probe)() == PSM_SUCCESS) { + PRM_POINT("psm_probe() PSM_SUCCESS"); psmcnt++; swp->psw_flag |= PSM_MOD_IDENTIFY; swp = swp->psw_forw; continue; } + PRM_POINT("psm_probe() FAILURE"); } /* remove the unsuccessful psm modules */ cswp = swp; @@ -429,7 +429,8 @@ psm_install(void) } mutex_exit(&psmsw_lock); if (psmcnt == 0) - halt(NOTSUP_MSG); + halt("the operating system does not yet support this hardware"); + PRM_POINT("psminitf()"); (*psminitf)(); } diff --git a/usr/src/uts/i86pc/os/mp_machdep.c b/usr/src/uts/i86pc/os/mp_machdep.c index f36f5f052d..f017995ac8 100644 --- a/usr/src/uts/i86pc/os/mp_machdep.c +++ b/usr/src/uts/i86pc/os/mp_machdep.c @@ -26,6 +26,7 @@ * Copyright (c) 2009-2010, Intel Corporation. * All rights reserved. * Copyright 2018 Joyent, Inc. + * Copyright 2020 Oxide Computer Company */ #define PSMI_1_7 @@ -63,6 +64,8 @@ #include <sys/sunddi.h> #include <sys/sunndi.h> #include <sys/cpc_pcbe.h> +#include <sys/prom_debug.h> + #define OFFSETOF(s, m) (size_t)(&(((s *)0)->m)) @@ -978,6 +981,7 @@ mach_init() { struct psm_ops *pops; + PRM_POINT("mach_construct_info()"); mach_construct_info(); pops = mach_set[0]; @@ -1017,6 +1021,7 @@ mach_init() notify_error = pops->psm_notify_error; } + PRM_POINT("psm_softinit()"); (*pops->psm_softinit)(); /* @@ -1034,6 +1039,7 @@ mach_init() #ifndef __xpv non_deep_idle_disp_enq_thread = disp_enq_thread; #endif + PRM_DEBUG(idle_cpu_use_hlt); if (idle_cpu_use_hlt) { idle_cpu = cpu_idle_adaptive; CPU->cpu_m.mcpu_idle_cpu = cpu_idle; @@ -1068,6 +1074,7 @@ mach_init() #endif } + PRM_POINT("mach_smpinit()"); mach_smpinit(); } diff --git a/usr/src/uts/i86pc/os/startup.c b/usr/src/uts/i86pc/os/startup.c index 636e58280a..dd2b5d703b 100644 --- a/usr/src/uts/i86pc/os/startup.c +++ b/usr/src/uts/i86pc/os/startup.c @@ -25,6 +25,7 @@ * Copyright 2017 Nexenta Systems, Inc. * Copyright (c) 2018 Joyent, Inc. * Copyright (c) 2015 by Delphix. All rights reserved. + * Copyright 2020 Oxide Computer Company */ /* * Copyright (c) 2010, Intel Corporation. @@ -74,6 +75,7 @@ #include <sys/memlist_plat.h> #include <sys/varargs.h> #include <sys/promif.h> +#include <sys/prom_debug.h> #include <sys/modctl.h> #include <sys/sunddi.h> @@ -464,7 +466,7 @@ static pgcnt_t kphysm_init(page_t *, pgcnt_t); * | | * 0xFFFFFXXX.XXX00000 |-----------------------|- segkvmm_base (floating) * | segkp | - * |-----------------------|- segkp_base (floating) + * |-----------------------|- segkp_base (floating) * | page_t structures | valloc_base + valloc_sz * | memsegs, memlists, | * | page hash, etc. | @@ -623,21 +625,8 @@ size_t toxic_bit_map_len = 0; /* in bits */ #endif /* __i386 */ -/* - * Simple boot time debug facilities - */ -static char *prm_dbg_str[] = { - "%s:%d: '%s' is 0x%x\n", - "%s:%d: '%s' is 0x%llx\n" -}; - int prom_debug; -#define PRM_DEBUG(q) if (prom_debug) \ - prom_printf(prm_dbg_str[sizeof (q) >> 3], "startup.c", __LINE__, #q, q); -#define PRM_POINT(q) if (prom_debug) \ - prom_printf("%s:%d: %s\n", "startup.c", __LINE__, q); - /* * This structure is used to keep track of the intial allocations * done in startup_memlist(). The value of NUM_ALLOCATIONS needs to @@ -2273,6 +2262,7 @@ startup_end(void) * We can now setup for XSAVE because fpu_probe is done in configure(). */ if (fp_save_mech == FP_XSAVE) { + PRM_POINT("xsave_setup_msr()"); xsave_setup_msr(CPU); } @@ -2281,7 +2271,9 @@ startup_end(void) * support. */ setx86isalist(); + PRM_POINT("cpu_intr_alloc()"); cpu_intr_alloc(CPU, NINTR_THREADS); + PRM_POINT("psm_install()"); psm_install(); /* diff --git a/usr/src/uts/i86pc/sys/hpet_acpi.h b/usr/src/uts/i86pc/sys/hpet_acpi.h index e60ebe4bba..81304674b5 100644 --- a/usr/src/uts/i86pc/sys/hpet_acpi.h +++ b/usr/src/uts/i86pc/sys/hpet_acpi.h @@ -36,7 +36,7 @@ extern "C" { #endif /* - * Solaris uses an HPET Timer to generate interrupts for CPUs in Deep C-state + * illumos uses an HPET Timer to generate interrupts for CPUs in Deep C-state * with stalled LAPIC Timers. All CPUs use one HPET timer. The timer's * interrupt targets one CPU (via the I/O APIC). The one CPU that receives * the HPET's interrupt wakes up other CPUs as needed during the HPET Interrupt @@ -46,7 +46,7 @@ extern "C" { * Please see the Intel Programmer's guides. Interrupts are disabled before * a CPU Halts into Deep C-state. (This allows CPU-hardware-specific cleanup * before servicing interrupts.) When a Deep C-state CPU wakes up (due to - * an externally generated interrupt), it resume execution where it halted. + * an externally generated interrupt), it resumes execution where it halted. * The CPU returning from Deep C-state must enable interrupts before it will * handle the pending interrupt that woke it from Deep C-state. * @@ -72,7 +72,7 @@ extern "C" { * } timers[32]; * } * - * There are 32 possible timers in an hpet. Only the first 3 timers are + * There are 32 possible timers in an HPET. Only the first 3 timers are * required. The other 29 timers are optional. * * HPETs can have 64-bit or 32-bit timers. Timers/compare registers can @@ -80,7 +80,7 @@ extern "C" { * The first two timers are not used. The HPET spec intends the first two * timers to be used as "legacy replacement" for the PIT and RTC timers. * - * Solaris uses the first available non-legacy replacement timer as a proxy + * illumos uses the first available non-legacy replacement timer as a proxy * timer for processor Local APIC Timers that stop in deep idle C-states. */ @@ -97,7 +97,7 @@ extern "C" { #define HPET_SIZE (1024) /* - * Offsets of hpet registers and macros to access them from HPET base address. + * Offsets of HPET registers and macros to access them from HPET base address. */ #define HPET_GEN_CAP_OFFSET (0) #define HPET_GEN_CONFIG_OFFSET (0x10) diff --git a/usr/src/uts/i86pc/sys/prom_debug.h b/usr/src/uts/i86pc/sys/prom_debug.h new file mode 100644 index 0000000000..ae64d91711 --- /dev/null +++ b/usr/src/uts/i86pc/sys/prom_debug.h @@ -0,0 +1,72 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2020 Oxide Computer Company + */ + +#ifndef _SYS_PROM_DEBUG_H +#define _SYS_PROM_DEBUG_H + +#include <sys/promif.h> + +/* + * These macros are used to emit coarse-grained early boot debugging + * information when the user sets "prom_debug" in the boot environment. They + * should only be used for information that we cannot easily obtain through a + * richer mechanism because the machine hangs or crashes before other debugging + * tools are available. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int prom_debug; + +/* + * Print a string message, used to signal that we have at least reached a + * particular point in the code: + */ +#define PRM_POINT(q) do { \ + if (prom_debug) { \ + prom_printf("%s:%d: %s\n", \ + __FILE__, __LINE__, (q)); \ + } \ + } while (0) + +/* + * Print the name and value of an integer variable: + */ +#define PRM_DEBUG(q) do { \ + if (prom_debug) { \ + prom_printf("%s:%d: '%s' is 0x%llx\n", \ + __FILE__, __LINE__, #q, (long long)(q)); \ + } \ + } while (0) + +/* + * Print the name and value of a string (char *) variable (which may be NULL): + */ +#define PRM_DEBUGS(q) do { \ + if (prom_debug) { \ + const char *qq = q; \ + prom_printf("%s:%d: '%s' is '%s'\n", \ + __FILE__, __LINE__, #q, \ + qq != NULL ? qq : "<NULL>"); \ + } \ + } while (0) + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_PROM_DEBUG_H */ diff --git a/usr/src/uts/i86pc/vmm/Makefile b/usr/src/uts/i86pc/vmm/Makefile index 4b426361ae..0106dd0a0f 100644 --- a/usr/src/uts/i86pc/vmm/Makefile +++ b/usr/src/uts/i86pc/vmm/Makefile @@ -43,7 +43,6 @@ INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE) # Overrides and additions # -CERRWARN += -_gcc=-Wno-empty-body # 3rd party code SMOFF += all_func_returns @@ -51,9 +50,6 @@ SMOFF += all_func_returns # needs work $(OBJS_DIR)/vmm_sol_dev.o := SMOFF += signed_integer_overflow_check -# a can't happen: vmx_setcap() warn: variable dereferenced before check 'pptr' -$(OBJS_DIR)/vmx.o := SMOFF += deref_check - ALL_BUILDS = $(ALL_BUILDSONLY64) DEF_BUILDS = $(DEF_BUILDSONLY64) PRE_INC_PATH = -I$(COMPAT)/bhyve -I$(COMPAT)/bhyve/amd64 \ @@ -61,15 +57,9 @@ PRE_INC_PATH = -I$(COMPAT)/bhyve -I$(COMPAT)/bhyve/amd64 \ INC_PATH += -I$(UTSBASE)/i86pc/io/vmm -I$(UTSBASE)/i86pc/io/vmm/io AS_INC_PATH += -I$(UTSBASE)/i86pc/io/vmm -I$(OBJS_DIR) -CFLAGS += -_gcc=-Wimplicit-function-declaration # enable collection of VMM statistics CFLAGS += -DVMM_KEEP_STATS -$(OBJS_DIR)/vmm.o := CERRWARN += -_gcc=-Wno-pointer-sign -_gcc=-Wno-type-limits -$(OBJS_DIR)/svm.o := CERRWARN += -_gcc=-Wno-pointer-sign -_gcc=-Wno-type-limits -$(OBJS_DIR)/vmx.o := CERRWARN += -_gcc=-Wno-unused-variable -$(OBJS_DIR)/iommu.o := CERRWARN += -_gcc=-Wno-unused-variable - LDFLAGS += -N misc/acpica -N misc/pcie -N fs/dev LDFLAGS += -z type=kmod -M $(MAPFILE) diff --git a/usr/src/uts/sun/sys/ser_async.h b/usr/src/uts/sun/sys/ser_async.h index 8e8a573829..0f89bce4c5 100644 --- a/usr/src/uts/sun/sys/ser_async.h +++ b/usr/src/uts/sun/sys/ser_async.h @@ -27,8 +27,6 @@ #ifndef _SYS_SER_ASYNC_H #define _SYS_SER_ASYNC_H -#pragma ident "%Z%%M% %I% %E% SMI" - /* * Initial port setup parameters for async lines */ @@ -57,9 +55,9 @@ extern "C" { #define ZFIFOSZ 3 /* - * this macro needs a constant Hertz, but we can now have a hires_tick. + * This macro needs a constant 100 Hz, but hires_tick or hz may change that. * ztdelay in zs_async.c converts to a true delay based on hz so we - * can use 100 for Hertz here. + * can use 100 Hz here. */ #define ZDELAY(n) ZSDelayConst(100, ZFIFOSZ, NBBY, n) @@ -166,9 +164,9 @@ struct asyncline { * and the second byte is the actual data. The ring buffer * needs to be defined as ushort_t to accomodate this. */ - ushort_t za_ring[RINGSIZE]; + ushort_t za_ring[RINGSIZE]; timeout_id_t za_kick_rcv_id; - int za_kick_rcv_count; + int za_kick_rcv_count; timeout_id_t za_zsa_restart_id; bufcall_id_t za_bufcid; mblk_t *za_rstandby[ZSA_MAX_RSTANDBY]; |