root/arch/i386/i386/p4tcc.c

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

DEFINITIONS

This source file includes following definitions.
  1. p4tcc_init
  2. p4tcc_cpuspeed
  3. p4tcc_setperf

    1 /*      $OpenBSD: p4tcc.c,v 1.14 2007/08/03 20:36:02 deraadt Exp $ */
    2 /*
    3  * Copyright (c) 2003 Ted Unangst
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   20  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
   22  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   23  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  */
   27 /*
   28  * Restrict power consumption by using thermal control circuit.
   29  * This operates independently of speedstep.
   30  * Found on Pentium 4 and later models (feature TM).
   31  *
   32  * References:
   33  * Intel Developer's manual v.3 #245472-012
   34  *
   35  * On some models, the cpu can hang if it's running at a slow speed.
   36  * Workarounds included below.
   37  */
   38 
   39 #include <sys/param.h>
   40 #include <sys/sysctl.h>
   41 
   42 #include <machine/cpu.h>
   43 #include <machine/cpufunc.h>
   44 #include <machine/specialreg.h>
   45 
   46 static struct {
   47         u_short level;
   48         u_short reg;
   49 } tcc[] = {
   50         { 88, 0 },
   51         { 75, 7 },
   52         { 63, 6 },
   53         { 50, 5 },
   54         { 38, 4 },
   55         { 25, 3 },
   56         { 13, 2 },
   57         { 0, 1 }
   58 };
   59 
   60 #define TCC_LEVELS sizeof(tcc) / sizeof(tcc[0])
   61 
   62 extern int setperf_prio;
   63 int p4tcc_level;
   64 
   65 int p4tcc_cpuspeed(int *);
   66 
   67 void
   68 p4tcc_init(int family, int step)
   69 {
   70         if (setperf_prio > 1)
   71                 return;
   72 
   73         switch (family) {
   74         case 0xf:       /* Pentium 4 */
   75                 switch (step) {
   76                 case 0x22:      /* errata O50 P44 and Z21 */
   77                 case 0x24:
   78                 case 0x25:
   79                 case 0x27:
   80                 case 0x29:
   81                         /* hang with 12.5 */
   82                         tcc[TCC_LEVELS - 1].reg = 2;
   83                         break;
   84                 case 0x07:      /* errata N44 and P18 */
   85                 case 0x0a:
   86                 case 0x12:
   87                 case 0x13:
   88                         /* hang at 12.5 and 25 */
   89                         tcc[TCC_LEVELS - 1].reg = 3;
   90                         tcc[TCC_LEVELS - 2].reg = 3;
   91                         break;
   92                 }
   93                 break;
   94         }
   95 
   96         p4tcc_level = tcc[0].level;
   97         cpu_setperf = p4tcc_setperf;
   98         cpu_cpuspeed = p4tcc_cpuspeed;
   99         setperf_prio = 1;
  100 }
  101 
  102 int
  103 p4tcc_cpuspeed(int *speed)
  104 {
  105         *speed = cpuspeed * (p4tcc_level + 12) / 100;
  106 
  107         return 0;
  108 }
  109 
  110 void
  111 p4tcc_setperf(int level)
  112 {
  113         int i;
  114         uint64_t msreg, vet;
  115 
  116         for (i = 0; i < TCC_LEVELS; i++) {
  117                 if (level >= tcc[i].level)
  118                         break;
  119         }
  120 
  121         msreg = rdmsr(MSR_THERM_CONTROL);
  122         msreg &= ~0x1e; /* bit 0 reserved */
  123         if (tcc[i].reg != 0) /* enable it */
  124                 msreg |= tcc[i].reg << 1 | 1 << 4;
  125         wrmsr(MSR_THERM_CONTROL, msreg);
  126         vet = rdmsr(MSR_THERM_CONTROL);
  127 
  128         if ((vet & 0x1e) != (msreg & 0x1e))
  129                 printf("p4_tcc: cpu did not honor request\n");
  130         else
  131                 p4tcc_level = tcc[i].level;
  132 }

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