[BACK]Return to cpuprobe.c CVS log [TXT][DIR] Up to [local] / sys / arch / i386 / stand / libsa

Annotation of sys/arch/i386/stand/libsa/cpuprobe.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: cpuprobe.c,v 1.1 2004/06/26 05:19:37 tom Exp $        */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 2004 Tom Cosgrove <tom.cosgrove@arches-consulting.com>
        !             5:  *
        !             6:  * Permission to use, copy, modify, and distribute this software for any
        !             7:  * purpose with or without fee is hereby granted, provided that the above
        !             8:  * copyright notice and this permission notice appear in all copies.
        !             9:  *
        !            10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !            11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            14:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            15:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            16:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            17:  */
        !            18:
        !            19: #include <machine/psl.h>
        !            20: #include <machine/specialreg.h>
        !            21:
        !            22: #include "libsa.h"
        !            23:
        !            24: int amd64_supported;
        !            25: static int cpu_family, cpu_model, cpu_stepping;
        !            26: static int psl_check;
        !            27: static u_int32_t feature_ecx, feature_edx, feature_amd;
        !            28: static char cpu_brandstr[48];          /* Includes term NUL byte */
        !            29: static char cpu_vendor[13];            /* 12 chars plus NUL term */
        !            30:
        !            31: /*
        !            32:  * cpuid instruction.  request in eax, result in eax, ebx, ecx, edx.
        !            33:  * requires caller to provide u_int32_t regs[4] array.
        !            34:  */
        !            35: u_int32_t
        !            36: cpuid(u_int32_t eax, u_int32_t *regs)
        !            37: {
        !            38:        __asm __volatile(
        !            39:            "cpuid\n\t"
        !            40:            "movl       %%eax, 0(%2)\n\t"
        !            41:            "movl       %%ebx, 4(%2)\n\t"
        !            42:            "movl       %%ecx, 8(%2)\n\t"
        !            43:            "movl       %%edx, 12(%2)\n\t"
        !            44:            : "=a" (eax)
        !            45:            : "0" (eax), "S" (regs)
        !            46:            : "bx", "cx", "dx");
        !            47:
        !            48:        return eax;
        !            49: }
        !            50:
        !            51: void
        !            52: cpuprobe(void)
        !            53: {
        !            54:        u_int32_t cpuid_max, extended_max;
        !            55:        u_int32_t regs[4];
        !            56:
        !            57:        /*
        !            58:         * The following is a simple check to see if cpuid is supported.
        !            59:         * We try to toggle bit 21 (PSL_ID) in eflags.  If it works, then
        !            60:         * cpuid is supported.  If not, there's no cpuid, and we don't
        !            61:         * try it (don't want /boot to get an invalid opcode exception).
        !            62:         *
        !            63:         * XXX The NexGen Nx586 does not support this bit, so this is not
        !            64:         *     a good method to detect the presence of cpuid on this
        !            65:         *     processor.  That's fine: the purpose here is to detect the
        !            66:         *     absence of cpuid.  We don't mind if the instruction's not
        !            67:         *     there - this is not intended to determine exactly what
        !            68:         *     processor is there, just whether it's i386 or amd64.
        !            69:         *
        !            70:         *     The only thing that would cause us grief is a processor which
        !            71:         *     does not support cpuid but which does allow the PSL_ID bit
        !            72:         *     in eflags to be toggled.
        !            73:         */
        !            74:        __asm __volatile(
        !            75:            "pushfl\n\t"
        !            76:            "popl       %2\n\t"
        !            77:            "xorl       %2, %0\n\t"
        !            78:            "pushl      %0\n\t"
        !            79:            "popfl\n\t"
        !            80:            "pushfl\n\t"
        !            81:            "popl       %0\n\t"
        !            82:            "xorl       %2, %0\n\t"             /* If %2 == %0, no cpuid */
        !            83:            : "=r" (psl_check)
        !            84:            : "0" (PSL_ID), "r" (0)
        !            85:            : "cc");
        !            86:
        !            87:        if (psl_check == PSL_ID) {                      /* cpuid supported */
        !            88:                cpuid_max = cpuid(0, regs);             /* Highest std call */
        !            89:
        !            90:                bcopy(&regs[1], cpu_vendor, sizeof(regs[1]));
        !            91:                bcopy(&regs[3], cpu_vendor + 4, sizeof(regs[3]));
        !            92:                bcopy(&regs[2], cpu_vendor + 8, sizeof(regs[2]));
        !            93:                cpu_vendor[sizeof(cpu_vendor) - 1] = '\0';
        !            94:
        !            95:                if (cpuid_max >= 1) {
        !            96:                        u_int32_t id;
        !            97:
        !            98:                        id = cpuid(1, regs);            /* Get basic info */
        !            99:                        cpu_stepping = id & 0x000000f;
        !           100:                        cpu_model = (id >> 4) & 0x0000000f;
        !           101:                        cpu_family = (id >> 8) & 0x0000000f;
        !           102:
        !           103:                        feature_ecx = regs[2];
        !           104:                        feature_edx = regs[3];
        !           105:                }
        !           106:
        !           107:                extended_max = cpuid(0x80000000, regs); /* Highest ext  */
        !           108:
        !           109:                if (extended_max >= 0x80000001) {
        !           110:                        cpuid(0x80000001, regs);
        !           111:                        feature_amd = regs[3];
        !           112:                        if (feature_amd & CPUID_LONG)
        !           113:                                amd64_supported = 1;
        !           114:                }
        !           115:
        !           116:                cpu_brandstr[0] = '\0';
        !           117:                if (extended_max >= 0x80000004) {
        !           118:                        u_int32_t brand_ints[12];
        !           119:
        !           120:                        cpuid(0x80000002, brand_ints);
        !           121:                        cpuid(0x80000003, brand_ints + 4);
        !           122:                        cpuid(0x80000004, brand_ints + 8);
        !           123:
        !           124:                        bcopy(brand_ints, cpu_brandstr,
        !           125:                            sizeof(cpu_brandstr) - 1);
        !           126:
        !           127:                        cpu_brandstr[sizeof(cpu_brandstr) - 1] = '\0';
        !           128:                }
        !           129:        }
        !           130:
        !           131:        printf("%s", amd64_supported ? " amd64" : " i386");
        !           132: }
        !           133:
        !           134: void
        !           135: dump_cpuinfo(void)
        !           136: {
        !           137:        printf("\"%s\", family %d, model %d, step %d\n",
        !           138:            cpu_vendor, cpu_family, cpu_model, cpu_stepping);
        !           139:
        !           140:        if (*cpu_brandstr)
        !           141:                printf("%s\n", cpu_brandstr);
        !           142:
        !           143:        printf("features: ecx 0x%x, edx 0x%x, amd 0x%x\n",
        !           144:            feature_ecx, feature_edx, feature_amd);
        !           145:
        !           146:        printf("psl_check: 0x%x\n", psl_check);
        !           147: }

CVSweb