[BACK]Return to identcpu.c CVS log [TXT][DIR] Up to [local] / sys / arch / amd64 / amd64

Annotation of sys/arch/amd64/amd64/identcpu.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: identcpu.c,v 1.14 2007/05/29 07:35:55 tedu Exp $      */
        !             2: /*     $NetBSD: identcpu.c,v 1.1 2003/04/26 18:39:28 fvdl Exp $        */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 2003 Wasabi Systems, Inc.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * Written by Frank van der Linden for Wasabi Systems, Inc.
        !             9:  *
        !            10:  * Redistribution and use in source and binary forms, with or without
        !            11:  * modification, are permitted provided that the following conditions
        !            12:  * are met:
        !            13:  * 1. Redistributions of source code must retain the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer.
        !            15:  * 2. Redistributions in binary form must reproduce the above copyright
        !            16:  *    notice, this list of conditions and the following disclaimer in the
        !            17:  *    documentation and/or other materials provided with the distribution.
        !            18:  * 3. All advertising materials mentioning features or use of this software
        !            19:  *    must display the following acknowledgement:
        !            20:  *      This product includes software developed for the NetBSD Project by
        !            21:  *      Wasabi Systems, Inc.
        !            22:  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
        !            23:  *    or promote products derived from this software without specific prior
        !            24:  *    written permission.
        !            25:  *
        !            26:  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
        !            27:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            28:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            29:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
        !            30:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            31:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            32:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            33:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            34:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            35:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            36:  * POSSIBILITY OF SUCH DAMAGE.
        !            37:  */
        !            38:
        !            39: #include <sys/param.h>
        !            40: #include <sys/systm.h>
        !            41: #include <sys/kernel.h>
        !            42: #include <sys/proc.h>
        !            43: #include <sys/user.h>
        !            44: #include <sys/sysctl.h>
        !            45: #include <machine/cpu.h>
        !            46: #include <machine/cpufunc.h>
        !            47:
        !            48: /* sysctl wants this. */
        !            49: char cpu_model[48];
        !            50: int cpuspeed;
        !            51:
        !            52: const struct {
        !            53:        u_int32_t       bit;
        !            54:        char            str[8];
        !            55: } cpu_cpuid_features[] = {
        !            56:        { CPUID_FPU,    "FPU" },
        !            57:        { CPUID_VME,    "VME" },
        !            58:        { CPUID_DE,     "DE" },
        !            59:        { CPUID_PSE,    "PSE" },
        !            60:        { CPUID_TSC,    "TSC" },
        !            61:        { CPUID_MSR,    "MSR" },
        !            62:        { CPUID_PAE,    "PAE" },
        !            63:        { CPUID_MCE,    "MCE" },
        !            64:        { CPUID_CX8,    "CX8" },
        !            65:        { CPUID_APIC,   "APIC" },
        !            66:        { CPUID_SEP,    "SEP" },
        !            67:        { CPUID_MTRR,   "MTRR" },
        !            68:        { CPUID_PGE,    "PGE" },
        !            69:        { CPUID_MCA,    "MCA" },
        !            70:        { CPUID_CMOV,   "CMOV" },
        !            71:        { CPUID_PAT,    "PAT" },
        !            72:        { CPUID_PSE36,  "PSE36" },
        !            73:        { CPUID_PN,     "PN" },
        !            74:        { CPUID_CFLUSH, "CFLUSH" },
        !            75:        { CPUID_DS,     "DS" },
        !            76:        { CPUID_ACPI,   "ACPI" },
        !            77:        { CPUID_MMX,    "MMX" },
        !            78:        { CPUID_FXSR,   "FXSR" },
        !            79:        { CPUID_SSE,    "SSE" },
        !            80:        { CPUID_SSE2,   "SSE2" },
        !            81:        { CPUID_SS,     "SS" },
        !            82:        { CPUID_HTT,    "HTT" },
        !            83:        { CPUID_TM,     "TM" },
        !            84:        { CPUID_SBF,    "SBF" }
        !            85: }, cpu_ecpuid_features[] = {
        !            86:        { CPUID_MPC,    "MPC" },
        !            87:        { CPUID_NXE,    "NXE" },
        !            88:        { CPUID_MMXX,   "MMXX" },
        !            89:        { CPUID_FFXSR,  "FFXSR" },
        !            90:        { CPUID_LONG,   "LONG" },
        !            91:        { CPUID_3DNOW2, "3DNOW2" },
        !            92:        { CPUID_3DNOW,  "3DNOW" }
        !            93: }, cpu_cpuid_ecxfeatures[] = {
        !            94:        { CPUIDECX_SSE3,        "SSE3" },
        !            95:        { CPUIDECX_MWAIT,       "MWAIT" },
        !            96:        { CPUIDECX_DSCPL,       "DS-CPL" },
        !            97:        { CPUIDECX_VMX,         "VMX" },
        !            98:        { CPUIDECX_EST,         "EST" },
        !            99:        { CPUIDECX_TM2,         "TM2" },
        !           100:        { CPUIDECX_CNXTID,      "CNXT-ID" },
        !           101:        { CPUIDECX_CX16,        "CX16" },
        !           102:        { CPUIDECX_XTPR,        "xTPR" }
        !           103: };
        !           104:
        !           105: int
        !           106: cpu_amd64speed(int *freq)
        !           107: {
        !           108:        *freq = cpuspeed;
        !           109:        return (0);
        !           110: }
        !           111:
        !           112: #ifndef SMALL_KERNEL
        !           113: void   intelcore_update_sensor(void *args);
        !           114: /*
        !           115:  * Temperature read on the CPU is relative to the maximum
        !           116:  * temperature supported by the CPU, Tj(Max).
        !           117:  * Poorly documented, refer to:
        !           118:  * http://softwarecommunity.intel.com/isn/Community/
        !           119:  * en-US/forums/thread/30228638.aspx
        !           120:  * Basically, depending on a bit in one msr, the max is either 85 or 100.
        !           121:  * Then we subtract the temperature portion of thermal status from
        !           122:  * max to get current temperature.
        !           123:  */
        !           124: void
        !           125: intelcore_update_sensor(void *args)
        !           126: {
        !           127:        struct cpu_info *ci = (struct cpu_info *) args;
        !           128:        u_int64_t msr;
        !           129:        int max = 100;
        !           130:
        !           131:        if (rdmsr(MSR_TEMPERATURE_TARGET) & MSR_TEMPERATURE_TARGET_LOW_BIT)
        !           132:                max = 85;
        !           133:
        !           134:        msr = rdmsr(MSR_THERM_STATUS);
        !           135:        if (msr & MSR_THERM_STATUS_VALID_BIT) {
        !           136:                ci->ci_sensor.value = max - MSR_THERM_STATUS_TEMP(msr);
        !           137:                /* micro degrees */
        !           138:                ci->ci_sensor.value *= 1000000;
        !           139:                /* kelvin */
        !           140:                ci->ci_sensor.value += 273150000;
        !           141:                ci->ci_sensor.flags &= ~SENSOR_FINVALID;
        !           142:        } else {
        !           143:                ci->ci_sensor.value = 0;
        !           144:                ci->ci_sensor.flags |= SENSOR_FINVALID;
        !           145:        }
        !           146: }
        !           147:
        !           148: #endif
        !           149:
        !           150: void (*setperf_setup)(struct cpu_info *);
        !           151:
        !           152: void
        !           153: identifycpu(struct cpu_info *ci)
        !           154: {
        !           155:        u_int64_t last_tsc;
        !           156:        u_int32_t dummy, val, pnfeatset;
        !           157:        u_int32_t brand[12];
        !           158:        u_int32_t vendor[4];
        !           159:        int i, max;
        !           160:        char *brandstr_from, *brandstr_to;
        !           161:        int skipspace;
        !           162:
        !           163:        CPUID(1, ci->ci_signature, val, dummy, ci->ci_feature_flags);
        !           164:        CPUID(0x80000000, pnfeatset, dummy, dummy, dummy);
        !           165:        CPUID(0x80000001, dummy, dummy, dummy, ci->ci_feature_eflags);
        !           166:
        !           167:        vendor[3] = 0;
        !           168:        CPUID(0, dummy, vendor[0], vendor[2], vendor[1]);       /* yup, 0 2 1 */
        !           169:        CPUID(0x80000002, brand[0], brand[1], brand[2], brand[3]);
        !           170:        CPUID(0x80000003, brand[4], brand[5], brand[6], brand[7]);
        !           171:        CPUID(0x80000004, brand[8], brand[9], brand[10], brand[11]);
        !           172:
        !           173:        strlcpy(cpu_model, (char *)brand, sizeof(cpu_model));
        !           174:
        !           175:        /* Remove leading and duplicated spaces from cpu_model */
        !           176:        brandstr_from = brandstr_to = cpu_model;
        !           177:        skipspace = 1;
        !           178:        while (*brandstr_from != '\0') {
        !           179:                if (!skipspace || *brandstr_from != ' ') {
        !           180:                        skipspace = 0;
        !           181:                        *(brandstr_to++) = *brandstr_from;
        !           182:                }
        !           183:                if (*brandstr_from == ' ')
        !           184:                        skipspace = 1;
        !           185:                brandstr_from++;
        !           186:        }
        !           187:        *brandstr_to = '\0';
        !           188:
        !           189:        if (cpu_model[0] == 0)
        !           190:                strlcpy(cpu_model, "Opteron or Athlon 64", sizeof(cpu_model));
        !           191:
        !           192:        last_tsc = rdtsc();
        !           193:        delay(100000);
        !           194:        ci->ci_tsc_freq = (rdtsc() - last_tsc) * 10;
        !           195:
        !           196:        amd_cpu_cacheinfo(ci);
        !           197:
        !           198:        printf("%s: %s", ci->ci_dev->dv_xname, cpu_model);
        !           199:
        !           200:        if (ci->ci_tsc_freq != 0)
        !           201:                printf(", %lu.%02lu MHz", (ci->ci_tsc_freq + 4999) / 1000000,
        !           202:                    ((ci->ci_tsc_freq + 4999) / 10000) % 100);
        !           203:        cpuspeed = (ci->ci_tsc_freq + 4999) / 1000000;
        !           204:        cpu_cpuspeed = cpu_amd64speed;
        !           205:
        !           206:        printf("\n%s: ", ci->ci_dev->dv_xname);
        !           207:
        !           208:        max = sizeof(cpu_cpuid_features) / sizeof(cpu_cpuid_features[0]);
        !           209:        for (i = 0; i < max; i++)
        !           210:                if (ci->ci_feature_flags & cpu_cpuid_features[i].bit)
        !           211:                        printf("%s%s", i? "," : "", cpu_cpuid_features[i].str);
        !           212:        max = sizeof(cpu_cpuid_ecxfeatures) / sizeof(cpu_cpuid_ecxfeatures[0]);
        !           213:        for (i = 0; i < max; i++)
        !           214:                if (cpu_ecxfeature & cpu_cpuid_ecxfeatures[i].bit)
        !           215:                        printf(",%s", cpu_cpuid_ecxfeatures[i].str);
        !           216:        max = sizeof(cpu_ecpuid_features) / sizeof(cpu_ecpuid_features[0]);
        !           217:        for (i = 0; i < max; i++)
        !           218:                if (ci->ci_feature_eflags & cpu_ecpuid_features[i].bit)
        !           219:                        printf(",%s", cpu_ecpuid_features[i].str);
        !           220:        printf("\n");
        !           221:
        !           222:        x86_print_cacheinfo(ci);
        !           223:
        !           224: #ifndef SMALL_KERNEL
        !           225:        if (pnfeatset > 0x80000007) {
        !           226:                CPUID(0x80000007, dummy, dummy, dummy, pnfeatset);
        !           227:
        !           228:                if (pnfeatset & 0x06) {
        !           229:                        if ((ci->ci_signature & 0xF00) == 0xf00)
        !           230:                                setperf_setup = k8_powernow_init;
        !           231:                }
        !           232:        }
        !           233:
        !           234:        if (!strncmp(cpu_model, "Intel", 5)) {
        !           235:                if (cpu_ecxfeature & CPUIDECX_EST) {
        !           236:                        setperf_setup = est_init;
        !           237:                }
        !           238:                CPUID(0x06, val, dummy, dummy, dummy);
        !           239:                if (val & 0x1) {
        !           240:                        strlcpy(ci->ci_sensordev.xname, ci->ci_dev->dv_xname,
        !           241:                            sizeof(ci->ci_sensordev.xname));
        !           242:                        ci->ci_sensor.type = SENSOR_TEMP;
        !           243:                        sensor_task_register(ci, intelcore_update_sensor, 5);
        !           244:                        sensor_attach(&ci->ci_sensordev, &ci->ci_sensor);
        !           245:                        sensordev_install(&ci->ci_sensordev);
        !           246:                }
        !           247:        }
        !           248:
        !           249: #endif
        !           250:
        !           251:
        !           252:        /* AuthenticAMD:    h t u A                    i t n e */
        !           253:        if (vendor[0] == 0x68747541 && vendor[1] == 0x69746e65 &&
        !           254:            vendor[2] == 0x444d4163)    /* DMAc */
        !           255:                amd64_errata(ci);
        !           256: }
        !           257:
        !           258: void
        !           259: cpu_probe_features(struct cpu_info *ci)
        !           260: {
        !           261:        ci->ci_feature_flags = cpu_feature;
        !           262:        ci->ci_signature = 0;
        !           263: }

CVSweb