simple_thread.cc revision 2132
14712SN/A/* 24712SN/A * Copyright (c) 2001-2005 The Regents of The University of Michigan 38332Snate@binkert.org * All rights reserved. 44712SN/A * 54712SN/A * Redistribution and use in source and binary forms, with or without 67087SN/A * modification, are permitted provided that the following conditions are 77087SN/A * met: redistributions of source code must retain the above copyright 87087SN/A * notice, this list of conditions and the following disclaimer; 97087SN/A * redistributions in binary form must reproduce the above copyright 107087SN/A * notice, this list of conditions and the following disclaimer in the 117087SN/A * documentation and/or other materials provided with the distribution; 127087SN/A * neither the name of the copyright holders nor the names of its 137087SN/A * contributors may be used to endorse or promote products derived from 144712SN/A * this software without specific prior written permission. 157087SN/A * 167087SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 177087SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 187087SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 197087SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 207087SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 217087SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 227087SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 234712SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 247087SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 254712SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 264712SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 274712SN/A */ 284712SN/A 294712SN/A#include <string> 304712SN/A 314712SN/A#include "cpu/base.hh" 324712SN/A#include "cpu/exec_context.hh" 334712SN/A 344712SN/A#if FULL_SYSTEM 354712SN/A#include "base/callback.hh" 364712SN/A#include "base/cprintf.hh" 374712SN/A#include "base/output.hh" 384712SN/A#include "cpu/profile.hh" 394712SN/A#include "kern/kernel_stats.hh" 404712SN/A#include "sim/serialize.hh" 414712SN/A#include "sim/sim_exit.hh" 424712SN/A#include "sim/system.hh" 434712SN/A#include "targetarch/stacktrace.hh" 444712SN/A#else 454712SN/A#include "sim/process.hh" 464712SN/A#endif 477715Sgblack@eecs.umich.edu 484712SN/Ausing namespace std; 494712SN/A 504806SN/A// constructor 514712SN/A#if FULL_SYSTEM 527715Sgblack@eecs.umich.eduExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, System *_sys, 534712SN/A AlphaITB *_itb, AlphaDTB *_dtb, 544712SN/A FunctionalMemory *_mem) 554712SN/A : _status(ExecContext::Unallocated), cpu(_cpu), thread_num(_thread_num), 564712SN/A cpu_id(-1), mem(_mem), itb(_itb), dtb(_dtb), system(_sys), 574712SN/A memctrl(_sys->memctrl), physmem(_sys->physmem), 584712SN/A kernelBinning(system->kernelBinning), bin(kernelBinning->bin), 594712SN/A fnbin(kernelBinning->fnbin), profile(NULL), 604712SN/A func_exe_inst(0), storeCondFailures(0) 614712SN/A{ 624712SN/A kernelStats = new Kernel::Statistics(this); 634712SN/A memset(®s, 0, sizeof(RegFile)); 647715Sgblack@eecs.umich.edu 654712SN/A if (cpu->params->profile) { 664712SN/A profile = new FunctionProfile(system->kernelSymtab); 674712SN/A Callback *cb = 684712SN/A new MakeCallback<ExecContext, &ExecContext::dumpFuncProfile>(this); 694712SN/A registerExitCallback(cb); 704712SN/A } 714712SN/A 724712SN/A // let's fill with a dummy node for now so we don't get a segfault 734712SN/A // on the first cycle when there's no node available. 747715Sgblack@eecs.umich.edu static ProfileNode dummyNode; 7512234Sgabeblack@google.com profileNode = &dummyNode; 764712SN/A profilePC = 3; 774712SN/A} 787715Sgblack@eecs.umich.edu#else 794712SN/AExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, 804712SN/A Process *_process, int _asid) 814712SN/A : _status(ExecContext::Unallocated), 827715Sgblack@eecs.umich.edu cpu(_cpu), thread_num(_thread_num), cpu_id(-1), 837715Sgblack@eecs.umich.edu process(_process), mem(process->getMemory()), asid(_asid), 844712SN/A func_exe_inst(0), storeCondFailures(0) 854712SN/A{ 864712SN/A memset(®s, 0, sizeof(RegFile)); 877715Sgblack@eecs.umich.edu} 884712SN/A 894712SN/AExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, 90 FunctionalMemory *_mem, int _asid) 91 : cpu(_cpu), thread_num(_thread_num), process(0), mem(_mem), asid(_asid), 92 func_exe_inst(0), storeCondFailures(0) 93{ 94 memset(®s, 0, sizeof(RegFile)); 95} 96#endif 97 98ExecContext::~ExecContext() 99{ 100#if FULL_SYSTEM 101 delete kernelStats; 102#endif 103} 104 105#if FULL_SYSTEM 106void 107ExecContext::dumpFuncProfile() 108{ 109 std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name())); 110 profile->dump(this, *os); 111} 112#endif 113 114void 115ExecContext::takeOverFrom(ExecContext *oldContext) 116{ 117 // some things should already be set up 118 assert(mem == oldContext->mem); 119#if FULL_SYSTEM 120 assert(system == oldContext->system); 121#else 122 assert(process == oldContext->process); 123#endif 124 125 // copy over functional state 126 _status = oldContext->_status; 127 regs = oldContext->regs; 128 cpu_id = oldContext->cpu_id; 129 func_exe_inst = oldContext->func_exe_inst; 130 131 storeCondFailures = 0; 132 133 oldContext->_status = ExecContext::Unallocated; 134} 135 136void 137ExecContext::serialize(ostream &os) 138{ 139 SERIALIZE_ENUM(_status); 140 regs.serialize(os); 141 // thread_num and cpu_id are deterministic from the config 142 SERIALIZE_SCALAR(func_exe_inst); 143 SERIALIZE_SCALAR(inst); 144 145#if FULL_SYSTEM 146 kernelStats->serialize(os); 147#endif 148} 149 150 151void 152ExecContext::unserialize(Checkpoint *cp, const std::string §ion) 153{ 154 UNSERIALIZE_ENUM(_status); 155 regs.unserialize(cp, section); 156 // thread_num and cpu_id are deterministic from the config 157 UNSERIALIZE_SCALAR(func_exe_inst); 158 UNSERIALIZE_SCALAR(inst); 159 160#if FULL_SYSTEM 161 kernelStats->unserialize(cp, section); 162#endif 163} 164 165 166void 167ExecContext::activate(int delay) 168{ 169 if (status() == Active) 170 return; 171 172 _status = Active; 173 cpu->activateContext(thread_num, delay); 174} 175 176void 177ExecContext::suspend() 178{ 179 if (status() == Suspended) 180 return; 181 182#if FULL_SYSTEM 183 // Don't change the status from active if there are pending interrupts 184 if (cpu->check_interrupts()) { 185 assert(status() == Active); 186 return; 187 } 188#endif 189 190 _status = Suspended; 191 cpu->suspendContext(thread_num); 192} 193 194void 195ExecContext::deallocate() 196{ 197 if (status() == Unallocated) 198 return; 199 200 _status = Unallocated; 201 cpu->deallocateContext(thread_num); 202} 203 204void 205ExecContext::halt() 206{ 207 if (status() == Halted) 208 return; 209 210 _status = Halted; 211 cpu->haltContext(thread_num); 212} 213 214 215void 216ExecContext::regStats(const string &name) 217{ 218#if FULL_SYSTEM 219 kernelStats->regStats(name + ".kern"); 220#endif 221} 222 223void 224ExecContext::trap(Fault fault) 225{ 226 //TheISA::trap(fault); //One possible way to do it... 227 228 /** @todo: Going to hack it for now. Do a true fixup later. */ 229#if FULL_SYSTEM 230 ev5_trap(fault); 231#else 232 fatal("fault (%d) detected @ PC 0x%08p", fault, readPC()); 233#endif 234} 235