simple_thread.cc revision 3402:db60546818d0
12SN/A/* 28707Sandreas.hansson@arm.com * Copyright (c) 2001-2006 The Regents of The University of Michigan 38707Sandreas.hansson@arm.com * All rights reserved. 48707Sandreas.hansson@arm.com * 58707Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without 68707Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are 78707Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright 88707Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer; 98707Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright 108707Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the 118707Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution; 128707Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its 138707Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from 141762SN/A * this software without specific prior written permission. 157897Shestness@cs.utexas.edu * 162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272SN/A * 282SN/A * Authors: Steve Reinhardt 292SN/A * Nathan Binkert 302SN/A * Lisa Hsu 312SN/A * Kevin Lim 322SN/A */ 332SN/A 342SN/A#include <string> 352SN/A 362SN/A#include "arch/isa_traits.hh" 372SN/A#include "cpu/base.hh" 382SN/A#include "cpu/simple_thread.hh" 392SN/A#include "cpu/thread_context.hh" 402665Ssaidi@eecs.umich.edu 412665Ssaidi@eecs.umich.edu#if FULL_SYSTEM 422665Ssaidi@eecs.umich.edu#include "base/callback.hh" 437897Shestness@cs.utexas.edu#include "base/cprintf.hh" 442SN/A#include "base/output.hh" 452SN/A#include "base/trace.hh" 461388SN/A#include "cpu/profile.hh" 478229Snate@binkert.org#include "cpu/quiesce_event.hh" 482SN/A#include "kern/kernel_stats.hh" 492SN/A#include "sim/serialize.hh" 507781SAli.Saidi@ARM.com#include "sim/sim_exit.hh" 518229Snate@binkert.org#include "arch/stacktrace.hh" 521191SN/A#else 531191SN/A#include "sim/process.hh" 541388SN/A#include "sim/system.hh" 555529Snate@binkert.org#include "mem/translating_port.hh" 568733Sgeoffrey.blake@arm.com#endif 571717SN/A 582651Ssaidi@eecs.umich.eduusing namespace std; 598229Snate@binkert.org 602680Sktlim@umich.edu// constructor 618232Snate@binkert.org#if FULL_SYSTEM 625529Snate@binkert.orgSimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys, 638779Sgblack@eecs.umich.edu AlphaITB *_itb, AlphaDTB *_dtb, 642190SN/A bool use_kernel_stats) 6556SN/A : ThreadState(_cpu, -1, _thread_num), cpu(_cpu), system(_sys), itb(_itb), 668229Snate@binkert.org dtb(_dtb) 672190SN/A 682SN/A{ 698733Sgeoffrey.blake@arm.com tc = new ProxyThreadContext<SimpleThread>(this); 708733Sgeoffrey.blake@arm.com 718733Sgeoffrey.blake@arm.com quiesceEvent = new EndQuiesceEvent(tc); 728733Sgeoffrey.blake@arm.com 732359SN/A regs.clear(); 742359SN/A 752359SN/A if (cpu->params->profile) { 762SN/A profile = new FunctionProfile(system->kernelSymtab); 772SN/A Callback *cb = 782SN/A new MakeCallback<SimpleThread, 792SN/A &SimpleThread::dumpFuncProfile>(this); 802SN/A registerExitCallback(cb); 812SN/A } 822SN/A 832SN/A // let's fill with a dummy node for now so we don't get a segfault 842SN/A // on the first cycle when there's no node available. 855606Snate@binkert.org static ProfileNode dummyNode; 866144Sksewell@umich.edu profileNode = &dummyNode; 876144Sksewell@umich.edu profilePC = 3; 883126Sktlim@umich.edu 896144Sksewell@umich.edu if (use_kernel_stats) { 907823Ssteve.reinhardt@amd.com kernelStats = new Kernel::Statistics(system); 913126Sktlim@umich.edu } else { 923126Sktlim@umich.edu kernelStats = NULL; 932356SN/A } 942356SN/A Port *mem_port; 952356SN/A physPort = new FunctionalPort(csprintf("%s-%d-funcport", 968834Satgutier@umich.edu cpu->name(), tid)); 972356SN/A mem_port = system->physmem->getPort("functional"); 986144Sksewell@umich.edu mem_port->setPeer(physPort); 992367SN/A physPort->setPeer(mem_port); 1006144Sksewell@umich.edu 1016144Sksewell@umich.edu virtPort = new VirtualPort(csprintf("%s-%d-vport", 1026144Sksewell@umich.edu cpu->name(), tid)); 1032356SN/A mem_port = system->physmem->getPort("functional"); 1042367SN/A mem_port->setPeer(virtPort); 1056144Sksewell@umich.edu virtPort->setPeer(mem_port); 1067823Ssteve.reinhardt@amd.com} 1076144Sksewell@umich.edu#else 1082367SN/ASimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, 1092356SN/A Process *_process, int _asid) 1106144Sksewell@umich.edu : ThreadState(_cpu, -1, _thread_num, _process, _asid), 1116144Sksewell@umich.edu cpu(_cpu) 1127823Ssteve.reinhardt@amd.com{ 1132356SN/A regs.clear(); 1142356SN/A tc = new ProxyThreadContext<SimpleThread>(this); 1152356SN/A} 1165336Shines@cs.fsu.edu 1172356SN/A#endif 1184873Sstever@eecs.umich.edu 1192356SN/ASimpleThread::SimpleThread() 1202356SN/A#if FULL_SYSTEM 1211400SN/A : ThreadState(NULL, -1, -1) 1225712Shsul@eecs.umich.edu#else 1238832SAli.Saidi@ARM.com : ThreadState(NULL, -1, -1, NULL, -1) 1248832SAli.Saidi@ARM.com#endif 1255712Shsul@eecs.umich.edu{ 1266221Snate@binkert.org tc = new ProxyThreadContext<SimpleThread>(this); 1273661Srdreslin@umich.edu regs.clear(); 1282SN/A} 1297823Ssteve.reinhardt@amd.com 1301062SN/ASimpleThread::~SimpleThread() 1315712Shsul@eecs.umich.edu{ 1325712Shsul@eecs.umich.edu delete tc; 1335712Shsul@eecs.umich.edu} 1345712Shsul@eecs.umich.edu 1355712Shsul@eecs.umich.eduvoid 1362SN/ASimpleThread::takeOverFrom(ThreadContext *oldContext) 1372SN/A{ 1382SN/A // some things should already be set up 1395712Shsul@eecs.umich.edu#if FULL_SYSTEM 1405712Shsul@eecs.umich.edu assert(system == oldContext->getSystemPtr()); 1416221Snate@binkert.org#else 1426221Snate@binkert.org assert(process == oldContext->getProcessPtr()); 1432SN/A#endif 1442SN/A 1456221Snate@binkert.org copyState(oldContext); 1466221Snate@binkert.org#if FULL_SYSTEM 1476221Snate@binkert.org EndQuiesceEvent *quiesce = oldContext->getQuiesceEvent(); 1486221Snate@binkert.org if (quiesce) { 1492SN/A // Point the quiesce event's TC at this TC so that it wakes up 1502SN/A // the proper CPU. 1512SN/A quiesce->tc = tc; 1522SN/A } 1535606Snate@binkert.org if (quiesceEvent) { 1545606Snate@binkert.org quiesceEvent->tc = tc; 1556221Snate@binkert.org } 1565606Snate@binkert.org 1576221Snate@binkert.org Kernel::Statistics *stats = oldContext->getKernelStats(); 1585606Snate@binkert.org if (stats) { 1595606Snate@binkert.org kernelStats = stats; 1602SN/A } 1611400SN/A#endif 1625606Snate@binkert.org 1635606Snate@binkert.org storeCondFailures = 0; 1642SN/A 1652SN/A oldContext->setStatus(ThreadContext::Unallocated); 1662SN/A} 1672SN/A 1686221Snate@binkert.orgvoid 1696221Snate@binkert.orgSimpleThread::copyTC(ThreadContext *context) 1705606Snate@binkert.org{ 1716670Shsul@eecs.umich.edu copyState(context); 1725606Snate@binkert.org 1732SN/A#if FULL_SYSTEM 1742SN/A EndQuiesceEvent *quiesce = context->getQuiesceEvent(); 175124SN/A if (quiesce) { 1766221Snate@binkert.org quiesceEvent = quiesce; 1776221Snate@binkert.org } 1786221Snate@binkert.org Kernel::Statistics *stats = context->getKernelStats(); 179124SN/A if (stats) { 180124SN/A kernelStats = stats; 181124SN/A } 182124SN/A#endif 1835606Snate@binkert.org} 1845606Snate@binkert.org 1856221Snate@binkert.orgvoid 1865606Snate@binkert.orgSimpleThread::copyState(ThreadContext *oldContext) 1876221Snate@binkert.org{ 1885606Snate@binkert.org // copy over functional state 1895606Snate@binkert.org _status = oldContext->status(); 190124SN/A copyArchRegs(oldContext); 1911400SN/A cpuId = oldContext->readCpuId(); 1925606Snate@binkert.org#if !FULL_SYSTEM 193124SN/A funcExeInst = oldContext->readFuncExeInst(); 194124SN/A#endif 195124SN/A inst = oldContext->getInst(); 196124SN/A} 1976221Snate@binkert.org 1986221Snate@binkert.orgvoid 1995606Snate@binkert.orgSimpleThread::serialize(ostream &os) 2006221Snate@binkert.org{ 2015606Snate@binkert.org ThreadState::serialize(os); 202124SN/A regs.serialize(os); 203124SN/A // thread_num and cpu_id are deterministic from the config 2041191SN/A} 2055529Snate@binkert.org 2068634Schris.emmons@arm.com 2078634Schris.emmons@arm.comvoid 2088634Schris.emmons@arm.comSimpleThread::unserialize(Checkpoint *cp, const std::string §ion) 2098634Schris.emmons@arm.com{ 2108634Schris.emmons@arm.com ThreadState::unserialize(cp, section); 2111191SN/A regs.unserialize(cp, section); 2125529Snate@binkert.org // thread_num and cpu_id are deterministic from the config 2131191SN/A} 2145529Snate@binkert.org 2151191SN/A#if FULL_SYSTEM 2161191SN/Avoid 2175606Snate@binkert.orgSimpleThread::dumpFuncProfile() 2185606Snate@binkert.org{ 2195606Snate@binkert.org std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name())); 2201191SN/A profile->dump(tc, *os); 2211191SN/A} 2228733Sgeoffrey.blake@arm.com#endif 2238733Sgeoffrey.blake@arm.com 2248733Sgeoffrey.blake@arm.comvoid 2258733Sgeoffrey.blake@arm.comSimpleThread::activate(int delay) 2265810Sgblack@eecs.umich.edu{ 2278779Sgblack@eecs.umich.edu if (status() == ThreadContext::Active) 2288779Sgblack@eecs.umich.edu return; 2298779Sgblack@eecs.umich.edu 2308779Sgblack@eecs.umich.edu lastActivate = curTick; 2318779Sgblack@eecs.umich.edu 2325529Snate@binkert.org if (status() == ThreadContext::Unallocated) { 2331917SN/A cpu->activateWhenReady(tid); 2341191SN/A return; 2351191SN/A } 2361191SN/A 2371191SN/A _status = ThreadContext::Active; 2381191SN/A 2391191SN/A // status() == Suspended 2401191SN/A cpu->activateContext(tid, delay); 2411191SN/A} 2421191SN/A 2431191SN/Avoid 2441191SN/ASimpleThread::suspend() 2451129SN/A{ 2461129SN/A if (status() == ThreadContext::Suspended) 2471129SN/A return; 2485529Snate@binkert.org 2492680Sktlim@umich.edu lastActivate = curTick; 2501129SN/A lastSuspend = curTick; 251180SN/A/* 2522SN/A#if FULL_SYSTEM 2531917SN/A // Don't change the status from active if there are pending interrupts 2541917SN/A if (cpu->check_interrupts()) { 2558779Sgblack@eecs.umich.edu assert(status() == ThreadContext::Active); 2568779Sgblack@eecs.umich.edu return; 2578779Sgblack@eecs.umich.edu } 2588779Sgblack@eecs.umich.edu#endif 2592356SN/A*/ 2605529Snate@binkert.org _status = ThreadContext::Suspended; 2615606Snate@binkert.org cpu->suspendContext(tid); 2626144Sksewell@umich.edu} 2638607Sgblack@eecs.umich.edu 2642356SN/Avoid 2651917SN/ASimpleThread::deallocate() 2661917SN/A{ 2671917SN/A if (status() == ThreadContext::Unallocated) 2681917SN/A return; 2692SN/A 2702SN/A _status = ThreadContext::Unallocated; 271729SN/A cpu->deallocateContext(tid); 272707SN/A} 273707SN/A 274707SN/Avoid 275707SN/ASimpleThread::halt() 276707SN/A{ 277707SN/A if (status() == ThreadContext::Halted) 2787914SBrad.Beckmann@amd.com return; 2797914SBrad.Beckmann@amd.com 2807914SBrad.Beckmann@amd.com _status = ThreadContext::Halted; 2817914SBrad.Beckmann@amd.com cpu->haltContext(tid); 2827914SBrad.Beckmann@amd.com} 2837914SBrad.Beckmann@amd.com 2847914SBrad.Beckmann@amd.com 2857914SBrad.Beckmann@amd.comvoid 2867914SBrad.Beckmann@amd.comSimpleThread::regStats(const string &name) 2877914SBrad.Beckmann@amd.com{ 2882680Sktlim@umich.edu#if FULL_SYSTEM 2892SN/A if (kernelStats) 2902SN/A kernelStats->regStats(name + ".kern"); 2912SN/A#endif 2922SN/A} 2932680Sktlim@umich.edu 2942SN/Avoid 2952SN/ASimpleThread::copyArchRegs(ThreadContext *src_tc) 2962680Sktlim@umich.edu{ 2972SN/A TheISA::copyRegs(src_tc, tc); 2982SN/A} 2993495Sktlim@umich.edu 3003495Sktlim@umich.edu#if FULL_SYSTEM 3013495Sktlim@umich.eduVirtualPort* 3027823Ssteve.reinhardt@amd.comSimpleThread::getVirtPort(ThreadContext *src_tc) 3033495Sktlim@umich.edu{ 3043661Srdreslin@umich.edu if (!src_tc) 3053495Sktlim@umich.edu return virtPort; 3063495Sktlim@umich.edu 3073495Sktlim@umich.edu VirtualPort *vp; 3083495Sktlim@umich.edu Port *mem_port; 3093495Sktlim@umich.edu 3103495Sktlim@umich.edu vp = new VirtualPort("tc-vport", src_tc); 3113495Sktlim@umich.edu mem_port = system->physmem->getPort("functional"); 3124599Sacolyte@umich.edu mem_port->setPeer(vp); 3134599Sacolyte@umich.edu vp->setPeer(mem_port); 3143661Srdreslin@umich.edu return vp; 3153495Sktlim@umich.edu} 3167823Ssteve.reinhardt@amd.com 3173495Sktlim@umich.eduvoid 3183495Sktlim@umich.eduSimpleThread::delVirtPort(VirtualPort *vp) 319180SN/A{ 320180SN/A if (vp != virtPort) { 3212680Sktlim@umich.edu delete vp->getPeer(); 322180SN/A delete vp; 3236221Snate@binkert.org } 3246221Snate@binkert.org} 3256221Snate@binkert.org 3262378SN/A#else 3275718Shsul@eecs.umich.eduTranslatingPort * 3285718Shsul@eecs.umich.eduSimpleThread::getMemPort() 3295718Shsul@eecs.umich.edu{ 3305718Shsul@eecs.umich.edu if (port != NULL) 3315718Shsul@eecs.umich.edu return port; 3325718Shsul@eecs.umich.edu 3335718Shsul@eecs.umich.edu /* Use this port to for syscall emulation writes to memory. */ 3346221Snate@binkert.org Port *dcache_port; 3355718Shsul@eecs.umich.edu port = new TranslatingPort(csprintf("%s-%d-funcport", 3365718Shsul@eecs.umich.edu cpu->name(), tid), 3375718Shsul@eecs.umich.edu process->pTable, false); 3388779Sgblack@eecs.umich.edu dcache_port = cpu->getPort("dcache_port"); 3398779Sgblack@eecs.umich.edu assert(dcache_port != NULL); 3408779Sgblack@eecs.umich.edu dcache_port = dcache_port->getPeer(); 341180SN/A// mem_port->setPeer(port); 342180SN/A port->setPeer(dcache_port); 343180SN/A return port; 344180SN/A} 3454000Ssaidi@eecs.umich.edu 3464000Ssaidi@eecs.umich.edu#endif 3474000Ssaidi@eecs.umich.edu 3486221Snate@binkert.org