simple_thread.cc revision 1982
1/*
2 * Copyright (c) 2001-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <string>
30
31#include "cpu/base.hh"
32#include "cpu/exec_context.hh"
33
34#if FULL_SYSTEM
35#include "base/callback.hh"
36#include "base/cprintf.hh"
37#include "base/output.hh"
38#include "cpu/profile.hh"
39#include "kern/kernel_stats.hh"
40#include "sim/serialize.hh"
41#include "sim/sim_exit.hh"
42#include "sim/system.hh"
43#include "targetarch/stacktrace.hh"
44#else
45#include "sim/process.hh"
46#endif
47
48using namespace std;
49
50// constructor
51#if FULL_SYSTEM
52ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, System *_sys,
53                         AlphaITB *_itb, AlphaDTB *_dtb,
54                         FunctionalMemory *_mem)
55    : _status(ExecContext::Unallocated), cpu(_cpu), thread_num(_thread_num),
56      cpu_id(-1), mem(_mem), itb(_itb), dtb(_dtb), system(_sys),
57      memctrl(_sys->memctrl), physmem(_sys->physmem),
58      kernelBinning(system->kernelBinning), bin(kernelBinning->bin),
59      fnbin(kernelBinning->fnbin), profile(NULL),
60      func_exe_inst(0), storeCondFailures(0)
61{
62    kernelStats = new Kernel::Statistics(this);
63    memset(&regs, 0, sizeof(RegFile));
64
65    if (cpu->params->profile) {
66        profile = new FunctionProfile(system->kernelSymtab);
67        Callback *cb =
68            new MakeCallback<ExecContext, &ExecContext::dumpFuncProfile>(this);
69        registerExitCallback(cb);
70    }
71
72    // let's fill with a dummy node for now so we don't get a segfault
73    // on the first cycle when there's no node available.
74    static ProfileNode dummyNode;
75    profileNode = &dummyNode;
76    profilePC = 3;
77}
78#else
79ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num,
80                         Process *_process, int _asid)
81    : _status(ExecContext::Unallocated),
82      cpu(_cpu), thread_num(_thread_num), cpu_id(-1),
83      process(_process), mem(process->getMemory()), asid(_asid),
84      func_exe_inst(0), storeCondFailures(0)
85{
86    memset(&regs, 0, sizeof(RegFile));
87}
88
89ExecContext::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