2009-11-18 01:02:08 +01:00
|
|
|
/*
|
2014-04-29 23:05:02 +02:00
|
|
|
* Copyright (c) 2009-2014 ARM Limited
|
2009-11-18 01:02:08 +01:00
|
|
|
* All rights reserved.
|
|
|
|
*
|
2010-06-02 19:58:00 +02:00
|
|
|
* The license below extends only to copyright in the software and shall
|
|
|
|
* not be construed as granting a license to any other intellectual
|
|
|
|
* property including but not limited to intellectual property relating
|
|
|
|
* to a hardware implementation of the functionality of the software
|
|
|
|
* licensed hereunder. You may use the software subject to the license
|
|
|
|
* terms below provided that you ensure that this notice is replicated
|
|
|
|
* unmodified and in its entirety in all distributions of the software,
|
|
|
|
* modified or unmodified, in source code or in binary form.
|
|
|
|
*
|
2009-11-18 01:02:08 +01:00
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions are
|
|
|
|
* met: redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer;
|
|
|
|
* redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution;
|
|
|
|
* neither the name of the copyright holders nor the names of its
|
|
|
|
* contributors may be used to endorse or promote products derived from
|
|
|
|
* this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*
|
|
|
|
* Authors: Ali Saidi
|
|
|
|
*/
|
2009-11-11 05:34:38 +01:00
|
|
|
|
2014-10-16 11:49:51 +02:00
|
|
|
#include <memory>
|
2009-11-18 01:02:08 +01:00
|
|
|
|
|
|
|
#include "arch/arm/faults.hh"
|
2010-10-16 08:57:06 +02:00
|
|
|
#include "arch/arm/isa_traits.hh"
|
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
2014-01-24 22:29:34 +01:00
|
|
|
#include "arch/arm/system.hh"
|
2011-11-02 09:25:15 +01:00
|
|
|
#include "arch/arm/tlb.hh"
|
2009-11-18 01:02:08 +01:00
|
|
|
#include "arch/arm/utility.hh"
|
2010-10-01 23:02:46 +02:00
|
|
|
#include "arch/arm/vtophys.hh"
|
2012-03-09 15:59:27 +01:00
|
|
|
#include "cpu/checker/cpu.hh"
|
2012-03-09 15:59:26 +01:00
|
|
|
#include "cpu/base.hh"
|
2011-11-02 09:25:15 +01:00
|
|
|
#include "cpu/thread_context.hh"
|
2012-01-17 19:55:08 +01:00
|
|
|
#include "mem/fs_translating_port_proxy.hh"
|
2011-11-02 09:25:15 +01:00
|
|
|
#include "sim/full_system.hh"
|
2010-11-15 21:04:03 +01:00
|
|
|
|
2009-11-11 05:34:38 +01:00
|
|
|
namespace ArmISA {
|
|
|
|
|
|
|
|
void
|
|
|
|
initCPU(ThreadContext *tc, int cpuId)
|
|
|
|
{
|
|
|
|
// Reset CP15?? What does that mean -- ali
|
2012-06-05 20:20:13 +02:00
|
|
|
|
2009-11-11 05:34:38 +01:00
|
|
|
// FPEXC.EN = 0
|
2012-03-09 15:59:26 +01:00
|
|
|
|
2014-10-16 11:49:51 +02:00
|
|
|
static Fault reset = std::make_shared<Reset>();
|
2011-05-05 03:38:28 +02:00
|
|
|
reset->invoke(tc);
|
2009-11-11 05:34:38 +01:00
|
|
|
}
|
|
|
|
|
2010-10-16 08:57:06 +02:00
|
|
|
uint64_t
|
|
|
|
getArgument(ThreadContext *tc, int &number, uint16_t size, bool fp)
|
|
|
|
{
|
2012-01-29 11:04:34 +01:00
|
|
|
if (!FullSystem) {
|
|
|
|
panic("getArgument() only implemented for full system mode.\n");
|
|
|
|
M5_DUMMY_RETURN
|
|
|
|
}
|
2010-10-01 23:02:46 +02:00
|
|
|
|
2012-01-29 11:04:34 +01:00
|
|
|
if (fp)
|
|
|
|
panic("getArgument(): Floating point arguments not implemented\n");
|
|
|
|
|
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
2014-01-24 22:29:34 +01:00
|
|
|
if (inAArch64(tc)) {
|
|
|
|
if (size == (uint16_t)(-1))
|
|
|
|
size = sizeof(uint64_t);
|
|
|
|
|
|
|
|
if (number < 8 /*NumArgumentRegs64*/) {
|
|
|
|
return tc->readIntReg(number);
|
2012-01-29 11:04:34 +01:00
|
|
|
} else {
|
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
2014-01-24 22:29:34 +01:00
|
|
|
panic("getArgument(): No support reading stack args for AArch64\n");
|
2010-10-01 23:02:46 +02:00
|
|
|
}
|
2011-11-02 09:25:15 +01:00
|
|
|
} else {
|
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
2014-01-24 22:29:34 +01:00
|
|
|
if (size == (uint16_t)(-1))
|
2014-09-03 13:42:21 +02:00
|
|
|
// todo: should this not be sizeof(uint32_t) rather?
|
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
2014-01-24 22:29:34 +01:00
|
|
|
size = ArmISA::MachineBytes;
|
|
|
|
|
|
|
|
if (number < NumArgumentRegs) {
|
|
|
|
// If the argument is 64 bits, it must be in an even regiser
|
|
|
|
// number. Increment the number here if it isn't even.
|
|
|
|
if (size == sizeof(uint64_t)) {
|
|
|
|
if ((number % 2) != 0)
|
|
|
|
number++;
|
|
|
|
// Read the two halves of the data. Number is inc here to
|
|
|
|
// get the second half of the 64 bit reg.
|
|
|
|
uint64_t tmp;
|
|
|
|
tmp = tc->readIntReg(number++);
|
|
|
|
tmp |= tc->readIntReg(number) << 32;
|
|
|
|
return tmp;
|
|
|
|
} else {
|
|
|
|
return tc->readIntReg(number);
|
|
|
|
}
|
2012-01-29 11:04:34 +01:00
|
|
|
} else {
|
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
2014-01-24 22:29:34 +01:00
|
|
|
Addr sp = tc->readIntReg(StackPointerReg);
|
|
|
|
FSTranslatingPortProxy &vp = tc->getVirtProxy();
|
|
|
|
uint64_t arg;
|
|
|
|
if (size == sizeof(uint64_t)) {
|
|
|
|
// If the argument is even it must be aligned
|
|
|
|
if ((number % 2) != 0)
|
|
|
|
number++;
|
|
|
|
arg = vp.read<uint64_t>(sp +
|
|
|
|
(number-NumArgumentRegs) * sizeof(uint32_t));
|
|
|
|
// since two 32 bit args == 1 64 bit arg, increment number
|
|
|
|
number++;
|
|
|
|
} else {
|
|
|
|
arg = vp.read<uint32_t>(sp +
|
|
|
|
(number-NumArgumentRegs) * sizeof(uint32_t));
|
|
|
|
}
|
|
|
|
return arg;
|
2012-01-29 11:04:34 +01:00
|
|
|
}
|
2010-08-26 02:10:43 +02:00
|
|
|
}
|
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
2014-01-24 22:29:34 +01:00
|
|
|
panic("getArgument() should always return\n");
|
2009-11-18 01:02:08 +01:00
|
|
|
}
|
|
|
|
|
2010-10-01 23:02:46 +02:00
|
|
|
void
|
|
|
|
skipFunction(ThreadContext *tc)
|
|
|
|
{
|
2013-10-15 20:22:44 +02:00
|
|
|
PCState newPC = tc->pcState();
|
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
2014-01-24 22:29:34 +01:00
|
|
|
if (inAArch64(tc)) {
|
|
|
|
newPC.set(tc->readIntReg(INTREG_X30));
|
|
|
|
} else {
|
|
|
|
newPC.set(tc->readIntReg(ReturnAddressReg) & ~ULL(1));
|
|
|
|
}
|
2012-03-09 15:59:27 +01:00
|
|
|
|
|
|
|
CheckerCPU *checker = tc->getCheckerCpuPtr();
|
|
|
|
if (checker) {
|
|
|
|
tc->pcStateNoRecord(newPC);
|
|
|
|
} else {
|
|
|
|
tc->pcState(newPC);
|
|
|
|
}
|
2010-10-01 23:02:46 +02:00
|
|
|
}
|
|
|
|
|
2010-11-15 21:04:03 +01:00
|
|
|
void
|
|
|
|
copyRegs(ThreadContext *src, ThreadContext *dest)
|
|
|
|
{
|
2013-10-15 20:22:44 +02:00
|
|
|
for (int i = 0; i < NumIntRegs; i++)
|
2013-01-07 19:05:44 +01:00
|
|
|
dest->setIntRegFlat(i, src->readIntRegFlat(i));
|
2011-04-04 18:42:28 +02:00
|
|
|
|
2013-10-15 20:22:44 +02:00
|
|
|
for (int i = 0; i < NumFloatRegs; i++)
|
2013-01-07 19:05:44 +01:00
|
|
|
dest->setFloatRegFlat(i, src->readFloatRegFlat(i));
|
2011-04-04 18:42:28 +02:00
|
|
|
|
2014-04-29 23:05:02 +02:00
|
|
|
for (int i = 0; i < NumCCRegs; i++)
|
|
|
|
dest->setCCReg(i, src->readCCReg(i));
|
2013-10-15 20:22:44 +02:00
|
|
|
|
2015-07-26 17:21:20 +02:00
|
|
|
// Copy vector registers when vector registers put to use.
|
|
|
|
assert(NumVectorRegs == 0);
|
|
|
|
|
2013-10-15 20:22:44 +02:00
|
|
|
for (int i = 0; i < NumMiscRegs; i++)
|
2010-11-15 21:04:03 +01:00
|
|
|
dest->setMiscRegNoEffect(i, src->readMiscRegNoEffect(i));
|
2009-11-18 01:02:09 +01:00
|
|
|
|
2010-11-15 21:04:03 +01:00
|
|
|
// setMiscReg "with effect" will set the misc register mapping correctly.
|
|
|
|
// e.g. updateRegMap(val)
|
|
|
|
dest->setMiscReg(MISCREG_CPSR, src->readMiscRegNoEffect(MISCREG_CPSR));
|
|
|
|
|
2010-11-15 21:04:03 +01:00
|
|
|
// Copy over the PC State
|
2010-11-15 21:04:03 +01:00
|
|
|
dest->pcState(src->pcState());
|
2010-11-15 21:04:03 +01:00
|
|
|
|
|
|
|
// Invalidate the tlb misc register cache
|
|
|
|
dest->getITBPtr()->invalidateMiscReg();
|
|
|
|
dest->getDTBPtr()->invalidateMiscReg();
|
2010-11-15 21:04:03 +01:00
|
|
|
}
|
2010-11-15 21:04:03 +01:00
|
|
|
|
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
2014-01-24 22:29:34 +01:00
|
|
|
bool
|
|
|
|
inSecureState(ThreadContext *tc)
|
|
|
|
{
|
|
|
|
SCR scr = inAArch64(tc) ? tc->readMiscReg(MISCREG_SCR_EL3) :
|
|
|
|
tc->readMiscReg(MISCREG_SCR);
|
|
|
|
return ArmSystem::haveSecurity(tc) && inSecureState(
|
|
|
|
scr, tc->readMiscReg(MISCREG_CPSR));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
inAArch64(ThreadContext *tc)
|
|
|
|
{
|
|
|
|
CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
|
|
|
|
return opModeIs64((OperatingMode) (uint8_t) cpsr.mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
longDescFormatInUse(ThreadContext *tc)
|
|
|
|
{
|
|
|
|
TTBCR ttbcr = tc->readMiscReg(MISCREG_TTBCR);
|
|
|
|
return ArmSystem::haveLPAE(tc) && ttbcr.eae;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t
|
|
|
|
getMPIDR(ArmSystem *arm_sys, ThreadContext *tc)
|
|
|
|
{
|
2014-05-10 00:58:46 +02:00
|
|
|
// Multiprocessor Affinity Register MPIDR from Cortex(tm)-A15 Technical
|
|
|
|
// Reference Manual
|
|
|
|
//
|
|
|
|
// bit 31 - Multi-processor extensions available
|
|
|
|
// bit 30 - Uni-processor system
|
|
|
|
// bit 24 - Multi-threaded cores
|
|
|
|
// bit 11-8 - Cluster ID
|
|
|
|
// bit 1-0 - CPU ID
|
|
|
|
//
|
|
|
|
// We deliberately extend both the Cluster ID and CPU ID fields to allow
|
|
|
|
// for simulation of larger systems
|
|
|
|
assert((0 <= tc->cpuId()) && (tc->cpuId() < 256));
|
|
|
|
assert((0 <= tc->socketId()) && (tc->socketId() < 65536));
|
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
2014-01-24 22:29:34 +01:00
|
|
|
if (arm_sys->multiProc) {
|
|
|
|
return 0x80000000 | // multiprocessor extensions available
|
2014-05-10 00:58:46 +02:00
|
|
|
tc->cpuId() | tc->socketId() << 8;
|
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
2014-01-24 22:29:34 +01:00
|
|
|
} else {
|
|
|
|
return 0x80000000 | // multiprocessor extensions available
|
|
|
|
0x40000000 | // in up system
|
2014-05-10 00:58:46 +02:00
|
|
|
tc->cpuId() | tc->socketId() << 8;
|
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
2014-01-24 22:29:34 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
ELIs64(ThreadContext *tc, ExceptionLevel el)
|
|
|
|
{
|
|
|
|
if (ArmSystem::highestEL(tc) == el)
|
|
|
|
// Register width is hard-wired
|
|
|
|
return ArmSystem::highestELIs64(tc);
|
|
|
|
|
|
|
|
switch (el) {
|
|
|
|
case EL0:
|
|
|
|
return opModeIs64(currOpMode(tc));
|
|
|
|
case EL1:
|
|
|
|
{
|
|
|
|
// @todo: uncomment this to enable Virtualization
|
|
|
|
// if (ArmSystem::haveVirtualization(tc)) {
|
|
|
|
// HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
|
|
|
|
// return hcr.rw;
|
|
|
|
// }
|
|
|
|
assert(ArmSystem::haveSecurity(tc));
|
|
|
|
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
|
|
|
|
return scr.rw;
|
|
|
|
}
|
|
|
|
case EL2:
|
|
|
|
{
|
|
|
|
assert(ArmSystem::haveSecurity(tc));
|
|
|
|
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
|
|
|
|
return scr.rw;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
panic("Invalid exception level");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
isBigEndian64(ThreadContext *tc)
|
|
|
|
{
|
|
|
|
switch (opModeToEL(currOpMode(tc))) {
|
|
|
|
case EL3:
|
|
|
|
return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL3)).ee;
|
|
|
|
case EL2:
|
|
|
|
return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL2)).ee;
|
|
|
|
case EL1:
|
|
|
|
return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL1)).ee;
|
|
|
|
case EL0:
|
|
|
|
return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL1)).e0e;
|
|
|
|
default:
|
|
|
|
panic("Invalid exception level");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-26 09:21:42 +02:00
|
|
|
Addr
|
|
|
|
purifyTaggedAddr(Addr addr, ThreadContext *tc, ExceptionLevel el,
|
|
|
|
TTBCR tcr)
|
|
|
|
{
|
|
|
|
switch (el) {
|
|
|
|
case EL0:
|
|
|
|
case EL1:
|
|
|
|
if (bits(addr, 55, 48) == 0xFF && tcr.tbi1)
|
|
|
|
return addr | mask(63, 55);
|
|
|
|
else if (!bits(addr, 55, 48) && tcr.tbi0)
|
|
|
|
return bits(addr,55, 0);
|
|
|
|
break;
|
|
|
|
// @todo: uncomment this to enable Virtualization
|
|
|
|
// case EL2:
|
|
|
|
// assert(ArmSystem::haveVirtualization());
|
|
|
|
// tcr = tc->readMiscReg(MISCREG_TCR_EL2);
|
|
|
|
// if (tcr.tbi)
|
|
|
|
// return addr & mask(56);
|
|
|
|
// break;
|
|
|
|
case EL3:
|
|
|
|
assert(ArmSystem::haveSecurity(tc));
|
|
|
|
if (tcr.tbi)
|
|
|
|
return addr & mask(56);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
panic("Invalid exception level");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return addr; // Nothing to do if this is not a tagged address
|
|
|
|
}
|
|
|
|
|
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
2014-01-24 22:29:34 +01:00
|
|
|
Addr
|
|
|
|
purifyTaggedAddr(Addr addr, ThreadContext *tc, ExceptionLevel el)
|
|
|
|
{
|
|
|
|
TTBCR tcr;
|
|
|
|
|
|
|
|
switch (el) {
|
|
|
|
case EL0:
|
|
|
|
case EL1:
|
|
|
|
tcr = tc->readMiscReg(MISCREG_TCR_EL1);
|
|
|
|
if (bits(addr, 55, 48) == 0xFF && tcr.tbi1)
|
|
|
|
return addr | mask(63, 55);
|
|
|
|
else if (!bits(addr, 55, 48) && tcr.tbi0)
|
|
|
|
return bits(addr,55, 0);
|
|
|
|
break;
|
|
|
|
// @todo: uncomment this to enable Virtualization
|
|
|
|
// case EL2:
|
|
|
|
// assert(ArmSystem::haveVirtualization());
|
|
|
|
// tcr = tc->readMiscReg(MISCREG_TCR_EL2);
|
|
|
|
// if (tcr.tbi)
|
|
|
|
// return addr & mask(56);
|
|
|
|
// break;
|
|
|
|
case EL3:
|
|
|
|
assert(ArmSystem::haveSecurity(tc));
|
|
|
|
tcr = tc->readMiscReg(MISCREG_TCR_EL3);
|
|
|
|
if (tcr.tbi)
|
|
|
|
return addr & mask(56);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
panic("Invalid exception level");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return addr; // Nothing to do if this is not a tagged address
|
|
|
|
}
|
|
|
|
|
2010-11-15 21:04:03 +01:00
|
|
|
Addr
|
|
|
|
truncPage(Addr addr)
|
|
|
|
{
|
|
|
|
return addr & ~(PageBytes - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
Addr
|
|
|
|
roundPage(Addr addr)
|
|
|
|
{
|
|
|
|
return (addr + PageBytes - 1) & ~(PageBytes - 1);
|
2009-11-18 01:02:08 +01:00
|
|
|
}
|
2010-11-15 21:04:03 +01:00
|
|
|
|
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
2014-01-24 22:29:34 +01:00
|
|
|
bool
|
|
|
|
mcrMrc15TrapToHyp(const MiscRegIndex miscReg, HCR hcr, CPSR cpsr, SCR scr,
|
|
|
|
HDCR hdcr, HSTR hstr, HCPTR hcptr, uint32_t iss)
|
|
|
|
{
|
|
|
|
bool isRead;
|
|
|
|
uint32_t crm;
|
|
|
|
IntRegIndex rt;
|
|
|
|
uint32_t crn;
|
|
|
|
uint32_t opc1;
|
|
|
|
uint32_t opc2;
|
|
|
|
bool trapToHype = false;
|
|
|
|
|
|
|
|
|
|
|
|
if (!inSecureState(scr, cpsr) && (cpsr.mode != MODE_HYP)) {
|
|
|
|
mcrMrcIssExtract(iss, isRead, crm, rt, crn, opc1, opc2);
|
|
|
|
trapToHype = ((uint32_t) hstr) & (1 << crn);
|
|
|
|
trapToHype |= hdcr.tpm && (crn == 9) && (crm >= 12);
|
|
|
|
trapToHype |= hcr.tidcp && (
|
|
|
|
((crn == 9) && ((crm <= 2) || ((crm >= 5) && (crm <= 8)))) ||
|
|
|
|
((crn == 10) && ((crm <= 1) || (crm == 4) || (crm == 8))) ||
|
|
|
|
((crn == 11) && ((crm <= 8) || (crm == 15))) );
|
|
|
|
|
|
|
|
if (!trapToHype) {
|
|
|
|
switch (unflattenMiscReg(miscReg)) {
|
|
|
|
case MISCREG_CPACR:
|
|
|
|
trapToHype = hcptr.tcpac;
|
|
|
|
break;
|
|
|
|
case MISCREG_REVIDR:
|
|
|
|
case MISCREG_TCMTR:
|
|
|
|
case MISCREG_TLBTR:
|
|
|
|
case MISCREG_AIDR:
|
|
|
|
trapToHype = hcr.tid1;
|
|
|
|
break;
|
|
|
|
case MISCREG_CTR:
|
|
|
|
case MISCREG_CCSIDR:
|
|
|
|
case MISCREG_CLIDR:
|
|
|
|
case MISCREG_CSSELR:
|
|
|
|
trapToHype = hcr.tid2;
|
|
|
|
break;
|
|
|
|
case MISCREG_ID_PFR0:
|
|
|
|
case MISCREG_ID_PFR1:
|
|
|
|
case MISCREG_ID_DFR0:
|
|
|
|
case MISCREG_ID_AFR0:
|
|
|
|
case MISCREG_ID_MMFR0:
|
|
|
|
case MISCREG_ID_MMFR1:
|
|
|
|
case MISCREG_ID_MMFR2:
|
|
|
|
case MISCREG_ID_MMFR3:
|
|
|
|
case MISCREG_ID_ISAR0:
|
|
|
|
case MISCREG_ID_ISAR1:
|
|
|
|
case MISCREG_ID_ISAR2:
|
|
|
|
case MISCREG_ID_ISAR3:
|
|
|
|
case MISCREG_ID_ISAR4:
|
|
|
|
case MISCREG_ID_ISAR5:
|
|
|
|
trapToHype = hcr.tid3;
|
|
|
|
break;
|
|
|
|
case MISCREG_DCISW:
|
|
|
|
case MISCREG_DCCSW:
|
|
|
|
case MISCREG_DCCISW:
|
|
|
|
trapToHype = hcr.tsw;
|
|
|
|
break;
|
|
|
|
case MISCREG_DCIMVAC:
|
|
|
|
case MISCREG_DCCIMVAC:
|
|
|
|
case MISCREG_DCCMVAC:
|
|
|
|
trapToHype = hcr.tpc;
|
|
|
|
break;
|
|
|
|
case MISCREG_ICIMVAU:
|
|
|
|
case MISCREG_ICIALLU:
|
|
|
|
case MISCREG_ICIALLUIS:
|
|
|
|
case MISCREG_DCCMVAU:
|
|
|
|
trapToHype = hcr.tpu;
|
|
|
|
break;
|
|
|
|
case MISCREG_TLBIALLIS:
|
|
|
|
case MISCREG_TLBIMVAIS:
|
|
|
|
case MISCREG_TLBIASIDIS:
|
|
|
|
case MISCREG_TLBIMVAAIS:
|
|
|
|
case MISCREG_DTLBIALL:
|
|
|
|
case MISCREG_ITLBIALL:
|
|
|
|
case MISCREG_DTLBIMVA:
|
|
|
|
case MISCREG_ITLBIMVA:
|
|
|
|
case MISCREG_DTLBIASID:
|
|
|
|
case MISCREG_ITLBIASID:
|
|
|
|
case MISCREG_TLBIMVAA:
|
|
|
|
case MISCREG_TLBIALL:
|
|
|
|
case MISCREG_TLBIMVA:
|
|
|
|
case MISCREG_TLBIASID:
|
|
|
|
trapToHype = hcr.ttlb;
|
|
|
|
break;
|
|
|
|
case MISCREG_ACTLR:
|
|
|
|
trapToHype = hcr.tac;
|
|
|
|
break;
|
|
|
|
case MISCREG_SCTLR:
|
|
|
|
case MISCREG_TTBR0:
|
|
|
|
case MISCREG_TTBR1:
|
|
|
|
case MISCREG_TTBCR:
|
|
|
|
case MISCREG_DACR:
|
|
|
|
case MISCREG_DFSR:
|
|
|
|
case MISCREG_IFSR:
|
|
|
|
case MISCREG_DFAR:
|
|
|
|
case MISCREG_IFAR:
|
|
|
|
case MISCREG_ADFSR:
|
|
|
|
case MISCREG_AIFSR:
|
|
|
|
case MISCREG_PRRR:
|
|
|
|
case MISCREG_NMRR:
|
|
|
|
case MISCREG_MAIR0:
|
|
|
|
case MISCREG_MAIR1:
|
|
|
|
case MISCREG_CONTEXTIDR:
|
|
|
|
trapToHype = hcr.tvm & !isRead;
|
|
|
|
break;
|
|
|
|
case MISCREG_PMCR:
|
|
|
|
trapToHype = hdcr.tpmcr;
|
|
|
|
break;
|
|
|
|
// No default action needed
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return trapToHype;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
mcrMrc14TrapToHyp(const MiscRegIndex miscReg, HCR hcr, CPSR cpsr, SCR scr,
|
|
|
|
HDCR hdcr, HSTR hstr, HCPTR hcptr, uint32_t iss)
|
|
|
|
{
|
|
|
|
bool isRead;
|
|
|
|
uint32_t crm;
|
|
|
|
IntRegIndex rt;
|
|
|
|
uint32_t crn;
|
|
|
|
uint32_t opc1;
|
|
|
|
uint32_t opc2;
|
|
|
|
bool trapToHype = false;
|
|
|
|
|
|
|
|
if (!inSecureState(scr, cpsr) && (cpsr.mode != MODE_HYP)) {
|
|
|
|
mcrMrcIssExtract(iss, isRead, crm, rt, crn, opc1, opc2);
|
|
|
|
inform("trap check M:%x N:%x 1:%x 2:%x hdcr %x, hcptr %x, hstr %x\n",
|
|
|
|
crm, crn, opc1, opc2, hdcr, hcptr, hstr);
|
|
|
|
trapToHype = hdcr.tda && (opc1 == 0);
|
|
|
|
trapToHype |= hcptr.tta && (opc1 == 1);
|
|
|
|
if (!trapToHype) {
|
|
|
|
switch (unflattenMiscReg(miscReg)) {
|
|
|
|
case MISCREG_DBGOSLSR:
|
|
|
|
case MISCREG_DBGOSLAR:
|
|
|
|
case MISCREG_DBGOSDLR:
|
|
|
|
case MISCREG_DBGPRCR:
|
|
|
|
trapToHype = hdcr.tdosa;
|
|
|
|
break;
|
|
|
|
case MISCREG_DBGDRAR:
|
|
|
|
case MISCREG_DBGDSAR:
|
|
|
|
trapToHype = hdcr.tdra;
|
|
|
|
break;
|
|
|
|
case MISCREG_JIDR:
|
|
|
|
trapToHype = hcr.tid0;
|
|
|
|
break;
|
|
|
|
case MISCREG_JOSCR:
|
|
|
|
case MISCREG_JMCR:
|
|
|
|
trapToHype = hstr.tjdbx;
|
|
|
|
break;
|
|
|
|
case MISCREG_TEECR:
|
|
|
|
case MISCREG_TEEHBR:
|
|
|
|
trapToHype = hstr.ttee;
|
|
|
|
break;
|
|
|
|
// No default action needed
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return trapToHype;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
mcrrMrrc15TrapToHyp(const MiscRegIndex miscReg, CPSR cpsr, SCR scr, HSTR hstr,
|
|
|
|
HCR hcr, uint32_t iss)
|
|
|
|
{
|
|
|
|
uint32_t crm;
|
|
|
|
IntRegIndex rt;
|
|
|
|
uint32_t crn;
|
|
|
|
uint32_t opc1;
|
|
|
|
uint32_t opc2;
|
|
|
|
bool isRead;
|
|
|
|
bool trapToHype = false;
|
|
|
|
|
|
|
|
if (!inSecureState(scr, cpsr) && (cpsr.mode != MODE_HYP)) {
|
|
|
|
// This is technically the wrong function, but we can re-use it for
|
|
|
|
// the moment because we only need one field, which overlaps with the
|
|
|
|
// mcrmrc layout
|
|
|
|
mcrMrcIssExtract(iss, isRead, crm, rt, crn, opc1, opc2);
|
|
|
|
trapToHype = ((uint32_t) hstr) & (1 << crm);
|
|
|
|
|
|
|
|
if (!trapToHype) {
|
|
|
|
switch (unflattenMiscReg(miscReg)) {
|
|
|
|
case MISCREG_SCTLR:
|
|
|
|
case MISCREG_TTBR0:
|
|
|
|
case MISCREG_TTBR1:
|
|
|
|
case MISCREG_TTBCR:
|
|
|
|
case MISCREG_DACR:
|
|
|
|
case MISCREG_DFSR:
|
|
|
|
case MISCREG_IFSR:
|
|
|
|
case MISCREG_DFAR:
|
|
|
|
case MISCREG_IFAR:
|
|
|
|
case MISCREG_ADFSR:
|
|
|
|
case MISCREG_AIFSR:
|
|
|
|
case MISCREG_PRRR:
|
|
|
|
case MISCREG_NMRR:
|
|
|
|
case MISCREG_MAIR0:
|
|
|
|
case MISCREG_MAIR1:
|
|
|
|
case MISCREG_CONTEXTIDR:
|
|
|
|
trapToHype = hcr.tvm & !isRead;
|
|
|
|
break;
|
|
|
|
// No default action needed
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return trapToHype;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
msrMrs64TrapToSup(const MiscRegIndex miscReg, ExceptionLevel el,
|
|
|
|
CPACR cpacr /* CPACR_EL1 */)
|
|
|
|
{
|
|
|
|
bool trapToSup = false;
|
|
|
|
switch (miscReg) {
|
|
|
|
case MISCREG_FPCR:
|
|
|
|
case MISCREG_FPSR:
|
|
|
|
case MISCREG_FPEXC32_EL2:
|
|
|
|
if ((el == EL0 && cpacr.fpen != 0x3) ||
|
|
|
|
(el == EL1 && !(cpacr.fpen & 0x1)))
|
|
|
|
trapToSup = true;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return trapToSup;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
msrMrs64TrapToHyp(const MiscRegIndex miscReg, bool isRead,
|
|
|
|
CPTR cptr /* CPTR_EL2 */,
|
|
|
|
HCR hcr /* HCR_EL2 */,
|
|
|
|
bool * isVfpNeon)
|
|
|
|
{
|
|
|
|
bool trapToHyp = false;
|
|
|
|
*isVfpNeon = false;
|
|
|
|
|
|
|
|
switch (miscReg) {
|
|
|
|
// FP/SIMD regs
|
|
|
|
case MISCREG_FPCR:
|
|
|
|
case MISCREG_FPSR:
|
|
|
|
case MISCREG_FPEXC32_EL2:
|
|
|
|
trapToHyp = cptr.tfp;
|
|
|
|
*isVfpNeon = true;
|
|
|
|
break;
|
|
|
|
// CPACR
|
|
|
|
case MISCREG_CPACR_EL1:
|
|
|
|
trapToHyp = cptr.tcpac;
|
|
|
|
break;
|
|
|
|
// Virtual memory control regs
|
|
|
|
case MISCREG_SCTLR_EL1:
|
|
|
|
case MISCREG_TTBR0_EL1:
|
|
|
|
case MISCREG_TTBR1_EL1:
|
|
|
|
case MISCREG_TCR_EL1:
|
|
|
|
case MISCREG_ESR_EL1:
|
|
|
|
case MISCREG_FAR_EL1:
|
|
|
|
case MISCREG_AFSR0_EL1:
|
|
|
|
case MISCREG_AFSR1_EL1:
|
|
|
|
case MISCREG_MAIR_EL1:
|
|
|
|
case MISCREG_AMAIR_EL1:
|
|
|
|
case MISCREG_CONTEXTIDR_EL1:
|
|
|
|
trapToHyp = (hcr.trvm && isRead) || (hcr.tvm && !isRead);
|
|
|
|
break;
|
|
|
|
// TLB maintenance instructions
|
|
|
|
case MISCREG_TLBI_VMALLE1:
|
|
|
|
case MISCREG_TLBI_VAE1_Xt:
|
|
|
|
case MISCREG_TLBI_ASIDE1_Xt:
|
|
|
|
case MISCREG_TLBI_VAAE1_Xt:
|
|
|
|
case MISCREG_TLBI_VALE1_Xt:
|
|
|
|
case MISCREG_TLBI_VAALE1_Xt:
|
|
|
|
case MISCREG_TLBI_VMALLE1IS:
|
|
|
|
case MISCREG_TLBI_VAE1IS_Xt:
|
|
|
|
case MISCREG_TLBI_ASIDE1IS_Xt:
|
|
|
|
case MISCREG_TLBI_VAAE1IS_Xt:
|
|
|
|
case MISCREG_TLBI_VALE1IS_Xt:
|
|
|
|
case MISCREG_TLBI_VAALE1IS_Xt:
|
|
|
|
trapToHyp = hcr.ttlb;
|
|
|
|
break;
|
|
|
|
// Cache maintenance instructions to the point of unification
|
|
|
|
case MISCREG_IC_IVAU_Xt:
|
|
|
|
case MISCREG_ICIALLU:
|
|
|
|
case MISCREG_ICIALLUIS:
|
|
|
|
case MISCREG_DC_CVAU_Xt:
|
|
|
|
trapToHyp = hcr.tpu;
|
|
|
|
break;
|
|
|
|
// Data/Unified cache maintenance instructions to the point of coherency
|
|
|
|
case MISCREG_DC_IVAC_Xt:
|
|
|
|
case MISCREG_DC_CIVAC_Xt:
|
|
|
|
case MISCREG_DC_CVAC_Xt:
|
|
|
|
trapToHyp = hcr.tpc;
|
|
|
|
break;
|
|
|
|
// Data/Unified cache maintenance instructions by set/way
|
|
|
|
case MISCREG_DC_ISW_Xt:
|
|
|
|
case MISCREG_DC_CSW_Xt:
|
|
|
|
case MISCREG_DC_CISW_Xt:
|
|
|
|
trapToHyp = hcr.tsw;
|
|
|
|
break;
|
|
|
|
// ACTLR
|
|
|
|
case MISCREG_ACTLR_EL1:
|
|
|
|
trapToHyp = hcr.tacr;
|
|
|
|
break;
|
|
|
|
|
|
|
|
// @todo: Trap implementation-dependent functionality based on
|
|
|
|
// hcr.tidcp
|
|
|
|
|
|
|
|
// ID regs, group 3
|
|
|
|
case MISCREG_ID_PFR0_EL1:
|
|
|
|
case MISCREG_ID_PFR1_EL1:
|
|
|
|
case MISCREG_ID_DFR0_EL1:
|
|
|
|
case MISCREG_ID_AFR0_EL1:
|
|
|
|
case MISCREG_ID_MMFR0_EL1:
|
|
|
|
case MISCREG_ID_MMFR1_EL1:
|
|
|
|
case MISCREG_ID_MMFR2_EL1:
|
|
|
|
case MISCREG_ID_MMFR3_EL1:
|
|
|
|
case MISCREG_ID_ISAR0_EL1:
|
|
|
|
case MISCREG_ID_ISAR1_EL1:
|
|
|
|
case MISCREG_ID_ISAR2_EL1:
|
|
|
|
case MISCREG_ID_ISAR3_EL1:
|
|
|
|
case MISCREG_ID_ISAR4_EL1:
|
|
|
|
case MISCREG_ID_ISAR5_EL1:
|
|
|
|
case MISCREG_MVFR0_EL1:
|
|
|
|
case MISCREG_MVFR1_EL1:
|
|
|
|
case MISCREG_MVFR2_EL1:
|
|
|
|
case MISCREG_ID_AA64PFR0_EL1:
|
|
|
|
case MISCREG_ID_AA64PFR1_EL1:
|
|
|
|
case MISCREG_ID_AA64DFR0_EL1:
|
|
|
|
case MISCREG_ID_AA64DFR1_EL1:
|
|
|
|
case MISCREG_ID_AA64ISAR0_EL1:
|
|
|
|
case MISCREG_ID_AA64ISAR1_EL1:
|
|
|
|
case MISCREG_ID_AA64MMFR0_EL1:
|
|
|
|
case MISCREG_ID_AA64MMFR1_EL1:
|
|
|
|
case MISCREG_ID_AA64AFR0_EL1:
|
|
|
|
case MISCREG_ID_AA64AFR1_EL1:
|
|
|
|
assert(isRead);
|
|
|
|
trapToHyp = hcr.tid3;
|
|
|
|
break;
|
|
|
|
// ID regs, group 2
|
|
|
|
case MISCREG_CTR_EL0:
|
|
|
|
case MISCREG_CCSIDR_EL1:
|
|
|
|
case MISCREG_CLIDR_EL1:
|
|
|
|
case MISCREG_CSSELR_EL1:
|
|
|
|
trapToHyp = hcr.tid2;
|
|
|
|
break;
|
|
|
|
// ID regs, group 1
|
|
|
|
case MISCREG_AIDR_EL1:
|
|
|
|
case MISCREG_REVIDR_EL1:
|
|
|
|
assert(isRead);
|
|
|
|
trapToHyp = hcr.tid1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return trapToHyp;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
msrMrs64TrapToMon(const MiscRegIndex miscReg, CPTR cptr /* CPTR_EL3 */,
|
|
|
|
ExceptionLevel el, bool * isVfpNeon)
|
|
|
|
{
|
|
|
|
bool trapToMon = false;
|
|
|
|
*isVfpNeon = false;
|
|
|
|
|
|
|
|
switch (miscReg) {
|
|
|
|
// FP/SIMD regs
|
|
|
|
case MISCREG_FPCR:
|
|
|
|
case MISCREG_FPSR:
|
|
|
|
case MISCREG_FPEXC32_EL2:
|
|
|
|
trapToMon = cptr.tfp;
|
|
|
|
*isVfpNeon = true;
|
|
|
|
break;
|
|
|
|
// CPACR, CPTR
|
|
|
|
case MISCREG_CPACR_EL1:
|
|
|
|
if (el == EL1) {
|
|
|
|
trapToMon = cptr.tcpac;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MISCREG_CPTR_EL2:
|
|
|
|
if (el == EL2) {
|
|
|
|
trapToMon = cptr.tcpac;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return trapToMon;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
decodeMrsMsrBankedReg(uint8_t sysM, bool r, bool &isIntReg, int ®Idx,
|
|
|
|
CPSR cpsr, SCR scr, NSACR nsacr, bool checkSecurity)
|
|
|
|
{
|
2014-03-07 21:56:23 +01:00
|
|
|
OperatingMode mode = MODE_UNDEFINED;
|
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
2014-01-24 22:29:34 +01:00
|
|
|
bool ok = true;
|
|
|
|
|
|
|
|
// R mostly indicates if its a int register or a misc reg, we override
|
|
|
|
// below if the few corner cases
|
|
|
|
isIntReg = !r;
|
|
|
|
// Loosely based on ARM ARM issue C section B9.3.10
|
|
|
|
if (r) {
|
|
|
|
switch (sysM)
|
|
|
|
{
|
|
|
|
case 0xE:
|
|
|
|
regIdx = MISCREG_SPSR_FIQ;
|
|
|
|
mode = MODE_FIQ;
|
|
|
|
break;
|
|
|
|
case 0x10:
|
|
|
|
regIdx = MISCREG_SPSR_IRQ;
|
|
|
|
mode = MODE_IRQ;
|
|
|
|
break;
|
|
|
|
case 0x12:
|
|
|
|
regIdx = MISCREG_SPSR_SVC;
|
|
|
|
mode = MODE_SVC;
|
|
|
|
break;
|
|
|
|
case 0x14:
|
|
|
|
regIdx = MISCREG_SPSR_ABT;
|
|
|
|
mode = MODE_ABORT;
|
|
|
|
break;
|
|
|
|
case 0x16:
|
|
|
|
regIdx = MISCREG_SPSR_UND;
|
|
|
|
mode = MODE_UNDEFINED;
|
|
|
|
break;
|
|
|
|
case 0x1C:
|
|
|
|
regIdx = MISCREG_SPSR_MON;
|
|
|
|
mode = MODE_MON;
|
|
|
|
break;
|
|
|
|
case 0x1E:
|
|
|
|
regIdx = MISCREG_SPSR_HYP;
|
|
|
|
mode = MODE_HYP;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ok = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
int sysM4To3 = bits(sysM, 4, 3);
|
|
|
|
|
|
|
|
if (sysM4To3 == 0) {
|
|
|
|
mode = MODE_USER;
|
|
|
|
regIdx = intRegInMode(mode, bits(sysM, 2, 0) + 8);
|
|
|
|
} else if (sysM4To3 == 1) {
|
|
|
|
mode = MODE_FIQ;
|
|
|
|
regIdx = intRegInMode(mode, bits(sysM, 2, 0) + 8);
|
|
|
|
} else if (sysM4To3 == 3) {
|
|
|
|
if (bits(sysM, 1) == 0) {
|
|
|
|
mode = MODE_MON;
|
|
|
|
regIdx = intRegInMode(mode, 14 - bits(sysM, 0));
|
|
|
|
} else {
|
|
|
|
mode = MODE_HYP;
|
|
|
|
if (bits(sysM, 0) == 1) {
|
|
|
|
regIdx = intRegInMode(mode, 13); // R13 in HYP
|
|
|
|
} else {
|
|
|
|
isIntReg = false;
|
|
|
|
regIdx = MISCREG_ELR_HYP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else { // Other Banked registers
|
|
|
|
int sysM2 = bits(sysM, 2);
|
|
|
|
int sysM1 = bits(sysM, 1);
|
|
|
|
|
|
|
|
mode = (OperatingMode) ( ((sysM2 || sysM1) << 0) |
|
|
|
|
(1 << 1) |
|
|
|
|
((sysM2 && !sysM1) << 2) |
|
|
|
|
((sysM2 && sysM1) << 3) |
|
|
|
|
(1 << 4) );
|
|
|
|
regIdx = intRegInMode(mode, 14 - bits(sysM, 0));
|
|
|
|
// Don't flatten the register here. This is going to go through
|
|
|
|
// setIntReg() which will do the flattening
|
|
|
|
ok &= mode != cpsr.mode;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check that the requested register is accessable from the current mode
|
|
|
|
if (ok && checkSecurity && mode != cpsr.mode) {
|
|
|
|
switch (cpsr.mode)
|
|
|
|
{
|
|
|
|
case MODE_USER:
|
|
|
|
ok = false;
|
|
|
|
break;
|
|
|
|
case MODE_FIQ:
|
|
|
|
ok &= mode != MODE_HYP;
|
|
|
|
ok &= (mode != MODE_MON) || !scr.ns;
|
|
|
|
break;
|
|
|
|
case MODE_HYP:
|
|
|
|
ok &= mode != MODE_MON;
|
|
|
|
ok &= (mode != MODE_FIQ) || !nsacr.rfr;
|
|
|
|
break;
|
|
|
|
case MODE_IRQ:
|
|
|
|
case MODE_SVC:
|
|
|
|
case MODE_ABORT:
|
|
|
|
case MODE_UNDEFINED:
|
|
|
|
case MODE_SYSTEM:
|
|
|
|
ok &= mode != MODE_HYP;
|
|
|
|
ok &= (mode != MODE_MON) || !scr.ns;
|
|
|
|
ok &= (mode != MODE_FIQ) || !nsacr.rfr;
|
|
|
|
break;
|
|
|
|
// can access everything, no further checks required
|
|
|
|
case MODE_MON:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
panic("unknown Mode 0x%x\n", cpsr.mode);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (ok);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
vfpNeonEnabled(uint32_t &seq, HCPTR hcptr, NSACR nsacr, CPACR cpacr, CPSR cpsr,
|
|
|
|
uint32_t &iss, bool &trap, ThreadContext *tc, FPEXC fpexc,
|
|
|
|
bool isSIMD)
|
|
|
|
{
|
|
|
|
iss = 0;
|
|
|
|
trap = false;
|
|
|
|
bool undefined = false;
|
|
|
|
bool haveSecurity = ArmSystem::haveSecurity(tc);
|
|
|
|
bool haveVirtualization = ArmSystem::haveVirtualization(tc);
|
|
|
|
bool isSecure = inSecureState(tc);
|
|
|
|
|
|
|
|
// Non-secure view of CPACR and HCPTR determines behavior
|
|
|
|
// Copy register values
|
|
|
|
uint8_t cpacr_cp10 = cpacr.cp10;
|
|
|
|
bool cpacr_asedis = cpacr.asedis;
|
|
|
|
bool hcptr_cp10 = false;
|
|
|
|
bool hcptr_tase = false;
|
|
|
|
|
|
|
|
bool cp10_enabled = cpacr.cp10 == 0x3
|
|
|
|
|| (cpacr.cp10 == 0x1 && inPrivilegedMode(cpsr));
|
|
|
|
|
|
|
|
bool cp11_enabled = cpacr.cp11 == 0x3
|
|
|
|
|| (cpacr.cp11 == 0x1 && inPrivilegedMode(cpsr));
|
|
|
|
|
|
|
|
if (cp11_enabled) {
|
|
|
|
undefined |= !(fpexc.en && cp10_enabled);
|
|
|
|
} else {
|
|
|
|
undefined |= !(fpexc.en && cp10_enabled && (cpacr.cp11 == cpacr.cp10));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (haveVirtualization) {
|
|
|
|
hcptr_cp10 = hcptr.tcp10;
|
|
|
|
undefined |= hcptr.tcp10 != hcptr.tcp11;
|
|
|
|
hcptr_tase = hcptr.tase;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (haveSecurity) {
|
|
|
|
undefined |= nsacr.cp10 != nsacr.cp11;
|
|
|
|
if (!isSecure) {
|
|
|
|
// Modify register values to the Non-secure view
|
|
|
|
if (!nsacr.cp10) {
|
|
|
|
cpacr_cp10 = 0;
|
|
|
|
if (haveVirtualization) {
|
|
|
|
hcptr_cp10 = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (nsacr.nsasedis) {
|
|
|
|
cpacr_asedis = true;
|
|
|
|
if (haveVirtualization) {
|
|
|
|
hcptr_tase = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check Coprocessor Access Control Register for permission to use CP10/11.
|
|
|
|
if (!haveVirtualization || (cpsr.mode != MODE_HYP)) {
|
|
|
|
switch (cpacr_cp10)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
undefined = true;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
undefined |= inUserMode(cpsr);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if SIMD operations are disabled
|
|
|
|
if (isSIMD && cpacr_asedis) undefined = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If required, check FPEXC enabled bit.
|
|
|
|
undefined |= !fpexc.en;
|
|
|
|
|
|
|
|
if (haveSecurity && haveVirtualization && !isSecure) {
|
|
|
|
if (hcptr_cp10 || (isSIMD && hcptr_tase)) {
|
|
|
|
iss = isSIMD ? (1 << 5) : 0xA;
|
|
|
|
trap = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (!undefined);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
SPAlignmentCheckEnabled(ThreadContext* tc)
|
|
|
|
{
|
|
|
|
switch (opModeToEL(currOpMode(tc))) {
|
|
|
|
case EL3:
|
|
|
|
return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL3)).sa;
|
|
|
|
case EL2:
|
|
|
|
return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL2)).sa;
|
|
|
|
case EL1:
|
|
|
|
return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL1)).sa;
|
|
|
|
case EL0:
|
|
|
|
return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL1)).sa0;
|
|
|
|
default:
|
|
|
|
panic("Invalid exception level");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
decodePhysAddrRange64(uint8_t pa_enc)
|
|
|
|
{
|
|
|
|
switch (pa_enc) {
|
|
|
|
case 0x0:
|
|
|
|
return 32;
|
|
|
|
case 0x1:
|
|
|
|
return 36;
|
|
|
|
case 0x2:
|
|
|
|
return 40;
|
|
|
|
case 0x3:
|
|
|
|
return 42;
|
|
|
|
case 0x4:
|
|
|
|
return 44;
|
|
|
|
case 0x5:
|
|
|
|
case 0x6:
|
|
|
|
case 0x7:
|
|
|
|
return 48;
|
|
|
|
default:
|
|
|
|
panic("Invalid phys. address range encoding");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t
|
|
|
|
encodePhysAddrRange64(int pa_size)
|
|
|
|
{
|
|
|
|
switch (pa_size) {
|
|
|
|
case 32:
|
|
|
|
return 0x0;
|
|
|
|
case 36:
|
|
|
|
return 0x1;
|
|
|
|
case 40:
|
|
|
|
return 0x2;
|
|
|
|
case 42:
|
|
|
|
return 0x3;
|
|
|
|
case 44:
|
|
|
|
return 0x4;
|
|
|
|
case 48:
|
|
|
|
return 0x5;
|
|
|
|
default:
|
|
|
|
panic("Invalid phys. address range");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-15 21:04:03 +01:00
|
|
|
} // namespace ArmISA
|