diff options
Diffstat (limited to 'src/arch/x86/cpuid.cc')
-rw-r--r-- | src/arch/x86/cpuid.cc | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/src/arch/x86/cpuid.cc b/src/arch/x86/cpuid.cc new file mode 100644 index 000000000..247965df4 --- /dev/null +++ b/src/arch/x86/cpuid.cc @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2008 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "arch/x86/cpuid.hh" +#include "base/bitfield.hh" +#include "cpu/thread_context.hh" + +namespace X86ISA { + enum StandardCpuidFunction { + VendorAndLargestStdFunc, + FamilyModelStepping, + NumStandardCpuidFuncs + }; + + enum ExtendedCpuidFunctions { + VendorAndLargestExtFunc, + FamilyModelSteppingBrandFeatures, + NameString1, + NameString2, + NameString3, + L1CacheAndTLB, + L2L3CacheAndL2TLB, + APMInfo, + + /* + * The following are defined by the spec but not yet implemented + */ +/* LongModeAddressSize, + // Function 9 is reserved + SVMInfo = 10, + // Functions 11-24 are reserved + TLB1GBPageInfo = 25, + PerformanceInfo,*/ + + NumExtendedCpuidFuncs + }; + + static const int vendorStringSize = 13; + static const char vendorString[vendorStringSize] = "AuthenticAMD"; + static const int nameStringSize = 48; + static const char nameString[nameStringSize] = "Fake M5 x86_64 CPU"; + + uint64_t + stringToRegister(const char *str) + { + uint64_t reg = 0; + for (int pos = 3; pos >=0; pos--) { + reg <<= 8; + reg |= str[pos]; + } + return reg; + } + + bool + doCpuid(ThreadContext * tc, uint32_t function, CpuidResult &result) + { + uint16_t family = bits(function, 31, 16); + uint16_t funcNum = bits(function, 15, 0); + if (family == 0x8000) { + // The extended functions + switch (funcNum) { + case VendorAndLargestExtFunc: + assert(vendorStringSize >= 12); + result = CpuidResult( + NumExtendedCpuidFuncs - 1, + stringToRegister(vendorString), + stringToRegister(vendorString + 4), + stringToRegister(vendorString + 8)); + break; + case FamilyModelSteppingBrandFeatures: + result = CpuidResult(0x00020f51, 0x00000405, + 0xe3d3fbff, 0x00000001); + break; + case NameString1: + case NameString2: + case NameString3: + { + // Zero fill anything beyond the end of the string. This + // should go away once the string is a vetted parameter. + char cleanName[nameStringSize]; + memset(cleanName, '\0', nameStringSize); + strncpy(cleanName, nameString, nameStringSize); + + int offset = (funcNum - NameString1) * 16; + assert(nameStringSize >= offset + 16); + result = CpuidResult( + stringToRegister(cleanName + offset + 0), + stringToRegister(cleanName + offset + 4), + stringToRegister(cleanName + offset + 8), + stringToRegister(cleanName + offset + 12)); + } + break; + case L1CacheAndTLB: + result = CpuidResult(0xff08ff08, 0xff20ff20, + 0x40020140, 0x40020140); + break; + case L2L3CacheAndL2TLB: + result = CpuidResult(0x00000000, 0x42004200, + 0x00000000, 0x04008140); + break; + case APMInfo: + result = CpuidResult(0x80000018, 0x68747541, + 0x69746e65, 0x444d4163); + break; +/* case LongModeAddressSize: + case SVMInfo: + case TLB1GBPageInfo: + case PerformanceInfo:*/ + default: + return false; + } + } else if(family == 0x0000) { + // The standard functions + switch (funcNum) { + case VendorAndLargestStdFunc: + assert(vendorStringSize >= 12); + result = CpuidResult( + NumStandardCpuidFuncs - 1, + stringToRegister(vendorString), + stringToRegister(vendorString + 4), + stringToRegister(vendorString + 8)); + break; + case FamilyModelStepping: + result = CpuidResult(0x00020f51, 0000000405, + 0xe3d3fbff, 0x00000001); + break; + default: + return false; + } + } + return true; + } +} //namespace X86ISA |