isa.hh revision 13114:777d445423d6
1/*
2 * Copyright (c) 2010, 2012-2018 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 * Copyright (c) 2009 The Regents of The University of Michigan
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Authors: Gabe Black
41 */
42
43#ifndef __ARCH_ARM_ISA_HH__
44#define __ARCH_ARM_ISA_HH__
45
46#include "arch/arm/isa_device.hh"
47#include "arch/arm/miscregs.hh"
48#include "arch/arm/registers.hh"
49#include "arch/arm/system.hh"
50#include "arch/arm/tlb.hh"
51#include "arch/arm/types.hh"
52#include "arch/generic/traits.hh"
53#include "debug/Checkpoint.hh"
54#include "enums/VecRegRenameMode.hh"
55#include "sim/sim_object.hh"
56#include "enums/DecoderFlavour.hh"
57
58struct ArmISAParams;
59struct DummyArmISADeviceParams;
60class ThreadContext;
61class Checkpoint;
62class EventManager;
63
64namespace ArmISA
65{
66    class ISA : public SimObject
67    {
68      protected:
69        // Parent system
70        ArmSystem *system;
71
72        // Micro Architecture
73        const Enums::DecoderFlavour _decoderFlavour;
74        const Enums::VecRegRenameMode _vecRegRenameMode;
75
76        /** Dummy device for to handle non-existing ISA devices */
77        DummyISADevice dummyDevice;
78
79        // PMU belonging to this ISA
80        BaseISADevice *pmu;
81
82        // Generic timer interface belonging to this ISA
83        std::unique_ptr<BaseISADevice> timer;
84
85        // Cached copies of system-level properties
86        bool highestELIs64;
87        bool haveSecurity;
88        bool haveLPAE;
89        bool haveVirtualization;
90        bool haveLargeAsid64;
91        uint8_t physAddrRange;
92
93        /**
94         * If true, accesses to IMPLEMENTATION DEFINED registers are treated
95         * as NOP hence not causing UNDEFINED INSTRUCTION.
96         */
97        bool impdefAsNop;
98
99        /** MiscReg metadata **/
100        struct MiscRegLUTEntry {
101            uint32_t lower;  // Lower half mapped to this register
102            uint32_t upper;  // Upper half mapped to this register
103            uint64_t _reset; // value taken on reset (i.e. initialization)
104            uint64_t _res0;  // reserved
105            uint64_t _res1;  // reserved
106            uint64_t _raz;   // read as zero (fixed at 0)
107            uint64_t _rao;   // read as one (fixed at 1)
108          public:
109            MiscRegLUTEntry() :
110              lower(0), upper(0),
111              _reset(0), _res0(0), _res1(0), _raz(0), _rao(0) {}
112            uint64_t reset() const { return _reset; }
113            uint64_t res0()  const { return _res0; }
114            uint64_t res1()  const { return _res1; }
115            uint64_t raz()   const { return _raz; }
116            uint64_t rao()   const { return _rao; }
117            // raz/rao implies writes ignored
118            uint64_t wi()    const { return _raz | _rao; }
119        };
120
121        /** Metadata table accessible via the value of the register */
122        static std::vector<struct MiscRegLUTEntry> lookUpMiscReg;
123
124        class MiscRegLUTEntryInitializer {
125            struct MiscRegLUTEntry &entry;
126            std::bitset<NUM_MISCREG_INFOS> &info;
127            typedef const MiscRegLUTEntryInitializer& chain;
128          public:
129            chain mapsTo(uint32_t l, uint32_t u = 0) const {
130                entry.lower = l;
131                entry.upper = u;
132                return *this;
133            }
134            chain res0(uint64_t mask) const {
135                entry._res0 = mask;
136                return *this;
137            }
138            chain res1(uint64_t mask) const {
139                entry._res1 = mask;
140                return *this;
141            }
142            chain raz(uint64_t mask) const {
143                entry._raz  = mask;
144                return *this;
145            }
146            chain rao(uint64_t mask) const {
147                entry._rao  = mask;
148                return *this;
149            }
150            chain implemented(bool v = true) const {
151                info[MISCREG_IMPLEMENTED] = v;
152                return *this;
153            }
154            chain unimplemented() const {
155                return implemented(false);
156            }
157            chain unverifiable(bool v = true) const {
158                info[MISCREG_UNVERIFIABLE] = v;
159                return *this;
160            }
161            chain warnNotFail(bool v = true) const {
162                info[MISCREG_WARN_NOT_FAIL] = v;
163                return *this;
164            }
165            chain mutex(bool v = true) const {
166                info[MISCREG_MUTEX] = v;
167                return *this;
168            }
169            chain banked(bool v = true) const {
170                info[MISCREG_BANKED] = v;
171                return *this;
172            }
173            chain bankedChild(bool v = true) const {
174                info[MISCREG_BANKED_CHILD] = v;
175                return *this;
176            }
177            chain userNonSecureRead(bool v = true) const {
178                info[MISCREG_USR_NS_RD] = v;
179                return *this;
180            }
181            chain userNonSecureWrite(bool v = true) const {
182                info[MISCREG_USR_NS_WR] = v;
183                return *this;
184            }
185            chain userSecureRead(bool v = true) const {
186                info[MISCREG_USR_S_RD] = v;
187                return *this;
188            }
189            chain userSecureWrite(bool v = true) const {
190                info[MISCREG_USR_S_WR] = v;
191                return *this;
192            }
193            chain user(bool v = true) const {
194                userNonSecureRead(v);
195                userNonSecureWrite(v);
196                userSecureRead(v);
197                userSecureWrite(v);
198                return *this;
199            }
200            chain privNonSecureRead(bool v = true) const {
201                info[MISCREG_PRI_NS_RD] = v;
202                return *this;
203            }
204            chain privNonSecureWrite(bool v = true) const {
205                info[MISCREG_PRI_NS_WR] = v;
206                return *this;
207            }
208            chain privNonSecure(bool v = true) const {
209                privNonSecureRead(v);
210                privNonSecureWrite(v);
211                return *this;
212            }
213            chain privSecureRead(bool v = true) const {
214                info[MISCREG_PRI_S_RD] = v;
215                return *this;
216            }
217            chain privSecureWrite(bool v = true) const {
218                info[MISCREG_PRI_S_WR] = v;
219                return *this;
220            }
221            chain privSecure(bool v = true) const {
222                privSecureRead(v);
223                privSecureWrite(v);
224                return *this;
225            }
226            chain priv(bool v = true) const {
227                privSecure(v);
228                privNonSecure(v);
229                return *this;
230            }
231            chain hypRead(bool v = true) const {
232                info[MISCREG_HYP_RD] = v;
233                return *this;
234            }
235            chain hypWrite(bool v = true) const {
236                info[MISCREG_HYP_WR] = v;
237                return *this;
238            }
239            chain hyp(bool v = true) const {
240                hypRead(v);
241                hypWrite(v);
242                return *this;
243            }
244            chain monSecureRead(bool v = true) const {
245                info[MISCREG_MON_NS0_RD] = v;
246                return *this;
247            }
248            chain monSecureWrite(bool v = true) const {
249                info[MISCREG_MON_NS0_WR] = v;
250                return *this;
251            }
252            chain monNonSecureRead(bool v = true) const {
253                info[MISCREG_MON_NS1_RD] = v;
254                return *this;
255            }
256            chain monNonSecureWrite(bool v = true) const {
257                info[MISCREG_MON_NS1_WR] = v;
258                return *this;
259            }
260            chain mon(bool v = true) const {
261                monSecureRead(v);
262                monSecureWrite(v);
263                monNonSecureRead(v);
264                monNonSecureWrite(v);
265                return *this;
266            }
267            chain monSecure(bool v = true) const {
268                monSecureRead(v);
269                monSecureWrite(v);
270                return *this;
271            }
272            chain monNonSecure(bool v = true) const {
273                monNonSecureRead(v);
274                monNonSecureWrite(v);
275                return *this;
276            }
277            chain allPrivileges(bool v = true) const {
278                userNonSecureRead(v);
279                userNonSecureWrite(v);
280                userSecureRead(v);
281                userSecureWrite(v);
282                privNonSecureRead(v);
283                privNonSecureWrite(v);
284                privSecureRead(v);
285                privSecureWrite(v);
286                hypRead(v);
287                hypWrite(v);
288                monSecureRead(v);
289                monSecureWrite(v);
290                monNonSecureRead(v);
291                monNonSecureWrite(v);
292                return *this;
293            }
294            chain nonSecure(bool v = true) const {
295                userNonSecureRead(v);
296                userNonSecureWrite(v);
297                privNonSecureRead(v);
298                privNonSecureWrite(v);
299                hypRead(v);
300                hypWrite(v);
301                monNonSecureRead(v);
302                monNonSecureWrite(v);
303                return *this;
304            }
305            chain secure(bool v = true) const {
306                userSecureRead(v);
307                userSecureWrite(v);
308                privSecureRead(v);
309                privSecureWrite(v);
310                monSecureRead(v);
311                monSecureWrite(v);
312                return *this;
313            }
314            chain reads(bool v) const {
315                userNonSecureRead(v);
316                userSecureRead(v);
317                privNonSecureRead(v);
318                privSecureRead(v);
319                hypRead(v);
320                monSecureRead(v);
321                monNonSecureRead(v);
322                return *this;
323            }
324            chain writes(bool v) const {
325                userNonSecureWrite(v);
326                userSecureWrite(v);
327                privNonSecureWrite(v);
328                privSecureWrite(v);
329                hypWrite(v);
330                monSecureWrite(v);
331                monNonSecureWrite(v);
332                return *this;
333            }
334            chain exceptUserMode() const {
335                user(0);
336                return *this;
337            }
338            MiscRegLUTEntryInitializer(struct MiscRegLUTEntry &e,
339                                       std::bitset<NUM_MISCREG_INFOS> &i)
340              : entry(e),
341                info(i)
342            {
343                // force unimplemented registers to be thusly declared
344                implemented(1);
345            }
346        };
347
348        const MiscRegLUTEntryInitializer InitReg(uint32_t reg) {
349            return MiscRegLUTEntryInitializer(lookUpMiscReg[reg],
350                                              miscRegInfo[reg]);
351        }
352
353        void initializeMiscRegMetadata();
354
355        MiscReg miscRegs[NumMiscRegs];
356        const IntRegIndex *intRegMap;
357
358        void
359        updateRegMap(CPSR cpsr)
360        {
361            if (cpsr.width == 0) {
362                intRegMap = IntReg64Map;
363            } else {
364                switch (cpsr.mode) {
365                  case MODE_USER:
366                  case MODE_SYSTEM:
367                    intRegMap = IntRegUsrMap;
368                    break;
369                  case MODE_FIQ:
370                    intRegMap = IntRegFiqMap;
371                    break;
372                  case MODE_IRQ:
373                    intRegMap = IntRegIrqMap;
374                    break;
375                  case MODE_SVC:
376                    intRegMap = IntRegSvcMap;
377                    break;
378                  case MODE_MON:
379                    intRegMap = IntRegMonMap;
380                    break;
381                  case MODE_ABORT:
382                    intRegMap = IntRegAbtMap;
383                    break;
384                  case MODE_HYP:
385                    intRegMap = IntRegHypMap;
386                    break;
387                  case MODE_UNDEFINED:
388                    intRegMap = IntRegUndMap;
389                    break;
390                  default:
391                    panic("Unrecognized mode setting in CPSR.\n");
392                }
393            }
394        }
395
396        BaseISADevice &getGenericTimer(ThreadContext *tc);
397
398
399      private:
400        inline void assert32(ThreadContext *tc) {
401            CPSR cpsr M5_VAR_USED = readMiscReg(MISCREG_CPSR, tc);
402            assert(cpsr.width);
403        }
404
405        inline void assert64(ThreadContext *tc) {
406            CPSR cpsr M5_VAR_USED = readMiscReg(MISCREG_CPSR, tc);
407            assert(!cpsr.width);
408        }
409
410      public:
411        void clear();
412
413      protected:
414        void clear64(const ArmISAParams *p);
415        void initID32(const ArmISAParams *p);
416        void initID64(const ArmISAParams *p);
417
418      public:
419        MiscReg readMiscRegNoEffect(int misc_reg) const;
420        MiscReg readMiscReg(int misc_reg, ThreadContext *tc);
421        void setMiscRegNoEffect(int misc_reg, const MiscReg &val);
422        void setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc);
423
424        RegId
425        flattenRegId(const RegId& regId) const
426        {
427            switch (regId.classValue()) {
428              case IntRegClass:
429                return RegId(IntRegClass, flattenIntIndex(regId.index()));
430              case FloatRegClass:
431                return RegId(FloatRegClass, flattenFloatIndex(regId.index()));
432              case VecRegClass:
433                return RegId(VecRegClass, flattenVecIndex(regId.index()));
434              case VecElemClass:
435                return RegId(VecElemClass, flattenVecElemIndex(regId.index()));
436              case CCRegClass:
437                return RegId(CCRegClass, flattenCCIndex(regId.index()));
438              case MiscRegClass:
439                return RegId(MiscRegClass, flattenMiscIndex(regId.index()));
440            }
441            return RegId();
442        }
443
444        int
445        flattenIntIndex(int reg) const
446        {
447            assert(reg >= 0);
448            if (reg < NUM_ARCH_INTREGS) {
449                return intRegMap[reg];
450            } else if (reg < NUM_INTREGS) {
451                return reg;
452            } else if (reg == INTREG_SPX) {
453                CPSR cpsr = miscRegs[MISCREG_CPSR];
454                ExceptionLevel el = opModeToEL(
455                    (OperatingMode) (uint8_t) cpsr.mode);
456                if (!cpsr.sp && el != EL0)
457                    return INTREG_SP0;
458                switch (el) {
459                  case EL3:
460                    return INTREG_SP3;
461                  case EL2:
462                    return INTREG_SP2;
463                  case EL1:
464                    return INTREG_SP1;
465                  case EL0:
466                    return INTREG_SP0;
467                  default:
468                    panic("Invalid exception level");
469                    return 0;  // Never happens.
470                }
471            } else {
472                return flattenIntRegModeIndex(reg);
473            }
474        }
475
476        int
477        flattenFloatIndex(int reg) const
478        {
479            assert(reg >= 0);
480            return reg;
481        }
482
483        int
484        flattenVecIndex(int reg) const
485        {
486            assert(reg >= 0);
487            return reg;
488        }
489
490        int
491        flattenVecElemIndex(int reg) const
492        {
493            assert(reg >= 0);
494            return reg;
495        }
496
497        int
498        flattenCCIndex(int reg) const
499        {
500            assert(reg >= 0);
501            return reg;
502        }
503
504        int
505        flattenMiscIndex(int reg) const
506        {
507            assert(reg >= 0);
508            int flat_idx = reg;
509
510            if (reg == MISCREG_SPSR) {
511                CPSR cpsr = miscRegs[MISCREG_CPSR];
512                switch (cpsr.mode) {
513                  case MODE_EL0T:
514                    warn("User mode does not have SPSR\n");
515                    flat_idx = MISCREG_SPSR;
516                    break;
517                  case MODE_EL1T:
518                  case MODE_EL1H:
519                    flat_idx = MISCREG_SPSR_EL1;
520                    break;
521                  case MODE_EL2T:
522                  case MODE_EL2H:
523                    flat_idx = MISCREG_SPSR_EL2;
524                    break;
525                  case MODE_EL3T:
526                  case MODE_EL3H:
527                    flat_idx = MISCREG_SPSR_EL3;
528                    break;
529                  case MODE_USER:
530                    warn("User mode does not have SPSR\n");
531                    flat_idx = MISCREG_SPSR;
532                    break;
533                  case MODE_FIQ:
534                    flat_idx = MISCREG_SPSR_FIQ;
535                    break;
536                  case MODE_IRQ:
537                    flat_idx = MISCREG_SPSR_IRQ;
538                    break;
539                  case MODE_SVC:
540                    flat_idx = MISCREG_SPSR_SVC;
541                    break;
542                  case MODE_MON:
543                    flat_idx = MISCREG_SPSR_MON;
544                    break;
545                  case MODE_ABORT:
546                    flat_idx = MISCREG_SPSR_ABT;
547                    break;
548                  case MODE_HYP:
549                    flat_idx = MISCREG_SPSR_HYP;
550                    break;
551                  case MODE_UNDEFINED:
552                    flat_idx = MISCREG_SPSR_UND;
553                    break;
554                  default:
555                    warn("Trying to access SPSR in an invalid mode: %d\n",
556                         cpsr.mode);
557                    flat_idx = MISCREG_SPSR;
558                    break;
559                }
560            } else if (miscRegInfo[reg][MISCREG_MUTEX]) {
561                // Mutually exclusive CP15 register
562                switch (reg) {
563                  case MISCREG_PRRR_MAIR0:
564                  case MISCREG_PRRR_MAIR0_NS:
565                  case MISCREG_PRRR_MAIR0_S:
566                    {
567                        TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
568                        // If the muxed reg has been flattened, work out the
569                        // offset and apply it to the unmuxed reg
570                        int idxOffset = reg - MISCREG_PRRR_MAIR0;
571                        if (ttbcr.eae)
572                            flat_idx = flattenMiscIndex(MISCREG_MAIR0 +
573                                                        idxOffset);
574                        else
575                            flat_idx = flattenMiscIndex(MISCREG_PRRR +
576                                                        idxOffset);
577                    }
578                    break;
579                  case MISCREG_NMRR_MAIR1:
580                  case MISCREG_NMRR_MAIR1_NS:
581                  case MISCREG_NMRR_MAIR1_S:
582                    {
583                        TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
584                        // If the muxed reg has been flattened, work out the
585                        // offset and apply it to the unmuxed reg
586                        int idxOffset = reg - MISCREG_NMRR_MAIR1;
587                        if (ttbcr.eae)
588                            flat_idx = flattenMiscIndex(MISCREG_MAIR1 +
589                                                        idxOffset);
590                        else
591                            flat_idx = flattenMiscIndex(MISCREG_NMRR +
592                                                        idxOffset);
593                    }
594                    break;
595                  case MISCREG_PMXEVTYPER_PMCCFILTR:
596                    {
597                        PMSELR pmselr = miscRegs[MISCREG_PMSELR];
598                        if (pmselr.sel == 31)
599                            flat_idx = flattenMiscIndex(MISCREG_PMCCFILTR);
600                        else
601                            flat_idx = flattenMiscIndex(MISCREG_PMXEVTYPER);
602                    }
603                    break;
604                  default:
605                    panic("Unrecognized misc. register.\n");
606                    break;
607                }
608            } else {
609                if (miscRegInfo[reg][MISCREG_BANKED]) {
610                    bool secureReg = haveSecurity && !highestELIs64 &&
611                                     inSecureState(miscRegs[MISCREG_SCR],
612                                                   miscRegs[MISCREG_CPSR]);
613                    flat_idx += secureReg ? 2 : 1;
614                }
615            }
616            return flat_idx;
617        }
618
619        std::pair<int,int> getMiscIndices(int misc_reg) const
620        {
621            // Note: indexes of AArch64 registers are left unchanged
622            int flat_idx = flattenMiscIndex(misc_reg);
623
624            if (lookUpMiscReg[flat_idx].lower == 0) {
625                return std::make_pair(flat_idx, 0);
626            }
627
628            // do additional S/NS flattenings if mapped to NS while in S
629            bool S = haveSecurity && !highestELIs64 &&
630                     inSecureState(miscRegs[MISCREG_SCR],
631                                   miscRegs[MISCREG_CPSR]);
632            int lower = lookUpMiscReg[flat_idx].lower;
633            int upper = lookUpMiscReg[flat_idx].upper;
634            // upper == 0, which is CPSR, is not MISCREG_BANKED_CHILD (no-op)
635            lower += S && miscRegInfo[lower][MISCREG_BANKED_CHILD];
636            upper += S && miscRegInfo[upper][MISCREG_BANKED_CHILD];
637            return std::make_pair(lower, upper);
638        }
639
640        void serialize(CheckpointOut &cp) const
641        {
642            DPRINTF(Checkpoint, "Serializing Arm Misc Registers\n");
643            SERIALIZE_ARRAY(miscRegs, NUM_PHYS_MISCREGS);
644
645            SERIALIZE_SCALAR(highestELIs64);
646            SERIALIZE_SCALAR(haveSecurity);
647            SERIALIZE_SCALAR(haveLPAE);
648            SERIALIZE_SCALAR(haveVirtualization);
649            SERIALIZE_SCALAR(haveLargeAsid64);
650            SERIALIZE_SCALAR(physAddrRange);
651        }
652        void unserialize(CheckpointIn &cp)
653        {
654            DPRINTF(Checkpoint, "Unserializing Arm Misc Registers\n");
655            UNSERIALIZE_ARRAY(miscRegs, NUM_PHYS_MISCREGS);
656            CPSR tmp_cpsr = miscRegs[MISCREG_CPSR];
657            updateRegMap(tmp_cpsr);
658
659            UNSERIALIZE_SCALAR(highestELIs64);
660            UNSERIALIZE_SCALAR(haveSecurity);
661            UNSERIALIZE_SCALAR(haveLPAE);
662            UNSERIALIZE_SCALAR(haveVirtualization);
663            UNSERIALIZE_SCALAR(haveLargeAsid64);
664            UNSERIALIZE_SCALAR(physAddrRange);
665        }
666
667        void startup(ThreadContext *tc);
668
669        Enums::DecoderFlavour decoderFlavour() const { return _decoderFlavour; }
670
671        Enums::VecRegRenameMode
672        vecRegRenameMode() const
673        {
674            return _vecRegRenameMode;
675        }
676
677        /// Explicitly import the otherwise hidden startup
678        using SimObject::startup;
679
680        typedef ArmISAParams Params;
681
682        const Params *params() const;
683
684        ISA(Params *p);
685    };
686}
687
688template<>
689struct initRenameMode<ArmISA::ISA>
690{
691    static Enums::VecRegRenameMode mode(const ArmISA::ISA* isa)
692    {
693        return isa->vecRegRenameMode();
694    }
695    static bool equals(const ArmISA::ISA* isa1, const ArmISA::ISA* isa2)
696    {
697        return mode(isa1) == mode(isa2);
698    }
699};
700
701#endif
702