[BACK]Return to cpu.c CVS log [TXT][DIR] Up to [local] / prex / dev / i386 / i386

Annotation of prex/dev/i386/i386/cpu.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: est.c,v 1.11 2005/03/07 06:59:14 mbalmer Exp $ */
                      2: /*
                      3:  * Copyright (c) 2003 Michael Eriksson.
                      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:  * 3. The name of the author may not be used to endorse or promote products
                     15:  *    derived from this software without specific prior written permission.
                     16:  *
                     17:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     18:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     19:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     20:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     21:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     22:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     23:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     24:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     25:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     26:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     27:  */
                     28: /*
                     29:  * This is a driver for Intel's Enhanced SpeedStep, as implemented in
                     30:  * Pentium M processors.
                     31:  *
                     32:  * Reference documentation:
                     33:  *
                     34:  * - IA-32 Intel Architecture Software Developer's Manual, Volume 3:
                     35:  *   System Programming Guide.
                     36:  *   Section 13.14, Enhanced Intel SpeedStep technology.
                     37:  *   Table B-2, MSRs in Pentium M Processors.
                     38:  *   http://www.intel.com/design/pentium4/manuals/245472.htm
                     39:  *
                     40:  * - Intel Pentium M Processor Datasheet.
                     41:  *   Table 5, Voltage and Current Specifications.
                     42:  *   http://www.intel.com/design/mobile/datashts/252612.htm
                     43:  *
                     44:  * - Intel Pentium M Processor on 90 nm Process with 2-MB L2 Cache Datasheet
                     45:  *   Table 3-4, Voltage and Current Specifications.
                     46:  *   http://www.intel.com/design/mobile/datashts/302189.htm
                     47:  *
                     48:  * - Linux cpufreq patches, speedstep-centrino.c.
                     49:  *   Encoding of MSR_PERF_CTL and MSR_PERF_STATUS.
                     50:  *   http://www.codemonkey.org.uk/projects/cpufreq/cpufreq-2.4.22-pre6-1.gz
                     51:  */
                     52:
                     53: /*
                     54:  * cpu.c - Processor driver for Intel CPU
                     55:  */
                     56:
                     57: #include <driver.h>
                     58: #include <sys/ioctl.h>
                     59: #include <cpufunc.h>
                     60:
                     61: /* #define DEBUG_CPU 1 */
                     62:
                     63: #ifdef DEBUG
                     64: #define DPRINTF(a) printf a
                     65: #else
                     66: #define DPRINTF(a)
                     67: #endif
                     68:
                     69: /* Status/control registers (from the IA-32 System Programming Guide). */
                     70: #define MSR_PERF_STATUS                0x198
                     71: #define MSR_PERF_CTL           0x199
                     72:
                     73: /* Register and bit for enabling SpeedStep. */
                     74: #define MSR_MISC_ENABLE                0x1a0
                     75: #define MSR_SS_ENABLE          (1<<16)
                     76:
                     77: static int cpu_ioctl(device_t dev, u_long cmd, void *arg);
                     78: static int cpu_init(void);
                     79:
                     80: /*
                     81:  * Driver structure
                     82:  */
                     83: struct driver cpu_drv = {
                     84:        /* name */      "Processor",
                     85:        /* order */     1,
                     86:        /* init */      cpu_init,
                     87: };
                     88:
                     89: static struct devio cpu_io = {
                     90:        /* open */      NULL,
                     91:        /* close */     NULL,
                     92:        /* read */      NULL,
                     93:        /* write */     NULL,
                     94:        /* ioctl */     cpu_ioctl,
                     95:        /* event */     NULL,
                     96: };
                     97:
                     98: static device_t cpu_dev;               /* Device object */
                     99:
                    100: /*
                    101:  * Frequency tables
                    102:  */
                    103: struct fq_info {
                    104:        u_short mhz;
                    105:        u_short mv;
                    106: };
                    107:
                    108: /* Ultra Low Voltage Intel Pentium M processor 900 MHz */
                    109: static const struct fq_info pentium_m_900[] = {
                    110:        {  900, 1004 },
                    111:        {  800,  988 },
                    112:        {  600,  844 },
                    113: };
                    114:
                    115: /* Ultra Low Voltage Intel Pentium M processor 1.00 GHz */
                    116: static const struct fq_info pentium_m_1000[] = {
                    117:        { 1000, 1004 },
                    118:        {  900,  988 },
                    119:        {  800,  972 },
                    120:        {  600,  844 },
                    121: };
                    122:
                    123: /* Low Voltage Intel Pentium M processor 1.10 GHz */
                    124: static const struct fq_info pentium_m_1100[] = {
                    125:        { 1100, 1180 },
                    126:        { 1000, 1164 },
                    127:        {  900, 1100 },
                    128:        {  800, 1020 },
                    129:        {  600,  956 },
                    130: };
                    131:
                    132: /* Low Voltage Intel Pentium M processor 1.20 GHz */
                    133: static const struct fq_info pentium_m_1200[] = {
                    134:        { 1200, 1180 },
                    135:        { 1100, 1164 },
                    136:        { 1000, 1100 },
                    137:        {  900, 1020 },
                    138:        {  800, 1004 },
                    139:        {  600,  956 },
                    140: };
                    141:
                    142: /* Intel Pentium M processor 1.30 GHz */
                    143: static const struct fq_info pentium_m_1300[] = {
                    144:        { 1300, 1388 },
                    145:        { 1200, 1356 },
                    146:        { 1000, 1292 },
                    147:        {  800, 1260 },
                    148:        {  600,  956 },
                    149: };
                    150:
                    151: /* Intel Pentium M processor 1.40 GHz */
                    152: static const struct fq_info pentium_m_1400[] = {
                    153:        { 1400, 1484 },
                    154:        { 1200, 1436 },
                    155:        { 1000, 1308 },
                    156:        {  800, 1180 },
                    157:        {  600,  956 }
                    158: };
                    159:
                    160: /* Intel Pentium M processor 1.50 GHz */
                    161: static const struct fq_info pentium_m_1500[] = {
                    162:        { 1500, 1484 },
                    163:        { 1400, 1452 },
                    164:        { 1200, 1356 },
                    165:        { 1000, 1228 },
                    166:        {  800, 1116 },
                    167:        {  600,  956 }
                    168: };
                    169:
                    170: /* Intel Pentium M processor 1.60 GHz */
                    171: static const struct fq_info pentium_m_1600[] = {
                    172:        { 1600, 1484 },
                    173:        { 1400, 1420 },
                    174:        { 1200, 1276 },
                    175:        { 1000, 1164 },
                    176:        {  800, 1036 },
                    177:        {  600,  956 }
                    178: };
                    179:
                    180: /* Intel Pentium M processor 1.70 GHz */
                    181: static const struct fq_info pentium_m_1700[] = {
                    182:        { 1700, 1484 },
                    183:        { 1400, 1308 },
                    184:        { 1200, 1228 },
                    185:        { 1000, 1116 },
                    186:        {  800, 1004 },
                    187:        {  600,  956 }
                    188: };
                    189:
                    190:
                    191: /* Intel Pentium M processor 723 1.0 GHz */
                    192: static const struct fq_info pentium_m_n723[] = {
                    193:        { 1000,  940 },
                    194:        {  900,  908 },
                    195:        {  800,  876 },
                    196:        {  600,  812 }
                    197: };
                    198:
                    199: /* Intel Pentium M processor 733 1.1 GHz */
                    200: static const struct fq_info pentium_m_n733[] = {
                    201:        { 1100,  940 },
                    202:        { 1000,  924 },
                    203:        {  900,  892 },
                    204:        {  800,  876 },
                    205:        {  600,  812 }
                    206: };
                    207:
                    208: /* Intel Pentium M processor 753 1.2 GHz */
                    209: static const struct fq_info pentium_m_n753[] = {
                    210:        { 1200,  940 },
                    211:        { 1100,  924 },
                    212:        { 1000,  908 },
                    213:        {  900,  876 },
                    214:        {  800,  860 },
                    215:        {  600,  812 }
                    216: };
                    217:
                    218: /* Intel Pentium M processor 738 1.4 GHz */
                    219: static const struct fq_info pentium_m_n738[] = {
                    220:        { 1400, 1116 },
                    221:        { 1300, 1116 },
                    222:        { 1200, 1100 },
                    223:        { 1100, 1068 },
                    224:        { 1000, 1052 },
                    225:        {  900, 1036 },
                    226:        {  800, 1020 },
                    227:        {  600,  988 }
                    228: };
                    229:
                    230: #if 0
                    231: /* Intel Pentium M processor 758 1.5 GHz */
                    232: static const struct fq_info pentium_m_n758[] = {
                    233:        { 1500, 1116 },
                    234:        { 1400, 1116 },
                    235:        { 1300, 1100 },
                    236:        { 1200, 1084 },
                    237:        { 1100, 1068 },
                    238:        { 1000, 1052 },
                    239:        {  900, 1036 },
                    240:        {  800, 1020 },
                    241:        {  600,  988 }
                    242: };
                    243: #endif
                    244:
                    245: /* Intel Pentium M processor 715 1.5 GHz */
                    246: static const struct fq_info pentium_m_n715[] = {
                    247:        { 1500, 1340 },
                    248:        { 1200, 1228 },
                    249:        { 1000, 1148 },
                    250:        {  800, 1068 },
                    251:        {  600,  988 }
                    252: };
                    253:
                    254: /* Intel Pentium M processor 725 1.6 GHz */
                    255: static const struct fq_info pentium_m_n725[] = {
                    256:        { 1600, 1340 },
                    257:        { 1400, 1276 },
                    258:        { 1200, 1212 },
                    259:        { 1000, 1132 },
                    260:        {  800, 1068 },
                    261:        {  600,  988 }
                    262: };
                    263:
                    264: /* Intel Pentium M processor 735 1.7 GHz */
                    265: static const struct fq_info pentium_m_n735[] = {
                    266:        { 1700, 1340 },
                    267:        { 1400, 1244 },
                    268:        { 1200, 1180 },
                    269:        { 1000, 1116 },
                    270:        {  800, 1052 },
                    271:        {  600,  988 }
                    272: };
                    273:
                    274: /* Intel Pentium M processor 745 1.8 GHz */
                    275: static const struct fq_info pentium_m_n745[] = {
                    276:        { 1800, 1340 },
                    277:        { 1600, 1292 },
                    278:        { 1400, 1228 },
                    279:        { 1200, 1164 },
                    280:        { 1000, 1116 },
                    281:        {  800, 1052 },
                    282:        {  600,  988 }
                    283: };
                    284:
                    285: /* Intel Pentium M processor 755 2.0 GHz */
                    286: static const struct fq_info pentium_m_n755[] = {
                    287:        { 2000, 1340 },
                    288:        { 1800, 1292 },
                    289:        { 1600, 1244 },
                    290:        { 1400, 1196 },
                    291:        { 1200, 1148 },
                    292:        { 1000, 1100 },
                    293:        {  800, 1052 },
                    294:        {  600,  988 }
                    295: };
                    296:
                    297: /* Intel Pentium M processor 765 2.1 GHz */
                    298: static const struct fq_info pentium_m_n765[] = {
                    299:        { 2100, 1340 },
                    300:        { 1800, 1276 },
                    301:        { 1600, 1228 },
                    302:        { 1400, 1180 },
                    303:        { 1200, 1132 },
                    304:        { 1000, 1084 },
                    305:        {  800, 1036 },
                    306:        {  600,  988 }
                    307: };
                    308:
                    309: struct fqlist {
                    310:        const char *brand_tag;
                    311:        const struct fq_info *table;
                    312:        int n;
                    313: };
                    314:
                    315: static const struct fqlist pentium_m[] = {
                    316: #define ENTRY(s, v)    { s, v, sizeof(v) / sizeof((v)[0]) }
                    317:        ENTRY(" 900", pentium_m_900),
                    318:        ENTRY("1000", pentium_m_1000),
                    319:        ENTRY("1100", pentium_m_1100),
                    320:        ENTRY("1200", pentium_m_1200),
                    321:        ENTRY("1300", pentium_m_1300),
                    322:        ENTRY("1400", pentium_m_1400),
                    323:        ENTRY("1500", pentium_m_1500),
                    324:        ENTRY("1600", pentium_m_1600),
                    325:        ENTRY("1700", pentium_m_1700),
                    326: #undef ENTRY
                    327: };
                    328:
                    329: static const struct fqlist pentium_m_dothan[] = {
                    330: #define ENTRY(s, v)    { s, v, sizeof(v) / sizeof((v)[0]) }
                    331:        ENTRY("1.00", pentium_m_n723),
                    332:        ENTRY("1.10", pentium_m_n733),
                    333:        ENTRY("1.20", pentium_m_n753),
                    334:        ENTRY("1.40", pentium_m_n738),
                    335: #if 0
                    336:        ENTRY("1.50", pentium_m_n758),
                    337: #endif
                    338:        ENTRY("1.50", pentium_m_n715),
                    339:        ENTRY("1.60", pentium_m_n725),
                    340:        ENTRY("1.70", pentium_m_n735),
                    341:        ENTRY("1.80", pentium_m_n745),
                    342:        ENTRY("2.00", pentium_m_n755),
                    343:        ENTRY("2.10", pentium_m_n765),
                    344: #undef ENTRY
                    345: };
                    346:
                    347: struct est_cpu {
                    348:        const char *brand_prefix;
                    349:        const char *brand_suffix;
                    350:        const struct fqlist *list;
                    351:        int n;
                    352: };
                    353:
                    354: static const struct est_cpu est_cpus[] = {
                    355:        {
                    356:                "Intel(R) Pentium(R) M processor ", "MHz",
                    357:                pentium_m,
                    358:                (sizeof(pentium_m) / sizeof(pentium_m[0]))
                    359:        },
                    360:        {
                    361:                "Intel(R) Pentium(R) M processor ", "GHz",
                    362:                pentium_m_dothan,
                    363:                (sizeof(pentium_m_dothan) / sizeof(pentium_m_dothan[0]))
                    364:        },
                    365: };
                    366:
                    367: #define NESTCPUS         (int)(sizeof(est_cpus) / sizeof(est_cpus[0]))
                    368:
                    369:
                    370: #define MSRVALUE(mhz, mv)      ((((mhz) / 100) << 8) | (((mv) - 700) / 16))
                    371: #define MSR2MHZ(msr)           ((((u_int) (msr) >> 8) & 0xff) * 100)
                    372: #define MSR2MV(msr)            (((int) (msr) & 0xff) * 16 + 700)
                    373:
                    374: static const struct fqlist *est_fqlist;
                    375:
                    376: static struct cpu_info cpu_info;
                    377: static struct cpu_stat cpu_stat;
                    378: #ifdef CONFIG_DVS_EMULATION
                    379: static int bochs;
                    380: #endif
                    381:
                    382: /*
                    383:  * Set CPU performance
                    384:  *
                    385:  * @level: percent of cpu speed
                    386:  */
                    387: int
                    388: cpu_setperf(int level)
                    389: {
                    390:        int i, fq;
                    391:        u_int msr_lo, msr_hi;
                    392:        int max_mhz;
                    393:
                    394:        ASSERT(cpu_info.clock_ctrl);
                    395:
                    396:        max_mhz = est_fqlist->table[0].mhz;
                    397:        fq = max_mhz * level / 100;
                    398:
                    399:        for (i = est_fqlist->n - 1; i > 0; i--)
                    400:                if (est_fqlist->table[i].mhz >= fq)
                    401:                        break;
                    402:
                    403:        if (est_fqlist->table[i].mhz == cpu_stat.speed)
                    404:                return 0;
                    405:
                    406:        cpu_stat.speed = est_fqlist->table[i].mhz;
                    407:        cpu_stat.power = est_fqlist->table[i].mv;
                    408: #ifdef DEBUG_CPU
                    409:        DPRINTF(("setperf: %dMHz %dmV\n", cpu_stat.speed, cpu_stat.power));
                    410: #endif
                    411: #ifdef CONFIG_DVS_EMULATION
                    412:        if (bochs)
                    413:                return 0;
                    414: #endif
                    415:        rdmsr(MSR_PERF_CTL, &msr_lo, &msr_hi);
                    416:        msr_lo = (msr_lo & ~0xffff) |
                    417:                MSRVALUE(est_fqlist->table[i].mhz, est_fqlist->table[i].mv);
                    418:        wrmsr(MSR_PERF_CTL, msr_lo, msr_hi);
                    419:        return 0;
                    420: }
                    421:
                    422: /*
                    423:  * Get CPU performance
                    424:  */
                    425: int
                    426: cpu_getperf(void)
                    427: {
                    428:        int max_mhz;
                    429:        int level;
                    430:
                    431:        ASSERT(cpu_info.clock_ctrl);
                    432:
                    433:        max_mhz = est_fqlist->table[0].mhz;
                    434:        ASSERT(max_mhz);
                    435:        level = cpu_stat.speed * 100 / max_mhz;
                    436:        return level;
                    437: }
                    438:
                    439: /*
                    440:  * Initialize CPU performance
                    441:  * Return false on error.
                    442:  */
                    443: int
                    444: cpu_initperf(void)
                    445: {
                    446:        int i, j, n, mhz, mv;
                    447:        const struct est_cpu *cpu;
                    448:        u_int msr_lo, msr_hi;
                    449:        char *tag, *brand_str;
                    450:        const struct fqlist *fql;
                    451:
                    452:        if (!cpu_info.clock_ctrl)
                    453:                return -1;
                    454:
                    455: #ifdef CONFIG_DVS_EMULATION
                    456:        if (bochs) {
                    457:                msr_lo = 0x1031;
                    458:                cpu = &est_cpus[0];
                    459:                est_fqlist = &cpu->list[7];
                    460:        } else
                    461:                rdmsr(MSR_PERF_STATUS, &msr_lo, &msr_hi);
                    462: #else
                    463:        rdmsr(MSR_PERF_STATUS, &msr_lo, &msr_hi);
                    464: #endif
                    465:
                    466:        mhz = MSR2MHZ(msr_lo);
                    467:        mv = MSR2MV(msr_lo);
                    468:        DPRINTF(("Enhanced SpeedStep %d MHz (%d mV)\n", mhz, mv));
                    469:
                    470: #ifdef CONFIG_DVS_EMULATION
                    471:        if (!bochs) {
                    472: #endif
                    473:        /*
                    474:         * Look for a CPU matching brand_str.
                    475:         */
                    476:        brand_str = cpu_info.name;
                    477:        for (i = 0; est_fqlist == NULL && i < NESTCPUS; i++) {
                    478:                cpu = &est_cpus[i];
                    479:                n = strnlen(cpu->brand_prefix, 48);
                    480:                if (strncmp(cpu->brand_prefix, brand_str, n) != 0)
                    481:                        continue;
                    482:                tag = brand_str + n;
                    483:                for (j = 0; j < cpu->n; j++) {
                    484:                        fql = &cpu->list[j];
                    485:                        n = strnlen(fql->brand_tag, 48);
                    486:                        if (!strncmp(fql->brand_tag, tag, n) &&
                    487:                            !strncmp(cpu->brand_suffix, tag + n, 48)) {
                    488:                                est_fqlist = fql;
                    489:                                break;
                    490:                        }
                    491:                }
                    492:        }
                    493:        if (est_fqlist == NULL) {
                    494:                DPRINTF(("Unknown EST cpu, no changes possible\n"));
                    495:                cpu_info.clock_ctrl = 0;
                    496:                return -1;
                    497:        }
                    498:
                    499:        /*
                    500:         * Check that the current operating point is in our list.
                    501:         */
                    502:        for (i = est_fqlist->n - 1; i >= 0; i--)
                    503:                if (est_fqlist->table[i].mhz == mhz)
                    504:                        break;
                    505:        if (i < 0) {
                    506:                DPRINTF((" (not in table)\n"));
                    507:                cpu_info.clock_ctrl = 0;
                    508:                return -1;
                    509:        }
                    510: #ifdef CONFIG_DVS_EMULATION
                    511:        }
                    512: #endif
                    513:        /*
                    514:         * Store current state
                    515:         */
                    516:        cpu_info.speed = est_fqlist->table[0].mhz;
                    517:        cpu_info.power = est_fqlist->table[0].mv;
                    518:        cpu_stat.speed = mhz;
                    519:        cpu_stat.power = mv;
                    520:
                    521:        /*
                    522:         * OK, tell the user the available frequencies.
                    523:         */
                    524: #ifdef DEBUG
                    525:        printf("Speeds: ");
                    526:        for (i = 0; i < est_fqlist->n; i++)
                    527:                printf("%d%s", est_fqlist->table[i].mhz,
                    528:                       i < est_fqlist->n - 1 ? ", " : " MHz\n");
                    529: #endif
                    530:        return 0;
                    531: }
                    532:
                    533: static int
                    534: cpu_ioctl(device_t dev, u_long cmd, void *arg)
                    535: {
                    536:
                    537:        switch (cmd) {
                    538:        case CPUIOC_GET_INFO:
                    539:                if (umem_copyout(&cpu_info, arg, sizeof(cpu_info)))
                    540:                        return EFAULT;
                    541:                break;
                    542:        case CPUIOC_GET_STAT:
                    543:                if (umem_copyout(&cpu_stat, arg, sizeof(cpu_stat)))
                    544:                        return EFAULT;
                    545:                break;
                    546:        default:
                    547:                return EINVAL;
                    548:        }
                    549:        return 0;
                    550: }
                    551:
                    552: /*
                    553:  * Initialize CPU addon feature
                    554:  *
                    555:  * FIXME: i486 does not support cpuid instruction
                    556:  */
                    557: static int
                    558: cpu_init(void)
                    559: {
                    560:        u_int regs[4];
                    561:        char brand_str[49];
                    562:        char *p, *q;
                    563:
                    564:        /* Create device object */
                    565:        cpu_dev = device_create(&cpu_io, "cpu", DF_CHR);
                    566:        ASSERT(cpu_dev);
                    567:
                    568: #ifdef CONFIG_DVS_EMULATION
                    569:        bochs = 0;
                    570:        if (inb(0xe9) == 0xe9) {
                    571:                /*
                    572:                 * Detect Bochs. Fake the cpuid value.
                    573:                 */
                    574:                bochs = 1;
                    575:                cpu_info.id = 0x6d6;
                    576:                cpu_info.clock_ctrl = 1;
                    577:                strncpy(cpu_info.name,
                    578:                        "Intel(R) Pentium(R) M processor 1600MHz", 50);
                    579:
                    580:                DPRINTF(("CPU ID: %08x\n", cpu_info.id));
                    581:                DPRINTF(("CPU brand: %s\n", cpu_info.name));
                    582:                return 0;
                    583:        }
                    584: #endif
                    585:        /*
                    586:         * Check enhanced speed step capability
                    587:         */
                    588:        cpuid(1, regs);
                    589:        cpu_info.id = regs[0];
                    590:        DPRINTF(("CPU ID: %08x\n", regs[0]));
                    591:
                    592:        if ((regs[2] & 0x80) == 0) {
                    593:                DPRINTF(("cpu: Clock control not supported\n"));
                    594:                cpu_info.clock_ctrl = 0;
                    595:                return 0;
                    596:        }
                    597:        cpu_info.clock_ctrl = 1;
                    598:
                    599:        /*
                    600:         * Get CPU brand string
                    601:         */
                    602:        cpuid(0x80000002, regs);
                    603:        memcpy(brand_str, regs, sizeof(regs));
                    604:        cpuid(0x80000003, regs);
                    605:        memcpy(brand_str + 16, regs, sizeof(regs));
                    606:        cpuid(0x80000004, regs);
                    607:        memcpy(brand_str + 32, regs, sizeof(regs));
                    608:
                    609:        /* Store string with lef-align */
                    610:        q = &cpu_info.name[0];
                    611:        p = brand_str;
                    612:        while (*p == ' ')
                    613:                p++;
                    614:        while (*p)
                    615:                *q++ = *p++;
                    616:        *q = '\0';
                    617:
                    618:        DPRINTF(("CPU brand: %s\n", cpu_info.name));
                    619:        return 0;
                    620: }

CVSweb