diff options
author | Korey Sewell <ksewell@umich.edu> | 2009-07-31 10:40:42 -0400 |
---|---|---|
committer | Korey Sewell <ksewell@umich.edu> | 2009-07-31 10:40:42 -0400 |
commit | aa75b9a7a7489bf86c4e6d406ff612e596ddff96 (patch) | |
tree | 58a6816583a21c19c181e32bff10bf74aa9ad15f /src/arch/arm | |
parent | 60063cc700912666fa8b7968d692d00a1e82cb67 (diff) | |
parent | 3dd3de5feb31055a48acb39575da25a9cea2626d (diff) | |
download | gem5-aa75b9a7a7489bf86c4e6d406ff612e596ddff96.tar.xz |
merge mips fix and statetrace changes
Diffstat (limited to 'src/arch/arm')
-rw-r--r-- | src/arch/arm/ArmNativeTrace.py | 37 | ||||
-rw-r--r-- | src/arch/arm/SConscript | 3 | ||||
-rw-r--r-- | src/arch/arm/isa.hh | 6 | ||||
-rw-r--r-- | src/arch/arm/isa/decoder.isa | 26 | ||||
-rw-r--r-- | src/arch/arm/isa/formats/pred.isa | 6 | ||||
-rw-r--r-- | src/arch/arm/isa/operands.isa | 8 | ||||
-rw-r--r-- | src/arch/arm/linux/linux.hh | 73 | ||||
-rw-r--r-- | src/arch/arm/linux/process.cc | 10 | ||||
-rw-r--r-- | src/arch/arm/miscregs.hh | 3 | ||||
-rw-r--r-- | src/arch/arm/nativetrace.cc | 183 | ||||
-rw-r--r-- | src/arch/arm/nativetrace.hh | 112 | ||||
-rw-r--r-- | src/arch/arm/process.cc | 240 |
12 files changed, 633 insertions, 74 deletions
diff --git a/src/arch/arm/ArmNativeTrace.py b/src/arch/arm/ArmNativeTrace.py new file mode 100644 index 000000000..0a76913e3 --- /dev/null +++ b/src/arch/arm/ArmNativeTrace.py @@ -0,0 +1,37 @@ +# Copyright (c) 2009 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 + +from m5.SimObject import SimObject +from m5.params import * +from NativeTrace import NativeTrace + +class ArmNativeTrace(NativeTrace): + type = 'ArmNativeTrace' + cxx_class = 'Trace::ArmNativeTrace' + stop_on_pc_error = Param.Bool(True, + "Stop M5 if it and statetrace's pcs are different") diff --git a/src/arch/arm/SConscript b/src/arch/arm/SConscript index 519435489..55ecabdc3 100644 --- a/src/arch/arm/SConscript +++ b/src/arch/arm/SConscript @@ -39,11 +39,14 @@ if env['TARGET_ISA'] == 'arm': Source('insts/mem.cc') Source('insts/pred_inst.cc') Source('insts/static_inst.cc') + Source('nativetrace.cc') Source('pagetable.cc') Source('tlb.cc') Source('vtophys.cc') + SimObject('ArmNativeTrace.py') SimObject('ArmTLB.py') + TraceFlag('Arm') if env['FULL_SYSTEM']: diff --git a/src/arch/arm/isa.hh b/src/arch/arm/isa.hh index 39acc9c08..2315afa9e 100644 --- a/src/arch/arm/isa.hh +++ b/src/arch/arm/isa.hh @@ -48,7 +48,11 @@ namespace ArmISA public: void clear() { - // Unknown startup state currently + memset(miscRegs, 0, sizeof(miscRegs)); + CPSR cpsr = 0; + cpsr.mode = MODE_USER; + miscRegs[MISCREG_CPSR] = cpsr; + //XXX We need to initialize the rest of the state. } MiscReg diff --git a/src/arch/arm/isa/decoder.isa b/src/arch/arm/isa/decoder.isa index 76d584858..a999b52e9 100644 --- a/src/arch/arm/isa/decoder.isa +++ b/src/arch/arm/isa/decoder.isa @@ -113,8 +113,7 @@ format DataOp { 0x1: decode OPCODE { 0x9: BranchExchange::bx({{ }}); 0xb: PredOp::clz({{ - unsigned lsb = findLsbSet(Rm); - Rd = (lsb > 31) ? 32 : lsb; + Rd = ((Rm == 0) ? 32 : (31 - findMsbSet(Rm))); }}); } 0x2: decode OPCODE { @@ -319,6 +318,10 @@ format DataOp { 0x12,0x16,0x1a,0x1e: ArmMacroFMOp::sfm_pw({{ }}); 0x13,0x17,0x1b,0x1f: ArmMacroFMOp::lfm_pw({{ }}); } + 0xb: decode LOADOP { + 0x0: WarnUnimpl::fstmx(); + 0x1: WarnUnimpl::fldmx(); + } } 0x7: decode OPCODE_24 { 0: decode CPNUM { @@ -417,12 +420,29 @@ format DataOp { } } } + 0xa: decode MISC_OPCODE { + 0x1: decode MEDIA_OPCODE { + 0xf: decode RN { + 0x0: FloatOp::fmrx_fpsid({{ Rd = Fpsid; }}); + 0x1: FloatOp::fmrx_fpscr({{ Rd = Fpscr; }}); + 0x8: FloatOp::fmrx_fpexc({{ Rd = Fpexc; }}); + } + 0xe: decode RN { + 0x0: FloatOp::fmxr_fpsid({{ Fpsid = Rd; }}); + 0x1: FloatOp::fmxr_fpscr({{ Fpscr = Rd; }}); + 0x8: FloatOp::fmxr_fpexc({{ Fpexc = Rd; }}); + } + } + } } format PredOp { // ARM System Call (SoftWare Interrupt) 1: swi({{ if (testPredicate(Cpsr, condCode)) { - xc->syscall(IMMED_23_0); + if (IMMED_23_0) + xc->syscall(IMMED_23_0); + else + xc->syscall(R7); } }}); } diff --git a/src/arch/arm/isa/formats/pred.isa b/src/arch/arm/isa/formats/pred.isa index 50e162f3d..e90788c91 100644 --- a/src/arch/arm/isa/formats/pred.isa +++ b/src/arch/arm/isa/formats/pred.isa @@ -105,7 +105,8 @@ let {{ def getCcCode(flagtype): icReg = icImm = iv = '' if flagtype == "none": - icReg = icImm = iv = '1' + icReg = icImm = 'Cpsr<29:>' + iv = 'Cpsr<28:>' elif flagtype == "add": icReg = icImm = 'findCarry(32, resTemp, Rn, op2)' iv = 'findOverflow(32, resTemp, Rn, op2)' @@ -125,7 +126,8 @@ let {{ def getImmCcCode(flagtype): ivValue = icValue = '' if flagtype == "none": - icValue = ivValue = '1' + icValue = 'Cpsr<29:>' + ivValue = 'Cpsr<28:>' elif flagtype == "add": icValue = 'findCarry(32, resTemp, Rn, rotated_imm)' ivValue = 'findOverflow(32, resTemp, Rn, rotated_imm)' diff --git a/src/arch/arm/isa/operands.isa b/src/arch/arm/isa/operands.isa index fa41918c1..ac7427dad 100644 --- a/src/arch/arm/isa/operands.isa +++ b/src/arch/arm/isa/operands.isa @@ -57,6 +57,7 @@ def operands {{ 'Rm': ('IntReg', 'uw', 'RM', 'IsInteger', 2, maybePCRead, maybePCWrite), 'Rs': ('IntReg', 'uw', 'RS', 'IsInteger', 3, maybePCRead, maybePCWrite), 'Rn': ('IntReg', 'uw', 'RN', 'IsInteger', 4, maybePCRead, maybePCWrite), + 'R7': ('IntReg', 'uw', '7', 'IsInteger', 5), #Destination register for load/store double instructions 'Rdo': ('IntReg', 'uw', '(RD & ~1)', 'IsInteger', 4, maybePCRead, maybePCWrite), @@ -81,7 +82,10 @@ def operands {{ 'Cpsr': ('ControlReg', 'uw', 'MISCREG_CPSR', 'IsInteger', 40), 'Fpsr': ('ControlReg', 'uw', 'MISCREG_FPSR', 'IsInteger', 41), - 'NPC': ('NPC', 'uw', None, (None, None, 'IsControl'), 42), - 'NNPC': ('NNPC', 'uw', None, (None, None, 'IsControl'), 43), + 'Fpsid': ('ControlReg', 'uw', 'MISCREG_FPSID', 'IsInteger', 42), + 'Fpscr': ('ControlReg', 'uw', 'MISCREG_FPSCR', 'IsInteger', 43), + 'Fpexc': ('ControlReg', 'uw', 'MISCREG_FPEXC', 'IsInteger', 44), + 'NPC': ('NPC', 'uw', None, (None, None, 'IsControl'), 45), + 'NNPC': ('NNPC', 'uw', None, (None, None, 'IsControl'), 46) }}; diff --git a/src/arch/arm/linux/linux.hh b/src/arch/arm/linux/linux.hh index 16bcee47a..d99fa8e49 100644 --- a/src/arch/arm/linux/linux.hh +++ b/src/arch/arm/linux/linux.hh @@ -66,18 +66,7 @@ class ArmLinux : public Linux //@} /// For mmap(). - static const unsigned TGT_MAP_ANONYMOUS = 0x800; - - //@{ - /// For getsysinfo(). - static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name as string - static const unsigned GSI_CPU_INFO = 59; //!< CPU information - static const unsigned GSI_PROC_TYPE = 60; //!< get proc_type - static const unsigned GSI_MAX_CPU = 30; //!< max # cpu's on this machine - static const unsigned GSI_CPUS_IN_BOX = 55; //!< number of CPUs in system - static const unsigned GSI_PHYSMEM = 19; //!< Physical memory in KB - static const unsigned GSI_CLK_TCK = 42; //!< clock freq in Hz - //@} + static const unsigned TGT_MAP_ANONYMOUS = 0x20; //@{ /// For getrusage(). @@ -87,13 +76,8 @@ class ArmLinux : public Linux //@} //@{ - /// For setsysinfo(). - static const unsigned SSI_IEEE_FP_CONTROL = 14; //!< ieee_set_fp_control() - //@} - - //@{ /// ioctl() command codes. - static const unsigned TIOCGETP_ = 0x40067408; + static const unsigned TIOCGETP_ = 0x5401; static const unsigned TIOCSETP_ = 0x80067409; static const unsigned TIOCSETN_ = 0x8006740a; static const unsigned TIOCSETC_ = 0x80067411; @@ -114,15 +98,56 @@ class ArmLinux : public Linux TGT_RLIMIT_DATA = 2, TGT_RLIMIT_STACK = 3, TGT_RLIMIT_CORE = 4, - TGT_RLIMIT_NOFILE = 5, - TGT_RLIMIT_AS = 6, - TGT_RLIMIT_RSS = 7, - TGT_RLIMIT_VMEM = 7, - TGT_RLIMIT_NPROC = 8, - TGT_RLIMIT_MEMLOCK = 9, + TGT_RLIMIT_RSS = 5, + TGT_RLIMIT_NPROC = 6, + TGT_RLIMIT_NOFILE = 7, + TGT_RLIMIT_MEMLOCK = 8, + TGT_RLIMIT_AS = 9, TGT_RLIMIT_LOCKS = 10 }; + typedef struct { + uint32_t st_dev; + uint32_t st_ino; + uint16_t st_mode; + uint16_t st_nlink; + uint16_t st_uid; + uint16_t st_gid; + uint32_t st_rdev; + uint32_t st_size; + uint32_t st_blksize; + uint32_t st_blocks; + uint32_t st_atimeX; + uint32_t st_atime_nsec; + uint32_t st_mtimeX; + uint32_t st_mtime_nsec; + uint32_t st_ctimeX; + uint32_t st_ctime_nsec; + } tgt_stat; + + typedef struct { + uint64_t st_dev; + uint8_t __pad0[4]; + uint32_t __st_ino; + uint32_t st_mode; + uint32_t st_nlink; + uint32_t st_uid; + uint32_t st_gid; + uint64_t st_rdev; + uint8_t __pad3[4]; + int64_t __attribute__ ((aligned (8))) st_size; + uint32_t st_blksize; + uint64_t __attribute__ ((aligned (8))) st_blocks; + uint32_t st_atimeX; + uint32_t st_atime_nsec; + uint32_t st_mtimeX; + uint32_t st_mtime_nsec; + uint32_t st_ctimeX; + uint32_t st_ctime_nsec; + uint64_t st_ino; + } tgt_stat64; + + }; #endif diff --git a/src/arch/arm/linux/process.cc b/src/arch/arm/linux/process.cc index 7158acfff..56e3588a7 100644 --- a/src/arch/arm/linux/process.cc +++ b/src/arch/arm/linux/process.cc @@ -106,7 +106,7 @@ SyscallDesc ArmLinuxProcess::syscallDescs[] = { /* 40 */ SyscallDesc("rmdir", unimplementedFunc), /* 41 */ SyscallDesc("dup", unimplementedFunc), /* 42 */ SyscallDesc("pipe", unimplementedFunc), - /* 43 */ SyscallDesc("times", unimplementedFunc), + /* 43 */ SyscallDesc("times", ignoreFunc), /* 44 */ SyscallDesc("prof", unimplementedFunc), /* 45 */ SyscallDesc("brk", brkFunc), /* 46 */ SyscallDesc("setgid", unimplementedFunc), @@ -260,7 +260,7 @@ SyscallDesc ArmLinuxProcess::syscallDescs[] = { /* 194 */ SyscallDesc("ftruncate64", unimplementedFunc), /* 195 */ SyscallDesc("stat64", unimplementedFunc), /* 196 */ SyscallDesc("lstat64", lstat64Func<ArmLinux>), - /* 197 */ SyscallDesc("fstat64", fstatFunc<ArmLinux>), + /* 197 */ SyscallDesc("fstat64", fstat64Func<ArmLinux>), /* 198 */ SyscallDesc("lchown", unimplementedFunc), /* 199 */ SyscallDesc("getuid", getuidFunc), /* 200 */ SyscallDesc("getgid", getgidFunc), @@ -418,7 +418,6 @@ setTLSFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) { uint32_t tlsPtr = process->getSyscallArg(tc, 0); - TypedBufferArg<Linux::utsname> name(process->getSyscallArg(tc, 0)); tc->getMemPort()->writeBlob(ArmLinuxProcess::commPage + 0x0ff0, (uint8_t *)&tlsPtr, sizeof(tlsPtr)); @@ -448,7 +447,8 @@ ArmLinuxProcess::getDesc(int callnum) // Angel SWI syscalls are unsupported in this release if (callnum == 0x123456) { panic("Attempt to execute an ANGEL_SWI system call (newlib-related)"); - } else if ((callnum & 0x00f00000) == 0x00900000) { + } else if ((callnum & 0x00f00000) == 0x00900000 || + (callnum & 0xf0000) == 0xf0000) { callnum &= 0x000fffff; if ((callnum & 0x0f0000) == 0xf0000) { callnum -= 0x0f0001; @@ -496,7 +496,7 @@ ArmLinuxProcess::startup() { 0x00, 0x30, 0x92, 0xe5, //ldr r3, [r2] 0x00, 0x30, 0x53, 0xe0, //subs r3, r3, r0 - 0x00, 0x10, 0x92, 0x05, //streq r1, [r2] + 0x00, 0x10, 0x82, 0x05, //streq r1, [r2] 0x03, 0x00, 0xa0, 0xe1, //mov r0, r3 0x0e, 0xf0, 0xa0, 0xe1 //usr_ret lr }; diff --git a/src/arch/arm/miscregs.hh b/src/arch/arm/miscregs.hh index 42065b0fd..3180669de 100644 --- a/src/arch/arm/miscregs.hh +++ b/src/arch/arm/miscregs.hh @@ -62,6 +62,9 @@ namespace ArmISA MISCREG_SPSR_UND, MISCREG_SPSR_ABT, MISCREG_FPSR, + MISCREG_FPSID, + MISCREG_FPSCR, + MISCREG_FPEXC, NUM_MISCREGS }; diff --git a/src/arch/arm/nativetrace.cc b/src/arch/arm/nativetrace.cc new file mode 100644 index 000000000..1ad9e1a19 --- /dev/null +++ b/src/arch/arm/nativetrace.cc @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2006 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/arm/isa_traits.hh" +#include "arch/arm/miscregs.hh" +#include "arch/arm/nativetrace.hh" +#include "cpu/thread_context.hh" +#include "params/ArmNativeTrace.hh" + +namespace Trace { + +#if TRACING_ON +static const char *regNames[] = { + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "fp", "r12", "sp", "lr", "pc", + "cpsr" +}; +#endif + +void +Trace::ArmNativeTrace::ThreadState::update(NativeTrace *parent) +{ + oldState = state[current]; + current = (current + 1) % 2; + newState = state[current]; + + memcpy(newState, oldState, sizeof(state[0])); + + uint32_t diffVector; + parent->read(&diffVector, sizeof(diffVector)); + diffVector = ArmISA::gtoh(diffVector); + + int changes = 0; + for (int i = 0; i < STATE_NUMVALS; i++) { + if (diffVector & 0x1) { + changed[i] = true; + changes++; + } else { + changed[i] = false; + } + diffVector >>= 1; + } + + uint32_t values[changes]; + parent->read(values, sizeof(values)); + int pos = 0; + for (int i = 0; i < STATE_NUMVALS; i++) { + if (changed[i]) { + newState[i] = ArmISA::gtoh(values[pos++]); + changed[i] = (newState[i] != oldState[i]); + } + } +} + +void +Trace::ArmNativeTrace::ThreadState::update(ThreadContext *tc) +{ + oldState = state[current]; + current = (current + 1) % 2; + newState = state[current]; + + // Regular int regs + for (int i = 0; i < 15; i++) { + newState[i] = tc->readIntReg(i); + changed[i] = (oldState[i] != newState[i]); + } + + //R15, aliased with the PC + newState[STATE_PC] = tc->readNextPC(); + changed[STATE_PC] = (newState[STATE_PC] != oldState[STATE_PC]); + + //CPSR + newState[STATE_CPSR] = tc->readMiscReg(MISCREG_CPSR); + changed[STATE_CPSR] = (newState[STATE_CPSR] != oldState[STATE_CPSR]); +} + +void +Trace::ArmNativeTrace::check(NativeTraceRecord *record) +{ + ThreadContext *tc = record->getThread(); + // This area is read only on the target. It can't stop there to tell us + // what's going on, so we should skip over anything there also. + if (tc->readNextPC() > 0xffff0000) + return; + nState.update(this); + mState.update(tc); + + bool errorFound = false; + // Regular int regs + for (int i = 0; i < STATE_NUMVALS; i++) { + if (nState.changed[i] || mState.changed[i]) { + const char *vergence = " "; + bool oldMatch = (mState.oldState[i] == nState.oldState[i]); + bool newMatch = (mState.newState[i] == nState.newState[i]); + if (oldMatch && newMatch) { + // The more things change, the more they stay the same. + continue; + } else if (oldMatch && !newMatch) { + vergence = "<>"; + } else if (!oldMatch && newMatch) { + vergence = "><"; + } + errorFound = true; + if (!nState.changed[i]) { + DPRINTF(ExecRegDelta, "%s [%5s] "\ + "Native: %#010x "\ + "M5: %#010x => %#010x\n", + vergence, regNames[i], + nState.newState[i], + mState.oldState[i], mState.newState[i]); + } else if (!mState.changed[i]) { + DPRINTF(ExecRegDelta, "%s [%5s] "\ + "Native: %#010x => %#010x "\ + "M5: %#010x \n", + vergence, regNames[i], + nState.oldState[i], nState.newState[i], + mState.newState[i]); + } else { + DPRINTF(ExecRegDelta, "%s [%5s] "\ + "Native: %#010x => %#010x "\ + "M5: %#010x => %#010x\n", + vergence, regNames[i], + nState.oldState[i], nState.newState[i], + mState.oldState[i], mState.newState[i]); + } + } + } + if (errorFound) { + StaticInstPtr inst = record->getStaticInst(); + assert(inst); + bool ran = true; + if (inst->isMicroop()) { + ran = false; + inst = record->getMacroStaticInst(); + } + assert(inst); + record->traceInst(inst, ran); + + bool pcError = (mState.newState[STATE_PC] != + nState.newState[STATE_PC]); + if (stopOnPCError && pcError) + panic("Native trace detected an error in control flow!"); + } +} + +} /* namespace Trace */ + +//////////////////////////////////////////////////////////////////////// +// +// ExeTracer Simulation Object +// +Trace::ArmNativeTrace * +ArmNativeTraceParams::create() +{ + return new Trace::ArmNativeTrace(this); +}; diff --git a/src/arch/arm/nativetrace.hh b/src/arch/arm/nativetrace.hh new file mode 100644 index 000000000..7467e3378 --- /dev/null +++ b/src/arch/arm/nativetrace.hh @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2006 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 + */ + +#ifndef __ARCH_ARM_NATIVETRACE_HH__ +#define __ARCH_ARM_NATIVETRACE_HH__ + +#include "base/types.hh" +#include "cpu/nativetrace.hh" +#include "params/ArmNativeTrace.hh" + +namespace Trace { + +class ArmNativeTrace : public NativeTrace +{ + public: + enum StateID { + STATE_R0, + STATE_R1, + STATE_R2, + STATE_R3, + STATE_R4, + STATE_R5, + STATE_R6, + STATE_R7, + STATE_R8, + STATE_R9, + STATE_R10, + STATE_R11, + STATE_FP = STATE_R11, + STATE_R12, + STATE_R13, + STATE_SP = STATE_R13, + STATE_R14, + STATE_LR = STATE_R14, + STATE_R15, + STATE_PC = STATE_R15, + STATE_CPSR, + STATE_NUMVALS + }; + + protected: + struct ThreadState { + bool changed[STATE_NUMVALS]; + uint32_t state[2][STATE_NUMVALS]; + uint32_t *newState; + uint32_t *oldState; + int current; + void update(NativeTrace *parent); + void update(ThreadContext *tc); + + ThreadState() + { + for (int i = 0; i < STATE_NUMVALS; i++) { + changed[i] = false; + state[0][i] = state[1][i] = 0; + current = 0; + newState = state[0]; + oldState = state[1]; + } + } + }; + + ThreadState nState, mState; + + bool stopOnPCError; + + public: + typedef ArmNativeTraceParams Params; + + const Params * + params() const + { + return dynamic_cast<const Params *>(_params); + } + + ArmNativeTrace(const Params *p) : + NativeTrace(p), stopOnPCError(p->stop_on_pc_error) + {} + + void check(NativeTraceRecord *record); +}; + +} /* namespace Trace */ + +#endif // __ARCH_ARM_NATIVETRACE_HH__ diff --git a/src/arch/arm/process.cc b/src/arch/arm/process.cc index 365d5b22c..cd7cc9736 100644 --- a/src/arch/arm/process.cc +++ b/src/arch/arm/process.cc @@ -46,7 +46,7 @@ using namespace ArmISA; ArmLiveProcess::ArmLiveProcess(LiveProcessParams *params, ObjectFile *objFile) : LiveProcess(params, objFile) { - stack_base = 0xc0000000L; + stack_base = 0xbf000000L; // Set pointer for next thread stack. Reserve 8M for main stack. next_thread_stack_base = stack_base - (8 * 1024 * 1024); @@ -88,73 +88,239 @@ ArmLiveProcess::copyStringArray32(std::vector<std::string> &strings, void ArmLiveProcess::argsInit(int intSize, int pageSize) { + typedef AuxVector<uint32_t> auxv_t; + std::vector<auxv_t> auxv; + + string filename; + if (argv.size() < 1) + filename = ""; + else + filename = argv[0]; + + //We want 16 byte alignment + uint64_t align = 16; + // Overloaded argsInit so that we can fine-tune for ARM architecture Process::startup(); // load object file into target memory objFile->loadSections(initVirtMem); - // Calculate how much space we need for arg & env arrays. - int argv_array_size = intSize * (argv.size() + 1); - int envp_array_size = intSize * (envp.size() + 1); - int arg_data_size = 0; - for (int i = 0; i < argv.size(); ++i) { - arg_data_size += argv[i].size() + 1; + enum ArmCpuFeature { + Arm_Swp = 1 << 0, + Arm_Half = 1 << 1, + Arm_Thumb = 1 << 2, + Arm_26Bit = 1 << 3, + Arm_FastMult = 1 << 4, + Arm_Fpa = 1 << 5, + Arm_Vfp = 1 << 6, + Arm_Edsp = 1 << 7, + Arm_Java = 1 << 8, + Arm_Iwmmxt = 1 << 9, + Arm_Crunch = 1 << 10 + }; + + //Setup the auxilliary vectors. These will already have endian conversion. + //Auxilliary vectors are loaded only for elf formatted executables. + ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile); + if (elfObject) { + uint32_t features = + Arm_Swp | + Arm_Half | + Arm_Thumb | +// Arm_26Bit | + Arm_FastMult | +// Arm_Fpa | + Arm_Vfp | + Arm_Edsp | + Arm_Java | +// Arm_Iwmmxt | +// Arm_Crunch | + 0; + + //Bits which describe the system hardware capabilities + //XXX Figure out what these should be + auxv.push_back(auxv_t(M5_AT_HWCAP, features)); + //The system page size + auxv.push_back(auxv_t(M5_AT_PAGESZ, ArmISA::VMPageSize)); + //Frequency at which times() increments + auxv.push_back(auxv_t(M5_AT_CLKTCK, 0x64)); + // For statically linked executables, this is the virtual address of the + // program header tables if they appear in the executable image + auxv.push_back(auxv_t(M5_AT_PHDR, elfObject->programHeaderTable())); + // This is the size of a program header entry from the elf file. + auxv.push_back(auxv_t(M5_AT_PHENT, elfObject->programHeaderSize())); + // This is the number of program headers from the original elf file. + auxv.push_back(auxv_t(M5_AT_PHNUM, elfObject->programHeaderCount())); + //This is the address of the elf "interpreter", It should be set + //to 0 for regular executables. It should be something else + //(not sure what) for dynamic libraries. + auxv.push_back(auxv_t(M5_AT_BASE, 0)); + + //XXX Figure out what this should be. + auxv.push_back(auxv_t(M5_AT_FLAGS, 0)); + //The entry point to the program + auxv.push_back(auxv_t(M5_AT_ENTRY, objFile->entryPoint())); + //Different user and group IDs + auxv.push_back(auxv_t(M5_AT_UID, uid())); + auxv.push_back(auxv_t(M5_AT_EUID, euid())); + auxv.push_back(auxv_t(M5_AT_GID, gid())); + auxv.push_back(auxv_t(M5_AT_EGID, egid())); + //Whether to enable "secure mode" in the executable + auxv.push_back(auxv_t(M5_AT_SECURE, 0)); + //The filename of the program + auxv.push_back(auxv_t(M5_AT_EXECFN, 0)); + //The string "v51" with unknown meaning + auxv.push_back(auxv_t(M5_AT_PLATFORM, 0)); } + + //Figure out how big the initial stack nedes to be + + // A sentry NULL void pointer at the top of the stack. + int sentry_size = intSize; + + string platform = "v51"; + int platform_size = platform.size() + 1; + + // The aux vectors are put on the stack in two groups. The first group are + // the vectors that are generated as the elf is loaded. The second group + // are the ones that were computed ahead of time and include the platform + // string. + int aux_data_size = filename.size() + 1; + int env_data_size = 0; for (int i = 0; i < envp.size(); ++i) { env_data_size += envp[i].size() + 1; } + int arg_data_size = 0; + for (int i = 0; i < argv.size(); ++i) { + arg_data_size += argv[i].size() + 1; + } - int space_needed = - argv_array_size + envp_array_size + arg_data_size + env_data_size; - if (space_needed < 16*1024) - space_needed = 16*1024; + int info_block_size = + sentry_size + env_data_size + arg_data_size + + aux_data_size + platform_size; + + //Each auxilliary vector is two 4 byte words + int aux_array_size = intSize * 2 * (auxv.size() + 1); + + int envp_array_size = intSize * (envp.size() + 1); + int argv_array_size = intSize * (argv.size() + 1); + + int argc_size = intSize; + + //Figure out the size of the contents of the actual initial frame + int frame_size = + info_block_size + + aux_array_size + + envp_array_size + + argv_array_size + + argc_size; + + //There needs to be padding after the auxiliary vector data so that the + //very bottom of the stack is aligned properly. + int partial_size = frame_size; + int aligned_partial_size = roundUp(partial_size, align); + int aux_padding = aligned_partial_size - partial_size; + + int space_needed = frame_size + aux_padding; - // set bottom of stack stack_min = stack_base - space_needed; - // align it - stack_min = roundDown(stack_min, pageSize); + stack_min = roundDown(stack_min, align); stack_size = stack_base - stack_min; + // map memory - pTable->allocate(stack_min, roundUp(stack_size, pageSize)); + pTable->allocate(roundDown(stack_min, pageSize), + roundUp(stack_size, pageSize)); // map out initial stack contents - Addr argv_array_base = stack_min + intSize; // room for argc - Addr envp_array_base = argv_array_base + argv_array_size; - Addr arg_data_base = envp_array_base + envp_array_size; - Addr env_data_base = arg_data_base + arg_data_size; + uint32_t sentry_base = stack_base - sentry_size; + uint32_t aux_data_base = sentry_base - aux_data_size; + uint32_t env_data_base = aux_data_base - env_data_size; + uint32_t arg_data_base = env_data_base - arg_data_size; + uint32_t platform_base = arg_data_base - platform_size; + uint32_t auxv_array_base = platform_base - aux_array_size - aux_padding; + uint32_t envp_array_base = auxv_array_base - envp_array_size; + uint32_t argv_array_base = envp_array_base - argv_array_size; + uint32_t argc_base = argv_array_base - argc_size; + + DPRINTF(Stack, "The addresses of items on the initial stack:\n"); + DPRINTF(Stack, "0x%x - aux data\n", aux_data_base); + DPRINTF(Stack, "0x%x - env data\n", env_data_base); + DPRINTF(Stack, "0x%x - arg data\n", arg_data_base); + DPRINTF(Stack, "0x%x - platform base\n", platform_base); + DPRINTF(Stack, "0x%x - auxv array\n", auxv_array_base); + DPRINTF(Stack, "0x%x - envp array\n", envp_array_base); + DPRINTF(Stack, "0x%x - argv array\n", argv_array_base); + DPRINTF(Stack, "0x%x - argc \n", argc_base); + DPRINTF(Stack, "0x%x - stack min\n", stack_min); // write contents to stack - uint64_t argc = argv.size(); - if (intSize == 8) - argc = htog((uint64_t)argc); - else if (intSize == 4) - argc = htog((uint32_t)argc); - else - panic("Unknown int size"); - initVirtMem->writeBlob(stack_min, (uint8_t*)&argc, intSize); + // figure out argc + uint32_t argc = argv.size(); + uint32_t guestArgc = ArmISA::htog(argc); - copyStringArray32(argv, argv_array_base, arg_data_base, initVirtMem); - copyStringArray32(envp, envp_array_base, env_data_base, initVirtMem); + //Write out the sentry void * + uint32_t sentry_NULL = 0; + initVirtMem->writeBlob(sentry_base, + (uint8_t*)&sentry_NULL, sentry_size); - /* - //uint8_t insns[] = {0xe5, 0x9f, 0x00, 0x08, 0xe1, 0xa0, 0xf0, 0x0e}; - uint8_t insns[] = {0x08, 0x00, 0x9f, 0xe5, 0x0e, 0xf0, 0xa0, 0xe1}; + //Fix up the aux vectors which point to other data + for (int i = auxv.size() - 1; i >= 0; i--) { + if (auxv[i].a_type == M5_AT_PLATFORM) { + auxv[i].a_val = platform_base; + initVirtMem->writeString(platform_base, platform.c_str()); + } else if (auxv[i].a_type == M5_AT_EXECFN) { + auxv[i].a_val = aux_data_base; + initVirtMem->writeString(aux_data_base, filename.c_str()); + } + } - initVirtMem->writeBlob(0xffff0fe0, insns, 8); - */ + //Copy the aux stuff + for(int x = 0; x < auxv.size(); x++) + { + initVirtMem->writeBlob(auxv_array_base + x * 2 * intSize, + (uint8_t*)&(auxv[x].a_type), intSize); + initVirtMem->writeBlob(auxv_array_base + (x * 2 + 1) * intSize, + (uint8_t*)&(auxv[x].a_val), intSize); + } + //Write out the terminating zeroed auxilliary vector + const uint64_t zero = 0; + initVirtMem->writeBlob(auxv_array_base + 2 * intSize * auxv.size(), + (uint8_t*)&zero, 2 * intSize); - ThreadContext *tc = system->getThreadContext(contextIds[0]); + copyStringArray(envp, envp_array_base, env_data_base, initVirtMem); + copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem); + + initVirtMem->writeBlob(argc_base, (uint8_t*)&guestArgc, intSize); - tc->setIntReg(ArgumentReg1, argc); - tc->setIntReg(ArgumentReg2, argv_array_base); + ThreadContext *tc = system->getThreadContext(contextIds[0]); + //Set the stack pointer register tc->setIntReg(StackPointerReg, stack_min); + //A pointer to a function to run when the program exits. We'll set this + //to zero explicitly to make sure this isn't used. + tc->setIntReg(ArgumentReg0, 0); + //Set argument regs 1 and 2 to argv[0] and envp[0] respectively + if (argv.size() > 0) { + tc->setIntReg(ArgumentReg1, arg_data_base + arg_data_size - + argv[argv.size() - 1].size() - 1); + } else { + tc->setIntReg(ArgumentReg1, 0); + } + if (envp.size() > 0) { + tc->setIntReg(ArgumentReg2, env_data_base + env_data_size - + envp[envp.size() - 1].size() - 1); + } else { + tc->setIntReg(ArgumentReg2, 0); + } Addr prog_entry = objFile->entryPoint(); tc->setPC(prog_entry); tc->setNextPC(prog_entry + sizeof(MachInst)); + + //Align the "stack_min" to a page boundary. + stack_min = roundDown(stack_min, pageSize); } ArmISA::IntReg |