diff options
author | Gabe Black <gblack@eecs.umich.edu> | 2006-03-09 18:35:28 -0500 |
---|---|---|
committer | Gabe Black <gblack@eecs.umich.edu> | 2006-03-09 18:35:28 -0500 |
commit | 872bbdfc33cb82bf32576db3a57d3055a04acbac (patch) | |
tree | 837dd214bd682ac7efa515b18857bec7d4d35bef /sim | |
parent | 3adb45144aca819c9796168ecde7a263169d9d4d (diff) | |
parent | 7b283dbc090d1197593b00fd1279b92f7c2e693e (diff) | |
download | gem5-872bbdfc33cb82bf32576db3a57d3055a04acbac.tar.xz |
Hand merge. Stuff probably doesn't compile.
--HG--
rename : arch/alpha/isa_desc => arch/alpha/isa/main.isa
rename : arch/alpha/alpha_linux_process.cc => arch/alpha/linux/process.cc
rename : arch/alpha/alpha_linux_process.hh => arch/alpha/linux/process.hh
rename : arch/alpha/alpha_tru64_process.cc => arch/alpha/tru64/process.cc
rename : arch/alpha/alpha_tru64_process.hh => arch/alpha/tru64/process.hh
rename : cpu/exec_context.cc => cpu/cpu_exec_context.cc
rename : cpu/exec_context.hh => cpu/cpu_exec_context.hh
extra : convert_revision : 7d1efcedd708815d985a951f6f010fbd83dc27e8
Diffstat (limited to 'sim')
-rw-r--r-- | sim/byteswap.hh | 146 | ||||
-rw-r--r-- | sim/faults.cc | 46 | ||||
-rw-r--r-- | sim/faults.hh | 67 | ||||
-rw-r--r-- | sim/host.hh | 8 | ||||
-rw-r--r-- | sim/process.cc | 69 | ||||
-rw-r--r-- | sim/process.hh | 11 | ||||
-rw-r--r-- | sim/pseudo_inst.cc | 285 | ||||
-rw-r--r-- | sim/pseudo_inst.hh | 62 | ||||
-rw-r--r-- | sim/syscall_emul.cc | 177 | ||||
-rw-r--r-- | sim/syscall_emul.hh | 145 | ||||
-rw-r--r-- | sim/system.cc | 288 | ||||
-rw-r--r-- | sim/system.hh | 55 | ||||
-rw-r--r-- | sim/vptr.hh | 116 |
13 files changed, 1073 insertions, 402 deletions
diff --git a/sim/byteswap.hh b/sim/byteswap.hh new file mode 100644 index 000000000..c5d8801ab --- /dev/null +++ b/sim/byteswap.hh @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2004 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. + */ + +//The purpose of this file is to provide endainness conversion utility +//functions. Depending on the endianness of the guest system, either +//the LittleEndianGuest or BigEndianGuest namespace is used. + +#ifndef __SIM_BYTE_SWAP_HH__ +#define __SIM_BYTE_SWAP_HH__ + +#include "sim/host.hh" + +// This lets us figure out what the byte order of the host system is +#if defined(linux) +#include <endian.h> +#else +#include <machine/endian.h> +#endif + +//These functions actually perform the swapping for parameters +//of various bit lengths +static inline uint64_t +swap_byte64(uint64_t x) +{ + return (uint64_t)((((uint64_t)(x) & 0xff) << 56) | + ((uint64_t)(x) & 0xff00ULL) << 40 | + ((uint64_t)(x) & 0xff0000ULL) << 24 | + ((uint64_t)(x) & 0xff000000ULL) << 8 | + ((uint64_t)(x) & 0xff00000000ULL) >> 8 | + ((uint64_t)(x) & 0xff0000000000ULL) >> 24 | + ((uint64_t)(x) & 0xff000000000000ULL) >> 40 | + ((uint64_t)(x) & 0xff00000000000000ULL) >> 56) ; +} + +static inline uint32_t +swap_byte32(uint32_t x) +{ + return (uint32_t)(((uint32_t)(x) & 0xff) << 24 | + ((uint32_t)(x) & 0xff00) << 8 | ((uint32_t)(x) & 0xff0000) >> 8 | + ((uint32_t)(x) & 0xff000000) >> 24); + +} + +static inline uint16_t +swap_byte16(uint16_t x) +{ + return (uint16_t)(((uint16_t)(x) & 0xff) << 8 | + ((uint16_t)(x) & 0xff00) >> 8); +} + +//This lets the compiler figure out how to call the swap_byte functions above +//for different data types. +static inline uint64_t swap_byte(uint64_t x) {return swap_byte64(x);} +static inline int64_t swap_byte(int64_t x) {return swap_byte64((uint64_t)x);} +static inline uint32_t swap_byte(uint32_t x) {return swap_byte32(x);} +static inline int32_t swap_byte(int32_t x) {return swap_byte32((uint32_t)x);} +#if defined(__APPLE__) +static inline long swap_byte(long x) {return swap_byte32((long)x);} +static inline unsigned long swap_byte(unsigned long x) + { return swap_byte32((unsigned long)x);} +#endif +static inline uint16_t swap_byte(uint16_t x) {return swap_byte32(x);} +static inline int16_t swap_byte(int16_t x) {return swap_byte16((uint16_t)x);} +static inline uint8_t swap_byte(uint8_t x) {return x;} +static inline int8_t swap_byte(int8_t x) {return x;} +static inline double swap_byte(double x) {return swap_byte64((uint64_t)x);} +static inline float swap_byte(float x) {return swap_byte32((uint32_t)x);} + +//The conversion functions with fixed endianness on both ends don't need to +//be in a namespace +template <typename T> static inline T betole(T value) {return swap_byte(value);} +template <typename T> static inline T letobe(T value) {return swap_byte(value);} + +//For conversions not involving the guest system, we can define the functions +//conditionally based on the BYTE_ORDER macro and outside of the namespaces +#if BYTE_ORDER == BIG_ENDIAN +template <typename T> static inline T htole(T value) {return swap_byte(value);} +template <typename T> static inline T letoh(T value) {return swap_byte(value);} +template <typename T> static inline T htobe(T value) {return value;} +template <typename T> static inline T betoh(T value) {return value;} +#elif BYTE_ORDER == LITTLE_ENDIAN +template <typename T> static inline T htole(T value) {return value;} +template <typename T> static inline T letoh(T value) {return value;} +template <typename T> static inline T htobe(T value) {return swap_byte(value);} +template <typename T> static inline T betoh(T value) {return swap_byte(value);} +#else + #error Invalid Endianess +#endif + +namespace BigEndianGuest +{ + template <typename T> + static inline T gtole(T value) {return betole(value);} + template <typename T> + static inline T letog(T value) {return letobe(value);} + template <typename T> + static inline T gtobe(T value) {return value;} + template <typename T> + static inline T betog(T value) {return value;} + template <typename T> + static inline T htog(T value) {return htobe(value);} + template <typename T> + static inline T gtoh(T value) {return betoh(value);} +} + +namespace LittleEndianGuest +{ + template <typename T> + static inline T gtole(T value) {return value;} + template <typename T> + static inline T letog(T value) {return value;} + template <typename T> + static inline T gtobe(T value) {return letobe(value);} + template <typename T> + static inline T betog(T value) {return betole(value);} + template <typename T> + static inline T htog(T value) {return htole(value);} + template <typename T> + static inline T gtoh(T value) {return letoh(value);} +} +#endif // __SIM_BYTE_SWAP_HH__ diff --git a/sim/faults.cc b/sim/faults.cc new file mode 100644 index 000000000..701384989 --- /dev/null +++ b/sim/faults.cc @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2003-2005 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. + */ + +#include "sim/faults.hh" +#include "cpu/exec_context.hh" +#include "cpu/base.hh" + +#if !FULL_SYSTEM +void FaultBase::invoke(ExecContext * xc) +{ + fatal("fault (%s) detected @ PC 0x%08p", name(), xc->readPC()); +} +#else +void FaultBase::invoke(ExecContext * xc) +{ + DPRINTF(Fault, "Fault %s at PC: %#x\n", name(), xc->readPC()); + xc->getCpuPtr()->recordEvent(csprintf("Fault %s", name())); + + assert(!xc->misspeculating()); +} +#endif diff --git a/sim/faults.hh b/sim/faults.hh new file mode 100644 index 000000000..18601e8f1 --- /dev/null +++ b/sim/faults.hh @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2003-2005 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. + */ + +#ifndef __FAULTS_HH__ +#define __FAULTS_HH__ + +#include "base/refcnt.hh" +#include "sim/stats.hh" +#include "config/full_system.hh" + +class ExecContext; +class FaultBase; +typedef RefCountingPtr<FaultBase> Fault; + +typedef const char * FaultName; +typedef Stats::Scalar<> FaultStat; + +// Each class has it's name statically define in _name, +// and has a virtual function to access it's name. +// The function is necessary because otherwise, all objects +// which are being accessed cast as a FaultBase * (namely +// all faults returned using the Fault type) will use the +// generic FaultBase name. + +class FaultBase : public RefCounted +{ + public: + virtual FaultName name() = 0; +#if FULL_SYSTEM + virtual void invoke(ExecContext * xc); +#else + virtual void invoke(ExecContext * xc); +#endif +// template<typename T> +// bool isA() {return dynamic_cast<T *>(this);} + virtual bool isMachineCheckFault() {return false;} + virtual bool isAlignmentFault() {return false;} +}; + +FaultBase * const NoFault = 0; + +#endif // __FAULTS_HH__ diff --git a/sim/host.hh b/sim/host.hh index ef7008042..f7e64f23c 100644 --- a/sim/host.hh +++ b/sim/host.hh @@ -54,4 +54,12 @@ typedef int64_t Counter; */ typedef int64_t Tick; +/** + * Address type + * This will probably be moved somewhere else in the near future. + * This should be at least as big as the biggest address width in use + * in the system, which will probably be 64 bits. + */ +typedef uint64_t Addr; + #endif // __HOST_H__ diff --git a/sim/process.cc b/sim/process.cc index bb13bd35f..70a92a604 100644 --- a/sim/process.cc +++ b/sim/process.cc @@ -37,6 +37,7 @@ #include "base/loader/symtab.hh" #include "base/statistics.hh" #include "config/full_system.hh" +#include "cpu/cpu_exec_context.hh" #include "cpu/exec_context.hh" #include "cpu/smt.hh" #include "encumbered/cpu/full/thread.hh" @@ -48,14 +49,13 @@ #include "sim/fake_syscall.hh" #include "sim/process.hh" #include "sim/stats.hh" +#include "sim/syscall_emul.hh" #include "sim/system.hh" -#ifdef TARGET_ALPHA -#include "arch/alpha/alpha_tru64_process.hh" -#include "arch/alpha/alpha_linux_process.hh" -#endif +#include "arch/process.hh" using namespace std; +using namespace TheISA; // // The purpose of this code is to fake the loader & syscall mechanism @@ -247,8 +247,10 @@ static void copyStringArray(vector<string> &strings, Addr array_ptr, Addr data_ptr, TranslatingPort* memPort) { + Addr data_ptr_swap; for (int i = 0; i < strings.size(); ++i) { - memPort->writeBlobFunctional(array_ptr, (uint8_t*)&data_ptr, sizeof(Addr)); + data_ptr_swap = htog(data_ptr); + memPort->writeBlobFunctional(array_ptr, (uint8_t*)&data_ptr_swap, sizeof(Addr)); memPort->writeStringFunctional(data_ptr, strings[i].c_str()); array_ptr += sizeof(Addr); data_ptr += strings[i].size() + 1; @@ -342,23 +344,35 @@ LiveProcess::startup() // write contents to stack uint64_t argc = argv.size(); + argc = htog(argc); initVirtMem->writeBlobFunctional(stack_min, (uint8_t*)&argc, sizeof(uint64_t)); copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem); copyStringArray(envp, envp_array_base, env_data_base, initVirtMem); - RegFile *init_regs = &(execContexts[0]->regs); - - init_regs->intRegFile[ArgumentReg0] = argc; - init_regs->intRegFile[ArgumentReg1] = argv_array_base; - init_regs->intRegFile[StackPointerReg] = stack_min; - init_regs->intRegFile[GlobalPointerReg] = objFile->globalPointer(); - init_regs->pc = prog_entry; - init_regs->npc = prog_entry + sizeof(MachInst); + execContexts[0]->setIntReg(ArgumentReg0, argc); + execContexts[0]->setIntReg(ArgumentReg1, argv_array_base); + execContexts[0]->setIntReg(StackPointerReg, stack_min); + execContexts[0]->setIntReg(GlobalPointerReg, objFile->globalPointer()); + execContexts[0]->setPC(prog_entry); + execContexts[0]->setNextPC(prog_entry + sizeof(MachInst)); num_processes++; } +void +LiveProcess::syscall(ExecContext *xc) +{ + num_syscalls++; + + int64_t callnum = xc->readIntReg(SyscallNumReg); + + SyscallDesc *desc = getDesc(callnum); + if (desc == NULL) + fatal("Syscall %d out of range", callnum); + + desc->doSyscall(callnum, this, xc); +} LiveProcess * LiveProcess::create(const string &nm, System *system, @@ -372,30 +386,10 @@ LiveProcess::create(const string &nm, System *system, fatal("Can't load object file %s", executable); } - // check object type & set up syscall emulation pointer - if (objFile->getArch() == ObjectFile::Alpha) { - - switch (objFile->getOpSys()) { - case ObjectFile::Tru64: - process = new AlphaTru64Process(nm, objFile, system, - stdin_fd, stdout_fd, stderr_fd, - argv, envp); - - break; - - case ObjectFile::Linux: - process = new AlphaLinuxProcess(nm, objFile, system, - stdin_fd, stdout_fd, stderr_fd, - argv, envp); - - break; - - default: - fatal("Unknown/unsupported operating system."); - } - } else { - fatal("Unknown object file architecture."); - } + // set up syscall emulation pointer for the current ISA + process = createProcess(nm, objFile, system, + stdin_fd, stdout_fd, stderr_fd, + argv, envp); if (process == NULL) fatal("Unknown error creating process object."); @@ -404,6 +398,7 @@ LiveProcess::create(const string &nm, System *system, } + BEGIN_DECLARE_SIM_OBJECT_PARAMS(LiveProcess) VectorParam<string> cmd; diff --git a/sim/process.hh b/sim/process.hh index 8d8c9e676..fc600fb06 100644 --- a/sim/process.hh +++ b/sim/process.hh @@ -40,6 +40,7 @@ #include <vector> +#include "arch/isa_traits.hh" #include "base/statistics.hh" #include "base/trace.hh" #include "mem/memory.hh" @@ -49,12 +50,17 @@ #include "sim/stats.hh" #include "targetarch/isa_traits.hh" +class CPUExecContext; class ExecContext; +class SyscallDesc; class TranslatingPort; class System; class Process : public SimObject { + protected: + typedef TheISA::RegFile RegFile; + typedef TheISA::MachInst MachInst; public: /// Pointer to object representing the system this process is @@ -216,6 +222,11 @@ class LiveProcess : public Process std::string executable, std::vector<std::string> &argv, std::vector<std::string> &envp); + + virtual void syscall(ExecContext *xc); + + virtual SyscallDesc* getDesc(int callnum) { panic("Must be implemented."); } + }; diff --git a/sim/pseudo_inst.cc b/sim/pseudo_inst.cc new file mode 100644 index 000000000..e475006e7 --- /dev/null +++ b/sim/pseudo_inst.cc @@ -0,0 +1,285 @@ +/* + * Copyright (c) 2003-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. + */ + +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> +#include <cstdio> + +#include <string> + +#include "sim/pseudo_inst.hh" +#include "arch/vtophys.hh" +#include "cpu/base.hh" +#include "cpu/sampler/sampler.hh" +#include "cpu/exec_context.hh" +#include "kern/kernel_stats.hh" +#include "sim/param.hh" +#include "sim/serialize.hh" +#include "sim/sim_exit.hh" +#include "sim/stat_control.hh" +#include "sim/stats.hh" +#include "sim/system.hh" +#include "sim/debug.hh" +#include "sim/vptr.hh" + +using namespace std; + +extern Sampler *SampCPU; + +using namespace Stats; +using namespace TheISA; + +namespace AlphaPseudo +{ + bool doStatisticsInsts; + bool doCheckpointInsts; + bool doQuiesce; + + void + arm(ExecContext *xc) + { + xc->getCpuPtr()->kernelStats->arm(); + } + + void + quiesce(ExecContext *xc) + { + if (!doQuiesce) + return; + + xc->suspend(); + xc->getCpuPtr()->kernelStats->quiesce(); + } + + void + quiesceNs(ExecContext *xc, uint64_t ns) + { + if (!doQuiesce || ns == 0) + return; + + Event *quiesceEvent = xc->getQuiesceEvent(); + + if (quiesceEvent->scheduled()) + quiesceEvent->reschedule(curTick + Clock::Int::ns * ns); + else + quiesceEvent->schedule(curTick + Clock::Int::ns * ns); + + xc->suspend(); + xc->getCpuPtr()->kernelStats->quiesce(); + } + + void + quiesceCycles(ExecContext *xc, uint64_t cycles) + { + if (!doQuiesce || cycles == 0) + return; + + Event *quiesceEvent = xc->getQuiesceEvent(); + + if (quiesceEvent->scheduled()) + quiesceEvent->reschedule(curTick + + xc->getCpuPtr()->cycles(cycles)); + else + quiesceEvent->schedule(curTick + + xc->getCpuPtr()->cycles(cycles)); + + xc->suspend(); + xc->getCpuPtr()->kernelStats->quiesce(); + } + + uint64_t + quiesceTime(ExecContext *xc) + { + return (xc->readLastActivate() - xc->readLastSuspend()) / Clock::Int::ns; + } + + void + ivlb(ExecContext *xc) + { + xc->getCpuPtr()->kernelStats->ivlb(); + } + + void + ivle(ExecContext *xc) + { + } + + void + m5exit_old(ExecContext *xc) + { + SimExit(curTick, "m5_exit_old instruction encountered"); + } + + void + m5exit(ExecContext *xc, Tick delay) + { + Tick when = curTick + delay * Clock::Int::ns; + SimExit(when, "m5_exit instruction encountered"); + } + + void + resetstats(ExecContext *xc, Tick delay, Tick period) + { + if (!doStatisticsInsts) + return; + + + Tick when = curTick + delay * Clock::Int::ns; + Tick repeat = period * Clock::Int::ns; + + using namespace Stats; + SetupEvent(Reset, when, repeat); + } + + void + dumpstats(ExecContext *xc, Tick delay, Tick period) + { + if (!doStatisticsInsts) + return; + + + Tick when = curTick + delay * Clock::Int::ns; + Tick repeat = period * Clock::Int::ns; + + using namespace Stats; + SetupEvent(Dump, when, repeat); + } + + void + addsymbol(ExecContext *xc, Addr addr, Addr symbolAddr) + { + char symb[100]; + CopyString(xc, symb, symbolAddr, 100); + std::string symbol(symb); + + DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr); + + xc->getSystemPtr()->kernelSymtab->insert(addr,symbol); + } + + void + dumpresetstats(ExecContext *xc, Tick delay, Tick period) + { + if (!doStatisticsInsts) + return; + + + Tick when = curTick + delay * Clock::Int::ns; + Tick repeat = period * Clock::Int::ns; + + using namespace Stats; + SetupEvent(Dump|Reset, when, repeat); + } + + void + m5checkpoint(ExecContext *xc, Tick delay, Tick period) + { + if (!doCheckpointInsts) + return; + + + Tick when = curTick + delay * Clock::Int::ns; + Tick repeat = period * Clock::Int::ns; + + Checkpoint::setup(when, repeat); + } + + uint64_t + readfile(ExecContext *xc, Addr vaddr, uint64_t len, uint64_t offset) + { + const string &file = xc->getCpuPtr()->system->params()->readfile; + if (file.empty()) { + return ULL(0); + } + + uint64_t result = 0; + + int fd = ::open(file.c_str(), O_RDONLY, 0); + if (fd < 0) + panic("could not open file %s\n", file); + + if (::lseek(fd, offset, SEEK_SET) < 0) + panic("could not seek: %s", strerror(errno)); + + char *buf = new char[len]; + char *p = buf; + while (len > 0) { + int bytes = ::read(fd, p, len); + if (bytes <= 0) + break; + + p += bytes; + result += bytes; + len -= bytes; + } + + close(fd); + CopyIn(xc, vaddr, buf, result); + delete [] buf; + return result; + } + + class Context : public ParamContext + { + public: + Context(const string §ion) : ParamContext(section) {} + void checkParams(); + }; + + Context context("pseudo_inst"); + + Param<bool> __quiesce(&context, "quiesce", + "enable quiesce instructions", + true); + Param<bool> __statistics(&context, "statistics", + "enable statistics pseudo instructions", + true); + Param<bool> __checkpoint(&context, "checkpoint", + "enable checkpoint pseudo instructions", + true); + + void + Context::checkParams() + { + doQuiesce = __quiesce; + doStatisticsInsts = __statistics; + doCheckpointInsts = __checkpoint; + } + + void debugbreak(ExecContext *xc) + { + debug_break(); + } + + void switchcpu(ExecContext *xc) + { + if (SampCPU) + SampCPU->switchCPUs(); + } +} diff --git a/sim/pseudo_inst.hh b/sim/pseudo_inst.hh new file mode 100644 index 000000000..4dd427c99 --- /dev/null +++ b/sim/pseudo_inst.hh @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2003-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. + */ + +class ExecContext; + +//We need the "Tick" data type from here +#include "sim/host.hh" +//We need the "Addr" data type from here +#include "arch/isa_traits.hh" + +namespace AlphaPseudo +{ + /** + * @todo these externs are only here for a hack in fullCPU::takeOver... + */ + extern bool doStatisticsInsts; + extern bool doCheckpointInsts; + extern bool doQuiesce; + + void arm(ExecContext *xc); + void quiesce(ExecContext *xc); + void quiesceNs(ExecContext *xc, uint64_t ns); + void quiesceCycles(ExecContext *xc, uint64_t cycles); + uint64_t quiesceTime(ExecContext *xc); + void ivlb(ExecContext *xc); + void ivle(ExecContext *xc); + void m5exit(ExecContext *xc, Tick delay); + void m5exit_old(ExecContext *xc); + void resetstats(ExecContext *xc, Tick delay, Tick period); + void dumpstats(ExecContext *xc, Tick delay, Tick period); + void dumpresetstats(ExecContext *xc, Tick delay, Tick period); + void m5checkpoint(ExecContext *xc, Tick delay, Tick period); + uint64_t readfile(ExecContext *xc, Addr vaddr, uint64_t len, uint64_t offset); + void debugbreak(ExecContext *xc); + void switchcpu(ExecContext *xc); + void addsymbol(ExecContext *xc, Addr addr, Addr symbolAddr); +} diff --git a/sim/syscall_emul.cc b/sim/syscall_emul.cc index 0cebee0e1..1d0b3a375 100644 --- a/sim/syscall_emul.cc +++ b/sim/syscall_emul.cc @@ -26,6 +26,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include <fcntl.h> #include <unistd.h> #include <string> @@ -40,17 +41,18 @@ #include "sim/sim_events.hh" using namespace std; +using namespace TheISA; void SyscallDesc::doSyscall(int callnum, Process *process, ExecContext *xc) { DPRINTFR(SyscallVerbose, "%s: syscall %s called\n", - xc->cpu->name(), name); + xc->getCpuPtr()->name(), name); SyscallReturn retval = (*funcPtr)(this, callnum, process, xc); DPRINTFR(SyscallVerbose, "%s: syscall %s returns %d\n", - xc->cpu->name(), name, retval.value()); + xc->getCpuPtr()->name(), name, retval.value()); if (!(flags & SyscallDesc::SuppressReturnValue)) xc->setSyscallReturn(retval); @@ -89,7 +91,7 @@ exitFunc(SyscallDesc *desc, int callnum, Process *process, SyscallReturn getpagesizeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) { - return VMPageSize; + return (int)VMPageSize; } @@ -191,7 +193,7 @@ unlinkFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) { string path; - if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != No_Fault) + if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault) return (TheISA::IntReg)-EFAULT; int result = unlink(path.c_str()); @@ -203,12 +205,12 @@ renameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) { string old_name; - if (xc->port->readStringFunctional(old_name, xc->getSyscallArg(0)) != No_Fault) + if (xc->port->readStringFunctional(old_name, xc->getSyscallArg(0)) != NoFault) return -EFAULT; string new_name; - if (xc->port->readStringFunctional(new_name, xc->getSyscallArg(1)) != No_Fault) + if (xc->port->readStringFunctional(new_name, xc->getSyscallArg(1)) != NoFault) return -EFAULT; int64_t result = rename(old_name.c_str(), new_name.c_str()); @@ -220,7 +222,7 @@ truncateFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) { string path; - if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != No_Fault) + if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault) return -EFAULT; off_t length = xc->getSyscallArg(1); @@ -248,7 +250,7 @@ chownFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) { string path; - if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != No_Fault) + if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault) return -EFAULT; /* XXX endianess */ @@ -278,3 +280,162 @@ fchownFunc(SyscallDesc *desc, int num, Process *process, ExecContext *xc) int result = fchown(fd, hostOwner, hostGroup); return (result == -1) ? -errno : result; } + + +SyscallReturn +fcntlFunc(SyscallDesc *desc, int num, Process *process, + ExecContext *xc) +{ + int fd = xc->getSyscallArg(0); + + if (fd < 0 || process->sim_fd(fd) < 0) + return -EBADF; + + int cmd = xc->getSyscallArg(1); + switch (cmd) { + case 0: // F_DUPFD + // if we really wanted to support this, we'd need to do it + // in the target fd space. + warn("fcntl(%d, F_DUPFD) not supported, error returned\n", fd); + return -EMFILE; + + case 1: // F_GETFD (get close-on-exec flag) + case 2: // F_SETFD (set close-on-exec flag) + return 0; + + case 3: // F_GETFL (get file flags) + case 4: // F_SETFL (set file flags) + // not sure if this is totally valid, but we'll pass it through + // to the underlying OS + warn("fcntl(%d, %d) passed through to host\n", fd, cmd); + return fcntl(process->sim_fd(fd), cmd); + // return 0; + + case 7: // F_GETLK (get lock) + case 8: // F_SETLK (set lock) + case 9: // F_SETLKW (set lock and wait) + // don't mess with file locking... just act like it's OK + warn("File lock call (fcntl(%d, %d)) ignored.\n", fd, cmd); + return 0; + + default: + warn("Unknown fcntl command %d\n", cmd); + return 0; + } +} + +SyscallReturn +pipePseudoFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) +{ + int fds[2], sim_fds[2]; + int pipe_retval = pipe(fds); + + if (pipe_retval < 0) { + // error + return pipe_retval; + } + + sim_fds[0] = process->alloc_fd(fds[0]); + sim_fds[1] = process->alloc_fd(fds[1]); + + // Alpha Linux convention for pipe() is that fd[0] is returned as + // the return value of the function, and fd[1] is returned in r20. + xc->setIntReg(SyscallPseudoReturnReg, sim_fds[1]); + return sim_fds[0]; +} + + +SyscallReturn +getpidPseudoFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) +{ + // Make up a PID. There's no interprocess communication in + // fake_syscall mode, so there's no way for a process to know it's + // not getting a unique value. + + xc->setIntReg(SyscallPseudoReturnReg, 99); + return 100; +} + + +SyscallReturn +getuidPseudoFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) +{ + // Make up a UID and EUID... it shouldn't matter, and we want the + // simulation to be deterministic. + + // EUID goes in r20. + xc->setIntReg(SyscallPseudoReturnReg, 100); //EUID + return 100; // UID +} + + +SyscallReturn +getgidPseudoFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) +{ + // Get current group ID. EGID goes in r20. + xc->setIntReg(SyscallPseudoReturnReg, 100); //EGID + return 100; +} + + +SyscallReturn +setuidFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) +{ + // can't fathom why a benchmark would call this. + warn("Ignoring call to setuid(%d)\n", xc->getSyscallArg(0)); + return 0; +} + +SyscallReturn +getpidFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) +{ + // Make up a PID. There's no interprocess communication in + // fake_syscall mode, so there's no way for a process to know it's + // not getting a unique value. + + xc->setIntReg(SyscallPseudoReturnReg, 99); //PID + return 100; +} + +SyscallReturn +getppidFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) +{ + return 99; +} + +SyscallReturn +getuidFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) +{ + return 100; // UID +} + +SyscallReturn +geteuidFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) +{ + return 100; // UID +} + +SyscallReturn +getgidFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) +{ + return 100; +} + +SyscallReturn +getegidFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) +{ + return 100; +} + + diff --git a/sim/syscall_emul.hh b/sim/syscall_emul.hh index ed3b0fc8b..25f8c6cb8 100644 --- a/sim/syscall_emul.hh +++ b/sim/syscall_emul.hh @@ -29,6 +29,9 @@ #ifndef __SIM_SYSCALL_EMUL_HH__ #define __SIM_SYSCALL_EMUL_HH__ +#define BSD_HOST (defined(__APPLE__) || defined(__OpenBSD__) || \ + defined(__FreeBSD__)) + /// /// @file syscall_emul.hh /// @@ -44,7 +47,7 @@ #include "base/intmath.hh" // for RoundUp #include "mem/translating_port.hh" -#include "targetarch/isa_traits.hh" // for Addr +#include "arch/isa_traits.hh" // for Addr #include "base/trace.hh" #include "cpu/exec_context.hh" @@ -237,6 +240,58 @@ SyscallReturn chownFunc(SyscallDesc *desc, int num, SyscallReturn fchownFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); +/// Target fnctl() handler. +SyscallReturn fcntlFunc(SyscallDesc *desc, int num, + Process *process, ExecContext *xc); + +/// Target setuid() handler. +SyscallReturn setuidFunc(SyscallDesc *desc, int num, + Process *p, ExecContext *xc); + +/// Target getpid() handler. +SyscallReturn getpidFunc(SyscallDesc *desc, int num, + Process *p, ExecContext *xc); + +/// Target getuid() handler. +SyscallReturn getuidFunc(SyscallDesc *desc, int num, + Process *p, ExecContext *xc); + +/// Target getgid() handler. +SyscallReturn getgidFunc(SyscallDesc *desc, int num, + Process *p, ExecContext *xc); + +/// Target getppid() handler. +SyscallReturn getppidFunc(SyscallDesc *desc, int num, + Process *p, ExecContext *xc); + +/// Target geteuid() handler. +SyscallReturn geteuidFunc(SyscallDesc *desc, int num, + Process *p, ExecContext *xc); + +/// Target getegid() handler. +SyscallReturn getegidFunc(SyscallDesc *desc, int num, + Process *p, ExecContext *xc); + + + +/// Pseudo Funcs - These functions use a different return convension, +/// returning a second value in a register other than the normal return register +SyscallReturn pipePseudoFunc(SyscallDesc *desc, int num, + Process *process, ExecContext *xc); + +/// Target getpidPseudo() handler. +SyscallReturn getpidPseudoFunc(SyscallDesc *desc, int num, + Process *p, ExecContext *xc); + +/// Target getuidPseudo() handler. +SyscallReturn getuidPseudoFunc(SyscallDesc *desc, int num, + Process *p, ExecContext *xc); + +/// Target getgidPseudo() handler. +SyscallReturn getgidPseudoFunc(SyscallDesc *desc, int num, + Process *p, ExecContext *xc); + + /// This struct is used to build an target-OS-dependent table that /// maps the target's open() flags to the host open() flags. struct OpenFlagTransTable { @@ -315,7 +370,7 @@ openFunc(SyscallDesc *desc, int callnum, Process *process, { std::string path; - if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != No_Fault) + if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault) return -EFAULT; if (path == "/dev/sysdev0") { @@ -362,7 +417,7 @@ chmodFunc(SyscallDesc *desc, int callnum, Process *process, { std::string path; - if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != No_Fault) + if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault) return -EFAULT; uint32_t mode = xc->getSyscallArg(1); @@ -374,7 +429,7 @@ chmodFunc(SyscallDesc *desc, int callnum, Process *process, // do the chmod int result = chmod(path.c_str(), hostMode); if (result < 0) - return errno; + return -errno; return 0; } @@ -401,7 +456,7 @@ fchmodFunc(SyscallDesc *desc, int callnum, Process *process, // do the fchmod int result = fchmod(process->sim_fd(fd), hostMode); if (result < 0) - return errno; + return -errno; return 0; } @@ -415,14 +470,14 @@ statFunc(SyscallDesc *desc, int callnum, Process *process, { std::string path; - if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != No_Fault) + if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault) return -EFAULT; struct stat hostBuf; int result = stat(path.c_str(), &hostBuf); if (result < 0) - return errno; + return -errno; OS::copyOutStatBuf(xc->port, xc->getSyscallArg(1), &hostBuf); @@ -442,13 +497,18 @@ fstat64Func(SyscallDesc *desc, int callnum, Process *process, return -EBADF; } - struct stat64 hostBuf; +#if BSD_HOST + struct stat hostBuf; + int result = fstat(process->sim_fd(fd), &hostBuf); +#else + struct stat64 hostBuf; int result = fstat64(process->sim_fd(fd), &hostBuf); +#endif if (result < 0) - return errno; + return -errno; - OS::copyOutStat64Buf(xc->port, xc->getSyscallArg(1), &hostBuf); + OS::copyOutStat64Buf(xc->port, fd, xc->getSyscallArg(1), &hostBuf); return 0; } @@ -462,7 +522,7 @@ lstatFunc(SyscallDesc *desc, int callnum, Process *process, { std::string path; - if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != No_Fault) + if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault) return -EFAULT; struct stat hostBuf; @@ -484,16 +544,21 @@ lstat64Func(SyscallDesc *desc, int callnum, Process *process, { std::string path; - if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != No_Fault) + if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault) return -EFAULT; +#if BSD_HOST + struct stat hostBuf; + int result = lstat(path.c_str(), &hostBuf); +#else struct stat64 hostBuf; int result = lstat64(path.c_str(), &hostBuf); +#endif if (result < 0) return -errno; - OS::copyOutStat64Buf(xc->port, xc->getSyscallArg(1), &hostBuf); + OS::copyOutStat64Buf(xc->port, -1, xc->getSyscallArg(1), &hostBuf); return 0; } @@ -531,14 +596,14 @@ statfsFunc(SyscallDesc *desc, int callnum, Process *process, { std::string path; - if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != No_Fault) + if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault) return -EFAULT; struct statfs hostBuf; int result = statfs(path.c_str(), &hostBuf); if (result < 0) - return errno; + return -errno; OS::copyOutStatfsBuf(xc->port, xc->getSyscallArg(1), &hostBuf); @@ -561,7 +626,7 @@ fstatfsFunc(SyscallDesc *desc, int callnum, Process *process, int result = fstatfs(fd, &hostBuf); if (result < 0) - return errno; + return -errno; OS::copyOutStatfsBuf(xc->port, xc->getSyscallArg(1), &hostBuf); @@ -589,9 +654,9 @@ writevFunc(SyscallDesc *desc, int callnum, Process *process, typename OS::tgt_iovec tiov; xc->port->readBlobFunctional(tiov_base + i*sizeof(typename OS::tgt_iovec),(uint8_t*) &tiov, sizeof(typename OS::tgt_iovec)); - hiov[i].iov_len = tiov.iov_len; + hiov[i].iov_len = gtoh(tiov.iov_len); hiov[i].iov_base = new char [hiov[i].iov_len]; - xc->port->readBlobFunctional(tiov.iov_base, + xc->port->readBlobFunctional(gtoh(tiov.iov_base), (uint8_t *)hiov[i].iov_base, hiov[i].iov_len); } @@ -603,7 +668,7 @@ writevFunc(SyscallDesc *desc, int callnum, Process *process, } if (result < 0) - return errno; + return -errno; return 0; } @@ -635,7 +700,7 @@ mmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) if (start == 0) { // user didn't give an address... pick one from our "mmap region" start = p->mmap_end; - p->mmap_end += roundUp(length, VMPageSize); + p->mmap_end += roundUp(length, TheISA::VMPageSize); if (p->nxm_start != 0) { //If we have an nxm space, make sure we haven't colided assert(p->mmap_end < p->nxm_start); @@ -654,22 +719,24 @@ mmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) template <class OS> SyscallReturn getrlimitFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) + ExecContext *xc) { unsigned resource = xc->getSyscallArg(0); TypedBufferArg<typename OS::rlimit> rlp(xc->getSyscallArg(1)); switch (resource) { - case OS::RLIMIT_STACK: - // max stack size in bytes: make up a number (2MB for now) - rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024; - break; - - default: - std::cerr << "getrlimitFunc: unimplemented resource " << resource - << std::endl; - abort(); - break; + case OS::TGT_RLIMIT_STACK: + // max stack size in bytes: make up a number (2MB for now) + rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024; + rlp->rlim_cur = htog(rlp->rlim_cur); + rlp->rlim_max = htog(rlp->rlim_max); + break; + + default: + std::cerr << "getrlimitFunc: unimplemented resource " << resource + << std::endl; + abort(); + break; } rlp.copyOut(xc->port); @@ -680,12 +747,14 @@ getrlimitFunc(SyscallDesc *desc, int callnum, Process *process, template <class OS> SyscallReturn gettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) + ExecContext *xc) { TypedBufferArg<typename OS::timeval> tp(xc->getSyscallArg(0)); getElapsedTime(tp->tv_sec, tp->tv_usec); tp->tv_sec += seconds_since_epoch; + tp->tv_sec = htog(tp->tv_sec); + tp->tv_usec = htog(tp->tv_usec); tp.copyOut(xc->port); @@ -701,7 +770,7 @@ utimesFunc(SyscallDesc *desc, int callnum, Process *process, { std::string path; - if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != No_Fault) + if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault) return -EFAULT; TypedBufferArg<typename OS::timeval [2]> tp(xc->getSyscallArg(1)); @@ -710,8 +779,8 @@ utimesFunc(SyscallDesc *desc, int callnum, Process *process, struct timeval hostTimeval[2]; for (int i = 0; i < 2; ++i) { - hostTimeval[i].tv_sec = (*tp)[i].tv_sec; - hostTimeval[i].tv_usec = (*tp)[i].tv_usec; + hostTimeval[i].tv_sec = gtoh((*tp)[i].tv_sec); + hostTimeval[i].tv_usec = gtoh((*tp)[i].tv_usec); } int result = utimes(path.c_str(), hostTimeval); @@ -720,7 +789,6 @@ utimesFunc(SyscallDesc *desc, int callnum, Process *process, return 0; } - /// Target getrusage() function. template <class OS> SyscallReturn @@ -730,7 +798,7 @@ getrusageFunc(SyscallDesc *desc, int callnum, Process *process, int who = xc->getSyscallArg(0); // THREAD, SELF, or CHILDREN TypedBufferArg<typename OS::rusage> rup(xc->getSyscallArg(1)); - if (who != OS::RUSAGE_SELF) { + if (who != OS::TGT_RUSAGE_SELF) { // don't really handle THREAD or CHILDREN, but just warn and // plow ahead warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.", @@ -738,6 +806,9 @@ getrusageFunc(SyscallDesc *desc, int callnum, Process *process, } getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec); + rup->ru_utime.tv_sec = htog(rup->ru_utime.tv_sec); + rup->ru_utime.tv_usec = htog(rup->ru_utime.tv_usec); + rup->ru_stime.tv_sec = 0; rup->ru_stime.tv_usec = 0; rup->ru_maxrss = 0; diff --git a/sim/system.cc b/sim/system.cc index 07eb81c71..3ed7ed590 100644 --- a/sim/system.cc +++ b/sim/system.cc @@ -1,36 +1,11 @@ -/* - * Copyright (c) 2002-2005 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. - */ - #include "base/loader/object_file.hh" #include "base/loader/symtab.hh" #include "cpu/exec_context.hh" +#include "arch/vtophys.hh" #include "mem/memory.hh" #include "sim/builder.hh" +#include "arch/isa_traits.hh" +#include "sim/byteswap.hh" #include "sim/system.hh" #include "base/trace.hh" #if FULL_SYSTEM @@ -41,6 +16,7 @@ #endif using namespace std; +using namespace TheISA; vector<System *> System::systemList; @@ -53,39 +29,24 @@ System::System(Params *p) #else page_ptr(0), #endif - params(p) + _params(p) { // add self to global system list systemList.push_back(this); #if FULL_SYSTEM kernelSymtab = new SymbolTable; - consoleSymtab = new SymbolTable; - palSymtab = new SymbolTable; debugSymbolTable = new SymbolTable; /** - * Load the kernel, pal, and console code into memory + * Load the kernel code into memory */ // Load kernel code - kernel = createObjectFile(params->kernel_path); + kernel = createObjectFile(params()->kernel_path); if (kernel == NULL) - fatal("Could not load kernel file %s", params->kernel_path); - - // Load Console Code - console = createObjectFile(params->console_path); - if (console == NULL) - fatal("Could not load console file %s", params->console_path); - - // Load pal file - pal = createObjectFile(params->palcode); - if (pal == NULL) - fatal("Could not load PALcode file %s", params->palcode); - + fatal("Could not load kernel file %s", params()->kernel_path); // Load program sections into memory - pal->loadSections(physmem, true); - console->loadSections(physmem, true); kernel->loadSections(physmem, true); // setup entry points @@ -100,73 +61,19 @@ System::System(Params *p) if (!kernel->loadLocalSymbols(kernelSymtab)) panic("could not load kernel local symbols\n"); - if (!console->loadGlobalSymbols(consoleSymtab)) - panic("could not load console symbols\n"); - - if (!pal->loadGlobalSymbols(palSymtab)) - panic("could not load pal symbols\n"); - - if (!pal->loadLocalSymbols(palSymtab)) - panic("could not load pal symbols\n"); - if (!kernel->loadGlobalSymbols(debugSymbolTable)) panic("could not load kernel symbols\n"); if (!kernel->loadLocalSymbols(debugSymbolTable)) panic("could not load kernel local symbols\n"); - if (!console->loadGlobalSymbols(debugSymbolTable)) - panic("could not load console symbols\n"); - - if (!pal->loadGlobalSymbols(debugSymbolTable)) - panic("could not load pal symbols\n"); - - if (!pal->loadLocalSymbols(debugSymbolTable)) - panic("could not load pal symbols\n"); - - DPRINTF(Loader, "Kernel start = %#x\n", kernelStart); DPRINTF(Loader, "Kernel end = %#x\n", kernelEnd); DPRINTF(Loader, "Kernel entry = %#x\n", kernelEntry); DPRINTF(Loader, "Kernel loaded...\n"); - Addr addr = 0; -#ifdef DEBUG - consolePanicEvent = addConsoleFuncEvent<BreakPCEvent>("panic"); -#endif - - /** - * Copy the osflags (kernel arguments) into the consoles - * memory. (Presently Linux does not use the console service - * routine to get these command line arguments, but Tru64 and - * others do.) - */ - if (consoleSymtab->findAddress("env_booted_osflags", addr)) { - Addr paddr = vtophys(physmem, addr); - char *osflags = (char *)physmem->dma_addr(paddr, sizeof(uint32_t)); - - if (osflags) - strcpy(osflags, params->boot_osflags.c_str()); - } - - /** - * Set the hardware reset parameter block system type and revision - * information to Tsunami. - */ - if (consoleSymtab->findAddress("m5_rpb", addr)) { - Addr paddr = vtophys(physmem, addr); - char *hwrpb = (char *)physmem->dma_addr(paddr, sizeof(uint64_t)); - - if (!hwrpb) - panic("could not translate hwrpb addr\n"); - - *(uint64_t*)(hwrpb+0x50) = htog(params->system_type); - *(uint64_t*)(hwrpb+0x58) = htog(params->system_rev); - } else - panic("could not find hwrpb\n"); - +#if FULL_SYSTEM kernelBinning = new Kernel::Binning(this); - #endif // FULL_SYSTEM // increment the number of running systms @@ -177,77 +84,9 @@ System::~System() { #if FULL_SYSTEM delete kernelSymtab; - delete consoleSymtab; delete kernel; - delete console; - delete pal; delete kernelBinning; - -#ifdef DEBUG - delete consolePanicEvent; -#endif - -#endif // FULL_SYSTEM -} - - -/** - * This function fixes up addresses that are used to match PCs for - * hooking simulator events on to target function executions. - * - * Alpha binaries may have multiple global offset table (GOT) - * sections. A function that uses the GOT starts with a - * two-instruction prolog which sets the global pointer (gp == r29) to - * the appropriate GOT section. The proper gp value is calculated - * based on the function address, which must be passed by the caller - * in the procedure value register (pv aka t12 == r27). This sequence - * looks like the following: - * - * opcode Ra Rb offset - * ldah gp,X(pv) 09 29 27 X - * lda gp,Y(gp) 08 29 29 Y - * - * for some constant offsets X and Y. The catch is that the linker - * (or maybe even the compiler, I'm not sure) may recognize that the - * caller and callee are using the same GOT section, making this - * prolog redundant, and modify the call target to skip these - * instructions. If we check for execution of the first instruction - * of a function (the one the symbol points to) to detect when to skip - * it, we'll miss all these modified calls. It might work to - * unconditionally check for the third instruction, but not all - * functions have this prolog, and there's some chance that those - * first two instructions could have undesired consequences. So we do - * the Right Thing and pattern-match the first two instructions of the - * function to decide where to patch. - * - * Eventually this code should be moved into an ISA-specific file. - */ -Addr -System::fixFuncEventAddr(Addr addr) -{ -#if FULL_SYSTEM - // mask for just the opcode, Ra, and Rb fields (not the offset) - const uint32_t inst_mask = 0xffff0000; - // ldah gp,X(pv): opcode 9, Ra = 29, Rb = 27 - const uint32_t gp_ldah_pattern = (9 << 26) | (29 << 21) | (27 << 16); - // lda gp,Y(gp): opcode 8, Ra = 29, rb = 29 - const uint32_t gp_lda_pattern = (8 << 26) | (29 << 21) | (29 << 16); - // instruction size - const int sz = sizeof(uint32_t); - - Addr paddr = vtophys(physmem, addr); - uint32_t i1 = *(uint32_t *)physmem->dma_addr(paddr, sz); - uint32_t i2 = *(uint32_t *)physmem->dma_addr(paddr+sz, sz); - - if ((i1 & inst_mask) == gp_ldah_pattern && - (i2 & inst_mask) == gp_lda_pattern) { - Addr new_addr = addr + 2*sz; - DPRINTF(Loader, "fixFuncEventAddr: %p -> %p", addr, new_addr); - return new_addr; - } else { - return addr; - } #else panic("System::fixFuncEventAddr needs to be rewritten " "to work with syscall emulation"); @@ -255,29 +94,7 @@ System::fixFuncEventAddr(Addr addr) } #if FULL_SYSTEM -void -System::setAlphaAccess(Addr access) -{ - Addr addr = 0; - if (consoleSymtab->findAddress("m5AlphaAccess", addr)) { - Addr paddr = vtophys(physmem, addr); - uint64_t *m5AlphaAccess = - (uint64_t *)physmem->dma_addr(paddr, sizeof(uint64_t)); - - if (!m5AlphaAccess) - panic("could not translate m5AlphaAccess addr\n"); - - *m5AlphaAccess = htog(EV5::Phys2K0Seg(access)); - } else - panic("could not find m5AlphaAccess\n"); -} - -bool -System::breakpoint() -{ - return remoteGDB[0]->trap(ALPHA_KENTRY_INT); -} int rgdb_wait = -1; @@ -326,11 +143,9 @@ System::registerExecContext(ExecContext *xc, int id) void System::startup() { - if (!execContexts.empty()) { - // activate with zero delay so that we start ticking right - // away on cycle 0 - execContexts[0]->activate(0); - } + int i; + for (i = 0; i < execContexts.size(); i++) + execContexts[i]->activate(0); } void @@ -372,8 +187,6 @@ System::serialize(ostream &os) kernelBinning->serialize(os); kernelSymtab->serialize("kernel_symtab", os); - consoleSymtab->serialize("console_symtab", os); - palSymtab->serialize("pal_symtab", os); #endif // FULL_SYSTEM } @@ -385,8 +198,6 @@ System::unserialize(Checkpoint *cp, const string §ion) kernelBinning->unserialize(cp, section); kernelSymtab->unserialize("kernel_symtab", cp, section); - consoleSymtab->unserialize("console_symtab", cp, section); - palSymtab->unserialize("pal_symtab", cp, section); #endif // FULL_SYSTEM } @@ -408,78 +219,5 @@ printSystems() System::printSystems(); } -BEGIN_DECLARE_SIM_OBJECT_PARAMS(System) - - SimObjectParam<Memory *> physmem; - -#if FULL_SYSTEM - Param<Tick> boot_cpu_frequency; - SimObjectParam<MemoryController *> memctrl; - - Param<string> kernel; - Param<string> console; - Param<string> pal; - - Param<string> boot_osflags; - Param<string> readfile; - Param<unsigned int> init_param; - - Param<uint64_t> system_type; - Param<uint64_t> system_rev; - - Param<bool> bin; - VectorParam<string> binned_fns; - Param<bool> bin_int; -#endif // FULL_SYSTEM - -END_DECLARE_SIM_OBJECT_PARAMS(System) - -BEGIN_INIT_SIM_OBJECT_PARAMS(System) - - INIT_PARAM(physmem, "physical memory") - -#if FULL_SYSTEM - , - INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"), - INIT_PARAM(memctrl, "memory controller"), - INIT_PARAM(kernel, "file that contains the kernel code"), - INIT_PARAM(console, "file that contains the console code"), - INIT_PARAM(pal, "file that contains palcode"), - INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot", - "a"), - INIT_PARAM_DFLT(readfile, "file to read startup script from", ""), - INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0), - INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 34), - INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10), - INIT_PARAM_DFLT(bin, "is this system to be binned", false), - INIT_PARAM(binned_fns, "functions to be broken down and binned"), - INIT_PARAM_DFLT(bin_int, "is interrupt code binned seperately?", true) -#endif // FULL_SYSTEM - -END_INIT_SIM_OBJECT_PARAMS(System) - -CREATE_SIM_OBJECT(System) -{ - System::Params *p = new System::Params; - p->name = getInstanceName(); - p->physmem = physmem; -#if FULL_SYSTEM - p->boot_cpu_frequency = boot_cpu_frequency; - p->memctrl = memctrl; - p->kernel_path = kernel; - p->console_path = console; - p->palcode = pal; - p->boot_osflags = boot_osflags; - p->init_param = init_param; - p->readfile = readfile; - p->system_type = system_type; - p->system_rev = system_rev; - p->bin = bin; - p->binned_fns = binned_fns; - p->bin_int = bin_int; -#endif // FULL_SYSTEM - return new System(p); -} - -REGISTER_SIM_OBJECT("System", System) +DEFINE_SIM_OBJECT_CLASS_NAME("System", System) diff --git a/sim/system.hh b/sim/system.hh index 8922373cc..cbe876c42 100644 --- a/sim/system.hh +++ b/sim/system.hh @@ -78,21 +78,9 @@ class System : public SimObject /** kernel symbol table */ SymbolTable *kernelSymtab; - /** console symbol table */ - SymbolTable *consoleSymtab; - - /** pal symbol table */ - SymbolTable *palSymtab; - /** Object pointer for the kernel code */ ObjectFile *kernel; - /** Object pointer for the console code */ - ObjectFile *console; - - /** Object pointer for the PAL code */ - ObjectFile *pal; - /** Begining of kernel code */ Addr kernelStart; @@ -104,11 +92,6 @@ class System : public SimObject Kernel::Binning *kernelBinning; -#ifdef DEBUG - /** Event to halt the simulator if the console calls panic() */ - BreakPCEvent *consolePanicEvent; -#endif - #else int page_ptr; @@ -123,7 +106,7 @@ class System : public SimObject * events on to target function executions. See comment in * system.cc for details. */ - Addr fixFuncEventAddr(Addr addr); + virtual Addr fixFuncEventAddr(Addr addr) = 0; /** * Add a function-based event to the given function, to be looked @@ -150,26 +133,12 @@ class System : public SimObject return addFuncEvent<T>(kernelSymtab, lbl); } - /** Add a function-based event to PALcode. */ - template <class T> - T *System::addPalFuncEvent(const char *lbl) - { - return addFuncEvent<T>(palSymtab, lbl); - } - - /** Add a function-based event to the console code. */ - template <class T> - T *System::addConsoleFuncEvent(const char *lbl) - { - return addFuncEvent<T>(consoleSymtab, lbl); - } #endif - public: #if FULL_SYSTEM std::vector<RemoteGDB *> remoteGDB; std::vector<GDBListener *> gdbListen; - bool breakpoint(); + virtual bool breakpoint() = 0; #endif // FULL_SYSTEM public: @@ -187,31 +156,25 @@ class System : public SimObject bool bin_int; std::string kernel_path; - std::string console_path; - std::string palcode; - std::string boot_osflags; - std::string readfile; - uint64_t system_type; - uint64_t system_rev; #endif }; - Params *params; + protected: + Params *_params; + + public: System(Params *p); ~System(); void startup(); + const Params *params() const { return (const Params *)_params; } + public: #if FULL_SYSTEM /** - * Set the m5AlphaAccess pointer in the console - */ - void setAlphaAccess(Addr access); - - /** * Returns the addess the kernel starts at. * @return address the kernel starts at */ @@ -253,6 +216,8 @@ class System : public SimObject static int numSystemsRunning; static void printSystems(); + + }; #endif // __SYSTEM_HH__ diff --git a/sim/vptr.hh b/sim/vptr.hh new file mode 100644 index 000000000..0ec452f25 --- /dev/null +++ b/sim/vptr.hh @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2004-2005 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. + */ + +#ifndef __ARCH_ALPHA_VPTR_HH__ +#define __ARCH_ALPHA_VPTR_HH__ + +#include "arch/vtophys.hh" +#include "arch/isa_traits.hh" + +class ExecContext; + +template <class T> +class VPtr +{ + public: + typedef T Type; + + private: + ExecContext *xc; + Addr ptr; + + public: + ExecContext *GetXC() const { return xc; } + Addr GetPointer() const { return ptr; } + + public: + explicit VPtr(ExecContext *_xc, Addr p = 0) : xc(_xc), ptr(p) { } + template <class U> + VPtr(const VPtr<U> &vp) : xc(vp.GetXC()), ptr(vp.GetPointer()) {} + ~VPtr() {} + + bool operator!() const + { + return ptr == 0; + } + + VPtr<T> operator+(int offset) + { + VPtr<T> ptr(*this); + ptr += offset; + + return ptr; + } + + const VPtr<T> &operator+=(int offset) + { + ptr += offset; + assert((ptr & (TheISA::PageBytes - 1)) + sizeof(T) + < TheISA::PageBytes); + + return *this; + } + + const VPtr<T> &operator=(Addr p) + { + assert((p & (TheISA::PageBytes - 1)) + sizeof(T) + < TheISA::PageBytes); + ptr = p; + + return *this; + } + + template <class U> + const VPtr<T> &operator=(const VPtr<U> &vp) + { + xc = vp.GetXC(); + ptr = vp.GetPointer(); + + return *this; + } + + operator T *() + { + void *addr = vtomem(xc, ptr, sizeof(T)); + return (T *)addr; + } + + T *operator->() + { + void *addr = vtomem(xc, ptr, sizeof(T)); + return (T *)addr; + } + + T &operator*() + { + void *addr = vtomem(xc, ptr, sizeof(T)); + return *(T *)addr; + } +}; + +#endif // __ARCH_ALPHA_VPTR_HH__ |