arm: Correctly check FP/SIMD access permission in aarch32
The current implementation of aarch32 FP/SIMD in gem5 assumes that EL1 and higher are all 32-bit. This breaks interprocessing since an aarch64 EL1 uses different enable/disable bits. This change updates the permission checks to according to what is prescribed by the ARM ARM. Change-Id: Icdcef31b00644cfeebec00216b3993aa1de12b88 Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com> Reviewed-by: Mitch Hayenga <mitch.hayenga@arm.com> Reviewed-by: Nathanael Premillieu <nathanael.premillieu@arm.com>
This commit is contained in:
parent
53ae19bb5d
commit
f48ad5b29d
7 changed files with 227 additions and 232 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010-2014 ARM Limited
|
* Copyright (c) 2010-2014, 2016 ARM Limited
|
||||||
* Copyright (c) 2013 Advanced Micro Devices, Inc.
|
* Copyright (c) 2013 Advanced Micro Devices, Inc.
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
*
|
||||||
|
@ -595,4 +595,136 @@ ArmStaticInst::generateDisassembly(Addr pc,
|
||||||
printMnemonic(ss);
|
printMnemonic(ss);
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Fault
|
||||||
|
ArmStaticInst::advSIMDFPAccessTrap64(ExceptionLevel el) const
|
||||||
|
{
|
||||||
|
switch (el) {
|
||||||
|
case EL1:
|
||||||
|
return std::make_shared<SupervisorTrap>(machInst, 0x1E00000,
|
||||||
|
EC_TRAPPED_SIMD_FP);
|
||||||
|
case EL2:
|
||||||
|
return std::make_shared<HypervisorTrap>(machInst, 0x1E00000,
|
||||||
|
EC_TRAPPED_SIMD_FP);
|
||||||
|
case EL3:
|
||||||
|
return std::make_shared<SecureMonitorTrap>(machInst, 0x1E00000,
|
||||||
|
EC_TRAPPED_SIMD_FP);
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic("Illegal EL in advSIMDFPAccessTrap64\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Fault
|
||||||
|
ArmStaticInst::checkFPAdvSIMDTrap64(ThreadContext *tc, CPSR cpsr) const
|
||||||
|
{
|
||||||
|
const ExceptionLevel el = (ExceptionLevel) (uint8_t)cpsr.el;
|
||||||
|
|
||||||
|
if (ArmSystem::haveVirtualization(tc) && el <= EL2) {
|
||||||
|
HCPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL2);
|
||||||
|
if (cptrEnCheck.tfp)
|
||||||
|
return advSIMDFPAccessTrap64(EL2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ArmSystem::haveSecurity(tc)) {
|
||||||
|
HCPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL3);
|
||||||
|
if (cptrEnCheck.tfp)
|
||||||
|
return advSIMDFPAccessTrap64(EL3);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NoFault;
|
||||||
|
}
|
||||||
|
|
||||||
|
Fault
|
||||||
|
ArmStaticInst::checkFPAdvSIMDEnabled64(ThreadContext *tc,
|
||||||
|
CPSR cpsr, CPACR cpacr) const
|
||||||
|
{
|
||||||
|
const ExceptionLevel el = (ExceptionLevel) (uint8_t)cpsr.el;
|
||||||
|
if ((el == EL0 && cpacr.fpen != 0x3) ||
|
||||||
|
(el == EL1 && !(cpacr.fpen & 0x1)))
|
||||||
|
return advSIMDFPAccessTrap64(EL1);
|
||||||
|
|
||||||
|
return checkFPAdvSIMDTrap64(tc, cpsr);
|
||||||
|
}
|
||||||
|
|
||||||
|
Fault
|
||||||
|
ArmStaticInst::checkAdvSIMDOrFPEnabled32(ThreadContext *tc,
|
||||||
|
CPSR cpsr, CPACR cpacr,
|
||||||
|
NSACR nsacr, FPEXC fpexc,
|
||||||
|
bool fpexc_check, bool advsimd) const
|
||||||
|
{
|
||||||
|
const bool have_virtualization = ArmSystem::haveVirtualization(tc);
|
||||||
|
const bool have_security = ArmSystem::haveSecurity(tc);
|
||||||
|
const bool is_secure = inSecureState(tc);
|
||||||
|
const ExceptionLevel cur_el = opModeToEL(currOpMode(tc));
|
||||||
|
|
||||||
|
if (cur_el == EL0 && ELIs64(tc, EL1))
|
||||||
|
return checkFPAdvSIMDEnabled64(tc, cpsr, cpacr);
|
||||||
|
|
||||||
|
uint8_t cpacr_cp10 = cpacr.cp10;
|
||||||
|
bool cpacr_asedis = cpacr.asedis;
|
||||||
|
|
||||||
|
if (have_security && !ELIs64(tc, EL3) && !is_secure) {
|
||||||
|
if (nsacr.nsasedis)
|
||||||
|
cpacr_asedis = true;
|
||||||
|
if (nsacr.cp10 == 0)
|
||||||
|
cpacr_cp10 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cur_el != EL2) {
|
||||||
|
if (advsimd && cpacr_asedis)
|
||||||
|
return disabledFault();
|
||||||
|
|
||||||
|
if ((cur_el == EL0 && cpacr_cp10 != 0x3) ||
|
||||||
|
(cur_el != EL0 && !(cpacr_cp10 & 0x1)))
|
||||||
|
return disabledFault();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fpexc_check && !fpexc.en)
|
||||||
|
return disabledFault();
|
||||||
|
|
||||||
|
// -- aarch32/exceptions/traps/AArch32.CheckFPAdvSIMDTrap --
|
||||||
|
|
||||||
|
if (have_virtualization && !is_secure && ELIs64(tc, EL2))
|
||||||
|
return checkFPAdvSIMDTrap64(tc, cpsr);
|
||||||
|
|
||||||
|
if (have_virtualization && !is_secure) {
|
||||||
|
HCPTR hcptr = tc->readMiscReg(MISCREG_HCPTR);
|
||||||
|
bool hcptr_cp10 = hcptr.tcp10;
|
||||||
|
bool hcptr_tase = hcptr.tase;
|
||||||
|
|
||||||
|
if (have_security && !ELIs64(tc, EL3) && !is_secure) {
|
||||||
|
if (nsacr.nsasedis)
|
||||||
|
hcptr_tase = true;
|
||||||
|
if (nsacr.cp10)
|
||||||
|
hcptr_cp10 = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((advsimd && hcptr_tase) || hcptr_cp10) {
|
||||||
|
const uint32_t iss = advsimd ? (1 << 5) : 0xA;
|
||||||
|
if (cur_el == EL2) {
|
||||||
|
return std::make_shared<UndefinedInstruction>(
|
||||||
|
machInst, iss,
|
||||||
|
EC_TRAPPED_HCPTR, mnemonic);
|
||||||
|
} else {
|
||||||
|
return std::make_shared<HypervisorTrap>(
|
||||||
|
machInst, iss,
|
||||||
|
EC_TRAPPED_HCPTR);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (have_security && ELIs64(tc, EL3)) {
|
||||||
|
HCPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL3);
|
||||||
|
if (cptrEnCheck.tfp)
|
||||||
|
return advSIMDFPAccessTrap64(EL3);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NoFault;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010-2013 ARM Limited
|
* Copyright (c) 2010-2013, 2016 ARM Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
*
|
||||||
* The license below extends only to copyright in the software and shall
|
* The license below extends only to copyright in the software and shall
|
||||||
|
@ -363,6 +363,47 @@ class ArmStaticInst : public StaticInst
|
||||||
mnemonic, true);
|
mnemonic, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trap an access to Advanced SIMD or FP registers due to access
|
||||||
|
* control bits.
|
||||||
|
*
|
||||||
|
* See aarch64/exceptions/traps/AArch64.AdvSIMDFPAccessTrap in the
|
||||||
|
* ARM ARM psueodcode library.
|
||||||
|
*
|
||||||
|
* @param el Target EL for the trap
|
||||||
|
*/
|
||||||
|
Fault advSIMDFPAccessTrap64(ExceptionLevel el) const;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check an Advaned SIMD access against CPTR_EL2 and CPTR_EL3.
|
||||||
|
*
|
||||||
|
* See aarch64/exceptions/traps/AArch64.CheckFPAdvSIMDTrap in the
|
||||||
|
* ARM ARM psueodcode library.
|
||||||
|
*/
|
||||||
|
Fault checkFPAdvSIMDTrap64(ThreadContext *tc, CPSR cpsr) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check an Advaned SIMD access against CPACR_EL1, CPTR_EL2, and
|
||||||
|
* CPTR_EL3.
|
||||||
|
*
|
||||||
|
* See aarch64/exceptions/traps/AArch64.CheckFPAdvSIMDEnabled in the
|
||||||
|
* ARM ARM psueodcode library.
|
||||||
|
*/
|
||||||
|
Fault checkFPAdvSIMDEnabled64(ThreadContext *tc,
|
||||||
|
CPSR cpsr, CPACR cpacr) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a VFP/SIMD access from aarch32 should be allowed.
|
||||||
|
*
|
||||||
|
* See aarch32/exceptions/traps/AArch32.CheckAdvSIMDOrFPEnabled in the
|
||||||
|
* ARM ARM psueodcode library.
|
||||||
|
*/
|
||||||
|
Fault checkAdvSIMDOrFPEnabled32(ThreadContext *tc,
|
||||||
|
CPSR cpsr, CPACR cpacr,
|
||||||
|
NSACR nsacr, FPEXC fpexc,
|
||||||
|
bool fpexc_check, bool advsimd) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void
|
virtual void
|
||||||
annotateFault(ArmFault *fault) {}
|
annotateFault(ArmFault *fault) {}
|
||||||
|
|
|
@ -260,7 +260,7 @@ let {{
|
||||||
decoder_output += FpRegRegOpConstructor.subst(vmrsFpscrIop);
|
decoder_output += FpRegRegOpConstructor.subst(vmrsFpscrIop);
|
||||||
exec_output += PredOpExecute.subst(vmrsFpscrIop);
|
exec_output += PredOpExecute.subst(vmrsFpscrIop);
|
||||||
|
|
||||||
vmrsApsrFpscrCode = vmrsApsrEnabledCheckCode + '''
|
vmrsApsrFpscrCode = vfpEnabledCheckCode + '''
|
||||||
FPSCR fpscr = FpCondCodes;
|
FPSCR fpscr = FpCondCodes;
|
||||||
CondCodesNZ = (fpscr.n << 1) | fpscr.z;
|
CondCodesNZ = (fpscr.n << 1) | fpscr.z;
|
||||||
CondCodesC = fpscr.c;
|
CondCodesC = fpscr.c;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// -*- mode:c++ -*-
|
// -*- mode:c++ -*-
|
||||||
|
|
||||||
// Copyright (c) 2010-2012 ARM Limited
|
// Copyright (c) 2010-2012, 2016 ARM Limited
|
||||||
// All rights reserved
|
// All rights reserved
|
||||||
//
|
//
|
||||||
// The license below extends only to copyright in the software and shall
|
// The license below extends only to copyright in the software and shall
|
||||||
|
@ -40,26 +40,11 @@
|
||||||
let {{
|
let {{
|
||||||
simdEnabledCheckCode = '''
|
simdEnabledCheckCode = '''
|
||||||
{
|
{
|
||||||
uint32_t issEnCheck;
|
Fault fault = checkAdvSIMDOrFPEnabled32(xc->tcBase(),
|
||||||
bool trapEnCheck;
|
Cpsr, Cpacr, Nsacr, Fpexc,
|
||||||
uint32_t seq;
|
true, true);
|
||||||
if (!vfpNeonEnabled(seq, Hcptr, Nsacr, Cpacr, Cpsr, issEnCheck,
|
if (fault != NoFault)
|
||||||
trapEnCheck, xc->tcBase(), Fpexc, true))
|
return fault;
|
||||||
{return disabledFault();}
|
|
||||||
if (trapEnCheck) {
|
|
||||||
CPSR cpsrEnCheck = Cpsr;
|
|
||||||
if (cpsrEnCheck.mode == MODE_HYP) {
|
|
||||||
return std::make_shared<UndefinedInstruction>(
|
|
||||||
machInst, issEnCheck,
|
|
||||||
EC_TRAPPED_HCPTR);
|
|
||||||
} else {
|
|
||||||
if (!inSecureState(Scr, Cpsr)) {
|
|
||||||
return std::make_shared<HypervisorTrap>(
|
|
||||||
machInst, issEnCheck,
|
|
||||||
EC_TRAPPED_HCPTR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
'''
|
'''
|
||||||
}};
|
}};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// -*- mode:c++ -*-
|
// -*- mode:c++ -*-
|
||||||
|
|
||||||
// Copyright (c) 2010-2013 ARM Limited
|
// Copyright (c) 2010-2013, 2016 ARM Limited
|
||||||
// All rights reserved
|
// All rights reserved
|
||||||
//
|
//
|
||||||
// The license below extends only to copyright in the software and shall
|
// The license below extends only to copyright in the software and shall
|
||||||
|
@ -39,125 +39,61 @@
|
||||||
|
|
||||||
let {{
|
let {{
|
||||||
vfpEnabledCheckCode = '''
|
vfpEnabledCheckCode = '''
|
||||||
uint32_t issEnCheck;
|
{
|
||||||
bool trapEnCheck;
|
Fault fault = checkAdvSIMDOrFPEnabled32(xc->tcBase(),
|
||||||
uint32_t seq;
|
Cpsr, Cpacr, Nsacr, Fpexc,
|
||||||
if (!vfpNeonEnabled(seq,Hcptr, Nsacr, Cpacr, Cpsr, issEnCheck,
|
true, false);
|
||||||
trapEnCheck, xc->tcBase(), Fpexc))
|
if (fault != NoFault)
|
||||||
{return disabledFault();}
|
return fault;
|
||||||
if (trapEnCheck) {
|
}
|
||||||
CPSR cpsrEnCheck = Cpsr;
|
|
||||||
if (cpsrEnCheck.mode == MODE_HYP) {
|
|
||||||
return std::make_shared<UndefinedInstruction>(
|
|
||||||
machInst, issEnCheck,
|
|
||||||
EC_TRAPPED_HCPTR, mnemonic);
|
|
||||||
} else {
|
|
||||||
if (!inSecureState(Scr, Cpsr)) {
|
|
||||||
return std::make_shared<HypervisorTrap>(
|
|
||||||
machInst, issEnCheck,
|
|
||||||
EC_TRAPPED_HCPTR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
vfp64EnabledCheckCode = '''
|
vfp64EnabledCheckCode = '''
|
||||||
CPSR cpsrEnCheck = Cpsr;
|
{
|
||||||
ExceptionLevel el = (ExceptionLevel) (uint8_t) cpsrEnCheck.el;
|
Fault fault = checkFPAdvSIMDEnabled64(xc->tcBase(), Cpsr, Cpacr64);
|
||||||
if (!vfpNeon64Enabled(Cpacr64, el))
|
if (fault != NoFault)
|
||||||
return std::make_shared<SupervisorTrap>(machInst, 0x1E00000,
|
return fault;
|
||||||
EC_TRAPPED_SIMD_FP);
|
}
|
||||||
|
|
||||||
if (ArmSystem::haveVirtualization(xc->tcBase()) && el <= EL2) {
|
|
||||||
HCPTR cptrEnCheck = xc->tcBase()->readMiscReg(MISCREG_CPTR_EL2);
|
|
||||||
if (cptrEnCheck.tfp)
|
|
||||||
return std::make_shared<HypervisorTrap>(machInst, 0x1E00000,
|
|
||||||
EC_TRAPPED_SIMD_FP);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ArmSystem::haveSecurity(xc->tcBase())) {
|
|
||||||
HCPTR cptrEnCheck = xc->tcBase()->readMiscReg(MISCREG_CPTR_EL3);
|
|
||||||
if (cptrEnCheck.tfp)
|
|
||||||
return std::make_shared<SecureMonitorTrap>(machInst, 0x1E00000,
|
|
||||||
EC_TRAPPED_SIMD_FP);
|
|
||||||
}
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
vmsrEnabledCheckCode = '''
|
vmsrEnabledCheckCode = '''
|
||||||
uint32_t issEnCheck;
|
{
|
||||||
bool trapEnCheck;
|
Fault fault = NoFault;
|
||||||
uint32_t seq;
|
if (dest == (int)MISCREG_FPSCR) {
|
||||||
if (!vfpNeonEnabled(seq,Hcptr, Nsacr, Cpacr, Cpsr, issEnCheck,
|
fault = checkAdvSIMDOrFPEnabled32(xc->tcBase(),
|
||||||
trapEnCheck, xc->tcBase()))
|
Cpsr, Cpacr, Nsacr, Fpexc,
|
||||||
if (dest != (int)MISCREG_FPEXC && dest != (int)MISCREG_FPSID)
|
true, false);
|
||||||
{return disabledFault();}
|
} else if (!inPrivilegedMode(Cpsr)) {
|
||||||
if (!inPrivilegedMode(Cpsr))
|
fault = disabledFault();
|
||||||
if (dest != (int)MISCREG_FPSCR)
|
} else {
|
||||||
return disabledFault();
|
fault = checkAdvSIMDOrFPEnabled32(xc->tcBase(),
|
||||||
if (trapEnCheck) {
|
Cpsr, Cpacr, Nsacr, Fpexc,
|
||||||
CPSR cpsrEnCheck = Cpsr;
|
false, false);
|
||||||
if (cpsrEnCheck.mode == MODE_HYP) {
|
|
||||||
return std::make_shared<UndefinedInstruction>(
|
|
||||||
machInst, issEnCheck,
|
|
||||||
EC_TRAPPED_HCPTR, mnemonic);
|
|
||||||
} else {
|
|
||||||
if (!inSecureState(Scr, Cpsr)) {
|
|
||||||
return std::make_shared<HypervisorTrap>(
|
|
||||||
machInst, issEnCheck,
|
|
||||||
EC_TRAPPED_HCPTR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fault != NoFault)
|
||||||
|
return fault;
|
||||||
|
}
|
||||||
'''
|
'''
|
||||||
|
|
||||||
vmrsEnabledCheckCode = '''
|
vmrsEnabledCheckCode = '''
|
||||||
uint32_t issEnCheck;
|
{
|
||||||
bool trapEnCheck;
|
Fault fault = NoFault;
|
||||||
uint32_t seq;
|
if (op1 == (int)MISCREG_FPSCR) {
|
||||||
if (!vfpNeonEnabled(seq,Hcptr, Nsacr, Cpacr, Cpsr, issEnCheck,
|
fault = checkAdvSIMDOrFPEnabled32(xc->tcBase(),
|
||||||
trapEnCheck, xc->tcBase()))
|
Cpsr, Cpacr, Nsacr, Fpexc,
|
||||||
if (op1 != (int)MISCREG_FPEXC && op1 != (int)MISCREG_FPSID &&
|
true, false);
|
||||||
op1 != (int)MISCREG_MVFR0 && op1 != (int)MISCREG_MVFR1)
|
} else if (!inPrivilegedMode(Cpsr)) {
|
||||||
{return disabledFault();}
|
fault = disabledFault();
|
||||||
if (!inPrivilegedMode(Cpsr))
|
} else {
|
||||||
if (op1 != (int)MISCREG_FPSCR)
|
fault = checkAdvSIMDOrFPEnabled32(xc->tcBase(),
|
||||||
return disabledFault();
|
Cpsr, Cpacr, Nsacr, Fpexc,
|
||||||
if (trapEnCheck) {
|
false, false);
|
||||||
CPSR cpsrEnCheck = Cpsr;
|
|
||||||
if (cpsrEnCheck.mode == MODE_HYP) {
|
|
||||||
return std::make_shared<UndefinedInstruction>(
|
|
||||||
machInst, issEnCheck,
|
|
||||||
EC_TRAPPED_HCPTR, mnemonic);
|
|
||||||
} else {
|
|
||||||
if (!inSecureState(Scr, Cpsr)) {
|
|
||||||
return std::make_shared<HypervisorTrap>(
|
|
||||||
machInst, issEnCheck,
|
|
||||||
EC_TRAPPED_HCPTR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
'''
|
|
||||||
vmrsApsrEnabledCheckCode = '''
|
|
||||||
uint32_t issEnCheck;
|
|
||||||
bool trapEnCheck;
|
|
||||||
uint32_t seq;
|
|
||||||
if (!vfpNeonEnabled(seq,Hcptr, Nsacr, Cpacr, Cpsr, issEnCheck,
|
|
||||||
trapEnCheck, xc->tcBase()))
|
|
||||||
{return disabledFault();}
|
|
||||||
if (trapEnCheck) {
|
|
||||||
CPSR cpsrEnCheck = Cpsr;
|
|
||||||
if (cpsrEnCheck.mode == MODE_HYP) {
|
|
||||||
return std::make_shared<UndefinedInstruction>(
|
|
||||||
machInst, issEnCheck,
|
|
||||||
EC_TRAPPED_HCPTR, mnemonic);
|
|
||||||
} else {
|
|
||||||
if (!inSecureState(Scr, Cpsr)) {
|
|
||||||
return std::make_shared<HypervisorTrap>(
|
|
||||||
machInst, issEnCheck,
|
|
||||||
EC_TRAPPED_HCPTR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fault != NoFault)
|
||||||
|
return fault;
|
||||||
|
}
|
||||||
'''
|
'''
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
|
|
@ -869,91 +869,6 @@ decodeMrsMsrBankedReg(uint8_t sysM, bool r, bool &isIntReg, int ®Idx,
|
||||||
return (ok);
|
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
|
bool
|
||||||
SPAlignmentCheckEnabled(ThreadContext* tc)
|
SPAlignmentCheckEnabled(ThreadContext* tc)
|
||||||
{
|
{
|
||||||
|
|
|
@ -260,20 +260,6 @@ bool msrMrs64TrapToHyp(const MiscRegIndex miscReg, bool isRead, CPTR cptr,
|
||||||
bool msrMrs64TrapToMon(const MiscRegIndex miscReg, CPTR cptr,
|
bool msrMrs64TrapToMon(const MiscRegIndex miscReg, CPTR cptr,
|
||||||
ExceptionLevel el, bool * isVfpNeon);
|
ExceptionLevel el, bool * isVfpNeon);
|
||||||
|
|
||||||
bool
|
|
||||||
vfpNeonEnabled(uint32_t &seq, HCPTR hcptr, NSACR nsacr, CPACR cpacr, CPSR cpsr,
|
|
||||||
uint32_t &iss, bool &trap, ThreadContext *tc,
|
|
||||||
FPEXC fpexc = (1<<30), bool isSIMD = false);
|
|
||||||
|
|
||||||
static inline bool
|
|
||||||
vfpNeon64Enabled(CPACR cpacr, ExceptionLevel el)
|
|
||||||
{
|
|
||||||
if ((el == EL0 && cpacr.fpen != 0x3) ||
|
|
||||||
(el == EL1 && !(cpacr.fpen & 0x1)))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SPAlignmentCheckEnabled(ThreadContext* tc);
|
bool SPAlignmentCheckEnabled(ThreadContext* tc);
|
||||||
|
|
||||||
uint64_t getArgument(ThreadContext *tc, int &number, uint16_t size, bool fp);
|
uint64_t getArgument(ThreadContext *tc, int &number, uint16_t size, bool fp);
|
||||||
|
|
Loading…
Reference in a new issue