system.cc revision 5222
1/*
2 * Copyright .AN) 2007 MIPS Technologies, Inc.  All Rights Reserved
3 *
4 * This software is part of the M5 simulator.
5 *
6 * THIS IS A LEGAL AGREEMENT.  BY DOWNLOADING, USING, COPYING, CREATING
7 * DERIVATIVE WORKS, AND/OR DISTRIBUTING THIS SOFTWARE YOU ARE AGREEING
8 * TO THESE TERMS AND CONDITIONS.
9 *
10 * Permission is granted to use, copy, create derivative works and
11 * distribute this software and such derivative works for any purpose,
12 * so long as (1) the copyright notice above, this grant of permission,
13 * and the disclaimer below appear in all copies and derivative works
14 * made, (2) the copyright notice above is augmented as appropriate to
15 * reflect the addition of any new copyrightable work in a derivative
16 * work (e.g., Copyright .AN) <Publication Year> Copyright Owner), and (3)
17 * the name of MIPS Technologies, Inc. ($B!H(BMIPS$B!I(B) is not used in any
18 * advertising or publicity pertaining to the use or distribution of
19 * this software without specific, written prior authorization.
20 *
21 * THIS SOFTWARE IS PROVIDED $B!H(BAS IS.$B!I(B  MIPS MAKES NO WARRANTIES AND
22 * DISCLAIMS ALL WARRANTIES, WHETHER EXPRESS, STATUTORY, IMPLIED OR
23 * OTHERWISE, INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
25 * NON-INFRINGEMENT OF THIRD PARTY RIGHTS, REGARDING THIS SOFTWARE.
26 * IN NO EVENT SHALL MIPS BE LIABLE FOR ANY DAMAGES, INCLUDING DIRECT,
27 * INDIRECT, INCIDENTAL, CONSEQUENTIAL, SPECIAL, OR PUNITIVE DAMAGES OF
28 * ANY KIND OR NATURE, ARISING OUT OF OR IN CONNECTION WITH THIS AGREEMENT,
29 * THIS SOFTWARE AND/OR THE USE OF THIS SOFTWARE, WHETHER SUCH LIABILITY
30 * IS ASSERTED ON THE BASIS OF CONTRACT, TORT (INCLUDING NEGLIGENCE OR
31 * STRICT LIABILITY), OR OTHERWISE, EVEN IF MIPS HAS BEEN WARNED OF THE
32 * POSSIBILITY OF ANY SUCH LOSS OR DAMAGE IN ADVANCE.
33 *
34 *
35 * Authors: Ali G. Saidi
36 *          Lisa R. Hsu
37 *          Nathan L. Binkert
38 *          Steven K. Reinhardt
39 */
40
41/**
42 * @file
43 * This code loads the linux kernel, console, pal and patches certain
44 * functions.  The symbol tables are loaded so that traces can show
45 * the executing function and we can skip functions. Various delay
46 * loops are skipped and their final values manually computed to speed
47 * up boot time.
48 */
49
50#include "arch/vtophys.hh"
51#include "arch/mips/idle_event.hh"
52#include "arch/mips/linux/system.hh"
53#include "arch/mips/linux/threadinfo.hh"
54#include "arch/mips/system.hh"
55#include "base/loader/symtab.hh"
56#include "cpu/thread_context.hh"
57#include "cpu/base.hh"
58#include "dev/platform.hh"
59#include "kern/linux/printk.hh"
60#include "kern/linux/events.hh"
61#include "mem/physical.hh"
62#include "mem/port.hh"
63#include "sim/arguments.hh"
64#include "sim/byteswap.hh"
65
66using namespace std;
67using namespace MipsISA;
68using namespace Linux;
69
70LinuxMipsSystem::LinuxMipsSystem(Params *p)
71    : MipsSystem(p)
72{
73    Addr addr = 0;
74
75    /**
76     * The symbol swapper_pg_dir marks the beginning of the kernel and
77     * the location of bootloader passed arguments
78     */
79    if (!kernelSymtab->findAddress("swapper_pg_dir", KernelStart)) {
80        panic("Could not determine start location of kernel");
81    }
82
83    /**
84     * Since we aren't using a bootloader, we have to copy the
85     * kernel arguments directly into the kernel's memory.
86     */
87    virtPort.writeBlob(CommandLine(), (uint8_t*)params()->boot_osflags.c_str(),
88                params()->boot_osflags.length()+1);
89
90    /**
91     * find the address of the est_cycle_freq variable and insert it
92     * so we don't through the lengthly process of trying to
93     * calculated it by using the PIT, RTC, etc.
94     */
95    if (kernelSymtab->findAddress("est_cycle_freq", addr))
96        virtPort.write(addr, (uint64_t)(Clock::Frequency /
97                    p->boot_cpu_frequency));
98
99
100    /**
101     * EV5 only supports 127 ASNs so we are going to tell the kernel that the
102     * paritiuclar EV6 we have only supports 127 asns.
103     * @todo At some point we should change ev5.hh and the palcode to support
104     * 255 ASNs.
105     */
106    if (kernelSymtab->findAddress("dp264_mv", addr))
107        virtPort.write(addr + 0x18, LittleEndianGuest::htog((uint32_t)127));
108    else
109        panic("could not find dp264_mv\n");
110
111#ifndef NDEBUG
112    kernelPanicEvent = addKernelFuncEvent<BreakPCEvent>("panic");
113    if (!kernelPanicEvent)
114        panic("could not find kernel symbol \'panic\'");
115
116#if 0
117    kernelDieEvent = addKernelFuncEvent<BreakPCEvent>("die_if_kernel");
118    if (!kernelDieEvent)
119        panic("could not find kernel symbol \'die_if_kernel\'");
120#endif
121
122#endif
123
124    /**
125     * Any time ide_delay_50ms, calibarte_delay or
126     * determine_cpu_caches is called just skip the
127     * function. Currently determine_cpu_caches only is used put
128     * information in proc, however if that changes in the future we
129     * will have to fill in the cache size variables appropriately.
130     */
131
132    skipIdeDelay50msEvent =
133        addKernelFuncEvent<SkipFuncEvent>("ide_delay_50ms");
134    skipDelayLoopEvent =
135        addKernelFuncEvent<SkipDelayLoopEvent>("calibrate_delay");
136    skipCacheProbeEvent =
137        addKernelFuncEvent<SkipFuncEvent>("determine_cpu_caches");
138    debugPrintkEvent = addKernelFuncEvent<DebugPrintkEvent>("dprintk");
139    idleStartEvent = addKernelFuncEvent<IdleStartEvent>("cpu_idle");
140
141    // Disable for now as it runs into panic() calls in VPTr methods
142    // (see sim/vptr.hh).  Once those bugs are fixed, we can
143    // re-enable, but we should find a better way to turn it on than
144    // using DTRACE(Thread), since looking at a trace flag at tick 0
145    // leads to non-intuitive behavior with --trace-start.
146    if (false && kernelSymtab->findAddress("mips_switch_to", addr)) {
147        printThreadEvent = new PrintThreadInfo(&pcEventQueue, "threadinfo",
148                                               addr + sizeof(MachInst) * 6);
149    } else {
150        printThreadEvent = NULL;
151    }
152}
153
154LinuxMipsSystem::~LinuxMipsSystem()
155{
156#ifndef NDEBUG
157    delete kernelPanicEvent;
158#endif
159    delete skipIdeDelay50msEvent;
160    delete skipDelayLoopEvent;
161    delete skipCacheProbeEvent;
162    delete debugPrintkEvent;
163    delete idleStartEvent;
164    delete printThreadEvent;
165}
166
167
168void
169LinuxMipsSystem::setDelayLoop(ThreadContext *tc)
170{
171    Addr addr = 0;
172    if (kernelSymtab->findAddress("loops_per_jiffy", addr)) {
173        Tick cpuFreq = tc->getCpuPtr()->frequency();
174        Tick intrFreq = platform->intrFrequency();
175        VirtualPort *vp;
176
177        vp = tc->getVirtPort();
178        vp->writeHtoG(addr, (uint32_t)((cpuFreq / intrFreq) * 0.9988));
179        tc->delVirtPort(vp);
180    }
181}
182
183
184void
185LinuxMipsSystem::SkipDelayLoopEvent::process(ThreadContext *tc)
186{
187    SkipFuncEvent::process(tc);
188    // calculate and set loops_per_jiffy
189    ((LinuxMipsSystem *)tc->getSystemPtr())->setDelayLoop(tc);
190}
191
192void
193LinuxMipsSystem::PrintThreadInfo::process(ThreadContext *tc)
194{
195    Linux::ThreadInfo ti(tc);
196
197    DPRINTF(Thread, "Currently Executing Thread %s, pid %d, started at: %d\n",
198            ti.curTaskName(), ti.curTaskPID(), ti.curTaskStart());
199}
200
201LinuxMipsSystem *
202LinuxMipsSystemParams::create()
203{
204    return new LinuxMipsSystem(this);
205}
206