system.cc revision 8229:78bf55f23338
112853Sgabeblack@google.com/*
212853Sgabeblack@google.com * Copyright (c) 2004-2005 The Regents of The University of Michigan
312853Sgabeblack@google.com * All rights reserved.
412853Sgabeblack@google.com *
512853Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without
612853Sgabeblack@google.com * modification, are permitted provided that the following conditions are
712853Sgabeblack@google.com * met: redistributions of source code must retain the above copyright
812853Sgabeblack@google.com * notice, this list of conditions and the following disclaimer;
912853Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright
1012853Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the
1112853Sgabeblack@google.com * documentation and/or other materials provided with the distribution;
1212853Sgabeblack@google.com * neither the name of the copyright holders nor the names of its
1312853Sgabeblack@google.com * contributors may be used to endorse or promote products derived from
1412853Sgabeblack@google.com * this software without specific prior written permission.
1512853Sgabeblack@google.com *
1612853Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1712853Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1812853Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1912853Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2012853Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2112853Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2212853Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2312853Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2412853Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2512853Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2612853Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2712853Sgabeblack@google.com *
2812853Sgabeblack@google.com * Authors: Ali Saidi
2912853Sgabeblack@google.com *          Lisa Hsu
3012853Sgabeblack@google.com *          Nathan Binkert
3112853Sgabeblack@google.com *          Steve Reinhardt
3212853Sgabeblack@google.com */
3312853Sgabeblack@google.com
3412853Sgabeblack@google.com/**
3512853Sgabeblack@google.com * @file
3612853Sgabeblack@google.com * This code loads the linux kernel, console, pal and patches certain
3712853Sgabeblack@google.com * functions.  The symbol tables are loaded so that traces can show
3812853Sgabeblack@google.com * the executing function and we can skip functions. Various delay
3912853Sgabeblack@google.com * loops are skipped and their final values manually computed to speed
4012853Sgabeblack@google.com * up boot time.
4112853Sgabeblack@google.com */
4212853Sgabeblack@google.com
4312853Sgabeblack@google.com#include "arch/alpha/linux/system.hh"
4412853Sgabeblack@google.com#include "arch/alpha/linux/threadinfo.hh"
4512853Sgabeblack@google.com#include "arch/alpha/idle_event.hh"
4612853Sgabeblack@google.com#include "arch/alpha/system.hh"
4712853Sgabeblack@google.com#include "arch/vtophys.hh"
4812853Sgabeblack@google.com#include "base/loader/symtab.hh"
4912853Sgabeblack@google.com#include "cpu/base.hh"
5012853Sgabeblack@google.com#include "cpu/thread_context.hh"
5112853Sgabeblack@google.com#include "dev/platform.hh"
5212853Sgabeblack@google.com#include "kern/linux/events.hh"
5312853Sgabeblack@google.com#include "kern/linux/printk.hh"
5412853Sgabeblack@google.com#include "mem/physical.hh"
5512853Sgabeblack@google.com#include "mem/port.hh"
5612853Sgabeblack@google.com#include "sim/arguments.hh"
5712853Sgabeblack@google.com#include "sim/byteswap.hh"
5812853Sgabeblack@google.com
5912853Sgabeblack@google.comusing namespace std;
6012853Sgabeblack@google.comusing namespace AlphaISA;
6112853Sgabeblack@google.comusing namespace Linux;
6212853Sgabeblack@google.com
6312853Sgabeblack@google.comLinuxAlphaSystem::LinuxAlphaSystem(Params *p)
6412853Sgabeblack@google.com    : AlphaSystem(p)
6512853Sgabeblack@google.com{
6612853Sgabeblack@google.com    Addr addr = 0;
6712853Sgabeblack@google.com
6812853Sgabeblack@google.com    /**
6912853Sgabeblack@google.com     * The symbol swapper_pg_dir marks the beginning of the kernel and
7012853Sgabeblack@google.com     * the location of bootloader passed arguments
7112853Sgabeblack@google.com     */
7212853Sgabeblack@google.com    if (!kernelSymtab->findAddress("swapper_pg_dir", KernelStart)) {
7312853Sgabeblack@google.com        panic("Could not determine start location of kernel");
7412853Sgabeblack@google.com    }
7512853Sgabeblack@google.com
7612853Sgabeblack@google.com    /**
7712853Sgabeblack@google.com     * Since we aren't using a bootloader, we have to copy the
7812853Sgabeblack@google.com     * kernel arguments directly into the kernel's memory.
7912853Sgabeblack@google.com     */
8012853Sgabeblack@google.com    virtPort->writeBlob(CommandLine(), (uint8_t*)params()->boot_osflags.c_str(),
8112853Sgabeblack@google.com                params()->boot_osflags.length()+1);
8212853Sgabeblack@google.com
8312853Sgabeblack@google.com    /**
8412853Sgabeblack@google.com     * find the address of the est_cycle_freq variable and insert it
8512853Sgabeblack@google.com     * so we don't through the lengthly process of trying to
8612853Sgabeblack@google.com     * calculated it by using the PIT, RTC, etc.
8712853Sgabeblack@google.com     */
8812853Sgabeblack@google.com    if (kernelSymtab->findAddress("est_cycle_freq", addr))
8912853Sgabeblack@google.com        virtPort->write(addr, (uint64_t)(SimClock::Frequency /
9012853Sgabeblack@google.com                    p->boot_cpu_frequency));
9112853Sgabeblack@google.com
9212853Sgabeblack@google.com
9312853Sgabeblack@google.com    /**
9412853Sgabeblack@google.com     * EV5 only supports 127 ASNs so we are going to tell the kernel that the
9512853Sgabeblack@google.com     * paritiuclar EV6 we have only supports 127 asns.
9612853Sgabeblack@google.com     * @todo At some point we should change ev5.hh and the palcode to support
9712853Sgabeblack@google.com     * 255 ASNs.
9812853Sgabeblack@google.com     */
9912853Sgabeblack@google.com    if (kernelSymtab->findAddress("dp264_mv", addr))
10012853Sgabeblack@google.com        virtPort->write(addr + 0x18, LittleEndianGuest::htog((uint32_t)127));
10112853Sgabeblack@google.com    else
10212853Sgabeblack@google.com        panic("could not find dp264_mv\n");
10312853Sgabeblack@google.com
10412853Sgabeblack@google.com#ifndef NDEBUG
10512853Sgabeblack@google.com    kernelPanicEvent = addKernelFuncEvent<BreakPCEvent>("panic");
10612853Sgabeblack@google.com    if (!kernelPanicEvent)
10712853Sgabeblack@google.com        panic("could not find kernel symbol \'panic\'");
10812853Sgabeblack@google.com
10912853Sgabeblack@google.com#if 0
11012853Sgabeblack@google.com    kernelDieEvent = addKernelFuncEvent<BreakPCEvent>("die_if_kernel");
11112853Sgabeblack@google.com    if (!kernelDieEvent)
11212853Sgabeblack@google.com        panic("could not find kernel symbol \'die_if_kernel\'");
11312853Sgabeblack@google.com#endif
11412853Sgabeblack@google.com
11512853Sgabeblack@google.com#endif
11612853Sgabeblack@google.com
11712853Sgabeblack@google.com    /**
11812853Sgabeblack@google.com     * Any time ide_delay_50ms, calibarte_delay or
11912853Sgabeblack@google.com     * determine_cpu_caches is called just skip the
12012853Sgabeblack@google.com     * function. Currently determine_cpu_caches only is used put
12112853Sgabeblack@google.com     * information in proc, however if that changes in the future we
12212853Sgabeblack@google.com     * will have to fill in the cache size variables appropriately.
12312853Sgabeblack@google.com     */
12412853Sgabeblack@google.com
12512853Sgabeblack@google.com    skipIdeDelay50msEvent =
12612853Sgabeblack@google.com        addKernelFuncEvent<SkipFuncEvent>("ide_delay_50ms");
12712853Sgabeblack@google.com    skipDelayLoopEvent =
12812853Sgabeblack@google.com        addKernelFuncEvent<SkipDelayLoopEvent>("calibrate_delay");
12912853Sgabeblack@google.com    skipCacheProbeEvent =
13012853Sgabeblack@google.com        addKernelFuncEvent<SkipFuncEvent>("determine_cpu_caches");
13112853Sgabeblack@google.com    debugPrintkEvent = addKernelFuncEvent<DebugPrintkEvent>("dprintk");
13212853Sgabeblack@google.com    idleStartEvent = addKernelFuncEvent<IdleStartEvent>("cpu_idle");
13312853Sgabeblack@google.com
13412853Sgabeblack@google.com    // Disable for now as it runs into panic() calls in VPTr methods
13512853Sgabeblack@google.com    // (see sim/vptr.hh).  Once those bugs are fixed, we can
13612853Sgabeblack@google.com    // re-enable, but we should find a better way to turn it on than
13712853Sgabeblack@google.com    // using DTRACE(Thread), since looking at a trace flag at tick 0
13812853Sgabeblack@google.com    // leads to non-intuitive behavior with --trace-start.
13912853Sgabeblack@google.com    if (false && kernelSymtab->findAddress("alpha_switch_to", addr)) {
14012853Sgabeblack@google.com        printThreadEvent = new PrintThreadInfo(&pcEventQueue, "threadinfo",
14112853Sgabeblack@google.com                                               addr + sizeof(MachInst) * 6);
14212853Sgabeblack@google.com    } else {
14312853Sgabeblack@google.com        printThreadEvent = NULL;
14412853Sgabeblack@google.com    }
14512853Sgabeblack@google.com}
14612853Sgabeblack@google.com
14712853Sgabeblack@google.comLinuxAlphaSystem::~LinuxAlphaSystem()
14812853Sgabeblack@google.com{
14912853Sgabeblack@google.com#ifndef NDEBUG
15012853Sgabeblack@google.com    delete kernelPanicEvent;
15112853Sgabeblack@google.com#endif
15212853Sgabeblack@google.com    delete skipIdeDelay50msEvent;
15312853Sgabeblack@google.com    delete skipDelayLoopEvent;
15412853Sgabeblack@google.com    delete skipCacheProbeEvent;
15512853Sgabeblack@google.com    delete debugPrintkEvent;
15612853Sgabeblack@google.com    delete idleStartEvent;
15712853Sgabeblack@google.com    delete printThreadEvent;
15812853Sgabeblack@google.com}
15912853Sgabeblack@google.com
16012853Sgabeblack@google.comvoid
16112853Sgabeblack@google.comLinuxAlphaSystem::setDelayLoop(ThreadContext *tc)
16212853Sgabeblack@google.com{
16312853Sgabeblack@google.com    Addr addr = 0;
16412853Sgabeblack@google.com    if (kernelSymtab->findAddress("loops_per_jiffy", addr)) {
16512853Sgabeblack@google.com        Tick cpuFreq = tc->getCpuPtr()->frequency();
16612853Sgabeblack@google.com        Tick intrFreq = platform->intrFrequency();
16712853Sgabeblack@google.com        VirtualPort *vp;
16812853Sgabeblack@google.com
16912853Sgabeblack@google.com        vp = tc->getVirtPort();
17012853Sgabeblack@google.com        vp->writeHtoG(addr, (uint32_t)((cpuFreq / intrFreq) * 0.9988));
17112853Sgabeblack@google.com    }
17212853Sgabeblack@google.com}
17312853Sgabeblack@google.com
17412853Sgabeblack@google.comvoid
17512853Sgabeblack@google.comLinuxAlphaSystem::SkipDelayLoopEvent::process(ThreadContext *tc)
17612853Sgabeblack@google.com{
17712853Sgabeblack@google.com    SkipFuncEvent::process(tc);
17812853Sgabeblack@google.com    // calculate and set loops_per_jiffy
17912853Sgabeblack@google.com    ((LinuxAlphaSystem *)tc->getSystemPtr())->setDelayLoop(tc);
18012853Sgabeblack@google.com}
18112853Sgabeblack@google.com
18212853Sgabeblack@google.comvoid
18312853Sgabeblack@google.comLinuxAlphaSystem::PrintThreadInfo::process(ThreadContext *tc)
18412853Sgabeblack@google.com{
18512853Sgabeblack@google.com    Linux::ThreadInfo ti(tc);
18612853Sgabeblack@google.com
18712853Sgabeblack@google.com    DPRINTF(Thread, "Currently Executing Thread %s, pid %d, started at: %d\n",
18812853Sgabeblack@google.com            ti.curTaskName(), ti.curTaskPID(), ti.curTaskStart());
18912853Sgabeblack@google.com}
19012853Sgabeblack@google.com
19112853Sgabeblack@google.comLinuxAlphaSystem *
19212853Sgabeblack@google.comLinuxAlphaSystemParams::create()
19312853Sgabeblack@google.com{
19412853Sgabeblack@google.com    return new LinuxAlphaSystem(this);
19512853Sgabeblack@google.com}
19612853Sgabeblack@google.com