b8aa9a67e076b569f142c941171354f303627778
2 * Copyright (c) 2001-2006 The Regents of The University of Michigan
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.
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.
31 #include "arch/isa_traits.hh"
32 #include "cpu/base.hh"
33 #include "cpu/cpu_exec_context.hh"
34 #include "cpu/exec_context.hh"
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"
47 #include "sim/process.hh"
48 #include "sim/system.hh"
49 #include "mem/translating_port.hh"
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),
64 proxy
= new ProxyExecContext
<CPUExecContext
>(this);
68 if (cpu
->params
->profile
) {
69 profile
= new FunctionProfile(system
->kernelSymtab
);
71 new MakeCallback
<CPUExecContext
,
72 &CPUExecContext::dumpFuncProfile
>(this);
73 registerExitCallback(cb
);
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
;
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
);
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
);
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)
103 /* Use this port to for syscall emulation writes to memory. */
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
);
113 proxy
= new ProxyExecContext
<CPUExecContext
>(this);
116 CPUExecContext::CPUExecContext(RegFile
*regFile
)
117 : cpu(NULL
), thread_num(-1), process(NULL
), asid(-1),
118 func_exe_inst(0), storeCondFailures(0)
121 proxy
= new ProxyExecContext
<CPUExecContext
>(this);
126 CPUExecContext::~CPUExecContext()
133 CPUExecContext::dumpFuncProfile()
135 std::ostream
*os
= simout
.create(csprintf("profile.%s.dat", cpu
->name()));
136 profile
->dump(proxy
, *os
);
139 CPUExecContext::EndQuiesceEvent::EndQuiesceEvent(CPUExecContext
*_cpuXC
)
140 : Event(&mainEventQueue
), cpuXC(_cpuXC
)
145 CPUExecContext::EndQuiesceEvent::process()
151 CPUExecContext::EndQuiesceEvent::description()
153 return "End Quiesce Event.";
157 CPUExecContext::profileClear()
164 CPUExecContext::profileSample()
167 profile
->sample(profileNode
, profilePC
);
173 CPUExecContext::takeOverFrom(ExecContext
*oldContext
)
175 // some things should already be set up
177 assert(system
== oldContext
->getSystemPtr());
179 assert(process
== oldContext
->getProcessPtr());
182 // copy over functional state
183 _status
= oldContext
->status();
184 copyArchRegs(oldContext
);
185 cpu_id
= oldContext
->readCpuId();
187 func_exe_inst
= oldContext
->readFuncExeInst();
190 storeCondFailures
= 0;
192 oldContext
->setStatus(ExecContext::Unallocated
);
196 CPUExecContext::serialize(ostream
&os
)
198 SERIALIZE_ENUM(_status
);
200 // thread_num and cpu_id are deterministic from the config
201 SERIALIZE_SCALAR(func_exe_inst
);
202 SERIALIZE_SCALAR(inst
);
205 Tick quiesceEndTick
= 0;
206 if (quiesceEvent
.scheduled())
207 quiesceEndTick
= quiesceEvent
.when();
208 SERIALIZE_SCALAR(quiesceEndTick
);
215 CPUExecContext::unserialize(Checkpoint
*cp
, const std::string
§ion
)
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
);
225 UNSERIALIZE_SCALAR(quiesceEndTick
);
227 quiesceEvent
.schedule(quiesceEndTick
);
233 CPUExecContext::activate(int delay
)
235 if (status() == ExecContext::Active
)
238 lastActivate
= curTick
;
240 _status
= ExecContext::Active
;
241 cpu
->activateContext(thread_num
, delay
);
245 CPUExecContext::suspend()
247 if (status() == ExecContext::Suspended
)
250 lastActivate
= curTick
;
251 lastSuspend
= curTick
;
254 // Don't change the status from active if there are pending interrupts
255 if (cpu->check_interrupts()) {
256 assert(status() == ExecContext::Active);
261 _status
= ExecContext::Suspended
;
262 cpu
->suspendContext(thread_num
);
266 CPUExecContext::deallocate()
268 if (status() == ExecContext::Unallocated
)
271 _status
= ExecContext::Unallocated
;
272 cpu
->deallocateContext(thread_num
);
276 CPUExecContext::halt()
278 if (status() == ExecContext::Halted
)
281 _status
= ExecContext::Halted
;
282 cpu
->haltContext(thread_num
);
287 CPUExecContext::regStats(const string
&name
)
292 CPUExecContext::copyArchRegs(ExecContext
*xc
)
294 TheISA::copyRegs(xc
, proxy
);
299 CPUExecContext::getVirtPort(ExecContext
*xc
)
307 vp
= new VirtualPort("xc-vport", xc
);
308 mem_port
= system
->physmem
->getPort("functional");
309 mem_port
->setPeer(vp
);
310 vp
->setPeer(mem_port
);
315 CPUExecContext::delVirtPort(VirtualPort
*vp
)
317 // assert(!vp->nullExecContext());
318 delete vp
->getPeer();