diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/uts/common/io/cpuid_drv.c | 4 | ||||
-rw-r--r-- | usr/src/uts/i86pc/ml/locore.s | 6 | ||||
-rw-r--r-- | usr/src/uts/i86pc/os/cpupm/pwrnow.c | 9 | ||||
-rw-r--r-- | usr/src/uts/i86pc/os/cpupm/speedstep.c | 9 | ||||
-rw-r--r-- | usr/src/uts/i86pc/os/mlsetup.c | 25 | ||||
-rw-r--r-- | usr/src/uts/i86pc/os/mp_startup.c | 16 | ||||
-rw-r--r-- | usr/src/uts/i86pc/os/pci_mech1_amd.c | 5 | ||||
-rw-r--r-- | usr/src/uts/i86pc/os/startup.c | 20 | ||||
-rw-r--r-- | usr/src/uts/intel/os/archdep.c | 2 | ||||
-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.h | 23 |
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(®s); @@ -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 */ |