From 90e8a35bfb32fcc755c531b4ee1b04417330d387 Mon Sep 17 00:00:00 2001 From: Alexander Polakov Date: Sun, 13 Dec 2009 00:47:27 +0300 Subject: [PATCH] i386: sync identcpu with FreeBSD * more feature strings * core/package detection (from x86_64) * replace cpu_vendor with cpu_vendor_id * move cpu identification variables declaration to initcpu.c --- sys/cpu/i386/include/cpufunc.h | 8 + sys/cpu/i386/include/cputypes.h | 16 + sys/cpu/i386/include/specialreg.h | 341 +++++-- .../pc32/acpica5/acpi_pstate_machdep.c | 5 +- sys/platform/pc32/apic/mpapic.c | 3 +- sys/platform/pc32/i386/identcpu.c | 937 +++++++++++------- sys/platform/pc32/i386/initcpu.c | 21 +- sys/platform/pc32/i386/locore.s | 14 +- sys/platform/pc32/i386/mp_machdep.c | 3 +- sys/platform/pc32/include/md_var.h | 4 + 10 files changed, 894 insertions(+), 458 deletions(-) diff --git a/sys/cpu/i386/include/cpufunc.h b/sys/cpu/i386/include/cpufunc.h index 9b7e80e4df..3f6823583e 100644 --- a/sys/cpu/i386/include/cpufunc.h +++ b/sys/cpu/i386/include/cpufunc.h @@ -141,6 +141,14 @@ do_cpuid(u_int ax, u_int *p) : "0" (ax)); } +static __inline void +cpuid_count(u_int ax, u_int cx, u_int *p) +{ + __asm __volatile("cpuid" + : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3]) + : "0" (ax), "c" (cx)); +} + #ifndef _CPU_DISABLE_INTR_DEFINED static __inline void diff --git a/sys/cpu/i386/include/cputypes.h b/sys/cpu/i386/include/cputypes.h index 338c545d1c..4da9929b07 100644 --- a/sys/cpu/i386/include/cputypes.h +++ b/sys/cpu/i386/include/cputypes.h @@ -62,6 +62,22 @@ #define CPU_P4 16 /* Intel Pentium 4 */ #define CPU_GEODE1100 17 /* NS Geode SC1100 */ +/* + * Vendors of processor. + */ +#define CPU_VENDOR_NSC 0x100b /* NSC */ +#define CPU_VENDOR_IBM 0x1014 /* IBM */ +#define CPU_VENDOR_AMD 0x1022 /* AMD */ +#define CPU_VENDOR_SIS 0x1039 /* SiS */ +#define CPU_VENDOR_UMC 0x1060 /* UMC */ +#define CPU_VENDOR_NEXGEN 0x1074 /* Nexgen */ +#define CPU_VENDOR_CYRIX 0x1078 /* Cyrix */ +#define CPU_VENDOR_IDT 0x111d /* Centaur/IDT/VIA */ +#define CPU_VENDOR_TRANSMETA 0x1279 /* Transmeta */ +#define CPU_VENDOR_INTEL 0x8086 /* Intel */ +#define CPU_VENDOR_RISE 0xdead2bad /* Rise */ +#define CPU_VENDOR_CENTAUR CPU_VENDOR_IDT + #ifndef LOCORE struct cpu_nameclass { char *cpu_name; diff --git a/sys/cpu/i386/include/specialreg.h b/sys/cpu/i386/include/specialreg.h index b9301ce3bb..484cba8e4d 100644 --- a/sys/cpu/i386/include/specialreg.h +++ b/sys/cpu/i386/include/specialreg.h @@ -10,10 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -31,8 +27,7 @@ * SUCH DAMAGE. * * from: @(#)specialreg.h 7.1 (Berkeley) 5/9/91 - * $FreeBSD: src/sys/i386/include/specialreg.h,v 1.19.2.3 2003/01/22 17:24:28 jhb Exp $ - * $DragonFly: src/sys/cpu/i386/include/specialreg.h,v 1.9 2007/10/02 13:16:42 hasso Exp $ + * $FreeBSD: src/sys/i386/include/specialreg.h,v 1.54 2009/09/10 17:27:36 jkim Exp $ */ #ifndef _CPU_SPECIALREG_H_ @@ -42,12 +37,9 @@ * Bits in 386 special registers: */ #define CR0_PE 0x00000001 /* Protected mode Enable */ -#define CR0_MP 0x00000002 /* "Math" Present (NPX or NPX emulator) */ -#define CR0_EM 0x00000004 /* EMulate non-NPX coproc. (trap ESC only) */ +#define CR0_MP 0x00000002 /* "Math" (fpu) Present */ +#define CR0_EM 0x00000004 /* EMulate FPU instructions. (trap ESC only) */ #define CR0_TS 0x00000008 /* Task Switched (if MP, trap ESC and WAIT) */ -#ifdef notused -#define CR0_ET 0x00000010 /* Extension Type (387 (if set) vs 287) */ -#endif #define CR0_PG 0x80000000 /* PaGing enable */ /* @@ -75,6 +67,11 @@ #define CR4_FXSR 0x00000200 /* Fast FPU save/restore used by OS */ #define CR4_XMM 0x00000400 /* enable SIMD/MMX2 to use except 16 */ +/* + * Bits in AMD64 special registers. EFER is 64 bits wide. + */ +#define EFER_NXE 0x000000800 /* PTE No-Execute bit enable (R/W) */ + /* * CPUID instruction features register */ @@ -109,18 +106,73 @@ #define CPUID_SS 0x08000000 #define CPUID_HTT 0x10000000 #define CPUID_TM 0x20000000 -#define CPUID_B30 0x40000000 +#define CPUID_IA64 0x40000000 #define CPUID_PBE 0x80000000 #define CPUID2_SSE3 0x00000001 +#define CPUID2_DTES64 0x00000004 #define CPUID2_MON 0x00000008 #define CPUID2_DS_CPL 0x00000010 #define CPUID2_VMX 0x00000020 +#define CPUID2_SMX 0x00000040 #define CPUID2_EST 0x00000080 #define CPUID2_TM2 0x00000100 #define CPUID2_SSSE3 0x00000200 -#define CPUID2_CNTXID 0x00000400 +#define CPUID2_CNXTID 0x00000400 #define CPUID2_CX16 0x00002000 +#define CPUID2_XTPR 0x00004000 +#define CPUID2_PDCM 0x00008000 +#define CPUID2_DCA 0x00040000 +#define CPUID2_SSE41 0x00080000 +#define CPUID2_SSE42 0x00100000 +#define CPUID2_X2APIC 0x00200000 +#define CPUID2_POPCNT 0x00800000 + +/* + * Important bits in the AMD extended cpuid flags + */ +#define AMDID_SYSCALL 0x00000800 +#define AMDID_MP 0x00080000 +#define AMDID_NX 0x00100000 +#define AMDID_EXT_MMX 0x00400000 +#define AMDID_FFXSR 0x01000000 +#define AMDID_PAGE1GB 0x04000000 +#define AMDID_RDTSCP 0x08000000 +#define AMDID_LM 0x20000000 +#define AMDID_EXT_3DNOW 0x40000000 +#define AMDID_3DNOW 0x80000000 + +#define AMDID2_LAHF 0x00000001 +#define AMDID2_CMP 0x00000002 +#define AMDID2_SVM 0x00000004 +#define AMDID2_EXT_APIC 0x00000008 +#define AMDID2_CR8 0x00000010 +#define AMDID2_ABM 0x00000020 +#define AMDID2_SSE4A 0x00000040 +#define AMDID2_MAS 0x00000080 +#define AMDID2_PREFETCH 0x00000100 +#define AMDID2_OSVW 0x00000200 +#define AMDID2_IBS 0x00000400 +#define AMDID2_SSE5 0x00000800 +#define AMDID2_SKINIT 0x00001000 +#define AMDID2_WDT 0x00002000 + +/* + * CPUID instruction 1 eax info + */ +#define CPUID_STEPPING 0x0000000f +#define CPUID_MODEL 0x000000f0 +#define CPUID_FAMILY 0x00000f00 +#define CPUID_EXT_MODEL 0x000f0000 +#define CPUID_EXT_FAMILY 0x0ff00000 +#define CPUID_TO_MODEL(id) \ + ((((id) & CPUID_MODEL) >> 4) | \ + ((((id) & CPUID_FAMILY) >= 0x600) ? \ + (((id) & CPUID_EXT_MODEL) >> 12) : 0)) +#define CPUID_TO_FAMILY(id) \ + ((((id) & CPUID_FAMILY) >> 8) + \ + ((((id) & CPUID_FAMILY) == 0xf00) ? \ + (((id) & CPUID_EXT_FAMILY) >> 20) : 0)) /* * CPUID instruction 1 ebx info @@ -130,67 +182,159 @@ #define CPUID_HTT_CORES 0x00ff0000 #define CPUID_LOCAL_APIC_ID 0xff000000 +/* + * CPUID instruction 0xb ebx info. + */ +#define CPUID_TYPE_INVAL 0 +#define CPUID_TYPE_SMT 1 +#define CPUID_TYPE_CORE 2 + +/* + * AMD extended function 8000_0007h edx info + */ +#define AMDPM_TS 0x00000001 +#define AMDPM_FID 0x00000002 +#define AMDPM_VID 0x00000004 +#define AMDPM_TTP 0x00000008 +#define AMDPM_TM 0x00000010 +#define AMDPM_STC 0x00000020 +#define AMDPM_100MHZ_STEPS 0x00000040 +#define AMDPM_HW_PSTATE 0x00000080 +#define AMDPM_TSC_INVARIANT 0x00000100 + +/* + * AMD extended function 8000_0008h ecx info + */ +#define AMDID_CMP_CORES 0x000000ff + +/* + * CPUID manufacturers identifiers + */ +#define AMD_VENDOR_ID "AuthenticAMD" +#define CENTAUR_VENDOR_ID "CentaurHauls" +#define CYRIX_VENDOR_ID "CyrixInstead" +#define INTEL_VENDOR_ID "GenuineIntel" +#define NEXGEN_VENDOR_ID "NexGenDriven" +#define NSC_VENDOR_ID "Geode by NSC" +#define RISE_VENDOR_ID "RiseRiseRise" +#define SIS_VENDOR_ID "SiS SiS SiS " +#define TRANSMETA_VENDOR_ID "GenuineTMx86" +#define UMC_VENDOR_ID "UMC UMC UMC " + /* * Model-specific registers for the i386 family */ -#define MSR_P5_MC_ADDR 0x000 -#define MSR_P5_MC_TYPE 0x001 -#define MSR_TSC 0x010 -#define MSR_APICBASE 0x01b -#define MSR_EBL_CR_POWERON 0x02a -#define MSR_BIOS_UPDT_TRIG 0x079 -#define MSR_BIOS_SIGN 0x08b -#define MSR_PERFCTR0 0x0c1 -#define MSR_PERFCTR1 0x0c2 -#define MSR_IA32_EXT_CONFIG 0x0ee /* Undocumented. Core Solo/Duo only */ -#define MSR_MTRRcap 0x0fe -#define MSR_MCG_CAP 0x179 -#define MSR_MCG_STATUS 0x17a -#define MSR_MCG_CTL 0x17b -#define MSR_EVNTSEL0 0x186 -#define MSR_EVNTSEL1 0x187 -#define MSR_DEBUGCTLMSR 0x1d9 -#define MSR_LASTBRANCHFROMIP 0x1db -#define MSR_LASTBRANCHTOIP 0x1dc -#define MSR_LASTINTFROMIP 0x1dd -#define MSR_LASTINTTOIP 0x1de -#define MSR_ROB_CR_BKUPTMPDR6 0x1e0 -#define MSR_MTRRVarBase 0x200 -#define MSR_MTRR64kBase 0x250 -#define MSR_MTRR16kBase 0x258 -#define MSR_MTRR4kBase 0x268 -#define MSR_MTRRdefType 0x2ff -#define MSR_MC0_CTL 0x400 -#define MSR_MC0_STATUS 0x401 -#define MSR_MC0_ADDR 0x402 -#define MSR_MC0_MISC 0x403 -#define MSR_MC1_CTL 0x404 -#define MSR_MC1_STATUS 0x405 -#define MSR_MC1_ADDR 0x406 -#define MSR_MC1_MISC 0x407 -#define MSR_MC2_CTL 0x408 -#define MSR_MC2_STATUS 0x409 -#define MSR_MC2_ADDR 0x40a -#define MSR_MC2_MISC 0x40b -#define MSR_MC4_CTL 0x40c -#define MSR_MC4_STATUS 0x40d -#define MSR_MC4_ADDR 0x40e -#define MSR_MC4_MISC 0x40f -#define MSR_MC3_CTL 0x410 -#define MSR_MC3_STATUS 0x411 -#define MSR_MC3_ADDR 0x412 -#define MSR_MC3_MISC 0x413 -#define MSR_THERM_CONTROL 0x19a -#define MSR_THERM_INTERRUPT 0x19b -#define MSR_THERM_STATUS 0x19c +#define MSR_P5_MC_ADDR 0x000 +#define MSR_P5_MC_TYPE 0x001 +#define MSR_TSC 0x010 +#define MSR_P5_CESR 0x011 +#define MSR_P5_CTR0 0x012 +#define MSR_P5_CTR1 0x013 +#define MSR_IA32_PLATFORM_ID 0x017 +#define MSR_APICBASE 0x01b +#define MSR_EBL_CR_POWERON 0x02a +#define MSR_TEST_CTL 0x033 +#define MSR_BIOS_UPDT_TRIG 0x079 +#define MSR_BBL_CR_D0 0x088 +#define MSR_BBL_CR_D1 0x089 +#define MSR_BBL_CR_D2 0x08a +#define MSR_BIOS_SIGN 0x08b +#define MSR_PERFCTR0 0x0c1 +#define MSR_PERFCTR1 0x0c2 +#define MSR_IA32_EXT_CONFIG 0x0ee /* Undocumented. Core Solo/Duo only */ +#define MSR_MTRRcap 0x0fe +#define MSR_BBL_CR_ADDR 0x116 +#define MSR_BBL_CR_DECC 0x118 +#define MSR_BBL_CR_CTL 0x119 +#define MSR_BBL_CR_TRIG 0x11a +#define MSR_BBL_CR_BUSY 0x11b +#define MSR_BBL_CR_CTL3 0x11e +#define MSR_SYSENTER_CS_MSR 0x174 +#define MSR_SYSENTER_ESP_MSR 0x175 +#define MSR_SYSENTER_EIP_MSR 0x176 +#define MSR_MCG_CAP 0x179 +#define MSR_MCG_STATUS 0x17a +#define MSR_MCG_CTL 0x17b +#define MSR_EVNTSEL0 0x186 +#define MSR_EVNTSEL1 0x187 +#define MSR_THERM_CONTROL 0x19a +#define MSR_THERM_INTERRUPT 0x19b +#define MSR_THERM_STATUS 0x19c +#define MSR_IA32_MISC_ENABLE 0x1a0 +#define MSR_DEBUGCTLMSR 0x1d9 +#define MSR_LASTBRANCHFROMIP 0x1db +#define MSR_LASTBRANCHTOIP 0x1dc +#define MSR_LASTINTFROMIP 0x1dd +#define MSR_LASTINTTOIP 0x1de +#define MSR_ROB_CR_BKUPTMPDR6 0x1e0 +#define MSR_MTRRVarBase 0x200 +#define MSR_MTRR64kBase 0x250 +#define MSR_MTRR16kBase 0x258 +#define MSR_MTRR4kBase 0x268 +#define MSR_PAT 0x277 +#define MSR_MTRRdefType 0x2ff +#define MSR_MC0_CTL 0x400 +#define MSR_MC0_STATUS 0x401 +#define MSR_MC0_ADDR 0x402 +#define MSR_MC0_MISC 0x403 +#define MSR_MC1_CTL 0x404 +#define MSR_MC1_STATUS 0x405 +#define MSR_MC1_ADDR 0x406 +#define MSR_MC1_MISC 0x407 +#define MSR_MC2_CTL 0x408 +#define MSR_MC2_STATUS 0x409 +#define MSR_MC2_ADDR 0x40a +#define MSR_MC2_MISC 0x40b +#define MSR_MC3_CTL 0x40c +#define MSR_MC3_STATUS 0x40d +#define MSR_MC3_ADDR 0x40e +#define MSR_MC3_MISC 0x40f +#define MSR_MC4_CTL 0x410 +#define MSR_MC4_STATUS 0x411 +#define MSR_MC4_ADDR 0x412 +#define MSR_MC4_MISC 0x413 + +/* + * Constants related to MSR's. + */ +#define APICBASE_RESERVED 0x000006ff +#define APICBASE_BSP 0x00000100 +#define APICBASE_ENABLED 0x00000800 +#define APICBASE_ADDRESS 0xfffff000 +/* + * PAT modes. + */ +#define PAT_UNCACHEABLE 0x00 +#define PAT_WRITE_COMBINING 0x01 +#define PAT_WRITE_THROUGH 0x04 +#define PAT_WRITE_PROTECTED 0x05 +#define PAT_WRITE_BACK 0x06 +#define PAT_UNCACHED 0x07 +#define PAT_VALUE(i, m) ((long long)(m) << (8 * (i))) +#define PAT_MASK(i) PAT_VALUE(i, 0xff) /* * Constants related to MTRRs */ -#define MTRR_N64K 8 /* numbers of fixed-size entries */ -#define MTRR_N16K 16 -#define MTRR_N4K 64 +#define MTRR_UNCACHEABLE 0x00 +#define MTRR_WRITE_COMBINING 0x01 +#define MTRR_WRITE_THROUGH 0x04 +#define MTRR_WRITE_PROTECTED 0x05 +#define MTRR_WRITE_BACK 0x06 +#define MTRR_N64K 8 /* numbers of fixed-size entries */ +#define MTRR_N16K 16 +#define MTRR_N4K 64 +#define MTRR_CAP_WC 0x0000000000000400ULL +#define MTRR_CAP_FIXED 0x0000000000000100ULL +#define MTRR_CAP_VCNT 0x00000000000000ffULL +#define MTRR_DEF_ENABLE 0x0000000000000800ULL +#define MTRR_DEF_FIXED_ENABLE 0x0000000000000400ULL +#define MTRR_DEF_TYPE 0x00000000000000ffULL +#define MTRR_PHYSBASE_PHYSBASE 0x000ffffffffff000ULL +#define MTRR_PHYSBASE_TYPE 0x00000000000000ffULL +#define MTRR_PHYSMASK_PHYSMASK 0x000ffffffffff000ULL +#define MTRR_PHYSMASK_VALID 0x0000000000000800ULL /* * Cyrix configuration registers, accessible as IO ports. @@ -223,7 +367,7 @@ #define CCR2_SUSP_HLT 0x08 /* Suspend on HALT */ #define CCR2_WT1 0x10 /* WT region 1 */ #define CCR2_WPR1 0x10 /* Write-protect region 1 */ -#define CCR2_BARB 0x20 /* Flushes write-back cache when entering +#define CCR2_BARB 0x20 /* Flushes write-back cache when entering hold state. */ #define CCR2_BWRT 0x40 /* Enables burst write cycles */ #define CCR2_USE_SUSP 0x80 /* Enables suspend pins */ @@ -270,6 +414,34 @@ #define DIR0 0xfe #define DIR1 0xff +/* + * Machine Check register constants. + */ +#define MCG_CAP_COUNT 0x000000ff +#define MCG_CAP_CTL_P 0x00000100 +#define MCG_CAP_EXT_P 0x00000200 +#define MCG_CAP_TES_P 0x00000800 +#define MCG_CAP_EXT_CNT 0x00ff0000 +#define MCG_STATUS_RIPV 0x00000001 +#define MCG_STATUS_EIPV 0x00000002 +#define MCG_STATUS_MCIP 0x00000004 +#define MCG_CTL_ENABLE 0xffffffffffffffffUL +#define MCG_CTL_DISABLE 0x0000000000000000UL +#define MSR_MC_CTL(x) (MSR_MC0_CTL + (x) * 4) +#define MSR_MC_STATUS(x) (MSR_MC0_STATUS + (x) * 4) +#define MSR_MC_ADDR(x) (MSR_MC0_ADDR + (x) * 4) +#define MSR_MC_MISC(x) (MSR_MC0_MISC + (x) * 4) +#define MC_STATUS_MCA_ERROR 0x000000000000ffffUL +#define MC_STATUS_MODEL_ERROR 0x00000000ffff0000UL +#define MC_STATUS_OTHER_INFO 0x01ffffff00000000UL +#define MC_STATUS_PCC 0x0200000000000000UL +#define MC_STATUS_ADDRV 0x0400000000000000UL +#define MC_STATUS_MISCV 0x0800000000000000UL +#define MC_STATUS_EN 0x1000000000000000UL +#define MC_STATUS_UC 0x2000000000000000UL +#define MC_STATUS_OVER 0x4000000000000000UL +#define MC_STATUS_VAL 0x8000000000000000UL + /* * The following four 3-byte registers control the non-cacheable regions. * These registers must be written as three separate bytes. @@ -350,11 +522,11 @@ #define RCR6 0xe2 #define RCR7 0xe3 -#define RCR_RCD 0x01 /* Disables caching for ARRx (x = 0-6). */ -#define RCR_RCE 0x01 /* Enables caching for ARR7. */ -#define RCR_WWO 0x02 /* Weak write ordering. */ +#define RCR_RCD 0x01 /* Disables caching for ARRx (x = 0-6). */ +#define RCR_RCE 0x01 /* Enables caching for ARR7. */ +#define RCR_WWO 0x02 /* Weak write ordering. */ #define RCR_WL 0x04 /* Weak locking. */ -#define RCR_WG 0x08 /* Write gathering. */ +#define RCR_WG 0x08 /* Write gathering. */ #define RCR_WT 0x10 /* Write-through. */ #define RCR_NLB 0x20 /* LBA# pin is not asserted. */ @@ -363,6 +535,10 @@ #define AMD_WT_ALLOC_PRE 0x20000 /* programmable range enable */ #define AMD_WT_ALLOC_FRE 0x10000 /* fixed (A0000-FFFFF) range enable */ +/* AMD64 MSR's */ +#define MSR_EFER 0xc0000080 /* extended features */ +#define MSR_K8_UCODE_UPDATE 0xc0010020 /* update microcode */ + /* VIA ACE crypto featureset: for via_feature_rng */ #define VIA_HAS_RNG 1 /* cpu has RNG */ @@ -384,6 +560,21 @@ #define VIA_CPUID_HAS_PMM 0x001000 #define VIA_CPUID_DO_PMM 0x002000 +/* VIA ACE xcrypt-* instruction context control options */ +#define VIA_CRYPT_CWLO_ROUND_M 0x0000000f +#define VIA_CRYPT_CWLO_ALG_M 0x00000070 +#define VIA_CRYPT_CWLO_ALG_AES 0x00000000 +#define VIA_CRYPT_CWLO_KEYGEN_M 0x00000080 +#define VIA_CRYPT_CWLO_KEYGEN_HW 0x00000000 +#define VIA_CRYPT_CWLO_KEYGEN_SW 0x00000080 +#define VIA_CRYPT_CWLO_NORMAL 0x00000000 +#define VIA_CRYPT_CWLO_INTERMEDIATE 0x00000100 +#define VIA_CRYPT_CWLO_ENCRYPT 0x00000000 +#define VIA_CRYPT_CWLO_DECRYPT 0x00000200 +#define VIA_CRYPT_CWLO_KEY128 0x0000000a /* 128bit, 10 rds */ +#define VIA_CRYPT_CWLO_KEY192 0x0000040c /* 192bit, 12 rds */ +#define VIA_CRYPT_CWLO_KEY256 0x0000080e /* 256bit, 15 rds */ + #ifndef LOCORE #ifndef _SYS_TYPES_H_ @@ -396,15 +587,15 @@ static __inline u_char read_cyrix_reg(u_char reg) { - outb(0x22, reg); - return inb(0x23); + outb(0x22, reg); + return inb(0x23); } static __inline void write_cyrix_reg(u_char reg, u_char data) { - outb(0x22, reg); - outb(0x23, data); + outb(0x22, reg); + outb(0x23, data); } #endif diff --git a/sys/platform/pc32/acpica5/acpi_pstate_machdep.c b/sys/platform/pc32/acpica5/acpi_pstate_machdep.c index 7a19833384..8b8454d50b 100644 --- a/sys/platform/pc32/acpica5/acpi_pstate_machdep.c +++ b/sys/platform/pc32/acpica5/acpi_pstate_machdep.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include "acpi.h" @@ -139,9 +140,9 @@ static const struct acpi_pst_md acpi_pst_intel = { const struct acpi_pst_md * acpi_pst_md_probe(void) { - if (strcmp(cpu_vendor, "AuthenticAMD") == 0) + if (cpu_vendor_id == CPU_VENDOR_AMD) return acpi_pst_amd_probe(); - else if (strcmp(cpu_vendor, "GenuineIntel") == 0) + else if (cpu_vendor_id == CPU_VENDOR_INTEL) return acpi_pst_intel_probe(); return NULL; } diff --git a/sys/platform/pc32/apic/mpapic.c b/sys/platform/pc32/apic/mpapic.c index 3990f96618..2d30c751b7 100644 --- a/sys/platform/pc32/apic/mpapic.c +++ b/sys/platform/pc32/apic/mpapic.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -313,7 +314,7 @@ lapic_timer_fixup_handler(void *arg) if (started != NULL) *started = 0; - if (strcmp(cpu_vendor, "AuthenticAMD") == 0) { + if (cpu_vendor_id == CPU_VENDOR_AMD) { /* * Detect the presence of C1E capability mostly on latest * dual-cores (or future) k8 family. This feature renders diff --git a/sys/platform/pc32/i386/identcpu.c b/sys/platform/pc32/i386/identcpu.c index 3257a38a37..5457605eb0 100644 --- a/sys/platform/pc32/i386/identcpu.c +++ b/sys/platform/pc32/i386/identcpu.c @@ -1,9 +1,7 @@ -/* - * Copyright (c) 1982, 1987, 1990 The Regents of the University of California. +/*- * Copyright (c) 1992 Terrence R. Lambert. + * Copyright (c) 1982, 1987, 1990 The Regents of the University of California. * Copyright (c) 1997 KATO Takenori. - * Copyright (c) 2001 Tamotsu Hattori. - * Copyright (c) 2001 Mitsuru IWASAKI. * All rights reserved. * * This code is derived from software contributed to Berkeley by @@ -38,10 +36,8 @@ * SUCH DAMAGE. * * from: Id: machdep.c,v 1.193 1996/06/18 01:22:04 bde Exp - * $FreeBSD: src/sys/i386/i386/identcpu.c,v 1.80.2.15 2003/04/11 17:06:41 jhb Exp $ - * $DragonFly: src/sys/platform/pc32/i386/identcpu.c,v 1.24 2008/11/24 13:14:21 swildner Exp $ + * $FreeBSD: src/sys/i386/i386/identcpu.c,v 1.206 2009/11/12 10:59:00 nyan */ - #include "opt_cpu.h" #include @@ -66,6 +62,7 @@ /* XXX - should be in header file: */ void printcpuinfo(void); void finishidentcpu(void); +void earlysetcpuclass(void); #if defined(I586_CPU) && defined(CPU_WT_ALLOC) void enable_K5_wt_alloc(void); void enable_K6_wt_alloc(void); @@ -74,16 +71,16 @@ void enable_K6_2_wt_alloc(void); void panicifcpuunsupported(void); static void identifycyrix(void); -#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) -static void print_AMD_features(void); -#endif +static void init_exthigh(void); +static u_int find_cpu_vendor_id(void); static void print_AMD_info(void); +static void print_INTEL_info(void); +static void print_INTEL_TLB(u_int data); static void print_AMD_assoc(int i); static void print_transmeta_info(void); -static void setup_tmx86_longrun(void); static void print_via_padlock_info(void); -int cpu_class = CPUCLASS_386; +int cpu_class; u_int cpu_exthigh; /* Highest arg to extended CPUID */ u_int cyrix_did; /* Device ID of Cyrix CPU */ char machine[] = MACHINE; @@ -94,47 +91,35 @@ static char cpu_model[128]; SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, cpu_model, 0, "Machine model"); +static int hw_clockrate; +SYSCTL_INT(_hw, OID_AUTO, clockrate, CTLFLAG_RD, + &hw_clockrate, 0, "CPU instruction clock rate"); + static char cpu_brand[48]; -#define MAX_ADDITIONAL_INFO 16 +#define MAX_ADDITIONAL_INFO 16 static const char *additional_cpu_info_ary[MAX_ADDITIONAL_INFO]; static u_int additional_cpu_info_count; -#define MAX_BRAND_INDEX 23 +#define MAX_BRAND_INDEX 8 -/* - * Brand ID's according to Intel document AP-485, number 241618-31, published - * September 2006, page 42. - */ static const char *cpu_brandtable[MAX_BRAND_INDEX + 1] = { NULL, /* No brand */ "Intel Celeron", "Intel Pentium III", "Intel Pentium III Xeon", - "Intel Pentium III", - NULL, /* Unspecified */ - "Mobile Intel Pentium III-M", - "Mobile Intel Celeron", - "Intel Pentium 4", - "Intel Pentium 4", - "Intel Celeron", - "Intel Xeon", - "Intel Xeon MP", - NULL, /* Unspecified */ - "Mobile Intel Pentium 4-M", - "Mobile Intel Celeron", - NULL, /* Unspecified */ - "Mobile Genuine Intel", - "Intel Celeron M", - "Mobile Intel Celeron", - "Intel Celeron", - "Mobile Genuine Intel", - "Intel Pentium M", - "Mobile Intel Celeron" + NULL, + NULL, + NULL, + NULL, + "Intel Pentium 4" }; -static struct cpu_nameclass i386_cpus[] = { +static struct { + char *cpu_name; + int cpu_class; +} i386_cpus[] = { { "Intel 80286", CPUCLASS_286 }, /* CPU_286 */ { "i386SX", CPUCLASS_386 }, /* CPU_386SX */ { "i386DX", CPUCLASS_386 }, /* CPU_386 */ @@ -154,44 +139,77 @@ static struct cpu_nameclass i386_cpus[] = { { "Pentium 4", CPUCLASS_686 }, /* CPU_P4 */ }; +static struct { + char *vendor; + u_int vendor_id; +} cpu_vendors[] = { + { INTEL_VENDOR_ID, CPU_VENDOR_INTEL }, /* GenuineIntel */ + { AMD_VENDOR_ID, CPU_VENDOR_AMD }, /* AuthenticAMD */ + { CENTAUR_VENDOR_ID, CPU_VENDOR_CENTAUR }, /* CentaurHauls */ + { NSC_VENDOR_ID, CPU_VENDOR_NSC }, /* Geode by NSC */ + { CYRIX_VENDOR_ID, CPU_VENDOR_CYRIX }, /* CyrixInstead */ + { TRANSMETA_VENDOR_ID, CPU_VENDOR_TRANSMETA }, /* GenuineTMx86 */ + { SIS_VENDOR_ID, CPU_VENDOR_SIS }, /* SiS SiS SiS */ + { UMC_VENDOR_ID, CPU_VENDOR_UMC }, /* UMC UMC UMC */ + { NEXGEN_VENDOR_ID, CPU_VENDOR_NEXGEN }, /* NexGenDriven */ + { RISE_VENDOR_ID, CPU_VENDOR_RISE }, /* RiseRiseRise */ +#if 0 + /* XXX CPUID 8000_0000h and 8086_0000h, not 0000_0000h */ + { "TransmetaCPU", CPU_VENDOR_TRANSMETA }, +#endif +}; + +int cpu_cores; +int cpu_logical; + #if defined(I586_CPU) && !defined(NO_F00F_HACK) int has_f00f_bug = 0; /* Initialized so that it can be patched. */ #endif +static void +init_exthigh(void) +{ + static int done = 0; + u_int regs[4]; + + if (done == 0) { + if (cpu_high > 0 && + (cpu_vendor_id == CPU_VENDOR_INTEL || + cpu_vendor_id == CPU_VENDOR_AMD || + cpu_vendor_id == CPU_VENDOR_TRANSMETA || + cpu_vendor_id == CPU_VENDOR_CENTAUR || + cpu_vendor_id == CPU_VENDOR_NSC)) { + do_cpuid(0x80000000, regs); + if (regs[0] >= 0x80000000) + cpu_exthigh = regs[0]; + } + + done = 1; + } +} + void printcpuinfo(void) { -#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) u_int regs[4], i; -#endif char *brand; cpu_class = i386_cpus[cpu].cpu_class; kprintf("CPU: "); strncpy(cpu_model, i386_cpus[cpu].cpu_name, sizeof (cpu_model)); -#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) /* Check for extended CPUID information and a processor name. */ - if (cpu_high > 0 && - (strcmp(cpu_vendor, "GenuineIntel") == 0 || - strcmp(cpu_vendor, "AuthenticAMD") == 0 || - strcmp(cpu_vendor, "GenuineTMx86") == 0 || - strcmp(cpu_vendor, "TransmetaCPU") == 0)) { - do_cpuid(0x80000000, regs); - if (regs[0] >= 0x80000000) { - cpu_exthigh = regs[0]; - if (cpu_exthigh >= 0x80000004) { - brand = cpu_brand; - for (i = 0x80000002; i < 0x80000005; i++) { - do_cpuid(i, regs); - memcpy(brand, regs, sizeof(regs)); - brand += sizeof(regs); - } - } + init_exthigh(); + if (cpu_exthigh >= 0x80000004) { + brand = cpu_brand; + for (i = 0x80000002; i < 0x80000005; i++) { + do_cpuid(i, regs); + memcpy(brand, regs, sizeof(regs)); + brand += sizeof(regs); } } - if (strcmp(cpu_vendor, "GenuineIntel") == 0) { + if (cpu_vendor_id == CPU_VENDOR_INTEL) { if ((cpu_id & 0xf00) > 0x300) { u_int brand_index; @@ -250,7 +268,7 @@ printcpuinfo(void) strcat(cpu_model, "/P54C"); break; case 0x30: - strcat(cpu_model, "/P54T Overdrive"); + strcat(cpu_model, "/P24T"); break; case 0x40: strcat(cpu_model, "/P55C"); @@ -324,7 +342,7 @@ printcpuinfo(void) cpu_brandtable[brand_index]); } } - } else if (strcmp(cpu_vendor, "AuthenticAMD") == 0) { + } else if (cpu_vendor_id == CPU_VENDOR_AMD) { /* * Values taken from AMD Processor Recognition * http://www.amd.com/K6/k6docs/pdf/20734g.pdf @@ -382,7 +400,7 @@ printcpuinfo(void) strcat(cpu_model, "Geode LX"); /* * Make sure the TSC runs through suspension, - * otherwise we can't use it as timecounter. + * otherwise we can't use it as timecounter */ wrmsr(0x1900, rdmsr(0x1900) | 0x20ULL); break; @@ -404,7 +422,7 @@ printcpuinfo(void) enable_K6_wt_alloc(); } #endif - } else if (strcmp(cpu_vendor, "CyrixInstead") == 0) { + } else if (cpu_vendor_id == CPU_VENDOR_CYRIX) { strcpy(cpu_model, "Cyrix "); switch (cpu_id & 0xff0) { case 0x440: @@ -540,7 +558,7 @@ printcpuinfo(void) } break; } - } else if (strcmp(cpu_vendor, "RiseRiseRise") == 0) { + } else if (cpu_vendor_id == CPU_VENDOR_RISE) { strcpy(cpu_model, "Rise "); switch (cpu_id & 0xff0) { case 0x500: @@ -549,7 +567,7 @@ printcpuinfo(void) default: strcat(cpu_model, "Unknown"); } - } else if (strcmp(cpu_vendor, "CentaurHauls") == 0) { + } else if (cpu_vendor_id == CPU_VENDOR_CENTAUR) { switch (cpu_id & 0xff0) { case 0x540: strcpy(cpu_model, "IDT WinChip C6"); @@ -583,8 +601,19 @@ printcpuinfo(void) default: strcpy(cpu_model, "VIA/IDT Unknown"); } - } else if (strcmp(cpu_vendor, "IBM") == 0) { + } else if (cpu_vendor_id == CPU_VENDOR_IBM) { strcpy(cpu_model, "Blue Lightning CPU"); + } else if (cpu_vendor_id == CPU_VENDOR_NSC) { + switch (cpu_id & 0xfff) { + case 0x540: + strcpy(cpu_model, "Geode SC1100"); + cpu = CPU_GEODE1100; + tsc_is_broken = 1; + break; + default: + strcpy(cpu_model, "Geode/NSC unknown"); + break; + } } /* @@ -597,8 +626,6 @@ printcpuinfo(void) if (*brand != '\0') strcpy(cpu_model, brand); -#endif - kprintf("%s (", cpu_model); switch(cpu_class) { case CPUCLASS_286: @@ -610,22 +637,24 @@ printcpuinfo(void) #if defined(I486_CPU) case CPUCLASS_486: kprintf("486"); - /* bzero = i486_bzero; */ + /* bzero_vector = i486_bzero; */ break; #endif #if defined(I586_CPU) case CPUCLASS_586: - kprintf("%lld.%02lld-MHz ", - (tsc_frequency + 4999LL) / 1000000LL, - ((tsc_frequency + 4999LL) / 10000LL) % 100LL); + hw_clockrate = (tsc_frequency + 5000) / 1000000; + kprintf("%jd.%02d-MHz ", + (intmax_t)(tsc_frequency + 4999) / 1000000, + (u_int)((tsc_frequency + 4999) / 10000) % 100); kprintf("586"); break; #endif #if defined(I686_CPU) case CPUCLASS_686: - kprintf("%lld.%02lld-MHz ", - (tsc_frequency + 4999LL) / 1000000LL, - ((tsc_frequency + 4999LL) / 10000LL) % 100LL); + hw_clockrate = (tsc_frequency + 5000) / 1000000; + kprintf("%jd.%02d-MHz ", + (intmax_t)(tsc_frequency + 4999) / 1000000, + (u_int)((tsc_frequency + 4999) / 10000) % 100); kprintf("686"); break; #endif @@ -633,22 +662,25 @@ printcpuinfo(void) kprintf("Unknown"); /* will panic below... */ } kprintf("-class CPU)\n"); -#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) if(*cpu_vendor) kprintf(" Origin = \"%s\"",cpu_vendor); if(cpu_id) kprintf(" Id = 0x%x", cpu_id); - if (strcmp(cpu_vendor, "GenuineIntel") == 0 || - strcmp(cpu_vendor, "AuthenticAMD") == 0 || - strcmp(cpu_vendor, "RiseRiseRise") == 0 || - strcmp(cpu_vendor, "CentaurHauls") == 0 || - ((strcmp(cpu_vendor, "CyrixInstead") == 0) && + if (cpu_vendor_id == CPU_VENDOR_INTEL || + cpu_vendor_id == CPU_VENDOR_AMD || + cpu_vendor_id == CPU_VENDOR_TRANSMETA || + cpu_vendor_id == CPU_VENDOR_RISE || + cpu_vendor_id == CPU_VENDOR_CENTAUR || + cpu_vendor_id == CPU_VENDOR_NSC || + (cpu_vendor_id == CPU_VENDOR_CYRIX && ((cpu_id & 0xf00) > 0x500))) { kprintf(" Stepping = %u", cpu_id & 0xf); - if (strcmp(cpu_vendor, "CyrixInstead") == 0) + if (cpu_vendor_id == CPU_VENDOR_CYRIX) kprintf(" DIR=0x%04x", cyrix_did); if (cpu_high > 0) { + u_int cmp = 1, htt = 1; + /* * Here we should probably set up flags indicating * whether or not various features are available. @@ -718,7 +750,7 @@ printcpuinfo(void) "\024SSE4.1" "\025SSE4.2" "\026x2APIC" /* xAPIC Extensions */ - "\027MOVBE" /* MOVBE instruction */ + "\027" "\030POPCNT" "\031" "\032" @@ -731,22 +763,153 @@ printcpuinfo(void) ); } - if (strcmp(cpu_vendor, "CentaurHauls") == 0) + /* + * AMD64 Architecture Programmer's Manual Volume 3: + * General-Purpose and System Instructions + * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/24594.pdf + * + * IA-32 Intel Architecture Software Developer's Manual, + * Volume 2A: Instruction Set Reference, A-M + * ftp://download.intel.com/design/Pentium4/manuals/25366617.pdf + */ + if (amd_feature != 0) { + kprintf("\n AMD Features=0x%b", amd_feature, + "\020" /* in hex */ + "\001" /* Same */ + "\002" /* Same */ + "\003" /* Same */ + "\004" /* Same */ + "\005" /* Same */ + "\006" /* Same */ + "\007" /* Same */ + "\010" /* Same */ + "\011" /* Same */ + "\012" /* Same */ + "\013" /* Undefined */ + "\014SYSCALL" /* Have SYSCALL/SYSRET */ + "\015" /* Same */ + "\016" /* Same */ + "\017" /* Same */ + "\020" /* Same */ + "\021" /* Same */ + "\022" /* Same */ + "\023" /* Reserved, unknown */ + "\024MP" /* Multiprocessor Capable */ + "\025NX" /* Has EFER.NXE, NX */ + "\026" /* Undefined */ + "\027MMX+" /* AMD MMX Extensions */ + "\030" /* Same */ + "\031" /* Same */ + "\032FFXSR" /* Fast FXSAVE/FXRSTOR */ + "\033Page1GB" /* 1-GB large page support */ + "\034RDTSCP" /* RDTSCP */ + "\035" /* Undefined */ + "\036LM" /* 64 bit long mode */ + "\0373DNow!+" /* AMD 3DNow! Extensions */ + "\0403DNow!" /* AMD 3DNow! */ + ); + } + + if (amd_feature2 != 0) { + kprintf("\n AMD Features2=0x%b", amd_feature2, + "\020" + "\001LAHF" /* LAHF/SAHF in long mode */ + "\002CMP" /* CMP legacy */ + "\003SVM" /* Secure Virtual Mode */ + "\004ExtAPIC" /* Extended APIC register */ + "\005CR8" /* CR8 in legacy mode */ + "\006ABM" /* LZCNT instruction */ + "\007SSE4A" /* SSE4A */ + "\010MAS" /* Misaligned SSE mode */ + "\011Prefetch" /* 3DNow! Prefetch/PrefetchW */ + "\012OSVW" /* OS visible workaround */ + "\013IBS" /* Instruction based sampling */ + "\014SSE5" /* SSE5 */ + "\015SKINIT" /* SKINIT/STGI */ + "\016WDT" /* Watchdog timer */ + "\017" + "\020" + "\021" + "\022" + "\023" + "\024" + "\025" + "\026" + "\027" + "\030" + "\031" + "\032" + "\033" + "\034" + "\035" + "\036" + "\037" + "\040" + ); + } + + if (cpu_vendor_id == CPU_VENDOR_CENTAUR) print_via_padlock_info(); + if ((cpu_feature & CPUID_HTT) && + cpu_vendor_id == CPU_VENDOR_AMD) + cpu_feature &= ~CPUID_HTT; + + /* + * If this CPU supports HTT or CMP then mention the + * number of physical/logical cores it contains. + */ + if (cpu_feature & CPUID_HTT) + htt = (cpu_procinfo & CPUID_HTT_CORES) >> 16; + if (cpu_vendor_id == CPU_VENDOR_AMD && + (amd_feature2 & AMDID2_CMP)) + cmp = (cpu_procinfo2 & AMDID_CMP_CORES) + 1; + else if (cpu_vendor_id == CPU_VENDOR_INTEL && + (cpu_high >= 4)) { + cpuid_count(4, 0, regs); + if ((regs[0] & 0x1f) != 0) + cmp = ((regs[0] >> 26) & 0x3f) + 1; + } + cpu_cores = cmp; + cpu_logical = htt / cmp; + if (cmp > 1) + kprintf("\n Cores per package: %d", cmp); + if ((htt / cmp) > 1) + kprintf("\n Logical CPUs per core: %d", + cpu_logical); +#if 0 /* - * If this CPU supports hyperthreading then mention - * the number of logical CPU's it contains. + * If this CPU supports P-state invariant TSC then + * mention the capability. */ - if (cpu_feature & CPUID_HTT && - (cpu_procinfo & CPUID_HTT_CORES) >> 16 > 1) - kprintf("\n Hyperthreading: %d logical CPUs", - (cpu_procinfo & CPUID_HTT_CORES) >> 16); + switch (cpu_vendor_id) { + case CPU_VENDOR_AMD: + if ((amd_pminfo & AMDPM_TSC_INVARIANT) || + CPUID_TO_FAMILY(cpu_id) >= 0x10 || + cpu_id == 0x60fb2) + tsc_is_invariant = 1; + break; + case CPU_VENDOR_INTEL: + if ((amd_pminfo & AMDPM_TSC_INVARIANT) || + (CPUID_TO_FAMILY(cpu_id) == 0x6 && + CPUID_TO_MODEL(cpu_id) >= 0xe) || + (CPUID_TO_FAMILY(cpu_id) == 0xf && + CPUID_TO_MODEL(cpu_id) >= 0x3)) + tsc_is_invariant = 1; + break; + case CPU_VENDOR_CENTAUR: + if (CPUID_TO_FAMILY(cpu_id) == 0x6 && + CPUID_TO_MODEL(cpu_id) >= 0xf && + (rdmsr(0x1203) & 0x100000000ULL) == 0) + tsc_is_invariant = 1; + break; + } + if (tsc_is_invariant) + kprintf("\n TSC: P-state invariant"); +#endif + } - if (strcmp(cpu_vendor, "AuthenticAMD") == 0 && - cpu_exthigh >= 0x80000001) - print_AMD_features(); - } else if (strcmp(cpu_vendor, "CyrixInstead") == 0) { + } else if (cpu_vendor_id == CPU_VENDOR_CYRIX) { kprintf(" DIR=0x%04x", cyrix_did); kprintf(" Stepping=%u", (cyrix_did & 0xf000) >> 12); kprintf(" Revision=%u", (cyrix_did & 0x0f00) >> 8); @@ -755,54 +918,42 @@ printcpuinfo(void) kprintf("\n CPU cache: write-through mode"); #endif } + /* Avoid ugly blank lines: only print newline when we have to. */ if (*cpu_vendor || cpu_id) kprintf("\n"); -#endif - if (strcmp(cpu_vendor, "GenuineTMx86") == 0 || - strcmp(cpu_vendor, "TransmetaCPU") == 0) { - setup_tmx86_longrun(); - } - for (i = 0; i < additional_cpu_info_count; ++i) { kprintf(" %s\n", additional_cpu_info_ary[i]); - } + } if (!bootverbose) return; - if (strcmp(cpu_vendor, "AuthenticAMD") == 0) + if (cpu_vendor_id == CPU_VENDOR_AMD) print_AMD_info(); - else if (strcmp(cpu_vendor, "GenuineTMx86") == 0 || - strcmp(cpu_vendor, "TransmetaCPU") == 0) + else if (cpu_vendor_id == CPU_VENDOR_INTEL) + print_INTEL_info(); + else if (cpu_vendor_id == CPU_VENDOR_TRANSMETA) print_transmeta_info(); - -#ifdef I686_CPU - /* - * XXX - Do PPro CPUID level=2 stuff here? - * - * No, but maybe in a print_Intel_info() function called from here. - */ -#endif } void panicifcpuunsupported(void) { +#if !defined(lint) #if !defined(I486_CPU) && !defined(I586_CPU) && !defined(I686_CPU) #error This kernel is not configured for one of the supported CPUs #endif +#else /* lint */ +#endif /* lint */ /* * Now that we have told the user what they have, * let them know if that machine type isn't configured. */ switch (cpu_class) { - /* - * A 286 and 386 should not make it this far, anyway. - */ - case CPUCLASS_286: + case CPUCLASS_286: /* a 286 should not make it this far, anyway */ case CPUCLASS_386: #if !defined(I486_CPU) case CPUCLASS_486: @@ -831,16 +982,17 @@ static volatile u_int trap_by_rdmsr; */ inthand_t bluetrap6; -__asm( - " .text \n" - " .p2align 2,0x90 \n" - " .type " __XSTRING(CNAME(bluetrap6)) ",@function \n" - __XSTRING(CNAME(bluetrap6)) ": \n" - " ss \n" - " movl $0xa8c1d," __XSTRING(CNAME(trap_by_rdmsr)) " \n" - " addl $2, (%esp) # I know rdmsr is a 2-bytes instruction. \n" - " iret \n" -); +__asm +(" \n\ + .text \n\ + .p2align 2,0x90 \n\ + .type " __XSTRING(CNAME(bluetrap6)) ",@function \n\ +" __XSTRING(CNAME(bluetrap6)) ": \n\ + ss \n\ + movl $0xa8c1d," __XSTRING(CNAME(trap_by_rdmsr)) " \n\ + addl $2, (%esp) /* rdmsr is a 2-byte instruction */ \n\ + iret \n\ +"); /* * Special exception 13 handler. @@ -848,17 +1000,18 @@ __asm( */ inthand_t bluetrap13; -__asm( - " .text \n" - " .p2align 2,0x90 \n" - " .type " __XSTRING(CNAME(bluetrap13)) ",@function \n" - __XSTRING(CNAME(bluetrap13)) ": \n" - " ss \n" - " movl $0xa89c4," __XSTRING(CNAME(trap_by_rdmsr)) " \n" - " popl %eax # discard errorcode. \n" - " addl $2, (%esp) # I know rdmsr is a 2-bytes instruction. \n" - " iret \n" -); +__asm +(" \n\ + .text \n\ + .p2align 2,0x90 \n\ + .type " __XSTRING(CNAME(bluetrap13)) ",@function \n\ +" __XSTRING(CNAME(bluetrap13)) ": \n\ + ss \n\ + movl $0xa89c4," __XSTRING(CNAME(trap_by_rdmsr)) " \n\ + popl %eax /* discard error code */ \n\ + addl $2, (%esp) /* rdmsr is a 2-byte instruction */ \n\ + iret \n\ +"); /* * Distinguish IBM Blue Lightning CPU from Cyrix CPUs that does not @@ -880,14 +1033,16 @@ identblue(void) * will be trapped by bluetrap6() on Cyrix 486-class CPU. The * bluetrap6() set the magic number to trap_by_rdmsr. */ - setidt(6, bluetrap6, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); + setidt(6, bluetrap6, SDT_SYS386TGT, SEL_KPL, + GSEL(GCODE_SEL, SEL_KPL)); /* * Certain BIOS disables cpuid instruction of Cyrix 6x86MX CPU. * In this case, rdmsr generates general protection fault, and * exception will be trapped by bluetrap13(). */ - setidt(13, bluetrap13, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); + setidt(13, bluetrap13, SDT_SYS386TGT, SEL_KPL, + GSEL(GCODE_SEL, SEL_KPL)); rdmsr(0x1002); /* Cyrix CPU generates fault. */ @@ -938,10 +1093,26 @@ identifycyrix(void) cyrix_did = 0x0010; /* 486S A-step */ else cyrix_did = 0x00ff; /* Old 486SLC/DLC and TI486SXLC/SXL */ - mpintr_unlock(); } +#if 0 +/* Update TSC freq with the value indicated by the caller. */ +static void +tsc_frequency_changed(void *arg, const struct cf_level *level, int status) +{ + /* + * If there was an error during the transition or + * TSC is P-state invariant, don't do anything. + */ + if (status != 0 || tsc_is_invariant) + return; + + /* Total setting for this level gives the new frequency in MHz. */ + hw_clockrate = level->total_set.freq; +} +#endif + /* * Final stage of CPU identification. -- Should I check TI? */ @@ -952,7 +1123,46 @@ finishidentcpu(void) u_char ccr3; u_int regs[4]; - if (strcmp(cpu_vendor, "CyrixInstead") == 0) { + cpu_vendor_id = find_cpu_vendor_id(); + + /* + * Clear "Limit CPUID Maxval" bit and get the largest standard CPUID + * function number again if it is set from BIOS. It is necessary + * for probing correct CPU topology later. + * XXX This is only done on the BSP package. + */ + if (cpu_vendor_id == CPU_VENDOR_INTEL && cpu_high > 0 && cpu_high < 4 && + ((CPUID_TO_FAMILY(cpu_id) == 0xf && CPUID_TO_MODEL(cpu_id) >= 0x3) || + (CPUID_TO_FAMILY(cpu_id) == 0x6 && CPUID_TO_MODEL(cpu_id) >= 0xe))) { + uint64_t msr; + msr = rdmsr(MSR_IA32_MISC_ENABLE); + if ((msr & 0x400000ULL) != 0) { + wrmsr(MSR_IA32_MISC_ENABLE, msr & ~0x400000ULL); + do_cpuid(0, regs); + cpu_high = regs[0]; + } + } + + /* Detect AMD features (PTE no-execute bit, 3dnow, 64 bit mode etc) */ + if (cpu_vendor_id == CPU_VENDOR_INTEL || + cpu_vendor_id == CPU_VENDOR_AMD) { + init_exthigh(); + if (cpu_exthigh >= 0x80000001) { + do_cpuid(0x80000001, regs); + amd_feature = regs[3] & ~(cpu_feature & 0x0183f3ff); + amd_feature2 = regs[2]; + } +#if 0 + if (cpu_exthigh >= 0x80000007) { + do_cpuid(0x80000007, regs); + amd_pminfo = regs[3]; + } +#endif + if (cpu_exthigh >= 0x80000008) { + do_cpuid(0x80000008, regs); + cpu_procinfo2 = regs[2]; + } + } else if (cpu_vendor_id == CPU_VENDOR_CYRIX) { if (cpu == CPU_486) { /* * These conditions are equivalent to: @@ -962,6 +1172,7 @@ finishidentcpu(void) isblue = identblue(); if (isblue == IDENTBLUE_IBMCPU) { strcpy(cpu_vendor, "IBM"); + cpu_vendor_id = CPU_VENDOR_IBM; cpu = CPU_BLUE; return; } @@ -1035,12 +1246,24 @@ finishidentcpu(void) isblue = identblue(); if (isblue == IDENTBLUE_IBMCPU) { strcpy(cpu_vendor, "IBM"); + cpu_vendor_id = CPU_VENDOR_IBM; cpu = CPU_BLUE; return; } } } +static u_int +find_cpu_vendor_id(void) +{ + int i; + + for (i = 0; i < sizeof(cpu_vendors) / sizeof(cpu_vendors[0]); i++) + if (strcmp(cpu_vendor, cpu_vendors[i].vendor) == 0) + return (cpu_vendors[i].vendor_id); + return (0); +} + static void print_AMD_assoc(int i) { @@ -1100,7 +1323,7 @@ print_AMD_info(void) kprintf(", %d bytes/line", regs[3] & 0xff); kprintf(", %d lines/tag", (regs[3] >> 8) & 0xff); print_AMD_assoc((regs[3] >> 16) & 0xff); - if (cpu_exthigh >= 0x80000006) { /* K6-III, or later */ + if (cpu_exthigh >= 0x80000006) { /* K6-III or later */ do_cpuid(0x80000006, regs); /* * Report right L2 cache size on Duron rev. A0. @@ -1108,8 +1331,7 @@ print_AMD_info(void) if ((cpu_id & 0xFF0) == 0x630) kprintf("L2 internal cache: 64 kbytes"); else - kprintf("L2 internal cache: %d kbytes", - regs[2] >> 16); + kprintf("L2 internal cache: %d kbytes", regs[2] >> 16); kprintf(", %d bytes/line", regs[2] & 0xff); kprintf(", %d lines/tag", (regs[2] >> 8) & 0x0f); @@ -1158,232 +1380,228 @@ print_AMD_info(void) (amd_whcr & 0x0100) ? "Enable" : "Disable"); } } -} - -#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) -static void -print_AMD_features(void) -{ - u_int regs[4]; /* - * Values taken from AMD Processor Recognition - * http://www.amd.com/products/cpg/athlon/techdocs/pdf/20734.pdf + * Opteron Rev E shows a bug as in very rare occasions a read memory + * barrier is not performed as expected if it is followed by a + * non-atomic read-modify-write instruction. + * As long as that bug pops up very rarely (intensive machine usage + * on other operating systems generally generates one unexplainable + * crash any 2 months) and as long as a model specific fix would be + * impratical at this stage, print out a warning string if the broken + * model and family are identified. */ - do_cpuid(0x80000001, regs); - kprintf("\n AMD Features=0x%b", regs[3] &~ cpu_feature, - "\020" /* in hex */ - "\001FPU" /* Integral FPU */ - "\002VME" /* Extended VM86 mode support */ - "\003DE" /* Debug extensions */ - "\004PSE" /* 4MByte page tables */ - "\005TSC" /* Timestamp counter */ - "\006MSR" /* Machine specific registers */ - "\007PAE" /* Physical address extension */ - "\010MCE" /* Machine Check support */ - "\011CX8" /* CMPEXCH8 instruction */ - "\012APIC" /* SMP local APIC */ - "\013" - "\014SYSCALL" /* SYSENTER/SYSEXIT instructions */ - "\015MTRR" /* Memory Type Range Registers */ - "\016PGE" /* PG_G (global bit) support */ - "\017MCA" /* Machine Check Architecture */ - "\020ICMOV" /* CMOV instruction */ - "\021PAT" /* Page attributes table */ - "\022PGE36" /* 36 bit address space support */ - "\023RSVD" /* Reserved, unknown */ - "\024MP" /* Multiprocessor Capable */ - "\025NX" /* No-execute page protection */ - "\026" - "\027AMIE" /* AMD MMX Instruction Extensions */ - "\030MMX" - "\031FXSAVE" /* FXSAVE/FXRSTOR */ - "\032" - "\033" - "\034RDTSCP" /* RDTSCP instruction */ - "\035" - "\036LM" /* Long mode */ - "\037DSP" /* AMD 3DNow! Instruction Extensions */ - "\0403DNow!" - ); -} -#endif - -/* - * Transmeta Crusoe LongRun Support by Tamotsu Hattori. - */ - -#define MSR_TMx86_LONGRUN 0x80868010 -#define MSR_TMx86_LONGRUN_FLAGS 0x80868011 - -#define LONGRUN_MODE_MASK(x) ((x) & 0x000000007f) -#define LONGRUN_MODE_RESERVED(x) ((x) & 0xffffff80) -#define LONGRUN_MODE_WRITE(x, y) (LONGRUN_MODE_RESERVED(x) | LONGRUN_MODE_MASK(y)) - -#define LONGRUN_MODE_MINFREQUENCY 0x00 -#define LONGRUN_MODE_ECONOMY 0x01 -#define LONGRUN_MODE_PERFORMANCE 0x02 -#define LONGRUN_MODE_MAXFREQUENCY 0x03 -#define LONGRUN_MODE_UNKNOWN 0x04 -#define LONGRUN_MODE_MAX 0x04 - -union msrinfo { - u_int64_t msr; - u_int32_t regs[2]; -}; - -u_int32_t longrun_modes[LONGRUN_MODE_MAX][3] = { - /* MSR low, MSR high, flags bit0 */ - { 0, 0, 0}, /* LONGRUN_MODE_MINFREQUENCY */ - { 0, 100, 0}, /* LONGRUN_MODE_ECONOMY */ - { 0, 100, 1}, /* LONGRUN_MODE_PERFORMANCE */ - { 100, 100, 1}, /* LONGRUN_MODE_MAXFREQUENCY */ -}; - -static u_int -tmx86_get_longrun_mode(void) -{ - union msrinfo msrinfo; - u_int low, high, flags, mode; - - mpintr_lock(); - - msrinfo.msr = rdmsr(MSR_TMx86_LONGRUN); - low = LONGRUN_MODE_MASK(msrinfo.regs[0]); - high = LONGRUN_MODE_MASK(msrinfo.regs[1]); - flags = rdmsr(MSR_TMx86_LONGRUN_FLAGS) & 0x01; - - for (mode = 0; mode < LONGRUN_MODE_MAX; mode++) { - if (low == longrun_modes[mode][0] && - high == longrun_modes[mode][1] && - flags == longrun_modes[mode][2]) { - goto out; - } - } - mode = LONGRUN_MODE_UNKNOWN; -out: - mpintr_unlock(); - return (mode); -} - -static u_int -tmx86_get_longrun_status(u_int * frequency, u_int * voltage, u_int * percentage) -{ - u_int regs[4]; - - mpintr_lock(); - - do_cpuid(0x80860007, regs); - *frequency = regs[0]; - *voltage = regs[1]; - *percentage = regs[2]; - - mpintr_unlock(); - return (1); + if (CPUID_TO_FAMILY(cpu_id) == 0xf && CPUID_TO_MODEL(cpu_id) >= 0x20 && + CPUID_TO_MODEL(cpu_id) <= 0x3f) + kprintf("WARNING: This architecture revision has known SMP " + "hardware bugs which may cause random instability\n"); } -static u_int -tmx86_set_longrun_mode(u_int mode) +static void +print_INTEL_info(void) { - union msrinfo msrinfo; - - if (mode >= LONGRUN_MODE_UNKNOWN) { - return (0); + u_int regs[4]; + u_int rounds, regnum; + u_int nwaycode, nway; + + if (cpu_high >= 2) { + rounds = 0; + do { + do_cpuid(0x2, regs); + if (rounds == 0 && (rounds = (regs[0] & 0xff)) == 0) + break; /* we have a buggy CPU */ + + for (regnum = 0; regnum <= 3; ++regnum) { + if (regs[regnum] & (1<<31)) + continue; + if (regnum != 0) + print_INTEL_TLB(regs[regnum] & 0xff); + print_INTEL_TLB((regs[regnum] >> 8) & 0xff); + print_INTEL_TLB((regs[regnum] >> 16) & 0xff); + print_INTEL_TLB((regs[regnum] >> 24) & 0xff); + } + } while (--rounds > 0); } - mpintr_lock(); - - /* Write LongRun mode values to Model Specific Register. */ - msrinfo.msr = rdmsr(MSR_TMx86_LONGRUN); - msrinfo.regs[0] = LONGRUN_MODE_WRITE(msrinfo.regs[0], - longrun_modes[mode][0]); - msrinfo.regs[1] = LONGRUN_MODE_WRITE(msrinfo.regs[1], - longrun_modes[mode][1]); - wrmsr(MSR_TMx86_LONGRUN, msrinfo.msr); - - /* Write LongRun mode flags to Model Specific Register. */ - msrinfo.msr = rdmsr(MSR_TMx86_LONGRUN_FLAGS); - msrinfo.regs[0] = (msrinfo.regs[0] & ~0x01) | longrun_modes[mode][2]; - wrmsr(MSR_TMx86_LONGRUN_FLAGS, msrinfo.msr); - - mpintr_unlock(); - return (1); -} - -static u_int crusoe_longrun; -static u_int crusoe_frequency; -static u_int crusoe_voltage; -static u_int crusoe_percentage; -static struct sysctl_ctx_list crusoe_sysctl_ctx; -static struct sysctl_oid *crusoe_sysctl_tree; - -static int -tmx86_longrun_sysctl(SYSCTL_HANDLER_ARGS) -{ - u_int mode; - int error; - - crusoe_longrun = tmx86_get_longrun_mode(); - mode = crusoe_longrun; - error = sysctl_handle_int(oidp, &mode, 0, req); - if (error || !req->newptr) { - return (error); - } - if (mode >= LONGRUN_MODE_UNKNOWN) { - error = EINVAL; - return (error); - } - if (crusoe_longrun != mode) { - crusoe_longrun = mode; - tmx86_set_longrun_mode(crusoe_longrun); + if (cpu_exthigh >= 0x80000006) { + do_cpuid(0x80000006, regs); + nwaycode = (regs[2] >> 12) & 0x0f; + if (nwaycode >= 0x02 && nwaycode <= 0x08) + nway = 1 << (nwaycode / 2); + else + nway = 0; + kprintf("\nL2 cache: %u kbytes, %u-way associative, %u bytes/line", + (regs[2] >> 16) & 0xffff, nway, regs[2] & 0xff); } - return (error); -} - -static int -tmx86_status_sysctl(SYSCTL_HANDLER_ARGS) -{ - u_int val; - int error; - - tmx86_get_longrun_status(&crusoe_frequency, - &crusoe_voltage, &crusoe_percentage); - val = *(u_int *)oidp->oid_arg1; - error = sysctl_handle_int(oidp, &val, 0, req); - return (error); + kprintf("\n"); } static void -setup_tmx86_longrun(void) +print_INTEL_TLB(u_int data) { - static int done = 0; - - if (done) - return; - done++; - - sysctl_ctx_init(&crusoe_sysctl_ctx); - crusoe_sysctl_tree = SYSCTL_ADD_NODE(&crusoe_sysctl_ctx, - SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO, - "crusoe", CTLFLAG_RD, 0, - "Transmeta Crusoe LongRun support"); - SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree), - OID_AUTO, "longrun", CTLTYPE_INT | CTLFLAG_RW, - &crusoe_longrun, 0, tmx86_longrun_sysctl, "I", - "LongRun mode [0-3]"); - SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree), - OID_AUTO, "frequency", CTLTYPE_INT | CTLFLAG_RD, - &crusoe_frequency, 0, tmx86_status_sysctl, "I", - "Current frequency (MHz)"); - SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree), - OID_AUTO, "voltage", CTLTYPE_INT | CTLFLAG_RD, - &crusoe_voltage, 0, tmx86_status_sysctl, "I", - "Current voltage (mV)"); - SYSCTL_ADD_PROC(&crusoe_sysctl_ctx, SYSCTL_CHILDREN(crusoe_sysctl_tree), - OID_AUTO, "percentage", CTLTYPE_INT | CTLFLAG_RD, - &crusoe_percentage, 0, tmx86_status_sysctl, "I", - "Processing performance (%)"); + switch (data) { + case 0x0: + case 0x40: + default: + break; + case 0x1: + kprintf("\nInstruction TLB: 4 KB pages, 4-way set associative, 32 entries"); + break; + case 0x2: + kprintf("\nInstruction TLB: 4 MB pages, fully associative, 2 entries"); + break; + case 0x3: + kprintf("\nData TLB: 4 KB pages, 4-way set associative, 64 entries"); + break; + case 0x4: + kprintf("\nData TLB: 4 MB Pages, 4-way set associative, 8 entries"); + break; + case 0x6: + kprintf("\n1st-level instruction cache: 8 KB, 4-way set associative, 32 byte line size"); + break; + case 0x8: + kprintf("\n1st-level instruction cache: 16 KB, 4-way set associative, 32 byte line size"); + break; + case 0xa: + kprintf("\n1st-level data cache: 8 KB, 2-way set associative, 32 byte line size"); + break; + case 0xc: + kprintf("\n1st-level data cache: 16 KB, 4-way set associative, 32 byte line size"); + break; + case 0x22: + kprintf("\n3rd-level cache: 512 KB, 4-way set associative, sectored cache, 64 byte line size"); + break; + case 0x23: + kprintf("\n3rd-level cache: 1 MB, 8-way set associative, sectored cache, 64 byte line size"); + break; + case 0x25: + kprintf("\n3rd-level cache: 2 MB, 8-way set associative, sectored cache, 64 byte line size"); + break; + case 0x29: + kprintf("\n3rd-level cache: 4 MB, 8-way set associative, sectored cache, 64 byte line size"); + break; + case 0x2c: + kprintf("\n1st-level data cache: 32 KB, 8-way set associative, 64 byte line size"); + break; + case 0x30: + kprintf("\n1st-level instruction cache: 32 KB, 8-way set associative, 64 byte line size"); + break; + case 0x39: + kprintf("\n2nd-level cache: 128 KB, 4-way set associative, sectored cache, 64 byte line size"); + break; + case 0x3b: + kprintf("\n2nd-level cache: 128 KB, 2-way set associative, sectored cache, 64 byte line size"); + break; + case 0x3c: + kprintf("\n2nd-level cache: 256 KB, 4-way set associative, sectored cache, 64 byte line size"); + break; + case 0x41: + kprintf("\n2nd-level cache: 128 KB, 4-way set associative, 32 byte line size"); + break; + case 0x42: + kprintf("\n2nd-level cache: 256 KB, 4-way set associative, 32 byte line size"); + break; + case 0x43: + kprintf("\n2nd-level cache: 512 KB, 4-way set associative, 32 byte line size"); + break; + case 0x44: + kprintf("\n2nd-level cache: 1 MB, 4-way set associative, 32 byte line size"); + break; + case 0x45: + kprintf("\n2nd-level cache: 2 MB, 4-way set associative, 32 byte line size"); + break; + case 0x46: + kprintf("\n3rd-level cache: 4 MB, 4-way set associative, 64 byte line size"); + break; + case 0x47: + kprintf("\n3rd-level cache: 8 MB, 8-way set associative, 64 byte line size"); + break; + case 0x50: + kprintf("\nInstruction TLB: 4 KB, 2 MB or 4 MB pages, fully associative, 64 entries"); + break; + case 0x51: + kprintf("\nInstruction TLB: 4 KB, 2 MB or 4 MB pages, fully associative, 128 entries"); + break; + case 0x52: + kprintf("\nInstruction TLB: 4 KB, 2 MB or 4 MB pages, fully associative, 256 entries"); + break; + case 0x5b: + kprintf("\nData TLB: 4 KB or 4 MB pages, fully associative, 64 entries"); + break; + case 0x5c: + kprintf("\nData TLB: 4 KB or 4 MB pages, fully associative, 128 entries"); + break; + case 0x5d: + kprintf("\nData TLB: 4 KB or 4 MB pages, fully associative, 256 entries"); + break; + case 0x60: + kprintf("\n1st-level data cache: 16 KB, 8-way set associative, sectored cache, 64 byte line size"); + break; + case 0x66: + kprintf("\n1st-level data cache: 8 KB, 4-way set associative, sectored cache, 64 byte line size"); + break; + case 0x67: + kprintf("\n1st-level data cache: 16 KB, 4-way set associative, sectored cache, 64 byte line size"); + break; + case 0x68: + kprintf("\n1st-level data cache: 32 KB, 4 way set associative, sectored cache, 64 byte line size"); + break; + case 0x70: + kprintf("\nTrace cache: 12K-uops, 8-way set associative"); + break; + case 0x71: + kprintf("\nTrace cache: 16K-uops, 8-way set associative"); + break; + case 0x72: + kprintf("\nTrace cache: 32K-uops, 8-way set associative"); + break; + case 0x78: + kprintf("\n2nd-level cache: 1 MB, 4-way set associative, 64-byte line size"); + break; + case 0x79: + kprintf("\n2nd-level cache: 128 KB, 8-way set associative, sectored cache, 64 byte line size"); + break; + case 0x7a: + kprintf("\n2nd-level cache: 256 KB, 8-way set associative, sectored cache, 64 byte line size"); + break; + case 0x7b: + kprintf("\n2nd-level cache: 512 KB, 8-way set associative, sectored cache, 64 byte line size"); + break; + case 0x7c: + kprintf("\n2nd-level cache: 1 MB, 8-way set associative, sectored cache, 64 byte line size"); + break; + case 0x7d: + kprintf("\n2nd-level cache: 2-MB, 8-way set associative, 64-byte line size"); + break; + case 0x7f: + kprintf("\n2nd-level cache: 512-KB, 2-way set associative, 64-byte line size"); + break; + case 0x82: + kprintf("\n2nd-level cache: 256 KB, 8-way set associative, 32 byte line size"); + break; + case 0x83: + kprintf("\n2nd-level cache: 512 KB, 8-way set associative, 32 byte line size"); + break; + case 0x84: + kprintf("\n2nd-level cache: 1 MB, 8-way set associative, 32 byte line size"); + break; + case 0x85: + kprintf("\n2nd-level cache: 2 MB, 8-way set associative, 32 byte line size"); + break; + case 0x86: + kprintf("\n2nd-level cache: 512 KB, 4-way set associative, 64 byte line size"); + break; + case 0x87: + kprintf("\n2nd-level cache: 1 MB, 8-way set associative, 64 byte line size"); + break; + case 0xb0: + kprintf("\nInstruction TLB: 4 KB Pages, 4-way set associative, 128 entries"); + break; + case 0xb3: + kprintf("\nData TLB: 4 KB Pages, 4-way set associative, 128 entries"); + break; + } } static void @@ -1419,12 +1637,6 @@ print_transmeta_info(void) info[64] = 0; kprintf(" %s\n", info); } - - crusoe_longrun = tmx86_get_longrun_mode(); - tmx86_get_longrun_status(&crusoe_frequency, - &crusoe_voltage, &crusoe_percentage); - kprintf(" LongRun mode: %d <%dMHz %dmV %d%%>\n", crusoe_longrun, - crusoe_frequency, crusoe_voltage, crusoe_percentage); } static void @@ -1471,4 +1683,3 @@ additional_cpu_info(const char *line) ++additional_cpu_info_count; } } - diff --git a/sys/platform/pc32/i386/initcpu.c b/sys/platform/pc32/i386/initcpu.c index 7ddc65f91e..1f96085a42 100644 --- a/sys/platform/pc32/i386/initcpu.c +++ b/sys/platform/pc32/i386/initcpu.c @@ -69,8 +69,21 @@ static int hw_instruction_sse; SYSCTL_INT(_hw, OID_AUTO, instruction_sse, CTLFLAG_RD, &hw_instruction_sse, 0, "SIMD/MMX2 instructions available in CPU"); +/* Must *NOT* be BSS or locore will bzero these after setting them */ +int cpu = 0; /* Are we 386, 386sx, 486, etc? */ +u_int cpu_feature = 0; /* Feature flags */ +u_int cpu_feature2 = 0; /* Feature flags */ +u_int amd_feature = 0; /* AMD feature flags */ +u_int amd_feature2 = 0; /* AMD feature flags */ +u_int amd_pminfo = 0; /* AMD advanced power management info */ u_int via_feature_rng = 0; /* VIA RNG features */ u_int via_feature_xcrypt = 0; /* VIA ACE features */ +u_int cpu_high = 0; /* Highest arg to CPUID */ +u_int cpu_id = 0; /* Stepping ID */ +u_int cpu_procinfo = 0; /* HyperThreading Info / Brand Index / CLFUSH */ +u_int cpu_procinfo2 = 0; /* Multicore info */ +char cpu_vendor[20] = ""; /* CPU Origin code */ +u_int cpu_vendor_id = 0; /* CPU vendor ID */ SYSCTL_UINT(_hw, OID_AUTO, via_feature_rng, CTLFLAG_RD, &via_feature_rng, 0, "VIA C3/C7 RNG feature available in CPU"); @@ -669,7 +682,7 @@ initializecpu(void) init_6x86MX(); break; case CPU_686: - if (strcmp(cpu_vendor, "GenuineIntel") == 0) { + if (cpu_vendor_id == CPU_VENDOR_INTEL) { switch (cpu_id & 0xff0) { case 0x610: init_ppro(); @@ -678,9 +691,9 @@ initializecpu(void) init_mendocino(); break; } - } else if (strcmp(cpu_vendor, "AuthenticAMD") == 0) { + } else if (cpu_vendor_id == CPU_VENDOR_AMD) { init_686_amd(); - } else if (strcmp(cpu_vendor, "CentaurHauls") == 0) { + } else if (cpu_vendor_id == CPU_VENDOR_CENTAUR) { switch (cpu_id & 0xff0) { case 0x690: if ((cpu_id & 0xf) < 3) @@ -863,7 +876,7 @@ DB_SHOW_COMMAND(cyrixreg, cyrixreg) u_char ccr0 = 0, ccr4 = 0, ccr5 = 0, pcr0 = 0; cr0 = rcr0(); - if (strcmp(cpu_vendor,"CyrixInstead") == 0) { + if (cpu_vendor_id == CPU_VENDOR_CYRIX) { eflags = read_eflags(); cpu_disable_intr(); diff --git a/sys/platform/pc32/i386/locore.s b/sys/platform/pc32/i386/locore.s index c92ec6ffb0..d550de1f94 100644 --- a/sys/platform/pc32/i386/locore.s +++ b/sys/platform/pc32/i386/locore.s @@ -100,18 +100,8 @@ .space 0x2000 /* space for tmpstk - temporary stack */ .tmpstk: - .globl boothowto,bootdev - - .globl cpu,cpu_vendor,cpu_id,bootinfo - .globl cpu_high, cpu_feature, cpu_feature2, cpu_procinfo - -cpu: .long 0 /* are we 386, 386sx, or 486 */ -cpu_id: .long 0 /* stepping ID */ -cpu_high: .long 0 /* highest arg to CPUID */ -cpu_feature: .long 0 /* features */ -cpu_feature2: .long 0 /* additional features */ -cpu_procinfo: .long 0 /* brand index / HTT info */ -cpu_vendor: .space 20 /* CPU origin code */ + .globl boothowto,bootdev,bootinfo + bootinfo: .space BOOTINFO_SIZE /* bootinfo buffer space */ KERNend: .long 0 /* phys addr end of kernel (just after bss) */ diff --git a/sys/platform/pc32/i386/mp_machdep.c b/sys/platform/pc32/i386/mp_machdep.c index 67790ed154..84ba12a60a 100644 --- a/sys/platform/pc32/i386/mp_machdep.c +++ b/sys/platform/pc32/i386/mp_machdep.c @@ -53,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -1029,7 +1030,7 @@ mptable_hyperthread_fixup(u_int id_mask, int cpu_count) if (lcpus_max <= 1) return 0; - if (strcmp(cpu_vendor, "GenuineIntel") == 0) { + if (cpu_vendor_id == CPU_VENDOR_INTEL) { /* * INSTRUCTION SET REFERENCE, A-M (#253666) * Page 3-181, Table 3-20 diff --git a/sys/platform/pc32/include/md_var.h b/sys/platform/pc32/include/md_var.h index 07b936f83f..52c27e1122 100644 --- a/sys/platform/pc32/include/md_var.h +++ b/sys/platform/pc32/include/md_var.h @@ -52,13 +52,17 @@ extern int (*copyout_vector) (const void *kaddr, void *udaddr, size_t len); extern void (*cpu_idle_hook)(void); extern u_int cpu_exthigh; +extern u_int amd_feature; +extern u_int amd_feature2; extern u_int via_feature_rng; extern u_int via_feature_xcrypt; extern u_int cpu_fxsr; extern u_int cpu_high; extern u_int cpu_id; extern u_int cpu_procinfo; +extern u_int cpu_procinfo2; extern char cpu_vendor[]; +extern u_int cpu_vendor_id; extern u_int cyrix_did; extern char kstack[]; extern char sigcode[]; -- 2.41.0