simple_thread.cc revision 2188
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 "targetarch/stacktrace.hh" 45#else 46#include "sim/process.hh" 47#endif 48 49using namespace std; 50 51// constructor 52#if FULL_SYSTEM 53ExecContext::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(®s, 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 80ExecContext::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(®s, 0, sizeof(RegFile)); 88} 89 90ExecContext::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(®s, 0, sizeof(RegFile)); 96} 97#endif 98 99ExecContext::~ExecContext() 100{ 101#if FULL_SYSTEM 102 delete kernelStats; 103#endif 104} 105 106#if FULL_SYSTEM 107void 108ExecContext::dumpFuncProfile() 109{ 110 std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name())); 111 profile->dump(this, *os); 112} 113 114ExecContext::EndQuiesceEvent::EndQuiesceEvent(ExecContext *_xc) 115 : Event(&mainEventQueue), xc(_xc) 116{ 117} 118 119void 120ExecContext::EndQuiesceEvent::process() 121{ 122 xc->activate(); 123} 124 125const char* 126ExecContext::EndQuiesceEvent::description() 127{ 128 return "End Quiesce Event."; 129} 130#endif 131 132void 133ExecContext::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 154void 155ExecContext::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 174void 175ExecContext::unserialize(Checkpoint *cp, const std::string §ion) 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 194void 195ExecContext::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 206void 207ExecContext::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 227void 228ExecContext::deallocate() 229{ 230 if (status() == Unallocated) 231 return; 232 233 _status = Unallocated; 234 cpu->deallocateContext(thread_num); 235} 236 237void 238ExecContext::halt() 239{ 240 if (status() == Halted) 241 return; 242 243 _status = Halted; 244 cpu->haltContext(thread_num); 245} 246 247 248void 249ExecContext::regStats(const string &name) 250{ 251#if FULL_SYSTEM 252 kernelStats->regStats(name + ".kern"); 253#endif 254} 255 256void 257ExecContext::trap(Fault fault) 258{ 259 //TheISA::trap(fault); //One possible way to do it... 260 261 /** @todo: Going to hack it for now. Do a true fixup later. */ 262#if FULL_SYSTEM 263 ev5_trap(fault); 264#else 265 fatal("fault (%d) detected @ PC 0x%08p", fault, readPC()); 266#endif 267} 268