system.cc revision 869
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
48using namespace std;
49
50LinuxSystem::LinuxSystem(const string _name, const uint64_t _init_param,
51                         MemoryController *_memCtrl, PhysicalMemory *_physmem,
52                         const string &kernel_path, const string &console_path,
53                         const string &palcode, const string &boot_osflags,
54                         const string &bootloader_path, const bool _bin,
55                         const vector<string> &_binned_fns)
56     : System(_name, _init_param, _memCtrl, _physmem, _bin, _binned_fns),
57       bin(_bin), binned_fns(_binned_fns)
58{
59    kernelSymtab = new SymbolTable;
60    consoleSymtab = new SymbolTable;
61    bootloaderSymtab = new SymbolTable;
62
63    ObjectFile *kernel = createObjectFile(kernel_path);
64    if (kernel == NULL)
65        fatal("Could not load kernel file %s", kernel_path);
66
67    ObjectFile *console = createObjectFile(console_path);
68    if (console == NULL)
69        fatal("Could not load console file %s", console_path);
70
71    ObjectFile *bootloader = createObjectFile(bootloader_path);
72    if (bootloader == NULL)
73        fatal("Could not load bootloader file %s", bootloader_path);
74
75    if (!kernel->loadGlobalSymbols(kernelSymtab))
76        panic("could not load kernel symbols\n");
77    debugSymbolTable = kernelSymtab;
78
79    if (!kernel->loadLocalSymbols(kernelSymtab))
80        panic("could not load kernel local symbols\n");
81
82    if (!console->loadGlobalSymbols(consoleSymtab))
83        panic("could not load console symbols\n");
84
85    if (!bootloader->loadGlobalSymbols(bootloaderSymtab))
86        panic("could not load bootloader symbols\n");
87
88    // Load pal file
89    ObjectFile *pal = createObjectFile(palcode);
90    if (pal == NULL)
91        fatal("Could not load PALcode file %s", palcode);
92    pal->loadSections(physmem, true);
93
94    // Load console file
95    console->loadSections(physmem, true);
96
97    // Load kernel file
98    kernel->loadSections(physmem, true);
99    kernelStart = kernel->textBase();
100    kernelEnd = kernel->bssBase() + kernel->bssSize();
101    /* FIXME: entrypoint not in kernel, but in bootloader,
102       variable should be re-named appropriately */
103    kernelEntry = kernel->entryPoint();
104
105
106    DPRINTF(Loader, "Kernel start = %#x\n"
107            "Kernel end   = %#x\n"
108            "Kernel entry = %#x\n",
109            kernelStart, kernelEnd, kernelEntry);
110
111    DPRINTF(Loader, "Kernel loaded...\n");
112
113    // Load bootloader file
114    bootloader->loadSections(physmem, true);
115    kernelEntry = bootloader->entryPoint();
116    kernelStart = bootloader->textBase();
117    DPRINTF(Loader, "Bootloader entry at %#x\n", kernelEntry);
118
119#ifdef DEBUG
120    kernelPanicEvent = new BreakPCEvent(&pcEventQueue, "kernel panic");
121    consolePanicEvent = new BreakPCEvent(&pcEventQueue, "console panic");
122#endif
123
124    skipIdeDelay50msEvent = new LinuxSkipIdeDelay50msEvent(&pcEventQueue,
125                                                     "ide_delay_50ms");
126
127    skipDelayLoopEvent = new LinuxSkipDelayLoopEvent(&pcEventQueue,
128                                                     "calibrate_delay");
129
130    skipCacheProbeEvent = new LinuxSkipFuncEvent(&pcEventQueue, "determine_cpu_caches");
131
132    Addr addr = 0;
133
134    if (kernelSymtab->findAddress("est_cycle_freq", addr)) {
135        Addr paddr = vtophys(physmem, addr);
136        uint8_t *est_cycle_frequency =
137            physmem->dma_addr(paddr, sizeof(uint64_t));
138
139        if (est_cycle_frequency)
140            *(uint64_t *)est_cycle_frequency = ticksPerSecond;
141    }
142
143    if (kernelSymtab->findAddress("aic7xxx_no_reset", addr)) {
144        Addr paddr = vtophys(physmem, addr);
145        uint8_t *aic7xxx_no_reset =
146            physmem->dma_addr(paddr, sizeof(uint32_t));
147
148        if (aic7xxx_no_reset) {
149            *(uint32_t *)aic7xxx_no_reset = 1;
150        }
151    }
152
153    if (consoleSymtab->findAddress("env_booted_osflags", addr)) {
154        Addr paddr = vtophys(physmem, addr);
155        char *osflags = (char *)physmem->dma_addr(paddr, sizeof(uint32_t));
156
157        if (osflags)
158            strcpy(osflags, boot_osflags.c_str());
159    }
160
161    if (consoleSymtab->findAddress("xxm_rpb", addr)) {
162        Addr paddr = vtophys(physmem, addr);
163        char *hwprb = (char *)physmem->dma_addr(paddr, sizeof(uint64_t));
164
165        if (hwprb) {
166            *(uint64_t*)(hwprb+0x50) = 34;      // Tsunami
167            *(uint64_t*)(hwprb+0x58) = (1<<10);
168        }
169        else
170            panic("could not translate hwprb addr to set system type/variation\n");
171
172    } else
173        panic("could not find hwprb to set system type/variation\n");
174
175#ifdef DEBUG
176    if (kernelSymtab->findAddress("panic", addr))
177        kernelPanicEvent->schedule(addr);
178    else
179        panic("could not find kernel symbol \'panic\'");
180
181    if (consoleSymtab->findAddress("panic", addr))
182        consolePanicEvent->schedule(addr);
183#endif
184
185    if (kernelSymtab->findAddress("ide_delay_50ms", addr))
186        skipIdeDelay50msEvent->schedule(addr+8);
187
188    if (kernelSymtab->findAddress("calibrate_delay", addr))
189        skipDelayLoopEvent->schedule(addr+8);
190
191    if (kernelSymtab->findAddress("determine_cpu_caches", addr))
192        skipCacheProbeEvent->schedule(addr+8);
193}
194
195LinuxSystem::~LinuxSystem()
196{
197    delete kernel;
198    delete console;
199
200    delete kernelSymtab;
201    delete consoleSymtab;
202    delete bootloaderSymtab;
203
204    delete kernelPanicEvent;
205    delete consolePanicEvent;
206    delete skipIdeDelay50msEvent;
207    delete skipDelayLoopEvent;
208    delete skipCacheProbeEvent;
209}
210
211void
212LinuxSystem::setDelayLoop(ExecContext *xc)
213{
214    Addr addr = 0;
215    if (kernelSymtab->findAddress("loops_per_jiffy", addr)) {
216        Addr paddr = vtophys(physmem, addr);
217
218        uint8_t *loops_per_jiffy =
219            physmem->dma_addr(paddr, sizeof(uint32_t));
220
221        Tick cpuFreq = xc->cpu->getFreq();
222        Tick intrFreq = platform->interrupt_frequency;
223        *(uint32_t *)loops_per_jiffy =
224            (uint32_t)((cpuFreq / intrFreq) * 0.9988);
225    }
226}
227
228int
229LinuxSystem::registerExecContext(ExecContext *xc)
230{
231    int xcIndex = System::registerExecContext(xc);
232
233    if (xcIndex == 0) {
234        // activate with zero delay so that we start ticking right
235        // away on cycle 0
236        xc->activate(0);
237    }
238
239    RemoteGDB *rgdb = new RemoteGDB(this, xc);
240    GDBListener *gdbl = new GDBListener(rgdb, 7000 + xcIndex);
241    gdbl->listen();
242//    gdbl->accept();
243
244    if (remoteGDB.size() <= xcIndex) {
245        remoteGDB.resize(xcIndex+1);
246    }
247
248    remoteGDB[xcIndex] = rgdb;
249
250    return xcIndex;
251}
252
253
254void
255LinuxSystem::replaceExecContext(ExecContext *xc, int xcIndex)
256{
257    System::replaceExecContext(xcIndex, xc);
258    remoteGDB[xcIndex]->replaceExecContext(xc);
259}
260
261bool
262LinuxSystem::breakpoint()
263{
264    return remoteGDB[0]->trap(ALPHA_KENTRY_IF);
265}
266
267BEGIN_DECLARE_SIM_OBJECT_PARAMS(LinuxSystem)
268
269    Param<bool> bin;
270    SimObjectParam<MemoryController *> mem_ctl;
271    SimObjectParam<PhysicalMemory *> physmem;
272    Param<uint64_t> init_param;
273
274    Param<string> kernel_code;
275    Param<string> console_code;
276    Param<string> pal_code;
277    Param<string> boot_osflags;
278    Param<string> bootloader_code;
279    VectorParam<string> binned_fns;
280
281END_DECLARE_SIM_OBJECT_PARAMS(LinuxSystem)
282
283BEGIN_INIT_SIM_OBJECT_PARAMS(LinuxSystem)
284
285
286    INIT_PARAM_DFLT(bin, "is this system to be binned", false),
287    INIT_PARAM(mem_ctl, "memory controller"),
288    INIT_PARAM(physmem, "phsyical memory"),
289    INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0),
290    INIT_PARAM(kernel_code, "file that contains the code"),
291    INIT_PARAM(console_code, "file that contains the console code"),
292    INIT_PARAM(pal_code, "file that contains palcode"),
293    INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot",
294                                   "a"),
295    INIT_PARAM(bootloader_code, "file that contains the bootloader"),
296    INIT_PARAM(binned_fns, "functions to be broken down and binned")
297
298
299END_INIT_SIM_OBJECT_PARAMS(LinuxSystem)
300
301CREATE_SIM_OBJECT(LinuxSystem)
302{
303    LinuxSystem *sys = new LinuxSystem(getInstanceName(), init_param, mem_ctl,
304                                       physmem, kernel_code, console_code,
305                                       pal_code, boot_osflags, bootloader_code,
306                                       bin, binned_fns);
307
308    return sys;
309}
310
311REGISTER_SIM_OBJECT("LinuxSystem", LinuxSystem)
312