X86: Implement MSR reads and writes and the wrsmr and rdmsr instructions.
authorGabe Black <gblack@eecs.umich.edu>
Fri, 12 Oct 2007 23:37:55 +0000 (16:37 -0700)
committerGabe Black <gblack@eecs.umich.edu>
Fri, 12 Oct 2007 23:37:55 +0000 (16:37 -0700)
There are no priviledge checks, so these instructions will all work in all
modes.

--HG--
extra : convert_revision : ff893eb569313d8aecbfffb47bcbd1c2d65cd393

src/arch/x86/SConscript
src/arch/x86/isa/decoder/two_byte_opcodes.isa
src/arch/x86/isa/insts/system/__init__.py
src/arch/x86/isa/insts/system/msrs.py [new file with mode: 0644]
src/arch/x86/isa/microasm.isa
src/arch/x86/isa/microops/ldstop.isa
src/arch/x86/miscregs.hh
src/arch/x86/mmaped_ipr.hh
src/arch/x86/tlb.cc
src/arch/x86/x86_traits.hh

index 6d79841473c2ebf06f1e8695eb778bed9593a5ad..6d65fbb5703b8082b86d6492547eee10ef76a5e1 100644 (file)
@@ -179,6 +179,7 @@ if env['TARGET_ISA'] == 'x86':
         'general_purpose/system_calls.py',
         'system/__init__.py',
         'system/undefined_operation.py',
+        'system/msrs.py',
         'simd128/__init__.py',
         'simd128/integer/__init__.py',
         'simd128/integer/data_transfer/__init__.py',
index eae994706e0898a1ec729d9682a9f0c64d0c5d71..0482fdf23899fb5131e97a6852b936377a812558 100644 (file)
                 default: Inst::UD2();
             }
             0x06: decode OPCODE_OP_BOTTOM3 {
-                0x0: wrmsr();
+                0x0: Inst::WRMSR();
                 0x1: rdtsc();
-                0x2: rdmsr();
+                0x2: Inst::RDMSR();
                 0x3: rdpmc();
                 0x4: sysenter();
                 0x5: sysexit();
index 72e3bdf0a7edd6f0bcef9ebeacc7aeed2cbb6289..6d4b3f3d15355e212cb330f5a83e78809bcffa96 100644 (file)
@@ -53,7 +53,8 @@
 #
 # Authors: Gabe Black
 
-categories = ["undefined_operation"]
+categories = ["undefined_operation",
+              "msrs"]
 
 microcode = ""
 for category in categories:
diff --git a/src/arch/x86/isa/insts/system/msrs.py b/src/arch/x86/isa/insts/system/msrs.py
new file mode 100644 (file)
index 0000000..ea57651
--- /dev/null
@@ -0,0 +1,74 @@
+# Copyright (c) 2007 The Hewlett-Packard Development Company
+# All rights reserved.
+#
+# Redistribution and use of this software in source and binary forms,
+# with or without modification, are permitted provided that the
+# following conditions are met:
+#
+# The software must be used only for Non-Commercial Use which means any
+# use which is NOT directed to receiving any direct monetary
+# compensation for, or commercial advantage from such use.  Illustrative
+# examples of non-commercial use are academic research, personal study,
+# teaching, education and corporate research & development.
+# Illustrative examples of commercial use are distributing products for
+# commercial advantage and providing services using the software for
+# commercial advantage.
+#
+# If you wish to use this software or functionality therein that may be
+# covered by patents for commercial use, please contact:
+#     Director of Intellectual Property Licensing
+#     Office of Strategy and Technology
+#     Hewlett-Packard Company
+#     1501 Page Mill Road
+#     Palo Alto, California  94304
+#
+# 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.  No right of
+# sublicense is granted herewith.  Derivatives of the software and
+# output created using the software may be prepared, but only for
+# Non-Commercial Uses.  Derivatives of the software may be shared with
+# others provided: (i) the others agree to abide by the list of
+# conditions herein which includes the Non-Commercial Use restrictions;
+# and (ii) such Derivatives of the software include the above copyright
+# notice to acknowledge the contribution from this software where
+# applicable, this list of conditions and the disclaimer below.
+#
+# 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
+
+microcode = '''
+def macroop WRMSR
+{
+    limm t1, "IntAddrPrefixMSR >> 3"
+    ld t2, intseg, [8, t1, rcx], dataSize=8, addressSize=4
+    mov rax, rax, t2, dataSize=4
+    srli t2, t2, 32, dataSize=8
+    mov rdx, rdx, t2, dataSize=4
+};
+
+def macroop RDMSR
+{
+    limm t1, "IntAddrPrefixMSR >> 3"
+    mov t2, t2, rdx, dataSize=4
+    slli t2, t2, 32, dataSize=8
+    mov t2, t2, rax, dataSize=4
+    st t2, intseg, [8, t1, rcx], dataSize=8, addressSize=4
+};
+'''
index c8bc36b6967491a02397d5c1162f6ced29cb2179..50135e30cbc534a5305579c8a2ac686bb7f66905 100644 (file)
@@ -106,6 +106,10 @@ let {{
     assembler.symbols["riprel"] = \
         ["1", assembler.symbols["t0"], assembler.symbols["t7"]]
 
+    # This segment selects an internal address space mapped to MSRs,
+    # CPUID info, etc.
+    assembler.symbols["intseg"] = "NUM_SEGMENTREGS"
+
     for reg in ('ax', 'bx', 'cx', 'dx', 'sp', 'bp', 'si', 'di'):
         assembler.symbols["r%s" % reg] = "INTREG_R%s" % reg.upper()
 
index 106a8a0fe681a11514e78330618c0b1d87d1515a..32fefb5fad62c5c82b5a6c1d9d03ea6995ee8c92 100644 (file)
@@ -325,13 +325,13 @@ def template MicroLdStOpConstructor {{
 
 let {{
     class LdStOp(X86Microop):
-        def __init__(self, data, segment, addr, disp, dataSize):
+        def __init__(self, data, segment, addr, disp, dataSize, addressSize):
             self.data = data
             [self.scale, self.index, self.base] = addr
             self.disp = disp
             self.segment = segment
             self.dataSize = dataSize
-            self.addressSize = "env.addressSize"
+            self.addressSize = addressSize
 
         def getAllocator(self, *microFlags):
             allocator = '''new %(class_name)s(machInst, mnemonic
@@ -378,10 +378,10 @@ let {{
         exec_output += MicroLoadCompleteAcc.subst(iop)
 
         class LoadOp(LdStOp):
-            def __init__(self, data, segment, addr,
-                    disp = 0, dataSize="env.dataSize"):
+            def __init__(self, data, segment, addr, disp = 0,
+                    dataSize="env.dataSize", addressSize="env.addressSize"):
                 super(LoadOp, self).__init__(data, segment,
-                        addr, disp, dataSize)
+                        addr, disp, dataSize, addressSize)
                 self.className = Name
                 self.mnemonic = name
 
@@ -411,10 +411,10 @@ let {{
         exec_output += MicroStoreCompleteAcc.subst(iop)
 
         class StoreOp(LdStOp):
-            def __init__(self, data, segment, addr,
-                    disp = 0, dataSize="env.dataSize"):
+            def __init__(self, data, segment, addr, disp = 0,
+                    dataSize="env.dataSize", addressSize="env.addressSize"):
                 super(StoreOp, self).__init__(data, segment,
-                        addr, disp, dataSize)
+                        addr, disp, dataSize, addressSize)
                 self.className = Name
                 self.mnemonic = name
 
@@ -432,10 +432,10 @@ let {{
     exec_output += MicroLeaExecute.subst(iop)
 
     class LeaOp(LdStOp):
-        def __init__(self, data, segment, addr,
-                disp = 0, dataSize="env.dataSize"):
+        def __init__(self, data, segment, addr, disp = 0,
+                dataSize="env.dataSize", addressSize="env.addressSize"):
             super(LeaOp, self).__init__(data, segment,
-                    addr, disp, dataSize)
+                    addr, disp, dataSize, addressSize)
             self.className = "Lea"
             self.mnemonic = "lea"
 
index b4d06092b120947b9450c9f99b500d43650bb298..a516a2018a06252c7535faa804158d4f7db28882 100644 (file)
@@ -164,7 +164,7 @@ namespace X86ISA
         MISCREG_MTRR_FIX_16K_80000,
         MISCREG_MTRR_FIX_16K_A0000,
         MISCREG_MTRR_FIX_4K_C0000,
-        MISCREG_MTRR_FIX_4k_C8000,
+        MISCREG_MTRR_FIX_4K_C8000,
         MISCREG_MTRR_FIX_4K_D0000,
         MISCREG_MTRR_FIX_4K_D8000,
         MISCREG_MTRR_FIX_4K_E0000,
index 1fef72fa62af7396efce99ab5910bc4925b3d8a6..c7befa35b89e7e5643f3f33d95ca1a61423ae8d4 100644 (file)
@@ -76,7 +76,7 @@ namespace X86ISA
 #if !FULL_SYSTEM
         panic("Shouldn't have a memory mapped register in SE\n");
 #else
-        panic("Memory mapped registers aren't implemented for x86!\n");
+        pkt->set(xc->readMiscReg(pkt->getAddr() / sizeof(MiscReg)));
 #endif
     }
 
@@ -86,7 +86,8 @@ namespace X86ISA
 #if !FULL_SYSTEM
         panic("Shouldn't have a memory mapped register in SE\n");
 #else
-        panic("Memory mapped registers aren't implemented for x86!\n");
+        xc->setMiscReg(pkt->getAddr() / sizeof(MiscReg),
+                gtoh(pkt->get<uint64_t>()));
 #endif
     }
 };
index 93df088307a7b5a9b97e5047ce768390eaf94dd6..d55f04080961280229f68a2dc1e63f42bc9a0935 100644 (file)
@@ -61,6 +61,7 @@
 
 #include "arch/x86/pagetable.hh"
 #include "arch/x86/tlb.hh"
+#include "arch/x86/x86_traits.hh"
 #include "base/bitfield.hh"
 #include "base/trace.hh"
 #include "cpu/thread_context.hh"
@@ -142,10 +143,304 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute)
     uint32_t flags = req->getFlags();
     bool storeCheck = flags & StoreCheck;
 
-    int seg = flags & (mask(NUM_SEGMENTREGS));
+    int seg = flags & mask(3);
 
     //XXX Junk code to surpress the warning
-    if (storeCheck) seg = seg;
+    if (storeCheck);
+
+    // If this is true, we're dealing with a request to read an internal
+    // value.
+    if (seg == NUM_SEGMENTREGS) {
+        Addr prefix = vaddr & IntAddrPrefixMask;
+        if (prefix == IntAddrPrefixCPUID) {
+            panic("CPUID memory space not yet implemented!\n");
+        } else if (prefix == IntAddrPrefixMSR) {
+            req->setMmapedIpr(true);
+            Addr regNum = 0;
+            switch (vaddr & ~IntAddrPrefixMask) {
+              case 0x10:
+                regNum = MISCREG_TSC;
+                break;
+              case 0xFE:
+                regNum = MISCREG_MTRRCAP;
+                break;
+              case 0x174:
+                regNum = MISCREG_SYSENTER_CS;
+                break;
+              case 0x175:
+                regNum = MISCREG_SYSENTER_ESP;
+                break;
+              case 0x176:
+                regNum = MISCREG_SYSENTER_EIP;
+                break;
+              case 0x179:
+                regNum = MISCREG_MCG_CAP;
+                break;
+              case 0x17A:
+                regNum = MISCREG_MCG_STATUS;
+                break;
+              case 0x17B:
+                regNum = MISCREG_MCG_CTL;
+                break;
+              case 0x1D9:
+                regNum = MISCREG_DEBUG_CTL_MSR;
+                break;
+              case 0x1DB:
+                regNum = MISCREG_LAST_BRANCH_FROM_IP;
+                break;
+              case 0x1DC:
+                regNum = MISCREG_LAST_BRANCH_TO_IP;
+                break;
+              case 0x1DD:
+                regNum = MISCREG_LAST_EXCEPTION_FROM_IP;
+                break;
+              case 0x1DE:
+                regNum = MISCREG_LAST_EXCEPTION_TO_IP;
+                break;
+              case 0x200:
+                regNum = MISCREG_MTRR_PHYS_BASE_0;
+                break;
+              case 0x201:
+                regNum = MISCREG_MTRR_PHYS_MASK_0;
+                break;
+              case 0x202:
+                regNum = MISCREG_MTRR_PHYS_BASE_1;
+                break;
+              case 0x203:
+                regNum = MISCREG_MTRR_PHYS_MASK_1;
+                break;
+              case 0x204:
+                regNum = MISCREG_MTRR_PHYS_BASE_2;
+                break;
+              case 0x205:
+                regNum = MISCREG_MTRR_PHYS_MASK_2;
+                break;
+              case 0x206:
+                regNum = MISCREG_MTRR_PHYS_BASE_3;
+                break;
+              case 0x207:
+                regNum = MISCREG_MTRR_PHYS_MASK_3;
+                break;
+              case 0x208:
+                regNum = MISCREG_MTRR_PHYS_BASE_4;
+                break;
+              case 0x209:
+                regNum = MISCREG_MTRR_PHYS_MASK_4;
+                break;
+              case 0x20A:
+                regNum = MISCREG_MTRR_PHYS_BASE_5;
+                break;
+              case 0x20B:
+                regNum = MISCREG_MTRR_PHYS_MASK_5;
+                break;
+              case 0x20C:
+                regNum = MISCREG_MTRR_PHYS_BASE_6;
+                break;
+              case 0x20D:
+                regNum = MISCREG_MTRR_PHYS_MASK_6;
+                break;
+              case 0x20E:
+                regNum = MISCREG_MTRR_PHYS_BASE_7;
+                break;
+              case 0x20F:
+                regNum = MISCREG_MTRR_PHYS_MASK_7;
+                break;
+              case 0x250:
+                regNum = MISCREG_MTRR_FIX_64K_00000;
+                break;
+              case 0x258:
+                regNum = MISCREG_MTRR_FIX_16K_80000;
+                break;
+              case 0x259:
+                regNum = MISCREG_MTRR_FIX_16K_A0000;
+                break;
+              case 0x268:
+                regNum = MISCREG_MTRR_FIX_4K_C0000;
+                break;
+              case 0x269:
+                regNum = MISCREG_MTRR_FIX_4K_C8000;
+                break;
+              case 0x26A:
+                regNum = MISCREG_MTRR_FIX_4K_D0000;
+                break;
+              case 0x26B:
+                regNum = MISCREG_MTRR_FIX_4K_D8000;
+                break;
+              case 0x26C:
+                regNum = MISCREG_MTRR_FIX_4K_E0000;
+                break;
+              case 0x26D:
+                regNum = MISCREG_MTRR_FIX_4K_E8000;
+                break;
+              case 0x26E:
+                regNum = MISCREG_MTRR_FIX_4K_F0000;
+                break;
+              case 0x26F:
+                regNum = MISCREG_MTRR_FIX_4K_F8000;
+                break;
+              case 0x277:
+                regNum = MISCREG_PAT;
+                break;
+              case 0x2FF:
+                regNum = MISCREG_DEF_TYPE;
+                break;
+              case 0x400:
+                regNum = MISCREG_MC0_CTL;
+                break;
+              case 0x404:
+                regNum = MISCREG_MC1_CTL;
+                break;
+              case 0x408:
+                regNum = MISCREG_MC2_CTL;
+                break;
+              case 0x40C:
+                regNum = MISCREG_MC3_CTL;
+                break;
+              case 0x410:
+                regNum = MISCREG_MC4_CTL;
+                break;
+              case 0x401:
+                regNum = MISCREG_MC0_STATUS;
+                break;
+              case 0x405:
+                regNum = MISCREG_MC1_STATUS;
+                break;
+              case 0x409:
+                regNum = MISCREG_MC2_STATUS;
+                break;
+              case 0x40D:
+                regNum = MISCREG_MC3_STATUS;
+                break;
+              case 0x411:
+                regNum = MISCREG_MC4_STATUS;
+                break;
+              case 0x402:
+                regNum = MISCREG_MC0_ADDR;
+                break;
+              case 0x406:
+                regNum = MISCREG_MC1_ADDR;
+                break;
+              case 0x40A:
+                regNum = MISCREG_MC2_ADDR;
+                break;
+              case 0x40E:
+                regNum = MISCREG_MC3_ADDR;
+                break;
+              case 0x412:
+                regNum = MISCREG_MC4_ADDR;
+                break;
+              case 0x403:
+                regNum = MISCREG_MC0_MISC;
+                break;
+              case 0x407:
+                regNum = MISCREG_MC1_MISC;
+                break;
+              case 0x40B:
+                regNum = MISCREG_MC2_MISC;
+                break;
+              case 0x40F:
+                regNum = MISCREG_MC3_MISC;
+                break;
+              case 0x413:
+                regNum = MISCREG_MC4_MISC;
+                break;
+              case 0xC0000080:
+                regNum = MISCREG_EFER;
+                break;
+              case 0xC0000081:
+                regNum = MISCREG_STAR;
+                break;
+              case 0xC0000082:
+                regNum = MISCREG_LSTAR;
+                break;
+              case 0xC0000083:
+                regNum = MISCREG_CSTAR;
+                break;
+              case 0xC0000084:
+                regNum = MISCREG_SF_MASK;
+                break;
+              case 0xC0000100:
+                regNum = MISCREG_FS_BASE;
+                break;
+              case 0xC0000101:
+                regNum = MISCREG_GS_BASE;
+                break;
+              case 0xC0000102:
+                regNum = MISCREG_KERNEL_GS_BASE;
+                break;
+              case 0xC0000103:
+                regNum = MISCREG_TSC_AUX;
+                break;
+              case 0xC0010000:
+                regNum = MISCREG_PERF_EVT_SEL0;
+                break;
+              case 0xC0010001:
+                regNum = MISCREG_PERF_EVT_SEL1;
+                break;
+              case 0xC0010002:
+                regNum = MISCREG_PERF_EVT_SEL2;
+                break;
+              case 0xC0010003:
+                regNum = MISCREG_PERF_EVT_SEL3;
+                break;
+              case 0xC0010004:
+                regNum = MISCREG_PERF_EVT_CTR0;
+                break;
+              case 0xC0010005:
+                regNum = MISCREG_PERF_EVT_CTR1;
+                break;
+              case 0xC0010006:
+                regNum = MISCREG_PERF_EVT_CTR2;
+                break;
+              case 0xC0010007:
+                regNum = MISCREG_PERF_EVT_CTR3;
+                break;
+              case 0xC0010010:
+                regNum = MISCREG_SYSCFG;
+                break;
+              case 0xC0010016:
+                regNum = MISCREG_IORR_BASE0;
+                break;
+              case 0xC0010017:
+                regNum = MISCREG_IORR_BASE1;
+                break;
+              case 0xC0010018:
+                regNum = MISCREG_IORR_MASK0;
+                break;
+              case 0xC0010019:
+                regNum = MISCREG_IORR_MASK1;
+                break;
+              case 0xC001001A:
+                regNum = MISCREG_TOP_MEM;
+                break;
+              case 0xC001001D:
+                regNum = MISCREG_TOP_MEM2;
+                break;
+              case 0xC0010114:
+                regNum = MISCREG_VM_CR;
+                break;
+              case 0xC0010115:
+                regNum = MISCREG_IGNNE;
+                break;
+              case 0xC0010116:
+                regNum = MISCREG_SMM_CTL;
+                break;
+              case 0xC0010117:
+                regNum = MISCREG_VM_HSAVE_PA;
+                break;
+              default:
+                return new GeneralProtection(0);
+            }
+            //The index is multiplied by the size of a MiscReg so that
+            //any memory dependence calculations will not see these as
+            //overlapping.
+            req->setPaddr(regNum * sizeof(MiscReg));
+            return NoFault;
+        } else {
+            panic("Access to unrecognized internal address space %#x.\n",
+                    prefix);
+        }
+    }
 
     // Get cr0. This will tell us how to do translation. We'll assume it was
     // verified to be correct and consistent when set.
index 33ec133728700c1ced61c3b7244c4e5812c29cbe..beb1898ce7be5f60c44d227e567fb5304bc91191 100644 (file)
@@ -55,6 +55,8 @@
  * Authors: Gabe Black
  */
 
+#include "sim/host.hh"
+
 #ifndef __ARCH_X86_X86TRAITS_HH__
 #define __ARCH_X86_X86TRAITS_HH__
 
@@ -80,6 +82,10 @@ namespace X86ISA
 
     const int NumSegments = 6;
     const int NumSysSegments = 4;
+
+    const Addr IntAddrPrefixMask = ULL(0xffffffff00000000);
+    const Addr IntAddrPrefixCPUID = ULL(0x100000000);
+    const Addr IntAddrPrefixMSR = ULL(0x200000000);
 }
 
 #endif //__ARCH_X86_X86TRAITS_HH__