system.cc revision 2
1/*
2 * Copyright (c) 2003 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include "kernel_loader.hh"
30#include "exec_context.hh"
31#include "object_file.hh"
32#include "memory_control.hh"
33#include "physical_memory.hh"
34#include "symtab.hh"
35#include "remote_gdb.hh"
36#include "vtophys.hh"
37#include "system.hh"
38#include "trace.hh"
39
40using namespace std;
41
42vector<System *> System::systemList;
43
44int System::numSystemsRunning = 0;
45
46System::System(const std::string _name,
47               MemoryController *_memCtrl,
48               PhysicalMemory *_physmem,
49               const std::string &kernel_path,
50               const std::string &console_path,
51               const std::string &palcode,
52               const std::string &boot_osflags)
53    : SimObject(_name),
54      kernel_panic_event(&pcEventQueue, "kernel panic"),
55      console_panic_event(&pcEventQueue, "console panic"),
56      badaddr_event(&pcEventQueue, "badaddr"),
57      skip_power_state(&pcEventQueue, "tl_v48_capture_power_state"),
58      skip_scavenge_boot(&pcEventQueue, "pmap_scavenge_boot"),
59      printf_event(&pcEventQueue, "printf"),
60      debug_printf_event(&pcEventQueue, "debug_printf", false),
61      debug_printfr_event(&pcEventQueue, "debug_printfr", true),
62      dump_mbuf_event(&pcEventQueue, "dump_mbuf"),
63      memCtrl(_memCtrl),
64      physmem(_physmem),
65      remoteGDB(NULL),
66      gdbListen(NULL)
67{
68    kernelSymtab = new SymbolTable;
69    consoleSymtab = new SymbolTable;
70
71    EcoffObject kernel(kernel_path);
72    EcoffObject console(console_path);
73
74    if (!kernel.loadGlobals(kernelSymtab))
75        panic("could not load kernel symbols\n");
76
77    if (!console.loadGlobals(consoleSymtab))
78        panic("could not load console symbols\n");
79
80    // Load pal file
81    loadPal(palcode, physmem, PAL_BASE);
82
83    // copy of initial reg file contents
84    initRegs = new RegFile;
85    memset(initRegs, 0, sizeof(RegFile));
86
87    // Load console file
88    loadKernel(console_path, physmem);
89
90    // Load kernel file
91    loadKernel(kernel_path, physmem, initRegs,
92               &kernelStart, &kernelEnd, &kernelEntry);
93
94    DPRINTF(Loader, "Kernel loaded...\n");
95
96#ifdef FULL_SYSTEM
97    Addr addr = 0;
98
99    for(int i = 0; i < 12/*MAX_CPUS*/; i++)
100        xc_array[i] = (ExecContext *) 0;
101
102    num_cpus = 0;
103
104    if (kernelSymtab->findAddress("enable_async_printf", addr)) {
105        Addr paddr = vtophys(physmem, addr);
106        uint8_t *enable_async_printf =
107            physmem->dma_addr(paddr, sizeof(uint32_t));
108
109        if (enable_async_printf)
110            *(uint32_t *)enable_async_printf = 0;
111    }
112
113    if (consoleSymtab->findAddress("env_booted_osflags", addr)) {
114        Addr paddr = vtophys(physmem, addr);
115        char *osflags = (char *)physmem->dma_addr(paddr, sizeof(uint32_t));
116
117        if (osflags)
118            strcpy(osflags, boot_osflags.c_str());
119    }
120
121    if (kernelSymtab->findAddress("panic", addr))
122        kernel_panic_event.schedule(addr);
123    else
124        panic("could not find kernel symbol \'panic\'");
125
126    if (consoleSymtab->findAddress("panic", addr))
127        console_panic_event.schedule(addr);
128
129    if (kernelSymtab->findAddress("badaddr", addr))
130        badaddr_event.schedule(addr);
131    else
132        panic("could not find kernel symbol \'badaddr\'");
133
134    if (kernelSymtab->findAddress("tl_v48_capture_power_state", addr))
135        skip_power_state.schedule(addr);
136
137    if (kernelSymtab->findAddress("pmap_scavenge_boot", addr))
138        skip_scavenge_boot.schedule(addr);
139
140#if TRACING_ON
141    if (kernelSymtab->findAddress("printf", addr))
142        printf_event.schedule(addr);
143
144    if (kernelSymtab->findAddress("m5printf", addr))
145        debug_printf_event.schedule(addr);
146
147    if (kernelSymtab->findAddress("m5printfr", addr))
148        debug_printfr_event.schedule(addr);
149
150    if (kernelSymtab->findAddress("m5_dump_mbuf", addr))
151        dump_mbuf_event.schedule(addr);
152#endif
153
154#endif
155
156    // add self to global system list
157    systemList.push_back(this);
158
159    numSystemsRunning++;
160}
161
162
163System::~System()
164{
165    delete kernelSymtab;
166    delete consoleSymtab;
167    delete initRegs;
168}
169
170
171void
172System::initBootContext(ExecContext *xc)
173{
174    xc->regs = *initRegs;
175
176    remoteGDB = new RemoteGDB(this, xc);
177    gdbListen = new GDBListener(remoteGDB, 7000);
178    gdbListen->listen();
179
180    // Reset the system
181    //
182    TheISA::init(physmem, &xc->regs);
183}
184
185
186void
187System::registerExecContext(ExecContext *xc)
188{
189    if (num_cpus == 12/*MAX_CPUS*/)
190        panic("Too many CPU's\n");
191    xc_array[xc->cpu_id] = xc;
192    num_cpus++;
193}
194
195
196void
197System::printSystems()
198{
199    vector<System *>::iterator i = systemList.begin();
200    vector<System *>::iterator end = systemList.end();
201    for (; i != end; ++i) {
202        System *sys = *i;
203        cerr << "System " << sys->name() << ": " << hex << sys << endl;
204    }
205}
206
207
208extern "C"
209void
210printSystems()
211{
212    System::printSystems();
213}
214
215
216BEGIN_DECLARE_SIM_OBJECT_PARAMS(System)
217
218    SimObjectParam<MemoryController *> mem_ctl;
219    SimObjectParam<PhysicalMemory *> physmem;
220
221    Param<string> kernel_code;
222    Param<string> console_code;
223    Param<string> pal_code;
224    Param<string> boot_osflags;
225
226END_DECLARE_SIM_OBJECT_PARAMS(System)
227
228BEGIN_INIT_SIM_OBJECT_PARAMS(System)
229
230    INIT_PARAM(mem_ctl, "memory controller"),
231    INIT_PARAM(physmem, "phsyical memory"),
232    INIT_PARAM(kernel_code, "file that contains the kernel code"),
233    INIT_PARAM(console_code, "file that contains the console code"),
234    INIT_PARAM(pal_code, "file that contains palcode"),
235    INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot",
236                    "a")
237
238END_INIT_SIM_OBJECT_PARAMS(System)
239
240
241CREATE_SIM_OBJECT(System)
242{
243    System *sys = new System(getInstanceName(), mem_ctl, physmem,
244                             kernel_code, console_code, pal_code,
245                             boot_osflags);
246
247    return sys;
248}
249
250REGISTER_SIM_OBJECT("System", System)
251