simple_thread.cc revision 2465
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 "sim/system.hh" 46#include "arch/stacktrace.hh" 47#else 48#include "sim/process.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 Memory *_mem) 59 : _status(ExecContext::Unallocated), cpu(_cpu), thread_num(_thread_num), 60 cpu_id(-1), lastActivate(0), lastSuspend(0), mem(_mem), itb(_itb), 61 dtb(_dtb), system(_sys), memctrl(_sys->memctrl), physmem(_sys->physmem), 62 profile(NULL), quiesceEvent(this), func_exe_inst(0), storeCondFailures(0) 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#else 83CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num, 84 Process *_process, int _asid, Port *mem_port) 85 : _status(ExecContext::Unallocated), 86 cpu(_cpu), thread_num(_thread_num), cpu_id(-1), lastActivate(0), 87 lastSuspend(0), process(_process), asid(_asid), 88 func_exe_inst(0), storeCondFailures(0) 89{ 90 port = new TranslatingPort(mem_port, process->pTable); 91 memset(®s, 0, sizeof(RegFile)); 92 proxy = new ProxyExecContext<CPUExecContext>(this); 93} 94 95CPUExecContext::CPUExecContext(RegFile *regFile) 96 : cpu(NULL), thread_num(-1), process(NULL), asid(-1), 97 func_exe_inst(0), storeCondFailures(0) 98{ 99 regs = *regFile; 100 proxy = new ProxyExecContext<CPUExecContext>(this); 101} 102 103#endif 104 105CPUExecContext::~CPUExecContext() 106{ 107 delete proxy; 108} 109 110#if FULL_SYSTEM 111void 112CPUExecContext::dumpFuncProfile() 113{ 114 std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name())); 115 profile->dump(proxy, *os); 116} 117 118CPUExecContext::EndQuiesceEvent::EndQuiesceEvent(CPUExecContext *_cpuXC) 119 : Event(&mainEventQueue), cpuXC(_cpuXC) 120{ 121} 122 123void 124CPUExecContext::EndQuiesceEvent::process() 125{ 126 cpuXC->activate(); 127} 128 129const char* 130CPUExecContext::EndQuiesceEvent::description() 131{ 132 return "End Quiesce Event."; 133} 134 135void 136CPUExecContext::profileClear() 137{ 138 if (profile) 139 profile->clear(); 140} 141 142void 143CPUExecContext::profileSample() 144{ 145 if (profile) 146 profile->sample(profileNode, profilePC); 147} 148 149#endif 150 151void 152CPUExecContext::takeOverFrom(ExecContext *oldContext) 153{ 154 // some things should already be set up 155#if FULL_SYSTEM 156 assert(system == oldContext->getSystemPtr()); 157#else 158 assert(process == oldContext->getProcessPtr()); 159#endif 160 161 // copy over functional state 162 _status = oldContext->status(); 163 copyArchRegs(oldContext); 164 cpu_id = oldContext->readCpuId(); 165#if !FULL_SYSTEM 166 func_exe_inst = oldContext->readFuncExeInst(); 167#endif 168 169 storeCondFailures = 0; 170 171 oldContext->setStatus(ExecContext::Unallocated); 172} 173 174void 175CPUExecContext::serialize(ostream &os) 176{ 177 SERIALIZE_ENUM(_status); 178 regs.serialize(os); 179 // thread_num and cpu_id are deterministic from the config 180 SERIALIZE_SCALAR(func_exe_inst); 181 SERIALIZE_SCALAR(inst); 182 183#if FULL_SYSTEM 184 Tick quiesceEndTick = 0; 185 if (quiesceEvent.scheduled()) 186 quiesceEndTick = quiesceEvent.when(); 187 SERIALIZE_SCALAR(quiesceEndTick); 188 189#endif 190} 191 192 193void 194CPUExecContext::unserialize(Checkpoint *cp, const std::string §ion) 195{ 196 UNSERIALIZE_ENUM(_status); 197 regs.unserialize(cp, section); 198 // thread_num and cpu_id are deterministic from the config 199 UNSERIALIZE_SCALAR(func_exe_inst); 200 UNSERIALIZE_SCALAR(inst); 201 202#if FULL_SYSTEM 203 Tick quiesceEndTick; 204 UNSERIALIZE_SCALAR(quiesceEndTick); 205 if (quiesceEndTick) 206 quiesceEvent.schedule(quiesceEndTick); 207#endif 208} 209 210 211void 212CPUExecContext::activate(int delay) 213{ 214 if (status() == ExecContext::Active) 215 return; 216 217 lastActivate = curTick; 218 219 _status = ExecContext::Active; 220 cpu->activateContext(thread_num, delay); 221} 222 223void 224CPUExecContext::suspend() 225{ 226 if (status() == ExecContext::Suspended) 227 return; 228 229 lastActivate = curTick; 230 lastSuspend = curTick; 231/* 232#if FULL_SYSTEM 233 // Don't change the status from active if there are pending interrupts 234 if (cpu->check_interrupts()) { 235 assert(status() == ExecContext::Active); 236 return; 237 } 238#endif 239*/ 240 _status = ExecContext::Suspended; 241 cpu->suspendContext(thread_num); 242} 243 244void 245CPUExecContext::deallocate() 246{ 247 if (status() == ExecContext::Unallocated) 248 return; 249 250 _status = ExecContext::Unallocated; 251 cpu->deallocateContext(thread_num); 252} 253 254void 255CPUExecContext::halt() 256{ 257 if (status() == ExecContext::Halted) 258 return; 259 260 _status = ExecContext::Halted; 261 cpu->haltContext(thread_num); 262} 263 264 265void 266CPUExecContext::regStats(const string &name) 267{ 268} 269 270void 271CPUExecContext::copyArchRegs(ExecContext *xc) 272{ 273 TheISA::copyRegs(xc, proxy); 274} 275 276