summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr/src/man/man4d/pty.4d4
-rw-r--r--usr/src/pkg/manifests/system-test-ostest.p5m3
-rw-r--r--usr/src/test/os-tests/runfiles/default.run3
-rw-r--r--usr/src/test/os-tests/tests/Makefile1
-rw-r--r--usr/src/test/os-tests/tests/portfs/Makefile61
-rw-r--r--usr/src/test/os-tests/tests/portfs/file_assoc.c259
-rw-r--r--usr/src/uts/common/fs/portfs/port_fop.c10
-rw-r--r--usr/src/uts/common/io/cpuid_drv.c4
-rw-r--r--usr/src/uts/common/io/mac/mac_client.c5
-rw-r--r--usr/src/uts/i86pc/ml/locore.s6
-rw-r--r--usr/src/uts/i86pc/os/cpupm/pwrnow.c9
-rw-r--r--usr/src/uts/i86pc/os/cpupm/speedstep.c9
-rw-r--r--usr/src/uts/i86pc/os/mlsetup.c25
-rw-r--r--usr/src/uts/i86pc/os/mp_startup.c16
-rw-r--r--usr/src/uts/i86pc/os/pci_mech1_amd.c5
-rw-r--r--usr/src/uts/i86pc/os/startup.c20
-rw-r--r--usr/src/uts/intel/os/archdep.c2
-rw-r--r--usr/src/uts/intel/os/cpuid.c (renamed from usr/src/uts/i86pc/os/cpuid.c)419
-rw-r--r--usr/src/uts/intel/os/cpuid_subr.c (renamed from usr/src/uts/i86pc/os/cpuid_subr.c)8
-rw-r--r--usr/src/uts/intel/sys/x86_archext.h23
20 files changed, 655 insertions, 237 deletions
diff --git a/usr/src/man/man4d/pty.4d b/usr/src/man/man4d/pty.4d
index 0e7cb9ad2f..d9e73c5a4b 100644
--- a/usr/src/man/man4d/pty.4d
+++ b/usr/src/man/man4d/pty.4d
@@ -4,7 +4,7 @@
.\" 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]
.\" Copyright 2022 Oxide Computer Company
-.Dd February 5, 2022
+.Dd August 19, 2022
.Dt PTY 4D
.Os
.Sh NAME
@@ -249,7 +249,7 @@ Pseudo-terminal subsidiary devices.
.El
.Sh SEE ALSO
.Xr rlogin 1 ,
-.Xr posix_openpty 3C ,
+.Xr posix_openpt 3C ,
.Xr ptm 4D ,
.Xr termio 4I ,
.Xr ldterm 4M ,
diff --git a/usr/src/pkg/manifests/system-test-ostest.p5m b/usr/src/pkg/manifests/system-test-ostest.p5m
index 3109a486f5..2315c52658 100644
--- a/usr/src/pkg/manifests/system-test-ostest.p5m
+++ b/usr/src/pkg/manifests/system-test-ostest.p5m
@@ -100,6 +100,9 @@ file path=opt/os-tests/tests/pf_key/kmc-updater mode=0555
dir path=opt/os-tests/tests/poll
file path=opt/os-tests/tests/poll/epoll_test mode=0555
file path=opt/os-tests/tests/poll/poll_test mode=0555
+dir path=opt/os-tests/tests/portfs
+file path=opt/os-tests/tests/portfs/file_assoc.32 mode=0555
+file path=opt/os-tests/tests/portfs/file_assoc.64 mode=0555
dir path=opt/os-tests/tests/sdevfs
file path=opt/os-tests/tests/sdevfs/sdevfs_eisdir mode=0555
dir path=opt/os-tests/tests/secflags
diff --git a/usr/src/test/os-tests/runfiles/default.run b/usr/src/test/os-tests/runfiles/default.run
index f238590938..52c10ac81c 100644
--- a/usr/src/test/os-tests/runfiles/default.run
+++ b/usr/src/test/os-tests/runfiles/default.run
@@ -158,3 +158,6 @@ pre = core_prereqs
tests = ['coretests']
[/opt/os-tests/tests/zen_umc_test]
+
+[/opt/os-tests/tests/portfs]
+tests = ['file_assoc.32', 'file_assoc.64']
diff --git a/usr/src/test/os-tests/tests/Makefile b/usr/src/test/os-tests/tests/Makefile
index 10afe404aa..6dfe29087d 100644
--- a/usr/src/test/os-tests/tests/Makefile
+++ b/usr/src/test/os-tests/tests/Makefile
@@ -28,6 +28,7 @@ SUBDIRS = \
libtopo \
pf_key \
poll \
+ portfs \
sdevfs \
secflags \
sigqueue \
diff --git a/usr/src/test/os-tests/tests/portfs/Makefile b/usr/src/test/os-tests/tests/portfs/Makefile
new file mode 100644
index 0000000000..61d7d4bda4
--- /dev/null
+++ b/usr/src/test/os-tests/tests/portfs/Makefile
@@ -0,0 +1,61 @@
+#
+# 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
+#
+
+PROGS = \
+ file_assoc
+
+PROGS32 = $(PROGS:%=%.32)
+PROGS64 = $(PROGS:%=%.64)
+
+ROOTOPTDIR = $(ROOT)/opt/os-tests/tests
+ROOTOPTPORTFS = $(ROOTOPTDIR)/portfs
+ROOTOPTPROGS = $(PROGS32:%=$(ROOTOPTPORTFS)/%) \
+ $(PROGS64:%=$(ROOTOPTPORTFS)/%)
+
+include $(SRC)/cmd/Makefile.cmd
+
+CSTD=$(GNU_C99)
+
+.KEEP_STATE:
+
+all: $(PROGS32) $(PROGS64)
+
+install: $(ROOTOPTPROGS)
+
+clean:
+
+$(ROOTOPTPROGS): $(PROGS32) $(PROGS64) $(ROOTOPTPORTFS)
+
+$(ROOTOPTDIR):
+ $(INS.dir)
+
+$(ROOTOPTPORTFS): $(ROOTOPTDIR)
+ $(INS.dir)
+
+$(ROOTOPTPORTFS)/%: %
+ $(INS.file)
+
+%.64: %.c
+ $(LINK64.c) -o $@ $< $(LDLIBS64)
+ $(POST_PROCESS)
+
+%.32: %.c
+ $(LINK.c) -o $@ $< $(LDLIBS)
+ $(POST_PROCESS)
+
+clobber:
+ $(RM) $(PROGS32) $(PROGS64)
+
+FRC:
diff --git a/usr/src/test/os-tests/tests/portfs/file_assoc.c b/usr/src/test/os-tests/tests/portfs/file_assoc.c
new file mode 100644
index 0000000000..6fa5c7de4e
--- /dev/null
+++ b/usr/src/test/os-tests/tests/portfs/file_assoc.c
@@ -0,0 +1,259 @@
+/*
+ * 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
+ */
+
+/*
+ * This is designed to act as a basic test of PORT_SOURCE_FILE associations and
+ * a regression test for illumos#14898. In particular we want to verify certain
+ * behaviors of association and disassociation with respect to the value in the
+ * user payload. We will create and tear down the underlying event port each
+ * time. The rough cases are:
+ *
+ * o associate, trigger, port_get -> first associate event
+ * o associate, associate, trigger, port_get -> second associate event
+ * o associate, trigger, associate, port_get -> second associate event
+ * o associate, disassociate, port_get -> no event
+ * o associate, trigger, disassociate, port_get -> no event
+ * o associate, trigger, disassociate, associate, port_get -> second associate
+ * event
+ * o associate, trigger, disassociate, fstat, associate, port_get -> no event
+ */
+
+#include <port.h>
+#include <err.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <stdbool.h>
+#include <sys/sysmacros.h>
+
+static int fa_nfail = 0;
+static uintptr_t fa_user = 1;
+static char *fa_path;
+
+/*
+ * This is a series of actions that we want to be able to take on our port. We
+ * keep going until we do encounter a FA_DONE, at which point we do a
+ * port_get() to compare things.
+ */
+typedef enum {
+ FA_DONE,
+ FA_ASSOC,
+ FA_DEASSOC,
+ FA_FSTAT,
+ FA_TRIGGER
+} fa_act_t;
+
+#define FA_MAX_EVENTS 6
+
+typedef struct {
+ bool fa_getevent;
+ const char *fa_msg;
+ fa_act_t fa_acts[FA_MAX_EVENTS];
+} fa_test_t;
+
+fa_test_t fa_tests[] = {
+ { false, "port_get -> no event",
+ { FA_TRIGGER, FA_DONE } },
+ { false, "associate, port_get -> no event",
+ { FA_ASSOC, FA_DONE } },
+ { true, "associate, trigger, port_get -> first user",
+ { FA_ASSOC, FA_TRIGGER, FA_DONE } },
+ { true, "associate, associate, trigger, port_get -> second user",
+ { FA_ASSOC, FA_ASSOC, FA_TRIGGER, FA_DONE } },
+ { true, "associate, trigger, associate, port_get -> second user",
+ { FA_ASSOC, FA_TRIGGER, FA_ASSOC, FA_DONE } },
+ { false, "associate, disassociate, port_get -> no event",
+ { FA_ASSOC, FA_DEASSOC, FA_DONE } },
+ { false, "associate, trigger, disassociate, port_get -> no event",
+ { FA_ASSOC, FA_TRIGGER, FA_DEASSOC, FA_DONE } },
+ { true, "associate, trigger, disassociate, associate, port_get -> "
+ "second user", { FA_ASSOC, FA_TRIGGER, FA_DEASSOC, FA_ASSOC,
+ FA_DONE } },
+ { false, "associate, trigger, disassociate, fstat, associate, port_get "
+ "-> no event", { FA_ASSOC, FA_TRIGGER, FA_DEASSOC, FA_FSTAT,
+ FA_ASSOC, FA_DONE } },
+};
+
+static void
+fa_run_test(int portfd, int filefd, fa_test_t *test)
+{
+ int ret;
+ uint_t nget;
+ struct stat st;
+ struct file_obj fo;
+ port_event_t pe;
+ struct timespec to;
+ bool pass;
+
+ /*
+ * At the beginning of a test we stat our underlying file so we can make
+ * sure our information is up to date. We purposefully keep it the same
+ * across a run so that way certain tests will automatically trigger an
+ * event on association.
+ */
+ if (fstat(filefd, &st) != 0) {
+ warn("failed to stat %s", fa_path);
+ (void) printf("TEST FAILED: %s\n", test->fa_msg);
+ fa_nfail = 1;
+ return;
+ }
+
+ bzero(&fo, sizeof (fo));
+
+ for (uint_t i = 0; test->fa_acts[i] != FA_DONE; i++) {
+ uint32_t data;
+
+ switch (test->fa_acts[i]) {
+ case FA_ASSOC:
+ bzero(&fo, sizeof (fo));
+ fo.fo_atime = st.st_atim;
+ fo.fo_mtime = st.st_mtim;
+ fo.fo_ctime = st.st_ctim;
+ fo.fo_name = fa_path;
+
+ fa_user++;
+ if (port_associate(portfd, PORT_SOURCE_FILE,
+ (uintptr_t)&fo, FILE_MODIFIED, (void *)fa_user) <
+ 0) {
+ warn("failed to associate event");
+ fa_nfail = 1;
+ }
+ break;
+ case FA_DEASSOC:
+ if (port_dissociate(portfd, PORT_SOURCE_FILE,
+ (uintptr_t)&fo) != 0) {
+ warn("failed to dissociate event");
+ fa_nfail = 1;
+ }
+ break;
+ case FA_FSTAT:
+ if (fstat(filefd, &st) != 0) {
+ warn("failed to stat %s", fa_path);
+ fa_nfail = 1;
+ }
+ break;
+ case FA_TRIGGER:
+ data = arc4random();
+ if (write(filefd, &data, sizeof (data)) < 0) {
+ warn("failed to write data to %s", fa_path);
+ }
+ break;
+ default:
+ abort();
+ }
+ }
+
+ /*
+ * At this point we attempt to see if there's an event for us. We
+ * explicitly zero the timeout so we don't wait at all.
+ */
+ bzero(&to, sizeof (to));
+ bzero(&pe, sizeof (pe));
+ nget = 1;
+ ret = port_getn(portfd, &pe, 1, &nget, &to);
+ if (ret < 0) {
+ warn("port_getn failed unexpectedly");
+ (void) printf("TEST FAILED: %s\n", test->fa_msg);
+ fa_nfail = 1;
+ return;
+ }
+
+ if (!test->fa_getevent) {
+ if (nget != 0) {
+ warnx("port_getn() returned an event, but we expected "
+ "none");
+ (void) printf("portev_events: 0x%x, portev_source: "
+ "0x%x\n", pe.portev_events, pe.portev_source);
+ (void) printf("TEST FAILED: %s\n", test->fa_msg);
+ fa_nfail = 1;
+ } else {
+ (void) printf("TEST PASSED: %s\n", test->fa_msg);
+ }
+ return;
+ } else {
+ if (nget == 0) {
+ warnx("port_getn() returned no events, but we expected "
+ "one");
+ (void) printf("TEST FAILED: %s\n", test->fa_msg);
+ fa_nfail = 1;
+ return;
+ }
+ }
+
+ pass = true;
+ if (pe.portev_source != PORT_SOURCE_FILE) {
+ (void) printf("port source mismatch: found 0x%x, expected "
+ "0x%x\n", pe.portev_source, PORT_SOURCE_FILE);
+ pass = false;
+ }
+
+ if (pe.portev_events != FILE_MODIFIED) {
+ (void) printf("port events mismatch: found 0x%x, expected "
+ "0x%x\n", pe.portev_events, FILE_MODIFIED);
+ pass = false;
+ }
+
+ if ((uintptr_t)pe.portev_user != fa_user) {
+ (void) printf("port user mismatch: found 0x%p, expected "
+ "0x%lx\n", pe.portev_user, fa_user);
+ pass = false;
+
+ }
+
+ if (pass) {
+ (void) printf("TEST PASSED: %s\n", test->fa_msg);
+ } else {
+ fa_nfail = 1;
+ (void) printf("TEST FAILED: %s\n", test->fa_msg);
+ }
+}
+
+int
+main(void)
+{
+ int fd;
+
+
+ if (asprintf(&fa_path, "/tmp/file_assoc_test.%d", getpid()) < 0) {
+ err(EXIT_FAILURE, "failed to create temp file");
+ }
+
+ fd = open(fa_path, O_RDWR | O_CREAT, 0644);
+ if (fd < 0) {
+ err(EXIT_FAILURE, "failed to create %s", fa_path);
+ }
+
+ /*
+ * We open and close the underlying port that we're using for each run
+ * to make sure that any associations that were created do not persist.
+ */
+ for (uint_t i = 0; i < ARRAY_SIZE(fa_tests); i++) {
+ int port = port_create();
+ if (port < 0) {
+ err(EXIT_FAILURE, "failed to create event port");
+ }
+ fa_run_test(port, fd, &fa_tests[i]);
+ (void) close(port);
+ }
+
+ (void) close(fd);
+ (void) unlink(fa_path);
+ return (fa_nfail);
+}
diff --git a/usr/src/uts/common/fs/portfs/port_fop.c b/usr/src/uts/common/fs/portfs/port_fop.c
index a6ca583a4d..e11d5c8be4 100644
--- a/usr/src/uts/common/fs/portfs/port_fop.c
+++ b/usr/src/uts/common/fs/portfs/port_fop.c
@@ -25,6 +25,7 @@
/*
* Copyright 2020 Joyent, Inc.
+ * Copyright 2022 Oxide Computer Company
*/
/*
@@ -730,8 +731,8 @@ port_cache_lookup_fop(portfop_cache_t *pfcp, pid_t pid, uintptr_t obj)
* caller has to VN_PHANTOM_RELE the vnode(s).
*/
int
-port_fop_getdvp(void *objptr, vnode_t **vp, vnode_t **dvp,
- char **cname, int *len, int follow)
+port_fop_getdvp(void *objptr, vnode_t **vp, vnode_t **dvp, char **cname,
+ int *len, int follow)
{
int error = 0;
struct pathname pn;
@@ -1476,16 +1477,17 @@ port_associate_fop(port_t *pp, int source, uintptr_t object, int events,
mutex_enter(&pvp->pvp_mutex);
/*
- * remove any queued up event.
+ * Remove any queued up event.
*/
if (port_remove_done_event(pfp->pfop_pev)) {
pfp->pfop_flags &= ~PORT_FOP_KEV_ONQ;
}
/*
- * set new events to watch.
+ * Set new events to watch and update the user pointer.
*/
pfp->pfop_events = events;
+ pfp->pfop_pev->portkev_user = user;
/*
* If not active, mark it active even if it is being
diff --git a/usr/src/uts/common/io/cpuid_drv.c b/usr/src/uts/common/io/cpuid_drv.c
index 35bc999b44..ef3a21793f 100644
--- a/usr/src/uts/common/io/cpuid_drv.c
+++ b/usr/src/uts/common/io/cpuid_drv.c
@@ -23,6 +23,7 @@
*/
/*
* Copyright 2019 Joyent, Inc.
+ * Copyright 2022 Oxide Computer Co.
*/
@@ -114,8 +115,7 @@ cpuid_read(dev_t dev, uio_t *uio, cred_t *cr)
struct cpuid_regs crs;
int error = 0;
- if (!is_x86_feature(x86_featureset, X86FSET_CPUID))
- return (ENXIO);
+ ASSERT(is_x86_feature(x86_featureset, X86FSET_CPUID));
if (uio->uio_resid & (sizeof (crs) - 1))
return (EINVAL);
diff --git a/usr/src/uts/common/io/mac/mac_client.c b/usr/src/uts/common/io/mac/mac_client.c
index b166e7987a..952b4c844b 100644
--- a/usr/src/uts/common/io/mac/mac_client.c
+++ b/usr/src/uts/common/io/mac/mac_client.c
@@ -23,7 +23,7 @@
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2019 Joyent, Inc.
* Copyright 2017 RackTop Systems.
- * Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
+ * Copyright 2022 OmniOS Community Edition (OmniOSce) Association.
*/
/*
@@ -1612,7 +1612,6 @@ mac_rx_set(mac_client_handle_t mch, mac_rx_t rx_fn, void *arg)
mcip->mci_rx_fn = rx_fn;
mcip->mci_rx_arg = arg;
mac_rx_client_restart(mch);
- i_mac_perim_exit(mip);
/*
* If we're changing the Rx function on the primary MAC of a VNIC,
@@ -1622,6 +1621,8 @@ mac_rx_set(mac_client_handle_t mch, mac_rx_t rx_fn, void *arg)
ASSERT((umip->mi_state_flags & MIS_IS_VNIC) != 0);
mac_vnic_secondary_update(umip);
}
+
+ i_mac_perim_exit(mip);
}
/*
diff --git a/usr/src/uts/i86pc/ml/locore.s b/usr/src/uts/i86pc/ml/locore.s
index b7bd1ba4e4..5aac5e860b 100644
--- a/usr/src/uts/i86pc/ml/locore.s
+++ b/usr/src/uts/i86pc/ml/locore.s
@@ -41,7 +41,6 @@
#include <sys/privregs.h>
#include <sys/psw.h>
#include <sys/reboot.h>
-#include <sys/x86_archext.h>
#include <sys/machparam.h>
#include <sys/segments.h>
@@ -183,11 +182,6 @@
#endif /* __xpv */
/*
- * (We just assert this works by virtue of being here)
- */
- btsl $X86FSET_CPUID, x86_featureset(%rip)
-
- /*
* mlsetup() gets called with a struct regs as argument, while
* main takes no args and should never return.
*/
diff --git a/usr/src/uts/i86pc/os/cpupm/pwrnow.c b/usr/src/uts/i86pc/os/cpupm/pwrnow.c
index c7f2415e74..f5af02a2ae 100644
--- a/usr/src/uts/i86pc/os/cpupm/pwrnow.c
+++ b/usr/src/uts/i86pc/os/cpupm/pwrnow.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2022 Oxide Computer Co.
*/
#include <sys/x86_archext.h>
@@ -240,8 +241,8 @@ pwrnow_supported()
struct cpuid_regs cpu_regs;
/* Required features */
- if (!is_x86_feature(x86_featureset, X86FSET_CPUID) ||
- !is_x86_feature(x86_featureset, X86FSET_MSR)) {
+ ASSERT(is_x86_feature(x86_featureset, X86FSET_CPUID));
+ if (!is_x86_feature(x86_featureset, X86FSET_MSR)) {
PWRNOW_DEBUG(("No CPUID or MSR support."));
return (B_FALSE);
}
@@ -279,8 +280,8 @@ pwrnow_cpb_supported(void)
struct cpuid_regs cpu_regs;
/* Required features */
- if (!is_x86_feature(x86_featureset, X86FSET_CPUID) ||
- !is_x86_feature(x86_featureset, X86FSET_MSR)) {
+ ASSERT(is_x86_feature(x86_featureset, X86FSET_CPUID));
+ if (!is_x86_feature(x86_featureset, X86FSET_MSR)) {
PWRNOW_DEBUG(("No CPUID or MSR support."));
return (B_FALSE);
}
diff --git a/usr/src/uts/i86pc/os/cpupm/speedstep.c b/usr/src/uts/i86pc/os/cpupm/speedstep.c
index dfd2eebd64..3907024791 100644
--- a/usr/src/uts/i86pc/os/cpupm/speedstep.c
+++ b/usr/src/uts/i86pc/os/cpupm/speedstep.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2022 Oxide Computer Co.
*/
/*
* Copyright (c) 2009, Intel Corporation.
@@ -270,8 +271,8 @@ speedstep_supported(uint_t family, uint_t model)
struct cpuid_regs cpu_regs;
/* Required features */
- if (!is_x86_feature(x86_featureset, X86FSET_CPUID) ||
- !is_x86_feature(x86_featureset, X86FSET_MSR)) {
+ ASSERT(is_x86_feature(x86_featureset, X86FSET_CPUID));
+ if (!is_x86_feature(x86_featureset, X86FSET_MSR)) {
return (B_FALSE);
}
@@ -302,8 +303,8 @@ speedstep_turbo_supported(void)
struct cpuid_regs cpu_regs;
/* Required features */
- if (!is_x86_feature(x86_featureset, X86FSET_CPUID) ||
- !is_x86_feature(x86_featureset, X86FSET_MSR)) {
+ ASSERT(is_x86_feature(x86_featureset, X86FSET_CPUID));
+ if (!is_x86_feature(x86_featureset, X86FSET_MSR)) {
return (B_FALSE);
}
diff --git a/usr/src/uts/i86pc/os/mlsetup.c b/usr/src/uts/i86pc/os/mlsetup.c
index 3a96748a89..4522430b3c 100644
--- a/usr/src/uts/i86pc/os/mlsetup.c
+++ b/usr/src/uts/i86pc/os/mlsetup.c
@@ -206,6 +206,12 @@ mlsetup(struct regs *rp)
init_desctbls();
/*
+ * Ensure that we have set the necessary feature bits before setting up
+ * PCI config space access.
+ */
+ cpuid_execpass(cpu[0], CPUID_PASS_PRELUDE, x86_featureset);
+
+ /*
* lgrp_init() and possibly cpuid_pass1() need PCI config
* space access
*/
@@ -222,17 +228,18 @@ mlsetup(struct regs *rp)
#endif
/*
- * The first lightweight pass (pass0) through the cpuid data
- * was done in locore before mlsetup was called. Do the next
- * pass in C code.
+ * i86pc doesn't require anything in between the IDENT and BASIC passes;
+ * we assume that a BIOS has already set up any necessary cpuid feature
+ * bits, so we run both passes together here.
*
- * The x86_featureset is initialized here based on the capabilities
- * of the boot CPU. Note that if we choose to support CPUs that have
- * different feature sets (at which point we would almost certainly
- * want to set the feature bits to correspond to the feature
- * minimum) this value may be altered.
+ * The x86_featureset is initialized here based on the capabilities of
+ * the boot CPU. Note that if we choose to support CPUs that have
+ * different feature sets (at which point we would almost certainly want
+ * to set the feature bits to correspond to the feature minimum) this
+ * value may be altered.
*/
- cpuid_pass1(cpu[0], x86_featureset);
+ cpuid_execpass(cpu[0], CPUID_PASS_IDENT, NULL);
+ cpuid_execpass(cpu[0], CPUID_PASS_BASIC, x86_featureset);
#if !defined(__xpv)
if ((get_hwenv() & HW_XEN_HVM) != 0)
diff --git a/usr/src/uts/i86pc/os/mp_startup.c b/usr/src/uts/i86pc/os/mp_startup.c
index 5310c79db9..008b614da8 100644
--- a/usr/src/uts/i86pc/os/mp_startup.c
+++ b/usr/src/uts/i86pc/os/mp_startup.c
@@ -156,8 +156,8 @@ init_cpu_info(struct cpu *cp)
* If called for the BSP, cp is equal to current CPU.
* For non-BSPs, cpuid info of cp is not ready yet, so use cpuid info
* of current CPU as default values for cpu_idstr and cpu_brandstr.
- * They will be corrected in mp_startup_common() after cpuid_pass1()
- * has been invoked on target CPU.
+ * They will be corrected in mp_startup_common() after
+ * CPUID_PASS_DYNAMIC has been invoked on target CPU.
*/
(void) cpuid_getidstr(CPU, cp->cpu_idstr, CPU_IDSTRLEN);
(void) cpuid_getbrandstr(CPU, cp->cpu_brandstr, CPU_IDSTRLEN);
@@ -1700,7 +1700,9 @@ mp_startup_common(boolean_t boot)
* right away.
*/
bzero(new_x86_featureset, BT_SIZEOFMAP(NUM_X86_FEATURES));
- cpuid_pass1(cp, new_x86_featureset);
+ cpuid_execpass(cp, CPUID_PASS_PRELUDE, new_x86_featureset);
+ cpuid_execpass(cp, CPUID_PASS_IDENT, NULL);
+ cpuid_execpass(cp, CPUID_PASS_BASIC, new_x86_featureset);
if (boot && get_hwenv() == HW_NATIVE &&
cpuid_getvendor(CPU) == X86_VENDOR_Intel &&
@@ -1805,13 +1807,13 @@ mp_startup_common(boolean_t boot)
xsave_setup_msr(cp);
}
- cpuid_pass2(cp);
- cpuid_pass3(cp);
- cpuid_pass4(cp, NULL);
+ cpuid_execpass(cp, CPUID_PASS_EXTENDED, NULL);
+ cpuid_execpass(cp, CPUID_PASS_DYNAMIC, NULL);
+ cpuid_execpass(cp, CPUID_PASS_RESOLVE, NULL);
/*
* Correct cpu_idstr and cpu_brandstr on target CPU after
- * cpuid_pass1() is done.
+ * CPUID_PASS_DYNAMIC is done.
*/
(void) cpuid_getidstr(cp, cp->cpu_idstr, CPU_IDSTRLEN);
(void) cpuid_getbrandstr(cp, cp->cpu_brandstr, CPU_IDSTRLEN);
diff --git a/usr/src/uts/i86pc/os/pci_mech1_amd.c b/usr/src/uts/i86pc/os/pci_mech1_amd.c
index e50a04d90d..42679944a0 100644
--- a/usr/src/uts/i86pc/os/pci_mech1_amd.c
+++ b/usr/src/uts/i86pc/os/pci_mech1_amd.c
@@ -21,7 +21,7 @@
/*
* Copyright 2010 Advanced Micro Devices, Inc.
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2021 Oxide Computer Company
+ * Copyright 2022 Oxide Computer Company
*/
/*
@@ -43,8 +43,7 @@ pci_check_amd_ioecs(void)
struct cpuid_regs cp;
int family;
- if (!is_x86_feature(x86_featureset, X86FSET_CPUID))
- return (B_FALSE);
+ ASSERT(is_x86_feature(x86_featureset, X86FSET_CPUID));
/*
* Get the CPU vendor string from CPUID.
diff --git a/usr/src/uts/i86pc/os/startup.c b/usr/src/uts/i86pc/os/startup.c
index a8d3a35908..e1e92ffe4f 100644
--- a/usr/src/uts/i86pc/os/startup.c
+++ b/usr/src/uts/i86pc/os/startup.c
@@ -27,6 +27,7 @@
* Copyright (c) 2015 by Delphix. All rights reserved.
* Copyright 2022 Oxide Computer Company
* Copyright (c) 2020 Carlos Neira <cneirabustos@gmail.com>
+ * Copyright 2022 Oxide Computer Co.
*/
/*
* Copyright (c) 2010, Intel Corporation.
@@ -785,7 +786,7 @@ startup_init()
/*
* Complete the extraction of cpuid data
*/
- cpuid_pass2(CPU);
+ cpuid_execpass(CPU, CPUID_PASS_EXTENDED, NULL);
(void) check_boot_version(BOP_GETVERSION(bootops));
@@ -1965,7 +1966,7 @@ startup_vm(void)
/*
* Mangle the brand string etc.
*/
- cpuid_pass3(CPU);
+ cpuid_execpass(CPU, CPUID_PASS_DYNAMIC, NULL);
/*
* Create the device arena for toxic (to dtrace/kmdb) mappings.
@@ -3107,16 +3108,11 @@ setx86isalist(void)
}
/*FALLTHROUGH*/
case X86_VENDOR_Cyrix:
- /*
- * The Cyrix 6x86 does not have any Pentium features
- * accessible while not at privilege level 0.
- */
- if (is_x86_feature(x86_featureset, X86FSET_CPUID)) {
- (void) strcat(tp, "pentium");
- (void) strcat(tp,
- is_x86_feature(x86_featureset, X86FSET_MMX) ?
- "+mmx pentium " : " ");
- }
+ ASSERT(is_x86_feature(x86_featureset, X86FSET_CPUID));
+ (void) strcat(tp, "pentium");
+ (void) strcat(tp,
+ is_x86_feature(x86_featureset, X86FSET_MMX) ?
+ "+mmx pentium " : " ");
break;
default:
break;
diff --git a/usr/src/uts/intel/os/archdep.c b/usr/src/uts/intel/os/archdep.c
index 49473fa2fa..eb926ed8e9 100644
--- a/usr/src/uts/intel/os/archdep.c
+++ b/usr/src/uts/intel/os/archdep.c
@@ -882,7 +882,7 @@ void
bind_hwcap(void)
{
uint_t cpu_hwcap_flags[2];
- cpuid_pass4(NULL, cpu_hwcap_flags);
+ cpuid_execpass(NULL, CPUID_PASS_RESOLVE, cpu_hwcap_flags);
auxv_hwcap = (auxv_hwcap_include | cpu_hwcap_flags[0]) &
~auxv_hwcap_exclude;
diff --git a/usr/src/uts/i86pc/os/cpuid.c b/usr/src/uts/intel/os/cpuid.c
index 35476bb9ed..ad54edc4b5 100644
--- a/usr/src/uts/i86pc/os/cpuid.c
+++ b/usr/src/uts/intel/os/cpuid.c
@@ -200,20 +200,39 @@
* ------------
*
* As part of performing feature detection, we break this into several different
- * passes. The passes are as follows:
- *
- * Pass 0 This is a primordial pass done in locore.s to deal with
- * Cyrix CPUs that don't support cpuid. The reality is that
- * we likely don't run on them any more, but there is still
- * logic for handling them.
- *
- * Pass 1 This is the primary pass and is responsible for doing a
+ * passes. There used to be a pass 0 that was done from assembly in locore.s to
+ * support processors that have a missing or broken cpuid instruction (notably
+ * certain Cyrix processors) but those were all 32-bit processors which are no
+ * longer supported. Passes are no longer numbered explicitly to make it easier
+ * to break them up or move them around as needed; however, they still have a
+ * well-defined execution ordering enforced by the definition of cpuid_pass_t in
+ * x86_archext.h. The external interface to execute a cpuid pass or determine
+ * whether a pass has been completed consists of cpuid_execpass() and
+ * cpuid_checkpass() respectively. The passes now, in that execution order,
+ * are as follows:
+ *
+ * PRELUDE This pass does not have any dependencies on system
+ * setup; in particular, unlike all subsequent passes it is
+ * guaranteed not to require PCI config space access. It
+ * sets the flag indicating that the processor we are
+ * running on supports the cpuid instruction, which all
+ * 64-bit processors do. This would also be the place to
+ * add any other basic state that is required later on and
+ * can be learned without dependencies.
+ *
+ * IDENT Determine which vendor manufactured the CPU, the family,
+ * model, and stepping information, and compute basic
+ * identifying tags from those values. This is done first
+ * so that machine-dependent code can control the features
+ * the cpuid instruction will report during subsequent
+ * passes if needed, and so that any intervening
+ * machine-dependent code that needs basic identity will
+ * have it available.
+ *
+ * BASIC This is the primary pass and is responsible for doing a
* large number of different things:
*
- * 1. Determine which vendor manufactured the CPU and
- * determining the family, model, and stepping information.
- *
- * 2. Gathering a large number of feature flags to
+ * 1. Gathering a large number of feature flags to
* determine which features the CPU support and which
* indicate things that we need to do other work in the OS
* to enable. Features detected this way are added to the
@@ -222,31 +241,31 @@
* all of the basic and extended CPU features that we care
* about.
*
- * 3. Determining the CPU's topology. This includes
+ * 2. Determining the CPU's topology. This includes
* information about how many cores and threads are present
* in the package. It also is responsible for figuring out
* which logical CPUs are potentially part of the same core
* and what other resources they might share. For more
* information see the 'Topology' section.
*
- * 4. Determining the set of CPU security-specific features
+ * 3. Determining the set of CPU security-specific features
* that we need to worry about and determine the
* appropriate set of workarounds.
*
* Pass 1 on the boot CPU occurs before KMDB is started.
*
- * Pass 2 The second pass is done after startup(). Here, we check
+ * EXTENDED The second pass is done after startup(). Here, we check
* other miscellaneous features. Most of this is gathering
* additional basic and extended features that we'll use in
* later passes or for debugging support.
*
- * Pass 3 The third pass occurs after the kernel memory allocator
+ * DYNAMIC The third pass occurs after the kernel memory allocator
* has been fully initialized. This gathers information
* where we might need dynamic memory available for our
* uses. This includes several varying width leaves that
* have cache information and the processor's brand string.
*
- * Pass 4 The fourth and final normal pass is performed after the
+ * RESOLVE The fourth and final normal pass is performed after the
* kernel has brought most everything online. This is
* invoked from post_startup(). In this pass, we go through
* the set of features that we have enabled and turn that
@@ -255,21 +274,34 @@
* by the run-time link-editor (RTLD), though userland
* software could also refer to it directly.
*
- * Microcode After a microcode update, we do a selective rescan of
- * the cpuid leaves to determine what features have
- * changed. Microcode updates can provide more details
- * about security related features to deal with issues like
- * Spectre and L1TF. On occasion, vendors have violated
- * their contract and removed bits. However, we don't try
- * to detect that because that puts us in a situation that
- * we really can't deal with. As such, the only thing we
- * rescan are security related features today. See
- * cpuid_pass_ucode().
- *
- * All of the passes (except pass 0) are run on all CPUs. However, for the most
- * part we only care about what the boot CPU says about this information and use
- * the other CPUs as a rough guide to sanity check that we have the same feature
- * set.
+ * The function that performs a pass is currently assumed to be infallible, and
+ * all existing implementation are. This simplifies callers by allowing
+ * cpuid_execpass() to return void. Similarly, implementers do not need to check
+ * for a NULL CPU argument; the current CPU's cpu_t is substituted if necessary.
+ * Both of these assumptions can be relaxed if needed by future developments.
+ * Tracking of completed states is handled by cpuid_execpass(). It is programmer
+ * error to attempt to execute a pass before all previous passes have been
+ * completed on the specified CPU, or to request cpuid information before the
+ * pass that captures it has been executed. These conditions can be tested
+ * using cpuid_checkpass().
+ *
+ * The Microcode Pass
+ *
+ * After a microcode update, we do a selective rescan of the cpuid leaves to
+ * determine what features have changed. Microcode updates can provide more
+ * details about security related features to deal with issues like Spectre and
+ * L1TF. On occasion, vendors have violated their contract and removed bits.
+ * However, we don't try to detect that because that puts us in a situation that
+ * we really can't deal with. As such, the only thing we rescan are security
+ * related features today. See cpuid_pass_ucode(). This pass may be run in a
+ * different sequence on APs and therefore is not part of the sequential order;
+ * It is invoked directly instead of by cpuid_execpass() and its completion
+ * status cannot be checked by cpuid_checkpass(). This could be integrated with
+ * a more complex dependency mechanism if warranted by future developments.
+ *
+ * All of the passes are run on all CPUs. However, for the most part we only
+ * care about what the boot CPU says about this information and use the other
+ * CPUs as a rough guide to sanity check that we have the same feature set.
*
* We do not support running multiple logical CPUs with disjoint, let alone
* different, feature sets.
@@ -1347,10 +1379,11 @@
* We track whether or not we should do this based on what cpuid pass we're in.
* Whenever we hit cpuid_scan_security() on the boot CPU and we're still on pass
* 1 of the cpuid logic, then we can completely turn off TSX. Notably this
- * should happen twice. Once in the normal cpuid_pass1() code and then a second
- * time after we do the initial microcode update. As a result we need to be
- * careful in cpuid_apply_tsx() to only use the MSR if we've loaded a suitable
- * microcode on the current CPU (which happens prior to cpuid_pass_ucode()).
+ * should happen twice. Once in the normal cpuid_pass_basic() code and then a
+ * second time after we do the initial microcode update. As a result we need to
+ * be careful in cpuid_apply_tsx() to only use the MSR if we've loaded a
+ * suitable microcode on the current CPU (which happens prior to
+ * cpuid_pass_ucode()).
*
* If TAA has been fixed, then it will be enumerated in IA32_ARCH_CAPABILITIES
* as TAA_NO. In such a case, we will still disable TSX: it's proven to be an
@@ -2022,8 +2055,9 @@ cpuid_free_space(cpu_t *cpu)
* Determine the type of the underlying platform. This is used to customize
* initialization of various subsystems (e.g. TSC). determine_platform() must
* only ever be called once to prevent two processors from seeing different
- * values of platform_type. Must be called before cpuid_pass1(), the earliest
- * consumer to execute (uses _cpuid_chiprev --> synth_amd_info --> get_hwenv).
+ * values of platform_type. Must be called before cpuid_pass_ident(), the
+ * earliest consumer to execute; the identification pass will call
+ * synth_amd_info() to compute the chiprev, which in turn calls get_hwenv().
*/
void
determine_platform(void)
@@ -2489,7 +2523,7 @@ cpuid_amd_get_coreid(cpu_t *cpu)
* synthesize this case by using cpu->cpu_id. This scheme does not,
* however, guarantee that sibling cores of a chip will have sequential
* coreids starting at a multiple of the number of cores per chip - that is
- * usually the case, but if the ACPI MADT table is presented in a different
+ * usually the case, but if the APIC IDs have been set up in a different
* order then we need to perform a few more gymnastics for the pkgcoreid.
*
* 2. In families 0x15 and 16x (Bulldozer and co.) the cores came in groups
@@ -3161,7 +3195,7 @@ setup_xfem(void)
}
static void
-cpuid_pass1_topology(cpu_t *cpu, uchar_t *featureset)
+cpuid_basic_topology(cpu_t *cpu, uchar_t *featureset)
{
struct cpuid_info *cpi;
@@ -3282,7 +3316,7 @@ cpuid_pass1_topology(cpu_t *cpu, uchar_t *featureset)
* for below.
*/
static void
-cpuid_pass1_thermal(cpu_t *cpu, uchar_t *featureset)
+cpuid_basic_thermal(cpu_t *cpu, uchar_t *featureset)
{
struct cpuid_regs *cp;
struct cpuid_info *cpi = cpu->cpu_m.mcpu_cpi;
@@ -3317,7 +3351,7 @@ cpuid_pass1_thermal(cpu_t *cpu, uchar_t *featureset)
*/
#if !defined(__xpv)
static void
-cpuid_pass1_ppin(cpu_t *cpu, uchar_t *featureset)
+cpuid_basic_ppin(cpu_t *cpu, uchar_t *featureset)
{
on_trap_data_t otd;
struct cpuid_info *cpi = cpu->cpu_m.mcpu_cpi;
@@ -3365,29 +3399,34 @@ cpuid_pass1_ppin(cpu_t *cpu, uchar_t *featureset)
}
#endif /* ! __xpv */
-void
-cpuid_pass1(cpu_t *cpu, uchar_t *featureset)
+static void
+cpuid_pass_prelude(cpu_t *cpu, void *arg)
+{
+ uchar_t *featureset = (uchar_t *)arg;
+
+ /*
+ * We don't run on any processor that doesn't have cpuid, and could not
+ * possibly have arrived here.
+ */
+ add_x86_feature(featureset, X86FSET_CPUID);
+}
+
+static void
+cpuid_pass_ident(cpu_t *cpu, void *arg __unused)
{
- uint32_t mask_ecx, mask_edx;
struct cpuid_info *cpi;
struct cpuid_regs *cp;
- int xcpuid;
-#if !defined(__xpv)
- extern int idle_cpu_prefer_mwait;
-#endif
/*
- * Space statically allocated for BSP, ensure pointer is set
+ * We require that virtual/native detection be complete and that PCI
+ * config space access has been set up; at present there is no reliable
+ * way to determine the latter.
*/
- if (cpu->cpu_id == 0) {
- if (cpu->cpu_m.mcpu_cpi == NULL)
- cpu->cpu_m.mcpu_cpi = &cpuid_info0;
- }
-
- add_x86_feature(featureset, X86FSET_CPUID);
+ ASSERT3S(platform_type, !=, -1);
cpi = cpu->cpu_m.mcpu_cpi;
ASSERT(cpi != NULL);
+
cp = &cpi->cpi_std[0];
cp->cp_eax = 0;
cpi->cpi_maxeax = __cpuid_insn(cp);
@@ -3408,7 +3447,7 @@ cpuid_pass1(cpu_t *cpu, uchar_t *featureset)
if (cpi->cpi_maxeax > CPI_MAXEAX_MAX)
cpi->cpi_maxeax = CPI_MAXEAX_MAX;
if (cpi->cpi_maxeax < 1)
- goto pass1_done;
+ return;
cp = &cpi->cpi_std[1];
cp->cp_eax = 1;
@@ -3451,6 +3490,40 @@ cpuid_pass1(cpu_t *cpu, uchar_t *featureset)
cpi->cpi_brandid = CPI_BRANDID(cpi);
/*
+ * Synthesize chip "revision" and socket type
+ */
+ cpi->cpi_chiprev = _cpuid_chiprev(cpi->cpi_vendor, cpi->cpi_family,
+ cpi->cpi_model, cpi->cpi_step);
+ cpi->cpi_chiprevstr = _cpuid_chiprevstr(cpi->cpi_vendor,
+ cpi->cpi_family, cpi->cpi_model, cpi->cpi_step);
+ cpi->cpi_socket = _cpuid_skt(cpi->cpi_vendor, cpi->cpi_family,
+ cpi->cpi_model, cpi->cpi_step);
+}
+
+static void
+cpuid_pass_basic(cpu_t *cpu, void *arg)
+{
+ uchar_t *featureset = (uchar_t *)arg;
+ uint32_t mask_ecx, mask_edx;
+ struct cpuid_info *cpi;
+ struct cpuid_regs *cp;
+ int xcpuid;
+#if !defined(__xpv)
+ extern int idle_cpu_prefer_mwait;
+#endif
+
+ cpi = cpu->cpu_m.mcpu_cpi;
+ ASSERT(cpi != NULL);
+
+ if (cpi->cpi_maxeax < 1)
+ return;
+
+ /*
+ * This was filled during the identification pass.
+ */
+ cp = &cpi->cpi_std[1];
+
+ /*
* *default* assumptions:
* - believe %edx feature word
* - ignore %ecx feature word
@@ -3993,7 +4066,7 @@ cpuid_pass1(cpu_t *cpu, uchar_t *featureset)
/*
* Work on the "extended" feature information, doing
- * some basic initialization for cpuid_pass2()
+ * some basic initialization to be used in the extended pass.
*/
xcpuid = 0;
switch (cpi->cpi_vendor) {
@@ -4227,25 +4300,15 @@ cpuid_pass1(cpu_t *cpu, uchar_t *featureset)
}
/*
- * cpuid_pass1_ppin assumes that cpuid_pass1_topology has already been
+ * cpuid_basic_ppin assumes that cpuid_basic_topology has already been
* run and thus gathered some of its dependent leaves.
*/
- cpuid_pass1_topology(cpu, featureset);
- cpuid_pass1_thermal(cpu, featureset);
+ cpuid_basic_topology(cpu, featureset);
+ cpuid_basic_thermal(cpu, featureset);
#if !defined(__xpv)
- cpuid_pass1_ppin(cpu, featureset);
+ cpuid_basic_ppin(cpu, featureset);
#endif
- /*
- * Synthesize chip "revision" and socket type
- */
- cpi->cpi_chiprev = _cpuid_chiprev(cpi->cpi_vendor, cpi->cpi_family,
- cpi->cpi_model, cpi->cpi_step);
- cpi->cpi_chiprevstr = _cpuid_chiprevstr(cpi->cpi_vendor,
- cpi->cpi_family, cpi->cpi_model, cpi->cpi_step);
- cpi->cpi_socket = _cpuid_skt(cpi->cpi_vendor, cpi->cpi_family,
- cpi->cpi_model, cpi->cpi_step);
-
if (cpi->cpi_vendor == X86_VENDOR_AMD ||
cpi->cpi_vendor == X86_VENDOR_HYGON) {
if (cpi->cpi_xmaxeax >= CPUID_LEAF_EXT_8 &&
@@ -4316,9 +4379,6 @@ cpuid_pass1(cpu_t *cpu, uchar_t *featureset)
* Check the processor leaves that are used for security features.
*/
cpuid_scan_security(cpu, featureset);
-
-pass1_done:
- cpi->cpi_pass = 1;
}
/*
@@ -4329,9 +4389,8 @@ pass1_done:
* this stuff in a crash dump.
*/
-/*ARGSUSED*/
-void
-cpuid_pass2(cpu_t *cpu)
+static void
+cpuid_pass_extended(cpu_t *cpu, void *_arg __unused)
{
uint_t n, nmax;
int i;
@@ -4340,19 +4399,17 @@ cpuid_pass2(cpu_t *cpu)
uint32_t *iptr;
struct cpuid_info *cpi = cpu->cpu_m.mcpu_cpi;
- ASSERT(cpi->cpi_pass == 1);
-
if (cpi->cpi_maxeax < 1)
- goto pass2_done;
+ return;
if ((nmax = cpi->cpi_maxeax + 1) > NMAX_CPI_STD)
nmax = NMAX_CPI_STD;
/*
- * (We already handled n == 0 and n == 1 in pass 1)
+ * (We already handled n == 0 and n == 1 in the basic pass)
*/
for (n = 2, cp = &cpi->cpi_std[2]; n < nmax; n++, cp++) {
/*
- * leaves 6 and 7 were handled in pass 1
+ * leaves 6 and 7 were handled in the basic pass
*/
if (n == 6 || n == 7)
continue;
@@ -4368,7 +4425,7 @@ cpuid_pass2(cpu_t *cpu)
* caches.
*
* Here, populate cpi_std[4] with the information returned by
- * function 4 when %ecx == 0, and do the rest in cpuid_pass3()
+ * function 4 when %ecx == 0, and do the rest in a later pass
* when dynamic memory allocation becomes available.
*
* Note: we need to explicitly initialize %ecx here, since
@@ -4442,7 +4499,8 @@ cpuid_pass2(cpu_t *cpu)
size_t mwait_size;
/*
- * check cpi_mwait.support which was set in cpuid_pass1
+ * check cpi_mwait.support which was set in
+ * cpuid_pass_basic()
*/
if (!(cpi->cpi_mwait.support & MWAIT_SUPPORT))
break;
@@ -4700,13 +4758,13 @@ cpuid_pass2(cpu_t *cpu)
if ((cpi->cpi_xmaxeax & CPUID_LEAF_EXT_0) == 0)
- goto pass2_done;
+ return;
if ((nmax = cpi->cpi_xmaxeax - CPUID_LEAF_EXT_0 + 1) > NMAX_CPI_EXTD)
nmax = NMAX_CPI_EXTD;
/*
* Copy the extended properties, fixing them as we go.
- * (We already handled n == 0 and n == 1 in pass 1)
+ * (We already handled n == 0 and n == 1 in the basic pass)
*/
iptr = (void *)cpi->cpi_brandstr;
for (n = 2, cp = &cpi->cpi_extd[2]; n < nmax; cp++, n++) {
@@ -4806,9 +4864,6 @@ cpuid_pass2(cpu_t *cpu)
break;
}
}
-
-pass2_done:
- cpi->cpi_pass = 2;
}
static const char *
@@ -4816,9 +4871,7 @@ intel_cpubrand(const struct cpuid_info *cpi)
{
int i;
- if (!is_x86_feature(x86_featureset, X86FSET_CPUID) ||
- cpi->cpi_maxeax < 1 || cpi->cpi_family < 5)
- return ("i486");
+ ASSERT(is_x86_feature(x86_featureset, X86FSET_CPUID));
switch (cpi->cpi_family) {
case 5:
@@ -4950,9 +5003,7 @@ intel_cpubrand(const struct cpuid_info *cpi)
static const char *
amd_cpubrand(const struct cpuid_info *cpi)
{
- if (!is_x86_feature(x86_featureset, X86FSET_CPUID) ||
- cpi->cpi_maxeax < 1 || cpi->cpi_family < 5)
- return ("i486 compatible");
+ ASSERT(is_x86_feature(x86_featureset, X86FSET_CPUID));
switch (cpi->cpi_family) {
case 5:
@@ -5020,10 +5071,7 @@ amd_cpubrand(const struct cpuid_info *cpi)
static const char *
cyrix_cpubrand(struct cpuid_info *cpi, uint_t type)
{
- if (!is_x86_feature(x86_featureset, X86FSET_CPUID) ||
- cpi->cpi_maxeax < 1 || cpi->cpi_family < 5 ||
- type == X86_TYPE_CYRIX_486)
- return ("i486 compatible");
+ ASSERT(is_x86_feature(x86_featureset, X86FSET_CPUID));
switch (type) {
case X86_TYPE_CYRIX_6x86:
@@ -5153,17 +5201,15 @@ fabricate_brandstr(struct cpuid_info *cpi)
* Fixup the brand string, and collect any information from cpuid
* that requires dynamically allocated storage to represent.
*/
-/*ARGSUSED*/
-void
-cpuid_pass3(cpu_t *cpu)
+
+static void
+cpuid_pass_dynamic(cpu_t *cpu, void *_arg __unused)
{
int i, max, shft, level, size;
struct cpuid_regs regs;
struct cpuid_regs *cp;
struct cpuid_info *cpi = cpu->cpu_m.mcpu_cpi;
- ASSERT(cpi->cpi_pass == 2);
-
/*
* Deterministic cache parameters
*
@@ -5220,7 +5266,7 @@ cpuid_pass3(cpu_t *cpu)
/*
* Allocate the cpi_cache_leaves array. The first element
* references the regs for the corresponding leaf with %ecx set
- * to 0. This was gathered in cpuid_pass2().
+ * to 0. This was gathered in cpuid_pass_extended().
*/
if (size > 0) {
cpi->cpi_cache_leaves =
@@ -5327,7 +5373,6 @@ cpuid_pass3(cpu_t *cpu)
} else
fabricate_brandstr(cpi);
}
- cpi->cpi_pass = 3;
}
/*
@@ -5336,18 +5381,16 @@ cpuid_pass3(cpu_t *cpu)
* the hardware feature support and kernel support for those features into
* what we're actually going to tell applications via the aux vector.
*/
-void
-cpuid_pass4(cpu_t *cpu, uint_t *hwcap_out)
+
+static void
+cpuid_pass_resolve(cpu_t *cpu, void *arg)
{
+ uint_t *hwcap_out = (uint_t *)arg;
struct cpuid_info *cpi;
uint_t hwcap_flags = 0, hwcap_flags_2 = 0;
- if (cpu == NULL)
- cpu = CPU;
cpi = cpu->cpu_m.mcpu_cpi;
- ASSERT(cpi->cpi_pass == 3);
-
if (cpi->cpi_maxeax >= 1) {
uint32_t *edx = &cpi->cpi_support[STD_EDX_FEATURES];
uint32_t *ecx = &cpi->cpi_support[STD_ECX_FEATURES];
@@ -5530,13 +5573,13 @@ cpuid_pass4(cpu_t *cpu, uint_t *hwcap_out)
}
/*
- * Check a few miscilaneous features.
+ * Check a few miscellaneous features.
*/
if (is_x86_feature(x86_featureset, X86FSET_CLZERO))
hwcap_flags_2 |= AV_386_2_CLZERO;
if (cpi->cpi_xmaxeax < 0x80000001)
- goto pass4_done;
+ goto resolve_done;
switch (cpi->cpi_vendor) {
struct cpuid_regs cp;
@@ -5648,8 +5691,7 @@ cpuid_pass4(cpu_t *cpu, uint_t *hwcap_out)
break;
}
-pass4_done:
- cpi->cpi_pass = 4;
+resolve_done:
if (hwcap_out != NULL) {
hwcap_out[0] = hwcap_flags;
hwcap_out[1] = hwcap_flags_2;
@@ -5672,7 +5714,7 @@ cpuid_insn(cpu_t *cpu, struct cpuid_regs *cp)
cpu = CPU;
cpi = cpu->cpu_m.mcpu_cpi;
- ASSERT(cpuid_checkpass(cpu, 3));
+ ASSERT(cpuid_checkpass(cpu, CPUID_PASS_DYNAMIC));
/*
* CPUID data is cached in two separate places: cpi_std for standard
@@ -5700,8 +5742,8 @@ cpuid_insn(cpu_t *cpu, struct cpuid_regs *cp)
return (cp->cp_eax);
}
-int
-cpuid_checkpass(cpu_t *cpu, int pass)
+boolean_t
+cpuid_checkpass(const cpu_t *const cpu, const cpuid_pass_t pass)
{
return (cpu != NULL && cpu->cpu_m.mcpu_cpi != NULL &&
cpu->cpu_m.mcpu_cpi->cpi_pass >= pass);
@@ -5710,7 +5752,7 @@ cpuid_checkpass(cpu_t *cpu, int pass)
int
cpuid_getbrandstr(cpu_t *cpu, char *s, size_t n)
{
- ASSERT(cpuid_checkpass(cpu, 3));
+ ASSERT(cpuid_checkpass(cpu, CPUID_PASS_DYNAMIC));
return (snprintf(s, n, "%s", cpu->cpu_m.mcpu_cpi->cpi_brandstr));
}
@@ -5721,7 +5763,7 @@ cpuid_is_cmt(cpu_t *cpu)
if (cpu == NULL)
cpu = CPU;
- ASSERT(cpuid_checkpass(cpu, 1));
+ ASSERT(cpuid_checkpass(cpu, CPUID_PASS_BASIC));
return (cpu->cpu_m.mcpu_cpi->cpi_chipid >= 0);
}
@@ -5742,7 +5784,7 @@ cpuid_is_cmt(cpu_t *cpu)
int
cpuid_syscall32_insn(cpu_t *cpu)
{
- ASSERT(cpuid_checkpass((cpu == NULL ? CPU : cpu), 1));
+ ASSERT(cpuid_checkpass((cpu == NULL ? CPU : cpu), CPUID_PASS_BASIC));
#if !defined(__xpv)
if (cpu == NULL)
@@ -5772,7 +5814,7 @@ cpuid_getidstr(cpu_t *cpu, char *s, size_t n)
static const char fmt_ht[] =
"x86 (chipid 0x%x %s %X family %d model %d step %d clock %d MHz)";
- ASSERT(cpuid_checkpass(cpu, 1));
+ ASSERT(cpuid_checkpass(cpu, CPUID_PASS_BASIC));
if (cpuid_is_cmt(cpu))
return (snprintf(s, n, fmt_ht, cpi->cpi_chipid,
@@ -5788,91 +5830,91 @@ cpuid_getidstr(cpu_t *cpu, char *s, size_t n)
const char *
cpuid_getvendorstr(cpu_t *cpu)
{
- ASSERT(cpuid_checkpass(cpu, 1));
+ ASSERT(cpuid_checkpass(cpu, CPUID_PASS_IDENT));
return ((const char *)cpu->cpu_m.mcpu_cpi->cpi_vendorstr);
}
uint_t
cpuid_getvendor(cpu_t *cpu)
{
- ASSERT(cpuid_checkpass(cpu, 1));
+ ASSERT(cpuid_checkpass(cpu, CPUID_PASS_IDENT));
return (cpu->cpu_m.mcpu_cpi->cpi_vendor);
}
uint_t
cpuid_getfamily(cpu_t *cpu)
{
- ASSERT(cpuid_checkpass(cpu, 1));
+ ASSERT(cpuid_checkpass(cpu, CPUID_PASS_IDENT));
return (cpu->cpu_m.mcpu_cpi->cpi_family);
}
uint_t
cpuid_getmodel(cpu_t *cpu)
{
- ASSERT(cpuid_checkpass(cpu, 1));
+ ASSERT(cpuid_checkpass(cpu, CPUID_PASS_IDENT));
return (cpu->cpu_m.mcpu_cpi->cpi_model);
}
uint_t
cpuid_get_ncpu_per_chip(cpu_t *cpu)
{
- ASSERT(cpuid_checkpass(cpu, 1));
+ ASSERT(cpuid_checkpass(cpu, CPUID_PASS_BASIC));
return (cpu->cpu_m.mcpu_cpi->cpi_ncpu_per_chip);
}
uint_t
cpuid_get_ncore_per_chip(cpu_t *cpu)
{
- ASSERT(cpuid_checkpass(cpu, 1));
+ ASSERT(cpuid_checkpass(cpu, CPUID_PASS_BASIC));
return (cpu->cpu_m.mcpu_cpi->cpi_ncore_per_chip);
}
uint_t
cpuid_get_ncpu_sharing_last_cache(cpu_t *cpu)
{
- ASSERT(cpuid_checkpass(cpu, 2));
+ ASSERT(cpuid_checkpass(cpu, CPUID_PASS_EXTENDED));
return (cpu->cpu_m.mcpu_cpi->cpi_ncpu_shr_last_cache);
}
id_t
cpuid_get_last_lvl_cacheid(cpu_t *cpu)
{
- ASSERT(cpuid_checkpass(cpu, 2));
+ ASSERT(cpuid_checkpass(cpu, CPUID_PASS_EXTENDED));
return (cpu->cpu_m.mcpu_cpi->cpi_last_lvl_cacheid);
}
uint_t
cpuid_getstep(cpu_t *cpu)
{
- ASSERT(cpuid_checkpass(cpu, 1));
+ ASSERT(cpuid_checkpass(cpu, CPUID_PASS_IDENT));
return (cpu->cpu_m.mcpu_cpi->cpi_step);
}
uint_t
cpuid_getsig(struct cpu *cpu)
{
- ASSERT(cpuid_checkpass(cpu, 1));
+ ASSERT(cpuid_checkpass(cpu, CPUID_PASS_BASIC));
return (cpu->cpu_m.mcpu_cpi->cpi_std[1].cp_eax);
}
uint32_t
cpuid_getchiprev(struct cpu *cpu)
{
- ASSERT(cpuid_checkpass(cpu, 1));
+ ASSERT(cpuid_checkpass(cpu, CPUID_PASS_IDENT));
return (cpu->cpu_m.mcpu_cpi->cpi_chiprev);
}
const char *
cpuid_getchiprevstr(struct cpu *cpu)
{
- ASSERT(cpuid_checkpass(cpu, 1));
+ ASSERT(cpuid_checkpass(cpu, CPUID_PASS_IDENT));
return (cpu->cpu_m.mcpu_cpi->cpi_chiprevstr);
}
uint32_t
cpuid_getsockettype(struct cpu *cpu)
{
- ASSERT(cpuid_checkpass(cpu, 1));
+ ASSERT(cpuid_checkpass(cpu, CPUID_PASS_IDENT));
return (cpu->cpu_m.mcpu_cpi->cpi_socket);
}
@@ -5882,7 +5924,7 @@ cpuid_getsocketstr(cpu_t *cpu)
static const char *socketstr = NULL;
struct cpuid_info *cpi;
- ASSERT(cpuid_checkpass(cpu, 1));
+ ASSERT(cpuid_checkpass(cpu, CPUID_PASS_IDENT));
cpi = cpu->cpu_m.mcpu_cpi;
/* Assume that socket types are the same across the system */
@@ -5897,7 +5939,7 @@ cpuid_getsocketstr(cpu_t *cpu)
int
cpuid_get_chipid(cpu_t *cpu)
{
- ASSERT(cpuid_checkpass(cpu, 1));
+ ASSERT(cpuid_checkpass(cpu, CPUID_PASS_BASIC));
if (cpuid_is_cmt(cpu))
return (cpu->cpu_m.mcpu_cpi->cpi_chipid);
@@ -5907,63 +5949,63 @@ cpuid_get_chipid(cpu_t *cpu)
id_t
cpuid_get_coreid(cpu_t *cpu)
{
- ASSERT(cpuid_checkpass(cpu, 1));
+ ASSERT(cpuid_checkpass(cpu, CPUID_PASS_BASIC));
return (cpu->cpu_m.mcpu_cpi->cpi_coreid);
}
int
cpuid_get_pkgcoreid(cpu_t *cpu)
{
- ASSERT(cpuid_checkpass(cpu, 1));
+ ASSERT(cpuid_checkpass(cpu, CPUID_PASS_BASIC));
return (cpu->cpu_m.mcpu_cpi->cpi_pkgcoreid);
}
int
cpuid_get_clogid(cpu_t *cpu)
{
- ASSERT(cpuid_checkpass(cpu, 1));
+ ASSERT(cpuid_checkpass(cpu, CPUID_PASS_BASIC));
return (cpu->cpu_m.mcpu_cpi->cpi_clogid);
}
int
cpuid_get_cacheid(cpu_t *cpu)
{
- ASSERT(cpuid_checkpass(cpu, 1));
+ ASSERT(cpuid_checkpass(cpu, CPUID_PASS_BASIC));
return (cpu->cpu_m.mcpu_cpi->cpi_last_lvl_cacheid);
}
uint_t
cpuid_get_procnodeid(cpu_t *cpu)
{
- ASSERT(cpuid_checkpass(cpu, 1));
+ ASSERT(cpuid_checkpass(cpu, CPUID_PASS_BASIC));
return (cpu->cpu_m.mcpu_cpi->cpi_procnodeid);
}
uint_t
cpuid_get_procnodes_per_pkg(cpu_t *cpu)
{
- ASSERT(cpuid_checkpass(cpu, 1));
+ ASSERT(cpuid_checkpass(cpu, CPUID_PASS_BASIC));
return (cpu->cpu_m.mcpu_cpi->cpi_procnodes_per_pkg);
}
uint_t
cpuid_get_compunitid(cpu_t *cpu)
{
- ASSERT(cpuid_checkpass(cpu, 1));
+ ASSERT(cpuid_checkpass(cpu, CPUID_PASS_BASIC));
return (cpu->cpu_m.mcpu_cpi->cpi_compunitid);
}
uint_t
cpuid_get_cores_per_compunit(cpu_t *cpu)
{
- ASSERT(cpuid_checkpass(cpu, 1));
+ ASSERT(cpuid_checkpass(cpu, CPUID_PASS_BASIC));
return (cpu->cpu_m.mcpu_cpi->cpi_cores_per_compunit);
}
uint32_t
cpuid_get_apicid(cpu_t *cpu)
{
- ASSERT(cpuid_checkpass(cpu, 1));
+ ASSERT(cpuid_checkpass(cpu, CPUID_PASS_BASIC));
if (cpu->cpu_m.mcpu_cpi->cpi_maxeax < 1) {
return (UINT32_MAX);
} else {
@@ -5980,7 +6022,7 @@ cpuid_get_addrsize(cpu_t *cpu, uint_t *pabits, uint_t *vabits)
cpu = CPU;
cpi = cpu->cpu_m.mcpu_cpi;
- ASSERT(cpuid_checkpass(cpu, 1));
+ ASSERT(cpuid_checkpass(cpu, CPUID_PASS_BASIC));
if (pabits)
*pabits = cpi->cpi_pabits;
@@ -6026,7 +6068,7 @@ cpuid_get_dtlb_nent(cpu_t *cpu, size_t pagesize)
cpu = CPU;
cpi = cpu->cpu_m.mcpu_cpi;
- ASSERT(cpuid_checkpass(cpu, 1));
+ ASSERT(cpuid_checkpass(cpu, CPUID_PASS_BASIC));
/*
* Check the L2 TLB info
@@ -6966,9 +7008,7 @@ cpuid_set_cpu_properties(void *dip, processorid_t cpu_id,
"clock-frequency", (int)mul);
}
- if (!is_x86_feature(x86_featureset, X86FSET_CPUID)) {
- return;
- }
+ ASSERT(is_x86_feature(x86_featureset, X86FSET_CPUID));
/* vendor-id */
(void) ndi_prop_update_string(DDI_DEV_T_NONE, cpu_devi,
@@ -7290,7 +7330,7 @@ cpuid_mwait_alloc(cpu_t *cpu)
uint32_t *ret;
size_t mwait_size;
- ASSERT(cpuid_checkpass(CPU, 2));
+ ASSERT(cpuid_checkpass(CPU, CPUID_PASS_EXTENDED));
mwait_size = CPU->cpu_m.mcpu_cpi->cpi_mwait.mon_max;
if (mwait_size == 0)
@@ -7376,20 +7416,18 @@ cpuid_deep_cstates_supported(void)
struct cpuid_info *cpi;
struct cpuid_regs regs;
- ASSERT(cpuid_checkpass(CPU, 1));
+ ASSERT(cpuid_checkpass(CPU, CPUID_PASS_BASIC));
+ ASSERT(is_x86_feature(x86_featureset, X86FSET_CPUID));
cpi = CPU->cpu_m.mcpu_cpi;
- if (!is_x86_feature(x86_featureset, X86FSET_CPUID))
- return (0);
-
switch (cpi->cpi_vendor) {
case X86_VENDOR_Intel:
if (cpi->cpi_xmaxeax < 0x80000007)
return (0);
/*
- * TSC run at a constant rate in all ACPI C-states?
+ * Does TSC run at a constant rate in all C-states?
*/
regs.cp_eax = 0x80000007;
(void) __cpuid_insn(&regs);
@@ -7459,12 +7497,13 @@ enable_pcid(void)
* ops will execute on the processor before the MSRs are properly set up.
*
* Current implementation has the following assumption:
- * - cpuid_pass1() is done, so that X86 features are known.
+ * - cpuid_pass_basic() is done, so that X86 features are known.
* - fpu_probe() is done, so that fp_save_mech is chosen.
*/
void
xsave_setup_msr(cpu_t *cpu)
{
+ ASSERT(cpuid_checkpass(cpu, CPUID_PASS_BASIC));
ASSERT(fp_save_mech == FP_XSAVE);
ASSERT(is_x86_feature(x86_featureset, X86FSET_XSAVE));
@@ -7489,7 +7528,7 @@ cpuid_arat_supported(void)
struct cpuid_info *cpi;
struct cpuid_regs regs;
- ASSERT(cpuid_checkpass(CPU, 1));
+ ASSERT(cpuid_checkpass(CPU, CPUID_PASS_BASIC));
ASSERT(is_x86_feature(x86_featureset, X86FSET_CPUID));
cpi = CPU->cpu_m.mcpu_cpi;
@@ -7521,10 +7560,10 @@ cpuid_iepb_supported(struct cpu *cp)
struct cpuid_info *cpi = cp->cpu_m.mcpu_cpi;
struct cpuid_regs regs;
- ASSERT(cpuid_checkpass(cp, 1));
+ ASSERT(cpuid_checkpass(cp, CPUID_PASS_BASIC));
+ ASSERT(is_x86_feature(x86_featureset, X86FSET_CPUID));
- if (!(is_x86_feature(x86_featureset, X86FSET_CPUID)) ||
- !(is_x86_feature(x86_featureset, X86FSET_MSR))) {
+ if (!(is_x86_feature(x86_featureset, X86FSET_MSR))) {
return (0);
}
@@ -7555,7 +7594,7 @@ cpuid_deadline_tsc_supported(void)
struct cpuid_info *cpi = CPU->cpu_m.mcpu_cpi;
struct cpuid_regs regs;
- ASSERT(cpuid_checkpass(CPU, 1));
+ ASSERT(cpuid_checkpass(CPU, CPUID_PASS_BASIC));
ASSERT(is_x86_feature(x86_featureset, X86FSET_CPUID));
switch (cpi->cpi_vendor) {
@@ -7608,7 +7647,7 @@ cpuid_get_ext_topo(cpu_t *cpu, uint_t *core_nbits, uint_t *strand_nbits)
{
struct cpuid_info *cpi;
- VERIFY(cpuid_checkpass(CPU, 1));
+ VERIFY(cpuid_checkpass(CPU, CPUID_PASS_BASIC));
cpi = cpu->cpu_m.mcpu_cpi;
if (cpi->cpi_ncore_bits > *core_nbits) {
@@ -7777,3 +7816,51 @@ cpuid_post_ucodeadm(void)
}
kmem_free(argdata, sizeof (x86_featureset) * NCPU);
}
+
+typedef void (*cpuid_pass_f)(cpu_t *, void *);
+
+typedef struct cpuid_pass_def {
+ cpuid_pass_t cpd_pass;
+ cpuid_pass_f cpd_func;
+} cpuid_pass_def_t;
+
+/*
+ * See block comment at the top; note that cpuid_pass_ucode is not a pass in the
+ * normal sense and should not appear here.
+ */
+static const cpuid_pass_def_t cpuid_pass_defs[] = {
+ { CPUID_PASS_PRELUDE, cpuid_pass_prelude },
+ { CPUID_PASS_IDENT, cpuid_pass_ident },
+ { CPUID_PASS_BASIC, cpuid_pass_basic },
+ { CPUID_PASS_EXTENDED, cpuid_pass_extended },
+ { CPUID_PASS_DYNAMIC, cpuid_pass_dynamic },
+ { CPUID_PASS_RESOLVE, cpuid_pass_resolve },
+};
+
+void
+cpuid_execpass(cpu_t *cp, cpuid_pass_t pass, void *arg)
+{
+ VERIFY3S(pass, !=, CPUID_PASS_NONE);
+
+ if (cp == NULL)
+ cp = CPU;
+
+ /*
+ * Space statically allocated for BSP, ensure pointer is set
+ */
+ if (cp->cpu_id == 0 && cp->cpu_m.mcpu_cpi == NULL)
+ cp->cpu_m.mcpu_cpi = &cpuid_info0;
+
+ ASSERT(cpuid_checkpass(cp, pass - 1));
+
+ for (uint_t i = 0; i < ARRAY_SIZE(cpuid_pass_defs); i++) {
+ if (cpuid_pass_defs[i].cpd_pass == pass) {
+ cpuid_pass_defs[i].cpd_func(cp, arg);
+ cp->cpu_m.mcpu_cpi->cpi_pass = pass;
+ return;
+ }
+ }
+
+ panic("unable to execute invalid cpuid pass %d on cpu%d\n",
+ pass, cp->cpu_id);
+}
diff --git a/usr/src/uts/i86pc/os/cpuid_subr.c b/usr/src/uts/intel/os/cpuid_subr.c
index 1c79138139..8f8aa89062 100644
--- a/usr/src/uts/i86pc/os/cpuid_subr.c
+++ b/usr/src/uts/intel/os/cpuid_subr.c
@@ -898,12 +898,6 @@ _cpuid_chiprevstr(uint_t vendor, uint_t family, uint_t model, uint_t step)
}
/*
- * CyrixInstead is a variable used by the Cyrix detection code
- * in locore.
- */
-const char CyrixInstead[] = X86_VENDORSTR_CYRIX;
-
-/*
* Map the vendor string to a type code
*/
uint_t
@@ -917,7 +911,7 @@ _cpuid_vendorstr_to_vendorcode(char *vendorstr)
return (X86_VENDOR_HYGON);
else if (strcmp(vendorstr, X86_VENDORSTR_TM) == 0)
return (X86_VENDOR_TM);
- else if (strcmp(vendorstr, CyrixInstead) == 0)
+ else if (strcmp(vendorstr, X86_VENDORSTR_CYRIX) == 0)
return (X86_VENDOR_Cyrix);
else if (strcmp(vendorstr, X86_VENDORSTR_UMC) == 0)
return (X86_VENDOR_UMC);
diff --git a/usr/src/uts/intel/sys/x86_archext.h b/usr/src/uts/intel/sys/x86_archext.h
index c16d430c2e..b936012dac 100644
--- a/usr/src/uts/intel/sys/x86_archext.h
+++ b/usr/src/uts/intel/sys/x86_archext.h
@@ -1204,8 +1204,6 @@ extern uint_t x86_clflush_size;
extern uint_t pentiumpro_bug4046376;
-extern const char CyrixInstead[];
-
/*
* These functions are all used to perform various side-channel mitigations.
* Please see uts/i86pc/os/cpuid.c for more information.
@@ -1255,9 +1253,21 @@ extern void mtrr_sync(void);
extern void cpu_fast_syscall_enable(void);
extern void cpu_fast_syscall_disable(void);
+typedef enum cpuid_pass {
+ CPUID_PASS_NONE = 0,
+ CPUID_PASS_PRELUDE,
+ CPUID_PASS_IDENT,
+ CPUID_PASS_BASIC,
+ CPUID_PASS_EXTENDED,
+ CPUID_PASS_DYNAMIC,
+ CPUID_PASS_RESOLVE
+} cpuid_pass_t;
+
struct cpu;
-extern int cpuid_checkpass(struct cpu *, int);
+extern boolean_t cpuid_checkpass(const struct cpu *const, const cpuid_pass_t);
+extern void cpuid_execpass(struct cpu *, const cpuid_pass_t, void *);
+extern void cpuid_pass_ucode(struct cpu *, uchar_t *);
extern uint32_t cpuid_insn(struct cpu *, struct cpuid_regs *);
extern uint32_t __cpuid_insn(struct cpuid_regs *);
extern int cpuid_getbrandstr(struct cpu *, char *, size_t);
@@ -1300,13 +1310,8 @@ struct cpuid_info;
extern void setx86isalist(void);
extern void cpuid_alloc_space(struct cpu *);
extern void cpuid_free_space(struct cpu *);
-extern void cpuid_pass1(struct cpu *, uchar_t *);
-extern void cpuid_pass2(struct cpu *);
-extern void cpuid_pass3(struct cpu *);
-extern void cpuid_pass4(struct cpu *, uint_t *);
extern void cpuid_set_cpu_properties(void *, processorid_t,
struct cpuid_info *);
-extern void cpuid_pass_ucode(struct cpu *, uchar_t *);
extern void cpuid_post_ucodeadm(void);
extern void cpuid_get_addrsize(struct cpu *, uint_t *, uint_t *);
@@ -1385,6 +1390,8 @@ extern void xsave_setup_msr(struct cpu *);
extern void reset_gdtr_limit(void);
#endif
+extern int enable_platform_detection;
+
/*
* Hypervisor signatures
*/