utility.cc revision 12788
1955SN/A/*
2955SN/A * Copyright (c) 2009-2014, 2016-2018 ARM Limited
31762SN/A * All rights reserved.
4955SN/A *
5955SN/A * The license below extends only to copyright in the software and shall
6955SN/A * not be construed as granting a license to any other intellectual
7955SN/A * property including but not limited to intellectual property relating
8955SN/A * to a hardware implementation of the functionality of the software
9955SN/A * licensed hereunder.  You may use the software subject to the license
10955SN/A * terms below provided that you ensure that this notice is replicated
11955SN/A * unmodified and in its entirety in all distributions of the software,
12955SN/A * modified or unmodified, in source code or in binary form.
13955SN/A *
14955SN/A * Redistribution and use in source and binary forms, with or without
15955SN/A * modification, are permitted provided that the following conditions are
16955SN/A * met: redistributions of source code must retain the above copyright
17955SN/A * notice, this list of conditions and the following disclaimer;
18955SN/A * redistributions in binary form must reproduce the above copyright
19955SN/A * notice, this list of conditions and the following disclaimer in the
20955SN/A * documentation and/or other materials provided with the distribution;
21955SN/A * neither the name of the copyright holders nor the names of its
22955SN/A * contributors may be used to endorse or promote products derived from
23955SN/A * this software without specific prior written permission.
24955SN/A *
25955SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26955SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27955SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
282665Ssaidi@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
294762Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30955SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
315522Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
326143Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
334762Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
345522Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35955SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
365522Snate@binkert.org *
37955SN/A * Authors: Ali Saidi
385522Snate@binkert.org */
394202Sbinkertn@umich.edu
405742Snate@binkert.org#include "arch/arm/utility.hh"
41955SN/A
424381Sbinkertn@umich.edu#include <memory>
434381Sbinkertn@umich.edu
44955SN/A#include "arch/arm/faults.hh"
45955SN/A#include "arch/arm/isa_traits.hh"
46955SN/A#include "arch/arm/system.hh"
474202Sbinkertn@umich.edu#include "arch/arm/tlb.hh"
48955SN/A#include "arch/arm/vtophys.hh"
494382Sbinkertn@umich.edu#include "cpu/base.hh"
504382Sbinkertn@umich.edu#include "cpu/checker/cpu.hh"
514382Sbinkertn@umich.edu#include "cpu/thread_context.hh"
526654Snate@binkert.org#include "mem/fs_translating_port_proxy.hh"
535517Snate@binkert.org#include "sim/full_system.hh"
546143Snate@binkert.org
556143Snate@binkert.orgnamespace ArmISA {
566143Snate@binkert.org
576143Snate@binkert.orgvoid
586143Snate@binkert.orginitCPU(ThreadContext *tc, int cpuId)
596143Snate@binkert.org{
606143Snate@binkert.org    // Reset CP15?? What does that mean -- ali
616143Snate@binkert.org
626143Snate@binkert.org    // FPEXC.EN = 0
636143Snate@binkert.org
646143Snate@binkert.org    static Fault reset = std::make_shared<Reset>();
656143Snate@binkert.org    reset->invoke(tc);
666143Snate@binkert.org}
676143Snate@binkert.org
686143Snate@binkert.orguint64_t
694762Snate@binkert.orggetArgument(ThreadContext *tc, int &number, uint16_t size, bool fp)
706143Snate@binkert.org{
716143Snate@binkert.org    if (!FullSystem) {
726143Snate@binkert.org        panic("getArgument() only implemented for full system mode.\n");
736143Snate@binkert.org        M5_DUMMY_RETURN
746143Snate@binkert.org    }
756143Snate@binkert.org
766143Snate@binkert.org    if (fp)
776143Snate@binkert.org        panic("getArgument(): Floating point arguments not implemented\n");
786143Snate@binkert.org
796143Snate@binkert.org    if (inAArch64(tc)) {
806143Snate@binkert.org        if (size == (uint16_t)(-1))
816143Snate@binkert.org            size = sizeof(uint64_t);
826143Snate@binkert.org
836143Snate@binkert.org        if (number < 8 /*NumArgumentRegs64*/) {
846143Snate@binkert.org               return tc->readIntReg(number);
856143Snate@binkert.org        } else {
866143Snate@binkert.org            panic("getArgument(): No support reading stack args for AArch64\n");
876143Snate@binkert.org        }
886143Snate@binkert.org    } else {
896143Snate@binkert.org        if (size == (uint16_t)(-1))
906143Snate@binkert.org            // todo: should this not be sizeof(uint32_t) rather?
916143Snate@binkert.org            size = ArmISA::MachineBytes;
926143Snate@binkert.org
936143Snate@binkert.org        if (number < NumArgumentRegs) {
946143Snate@binkert.org            // If the argument is 64 bits, it must be in an even regiser
956143Snate@binkert.org            // number. Increment the number here if it isn't even.
966143Snate@binkert.org            if (size == sizeof(uint64_t)) {
976143Snate@binkert.org                if ((number % 2) != 0)
986143Snate@binkert.org                    number++;
996143Snate@binkert.org                // Read the two halves of the data. Number is inc here to
1006143Snate@binkert.org                // get the second half of the 64 bit reg.
1016143Snate@binkert.org                uint64_t tmp;
1026143Snate@binkert.org                tmp = tc->readIntReg(number++);
1036143Snate@binkert.org                tmp |= tc->readIntReg(number) << 32;
1046143Snate@binkert.org                return tmp;
1056143Snate@binkert.org            } else {
1066143Snate@binkert.org               return tc->readIntReg(number);
1076143Snate@binkert.org            }
1086143Snate@binkert.org        } else {
1096143Snate@binkert.org            Addr sp = tc->readIntReg(StackPointerReg);
1106143Snate@binkert.org            FSTranslatingPortProxy &vp = tc->getVirtProxy();
1116143Snate@binkert.org            uint64_t arg;
1126143Snate@binkert.org            if (size == sizeof(uint64_t)) {
1135522Snate@binkert.org                // If the argument is even it must be aligned
1146143Snate@binkert.org                if ((number % 2) != 0)
1156143Snate@binkert.org                    number++;
1166143Snate@binkert.org                arg = vp.read<uint64_t>(sp +
1176143Snate@binkert.org                        (number-NumArgumentRegs) * sizeof(uint32_t));
1186143Snate@binkert.org                // since two 32 bit args == 1 64 bit arg, increment number
1196143Snate@binkert.org                number++;
1206143Snate@binkert.org            } else {
1216143Snate@binkert.org                arg = vp.read<uint32_t>(sp +
1226143Snate@binkert.org                               (number-NumArgumentRegs) * sizeof(uint32_t));
1236143Snate@binkert.org            }
1245522Snate@binkert.org            return arg;
1255522Snate@binkert.org        }
1265522Snate@binkert.org    }
1275522Snate@binkert.org    panic("getArgument() should always return\n");
1285604Snate@binkert.org}
1295604Snate@binkert.org
1306143Snate@binkert.orgvoid
1316143Snate@binkert.orgskipFunction(ThreadContext *tc)
1324762Snate@binkert.org{
1334762Snate@binkert.org    PCState newPC = tc->pcState();
1346143Snate@binkert.org    if (inAArch64(tc)) {
1356143Snate@binkert.org        newPC.set(tc->readIntReg(INTREG_X30));
1366143Snate@binkert.org    } else {
1376143Snate@binkert.org        newPC.set(tc->readIntReg(ReturnAddressReg) & ~ULL(1));
1384762Snate@binkert.org    }
1396143Snate@binkert.org
1406143Snate@binkert.org    CheckerCPU *checker = tc->getCheckerCpuPtr();
1416143Snate@binkert.org    if (checker) {
1426143Snate@binkert.org        tc->pcStateNoRecord(newPC);
1436143Snate@binkert.org    } else {
1446143Snate@binkert.org        tc->pcState(newPC);
1456143Snate@binkert.org    }
1466143Snate@binkert.org}
1475604Snate@binkert.org
1486143Snate@binkert.orgvoid
1496143Snate@binkert.orgcopyRegs(ThreadContext *src, ThreadContext *dest)
1506143Snate@binkert.org{
1514762Snate@binkert.org    for (int i = 0; i < NumIntRegs; i++)
1526143Snate@binkert.org        dest->setIntRegFlat(i, src->readIntRegFlat(i));
1534762Snate@binkert.org
1544762Snate@binkert.org    for (int i = 0; i < NumFloatRegs; i++)
1554762Snate@binkert.org        dest->setFloatRegFlat(i, src->readFloatRegFlat(i));
1566143Snate@binkert.org
1576143Snate@binkert.org    for (int i = 0; i < NumVecRegs; i++)
1584762Snate@binkert.org        dest->setVecRegFlat(i, src->readVecRegFlat(i));
1596143Snate@binkert.org
1606143Snate@binkert.org    for (int i = 0; i < NumCCRegs; i++)
1616143Snate@binkert.org        dest->setCCReg(i, src->readCCReg(i));
1626143Snate@binkert.org
1634762Snate@binkert.org    for (int i = 0; i < NumMiscRegs; i++)
1646143Snate@binkert.org        dest->setMiscRegNoEffect(i, src->readMiscRegNoEffect(i));
1654762Snate@binkert.org
1666143Snate@binkert.org    // setMiscReg "with effect" will set the misc register mapping correctly.
1674762Snate@binkert.org    // e.g. updateRegMap(val)
1686143Snate@binkert.org    dest->setMiscReg(MISCREG_CPSR, src->readMiscRegNoEffect(MISCREG_CPSR));
1696143Snate@binkert.org
1706143Snate@binkert.org    // Copy over the PC State
1716143Snate@binkert.org    dest->pcState(src->pcState());
1726143Snate@binkert.org
1736143Snate@binkert.org    // Invalidate the tlb misc register cache
1746143Snate@binkert.org    dynamic_cast<TLB *>(dest->getITBPtr())->invalidateMiscReg();
1756143Snate@binkert.org    dynamic_cast<TLB *>(dest->getDTBPtr())->invalidateMiscReg();
1766143Snate@binkert.org}
1776143Snate@binkert.org
1786143Snate@binkert.orgbool
1796143Snate@binkert.orginSecureState(ThreadContext *tc)
1806143Snate@binkert.org{
181955SN/A    SCR scr = inAArch64(tc) ? tc->readMiscReg(MISCREG_SCR_EL3) :
1825584Snate@binkert.org        tc->readMiscReg(MISCREG_SCR);
1835584Snate@binkert.org    return ArmSystem::haveSecurity(tc) && inSecureState(
1845584Snate@binkert.org        scr, tc->readMiscReg(MISCREG_CPSR));
1855584Snate@binkert.org}
1866143Snate@binkert.org
1876143Snate@binkert.orginline bool
1886143Snate@binkert.orgisSecureBelowEL3(ThreadContext *tc)
1895584Snate@binkert.org{
1904382Sbinkertn@umich.edu    SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
1914202Sbinkertn@umich.edu    return ArmSystem::haveEL(tc, EL3) && scr.ns == 0;
1924382Sbinkertn@umich.edu}
1934382Sbinkertn@umich.edu
1944382Sbinkertn@umich.edubool
1955584Snate@binkert.orginAArch64(ThreadContext *tc)
1964382Sbinkertn@umich.edu{
1974382Sbinkertn@umich.edu    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
1984382Sbinkertn@umich.edu    return opModeIs64((OperatingMode) (uint8_t) cpsr.mode);
1995192Ssaidi@eecs.umich.edu}
2005192Ssaidi@eecs.umich.edu
2015799Snate@binkert.orgbool
2025799Snate@binkert.orglongDescFormatInUse(ThreadContext *tc)
2035799Snate@binkert.org{
2045192Ssaidi@eecs.umich.edu    TTBCR ttbcr = tc->readMiscReg(MISCREG_TTBCR);
2055799Snate@binkert.org    return ArmSystem::haveLPAE(tc) && ttbcr.eae;
2065192Ssaidi@eecs.umich.edu}
2075799Snate@binkert.org
2085799Snate@binkert.orguint32_t
2095192Ssaidi@eecs.umich.edugetMPIDR(ArmSystem *arm_sys, ThreadContext *tc)
2105192Ssaidi@eecs.umich.edu{
2115192Ssaidi@eecs.umich.edu    // Multiprocessor Affinity Register MPIDR from Cortex(tm)-A15 Technical
2125799Snate@binkert.org    // Reference Manual
2135192Ssaidi@eecs.umich.edu    //
2145192Ssaidi@eecs.umich.edu    // bit   31 - Multi-processor extensions available
2155192Ssaidi@eecs.umich.edu    // bit   30 - Uni-processor system
2165192Ssaidi@eecs.umich.edu    // bit   24 - Multi-threaded cores
2175192Ssaidi@eecs.umich.edu    // bit 11-8 - Cluster ID
2185192Ssaidi@eecs.umich.edu    // bit  1-0 - CPU ID
2194382Sbinkertn@umich.edu    //
2204382Sbinkertn@umich.edu    // We deliberately extend both the Cluster ID and CPU ID fields to allow
2214382Sbinkertn@umich.edu    // for simulation of larger systems
2222667Sstever@eecs.umich.edu    assert((0 <= tc->cpuId()) && (tc->cpuId() < 256));
2232667Sstever@eecs.umich.edu    assert(tc->socketId() < 65536);
2242667Sstever@eecs.umich.edu    if (arm_sys->multiThread) {
2252667Sstever@eecs.umich.edu       return 0x80000000 | // multiprocessor extensions available
2262667Sstever@eecs.umich.edu              0x01000000 | // multi-threaded cores
2272667Sstever@eecs.umich.edu              tc->contextId();
2285742Snate@binkert.org    } else if (arm_sys->multiProc) {
2295742Snate@binkert.org       return 0x80000000 | // multiprocessor extensions available
2305742Snate@binkert.org              tc->cpuId() | tc->socketId() << 8;
2312037SN/A    } else {
2322037SN/A       return 0x80000000 |  // multiprocessor extensions available
2332037SN/A              0x40000000 |  // in up system
2345793Snate@binkert.org              tc->cpuId() | tc->socketId() << 8;
2355793Snate@binkert.org    }
2365793Snate@binkert.org}
2375793Snate@binkert.org
2385793Snate@binkert.orgbool
2394382Sbinkertn@umich.eduELIs64(ThreadContext *tc, ExceptionLevel el)
2404762Snate@binkert.org{
2415344Sstever@gmail.com    return !ELIs32(tc, el);
2424382Sbinkertn@umich.edu}
2435341Sstever@gmail.com
2445742Snate@binkert.orgbool
2455742Snate@binkert.orgELIs32(ThreadContext *tc, ExceptionLevel el)
2465742Snate@binkert.org{
2475742Snate@binkert.org    bool known, aarch32;
2485742Snate@binkert.org    std::tie(known, aarch32) = ELUsingAArch32K(tc, el);
2494762Snate@binkert.org    panic_if(!known, "EL state is UNKNOWN");
2505742Snate@binkert.org    return aarch32;
2515742Snate@binkert.org}
2525742Snate@binkert.org
2535742Snate@binkert.orgstd::pair<bool, bool>
2545742Snate@binkert.orgELUsingAArch32K(ThreadContext *tc, ExceptionLevel el)
2555742Snate@binkert.org{
2565742Snate@binkert.org    // Return true if the specified EL is in aarch32 state.
2575341Sstever@gmail.com    const bool have_el3 = ArmSystem::haveSecurity(tc);
2585742Snate@binkert.org    const bool have_el2 = ArmSystem::haveVirtualization(tc);
2595341Sstever@gmail.com
2604773Snate@binkert.org    panic_if(el == EL2 && !have_el2, "Asking for EL2 when it doesn't exist");
2616108Snate@binkert.org    panic_if(el == EL3 && !have_el3, "Asking for EL3 when it doesn't exist");
2621858SN/A
2631085SN/A    bool known, aarch32;
2644382Sbinkertn@umich.edu    known = aarch32 = false;
2654382Sbinkertn@umich.edu    if (ArmSystem::highestELIs64(tc) && ArmSystem::highestEL(tc) == el) {
2664762Snate@binkert.org        // Target EL is the highest one in a system where
2674762Snate@binkert.org        // the highest is using AArch64.
2684762Snate@binkert.org        known = true; aarch32 = false;
2696654Snate@binkert.org    } else if (!ArmSystem::highestELIs64(tc)) {
2706654Snate@binkert.org        // All ELs are using AArch32:
2715517Snate@binkert.org        known = true; aarch32 = true;
2725517Snate@binkert.org    } else {
2735517Snate@binkert.org        SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
2745517Snate@binkert.org        bool aarch32_below_el3 = (have_el3 && scr.rw == 0);
2755517Snate@binkert.org
2765517Snate@binkert.org        HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
2775517Snate@binkert.org        bool aarch32_at_el1 = (aarch32_below_el3
2785517Snate@binkert.org                               || (have_el2
2795517Snate@binkert.org                               && !isSecureBelowEL3(tc) && hcr.rw == 0));
2805517Snate@binkert.org
2815517Snate@binkert.org        // Only know if EL0 using AArch32 from PSTATE
2825517Snate@binkert.org        if (el == EL0 && !aarch32_at_el1) {
2835517Snate@binkert.org            // EL0 controlled by PSTATE
2845517Snate@binkert.org            CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
2855517Snate@binkert.org
2865517Snate@binkert.org            known = (cpsr.el == EL0);
2875517Snate@binkert.org            aarch32 = (cpsr.width == 1);
2886654Snate@binkert.org        } else {
2895517Snate@binkert.org            known = true;
2905517Snate@binkert.org            aarch32 = (aarch32_below_el3 && el != EL3)
2915517Snate@binkert.org                      || (aarch32_at_el1 && (el == EL0 || el == EL1) );
2925517Snate@binkert.org        }
2935517Snate@binkert.org    }
2945517Snate@binkert.org
2955517Snate@binkert.org    return std::make_pair(known, aarch32);
2965517Snate@binkert.org}
2976143Snate@binkert.org
2986654Snate@binkert.orgbool
2995517Snate@binkert.orgisBigEndian64(ThreadContext *tc)
3005517Snate@binkert.org{
3015517Snate@binkert.org    switch (opModeToEL(currOpMode(tc))) {
3025517Snate@binkert.org      case EL3:
3035517Snate@binkert.org        return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL3)).ee;
3045517Snate@binkert.org      case EL2:
3055517Snate@binkert.org        return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL2)).ee;
3065517Snate@binkert.org      case EL1:
3075517Snate@binkert.org        return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL1)).ee;
3085517Snate@binkert.org      case EL0:
3095517Snate@binkert.org        return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL1)).e0e;
3105517Snate@binkert.org      default:
3115517Snate@binkert.org        panic("Invalid exception level");
3125517Snate@binkert.org        break;
3136654Snate@binkert.org    }
3146654Snate@binkert.org}
3155517Snate@binkert.org
3165517Snate@binkert.orgbool
3176143Snate@binkert.orgbadMode32(ThreadContext *tc, OperatingMode mode)
3186143Snate@binkert.org{
3196143Snate@binkert.org    return unknownMode32(mode) || !ArmSystem::haveEL(tc, opModeToEL(mode));
3206143Snate@binkert.org}
3215517Snate@binkert.org
3226143Snate@binkert.orgbool
3235517Snate@binkert.orgbadMode(ThreadContext *tc, OperatingMode mode)
3245517Snate@binkert.org{
3255517Snate@binkert.org    return unknownMode(mode) || !ArmSystem::haveEL(tc, opModeToEL(mode));
3266654Snate@binkert.org}
3276654Snate@binkert.org
3286654Snate@binkert.orgAddr
3296654Snate@binkert.orgpurifyTaggedAddr(Addr addr, ThreadContext *tc, ExceptionLevel el,
3306654Snate@binkert.org                 TTBCR tcr)
3316654Snate@binkert.org{
3325517Snate@binkert.org    switch (el) {
3335517Snate@binkert.org      case EL0:
3345517Snate@binkert.org      case EL1:
3356143Snate@binkert.org        if (bits(addr, 55, 48) == 0xFF && tcr.tbi1)
3365517Snate@binkert.org            return addr | mask(63, 55);
3374762Snate@binkert.org        else if (!bits(addr, 55, 48) && tcr.tbi0)
3385517Snate@binkert.org            return bits(addr,55, 0);
3395517Snate@binkert.org        break;
3406143Snate@binkert.org      case EL2:
3416143Snate@binkert.org        assert(ArmSystem::haveVirtualization(tc));
3425517Snate@binkert.org        tcr = tc->readMiscReg(MISCREG_TCR_EL2);
3435517Snate@binkert.org        if (tcr.tbi)
3445517Snate@binkert.org            return addr & mask(56);
3455517Snate@binkert.org        break;
3465517Snate@binkert.org      case EL3:
3475517Snate@binkert.org        assert(ArmSystem::haveSecurity(tc));
3485517Snate@binkert.org        if (tcr.tbi)
3495517Snate@binkert.org            return addr & mask(56);
3505517Snate@binkert.org        break;
3515517Snate@binkert.org      default:
3526143Snate@binkert.org        panic("Invalid exception level");
3535517Snate@binkert.org        break;
3546654Snate@binkert.org    }
3556654Snate@binkert.org
3566654Snate@binkert.org    return addr;  // Nothing to do if this is not a tagged address
3576654Snate@binkert.org}
3586654Snate@binkert.org
3596654Snate@binkert.orgAddr
3605517Snate@binkert.orgpurifyTaggedAddr(Addr addr, ThreadContext *tc, ExceptionLevel el)
3615517Snate@binkert.org{
3625517Snate@binkert.org    TTBCR tcr;
3635517Snate@binkert.org
3645517Snate@binkert.org    switch (el) {
3654762Snate@binkert.org      case EL0:
3664762Snate@binkert.org      case EL1:
3674762Snate@binkert.org        tcr = tc->readMiscReg(MISCREG_TCR_EL1);
3684762Snate@binkert.org        if (bits(addr, 55, 48) == 0xFF && tcr.tbi1)
3694762Snate@binkert.org            return addr | mask(63, 55);
3704762Snate@binkert.org        else if (!bits(addr, 55, 48) && tcr.tbi0)
3716143Snate@binkert.org            return bits(addr,55, 0);
3724762Snate@binkert.org        break;
3734762Snate@binkert.org      case EL2:
3744762Snate@binkert.org        assert(ArmSystem::haveVirtualization(tc));
3754762Snate@binkert.org        tcr = tc->readMiscReg(MISCREG_TCR_EL2);
3764382Sbinkertn@umich.edu        if (tcr.tbi)
3774382Sbinkertn@umich.edu            return addr & mask(56);
3785517Snate@binkert.org        break;
3796654Snate@binkert.org      case EL3:
3805517Snate@binkert.org        assert(ArmSystem::haveSecurity(tc));
3815798Snate@binkert.org        tcr = tc->readMiscReg(MISCREG_TCR_EL3);
3826654Snate@binkert.org        if (tcr.tbi)
3836654Snate@binkert.org            return addr & mask(56);
3846654Snate@binkert.org        break;
3856654Snate@binkert.org      default:
3866654Snate@binkert.org        panic("Invalid exception level");
3876654Snate@binkert.org        break;
3886654Snate@binkert.org    }
3896654Snate@binkert.org
3906654Snate@binkert.org    return addr;  // Nothing to do if this is not a tagged address
3916654Snate@binkert.org}
3926654Snate@binkert.org
3936654Snate@binkert.orgAddr
3946654Snate@binkert.orgtruncPage(Addr addr)
3956654Snate@binkert.org{
3966654Snate@binkert.org    return addr & ~(PageBytes - 1);
3975517Snate@binkert.org}
3985863Snate@binkert.org
3995798Snate@binkert.orgAddr
4005798Snate@binkert.orgroundPage(Addr addr)
4015798Snate@binkert.org{
4025798Snate@binkert.org    return (addr + PageBytes - 1) & ~(PageBytes - 1);
4035517Snate@binkert.org}
4045517Snate@binkert.org
4055517Snate@binkert.orgbool
4065517Snate@binkert.orgmcrMrc15TrapToHyp(const MiscRegIndex miscReg, HCR hcr, CPSR cpsr, SCR scr,
4075517Snate@binkert.org                  HDCR hdcr, HSTR hstr, HCPTR hcptr, uint32_t iss)
4085517Snate@binkert.org{
4095517Snate@binkert.org    bool        isRead;
4105517Snate@binkert.org    uint32_t    crm;
4115798Snate@binkert.org    IntRegIndex rt;
4125798Snate@binkert.org    uint32_t    crn;
4135798Snate@binkert.org    uint32_t    opc1;
4145798Snate@binkert.org    uint32_t    opc2;
4155798Snate@binkert.org    bool        trapToHype = false;
4165798Snate@binkert.org
4175517Snate@binkert.org
4185517Snate@binkert.org    if (!inSecureState(scr, cpsr) && (cpsr.mode != MODE_HYP)) {
4195517Snate@binkert.org        mcrMrcIssExtract(iss, isRead, crm, rt, crn, opc1, opc2);
4205517Snate@binkert.org        trapToHype  = ((uint32_t) hstr) & (1 << crn);
4215517Snate@binkert.org        trapToHype |= hdcr.tpm  && (crn == 9) && (crm >= 12);
4225517Snate@binkert.org        trapToHype |= hcr.tidcp && (
4235517Snate@binkert.org            ((crn ==  9) && ((crm <= 2) || ((crm >= 5) && (crm <= 8)))) ||
4245517Snate@binkert.org            ((crn == 10) && ((crm <= 1) ||  (crm == 4) || (crm == 8)))  ||
4255517Snate@binkert.org            ((crn == 11) && ((crm <= 8) ||  (crm == 15)))               );
4264762Snate@binkert.org
4274382Sbinkertn@umich.edu        if (!trapToHype) {
4286143Snate@binkert.org            switch (unflattenMiscReg(miscReg)) {
4295517Snate@binkert.org              case MISCREG_CPACR:
4304382Sbinkertn@umich.edu                trapToHype = hcptr.tcpac;
4314382Sbinkertn@umich.edu                break;
4324762Snate@binkert.org              case MISCREG_REVIDR:
4334762Snate@binkert.org              case MISCREG_TCMTR:
4344762Snate@binkert.org              case MISCREG_TLBTR:
4354762Snate@binkert.org              case MISCREG_AIDR:
4364762Snate@binkert.org                trapToHype = hcr.tid1;
4375517Snate@binkert.org                break;
4385517Snate@binkert.org              case MISCREG_CTR:
4395517Snate@binkert.org              case MISCREG_CCSIDR:
4405517Snate@binkert.org              case MISCREG_CLIDR:
4415517Snate@binkert.org              case MISCREG_CSSELR:
4425517Snate@binkert.org                trapToHype = hcr.tid2;
4435517Snate@binkert.org                break;
4445517Snate@binkert.org              case MISCREG_ID_PFR0:
4456143Snate@binkert.org              case MISCREG_ID_PFR1:
4465517Snate@binkert.org              case MISCREG_ID_DFR0:
4475517Snate@binkert.org              case MISCREG_ID_AFR0:
4485517Snate@binkert.org              case MISCREG_ID_MMFR0:
4495517Snate@binkert.org              case MISCREG_ID_MMFR1:
4505517Snate@binkert.org              case MISCREG_ID_MMFR2:
4515517Snate@binkert.org              case MISCREG_ID_MMFR3:
4525517Snate@binkert.org              case MISCREG_ID_ISAR0:
4535517Snate@binkert.org              case MISCREG_ID_ISAR1:
4545517Snate@binkert.org              case MISCREG_ID_ISAR2:
4555517Snate@binkert.org              case MISCREG_ID_ISAR3:
4566143Snate@binkert.org              case MISCREG_ID_ISAR4:
4575517Snate@binkert.org              case MISCREG_ID_ISAR5:
4585517Snate@binkert.org                trapToHype = hcr.tid3;
4595517Snate@binkert.org                break;
4605517Snate@binkert.org              case MISCREG_DCISW:
4615517Snate@binkert.org              case MISCREG_DCCSW:
4625517Snate@binkert.org              case MISCREG_DCCISW:
4635517Snate@binkert.org                trapToHype = hcr.tsw;
4645517Snate@binkert.org                break;
4655517Snate@binkert.org              case MISCREG_DCIMVAC:
4665517Snate@binkert.org              case MISCREG_DCCIMVAC:
4675517Snate@binkert.org              case MISCREG_DCCMVAC:
4685517Snate@binkert.org                trapToHype = hcr.tpc;
4695517Snate@binkert.org                break;
4705517Snate@binkert.org              case MISCREG_ICIMVAU:
4715517Snate@binkert.org              case MISCREG_ICIALLU:
4725517Snate@binkert.org              case MISCREG_ICIALLUIS:
4735517Snate@binkert.org              case MISCREG_DCCMVAU:
4745517Snate@binkert.org                trapToHype = hcr.tpu;
4755517Snate@binkert.org                break;
4766143Snate@binkert.org              case MISCREG_TLBIALLIS:
4775517Snate@binkert.org              case MISCREG_TLBIMVAIS:
4784762Snate@binkert.org              case MISCREG_TLBIASIDIS:
4794762Snate@binkert.org              case MISCREG_TLBIMVAAIS:
4806143Snate@binkert.org              case MISCREG_TLBIMVALIS:
4816143Snate@binkert.org              case MISCREG_TLBIMVAALIS:
4826143Snate@binkert.org              case MISCREG_DTLBIALL:
4834762Snate@binkert.org              case MISCREG_ITLBIALL:
4844762Snate@binkert.org              case MISCREG_DTLBIMVA:
4854762Snate@binkert.org              case MISCREG_ITLBIMVA:
4865517Snate@binkert.org              case MISCREG_DTLBIASID:
4874762Snate@binkert.org              case MISCREG_ITLBIASID:
4884762Snate@binkert.org              case MISCREG_TLBIMVAA:
4894762Snate@binkert.org              case MISCREG_TLBIALL:
4905463Snate@binkert.org              case MISCREG_TLBIMVA:
4915517Snate@binkert.org              case MISCREG_TLBIMVAL:
4924762Snate@binkert.org              case MISCREG_TLBIMVAAL:
4934762Snate@binkert.org              case MISCREG_TLBIASID:
4944762Snate@binkert.org                trapToHype = hcr.ttlb;
4954762Snate@binkert.org                break;
4964762Snate@binkert.org              case MISCREG_ACTLR:
4974762Snate@binkert.org                trapToHype = hcr.tac;
4985463Snate@binkert.org                break;
4995517Snate@binkert.org              case MISCREG_SCTLR:
5004762Snate@binkert.org              case MISCREG_TTBR0:
5014762Snate@binkert.org              case MISCREG_TTBR1:
5024762Snate@binkert.org              case MISCREG_TTBCR:
5036143Snate@binkert.org              case MISCREG_DACR:
5046143Snate@binkert.org              case MISCREG_DFSR:
5056143Snate@binkert.org              case MISCREG_IFSR:
5064762Snate@binkert.org              case MISCREG_DFAR:
5074762Snate@binkert.org              case MISCREG_IFAR:
5085517Snate@binkert.org              case MISCREG_ADFSR:
5094762Snate@binkert.org              case MISCREG_AIFSR:
5104762Snate@binkert.org              case MISCREG_PRRR:
5114762Snate@binkert.org              case MISCREG_NMRR:
5124762Snate@binkert.org              case MISCREG_MAIR0:
5135517Snate@binkert.org              case MISCREG_MAIR1:
5144762Snate@binkert.org              case MISCREG_CONTEXTIDR:
5154762Snate@binkert.org                trapToHype = hcr.tvm & !isRead;
5164762Snate@binkert.org                break;
5174762Snate@binkert.org              case MISCREG_PMCR:
5185517Snate@binkert.org                trapToHype = hdcr.tpmcr;
5195517Snate@binkert.org                break;
5205517Snate@binkert.org              // No default action needed
5215517Snate@binkert.org              default:
5225517Snate@binkert.org                break;
5235517Snate@binkert.org            }
5245517Snate@binkert.org        }
5255517Snate@binkert.org    }
5265517Snate@binkert.org    return trapToHype;
5275517Snate@binkert.org}
5285517Snate@binkert.org
5295517Snate@binkert.org
5305517Snate@binkert.orgbool
5315517Snate@binkert.orgmcrMrc14TrapToHyp(const MiscRegIndex miscReg, HCR hcr, CPSR cpsr, SCR scr,
5325517Snate@binkert.org                  HDCR hdcr, HSTR hstr, HCPTR hcptr, uint32_t iss)
5335517Snate@binkert.org{
5345517Snate@binkert.org    bool        isRead;
5355517Snate@binkert.org    uint32_t    crm;
5365517Snate@binkert.org    IntRegIndex rt;
5375517Snate@binkert.org    uint32_t    crn;
5385517Snate@binkert.org    uint32_t    opc1;
5395517Snate@binkert.org    uint32_t    opc2;
5405517Snate@binkert.org    bool        trapToHype = false;
5415517Snate@binkert.org
5425517Snate@binkert.org    if (!inSecureState(scr, cpsr) && (cpsr.mode != MODE_HYP)) {
5435517Snate@binkert.org        mcrMrcIssExtract(iss, isRead, crm, rt, crn, opc1, opc2);
5445517Snate@binkert.org        inform("trap check M:%x N:%x 1:%x 2:%x hdcr %x, hcptr %x, hstr %x\n",
5455517Snate@binkert.org                crm, crn, opc1, opc2, hdcr, hcptr, hstr);
5465517Snate@binkert.org        trapToHype  = hdcr.tda  && (opc1 == 0);
5475517Snate@binkert.org        trapToHype |= hcptr.tta && (opc1 == 1);
5485517Snate@binkert.org        if (!trapToHype) {
5495517Snate@binkert.org            switch (unflattenMiscReg(miscReg)) {
5505517Snate@binkert.org              case MISCREG_DBGOSLSR:
5515517Snate@binkert.org              case MISCREG_DBGOSLAR:
5525517Snate@binkert.org              case MISCREG_DBGOSDLR:
5535517Snate@binkert.org              case MISCREG_DBGPRCR:
5545517Snate@binkert.org                trapToHype = hdcr.tdosa;
5555517Snate@binkert.org                break;
5565517Snate@binkert.org              case MISCREG_DBGDRAR:
5575517Snate@binkert.org              case MISCREG_DBGDSAR:
5585517Snate@binkert.org                trapToHype = hdcr.tdra;
5595517Snate@binkert.org                break;
5605517Snate@binkert.org              case MISCREG_JIDR:
5615517Snate@binkert.org                trapToHype = hcr.tid0;
5625517Snate@binkert.org                break;
5635517Snate@binkert.org              case MISCREG_JOSCR:
5645517Snate@binkert.org              case MISCREG_JMCR:
5655517Snate@binkert.org                trapToHype = hstr.tjdbx;
5665517Snate@binkert.org                break;
5675517Snate@binkert.org              case MISCREG_TEECR:
5685517Snate@binkert.org              case MISCREG_TEEHBR:
5695517Snate@binkert.org                trapToHype = hstr.ttee;
5705517Snate@binkert.org                break;
5715517Snate@binkert.org              // No default action needed
5725517Snate@binkert.org              default:
5735517Snate@binkert.org                break;
5745517Snate@binkert.org            }
5755517Snate@binkert.org        }
5765517Snate@binkert.org    }
5775517Snate@binkert.org    return trapToHype;
5785517Snate@binkert.org}
5795517Snate@binkert.org
5805517Snate@binkert.orgbool
5815517Snate@binkert.orgmcrrMrrc15TrapToHyp(const MiscRegIndex miscReg, CPSR cpsr, SCR scr, HSTR hstr,
5825517Snate@binkert.org                    HCR hcr, uint32_t iss)
5835517Snate@binkert.org{
5845610Snate@binkert.org    uint32_t    crm;
5855623Snate@binkert.org    IntRegIndex rt;
5865623Snate@binkert.org    uint32_t    crn;
5875623Snate@binkert.org    uint32_t    opc1;
5885610Snate@binkert.org    uint32_t    opc2;
5895517Snate@binkert.org    bool        isRead;
5905623Snate@binkert.org    bool        trapToHype = false;
5915623Snate@binkert.org
5925623Snate@binkert.org    if (!inSecureState(scr, cpsr) && (cpsr.mode != MODE_HYP)) {
5935623Snate@binkert.org        // This is technically the wrong function, but we can re-use it for
5945623Snate@binkert.org        // the moment because we only need one field, which overlaps with the
5955623Snate@binkert.org        // mcrmrc layout
5965623Snate@binkert.org        mcrMrcIssExtract(iss, isRead, crm, rt, crn, opc1, opc2);
5975517Snate@binkert.org        trapToHype = ((uint32_t) hstr) & (1 << crm);
5985610Snate@binkert.org
5995610Snate@binkert.org        if (!trapToHype) {
6005610Snate@binkert.org            switch (unflattenMiscReg(miscReg)) {
6015610Snate@binkert.org              case MISCREG_SCTLR:
6025517Snate@binkert.org              case MISCREG_TTBR0:
6035517Snate@binkert.org              case MISCREG_TTBR1:
6045610Snate@binkert.org              case MISCREG_TTBCR:
6055610Snate@binkert.org              case MISCREG_DACR:
6065517Snate@binkert.org              case MISCREG_DFSR:
6075517Snate@binkert.org              case MISCREG_IFSR:
6085517Snate@binkert.org              case MISCREG_DFAR:
6095517Snate@binkert.org              case MISCREG_IFAR:
6105517Snate@binkert.org              case MISCREG_ADFSR:
6115517Snate@binkert.org              case MISCREG_AIFSR:
6125517Snate@binkert.org              case MISCREG_PRRR:
6135517Snate@binkert.org              case MISCREG_NMRR:
6145517Snate@binkert.org              case MISCREG_MAIR0:
6155517Snate@binkert.org              case MISCREG_MAIR1:
6164762Snate@binkert.org              case MISCREG_CONTEXTIDR:
6176143Snate@binkert.org                trapToHype = hcr.tvm & !isRead;
6186143Snate@binkert.org                break;
6195463Snate@binkert.org              // No default action needed
6204762Snate@binkert.org              default:
6214762Snate@binkert.org                break;
6224762Snate@binkert.org            }
6236143Snate@binkert.org        }
6246143Snate@binkert.org    }
6254382Sbinkertn@umich.edu    return trapToHype;
6264382Sbinkertn@umich.edu}
6276143Snate@binkert.org
6286143Snate@binkert.orgbool
6294382Sbinkertn@umich.edumsrMrs64TrapToSup(const MiscRegIndex miscReg, ExceptionLevel el,
6304762Snate@binkert.org                  CPACR cpacr /* CPACR_EL1 */)
6315517Snate@binkert.org{
6325517Snate@binkert.org    bool trapToSup = false;
6335517Snate@binkert.org    switch (miscReg) {
6345517Snate@binkert.org      case MISCREG_FPCR:
6355517Snate@binkert.org      case MISCREG_FPSR:
6365517Snate@binkert.org      case MISCREG_FPEXC32_EL2:
6375522Snate@binkert.org        if ((el == EL0 && cpacr.fpen != 0x3) ||
6385517Snate@binkert.org            (el == EL1 && !(cpacr.fpen & 0x1)))
6395517Snate@binkert.org            trapToSup = true;
6405517Snate@binkert.org        break;
6415517Snate@binkert.org      default:
6425517Snate@binkert.org        break;
6436143Snate@binkert.org    }
6446143Snate@binkert.org    return trapToSup;
6456143Snate@binkert.org}
6465522Snate@binkert.org
6474382Sbinkertn@umich.edubool
6486229Snate@binkert.orgmsrMrs64TrapToHyp(const MiscRegIndex miscReg,
6496229Snate@binkert.org                  ExceptionLevel el,
6506229Snate@binkert.org                  bool isRead,
6516229Snate@binkert.org                  CPTR cptr /* CPTR_EL2 */,
6526229Snate@binkert.org                  HCR hcr /* HCR_EL2 */,
6536229Snate@binkert.org                  bool * isVfpNeon)
6546229Snate@binkert.org{
6556229Snate@binkert.org    bool trapToHyp = false;
6566229Snate@binkert.org    *isVfpNeon = false;
6576229Snate@binkert.org
6586229Snate@binkert.org    switch (miscReg) {
6596229Snate@binkert.org      // FP/SIMD regs
6606229Snate@binkert.org      case MISCREG_FPCR:
6616229Snate@binkert.org      case MISCREG_FPSR:
6626229Snate@binkert.org      case MISCREG_FPEXC32_EL2:
6636229Snate@binkert.org        trapToHyp = cptr.tfp;
6646229Snate@binkert.org        *isVfpNeon = true;
6656229Snate@binkert.org        break;
6666229Snate@binkert.org      // CPACR
6676229Snate@binkert.org      case MISCREG_CPACR_EL1:
6686229Snate@binkert.org        trapToHyp = cptr.tcpac && el == EL1;
6695192Ssaidi@eecs.umich.edu        break;
6705517Snate@binkert.org      // Virtual memory control regs
6715517Snate@binkert.org      case MISCREG_SCTLR_EL1:
6725517Snate@binkert.org      case MISCREG_TTBR0_EL1:
6735517Snate@binkert.org      case MISCREG_TTBR1_EL1:
6746229Snate@binkert.org      case MISCREG_TCR_EL1:
6756229Snate@binkert.org      case MISCREG_ESR_EL1:
6765799Snate@binkert.org      case MISCREG_FAR_EL1:
6775799Snate@binkert.org      case MISCREG_AFSR0_EL1:
6785517Snate@binkert.org      case MISCREG_AFSR1_EL1:
6795517Snate@binkert.org      case MISCREG_MAIR_EL1:
6805517Snate@binkert.org      case MISCREG_AMAIR_EL1:
6815517Snate@binkert.org      case MISCREG_CONTEXTIDR_EL1:
6825517Snate@binkert.org        trapToHyp = ((hcr.trvm && isRead) || (hcr.tvm && !isRead))
6835517Snate@binkert.org                    && el == EL1;
6845799Snate@binkert.org        break;
6855517Snate@binkert.org      // TLB maintenance instructions
6865517Snate@binkert.org      case MISCREG_TLBI_VMALLE1:
6875517Snate@binkert.org      case MISCREG_TLBI_VAE1_Xt:
6885517Snate@binkert.org      case MISCREG_TLBI_ASIDE1_Xt:
6895517Snate@binkert.org      case MISCREG_TLBI_VAAE1_Xt:
6905517Snate@binkert.org      case MISCREG_TLBI_VALE1_Xt:
6915517Snate@binkert.org      case MISCREG_TLBI_VAALE1_Xt:
6925799Snate@binkert.org      case MISCREG_TLBI_VMALLE1IS:
6935517Snate@binkert.org      case MISCREG_TLBI_VAE1IS_Xt:
6945517Snate@binkert.org      case MISCREG_TLBI_ASIDE1IS_Xt:
6955799Snate@binkert.org      case MISCREG_TLBI_VAAE1IS_Xt:
6965517Snate@binkert.org      case MISCREG_TLBI_VALE1IS_Xt:
6975517Snate@binkert.org      case MISCREG_TLBI_VAALE1IS_Xt:
6985517Snate@binkert.org        trapToHyp = hcr.ttlb && el == EL1;
6995517Snate@binkert.org        break;
7005517Snate@binkert.org      // Cache maintenance instructions to the point of unification
7015517Snate@binkert.org      case MISCREG_IC_IVAU_Xt:
7025517Snate@binkert.org      case MISCREG_ICIALLU:
7035517Snate@binkert.org      case MISCREG_ICIALLUIS:
7045799Snate@binkert.org      case MISCREG_DC_CVAU_Xt:
7055517Snate@binkert.org        trapToHyp = hcr.tpu && el <= EL1;
7065517Snate@binkert.org        break;
7075517Snate@binkert.org      // Data/Unified cache maintenance instructions to the point of coherency
7085517Snate@binkert.org      case MISCREG_DC_IVAC_Xt:
7095517Snate@binkert.org      case MISCREG_DC_CIVAC_Xt:
7105517Snate@binkert.org      case MISCREG_DC_CVAC_Xt:
7115517Snate@binkert.org        trapToHyp = hcr.tpc && el <= EL1;
7125517Snate@binkert.org        break;
7135517Snate@binkert.org      // Data/Unified cache maintenance instructions by set/way
7145517Snate@binkert.org      case MISCREG_DC_ISW_Xt:
7155517Snate@binkert.org      case MISCREG_DC_CSW_Xt:
7165517Snate@binkert.org      case MISCREG_DC_CISW_Xt:
7176229Snate@binkert.org        trapToHyp = hcr.tsw && el == EL1;
7185517Snate@binkert.org        break;
7195517Snate@binkert.org      // ACTLR
7205517Snate@binkert.org      case MISCREG_ACTLR_EL1:
7215517Snate@binkert.org        trapToHyp = hcr.tacr && el == EL1;
7225517Snate@binkert.org        break;
7235517Snate@binkert.org
7245517Snate@binkert.org      // @todo: Trap implementation-dependent functionality based on
7255517Snate@binkert.org      // hcr.tidcp
7265517Snate@binkert.org
7275517Snate@binkert.org      // ID regs, group 3
7285517Snate@binkert.org      case MISCREG_ID_PFR0_EL1:
7295517Snate@binkert.org      case MISCREG_ID_PFR1_EL1:
7305517Snate@binkert.org      case MISCREG_ID_DFR0_EL1:
7315517Snate@binkert.org      case MISCREG_ID_AFR0_EL1:
7325517Snate@binkert.org      case MISCREG_ID_MMFR0_EL1:
7335517Snate@binkert.org      case MISCREG_ID_MMFR1_EL1:
7345517Snate@binkert.org      case MISCREG_ID_MMFR2_EL1:
7355517Snate@binkert.org      case MISCREG_ID_MMFR3_EL1:
7365517Snate@binkert.org      case MISCREG_ID_ISAR0_EL1:
7375517Snate@binkert.org      case MISCREG_ID_ISAR1_EL1:
7385517Snate@binkert.org      case MISCREG_ID_ISAR2_EL1:
7395517Snate@binkert.org      case MISCREG_ID_ISAR3_EL1:
7405517Snate@binkert.org      case MISCREG_ID_ISAR4_EL1:
7415517Snate@binkert.org      case MISCREG_ID_ISAR5_EL1:
7425517Snate@binkert.org      case MISCREG_MVFR0_EL1:
7435517Snate@binkert.org      case MISCREG_MVFR1_EL1:
7445517Snate@binkert.org      case MISCREG_MVFR2_EL1:
7455517Snate@binkert.org      case MISCREG_ID_AA64PFR0_EL1:
7465517Snate@binkert.org      case MISCREG_ID_AA64PFR1_EL1:
7475517Snate@binkert.org      case MISCREG_ID_AA64DFR0_EL1:
7485517Snate@binkert.org      case MISCREG_ID_AA64DFR1_EL1:
7495517Snate@binkert.org      case MISCREG_ID_AA64ISAR0_EL1:
7505517Snate@binkert.org      case MISCREG_ID_AA64ISAR1_EL1:
7515517Snate@binkert.org      case MISCREG_ID_AA64MMFR0_EL1:
7525517Snate@binkert.org      case MISCREG_ID_AA64MMFR1_EL1:
7535517Snate@binkert.org      case MISCREG_ID_AA64AFR0_EL1:
7545517Snate@binkert.org      case MISCREG_ID_AA64AFR1_EL1:
7555517Snate@binkert.org        assert(isRead);
7565517Snate@binkert.org        trapToHyp = hcr.tid3 && el == EL1;
7575517Snate@binkert.org        break;
7585517Snate@binkert.org      // ID regs, group 2
7595517Snate@binkert.org      case MISCREG_CTR_EL0:
7605517Snate@binkert.org      case MISCREG_CCSIDR_EL1:
7615517Snate@binkert.org      case MISCREG_CLIDR_EL1:
7625517Snate@binkert.org      case MISCREG_CSSELR_EL1:
7635517Snate@binkert.org        trapToHyp = hcr.tid2 && el <= EL1;
7645517Snate@binkert.org        break;
7655517Snate@binkert.org      // ID regs, group 1
7665517Snate@binkert.org      case MISCREG_AIDR_EL1:
7675517Snate@binkert.org      case MISCREG_REVIDR_EL1:
7685517Snate@binkert.org        assert(isRead);
7695517Snate@binkert.org        trapToHyp = hcr.tid1 && el == EL1;
7705517Snate@binkert.org        break;
7715517Snate@binkert.org      default:
7725517Snate@binkert.org        break;
7735517Snate@binkert.org    }
7745517Snate@binkert.org    return trapToHyp;
7755517Snate@binkert.org}
7765517Snate@binkert.org
7775517Snate@binkert.orgbool
7785517Snate@binkert.orgmsrMrs64TrapToMon(const MiscRegIndex miscReg, CPTR cptr /* CPTR_EL3 */,
7795517Snate@binkert.org                  ExceptionLevel el, bool * isVfpNeon)
7805517Snate@binkert.org{
7815517Snate@binkert.org    bool trapToMon = false;
7825517Snate@binkert.org    *isVfpNeon = false;
7835517Snate@binkert.org
7845517Snate@binkert.org    switch (miscReg) {
7855517Snate@binkert.org      // FP/SIMD regs
7865517Snate@binkert.org      case MISCREG_FPCR:
7875517Snate@binkert.org      case MISCREG_FPSR:
7885517Snate@binkert.org      case MISCREG_FPEXC32_EL2:
7895517Snate@binkert.org        trapToMon = cptr.tfp;
7906229Snate@binkert.org        *isVfpNeon = true;
7915517Snate@binkert.org        break;
7925517Snate@binkert.org      // CPACR, CPTR
7935517Snate@binkert.org      case MISCREG_CPACR_EL1:
7945517Snate@binkert.org        if (el == EL1) {
7955517Snate@binkert.org           trapToMon = cptr.tcpac;
7965517Snate@binkert.org        }
7975517Snate@binkert.org        break;
7985517Snate@binkert.org      case MISCREG_CPTR_EL2:
7995517Snate@binkert.org        if (el == EL2) {
8005517Snate@binkert.org            trapToMon = cptr.tcpac;
8015517Snate@binkert.org        }
8025517Snate@binkert.org        break;
8035517Snate@binkert.org      default:
8045517Snate@binkert.org        break;
8055517Snate@binkert.org    }
8065517Snate@binkert.org    return trapToMon;
8075517Snate@binkert.org}
8085517Snate@binkert.org
8095517Snate@binkert.orgbool
8105517Snate@binkert.orgdecodeMrsMsrBankedReg(uint8_t sysM, bool r, bool &isIntReg, int &regIdx,
8115517Snate@binkert.org                      CPSR cpsr, SCR scr, NSACR nsacr, bool checkSecurity)
8125517Snate@binkert.org{
8135517Snate@binkert.org    OperatingMode mode = MODE_UNDEFINED;
8145517Snate@binkert.org    bool          ok = true;
8155517Snate@binkert.org
8165517Snate@binkert.org    // R mostly indicates if its a int register or a misc reg, we override
8175517Snate@binkert.org    // below if the few corner cases
8185517Snate@binkert.org    isIntReg = !r;
8195517Snate@binkert.org    // Loosely based on ARM ARM issue C section B9.3.10
8205517Snate@binkert.org    if (r) {
8215517Snate@binkert.org        switch (sysM)
8225517Snate@binkert.org        {
8235517Snate@binkert.org          case 0xE:
8245517Snate@binkert.org            regIdx = MISCREG_SPSR_FIQ;
8255517Snate@binkert.org            mode   = MODE_FIQ;
8265517Snate@binkert.org            break;
8275517Snate@binkert.org          case 0x10:
8285517Snate@binkert.org            regIdx = MISCREG_SPSR_IRQ;
8295517Snate@binkert.org            mode   = MODE_IRQ;
8305517Snate@binkert.org            break;
8315517Snate@binkert.org          case 0x12:
8325517Snate@binkert.org            regIdx = MISCREG_SPSR_SVC;
8335517Snate@binkert.org            mode   = MODE_SVC;
8345517Snate@binkert.org            break;
8355517Snate@binkert.org          case 0x14:
8365517Snate@binkert.org            regIdx = MISCREG_SPSR_ABT;
8375517Snate@binkert.org            mode   = MODE_ABORT;
8385517Snate@binkert.org            break;
8395517Snate@binkert.org          case 0x16:
8405517Snate@binkert.org            regIdx = MISCREG_SPSR_UND;
8415517Snate@binkert.org            mode   = MODE_UNDEFINED;
8425517Snate@binkert.org            break;
8435517Snate@binkert.org          case 0x1C:
8445517Snate@binkert.org            regIdx = MISCREG_SPSR_MON;
8455517Snate@binkert.org            mode   = MODE_MON;
8465517Snate@binkert.org            break;
8475517Snate@binkert.org          case 0x1E:
8485517Snate@binkert.org            regIdx = MISCREG_SPSR_HYP;
8495517Snate@binkert.org            mode   = MODE_HYP;
8505517Snate@binkert.org            break;
8515517Snate@binkert.org          default:
8526143Snate@binkert.org            ok = false;
8535517Snate@binkert.org            break;
8545192Ssaidi@eecs.umich.edu        }
8555192Ssaidi@eecs.umich.edu    } else {
8565517Snate@binkert.org        int sysM4To3 = bits(sysM, 4, 3);
8575517Snate@binkert.org
8585192Ssaidi@eecs.umich.edu        if (sysM4To3 == 0) {
8595192Ssaidi@eecs.umich.edu            mode = MODE_USER;
8605522Snate@binkert.org            regIdx = intRegInMode(mode, bits(sysM, 2, 0) + 8);
8615522Snate@binkert.org        } else if (sysM4To3 == 1) {
8625522Snate@binkert.org            mode = MODE_FIQ;
8635522Snate@binkert.org            regIdx = intRegInMode(mode, bits(sysM, 2, 0) + 8);
8645522Snate@binkert.org        } else if (sysM4To3 == 3) {
8655522Snate@binkert.org            if (bits(sysM, 1) == 0) {
8665522Snate@binkert.org                mode = MODE_MON;
8675522Snate@binkert.org                regIdx = intRegInMode(mode, 14 - bits(sysM, 0));
8685522Snate@binkert.org            } else {
8695522Snate@binkert.org                mode = MODE_HYP;
8705517Snate@binkert.org                if (bits(sysM, 0) == 1) {
8715522Snate@binkert.org                    regIdx = intRegInMode(mode, 13); // R13 in HYP
8725522Snate@binkert.org                } else {
8735517Snate@binkert.org                    isIntReg = false;
8746143Snate@binkert.org                    regIdx   = MISCREG_ELR_HYP;
8755604Snate@binkert.org                }
8765522Snate@binkert.org            }
8775522Snate@binkert.org        } else { // Other Banked registers
8785522Snate@binkert.org            int sysM2 = bits(sysM, 2);
8795517Snate@binkert.org            int sysM1 = bits(sysM, 1);
8805522Snate@binkert.org
8815522Snate@binkert.org            mode  = (OperatingMode) ( ((sysM2 ||  sysM1) << 0) |
8825522Snate@binkert.org                                      (1                 << 1) |
8835522Snate@binkert.org                                      ((sysM2 && !sysM1) << 2) |
8845522Snate@binkert.org                                      ((sysM2 &&  sysM1) << 3) |
8855522Snate@binkert.org                                      (1                 << 4) );
8865522Snate@binkert.org            regIdx = intRegInMode(mode, 14 - bits(sysM, 0));
8875522Snate@binkert.org            // Don't flatten the register here. This is going to go through
8885522Snate@binkert.org            // setIntReg() which will do the flattening
8895522Snate@binkert.org            ok &= mode != cpsr.mode;
8905522Snate@binkert.org        }
8915522Snate@binkert.org    }
8925522Snate@binkert.org
8935522Snate@binkert.org    // Check that the requested register is accessable from the current mode
8945522Snate@binkert.org    if (ok && checkSecurity && mode != cpsr.mode) {
8955522Snate@binkert.org        switch (cpsr.mode)
8965522Snate@binkert.org        {
8975522Snate@binkert.org          case MODE_USER:
8985522Snate@binkert.org            ok = false;
8996143Snate@binkert.org            break;
9005522Snate@binkert.org          case MODE_FIQ:
9015522Snate@binkert.org            ok &=  mode != MODE_HYP;
9024382Sbinkertn@umich.edu            ok &= (mode != MODE_MON) || !scr.ns;
9035522Snate@binkert.org            break;
9045522Snate@binkert.org          case MODE_HYP:
9055522Snate@binkert.org            ok &=  mode != MODE_MON;
9065522Snate@binkert.org            ok &= (mode != MODE_FIQ) || !nsacr.rfr;
9075522Snate@binkert.org            break;
9085522Snate@binkert.org          case MODE_IRQ:
9095522Snate@binkert.org          case MODE_SVC:
9104382Sbinkertn@umich.edu          case MODE_ABORT:
9115522Snate@binkert.org          case MODE_UNDEFINED:
9126143Snate@binkert.org          case MODE_SYSTEM:
9135522Snate@binkert.org            ok &=  mode != MODE_HYP;
9145522Snate@binkert.org            ok &= (mode != MODE_MON) || !scr.ns;
9155522Snate@binkert.org            ok &= (mode != MODE_FIQ) || !nsacr.rfr;
9165522Snate@binkert.org            break;
9175522Snate@binkert.org          // can access everything, no further checks required
9185522Snate@binkert.org          case MODE_MON:
9195522Snate@binkert.org            break;
9205522Snate@binkert.org          default:
9215522Snate@binkert.org            panic("unknown Mode 0x%x\n", cpsr.mode);
9225522Snate@binkert.org            break;
9235522Snate@binkert.org        }
9245522Snate@binkert.org    }
9255522Snate@binkert.org    return (ok);
9265522Snate@binkert.org}
9275522Snate@binkert.org
9285522Snate@binkert.orgbool
9295522Snate@binkert.orgSPAlignmentCheckEnabled(ThreadContext* tc)
9305522Snate@binkert.org{
9315522Snate@binkert.org    switch (opModeToEL(currOpMode(tc))) {
9325522Snate@binkert.org      case EL3:
9335522Snate@binkert.org        return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL3)).sa;
9345522Snate@binkert.org      case EL2:
9355522Snate@binkert.org        return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL2)).sa;
9365522Snate@binkert.org      case EL1:
9375522Snate@binkert.org        return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL1)).sa;
9385522Snate@binkert.org      case EL0:
9396143Snate@binkert.org        return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL1)).sa0;
9406143Snate@binkert.org      default:
9416143Snate@binkert.org        panic("Invalid exception level");
9426143Snate@binkert.org        break;
9435522Snate@binkert.org    }
9444382Sbinkertn@umich.edu}
9454382Sbinkertn@umich.edu
9464382Sbinkertn@umich.eduint
9474382Sbinkertn@umich.edudecodePhysAddrRange64(uint8_t pa_enc)
9484382Sbinkertn@umich.edu{
9494382Sbinkertn@umich.edu    switch (pa_enc) {
9504382Sbinkertn@umich.edu      case 0x0:
9514382Sbinkertn@umich.edu        return 32;
9524382Sbinkertn@umich.edu      case 0x1:
9534382Sbinkertn@umich.edu        return 36;
9546143Snate@binkert.org      case 0x2:
955955SN/A        return 40;
9562655Sstever@eecs.umich.edu      case 0x3:
9572655Sstever@eecs.umich.edu        return 42;
9582655Sstever@eecs.umich.edu      case 0x4:
9592655Sstever@eecs.umich.edu        return 44;
9602655Sstever@eecs.umich.edu      case 0x5:
9615601Snate@binkert.org      case 0x6:
9625601Snate@binkert.org      case 0x7:
9635601Snate@binkert.org        return 48;
9645601Snate@binkert.org      default:
9655522Snate@binkert.org        panic("Invalid phys. address range encoding");
9665863Snate@binkert.org    }
9675601Snate@binkert.org}
9685601Snate@binkert.org
9695601Snate@binkert.orguint8_t
9705863Snate@binkert.orgencodePhysAddrRange64(int pa_size)
9716143Snate@binkert.org{
9725559Snate@binkert.org    switch (pa_size) {
9735559Snate@binkert.org      case 32:
9745559Snate@binkert.org        return 0x0;
9755559Snate@binkert.org      case 36:
9765601Snate@binkert.org        return 0x1;
9776143Snate@binkert.org      case 40:
9786143Snate@binkert.org        return 0x2;
9796143Snate@binkert.org      case 42:
9806143Snate@binkert.org        return 0x3;
9816143Snate@binkert.org      case 44:
9826143Snate@binkert.org        return 0x4;
9836143Snate@binkert.org      case 48:
9846143Snate@binkert.org        return 0x5;
9856143Snate@binkert.org      default:
9866143Snate@binkert.org        panic("Invalid phys. address range");
9876143Snate@binkert.org    }
9886143Snate@binkert.org}
9896143Snate@binkert.org
9906143Snate@binkert.org} // namespace ArmISA
9916143Snate@binkert.org