From 9498e536c0231b808669f2bacb4c0628d1ec309a Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 12 Oct 2007 16:37:55 -0700 Subject: [PATCH] X86: Implement MSR reads and writes and the wrsmr and rdmsr instructions. There are no priviledge checks, so these instructions will all work in all modes. --HG-- extra : convert_revision : ff893eb569313d8aecbfffb47bcbd1c2d65cd393 --- src/arch/x86/SConscript | 1 + src/arch/x86/isa/decoder/two_byte_opcodes.isa | 4 +- src/arch/x86/isa/insts/system/__init__.py | 3 +- src/arch/x86/isa/insts/system/msrs.py | 74 +++++ src/arch/x86/isa/microasm.isa | 4 + src/arch/x86/isa/microops/ldstop.isa | 22 +- src/arch/x86/miscregs.hh | 2 +- src/arch/x86/mmaped_ipr.hh | 5 +- src/arch/x86/tlb.cc | 299 +++++++++++++++++- src/arch/x86/x86_traits.hh | 6 + 10 files changed, 401 insertions(+), 19 deletions(-) create mode 100644 src/arch/x86/isa/insts/system/msrs.py diff --git a/src/arch/x86/SConscript b/src/arch/x86/SConscript index 6d7984147..6d65fbb57 100644 --- a/src/arch/x86/SConscript +++ b/src/arch/x86/SConscript @@ -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', diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa index eae994706..0482fdf23 100644 --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -211,9 +211,9 @@ 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(); diff --git a/src/arch/x86/isa/insts/system/__init__.py b/src/arch/x86/isa/insts/system/__init__.py index 72e3bdf0a..6d4b3f3d1 100644 --- a/src/arch/x86/isa/insts/system/__init__.py +++ b/src/arch/x86/isa/insts/system/__init__.py @@ -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 index 000000000..ea576510b --- /dev/null +++ b/src/arch/x86/isa/insts/system/msrs.py @@ -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 +}; +''' diff --git a/src/arch/x86/isa/microasm.isa b/src/arch/x86/isa/microasm.isa index c8bc36b69..50135e30c 100644 --- a/src/arch/x86/isa/microasm.isa +++ b/src/arch/x86/isa/microasm.isa @@ -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() diff --git a/src/arch/x86/isa/microops/ldstop.isa b/src/arch/x86/isa/microops/ldstop.isa index 106a8a0fe..32fefb5fa 100644 --- a/src/arch/x86/isa/microops/ldstop.isa +++ b/src/arch/x86/isa/microops/ldstop.isa @@ -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" diff --git a/src/arch/x86/miscregs.hh b/src/arch/x86/miscregs.hh index b4d06092b..a516a2018 100644 --- a/src/arch/x86/miscregs.hh +++ b/src/arch/x86/miscregs.hh @@ -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, diff --git a/src/arch/x86/mmaped_ipr.hh b/src/arch/x86/mmaped_ipr.hh index 1fef72fa6..c7befa35b 100644 --- a/src/arch/x86/mmaped_ipr.hh +++ b/src/arch/x86/mmaped_ipr.hh @@ -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())); #endif } }; diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc index 93df08830..d55f04080 100644 --- a/src/arch/x86/tlb.cc +++ b/src/arch/x86/tlb.cc @@ -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. diff --git a/src/arch/x86/x86_traits.hh b/src/arch/x86/x86_traits.hh index 33ec13372..beb1898ce 100644 --- a/src/arch/x86/x86_traits.hh +++ b/src/arch/x86/x86_traits.hh @@ -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__ -- 2.30.2