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