160 lines
6.1 KiB
C++
160 lines
6.1 KiB
C++
/*
|
|
* 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] = "M5 Simulator";
|
|
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(
|
|
0x80000000 + 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 + 12),
|
|
stringToRegister(cleanName + offset + 8));
|
|
}
|
|
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,
|
|
0xe7d3fbff, 0x00000001);
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
} //namespace X86ISA
|