isa.hh revision 12577:5cafe57f87e5
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 physAddrRange64;
92
93        /** MiscReg metadata **/
94        struct MiscRegLUTEntry {
95            uint32_t lower;  // Lower half mapped to this register
96            uint32_t upper;  // Upper half mapped to this register
97            uint64_t _reset; // value taken on reset (i.e. initialization)
98            uint64_t _res0;  // reserved
99            uint64_t _res1;  // reserved
100            uint64_t _raz;   // read as zero (fixed at 0)
101            uint64_t _rao;   // read as one (fixed at 1)
102          public:
103            MiscRegLUTEntry() :
104              lower(0), upper(0),
105              _reset(0), _res0(0), _res1(0), _raz(0), _rao(0) {}
106            uint64_t reset() const { return _reset; }
107            uint64_t res0()  const { return _res0; }
108            uint64_t res1()  const { return _res1; }
109            uint64_t raz()   const { return _raz; }
110            uint64_t rao()   const { return _rao; }
111            // raz/rao implies writes ignored
112            uint64_t wi()    const { return _raz | _rao; }
113        };
114
115        /** Metadata table accessible via the value of the register */
116        static std::vector<struct MiscRegLUTEntry> lookUpMiscReg;
117
118        class MiscRegLUTEntryInitializer {
119            struct MiscRegLUTEntry &entry;
120            std::bitset<NUM_MISCREG_INFOS> &info;
121            typedef const MiscRegLUTEntryInitializer& chain;
122          public:
123            chain mapsTo(uint32_t l, uint32_t u = 0) const {
124                entry.lower = l;
125                entry.upper = u;
126                return *this;
127            }
128            chain res0(uint64_t mask) const {
129                entry._res0 = mask;
130                return *this;
131            }
132            chain res1(uint64_t mask) const {
133                entry._res1 = mask;
134                return *this;
135            }
136            chain raz(uint64_t mask) const {
137                entry._raz  = mask;
138                return *this;
139            }
140            chain rao(uint64_t mask) const {
141                entry._rao  = mask;
142                return *this;
143            }
144            chain implemented(bool v = true) const {
145                info[MISCREG_IMPLEMENTED] = v;
146                return *this;
147            }
148            chain unimplemented() const {
149                return implemented(false);
150            }
151            chain unverifiable(bool v = true) const {
152                info[MISCREG_UNVERIFIABLE] = v;
153                return *this;
154            }
155            chain warnNotFail(bool v = true) const {
156                info[MISCREG_WARN_NOT_FAIL] = v;
157                return *this;
158            }
159            chain mutex(bool v = true) const {
160                info[MISCREG_MUTEX] = v;
161                return *this;
162            }
163            chain banked(bool v = true) const {
164                info[MISCREG_BANKED] = v;
165                return *this;
166            }
167            chain bankedChild(bool v = true) const {
168                info[MISCREG_BANKED_CHILD] = v;
169                return *this;
170            }
171            chain userNonSecureRead(bool v = true) const {
172                info[MISCREG_USR_NS_RD] = v;
173                return *this;
174            }
175            chain userNonSecureWrite(bool v = true) const {
176                info[MISCREG_USR_NS_WR] = v;
177                return *this;
178            }
179            chain userSecureRead(bool v = true) const {
180                info[MISCREG_USR_S_RD] = v;
181                return *this;
182            }
183            chain userSecureWrite(bool v = true) const {
184                info[MISCREG_USR_S_WR] = v;
185                return *this;
186            }
187            chain user(bool v = true) const {
188                userNonSecureRead(v);
189                userNonSecureWrite(v);
190                userSecureRead(v);
191                userSecureWrite(v);
192                return *this;
193            }
194            chain privNonSecureRead(bool v = true) const {
195                info[MISCREG_PRI_NS_RD] = v;
196                return *this;
197            }
198            chain privNonSecureWrite(bool v = true) const {
199                info[MISCREG_PRI_NS_WR] = v;
200                return *this;
201            }
202            chain privSecureRead(bool v = true) const {
203                info[MISCREG_PRI_S_RD] = v;
204                return *this;
205            }
206            chain privSecureWrite(bool v = true) const {
207                info[MISCREG_PRI_S_WR] = v;
208                return *this;
209            }
210            chain privSecure(bool v = true) const {
211                privSecureRead(v);
212                privSecureWrite(v);
213                return *this;
214            }
215            chain hypRead(bool v = true) const {
216                info[MISCREG_HYP_RD] = v;
217                return *this;
218            }
219            chain hypWrite(bool v = true) const {
220                info[MISCREG_HYP_WR] = v;
221                return *this;
222            }
223            chain hyp(bool v = true) const {
224                hypRead(v);
225                hypWrite(v);
226                return *this;
227            }
228            chain monSecureRead(bool v = true) const {
229                info[MISCREG_MON_NS0_RD] = v;
230                return *this;
231            }
232            chain monSecureWrite(bool v = true) const {
233                info[MISCREG_MON_NS0_WR] = v;
234                return *this;
235            }
236            chain monNonSecureRead(bool v = true) const {
237                info[MISCREG_MON_NS1_RD] = v;
238                return *this;
239            }
240            chain monNonSecureWrite(bool v = true) const {
241                info[MISCREG_MON_NS1_WR] = v;
242                return *this;
243            }
244            chain mon(bool v = true) const {
245                monSecureRead(v);
246                monSecureWrite(v);
247                monNonSecureRead(v);
248                monNonSecureWrite(v);
249                return *this;
250            }
251            chain monSecure(bool v = true) const {
252                monSecureRead(v);
253                monSecureWrite(v);
254                return *this;
255            }
256            chain monNonSecure(bool v = true) const {
257                monNonSecureRead(v);
258                monNonSecureWrite(v);
259                return *this;
260            }
261            chain allPrivileges(bool v = true) const {
262                userNonSecureRead(v);
263                userNonSecureWrite(v);
264                userSecureRead(v);
265                userSecureWrite(v);
266                privNonSecureRead(v);
267                privNonSecureWrite(v);
268                privSecureRead(v);
269                privSecureWrite(v);
270                hypRead(v);
271                hypWrite(v);
272                monSecureRead(v);
273                monSecureWrite(v);
274                monNonSecureRead(v);
275                monNonSecureWrite(v);
276                return *this;
277            }
278            chain nonSecure(bool v = true) const {
279                userNonSecureRead(v);
280                userNonSecureWrite(v);
281                privNonSecureRead(v);
282                privNonSecureWrite(v);
283                hypRead(v);
284                hypWrite(v);
285                monNonSecureRead(v);
286                monNonSecureWrite(v);
287                return *this;
288            }
289            chain secure(bool v = true) const {
290                userSecureRead(v);
291                userSecureWrite(v);
292                privSecureRead(v);
293                privSecureWrite(v);
294                monSecureRead(v);
295                monSecureWrite(v);
296                return *this;
297            }
298            chain reads(bool v) const {
299                userNonSecureRead(v);
300                userSecureRead(v);
301                privNonSecureRead(v);
302                privSecureRead(v);
303                hypRead(v);
304                monSecureRead(v);
305                monNonSecureRead(v);
306                return *this;
307            }
308            chain writes(bool v) const {
309                userNonSecureWrite(v);
310                userSecureWrite(v);
311                privNonSecureWrite(v);
312                privSecureWrite(v);
313                hypWrite(v);
314                monSecureWrite(v);
315                monNonSecureWrite(v);
316                return *this;
317            }
318            chain exceptUserMode() const {
319                user(0);
320                return *this;
321            }
322            MiscRegLUTEntryInitializer(struct MiscRegLUTEntry &e,
323                                       std::bitset<NUM_MISCREG_INFOS> &i)
324              : entry(e),
325                info(i)
326            {
327                // force unimplemented registers to be thusly declared
328                implemented(1);
329            }
330        };
331
332        const MiscRegLUTEntryInitializer InitReg(uint32_t reg) {
333            return MiscRegLUTEntryInitializer(lookUpMiscReg[reg],
334                                              miscRegInfo[reg]);
335        }
336
337        void initializeMiscRegMetadata();
338
339        MiscReg miscRegs[NumMiscRegs];
340        const IntRegIndex *intRegMap;
341
342        void
343        updateRegMap(CPSR cpsr)
344        {
345            if (cpsr.width == 0) {
346                intRegMap = IntReg64Map;
347            } else {
348                switch (cpsr.mode) {
349                  case MODE_USER:
350                  case MODE_SYSTEM:
351                    intRegMap = IntRegUsrMap;
352                    break;
353                  case MODE_FIQ:
354                    intRegMap = IntRegFiqMap;
355                    break;
356                  case MODE_IRQ:
357                    intRegMap = IntRegIrqMap;
358                    break;
359                  case MODE_SVC:
360                    intRegMap = IntRegSvcMap;
361                    break;
362                  case MODE_MON:
363                    intRegMap = IntRegMonMap;
364                    break;
365                  case MODE_ABORT:
366                    intRegMap = IntRegAbtMap;
367                    break;
368                  case MODE_HYP:
369                    intRegMap = IntRegHypMap;
370                    break;
371                  case MODE_UNDEFINED:
372                    intRegMap = IntRegUndMap;
373                    break;
374                  default:
375                    panic("Unrecognized mode setting in CPSR.\n");
376                }
377            }
378        }
379
380        BaseISADevice &getGenericTimer(ThreadContext *tc);
381
382
383      private:
384        inline void assert32(ThreadContext *tc) {
385            CPSR cpsr M5_VAR_USED = readMiscReg(MISCREG_CPSR, tc);
386            assert(cpsr.width);
387        }
388
389        inline void assert64(ThreadContext *tc) {
390            CPSR cpsr M5_VAR_USED = readMiscReg(MISCREG_CPSR, tc);
391            assert(!cpsr.width);
392        }
393
394        void tlbiVA(ThreadContext *tc, MiscReg newVal, uint16_t asid,
395                    bool secure_lookup, uint8_t target_el);
396
397        void tlbiALL(ThreadContext *tc, bool secure_lookup, uint8_t target_el);
398
399        void tlbiALLN(ThreadContext *tc, bool hyp, uint8_t target_el);
400
401        void tlbiMVA(ThreadContext *tc, MiscReg newVal, bool secure_lookup,
402                     bool hyp, uint8_t target_el);
403
404        void tlbiIPA(ThreadContext *tc, MiscReg newVal, bool secure_lookup,
405                     uint8_t target_el);
406
407      public:
408        void clear();
409        void clear64(const ArmISAParams *p);
410
411        MiscReg readMiscRegNoEffect(int misc_reg) const;
412        MiscReg readMiscReg(int misc_reg, ThreadContext *tc);
413        void setMiscRegNoEffect(int misc_reg, const MiscReg &val);
414        void setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc);
415
416        RegId
417        flattenRegId(const RegId& regId) const
418        {
419            switch (regId.classValue()) {
420              case IntRegClass:
421                return RegId(IntRegClass, flattenIntIndex(regId.index()));
422              case FloatRegClass:
423                return RegId(FloatRegClass, flattenFloatIndex(regId.index()));
424              case VecRegClass:
425                return RegId(VecRegClass, flattenVecIndex(regId.index()));
426              case VecElemClass:
427                return RegId(VecElemClass, flattenVecElemIndex(regId.index()));
428              case CCRegClass:
429                return RegId(CCRegClass, flattenCCIndex(regId.index()));
430              case MiscRegClass:
431                return RegId(MiscRegClass, flattenMiscIndex(regId.index()));
432            }
433            return RegId();
434        }
435
436        int
437        flattenIntIndex(int reg) const
438        {
439            assert(reg >= 0);
440            if (reg < NUM_ARCH_INTREGS) {
441                return intRegMap[reg];
442            } else if (reg < NUM_INTREGS) {
443                return reg;
444            } else if (reg == INTREG_SPX) {
445                CPSR cpsr = miscRegs[MISCREG_CPSR];
446                ExceptionLevel el = opModeToEL(
447                    (OperatingMode) (uint8_t) cpsr.mode);
448                if (!cpsr.sp && el != EL0)
449                    return INTREG_SP0;
450                switch (el) {
451                  case EL3:
452                    return INTREG_SP3;
453                  case EL2:
454                    return INTREG_SP2;
455                  case EL1:
456                    return INTREG_SP1;
457                  case EL0:
458                    return INTREG_SP0;
459                  default:
460                    panic("Invalid exception level");
461                    break;
462                }
463            } else {
464                return flattenIntRegModeIndex(reg);
465            }
466        }
467
468        int
469        flattenFloatIndex(int reg) const
470        {
471            assert(reg >= 0);
472            return reg;
473        }
474
475        int
476        flattenVecIndex(int reg) const
477        {
478            assert(reg >= 0);
479            return reg;
480        }
481
482        int
483        flattenVecElemIndex(int reg) const
484        {
485            assert(reg >= 0);
486            return reg;
487        }
488
489        int
490        flattenCCIndex(int reg) const
491        {
492            assert(reg >= 0);
493            return reg;
494        }
495
496        int
497        flattenMiscIndex(int reg) const
498        {
499            assert(reg >= 0);
500            int flat_idx = reg;
501
502            if (reg == MISCREG_SPSR) {
503                CPSR cpsr = miscRegs[MISCREG_CPSR];
504                switch (cpsr.mode) {
505                  case MODE_EL0T:
506                    warn("User mode does not have SPSR\n");
507                    flat_idx = MISCREG_SPSR;
508                    break;
509                  case MODE_EL1T:
510                  case MODE_EL1H:
511                    flat_idx = MISCREG_SPSR_EL1;
512                    break;
513                  case MODE_EL2T:
514                  case MODE_EL2H:
515                    flat_idx = MISCREG_SPSR_EL2;
516                    break;
517                  case MODE_EL3T:
518                  case MODE_EL3H:
519                    flat_idx = MISCREG_SPSR_EL3;
520                    break;
521                  case MODE_USER:
522                    warn("User mode does not have SPSR\n");
523                    flat_idx = MISCREG_SPSR;
524                    break;
525                  case MODE_FIQ:
526                    flat_idx = MISCREG_SPSR_FIQ;
527                    break;
528                  case MODE_IRQ:
529                    flat_idx = MISCREG_SPSR_IRQ;
530                    break;
531                  case MODE_SVC:
532                    flat_idx = MISCREG_SPSR_SVC;
533                    break;
534                  case MODE_MON:
535                    flat_idx = MISCREG_SPSR_MON;
536                    break;
537                  case MODE_ABORT:
538                    flat_idx = MISCREG_SPSR_ABT;
539                    break;
540                  case MODE_HYP:
541                    flat_idx = MISCREG_SPSR_HYP;
542                    break;
543                  case MODE_UNDEFINED:
544                    flat_idx = MISCREG_SPSR_UND;
545                    break;
546                  default:
547                    warn("Trying to access SPSR in an invalid mode: %d\n",
548                         cpsr.mode);
549                    flat_idx = MISCREG_SPSR;
550                    break;
551                }
552            } else if (miscRegInfo[reg][MISCREG_MUTEX]) {
553                // Mutually exclusive CP15 register
554                switch (reg) {
555                  case MISCREG_PRRR_MAIR0:
556                  case MISCREG_PRRR_MAIR0_NS:
557                  case MISCREG_PRRR_MAIR0_S:
558                    {
559                        TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
560                        // If the muxed reg has been flattened, work out the
561                        // offset and apply it to the unmuxed reg
562                        int idxOffset = reg - MISCREG_PRRR_MAIR0;
563                        if (ttbcr.eae)
564                            flat_idx = flattenMiscIndex(MISCREG_MAIR0 +
565                                                        idxOffset);
566                        else
567                            flat_idx = flattenMiscIndex(MISCREG_PRRR +
568                                                        idxOffset);
569                    }
570                    break;
571                  case MISCREG_NMRR_MAIR1:
572                  case MISCREG_NMRR_MAIR1_NS:
573                  case MISCREG_NMRR_MAIR1_S:
574                    {
575                        TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
576                        // If the muxed reg has been flattened, work out the
577                        // offset and apply it to the unmuxed reg
578                        int idxOffset = reg - MISCREG_NMRR_MAIR1;
579                        if (ttbcr.eae)
580                            flat_idx = flattenMiscIndex(MISCREG_MAIR1 +
581                                                        idxOffset);
582                        else
583                            flat_idx = flattenMiscIndex(MISCREG_NMRR +
584                                                        idxOffset);
585                    }
586                    break;
587                  case MISCREG_PMXEVTYPER_PMCCFILTR:
588                    {
589                        PMSELR pmselr = miscRegs[MISCREG_PMSELR];
590                        if (pmselr.sel == 31)
591                            flat_idx = flattenMiscIndex(MISCREG_PMCCFILTR);
592                        else
593                            flat_idx = flattenMiscIndex(MISCREG_PMXEVTYPER);
594                    }
595                    break;
596                  default:
597                    panic("Unrecognized misc. register.\n");
598                    break;
599                }
600            } else {
601                if (miscRegInfo[reg][MISCREG_BANKED]) {
602                    bool secureReg = haveSecurity && !highestELIs64 &&
603                                     inSecureState(miscRegs[MISCREG_SCR],
604                                                   miscRegs[MISCREG_CPSR]);
605                    flat_idx += secureReg ? 2 : 1;
606                }
607            }
608            return flat_idx;
609        }
610
611        std::pair<int,int> getMiscIndices(int misc_reg) const
612        {
613            // Note: indexes of AArch64 registers are left unchanged
614            int flat_idx = flattenMiscIndex(misc_reg);
615
616            if (lookUpMiscReg[flat_idx].lower == 0) {
617                return std::make_pair(flat_idx, 0);
618            }
619
620            // do additional S/NS flattenings if mapped to NS while in S
621            bool S = haveSecurity && !highestELIs64 &&
622                     inSecureState(miscRegs[MISCREG_SCR],
623                                   miscRegs[MISCREG_CPSR]);
624            int lower = lookUpMiscReg[flat_idx].lower;
625            int upper = lookUpMiscReg[flat_idx].upper;
626            // upper == 0, which is CPSR, is not MISCREG_BANKED_CHILD (no-op)
627            lower += S && miscRegInfo[lower][MISCREG_BANKED_CHILD];
628            upper += S && miscRegInfo[upper][MISCREG_BANKED_CHILD];
629            return std::make_pair(lower, upper);
630        }
631
632        void serialize(CheckpointOut &cp) const
633        {
634            DPRINTF(Checkpoint, "Serializing Arm Misc Registers\n");
635            SERIALIZE_ARRAY(miscRegs, NUM_PHYS_MISCREGS);
636
637            SERIALIZE_SCALAR(highestELIs64);
638            SERIALIZE_SCALAR(haveSecurity);
639            SERIALIZE_SCALAR(haveLPAE);
640            SERIALIZE_SCALAR(haveVirtualization);
641            SERIALIZE_SCALAR(haveLargeAsid64);
642            SERIALIZE_SCALAR(physAddrRange64);
643        }
644        void unserialize(CheckpointIn &cp)
645        {
646            DPRINTF(Checkpoint, "Unserializing Arm Misc Registers\n");
647            UNSERIALIZE_ARRAY(miscRegs, NUM_PHYS_MISCREGS);
648            CPSR tmp_cpsr = miscRegs[MISCREG_CPSR];
649            updateRegMap(tmp_cpsr);
650
651            UNSERIALIZE_SCALAR(highestELIs64);
652            UNSERIALIZE_SCALAR(haveSecurity);
653            UNSERIALIZE_SCALAR(haveLPAE);
654            UNSERIALIZE_SCALAR(haveVirtualization);
655            UNSERIALIZE_SCALAR(haveLargeAsid64);
656            UNSERIALIZE_SCALAR(physAddrRange64);
657        }
658
659        void startup(ThreadContext *tc) {}
660
661        Enums::DecoderFlavour decoderFlavour() const { return _decoderFlavour; }
662
663        Enums::VecRegRenameMode
664        vecRegRenameMode() const
665        {
666            return _vecRegRenameMode;
667        }
668
669        /// Explicitly import the otherwise hidden startup
670        using SimObject::startup;
671
672        typedef ArmISAParams Params;
673
674        const Params *params() const;
675
676        ISA(Params *p);
677    };
678}
679
680template<>
681struct initRenameMode<ArmISA::ISA>
682{
683    static Enums::VecRegRenameMode mode(const ArmISA::ISA* isa)
684    {
685        return isa->vecRegRenameMode();
686    }
687    static bool equals(const ArmISA::ISA* isa1, const ArmISA::ISA* isa2)
688    {
689        return mode(isa1) == mode(isa2);
690    }
691};
692
693#endif
694