system.cc revision 882
19401SAndreas.Sandberg@ARM.com/*
29401SAndreas.Sandberg@ARM.com * Copyright (c) 2003 The Regents of The University of Michigan
39401SAndreas.Sandberg@ARM.com * All rights reserved.
49401SAndreas.Sandberg@ARM.com *
59401SAndreas.Sandberg@ARM.com * Redistribution and use in source and binary forms, with or without
69401SAndreas.Sandberg@ARM.com * modification, are permitted provided that the following conditions are
79401SAndreas.Sandberg@ARM.com * met: redistributions of source code must retain the above copyright
89401SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer;
99401SAndreas.Sandberg@ARM.com * redistributions in binary form must reproduce the above copyright
109401SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer in the
119401SAndreas.Sandberg@ARM.com * documentation and/or other materials provided with the distribution;
129401SAndreas.Sandberg@ARM.com * neither the name of the copyright holders nor the names of its
134977Ssaidi@eecs.umich.edu * contributors may be used to endorse or promote products derived from
142997Sstever@eecs.umich.edu * this software without specific prior written permission.
152997Sstever@eecs.umich.edu *
162997Sstever@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172997Sstever@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182997Sstever@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192997Sstever@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202997Sstever@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212997Sstever@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222997Sstever@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232997Sstever@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242997Sstever@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252997Sstever@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262997Sstever@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272997Sstever@eecs.umich.edu */
282997Sstever@eecs.umich.edu
292997Sstever@eecs.umich.edu#include "base/loader/aout_object.hh"
302997Sstever@eecs.umich.edu#include "base/loader/elf_object.hh"
312997Sstever@eecs.umich.edu#include "base/loader/object_file.hh"
322997Sstever@eecs.umich.edu#include "base/loader/symtab.hh"
332997Sstever@eecs.umich.edu#include "base/remote_gdb.hh"
342997Sstever@eecs.umich.edu#include "base/trace.hh"
352997Sstever@eecs.umich.edu#include "cpu/exec_context.hh"
362997Sstever@eecs.umich.edu#include "cpu/base_cpu.hh"
372997Sstever@eecs.umich.edu#include "kern/linux/linux_events.hh"
382997Sstever@eecs.umich.edu#include "kern/linux/linux_system.hh"
392997Sstever@eecs.umich.edu#include "mem/functional_mem/memory_control.hh"
402997Sstever@eecs.umich.edu#include "mem/functional_mem/physical_memory.hh"
415523Snate@binkert.org#include "sim/builder.hh"
425523Snate@binkert.org#include "dev/platform.hh"
436928SBrad.Beckmann@amd.com#include "targetarch/isa_traits.hh"
446928SBrad.Beckmann@amd.com#include "targetarch/vtophys.hh"
456289Snate@binkert.org
466289Snate@binkert.orgextern SymbolTable *debugSymbolTable;
479654SAndreas.Sandberg@ARM.com
489654SAndreas.Sandberg@ARM.comusing namespace std;
496289Snate@binkert.org
505523Snate@binkert.orgLinuxSystem::LinuxSystem(const string _name, const uint64_t _init_param,
515523Snate@binkert.org                         MemoryController *_memCtrl, PhysicalMemory *_physmem,
529401SAndreas.Sandberg@ARM.com                         const string &kernel_path, const string &console_path,
539401SAndreas.Sandberg@ARM.com                         const string &palcode, const string &boot_osflags,
549401SAndreas.Sandberg@ARM.com                         const bool _bin, const vector<string> &_binned_fns)
559401SAndreas.Sandberg@ARM.com     : System(_name, _init_param, _memCtrl, _physmem, _bin, _binned_fns),
569401SAndreas.Sandberg@ARM.com       bin(_bin), binned_fns(_binned_fns)
579401SAndreas.Sandberg@ARM.com{
589401SAndreas.Sandberg@ARM.com    kernelSymtab = new SymbolTable;
599401SAndreas.Sandberg@ARM.com    consoleSymtab = new SymbolTable;
609401SAndreas.Sandberg@ARM.com
619401SAndreas.Sandberg@ARM.com    // Load kernel code
629401SAndreas.Sandberg@ARM.com    ObjectFile *kernel = createObjectFile(kernel_path);
639401SAndreas.Sandberg@ARM.com    if (kernel == NULL)
649401SAndreas.Sandberg@ARM.com        fatal("Could not load kernel file %s", kernel_path);
659401SAndreas.Sandberg@ARM.com
669401SAndreas.Sandberg@ARM.com    // Load Console Code
679401SAndreas.Sandberg@ARM.com    ObjectFile *console = createObjectFile(console_path);
689401SAndreas.Sandberg@ARM.com    if (console == NULL)
699401SAndreas.Sandberg@ARM.com        fatal("Could not load console file %s", console_path);
709401SAndreas.Sandberg@ARM.com
719401SAndreas.Sandberg@ARM.com    // Load pal file
729401SAndreas.Sandberg@ARM.com    ObjectFile *pal = createObjectFile(palcode);
739401SAndreas.Sandberg@ARM.com    if (pal == NULL)
749401SAndreas.Sandberg@ARM.com        fatal("Could not load PALcode file %s", palcode);
759401SAndreas.Sandberg@ARM.com    pal->loadSections(physmem, true);
769401SAndreas.Sandberg@ARM.com
779401SAndreas.Sandberg@ARM.com    // Load console file
789401SAndreas.Sandberg@ARM.com    console->loadSections(physmem, true);
799401SAndreas.Sandberg@ARM.com
809401SAndreas.Sandberg@ARM.com    // Load kernel file
819401SAndreas.Sandberg@ARM.com    kernel->loadSections(physmem, true);
829401SAndreas.Sandberg@ARM.com    kernelStart = kernel->textBase();
839401SAndreas.Sandberg@ARM.com    kernelEnd = kernel->bssBase() + kernel->bssSize();
849401SAndreas.Sandberg@ARM.com    kernelEntry = kernel->entryPoint();
859401SAndreas.Sandberg@ARM.com
869401SAndreas.Sandberg@ARM.com    // load symbols
879401SAndreas.Sandberg@ARM.com    if (!kernel->loadGlobalSymbols(kernelSymtab))
889401SAndreas.Sandberg@ARM.com        panic("could not load kernel symbols\n");
899401SAndreas.Sandberg@ARM.com        debugSymbolTable = kernelSymtab;
909401SAndreas.Sandberg@ARM.com
919401SAndreas.Sandberg@ARM.com    if (!kernel->loadLocalSymbols(kernelSymtab))
929401SAndreas.Sandberg@ARM.com        panic("could not load kernel local symbols\n");
939401SAndreas.Sandberg@ARM.com
949401SAndreas.Sandberg@ARM.com    if (!console->loadGlobalSymbols(consoleSymtab))
959401SAndreas.Sandberg@ARM.com        panic("could not load console symbols\n");
969401SAndreas.Sandberg@ARM.com
979401SAndreas.Sandberg@ARM.com    DPRINTF(Loader, "Kernel start = %#x\n"
989654SAndreas.Sandberg@ARM.com            "Kernel end   = %#x\n"
999654SAndreas.Sandberg@ARM.com            "Kernel entry = %#x\n",
1009654SAndreas.Sandberg@ARM.com            kernelStart, kernelEnd, kernelEntry);
1019654SAndreas.Sandberg@ARM.com
1029654SAndreas.Sandberg@ARM.com    DPRINTF(Loader, "Kernel loaded...\n");
1039654SAndreas.Sandberg@ARM.com
1049654SAndreas.Sandberg@ARM.com
1059654SAndreas.Sandberg@ARM.com#ifdef DEBUG
1069654SAndreas.Sandberg@ARM.com    kernelPanicEvent = new BreakPCEvent(&pcEventQueue, "kernel panic");
1079654SAndreas.Sandberg@ARM.com    consolePanicEvent = new BreakPCEvent(&pcEventQueue, "console panic");
1089654SAndreas.Sandberg@ARM.com#endif
1099654SAndreas.Sandberg@ARM.com
1109654SAndreas.Sandberg@ARM.com    skipIdeDelay50msEvent = new LinuxSkipIdeDelay50msEvent(&pcEventQueue,
1119654SAndreas.Sandberg@ARM.com                                                     "ide_delay_50ms");
1129654SAndreas.Sandberg@ARM.com
1139654SAndreas.Sandberg@ARM.com    skipDelayLoopEvent = new LinuxSkipDelayLoopEvent(&pcEventQueue,
1149654SAndreas.Sandberg@ARM.com                                                     "calibrate_delay");
1159654SAndreas.Sandberg@ARM.com
1169654SAndreas.Sandberg@ARM.com    skipCacheProbeEvent = new LinuxSkipFuncEvent(&pcEventQueue, "determine_cpu_caches");
1179654SAndreas.Sandberg@ARM.com
1189654SAndreas.Sandberg@ARM.com    Addr addr = 0;
1199654SAndreas.Sandberg@ARM.com
1209654SAndreas.Sandberg@ARM.com    if (kernelSymtab->findAddress("est_cycle_freq", addr)) {
1219654SAndreas.Sandberg@ARM.com        Addr paddr = vtophys(physmem, addr);
1229654SAndreas.Sandberg@ARM.com        uint8_t *est_cycle_frequency =
1239654SAndreas.Sandberg@ARM.com            physmem->dma_addr(paddr, sizeof(uint64_t));
1249654SAndreas.Sandberg@ARM.com
1259654SAndreas.Sandberg@ARM.com        if (est_cycle_frequency)
1269654SAndreas.Sandberg@ARM.com            *(uint64_t *)est_cycle_frequency = ticksPerSecond;
1279654SAndreas.Sandberg@ARM.com    }
1289654SAndreas.Sandberg@ARM.com
1299654SAndreas.Sandberg@ARM.com
1309654SAndreas.Sandberg@ARM.com    if (consoleSymtab->findAddress("env_booted_osflags", addr)) {
1319654SAndreas.Sandberg@ARM.com        Addr paddr = vtophys(physmem, addr);
1329654SAndreas.Sandberg@ARM.com        char *osflags = (char *)physmem->dma_addr(paddr, sizeof(uint32_t));
1339654SAndreas.Sandberg@ARM.com
1349654SAndreas.Sandberg@ARM.com        if (osflags)
1359654SAndreas.Sandberg@ARM.com              strcpy(osflags, boot_osflags.c_str());
1369654SAndreas.Sandberg@ARM.com    }
1379654SAndreas.Sandberg@ARM.com
1389447SAndreas.Sandberg@ARM.com    {
1399447SAndreas.Sandberg@ARM.com        Addr paddr = vtophys(physmem, PARAM_ADDR);
1409447SAndreas.Sandberg@ARM.com        char *commandline = (char*)physmem->dma_addr(paddr, sizeof(uint64_t));
1419447SAndreas.Sandberg@ARM.com        if (commandline)
1429447SAndreas.Sandberg@ARM.com            strcpy(commandline, boot_osflags.c_str());
1439447SAndreas.Sandberg@ARM.com    }
1449447SAndreas.Sandberg@ARM.com
1459447SAndreas.Sandberg@ARM.com
1469447SAndreas.Sandberg@ARM.com    if (consoleSymtab->findAddress("xxm_rpb", addr)) {
1479447SAndreas.Sandberg@ARM.com        Addr paddr = vtophys(physmem, addr);
1485523Snate@binkert.org        char *hwprb = (char *)physmem->dma_addr(paddr, sizeof(uint64_t));
1495523Snate@binkert.org
1502997Sstever@eecs.umich.edu        if (hwprb) {
1512997Sstever@eecs.umich.edu            *(uint64_t*)(hwprb+0x50) = 34;      // Tsunami
1528802Sgblack@eecs.umich.edu            *(uint64_t*)(hwprb+0x58) = (1<<10);
1532997Sstever@eecs.umich.edu        }
1542997Sstever@eecs.umich.edu        else
1552997Sstever@eecs.umich.edu            panic("could not translate hwprb addr to set system type/variation\n");
1566874SSteve.Reinhardt@amd.com
1576874SSteve.Reinhardt@amd.com    } else
1586289Snate@binkert.org        panic("could not find hwprb to set system type/variation\n");
1592998Sstever@eecs.umich.edu
1602998Sstever@eecs.umich.edu#ifdef DEBUG
1612998Sstever@eecs.umich.edu    if (kernelSymtab->findAddress("panic", addr))
1622998Sstever@eecs.umich.edu        kernelPanicEvent->schedule(addr);
1632998Sstever@eecs.umich.edu    else
1642998Sstever@eecs.umich.edu        panic("could not find kernel symbol \'panic\'");
1656289Snate@binkert.org
1662997Sstever@eecs.umich.edu    if (consoleSymtab->findAddress("panic", addr))
1673475Sktlim@umich.edu        consolePanicEvent->schedule(addr);
1683475Sktlim@umich.edu#endif
1693475Sktlim@umich.edu
1703475Sktlim@umich.edu    if (kernelSymtab->findAddress("ide_delay_50ms", addr))
1713475Sktlim@umich.edu        skipIdeDelay50msEvent->schedule(addr+8);
1726289Snate@binkert.org
1733475Sktlim@umich.edu    if (kernelSymtab->findAddress("calibrate_delay", addr))
1742997Sstever@eecs.umich.edu        skipDelayLoopEvent->schedule(addr+8);
1756289Snate@binkert.org
1766928SBrad.Beckmann@amd.com    if (kernelSymtab->findAddress("determine_cpu_caches", addr))
1776928SBrad.Beckmann@amd.com        skipCacheProbeEvent->schedule(addr+8);
1786928SBrad.Beckmann@amd.com}
1796928SBrad.Beckmann@amd.com
1806928SBrad.Beckmann@amd.comLinuxSystem::~LinuxSystem()
1812997Sstever@eecs.umich.edu{
1822997Sstever@eecs.umich.edu    delete kernel;
1832998Sstever@eecs.umich.edu    delete console;
1845523Snate@binkert.org
1852997Sstever@eecs.umich.edu    delete kernelSymtab;
1862997Sstever@eecs.umich.edu    delete consoleSymtab;
1878802Sgblack@eecs.umich.edu
1888802Sgblack@eecs.umich.edu    delete kernelPanicEvent;
1892997Sstever@eecs.umich.edu    delete consolePanicEvent;
1909384SAndreas.Sandberg@arm.com    delete skipIdeDelay50msEvent;
1919384SAndreas.Sandberg@arm.com    delete skipDelayLoopEvent;
1929384SAndreas.Sandberg@arm.com    delete skipCacheProbeEvent;
1939384SAndreas.Sandberg@arm.com}
1949384SAndreas.Sandberg@arm.com
1959851Sandreas.hansson@arm.com
1969384SAndreas.Sandberg@arm.comvoid
1979851Sandreas.hansson@arm.comLinuxSystem::setDelayLoop(ExecContext *xc)
1989851Sandreas.hansson@arm.com{
1999384SAndreas.Sandberg@arm.com    Addr addr = 0;
2009384SAndreas.Sandberg@arm.com    if (kernelSymtab->findAddress("loops_per_jiffy", addr)) {
2019384SAndreas.Sandberg@arm.com        Addr paddr = vtophys(physmem, addr);
2029384SAndreas.Sandberg@arm.com
2039384SAndreas.Sandberg@arm.com        uint8_t *loops_per_jiffy =
2049384SAndreas.Sandberg@arm.com            physmem->dma_addr(paddr, sizeof(uint32_t));
2059384SAndreas.Sandberg@arm.com
2069384SAndreas.Sandberg@arm.com        Tick cpuFreq = xc->cpu->getFreq();
2079384SAndreas.Sandberg@arm.com        Tick intrFreq = platform->interrupt_frequency;
2089384SAndreas.Sandberg@arm.com        *(uint32_t *)loops_per_jiffy =
2099384SAndreas.Sandberg@arm.com            (uint32_t)((cpuFreq / intrFreq) * 0.9988);
2109384SAndreas.Sandberg@arm.com    }
2119384SAndreas.Sandberg@arm.com}
2129384SAndreas.Sandberg@arm.com
2139384SAndreas.Sandberg@arm.comint
2149384SAndreas.Sandberg@arm.comLinuxSystem::registerExecContext(ExecContext *xc)
2159384SAndreas.Sandberg@arm.com{
2169384SAndreas.Sandberg@arm.com    int xcIndex = System::registerExecContext(xc);
2179447SAndreas.Sandberg@ARM.com
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