15659Sgblack@eecs.umich.edu/*
25659Sgblack@eecs.umich.edu * Copyright (c) 2008 The Regents of The University of Michigan
35659Sgblack@eecs.umich.edu * All rights reserved.
45659Sgblack@eecs.umich.edu *
55659Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
65659Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
75659Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
85659Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
95659Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
105659Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
115659Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
125659Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
135659Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
145659Sgblack@eecs.umich.edu * this software without specific prior written permission.
155659Sgblack@eecs.umich.edu *
165659Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
175659Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
185659Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
195659Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
205659Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
215659Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
225659Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
235659Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
245659Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255659Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
265659Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275659Sgblack@eecs.umich.edu *
285659Sgblack@eecs.umich.edu * Authors: Gabe Black
295659Sgblack@eecs.umich.edu */
305659Sgblack@eecs.umich.edu
315659Sgblack@eecs.umich.edu#include "arch/x86/cpuid.hh"
3211793Sbrandon.potter@amd.com
335659Sgblack@eecs.umich.edu#include "base/bitfield.hh"
345659Sgblack@eecs.umich.edu#include "cpu/thread_context.hh"
355659Sgblack@eecs.umich.edu
365659Sgblack@eecs.umich.edunamespace X86ISA {
375659Sgblack@eecs.umich.edu    enum StandardCpuidFunction {
385659Sgblack@eecs.umich.edu        VendorAndLargestStdFunc,
395659Sgblack@eecs.umich.edu        FamilyModelStepping,
4012463Sswapnilster@gmail.com        CacheAndTLB,
4112463Sswapnilster@gmail.com        SerialNumber,
4212463Sswapnilster@gmail.com        CacheParams,
4312463Sswapnilster@gmail.com        MonitorMwait,
4412463Sswapnilster@gmail.com        ThermalPowerMgmt,
4512463Sswapnilster@gmail.com        ExtendedFeatures,
465659Sgblack@eecs.umich.edu        NumStandardCpuidFuncs
475659Sgblack@eecs.umich.edu    };
485659Sgblack@eecs.umich.edu
495659Sgblack@eecs.umich.edu    enum ExtendedCpuidFunctions {
505659Sgblack@eecs.umich.edu        VendorAndLargestExtFunc,
515659Sgblack@eecs.umich.edu        FamilyModelSteppingBrandFeatures,
525659Sgblack@eecs.umich.edu        NameString1,
535659Sgblack@eecs.umich.edu        NameString2,
545659Sgblack@eecs.umich.edu        NameString3,
555659Sgblack@eecs.umich.edu        L1CacheAndTLB,
565659Sgblack@eecs.umich.edu        L2L3CacheAndL2TLB,
575659Sgblack@eecs.umich.edu        APMInfo,
5810439Smajiuyue@ncic.ac.cn        LongModeAddressSize,
5911320Ssteve.reinhardt@amd.com
605659Sgblack@eecs.umich.edu        /*
615659Sgblack@eecs.umich.edu         * The following are defined by the spec but not yet implemented
625659Sgblack@eecs.umich.edu         */
6310439Smajiuyue@ncic.ac.cn/*      // Function 9 is reserved
645659Sgblack@eecs.umich.edu        SVMInfo = 10,
655659Sgblack@eecs.umich.edu        // Functions 11-24 are reserved
665659Sgblack@eecs.umich.edu        TLB1GBPageInfo = 25,
675659Sgblack@eecs.umich.edu        PerformanceInfo,*/
685659Sgblack@eecs.umich.edu
695659Sgblack@eecs.umich.edu        NumExtendedCpuidFuncs
705659Sgblack@eecs.umich.edu    };
715659Sgblack@eecs.umich.edu
725659Sgblack@eecs.umich.edu    static const int vendorStringSize = 13;
736040Sgblack@eecs.umich.edu    static const char vendorString[vendorStringSize] = "M5 Simulator";
745659Sgblack@eecs.umich.edu    static const int nameStringSize = 48;
755659Sgblack@eecs.umich.edu    static const char nameString[nameStringSize] = "Fake M5 x86_64 CPU";
765659Sgblack@eecs.umich.edu
775659Sgblack@eecs.umich.edu    uint64_t
785659Sgblack@eecs.umich.edu    stringToRegister(const char *str)
795659Sgblack@eecs.umich.edu    {
805659Sgblack@eecs.umich.edu        uint64_t reg = 0;
815659Sgblack@eecs.umich.edu        for (int pos = 3; pos >=0; pos--) {
825659Sgblack@eecs.umich.edu            reg <<= 8;
835659Sgblack@eecs.umich.edu            reg |= str[pos];
845659Sgblack@eecs.umich.edu        }
855659Sgblack@eecs.umich.edu        return reg;
865659Sgblack@eecs.umich.edu    }
875659Sgblack@eecs.umich.edu
885659Sgblack@eecs.umich.edu    bool
897072Sgblack@eecs.umich.edu    doCpuid(ThreadContext * tc, uint32_t function,
907072Sgblack@eecs.umich.edu            uint32_t index, CpuidResult &result)
915659Sgblack@eecs.umich.edu    {
925659Sgblack@eecs.umich.edu        uint16_t family = bits(function, 31, 16);
935659Sgblack@eecs.umich.edu        uint16_t funcNum = bits(function, 15, 0);
945659Sgblack@eecs.umich.edu        if (family == 0x8000) {
955659Sgblack@eecs.umich.edu            // The extended functions
965659Sgblack@eecs.umich.edu            switch (funcNum) {
975659Sgblack@eecs.umich.edu              case VendorAndLargestExtFunc:
985659Sgblack@eecs.umich.edu                assert(vendorStringSize >= 12);
995659Sgblack@eecs.umich.edu                result = CpuidResult(
1006052Sgblack@eecs.umich.edu                        0x80000000 + NumExtendedCpuidFuncs - 1,
1015659Sgblack@eecs.umich.edu                        stringToRegister(vendorString),
1025659Sgblack@eecs.umich.edu                        stringToRegister(vendorString + 4),
1035659Sgblack@eecs.umich.edu                        stringToRegister(vendorString + 8));
1045659Sgblack@eecs.umich.edu                break;
1055659Sgblack@eecs.umich.edu              case FamilyModelSteppingBrandFeatures:
1065659Sgblack@eecs.umich.edu                result = CpuidResult(0x00020f51, 0x00000405,
10710637Sgabeblack@google.com                                     0xe3d3fbff, 0x00000001);
1085659Sgblack@eecs.umich.edu                break;
1095659Sgblack@eecs.umich.edu              case NameString1:
1105659Sgblack@eecs.umich.edu              case NameString2:
1115659Sgblack@eecs.umich.edu              case NameString3:
1125659Sgblack@eecs.umich.edu                {
1135659Sgblack@eecs.umich.edu                    // Zero fill anything beyond the end of the string. This
1145659Sgblack@eecs.umich.edu                    // should go away once the string is a vetted parameter.
1155659Sgblack@eecs.umich.edu                    char cleanName[nameStringSize];
1165659Sgblack@eecs.umich.edu                    memset(cleanName, '\0', nameStringSize);
1175659Sgblack@eecs.umich.edu                    strncpy(cleanName, nameString, nameStringSize);
1185659Sgblack@eecs.umich.edu
1195659Sgblack@eecs.umich.edu                    int offset = (funcNum - NameString1) * 16;
1205659Sgblack@eecs.umich.edu                    assert(nameStringSize >= offset + 16);
1215659Sgblack@eecs.umich.edu                    result = CpuidResult(
1225659Sgblack@eecs.umich.edu                            stringToRegister(cleanName + offset + 0),
1235659Sgblack@eecs.umich.edu                            stringToRegister(cleanName + offset + 4),
1246068Sgblack@eecs.umich.edu                            stringToRegister(cleanName + offset + 12),
1256068Sgblack@eecs.umich.edu                            stringToRegister(cleanName + offset + 8));
1265659Sgblack@eecs.umich.edu                }
1275659Sgblack@eecs.umich.edu                break;
1285659Sgblack@eecs.umich.edu              case L1CacheAndTLB:
1295659Sgblack@eecs.umich.edu                result = CpuidResult(0xff08ff08, 0xff20ff20,
1305659Sgblack@eecs.umich.edu                                     0x40020140, 0x40020140);
1315659Sgblack@eecs.umich.edu                break;
1325659Sgblack@eecs.umich.edu              case L2L3CacheAndL2TLB:
1335659Sgblack@eecs.umich.edu                result = CpuidResult(0x00000000, 0x42004200,
1345659Sgblack@eecs.umich.edu                                     0x00000000, 0x04008140);
1355659Sgblack@eecs.umich.edu                break;
1365659Sgblack@eecs.umich.edu              case APMInfo:
1375659Sgblack@eecs.umich.edu                result = CpuidResult(0x80000018, 0x68747541,
1385659Sgblack@eecs.umich.edu                                     0x69746e65, 0x444d4163);
1395659Sgblack@eecs.umich.edu                break;
14010439Smajiuyue@ncic.ac.cn              case LongModeAddressSize:
14110539Sgabeblack@google.com                result = CpuidResult(0x00003030, 0x00000000,
14210439Smajiuyue@ncic.ac.cn                                     0x00000000, 0x00000000);
14310439Smajiuyue@ncic.ac.cn                break;
14410439Smajiuyue@ncic.ac.cn/*            case SVMInfo:
1455659Sgblack@eecs.umich.edu              case TLB1GBPageInfo:
1465659Sgblack@eecs.umich.edu              case PerformanceInfo:*/
1475659Sgblack@eecs.umich.edu              default:
14811217Sbaz21@cam.ac.uk                warn("x86 cpuid family 0x8000: unimplemented function %u",
14911217Sbaz21@cam.ac.uk                    funcNum);
1505659Sgblack@eecs.umich.edu                return false;
1515659Sgblack@eecs.umich.edu            }
15211321Ssteve.reinhardt@amd.com        } else if (family == 0x0000) {
1535659Sgblack@eecs.umich.edu            // The standard functions
1545659Sgblack@eecs.umich.edu            switch (funcNum) {
1555659Sgblack@eecs.umich.edu              case VendorAndLargestStdFunc:
1565659Sgblack@eecs.umich.edu                assert(vendorStringSize >= 12);
1575659Sgblack@eecs.umich.edu                result = CpuidResult(
1585659Sgblack@eecs.umich.edu                        NumStandardCpuidFuncs - 1,
1595659Sgblack@eecs.umich.edu                        stringToRegister(vendorString),
1605659Sgblack@eecs.umich.edu                        stringToRegister(vendorString + 4),
1615659Sgblack@eecs.umich.edu                        stringToRegister(vendorString + 8));
1625659Sgblack@eecs.umich.edu                break;
1635659Sgblack@eecs.umich.edu              case FamilyModelStepping:
1649473Snilay@cs.wisc.edu                result = CpuidResult(0x00020f51, 0x00000805,
16514165Sgabeblack@google.com                                     0xe7dbfbff, 0x00000209);
1665659Sgblack@eecs.umich.edu                break;
16712463Sswapnilster@gmail.com              case ExtendedFeatures:
16812463Sswapnilster@gmail.com                result = CpuidResult(0x00000000, 0x01800000,
16912463Sswapnilster@gmail.com                                     0x00000000, 0x00000000);
17012463Sswapnilster@gmail.com                break;
1715659Sgblack@eecs.umich.edu              default:
17211217Sbaz21@cam.ac.uk                warn("x86 cpuid family 0x0000: unimplemented function %u",
17311217Sbaz21@cam.ac.uk                    funcNum);
1745659Sgblack@eecs.umich.edu                return false;
1755659Sgblack@eecs.umich.edu            }
1769124Snilay@cs.wisc.edu        } else {
1779124Snilay@cs.wisc.edu            warn("x86 cpuid: unknown family %#x", family);
1789124Snilay@cs.wisc.edu            return false;
1795659Sgblack@eecs.umich.edu        }
1809124Snilay@cs.wisc.edu
1815659Sgblack@eecs.umich.edu        return true;
1825659Sgblack@eecs.umich.edu    }
1837811Ssteve.reinhardt@amd.com} // namespace X86ISA
184