simple_thread.cc revision 2526
11388SN/A/* 21388SN/A * Copyright (c) 2001-2006 The Regents of The University of Michigan 31388SN/A * All rights reserved. 41388SN/A * 51388SN/A * Redistribution and use in source and binary forms, with or without 61388SN/A * modification, are permitted provided that the following conditions are 71388SN/A * met: redistributions of source code must retain the above copyright 81388SN/A * notice, this list of conditions and the following disclaimer; 91388SN/A * redistributions in binary form must reproduce the above copyright 101388SN/A * notice, this list of conditions and the following disclaimer in the 111388SN/A * documentation and/or other materials provided with the distribution; 121388SN/A * neither the name of the copyright holders nor the names of its 131388SN/A * contributors may be used to endorse or promote products derived from 141388SN/A * this software without specific prior written permission. 151388SN/A * 161388SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 171388SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 181388SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 191388SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 201388SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 211388SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 221388SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 231388SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 241388SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 251388SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 261388SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu */ 282665Ssaidi@eecs.umich.edu 291388SN/A#include <string> 301388SN/A 311388SN/A#include "arch/isa_traits.hh" 321388SN/A#include "cpu/base.hh" 331388SN/A#include "cpu/cpu_exec_context.hh" 341388SN/A#include "cpu/exec_context.hh" 351388SN/A 361388SN/A#if FULL_SYSTEM 371388SN/A#include "base/callback.hh" 381388SN/A#include "base/cprintf.hh" 391388SN/A#include "base/output.hh" 401388SN/A#include "base/trace.hh" 411388SN/A#include "cpu/profile.hh" 421388SN/A#include "kern/kernel_stats.hh" 431388SN/A#include "sim/serialize.hh" 441388SN/A#include "sim/sim_exit.hh" 451388SN/A#include "arch/stacktrace.hh" 461388SN/A#else 471388SN/A#include "sim/process.hh" 481388SN/A#include "sim/system.hh" 491388SN/A#include "mem/translating_port.hh" 501388SN/A#endif 511388SN/A 521388SN/Ausing namespace std; 531388SN/A 541388SN/A// constructor 551388SN/A#if FULL_SYSTEM 561388SN/ACPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_sys, 571388SN/A AlphaITB *_itb, AlphaDTB *_dtb) 581388SN/A : _status(ExecContext::Unallocated), cpu(_cpu), thread_num(_thread_num), 591388SN/A cpu_id(-1), lastActivate(0), lastSuspend(0), system(_sys), itb(_itb), 601388SN/A dtb(_dtb), memctrl(_sys->memctrl), profile(NULL), 611388SN/A quiesceEvent(this), func_exe_inst(0), storeCondFailures(0) 621388SN/A{ 631388SN/A proxy = new ProxyExecContext<CPUExecContext>(this); 641388SN/A 651388SN/A regs.clear(); 661388SN/A 671388SN/A if (cpu->params->profile) { 681388SN/A profile = new FunctionProfile(system->kernelSymtab); 691388SN/A Callback *cb = 701388SN/A new MakeCallback<CPUExecContext, 711388SN/A &CPUExecContext::dumpFuncProfile>(this); 721388SN/A registerExitCallback(cb); 731388SN/A } 741388SN/A 751388SN/A // let's fill with a dummy node for now so we don't get a segfault 761388SN/A // on the first cycle when there's no node available. 771388SN/A static ProfileNode dummyNode; 781388SN/A profileNode = &dummyNode; 791388SN/A profilePC = 3; 801388SN/A} 811388SN/A#else 821388SN/ACPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num, 831388SN/A Process *_process, int _asid, MemObject* memobj) 841388SN/A : _status(ExecContext::Unallocated), 851388SN/A cpu(_cpu), thread_num(_thread_num), cpu_id(-1), lastActivate(0), 861388SN/A lastSuspend(0), process(_process), asid(_asid), 871388SN/A func_exe_inst(0), storeCondFailures(0) 881388SN/A{ 891388SN/A /* Use this port to for syscall emulation writes to memory. */ 904840Ssaidi@eecs.umich.edu Port *mem_port; 911388SN/A port = new TranslatingPort(process->pTable, false); 921388SN/A mem_port = memobj->getPort("functional"); 931388SN/A mem_port->setPeer(port); 941388SN/A port->setPeer(mem_port); 951388SN/A 961388SN/A regs.clear(); 971388SN/A proxy = new ProxyExecContext<CPUExecContext>(this); 984840Ssaidi@eecs.umich.edu} 994840Ssaidi@eecs.umich.edu 1001388SN/ACPUExecContext::CPUExecContext(RegFile *regFile) 1011388SN/A : cpu(NULL), thread_num(-1), process(NULL), asid(-1), 1021388SN/A func_exe_inst(0), storeCondFailures(0) 1031388SN/A{ 1041388SN/A regs = *regFile; 1051388SN/A proxy = new ProxyExecContext<CPUExecContext>(this); 1061388SN/A} 1071388SN/A 1081388SN/A#endif 1091388SN/A 1101388SN/ACPUExecContext::~CPUExecContext() 1111388SN/A{ 1121388SN/A delete proxy; 1131388SN/A} 1141388SN/A 1151388SN/A#if FULL_SYSTEM 1161388SN/Avoid 1171388SN/ACPUExecContext::dumpFuncProfile() 1181388SN/A{ 1191388SN/A std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name())); 1201388SN/A profile->dump(proxy, *os); 1211388SN/A} 1221388SN/A 1231388SN/ACPUExecContext::EndQuiesceEvent::EndQuiesceEvent(CPUExecContext *_cpuXC) 1241388SN/A : Event(&mainEventQueue), cpuXC(_cpuXC) 1251388SN/A{ 1261388SN/A} 1271388SN/A 1281388SN/Avoid 1291388SN/ACPUExecContext::EndQuiesceEvent::process() 1301388SN/A{ 1311388SN/A cpuXC->activate(); 1321388SN/A} 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