system.cc revision 3745
1955SN/A/*
2955SN/A * Copyright (c) 2003-2006 The Regents of The University of Michigan
313576Sciro.santilli@arm.com * All rights reserved.
413576Sciro.santilli@arm.com *
513576Sciro.santilli@arm.com * Redistribution and use in source and binary forms, with or without
613576Sciro.santilli@arm.com * modification, are permitted provided that the following conditions are
713576Sciro.santilli@arm.com * met: redistributions of source code must retain the above copyright
813576Sciro.santilli@arm.com * notice, this list of conditions and the following disclaimer;
913576Sciro.santilli@arm.com * redistributions in binary form must reproduce the above copyright
1013576Sciro.santilli@arm.com * notice, this list of conditions and the following disclaimer in the
1113576Sciro.santilli@arm.com * documentation and/or other materials provided with the distribution;
1213576Sciro.santilli@arm.com * neither the name of the copyright holders nor the names of its
1313576Sciro.santilli@arm.com * contributors may be used to endorse or promote products derived from
141762SN/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 *
28955SN/A * Authors: Steve Reinhardt
29955SN/A *          Lisa Hsu
30955SN/A *          Nathan Binkert
31955SN/A *          Ali Saidi
32955SN/A */
33955SN/A
34955SN/A#include "arch/isa_traits.hh"
35955SN/A#include "base/loader/object_file.hh"
36955SN/A#include "base/loader/symtab.hh"
37955SN/A#include "base/trace.hh"
38955SN/A#include "cpu/thread_context.hh"
392665Ssaidi@eecs.umich.edu#include "mem/mem_object.hh"
404762Snate@binkert.org#include "mem/physical.hh"
41955SN/A#include "sim/builder.hh"
4212563Sgabeblack@google.com#include "sim/byteswap.hh"
4312563Sgabeblack@google.com#include "sim/system.hh"
445522Snate@binkert.org#if FULL_SYSTEM
456143Snate@binkert.org#include "arch/vtophys.hh"
4612371Sgabeblack@google.com#include "arch/remote_gdb.hh"
474762Snate@binkert.org#include "kern/kernel_stats.hh"
485522Snate@binkert.org#endif
49955SN/A
505522Snate@binkert.orgusing namespace std;
5111974Sgabeblack@google.comusing namespace TheISA;
52955SN/A
535522Snate@binkert.orgvector<System *> System::systemList;
544202Sbinkertn@umich.edu
555742Snate@binkert.orgint System::numSystemsRunning = 0;
56955SN/A
574381Sbinkertn@umich.eduSystem::System(Params *p)
584381Sbinkertn@umich.edu    : SimObject(p->name), physmem(p->physmem), numcpus(0),
5912246Sgabeblack@google.com#if FULL_SYSTEM
6012246Sgabeblack@google.com      init_param(p->init_param),
618334Snate@binkert.org      functionalPort(p->name + "-fport"),
62955SN/A      virtPort(p->name + "-vport"),
63955SN/A#else
644202Sbinkertn@umich.edu      page_ptr(0),
65955SN/A#endif
664382Sbinkertn@umich.edu      memoryMode(p->mem_mode), _params(p)
674382Sbinkertn@umich.edu{
684382Sbinkertn@umich.edu    // add self to global system list
696654Snate@binkert.org    systemList.push_back(this);
705517Snate@binkert.org
718614Sgblack@eecs.umich.edu#if FULL_SYSTEM
727674Snate@binkert.org    kernelSymtab = new SymbolTable;
736143Snate@binkert.org    debugSymbolTable = new SymbolTable;
746143Snate@binkert.org
756143Snate@binkert.org
7612302Sgabeblack@google.com    /**
7712302Sgabeblack@google.com     * Get a functional port to memory
7812302Sgabeblack@google.com     */
7912371Sgabeblack@google.com    Port *mem_port;
8012371Sgabeblack@google.com    mem_port = physmem->getPort("functional");
8112371Sgabeblack@google.com    functionalPort.setPeer(mem_port);
8212371Sgabeblack@google.com    mem_port->setPeer(&functionalPort);
8312371Sgabeblack@google.com
8412371Sgabeblack@google.com    mem_port = physmem->getPort("functional");
8512371Sgabeblack@google.com    virtPort.setPeer(mem_port);
8612371Sgabeblack@google.com    mem_port->setPeer(&virtPort);
8712371Sgabeblack@google.com
8812371Sgabeblack@google.com
8912371Sgabeblack@google.com    /**
9012371Sgabeblack@google.com     * Load the kernel code into memory
9112371Sgabeblack@google.com     */
9212371Sgabeblack@google.com    // Load kernel code
9312371Sgabeblack@google.com    kernel = createObjectFile(params()->kernel_path);
9412371Sgabeblack@google.com    if (kernel == NULL)
9512371Sgabeblack@google.com        fatal("Could not load kernel file %s", params()->kernel_path);
9612371Sgabeblack@google.com
9712371Sgabeblack@google.com    // Load program sections into memory
9812371Sgabeblack@google.com    kernel->loadSections(&functionalPort, LoadAddrMask);
9912371Sgabeblack@google.com
10012371Sgabeblack@google.com    // setup entry points
10112371Sgabeblack@google.com    kernelStart = kernel->textBase();
10212371Sgabeblack@google.com    kernelEnd = kernel->bssBase() + kernel->bssSize();
10312371Sgabeblack@google.com    kernelEntry = kernel->entryPoint();
10412371Sgabeblack@google.com
10512371Sgabeblack@google.com    // load symbols
10612371Sgabeblack@google.com    if (!kernel->loadGlobalSymbols(kernelSymtab))
10712371Sgabeblack@google.com        panic("could not load kernel symbols\n");
10812371Sgabeblack@google.com
10912371Sgabeblack@google.com    if (!kernel->loadLocalSymbols(kernelSymtab))
11012371Sgabeblack@google.com        panic("could not load kernel local symbols\n");
11112371Sgabeblack@google.com
11212371Sgabeblack@google.com    if (!kernel->loadGlobalSymbols(debugSymbolTable))
11312371Sgabeblack@google.com        panic("could not load kernel symbols\n");
11412371Sgabeblack@google.com
11512371Sgabeblack@google.com    if (!kernel->loadLocalSymbols(debugSymbolTable))
11612371Sgabeblack@google.com        panic("could not load kernel local symbols\n");
11712371Sgabeblack@google.com
11812371Sgabeblack@google.com    DPRINTF(Loader, "Kernel start = %#x\n", kernelStart);
11912371Sgabeblack@google.com    DPRINTF(Loader, "Kernel end   = %#x\n", kernelEnd);
12012371Sgabeblack@google.com    DPRINTF(Loader, "Kernel entry = %#x\n", kernelEntry);
12112371Sgabeblack@google.com    DPRINTF(Loader, "Kernel loaded...\n");
12212371Sgabeblack@google.com#endif // FULL_SYSTEM
12312371Sgabeblack@google.com
12412371Sgabeblack@google.com    // increment the number of running systms
12512371Sgabeblack@google.com    numSystemsRunning++;
12612302Sgabeblack@google.com}
12712371Sgabeblack@google.com
12812302Sgabeblack@google.comSystem::~System()
12912371Sgabeblack@google.com{
13012302Sgabeblack@google.com#if FULL_SYSTEM
13112302Sgabeblack@google.com    delete kernelSymtab;
13212371Sgabeblack@google.com    delete kernel;
13312371Sgabeblack@google.com#else
13412371Sgabeblack@google.com    panic("System::fixFuncEventAddr needs to be rewritten "
13512371Sgabeblack@google.com          "to work with syscall emulation");
13612302Sgabeblack@google.com#endif // FULL_SYSTEM}
13712371Sgabeblack@google.com}
13812371Sgabeblack@google.com
13912371Sgabeblack@google.com#if FULL_SYSTEM
14012371Sgabeblack@google.com
14111983Sgabeblack@google.com
1426143Snate@binkert.orgint rgdb_wait = -1;
1438233Snate@binkert.org
14412302Sgabeblack@google.com#endif // FULL_SYSTEM
1456143Snate@binkert.org
1466143Snate@binkert.org
14712302Sgabeblack@google.comvoid
1484762Snate@binkert.orgSystem::setMemoryMode(MemoryMode mode)
1496143Snate@binkert.org{
1508233Snate@binkert.org    assert(getState() == Drained);
1518233Snate@binkert.org    memoryMode = mode;
15212302Sgabeblack@google.com}
15312302Sgabeblack@google.com
1546143Snate@binkert.orgint
15512362Sgabeblack@google.comSystem::registerThreadContext(ThreadContext *tc, int id)
15612362Sgabeblack@google.com{
15712362Sgabeblack@google.com    if (id == -1) {
15812362Sgabeblack@google.com        for (id = 0; id < threadContexts.size(); id++) {
15912302Sgabeblack@google.com            if (!threadContexts[id])
16012302Sgabeblack@google.com                break;
16112302Sgabeblack@google.com        }
16212302Sgabeblack@google.com    }
16312302Sgabeblack@google.com
16412363Sgabeblack@google.com    if (threadContexts.size() <= id)
16512363Sgabeblack@google.com        threadContexts.resize(id + 1);
16612363Sgabeblack@google.com
16712363Sgabeblack@google.com    if (threadContexts[id])
16812302Sgabeblack@google.com        panic("Cannot have two CPUs with the same id (%d)\n", id);
16912363Sgabeblack@google.com
17012363Sgabeblack@google.com    threadContexts[id] = tc;
17112363Sgabeblack@google.com    numcpus++;
17212363Sgabeblack@google.com
17312363Sgabeblack@google.com#if FULL_SYSTEM
1748233Snate@binkert.org    RemoteGDB *rgdb = new RemoteGDB(this, tc);
1756143Snate@binkert.org    GDBListener *gdbl = new GDBListener(rgdb, 7000 + id);
1766143Snate@binkert.org    gdbl->listen();
1776143Snate@binkert.org    /**
1786143Snate@binkert.org     * Uncommenting this line waits for a remote debugger to connect
1796143Snate@binkert.org     * to the simulator before continuing.
1806143Snate@binkert.org     */
1816143Snate@binkert.org    if (rgdb_wait != -1 && rgdb_wait == id)
1826143Snate@binkert.org        gdbl->accept();
1836143Snate@binkert.org
1847065Snate@binkert.org    if (remoteGDB.size() <= id) {
1856143Snate@binkert.org        remoteGDB.resize(id + 1);
18612362Sgabeblack@google.com    }
18712362Sgabeblack@google.com
18812362Sgabeblack@google.com    remoteGDB[id] = rgdb;
18912362Sgabeblack@google.com#endif // FULL_SYSTEM
19012362Sgabeblack@google.com
19112362Sgabeblack@google.com    return id;
19212362Sgabeblack@google.com}
19312362Sgabeblack@google.com
19412362Sgabeblack@google.comvoid
19512362Sgabeblack@google.comSystem::startup()
19612362Sgabeblack@google.com{
19712362Sgabeblack@google.com    int i;
1988233Snate@binkert.org    for (i = 0; i < threadContexts.size(); i++)
1998233Snate@binkert.org        threadContexts[i]->activate(0);
2008233Snate@binkert.org}
2018233Snate@binkert.org
2028233Snate@binkert.orgvoid
2038233Snate@binkert.orgSystem::replaceThreadContext(ThreadContext *tc, int id)
2048233Snate@binkert.org{
2058233Snate@binkert.org    if (id >= threadContexts.size()) {
2068233Snate@binkert.org        panic("replaceThreadContext: bad id, %d >= %d\n",
2078233Snate@binkert.org              id, threadContexts.size());
2088233Snate@binkert.org    }
2098233Snate@binkert.org
2108233Snate@binkert.org    threadContexts[id] = tc;
2118233Snate@binkert.org#if FULL_SYSTEM
2128233Snate@binkert.org    remoteGDB[id]->replaceThreadContext(tc);
2138233Snate@binkert.org#endif // FULL_SYSTEM
2148233Snate@binkert.org}
2158233Snate@binkert.org
2168233Snate@binkert.org#if !FULL_SYSTEM
2178233Snate@binkert.orgAddr
2188233Snate@binkert.orgSystem::new_page()
2196143Snate@binkert.org{
2206143Snate@binkert.org    Addr return_addr = page_ptr << LogVMPageSize;
2216143Snate@binkert.org    ++page_ptr;
2226143Snate@binkert.org    if (return_addr >= physmem->size())
2236143Snate@binkert.org        fatal("Out of memory, please increase size of physical memory.");
2246143Snate@binkert.org    return return_addr;
2259982Satgutier@umich.edu}
22613576Sciro.santilli@arm.com#endif
22713576Sciro.santilli@arm.com
22813576Sciro.santilli@arm.comvoid
22913576Sciro.santilli@arm.comSystem::serialize(ostream &os)
23013576Sciro.santilli@arm.com{
23113576Sciro.santilli@arm.com#if FULL_SYSTEM
23213576Sciro.santilli@arm.com    kernelSymtab->serialize("kernel_symtab", os);
23313576Sciro.santilli@arm.com#endif // FULL_SYSTEM
23413576Sciro.santilli@arm.com}
23513576Sciro.santilli@arm.com
23613576Sciro.santilli@arm.com
23713576Sciro.santilli@arm.comvoid
23813576Sciro.santilli@arm.comSystem::unserialize(Checkpoint *cp, const string &section)
23913576Sciro.santilli@arm.com{
24013576Sciro.santilli@arm.com#if FULL_SYSTEM
24113576Sciro.santilli@arm.com    kernelSymtab->unserialize("kernel_symtab", cp, section);
24213576Sciro.santilli@arm.com#endif // FULL_SYSTEM
24313576Sciro.santilli@arm.com}
24413576Sciro.santilli@arm.com
24513576Sciro.santilli@arm.comvoid
24613576Sciro.santilli@arm.comSystem::printSystems()
24713576Sciro.santilli@arm.com{
24813576Sciro.santilli@arm.com    vector<System *>::iterator i = systemList.begin();
24913576Sciro.santilli@arm.com    vector<System *>::iterator end = systemList.end();
25013576Sciro.santilli@arm.com    for (; i != end; ++i) {
25113576Sciro.santilli@arm.com        System *sys = *i;
25213576Sciro.santilli@arm.com        cerr << "System " << sys->name() << ": " << hex << sys << endl;
25313576Sciro.santilli@arm.com    }
25413576Sciro.santilli@arm.com}
25513576Sciro.santilli@arm.com
25613576Sciro.santilli@arm.comvoid
25713576Sciro.santilli@arm.comprintSystems()
25813576Sciro.santilli@arm.com{
25913576Sciro.santilli@arm.com    System::printSystems();
26013576Sciro.santilli@arm.com}
26113576Sciro.santilli@arm.com
26213576Sciro.santilli@arm.comconst char *System::MemoryModeStrings[3] = {"invalid", "atomic",
26313576Sciro.santilli@arm.com    "timing"};
26413576Sciro.santilli@arm.com
26513576Sciro.santilli@arm.com#if FULL_SYSTEM
26613576Sciro.santilli@arm.com
26713576Sciro.santilli@arm.com// In full system mode, only derived classes (e.g. AlphaLinuxSystem)
26813576Sciro.santilli@arm.com// can be created directly.
26913576Sciro.santilli@arm.com
27013576Sciro.santilli@arm.comDEFINE_SIM_OBJECT_CLASS_NAME("System", System)
27113576Sciro.santilli@arm.com
27213576Sciro.santilli@arm.com#else
27313576Sciro.santilli@arm.com
27413576Sciro.santilli@arm.comBEGIN_DECLARE_SIM_OBJECT_PARAMS(System)
27513576Sciro.santilli@arm.com
27613576Sciro.santilli@arm.com    SimObjectParam<PhysicalMemory *> physmem;
27713576Sciro.santilli@arm.com    SimpleEnumParam<System::MemoryMode> mem_mode;
27813576Sciro.santilli@arm.com
27913576Sciro.santilli@arm.comEND_DECLARE_SIM_OBJECT_PARAMS(System)
28013576Sciro.santilli@arm.com
28113576Sciro.santilli@arm.comBEGIN_INIT_SIM_OBJECT_PARAMS(System)
28213576Sciro.santilli@arm.com
28313576Sciro.santilli@arm.com    INIT_PARAM(physmem, "physical memory"),
28413576Sciro.santilli@arm.com    INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)",
28513576Sciro.santilli@arm.com            System::MemoryModeStrings)
28613576Sciro.santilli@arm.com
28713576Sciro.santilli@arm.comEND_INIT_SIM_OBJECT_PARAMS(System)
28813576Sciro.santilli@arm.com
28913576Sciro.santilli@arm.comCREATE_SIM_OBJECT(System)
29013576Sciro.santilli@arm.com{
29113576Sciro.santilli@arm.com    System::Params *p = new System::Params;
29213576Sciro.santilli@arm.com    p->name = getInstanceName();
29313576Sciro.santilli@arm.com    p->physmem = physmem;
29413576Sciro.santilli@arm.com    p->mem_mode = mem_mode;
29513576Sciro.santilli@arm.com    return new System(p);
2966143Snate@binkert.org}
29712302Sgabeblack@google.com
29812302Sgabeblack@google.comREGISTER_SIM_OBJECT("System", System)
29912302Sgabeblack@google.com
30012302Sgabeblack@google.com#endif
30112302Sgabeblack@google.com