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