b8aa9a67e076b569f142c941171354f303627778
[gem5.git] / src / cpu / 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 "arch/isa_traits.hh"
32 #include "cpu/base.hh"
33 #include "cpu/cpu_exec_context.hh"
34 #include "cpu/exec_context.hh"
35
36 #if FULL_SYSTEM
37 #include "base/callback.hh"
38 #include "base/cprintf.hh"
39 #include "base/output.hh"
40 #include "base/trace.hh"
41 #include "cpu/profile.hh"
42 #include "kern/kernel_stats.hh"
43 #include "sim/serialize.hh"
44 #include "sim/sim_exit.hh"
45 #include "arch/stacktrace.hh"
46 #else
47 #include "sim/process.hh"
48 #include "sim/system.hh"
49 #include "mem/translating_port.hh"
50 #endif
51
52 using namespace std;
53
54 // constructor
55 #if FULL_SYSTEM
56 CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_sys,
57 AlphaITB *_itb, AlphaDTB *_dtb)
58 : _status(ExecContext::Unallocated), cpu(_cpu), thread_num(_thread_num),
59 cpu_id(-1), lastActivate(0), lastSuspend(0), system(_sys), itb(_itb),
60 dtb(_dtb), profile(NULL), quiesceEvent(this), func_exe_inst(0),
61 storeCondFailures(0)
62
63 {
64 proxy = new ProxyExecContext<CPUExecContext>(this);
65
66 regs.clear();
67
68 if (cpu->params->profile) {
69 profile = new FunctionProfile(system->kernelSymtab);
70 Callback *cb =
71 new MakeCallback<CPUExecContext,
72 &CPUExecContext::dumpFuncProfile>(this);
73 registerExitCallback(cb);
74 }
75
76 // let's fill with a dummy node for now so we don't get a segfault
77 // on the first cycle when there's no node available.
78 static ProfileNode dummyNode;
79 profileNode = &dummyNode;
80 profilePC = 3;
81
82 Port *mem_port;
83 physPort = new FunctionalPort(csprintf("%s-%d-funcport",
84 cpu->name(), thread_num));
85 mem_port = system->physmem->getPort("functional");
86 mem_port->setPeer(physPort);
87 physPort->setPeer(mem_port);
88
89 virtPort = new VirtualPort(csprintf("%s-%d-vport",
90 cpu->name(), thread_num));
91 mem_port = system->physmem->getPort("functional");
92 mem_port->setPeer(virtPort);
93 virtPort->setPeer(mem_port);
94 }
95 #else
96 CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num,
97 Process *_process, int _asid, MemObject* memobj)
98 : _status(ExecContext::Unallocated),
99 cpu(_cpu), thread_num(_thread_num), cpu_id(-1), lastActivate(0),
100 lastSuspend(0), process(_process), asid(_asid),
101 func_exe_inst(0), storeCondFailures(0)
102 {
103 /* Use this port to for syscall emulation writes to memory. */
104 Port *mem_port;
105 port = new TranslatingPort(csprintf("%s-%d-funcport",
106 cpu->name(), thread_num),
107 process->pTable, false);
108 mem_port = memobj->getPort("functional");
109 mem_port->setPeer(port);
110 port->setPeer(mem_port);
111
112 regs.clear();
113 proxy = new ProxyExecContext<CPUExecContext>(this);
114 }
115
116 CPUExecContext::CPUExecContext(RegFile *regFile)
117 : cpu(NULL), thread_num(-1), process(NULL), asid(-1),
118 func_exe_inst(0), storeCondFailures(0)
119 {
120 regs = *regFile;
121 proxy = new ProxyExecContext<CPUExecContext>(this);
122 }
123
124 #endif
125
126 CPUExecContext::~CPUExecContext()
127 {
128 delete proxy;
129 }
130
131 #if FULL_SYSTEM
132 void
133 CPUExecContext::dumpFuncProfile()
134 {
135 std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name()));
136 profile->dump(proxy, *os);
137 }
138
139 CPUExecContext::EndQuiesceEvent::EndQuiesceEvent(CPUExecContext *_cpuXC)
140 : Event(&mainEventQueue), cpuXC(_cpuXC)
141 {
142 }
143
144 void
145 CPUExecContext::EndQuiesceEvent::process()
146 {
147 cpuXC->activate();
148 }
149
150 const char*
151 CPUExecContext::EndQuiesceEvent::description()
152 {
153 return "End Quiesce Event.";
154 }
155
156 void
157 CPUExecContext::profileClear()
158 {
159 if (profile)
160 profile->clear();
161 }
162
163 void
164 CPUExecContext::profileSample()
165 {
166 if (profile)
167 profile->sample(profileNode, profilePC);
168 }
169
170 #endif
171
172 void
173 CPUExecContext::takeOverFrom(ExecContext *oldContext)
174 {
175 // some things should already be set up
176 #if FULL_SYSTEM
177 assert(system == oldContext->getSystemPtr());
178 #else
179 assert(process == oldContext->getProcessPtr());
180 #endif
181
182 // copy over functional state
183 _status = oldContext->status();
184 copyArchRegs(oldContext);
185 cpu_id = oldContext->readCpuId();
186 #if !FULL_SYSTEM
187 func_exe_inst = oldContext->readFuncExeInst();
188 #endif
189
190 storeCondFailures = 0;
191
192 oldContext->setStatus(ExecContext::Unallocated);
193 }
194
195 void
196 CPUExecContext::serialize(ostream &os)
197 {
198 SERIALIZE_ENUM(_status);
199 regs.serialize(os);
200 // thread_num and cpu_id are deterministic from the config
201 SERIALIZE_SCALAR(func_exe_inst);
202 SERIALIZE_SCALAR(inst);
203
204 #if FULL_SYSTEM
205 Tick quiesceEndTick = 0;
206 if (quiesceEvent.scheduled())
207 quiesceEndTick = quiesceEvent.when();
208 SERIALIZE_SCALAR(quiesceEndTick);
209
210 #endif
211 }
212
213
214 void
215 CPUExecContext::unserialize(Checkpoint *cp, const std::string &section)
216 {
217 UNSERIALIZE_ENUM(_status);
218 regs.unserialize(cp, section);
219 // thread_num and cpu_id are deterministic from the config
220 UNSERIALIZE_SCALAR(func_exe_inst);
221 UNSERIALIZE_SCALAR(inst);
222
223 #if FULL_SYSTEM
224 Tick quiesceEndTick;
225 UNSERIALIZE_SCALAR(quiesceEndTick);
226 if (quiesceEndTick)
227 quiesceEvent.schedule(quiesceEndTick);
228 #endif
229 }
230
231
232 void
233 CPUExecContext::activate(int delay)
234 {
235 if (status() == ExecContext::Active)
236 return;
237
238 lastActivate = curTick;
239
240 _status = ExecContext::Active;
241 cpu->activateContext(thread_num, delay);
242 }
243
244 void
245 CPUExecContext::suspend()
246 {
247 if (status() == ExecContext::Suspended)
248 return;
249
250 lastActivate = curTick;
251 lastSuspend = curTick;
252 /*
253 #if FULL_SYSTEM
254 // Don't change the status from active if there are pending interrupts
255 if (cpu->check_interrupts()) {
256 assert(status() == ExecContext::Active);
257 return;
258 }
259 #endif
260 */
261 _status = ExecContext::Suspended;
262 cpu->suspendContext(thread_num);
263 }
264
265 void
266 CPUExecContext::deallocate()
267 {
268 if (status() == ExecContext::Unallocated)
269 return;
270
271 _status = ExecContext::Unallocated;
272 cpu->deallocateContext(thread_num);
273 }
274
275 void
276 CPUExecContext::halt()
277 {
278 if (status() == ExecContext::Halted)
279 return;
280
281 _status = ExecContext::Halted;
282 cpu->haltContext(thread_num);
283 }
284
285
286 void
287 CPUExecContext::regStats(const string &name)
288 {
289 }
290
291 void
292 CPUExecContext::copyArchRegs(ExecContext *xc)
293 {
294 TheISA::copyRegs(xc, proxy);
295 }
296
297 #if FULL_SYSTEM
298 VirtualPort*
299 CPUExecContext::getVirtPort(ExecContext *xc)
300 {
301 if (!xc)
302 return virtPort;
303
304 VirtualPort *vp;
305 Port *mem_port;
306
307 vp = new VirtualPort("xc-vport", xc);
308 mem_port = system->physmem->getPort("functional");
309 mem_port->setPeer(vp);
310 vp->setPeer(mem_port);
311 return vp;
312 }
313
314 void
315 CPUExecContext::delVirtPort(VirtualPort *vp)
316 {
317 // assert(!vp->nullExecContext());
318 delete vp->getPeer();
319 delete vp;
320 }
321
322
323 #endif
324