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:
Giacomo Travaglini
2024-04-25 14:57:10 +01:00
committed by GitHub
3 changed files with 114 additions and 26 deletions

View File

@@ -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

View File

@@ -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;

View 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__