simple_thread.cc revision 2132
14712SN/A/*
24712SN/A * Copyright (c) 2001-2005 The Regents of The University of Michigan
38332Snate@binkert.org * All rights reserved.
44712SN/A *
54712SN/A * Redistribution and use in source and binary forms, with or without
67087SN/A * modification, are permitted provided that the following conditions are
77087SN/A * met: redistributions of source code must retain the above copyright
87087SN/A * notice, this list of conditions and the following disclaimer;
97087SN/A * redistributions in binary form must reproduce the above copyright
107087SN/A * notice, this list of conditions and the following disclaimer in the
117087SN/A * documentation and/or other materials provided with the distribution;
127087SN/A * neither the name of the copyright holders nor the names of its
137087SN/A * contributors may be used to endorse or promote products derived from
144712SN/A * this software without specific prior written permission.
157087SN/A *
167087SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
177087SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
187087SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
197087SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
207087SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
217087SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
227087SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
234712SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
247087SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
254712SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
264712SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
274712SN/A */
284712SN/A
294712SN/A#include <string>
304712SN/A
314712SN/A#include "cpu/base.hh"
324712SN/A#include "cpu/exec_context.hh"
334712SN/A
344712SN/A#if FULL_SYSTEM
354712SN/A#include "base/callback.hh"
364712SN/A#include "base/cprintf.hh"
374712SN/A#include "base/output.hh"
384712SN/A#include "cpu/profile.hh"
394712SN/A#include "kern/kernel_stats.hh"
404712SN/A#include "sim/serialize.hh"
414712SN/A#include "sim/sim_exit.hh"
424712SN/A#include "sim/system.hh"
434712SN/A#include "targetarch/stacktrace.hh"
444712SN/A#else
454712SN/A#include "sim/process.hh"
464712SN/A#endif
477715Sgblack@eecs.umich.edu
484712SN/Ausing namespace std;
494712SN/A
504806SN/A// constructor
514712SN/A#if FULL_SYSTEM
527715Sgblack@eecs.umich.eduExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, System *_sys,
534712SN/A                         AlphaITB *_itb, AlphaDTB *_dtb,
544712SN/A                         FunctionalMemory *_mem)
554712SN/A    : _status(ExecContext::Unallocated), cpu(_cpu), thread_num(_thread_num),
564712SN/A      cpu_id(-1), mem(_mem), itb(_itb), dtb(_dtb), system(_sys),
574712SN/A      memctrl(_sys->memctrl), physmem(_sys->physmem),
584712SN/A      kernelBinning(system->kernelBinning), bin(kernelBinning->bin),
594712SN/A      fnbin(kernelBinning->fnbin), profile(NULL),
604712SN/A      func_exe_inst(0), storeCondFailures(0)
614712SN/A{
624712SN/A    kernelStats = new Kernel::Statistics(this);
634712SN/A    memset(&regs, 0, sizeof(RegFile));
647715Sgblack@eecs.umich.edu
654712SN/A    if (cpu->params->profile) {
664712SN/A        profile = new FunctionProfile(system->kernelSymtab);
674712SN/A        Callback *cb =
684712SN/A            new MakeCallback<ExecContext, &ExecContext::dumpFuncProfile>(this);
694712SN/A        registerExitCallback(cb);
704712SN/A    }
714712SN/A
724712SN/A    // let's fill with a dummy node for now so we don't get a segfault
734712SN/A    // on the first cycle when there's no node available.
747715Sgblack@eecs.umich.edu    static ProfileNode dummyNode;
7512234Sgabeblack@google.com    profileNode = &dummyNode;
764712SN/A    profilePC = 3;
774712SN/A}
787715Sgblack@eecs.umich.edu#else
794712SN/AExecContext::ExecContext(BaseCPU *_cpu, int _thread_num,
804712SN/A                         Process *_process, int _asid)
814712SN/A    : _status(ExecContext::Unallocated),
827715Sgblack@eecs.umich.edu      cpu(_cpu), thread_num(_thread_num), cpu_id(-1),
837715Sgblack@eecs.umich.edu      process(_process), mem(process->getMemory()), asid(_asid),
844712SN/A      func_exe_inst(0), storeCondFailures(0)
854712SN/A{
864712SN/A    memset(&regs, 0, sizeof(RegFile));
877715Sgblack@eecs.umich.edu}
884712SN/A
894712SN/AExecContext::ExecContext(BaseCPU *_cpu, int _thread_num,
90                         FunctionalMemory *_mem, int _asid)
91    : cpu(_cpu), thread_num(_thread_num), process(0), mem(_mem), asid(_asid),
92      func_exe_inst(0), storeCondFailures(0)
93{
94    memset(&regs, 0, sizeof(RegFile));
95}
96#endif
97
98ExecContext::~ExecContext()
99{
100#if FULL_SYSTEM
101    delete kernelStats;
102#endif
103}
104
105#if FULL_SYSTEM
106void
107ExecContext::dumpFuncProfile()
108{
109    std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name()));
110    profile->dump(this, *os);
111}
112#endif
113
114void
115ExecContext::takeOverFrom(ExecContext *oldContext)
116{
117    // some things should already be set up
118    assert(mem == oldContext->mem);
119#if FULL_SYSTEM
120    assert(system == oldContext->system);
121#else
122    assert(process == oldContext->process);
123#endif
124
125    // copy over functional state
126    _status = oldContext->_status;
127    regs = oldContext->regs;
128    cpu_id = oldContext->cpu_id;
129    func_exe_inst = oldContext->func_exe_inst;
130
131    storeCondFailures = 0;
132
133    oldContext->_status = ExecContext::Unallocated;
134}
135
136void
137ExecContext::serialize(ostream &os)
138{
139    SERIALIZE_ENUM(_status);
140    regs.serialize(os);
141    // thread_num and cpu_id are deterministic from the config
142    SERIALIZE_SCALAR(func_exe_inst);
143    SERIALIZE_SCALAR(inst);
144
145#if FULL_SYSTEM
146    kernelStats->serialize(os);
147#endif
148}
149
150
151void
152ExecContext::unserialize(Checkpoint *cp, const std::string &section)
153{
154    UNSERIALIZE_ENUM(_status);
155    regs.unserialize(cp, section);
156    // thread_num and cpu_id are deterministic from the config
157    UNSERIALIZE_SCALAR(func_exe_inst);
158    UNSERIALIZE_SCALAR(inst);
159
160#if FULL_SYSTEM
161    kernelStats->unserialize(cp, section);
162#endif
163}
164
165
166void
167ExecContext::activate(int delay)
168{
169    if (status() == Active)
170        return;
171
172    _status = Active;
173    cpu->activateContext(thread_num, delay);
174}
175
176void
177ExecContext::suspend()
178{
179    if (status() == Suspended)
180        return;
181
182#if FULL_SYSTEM
183    // Don't change the status from active if there are pending interrupts
184    if (cpu->check_interrupts()) {
185        assert(status() == Active);
186        return;
187    }
188#endif
189
190    _status = Suspended;
191    cpu->suspendContext(thread_num);
192}
193
194void
195ExecContext::deallocate()
196{
197    if (status() == Unallocated)
198        return;
199
200    _status = Unallocated;
201    cpu->deallocateContext(thread_num);
202}
203
204void
205ExecContext::halt()
206{
207    if (status() == Halted)
208        return;
209
210    _status = Halted;
211    cpu->haltContext(thread_num);
212}
213
214
215void
216ExecContext::regStats(const string &name)
217{
218#if FULL_SYSTEM
219    kernelStats->regStats(name + ".kern");
220#endif
221}
222
223void
224ExecContext::trap(Fault fault)
225{
226    //TheISA::trap(fault);    //One possible way to do it...
227
228    /** @todo: Going to hack it for now.  Do a true fixup later. */
229#if FULL_SYSTEM
230    ev5_trap(fault);
231#else
232    fatal("fault (%d) detected @ PC 0x%08p", fault, readPC());
233#endif
234}
235