Index: releng/6.1/sys/amd64/amd64/identcpu.c =================================================================== --- releng/6.1/sys/amd64/amd64/identcpu.c (nonexistent) +++ releng/6.1/sys/amd64/amd64/identcpu.c (revision 155951) @@ -0,0 +1,462 @@ +/*- + * Copyright (c) 1992 Terrence R. Lambert. + * Copyright (c) 1982, 1987, 1990 The Regents of the University of California. + * Copyright (c) 1997 KATO Takenori. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Id: machdep.c,v 1.193 1996/06/18 01:22:04 bde Exp + */ + +#include +__FBSDID("$FreeBSD$"); + +#include "opt_cpu.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* XXX - should be in header file: */ +void printcpuinfo(void); +void identify_cpu(void); +void earlysetcpuclass(void); +void panicifcpuunsupported(void); + +static void print_AMD_info(void); +static void print_AMD_assoc(int i); + +int cpu_class; +char machine[] = "amd64"; +SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, + machine, 0, "Machine class"); + +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]; + +static struct { + char *cpu_name; + int cpu_class; +} amd64_cpus[] = { + { "Clawhammer", CPUCLASS_K8 }, /* CPU_CLAWHAMMER */ + { "Sledgehammer", CPUCLASS_K8 }, /* CPU_SLEDGEHAMMER */ +}; + +void +printcpuinfo(void) +{ + u_int regs[4], i; + char *brand; + + cpu_class = amd64_cpus[cpu].cpu_class; + printf("CPU: "); + strncpy(cpu_model, amd64_cpus[cpu].cpu_name, sizeof (cpu_model)); + + /* Check for extended CPUID information and a processor name. */ + 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) { + /* Please make up your mind folks! */ + strcat(cpu_model, "EM64T"); + } else if (strcmp(cpu_vendor, "AuthenticAMD") == 0) { + /* + * Values taken from AMD Processor Recognition + * http://www.amd.com/K6/k6docs/pdf/20734g.pdf + * (also describes ``Features'' encodings. + */ + strcpy(cpu_model, "AMD "); + switch (cpu_id & 0xF00) { + case 0xf00: + strcat(cpu_model, "AMD64 Processor"); + break; + default: + strcat(cpu_model, "Unknown"); + break; + } + } + + /* + * Replace cpu_model with cpu_brand minus leading spaces if + * we have one. + */ + brand = cpu_brand; + while (*brand == ' ') + ++brand; + if (*brand != '\0') + strcpy(cpu_model, brand); + + printf("%s (", cpu_model); + switch(cpu_class) { + case CPUCLASS_K8: + hw_clockrate = (tsc_freq + 5000) / 1000000; + printf("%jd.%02d-MHz ", + (intmax_t)(tsc_freq + 4999) / 1000000, + (u_int)((tsc_freq + 4999) / 10000) % 100); + printf("K8"); + break; + default: + printf("Unknown"); /* will panic below... */ + } + printf("-class CPU)\n"); + if(*cpu_vendor) + printf(" Origin = \"%s\"",cpu_vendor); + if(cpu_id) + printf(" Id = 0x%x", cpu_id); + + if (strcmp(cpu_vendor, "GenuineIntel") == 0 || + strcmp(cpu_vendor, "AuthenticAMD") == 0) { + printf(" Stepping = %u", cpu_id & 0xf); + if (cpu_high > 0) { + /* + * Here we should probably set up flags indicating + * whether or not various features are available. + * The interesting ones are probably VME, PSE, PAE, + * and PGE. The code already assumes without bothering + * to check that all CPUs >= Pentium have a TSC and + * MSRs. + */ + printf("\n Features=0x%b", cpu_feature, + "\020" + "\001FPU" /* Integral FPU */ + "\002VME" /* Extended VM86 mode support */ + "\003DE" /* Debugging Extensions (CR4.DE) */ + "\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 */ + "\013oldMTRR" /* Previous implementation of MTRR */ + "\014SEP" /* Fast System Call */ + "\015MTRR" /* Memory Type Range Registers */ + "\016PGE" /* PG_G (global bit) support */ + "\017MCA" /* Machine Check Architecture */ + "\020CMOV" /* CMOV instruction */ + "\021PAT" /* Page attributes table */ + "\022PSE36" /* 36 bit address space support */ + "\023PN" /* Processor Serial number */ + "\024CLFLUSH" /* Has the CLFLUSH instruction */ + "\025" + "\026DTS" /* Debug Trace Store */ + "\027ACPI" /* ACPI support */ + "\030MMX" /* MMX instructions */ + "\031FXSR" /* FXSAVE/FXRSTOR */ + "\032SSE" /* Streaming SIMD Extensions */ + "\033SSE2" /* Streaming SIMD Extensions #2 */ + "\034SS" /* Self snoop */ + "\035HTT" /* Hyperthreading (see EBX bit 16-23) */ + "\036TM" /* Thermal Monitor clock slowdown */ + "\037IA64" /* CPU can execute IA64 instructions */ + "\040PBE" /* Pending Break Enable */ + ); + + if (cpu_feature2 != 0) { + printf("\n Features2=0x%b", cpu_feature2, + "\020" + "\001SSE3" /* SSE3 */ + "\002" + "\003RSVD2" /* "Reserved" bit 2 */ + "\004MON" /* MONITOR/MWAIT Instructions */ + "\005DS_CPL" /* CPL Qualified Debug Store */ + "\006VMX" /* Virtual Machine Extensions */ + "\007" + "\010EST" /* Enhanced SpeedStep */ + "\011TM2" /* Thermal Monitor 2 */ + "\012" + "\013CNTX-ID" /* L1 context ID available */ + "\014" + "\015" + "\016CX16" /* CMPXCHG16B Instruction */ + "\017" + "\020" + "\021" + "\022" + "\023" + "\024" + "\025" + "\026" + "\027" + "\030" + "\031" + "\032" + "\033" + "\034" + "\035" + "\036" + "\037" + "\040" + ); + } + if (amd_feature != 0) { + printf("\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 */ + "\032" /* Undefined */ + "\033" /* Undefined */ + "\034" /* Undefined */ + "\035" /* Undefined */ + "\036LM" /* 64 bit long mode */ + "\0373DNow+" /* AMD 3DNow! Extensions */ + "\0403DNow" /* AMD 3DNow! */ + ); + } + + if (cpu_feature & CPUID_HTT && strcmp(cpu_vendor, + "AuthenticAMD") == 0) { + cpu_feature &= ~CPUID_HTT; + if (bootverbose) + printf("\n HTT bit cleared - FreeBSD" + " does not have licenseing issues" + " requiring it.\n"); + } + + /* + * If this CPU supports hyperthreading then mention + * the number of logical CPU's it contains. + */ + if (cpu_feature & CPUID_HTT && + (cpu_procinfo & CPUID_HTT_CORES) >> 16 > 1) + printf("\n Hyperthreading: %d logical CPUs", + (cpu_procinfo & CPUID_HTT_CORES) >> 16); + } + } + /* Avoid ugly blank lines: only print newline when we have to. */ + if (*cpu_vendor || cpu_id) + printf("\n"); + + if (!bootverbose) + return; + + if (strcmp(cpu_vendor, "AuthenticAMD") == 0) + print_AMD_info(); +} + +void +panicifcpuunsupported(void) +{ + +#ifndef HAMMER +#error "You need to specify a cpu type" +#endif + /* + * Now that we have told the user what they have, + * let them know if that machine type isn't configured. + */ + switch (cpu_class) { + case CPUCLASS_X86: +#ifndef HAMMER + case CPUCLASS_K8: +#endif + panic("CPU class not configured"); + default: + break; + } +} + + +/* + * Final stage of CPU identification. -- Should I check TI? + */ +void +identify_cpu(void) +{ + u_int regs[4]; + + do_cpuid(0, regs); + cpu_high = regs[0]; + ((u_int *)&cpu_vendor)[0] = regs[1]; + ((u_int *)&cpu_vendor)[1] = regs[3]; + ((u_int *)&cpu_vendor)[2] = regs[2]; + cpu_vendor[12] = '\0'; + + do_cpuid(1, regs); + cpu_id = regs[0]; + cpu_procinfo = regs[1]; + cpu_feature = regs[3]; + cpu_feature2 = regs[2]; + + if (strcmp(cpu_vendor, "GenuineIntel") == 0 || + strcmp(cpu_vendor, "AuthenticAMD") == 0) { + do_cpuid(0x80000000, regs); + cpu_exthigh = regs[0]; + } + if (cpu_exthigh >= 0x80000001) { + do_cpuid(0x80000001, regs); + amd_feature = regs[3] & ~(cpu_feature & 0x0183f3ff); + } + + /* XXX */ + cpu = CPU_CLAWHAMMER; +} + +static void +print_AMD_assoc(int i) +{ + if (i == 255) + printf(", fully associative\n"); + else + printf(", %d-way associative\n", i); +} + +static void +print_AMD_l2_assoc(int i) +{ + switch (i & 0x0f) { + case 0: printf(", disabled/not present\n"); break; + case 1: printf(", direct mapped\n"); break; + case 2: printf(", 2-way associative\n"); break; + case 4: printf(", 4-way associative\n"); break; + case 6: printf(", 8-way associative\n"); break; + case 8: printf(", 16-way associative\n"); break; + case 15: printf(", fully associative\n"); break; + default: printf(", reserved configuration\n"); break; + } +} + +static void +print_AMD_info(void) +{ + u_int regs[4]; + + if (cpu_exthigh < 0x80000005) + return; + + do_cpuid(0x80000005, regs); + printf("L1 2MB data TLB: %d entries", (regs[0] >> 16) & 0xff); + print_AMD_assoc(regs[0] >> 24); + + printf("L1 2MB instruction TLB: %d entries", regs[0] & 0xff); + print_AMD_assoc((regs[0] >> 8) & 0xff); + + printf("L1 4KB data TLB: %d entries", (regs[1] >> 16) & 0xff); + print_AMD_assoc(regs[1] >> 24); + + printf("L1 4KB instruction TLB: %d entries", regs[1] & 0xff); + print_AMD_assoc((regs[1] >> 8) & 0xff); + + printf("L1 data cache: %d kbytes", regs[2] >> 24); + printf(", %d bytes/line", regs[2] & 0xff); + printf(", %d lines/tag", (regs[2] >> 8) & 0xff); + print_AMD_assoc((regs[2] >> 16) & 0xff); + + printf("L1 instruction cache: %d kbytes", regs[3] >> 24); + printf(", %d bytes/line", regs[3] & 0xff); + printf(", %d lines/tag", (regs[3] >> 8) & 0xff); + print_AMD_assoc((regs[3] >> 16) & 0xff); + + if (cpu_exthigh >= 0x80000006) { + do_cpuid(0x80000006, regs); + if ((regs[0] >> 16) != 0) { + printf("L2 2MB data TLB: %d entries", + (regs[0] >> 16) & 0xfff); + print_AMD_l2_assoc(regs[0] >> 28); + printf("L2 2MB instruction TLB: %d entries", + regs[0] & 0xfff); + print_AMD_l2_assoc((regs[0] >> 28) & 0xf); + } else { + printf("L2 2MB unified TLB: %d entries", + regs[0] & 0xfff); + print_AMD_l2_assoc((regs[0] >> 28) & 0xf); + } + if ((regs[1] >> 16) != 0) { + printf("L2 4KB data TLB: %d entries", + (regs[1] >> 16) & 0xfff); + print_AMD_l2_assoc(regs[1] >> 28); + + printf("L2 4KB instruction TLB: %d entries", + (regs[1] >> 16) & 0xfff); + print_AMD_l2_assoc((regs[1] >> 28) & 0xf); + } else { + printf("L2 4KB unified TLB: %d entries", + (regs[1] >> 16) & 0xfff); + print_AMD_l2_assoc((regs[1] >> 28) & 0xf); + } + printf("L2 unified cache: %d kbytes", regs[2] >> 16); + printf(", %d bytes/line", regs[2] & 0xff); + printf(", %d lines/tag", (regs[2] >> 8) & 0x0f); + print_AMD_l2_assoc((regs[2] >> 12) & 0x0f); + } +} Property changes on: releng/6.1/sys/amd64/amd64/identcpu.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: releng/6.1/sys/amd64/amd64/initcpu.c =================================================================== --- releng/6.1/sys/amd64/amd64/initcpu.c (nonexistent) +++ releng/6.1/sys/amd64/amd64/initcpu.c (revision 155951) @@ -0,0 +1,79 @@ +/*- + * Copyright (c) KATO Takenori, 1997, 1998. + * + * All rights reserved. Unpublished rights reserved under the copyright + * laws of Japan. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer as + * the first lines of this file unmodified. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include "opt_cpu.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +static int hw_instruction_sse; +SYSCTL_INT(_hw, OID_AUTO, instruction_sse, CTLFLAG_RD, + &hw_instruction_sse, 0, "SIMD/MMX2 instructions available in CPU"); + +int cpu; /* Are we 386, 386sx, 486, etc? */ +u_int cpu_feature; /* Feature flags */ +u_int cpu_feature2; /* Feature flags */ +u_int amd_feature; /* Feature flags */ +u_int cpu_high; /* Highest arg to CPUID */ +u_int cpu_exthigh; /* Highest arg to extended CPUID */ +u_int cpu_id; /* Stepping ID */ +u_int cpu_procinfo; /* HyperThreading Info / Brand Index / CLFUSH */ +char cpu_vendor[20]; /* CPU Origin code */ +u_int cpu_fxsr; /* SSE enabled */ + +/* + * Initialize CPU control registers + */ +void +initializecpu(void) +{ + uint64_t msr; + + if ((cpu_feature & CPUID_XMM) && (cpu_feature & CPUID_FXSR)) { + load_cr4(rcr4() | CR4_FXSR | CR4_XMM); + cpu_fxsr = hw_instruction_sse = 1; + } + if ((amd_feature & AMDID_NX) != 0) { + msr = rdmsr(MSR_EFER) | EFER_NXE; + wrmsr(MSR_EFER, msr); + pg_nx = PG_NX; + } +} Property changes on: releng/6.1/sys/amd64/amd64/initcpu.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: releng/6.1/sys/amd64/include/md_var.h =================================================================== --- releng/6.1/sys/amd64/include/md_var.h (nonexistent) +++ releng/6.1/sys/amd64/include/md_var.h (revision 155951) @@ -0,0 +1,77 @@ +/*- + * Copyright (c) 1995 Bruce D. Evans. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 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. Neither the name of the author nor the names of contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_MD_VAR_H_ +#define _MACHINE_MD_VAR_H_ + +/* + * Miscellaneous machine-dependent declarations. + */ + +extern long Maxmem; +extern u_int basemem; +extern int busdma_swi_pending; +extern u_int cpu_exthigh; +extern u_int cpu_feature; +extern u_int cpu_feature2; +extern u_int amd_feature; +extern u_int cpu_fxsr; +extern u_int cpu_high; +extern u_int cpu_id; +extern u_int cpu_procinfo; +extern char cpu_vendor[]; +extern char kstack[]; +extern char sigcode[]; +extern int szsigcode; + +extern struct pcpu __pcpu[]; + +typedef void alias_for_inthand_t(u_int cs, u_int ef, u_int esp, u_int ss); +struct thread; +struct reg; +struct fpreg; +struct dbreg; + +void busdma_swi(void); +void cpu_setregs(void); +void doreti_iret(void) __asm(__STRING(doreti_iret)); +void doreti_iret_fault(void) __asm(__STRING(doreti_iret_fault)); +void initializecpu(void); +void fillw(int /*u_short*/ pat, void *base, size_t cnt); +void fpstate_drop(struct thread *td); +int is_physical_memory(vm_paddr_t addr); +int isa_nmi(int cd); +void pagecopy(void *from, void *to); +void pagezero(void *addr); +void setidt(int idx, alias_for_inthand_t *func, int typ, int dpl, int ist); +int user_dbreg_trap(void); + +#endif /* !_MACHINE_MD_VAR_H_ */ Property changes on: releng/6.1/sys/amd64/include/md_var.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: releng/6.1/sys/amd64/include/specialreg.h =================================================================== --- releng/6.1/sys/amd64/include/specialreg.h (nonexistent) +++ releng/6.1/sys/amd64/include/specialreg.h (revision 155951) @@ -0,0 +1,360 @@ +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 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. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)specialreg.h 7.1 (Berkeley) 5/9/91 + * $FreeBSD$ + */ + +#ifndef _MACHINE_SPECIALREG_H_ +#define _MACHINE_SPECIALREG_H_ + +/* + * Bits in 386 special registers: + */ +#define CR0_PE 0x00000001 /* Protected mode Enable */ +#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) */ +#define CR0_PG 0x80000000 /* PaGing enable */ + +/* + * Bits in 486 special registers: + */ +#define CR0_NE 0x00000020 /* Numeric Error enable (EX16 vs IRQ13) */ +#define CR0_WP 0x00010000 /* Write Protect (honor page protect in + all modes) */ +#define CR0_AM 0x00040000 /* Alignment Mask (set to enable AC flag) */ +#define CR0_NW 0x20000000 /* Not Write-through */ +#define CR0_CD 0x40000000 /* Cache Disable */ + +/* + * Bits in PPro special registers + */ +#define CR4_VME 0x00000001 /* Virtual 8086 mode extensions */ +#define CR4_PVI 0x00000002 /* Protected-mode virtual interrupts */ +#define CR4_TSD 0x00000004 /* Time stamp disable */ +#define CR4_DE 0x00000008 /* Debugging extensions */ +#define CR4_PSE 0x00000010 /* Page size extensions */ +#define CR4_PAE 0x00000020 /* Physical address extension */ +#define CR4_MCE 0x00000040 /* Machine check enable */ +#define CR4_PGE 0x00000080 /* Page global enable */ +#define CR4_PCE 0x00000100 /* Performance monitoring counter enable */ +#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_SCE 0x000000001 /* System Call Extensions (R/W) */ +#define EFER_LME 0x000000100 /* Long mode enable (R/W) */ +#define EFER_LMA 0x000000400 /* Long mode active (R) */ +#define EFER_NXE 0x000000800 /* PTE No-Execute bit enable (R/W) */ + +/* + * CPUID instruction features register + */ +#define CPUID_FPU 0x00000001 +#define CPUID_VME 0x00000002 +#define CPUID_DE 0x00000004 +#define CPUID_PSE 0x00000008 +#define CPUID_TSC 0x00000010 +#define CPUID_MSR 0x00000020 +#define CPUID_PAE 0x00000040 +#define CPUID_MCE 0x00000080 +#define CPUID_CX8 0x00000100 +#define CPUID_APIC 0x00000200 +#define CPUID_B10 0x00000400 +#define CPUID_SEP 0x00000800 +#define CPUID_MTRR 0x00001000 +#define CPUID_PGE 0x00002000 +#define CPUID_MCA 0x00004000 +#define CPUID_CMOV 0x00008000 +#define CPUID_PAT 0x00010000 +#define CPUID_PSE36 0x00020000 +#define CPUID_PSN 0x00040000 +#define CPUID_CLFSH 0x00080000 +#define CPUID_B20 0x00100000 +#define CPUID_DS 0x00200000 +#define CPUID_ACPI 0x00400000 +#define CPUID_MMX 0x00800000 +#define CPUID_FXSR 0x01000000 +#define CPUID_SSE 0x02000000 +#define CPUID_XMM 0x02000000 +#define CPUID_SSE2 0x04000000 +#define CPUID_SS 0x08000000 +#define CPUID_HTT 0x10000000 +#define CPUID_TM 0x20000000 +#define CPUID_B30 0x40000000 +#define CPUID_PBE 0x80000000 + +#define CPUID2_SSE3 0x00000001 +#define CPUID2_MON 0x00000008 +#define CPUID2_DS_CPL 0x00000010 +#define CPUID2_EST 0x00000080 +#define CPUID2_TM2 0x00000100 +#define CPUID2_CNTXID 0x00000400 +#define CPUID2_CX16 0x00002000 + +/* + * Important bits in the AMD extended cpuid flags + */ +#define AMDID_SYSCALL 0x00000800 +#define AMDID_MP 0x00080000 +#define AMDID_NX 0x00100000 +#define AMDID_LM 0x20000000 + +/* + * CPUID instruction 1 ebx info + */ +#define CPUID_BRAND_INDEX 0x000000ff +#define CPUID_CLFUSH_SIZE 0x0000ff00 +#define CPUID_HTT_CORES 0x00ff0000 +#define CPUID_LOCAL_APIC_ID 0xff000000 + +/* + * 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_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_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_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_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 + +/* + * Constants related to MSR's. + */ +#define APICBASE_RESERVED 0x000006ff +#define APICBASE_BSP 0x00000100 +#define APICBASE_ENABLED 0x00000800 +#define APICBASE_ADDRESS 0xfffff000 + +/* + * Constants related to MTRRs + */ +#define MTRR_N64K 8 /* numbers of fixed-size entries */ +#define MTRR_N16K 16 +#define MTRR_N4K 64 + +/* Performance Control Register (5x86 only). */ +#define PCR0 0x20 +#define PCR0_RSTK 0x01 /* Enables return stack */ +#define PCR0_BTB 0x02 /* Enables branch target buffer */ +#define PCR0_LOOP 0x04 /* Enables loop */ +#define PCR0_AIS 0x08 /* Enables all instrcutions stalled to + serialize pipe. */ +#define PCR0_MLR 0x10 /* Enables reordering of misaligned loads */ +#define PCR0_BTBRT 0x40 /* Enables BTB test register. */ +#define PCR0_LSSER 0x80 /* Disable reorder */ + +/* Device Identification Registers */ +#define DIR0 0xfe +#define DIR1 0xff + +/* + * The following four 3-byte registers control the non-cacheable regions. + * These registers must be written as three separate bytes. + * + * NCRx+0: A31-A24 of starting address + * NCRx+1: A23-A16 of starting address + * NCRx+2: A15-A12 of starting address | NCR_SIZE_xx. + * + * The non-cacheable region's starting address must be aligned to the + * size indicated by the NCR_SIZE_xx field. + */ +#define NCR1 0xc4 +#define NCR2 0xc7 +#define NCR3 0xca +#define NCR4 0xcd + +#define NCR_SIZE_0K 0 +#define NCR_SIZE_4K 1 +#define NCR_SIZE_8K 2 +#define NCR_SIZE_16K 3 +#define NCR_SIZE_32K 4 +#define NCR_SIZE_64K 5 +#define NCR_SIZE_128K 6 +#define NCR_SIZE_256K 7 +#define NCR_SIZE_512K 8 +#define NCR_SIZE_1M 9 +#define NCR_SIZE_2M 10 +#define NCR_SIZE_4M 11 +#define NCR_SIZE_8M 12 +#define NCR_SIZE_16M 13 +#define NCR_SIZE_32M 14 +#define NCR_SIZE_4G 15 + +/* + * The address region registers are used to specify the location and + * size for the eight address regions. + * + * ARRx + 0: A31-A24 of start address + * ARRx + 1: A23-A16 of start address + * ARRx + 2: A15-A12 of start address | ARR_SIZE_xx + */ +#define ARR0 0xc4 +#define ARR1 0xc7 +#define ARR2 0xca +#define ARR3 0xcd +#define ARR4 0xd0 +#define ARR5 0xd3 +#define ARR6 0xd6 +#define ARR7 0xd9 + +#define ARR_SIZE_0K 0 +#define ARR_SIZE_4K 1 +#define ARR_SIZE_8K 2 +#define ARR_SIZE_16K 3 +#define ARR_SIZE_32K 4 +#define ARR_SIZE_64K 5 +#define ARR_SIZE_128K 6 +#define ARR_SIZE_256K 7 +#define ARR_SIZE_512K 8 +#define ARR_SIZE_1M 9 +#define ARR_SIZE_2M 10 +#define ARR_SIZE_4M 11 +#define ARR_SIZE_8M 12 +#define ARR_SIZE_16M 13 +#define ARR_SIZE_32M 14 +#define ARR_SIZE_4G 15 + +/* + * The region control registers specify the attributes associated with + * the ARRx addres regions. + */ +#define RCR0 0xdc +#define RCR1 0xdd +#define RCR2 0xde +#define RCR3 0xdf +#define RCR4 0xe0 +#define RCR5 0xe1 +#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_WL 0x04 /* Weak locking. */ +#define RCR_WG 0x08 /* Write gathering. */ +#define RCR_WT 0x10 /* Write-through. */ +#define RCR_NLB 0x20 /* LBA# pin is not asserted. */ + +/* AMD Write Allocate Top-Of-Memory and Control Register */ +#define AMD_WT_ALLOC_TME 0x40000 /* top-of-memory enable */ +#define AMD_WT_ALLOC_PRE 0x20000 /* programmable range enable */ +#define AMD_WT_ALLOC_FRE 0x10000 /* fixed (A0000-FFFFF) range enable */ + +/* X86-64 MSR's */ +#define MSR_EFER 0xc0000080 /* extended features */ +#define MSR_STAR 0xc0000081 /* legacy mode SYSCALL target/cs/ss */ +#define MSR_LSTAR 0xc0000082 /* long mode SYSCALL target rip */ +#define MSR_CSTAR 0xc0000083 /* compat mode SYSCALL target rip */ +#define MSR_SF_MASK 0xc0000084 /* syscall flags mask */ +#define MSR_FSBASE 0xc0000100 /* base address of the %fs "segment" */ +#define MSR_GSBASE 0xc0000101 /* base address of the %gs "segment" */ +#define MSR_KGSBASE 0xc0000102 /* base address of the kernel %gs */ +#define MSR_PERFEVSEL0 0xc0010000 +#define MSR_PERFEVSEL1 0xc0010001 +#define MSR_PERFEVSEL2 0xc0010002 +#define MSR_PERFEVSEL3 0xc0010003 +#undef MSR_PERFCTR0 +#undef MSR_PERFCTR1 +#define MSR_PERFCTR0 0xc0010004 +#define MSR_PERFCTR1 0xc0010005 +#define MSR_PERFCTR2 0xc0010006 +#define MSR_PERFCTR3 0xc0010007 +#define MSR_SYSCFG 0xc0010010 +#define MSR_IORRBASE0 0xc0010016 +#define MSR_IORRMASK0 0xc0010017 +#define MSR_IORRBASE1 0xc0010018 +#define MSR_IORRMASK1 0xc0010019 +#define MSR_TOP_MEM 0xc001001a /* boundary for ram below 4G */ +#define MSR_TOP_MEM2 0xc001001d /* boundary for ram above 4G */ + +#endif /* !_MACHINE_SPECIALREG_H_ */ Property changes on: releng/6.1/sys/amd64/include/specialreg.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: releng/6.1/sys/i386/i386/identcpu.c =================================================================== --- releng/6.1/sys/i386/i386/identcpu.c (nonexistent) +++ releng/6.1/sys/i386/i386/identcpu.c (revision 155951) @@ -0,0 +1,1186 @@ +/*- + * Copyright (c) 1992 Terrence R. Lambert. + * Copyright (c) 1982, 1987, 1990 The Regents of the University of California. + * Copyright (c) 1997 KATO Takenori. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Id: machdep.c,v 1.193 1996/06/18 01:22:04 bde Exp + */ + +#include +__FBSDID("$FreeBSD$"); + +#include "opt_cpu.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define IDENTBLUE_CYRIX486 0 +#define IDENTBLUE_IBMCPU 1 +#define IDENTBLUE_CYRIXM2 2 + +/* 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); +void enable_K6_2_wt_alloc(void); +#endif +void panicifcpuunsupported(void); + +static void identifycyrix(void); +static void print_AMD_info(void); +static void print_AMD_assoc(int i); +static void print_transmeta_info(void); + +int cpu_class; +u_int cpu_exthigh; /* Highest arg to extended CPUID */ +u_int cyrix_did; /* Device ID of Cyrix CPU */ +char machine[] = "i386"; +SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, + machine, 0, "Machine class"); + +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"); + +#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) +static char cpu_brand[48]; + +#define MAX_BRAND_INDEX 8 + +static const char *cpu_brandtable[MAX_BRAND_INDEX + 1] = { + NULL, /* No brand */ + "Intel Celeron", + "Intel Pentium III", + "Intel Pentium III Xeon", + NULL, + NULL, + NULL, + NULL, + "Intel Pentium 4" +}; +#endif + +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 */ + { "i486SX", CPUCLASS_486 }, /* CPU_486SX */ + { "i486DX", CPUCLASS_486 }, /* CPU_486 */ + { "Pentium", CPUCLASS_586 }, /* CPU_586 */ + { "Cyrix 486", CPUCLASS_486 }, /* CPU_486DLC */ + { "Pentium Pro", CPUCLASS_686 }, /* CPU_686 */ + { "Cyrix 5x86", CPUCLASS_486 }, /* CPU_M1SC */ + { "Cyrix 6x86", CPUCLASS_486 }, /* CPU_M1 */ + { "Blue Lightning", CPUCLASS_486 }, /* CPU_BLUE */ + { "Cyrix 6x86MX", CPUCLASS_686 }, /* CPU_M2 */ + { "NexGen 586", CPUCLASS_386 }, /* CPU_NX586 (XXX) */ + { "Cyrix 486S/DX", CPUCLASS_486 }, /* CPU_CY486DX */ + { "Pentium II", CPUCLASS_686 }, /* CPU_PII */ + { "Pentium III", CPUCLASS_686 }, /* CPU_PIII */ + { "Pentium 4", CPUCLASS_686 }, /* CPU_P4 */ +}; + +#if defined(I586_CPU) && !defined(NO_F00F_HACK) +int has_f00f_bug = 0; /* Initialized so that it can be patched. */ +#endif + +void +printcpuinfo(void) +{ +#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) + u_int regs[4], i; + char *brand; +#endif + + cpu_class = i386_cpus[cpu].cpu_class; + printf("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 || + strcmp(cpu_vendor, "Geode by NSC") == 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); + } + } + } + } + + /* Detect AMD features (PTE no-execute bit, 3dnow, 64 bit mode etc) */ + if (cpu_exthigh >= 0x80000001 && + (strcmp(cpu_vendor, "GenuineIntel") == 0 || + strcmp(cpu_vendor, "AuthenticAMD") == 0)) { + do_cpuid(0x80000001, regs); + amd_feature = regs[3] & ~(cpu_feature & 0x0183f3ff); + } + + if (strcmp(cpu_vendor, "GenuineIntel") == 0) { + if ((cpu_id & 0xf00) > 0x300) { + u_int brand_index; + + cpu_model[0] = '\0'; + + switch (cpu_id & 0x3000) { + case 0x1000: + strcpy(cpu_model, "Overdrive "); + break; + case 0x2000: + strcpy(cpu_model, "Dual "); + break; + } + + switch (cpu_id & 0xf00) { + case 0x400: + strcat(cpu_model, "i486 "); + /* Check the particular flavor of 486 */ + switch (cpu_id & 0xf0) { + case 0x00: + case 0x10: + strcat(cpu_model, "DX"); + break; + case 0x20: + strcat(cpu_model, "SX"); + break; + case 0x30: + strcat(cpu_model, "DX2"); + break; + case 0x40: + strcat(cpu_model, "SL"); + break; + case 0x50: + strcat(cpu_model, "SX2"); + break; + case 0x70: + strcat(cpu_model, + "DX2 Write-Back Enhanced"); + break; + case 0x80: + strcat(cpu_model, "DX4"); + break; + } + break; + case 0x500: + /* Check the particular flavor of 586 */ + strcat(cpu_model, "Pentium"); + switch (cpu_id & 0xf0) { + case 0x00: + strcat(cpu_model, " A-step"); + break; + case 0x10: + strcat(cpu_model, "/P5"); + break; + case 0x20: + strcat(cpu_model, "/P54C"); + break; + case 0x30: + strcat(cpu_model, "/P54T Overdrive"); + break; + case 0x40: + strcat(cpu_model, "/P55C"); + break; + case 0x70: + strcat(cpu_model, "/P54C"); + break; + case 0x80: + strcat(cpu_model, "/P55C (quarter-micron)"); + break; + default: + /* nothing */ + break; + } +#if defined(I586_CPU) && !defined(NO_F00F_HACK) + /* + * XXX - If/when Intel fixes the bug, this + * should also check the version of the + * CPU, not just that it's a Pentium. + */ + has_f00f_bug = 1; +#endif + break; + case 0x600: + /* Check the particular flavor of 686 */ + switch (cpu_id & 0xf0) { + case 0x00: + strcat(cpu_model, "Pentium Pro A-step"); + break; + case 0x10: + strcat(cpu_model, "Pentium Pro"); + break; + case 0x30: + case 0x50: + case 0x60: + strcat(cpu_model, + "Pentium II/Pentium II Xeon/Celeron"); + cpu = CPU_PII; + break; + case 0x70: + case 0x80: + case 0xa0: + case 0xb0: + strcat(cpu_model, + "Pentium III/Pentium III Xeon/Celeron"); + cpu = CPU_PIII; + break; + default: + strcat(cpu_model, "Unknown 80686"); + break; + } + break; + case 0xf00: + strcat(cpu_model, "Pentium 4"); + cpu = CPU_P4; + break; + default: + strcat(cpu_model, "unknown"); + break; + } + + /* + * If we didn't get a brand name from the extended + * CPUID, try to look it up in the brand table. + */ + if (cpu_high > 0 && *cpu_brand == '\0') { + brand_index = cpu_procinfo & CPUID_BRAND_INDEX; + if (brand_index <= MAX_BRAND_INDEX && + cpu_brandtable[brand_index] != NULL) + strcpy(cpu_brand, + cpu_brandtable[brand_index]); + } + } + } else if (strcmp(cpu_vendor, "AuthenticAMD") == 0) { + /* + * Values taken from AMD Processor Recognition + * http://www.amd.com/K6/k6docs/pdf/20734g.pdf + * (also describes ``Features'' encodings. + */ + strcpy(cpu_model, "AMD "); + switch (cpu_id & 0xFF0) { + case 0x410: + strcat(cpu_model, "Standard Am486DX"); + break; + case 0x430: + strcat(cpu_model, "Enhanced Am486DX2 Write-Through"); + break; + case 0x470: + strcat(cpu_model, "Enhanced Am486DX2 Write-Back"); + break; + case 0x480: + strcat(cpu_model, "Enhanced Am486DX4/Am5x86 Write-Through"); + break; + case 0x490: + strcat(cpu_model, "Enhanced Am486DX4/Am5x86 Write-Back"); + break; + case 0x4E0: + strcat(cpu_model, "Am5x86 Write-Through"); + break; + case 0x4F0: + strcat(cpu_model, "Am5x86 Write-Back"); + break; + case 0x500: + strcat(cpu_model, "K5 model 0"); + tsc_is_broken = 1; + break; + case 0x510: + strcat(cpu_model, "K5 model 1"); + break; + case 0x520: + strcat(cpu_model, "K5 PR166 (model 2)"); + break; + case 0x530: + strcat(cpu_model, "K5 PR200 (model 3)"); + break; + case 0x560: + strcat(cpu_model, "K6"); + break; + case 0x570: + strcat(cpu_model, "K6 266 (model 1)"); + break; + case 0x580: + strcat(cpu_model, "K6-2"); + break; + case 0x590: + strcat(cpu_model, "K6-III"); + break; + default: + strcat(cpu_model, "Unknown"); + break; + } +#if defined(I586_CPU) && defined(CPU_WT_ALLOC) + if ((cpu_id & 0xf00) == 0x500) { + if (((cpu_id & 0x0f0) > 0) + && ((cpu_id & 0x0f0) < 0x60) + && ((cpu_id & 0x00f) > 3)) + enable_K5_wt_alloc(); + else if (((cpu_id & 0x0f0) > 0x80) + || (((cpu_id & 0x0f0) == 0x80) + && (cpu_id & 0x00f) > 0x07)) + enable_K6_2_wt_alloc(); + else if ((cpu_id & 0x0f0) > 0x50) + enable_K6_wt_alloc(); + } +#endif + } else if (strcmp(cpu_vendor, "CyrixInstead") == 0) { + strcpy(cpu_model, "Cyrix "); + switch (cpu_id & 0xff0) { + case 0x440: + strcat(cpu_model, "MediaGX"); + break; + case 0x520: + strcat(cpu_model, "6x86"); + break; + case 0x540: + cpu_class = CPUCLASS_586; + strcat(cpu_model, "GXm"); + break; + case 0x600: + strcat(cpu_model, "6x86MX"); + break; + default: + /* + * Even though CPU supports the cpuid + * instruction, it can be disabled. + * Therefore, this routine supports all Cyrix + * CPUs. + */ + switch (cyrix_did & 0xf0) { + case 0x00: + switch (cyrix_did & 0x0f) { + case 0x00: + strcat(cpu_model, "486SLC"); + break; + case 0x01: + strcat(cpu_model, "486DLC"); + break; + case 0x02: + strcat(cpu_model, "486SLC2"); + break; + case 0x03: + strcat(cpu_model, "486DLC2"); + break; + case 0x04: + strcat(cpu_model, "486SRx"); + break; + case 0x05: + strcat(cpu_model, "486DRx"); + break; + case 0x06: + strcat(cpu_model, "486SRx2"); + break; + case 0x07: + strcat(cpu_model, "486DRx2"); + break; + case 0x08: + strcat(cpu_model, "486SRu"); + break; + case 0x09: + strcat(cpu_model, "486DRu"); + break; + case 0x0a: + strcat(cpu_model, "486SRu2"); + break; + case 0x0b: + strcat(cpu_model, "486DRu2"); + break; + default: + strcat(cpu_model, "Unknown"); + break; + } + break; + case 0x10: + switch (cyrix_did & 0x0f) { + case 0x00: + strcat(cpu_model, "486S"); + break; + case 0x01: + strcat(cpu_model, "486S2"); + break; + case 0x02: + strcat(cpu_model, "486Se"); + break; + case 0x03: + strcat(cpu_model, "486S2e"); + break; + case 0x0a: + strcat(cpu_model, "486DX"); + break; + case 0x0b: + strcat(cpu_model, "486DX2"); + break; + case 0x0f: + strcat(cpu_model, "486DX4"); + break; + default: + strcat(cpu_model, "Unknown"); + break; + } + break; + case 0x20: + if ((cyrix_did & 0x0f) < 8) + strcat(cpu_model, "6x86"); /* Where did you get it? */ + else + strcat(cpu_model, "5x86"); + break; + case 0x30: + strcat(cpu_model, "6x86"); + break; + case 0x40: + if ((cyrix_did & 0xf000) == 0x3000) { + cpu_class = CPUCLASS_586; + strcat(cpu_model, "GXm"); + } else + strcat(cpu_model, "MediaGX"); + break; + case 0x50: + strcat(cpu_model, "6x86MX"); + break; + case 0xf0: + switch (cyrix_did & 0x0f) { + case 0x0d: + strcat(cpu_model, "Overdrive CPU"); + break; + case 0x0e: + strcpy(cpu_model, "Texas Instruments 486SXL"); + break; + case 0x0f: + strcat(cpu_model, "486SLC/DLC"); + break; + default: + strcat(cpu_model, "Unknown"); + break; + } + break; + default: + strcat(cpu_model, "Unknown"); + break; + } + break; + } + } else if (strcmp(cpu_vendor, "RiseRiseRise") == 0) { + strcpy(cpu_model, "Rise "); + switch (cpu_id & 0xff0) { + case 0x500: + strcat(cpu_model, "mP6"); + break; + default: + strcat(cpu_model, "Unknown"); + } + } else if (strcmp(cpu_vendor, "CentaurHauls") == 0) { + switch (cpu_id & 0xff0) { + case 0x540: + strcpy(cpu_model, "IDT WinChip C6"); + tsc_is_broken = 1; + break; + case 0x580: + strcpy(cpu_model, "IDT WinChip 2"); + break; + case 0x660: + strcpy(cpu_model, "VIA C3 Samuel"); + break; + case 0x670: + if (cpu_id & 0x8) + strcpy(cpu_model, "VIA C3 Ezra"); + else + strcpy(cpu_model, "VIA C3 Samuel 2"); + break; + case 0x680: + strcpy(cpu_model, "VIA C3 Ezra-T"); + break; + case 0x690: + strcpy(cpu_model, "VIA C3 Nehemiah"); + do_cpuid(0xc0000000, regs); + if (regs[0] == 0xc0000001) { + do_cpuid(0xc0000001, regs); + if ((cpu_id & 0xf) >= 3) + if ((regs[3] & 0x0c) == 0x0c) + strcat(cpu_model, "+RNG"); + if ((cpu_id & 0xf) >= 8) + if ((regs[3] & 0xc0) == 0xc0) + strcat(cpu_model, "+ACE"); + } + break; + default: + strcpy(cpu_model, "VIA/IDT Unknown"); + } + } else if (strcmp(cpu_vendor, "IBM") == 0) { + strcpy(cpu_model, "Blue Lightning CPU"); + } else if (strcmp(cpu_vendor, "Geode by NSC") == 0) { + 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; + } + } + + /* + * Replace cpu_model with cpu_brand minus leading spaces if + * we have one. + */ + brand = cpu_brand; + while (*brand == ' ') + ++brand; + if (*brand != '\0') + strcpy(cpu_model, brand); + +#endif + + printf("%s (", cpu_model); + switch(cpu_class) { + case CPUCLASS_286: + printf("286"); + break; + case CPUCLASS_386: + printf("386"); + break; +#if defined(I486_CPU) + case CPUCLASS_486: + printf("486"); + bzero_vector = i486_bzero; + break; +#endif +#if defined(I586_CPU) + case CPUCLASS_586: + hw_clockrate = (tsc_freq + 5000) / 1000000; + printf("%jd.%02d-MHz ", + (intmax_t)(tsc_freq + 4999) / 1000000, + (u_int)((tsc_freq + 4999) / 10000) % 100); + printf("586"); + break; +#endif +#if defined(I686_CPU) + case CPUCLASS_686: + hw_clockrate = (tsc_freq + 5000) / 1000000; + printf("%jd.%02d-MHz ", + (intmax_t)(tsc_freq + 4999) / 1000000, + (u_int)((tsc_freq + 4999) / 10000) % 100); + printf("686"); + break; +#endif + default: + printf("Unknown"); /* will panic below... */ + } + printf("-class CPU)\n"); +#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) + if(*cpu_vendor) + printf(" Origin = \"%s\"",cpu_vendor); + if(cpu_id) + printf(" Id = 0x%x", cpu_id); + + if (strcmp(cpu_vendor, "GenuineIntel") == 0 || + strcmp(cpu_vendor, "AuthenticAMD") == 0 || + strcmp(cpu_vendor, "GenuineTMx86") == 0 || + strcmp(cpu_vendor, "TransmetaCPU") == 0 || + strcmp(cpu_vendor, "RiseRiseRise") == 0 || + strcmp(cpu_vendor, "CentaurHauls") == 0 || + strcmp(cpu_vendor, "Geode by NSC") == 0 || + ((strcmp(cpu_vendor, "CyrixInstead") == 0) && + ((cpu_id & 0xf00) > 0x500))) { + printf(" Stepping = %u", cpu_id & 0xf); + if (strcmp(cpu_vendor, "CyrixInstead") == 0) + printf(" DIR=0x%04x", cyrix_did); + if (cpu_high > 0) { + /* + * Here we should probably set up flags indicating + * whether or not various features are available. + * The interesting ones are probably VME, PSE, PAE, + * and PGE. The code already assumes without bothering + * to check that all CPUs >= Pentium have a TSC and + * MSRs. + */ + printf("\n Features=0x%b", cpu_feature, + "\020" + "\001FPU" /* Integral FPU */ + "\002VME" /* Extended VM86 mode support */ + "\003DE" /* Debugging Extensions (CR4.DE) */ + "\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 */ + "\013oldMTRR" /* Previous implementation of MTRR */ + "\014SEP" /* Fast System Call */ + "\015MTRR" /* Memory Type Range Registers */ + "\016PGE" /* PG_G (global bit) support */ + "\017MCA" /* Machine Check Architecture */ + "\020CMOV" /* CMOV instruction */ + "\021PAT" /* Page attributes table */ + "\022PSE36" /* 36 bit address space support */ + "\023PN" /* Processor Serial number */ + "\024CLFLUSH" /* Has the CLFLUSH instruction */ + "\025" + "\026DTS" /* Debug Trace Store */ + "\027ACPI" /* ACPI support */ + "\030MMX" /* MMX instructions */ + "\031FXSR" /* FXSAVE/FXRSTOR */ + "\032SSE" /* Streaming SIMD Extensions */ + "\033SSE2" /* Streaming SIMD Extensions #2 */ + "\034SS" /* Self snoop */ + "\035HTT" /* Hyperthreading (see EBX bit 16-23) */ + "\036TM" /* Thermal Monitor clock slowdown */ + "\037IA64" /* CPU can execute IA64 instructions */ + "\040PBE" /* Pending Break Enable */ + ); + + if (cpu_feature2 != 0) { + printf("\n Features2=0x%b", cpu_feature2, + "\020" + "\001SSE3" /* SSE3 */ + "\002" + "\003RSVD2" /* "Reserved" bit 2 */ + "\004MON" /* MONITOR/MWAIT Instructions */ + "\005DS_CPL" /* CPL Qualified Debug Store */ + "\006VMX" /* Virtual Machine Extensions */ + "\007" + "\010EST" /* Enhanced SpeedStep */ + "\011TM2" /* Thermal Monitor 2 */ + "\012" + "\013CNTX-ID" /* L1 context ID available */ + "\014" + "\015" + "\016CX16" /* CMPXCHG16B Instruction */ + "\017" + "\020" + "\021" + "\022" + "\023" + "\024" + "\025" + "\026" + "\027" + "\030" + "\031" + "\032" + "\033" + "\034" + "\035" + "\036" + "\037" + "\040" + ); + } + if (amd_feature != 0) { + printf("\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 */ + "\032" /* Undefined */ + "\033" /* Undefined */ + "\034" /* Undefined */ + "\035" /* Undefined */ + "\036LM" /* 64 bit long mode */ + "\0373DNow+" /* AMD 3DNow! Extensions */ + "\0403DNow" /* AMD 3DNow! */ + ); + } + + if (cpu_feature & CPUID_HTT && strcmp(cpu_vendor, + "AuthenticAMD") == 0) { + cpu_feature &= ~CPUID_HTT; + if (bootverbose) + printf("\n HTT bit cleared - FreeBSD" + " does not have licenseing issues" + " requiring it.\n"); + } + + /* + * If this CPU supports hyperthreading then mention + * the number of logical CPU's it contains. + */ + if (cpu_feature & CPUID_HTT && + (cpu_procinfo & CPUID_HTT_CORES) >> 16 > 1) + printf("\n Hyperthreading: %d logical CPUs", + (cpu_procinfo & CPUID_HTT_CORES) >> 16); + } + } else if (strcmp(cpu_vendor, "CyrixInstead") == 0) { + printf(" DIR=0x%04x", cyrix_did); + printf(" Stepping=%u", (cyrix_did & 0xf000) >> 12); + printf(" Revision=%u", (cyrix_did & 0x0f00) >> 8); +#ifndef CYRIX_CACHE_REALLY_WORKS + if (cpu == CPU_M1 && (cyrix_did & 0xff00) < 0x1700) + printf("\n CPU cache: write-through mode"); +#endif + } + /* Avoid ugly blank lines: only print newline when we have to. */ + if (*cpu_vendor || cpu_id) + printf("\n"); + +#endif + + if (!bootverbose) + return; + + if (strcmp(cpu_vendor, "AuthenticAMD") == 0) + print_AMD_info(); + else if (strcmp(cpu_vendor, "GenuineTMx86") == 0 || + strcmp(cpu_vendor, "TransmetaCPU") == 0) + 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) { + case CPUCLASS_286: /* a 286 should not make it this far, anyway */ + case CPUCLASS_386: +#if !defined(I486_CPU) + case CPUCLASS_486: +#endif +#if !defined(I586_CPU) + case CPUCLASS_586: +#endif +#if !defined(I686_CPU) + case CPUCLASS_686: +#endif + panic("CPU class not configured"); + default: + break; + } +} + + +static volatile u_int trap_by_rdmsr; + +/* + * Special exception 6 handler. + * The rdmsr instruction generates invalid opcodes fault on 486-class + * Cyrix CPU. Stacked eip register points the rdmsr instruction in the + * function identblue() when this handler is called. Stacked eip should + * be advanced. + */ +inthand_t bluetrap6; +#ifdef __GNUCLIKE_ASM +__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\ +"); +#endif + +/* + * Special exception 13 handler. + * Accessing non-existent MSR generates general protection fault. + */ +inthand_t bluetrap13; +#ifdef __GNUCLIKE_ASM +__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\ +"); +#endif + +/* + * Distinguish IBM Blue Lightning CPU from Cyrix CPUs that does not + * support cpuid instruction. This function should be called after + * loading interrupt descriptor table register. + * + * I don't like this method that handles fault, but I couldn't get + * information for any other methods. Does blue giant know? + */ +static int +identblue(void) +{ + + trap_by_rdmsr = 0; + + /* + * Cyrix 486-class CPU does not support rdmsr instruction. + * The rdmsr instruction generates invalid opcode fault, and exception + * will be trapped by bluetrap6() on Cyrix 486-class CPU. The + * bluetrap6() set the magic number to trap_by_rdmsr. + */ + setidt(IDT_UD, 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(IDT_GP, bluetrap13, SDT_SYS386TGT, SEL_KPL, + GSEL(GCODE_SEL, SEL_KPL)); + + rdmsr(0x1002); /* Cyrix CPU generates fault. */ + + if (trap_by_rdmsr == 0xa8c1d) + return IDENTBLUE_CYRIX486; + else if (trap_by_rdmsr == 0xa89c4) + return IDENTBLUE_CYRIXM2; + return IDENTBLUE_IBMCPU; +} + + +/* + * identifycyrix() set lower 16 bits of cyrix_did as follows: + * + * F E D C B A 9 8 7 6 5 4 3 2 1 0 + * +-------+-------+---------------+ + * | SID | RID | Device ID | + * | (DIR 1) | (DIR 0) | + * +-------+-------+---------------+ + */ +static void +identifycyrix(void) +{ + u_int eflags; + int ccr2_test = 0, dir_test = 0; + u_char ccr2, ccr3; + + eflags = read_eflags(); + disable_intr(); + + ccr2 = read_cyrix_reg(CCR2); + write_cyrix_reg(CCR2, ccr2 ^ CCR2_LOCK_NW); + read_cyrix_reg(CCR2); + if (read_cyrix_reg(CCR2) != ccr2) + ccr2_test = 1; + write_cyrix_reg(CCR2, ccr2); + + ccr3 = read_cyrix_reg(CCR3); + write_cyrix_reg(CCR3, ccr3 ^ CCR3_MAPEN3); + read_cyrix_reg(CCR3); + if (read_cyrix_reg(CCR3) != ccr3) + dir_test = 1; /* CPU supports DIRs. */ + write_cyrix_reg(CCR3, ccr3); + + if (dir_test) { + /* Device ID registers are available. */ + cyrix_did = read_cyrix_reg(DIR1) << 8; + cyrix_did += read_cyrix_reg(DIR0); + } else if (ccr2_test) + cyrix_did = 0x0010; /* 486S A-step */ + else + cyrix_did = 0x00ff; /* Old 486SLC/DLC and TI486SXLC/SXL */ + + write_eflags(eflags); +} + +/* + * Final stage of CPU identification. -- Should I check TI? + */ +void +finishidentcpu(void) +{ + int isblue = 0; + u_char ccr3; + u_int regs[4]; + + if (strcmp(cpu_vendor, "CyrixInstead") == 0) { + if (cpu == CPU_486) { + /* + * These conditions are equivalent to: + * - CPU does not support cpuid instruction. + * - Cyrix/IBM CPU is detected. + */ + isblue = identblue(); + if (isblue == IDENTBLUE_IBMCPU) { + strcpy(cpu_vendor, "IBM"); + cpu = CPU_BLUE; + return; + } + } + switch (cpu_id & 0xf00) { + case 0x600: + /* + * Cyrix's datasheet does not describe DIRs. + * Therefor, I assume it does not have them + * and use the result of the cpuid instruction. + * XXX they seem to have it for now at least. -Peter + */ + identifycyrix(); + cpu = CPU_M2; + break; + default: + identifycyrix(); + /* + * This routine contains a trick. + * Don't check (cpu_id & 0x00f0) == 0x50 to detect M2, now. + */ + switch (cyrix_did & 0x00f0) { + case 0x00: + case 0xf0: + cpu = CPU_486DLC; + break; + case 0x10: + cpu = CPU_CY486DX; + break; + case 0x20: + if ((cyrix_did & 0x000f) < 8) + cpu = CPU_M1; + else + cpu = CPU_M1SC; + break; + case 0x30: + cpu = CPU_M1; + break; + case 0x40: + /* MediaGX CPU */ + cpu = CPU_M1SC; + break; + default: + /* M2 and later CPUs are treated as M2. */ + cpu = CPU_M2; + + /* + * enable cpuid instruction. + */ + ccr3 = read_cyrix_reg(CCR3); + write_cyrix_reg(CCR3, CCR3_MAPEN0); + write_cyrix_reg(CCR4, read_cyrix_reg(CCR4) | CCR4_CPUID); + write_cyrix_reg(CCR3, ccr3); + + do_cpuid(0, regs); + cpu_high = regs[0]; /* eax */ + do_cpuid(1, regs); + cpu_id = regs[0]; /* eax */ + cpu_feature = regs[3]; /* edx */ + break; + } + } + } else if (cpu == CPU_486 && *cpu_vendor == '\0') { + /* + * There are BlueLightning CPUs that do not change + * undefined flags by dividing 5 by 2. In this case, + * the CPU identification routine in locore.s leaves + * cpu_vendor null string and puts CPU_486 into the + * cpu. + */ + isblue = identblue(); + if (isblue == IDENTBLUE_IBMCPU) { + strcpy(cpu_vendor, "IBM"); + cpu = CPU_BLUE; + return; + } + } +} + +static void +print_AMD_assoc(int i) +{ + if (i == 255) + printf(", fully associative\n"); + else + printf(", %d-way associative\n", i); +} + +static void +print_AMD_info(void) +{ + quad_t amd_whcr; + + if (cpu_exthigh >= 0x80000005) { + u_int regs[4]; + + do_cpuid(0x80000005, regs); + printf("Data TLB: %d entries", (regs[1] >> 16) & 0xff); + print_AMD_assoc(regs[1] >> 24); + printf("Instruction TLB: %d entries", regs[1] & 0xff); + print_AMD_assoc((regs[1] >> 8) & 0xff); + printf("L1 data cache: %d kbytes", regs[2] >> 24); + printf(", %d bytes/line", regs[2] & 0xff); + printf(", %d lines/tag", (regs[2] >> 8) & 0xff); + print_AMD_assoc((regs[2] >> 16) & 0xff); + printf("L1 instruction cache: %d kbytes", regs[3] >> 24); + printf(", %d bytes/line", regs[3] & 0xff); + printf(", %d lines/tag", (regs[3] >> 8) & 0xff); + print_AMD_assoc((regs[3] >> 16) & 0xff); + if (cpu_exthigh >= 0x80000006) { /* K6-III only */ + do_cpuid(0x80000006, regs); + printf("L2 internal cache: %d kbytes", regs[2] >> 16); + printf(", %d bytes/line", regs[2] & 0xff); + printf(", %d lines/tag", (regs[2] >> 8) & 0x0f); + print_AMD_assoc((regs[2] >> 12) & 0x0f); + } + } + if (((cpu_id & 0xf00) == 0x500) + && (((cpu_id & 0x0f0) > 0x80) + || (((cpu_id & 0x0f0) == 0x80) + && (cpu_id & 0x00f) > 0x07))) { + /* K6-2(new core [Stepping 8-F]), K6-III or later */ + amd_whcr = rdmsr(0xc0000082); + if (!(amd_whcr & (0x3ff << 22))) { + printf("Write Allocate Disable\n"); + } else { + printf("Write Allocate Enable Limit: %dM bytes\n", + (u_int32_t)((amd_whcr & (0x3ff << 22)) >> 22) * 4); + printf("Write Allocate 15-16M bytes: %s\n", + (amd_whcr & (1 << 16)) ? "Enable" : "Disable"); + } + } else if (((cpu_id & 0xf00) == 0x500) + && ((cpu_id & 0x0f0) > 0x50)) { + /* K6, K6-2(old core) */ + amd_whcr = rdmsr(0xc0000082); + if (!(amd_whcr & (0x7f << 1))) { + printf("Write Allocate Disable\n"); + } else { + printf("Write Allocate Enable Limit: %dM bytes\n", + (u_int32_t)((amd_whcr & (0x7f << 1)) >> 1) * 4); + printf("Write Allocate 15-16M bytes: %s\n", + (amd_whcr & 0x0001) ? "Enable" : "Disable"); + printf("Hardware Write Allocate Control: %s\n", + (amd_whcr & 0x0100) ? "Enable" : "Disable"); + } + } +} + +static void +print_transmeta_info() +{ + u_int regs[4], nreg = 0; + + do_cpuid(0x80860000, regs); + nreg = regs[0]; + if (nreg >= 0x80860001) { + do_cpuid(0x80860001, regs); + printf(" Processor revision %u.%u.%u.%u\n", + (regs[1] >> 24) & 0xff, + (regs[1] >> 16) & 0xff, + (regs[1] >> 8) & 0xff, + regs[1] & 0xff); + } + if (nreg >= 0x80860002) { + do_cpuid(0x80860002, regs); + printf(" Code Morphing Software revision %u.%u.%u-%u-%u\n", + (regs[1] >> 24) & 0xff, + (regs[1] >> 16) & 0xff, + (regs[1] >> 8) & 0xff, + regs[1] & 0xff, + regs[2]); + } + if (nreg >= 0x80860006) { + char info[65]; + do_cpuid(0x80860003, (u_int*) &info[0]); + do_cpuid(0x80860004, (u_int*) &info[16]); + do_cpuid(0x80860005, (u_int*) &info[32]); + do_cpuid(0x80860006, (u_int*) &info[48]); + info[64] = 0; + printf(" %s\n", info); + } +} Property changes on: releng/6.1/sys/i386/i386/identcpu.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: releng/6.1/sys/i386/i386/initcpu.c =================================================================== --- releng/6.1/sys/i386/i386/initcpu.c (nonexistent) +++ releng/6.1/sys/i386/i386/initcpu.c (revision 155951) @@ -0,0 +1,880 @@ +/*- + * Copyright (c) KATO Takenori, 1997, 1998. + * + * All rights reserved. Unpublished rights reserved under the copyright + * laws of Japan. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer as + * the first lines of this file unmodified. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include "opt_cpu.h" + +#include +#include +#include +#include + +#include +#include +#include + +#if !defined(CPU_DISABLE_SSE) && defined(I686_CPU) +#define CPU_ENABLE_SSE +#endif + +void initializecpu(void); +#if defined(I586_CPU) && defined(CPU_WT_ALLOC) +void enable_K5_wt_alloc(void); +void enable_K6_wt_alloc(void); +void enable_K6_2_wt_alloc(void); +#endif + +#ifdef I486_CPU +static void init_5x86(void); +static void init_bluelightning(void); +static void init_486dlc(void); +static void init_cy486dx(void); +#ifdef CPU_I486_ON_386 +static void init_i486_on_386(void); +#endif +static void init_6x86(void); +#endif /* I486_CPU */ + +#ifdef I686_CPU +static void init_6x86MX(void); +static void init_ppro(void); +static void init_mendocino(void); +#endif + +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; /* Feature flags */ +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 */ +char cpu_vendor[20] = ""; /* CPU Origin code */ + +#ifdef CPU_ENABLE_SSE +u_int cpu_fxsr; /* SSE enabled */ +#endif + +#ifdef I486_CPU +/* + * IBM Blue Lightning + */ +static void +init_bluelightning(void) +{ + u_long eflags; + +#if defined(PC98) && !defined(CPU_UPGRADE_HW_CACHE) + need_post_dma_flush = 1; +#endif + + eflags = read_eflags(); + disable_intr(); + + load_cr0(rcr0() | CR0_CD | CR0_NW); + invd(); + +#ifdef CPU_BLUELIGHTNING_FPU_OP_CACHE + wrmsr(0x1000, 0x9c92LL); /* FP operand can be cacheable on Cyrix FPU */ +#else + wrmsr(0x1000, 0x1c92LL); /* Intel FPU */ +#endif + /* Enables 13MB and 0-640KB cache. */ + wrmsr(0x1001, (0xd0LL << 32) | 0x3ff); +#ifdef CPU_BLUELIGHTNING_3X + wrmsr(0x1002, 0x04000000LL); /* Enables triple-clock mode. */ +#else + wrmsr(0x1002, 0x03000000LL); /* Enables double-clock mode. */ +#endif + + /* Enable caching in CR0. */ + load_cr0(rcr0() & ~(CR0_CD | CR0_NW)); /* CD = 0 and NW = 0 */ + invd(); + write_eflags(eflags); +} + +/* + * Cyrix 486SLC/DLC/SR/DR series + */ +static void +init_486dlc(void) +{ + u_long eflags; + u_char ccr0; + + eflags = read_eflags(); + disable_intr(); + invd(); + + ccr0 = read_cyrix_reg(CCR0); +#ifndef CYRIX_CACHE_WORKS + ccr0 |= CCR0_NC1 | CCR0_BARB; + write_cyrix_reg(CCR0, ccr0); + invd(); +#else + ccr0 &= ~CCR0_NC0; +#ifndef CYRIX_CACHE_REALLY_WORKS + ccr0 |= CCR0_NC1 | CCR0_BARB; +#else + ccr0 |= CCR0_NC1; +#endif +#ifdef CPU_DIRECT_MAPPED_CACHE + ccr0 |= CCR0_CO; /* Direct mapped mode. */ +#endif + write_cyrix_reg(CCR0, ccr0); + + /* Clear non-cacheable region. */ + write_cyrix_reg(NCR1+2, NCR_SIZE_0K); + write_cyrix_reg(NCR2+2, NCR_SIZE_0K); + write_cyrix_reg(NCR3+2, NCR_SIZE_0K); + write_cyrix_reg(NCR4+2, NCR_SIZE_0K); + + write_cyrix_reg(0, 0); /* dummy write */ + + /* Enable caching in CR0. */ + load_cr0(rcr0() & ~(CR0_CD | CR0_NW)); /* CD = 0 and NW = 0 */ + invd(); +#endif /* !CYRIX_CACHE_WORKS */ + write_eflags(eflags); +} + + +/* + * Cyrix 486S/DX series + */ +static void +init_cy486dx(void) +{ + u_long eflags; + u_char ccr2; + + eflags = read_eflags(); + disable_intr(); + invd(); + + ccr2 = read_cyrix_reg(CCR2); +#ifdef CPU_SUSP_HLT + ccr2 |= CCR2_SUSP_HLT; +#endif + +#ifdef PC98 + /* Enables WB cache interface pin and Lock NW bit in CR0. */ + ccr2 |= CCR2_WB | CCR2_LOCK_NW; + /* Unlock NW bit in CR0. */ + write_cyrix_reg(CCR2, ccr2 & ~CCR2_LOCK_NW); + load_cr0((rcr0() & ~CR0_CD) | CR0_NW); /* CD = 0, NW = 1 */ +#endif + + write_cyrix_reg(CCR2, ccr2); + write_eflags(eflags); +} + + +/* + * Cyrix 5x86 + */ +static void +init_5x86(void) +{ + u_long eflags; + u_char ccr2, ccr3, ccr4, pcr0; + + eflags = read_eflags(); + disable_intr(); + + load_cr0(rcr0() | CR0_CD | CR0_NW); + wbinvd(); + + (void)read_cyrix_reg(CCR3); /* dummy */ + + /* Initialize CCR2. */ + ccr2 = read_cyrix_reg(CCR2); + ccr2 |= CCR2_WB; +#ifdef CPU_SUSP_HLT + ccr2 |= CCR2_SUSP_HLT; +#else + ccr2 &= ~CCR2_SUSP_HLT; +#endif + ccr2 |= CCR2_WT1; + write_cyrix_reg(CCR2, ccr2); + + /* Initialize CCR4. */ + ccr3 = read_cyrix_reg(CCR3); + write_cyrix_reg(CCR3, CCR3_MAPEN0); + + ccr4 = read_cyrix_reg(CCR4); + ccr4 |= CCR4_DTE; + ccr4 |= CCR4_MEM; +#ifdef CPU_FASTER_5X86_FPU + ccr4 |= CCR4_FASTFPE; +#else + ccr4 &= ~CCR4_FASTFPE; +#endif + ccr4 &= ~CCR4_IOMASK; + /******************************************************************** + * WARNING: The "BIOS Writers Guide" mentions that I/O recovery time + * should be 0 for errata fix. + ********************************************************************/ +#ifdef CPU_IORT + ccr4 |= CPU_IORT & CCR4_IOMASK; +#endif + write_cyrix_reg(CCR4, ccr4); + + /* Initialize PCR0. */ + /**************************************************************** + * WARNING: RSTK_EN and LOOP_EN could make your system unstable. + * BTB_EN might make your system unstable. + ****************************************************************/ + pcr0 = read_cyrix_reg(PCR0); +#ifdef CPU_RSTK_EN + pcr0 |= PCR0_RSTK; +#else + pcr0 &= ~PCR0_RSTK; +#endif +#ifdef CPU_BTB_EN + pcr0 |= PCR0_BTB; +#else + pcr0 &= ~PCR0_BTB; +#endif +#ifdef CPU_LOOP_EN + pcr0 |= PCR0_LOOP; +#else + pcr0 &= ~PCR0_LOOP; +#endif + + /**************************************************************** + * WARNING: if you use a memory mapped I/O device, don't use + * DISABLE_5X86_LSSER option, which may reorder memory mapped + * I/O access. + * IF YOUR MOTHERBOARD HAS PCI BUS, DON'T DISABLE LSSER. + ****************************************************************/ +#ifdef CPU_DISABLE_5X86_LSSER + pcr0 &= ~PCR0_LSSER; +#else + pcr0 |= PCR0_LSSER; +#endif + write_cyrix_reg(PCR0, pcr0); + + /* Restore CCR3. */ + write_cyrix_reg(CCR3, ccr3); + + (void)read_cyrix_reg(0x80); /* dummy */ + + /* Unlock NW bit in CR0. */ + write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_LOCK_NW); + load_cr0((rcr0() & ~CR0_CD) | CR0_NW); /* CD = 0, NW = 1 */ + /* Lock NW bit in CR0. */ + write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_LOCK_NW); + + write_eflags(eflags); +} + +#ifdef CPU_I486_ON_386 +/* + * There are i486 based upgrade products for i386 machines. + * In this case, BIOS doesn't enables CPU cache. + */ +static void +init_i486_on_386(void) +{ + u_long eflags; + +#if defined(PC98) && !defined(CPU_UPGRADE_HW_CACHE) + need_post_dma_flush = 1; +#endif + + eflags = read_eflags(); + disable_intr(); + + load_cr0(rcr0() & ~(CR0_CD | CR0_NW)); /* CD = 0, NW = 0 */ + + write_eflags(eflags); +} +#endif + +/* + * Cyrix 6x86 + * + * XXX - What should I do here? Please let me know. + */ +static void +init_6x86(void) +{ + u_long eflags; + u_char ccr3, ccr4; + + eflags = read_eflags(); + disable_intr(); + + load_cr0(rcr0() | CR0_CD | CR0_NW); + wbinvd(); + + /* Initialize CCR0. */ + write_cyrix_reg(CCR0, read_cyrix_reg(CCR0) | CCR0_NC1); + + /* Initialize CCR1. */ +#ifdef CPU_CYRIX_NO_LOCK + write_cyrix_reg(CCR1, read_cyrix_reg(CCR1) | CCR1_NO_LOCK); +#else + write_cyrix_reg(CCR1, read_cyrix_reg(CCR1) & ~CCR1_NO_LOCK); +#endif + + /* Initialize CCR2. */ +#ifdef CPU_SUSP_HLT + write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_SUSP_HLT); +#else + write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_SUSP_HLT); +#endif + + ccr3 = read_cyrix_reg(CCR3); + write_cyrix_reg(CCR3, CCR3_MAPEN0); + + /* Initialize CCR4. */ + ccr4 = read_cyrix_reg(CCR4); + ccr4 |= CCR4_DTE; + ccr4 &= ~CCR4_IOMASK; +#ifdef CPU_IORT + write_cyrix_reg(CCR4, ccr4 | (CPU_IORT & CCR4_IOMASK)); +#else + write_cyrix_reg(CCR4, ccr4 | 7); +#endif + + /* Initialize CCR5. */ +#ifdef CPU_WT_ALLOC + write_cyrix_reg(CCR5, read_cyrix_reg(CCR5) | CCR5_WT_ALLOC); +#endif + + /* Restore CCR3. */ + write_cyrix_reg(CCR3, ccr3); + + /* Unlock NW bit in CR0. */ + write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_LOCK_NW); + + /* + * Earlier revision of the 6x86 CPU could crash the system if + * L1 cache is in write-back mode. + */ + if ((cyrix_did & 0xff00) > 0x1600) + load_cr0(rcr0() & ~(CR0_CD | CR0_NW)); /* CD = 0 and NW = 0 */ + else { + /* Revision 2.6 and lower. */ +#ifdef CYRIX_CACHE_REALLY_WORKS + load_cr0(rcr0() & ~(CR0_CD | CR0_NW)); /* CD = 0 and NW = 0 */ +#else + load_cr0((rcr0() & ~CR0_CD) | CR0_NW); /* CD = 0 and NW = 1 */ +#endif + } + + /* Lock NW bit in CR0. */ + write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_LOCK_NW); + + write_eflags(eflags); +} +#endif /* I486_CPU */ + +#ifdef I686_CPU +/* + * Cyrix 6x86MX (code-named M2) + * + * XXX - What should I do here? Please let me know. + */ +static void +init_6x86MX(void) +{ + u_long eflags; + u_char ccr3, ccr4; + + eflags = read_eflags(); + disable_intr(); + + load_cr0(rcr0() | CR0_CD | CR0_NW); + wbinvd(); + + /* Initialize CCR0. */ + write_cyrix_reg(CCR0, read_cyrix_reg(CCR0) | CCR0_NC1); + + /* Initialize CCR1. */ +#ifdef CPU_CYRIX_NO_LOCK + write_cyrix_reg(CCR1, read_cyrix_reg(CCR1) | CCR1_NO_LOCK); +#else + write_cyrix_reg(CCR1, read_cyrix_reg(CCR1) & ~CCR1_NO_LOCK); +#endif + + /* Initialize CCR2. */ +#ifdef CPU_SUSP_HLT + write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_SUSP_HLT); +#else + write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_SUSP_HLT); +#endif + + ccr3 = read_cyrix_reg(CCR3); + write_cyrix_reg(CCR3, CCR3_MAPEN0); + + /* Initialize CCR4. */ + ccr4 = read_cyrix_reg(CCR4); + ccr4 &= ~CCR4_IOMASK; +#ifdef CPU_IORT + write_cyrix_reg(CCR4, ccr4 | (CPU_IORT & CCR4_IOMASK)); +#else + write_cyrix_reg(CCR4, ccr4 | 7); +#endif + + /* Initialize CCR5. */ +#ifdef CPU_WT_ALLOC + write_cyrix_reg(CCR5, read_cyrix_reg(CCR5) | CCR5_WT_ALLOC); +#endif + + /* Restore CCR3. */ + write_cyrix_reg(CCR3, ccr3); + + /* Unlock NW bit in CR0. */ + write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) & ~CCR2_LOCK_NW); + + load_cr0(rcr0() & ~(CR0_CD | CR0_NW)); /* CD = 0 and NW = 0 */ + + /* Lock NW bit in CR0. */ + write_cyrix_reg(CCR2, read_cyrix_reg(CCR2) | CCR2_LOCK_NW); + + write_eflags(eflags); +} + +static void +init_ppro(void) +{ + u_int64_t apicbase; + + /* + * Local APIC should be disabled if it is not going to be used. + */ + apicbase = rdmsr(MSR_APICBASE); + apicbase &= ~APICBASE_ENABLED; + wrmsr(MSR_APICBASE, apicbase); +} + +/* + * Initialize BBL_CR_CTL3 (Control register 3: used to configure the + * L2 cache). + */ +static void +init_mendocino(void) +{ +#ifdef CPU_PPRO2CELERON + u_long eflags; + u_int64_t bbl_cr_ctl3; + + eflags = read_eflags(); + disable_intr(); + + load_cr0(rcr0() | CR0_CD | CR0_NW); + wbinvd(); + + bbl_cr_ctl3 = rdmsr(MSR_BBL_CR_CTL3); + + /* If the L2 cache is configured, do nothing. */ + if (!(bbl_cr_ctl3 & 1)) { + bbl_cr_ctl3 = 0x134052bLL; + + /* Set L2 Cache Latency (Default: 5). */ +#ifdef CPU_CELERON_L2_LATENCY +#if CPU_L2_LATENCY > 15 +#error invalid CPU_L2_LATENCY. +#endif + bbl_cr_ctl3 |= CPU_L2_LATENCY << 1; +#else + bbl_cr_ctl3 |= 5 << 1; +#endif + wrmsr(MSR_BBL_CR_CTL3, bbl_cr_ctl3); + } + + load_cr0(rcr0() & ~(CR0_CD | CR0_NW)); + write_eflags(eflags); +#endif /* CPU_PPRO2CELERON */ +} + +#endif /* I686_CPU */ + +/* + * Initialize CR4 (Control register 4) to enable SSE instructions. + */ +void +enable_sse(void) +{ +#if defined(CPU_ENABLE_SSE) + if ((cpu_feature & CPUID_XMM) && (cpu_feature & CPUID_FXSR)) { + load_cr4(rcr4() | CR4_FXSR | CR4_XMM); + cpu_fxsr = hw_instruction_sse = 1; + } +#endif +} + +void +initializecpu(void) +{ + + switch (cpu) { +#ifdef I486_CPU + case CPU_BLUE: + init_bluelightning(); + break; + case CPU_486DLC: + init_486dlc(); + break; + case CPU_CY486DX: + init_cy486dx(); + break; + case CPU_M1SC: + init_5x86(); + break; +#ifdef CPU_I486_ON_386 + case CPU_486: + init_i486_on_386(); + break; +#endif + case CPU_M1: + init_6x86(); + break; +#endif /* I486_CPU */ +#ifdef I686_CPU + case CPU_M2: + init_6x86MX(); + break; + case CPU_686: + if (strcmp(cpu_vendor, "GenuineIntel") == 0) { + switch (cpu_id & 0xff0) { + case 0x610: + init_ppro(); + break; + case 0x660: + init_mendocino(); + break; + } + } else if (strcmp(cpu_vendor, "AuthenticAMD") == 0) { +#if defined(I686_CPU) && defined(CPU_ATHLON_SSE_HACK) + /* + * Sometimes the BIOS doesn't enable SSE instructions. + * According to AMD document 20734, the mobile + * Duron, the (mobile) Athlon 4 and the Athlon MP + * support SSE. These correspond to cpu_id 0x66X + * or 0x67X. + */ + if ((cpu_feature & CPUID_XMM) == 0 && + ((cpu_id & ~0xf) == 0x660 || + (cpu_id & ~0xf) == 0x670 || + (cpu_id & ~0xf) == 0x680)) { + u_int regs[4]; + wrmsr(0xC0010015, rdmsr(0xC0010015) & ~0x08000); + do_cpuid(1, regs); + cpu_feature = regs[3]; + } +#endif + } + break; +#endif + default: + break; + } + enable_sse(); + +#if defined(PC98) && !defined(CPU_UPGRADE_HW_CACHE) + /* + * OS should flush L1 cache by itself because no PC-98 supports + * non-Intel CPUs. Use wbinvd instruction before DMA transfer + * when need_pre_dma_flush = 1, use invd instruction after DMA + * transfer when need_post_dma_flush = 1. If your CPU upgrade + * product supports hardware cache control, you can add the + * CPU_UPGRADE_HW_CACHE option in your kernel configuration file. + * This option eliminates unneeded cache flush instruction(s). + */ + if (strcmp(cpu_vendor, "CyrixInstead") == 0) { + switch (cpu) { +#ifdef I486_CPU + case CPU_486DLC: + need_post_dma_flush = 1; + break; + case CPU_M1SC: + need_pre_dma_flush = 1; + break; + case CPU_CY486DX: + need_pre_dma_flush = 1; +#ifdef CPU_I486_ON_386 + need_post_dma_flush = 1; +#endif + break; +#endif + default: + break; + } + } else if (strcmp(cpu_vendor, "AuthenticAMD") == 0) { + switch (cpu_id & 0xFF0) { + case 0x470: /* Enhanced Am486DX2 WB */ + case 0x490: /* Enhanced Am486DX4 WB */ + case 0x4F0: /* Am5x86 WB */ + need_pre_dma_flush = 1; + break; + } + } else if (strcmp(cpu_vendor, "IBM") == 0) { + need_post_dma_flush = 1; + } else { +#ifdef CPU_I486_ON_386 + need_pre_dma_flush = 1; +#endif + } +#endif /* PC98 && !CPU_UPGRADE_HW_CACHE */ +} + +#if defined(I586_CPU) && defined(CPU_WT_ALLOC) +/* + * Enable write allocate feature of AMD processors. + * Following two functions require the Maxmem variable being set. + */ +void +enable_K5_wt_alloc(void) +{ + u_int64_t msr; + register_t savecrit; + + /* + * Write allocate is supported only on models 1, 2, and 3, with + * a stepping of 4 or greater. + */ + if (((cpu_id & 0xf0) > 0) && ((cpu_id & 0x0f) > 3)) { + savecrit = intr_disable(); + msr = rdmsr(0x83); /* HWCR */ + wrmsr(0x83, msr & !(0x10)); + + /* + * We have to tell the chip where the top of memory is, + * since video cards could have frame bufferes there, + * memory-mapped I/O could be there, etc. + */ + if(Maxmem > 0) + msr = Maxmem / 16; + else + msr = 0; + msr |= AMD_WT_ALLOC_TME | AMD_WT_ALLOC_FRE; +#ifdef PC98 + if (!(inb(0x43b) & 4)) { + wrmsr(0x86, 0x0ff00f0); + msr |= AMD_WT_ALLOC_PRE; + } +#else + /* + * There is no way to know wheter 15-16M hole exists or not. + * Therefore, we disable write allocate for this range. + */ + wrmsr(0x86, 0x0ff00f0); + msr |= AMD_WT_ALLOC_PRE; +#endif + wrmsr(0x85, msr); + + msr=rdmsr(0x83); + wrmsr(0x83, msr|0x10); /* enable write allocate */ + intr_restore(savecrit); + } +} + +void +enable_K6_wt_alloc(void) +{ + quad_t size; + u_int64_t whcr; + u_long eflags; + + eflags = read_eflags(); + disable_intr(); + wbinvd(); + +#ifdef CPU_DISABLE_CACHE + /* + * Certain K6-2 box becomes unstable when write allocation is + * enabled. + */ + /* + * The AMD-K6 processer provides the 64-bit Test Register 12(TR12), + * but only the Cache Inhibit(CI) (bit 3 of TR12) is suppported. + * All other bits in TR12 have no effect on the processer's operation. + * The I/O Trap Restart function (bit 9 of TR12) is always enabled + * on the AMD-K6. + */ + wrmsr(0x0000000e, (u_int64_t)0x0008); +#endif + /* Don't assume that memory size is aligned with 4M. */ + if (Maxmem > 0) + size = ((Maxmem >> 8) + 3) >> 2; + else + size = 0; + + /* Limit is 508M bytes. */ + if (size > 0x7f) + size = 0x7f; + whcr = (rdmsr(0xc0000082) & ~(0x7fLL << 1)) | (size << 1); + +#if defined(PC98) || defined(NO_MEMORY_HOLE) + if (whcr & (0x7fLL << 1)) { +#ifdef PC98 + /* + * If bit 2 of port 0x43b is 0, disable wrte allocate for the + * 15-16M range. + */ + if (!(inb(0x43b) & 4)) + whcr &= ~0x0001LL; + else +#endif + whcr |= 0x0001LL; + } +#else + /* + * There is no way to know wheter 15-16M hole exists or not. + * Therefore, we disable write allocate for this range. + */ + whcr &= ~0x0001LL; +#endif + wrmsr(0x0c0000082, whcr); + + write_eflags(eflags); +} + +void +enable_K6_2_wt_alloc(void) +{ + quad_t size; + u_int64_t whcr; + u_long eflags; + + eflags = read_eflags(); + disable_intr(); + wbinvd(); + +#ifdef CPU_DISABLE_CACHE + /* + * Certain K6-2 box becomes unstable when write allocation is + * enabled. + */ + /* + * The AMD-K6 processer provides the 64-bit Test Register 12(TR12), + * but only the Cache Inhibit(CI) (bit 3 of TR12) is suppported. + * All other bits in TR12 have no effect on the processer's operation. + * The I/O Trap Restart function (bit 9 of TR12) is always enabled + * on the AMD-K6. + */ + wrmsr(0x0000000e, (u_int64_t)0x0008); +#endif + /* Don't assume that memory size is aligned with 4M. */ + if (Maxmem > 0) + size = ((Maxmem >> 8) + 3) >> 2; + else + size = 0; + + /* Limit is 4092M bytes. */ + if (size > 0x3fff) + size = 0x3ff; + whcr = (rdmsr(0xc0000082) & ~(0x3ffLL << 22)) | (size << 22); + +#if defined(PC98) || defined(NO_MEMORY_HOLE) + if (whcr & (0x3ffLL << 22)) { +#ifdef PC98 + /* + * If bit 2 of port 0x43b is 0, disable wrte allocate for the + * 15-16M range. + */ + if (!(inb(0x43b) & 4)) + whcr &= ~(1LL << 16); + else +#endif + whcr |= 1LL << 16; + } +#else + /* + * There is no way to know wheter 15-16M hole exists or not. + * Therefore, we disable write allocate for this range. + */ + whcr &= ~(1LL << 16); +#endif + wrmsr(0x0c0000082, whcr); + + write_eflags(eflags); +} +#endif /* I585_CPU && CPU_WT_ALLOC */ + +#include "opt_ddb.h" +#ifdef DDB +#include + +DB_SHOW_COMMAND(cyrixreg, cyrixreg) +{ + u_long eflags; + u_int cr0; + u_char ccr1, ccr2, ccr3; + u_char ccr0 = 0, ccr4 = 0, ccr5 = 0, pcr0 = 0; + + cr0 = rcr0(); + if (strcmp(cpu_vendor,"CyrixInstead") == 0) { + eflags = read_eflags(); + disable_intr(); + + + if ((cpu != CPU_M1SC) && (cpu != CPU_CY486DX)) { + ccr0 = read_cyrix_reg(CCR0); + } + ccr1 = read_cyrix_reg(CCR1); + ccr2 = read_cyrix_reg(CCR2); + ccr3 = read_cyrix_reg(CCR3); + if ((cpu == CPU_M1SC) || (cpu == CPU_M1) || (cpu == CPU_M2)) { + write_cyrix_reg(CCR3, CCR3_MAPEN0); + ccr4 = read_cyrix_reg(CCR4); + if ((cpu == CPU_M1) || (cpu == CPU_M2)) + ccr5 = read_cyrix_reg(CCR5); + else + pcr0 = read_cyrix_reg(PCR0); + write_cyrix_reg(CCR3, ccr3); /* Restore CCR3. */ + } + write_eflags(eflags); + + if ((cpu != CPU_M1SC) && (cpu != CPU_CY486DX)) + printf("CCR0=%x, ", (u_int)ccr0); + + printf("CCR1=%x, CCR2=%x, CCR3=%x", + (u_int)ccr1, (u_int)ccr2, (u_int)ccr3); + if ((cpu == CPU_M1SC) || (cpu == CPU_M1) || (cpu == CPU_M2)) { + printf(", CCR4=%x, ", (u_int)ccr4); + if (cpu == CPU_M1SC) + printf("PCR0=%x\n", pcr0); + else + printf("CCR5=%x\n", ccr5); + } + } + printf("CR0=%x\n", cr0); +} +#endif /* DDB */ Property changes on: releng/6.1/sys/i386/i386/initcpu.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: releng/6.1/sys/i386/include/md_var.h =================================================================== --- releng/6.1/sys/i386/include/md_var.h (nonexistent) +++ releng/6.1/sys/i386/include/md_var.h (revision 155951) @@ -0,0 +1,101 @@ +/*- + * Copyright (c) 1995 Bruce D. Evans. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 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. Neither the name of the author nor the names of contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_MD_VAR_H_ +#define _MACHINE_MD_VAR_H_ + +/* + * Miscellaneous machine-dependent declarations. + */ + +extern void (*bcopy_vector)(const void *from, void *to, size_t len); +extern void (*bzero_vector)(void *buf, size_t len); +extern int (*copyin_vector)(const void *udaddr, void *kaddr, size_t len); +extern int (*copyout_vector)(const void *kaddr, void *udaddr, size_t len); + +extern long Maxmem; +extern u_int basemem; /* PA of original top of base memory */ +extern int busdma_swi_pending; +extern u_int cpu_exthigh; +extern u_int cpu_feature; +extern u_int cpu_feature2; +extern u_int amd_feature; +extern u_int cpu_fxsr; +extern u_int cpu_high; +extern u_int cpu_id; +extern u_int cpu_procinfo; +extern char cpu_vendor[]; +extern u_int cyrix_did; +extern char kstack[]; +extern char sigcode[]; +extern int szsigcode; +#ifdef COMPAT_FREEBSD4 +extern int szfreebsd4_sigcode; +#endif +#ifdef COMPAT_43 +extern int szosigcode; +#endif + +typedef void alias_for_inthand_t(u_int cs, u_int ef, u_int esp, u_int ss); +struct thread; +struct reg; +struct fpreg; +struct dbreg; + +void bcopyb(const void *from, void *to, size_t len); +void busdma_swi(void); +void cpu_setregs(void); +void cpu_switch_load_gs(void) __asm(__STRING(cpu_switch_load_gs)); +void doreti_iret(void) __asm(__STRING(doreti_iret)); +void doreti_iret_fault(void) __asm(__STRING(doreti_iret_fault)); +void doreti_popl_ds(void) __asm(__STRING(doreti_popl_ds)); +void doreti_popl_ds_fault(void) __asm(__STRING(doreti_popl_ds_fault)); +void doreti_popl_es(void) __asm(__STRING(doreti_popl_es)); +void doreti_popl_es_fault(void) __asm(__STRING(doreti_popl_es_fault)); +void doreti_popl_fs(void) __asm(__STRING(doreti_popl_fs)); +void doreti_popl_fs_fault(void) __asm(__STRING(doreti_popl_fs_fault)); +void enable_sse(void); +void fillw(int /*u_short*/ pat, void *base, size_t cnt); +void i486_bzero(void *buf, size_t len); +void i586_bcopy(const void *from, void *to, size_t len); +void i586_bzero(void *buf, size_t len); +int i586_copyin(const void *udaddr, void *kaddr, size_t len); +int i586_copyout(const void *kaddr, void *udaddr, size_t len); +void i686_pagezero(void *addr); +void sse2_pagezero(void *addr); +void init_AMD_Elan_sc520(void); +int is_physical_memory(vm_paddr_t addr); +int isa_nmi(int cd); +vm_paddr_t kvtop(void *addr); +void setidt(int idx, alias_for_inthand_t *func, int typ, int dpl, int selec); +int user_dbreg_trap(void); + +#endif /* !_MACHINE_MD_VAR_H_ */ Property changes on: releng/6.1/sys/i386/include/md_var.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: releng/6.1/sys/i386/include/specialreg.h =================================================================== --- releng/6.1/sys/i386/include/specialreg.h (nonexistent) +++ releng/6.1/sys/i386/include/specialreg.h (revision 155951) @@ -0,0 +1,391 @@ +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 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. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)specialreg.h 7.1 (Berkeley) 5/9/91 + * $FreeBSD$ + */ + +#ifndef _MACHINE_SPECIALREG_H_ +#define _MACHINE_SPECIALREG_H_ + +/* + * 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_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 */ + +/* + * Bits in 486 special registers: + */ +#define CR0_NE 0x00000020 /* Numeric Error enable (EX16 vs IRQ13) */ +#define CR0_WP 0x00010000 /* Write Protect (honor page protect in + all modes) */ +#define CR0_AM 0x00040000 /* Alignment Mask (set to enable AC flag) */ +#define CR0_NW 0x20000000 /* Not Write-through */ +#define CR0_CD 0x40000000 /* Cache Disable */ + +/* + * Bits in PPro special registers + */ +#define CR4_VME 0x00000001 /* Virtual 8086 mode extensions */ +#define CR4_PVI 0x00000002 /* Protected-mode virtual interrupts */ +#define CR4_TSD 0x00000004 /* Time stamp disable */ +#define CR4_DE 0x00000008 /* Debugging extensions */ +#define CR4_PSE 0x00000010 /* Page size extensions */ +#define CR4_PAE 0x00000020 /* Physical address extension */ +#define CR4_MCE 0x00000040 /* Machine check enable */ +#define CR4_PGE 0x00000080 /* Page global enable */ +#define CR4_PCE 0x00000100 /* Performance monitoring counter enable */ +#define CR4_FXSR 0x00000200 /* Fast FPU save/restore used by OS */ +#define CR4_XMM 0x00000400 /* enable SIMD/MMX2 to use except 16 */ + +/* + * CPUID instruction features register + */ +#define CPUID_FPU 0x00000001 +#define CPUID_VME 0x00000002 +#define CPUID_DE 0x00000004 +#define CPUID_PSE 0x00000008 +#define CPUID_TSC 0x00000010 +#define CPUID_MSR 0x00000020 +#define CPUID_PAE 0x00000040 +#define CPUID_MCE 0x00000080 +#define CPUID_CX8 0x00000100 +#define CPUID_APIC 0x00000200 +#define CPUID_B10 0x00000400 +#define CPUID_SEP 0x00000800 +#define CPUID_MTRR 0x00001000 +#define CPUID_PGE 0x00002000 +#define CPUID_MCA 0x00004000 +#define CPUID_CMOV 0x00008000 +#define CPUID_PAT 0x00010000 +#define CPUID_PSE36 0x00020000 +#define CPUID_PSN 0x00040000 +#define CPUID_CLFSH 0x00080000 +#define CPUID_B20 0x00100000 +#define CPUID_DS 0x00200000 +#define CPUID_ACPI 0x00400000 +#define CPUID_MMX 0x00800000 +#define CPUID_FXSR 0x01000000 +#define CPUID_SSE 0x02000000 +#define CPUID_XMM 0x02000000 +#define CPUID_SSE2 0x04000000 +#define CPUID_SS 0x08000000 +#define CPUID_HTT 0x10000000 +#define CPUID_TM 0x20000000 +#define CPUID_IA64 0x40000000 +#define CPUID_PBE 0x80000000 + +/* + * CPUID instruction 1 ebx info + */ +#define CPUID_BRAND_INDEX 0x000000ff +#define CPUID_CLFUSH_SIZE 0x0000ff00 +#define CPUID_HTT_CORES 0x00ff0000 +#define CPUID_LOCAL_APIC_ID 0xff000000 + +/* + * 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_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_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_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 + +/* + * Constants related to MSR's. + */ +#define APICBASE_RESERVED 0x000006ff +#define APICBASE_BSP 0x00000100 +#define APICBASE_ENABLED 0x00000800 +#define APICBASE_ADDRESS 0xfffff000 + +/* + * Constants related to MTRRs + */ +#define MTRR_N64K 8 /* numbers of fixed-size entries */ +#define MTRR_N16K 16 +#define MTRR_N4K 64 + +/* + * Cyrix configuration registers, accessible as IO ports. + */ +#define CCR0 0xc0 /* Configuration control register 0 */ +#define CCR0_NC0 0x01 /* First 64K of each 1M memory region is + non-cacheable */ +#define CCR0_NC1 0x02 /* 640K-1M region is non-cacheable */ +#define CCR0_A20M 0x04 /* Enables A20M# input pin */ +#define CCR0_KEN 0x08 /* Enables KEN# input pin */ +#define CCR0_FLUSH 0x10 /* Enables FLUSH# input pin */ +#define CCR0_BARB 0x20 /* Flushes internal cache when entering hold + state */ +#define CCR0_CO 0x40 /* Cache org: 1=direct mapped, 0=2x set + assoc */ +#define CCR0_SUSPEND 0x80 /* Enables SUSP# and SUSPA# pins */ + +#define CCR1 0xc1 /* Configuration control register 1 */ +#define CCR1_RPL 0x01 /* Enables RPLSET and RPLVAL# pins */ +#define CCR1_SMI 0x02 /* Enables SMM pins */ +#define CCR1_SMAC 0x04 /* System management memory access */ +#define CCR1_MMAC 0x08 /* Main memory access */ +#define CCR1_NO_LOCK 0x10 /* Negate LOCK# */ +#define CCR1_SM3 0x80 /* SMM address space address region 3 */ + +#define CCR2 0xc2 +#define CCR2_WB 0x02 /* Enables WB cache interface pins */ +#define CCR2_SADS 0x02 /* Slow ADS */ +#define CCR2_LOCK_NW 0x04 /* LOCK NW Bit */ +#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 + hold state. */ +#define CCR2_BWRT 0x40 /* Enables burst write cycles */ +#define CCR2_USE_SUSP 0x80 /* Enables suspend pins */ + +#define CCR3 0xc3 +#define CCR3_SMILOCK 0x01 /* SMM register lock */ +#define CCR3_NMI 0x02 /* Enables NMI during SMM */ +#define CCR3_LINBRST 0x04 /* Linear address burst cycles */ +#define CCR3_SMMMODE 0x08 /* SMM Mode */ +#define CCR3_MAPEN0 0x10 /* Enables Map0 */ +#define CCR3_MAPEN1 0x20 /* Enables Map1 */ +#define CCR3_MAPEN2 0x40 /* Enables Map2 */ +#define CCR3_MAPEN3 0x80 /* Enables Map3 */ + +#define CCR4 0xe8 +#define CCR4_IOMASK 0x07 +#define CCR4_MEM 0x08 /* Enables momory bypassing */ +#define CCR4_DTE 0x10 /* Enables directory table entry cache */ +#define CCR4_FASTFPE 0x20 /* Fast FPU exception */ +#define CCR4_CPUID 0x80 /* Enables CPUID instruction */ + +#define CCR5 0xe9 +#define CCR5_WT_ALLOC 0x01 /* Write-through allocate */ +#define CCR5_SLOP 0x02 /* LOOP instruction slowed down */ +#define CCR5_LBR1 0x10 /* Local bus region 1 */ +#define CCR5_ARREN 0x20 /* Enables ARR region */ + +#define CCR6 0xea + +#define CCR7 0xeb + +/* Performance Control Register (5x86 only). */ +#define PCR0 0x20 +#define PCR0_RSTK 0x01 /* Enables return stack */ +#define PCR0_BTB 0x02 /* Enables branch target buffer */ +#define PCR0_LOOP 0x04 /* Enables loop */ +#define PCR0_AIS 0x08 /* Enables all instrcutions stalled to + serialize pipe. */ +#define PCR0_MLR 0x10 /* Enables reordering of misaligned loads */ +#define PCR0_BTBRT 0x40 /* Enables BTB test register. */ +#define PCR0_LSSER 0x80 /* Disable reorder */ + +/* Device Identification Registers */ +#define DIR0 0xfe +#define DIR1 0xff + +/* + * The following four 3-byte registers control the non-cacheable regions. + * These registers must be written as three separate bytes. + * + * NCRx+0: A31-A24 of starting address + * NCRx+1: A23-A16 of starting address + * NCRx+2: A15-A12 of starting address | NCR_SIZE_xx. + * + * The non-cacheable region's starting address must be aligned to the + * size indicated by the NCR_SIZE_xx field. + */ +#define NCR1 0xc4 +#define NCR2 0xc7 +#define NCR3 0xca +#define NCR4 0xcd + +#define NCR_SIZE_0K 0 +#define NCR_SIZE_4K 1 +#define NCR_SIZE_8K 2 +#define NCR_SIZE_16K 3 +#define NCR_SIZE_32K 4 +#define NCR_SIZE_64K 5 +#define NCR_SIZE_128K 6 +#define NCR_SIZE_256K 7 +#define NCR_SIZE_512K 8 +#define NCR_SIZE_1M 9 +#define NCR_SIZE_2M 10 +#define NCR_SIZE_4M 11 +#define NCR_SIZE_8M 12 +#define NCR_SIZE_16M 13 +#define NCR_SIZE_32M 14 +#define NCR_SIZE_4G 15 + +/* + * The address region registers are used to specify the location and + * size for the eight address regions. + * + * ARRx + 0: A31-A24 of start address + * ARRx + 1: A23-A16 of start address + * ARRx + 2: A15-A12 of start address | ARR_SIZE_xx + */ +#define ARR0 0xc4 +#define ARR1 0xc7 +#define ARR2 0xca +#define ARR3 0xcd +#define ARR4 0xd0 +#define ARR5 0xd3 +#define ARR6 0xd6 +#define ARR7 0xd9 + +#define ARR_SIZE_0K 0 +#define ARR_SIZE_4K 1 +#define ARR_SIZE_8K 2 +#define ARR_SIZE_16K 3 +#define ARR_SIZE_32K 4 +#define ARR_SIZE_64K 5 +#define ARR_SIZE_128K 6 +#define ARR_SIZE_256K 7 +#define ARR_SIZE_512K 8 +#define ARR_SIZE_1M 9 +#define ARR_SIZE_2M 10 +#define ARR_SIZE_4M 11 +#define ARR_SIZE_8M 12 +#define ARR_SIZE_16M 13 +#define ARR_SIZE_32M 14 +#define ARR_SIZE_4G 15 + +/* + * The region control registers specify the attributes associated with + * the ARRx addres regions. + */ +#define RCR0 0xdc +#define RCR1 0xdd +#define RCR2 0xde +#define RCR3 0xdf +#define RCR4 0xe0 +#define RCR5 0xe1 +#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_WL 0x04 /* Weak locking. */ +#define RCR_WG 0x08 /* Write gathering. */ +#define RCR_WT 0x10 /* Write-through. */ +#define RCR_NLB 0x20 /* LBA# pin is not asserted. */ + +/* AMD Write Allocate Top-Of-Memory and Control Register */ +#define AMD_WT_ALLOC_TME 0x40000 /* top-of-memory enable */ +#define AMD_WT_ALLOC_PRE 0x20000 /* programmable range enable */ +#define AMD_WT_ALLOC_FRE 0x10000 /* fixed (A0000-FFFFF) range enable */ + + +#ifndef LOCORE +static __inline u_char +read_cyrix_reg(u_char reg) +{ + outb(0x22, reg); + return inb(0x23); +} + +static __inline void +write_cyrix_reg(u_char reg, u_char data) +{ + outb(0x22, reg); + outb(0x23, data); +} +#endif + +#endif /* !_MACHINE_SPECIALREG_H_ */ Property changes on: releng/6.1/sys/i386/include/specialreg.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property