system.cc revision 8769
1/*
2 * Copyright (c) 2003-2006 The Regents of The University of Michigan
3 * Copyright (c) 2011 Regents of the University of California
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer;
10 * redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution;
13 * neither the name of the copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Authors: Steve Reinhardt
30 *          Lisa Hsu
31 *          Nathan Binkert
32 *          Ali Saidi
33 *          Rick Strong
34 */
35
36#include "arch/isa_traits.hh"
37#include "arch/remote_gdb.hh"
38#include "arch/utility.hh"
39#include "arch/vtophys.hh"
40#include "base/loader/object_file.hh"
41#include "base/loader/symtab.hh"
42#include "base/trace.hh"
43#include "config/the_isa.hh"
44#include "cpu/thread_context.hh"
45#include "debug/Loader.hh"
46#include "kern/kernel_stats.hh"
47#include "mem/mem_object.hh"
48#include "mem/physical.hh"
49#include "mem/vport.hh"
50#include "params/System.hh"
51#include "sim/byteswap.hh"
52#include "sim/debug.hh"
53#include "sim/full_system.hh"
54#include "sim/system.hh"
55
56using namespace std;
57using namespace TheISA;
58
59vector<System *> System::systemList;
60
61int System::numSystemsRunning = 0;
62
63System::System(Params *p)
64    : SimObject(p), physmem(p->physmem), _numContexts(0), pagePtr(0),
65      init_param(p->init_param),
66      loadAddrMask(p->load_addr_mask),
67      nextPID(0),
68      memoryMode(p->mem_mode),
69      workItemsBegin(0),
70      workItemsEnd(0),
71      _params(p),
72      totalNumInsts(0),
73      instEventQueue("system instruction-based event queue")
74{
75    // add self to global system list
76    systemList.push_back(this);
77
78    /** Keep track of all memories we can execute code out of
79     * in our system
80     */
81    for (int x = 0; x < p->memories.size(); x++) {
82        if (!p->memories[x])
83            continue;
84        memRanges.push_back(RangeSize(p->memories[x]->start(),
85                                      p->memories[x]->size()));
86    }
87
88    if (FullSystem) {
89        kernelSymtab = new SymbolTable;
90        if (!debugSymbolTable)
91            debugSymbolTable = new SymbolTable;
92
93
94        /**
95         * Get a functional port to memory
96         */
97        Port *mem_port;
98        functionalPort = new FunctionalPort(name() + "-fport");
99        mem_port = physmem->getPort("functional");
100        functionalPort->setPeer(mem_port);
101        mem_port->setPeer(functionalPort);
102
103        virtPort = new VirtualPort(name() + "-fport");
104        mem_port = physmem->getPort("functional");
105        virtPort->setPeer(mem_port);
106        mem_port->setPeer(virtPort);
107
108
109        /**
110         * Load the kernel code into memory
111         */
112        if (params()->kernel == "") {
113            inform("No kernel set for full system simulation. "
114                    "Assuming you know what you're doing...\n");
115        } else {
116            // Load kernel code
117            kernel = createObjectFile(params()->kernel);
118            inform("kernel located at: %s", params()->kernel);
119
120            if (kernel == NULL)
121                fatal("Could not load kernel file %s", params()->kernel);
122
123            // Load program sections into memory
124            kernel->loadSections(functionalPort, loadAddrMask);
125
126            // setup entry points
127            kernelStart = kernel->textBase();
128            kernelEnd = kernel->bssBase() + kernel->bssSize();
129            kernelEntry = kernel->entryPoint();
130
131            // load symbols
132            if (!kernel->loadGlobalSymbols(kernelSymtab))
133                fatal("could not load kernel symbols\n");
134
135            if (!kernel->loadLocalSymbols(kernelSymtab))
136                fatal("could not load kernel local symbols\n");
137
138            if (!kernel->loadGlobalSymbols(debugSymbolTable))
139                fatal("could not load kernel symbols\n");
140
141            if (!kernel->loadLocalSymbols(debugSymbolTable))
142                fatal("could not load kernel local symbols\n");
143
144            DPRINTF(Loader, "Kernel start = %#x\n", kernelStart);
145            DPRINTF(Loader, "Kernel end   = %#x\n", kernelEnd);
146            DPRINTF(Loader, "Kernel entry = %#x\n", kernelEntry);
147            DPRINTF(Loader, "Kernel loaded...\n");
148        }
149    }
150
151    // increment the number of running systms
152    numSystemsRunning++;
153
154    activeCpus.clear();
155}
156
157System::~System()
158{
159    delete kernelSymtab;
160    delete kernel;
161}
162
163void
164System::setMemoryMode(Enums::MemoryMode mode)
165{
166    assert(getState() == Drained);
167    memoryMode = mode;
168}
169
170bool System::breakpoint()
171{
172    if (remoteGDB.size())
173        return remoteGDB[0]->breakpoint();
174    return false;
175}
176
177/**
178 * Setting rgdb_wait to a positive integer waits for a remote debugger to
179 * connect to that context ID before continuing.  This should really
180   be a parameter on the CPU object or something...
181 */
182int rgdb_wait = -1;
183
184int
185System::registerThreadContext(ThreadContext *tc, int assigned)
186{
187    int id;
188    if (assigned == -1) {
189        for (id = 0; id < threadContexts.size(); id++) {
190            if (!threadContexts[id])
191                break;
192        }
193
194        if (threadContexts.size() <= id)
195            threadContexts.resize(id + 1);
196    } else {
197        if (threadContexts.size() <= assigned)
198            threadContexts.resize(assigned + 1);
199        id = assigned;
200    }
201
202    if (threadContexts[id])
203        fatal("Cannot have two CPUs with the same id (%d)\n", id);
204
205    threadContexts[id] = tc;
206    _numContexts++;
207
208    int port = getRemoteGDBPort();
209    if (port) {
210        RemoteGDB *rgdb = new RemoteGDB(this, tc);
211        GDBListener *gdbl = new GDBListener(rgdb, port + id);
212        gdbl->listen();
213
214        if (rgdb_wait != -1 && rgdb_wait == id)
215            gdbl->accept();
216
217        if (remoteGDB.size() <= id) {
218            remoteGDB.resize(id + 1);
219        }
220
221        remoteGDB[id] = rgdb;
222    }
223
224    activeCpus.push_back(false);
225
226    return id;
227}
228
229int
230System::numRunningContexts()
231{
232    int running = 0;
233    for (int i = 0; i < _numContexts; ++i) {
234        if (threadContexts[i]->status() != ThreadContext::Halted)
235            ++running;
236    }
237    return running;
238}
239
240void
241System::initState()
242{
243    if (FullSystem) {
244        int i;
245        for (i = 0; i < threadContexts.size(); i++)
246            TheISA::startupCPU(threadContexts[i], i);
247    }
248}
249
250void
251System::replaceThreadContext(ThreadContext *tc, int context_id)
252{
253    if (context_id >= threadContexts.size()) {
254        panic("replaceThreadContext: bad id, %d >= %d\n",
255              context_id, threadContexts.size());
256    }
257
258    threadContexts[context_id] = tc;
259    if (context_id < remoteGDB.size())
260        remoteGDB[context_id]->replaceThreadContext(tc);
261}
262
263Addr
264System::new_page()
265{
266    Addr return_addr = pagePtr << LogVMPageSize;
267    ++pagePtr;
268    if (return_addr >= physmem->size())
269        fatal("Out of memory, please increase size of physical memory.");
270    return return_addr;
271}
272
273Addr
274System::memSize()
275{
276    return physmem->size();
277}
278
279Addr
280System::freeMemSize()
281{
282   return physmem->size() - (pagePtr << LogVMPageSize);
283}
284
285bool
286System::isMemory(const Addr addr) const
287{
288    std::list<Range<Addr> >::const_iterator i;
289    for (i = memRanges.begin(); i != memRanges.end(); i++) {
290        if (*i == addr)
291            return true;
292    }
293    return false;
294}
295
296void
297System::resume()
298{
299    SimObject::resume();
300    totalNumInsts = 0;
301}
302
303void
304System::serialize(ostream &os)
305{
306    if (FullSystem)
307        kernelSymtab->serialize("kernel_symtab", os);
308    SERIALIZE_SCALAR(pagePtr);
309    SERIALIZE_SCALAR(nextPID);
310}
311
312
313void
314System::unserialize(Checkpoint *cp, const string &section)
315{
316    if (FullSystem)
317        kernelSymtab->unserialize("kernel_symtab", cp, section);
318    UNSERIALIZE_SCALAR(pagePtr);
319    UNSERIALIZE_SCALAR(nextPID);
320}
321
322void
323System::printSystems()
324{
325    vector<System *>::iterator i = systemList.begin();
326    vector<System *>::iterator end = systemList.end();
327    for (; i != end; ++i) {
328        System *sys = *i;
329        cerr << "System " << sys->name() << ": " << hex << sys << endl;
330    }
331}
332
333void
334printSystems()
335{
336    System::printSystems();
337}
338
339const char *System::MemoryModeStrings[3] = {"invalid", "atomic",
340    "timing"};
341
342System *
343SystemParams::create()
344{
345    return new System(this);
346}
347