summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/common/io/cpuid_drv.c4
-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)417
-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
12 files changed, 316 insertions, 228 deletions
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/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 7ea5270c7a..a0bb296e70 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.
@@ -3106,16 +3107,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 9ef480a69a..b28cd6c67a 100644
--- a/usr/src/uts/intel/os/archdep.c
+++ b/usr/src/uts/intel/os/archdep.c
@@ -860,7 +860,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 f4f3c2aed4..1bb87077dd 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];
@@ -5529,7 +5572,7 @@ cpuid_pass4(cpu_t *cpu, uint_t *hwcap_out)
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;
@@ -5641,8 +5684,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;
@@ -5665,7 +5707,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
@@ -5693,8 +5735,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);
@@ -5703,7 +5745,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));
}
@@ -5714,7 +5756,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);
}
@@ -5735,7 +5777,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)
@@ -5765,7 +5807,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,
@@ -5781,91 +5823,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);
}
@@ -5875,7 +5917,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 */
@@ -5890,7 +5932,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);
@@ -5900,63 +5942,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 {
@@ -5973,7 +6015,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;
@@ -6019,7 +6061,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
@@ -6959,9 +7001,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,
@@ -7283,7 +7323,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)
@@ -7369,20 +7409,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);
@@ -7452,12 +7490,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));
@@ -7482,7 +7521,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;
@@ -7514,10 +7553,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);
}
@@ -7548,7 +7587,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) {
@@ -7601,7 +7640,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) {
@@ -7770,3 +7809,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
*/