cpuid.cc revision 9473
12SN/A/*
21762SN/A * Copyright (c) 2008 The Regents of The University of Michigan
32SN/A * All rights reserved.
42SN/A *
52SN/A * Redistribution and use in source and binary forms, with or without
62SN/A * modification, are permitted provided that the following conditions are
72SN/A * met: redistributions of source code must retain the above copyright
82SN/A * notice, this list of conditions and the following disclaimer;
92SN/A * redistributions in binary form must reproduce the above copyright
102SN/A * notice, this list of conditions and the following disclaimer in the
112SN/A * documentation and/or other materials provided with the distribution;
122SN/A * neither the name of the copyright holders nor the names of its
132SN/A * contributors may be used to endorse or promote products derived from
142SN/A * this software without specific prior written permission.
152SN/A *
162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu *
282665Ssaidi@eecs.umich.edu * Authors: Gabe Black
292665Ssaidi@eecs.umich.edu */
302SN/A
312SN/A#include "arch/x86/cpuid.hh"
322SN/A#include "base/bitfield.hh"
332SN/A#include "cpu/thread_context.hh"
342SN/A
352520SN/Anamespace X86ISA {
362207SN/A    enum StandardCpuidFunction {
372207SN/A        VendorAndLargestStdFunc,
386214Snate@binkert.org        FamilyModelStepping,
392SN/A        NumStandardCpuidFuncs
402519SN/A    };
412SN/A
422SN/A    enum ExtendedCpuidFunctions {
432SN/A        VendorAndLargestExtFunc,
442SN/A        FamilyModelSteppingBrandFeatures,
45360SN/A        NameString1,
46360SN/A        NameString2,
47360SN/A        NameString3,
48360SN/A        L1CacheAndTLB,
492207SN/A        L2L3CacheAndL2TLB,
504111Sgblack@eecs.umich.edu        APMInfo,
514111Sgblack@eecs.umich.edu
524155Sgblack@eecs.umich.edu        /*
535874Sgblack@eecs.umich.edu         * The following are defined by the spec but not yet implemented
545874Sgblack@eecs.umich.edu         */
556691Stjones1@inf.ed.ac.uk/*      LongModeAddressSize,
567095Sgblack@eecs.umich.edu        // Function 9 is reserved
576691Stjones1@inf.ed.ac.uk        SVMInfo = 10,
58360SN/A        // Functions 11-24 are reserved
59360SN/A        TLB1GBPageInfo = 25,
60360SN/A        PerformanceInfo,*/
61360SN/A
62360SN/A        NumExtendedCpuidFuncs
632207SN/A    };
646392Ssaidi@eecs.umich.edu
656392Ssaidi@eecs.umich.edu    static const int vendorStringSize = 13;
66360SN/A    static const char vendorString[vendorStringSize] = "M5 Simulator";
67360SN/A    static const int nameStringSize = 48;
682SN/A    static const char nameString[nameStringSize] = "Fake M5 x86_64 CPU";
6912SN/A
702SN/A    uint64_t
7112SN/A    stringToRegister(const char *str)
722SN/A    {
732SN/A        uint64_t reg = 0;
74360SN/A        for (int pos = 3; pos >=0; pos--) {
75360SN/A            reg <<= 8;
76360SN/A            reg |= str[pos];
7712SN/A        }
78360SN/A        return reg;
79360SN/A    }
8012SN/A
812SN/A    bool
822SN/A    doCpuid(ThreadContext * tc, uint32_t function,
832SN/A            uint32_t index, CpuidResult &result)
842SN/A    {
852SN/A        uint16_t family = bits(function, 31, 16);
862520SN/A        uint16_t funcNum = bits(function, 15, 0);
872520SN/A        if (family == 0x8000) {
883812Ssaidi@eecs.umich.edu            // The extended functions
893812Ssaidi@eecs.umich.edu            switch (funcNum) {
903812Ssaidi@eecs.umich.edu              case VendorAndLargestExtFunc:
913812Ssaidi@eecs.umich.edu                assert(vendorStringSize >= 12);
922SN/A                result = CpuidResult(
935070Ssaidi@eecs.umich.edu                        0x80000000 + NumExtendedCpuidFuncs - 1,
945070Ssaidi@eecs.umich.edu                        stringToRegister(vendorString),
953917Ssaidi@eecs.umich.edu                        stringToRegister(vendorString + 4),
96360SN/A                        stringToRegister(vendorString + 8));
97360SN/A                break;
98360SN/A              case FamilyModelSteppingBrandFeatures:
992SN/A                result = CpuidResult(0x00020f51, 0x00000405,
1002SN/A                                     0xe3d3fbff, 0x00000001);
10112SN/A                break;
1022420SN/A              case NameString1:
1032420SN/A              case NameString2:
1042420SN/A              case NameString3:
10512SN/A                {
10612SN/A                    // Zero fill anything beyond the end of the string. This
10712SN/A                    // should go away once the string is a vetted parameter.
10812SN/A                    char cleanName[nameStringSize];
10912SN/A                    memset(cleanName, '\0', nameStringSize);
11012SN/A                    strncpy(cleanName, nameString, nameStringSize);
11112SN/A
11212SN/A                    int offset = (funcNum - NameString1) * 16;
1132SN/A                    assert(nameStringSize >= offset + 16);
1142520SN/A                    result = CpuidResult(
1152472SN/A                            stringToRegister(cleanName + offset + 0),
1162420SN/A                            stringToRegister(cleanName + offset + 4),
1172SN/A                            stringToRegister(cleanName + offset + 12),
11812SN/A                            stringToRegister(cleanName + offset + 8));
1192472SN/A                }
12012SN/A                break;
1212SN/A              case L1CacheAndTLB:
12212SN/A                result = CpuidResult(0xff08ff08, 0xff20ff20,
12312SN/A                                     0x40020140, 0x40020140);
12412SN/A                break;
12512SN/A              case L2L3CacheAndL2TLB:
12612SN/A                result = CpuidResult(0x00000000, 0x42004200,
12712SN/A                                     0x00000000, 0x04008140);
12812SN/A                break;
1293584Ssaidi@eecs.umich.edu              case APMInfo:
1303584Ssaidi@eecs.umich.edu                result = CpuidResult(0x80000018, 0x68747541,
1312SN/A                                     0x69746e65, 0x444d4163);
1322SN/A                break;
1333584Ssaidi@eecs.umich.edu/*            case LongModeAddressSize:
1342SN/A              case SVMInfo:
1352SN/A              case TLB1GBPageInfo:
1362SN/A              case PerformanceInfo:*/
137              default:
138                warn("x86 cpuid: unimplemented function %u", funcNum);
139                return false;
140            }
141        } else if(family == 0x0000) {
142            // The standard functions
143            switch (funcNum) {
144              case VendorAndLargestStdFunc:
145                assert(vendorStringSize >= 12);
146                result = CpuidResult(
147                        NumStandardCpuidFuncs - 1,
148                        stringToRegister(vendorString),
149                        stringToRegister(vendorString + 4),
150                        stringToRegister(vendorString + 8));
151                break;
152              case FamilyModelStepping:
153                result = CpuidResult(0x00020f51, 0x00000805,
154                                     0xe7dbfbff, 0x00000001);
155                break;
156              default:
157                warn("x86 cpuid: unimplemented function %u", funcNum);
158                return false;
159            }
160        } else {
161            warn("x86 cpuid: unknown family %#x", family);
162            return false;
163        }
164
165        return true;
166    }
167} // namespace X86ISA
168