simple_thread.cc revision 1917
1955SN/A/*
2955SN/A * Copyright (c) 2001-2005 The Regents of The University of Michigan
31762SN/A * All rights reserved.
4955SN/A *
5955SN/A * Redistribution and use in source and binary forms, with or without
6955SN/A * modification, are permitted provided that the following conditions are
7955SN/A * met: redistributions of source code must retain the above copyright
8955SN/A * notice, this list of conditions and the following disclaimer;
9955SN/A * redistributions in binary form must reproduce the above copyright
10955SN/A * notice, this list of conditions and the following disclaimer in the
11955SN/A * documentation and/or other materials provided with the distribution;
12955SN/A * neither the name of the copyright holders nor the names of its
13955SN/A * contributors may be used to endorse or promote products derived from
14955SN/A * this software without specific prior written permission.
15955SN/A *
16955SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17955SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18955SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19955SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20955SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21955SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22955SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23955SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24955SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25955SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26955SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27955SN/A */
282665Ssaidi@eecs.umich.edu
294762Snate@binkert.org#include <string>
30955SN/A
315522Snate@binkert.org#include "cpu/base.hh"
326143Snate@binkert.org#include "cpu/exec_context.hh"
334762Snate@binkert.org
345522Snate@binkert.org#if FULL_SYSTEM
35955SN/A#include "base/callback.hh"
365522Snate@binkert.org#include "base/cprintf.hh"
3711974Sgabeblack@google.com#include "base/output.hh"
38955SN/A#include "cpu/profile.hh"
395522Snate@binkert.org#include "kern/kernel_stats.hh"
404202Sbinkertn@umich.edu#include "sim/serialize.hh"
415742Snate@binkert.org#include "sim/sim_exit.hh"
42955SN/A#include "sim/system.hh"
434381Sbinkertn@umich.edu#include "targetarch/stacktrace.hh"
444381Sbinkertn@umich.edu#else
458334Snate@binkert.org#include "sim/process.hh"
46955SN/A#endif
47955SN/A
484202Sbinkertn@umich.eduusing namespace std;
49955SN/A
504382Sbinkertn@umich.edu// constructor
514382Sbinkertn@umich.edu#if FULL_SYSTEM
524382Sbinkertn@umich.eduExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, System *_sys,
536654Snate@binkert.org                         AlphaITB *_itb, AlphaDTB *_dtb,
545517Snate@binkert.org                         FunctionalMemory *_mem)
558614Sgblack@eecs.umich.edu    : _status(ExecContext::Unallocated), cpu(_cpu), thread_num(_thread_num),
567674Snate@binkert.org      cpu_id(-1), mem(_mem), itb(_itb), dtb(_dtb), system(_sys),
576143Snate@binkert.org      memctrl(_sys->memctrl), physmem(_sys->physmem),
586143Snate@binkert.org      kernelBinning(system->kernelBinning), bin(kernelBinning->bin),
596143Snate@binkert.org      fnbin(kernelBinning->fnbin), profile(NULL),
608233Snate@binkert.org      func_exe_inst(0), storeCondFailures(0)
618233Snate@binkert.org{
628233Snate@binkert.org    kernelStats = new Kernel::Statistics(this);
638233Snate@binkert.org    memset(&regs, 0, sizeof(RegFile));
648233Snate@binkert.org
658334Snate@binkert.org    if (cpu->params->profile) {
668334Snate@binkert.org        profile = new FunctionProfile(system->allSymtab);
6710453SAndrew.Bardsley@arm.com        Callback *cb =
6810453SAndrew.Bardsley@arm.com            new MakeCallback<ExecContext, &ExecContext::dumpFuncProfile>(this);
698233Snate@binkert.org        registerExitCallback(cb);
708233Snate@binkert.org    }
718233Snate@binkert.org
728233Snate@binkert.org    // let's fill with a dummy node for now so we don't get a segfault
738233Snate@binkert.org    // on the first cycle when there's no node available.
748233Snate@binkert.org    static ProfileNode dummyNode;
7511983Sgabeblack@google.com    profileNode = &dummyNode;
7611983Sgabeblack@google.com    profilePC = 3;
7711983Sgabeblack@google.com}
7811983Sgabeblack@google.com#else
7911983Sgabeblack@google.comExecContext::ExecContext(BaseCPU *_cpu, int _thread_num,
8011983Sgabeblack@google.com                         Process *_process, int _asid)
8111983Sgabeblack@google.com    : _status(ExecContext::Unallocated),
8211983Sgabeblack@google.com      cpu(_cpu), thread_num(_thread_num), cpu_id(-1),
8311983Sgabeblack@google.com      process(_process), mem(process->getMemory()), asid(_asid),
8411983Sgabeblack@google.com      func_exe_inst(0), storeCondFailures(0)
8511983Sgabeblack@google.com{
866143Snate@binkert.org    memset(&regs, 0, sizeof(RegFile));
878233Snate@binkert.org}
888233Snate@binkert.org
898233Snate@binkert.orgExecContext::ExecContext(BaseCPU *_cpu, int _thread_num,
906143Snate@binkert.org                         FunctionalMemory *_mem, int _asid)
916143Snate@binkert.org    : cpu(_cpu), thread_num(_thread_num), process(0), mem(_mem), asid(_asid),
926143Snate@binkert.org      func_exe_inst(0), storeCondFailures(0)
9311308Santhony.gutierrez@amd.com{
948233Snate@binkert.org    memset(&regs, 0, sizeof(RegFile));
958233Snate@binkert.org}
968233Snate@binkert.org#endif
9711983Sgabeblack@google.com
9811983Sgabeblack@google.comExecContext::~ExecContext()
994762Snate@binkert.org{
1006143Snate@binkert.org#if FULL_SYSTEM
1018233Snate@binkert.org    delete kernelStats;
1028233Snate@binkert.org#endif
1038233Snate@binkert.org}
1048233Snate@binkert.org
1058233Snate@binkert.org#if FULL_SYSTEM
1066143Snate@binkert.orgvoid
1078233Snate@binkert.orgExecContext::dumpFuncProfile()
1088233Snate@binkert.org{
1098233Snate@binkert.org    std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name()));
1108233Snate@binkert.org    profile->dump(this, *os);
1116143Snate@binkert.org}
1126143Snate@binkert.org#endif
1136143Snate@binkert.org
1146143Snate@binkert.orgvoid
1156143Snate@binkert.orgExecContext::takeOverFrom(ExecContext *oldContext)
1166143Snate@binkert.org{
1176143Snate@binkert.org    // some things should already be set up
1186143Snate@binkert.org    assert(mem == oldContext->mem);
1196143Snate@binkert.org#if FULL_SYSTEM
1207065Snate@binkert.org    assert(system == oldContext->system);
1216143Snate@binkert.org#else
1228233Snate@binkert.org    assert(process == oldContext->process);
1238233Snate@binkert.org#endif
1248233Snate@binkert.org
1258233Snate@binkert.org    // copy over functional state
1268233Snate@binkert.org    _status = oldContext->_status;
1278233Snate@binkert.org    regs = oldContext->regs;
1288233Snate@binkert.org    cpu_id = oldContext->cpu_id;
1298233Snate@binkert.org    func_exe_inst = oldContext->func_exe_inst;
1308233Snate@binkert.org
1318233Snate@binkert.org    storeCondFailures = 0;
1328233Snate@binkert.org
1338233Snate@binkert.org    oldContext->_status = ExecContext::Unallocated;
1348233Snate@binkert.org}
1358233Snate@binkert.org
1368233Snate@binkert.orgvoid
1378233Snate@binkert.orgExecContext::serialize(ostream &os)
1388233Snate@binkert.org{
1398233Snate@binkert.org    SERIALIZE_ENUM(_status);
1408233Snate@binkert.org    regs.serialize(os);
1418233Snate@binkert.org    // thread_num and cpu_id are deterministic from the config
1428233Snate@binkert.org    SERIALIZE_SCALAR(func_exe_inst);
1438233Snate@binkert.org    SERIALIZE_SCALAR(inst);
1448233Snate@binkert.org
1458233Snate@binkert.org#if FULL_SYSTEM
1468233Snate@binkert.org    kernelStats->serialize(os);
1478233Snate@binkert.org#endif
1488233Snate@binkert.org}
1498233Snate@binkert.org
1508233Snate@binkert.org
1518233Snate@binkert.orgvoid
1528233Snate@binkert.orgExecContext::unserialize(Checkpoint *cp, const std::string &section)
1536143Snate@binkert.org{
1546143Snate@binkert.org    UNSERIALIZE_ENUM(_status);
1556143Snate@binkert.org    regs.unserialize(cp, section);
1566143Snate@binkert.org    // thread_num and cpu_id are deterministic from the config
1576143Snate@binkert.org    UNSERIALIZE_SCALAR(func_exe_inst);
1586143Snate@binkert.org    UNSERIALIZE_SCALAR(inst);
1599982Satgutier@umich.edu
16010196SCurtis.Dunham@arm.com#if FULL_SYSTEM
16110196SCurtis.Dunham@arm.com    kernelStats->unserialize(cp, section);
16210196SCurtis.Dunham@arm.com#endif
16310196SCurtis.Dunham@arm.com}
16410196SCurtis.Dunham@arm.com
16510196SCurtis.Dunham@arm.com
16610196SCurtis.Dunham@arm.comvoid
16710196SCurtis.Dunham@arm.comExecContext::activate(int delay)
1686143Snate@binkert.org{
16911983Sgabeblack@google.com    if (status() == Active)
17011983Sgabeblack@google.com        return;
17111983Sgabeblack@google.com
17211983Sgabeblack@google.com    _status = Active;
17311983Sgabeblack@google.com    cpu->activateContext(thread_num, delay);
17411983Sgabeblack@google.com}
17511983Sgabeblack@google.com
17611983Sgabeblack@google.comvoid
17711983Sgabeblack@google.comExecContext::suspend()
1786143Snate@binkert.org{
17911988Sandreas.sandberg@arm.com    if (status() == Suspended)
1808233Snate@binkert.org        return;
1818233Snate@binkert.org
1826143Snate@binkert.org#if FULL_SYSTEM
1838945Ssteve.reinhardt@amd.com    // Don't change the status from active if there are pending interrupts
1846143Snate@binkert.org    if (cpu->check_interrupts()) {
18511983Sgabeblack@google.com        assert(status() == Active);
18611983Sgabeblack@google.com        return;
1876143Snate@binkert.org    }
1886143Snate@binkert.org#endif
1895522Snate@binkert.org
1906143Snate@binkert.org    _status = Suspended;
1916143Snate@binkert.org    cpu->suspendContext(thread_num);
1926143Snate@binkert.org}
1939982Satgutier@umich.edu
1948233Snate@binkert.orgvoid
1958233Snate@binkert.orgExecContext::deallocate()
1968233Snate@binkert.org{
1976143Snate@binkert.org    if (status() == Unallocated)
1986143Snate@binkert.org        return;
1996143Snate@binkert.org
2006143Snate@binkert.org    _status = Unallocated;
2015522Snate@binkert.org    cpu->deallocateContext(thread_num);
2025522Snate@binkert.org}
2035522Snate@binkert.org
2045522Snate@binkert.orgvoid
2055604Snate@binkert.orgExecContext::halt()
2065604Snate@binkert.org{
2076143Snate@binkert.org    if (status() == Halted)
2086143Snate@binkert.org        return;
2094762Snate@binkert.org
2104762Snate@binkert.org    _status = Halted;
2116143Snate@binkert.org    cpu->haltContext(thread_num);
2126727Ssteve.reinhardt@amd.com}
2136727Ssteve.reinhardt@amd.com
2146727Ssteve.reinhardt@amd.com
2154762Snate@binkert.orgvoid
2166143Snate@binkert.orgExecContext::regStats(const string &name)
2176143Snate@binkert.org{
2186143Snate@binkert.org#if FULL_SYSTEM
2196143Snate@binkert.org    kernelStats->regStats(name + ".kern");
2206727Ssteve.reinhardt@amd.com#endif
2216143Snate@binkert.org}
2227674Snate@binkert.org
2237674Snate@binkert.orgvoid
2245604Snate@binkert.orgExecContext::trap(Fault fault)
2256143Snate@binkert.org{
2266143Snate@binkert.org    //TheISA::trap(fault);    //One possible way to do it...
2276143Snate@binkert.org
2284762Snate@binkert.org    /** @todo: Going to hack it for now.  Do a true fixup later. */
2296143Snate@binkert.org#if FULL_SYSTEM
2304762Snate@binkert.org    ev5_trap(fault);
2314762Snate@binkert.org#else
2324762Snate@binkert.org    fatal("fault (%d) detected @ PC 0x%08p", fault, readPC());
2336143Snate@binkert.org#endif
2346143Snate@binkert.org}
2354762Snate@binkert.org