system.cc revision 2424
1#include "base/loader/object_file.hh"
2#include "base/loader/symtab.hh"
3#include "cpu/exec_context.hh"
4#include "mem/memory.hh"
5#include "sim/builder.hh"
6#include "arch/isa_traits.hh"
7#include "sim/byteswap.hh"
8#include "sim/system.hh"
9#include "base/trace.hh"
10#if FULL_SYSTEM
11#include "base/remote_gdb.hh"
12#include "kern/kernel_stats.hh"
13#include "mem/functional/memory_control.hh"
14#include "arch/vtophys.hh"
15#endif
16
17using namespace std;
18using namespace TheISA;
19
20vector<System *> System::systemList;
21
22int System::numSystemsRunning = 0;
23
24System::System(Params *p)
25    : SimObject(p->name), physmem(p->physmem), numcpus(0),
26#if FULL_SYSTEM
27      memctrl(p->memctrl), init_param(p->init_param),
28#else
29      page_ptr(0),
30#endif
31      _params(p)
32{
33    // add self to global system list
34    systemList.push_back(this);
35
36#if FULL_SYSTEM
37    kernelSymtab = new SymbolTable;
38    debugSymbolTable = new SymbolTable;
39
40    /**
41     * Load the kernel code into memory
42     */
43    // Load kernel code
44    kernel = createObjectFile(params()->kernel_path);
45    if (kernel == NULL)
46        fatal("Could not load kernel file %s", params()->kernel_path);
47
48    // Load program sections into memory
49    kernel->loadSections(physmem, true);
50
51    // setup entry points
52    kernelStart = kernel->textBase();
53    kernelEnd = kernel->bssBase() + kernel->bssSize();
54    kernelEntry = kernel->entryPoint();
55
56    // load symbols
57    if (!kernel->loadGlobalSymbols(kernelSymtab))
58        panic("could not load kernel symbols\n");
59
60    if (!kernel->loadLocalSymbols(kernelSymtab))
61        panic("could not load kernel local symbols\n");
62
63    if (!kernel->loadGlobalSymbols(debugSymbolTable))
64        panic("could not load kernel symbols\n");
65
66    if (!kernel->loadLocalSymbols(debugSymbolTable))
67        panic("could not load kernel local symbols\n");
68
69    DPRINTF(Loader, "Kernel start = %#x\n", kernelStart);
70    DPRINTF(Loader, "Kernel end   = %#x\n", kernelEnd);
71    DPRINTF(Loader, "Kernel entry = %#x\n", kernelEntry);
72    DPRINTF(Loader, "Kernel loaded...\n");
73
74    kernelBinning = new Kernel::Binning(this);
75#endif // FULL_SYSTEM
76
77    // increment the number of running systms
78    numSystemsRunning++;
79}
80
81System::~System()
82{
83#if FULL_SYSTEM
84    delete kernelSymtab;
85    delete kernel;
86
87    delete kernelBinning;
88#else
89    panic("System::fixFuncEventAddr needs to be rewritten "
90          "to work with syscall emulation");
91#endif // FULL_SYSTEM}
92}
93
94#if FULL_SYSTEM
95
96
97int rgdb_wait = -1;
98
99#endif // FULL_SYSTEM
100
101int
102System::registerExecContext(ExecContext *xc, int id)
103{
104    if (id == -1) {
105        for (id = 0; id < execContexts.size(); id++) {
106            if (!execContexts[id])
107                break;
108        }
109    }
110
111    if (execContexts.size() <= id)
112        execContexts.resize(id + 1);
113
114    if (execContexts[id])
115        panic("Cannot have two CPUs with the same id (%d)\n", id);
116
117    execContexts[id] = xc;
118    numcpus++;
119
120#if FULL_SYSTEM
121    RemoteGDB *rgdb = new RemoteGDB(this, xc);
122    GDBListener *gdbl = new GDBListener(rgdb, 7000 + id);
123    gdbl->listen();
124    /**
125     * Uncommenting this line waits for a remote debugger to connect
126     * to the simulator before continuing.
127     */
128    if (rgdb_wait != -1 && rgdb_wait == id)
129        gdbl->accept();
130
131    if (remoteGDB.size() <= id) {
132        remoteGDB.resize(id + 1);
133    }
134
135    remoteGDB[id] = rgdb;
136#endif // FULL_SYSTEM
137
138    return id;
139}
140
141void
142System::startup()
143{
144    int i;
145    for (i = 0; i < execContexts.size(); i++)
146        execContexts[i]->activate(0);
147}
148
149void
150System::replaceExecContext(ExecContext *xc, int id)
151{
152    if (id >= execContexts.size()) {
153        panic("replaceExecContext: bad id, %d >= %d\n",
154              id, execContexts.size());
155    }
156
157    execContexts[id] = xc;
158#if FULL_SYSTEM
159    remoteGDB[id]->replaceExecContext(xc);
160#endif // FULL_SYSTEM
161}
162
163#if !FULL_SYSTEM
164Addr
165System::new_page()
166{
167    Addr return_addr = page_ptr << LogVMPageSize;
168    ++page_ptr;
169    return return_addr;
170}
171#endif
172
173void
174System::regStats()
175{
176#if FULL_SYSTEM
177    kernelBinning->regStats(name() + ".kern");
178#endif // FULL_SYSTEM
179}
180
181void
182System::serialize(ostream &os)
183{
184#if FULL_SYSTEM
185    kernelBinning->serialize(os);
186
187    kernelSymtab->serialize("kernel_symtab", os);
188#endif // FULL_SYSTEM
189}
190
191
192void
193System::unserialize(Checkpoint *cp, const string &section)
194{
195#if FULL_SYSTEM
196    kernelBinning->unserialize(cp, section);
197
198    kernelSymtab->unserialize("kernel_symtab", cp, section);
199#endif // FULL_SYSTEM
200}
201
202void
203System::printSystems()
204{
205    vector<System *>::iterator i = systemList.begin();
206    vector<System *>::iterator end = systemList.end();
207    for (; i != end; ++i) {
208        System *sys = *i;
209        cerr << "System " << sys->name() << ": " << hex << sys << endl;
210    }
211}
212
213extern "C"
214void
215printSystems()
216{
217    System::printSystems();
218}
219
220#if FULL_SYSTEM
221
222// In full system mode, only derived classes (e.g. AlphaLinuxSystem)
223// can be created directly.
224
225DEFINE_SIM_OBJECT_CLASS_NAME("System", System)
226
227#else
228
229BEGIN_DECLARE_SIM_OBJECT_PARAMS(System)
230
231    SimObjectParam<Memory *> physmem;
232
233END_DECLARE_SIM_OBJECT_PARAMS(System)
234
235BEGIN_INIT_SIM_OBJECT_PARAMS(System)
236
237    INIT_PARAM(physmem, "physical memory")
238
239END_INIT_SIM_OBJECT_PARAMS(System)
240
241CREATE_SIM_OBJECT(System)
242{
243    System::Params *p = new System::Params;
244    p->name = getInstanceName();
245    p->physmem = physmem;
246    return new System(p);
247}
248
249REGISTER_SIM_OBJECT("System", System)
250
251#endif
252