system.cc revision 10037:5cac77888310
19885Sstever@gmail.com/*
29885Sstever@gmail.com * Copyright (c) 2010, 2012-2013 ARM Limited
39885Sstever@gmail.com * All rights reserved
410036SAli.Saidi@ARM.com *
59885Sstever@gmail.com * The license below extends only to copyright in the software and shall
610036SAli.Saidi@ARM.com * not be construed as granting a license to any other intellectual
79885Sstever@gmail.com * property including but not limited to intellectual property relating
89885Sstever@gmail.com * to a hardware implementation of the functionality of the software
99885Sstever@gmail.com * licensed hereunder.  You may use the software subject to the license
109885Sstever@gmail.com * terms below provided that you ensure that this notice is replicated
119885Sstever@gmail.com * unmodified and in its entirety in all distributions of the software,
129885Sstever@gmail.com * modified or unmodified, in source code or in binary form.
1310315Snilay@cs.wisc.edu *
149885Sstever@gmail.com * Copyright (c) 2002-2006 The Regents of The University of Michigan
159885Sstever@gmail.com * All rights reserved.
169885Sstever@gmail.com *
1710036SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without
189885Sstever@gmail.com * modification, are permitted provided that the following conditions are
199885Sstever@gmail.com * met: redistributions of source code must retain the above copyright
2010315Snilay@cs.wisc.edu * notice, this list of conditions and the following disclaimer;
219885Sstever@gmail.com * redistributions in binary form must reproduce the above copyright
2210315Snilay@cs.wisc.edu * notice, this list of conditions and the following disclaimer in the
239885Sstever@gmail.com * documentation and/or other materials provided with the distribution;
249885Sstever@gmail.com * neither the name of the copyright holders nor the names of its
259885Sstever@gmail.com * contributors may be used to endorse or promote products derived from
2610736Snilay@cs.wisc.edu * this software without specific prior written permission.
279885Sstever@gmail.com *
289885Sstever@gmail.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
299885Sstever@gmail.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
309885Sstever@gmail.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
319885Sstever@gmail.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
329885Sstever@gmail.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
339885Sstever@gmail.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
349885Sstever@gmail.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
359885Sstever@gmail.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
369885Sstever@gmail.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
379885Sstever@gmail.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
389885Sstever@gmail.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
399885Sstever@gmail.com *
409885Sstever@gmail.com * Authors: Ali Saidi
419885Sstever@gmail.com */
429885Sstever@gmail.com
4310315Snilay@cs.wisc.edu#include <iostream>
4410036SAli.Saidi@ARM.com
4510315Snilay@cs.wisc.edu#include "arch/arm/system.hh"
469885Sstever@gmail.com#include "base/loader/object_file.hh"
479885Sstever@gmail.com#include "base/loader/symtab.hh"
489885Sstever@gmail.com#include "cpu/thread_context.hh"
499885Sstever@gmail.com#include "mem/physical.hh"
5010036SAli.Saidi@ARM.com#include "mem/fs_translating_port_proxy.hh"
519885Sstever@gmail.com#include "sim/full_system.hh"
529885Sstever@gmail.com
539885Sstever@gmail.comusing namespace std;
549885Sstever@gmail.comusing namespace Linux;
559885Sstever@gmail.com
569885Sstever@gmail.comArmSystem::ArmSystem(Params *p)
579885Sstever@gmail.com    : System(p), bootldr(NULL), _haveSecurity(p->have_security),
5810036SAli.Saidi@ARM.com      _haveLPAE(p->have_lpae),
599885Sstever@gmail.com      _haveVirtualization(p->have_virtualization),
609885Sstever@gmail.com      _haveGenericTimer(p->have_generic_timer),
619885Sstever@gmail.com      _highestELIs64(p->highest_el_is_64),
6210315Snilay@cs.wisc.edu      _resetAddr64(p->reset_addr_64),
6310315Snilay@cs.wisc.edu      _physAddrRange64(p->phys_addr_range_64),
6410315Snilay@cs.wisc.edu      _haveLargeAsid64(p->have_large_asid_64),
6510315Snilay@cs.wisc.edu      multiProc(p->multi_proc)
6610315Snilay@cs.wisc.edu{
6710315Snilay@cs.wisc.edu    // Check if the physical address range is valid
6810315Snilay@cs.wisc.edu    if (_highestELIs64 && (
6910315Snilay@cs.wisc.edu            _physAddrRange64 < 32 ||
709885Sstever@gmail.com            _physAddrRange64 > 48 ||
7110451Snilay@cs.wisc.edu            (_physAddrRange64 % 4 != 0 && _physAddrRange64 != 42))) {
729885Sstever@gmail.com        fatal("Invalid physical address range (%d)\n", _physAddrRange64);
7310036SAli.Saidi@ARM.com    }
7410736Snilay@cs.wisc.edu
7510736Snilay@cs.wisc.edu    if (p->boot_loader != "") {
7610736Snilay@cs.wisc.edu        bootldr = createObjectFile(p->boot_loader);
779885Sstever@gmail.com
789885Sstever@gmail.com        if (!bootldr)
799885Sstever@gmail.com            fatal("Could not read bootloader: %s\n", p->boot_loader);
809885Sstever@gmail.com
819885Sstever@gmail.com        if ((bootldr->getArch() == ObjectFile::Arm64) && !_highestELIs64) {
829885Sstever@gmail.com            warn("Highest ARM exception-level set to AArch32 but bootloader "
839885Sstever@gmail.com                  "is for AArch64. Assuming you wanted these to match.\n");
8410736Snilay@cs.wisc.edu            _highestELIs64 = true;
859885Sstever@gmail.com        } else if ((bootldr->getArch() == ObjectFile::Arm) && _highestELIs64) {
869885Sstever@gmail.com            warn("Highest ARM exception-level set to AArch64 but bootloader "
879885Sstever@gmail.com                  "is for AArch32. Assuming you wanted these to match.\n");
889885Sstever@gmail.com            _highestELIs64 = false;
899885Sstever@gmail.com        }
909885Sstever@gmail.com
919885Sstever@gmail.com        bootldr->loadGlobalSymbols(debugSymbolTable);
929885Sstever@gmail.com
939885Sstever@gmail.com    }
949885Sstever@gmail.com    debugPrintkEvent = addKernelFuncEvent<DebugPrintkEvent>("dprintk");
9510036SAli.Saidi@ARM.com}
969885Sstever@gmail.com
979885Sstever@gmail.comvoid
989885Sstever@gmail.comArmSystem::initState()
999885Sstever@gmail.com{
1009885Sstever@gmail.com    // Moved from the constructor to here since it relies on the
1019885Sstever@gmail.com    // address map being resolved in the interconnect
10210736Snilay@cs.wisc.edu
10310315Snilay@cs.wisc.edu    // Call the initialisation of the super class
10410315Snilay@cs.wisc.edu    System::initState();
10510315Snilay@cs.wisc.edu
1069885Sstever@gmail.com    const Params* p = params();
1079885Sstever@gmail.com
1089885Sstever@gmail.com    if (bootldr) {
1099885Sstever@gmail.com        bootldr->loadSections(physProxy);
1109885Sstever@gmail.com
1119885Sstever@gmail.com        uint8_t jump_to_bl_32[] =
11210736Snilay@cs.wisc.edu        {
11310736Snilay@cs.wisc.edu            0x07, 0xf0, 0xa0, 0xe1  // branch to r7 in aarch32
11410736Snilay@cs.wisc.edu        };
11510736Snilay@cs.wisc.edu
11610736Snilay@cs.wisc.edu        uint8_t jump_to_bl_64[] =
11710736Snilay@cs.wisc.edu        {
11810736Snilay@cs.wisc.edu            0xe0, 0x00, 0x1f, 0xd6  // instruction "br x7" in aarch64
11910736Snilay@cs.wisc.edu        };
12010736Snilay@cs.wisc.edu
1219885Sstever@gmail.com        // write the jump to branch table into address 0
1229885Sstever@gmail.com        if (!_highestELIs64)
1239885Sstever@gmail.com            physProxy.writeBlob(0x0, jump_to_bl_32, sizeof(jump_to_bl_32));
1249885Sstever@gmail.com        else
1259885Sstever@gmail.com            physProxy.writeBlob(0x0, jump_to_bl_64, sizeof(jump_to_bl_64));
12610036SAli.Saidi@ARM.com
1279885Sstever@gmail.com        inform("Using bootloader at address %#x\n", bootldr->entryPoint());
1289885Sstever@gmail.com
1299885Sstever@gmail.com        // Put the address of the boot loader into r7 so we know
1309885Sstever@gmail.com        // where to branch to after the reset fault
1319885Sstever@gmail.com        // All other values needed by the boot loader to know what to do
1329885Sstever@gmail.com        if (!p->gic_cpu_addr || !p->flags_addr)
1339885Sstever@gmail.com            fatal("gic_cpu_addr && flags_addr must be set with bootloader\n");
134
135        for (int i = 0; i < threadContexts.size(); i++) {
136            if (!_highestELIs64)
137                threadContexts[i]->setIntReg(3, (kernelEntry & loadAddrMask) +
138                        loadAddrOffset);
139            threadContexts[i]->setIntReg(4, params()->gic_cpu_addr);
140            threadContexts[i]->setIntReg(5, params()->flags_addr);
141            threadContexts[i]->setIntReg(7, bootldr->entryPoint());
142        }
143        inform("Using kernel entry physical address at %#x\n",
144               (kernelEntry & loadAddrMask) + loadAddrOffset);
145    } else {
146        // Set the initial PC to be at start of the kernel code
147        if (!_highestELIs64)
148            threadContexts[0]->pcState((kernelEntry & loadAddrMask) +
149                    loadAddrOffset);
150    }
151}
152
153GenericTimer::ArchTimer *
154ArmSystem::getArchTimer(int cpu_id) const
155{
156    if (_genericTimer) {
157        return _genericTimer->getArchTimer(cpu_id);
158    }
159    return NULL;
160}
161
162GenericTimer::SystemCounter *
163ArmSystem::getSystemCounter() const
164{
165    if (_genericTimer) {
166        return _genericTimer->getSystemCounter();
167    }
168    return NULL;
169}
170
171bool
172ArmSystem::haveSecurity(ThreadContext *tc)
173{
174    if (!FullSystem)
175        return false;
176
177    ArmSystem *a_sys = dynamic_cast<ArmSystem *>(tc->getSystemPtr());
178    assert(a_sys);
179    return a_sys->haveSecurity();
180}
181
182
183ArmSystem::~ArmSystem()
184{
185    if (debugPrintkEvent)
186        delete debugPrintkEvent;
187}
188
189bool
190ArmSystem::haveLPAE(ThreadContext *tc)
191{
192    if (!FullSystem)
193        return false;
194
195    ArmSystem *a_sys = dynamic_cast<ArmSystem *>(tc->getSystemPtr());
196    assert(a_sys);
197    return a_sys->haveLPAE();
198}
199
200bool
201ArmSystem::haveVirtualization(ThreadContext *tc)
202{
203    if (!FullSystem)
204        return false;
205
206    ArmSystem *a_sys = dynamic_cast<ArmSystem *>(tc->getSystemPtr());
207    assert(a_sys);
208    return a_sys->haveVirtualization();
209}
210
211bool
212ArmSystem::highestELIs64(ThreadContext *tc)
213{
214    return dynamic_cast<ArmSystem *>(tc->getSystemPtr())->highestELIs64();
215}
216
217ExceptionLevel
218ArmSystem::highestEL(ThreadContext *tc)
219{
220    return dynamic_cast<ArmSystem *>(tc->getSystemPtr())->highestEL();
221}
222
223Addr
224ArmSystem::resetAddr64(ThreadContext *tc)
225{
226    return dynamic_cast<ArmSystem *>(tc->getSystemPtr())->resetAddr64();
227}
228
229uint8_t
230ArmSystem::physAddrRange(ThreadContext *tc)
231{
232    return dynamic_cast<ArmSystem *>(tc->getSystemPtr())->physAddrRange();
233}
234
235Addr
236ArmSystem::physAddrMask(ThreadContext *tc)
237{
238    return dynamic_cast<ArmSystem *>(tc->getSystemPtr())->physAddrMask();
239}
240
241bool
242ArmSystem::haveLargeAsid64(ThreadContext *tc)
243{
244    return dynamic_cast<ArmSystem *>(tc->getSystemPtr())->haveLargeAsid64();
245}
246ArmSystem *
247ArmSystemParams::create()
248{
249    return new ArmSystem(this);
250}
251