system.cc revision 869
1451SN/A/*
21762SN/A * Copyright (c) 2003 The Regents of The University of Michigan
3451SN/A * All rights reserved.
4451SN/A *
5451SN/A * Redistribution and use in source and binary forms, with or without
6451SN/A * modification, are permitted provided that the following conditions are
7451SN/A * met: redistributions of source code must retain the above copyright
8451SN/A * notice, this list of conditions and the following disclaimer;
9451SN/A * redistributions in binary form must reproduce the above copyright
10451SN/A * notice, this list of conditions and the following disclaimer in the
11451SN/A * documentation and/or other materials provided with the distribution;
12451SN/A * neither the name of the copyright holders nor the names of its
13451SN/A * contributors may be used to endorse or promote products derived from
14451SN/A * this software without specific prior written permission.
15451SN/A *
16451SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17451SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18451SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19451SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20451SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21451SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22451SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23451SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24451SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25451SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26451SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu */
282665Ssaidi@eecs.umich.edu
292665Ssaidi@eecs.umich.edu#include "base/loader/aout_object.hh"
302665Ssaidi@eecs.umich.edu#include "base/loader/elf_object.hh"
312665Ssaidi@eecs.umich.edu#include "base/loader/object_file.hh"
32451SN/A#include "base/loader/symtab.hh"
33451SN/A#include "base/remote_gdb.hh"
34885SN/A#include "base/trace.hh"
35885SN/A#include "cpu/exec_context.hh"
361040SN/A#include "cpu/base_cpu.hh"
371040SN/A#include "kern/linux/linux_events.hh"
381040SN/A#include "kern/linux/linux_system.hh"
391040SN/A#include "mem/functional_mem/memory_control.hh"
401040SN/A#include "mem/functional_mem/physical_memory.hh"
41885SN/A#include "sim/builder.hh"
42885SN/A#include "dev/platform.hh"
432212SN/A#include "targetarch/isa_traits.hh"
442212SN/A#include "targetarch/vtophys.hh"
453565Sgblack@eecs.umich.edu
462212SN/Aextern SymbolTable *debugSymbolTable;
472212SN/A
482158SN/Ausing namespace std;
491180SN/A
502680Sktlim@umich.eduLinuxSystem::LinuxSystem(const string _name, const uint64_t _init_param,
511717SN/A                         MemoryController *_memCtrl, PhysicalMemory *_physmem,
522212SN/A                         const string &kernel_path, const string &console_path,
531885SN/A                         const string &palcode, const string &boot_osflags,
542212SN/A                         const string &bootloader_path, const bool _bin,
552521SN/A                         const vector<string> &_binned_fns)
562521SN/A     : System(_name, _init_param, _memCtrl, _physmem, _bin, _binned_fns),
572036SN/A       bin(_bin), binned_fns(_binned_fns)
58451SN/A{
59451SN/A    kernelSymtab = new SymbolTable;
602212SN/A    consoleSymtab = new SymbolTable;
612212SN/A    bootloaderSymtab = new SymbolTable;
62451SN/A
632212SN/A    ObjectFile *kernel = createObjectFile(kernel_path);
642158SN/A    if (kernel == NULL)
65451SN/A        fatal("Could not load kernel file %s", kernel_path);
66451SN/A
671855SN/A    ObjectFile *console = createObjectFile(console_path);
681855SN/A    if (console == NULL)
691855SN/A        fatal("Could not load console file %s", console_path);
701855SN/A
711855SN/A    ObjectFile *bootloader = createObjectFile(bootloader_path);
721855SN/A    if (bootloader == NULL)
731855SN/A        fatal("Could not load bootloader file %s", bootloader_path);
741855SN/A
751855SN/A    if (!kernel->loadGlobalSymbols(kernelSymtab))
761855SN/A        panic("could not load kernel symbols\n");
771855SN/A    debugSymbolTable = kernelSymtab;
781855SN/A
791855SN/A    if (!kernel->loadLocalSymbols(kernelSymtab))
802521SN/A        panic("could not load kernel local symbols\n");
812548SN/A
82836SN/A    if (!console->loadGlobalSymbols(consoleSymtab))
83885SN/A        panic("could not load console symbols\n");
841070SN/A
851070SN/A    if (!bootloader->loadGlobalSymbols(bootloaderSymtab))
861070SN/A        panic("could not load bootloader symbols\n");
87885SN/A
882521SN/A    // Load pal file
892521SN/A    ObjectFile *pal = createObjectFile(palcode);
902521SN/A    if (pal == NULL)
91451SN/A        fatal("Could not load PALcode file %s", palcode);
92836SN/A    pal->loadSections(physmem, true);
93885SN/A
94943SN/A    // Load console file
95943SN/A    console->loadSections(physmem, true);
96943SN/A
97943SN/A    // Load kernel file
98943SN/A    kernel->loadSections(physmem, true);
992521SN/A    kernelStart = kernel->textBase();
1002521SN/A    kernelEnd = kernel->bssBase() + kernel->bssSize();
1012521SN/A    /* FIXME: entrypoint not in kernel, but in bootloader,
1021070SN/A       variable should be re-named appropriately */
103943SN/A    kernelEntry = kernel->entryPoint();
1041492SN/A
1051885SN/A
1061885SN/A    DPRINTF(Loader, "Kernel start = %#x\n"
107451SN/A            "Kernel end   = %#x\n"
1081885SN/A            "Kernel entry = %#x\n",
1091646SN/A            kernelStart, kernelEnd, kernelEntry);
1101885SN/A
1111885SN/A    DPRINTF(Loader, "Kernel loaded...\n");
1121492SN/A
1131646SN/A    // Load bootloader file
1141492SN/A    bootloader->loadSections(physmem, true);
115860SN/A    kernelEntry = bootloader->entryPoint();
116451SN/A    kernelStart = bootloader->textBase();
117885SN/A    DPRINTF(Loader, "Bootloader entry at %#x\n", kernelEntry);
1181895SN/A
1191070SN/A#ifdef DEBUG
1201070SN/A    kernelPanicEvent = new BreakPCEvent(&pcEventQueue, "kernel panic");
1211070SN/A    consolePanicEvent = new BreakPCEvent(&pcEventQueue, "console panic");
1221070SN/A#endif
123885SN/A
124848SN/A    skipIdeDelay50msEvent = new LinuxSkipIdeDelay50msEvent(&pcEventQueue,
1251885SN/A                                                     "ide_delay_50ms");
1261885SN/A
1271885SN/A    skipDelayLoopEvent = new LinuxSkipDelayLoopEvent(&pcEventQueue,
1281885SN/A                                                     "calibrate_delay");
1291885SN/A
1301885SN/A    skipCacheProbeEvent = new LinuxSkipFuncEvent(&pcEventQueue, "determine_cpu_caches");
1311885SN/A
1321885SN/A    Addr addr = 0;
1331885SN/A
1344741Sstever@eecs.umich.edu    if (kernelSymtab->findAddress("est_cycle_freq", addr)) {
1354741Sstever@eecs.umich.edu        Addr paddr = vtophys(physmem, addr);
1364741Sstever@eecs.umich.edu        uint8_t *est_cycle_frequency =
1374741Sstever@eecs.umich.edu            physmem->dma_addr(paddr, sizeof(uint64_t));
1384741Sstever@eecs.umich.edu
1394741Sstever@eecs.umich.edu        if (est_cycle_frequency)
1401885SN/A            *(uint64_t *)est_cycle_frequency = ticksPerSecond;
1411885SN/A    }
1421885SN/A
1431885SN/A    if (kernelSymtab->findAddress("aic7xxx_no_reset", addr)) {
1441657SN/A        Addr paddr = vtophys(physmem, addr);
145451SN/A        uint8_t *aic7xxx_no_reset =
146451SN/A            physmem->dma_addr(paddr, sizeof(uint32_t));
1472212SN/A
148451SN/A        if (aic7xxx_no_reset) {
1491492SN/A            *(uint32_t *)aic7xxx_no_reset = 1;
150451SN/A        }
1511070SN/A    }
152869SN/A
153869SN/A    if (consoleSymtab->findAddress("env_booted_osflags", addr)) {
154869SN/A        Addr paddr = vtophys(physmem, addr);
1551070SN/A        char *osflags = (char *)physmem->dma_addr(paddr, sizeof(uint32_t));
1561070SN/A
1571082SN/A        if (osflags)
158451SN/A            strcpy(osflags, boot_osflags.c_str());
159451SN/A    }
160882SN/A
161803SN/A    if (consoleSymtab->findAddress("xxm_rpb", addr)) {
1622680Sktlim@umich.edu        Addr paddr = vtophys(physmem, addr);
163803SN/A        char *hwprb = (char *)physmem->dma_addr(paddr, sizeof(uint64_t));
164803SN/A
165803SN/A        if (hwprb) {
1662680Sktlim@umich.edu            *(uint64_t*)(hwprb+0x50) = 34;      // Tsunami
1671634SN/A            *(uint64_t*)(hwprb+0x58) = (1<<10);
1682684Ssaidi@eecs.umich.edu        }
1692684Ssaidi@eecs.umich.edu        else
1702684Ssaidi@eecs.umich.edu            panic("could not translate hwprb addr to set system type/variation\n");
1712684Ssaidi@eecs.umich.edu
1722684Ssaidi@eecs.umich.edu    } else
173803SN/A        panic("could not find hwprb to set system type/variation\n");
174803SN/A
175803SN/A#ifdef DEBUG
1762212SN/A    if (kernelSymtab->findAddress("panic", addr))
1771885SN/A        kernelPanicEvent->schedule(addr);
1782680Sktlim@umich.edu    else
1791885SN/A        panic("could not find kernel symbol \'panic\'");
1802680Sktlim@umich.edu
1811885SN/A    if (consoleSymtab->findAddress("panic", addr))
1822680Sktlim@umich.edu        consolePanicEvent->schedule(addr);
1831885SN/A#endif
1841885SN/A
1851885SN/A    if (kernelSymtab->findAddress("ide_delay_50ms", addr))
1862680Sktlim@umich.edu        skipIdeDelay50msEvent->schedule(addr+8);
1871885SN/A
1882680Sktlim@umich.edu    if (kernelSymtab->findAddress("calibrate_delay", addr))
1891885SN/A        skipDelayLoopEvent->schedule(addr+8);
1901885SN/A
1911885SN/A    if (kernelSymtab->findAddress("determine_cpu_caches", addr))
1921885SN/A        skipCacheProbeEvent->schedule(addr+8);
1931885SN/A}
1944762Snate@binkert.org
1954762Snate@binkert.orgLinuxSystem::~LinuxSystem()
196451SN/A{
1974762Snate@binkert.org    delete kernel;
198451SN/A    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