system.cc revision 860
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 "base/loader/aout_object.hh"
30#include "base/loader/elf_object.hh"
31#include "base/loader/object_file.hh"
32#include "base/loader/symtab.hh"
33#include "base/remote_gdb.hh"
34#include "base/trace.hh"
35#include "cpu/exec_context.hh"
36#include "cpu/base_cpu.hh"
37#include "kern/linux/linux_events.hh"
38#include "kern/linux/linux_system.hh"
39#include "mem/functional_mem/memory_control.hh"
40#include "mem/functional_mem/physical_memory.hh"
41#include "sim/builder.hh"
42#include "dev/platform.hh"
43#include "targetarch/isa_traits.hh"
44#include "targetarch/vtophys.hh"
45
46extern SymbolTable *debugSymbolTable;
47
48//un-comment this to see the state of call stack when it changes.
49//#define SW_DEBUG
50
51using namespace std;
52
53LinuxSystem::LinuxSystem(const string _name, const uint64_t _init_param,
54                         MemoryController *_memCtrl, PhysicalMemory *_physmem,
55                         const string &kernel_path, const string &console_path,
56                         const string &palcode, const string &boot_osflags,
57                         const string &bootloader_path, const bool _bin)
58     : System(_name, _init_param, _memCtrl, _physmem, _bin), bin(_bin)
59{
60    kernelSymtab = new SymbolTable;
61    consoleSymtab = new SymbolTable;
62    bootloaderSymtab = new SymbolTable;
63
64    ObjectFile *kernel = createObjectFile(kernel_path);
65    if (kernel == NULL)
66        fatal("Could not load kernel file %s", kernel_path);
67
68    ObjectFile *console = createObjectFile(console_path);
69    if (console == NULL)
70        fatal("Could not load console file %s", console_path);
71
72    ObjectFile *bootloader = createObjectFile(bootloader_path);
73    if (bootloader == NULL)
74        fatal("Could not load bootloader file %s", bootloader_path);
75
76    if (!kernel->loadGlobalSymbols(kernelSymtab))
77        panic("could not load kernel symbols\n");
78    debugSymbolTable = kernelSymtab;
79
80    if (!kernel->loadLocalSymbols(kernelSymtab))
81        panic("could not load kernel local symbols\n");
82
83    if (!console->loadGlobalSymbols(consoleSymtab))
84        panic("could not load console symbols\n");
85
86    if (!bootloader->loadGlobalSymbols(bootloaderSymtab))
87        panic("could not load bootloader symbols\n");
88
89    // Load pal file
90    ObjectFile *pal = createObjectFile(palcode);
91    if (pal == NULL)
92        fatal("Could not load PALcode file %s", palcode);
93    pal->loadSections(physmem, true);
94
95    // Load console file
96    console->loadSections(physmem, true);
97
98    // Load kernel file
99    kernel->loadSections(physmem, true);
100    kernelStart = kernel->textBase();
101    kernelEnd = kernel->bssBase() + kernel->bssSize();
102    /* FIXME: entrypoint not in kernel, but in bootloader,
103       variable should be re-named appropriately */
104    kernelEntry = kernel->entryPoint();
105
106
107    DPRINTF(Loader, "Kernel start = %#x\n"
108            "Kernel end   = %#x\n"
109            "Kernel entry = %#x\n",
110            kernelStart, kernelEnd, kernelEntry);
111
112    DPRINTF(Loader, "Kernel loaded...\n");
113
114    // Load bootloader file
115    bootloader->loadSections(physmem, true);
116    kernelEntry = bootloader->entryPoint();
117    kernelStart = bootloader->textBase();
118    DPRINTF(Loader, "Bootloader entry at %#x\n", kernelEntry);
119
120#ifdef DEBUG
121    kernelPanicEvent = new BreakPCEvent(&pcEventQueue, "kernel panic");
122    consolePanicEvent = new BreakPCEvent(&pcEventQueue, "console panic");
123#endif
124
125    badaddrEvent = new LinuxBadAddrEvent(&pcEventQueue, "badaddr");
126    skipPowerStateEvent = new LinuxSkipFuncEvent(&pcEventQueue,
127                                            "tl_v48_capture_power_state");
128    skipScavengeBootEvent = new LinuxSkipFuncEvent(&pcEventQueue,
129                                              "pmap_scavenge_boot");
130    printfEvent = new LinuxPrintfEvent(&pcEventQueue, "printf");
131
132    skipIdeDelay50msEvent = new LinuxSkipIdeDelay50msEvent(&pcEventQueue,
133                                                     "ide_delay_50ms");
134
135    skipDelayLoopEvent = new LinuxSkipDelayLoopEvent(&pcEventQueue,
136                                                     "calibrate_delay");
137
138    skipCacheProbeEvent = new LinuxSkipFuncEvent(&pcEventQueue, "determine_cpu_caches");
139
140   /* debugPrintfEvent = new DebugPrintfEvent(&pcEventQueue,
141                                            "debug_printf", false);
142    debugPrintfrEvent = new DebugPrintfEvent(&pcEventQueue,
143                                             "debug_printfr", true);
144    dumpMbufEvent = new DumpMbufEvent(&pcEventQueue, "dump_mbuf");
145*/
146
147    Addr addr = 0;
148
149    if (kernelSymtab->findAddress("est_cycle_freq", addr)) {
150        Addr paddr = vtophys(physmem, addr);
151        uint8_t *est_cycle_frequency =
152            physmem->dma_addr(paddr, sizeof(uint64_t));
153
154        if (est_cycle_frequency)
155            *(uint64_t *)est_cycle_frequency = ticksPerSecond;
156    }
157
158    if (kernelSymtab->findAddress("aic7xxx_no_reset", addr)) {
159        Addr paddr = vtophys(physmem, addr);
160        uint8_t *aic7xxx_no_reset =
161            physmem->dma_addr(paddr, sizeof(uint32_t));
162
163        if (aic7xxx_no_reset) {
164            *(uint32_t *)aic7xxx_no_reset = 1;
165        }
166    }
167
168    if (consoleSymtab->findAddress("env_booted_osflags", addr)) {
169        Addr paddr = vtophys(physmem, addr);
170        char *osflags = (char *)physmem->dma_addr(paddr, sizeof(uint32_t));
171
172        if (osflags)
173            strcpy(osflags, boot_osflags.c_str());
174    }
175
176    if (consoleSymtab->findAddress("xxm_rpb", addr)) {
177        Addr paddr = vtophys(physmem, addr);
178        char *hwprb = (char *)physmem->dma_addr(paddr, sizeof(uint64_t));
179
180        if (hwprb) {
181            *(uint64_t*)(hwprb+0x50) = 34;      // Tsunami
182            *(uint64_t*)(hwprb+0x58) = (1<<10);
183        }
184        else
185            panic("could not translate hwprb addr to set system type/variation\n");
186
187    } else
188        panic("could not find hwprb to set system type/variation\n");
189
190#ifdef DEBUG
191    if (kernelSymtab->findAddress("panic", addr))
192        kernelPanicEvent->schedule(addr);
193    else
194        panic("could not find kernel symbol \'panic\'");
195
196    if (consoleSymtab->findAddress("panic", addr))
197        consolePanicEvent->schedule(addr);
198#endif
199
200    if (kernelSymtab->findAddress("badaddr", addr))
201        badaddrEvent->schedule(addr);
202   // else
203        //panic("could not find kernel symbol \'badaddr\'");
204
205    if (kernelSymtab->findAddress("tl_v48_capture_power_state", addr))
206        skipPowerStateEvent->schedule(addr);
207
208    if (kernelSymtab->findAddress("pmap_scavenge_boot", addr))
209        skipScavengeBootEvent->schedule(addr);
210
211    if (kernelSymtab->findAddress("ide_delay_50ms", addr))
212        skipIdeDelay50msEvent->schedule(addr+8);
213
214    if (kernelSymtab->findAddress("calibrate_delay", addr))
215        skipDelayLoopEvent->schedule(addr+8);
216
217    if (kernelSymtab->findAddress("determine_cpu_caches", addr))
218        skipCacheProbeEvent->schedule(addr+8);
219
220#if TRACING_ON
221    if (kernelSymtab->findAddress("printk", addr))
222        printfEvent->schedule(addr);
223
224    if (kernelSymtab->findAddress("m5printf", addr))
225        debugPrintfEvent->schedule(addr);
226
227    if (kernelSymtab->findAddress("m5printfr", addr))
228        debugPrintfrEvent->schedule(addr);
229
230    if (kernelSymtab->findAddress("m5_dump_mbuf", addr))
231        dumpMbufEvent->schedule(addr);
232#endif
233}
234
235LinuxSystem::~LinuxSystem()
236{
237    delete kernel;
238    delete console;
239
240    delete kernelSymtab;
241    delete consoleSymtab;
242    delete bootloaderSymtab;
243
244    delete kernelPanicEvent;
245    delete consolePanicEvent;
246    delete badaddrEvent;
247    delete skipPowerStateEvent;
248    delete skipScavengeBootEvent;
249    delete printfEvent;
250    /*delete debugPrintfEvent;
251    delete debugPrintfrEvent;
252    delete dumpMbufEvent;
253*/
254}
255
256void
257LinuxSystem::setDelayLoop(ExecContext *xc)
258{
259    Addr addr = 0;
260    if (kernelSymtab->findAddress("loops_per_jiffy", addr)) {
261        Addr paddr = vtophys(physmem, addr);
262
263        uint8_t *loops_per_jiffy =
264            physmem->dma_addr(paddr, sizeof(uint32_t));
265
266        Tick cpuFreq = xc->cpu->getFreq();
267        Tick intrFreq = platform->interrupt_frequency;
268        *(uint32_t *)loops_per_jiffy =
269            (uint32_t)((cpuFreq / intrFreq) * 0.9988);
270    }
271}
272
273int
274LinuxSystem::registerExecContext(ExecContext *xc)
275{
276    int xcIndex = System::registerExecContext(xc);
277
278    if (xcIndex == 0) {
279        // activate with zero delay so that we start ticking right
280        // away on cycle 0
281        xc->activate(0);
282    }
283
284    RemoteGDB *rgdb = new RemoteGDB(this, xc);
285    GDBListener *gdbl = new GDBListener(rgdb, 7000 + xcIndex);
286    gdbl->listen();
287//    gdbl->accept();
288
289    if (remoteGDB.size() <= xcIndex) {
290        remoteGDB.resize(xcIndex+1);
291    }
292
293    remoteGDB[xcIndex] = rgdb;
294
295    return xcIndex;
296}
297
298
299void
300LinuxSystem::replaceExecContext(ExecContext *xc, int xcIndex)
301{
302    System::replaceExecContext(xcIndex, xc);
303    remoteGDB[xcIndex]->replaceExecContext(xc);
304}
305
306bool
307LinuxSystem::breakpoint()
308{
309    return remoteGDB[0]->trap(ALPHA_KENTRY_IF);
310}
311
312void
313LinuxSystem::populateMap(std::string callee, std::string caller)
314{
315    multimap<const string, string>::const_iterator i;
316    i = callerMap.insert(make_pair(callee, caller));
317    assert(i != callerMap.end() && "should not fail populating callerMap");
318}
319
320bool
321LinuxSystem::findCaller(std::string callee, std::string caller) const
322{
323    typedef multimap<const std::string, std::string>::const_iterator iter;
324    pair<iter, iter> range;
325
326    range = callerMap.equal_range(callee);
327    for (iter i = range.first; i != range.second; ++i) {
328        if ((*i).second == caller)
329            return true;
330    }
331    return false;
332}
333
334void
335LinuxSystem::dumpState(ExecContext *xc) const
336{
337#ifndef SW_DEBUG
338    return;
339#endif
340    if (xc->swCtx) {
341        stack<fnCall *> copy(xc->swCtx->callStack);
342        if (copy.empty())
343            return;
344        cprintf("xc->swCtx:\n");
345        fnCall *top;
346        cprintf("||   call: %d\n",xc->swCtx->calls);
347        for (top = copy.top(); !copy.empty(); copy.pop() ) {
348            top = copy.top();
349            cprintf("||  %13s : %s \n", top->name, top->myBin->name());
350        }
351    }
352}
353
354BEGIN_DECLARE_SIM_OBJECT_PARAMS(LinuxSystem)
355
356    Param<bool> bin;
357    SimObjectParam<MemoryController *> mem_ctl;
358    SimObjectParam<PhysicalMemory *> physmem;
359    Param<uint64_t> init_param;
360
361    Param<string> kernel_code;
362    Param<string> console_code;
363    Param<string> pal_code;
364    Param<string> boot_osflags;
365    Param<string> bootloader_code;
366
367END_DECLARE_SIM_OBJECT_PARAMS(LinuxSystem)
368
369BEGIN_INIT_SIM_OBJECT_PARAMS(LinuxSystem)
370
371
372    INIT_PARAM_DFLT(bin, "is this system to be binned", false),
373    INIT_PARAM(mem_ctl, "memory controller"),
374    INIT_PARAM(physmem, "phsyical memory"),
375    INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0),
376    INIT_PARAM(kernel_code, "file that contains the code"),
377    INIT_PARAM(console_code, "file that contains the console code"),
378    INIT_PARAM(pal_code, "file that contains palcode"),
379    INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot",
380                                   "a"),
381    INIT_PARAM(bootloader_code, "file that contains the bootloader")
382
383
384END_INIT_SIM_OBJECT_PARAMS(LinuxSystem)
385
386CREATE_SIM_OBJECT(LinuxSystem)
387{
388    LinuxSystem *sys = new LinuxSystem(getInstanceName(), init_param, mem_ctl,
389                                       physmem, kernel_code, console_code,
390                                       pal_code, boot_osflags, bootloader_code, bin);
391
392    return sys;
393}
394
395REGISTER_SIM_OBJECT("LinuxSystem", LinuxSystem)
396