Whole mess'o'changes.. see individual files
[gem5.git] / cpu / exec_context.cc
1 /*
2 * Copyright (c) 2003 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_cpu.hh"
32 #include "cpu/exec_context.hh"
33
34 #ifdef FULL_SYSTEM
35 #include "sim/system.hh"
36 #else
37 #include "sim/process.hh"
38 #endif
39
40 using namespace std;
41
42 // constructor
43 #ifdef FULL_SYSTEM
44 ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, System *_sys,
45 AlphaItb *_itb, AlphaDtb *_dtb,
46 FunctionalMemory *_mem)
47 : _status(ExecContext::Unallocated),
48 kernelStats(this, _cpu), cpu(_cpu), thread_num(_thread_num),
49 cpu_id(-1), mem(_mem), itb(_itb), dtb(_dtb), system(_sys),
50 memCtrl(_sys->memCtrl), physmem(_sys->physmem),
51 swCtx(NULL), func_exe_inst(0), storeCondFailures(0)
52 {
53 memset(&regs, 0, sizeof(RegFile));
54 }
55 #else
56 ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num,
57 Process *_process, int _asid)
58 : _status(ExecContext::Unallocated),
59 cpu(_cpu), thread_num(_thread_num), cpu_id(-1),
60 process(_process), mem(process->getMemory()), asid(_asid),
61 func_exe_inst(0), storeCondFailures(0)
62 {
63 }
64
65 ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num,
66 FunctionalMemory *_mem, int _asid)
67 : cpu(_cpu), thread_num(_thread_num), process(0), mem(_mem), asid(_asid),
68 func_exe_inst(0), storeCondFailures(0)
69 {
70 }
71 #endif
72
73
74 void
75 ExecContext::takeOverFrom(ExecContext *oldContext)
76 {
77 // some things should already be set up
78 assert(mem == oldContext->mem);
79 #ifdef FULL_SYSTEM
80 assert(system == oldContext->system);
81 #else
82 assert(process == oldContext->process);
83 #endif
84
85 // copy over functional state
86 _status = oldContext->_status;
87 #ifdef FULL_SYSTEM
88 kernelStats = oldContext->kernelStats;
89 #endif
90 regs = oldContext->regs;
91 cpu_id = oldContext->cpu_id;
92 func_exe_inst = oldContext->func_exe_inst;
93
94 storeCondFailures = 0;
95
96 oldContext->_status = ExecContext::Unallocated;
97 }
98
99
100 void
101 ExecContext::serialize(ostream &os)
102 {
103 SERIALIZE_ENUM(_status);
104 regs.serialize(os);
105 // thread_num and cpu_id are deterministic from the config
106 SERIALIZE_SCALAR(func_exe_inst);
107
108 #ifdef FULL_SYSTEM
109 bool ctx = false;
110 if (swCtx) {
111 ctx = true;
112 SERIALIZE_SCALAR(ctx);
113 SERIALIZE_SCALAR(swCtx->calls);
114 std::stack<fnCall *> *stack = &(swCtx->callStack);
115 fnCall *top;
116 int size = stack->size();
117 SERIALIZE_SCALAR(size);
118
119 for (int j=0; j<size; ++j) {
120 top = stack->top();
121 paramOut(os, csprintf("stackpos[%d]",j), top->name);
122 delete top;
123 stack->pop();
124 }
125 } else {
126 SERIALIZE_SCALAR(ctx);
127 }
128 if (system->bin) {
129 Statistics::MainBin *cur = Statistics::MainBin::curBin();
130 string bin_name = cur->name();
131 SERIALIZE_SCALAR(bin_name);
132 }
133 #endif //FULL_SYSTEM
134 }
135
136
137 void
138 ExecContext::unserialize(Checkpoint *cp, const std::string &section)
139 {
140 UNSERIALIZE_ENUM(_status);
141 regs.unserialize(cp, section);
142 // thread_num and cpu_id are deterministic from the config
143 UNSERIALIZE_SCALAR(func_exe_inst);
144
145 #ifdef FULL_SYSTEM
146 bool ctx;
147 UNSERIALIZE_SCALAR(ctx);
148 if (ctx) {
149 swCtx = new SWContext;
150 UNSERIALIZE_SCALAR(swCtx->calls);
151 int size;
152 UNSERIALIZE_SCALAR(size);
153
154 vector<fnCall *> calls;
155 fnCall *call;
156 for (int i=0; i<size; ++i) {
157 call = new fnCall;
158 paramIn(cp, section, csprintf("stackpos[%d]",i), call->name);
159 call->myBin = system->getBin(call->name);
160 calls.push_back(call);
161 }
162
163 for (int i=size-1; i>=0; --i) {
164 swCtx->callStack.push(calls[i]);
165 }
166
167 }
168
169 if (system->bin) {
170 string bin_name;
171 UNSERIALIZE_SCALAR(bin_name);
172 system->getBin(bin_name)->activate();
173 }
174 #endif //FULL_SYSTEM
175 }
176
177
178 void
179 ExecContext::activate(int delay)
180 {
181 if (status() == Active)
182 return;
183
184 _status = Active;
185 cpu->activateContext(thread_num, delay);
186 }
187
188 void
189 ExecContext::suspend()
190 {
191 if (status() == Suspended)
192 return;
193
194 #ifdef FULL_SYSTEM
195 // Don't change the status from active if there are pending interrupts
196 if (cpu->check_interrupts()) {
197 assert(status() == Active);
198 return;
199 }
200 #endif
201
202 _status = Suspended;
203 cpu->suspendContext(thread_num);
204 }
205
206 void
207 ExecContext::deallocate()
208 {
209 if (status() == Unallocated)
210 return;
211
212 _status = Unallocated;
213 cpu->deallocateContext(thread_num);
214 }
215
216 void
217 ExecContext::halt()
218 {
219 if (status() == Halted)
220 return;
221
222 _status = Halted;
223 cpu->haltContext(thread_num);
224 }
225
226
227 void
228 ExecContext::regStats(const string &name)
229 {
230 #ifdef FULL_SYSTEM
231 kernelStats.regStats(name + ".kern");
232 #endif
233 }