Merge gblack@m5.eecs.umich.edu:/bk/multiarch
[gem5.git] / cpu / exec_context.cc
1 /*
2 * Copyright (c) 2001-2006 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 "base/trace.hh"
39 #include "cpu/profile.hh"
40 #include "kern/kernel_stats.hh"
41 #include "sim/serialize.hh"
42 #include "sim/sim_exit.hh"
43 #include "sim/system.hh"
44 #include "arch/stacktrace.hh"
45 #else
46 #include "sim/process.hh"
47 #endif
48
49 using namespace std;
50
51 // constructor
52 #if FULL_SYSTEM
53 ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, System *_sys,
54 AlphaITB *_itb, AlphaDTB *_dtb,
55 FunctionalMemory *_mem)
56 : _status(ExecContext::Unallocated), cpu(_cpu), thread_num(_thread_num),
57 cpu_id(-1), lastActivate(0), lastSuspend(0), mem(_mem), itb(_itb),
58 dtb(_dtb), system(_sys), memctrl(_sys->memctrl), physmem(_sys->physmem),
59 kernelBinning(system->kernelBinning), bin(kernelBinning->bin),
60 fnbin(kernelBinning->fnbin), profile(NULL), quiesceEvent(this),
61 func_exe_inst(0), storeCondFailures(0)
62 {
63 kernelStats = new Kernel::Statistics(this);
64 memset(&regs, 0, sizeof(RegFile));
65
66 if (cpu->params->profile) {
67 profile = new FunctionProfile(system->kernelSymtab);
68 Callback *cb =
69 new MakeCallback<ExecContext, &ExecContext::dumpFuncProfile>(this);
70 registerExitCallback(cb);
71 }
72
73 // let's fill with a dummy node for now so we don't get a segfault
74 // on the first cycle when there's no node available.
75 static ProfileNode dummyNode;
76 profileNode = &dummyNode;
77 profilePC = 3;
78 }
79 #else
80 ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num,
81 Process *_process, int _asid)
82 : _status(ExecContext::Unallocated),
83 cpu(_cpu), thread_num(_thread_num), cpu_id(-1), lastActivate(0),
84 lastSuspend(0), process(_process), mem(process->getMemory()), asid(_asid),
85 func_exe_inst(0), storeCondFailures(0)
86 {
87 memset(&regs, 0, sizeof(RegFile));
88 }
89
90 ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num,
91 FunctionalMemory *_mem, int _asid)
92 : cpu(_cpu), thread_num(_thread_num), process(0), mem(_mem), asid(_asid),
93 func_exe_inst(0), storeCondFailures(0)
94 {
95 memset(&regs, 0, sizeof(RegFile));
96 }
97 #endif
98
99 ExecContext::~ExecContext()
100 {
101 #if FULL_SYSTEM
102 delete kernelStats;
103 #endif
104 }
105
106 #if FULL_SYSTEM
107 void
108 ExecContext::dumpFuncProfile()
109 {
110 std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name()));
111 profile->dump(this, *os);
112 }
113
114 ExecContext::EndQuiesceEvent::EndQuiesceEvent(ExecContext *_xc)
115 : Event(&mainEventQueue), xc(_xc)
116 {
117 }
118
119 void
120 ExecContext::EndQuiesceEvent::process()
121 {
122 xc->activate();
123 }
124
125 const char*
126 ExecContext::EndQuiesceEvent::description()
127 {
128 return "End Quiesce Event.";
129 }
130 #endif
131
132 void
133 ExecContext::takeOverFrom(ExecContext *oldContext)
134 {
135 // some things should already be set up
136 assert(mem == oldContext->mem);
137 #if FULL_SYSTEM
138 assert(system == oldContext->system);
139 #else
140 assert(process == oldContext->process);
141 #endif
142
143 // copy over functional state
144 _status = oldContext->_status;
145 regs = oldContext->regs;
146 cpu_id = oldContext->cpu_id;
147 func_exe_inst = oldContext->func_exe_inst;
148
149 storeCondFailures = 0;
150
151 oldContext->_status = ExecContext::Unallocated;
152 }
153
154 void
155 ExecContext::serialize(ostream &os)
156 {
157 SERIALIZE_ENUM(_status);
158 regs.serialize(os);
159 // thread_num and cpu_id are deterministic from the config
160 SERIALIZE_SCALAR(func_exe_inst);
161 SERIALIZE_SCALAR(inst);
162
163 #if FULL_SYSTEM
164 Tick quiesceEndTick = 0;
165 if (quiesceEvent.scheduled())
166 quiesceEndTick = quiesceEvent.when();
167 SERIALIZE_SCALAR(quiesceEndTick);
168 kernelStats->serialize(os);
169
170 #endif
171 }
172
173
174 void
175 ExecContext::unserialize(Checkpoint *cp, const std::string &section)
176 {
177 UNSERIALIZE_ENUM(_status);
178 regs.unserialize(cp, section);
179 // thread_num and cpu_id are deterministic from the config
180 UNSERIALIZE_SCALAR(func_exe_inst);
181 UNSERIALIZE_SCALAR(inst);
182
183 #if FULL_SYSTEM
184 Tick quiesceEndTick;
185 UNSERIALIZE_SCALAR(quiesceEndTick);
186 if (quiesceEndTick)
187 quiesceEvent.schedule(quiesceEndTick);
188
189 kernelStats->unserialize(cp, section);
190 #endif
191 }
192
193
194 void
195 ExecContext::activate(int delay)
196 {
197 if (status() == Active)
198 return;
199
200 lastActivate = curTick;
201
202 _status = Active;
203 cpu->activateContext(thread_num, delay);
204 }
205
206 void
207 ExecContext::suspend()
208 {
209 if (status() == Suspended)
210 return;
211
212 lastActivate = curTick;
213 lastSuspend = curTick;
214 /*
215 #if FULL_SYSTEM
216 // Don't change the status from active if there are pending interrupts
217 if (cpu->check_interrupts()) {
218 assert(status() == Active);
219 return;
220 }
221 #endif
222 */
223 _status = Suspended;
224 cpu->suspendContext(thread_num);
225 }
226
227 void
228 ExecContext::deallocate()
229 {
230 if (status() == Unallocated)
231 return;
232
233 _status = Unallocated;
234 cpu->deallocateContext(thread_num);
235 }
236
237 void
238 ExecContext::halt()
239 {
240 if (status() == Halted)
241 return;
242
243 _status = Halted;
244 cpu->haltContext(thread_num);
245 }
246
247
248 void
249 ExecContext::regStats(const string &name)
250 {
251 #if FULL_SYSTEM
252 kernelStats->regStats(name + ".kern");
253 #endif
254 }
255