system.cc revision 882
12207SN/A/*
22207SN/A * Copyright (c) 2003 The Regents of The University of Michigan
32207SN/A * All rights reserved.
42207SN/A *
52207SN/A * Redistribution and use in source and binary forms, with or without
62207SN/A * modification, are permitted provided that the following conditions are
72207SN/A * met: redistributions of source code must retain the above copyright
82207SN/A * notice, this list of conditions and the following disclaimer;
92207SN/A * redistributions in binary form must reproduce the above copyright
102207SN/A * notice, this list of conditions and the following disclaimer in the
112207SN/A * documentation and/or other materials provided with the distribution;
122207SN/A * neither the name of the copyright holders nor the names of its
132207SN/A * contributors may be used to endorse or promote products derived from
142207SN/A * this software without specific prior written permission.
152207SN/A *
162207SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172207SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182207SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192207SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202207SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212207SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222207SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232207SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242207SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252207SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262207SN/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"
302207SN/A#include "base/loader/elf_object.hh"
312207SN/A#include "base/loader/object_file.hh"
323589Sgblack@eecs.umich.edu#include "base/loader/symtab.hh"
334111Sgblack@eecs.umich.edu#include "base/remote_gdb.hh"
342474SN/A#include "base/trace.hh"
352207SN/A#include "cpu/exec_context.hh"
363760Sgblack@eecs.umich.edu#include "cpu/base_cpu.hh"
372454SN/A#include "kern/linux/linux_events.hh"
382976Sgblack@eecs.umich.edu#include "kern/linux/linux_system.hh"
392454SN/A#include "mem/functional_mem/memory_control.hh"
402680Sktlim@umich.edu#include "mem/functional_mem/physical_memory.hh"
412561SN/A#include "sim/builder.hh"
424434Ssaidi@eecs.umich.edu#include "dev/platform.hh"
432561SN/A#include "targetarch/isa_traits.hh"
442474SN/A#include "targetarch/vtophys.hh"
452207SN/A
462458SN/Aextern SymbolTable *debugSymbolTable;
472474SN/A
482458SN/Ausing namespace std;
492207SN/A
505154Sgblack@eecs.umich.eduLinuxSystem::LinuxSystem(const string _name, const uint64_t _init_param,
515154Sgblack@eecs.umich.edu                         MemoryController *_memCtrl, PhysicalMemory *_physmem,
525154Sgblack@eecs.umich.edu                         const string &kernel_path, const string &console_path,
532474SN/A                         const string &palcode, const string &boot_osflags,
542474SN/A                         const bool _bin, const vector<string> &_binned_fns)
552474SN/A     : System(_name, _init_param, _memCtrl, _physmem, _bin, _binned_fns),
562474SN/A       bin(_bin), binned_fns(_binned_fns)
572474SN/A{
582474SN/A    kernelSymtab = new SymbolTable;
592474SN/A    consoleSymtab = new SymbolTable;
602474SN/A
613415Sgblack@eecs.umich.edu    // Load kernel code
623415Sgblack@eecs.umich.edu    ObjectFile *kernel = createObjectFile(kernel_path);
633415Sgblack@eecs.umich.edu    if (kernel == NULL)
643415Sgblack@eecs.umich.edu        fatal("Could not load kernel file %s", kernel_path);
652474SN/A
662474SN/A    // Load Console Code
674111Sgblack@eecs.umich.edu    ObjectFile *console = createObjectFile(console_path);
684111Sgblack@eecs.umich.edu    if (console == NULL)
694111Sgblack@eecs.umich.edu        fatal("Could not load console file %s", console_path);
704111Sgblack@eecs.umich.edu
715128Sgblack@eecs.umich.edu    // Load pal file
725128Sgblack@eecs.umich.edu    ObjectFile *pal = createObjectFile(palcode);
735128Sgblack@eecs.umich.edu    if (pal == NULL)
745128Sgblack@eecs.umich.edu        fatal("Could not load PALcode file %s", palcode);
755128Sgblack@eecs.umich.edu    pal->loadSections(physmem, true);
765128Sgblack@eecs.umich.edu
775128Sgblack@eecs.umich.edu    // Load console file
784111Sgblack@eecs.umich.edu    console->loadSections(physmem, true);
795128Sgblack@eecs.umich.edu
805128Sgblack@eecs.umich.edu    // Load kernel file
815128Sgblack@eecs.umich.edu    kernel->loadSections(physmem, true);
825128Sgblack@eecs.umich.edu    kernelStart = kernel->textBase();
835128Sgblack@eecs.umich.edu    kernelEnd = kernel->bssBase() + kernel->bssSize();
845128Sgblack@eecs.umich.edu    kernelEntry = kernel->entryPoint();
855128Sgblack@eecs.umich.edu
865128Sgblack@eecs.umich.edu    // load symbols
875128Sgblack@eecs.umich.edu    if (!kernel->loadGlobalSymbols(kernelSymtab))
885128Sgblack@eecs.umich.edu        panic("could not load kernel symbols\n");
895128Sgblack@eecs.umich.edu        debugSymbolTable = kernelSymtab;
905128Sgblack@eecs.umich.edu
915128Sgblack@eecs.umich.edu    if (!kernel->loadLocalSymbols(kernelSymtab))
925128Sgblack@eecs.umich.edu        panic("could not load kernel local symbols\n");
935128Sgblack@eecs.umich.edu
945128Sgblack@eecs.umich.edu    if (!console->loadGlobalSymbols(consoleSymtab))
955128Sgblack@eecs.umich.edu        panic("could not load console symbols\n");
965128Sgblack@eecs.umich.edu
975128Sgblack@eecs.umich.edu    DPRINTF(Loader, "Kernel start = %#x\n"
985128Sgblack@eecs.umich.edu            "Kernel end   = %#x\n"
995128Sgblack@eecs.umich.edu            "Kernel entry = %#x\n",
1005128Sgblack@eecs.umich.edu            kernelStart, kernelEnd, kernelEntry);
1015128Sgblack@eecs.umich.edu
1025128Sgblack@eecs.umich.edu    DPRINTF(Loader, "Kernel loaded...\n");
1035128Sgblack@eecs.umich.edu
1044111Sgblack@eecs.umich.edu
1054111Sgblack@eecs.umich.edu#ifdef DEBUG
1064111Sgblack@eecs.umich.edu    kernelPanicEvent = new BreakPCEvent(&pcEventQueue, "kernel panic");
1074111Sgblack@eecs.umich.edu    consolePanicEvent = new BreakPCEvent(&pcEventQueue, "console panic");
1084111Sgblack@eecs.umich.edu#endif
1094111Sgblack@eecs.umich.edu
1102474SN/A    skipIdeDelay50msEvent = new LinuxSkipIdeDelay50msEvent(&pcEventQueue,
1114111Sgblack@eecs.umich.edu                                                     "ide_delay_50ms");
1124111Sgblack@eecs.umich.edu
1134111Sgblack@eecs.umich.edu    skipDelayLoopEvent = new LinuxSkipDelayLoopEvent(&pcEventQueue,
1144111Sgblack@eecs.umich.edu                                                     "calibrate_delay");
1154111Sgblack@eecs.umich.edu
1164111Sgblack@eecs.umich.edu    skipCacheProbeEvent = new LinuxSkipFuncEvent(&pcEventQueue, "determine_cpu_caches");
1174648Sgblack@eecs.umich.edu
1184648Sgblack@eecs.umich.edu    Addr addr = 0;
1194111Sgblack@eecs.umich.edu
1204111Sgblack@eecs.umich.edu    if (kernelSymtab->findAddress("est_cycle_freq", addr)) {
1214172Ssaidi@eecs.umich.edu        Addr paddr = vtophys(physmem, addr);
1224111Sgblack@eecs.umich.edu        uint8_t *est_cycle_frequency =
1234172Ssaidi@eecs.umich.edu            physmem->dma_addr(paddr, sizeof(uint64_t));
1244111Sgblack@eecs.umich.edu
1254111Sgblack@eecs.umich.edu        if (est_cycle_frequency)
1264111Sgblack@eecs.umich.edu            *(uint64_t *)est_cycle_frequency = ticksPerSecond;
1274111Sgblack@eecs.umich.edu    }
1284111Sgblack@eecs.umich.edu
1294111Sgblack@eecs.umich.edu
1304172Ssaidi@eecs.umich.edu    if (consoleSymtab->findAddress("env_booted_osflags", addr)) {
1314111Sgblack@eecs.umich.edu        Addr paddr = vtophys(physmem, addr);
1324111Sgblack@eecs.umich.edu        char *osflags = (char *)physmem->dma_addr(paddr, sizeof(uint32_t));
1334172Ssaidi@eecs.umich.edu
1344111Sgblack@eecs.umich.edu        if (osflags)
1354111Sgblack@eecs.umich.edu              strcpy(osflags, boot_osflags.c_str());
1364172Ssaidi@eecs.umich.edu    }
1374111Sgblack@eecs.umich.edu
1384111Sgblack@eecs.umich.edu    {
1394172Ssaidi@eecs.umich.edu        Addr paddr = vtophys(physmem, PARAM_ADDR);
1404111Sgblack@eecs.umich.edu        char *commandline = (char*)physmem->dma_addr(paddr, sizeof(uint64_t));
1414111Sgblack@eecs.umich.edu        if (commandline)
1424172Ssaidi@eecs.umich.edu            strcpy(commandline, boot_osflags.c_str());
1434111Sgblack@eecs.umich.edu    }
1444172Ssaidi@eecs.umich.edu
1454111Sgblack@eecs.umich.edu
1464111Sgblack@eecs.umich.edu    if (consoleSymtab->findAddress("xxm_rpb", addr)) {
1474172Ssaidi@eecs.umich.edu        Addr paddr = vtophys(physmem, addr);
1484111Sgblack@eecs.umich.edu        char *hwprb = (char *)physmem->dma_addr(paddr, sizeof(uint64_t));
1494172Ssaidi@eecs.umich.edu
1504997Sgblack@eecs.umich.edu        if (hwprb) {
1514997Sgblack@eecs.umich.edu            *(uint64_t*)(hwprb+0x50) = 34;      // Tsunami
1524997Sgblack@eecs.umich.edu            *(uint64_t*)(hwprb+0x58) = (1<<10);
1534997Sgblack@eecs.umich.edu        }
1544997Sgblack@eecs.umich.edu        else
1554997Sgblack@eecs.umich.edu            panic("could not translate hwprb addr to set system type/variation\n");
1564111Sgblack@eecs.umich.edu
1574111Sgblack@eecs.umich.edu    } else
1584111Sgblack@eecs.umich.edu        panic("could not find hwprb to set system type/variation\n");
1594111Sgblack@eecs.umich.edu
1602474SN/A#ifdef DEBUG
1613760Sgblack@eecs.umich.edu    if (kernelSymtab->findAddress("panic", addr))
1622561SN/A        kernelPanicEvent->schedule(addr);
1632561SN/A    else
1642561SN/A        panic("could not find kernel symbol \'panic\'");
1652561SN/A
1664172Ssaidi@eecs.umich.edu    if (consoleSymtab->findAddress("panic", addr))
1672561SN/A        consolePanicEvent->schedule(addr);
1682646Ssaidi@eecs.umich.edu#endif
1694172Ssaidi@eecs.umich.edu
1702646Ssaidi@eecs.umich.edu    if (kernelSymtab->findAddress("ide_delay_50ms", addr))
1714172Ssaidi@eecs.umich.edu        skipIdeDelay50msEvent->schedule(addr+8);
1724997Sgblack@eecs.umich.edu
1732561SN/A    if (kernelSymtab->findAddress("calibrate_delay", addr))
1742561SN/A        skipDelayLoopEvent->schedule(addr+8);
1752561SN/A
1762561SN/A    if (kernelSymtab->findAddress("determine_cpu_caches", addr))
1772561SN/A        skipCacheProbeEvent->schedule(addr+8);
1784172Ssaidi@eecs.umich.edu}
1793761Sgblack@eecs.umich.edu
1802561SN/ALinuxSystem::~LinuxSystem()
1814172Ssaidi@eecs.umich.edu{
1823761Sgblack@eecs.umich.edu    delete kernel;
1832561SN/A    delete console;
1844172Ssaidi@eecs.umich.edu
1853761Sgblack@eecs.umich.edu    delete kernelSymtab;
1862561SN/A    delete consoleSymtab;
1874172Ssaidi@eecs.umich.edu
1883761Sgblack@eecs.umich.edu    delete kernelPanicEvent;
1892561SN/A    delete consolePanicEvent;
1904172Ssaidi@eecs.umich.edu    delete skipIdeDelay50msEvent;
1913415Sgblack@eecs.umich.edu    delete skipDelayLoopEvent;
1924172Ssaidi@eecs.umich.edu    delete skipCacheProbeEvent;
1933761Sgblack@eecs.umich.edu}
1943415Sgblack@eecs.umich.edu
1954172Ssaidi@eecs.umich.edu
1963589Sgblack@eecs.umich.eduvoid
1974172Ssaidi@eecs.umich.eduLinuxSystem::setDelayLoop(ExecContext *xc)
1984997Sgblack@eecs.umich.edu{
1994997Sgblack@eecs.umich.edu    Addr addr = 0;
2004997Sgblack@eecs.umich.edu    if (kernelSymtab->findAddress("loops_per_jiffy", addr)) {
2014997Sgblack@eecs.umich.edu        Addr paddr = vtophys(physmem, addr);
2024997Sgblack@eecs.umich.edu
2034997Sgblack@eecs.umich.edu        uint8_t *loops_per_jiffy =
2042474SN/A            physmem->dma_addr(paddr, sizeof(uint32_t));
2052474SN/A
2064111Sgblack@eecs.umich.edu        Tick cpuFreq = xc->cpu->getFreq();
2072585SN/A        Tick intrFreq = platform->interrupt_frequency;
2084111Sgblack@eecs.umich.edu        *(uint32_t *)loops_per_jiffy =
2094111Sgblack@eecs.umich.edu            (uint32_t)((cpuFreq / intrFreq) * 0.9988);
2102585SN/A    }
2112585SN/A}
2124111Sgblack@eecs.umich.edu
2133415Sgblack@eecs.umich.eduint
2144111Sgblack@eecs.umich.eduLinuxSystem::registerExecContext(ExecContext *xc)
2154111Sgblack@eecs.umich.edu{
2164111Sgblack@eecs.umich.edu    int xcIndex = System::registerExecContext(xc);
2173415Sgblack@eecs.umich.edu
2182561SN/A    if (xcIndex == 0) {
2194111Sgblack@eecs.umich.edu        // activate with zero delay so that we start ticking right
2202561SN/A        // away on cycle 0
2214111Sgblack@eecs.umich.edu        xc->activate(0);
2222561SN/A    }
2232474SN/A
2243044Sgblack@eecs.umich.edu    RemoteGDB *rgdb = new RemoteGDB(this, xc);
2253044Sgblack@eecs.umich.edu    GDBListener *gdbl = new GDBListener(rgdb, 7000 + xcIndex);
2263044Sgblack@eecs.umich.edu    gdbl->listen();
2273044Sgblack@eecs.umich.edu//    gdbl->accept();
2283044Sgblack@eecs.umich.edu
2293044Sgblack@eecs.umich.edu    if (remoteGDB.size() <= xcIndex) {
2302561SN/A        remoteGDB.resize(xcIndex+1);
2312561SN/A    }
2322561SN/A
2332561SN/A    remoteGDB[xcIndex] = rgdb;
2342561SN/A
2352585SN/A    return xcIndex;
2362585SN/A}
2372585SN/A
2382585SN/A
2392585SN/Avoid
2402585SN/ALinuxSystem::replaceExecContext(ExecContext *xc, int xcIndex)
2412585SN/A{
2422585SN/A    System::replaceExecContext(xcIndex, xc);
2432585SN/A    remoteGDB[xcIndex]->replaceExecContext(xc);
2442585SN/A}
2452585SN/A
2462585SN/Abool
2472585SN/ALinuxSystem::breakpoint()
2482585SN/A{
2492585SN/A    return remoteGDB[0]->trap(ALPHA_KENTRY_IF);
2502585SN/A}
2512585SN/A
2522585SN/ABEGIN_DECLARE_SIM_OBJECT_PARAMS(LinuxSystem)
2532585SN/A
2542585SN/A    Param<bool> bin;
2552585SN/A    SimObjectParam<MemoryController *> mem_ctl;
2562976Sgblack@eecs.umich.edu    SimObjectParam<PhysicalMemory *> physmem;
2572976Sgblack@eecs.umich.edu    Param<uint64_t> init_param;
2582976Sgblack@eecs.umich.edu
2592976Sgblack@eecs.umich.edu    Param<string> kernel_code;
2602976Sgblack@eecs.umich.edu    Param<string> console_code;
2612976Sgblack@eecs.umich.edu    Param<string> pal_code;
2622976Sgblack@eecs.umich.edu    Param<string> boot_osflags;
2634793Sgblack@eecs.umich.edu    VectorParam<string> binned_fns;
2642976Sgblack@eecs.umich.edu
2654793Sgblack@eecs.umich.eduEND_DECLARE_SIM_OBJECT_PARAMS(LinuxSystem)
2662976Sgblack@eecs.umich.edu
2672976Sgblack@eecs.umich.eduBEGIN_INIT_SIM_OBJECT_PARAMS(LinuxSystem)
2684793Sgblack@eecs.umich.edu
2692976Sgblack@eecs.umich.edu
2702976Sgblack@eecs.umich.edu    INIT_PARAM_DFLT(bin, "is this system to be binned", false),
2714793Sgblack@eecs.umich.edu    INIT_PARAM(mem_ctl, "memory controller"),
2722976Sgblack@eecs.umich.edu    INIT_PARAM(physmem, "phsyical memory"),
2734793Sgblack@eecs.umich.edu    INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0),
2742976Sgblack@eecs.umich.edu    INIT_PARAM(kernel_code, "file that contains the code"),
2754793Sgblack@eecs.umich.edu    INIT_PARAM(console_code, "file that contains the console code"),
2762976Sgblack@eecs.umich.edu    INIT_PARAM(pal_code, "file that contains palcode"),
2772976Sgblack@eecs.umich.edu    INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot",
2782976Sgblack@eecs.umich.edu                                   "a"),
2794793Sgblack@eecs.umich.edu    INIT_PARAM(binned_fns, "functions to be broken down and binned")
2802976Sgblack@eecs.umich.edu
2814793Sgblack@eecs.umich.edu
2822976Sgblack@eecs.umich.eduEND_INIT_SIM_OBJECT_PARAMS(LinuxSystem)
2834793Sgblack@eecs.umich.edu
2842976Sgblack@eecs.umich.eduCREATE_SIM_OBJECT(LinuxSystem)
2854793Sgblack@eecs.umich.edu{
2864793Sgblack@eecs.umich.edu    LinuxSystem *sys = new LinuxSystem(getInstanceName(), init_param, mem_ctl,
2874793Sgblack@eecs.umich.edu                                       physmem, kernel_code, console_code,
2884793Sgblack@eecs.umich.edu                                       pal_code, boot_osflags, bin, binned_fns);
2892976Sgblack@eecs.umich.edu
2904793Sgblack@eecs.umich.edu    return sys;
2912976Sgblack@eecs.umich.edu}
2922585SN/A
2932561SN/AREGISTER_SIM_OBJECT("LinuxSystem", LinuxSystem)
2942561SN/A