system.cc revision 12318:1402d90f344f
112070Snikos.nikoleris@arm.com/* 29380SAndreas.Sandberg@ARM.com * Copyright (c) 2010, 2012-2013, 2015,2017 ARM Limited 39380SAndreas.Sandberg@ARM.com * All rights reserved 49380SAndreas.Sandberg@ARM.com * 59380SAndreas.Sandberg@ARM.com * The license below extends only to copyright in the software and shall 69380SAndreas.Sandberg@ARM.com * not be construed as granting a license to any other intellectual 79380SAndreas.Sandberg@ARM.com * property including but not limited to intellectual property relating 89380SAndreas.Sandberg@ARM.com * to a hardware implementation of the functionality of the software 99380SAndreas.Sandberg@ARM.com * licensed hereunder. You may use the software subject to the license 109380SAndreas.Sandberg@ARM.com * terms below provided that you ensure that this notice is replicated 119380SAndreas.Sandberg@ARM.com * unmodified and in its entirety in all distributions of the software, 129380SAndreas.Sandberg@ARM.com * modified or unmodified, in source code or in binary form. 139380SAndreas.Sandberg@ARM.com * 149380SAndreas.Sandberg@ARM.com * Copyright (c) 2002-2006 The Regents of The University of Michigan 159380SAndreas.Sandberg@ARM.com * All rights reserved. 169380SAndreas.Sandberg@ARM.com * 179380SAndreas.Sandberg@ARM.com * Redistribution and use in source and binary forms, with or without 189380SAndreas.Sandberg@ARM.com * modification, are permitted provided that the following conditions are 199380SAndreas.Sandberg@ARM.com * met: redistributions of source code must retain the above copyright 209380SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer; 219380SAndreas.Sandberg@ARM.com * redistributions in binary form must reproduce the above copyright 229380SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer in the 239380SAndreas.Sandberg@ARM.com * documentation and/or other materials provided with the distribution; 249380SAndreas.Sandberg@ARM.com * neither the name of the copyright holders nor the names of its 259380SAndreas.Sandberg@ARM.com * contributors may be used to endorse or promote products derived from 269380SAndreas.Sandberg@ARM.com * this software without specific prior written permission. 279380SAndreas.Sandberg@ARM.com * 289380SAndreas.Sandberg@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 299380SAndreas.Sandberg@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 309380SAndreas.Sandberg@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 319380SAndreas.Sandberg@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 329380SAndreas.Sandberg@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 339380SAndreas.Sandberg@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 349380SAndreas.Sandberg@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 359380SAndreas.Sandberg@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 369380SAndreas.Sandberg@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 379792Sandreas.hansson@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 389380SAndreas.Sandberg@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 399380SAndreas.Sandberg@ARM.com * 4012070Snikos.nikoleris@arm.com * Authors: Ali Saidi 419380SAndreas.Sandberg@ARM.com */ 429380SAndreas.Sandberg@ARM.com 439380SAndreas.Sandberg@ARM.com#include "arch/arm/system.hh" 4411682Sandreas.hansson@arm.com 4511682Sandreas.hansson@arm.com#include <iostream> 4612070Snikos.nikoleris@arm.com 4711682Sandreas.hansson@arm.com#include "base/loader/object_file.hh" 4812070Snikos.nikoleris@arm.com#include "base/loader/symtab.hh" 499380SAndreas.Sandberg@ARM.com#include "cpu/thread_context.hh" 509654SAndreas.Sandberg@ARM.com#include "mem/fs_translating_port_proxy.hh" 519654SAndreas.Sandberg@ARM.com#include "mem/physical.hh" 529380SAndreas.Sandberg@ARM.com#include "sim/full_system.hh" 539380SAndreas.Sandberg@ARM.com 549380SAndreas.Sandberg@ARM.comusing namespace std; 559380SAndreas.Sandberg@ARM.comusing namespace Linux; 569380SAndreas.Sandberg@ARM.com 579380SAndreas.Sandberg@ARM.comArmSystem::ArmSystem(Params *p) 589380SAndreas.Sandberg@ARM.com : System(p), 599380SAndreas.Sandberg@ARM.com bootLoaders(), bootldr(nullptr), 609380SAndreas.Sandberg@ARM.com _haveSecurity(p->have_security), 619380SAndreas.Sandberg@ARM.com _haveLPAE(p->have_lpae), 629380SAndreas.Sandberg@ARM.com _haveVirtualization(p->have_virtualization), 639792Sandreas.hansson@arm.com _genericTimer(nullptr), 6411156Sandreas.sandberg@arm.com _highestELIs64(p->highest_el_is_64), 6512070Snikos.nikoleris@arm.com _resetAddr64(p->reset_addr_64), 669792Sandreas.hansson@arm.com _physAddrRange64(p->phys_addr_range_64), 679380SAndreas.Sandberg@ARM.com _haveLargeAsid64(p->have_large_asid_64), 689380SAndreas.Sandberg@ARM.com _m5opRange(p->m5ops_base ? 699380SAndreas.Sandberg@ARM.com RangeSize(p->m5ops_base, 0x10000) : 709792Sandreas.hansson@arm.com AddrRange(1, 0)), // Create an empty range if disabled 719380SAndreas.Sandberg@ARM.com multiProc(p->multi_proc) 729380SAndreas.Sandberg@ARM.com{ 739380SAndreas.Sandberg@ARM.com // Check if the physical address range is valid 7410512SAli.Saidi@ARM.com if (_highestELIs64 && ( 7512070Snikos.nikoleris@arm.com _physAddrRange64 < 32 || 769380SAndreas.Sandberg@ARM.com _physAddrRange64 > 48 || 779380SAndreas.Sandberg@ARM.com (_physAddrRange64 % 4 != 0 && _physAddrRange64 != 42))) { 789792Sandreas.hansson@arm.com fatal("Invalid physical address range (%d)\n", _physAddrRange64); 799380SAndreas.Sandberg@ARM.com } 809380SAndreas.Sandberg@ARM.com 8111156Sandreas.sandberg@arm.com bootLoaders.reserve(p->boot_loader.size()); 829380SAndreas.Sandberg@ARM.com for (const auto &bl : p->boot_loader) { 8312070Snikos.nikoleris@arm.com std::unique_ptr<ObjectFile> obj; 849380SAndreas.Sandberg@ARM.com obj.reset(createObjectFile(bl)); 859793Sakash.bagdia@arm.com 869380SAndreas.Sandberg@ARM.com fatal_if(!obj, "Could not read bootloader: %s\n", bl); 8711156Sandreas.sandberg@arm.com bootLoaders.emplace_back(std::move(obj)); 8811156Sandreas.sandberg@arm.com } 899793Sakash.bagdia@arm.com 909380SAndreas.Sandberg@ARM.com if (kernel) { 919380SAndreas.Sandberg@ARM.com bootldr = getBootLoader(kernel); 929380SAndreas.Sandberg@ARM.com } else if (!bootLoaders.empty()) { 939380SAndreas.Sandberg@ARM.com // No kernel specified, default to the first boot loader 949380SAndreas.Sandberg@ARM.com bootldr = bootLoaders[0].get(); 959380SAndreas.Sandberg@ARM.com } 969380SAndreas.Sandberg@ARM.com 979380SAndreas.Sandberg@ARM.com if (!bootLoaders.empty() && !bootldr) 989380SAndreas.Sandberg@ARM.com fatal("Can't find a matching boot loader / kernel combination!"); 999380SAndreas.Sandberg@ARM.com 1009380SAndreas.Sandberg@ARM.com if (bootldr) { 1019380SAndreas.Sandberg@ARM.com bootldr->loadGlobalSymbols(debugSymbolTable); 10210884Sandreas.hansson@arm.com if ((bootldr->getArch() == ObjectFile::Arm64) && !_highestELIs64) { 10310884Sandreas.hansson@arm.com warn("Highest ARM exception-level set to AArch32 but bootloader " 1049380SAndreas.Sandberg@ARM.com "is for AArch64. Assuming you wanted these to match.\n"); 1059380SAndreas.Sandberg@ARM.com _highestELIs64 = true; 1069380SAndreas.Sandberg@ARM.com } else if ((bootldr->getArch() == ObjectFile::Arm) && _highestELIs64) { 1079380SAndreas.Sandberg@ARM.com warn("Highest ARM exception-level set to AArch64 but bootloader " 1089380SAndreas.Sandberg@ARM.com "is for AArch32. Assuming you wanted these to match.\n"); 1099380SAndreas.Sandberg@ARM.com _highestELIs64 = false; 1109380SAndreas.Sandberg@ARM.com } 1119380SAndreas.Sandberg@ARM.com } 1129380SAndreas.Sandberg@ARM.com 1139380SAndreas.Sandberg@ARM.com debugPrintkEvent = addKernelFuncEvent<DebugPrintkEvent>("dprintk"); 11410720Sandreas.hansson@arm.com} 1159793Sakash.bagdia@arm.com 1169793Sakash.bagdia@arm.comvoid 1179380SAndreas.Sandberg@ARM.comArmSystem::initState() 1189380SAndreas.Sandberg@ARM.com{ 1199380SAndreas.Sandberg@ARM.com // Moved from the constructor to here since it relies on the 1209380SAndreas.Sandberg@ARM.com // address map being resolved in the interconnect 1219674Snilay@cs.wisc.edu 1229380SAndreas.Sandberg@ARM.com // Call the initialisation of the super class 1239380SAndreas.Sandberg@ARM.com System::initState(); 1249380SAndreas.Sandberg@ARM.com 1259380SAndreas.Sandberg@ARM.com const Params* p = params(); 1269380SAndreas.Sandberg@ARM.com 1279380SAndreas.Sandberg@ARM.com if (bootldr) { 1289674Snilay@cs.wisc.edu bootldr->loadSections(physProxy); 1299674Snilay@cs.wisc.edu 1309674Snilay@cs.wisc.edu uint8_t jump_to_bl_32[] = 1319674Snilay@cs.wisc.edu { 1329674Snilay@cs.wisc.edu 0x07, 0xf0, 0xa0, 0xe1 // branch to r7 in aarch32 1339380SAndreas.Sandberg@ARM.com }; 1349654SAndreas.Sandberg@ARM.com 1359654SAndreas.Sandberg@ARM.com uint8_t jump_to_bl_64[] = 1369654SAndreas.Sandberg@ARM.com { 1379654SAndreas.Sandberg@ARM.com 0xe0, 0x00, 0x1f, 0xd6 // instruction "br x7" in aarch64 1389654SAndreas.Sandberg@ARM.com }; 1399654SAndreas.Sandberg@ARM.com 1409654SAndreas.Sandberg@ARM.com // write the jump to branch table into address 0 1419654SAndreas.Sandberg@ARM.com if (!_highestELIs64) 1429380SAndreas.Sandberg@ARM.com physProxy.writeBlob(0x0, jump_to_bl_32, sizeof(jump_to_bl_32)); 1439380SAndreas.Sandberg@ARM.com else 1449380SAndreas.Sandberg@ARM.com physProxy.writeBlob(0x0, jump_to_bl_64, sizeof(jump_to_bl_64)); 1459380SAndreas.Sandberg@ARM.com 1469380SAndreas.Sandberg@ARM.com inform("Using bootloader at address %#x\n", bootldr->entryPoint()); 1479380SAndreas.Sandberg@ARM.com 1489793Sakash.bagdia@arm.com // Put the address of the boot loader into r7 so we know 1499793Sakash.bagdia@arm.com // where to branch to after the reset fault 1509380SAndreas.Sandberg@ARM.com // All other values needed by the boot loader to know what to do 1519654SAndreas.Sandberg@ARM.com if (!p->gic_cpu_addr || !p->flags_addr) 1529654SAndreas.Sandberg@ARM.com fatal("gic_cpu_addr && flags_addr must be set with bootloader\n"); 1539654SAndreas.Sandberg@ARM.com 1549654SAndreas.Sandberg@ARM.com for (int i = 0; i < threadContexts.size(); i++) { 15512070Snikos.nikoleris@arm.com if (!_highestELIs64) 15612070Snikos.nikoleris@arm.com threadContexts[i]->setIntReg(3, (kernelEntry & loadAddrMask) + 15712070Snikos.nikoleris@arm.com loadAddrOffset); 15812070Snikos.nikoleris@arm.com threadContexts[i]->setIntReg(4, params()->gic_cpu_addr); 15912070Snikos.nikoleris@arm.com threadContexts[i]->setIntReg(5, params()->flags_addr); 16012070Snikos.nikoleris@arm.com threadContexts[i]->setIntReg(7, bootldr->entryPoint()); 16111604Sandreas.hansson@arm.com } 16212070Snikos.nikoleris@arm.com inform("Using kernel entry physical address at %#x\n", 16312070Snikos.nikoleris@arm.com (kernelEntry & loadAddrMask) + loadAddrOffset); 16412070Snikos.nikoleris@arm.com } else { 16512070Snikos.nikoleris@arm.com // Set the initial PC to be at start of the kernel code 16612070Snikos.nikoleris@arm.com if (!_highestELIs64) 16712070Snikos.nikoleris@arm.com threadContexts[0]->pcState((kernelEntry & loadAddrMask) + 16812070Snikos.nikoleris@arm.com loadAddrOffset); 16912070Snikos.nikoleris@arm.com } 17012070Snikos.nikoleris@arm.com} 17112070Snikos.nikoleris@arm.com 17212070Snikos.nikoleris@arm.comArmSystem* 17312598Snikos.nikoleris@arm.comArmSystem::getArmSystem(ThreadContext *tc) 17412070Snikos.nikoleris@arm.com{ 17512598Snikos.nikoleris@arm.com ArmSystem *a_sys = dynamic_cast<ArmSystem *>(tc->getSystemPtr()); 17612070Snikos.nikoleris@arm.com assert(a_sys); 17712070Snikos.nikoleris@arm.com return a_sys; 17812070Snikos.nikoleris@arm.com} 17912070Snikos.nikoleris@arm.com 18012070Snikos.nikoleris@arm.combool 18112070Snikos.nikoleris@arm.comArmSystem::haveSecurity(ThreadContext *tc) 18212070Snikos.nikoleris@arm.com{ 18312070Snikos.nikoleris@arm.com return FullSystem? getArmSystem(tc)->haveSecurity() : false; 18412070Snikos.nikoleris@arm.com} 18512070Snikos.nikoleris@arm.com 18612070Snikos.nikoleris@arm.com 18712070Snikos.nikoleris@arm.comArmSystem::~ArmSystem() 18812070Snikos.nikoleris@arm.com{ 18912070Snikos.nikoleris@arm.com if (debugPrintkEvent) 1909380SAndreas.Sandberg@ARM.com delete debugPrintkEvent; 1919793Sakash.bagdia@arm.com} 1929793Sakash.bagdia@arm.com 1939793Sakash.bagdia@arm.comObjectFile * 1949793Sakash.bagdia@arm.comArmSystem::getBootLoader(ObjectFile *const obj) 1959827Sakash.bagdia@arm.com{ 1969827Sakash.bagdia@arm.com for (auto &bl : bootLoaders) { 1979827Sakash.bagdia@arm.com if (bl->getArch() == obj->getArch()) 1989827Sakash.bagdia@arm.com return bl.get(); 1999793Sakash.bagdia@arm.com } 2009793Sakash.bagdia@arm.com 2019793Sakash.bagdia@arm.com return nullptr; 2029827Sakash.bagdia@arm.com} 2039827Sakash.bagdia@arm.com 2049827Sakash.bagdia@arm.combool 2059793Sakash.bagdia@arm.comArmSystem::haveLPAE(ThreadContext *tc) 2069380SAndreas.Sandberg@ARM.com{ 2079380SAndreas.Sandberg@ARM.com return FullSystem? getArmSystem(tc)->haveLPAE() : false; 2089380SAndreas.Sandberg@ARM.com} 2099380SAndreas.Sandberg@ARM.com 2109380SAndreas.Sandberg@ARM.combool 2119380SAndreas.Sandberg@ARM.comArmSystem::haveVirtualization(ThreadContext *tc) 2129380SAndreas.Sandberg@ARM.com{ 2139380SAndreas.Sandberg@ARM.com return FullSystem? getArmSystem(tc)->haveVirtualization() : false; 2149380SAndreas.Sandberg@ARM.com} 2159380SAndreas.Sandberg@ARM.com 2169380SAndreas.Sandberg@ARM.combool 2179792Sandreas.hansson@arm.comArmSystem::highestELIs64(ThreadContext *tc) 2189792Sandreas.hansson@arm.com{ 2199792Sandreas.hansson@arm.com return FullSystem? getArmSystem(tc)->highestELIs64() : true; 2209792Sandreas.hansson@arm.com} 2219792Sandreas.hansson@arm.com 2229792Sandreas.hansson@arm.comExceptionLevel 2239792Sandreas.hansson@arm.comArmSystem::highestEL(ThreadContext *tc) 2249792Sandreas.hansson@arm.com{ 2259792Sandreas.hansson@arm.com return FullSystem? getArmSystem(tc)->highestEL() : EL1; 2269792Sandreas.hansson@arm.com} 2279792Sandreas.hansson@arm.com 22810720Sandreas.hansson@arm.combool 22911156Sandreas.sandberg@arm.comArmSystem::haveEL(ThreadContext *tc, ExceptionLevel el) 23011156Sandreas.sandberg@arm.com{ 23112070Snikos.nikoleris@arm.com switch (el) { 23212070Snikos.nikoleris@arm.com case EL0: 2339792Sandreas.hansson@arm.com case EL1: 2349792Sandreas.hansson@arm.com return true; 2359792Sandreas.hansson@arm.com case EL2: 2369792Sandreas.hansson@arm.com return haveVirtualization(tc); 2379792Sandreas.hansson@arm.com case EL3: 2389792Sandreas.hansson@arm.com return haveSecurity(tc); 2399792Sandreas.hansson@arm.com default: 2409792Sandreas.hansson@arm.com warn("Unimplemented Exception Level\n"); 2419792Sandreas.hansson@arm.com return false; 2429792Sandreas.hansson@arm.com } 2439792Sandreas.hansson@arm.com} 2449792Sandreas.hansson@arm.com 2459792Sandreas.hansson@arm.comAddr 2469792Sandreas.hansson@arm.comArmSystem::resetAddr64(ThreadContext *tc) 2479792Sandreas.hansson@arm.com{ 2489792Sandreas.hansson@arm.com return getArmSystem(tc)->resetAddr64(); 2499792Sandreas.hansson@arm.com} 2509792Sandreas.hansson@arm.com 2519792Sandreas.hansson@arm.comuint8_t 2529792Sandreas.hansson@arm.comArmSystem::physAddrRange(ThreadContext *tc) 2539792Sandreas.hansson@arm.com{ 2549792Sandreas.hansson@arm.com return getArmSystem(tc)->physAddrRange(); 2559792Sandreas.hansson@arm.com} 25610884Sandreas.hansson@arm.com 25710884Sandreas.hansson@arm.comAddr 2589792Sandreas.hansson@arm.comArmSystem::physAddrMask(ThreadContext *tc) 2599792Sandreas.hansson@arm.com{ 2609792Sandreas.hansson@arm.com return getArmSystem(tc)->physAddrMask(); 2619792Sandreas.hansson@arm.com} 2629792Sandreas.hansson@arm.com 2639380SAndreas.Sandberg@ARM.combool 2649380SAndreas.Sandberg@ARM.comArmSystem::haveLargeAsid64(ThreadContext *tc) 2659380SAndreas.Sandberg@ARM.com{ 2669380SAndreas.Sandberg@ARM.com return getArmSystem(tc)->haveLargeAsid64(); 2679380SAndreas.Sandberg@ARM.com} 2689380SAndreas.Sandberg@ARM.com 2699380SAndreas.Sandberg@ARM.comArmSystem * 2709380SAndreas.Sandberg@ARM.comArmSystemParams::create() 2719380SAndreas.Sandberg@ARM.com{ 27212070Snikos.nikoleris@arm.com return new ArmSystem(this); 27312070Snikos.nikoleris@arm.com} 27412070Snikos.nikoleris@arm.com 27512070Snikos.nikoleris@arm.comvoid 27612070Snikos.nikoleris@arm.comGenericArmSystem::initState() 27712070Snikos.nikoleris@arm.com{ 27812070Snikos.nikoleris@arm.com // Moved from the constructor to here since it relies on the 27912070Snikos.nikoleris@arm.com // address map being resolved in the interconnect 28012070Snikos.nikoleris@arm.com 28112070Snikos.nikoleris@arm.com // Call the initialisation of the super class 28212070Snikos.nikoleris@arm.com ArmSystem::initState(); 2839826Sandreas.hansson@arm.com} 28412070Snikos.nikoleris@arm.com 28512070Snikos.nikoleris@arm.comGenericArmSystem * 28612070Snikos.nikoleris@arm.comGenericArmSystemParams::create() 28712070Snikos.nikoleris@arm.com{ 2889380SAndreas.Sandberg@ARM.com 2899380SAndreas.Sandberg@ARM.com return new GenericArmSystem(this); 2909380SAndreas.Sandberg@ARM.com} 2919380SAndreas.Sandberg@ARM.com