summaryrefslogtreecommitdiff
path: root/sim
diff options
context:
space:
mode:
Diffstat (limited to 'sim')
-rw-r--r--sim/byteswap.hh146
-rw-r--r--sim/faults.cc46
-rw-r--r--sim/faults.hh67
-rw-r--r--sim/host.hh8
-rw-r--r--sim/process.cc69
-rw-r--r--sim/process.hh11
-rw-r--r--sim/pseudo_inst.cc285
-rw-r--r--sim/pseudo_inst.hh62
-rw-r--r--sim/syscall_emul.cc177
-rw-r--r--sim/syscall_emul.hh145
-rw-r--r--sim/system.cc288
-rw-r--r--sim/system.hh55
-rw-r--r--sim/vptr.hh116
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 &section) : 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 &section)
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__