summaryrefslogtreecommitdiff
path: root/src/arch/x86/cpuid.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/x86/cpuid.cc')
-rw-r--r--src/arch/x86/cpuid.cc160
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