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 &section)
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