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