simple_thread.cc revision 2521
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 52using namespace std; 53 54// constructor 55#if FULL_SYSTEM 56CPUExecContext::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 memset(®s, 0, sizeof(RegFile)); 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(); 84 mem_port = system->physmem->getPort("functional"); 85 mem_port->setPeer(physPort); 86 physPort->setPeer(mem_port); 87 88 virtPort = new VirtualPort(); 89 mem_port = system->physmem->getPort("functional"); 90 mem_port->setPeer(virtPort); 91 virtPort->setPeer(mem_port); 92} 93#else 94CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num, 95 Process *_process, int _asid, MemObject* memobj) 96 : _status(ExecContext::Unallocated), 97 cpu(_cpu), thread_num(_thread_num), cpu_id(-1), lastActivate(0), 98 lastSuspend(0), process(_process), asid(_asid), 99 func_exe_inst(0), storeCondFailures(0) 100{ 101 /* Use this port to for syscall emulation writes to memory. */ 102 Port *mem_port; 103 port = new TranslatingPort(process->pTable, false); 104 mem_port = memobj->getPort("functional"); 105 mem_port->setPeer(port); 106 port->setPeer(mem_port); 107 108 memset(®s, 0, sizeof(RegFile)); 109 proxy = new ProxyExecContext<CPUExecContext>(this); 110} 111 112CPUExecContext::CPUExecContext(RegFile *regFile) 113 : cpu(NULL), thread_num(-1), process(NULL), asid(-1), 114 func_exe_inst(0), storeCondFailures(0) 115{ 116 regs = *regFile; 117 proxy = new ProxyExecContext<CPUExecContext>(this); 118} 119 120#endif 121 122CPUExecContext::~CPUExecContext() 123{ 124 delete proxy; 125} 126 127#if FULL_SYSTEM 128void 129CPUExecContext::dumpFuncProfile() 130{ 131 std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name())); 132 profile->dump(proxy, *os); 133} 134 135CPUExecContext::EndQuiesceEvent::EndQuiesceEvent(CPUExecContext *_cpuXC) 136 : Event(&mainEventQueue), cpuXC(_cpuXC) 137{ 138} 139 140void 141CPUExecContext::EndQuiesceEvent::process() 142{ 143 cpuXC->activate(); 144} 145 146const char* 147CPUExecContext::EndQuiesceEvent::description() 148{ 149 return "End Quiesce Event."; 150} 151 152void 153CPUExecContext::profileClear() 154{ 155 if (profile) 156 profile->clear(); 157} 158 159void 160CPUExecContext::profileSample() 161{ 162 if (profile) 163 profile->sample(profileNode, profilePC); 164} 165 166#endif 167 168void 169CPUExecContext::takeOverFrom(ExecContext *oldContext) 170{ 171 // some things should already be set up 172#if FULL_SYSTEM 173 assert(system == oldContext->getSystemPtr()); 174#else 175 assert(process == oldContext->getProcessPtr()); 176#endif 177 178 // copy over functional state 179 _status = oldContext->status(); 180 copyArchRegs(oldContext); 181 cpu_id = oldContext->readCpuId(); 182#if !FULL_SYSTEM 183 func_exe_inst = oldContext->readFuncExeInst(); 184#endif 185 186 storeCondFailures = 0; 187 188 oldContext->setStatus(ExecContext::Unallocated); 189} 190 191void 192CPUExecContext::serialize(ostream &os) 193{ 194 SERIALIZE_ENUM(_status); 195 regs.serialize(os); 196 // thread_num and cpu_id are deterministic from the config 197 SERIALIZE_SCALAR(func_exe_inst); 198 SERIALIZE_SCALAR(inst); 199 200#if FULL_SYSTEM 201 Tick quiesceEndTick = 0; 202 if (quiesceEvent.scheduled()) 203 quiesceEndTick = quiesceEvent.when(); 204 SERIALIZE_SCALAR(quiesceEndTick); 205 206#endif 207} 208 209 210void 211CPUExecContext::unserialize(Checkpoint *cp, const std::string §ion) 212{ 213 UNSERIALIZE_ENUM(_status); 214 regs.unserialize(cp, section); 215 // thread_num and cpu_id are deterministic from the config 216 UNSERIALIZE_SCALAR(func_exe_inst); 217 UNSERIALIZE_SCALAR(inst); 218 219#if FULL_SYSTEM 220 Tick quiesceEndTick; 221 UNSERIALIZE_SCALAR(quiesceEndTick); 222 if (quiesceEndTick) 223 quiesceEvent.schedule(quiesceEndTick); 224#endif 225} 226 227 228void 229CPUExecContext::activate(int delay) 230{ 231 if (status() == ExecContext::Active) 232 return; 233 234 lastActivate = curTick; 235 236 _status = ExecContext::Active; 237 cpu->activateContext(thread_num, delay); 238} 239 240void 241CPUExecContext::suspend() 242{ 243 if (status() == ExecContext::Suspended) 244 return; 245 246 lastActivate = curTick; 247 lastSuspend = curTick; 248/* 249#if FULL_SYSTEM 250 // Don't change the status from active if there are pending interrupts 251 if (cpu->check_interrupts()) { 252 assert(status() == ExecContext::Active); 253 return; 254 } 255#endif 256*/ 257 _status = ExecContext::Suspended; 258 cpu->suspendContext(thread_num); 259} 260 261void 262CPUExecContext::deallocate() 263{ 264 if (status() == ExecContext::Unallocated) 265 return; 266 267 _status = ExecContext::Unallocated; 268 cpu->deallocateContext(thread_num); 269} 270 271void 272CPUExecContext::halt() 273{ 274 if (status() == ExecContext::Halted) 275 return; 276 277 _status = ExecContext::Halted; 278 cpu->haltContext(thread_num); 279} 280 281 282void 283CPUExecContext::regStats(const string &name) 284{ 285} 286 287void 288CPUExecContext::copyArchRegs(ExecContext *xc) 289{ 290 TheISA::copyRegs(xc, proxy); 291} 292 293#if FULL_SYSTEM 294VirtualPort* 295CPUExecContext::getVirtPort(ExecContext *xc) 296{ 297 if (!xc) 298 return virtPort; 299 300 VirtualPort *vp; 301 Port *mem_port; 302 303 vp = new VirtualPort(xc); 304 mem_port = system->physmem->getPort("functional"); 305 mem_port->setPeer(vp); 306 vp->setPeer(mem_port); 307 return vp; 308} 309 310void 311CPUExecContext::delVirtPort(VirtualPort *vp) 312{ 313 assert(!vp->nullExecContext()); 314 delete vp->getPeer(); 315 delete vp; 316} 317 318 319#endif 320 321