arch-arm: Add misc_accessor templated functions to read/write regs at different ELs (#1072)
A usual system register read/write pattern is something like the
following
```
switch(el) {
case EL1:
tc->readMiscReg(REG_EL1);
case EL2:
tc->readMiscReg(REG_EL2);
case EL3:
tc->readMiscReg(REG_EL3);
}
```
To avoid repeating these switch statements all over gem5, we define
templated functions which have
an accessor struct as a template parameter. These accessor will help
populating the templated switch
construct. We provide the FAR register accessor as an example. The
accessor should define the following
fields: (type, el0, el1, el2, el3)
Example:
```
struct FarAccessor
{
using type = RegVal;
static const MiscRegIndex el0 = NUM_MISCREGS;
static const MiscRegIndex el1 = MISCREG_FAR_EL1;
static const MiscRegIndex el2 = MISCREG_FAR_EL2;
static const MiscRegIndex el3 = MISCREG_FAR_EL3;
};
```
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2010, 2012-2014, 2016-2019, 2022 Arm Limited
|
* Copyright (c) 2010, 2012-2014, 2016-2019, 2022, 2024 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
|
||||||
@@ -44,6 +44,7 @@
|
|||||||
#include "arch/arm/insts/static_inst.hh"
|
#include "arch/arm/insts/static_inst.hh"
|
||||||
#include "arch/arm/interrupts.hh"
|
#include "arch/arm/interrupts.hh"
|
||||||
#include "arch/arm/isa.hh"
|
#include "arch/arm/isa.hh"
|
||||||
|
#include "arch/arm/regs/misc_accessors.hh"
|
||||||
#include "arch/arm/self_debug.hh"
|
#include "arch/arm/self_debug.hh"
|
||||||
#include "arch/arm/system.hh"
|
#include "arch/arm/system.hh"
|
||||||
#include "arch/arm/utility.hh"
|
#include "arch/arm/utility.hh"
|
||||||
@@ -378,22 +379,6 @@ ArmFault::getSyndromeReg64() const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MiscRegIndex
|
|
||||||
ArmFault::getFaultAddrReg64() const
|
|
||||||
{
|
|
||||||
switch (toEL) {
|
|
||||||
case EL1:
|
|
||||||
return MISCREG_FAR_EL1;
|
|
||||||
case EL2:
|
|
||||||
return MISCREG_FAR_EL2;
|
|
||||||
case EL3:
|
|
||||||
return MISCREG_FAR_EL3;
|
|
||||||
default:
|
|
||||||
panic("Invalid exception level");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ArmFault::setSyndrome(ThreadContext *tc, MiscRegIndex syndrome_reg)
|
ArmFault::setSyndrome(ThreadContext *tc, MiscRegIndex syndrome_reg)
|
||||||
{
|
{
|
||||||
@@ -1113,13 +1098,15 @@ AbortFault<T>::invoke(ThreadContext *tc, const StaticInstPtr &inst)
|
|||||||
if (stage2) {
|
if (stage2) {
|
||||||
// stage 2 fault, set HPFAR_EL2 to the faulting IPA
|
// stage 2 fault, set HPFAR_EL2 to the faulting IPA
|
||||||
// and FAR_EL2 to the Original VA
|
// and FAR_EL2 to the Original VA
|
||||||
tc->setMiscReg(AbortFault<T>::getFaultAddrReg64(), OVAddr);
|
misc_regs::writeRegister<misc_regs::FarAccessor>(
|
||||||
|
tc, OVAddr, this->toEL);
|
||||||
tc->setMiscReg(MISCREG_HPFAR_EL2, bits(faultAddr, 47, 12) << 4);
|
tc->setMiscReg(MISCREG_HPFAR_EL2, bits(faultAddr, 47, 12) << 4);
|
||||||
|
|
||||||
DPRINTF(Faults, "Abort Fault (Stage 2) VA: 0x%x IPA: 0x%x\n",
|
DPRINTF(Faults, "Abort Fault (Stage 2) VA: 0x%x IPA: 0x%x\n",
|
||||||
OVAddr, faultAddr);
|
OVAddr, faultAddr);
|
||||||
} else {
|
} else {
|
||||||
tc->setMiscReg(AbortFault<T>::getFaultAddrReg64(), faultAddr);
|
misc_regs::writeRegister<misc_regs::FarAccessor>(
|
||||||
|
tc, faultAddr, this->toEL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1517,7 +1504,7 @@ PCAlignmentFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
|
|||||||
ArmFaultVals<PCAlignmentFault>::invoke(tc, inst);
|
ArmFaultVals<PCAlignmentFault>::invoke(tc, inst);
|
||||||
assert(from64);
|
assert(from64);
|
||||||
// Set the FAR
|
// Set the FAR
|
||||||
tc->setMiscReg(getFaultAddrReg64(), faultPC);
|
misc_regs::writeRegister<misc_regs::FarAccessor>(tc, faultPC, toEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@@ -1661,8 +1648,7 @@ Watchpoint::invoke(ThreadContext *tc, const StaticInstPtr &inst)
|
|||||||
{
|
{
|
||||||
ArmFaultVals<Watchpoint>::invoke(tc, inst);
|
ArmFaultVals<Watchpoint>::invoke(tc, inst);
|
||||||
// Set the FAR
|
// Set the FAR
|
||||||
tc->setMiscReg(getFaultAddrReg64(), vAddr);
|
misc_regs::writeRegister<misc_regs::FarAccessor>(tc, vAddr, toEL);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2010, 2012-2013, 2016-2019, 2022 Arm Limited
|
* Copyright (c) 2010, 2012-2013, 2016-2019, 2022, 2024 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
|
||||||
@@ -220,9 +220,6 @@ class ArmFault : public FaultBase
|
|||||||
// Returns the actual syndrome register to use based on the target
|
// Returns the actual syndrome register to use based on the target
|
||||||
// exception level
|
// exception level
|
||||||
MiscRegIndex getSyndromeReg64() const;
|
MiscRegIndex getSyndromeReg64() const;
|
||||||
// Returns the actual fault address register to use based on the target
|
|
||||||
// exception level
|
|
||||||
MiscRegIndex getFaultAddrReg64() const;
|
|
||||||
|
|
||||||
void invoke(ThreadContext *tc, const StaticInstPtr &inst =
|
void invoke(ThreadContext *tc, const StaticInstPtr &inst =
|
||||||
nullStaticInstPtr) override;
|
nullStaticInstPtr) override;
|
||||||
|
|||||||
105
src/arch/arm/regs/misc_accessors.hh
Normal file
105
src/arch/arm/regs/misc_accessors.hh
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Arm Limited
|
||||||
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ARCH_ARM_REGS_MISC_ACCESSORS_HH__
|
||||||
|
#define __ARCH_ARM_REGS_MISC_ACCESSORS_HH__
|
||||||
|
|
||||||
|
#include "arch/arm/regs/misc_types.hh"
|
||||||
|
#include "cpu/thread_context.hh"
|
||||||
|
|
||||||
|
namespace gem5
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace ArmISA
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace misc_regs
|
||||||
|
{
|
||||||
|
|
||||||
|
struct FarAccessor
|
||||||
|
{
|
||||||
|
using type = RegVal;
|
||||||
|
static const MiscRegIndex el0 = NUM_MISCREGS;
|
||||||
|
static const MiscRegIndex el1 = MISCREG_FAR_EL1;
|
||||||
|
static const MiscRegIndex el2 = MISCREG_FAR_EL2;
|
||||||
|
static const MiscRegIndex el3 = MISCREG_FAR_EL3;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename RegAccessor>
|
||||||
|
MiscRegIndex
|
||||||
|
getRegVersion(ExceptionLevel el)
|
||||||
|
{
|
||||||
|
switch (el) {
|
||||||
|
case EL0:
|
||||||
|
return RegAccessor::el0;
|
||||||
|
case EL1:
|
||||||
|
return RegAccessor::el1;
|
||||||
|
case EL2:
|
||||||
|
return RegAccessor::el2;
|
||||||
|
case EL3:
|
||||||
|
return RegAccessor::el3;
|
||||||
|
default:
|
||||||
|
panic("Invalid EL\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename RegAccessor>
|
||||||
|
typename RegAccessor::type
|
||||||
|
readRegister(ThreadContext *tc, ExceptionLevel el)
|
||||||
|
{
|
||||||
|
return tc->readMiscReg(getRegVersion<RegAccessor>(el));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename RegAccessor>
|
||||||
|
typename RegAccessor::type
|
||||||
|
readRegisterNoEffect(ThreadContext *tc, ExceptionLevel el)
|
||||||
|
{
|
||||||
|
return tc->readMiscRegNoEffect(getRegVersion<RegAccessor>(el));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename RegAccessor>
|
||||||
|
void
|
||||||
|
writeRegister(ThreadContext *tc, RegVal val, ExceptionLevel el)
|
||||||
|
{
|
||||||
|
tc->setMiscReg(getRegVersion<RegAccessor>(el), val);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace misc_regs
|
||||||
|
} // namespace ArmISA
|
||||||
|
} // namespace gem5
|
||||||
|
|
||||||
|
#endif // __ARCH_ARM_REGS_MISC_ACCESSORS_HH__
|
||||||
Reference in New Issue
Block a user