diff options
author | ARM gem5 Developers <none@none> | 2014-01-24 15:29:34 -0600 |
---|---|---|
committer | ARM gem5 Developers <none@none> | 2014-01-24 15:29:34 -0600 |
commit | 612f8f074fa1099cf70faf495d46cc647762a031 (patch) | |
tree | bd1e99c43bf15292395eadd4b7ae3f5c823545c3 /src/arch/arm/system.cc | |
parent | f3585c841e964c98911784a187fc4f081a02a0a6 (diff) | |
download | gem5-612f8f074fa1099cf70faf495d46cc647762a031.tar.xz |
arm: Add support for ARMv8 (AArch64 & AArch32)
Note: AArch64 and AArch32 interworking is not supported. If you use an AArch64
kernel you are restricted to AArch64 user-mode binaries. This will be addressed
in a later patch.
Note: Virtualization is only supported in AArch32 mode. This will also be fixed
in a later patch.
Contributors:
Giacomo Gabrielli (TrustZone, LPAE, system-level AArch64, AArch64 NEON, validation)
Thomas Grocutt (AArch32 Virtualization, AArch64 FP, validation)
Mbou Eyole (AArch64 NEON, validation)
Ali Saidi (AArch64 Linux support, code integration, validation)
Edmund Grimley-Evans (AArch64 FP)
William Wang (AArch64 Linux support)
Rene De Jong (AArch64 Linux support, performance opt.)
Matt Horsnell (AArch64 MP, validation)
Matt Evans (device models, code integration, validation)
Chris Adeniyi-Jones (AArch64 syscall-emulation)
Prakash Ramrakhyani (validation)
Dam Sunwoo (validation)
Chander Sudanthi (validation)
Stephan Diestelhorst (validation)
Andreas Hansson (code integration, performance opt.)
Eric Van Hensbergen (performance opt.)
Gabe Black
Diffstat (limited to 'src/arch/arm/system.cc')
-rw-r--r-- | src/arch/arm/system.cc | 143 |
1 files changed, 136 insertions, 7 deletions
diff --git a/src/arch/arm/system.cc b/src/arch/arm/system.cc index b09784b64..00d9d7613 100644 --- a/src/arch/arm/system.cc +++ b/src/arch/arm/system.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 ARM Limited + * Copyright (c) 2010, 2012-2013 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -48,19 +48,46 @@ #include "cpu/thread_context.hh" #include "mem/physical.hh" #include "mem/fs_translating_port_proxy.hh" +#include "sim/full_system.hh" using namespace std; using namespace Linux; ArmSystem::ArmSystem(Params *p) - : System(p), bootldr(NULL), multiProc(p->multi_proc) + : System(p), bootldr(NULL), _haveSecurity(p->have_security), + _haveLPAE(p->have_lpae), + _haveVirtualization(p->have_virtualization), + _haveGenericTimer(p->have_generic_timer), + _highestELIs64(p->highest_el_is_64), + _resetAddr64(p->reset_addr_64), + _physAddrRange64(p->phys_addr_range_64), + _haveLargeAsid64(p->have_large_asid_64), + multiProc(p->multi_proc) { + // Check if the physical address range is valid + if (_highestELIs64 && ( + _physAddrRange64 < 32 || + _physAddrRange64 > 48 || + (_physAddrRange64 % 4 != 0 && _physAddrRange64 != 42))) { + fatal("Invalid physical address range (%d)\n", _physAddrRange64); + } + if (p->boot_loader != "") { bootldr = createObjectFile(p->boot_loader); if (!bootldr) fatal("Could not read bootloader: %s\n", p->boot_loader); + if ((bootldr->getArch() == ObjectFile::Arm64) && !_highestELIs64) { + warn("Highest ARM exception-level set to AArch32 but bootloader " + "is for AArch64. Assuming you wanted these to match.\n"); + _highestELIs64 = true; + } else if ((bootldr->getArch() == ObjectFile::Arm) && _highestELIs64) { + warn("Highest ARM exception-level set to AArch64 but bootloader " + "is for AArch32. Assuming you wanted these to match.\n"); + _highestELIs64 = false; + } + bootldr->loadGlobalSymbols(debugSymbolTable); } @@ -81,11 +108,21 @@ ArmSystem::initState() if (bootldr) { bootldr->loadSections(physProxy); - uint8_t jump_to_bl[] = + uint8_t jump_to_bl_32[] = + { + 0x07, 0xf0, 0xa0, 0xe1 // branch to r7 in aarch32 + }; + + uint8_t jump_to_bl_64[] = { - 0x07, 0xf0, 0xa0, 0xe1 // branch to r7 + 0xe0, 0x00, 0x1f, 0xd6 // instruction "br x7" in aarch64 }; - physProxy.writeBlob(0x0, jump_to_bl, sizeof(jump_to_bl)); + + // write the jump to branch table into address 0 + if (!_highestELIs64) + physProxy.writeBlob(0x0, jump_to_bl_32, sizeof(jump_to_bl_32)); + else + physProxy.writeBlob(0x0, jump_to_bl_64, sizeof(jump_to_bl_64)); inform("Using bootloader at address %#x\n", bootldr->entryPoint()); @@ -96,24 +133,116 @@ ArmSystem::initState() fatal("gic_cpu_addr && flags_addr must be set with bootloader\n"); for (int i = 0; i < threadContexts.size(); i++) { - threadContexts[i]->setIntReg(3, kernelEntry & loadAddrMask); + if (!_highestELIs64) + threadContexts[i]->setIntReg(3, (kernelEntry & loadAddrMask) + + loadAddrOffset); threadContexts[i]->setIntReg(4, params()->gic_cpu_addr); threadContexts[i]->setIntReg(5, params()->flags_addr); threadContexts[i]->setIntReg(7, bootldr->entryPoint()); } + inform("Using kernel entry physical address at %#x\n", + (kernelEntry & loadAddrMask) + loadAddrOffset); } else { // Set the initial PC to be at start of the kernel code - threadContexts[0]->pcState(kernelEntry & loadAddrMask); + if (!_highestELIs64) + threadContexts[0]->pcState((kernelEntry & loadAddrMask) + + loadAddrOffset); + } +} + +GenericTimer::ArchTimer * +ArmSystem::getArchTimer(int cpu_id) const +{ + if (_genericTimer) { + return _genericTimer->getArchTimer(cpu_id); } + return NULL; } +GenericTimer::SystemCounter * +ArmSystem::getSystemCounter() const +{ + if (_genericTimer) { + return _genericTimer->getSystemCounter(); + } + return NULL; +} + +bool +ArmSystem::haveSecurity(ThreadContext *tc) +{ + if (!FullSystem) + return false; + + ArmSystem *a_sys = dynamic_cast<ArmSystem *>(tc->getSystemPtr()); + assert(a_sys); + return a_sys->haveSecurity(); +} + + ArmSystem::~ArmSystem() { if (debugPrintkEvent) delete debugPrintkEvent; } +bool +ArmSystem::haveLPAE(ThreadContext *tc) +{ + if (!FullSystem) + return false; + ArmSystem *a_sys = dynamic_cast<ArmSystem *>(tc->getSystemPtr()); + assert(a_sys); + return a_sys->haveLPAE(); +} + +bool +ArmSystem::haveVirtualization(ThreadContext *tc) +{ + if (!FullSystem) + return false; + + ArmSystem *a_sys = dynamic_cast<ArmSystem *>(tc->getSystemPtr()); + assert(a_sys); + return a_sys->haveVirtualization(); +} + +bool +ArmSystem::highestELIs64(ThreadContext *tc) +{ + return dynamic_cast<ArmSystem *>(tc->getSystemPtr())->highestELIs64(); +} + +ExceptionLevel +ArmSystem::highestEL(ThreadContext *tc) +{ + return dynamic_cast<ArmSystem *>(tc->getSystemPtr())->highestEL(); +} + +Addr +ArmSystem::resetAddr64(ThreadContext *tc) +{ + return dynamic_cast<ArmSystem *>(tc->getSystemPtr())->resetAddr64(); +} + +uint8_t +ArmSystem::physAddrRange(ThreadContext *tc) +{ + return dynamic_cast<ArmSystem *>(tc->getSystemPtr())->physAddrRange(); +} + +Addr +ArmSystem::physAddrMask(ThreadContext *tc) +{ + return dynamic_cast<ArmSystem *>(tc->getSystemPtr())->physAddrMask(); +} + +bool +ArmSystem::haveLargeAsid64(ThreadContext *tc) +{ + return dynamic_cast<ArmSystem *>(tc->getSystemPtr())->haveLargeAsid64(); +} ArmSystem * ArmSystemParams::create() { |