[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

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