root/arch/i386/stand/libsa/cpuprobe.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cpuid
  2. cpuprobe
  3. dump_cpuinfo

    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 }

/* [<][>][^][v][top][bottom][index][help] */