diff options
author | Dan McDonald <danmcd@mnx.io> | 2022-07-14 20:42:12 -0400 |
---|---|---|
committer | Dan McDonald <danmcd@mnx.io> | 2022-07-14 20:42:12 -0400 |
commit | 964bebb5480b816d8a7d2dd58484eb826c732d52 (patch) | |
tree | 485159e8a28b01338bc963895ee0c2af4616d14b /usr | |
parent | 6638d136db644920fd3090c414ece292ca77b108 (diff) | |
parent | 62d03eda78495dc4dc79a65a6b1899e11dc34b12 (diff) | |
download | illumos-joyent-964bebb5480b816d8a7d2dd58484eb826c732d52.tar.gz |
Merge branch 'master' into OS-8394OS-8394
Diffstat (limited to 'usr')
36 files changed, 711 insertions, 289 deletions
diff --git a/usr/src/cmd/eeprom/i386/benv.c b/usr/src/cmd/eeprom/i386/benv.c index 2119bdc3af..2e559f83d3 100644 --- a/usr/src/cmd/eeprom/i386/benv.c +++ b/usr/src/cmd/eeprom/i386/benv.c @@ -934,12 +934,13 @@ main(int argc, char **argv) argc -= optind; argv += optind; + optind = 0; if (bootenv) { int rv = 0; if (argc == 1) - value = argv[0]; + value = argv[optind]; if (bootenv_print) return (lzbe_bootenv_print(name, nvlist, stdout)); @@ -978,7 +979,7 @@ main(int argc, char **argv) if (optind >= argc) { print_vars(elist); return (0); - } else + } else { while (optind < argc) { /* * If "-" specified, read variables from stdin; @@ -996,6 +997,7 @@ main(int argc, char **argv) optind++; } + } /* * don't write benv if we are processing delayed writes since diff --git a/usr/src/cmd/sgs/dump/Makefile b/usr/src/cmd/sgs/dump/Makefile index 745dc3e005..a83ee1a5d7 100644 --- a/usr/src/cmd/sgs/dump/Makefile +++ b/usr/src/cmd/sgs/dump/Makefile @@ -20,10 +20,9 @@ # CDDL HEADER END # # -#ident "%Z%%M% %I% %E% SMI" -# # Copyright (c) 1994 by Sun Microsystems, Inc. # -# cmd/sgs/dump/Makefile + +BUILD32 = $(POUND_SIGN) include ../Makefile.sub diff --git a/usr/src/cmd/sgs/dump/Makefile.com b/usr/src/cmd/sgs/dump/Makefile.com index 6fee454721..96a6b4aa58 100644 --- a/usr/src/cmd/sgs/dump/Makefile.com +++ b/usr/src/cmd/sgs/dump/Makefile.com @@ -40,12 +40,10 @@ OBJS = $(COMOBJS) .PARALLEL: $(OBJS) CPPFLAGS += -D__EXTENSIONS__ -LLDFLAGS = '$(LDPASS)-R$$ORIGIN/../../lib' -LLDFLAGS64 = '$(LDPASS)-R$$ORIGIN/../../../lib/$(MACH64)' -LDFLAGS += $(LLDFLAGS) +LDFLAGS += '-R$$ORIGIN/../../lib/$(MACH64)' CERRWARN += $(CNOWARN_UNINIT) SMOFF += indenting -LDLIBS += $(CONVLIBDIR) -lconv $(ELFLIBDIR) -lelf +LDLIBS += $(CONVLIBDIR64) -lconv $(ELFLIBDIR64) -lelf diff --git a/usr/src/cmd/sgs/dump/amd64/Makefile b/usr/src/cmd/sgs/dump/amd64/Makefile index 10cef7c92d..20455f057c 100644 --- a/usr/src/cmd/sgs/dump/amd64/Makefile +++ b/usr/src/cmd/sgs/dump/amd64/Makefile @@ -30,14 +30,11 @@ include ../Makefile.com .KEEP_STATE: -LLDFLAGS = $(LLDFLAGS64) -ELFLIBDIR = $(ELFLIBDIR64) -CONVLIBDIR = $(CONVLIBDIR64) - -ROOTPROG= $(ROOTPROG64) -ROOTCCSBINLINK= $(ROOTCCSBINLINK64) - include ../Makefile.targ include $(SRC)/Makefile.master.64 -install: $(ROOTPROG64) +install: $(ROOTPROG) $(ROOTPROG64) \ + $(ROOTCCSBINLINK) $(ROOTCCSBINLINK64) + +$(ROOTBIN64)/dump: + $(RM) $@; $(SYMLINK) ../../bin/dump $@ diff --git a/usr/src/cmd/sgs/dump/common/dump.c b/usr/src/cmd/sgs/dump/common/dump.c index 204c0d52f1..20acf25d3d 100644 --- a/usr/src/cmd/sgs/dump/common/dump.c +++ b/usr/src/cmd/sgs/dump/common/dump.c @@ -2010,11 +2010,6 @@ main(int argc, char *argv[], char *envp[]) char *optstr = OPTSTR; /* option string used by getopt() */ int optchar; - /* - * Check for a binary that better fits this architecture. - */ - (void) conv_check_native(argv, envp); - prog_name = argv[0]; (void) setlocale(LC_ALL, ""); diff --git a/usr/src/cmd/sgs/dump/i386/Makefile b/usr/src/cmd/sgs/dump/i386/Makefile deleted file mode 100644 index ba0a4032e6..0000000000 --- a/usr/src/cmd/sgs/dump/i386/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -# -# CDDL HEADER START -# -# 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] -# -# CDDL HEADER END -# - -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# Copyright 2019 OmniOS Community Edition (OmniOSce) Association. -# - -include ../Makefile.com - -.KEEP_STATE: - -include ../Makefile.targ diff --git a/usr/src/cmd/sgs/dump/sparc/Makefile b/usr/src/cmd/sgs/dump/sparc/Makefile deleted file mode 100644 index ba0a4032e6..0000000000 --- a/usr/src/cmd/sgs/dump/sparc/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -# -# CDDL HEADER START -# -# 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] -# -# CDDL HEADER END -# - -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# Copyright 2019 OmniOS Community Edition (OmniOSce) Association. -# - -include ../Makefile.com - -.KEEP_STATE: - -include ../Makefile.targ diff --git a/usr/src/cmd/sgs/dump/sparcv9/Makefile b/usr/src/cmd/sgs/dump/sparcv9/Makefile index 5632b0ecf0..20455f057c 100644 --- a/usr/src/cmd/sgs/dump/sparcv9/Makefile +++ b/usr/src/cmd/sgs/dump/sparcv9/Makefile @@ -30,14 +30,11 @@ include ../Makefile.com .KEEP_STATE: -LLDFLAGS = $(LLDFLAGS64) -ELFLIBDIR = $(ELFLIBDIR64) -CONVLIBDIR = $(CONVLIBDIR64) - -ROOTPROG = $(ROOTPROG64) -ROOTCCSBINLINK = $(ROOTCCSBINLINK64) - include ../Makefile.targ include $(SRC)/Makefile.master.64 -install: $(ROOTPROG64) +install: $(ROOTPROG) $(ROOTPROG64) \ + $(ROOTCCSBINLINK) $(ROOTCCSBINLINK64) + +$(ROOTBIN64)/dump: + $(RM) $@; $(SYMLINK) ../../bin/dump $@ diff --git a/usr/src/cmd/sgs/elfdump/Makefile b/usr/src/cmd/sgs/elfdump/Makefile index 2f70df00c7..35c78efe07 100644 --- a/usr/src/cmd/sgs/elfdump/Makefile +++ b/usr/src/cmd/sgs/elfdump/Makefile @@ -23,7 +23,7 @@ # Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# + +BUILD32 = $(POUND_SIGN) include $(SRC)/cmd/sgs/Makefile.sub diff --git a/usr/src/cmd/sgs/elfdump/Makefile.com b/usr/src/cmd/sgs/elfdump/Makefile.com index c5190adcd4..1caec6d1bf 100644 --- a/usr/src/cmd/sgs/elfdump/Makefile.com +++ b/usr/src/cmd/sgs/elfdump/Makefile.com @@ -51,11 +51,10 @@ MAPOPT= $(MAPFILE:%=-Wl,-M%) CPPFLAGS= -I. -I../common -I../../include -I../../include/$(MACH) \ -I$(SRC)/lib/libc/inc -I$(SRC)/uts/$(ARCH)/sys \ $(CPPFLAGS.master) -I$(ELFCAP) -LLDFLAGS = '-R$$ORIGIN/../../lib' -LLDFLAGS64 = '-R$$ORIGIN/../../../lib/$(MACH64)' -LDFLAGS += $(VERSREF) $(MAPOPT) $(LLDFLAGS) -LDLIBS += $(ELFLIBDIR) -lelf $(LDDBGLIBDIR) -llddbg \ - $(CONVLIBDIR) -lconv + +LDFLAGS += $(VERSREF) $(MAPOPT) '-R$$ORIGIN/../../lib/$(MACH64)' +LDLIBS += $(ELFLIBDIR64) -lelf $(LDDBGLIBDIR64) -llddbg \ + $(CONVLIBDIR64) -lconv NATIVE_LDFLAGS = $(LDASSERTS) $(BDIRECT) diff --git a/usr/src/cmd/sgs/elfdump/amd64/Makefile b/usr/src/cmd/sgs/elfdump/amd64/Makefile index b04872649b..0294565bb4 100644 --- a/usr/src/cmd/sgs/elfdump/amd64/Makefile +++ b/usr/src/cmd/sgs/elfdump/amd64/Makefile @@ -31,17 +31,14 @@ include ../Makefile.com .KEEP_STATE: ARCH = amd64 -LLDFLAGS = $(LLDFLAGS64) -ELFLIBDIR = $(ELFLIBDIR64) -LDDBGLIBDIR = $(LDDBGLIBDIR64) -CONVLIBDIR = $(CONVLIBDIR64) - -ROOTPROG = $(ROOTPROG64) -ROOTCCSBINLINK = $(ROOTCCSBINLINK64) install: all $(ROOTPROG64) include ../Makefile.targ include $(SRC)/Makefile.master.64 -install: $(ROOTPROG64) +install: $(ROOTPROG) $(ROOTPROG64) \ + $(ROOTCCSBINLINK) $(ROOTCCSBINLINK64) + +$(ROOTBIN64)/elfdump: + $(RM) $@; $(SYMLINK) ../../bin/elfdump $@ diff --git a/usr/src/cmd/sgs/elfdump/common/main.c b/usr/src/cmd/sgs/elfdump/common/main.c index ed95ad5892..7acecdaf96 100644 --- a/usr/src/cmd/sgs/elfdump/common/main.c +++ b/usr/src/cmd/sgs/elfdump/common/main.c @@ -174,7 +174,7 @@ detail_usage() */ void dump_hex_bytes(const void *data, size_t n, int indent, - int bytes_per_col, int col_per_row) + int bytes_per_col, int col_per_row) { const uchar_t *ldata = data; int bytes_per_row = bytes_per_col * col_per_row; @@ -735,12 +735,6 @@ main(int argc, char **argv, char **envp) uchar_t osabi = ELFOSABI_NONE; /* - * If we're on a 64-bit kernel, try to exec a full 64-bit version of - * the binary. If successful, conv_check_native() won't return. - */ - (void) conv_check_native(argv, envp); - - /* * Establish locale. */ (void) setlocale(LC_MESSAGES, MSG_ORIG(MSG_STR_EMPTY)); diff --git a/usr/src/cmd/sgs/elfdump/i386/Makefile b/usr/src/cmd/sgs/elfdump/i386/Makefile deleted file mode 100644 index 95390a2899..0000000000 --- a/usr/src/cmd/sgs/elfdump/i386/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -# -# CDDL HEADER START -# -# 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] -# -# CDDL HEADER END -# - -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -include ../Makefile.com - -.KEEP_STATE: - -ARCH = i386 - -install: all $(ROOTPROG32) - -include ../Makefile.targ diff --git a/usr/src/cmd/sgs/elfdump/sparc/Makefile b/usr/src/cmd/sgs/elfdump/sparc/Makefile deleted file mode 100644 index a2c6327b0b..0000000000 --- a/usr/src/cmd/sgs/elfdump/sparc/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -# -# CDDL HEADER START -# -# 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] -# -# CDDL HEADER END -# - -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -include ../Makefile.com - -.KEEP_STATE: - -ARCH = sparc - -include ../Makefile.targ diff --git a/usr/src/cmd/sgs/elfdump/sparcv9/Makefile b/usr/src/cmd/sgs/elfdump/sparcv9/Makefile index f24ce47957..2db168be93 100644 --- a/usr/src/cmd/sgs/elfdump/sparcv9/Makefile +++ b/usr/src/cmd/sgs/elfdump/sparcv9/Makefile @@ -31,16 +31,12 @@ include ../Makefile.com .KEEP_STATE: ARCH = sparcv9 -LLDFLAGS = $(LLDFLAGS64) -ELFLIBDIR = $(ELFLIBDIR64) -LDDBGLIBDIR = $(LDDBGLIBDIR64) -CONVLIBDIR = $(CONVLIBDIR64) - -ROOTPROG = $(ROOTPROG64) -ROOTCCSBINLINK = $(ROOTCCSBINLINK64) include ../Makefile.targ include $(SRC)/Makefile.master.64 -install: $(ROOTPROG64) +install: $(ROOTPROG) $(ROOTPROG64) \ + $(ROOTCCSBINLINK) $(ROOTCCSBINLINK64) +$(ROOTBIN64)/elfdump: + $(RM) $@; $(SYMLINK) ../../bin/elfdump $@ diff --git a/usr/src/cmd/ttymon/tmchild.c b/usr/src/cmd/ttymon/tmchild.c index a58099974b..960a9a816c 100644 --- a/usr/src/cmd/ttymon/tmchild.c +++ b/usr/src/cmd/ttymon/tmchild.c @@ -99,7 +99,7 @@ tmchild(struct pmtab *pmtab) */ (void) setsid(); } - speedef = get_speed(pmtab->p_ttylabel); + speedef = get_speed(pmtab); openline(pmtab, speedef); if (pmtab->p_ttyflags & (C_FLAG|B_FLAG)) { if (pmtab->p_fd >= 0) { diff --git a/usr/src/cmd/ttymon/tmexpress.c b/usr/src/cmd/ttymon/tmexpress.c index 345fdd1529..2a3f91d147 100644 --- a/usr/src/cmd/ttymon/tmexpress.c +++ b/usr/src/cmd/ttymon/tmexpress.c @@ -34,7 +34,6 @@ #include <ctype.h> #include <string.h> #include <signal.h> -#include <sys/stat.h> #include <utmpx.h> #include <pwd.h> #include <dirent.h> @@ -42,6 +41,7 @@ #include <sys/acl.h> #include <sys/stat.h> #include <sys/types.h> +#include <sys/mkdev.h> #include <sys/console.h> #include <libdevinfo.h> #include "ttymon.h" @@ -143,6 +143,44 @@ ttymon_express(int argc, char **argv) } /* + * For serial device, return ttyX-mode property value. + */ +static char * +get_ttymode_prop(dev_t rconsdev) +{ + char *rootpath = "/"; + char path[MAXPATHLEN]; + di_node_t root; + char *propname, *v; + struct stat st; + + (void) snprintf(path, sizeof (path), "/dev/tty%c", + 'a' + minor(rconsdev)); + if (stat(path, &st) < 0) + return (NULL); + + if (st.st_rdev != rconsdev) + return (NULL); + + if (asprintf(&propname, "%s-mode", path + 5) <= 0) + return (NULL); + + root = di_init(rootpath, DINFOPROP); + if (root == DI_NODE_NIL) { + free(propname); + return (NULL); + } + + v = NULL; + if (di_prop_lookup_strings(DDI_DEV_T_ANY, root, propname, &v) > 0) + v = strdup(v); + + di_fini(root); + free(propname); + return (v); +} + +/* * parse_arg - parse cmd line arguments */ static int @@ -172,11 +210,13 @@ parse_args(int argc, char **argv, struct pmtab *pmtab) pmtab->p_termtype = ""; pmtab->p_device = ""; pmtab->p_status = GETTY; + pmtab->p_ttymode = NULL; if (strcmp(lastname(argv[0]), "getty") == 0) { pmtab->p_ttylabel = "300"; getty_options(argc, argv, pmtab); } else { int cn_fd; + struct cons_getdev cnd; pmtab->p_ttylabel = "9600"; ttymon_options(argc, argv, pmtab); @@ -200,6 +240,10 @@ parse_args(int argc, char **argv, struct pmtab *pmtab) if (ioctl(cn_fd, CONS_GETTERM, &cnterm) != -1) pmtab->p_termtype = cnterm.cn_term_type; + + if (ioctl(cn_fd, CONS_GETDEV, &cnd) != -1) + pmtab->p_ttymode = + get_ttymode_prop(cnd.cnd_rconsdev); (void) close(cn_fd); } } diff --git a/usr/src/cmd/ttymon/tmextern.h b/usr/src/cmd/ttymon/tmextern.h index b08c59f04d..955e5773ff 100644 --- a/usr/src/cmd/ttymon/tmextern.h +++ b/usr/src/cmd/ttymon/tmextern.h @@ -222,7 +222,7 @@ extern "C" { extern int Splflag; /* ttymon.c */ - extern struct Gdef *get_speed(char *); + extern struct Gdef *get_speed(struct pmtab *); extern void open_device(struct pmtab *); extern void set_softcar(struct pmtab *); extern void setup_PCpipe(void); diff --git a/usr/src/cmd/ttymon/tmstruct.h b/usr/src/cmd/ttymon/tmstruct.h index 288c1ec122..8c4582896a 100644 --- a/usr/src/cmd/ttymon/tmstruct.h +++ b/usr/src/cmd/ttymon/tmstruct.h @@ -74,6 +74,7 @@ struct pmtab { uid_t p_uid; /* uid of p_identity */ gid_t p_gid; /* gid of p_identity */ char *p_dir; /* home dir of p_identity */ + char *p_ttymode; /* mode line for serial device */ struct pmtab *p_next; }; diff --git a/usr/src/cmd/ttymon/tmterm.c b/usr/src/cmd/ttymon/tmterm.c index 96e63af2d3..613cf2597d 100644 --- a/usr/src/cmd/ttymon/tmterm.c +++ b/usr/src/cmd/ttymon/tmterm.c @@ -244,7 +244,7 @@ initial_termio(int fd, struct pmtab *pmptr) int ret; struct Gdef *speedef; - speedef = get_speed(pmptr->p_ttylabel); + speedef = get_speed(pmptr); if (speedef->g_autobaud & A_FLAG) { pmptr->p_ttyflags |= A_FLAG; if (auto_termio(fd) == -1) { diff --git a/usr/src/cmd/ttymon/ttymon.c b/usr/src/cmd/ttymon/ttymon.c index 03ff520059..0c061a9c8c 100644 --- a/usr/src/cmd/ttymon/ttymon.c +++ b/usr/src/cmd/ttymon/ttymon.c @@ -26,6 +26,7 @@ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ +#include <ctype.h> #include <stdio_ext.h> #include <stdlib.h> #include <fcntl.h> @@ -597,25 +598,106 @@ free_defs(void) } /* + * rebuild flags entry using speed from ttymode. + */ +static char * +merge_flags(char *src, char *ttymode) +{ + char *data, *ptr, *flags; + + /* copy speed entry */ + data = strsave(src); + flags = strsave(ttymode); + ptr = strchr(flags, ','); + if (ptr == NULL) { /* ttymode is corrupted */ + free(flags); + return (data); + } + *ptr = '\0'; + ptr = flags; + flags = strsave(flags); + free(ptr); + + /* + * The flags line is supposed to have stty keywords separated by space. + * We need to split up the keywords, replace the speed and + * reconstruct the flags line. + */ + + ptr = strtok(data, " \t"); + if (ptr == NULL) { + free(data); + return (flags); + } + + do { + char *tmp; + + /* skip speed */ + if (isdigit(*ptr)) + continue; + + if (asprintf(&tmp, "%s %s", flags, ptr) <= 0) { + /* should we complain? */ + break; + } + free(flags); + flags = tmp; + } while ((ptr = strtok(NULL, " \t")) != NULL); + + free(data); + return (flags); +} + +/* * struct Gdef *get_speed(ttylabel) * - search "/etc/ttydefs" for speed and term. specification * using "ttylabel". If "ttylabel" is NULL, default * to DEFAULT + * - for /dev/console, if we are in fact using serial console, + * use ttyX-mode value to get speed. This allows us to use + * the value set for serial console either from firmware (or BMC sol), + * or boot loader default. * arg: ttylabel - label/id of speed settings. */ struct Gdef * -get_speed(char *ttylabel) +get_speed(struct pmtab *pmptr) { + static struct Gdef serial = { 0 }; struct Gdef *sp; + char *ttylabel = pmptr->p_ttylabel; if ((ttylabel != NULL) && (*ttylabel != '\0')) { if ((sp = find_def(ttylabel)) == NULL) { log("unable to find <%s> in \"%s\"", ttylabel, TTYDEFS); sp = &DEFAULT; /* use default */ } - } else sp = &DEFAULT; /* use default */ - return (sp); + } else { + sp = &DEFAULT; /* use default */ + } + + /* + * if this is not /dev/console or /dev/console is not using serial, + * we are done. + */ + if (pmptr->p_ttymode == NULL || + strcmp(pmptr->p_device, "/dev/console") != 0) + return (sp); + + /* is entry for serial set up? */ + if (serial.g_id == NULL) { + /* + * Copy data from sp, except we need to update inital and + * final flags. + */ + serial.g_id = strsave(sp->g_id); + serial.g_iflags = merge_flags(sp->g_iflags, pmptr->p_ttymode); + serial.g_fflags = merge_flags(sp->g_fflags, pmptr->p_ttymode); + serial.g_autobaud = sp->g_autobaud; + serial.g_nextid = strsave(sp->g_nextid); + } + return (&serial); } /* diff --git a/usr/src/pkg/manifests/developer-object-file.p5m b/usr/src/pkg/manifests/developer-object-file.p5m index e80006c2bd..14f22cd0e5 100644 --- a/usr/src/pkg/manifests/developer-object-file.p5m +++ b/usr/src/pkg/manifests/developer-object-file.p5m @@ -35,8 +35,8 @@ dir path=usr group=sys dir path=usr/bin dir path=usr/bin/$(ARCH64) file path=usr/bin/$(ARCH64)/ar mode=0555 -file path=usr/bin/$(ARCH64)/dump mode=0555 -file path=usr/bin/$(ARCH64)/elfdump mode=0555 +link path=usr/bin/$(ARCH64)/dump target=../../bin/dump +link path=usr/bin/$(ARCH64)/elfdump target=../../bin/elfdump file path=usr/bin/$(ARCH64)/elfedit mode=0555 file path=usr/bin/$(ARCH64)/mcs mode=0555 file path=usr/bin/$(ARCH64)/nm mode=0555 diff --git a/usr/src/pkg/manifests/system-bhyve-tests.p5m b/usr/src/pkg/manifests/system-bhyve-tests.p5m index 1df6e67bd5..aae7d2807a 100644 --- a/usr/src/pkg/manifests/system-bhyve-tests.p5m +++ b/usr/src/pkg/manifests/system-bhyve-tests.p5m @@ -49,6 +49,8 @@ file path=opt/bhyve-tests/tests/mevent/read_pause mode=0555 file path=opt/bhyve-tests/tests/mevent/read_requeue mode=0555 file path=opt/bhyve-tests/tests/mevent/vnode_file mode=0555 file path=opt/bhyve-tests/tests/mevent/vnode_zvol mode=0555 +dir path=opt/bhyve-tests/tests/viona +file path=opt/bhyve-tests/tests/viona/interface_version mode=0555 dir path=opt/bhyve-tests/tests/vmm file path=opt/bhyve-tests/tests/vmm/check_iommu mode=0555 file path=opt/bhyve-tests/tests/vmm/fpu_getset mode=0555 diff --git a/usr/src/test/bhyve-tests/runfiles/default.run b/usr/src/test/bhyve-tests/runfiles/default.run index 5cdd9647b6..8ec89a7a0a 100644 --- a/usr/src/test/bhyve-tests/runfiles/default.run +++ b/usr/src/test/bhyve-tests/runfiles/default.run @@ -49,6 +49,12 @@ tests = [ 'triple_fault' ] +[/opt/bhyve-tests/tests/viona] +user = root +tests = [ + 'interface_version' + ] + # Tests of userspace mevent system, built from cmd/bhyve [/opt/bhyve-tests/tests/mevent] tests = ['lists_delete', 'read_disable', 'read_pause', 'read_requeue', diff --git a/usr/src/test/bhyve-tests/tests/Makefile b/usr/src/test/bhyve-tests/tests/Makefile index 5dc416db01..6742106ae0 100644 --- a/usr/src/test/bhyve-tests/tests/Makefile +++ b/usr/src/test/bhyve-tests/tests/Makefile @@ -15,6 +15,6 @@ .PARALLEL: $(SUBDIRS) -SUBDIRS = inst_emul kdev vmm +SUBDIRS = inst_emul kdev viona vmm include $(SRC)/test/Makefile.com diff --git a/usr/src/test/bhyve-tests/tests/viona/Makefile b/usr/src/test/bhyve-tests/tests/viona/Makefile new file mode 100644 index 0000000000..8b68c11d35 --- /dev/null +++ b/usr/src/test/bhyve-tests/tests/viona/Makefile @@ -0,0 +1,51 @@ +# +# 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 2022 Oxide Computer Company + +include $(SRC)/cmd/Makefile.cmd +include $(SRC)/cmd/Makefile.cmd.64 +include $(SRC)/test/Makefile.com + +PROG = interface_version + +CLEAN_OBJS = $(PROG:%=%.o) + +ROOTOPTPKG = $(ROOT)/opt/bhyve-tests +TESTDIR = $(ROOTOPTPKG)/tests/viona + +CMDS = $(PROG:%=$(TESTDIR)/%) +$(CMDS) := FILEMODE = 0555 + +CSTD= $(CSTD_GNU99) +CPPFLAGS = $(CPPFLAGS.master) \ + -I$(SRC)/uts/intel + +all: $(PROG) + +install: all $(CMDS) + +clean: + -$(RM) $(CLEAN_OBJS) +clobber: clean + -$(RM) $(PROG) + +$(CMDS): $(TESTDIR) $(PROG) + +$(TESTDIR): + $(INS.dir) + +$(TESTDIR)/%: % + $(INS.file) + +%: %.o + $(LINK.c) -o $@ $< $(LDLIBS) + $(POST_PROCESS) diff --git a/usr/src/test/bhyve-tests/tests/viona/interface_version.c b/usr/src/test/bhyve-tests/tests/viona/interface_version.c new file mode 100644 index 0000000000..1b3cd585f0 --- /dev/null +++ b/usr/src/test/bhyve-tests/tests/viona/interface_version.c @@ -0,0 +1,51 @@ +/* + * 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 2022 Oxide Computer Company + */ + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <fcntl.h> +#include <libgen.h> + +#include <sys/viona_io.h> + +#define VIONA_DEV "/dev/viona" + +int +main(int argc, char *argv[]) +{ + const char *suite_name = basename(argv[0]); + + int ctl_fd = open(VIONA_DEV, O_EXCL | O_RDWR); + if (ctl_fd < 0) { + perror("could not open viona device"); + return (EXIT_FAILURE); + } + + int version = ioctl(ctl_fd, VNA_IOC_VERSION, 0); + if (version < 0) { + perror("VNA_IOC_VERSION ioctl failed"); + return (EXIT_FAILURE); + } + if (version != VIONA_CURRENT_INTERFACE_VERSION) { + (void) fprintf(stderr, "kernel version %d != expected %d\n", + version, VIONA_CURRENT_INTERFACE_VERSION); + return (EXIT_FAILURE); + } + + (void) close(ctl_fd); + (void) printf("%s\tPASS\n", suite_name); + return (0); +} diff --git a/usr/src/uts/common/io/scsi/impl/scsi_subr.c b/usr/src/uts/common/io/scsi/impl/scsi_subr.c index 1fd97aeeb3..6542098fe2 100644 --- a/usr/src/uts/common/io/scsi/impl/scsi_subr.c +++ b/usr/src/uts/common/io/scsi/impl/scsi_subr.c @@ -21,6 +21,7 @@ /* * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2022 Garrett D'Amore */ #include <sys/scsi/scsi.h> @@ -390,8 +391,6 @@ free_pktiopb(struct scsi_pkt *pkt, caddr_t datap, int datalen) * Common naming functions */ -static char scsi_tmpname[64]; - char * scsi_dname(int dtyp) { @@ -479,7 +478,7 @@ scsi_cname(uchar_t cmd, register char **cmdvec) } cmdvec++; } - return (sprintf(scsi_tmpname, "<undecoded cmd 0x%x>", cmd)); + return ("<undecoded cmd>"); } char * diff --git a/usr/src/uts/i86pc/io/pci/pci_common.c b/usr/src/uts/i86pc/io/pci/pci_common.c index feb5fbfd25..fe1918d121 100644 --- a/usr/src/uts/i86pc/io/pci/pci_common.c +++ b/usr/src/uts/i86pc/io/pci/pci_common.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2022 Oxide Computer Company */ /* @@ -1018,6 +1019,31 @@ pci_common_get_reg_prop(dev_info_t *dip, pci_regspec_t *pci_rp) for (i = 0; i < number; i++) { if ((assigned_addr[i].pci_phys_hi & PCI_CONF_ADDR_MASK) == phys_hi) { + /* + * When the system does not manage to allocate PCI + * resources for a device, then the value that is stored + * in assigned addresses ends up being the hardware + * default reset value of '0'. On currently supported + * platforms, physical address zero is associated with + * memory; however, on other platforms this may be the + * exception vector table (ARM), etc. and so we opt to + * generally keep the idea in PCI that the reset value + * will not be used for actual MMIO allocations. If such + * a platform comes around where it is worth using that + * bit of MMIO for PCI then we should make this check + * platform-specific. + * + * Note, the +1 in the print statement is because a + * given regs[0] describes B/D/F information for the + * device. + */ + if (assigned_addr[i].pci_phys_mid == 0 && + assigned_addr[i].pci_phys_low == 0) { + dev_err(dip, CE_WARN, "regs[%u] does not have " + "a valid MMIO address", i + 1); + goto err; + } + pci_rp->pci_phys_mid = assigned_addr[i].pci_phys_mid; pci_rp->pci_phys_low = assigned_addr[i].pci_phys_low; ddi_prop_free(assigned_addr); @@ -1025,6 +1051,7 @@ pci_common_get_reg_prop(dev_info_t *dip, pci_regspec_t *pci_rp) } } +err: ddi_prop_free(assigned_addr); return (DDI_FAILURE); } diff --git a/usr/src/uts/intel/io/viona/viona_impl.h b/usr/src/uts/intel/io/viona/viona_impl.h index 760474e78b..c99bd2c51e 100644 --- a/usr/src/uts/intel/io/viona/viona_impl.h +++ b/usr/src/uts/intel/io/viona/viona_impl.h @@ -35,7 +35,7 @@ * * Copyright 2015 Pluribus Networks Inc. * Copyright 2019 Joyent, Inc. - * Copyright 2021 Oxide Computer Company + * Copyright 2022 Oxide Computer Company */ #ifndef _VIONA_IMPL_H @@ -76,7 +76,8 @@ enum viona_ring_state { enum viona_ring_state_flags { VRSF_REQ_START = 0x1, /* start running from INIT state */ VRSF_REQ_STOP = 0x2, /* stop running, clean up, goto RESET state */ - VRSF_RENEW = 0x4, /* ring renewing lease */ + VRSF_REQ_PAUSE = 0x4, /* stop running, goto INIT state */ + VRSF_RENEW = 0x8, /* ring renewing lease */ }; typedef struct viona_vring { @@ -232,11 +233,6 @@ struct virtio_net_hdr { }; #pragma pack() -#define VRING_NEED_BAIL(ring, proc) \ - (((ring)->vr_state_flags & VRSF_REQ_STOP) != 0 || \ - ((proc)->p_flag & SEXITING) != 0) - - #define VNETHOOK_INTERESTED_IN(neti) \ (neti)->vni_nethook.vnh_event_in.he_interested #define VNETHOOK_INTERESTED_OUT(neti) \ @@ -288,12 +284,23 @@ struct virtio_net_hdr { #define VIRTIO_F_RING_INDIRECT_DESC (1 << 28) #define VIRTIO_F_RING_EVENT_IDX (1 << 29) +struct viona_ring_params { + uint64_t vrp_pa; + uint16_t vrp_size; + uint16_t vrp_avail_idx; + uint16_t vrp_used_idx; +}; void viona_ring_alloc(viona_link_t *, viona_vring_t *); void viona_ring_free(viona_vring_t *); +int viona_ring_get_state(viona_link_t *, uint16_t, struct viona_ring_params *); +int viona_ring_set_state(viona_link_t *, uint16_t, + const struct viona_ring_params *); int viona_ring_reset(viona_vring_t *, boolean_t); -int viona_ring_init(viona_link_t *, uint16_t, uint16_t, uint64_t); +int viona_ring_init(viona_link_t *, uint16_t, const struct viona_ring_params *); boolean_t viona_ring_lease_renew(viona_vring_t *); +bool vring_need_bail(const viona_vring_t *); +int viona_ring_pause(viona_vring_t *); int vq_popchain(viona_vring_t *, struct iovec *, uint_t, uint16_t *, vmm_page_t **); diff --git a/usr/src/uts/intel/io/viona/viona_main.c b/usr/src/uts/intel/io/viona/viona_main.c index a34196ba1a..c6a750d532 100644 --- a/usr/src/uts/intel/io/viona/viona_main.c +++ b/usr/src/uts/intel/io/viona/viona_main.c @@ -35,7 +35,7 @@ * * Copyright 2015 Pluribus Networks Inc. * Copyright 2019 Joyent, Inc. - * Copyright 2021 Oxide Computer Company + * Copyright 2022 Oxide Computer Company */ /* @@ -111,6 +111,14 @@ * | VRS_RESET and exit. * | ^ * | | + * |<-------------------------------------------<+ + * | | | + * | | ^ + * | * If ring is requested to pause (but not stop)from the + * | VRS_RUN state, it will return to the VRS_INIT state. + * | + * | ^ + * | | * | ^ * V * +-----------+ The worker thread associated with the ring has started @@ -286,8 +294,11 @@ static int viona_ioc_delete(viona_soft_state_t *, boolean_t); static int viona_ioc_set_notify_ioport(viona_link_t *, uint16_t); static int viona_ioc_ring_init(viona_link_t *, void *, int); +static int viona_ioc_ring_set_state(viona_link_t *, void *, int); +static int viona_ioc_ring_get_state(viona_link_t *, void *, int); static int viona_ioc_ring_reset(viona_link_t *, uint_t); static int viona_ioc_ring_kick(viona_link_t *, uint_t); +static int viona_ioc_ring_pause(viona_link_t *, uint_t); static int viona_ioc_ring_set_msi(viona_link_t *, void *, int); static int viona_ioc_ring_intr_clear(viona_link_t *, uint_t); static int viona_ioc_intr_poll(viona_link_t *, void *, int, int *); @@ -530,6 +541,9 @@ viona_ioctl(dev_t dev, int cmd, intptr_t data, int md, cred_t *cr, int *rv) return (viona_ioc_create(ss, dptr, md, cr)); case VNA_IOC_DELETE: return (viona_ioc_delete(ss, B_FALSE)); + case VNA_IOC_VERSION: + *rv = VIONA_CURRENT_INTERFACE_VERSION; + return (0); default: break; } @@ -578,6 +592,16 @@ viona_ioctl(dev_t dev, int cmd, intptr_t data, int md, cred_t *cr, int *rv) case VNA_IOC_RING_INTR_CLR: err = viona_ioc_ring_intr_clear(link, (uint_t)data); break; + case VNA_IOC_RING_SET_STATE: + err = viona_ioc_ring_set_state(link, dptr, md); + break; + case VNA_IOC_RING_GET_STATE: + err = viona_ioc_ring_get_state(link, dptr, md); + break; + case VNA_IOC_RING_PAUSE: + err = viona_ioc_ring_pause(link, (uint_t)data); + break; + case VNA_IOC_INTR_POLL: err = viona_ioc_intr_poll(link, dptr, md, rv); break; @@ -853,13 +877,65 @@ viona_ioc_ring_init(viona_link_t *link, void *udata, int md) if (ddi_copyin(udata, &kri, sizeof (kri), md) != 0) { return (EFAULT); } + const struct viona_ring_params params = { + .vrp_pa = kri.ri_qaddr, + .vrp_size = kri.ri_qsize, + .vrp_avail_idx = 0, + .vrp_used_idx = 0, + }; + + err = viona_ring_init(link, kri.ri_index, ¶ms); + + return (err); +} + +static int +viona_ioc_ring_set_state(viona_link_t *link, void *udata, int md) +{ + vioc_ring_state_t krs; + int err; + + if (ddi_copyin(udata, &krs, sizeof (krs), md) != 0) { + return (EFAULT); + } + const struct viona_ring_params params = { + .vrp_pa = krs.vrs_qaddr, + .vrp_size = krs.vrs_qsize, + .vrp_avail_idx = krs.vrs_avail_idx, + .vrp_used_idx = krs.vrs_used_idx, + }; - err = viona_ring_init(link, kri.ri_index, kri.ri_qsize, kri.ri_qaddr); + err = viona_ring_init(link, krs.vrs_index, ¶ms); return (err); } static int +viona_ioc_ring_get_state(viona_link_t *link, void *udata, int md) +{ + vioc_ring_state_t krs; + + if (ddi_copyin(udata, &krs, sizeof (krs), md) != 0) { + return (EFAULT); + } + + struct viona_ring_params params; + int err = viona_ring_get_state(link, krs.vrs_index, ¶ms); + if (err != 0) { + return (err); + } + krs.vrs_qsize = params.vrp_size; + krs.vrs_qaddr = params.vrp_pa; + krs.vrs_avail_idx = params.vrp_avail_idx; + krs.vrs_used_idx = params.vrp_used_idx; + + if (ddi_copyout(&krs, udata, sizeof (krs), md) != 0) { + return (EFAULT); + } + return (0); +} + +static int viona_ioc_ring_reset(viona_link_t *link, uint_t idx) { viona_vring_t *ring; @@ -909,6 +985,17 @@ viona_ioc_ring_kick(viona_link_t *link, uint_t idx) } static int +viona_ioc_ring_pause(viona_link_t *link, uint_t idx) +{ + if (idx >= VIONA_VQ_MAX) { + return (EINVAL); + } + + viona_vring_t *ring = &link->l_vrings[idx]; + return (viona_ring_pause(ring)); +} + +static int viona_ioc_ring_set_msi(viona_link_t *link, void *data, int md) { vioc_ring_msi_t vrm; @@ -935,21 +1022,33 @@ viona_notify_iop(void *arg, bool in, uint16_t port, uint8_t bytes, uint32_t *val) { viona_link_t *link = (viona_link_t *)arg; - uint16_t vq = *val; - if (in) { - /* - * Do not service read (in/ins) requests on this ioport. - * Instead, indicate that the handler is not found, causing a - * fallback to userspace processing. - */ + /* + * If the request is a read (in/ins), or direct at a port other than + * what we expect to be registered on, ignore it. + */ + if (in || port != link->l_notify_ioport) { return (ESRCH); } - if (port != link->l_notify_ioport) { - return (EINVAL); + /* Let userspace handle notifications for rings other than RX/TX. */ + const uint16_t vq = *val; + if (vq >= VIONA_VQ_MAX) { + return (ESRCH); } - return (viona_ioc_ring_kick(link, vq)); + + viona_vring_t *ring = &link->l_vrings[vq]; + int res = 0; + + mutex_enter(&ring->vr_lock); + if (ring->vr_state == VRS_RUN) { + cv_broadcast(&ring->vr_cv); + } else { + res = ESRCH; + } + mutex_exit(&ring->vr_lock); + + return (res); } static int diff --git a/usr/src/uts/intel/io/viona/viona_ring.c b/usr/src/uts/intel/io/viona/viona_ring.c index 2d847dda09..9339f805d4 100644 --- a/usr/src/uts/intel/io/viona/viona_ring.c +++ b/usr/src/uts/intel/io/viona/viona_ring.c @@ -35,7 +35,7 @@ * * Copyright 2015 Pluribus Networks Inc. * Copyright 2019 Joyent, Inc. - * Copyright 2021 Oxide Computer Company + * Copyright 2022 Oxide Computer Company */ @@ -281,15 +281,19 @@ viona_ring_free(viona_vring_t *ring) } int -viona_ring_init(viona_link_t *link, uint16_t idx, uint16_t qsz, uint64_t pa) +viona_ring_init(viona_link_t *link, uint16_t idx, + const struct viona_ring_params *params) { viona_vring_t *ring; kthread_t *t; int err = 0; + const uint16_t qsz = params->vrp_size; + const uint64_t pa = params->vrp_pa; if (idx >= VIONA_VQ_MAX) { return (EINVAL); } + if (qsz == 0 || qsz > VRING_MAX_LEN || (1 << (ffs(qsz) - 1)) != qsz) { return (EINVAL); } @@ -320,8 +324,8 @@ viona_ring_init(viona_link_t *link, uint16_t idx, uint16_t qsz, uint64_t pa) } /* Initialize queue indexes */ - ring->vr_cur_aidx = 0; - ring->vr_cur_uidx = 0; + ring->vr_cur_aidx = params->vrp_avail_idx; + ring->vr_cur_uidx = params->vrp_used_idx; if (idx == VIONA_VQ_TX) { viona_tx_ring_alloc(ring, qsz); @@ -351,11 +355,48 @@ fail: ring->vr_size = 0; ring->vr_mask = 0; ring->vr_pa = 0; + ring->vr_cur_aidx = 0; + ring->vr_cur_uidx = 0; mutex_exit(&ring->vr_lock); return (err); } int +viona_ring_get_state(viona_link_t *link, uint16_t idx, + struct viona_ring_params *params) +{ + viona_vring_t *ring; + + if (idx >= VIONA_VQ_MAX) { + return (EINVAL); + } + + ring = &link->l_vrings[idx]; + mutex_enter(&ring->vr_lock); + + params->vrp_size = ring->vr_size; + params->vrp_pa = ring->vr_pa; + + if (ring->vr_state == VRS_RUN) { + /* On a running ring, we must heed the avail/used locks */ + mutex_enter(&ring->vr_a_mutex); + params->vrp_avail_idx = ring->vr_cur_aidx; + mutex_exit(&ring->vr_a_mutex); + mutex_enter(&ring->vr_u_mutex); + params->vrp_used_idx = ring->vr_cur_uidx; + mutex_exit(&ring->vr_u_mutex); + } else { + /* Otherwise vr_lock is adequate protection */ + params->vrp_avail_idx = ring->vr_cur_aidx; + params->vrp_used_idx = ring->vr_cur_uidx; + } + + mutex_exit(&ring->vr_lock); + + return (0); +} + +int viona_ring_reset(viona_vring_t *ring, boolean_t heed_signals) { mutex_enter(&ring->vr_lock); @@ -485,40 +526,152 @@ viona_intr_ring(viona_vring_t *ring, boolean_t skip_flags_check) } } +static inline bool +vring_stop_req(const viona_vring_t *ring) +{ + return ((ring->vr_state_flags & VRSF_REQ_STOP) != 0); +} + +static inline bool +vring_pause_req(const viona_vring_t *ring) +{ + return ((ring->vr_state_flags & VRSF_REQ_PAUSE) != 0); +} + +static inline bool +vring_start_req(const viona_vring_t *ring) +{ + return ((ring->vr_state_flags & VRSF_REQ_START) != 0); +} + +/* + * Check if vring worker thread should bail out. This will heed indications + * that the containing process is exiting, as well as requests to stop or pause + * the ring. The `stop_only` parameter controls if pause requests are ignored + * (true) or checked (false). + * + * Caller should hold vr_lock. + */ +static bool +vring_need_bail_ext(const viona_vring_t *ring, bool stop_only) +{ + ASSERT(MUTEX_HELD(&ring->vr_lock)); + + if (vring_stop_req(ring) || + (!stop_only && vring_pause_req(ring))) { + return (true); + } + + kthread_t *t = ring->vr_worker_thread; + if (t != NULL) { + proc_t *p = ttoproc(t); + + ASSERT(p != NULL); + if ((p->p_flag & SEXITING) != 0) { + return (true); + } + } + return (false); +} + +bool +vring_need_bail(const viona_vring_t *ring) +{ + return (vring_need_bail_ext(ring, false)); +} + +int +viona_ring_pause(viona_vring_t *ring) +{ + mutex_enter(&ring->vr_lock); + switch (ring->vr_state) { + case VRS_RESET: + case VRS_SETUP: + case VRS_INIT: + /* + * For rings which have not yet started (even those in the + * VRS_SETUP and VRS_INIT phases, where there a running worker + * thread (waiting to be released to do its intended task), it + * is adequate to simply clear any start request, to keep them + * from proceeding into the actual work processing function. + */ + ring->vr_state_flags &= ~VRSF_REQ_START; + mutex_exit(&ring->vr_lock); + return (0); + + case VRS_STOP: + if ((ring->vr_state_flags & VRSF_REQ_STOP) != 0) { + /* A ring on its way to RESET cannot be paused. */ + mutex_exit(&ring->vr_lock); + return (EBUSY); + } + /* FALLTHROUGH */ + case VRS_RUN: + ring->vr_state_flags |= VRSF_REQ_PAUSE; + cv_broadcast(&ring->vr_cv); + break; + + default: + panic("invalid ring state %d", ring->vr_state); + break; + } + + for (;;) { + int res = cv_wait_sig(&ring->vr_cv, &ring->vr_lock); + + if (ring->vr_state == VRS_INIT || + (ring->vr_state_flags & VRSF_REQ_PAUSE) == 0) { + /* Ring made it to (or through) paused state */ + mutex_exit(&ring->vr_lock); + return (0); + } + if (res == 0) { + /* interrupted by signal */ + mutex_exit(&ring->vr_lock); + return (EINTR); + } + } + /* NOTREACHED */ +} + static void viona_worker(void *arg) { viona_vring_t *ring = (viona_vring_t *)arg; viona_link_t *link = ring->vr_link; - proc_t *p = ttoproc(curthread); mutex_enter(&ring->vr_lock); VERIFY3U(ring->vr_state, ==, VRS_SETUP); /* Bail immediately if ring shutdown or process exit was requested */ - if (VRING_NEED_BAIL(ring, p)) { - goto cleanup; + if (vring_need_bail_ext(ring, true)) { + goto ring_reset; } /* Report worker thread as alive and notify creator */ +ring_init: ring->vr_state = VRS_INIT; cv_broadcast(&ring->vr_cv); - while (ring->vr_state_flags == 0) { + while (!vring_start_req(ring)) { /* * Keeping lease renewals timely while waiting for the ring to * be started is important for avoiding deadlocks. */ if (vmm_drv_lease_expired(ring->vr_lease)) { if (!viona_ring_lease_renew(ring)) { - goto cleanup; + goto ring_reset; } } (void) cv_wait_sig(&ring->vr_cv, &ring->vr_lock); - if (VRING_NEED_BAIL(ring, p)) { - goto cleanup; + if (vring_pause_req(ring)) { + /* We are already paused in the INIT state. */ + ring->vr_state_flags &= ~VRSF_REQ_PAUSE; + } + if (vring_need_bail_ext(ring, true)) { + goto ring_reset; } } @@ -529,7 +682,7 @@ viona_worker(void *arg) /* Ensure ring lease is valid first */ if (vmm_drv_lease_expired(ring->vr_lease)) { if (!viona_ring_lease_renew(ring)) { - goto cleanup; + goto ring_reset; } } @@ -543,15 +696,18 @@ viona_worker(void *arg) } VERIFY3U(ring->vr_state, ==, VRS_STOP); + VERIFY3U(ring->vr_xfer_outstanding, ==, 0); -cleanup: - if (ring->vr_txdesb != NULL) { - /* - * Transmit activity must be entirely concluded before the - * associated descriptors can be cleaned up. - */ - VERIFY(ring->vr_xfer_outstanding == 0); + /* Respond to a pause request if the ring is not required to stop */ + if (vring_pause_req(ring)) { + ring->vr_state_flags &= ~VRSF_REQ_PAUSE; + + if (!vring_need_bail_ext(ring, true)) { + goto ring_init; + } } + +ring_reset: viona_ring_misc_free(ring); viona_ring_lease_drop(ring); diff --git a/usr/src/uts/intel/io/viona/viona_rx.c b/usr/src/uts/intel/io/viona/viona_rx.c index 2fbf6be972..e6f6f421d5 100644 --- a/usr/src/uts/intel/io/viona/viona_rx.c +++ b/usr/src/uts/intel/io/viona/viona_rx.c @@ -35,7 +35,7 @@ * * Copyright 2015 Pluribus Networks Inc. * Copyright 2019 Joyent, Inc. - * Copyright 2021 Oxide Computer Company + * Copyright 2022 Oxide Computer Company */ #include <sys/types.h> @@ -86,8 +86,6 @@ viona_rx_fini(void) void viona_worker_rx(viona_vring_t *ring, viona_link_t *link) { - proc_t *p = ttoproc(curthread); - (void) thread_vsetname(curthread, "viona_rx_%p", ring); ASSERT(MUTEX_HELD(&ring->vr_lock)); @@ -122,7 +120,7 @@ viona_worker_rx(viona_vring_t *ring, viona_link_t *link) * place to inject frames into the guest. */ (void) cv_wait_sig(&ring->vr_cv, &ring->vr_lock); - } while (!VRING_NEED_BAIL(ring, p)); + } while (!vring_need_bail(ring)); ring->vr_state = VRS_STOP; diff --git a/usr/src/uts/intel/io/viona/viona_tx.c b/usr/src/uts/intel/io/viona/viona_tx.c index 277ee521a1..306c6f308e 100644 --- a/usr/src/uts/intel/io/viona/viona_tx.c +++ b/usr/src/uts/intel/io/viona/viona_tx.c @@ -35,7 +35,7 @@ * * Copyright 2015 Pluribus Networks Inc. * Copyright 2019 Joyent, Inc. - * Copyright 2021 Oxide Computer Company + * Copyright 2022 Oxide Computer Company */ @@ -179,11 +179,11 @@ viona_tx_done(viona_vring_t *ring, uint32_t len, uint16_t cookie) viona_intr_ring(ring, B_FALSE); } +#define TX_BURST_THRESH 32 + void viona_worker_tx(viona_vring_t *ring, viona_link_t *link) { - proc_t *p = ttoproc(curthread); - (void) thread_vsetname(curthread, "viona_tx_%p", ring); ASSERT(MUTEX_HELD(&ring->vr_lock)); @@ -192,23 +192,30 @@ viona_worker_tx(viona_vring_t *ring, viona_link_t *link) mutex_exit(&ring->vr_lock); for (;;) { - boolean_t bail = B_FALSE; - boolean_t renew = B_FALSE; - uint_t ntx = 0; + uint_t ntx = 0, burst = 0; viona_ring_disable_notify(ring); - while (viona_ring_num_avail(ring)) { + while (viona_ring_num_avail(ring) != 0) { viona_tx(link, ring); + ntx++; + burst++; /* * It is advantageous for throughput to keep this * transmission loop tight, but periodic breaks to * check for other events are of value too. */ - if (ntx++ >= ring->vr_size) - break; + if (burst >= TX_BURST_THRESH) { + mutex_enter(&ring->vr_lock); + const bool need_bail = vring_need_bail(ring); + mutex_exit(&ring->vr_lock); + + if (need_bail) { + break; + } + burst = 0; + } } - viona_ring_enable_notify(ring); VIONA_PROBE2(tx, viona_link_t *, link, uint_t, ntx); @@ -219,14 +226,11 @@ viona_worker_tx(viona_vring_t *ring, viona_link_t *link) * The barrier ensures that visibility of the no-notify * store does not cross the viona_ring_num_avail() check below. */ + viona_ring_enable_notify(ring); membar_enter(); - bail = VRING_NEED_BAIL(ring, p); - renew = vmm_drv_lease_expired(ring->vr_lease); - if (!bail && !renew && viona_ring_num_avail(ring)) { - continue; - } - if ((link->l_features & VIRTIO_F_RING_NOTIFY_ON_EMPTY) != 0) { + if (viona_ring_num_avail(ring) == 0 && + (link->l_features & VIRTIO_F_RING_NOTIFY_ON_EMPTY) != 0) { /* * The NOTIFY_ON_EMPTY interrupt should not pay heed to * the presence of AVAIL_NO_INTERRUPT. @@ -235,36 +239,43 @@ viona_worker_tx(viona_vring_t *ring, viona_link_t *link) } mutex_enter(&ring->vr_lock); + for (;;) { + if (vring_need_bail(ring)) { + ring->vr_state = VRS_STOP; + viona_tx_wait_outstanding(ring); + return; + } - while (!bail && !renew && !viona_ring_num_avail(ring)) { - (void) cv_wait_sig(&ring->vr_cv, &ring->vr_lock); - bail = VRING_NEED_BAIL(ring, p); - renew = vmm_drv_lease_expired(ring->vr_lease); - } - - if (bail) { - break; - } else if (renew) { - ring->vr_state_flags |= VRSF_RENEW; - /* - * When renewing the lease for the ring, no TX - * frames may be outstanding, as they contain - * references to guest memory. - */ - viona_tx_wait_outstanding(ring); + if (vmm_drv_lease_expired(ring->vr_lease)) { + ring->vr_state_flags |= VRSF_RENEW; + /* + * When renewing the lease for the ring, no TX + * frames may be outstanding, as they contain + * references to guest memory. + */ + viona_tx_wait_outstanding(ring); + + const boolean_t renewed = + viona_ring_lease_renew(ring); + ring->vr_state_flags &= ~VRSF_RENEW; + + if (!renewed) { + /* stop ring on failed renewal */ + ring->vr_state = VRS_STOP; + return; + } + } - if (!viona_ring_lease_renew(ring)) { + if (viona_ring_num_avail(ring) != 0) { break; } - ring->vr_state_flags &= ~VRSF_RENEW; + + /* Wait for further activity on the ring */ + (void) cv_wait_sig(&ring->vr_cv, &ring->vr_lock); } mutex_exit(&ring->vr_lock); } - - ASSERT(MUTEX_HELD(&ring->vr_lock)); - - ring->vr_state = VRS_STOP; - viona_tx_wait_outstanding(ring); + /* UNREACHABLE */ } static void diff --git a/usr/src/uts/intel/io/vmm/vmm_sol_dev.c b/usr/src/uts/intel/io/vmm/vmm_sol_dev.c index ee07779b21..da83735e43 100644 --- a/usr/src/uts/intel/io/vmm/vmm_sol_dev.c +++ b/usr/src/uts/intel/io/vmm/vmm_sol_dev.c @@ -2239,6 +2239,24 @@ vmm_drv_purge(vmm_softc_t *sc) hold = list_next(&sc->vmm_holds, hold)) { hold->vmh_release_req = B_TRUE; } + + /* + * Require that all leases on the instance be broken, now that + * all associated holds have been marked as needing release. + * + * Dropping vmm_mtx is not strictly necessary, but if any of the + * lessees are slow to respond, it would be nice to leave it + * available for other parties. + */ + mutex_exit(&vmm_mtx); + vmm_lease_block(sc); + vmm_lease_unblock(sc); + mutex_enter(&vmm_mtx); + + /* + * With all of the leases broken, we can proceed in an orderly + * fashion to waiting for any lingering holds to be dropped. + */ while ((sc->vmm_flags & VMM_HELD) != 0) { if (cv_wait_sig(&sc->vmm_cv, &vmm_mtx) <= 0) { return (EINTR); diff --git a/usr/src/uts/intel/sys/viona_io.h b/usr/src/uts/intel/sys/viona_io.h index 46cc72eb06..761445986c 100644 --- a/usr/src/uts/intel/sys/viona_io.h +++ b/usr/src/uts/intel/sys/viona_io.h @@ -12,6 +12,7 @@ /* * Copyright 2013 Pluribus Networks Inc. * Copyright 2018 Joyent, Inc. + * Copyright 2022 Oxide Computer Company */ #ifndef _VIONA_IO_H_ @@ -20,18 +21,39 @@ #define VNA_IOC (('V' << 16)|('C' << 8)) #define VNA_IOC_CREATE (VNA_IOC | 0x01) #define VNA_IOC_DELETE (VNA_IOC | 0x02) +#define VNA_IOC_VERSION (VNA_IOC | 0x03) #define VNA_IOC_RING_INIT (VNA_IOC | 0x10) #define VNA_IOC_RING_RESET (VNA_IOC | 0x11) #define VNA_IOC_RING_KICK (VNA_IOC | 0x12) #define VNA_IOC_RING_SET_MSI (VNA_IOC | 0x13) #define VNA_IOC_RING_INTR_CLR (VNA_IOC | 0x14) +#define VNA_IOC_RING_SET_STATE (VNA_IOC | 0x15) +#define VNA_IOC_RING_GET_STATE (VNA_IOC | 0x16) +#define VNA_IOC_RING_PAUSE (VNA_IOC | 0x17) #define VNA_IOC_INTR_POLL (VNA_IOC | 0x20) #define VNA_IOC_SET_FEATURES (VNA_IOC | 0x21) #define VNA_IOC_GET_FEATURES (VNA_IOC | 0x22) #define VNA_IOC_SET_NOTIFY_IOP (VNA_IOC | 0x23) + +/* + * Viona Interface Version + * + * Like bhyve, viona exposes Private interfaces which are nonetheless consumed + * by out-of-gate consumers. While those consumers assume all risk of breakage + * incurred by subsequent changes, it would be nice to equip them to potentially + * detect (and handle) those modifications. + * + * There are no established criteria for the magnitude of change which requires + * this version to be incremented, and maintenance of it is considered a + * best-effort activity. Nothing is to be inferred about the magnitude of a + * change when the version is modified. It follows no rules like semver. + * + */ +#define VIONA_CURRENT_INTERFACE_VERSION 1 + typedef struct vioc_create { datalink_id_t c_linkid; int c_vmfd; @@ -43,6 +65,14 @@ typedef struct vioc_ring_init { uint64_t ri_qaddr; } vioc_ring_init_t; +typedef struct vioc_ring_state { + uint16_t vrs_index; + uint16_t vrs_avail_idx; + uint16_t vrs_used_idx; + uint16_t vrs_qsize; + uint64_t vrs_qaddr; +} vioc_ring_state_t; + typedef struct vioc_ring_msi { uint16_t rm_index; uint64_t rm_addr; |