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