system.cc revision 1070
112967Smatteo.andreozzi@arm.com/*
212967Smatteo.andreozzi@arm.com * Copyright (c) 2004 The Regents of The University of Michigan
312967Smatteo.andreozzi@arm.com * All rights reserved.
412967Smatteo.andreozzi@arm.com *
512967Smatteo.andreozzi@arm.com * Redistribution and use in source and binary forms, with or without
612967Smatteo.andreozzi@arm.com * modification, are permitted provided that the following conditions are
712967Smatteo.andreozzi@arm.com * met: redistributions of source code must retain the above copyright
812967Smatteo.andreozzi@arm.com * notice, this list of conditions and the following disclaimer;
912967Smatteo.andreozzi@arm.com * redistributions in binary form must reproduce the above copyright
1012967Smatteo.andreozzi@arm.com * notice, this list of conditions and the following disclaimer in the
1112967Smatteo.andreozzi@arm.com * documentation and/or other materials provided with the distribution;
1212967Smatteo.andreozzi@arm.com * neither the name of the copyright holders nor the names of its
1312967Smatteo.andreozzi@arm.com * contributors may be used to endorse or promote products derived from
1412967Smatteo.andreozzi@arm.com * this software without specific prior written permission.
1512967Smatteo.andreozzi@arm.com *
1612967Smatteo.andreozzi@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1712967Smatteo.andreozzi@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1812967Smatteo.andreozzi@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1912967Smatteo.andreozzi@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2012967Smatteo.andreozzi@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2112967Smatteo.andreozzi@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2212967Smatteo.andreozzi@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2312967Smatteo.andreozzi@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2412967Smatteo.andreozzi@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2512967Smatteo.andreozzi@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2612967Smatteo.andreozzi@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2712967Smatteo.andreozzi@arm.com */
2812967Smatteo.andreozzi@arm.com
2912967Smatteo.andreozzi@arm.com/**
3012967Smatteo.andreozzi@arm.com * @file
3112967Smatteo.andreozzi@arm.com * This code loads the linux kernel, console, pal and patches certain
3212967Smatteo.andreozzi@arm.com * functions.  The symbol tables are loaded so that traces can show
3312967Smatteo.andreozzi@arm.com * the executing function and we can skip functions. Various delay
3412967Smatteo.andreozzi@arm.com * loops are skipped and their final values manually computed to speed
3512967Smatteo.andreozzi@arm.com * up boot time.
3612967Smatteo.andreozzi@arm.com */
3712967Smatteo.andreozzi@arm.com
3812967Smatteo.andreozzi@arm.com#include "base/trace.hh"
3912967Smatteo.andreozzi@arm.com#include "cpu/exec_context.hh"
4012967Smatteo.andreozzi@arm.com#include "cpu/base_cpu.hh"
4112967Smatteo.andreozzi@arm.com#include "kern/linux/linux_events.hh"
4212967Smatteo.andreozzi@arm.com#include "kern/linux/linux_system.hh"
4312967Smatteo.andreozzi@arm.com#include "kern/system_events.hh"
4412967Smatteo.andreozzi@arm.com#include "mem/functional_mem/memory_control.hh"
4512967Smatteo.andreozzi@arm.com#include "mem/functional_mem/physical_memory.hh"
4612967Smatteo.andreozzi@arm.com#include "sim/builder.hh"
4712967Smatteo.andreozzi@arm.com#include "dev/platform.hh"
4812967Smatteo.andreozzi@arm.com#include "targetarch/isa_traits.hh"
4912967Smatteo.andreozzi@arm.com#include "targetarch/vtophys.hh"
5012967Smatteo.andreozzi@arm.com#include "sim/debug.hh"
5112967Smatteo.andreozzi@arm.com
5212967Smatteo.andreozzi@arm.comextern SymbolTable *debugSymbolTable;
5312967Smatteo.andreozzi@arm.com
5412967Smatteo.andreozzi@arm.comusing namespace std;
5512967Smatteo.andreozzi@arm.com
5612967Smatteo.andreozzi@arm.comLinuxSystem::LinuxSystem(Params *p)
5712967Smatteo.andreozzi@arm.com    : System(p)
5812967Smatteo.andreozzi@arm.com{
5912967Smatteo.andreozzi@arm.com    Addr addr = 0;
6012967Smatteo.andreozzi@arm.com
6112967Smatteo.andreozzi@arm.com    /**
6212967Smatteo.andreozzi@arm.com     * find the address of the est_cycle_freq variable and insert it
6312967Smatteo.andreozzi@arm.com     * so we don't through the lengthly process of trying to
6412967Smatteo.andreozzi@arm.com     * calculated it by using the PIT, RTC, etc.
6512967Smatteo.andreozzi@arm.com     */
6612967Smatteo.andreozzi@arm.com    if (kernelSymtab->findAddress("est_cycle_freq", addr)) {
6712967Smatteo.andreozzi@arm.com        Addr paddr = vtophys(physmem, addr);
6812967Smatteo.andreozzi@arm.com        uint8_t *est_cycle_frequency =
6912967Smatteo.andreozzi@arm.com            physmem->dma_addr(paddr, sizeof(uint64_t));
7012967Smatteo.andreozzi@arm.com
7112967Smatteo.andreozzi@arm.com        if (est_cycle_frequency)
7212967Smatteo.andreozzi@arm.com            *(uint64_t *)est_cycle_frequency = htoa(ticksPerSecond);
7312967Smatteo.andreozzi@arm.com    }
7412967Smatteo.andreozzi@arm.com
7512967Smatteo.andreozzi@arm.com
7612967Smatteo.andreozzi@arm.com    /**
7712967Smatteo.andreozzi@arm.com     * Since we aren't using a bootloader, we have to copy the kernel arguments
7812967Smatteo.andreozzi@arm.com     * directly into the kernels memory.
7912967Smatteo.andreozzi@arm.com     */
8012967Smatteo.andreozzi@arm.com    {
8112967Smatteo.andreozzi@arm.com        Addr paddr = vtophys(physmem, PARAM_ADDR);
8212967Smatteo.andreozzi@arm.com        char *commandline = (char*)physmem->dma_addr(paddr, sizeof(uint64_t));
8312967Smatteo.andreozzi@arm.com        if (commandline)
8412967Smatteo.andreozzi@arm.com            strcpy(commandline, params->boot_osflags.c_str());
8512967Smatteo.andreozzi@arm.com    }
8612967Smatteo.andreozzi@arm.com
8712967Smatteo.andreozzi@arm.com
8812967Smatteo.andreozzi@arm.com    /**
8912967Smatteo.andreozzi@arm.com     * EV5 only supports 127 ASNs so we are going to tell the kernel that the
9012967Smatteo.andreozzi@arm.com     * paritiuclar EV6 we have only supports 127 asns.
9112967Smatteo.andreozzi@arm.com     * @todo At some point we should change ev5.hh and the palcode to support
9212967Smatteo.andreozzi@arm.com     * 255 ASNs.
9312967Smatteo.andreozzi@arm.com     */
9412967Smatteo.andreozzi@arm.com    if (kernelSymtab->findAddress("dp264_mv", addr)) {
9512967Smatteo.andreozzi@arm.com        Addr paddr = vtophys(physmem, addr);
9612967Smatteo.andreozzi@arm.com        char *dp264_mv = (char *)physmem->dma_addr(paddr, sizeof(uint64_t));
9712967Smatteo.andreozzi@arm.com
9812967Smatteo.andreozzi@arm.com        if (dp264_mv) {
9912967Smatteo.andreozzi@arm.com            *(uint32_t*)(dp264_mv+0x18) = htoa((uint32_t)127);
10012967Smatteo.andreozzi@arm.com        } else
10112967Smatteo.andreozzi@arm.com            panic("could not translate dp264_mv addr\n");
10212967Smatteo.andreozzi@arm.com
10312967Smatteo.andreozzi@arm.com    } else
10412967Smatteo.andreozzi@arm.com        panic("could not find dp264_mv\n");
10512967Smatteo.andreozzi@arm.com
10612967Smatteo.andreozzi@arm.com#ifdef DEBUG
10712967Smatteo.andreozzi@arm.com    kernelPanicEvent = new BreakPCEvent(&pcEventQueue, "kernel panic");
10812967Smatteo.andreozzi@arm.com    if (kernelSymtab->findAddress("panic", addr))
10912967Smatteo.andreozzi@arm.com        kernelPanicEvent->schedule(addr);
11012967Smatteo.andreozzi@arm.com    else
11112967Smatteo.andreozzi@arm.com        panic("could not find kernel symbol \'panic\'");
11212967Smatteo.andreozzi@arm.com#endif
11312967Smatteo.andreozzi@arm.com
11412967Smatteo.andreozzi@arm.com    /**
11512967Smatteo.andreozzi@arm.com     * Any time ide_delay_50ms, calibarte_delay or
11612967Smatteo.andreozzi@arm.com     * determine_cpu_caches is called just skip the
11712967Smatteo.andreozzi@arm.com     * function. Currently determine_cpu_caches only is used put
11812967Smatteo.andreozzi@arm.com     * information in proc, however if that changes in the future we
11912967Smatteo.andreozzi@arm.com     * will have to fill in the cache size variables appropriately.
12012967Smatteo.andreozzi@arm.com     */
12112967Smatteo.andreozzi@arm.com    skipIdeDelay50msEvent = new SkipFuncEvent(&pcEventQueue, "ide_delay_50ms");
12212967Smatteo.andreozzi@arm.com    if (kernelSymtab->findAddress("ide_delay_50ms", addr))
12312967Smatteo.andreozzi@arm.com        skipIdeDelay50msEvent->schedule(addr+sizeof(MachInst));
12412967Smatteo.andreozzi@arm.com
12512967Smatteo.andreozzi@arm.com    skipDelayLoopEvent = new LinuxSkipDelayLoopEvent(&pcEventQueue,
12612967Smatteo.andreozzi@arm.com                                                     "calibrate_delay");
12712967Smatteo.andreozzi@arm.com    if (kernelSymtab->findAddress("calibrate_delay", addr))
12812967Smatteo.andreozzi@arm.com        skipDelayLoopEvent->schedule(addr+sizeof(MachInst));
12912967Smatteo.andreozzi@arm.com
13012967Smatteo.andreozzi@arm.com    skipCacheProbeEvent = new SkipFuncEvent(&pcEventQueue,
13112967Smatteo.andreozzi@arm.com                                            "determine_cpu_caches");
13212967Smatteo.andreozzi@arm.com    if (kernelSymtab->findAddress("determine_cpu_caches", addr))
13312967Smatteo.andreozzi@arm.com        skipCacheProbeEvent->schedule(addr+sizeof(MachInst));
13412967Smatteo.andreozzi@arm.com
13512967Smatteo.andreozzi@arm.com    debugPrintkEvent = new DebugPrintkEvent(&pcEventQueue, "dprintk");
13612967Smatteo.andreozzi@arm.com    if (kernelSymtab->findAddress("dprintk", addr))
13712967Smatteo.andreozzi@arm.com        debugPrintkEvent->schedule(addr+8);
13812967Smatteo.andreozzi@arm.com
13912967Smatteo.andreozzi@arm.com    idleStartEvent = new IdleStartEvent(&pcEventQueue, "cpu_idle", this);
14012967Smatteo.andreozzi@arm.com    if (kernelSymtab->findAddress("cpu_idle", addr))
14112967Smatteo.andreozzi@arm.com        idleStartEvent->schedule(addr);
14212967Smatteo.andreozzi@arm.com
14312967Smatteo.andreozzi@arm.com    printThreadEvent = new PrintThreadInfo(&pcEventQueue, "threadinfo");
14412967Smatteo.andreozzi@arm.com    if (kernelSymtab->findAddress("alpha_switch_to", addr) && DTRACE(Thread))
14512967Smatteo.andreozzi@arm.com        printThreadEvent->schedule(addr + sizeof(MachInst) * 6);
14612967Smatteo.andreozzi@arm.com}
14712967Smatteo.andreozzi@arm.com
14812967Smatteo.andreozzi@arm.comLinuxSystem::~LinuxSystem()
14912967Smatteo.andreozzi@arm.com{
15012967Smatteo.andreozzi@arm.com#ifdef DEBUG
15112967Smatteo.andreozzi@arm.com    delete kernelPanicEvent;
15212967Smatteo.andreozzi@arm.com#endif
15312967Smatteo.andreozzi@arm.com    delete skipIdeDelay50msEvent;
15412967Smatteo.andreozzi@arm.com    delete skipDelayLoopEvent;
15512967Smatteo.andreozzi@arm.com    delete skipCacheProbeEvent;
15612967Smatteo.andreozzi@arm.com    delete debugPrintkEvent;
15712967Smatteo.andreozzi@arm.com    delete idleStartEvent;
15812967Smatteo.andreozzi@arm.com}
15912967Smatteo.andreozzi@arm.com
16012967Smatteo.andreozzi@arm.com
16112967Smatteo.andreozzi@arm.comvoid
16212967Smatteo.andreozzi@arm.comLinuxSystem::setDelayLoop(ExecContext *xc)
16312967Smatteo.andreozzi@arm.com{
16412967Smatteo.andreozzi@arm.com    Addr addr = 0;
16512967Smatteo.andreozzi@arm.com    if (kernelSymtab->findAddress("loops_per_jiffy", addr)) {
16612967Smatteo.andreozzi@arm.com        Addr paddr = vtophys(physmem, addr);
16712967Smatteo.andreozzi@arm.com
16812967Smatteo.andreozzi@arm.com        uint8_t *loops_per_jiffy =
16912967Smatteo.andreozzi@arm.com            physmem->dma_addr(paddr, sizeof(uint32_t));
17012967Smatteo.andreozzi@arm.com
17112967Smatteo.andreozzi@arm.com        Tick cpuFreq = xc->cpu->getFreq();
17212967Smatteo.andreozzi@arm.com        Tick intrFreq = platform->interrupt_frequency;
17312967Smatteo.andreozzi@arm.com        *(uint32_t *)loops_per_jiffy =
17412967Smatteo.andreozzi@arm.com            (uint32_t)((cpuFreq / intrFreq) * 0.9988);
17512967Smatteo.andreozzi@arm.com    }
17612967Smatteo.andreozzi@arm.com}
17712967Smatteo.andreozzi@arm.com
17812967Smatteo.andreozzi@arm.comBEGIN_DECLARE_SIM_OBJECT_PARAMS(LinuxSystem)
17912967Smatteo.andreozzi@arm.com
18012967Smatteo.andreozzi@arm.com    SimObjectParam<MemoryController *> mem_ctl;
18112967Smatteo.andreozzi@arm.com    SimObjectParam<PhysicalMemory *> physmem;
18212967Smatteo.andreozzi@arm.com
18312967Smatteo.andreozzi@arm.com    Param<string> kernel_code;
18412967Smatteo.andreozzi@arm.com    Param<string> console_code;
18512967Smatteo.andreozzi@arm.com    Param<string> pal_code;
18612967Smatteo.andreozzi@arm.com
18712967Smatteo.andreozzi@arm.com    Param<string> boot_osflags;
18812967Smatteo.andreozzi@arm.com    Param<string> readfile;
18912967Smatteo.andreozzi@arm.com    Param<unsigned int> init_param;
19012967Smatteo.andreozzi@arm.com
19112967Smatteo.andreozzi@arm.com    Param<uint64_t> system_type;
19212967Smatteo.andreozzi@arm.com    Param<uint64_t> system_rev;
19312967Smatteo.andreozzi@arm.com
19412967Smatteo.andreozzi@arm.com    Param<bool> bin;
19512967Smatteo.andreozzi@arm.com    VectorParam<string> binned_fns;
19612967Smatteo.andreozzi@arm.com
19712967Smatteo.andreozzi@arm.comEND_DECLARE_SIM_OBJECT_PARAMS(LinuxSystem)
19812967Smatteo.andreozzi@arm.com
19912967Smatteo.andreozzi@arm.comBEGIN_INIT_SIM_OBJECT_PARAMS(LinuxSystem)
20012967Smatteo.andreozzi@arm.com
20112967Smatteo.andreozzi@arm.com    INIT_PARAM(mem_ctl, "memory controller"),
20212967Smatteo.andreozzi@arm.com    INIT_PARAM(physmem, "phsyical memory"),
20312967Smatteo.andreozzi@arm.com    INIT_PARAM(kernel_code, "file that contains the kernel code"),
20412967Smatteo.andreozzi@arm.com    INIT_PARAM(console_code, "file that contains the console code"),
20512967Smatteo.andreozzi@arm.com    INIT_PARAM(pal_code, "file that contains palcode"),
20612967Smatteo.andreozzi@arm.com    INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot",
20712967Smatteo.andreozzi@arm.com                    "a"),
20812967Smatteo.andreozzi@arm.com    INIT_PARAM_DFLT(readfile, "file to read startup script from", ""),
20912967Smatteo.andreozzi@arm.com    INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0),
21012967Smatteo.andreozzi@arm.com    INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 34),
21112967Smatteo.andreozzi@arm.com    INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10),
21212967Smatteo.andreozzi@arm.com    INIT_PARAM_DFLT(bin, "is this system to be binned", false),
21312967Smatteo.andreozzi@arm.com    INIT_PARAM(binned_fns, "functions to be broken down and binned")
21412967Smatteo.andreozzi@arm.com
21512967Smatteo.andreozzi@arm.comEND_INIT_SIM_OBJECT_PARAMS(LinuxSystem)
21612967Smatteo.andreozzi@arm.com
21712967Smatteo.andreozzi@arm.comCREATE_SIM_OBJECT(LinuxSystem)
21812967Smatteo.andreozzi@arm.com{
21912967Smatteo.andreozzi@arm.com    System::Params *p = new System::Params;
22012967Smatteo.andreozzi@arm.com    p->name = getInstanceName();
22112967Smatteo.andreozzi@arm.com    p->memctrl = mem_ctl;
22212967Smatteo.andreozzi@arm.com    p->physmem = physmem;
22312967Smatteo.andreozzi@arm.com    p->kernel_path = kernel_code;
22412967Smatteo.andreozzi@arm.com    p->console_path = console_code;
22512967Smatteo.andreozzi@arm.com    p->palcode = pal_code;
22612967Smatteo.andreozzi@arm.com    p->boot_osflags = boot_osflags;
22712967Smatteo.andreozzi@arm.com    p->init_param = init_param;
22812967Smatteo.andreozzi@arm.com    p->readfile = readfile;
22912967Smatteo.andreozzi@arm.com    p->system_type = system_type;
23012967Smatteo.andreozzi@arm.com    p->system_rev = system_rev;
23112967Smatteo.andreozzi@arm.com    p->bin = bin;
23212967Smatteo.andreozzi@arm.com    p->binned_fns = binned_fns;
23312967Smatteo.andreozzi@arm.com
23412967Smatteo.andreozzi@arm.com    return new LinuxSystem(p);
23512967Smatteo.andreozzi@arm.com}
23612967Smatteo.andreozzi@arm.com
23712967Smatteo.andreozzi@arm.comREGISTER_SIM_OBJECT("LinuxSystem", LinuxSystem)
23812967Smatteo.andreozzi@arm.com
23912967Smatteo.andreozzi@arm.com