1/*
2 * Copyright (c) 2009-2014, 2016-2019 ARM Limited
3 * All rights reserved.
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder.  You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Authors: Ali Saidi
38 */
39
40#include "arch/arm/utility.hh"
41
42#include <memory>
43
44#include "arch/arm/faults.hh"
45#include "arch/arm/isa_traits.hh"
46#include "arch/arm/system.hh"
47#include "arch/arm/tlb.hh"
48#include "arch/arm/vtophys.hh"
49#include "cpu/base.hh"
50#include "cpu/checker/cpu.hh"
51#include "cpu/thread_context.hh"
52#include "mem/fs_translating_port_proxy.hh"
53#include "sim/full_system.hh"
54
55namespace ArmISA {
56
57void
58initCPU(ThreadContext *tc, int cpuId)
59{
60    // Reset CP15?? What does that mean -- ali
61
62    // FPEXC.EN = 0
63
64    static Fault reset = std::make_shared<Reset>();
65    reset->invoke(tc);
66}
67
68uint64_t
69getArgument(ThreadContext *tc, int &number, uint16_t size, bool fp)
70{
71    if (!FullSystem) {
72        panic("getArgument() only implemented for full system mode.\n");
73        M5_DUMMY_RETURN
74    }
75
76    if (fp)
77        panic("getArgument(): Floating point arguments not implemented\n");
78
79    if (inAArch64(tc)) {
80        if (size == (uint16_t)(-1))
81            size = sizeof(uint64_t);
82
83        if (number < 8 /*NumArgumentRegs64*/) {
84               return tc->readIntReg(number);
85        } else {
86            panic("getArgument(): No support reading stack args for AArch64\n");
87        }
88    } else {
89        if (size == (uint16_t)(-1))
90            // todo: should this not be sizeof(uint32_t) rather?
91            size = ArmISA::MachineBytes;
92
93        if (number < NumArgumentRegs) {
94            // If the argument is 64 bits, it must be in an even regiser
95            // number. Increment the number here if it isn't even.
96            if (size == sizeof(uint64_t)) {
97                if ((number % 2) != 0)
98                    number++;
99                // Read the two halves of the data. Number is inc here to
100                // get the second half of the 64 bit reg.
101                uint64_t tmp;
102                tmp = tc->readIntReg(number++);
103                tmp |= tc->readIntReg(number) << 32;
104                return tmp;
105            } else {
106               return tc->readIntReg(number);
107            }
108        } else {
109            Addr sp = tc->readIntReg(StackPointerReg);
110            PortProxy &vp = tc->getVirtProxy();
111            uint64_t arg;
112            if (size == sizeof(uint64_t)) {
113                // If the argument is even it must be aligned
114                if ((number % 2) != 0)
115                    number++;
116                arg = vp.read<uint64_t>(sp +
117                        (number-NumArgumentRegs) * sizeof(uint32_t));
118                // since two 32 bit args == 1 64 bit arg, increment number
119                number++;
120            } else {
121                arg = vp.read<uint32_t>(sp +
122                               (number-NumArgumentRegs) * sizeof(uint32_t));
123            }
124            return arg;
125        }
126    }
127    panic("getArgument() should always return\n");
128}
129
130void
131skipFunction(ThreadContext *tc)
132{
133    PCState newPC = tc->pcState();
134    if (inAArch64(tc)) {
135        newPC.set(tc->readIntReg(INTREG_X30));
136    } else {
137        newPC.set(tc->readIntReg(ReturnAddressReg) & ~ULL(1));
138    }
139
140    CheckerCPU *checker = tc->getCheckerCpuPtr();
141    if (checker) {
142        tc->pcStateNoRecord(newPC);
143    } else {
144        tc->pcState(newPC);
145    }
146}
147
148static void
149copyVecRegs(ThreadContext *src, ThreadContext *dest)
150{
151    auto src_mode = RenameMode<ArmISA::ISA>::mode(src->pcState());
152
153    // The way vector registers are copied (VecReg vs VecElem) is relevant
154    // in the O3 model only.
155    if (src_mode == Enums::Full) {
156        for (auto idx = 0; idx < NumVecRegs; idx++)
157            dest->setVecRegFlat(idx, src->readVecRegFlat(idx));
158    } else {
159        for (auto idx = 0; idx < NumVecRegs; idx++)
160            for (auto elem_idx = 0; elem_idx < NumVecElemPerVecReg; elem_idx++)
161                dest->setVecElemFlat(
162                    idx, elem_idx, src->readVecElemFlat(idx, elem_idx));
163    }
164}
165
166void
167copyRegs(ThreadContext *src, ThreadContext *dest)
168{
169    for (int i = 0; i < NumIntRegs; i++)
170        dest->setIntRegFlat(i, src->readIntRegFlat(i));
171
172    for (int i = 0; i < NumFloatRegs; i++)
173        dest->setFloatRegFlat(i, src->readFloatRegFlat(i));
174
175    for (int i = 0; i < NumCCRegs; i++)
176        dest->setCCReg(i, src->readCCReg(i));
177
178    for (int i = 0; i < NumMiscRegs; i++)
179        dest->setMiscRegNoEffect(i, src->readMiscRegNoEffect(i));
180
181    copyVecRegs(src, dest);
182
183    // setMiscReg "with effect" will set the misc register mapping correctly.
184    // e.g. updateRegMap(val)
185    dest->setMiscReg(MISCREG_CPSR, src->readMiscRegNoEffect(MISCREG_CPSR));
186
187    // Copy over the PC State
188    dest->pcState(src->pcState());
189
190    // Invalidate the tlb misc register cache
191    dynamic_cast<TLB *>(dest->getITBPtr())->invalidateMiscReg();
192    dynamic_cast<TLB *>(dest->getDTBPtr())->invalidateMiscReg();
193}
194
195bool
196inSecureState(ThreadContext *tc)
197{
198    SCR scr = inAArch64(tc) ? tc->readMiscReg(MISCREG_SCR_EL3) :
199        tc->readMiscReg(MISCREG_SCR);
200    return ArmSystem::haveSecurity(tc) && inSecureState(
201        scr, tc->readMiscReg(MISCREG_CPSR));
202}
203
204inline bool
205isSecureBelowEL3(ThreadContext *tc)
206{
207    SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
208    return ArmSystem::haveEL(tc, EL3) && scr.ns == 0;
209}
210
211bool
212inAArch64(ThreadContext *tc)
213{
214    CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
215    return opModeIs64((OperatingMode) (uint8_t) cpsr.mode);
216}
217
218bool
219longDescFormatInUse(ThreadContext *tc)
220{
221    TTBCR ttbcr = tc->readMiscReg(MISCREG_TTBCR);
222    return ArmSystem::haveLPAE(tc) && ttbcr.eae;
223}
224
225RegVal
226readMPIDR(ArmSystem *arm_sys, ThreadContext *tc)
227{
228    const ExceptionLevel current_el = currEL(tc);
229
230    const bool is_secure = isSecureBelowEL3(tc);
231
232    switch (current_el) {
233      case EL0:
234        // Note: in MsrMrs instruction we read the register value before
235        // checking access permissions. This means that EL0 entry must
236        // be part of the table even if MPIDR is not accessible in user
237        // mode.
238        warn_once("Trying to read MPIDR at EL0\n");
239        M5_FALLTHROUGH;
240      case EL1:
241        if (ArmSystem::haveEL(tc, EL2) && !is_secure)
242            return tc->readMiscReg(MISCREG_VMPIDR_EL2);
243        else
244            return getMPIDR(arm_sys, tc);
245      case EL2:
246      case EL3:
247        return getMPIDR(arm_sys, tc);
248      default:
249        panic("Invalid EL for reading MPIDR register\n");
250    }
251}
252
253RegVal
254getMPIDR(ArmSystem *arm_sys, ThreadContext *tc)
255{
256    // Multiprocessor Affinity Register MPIDR from Cortex(tm)-A15 Technical
257    // Reference Manual
258    //
259    // bit   31 - Multi-processor extensions available
260    // bit   30 - Uni-processor system
261    // bit   24 - Multi-threaded cores
262    // bit 11-8 - Cluster ID
263    // bit  1-0 - CPU ID
264    //
265    // We deliberately extend both the Cluster ID and CPU ID fields to allow
266    // for simulation of larger systems
267    assert((0 <= tc->cpuId()) && (tc->cpuId() < 256));
268    assert(tc->socketId() < 65536);
269    if (arm_sys->multiThread) {
270       return 0x80000000 | // multiprocessor extensions available
271              0x01000000 | // multi-threaded cores
272              tc->contextId();
273    } else if (arm_sys->multiProc) {
274       return 0x80000000 | // multiprocessor extensions available
275              tc->cpuId() | tc->socketId() << 8;
276    } else {
277       return 0x80000000 |  // multiprocessor extensions available
278              0x40000000 |  // in up system
279              tc->cpuId() | tc->socketId() << 8;
280    }
281}
282
283bool
284ELIs64(ThreadContext *tc, ExceptionLevel el)
285{
286    return !ELIs32(tc, el);
287}
288
289bool
290ELIs32(ThreadContext *tc, ExceptionLevel el)
291{
292    bool known, aarch32;
293    std::tie(known, aarch32) = ELUsingAArch32K(tc, el);
294    panic_if(!known, "EL state is UNKNOWN");
295    return aarch32;
296}
297
298bool
299ELIsInHost(ThreadContext *tc, ExceptionLevel el)
300{
301    if (!ArmSystem::haveVirtualization(tc)) {
302        return false;
303    }
304    HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
305    return (!isSecureBelowEL3(tc) && !ELIs32(tc, EL2) && hcr.e2h == 1 &&
306            (el == EL2 || (el == EL0 && hcr.tge == 1)));
307}
308
309std::pair<bool, bool>
310ELUsingAArch32K(ThreadContext *tc, ExceptionLevel el)
311{
312    // Return true if the specified EL is in aarch32 state.
313    const bool have_el3 = ArmSystem::haveSecurity(tc);
314    const bool have_el2 = ArmSystem::haveVirtualization(tc);
315
316    panic_if(el == EL2 && !have_el2, "Asking for EL2 when it doesn't exist");
317    panic_if(el == EL3 && !have_el3, "Asking for EL3 when it doesn't exist");
318
319    bool known, aarch32;
320    known = aarch32 = false;
321    if (ArmSystem::highestELIs64(tc) && ArmSystem::highestEL(tc) == el) {
322        // Target EL is the highest one in a system where
323        // the highest is using AArch64.
324        known = true; aarch32 = false;
325    } else if (!ArmSystem::highestELIs64(tc)) {
326        // All ELs are using AArch32:
327        known = true; aarch32 = true;
328    } else {
329        SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
330        bool aarch32_below_el3 = (have_el3 && scr.rw == 0);
331
332        HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
333        bool aarch32_at_el1 = (aarch32_below_el3
334                               || (have_el2
335                               && !isSecureBelowEL3(tc) && hcr.rw == 0));
336
337        // Only know if EL0 using AArch32 from PSTATE
338        if (el == EL0 && !aarch32_at_el1) {
339            // EL0 controlled by PSTATE
340            CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
341
342            known = (currEL(tc) == EL0);
343            aarch32 = (cpsr.width == 1);
344        } else {
345            known = true;
346            aarch32 = (aarch32_below_el3 && el != EL3)
347                      || (aarch32_at_el1 && (el == EL0 || el == EL1) );
348        }
349    }
350
351    return std::make_pair(known, aarch32);
352}
353
354bool
355isBigEndian64(ThreadContext *tc)
356{
357    switch (currEL(tc)) {
358      case EL3:
359        return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL3)).ee;
360      case EL2:
361        return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL2)).ee;
362      case EL1:
363        return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL1)).ee;
364      case EL0:
365        return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL1)).e0e;
366      default:
367        panic("Invalid exception level");
368        break;
369    }
370}
371
372bool
373badMode32(ThreadContext *tc, OperatingMode mode)
374{
375    return unknownMode32(mode) || !ArmSystem::haveEL(tc, opModeToEL(mode));
376}
377
378bool
379badMode(ThreadContext *tc, OperatingMode mode)
380{
381    return unknownMode(mode) || !ArmSystem::haveEL(tc, opModeToEL(mode));
382}
383
384Addr
385purifyTaggedAddr(Addr addr, ThreadContext *tc, ExceptionLevel el,
386                 TTBCR tcr)
387{
388    switch (el) {
389      case EL0:
390      case EL1:
391        if (bits(addr, 55, 48) == 0xFF && tcr.tbi1)
392            return addr | mask(63, 55);
393        else if (!bits(addr, 55, 48) && tcr.tbi0)
394            return bits(addr,55, 0);
395        break;
396      case EL2:
397        assert(ArmSystem::haveVirtualization(tc));
398        tcr = tc->readMiscReg(MISCREG_TCR_EL2);
399        if (tcr.tbi)
400            return addr & mask(56);
401        break;
402      case EL3:
403        assert(ArmSystem::haveSecurity(tc));
404        if (tcr.tbi)
405            return addr & mask(56);
406        break;
407      default:
408        panic("Invalid exception level");
409        break;
410    }
411
412    return addr;  // Nothing to do if this is not a tagged address
413}
414
415Addr
416purifyTaggedAddr(Addr addr, ThreadContext *tc, ExceptionLevel el)
417{
418    TTBCR tcr;
419
420    switch (el) {
421      case EL0:
422      case EL1:
423        tcr = tc->readMiscReg(MISCREG_TCR_EL1);
424        if (bits(addr, 55, 48) == 0xFF && tcr.tbi1)
425            return addr | mask(63, 55);
426        else if (!bits(addr, 55, 48) && tcr.tbi0)
427            return bits(addr,55, 0);
428        break;
429      case EL2:
430        assert(ArmSystem::haveVirtualization(tc));
431        tcr = tc->readMiscReg(MISCREG_TCR_EL2);
432        if (tcr.tbi)
433            return addr & mask(56);
434        break;
435      case EL3:
436        assert(ArmSystem::haveSecurity(tc));
437        tcr = tc->readMiscReg(MISCREG_TCR_EL3);
438        if (tcr.tbi)
439            return addr & mask(56);
440        break;
441      default:
442        panic("Invalid exception level");
443        break;
444    }
445
446    return addr;  // Nothing to do if this is not a tagged address
447}
448
449Addr
450truncPage(Addr addr)
451{
452    return addr & ~(PageBytes - 1);
453}
454
455Addr
456roundPage(Addr addr)
457{
458    return (addr + PageBytes - 1) & ~(PageBytes - 1);
459}
460
461bool
462mcrMrc15TrapToHyp(const MiscRegIndex miscReg, ThreadContext *tc, uint32_t iss)
463{
464    bool        isRead;
465    uint32_t    crm;
466    IntRegIndex rt;
467    uint32_t    crn;
468    uint32_t    opc1;
469    uint32_t    opc2;
470    bool        trapToHype = false;
471
472    const CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
473    const HCR hcr = tc->readMiscReg(MISCREG_HCR);
474    const SCR scr = tc->readMiscReg(MISCREG_SCR);
475    const HDCR hdcr = tc->readMiscReg(MISCREG_HDCR);
476    const HSTR hstr = tc->readMiscReg(MISCREG_HSTR);
477    const HCPTR hcptr = tc->readMiscReg(MISCREG_HCPTR);
478
479    if (!inSecureState(scr, cpsr) && (cpsr.mode != MODE_HYP)) {
480        mcrMrcIssExtract(iss, isRead, crm, rt, crn, opc1, opc2);
481        trapToHype  = ((uint32_t) hstr) & (1 << crn);
482        trapToHype |= hdcr.tpm  && (crn == 9) && (crm >= 12);
483        trapToHype |= hcr.tidcp && (
484            ((crn ==  9) && ((crm <= 2) || ((crm >= 5) && (crm <= 8)))) ||
485            ((crn == 10) && ((crm <= 1) ||  (crm == 4) || (crm == 8)))  ||
486            ((crn == 11) && ((crm <= 8) ||  (crm == 15)))               );
487
488        if (!trapToHype) {
489            switch (unflattenMiscReg(miscReg)) {
490              case MISCREG_CPACR:
491                trapToHype = hcptr.tcpac;
492                break;
493              case MISCREG_REVIDR:
494              case MISCREG_TCMTR:
495              case MISCREG_TLBTR:
496              case MISCREG_AIDR:
497                trapToHype = hcr.tid1;
498                break;
499              case MISCREG_CTR:
500              case MISCREG_CCSIDR:
501              case MISCREG_CLIDR:
502              case MISCREG_CSSELR:
503                trapToHype = hcr.tid2;
504                break;
505              case MISCREG_ID_PFR0:
506              case MISCREG_ID_PFR1:
507              case MISCREG_ID_DFR0:
508              case MISCREG_ID_AFR0:
509              case MISCREG_ID_MMFR0:
510              case MISCREG_ID_MMFR1:
511              case MISCREG_ID_MMFR2:
512              case MISCREG_ID_MMFR3:
513              case MISCREG_ID_ISAR0:
514              case MISCREG_ID_ISAR1:
515              case MISCREG_ID_ISAR2:
516              case MISCREG_ID_ISAR3:
517              case MISCREG_ID_ISAR4:
518              case MISCREG_ID_ISAR5:
519                trapToHype = hcr.tid3;
520                break;
521              case MISCREG_DCISW:
522              case MISCREG_DCCSW:
523              case MISCREG_DCCISW:
524                trapToHype = hcr.tsw;
525                break;
526              case MISCREG_DCIMVAC:
527              case MISCREG_DCCIMVAC:
528              case MISCREG_DCCMVAC:
529                trapToHype = hcr.tpc;
530                break;
531              case MISCREG_ICIMVAU:
532              case MISCREG_ICIALLU:
533              case MISCREG_ICIALLUIS:
534              case MISCREG_DCCMVAU:
535                trapToHype = hcr.tpu;
536                break;
537              case MISCREG_TLBIALLIS:
538              case MISCREG_TLBIMVAIS:
539              case MISCREG_TLBIASIDIS:
540              case MISCREG_TLBIMVAAIS:
541              case MISCREG_TLBIMVALIS:
542              case MISCREG_TLBIMVAALIS:
543              case MISCREG_DTLBIALL:
544              case MISCREG_ITLBIALL:
545              case MISCREG_DTLBIMVA:
546              case MISCREG_ITLBIMVA:
547              case MISCREG_DTLBIASID:
548              case MISCREG_ITLBIASID:
549              case MISCREG_TLBIMVAA:
550              case MISCREG_TLBIALL:
551              case MISCREG_TLBIMVA:
552              case MISCREG_TLBIMVAL:
553              case MISCREG_TLBIMVAAL:
554              case MISCREG_TLBIASID:
555                trapToHype = hcr.ttlb;
556                break;
557              case MISCREG_ACTLR:
558                trapToHype = hcr.tac;
559                break;
560              case MISCREG_SCTLR:
561              case MISCREG_TTBR0:
562              case MISCREG_TTBR1:
563              case MISCREG_TTBCR:
564              case MISCREG_DACR:
565              case MISCREG_DFSR:
566              case MISCREG_IFSR:
567              case MISCREG_DFAR:
568              case MISCREG_IFAR:
569              case MISCREG_ADFSR:
570              case MISCREG_AIFSR:
571              case MISCREG_PRRR:
572              case MISCREG_NMRR:
573              case MISCREG_MAIR0:
574              case MISCREG_MAIR1:
575              case MISCREG_CONTEXTIDR:
576                trapToHype = hcr.tvm & !isRead;
577                break;
578              case MISCREG_PMCR:
579                trapToHype = hdcr.tpmcr;
580                break;
581              // GICv3 regs
582              case MISCREG_ICC_SGI0R:
583                if (tc->getIsaPtr()->haveGICv3CpuIfc())
584                    trapToHype = hcr.fmo;
585                break;
586              case MISCREG_ICC_SGI1R:
587              case MISCREG_ICC_ASGI1R:
588                if (tc->getIsaPtr()->haveGICv3CpuIfc())
589                    trapToHype = hcr.imo;
590                break;
591              // No default action needed
592              default:
593                break;
594            }
595        }
596    }
597    return trapToHype;
598}
599
600
601bool
602mcrMrc14TrapToHyp(const MiscRegIndex miscReg, HCR hcr, CPSR cpsr, SCR scr,
603                  HDCR hdcr, HSTR hstr, HCPTR hcptr, uint32_t iss)
604{
605    bool        isRead;
606    uint32_t    crm;
607    IntRegIndex rt;
608    uint32_t    crn;
609    uint32_t    opc1;
610    uint32_t    opc2;
611    bool        trapToHype = false;
612
613    if (!inSecureState(scr, cpsr) && (cpsr.mode != MODE_HYP)) {
614        mcrMrcIssExtract(iss, isRead, crm, rt, crn, opc1, opc2);
615        inform("trap check M:%x N:%x 1:%x 2:%x hdcr %x, hcptr %x, hstr %x\n",
616                crm, crn, opc1, opc2, hdcr, hcptr, hstr);
617        trapToHype  = hdcr.tda  && (opc1 == 0);
618        trapToHype |= hcptr.tta && (opc1 == 1);
619        if (!trapToHype) {
620            switch (unflattenMiscReg(miscReg)) {
621              case MISCREG_DBGOSLSR:
622              case MISCREG_DBGOSLAR:
623              case MISCREG_DBGOSDLR:
624              case MISCREG_DBGPRCR:
625                trapToHype = hdcr.tdosa;
626                break;
627              case MISCREG_DBGDRAR:
628              case MISCREG_DBGDSAR:
629                trapToHype = hdcr.tdra;
630                break;
631              case MISCREG_JIDR:
632                trapToHype = hcr.tid0;
633                break;
634              case MISCREG_JOSCR:
635              case MISCREG_JMCR:
636                trapToHype = hstr.tjdbx;
637                break;
638              case MISCREG_TEECR:
639              case MISCREG_TEEHBR:
640                trapToHype = hstr.ttee;
641                break;
642              // No default action needed
643              default:
644                break;
645            }
646        }
647    }
648    return trapToHype;
649}
650
651bool
652mcrrMrrc15TrapToHyp(const MiscRegIndex miscReg, CPSR cpsr, SCR scr, HSTR hstr,
653                    HCR hcr, uint32_t iss)
654{
655    uint32_t    crm;
656    IntRegIndex rt;
657    uint32_t    crn;
658    uint32_t    opc1;
659    uint32_t    opc2;
660    bool        isRead;
661    bool        trapToHype = false;
662
663    if (!inSecureState(scr, cpsr) && (cpsr.mode != MODE_HYP)) {
664        // This is technically the wrong function, but we can re-use it for
665        // the moment because we only need one field, which overlaps with the
666        // mcrmrc layout
667        mcrMrcIssExtract(iss, isRead, crm, rt, crn, opc1, opc2);
668        trapToHype = ((uint32_t) hstr) & (1 << crm);
669
670        if (!trapToHype) {
671            switch (unflattenMiscReg(miscReg)) {
672              case MISCREG_SCTLR:
673              case MISCREG_TTBR0:
674              case MISCREG_TTBR1:
675              case MISCREG_TTBCR:
676              case MISCREG_DACR:
677              case MISCREG_DFSR:
678              case MISCREG_IFSR:
679              case MISCREG_DFAR:
680              case MISCREG_IFAR:
681              case MISCREG_ADFSR:
682              case MISCREG_AIFSR:
683              case MISCREG_PRRR:
684              case MISCREG_NMRR:
685              case MISCREG_MAIR0:
686              case MISCREG_MAIR1:
687              case MISCREG_CONTEXTIDR:
688                trapToHype = hcr.tvm & !isRead;
689                break;
690              // No default action needed
691              default:
692                break;
693            }
694        }
695    }
696    return trapToHype;
697}
698
699bool
700decodeMrsMsrBankedReg(uint8_t sysM, bool r, bool &isIntReg, int &regIdx,
701                      CPSR cpsr, SCR scr, NSACR nsacr, bool checkSecurity)
702{
703    OperatingMode mode = MODE_UNDEFINED;
704    bool          ok = true;
705
706    // R mostly indicates if its a int register or a misc reg, we override
707    // below if the few corner cases
708    isIntReg = !r;
709    // Loosely based on ARM ARM issue C section B9.3.10
710    if (r) {
711        switch (sysM)
712        {
713          case 0xE:
714            regIdx = MISCREG_SPSR_FIQ;
715            mode   = MODE_FIQ;
716            break;
717          case 0x10:
718            regIdx = MISCREG_SPSR_IRQ;
719            mode   = MODE_IRQ;
720            break;
721          case 0x12:
722            regIdx = MISCREG_SPSR_SVC;
723            mode   = MODE_SVC;
724            break;
725          case 0x14:
726            regIdx = MISCREG_SPSR_ABT;
727            mode   = MODE_ABORT;
728            break;
729          case 0x16:
730            regIdx = MISCREG_SPSR_UND;
731            mode   = MODE_UNDEFINED;
732            break;
733          case 0x1C:
734            regIdx = MISCREG_SPSR_MON;
735            mode   = MODE_MON;
736            break;
737          case 0x1E:
738            regIdx = MISCREG_SPSR_HYP;
739            mode   = MODE_HYP;
740            break;
741          default:
742            ok = false;
743            break;
744        }
745    } else {
746        int sysM4To3 = bits(sysM, 4, 3);
747
748        if (sysM4To3 == 0) {
749            mode = MODE_USER;
750            regIdx = intRegInMode(mode, bits(sysM, 2, 0) + 8);
751        } else if (sysM4To3 == 1) {
752            mode = MODE_FIQ;
753            regIdx = intRegInMode(mode, bits(sysM, 2, 0) + 8);
754        } else if (sysM4To3 == 3) {
755            if (bits(sysM, 1) == 0) {
756                mode = MODE_MON;
757                regIdx = intRegInMode(mode, 14 - bits(sysM, 0));
758            } else {
759                mode = MODE_HYP;
760                if (bits(sysM, 0) == 1) {
761                    regIdx = intRegInMode(mode, 13); // R13 in HYP
762                } else {
763                    isIntReg = false;
764                    regIdx   = MISCREG_ELR_HYP;
765                }
766            }
767        } else { // Other Banked registers
768            int sysM2 = bits(sysM, 2);
769            int sysM1 = bits(sysM, 1);
770
771            mode  = (OperatingMode) ( ((sysM2 ||  sysM1) << 0) |
772                                      (1                 << 1) |
773                                      ((sysM2 && !sysM1) << 2) |
774                                      ((sysM2 &&  sysM1) << 3) |
775                                      (1                 << 4) );
776            regIdx = intRegInMode(mode, 14 - bits(sysM, 0));
777            // Don't flatten the register here. This is going to go through
778            // setIntReg() which will do the flattening
779            ok &= mode != cpsr.mode;
780        }
781    }
782
783    // Check that the requested register is accessable from the current mode
784    if (ok && checkSecurity && mode != cpsr.mode) {
785        switch (cpsr.mode)
786        {
787          case MODE_USER:
788            ok = false;
789            break;
790          case MODE_FIQ:
791            ok &=  mode != MODE_HYP;
792            ok &= (mode != MODE_MON) || !scr.ns;
793            break;
794          case MODE_HYP:
795            ok &=  mode != MODE_MON;
796            ok &= (mode != MODE_FIQ) || !nsacr.rfr;
797            break;
798          case MODE_IRQ:
799          case MODE_SVC:
800          case MODE_ABORT:
801          case MODE_UNDEFINED:
802          case MODE_SYSTEM:
803            ok &=  mode != MODE_HYP;
804            ok &= (mode != MODE_MON) || !scr.ns;
805            ok &= (mode != MODE_FIQ) || !nsacr.rfr;
806            break;
807          // can access everything, no further checks required
808          case MODE_MON:
809            break;
810          default:
811            panic("unknown Mode 0x%x\n", cpsr.mode);
812            break;
813        }
814    }
815    return (ok);
816}
817
818bool
819SPAlignmentCheckEnabled(ThreadContext* tc)
820{
821    switch (currEL(tc)) {
822      case EL3:
823        return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL3)).sa;
824      case EL2:
825        return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL2)).sa;
826      case EL1:
827        return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL1)).sa;
828      case EL0:
829        return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL1)).sa0;
830      default:
831        panic("Invalid exception level");
832        break;
833    }
834}
835
836int
837decodePhysAddrRange64(uint8_t pa_enc)
838{
839    switch (pa_enc) {
840      case 0x0:
841        return 32;
842      case 0x1:
843        return 36;
844      case 0x2:
845        return 40;
846      case 0x3:
847        return 42;
848      case 0x4:
849        return 44;
850      case 0x5:
851      case 0x6:
852      case 0x7:
853        return 48;
854      default:
855        panic("Invalid phys. address range encoding");
856    }
857}
858
859uint8_t
860encodePhysAddrRange64(int pa_size)
861{
862    switch (pa_size) {
863      case 32:
864        return 0x0;
865      case 36:
866        return 0x1;
867      case 40:
868        return 0x2;
869      case 42:
870        return 0x3;
871      case 44:
872        return 0x4;
873      case 48:
874        return 0x5;
875      default:
876        panic("Invalid phys. address range");
877    }
878}
879
880} // namespace ArmISA
881