isa.hh revision 12478:604310e2d7ad
1/*
2 * Copyright (c) 2010, 2012-2017 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/registers.hh"
48#include "arch/arm/system.hh"
49#include "arch/arm/tlb.hh"
50#include "arch/arm/types.hh"
51#include "arch/generic/traits.hh"
52#include "debug/Checkpoint.hh"
53#include "enums/VecRegRenameMode.hh"
54#include "sim/sim_object.hh"
55#include "enums/DecoderFlavour.hh"
56
57struct ArmISAParams;
58struct DummyArmISADeviceParams;
59class ThreadContext;
60class Checkpoint;
61class EventManager;
62
63namespace ArmISA
64{
65    class ISA : public SimObject
66    {
67      protected:
68        // Parent system
69        ArmSystem *system;
70
71        // Micro Architecture
72        const Enums::DecoderFlavour _decoderFlavour;
73        const Enums::VecRegRenameMode _vecRegRenameMode;
74
75        /** Dummy device for to handle non-existing ISA devices */
76        DummyISADevice dummyDevice;
77
78        // PMU belonging to this ISA
79        BaseISADevice *pmu;
80
81        // Generic timer interface belonging to this ISA
82        std::unique_ptr<BaseISADevice> timer;
83
84        // Cached copies of system-level properties
85        bool highestELIs64;
86        bool haveSecurity;
87        bool haveLPAE;
88        bool haveVirtualization;
89        bool haveLargeAsid64;
90        uint8_t physAddrRange64;
91
92        /** MiscReg metadata **/
93        struct MiscRegLUTEntry {
94            uint32_t lower;  // Lower half mapped to this register
95            uint32_t upper;  // Upper half mapped to this register
96            uint64_t _reset; // value taken on reset (i.e. initialization)
97            uint64_t _res0;  // reserved
98            uint64_t _res1;  // reserved
99            uint64_t _raz;   // read as zero (fixed at 0)
100            uint64_t _rao;   // read as one (fixed at 1)
101          public:
102            MiscRegLUTEntry() :
103              lower(0), upper(0),
104              _reset(0), _res0(0), _res1(0), _raz(0), _rao(0) {}
105            uint64_t reset() const { return _reset; }
106            uint64_t res0()  const { return _res0; }
107            uint64_t res1()  const { return _res1; }
108            uint64_t raz()   const { return _raz; }
109            uint64_t rao()   const { return _rao; }
110            // raz/rao implies writes ignored
111            uint64_t wi()    const { return _raz | _rao; }
112        };
113
114        /** Metadata table accessible via the value of the register */
115        std::vector<struct MiscRegLUTEntry> lookUpMiscReg;
116
117        class MiscRegLUTEntryInitializer {
118            struct MiscRegLUTEntry &entry;
119            typedef const MiscRegLUTEntryInitializer& chain;
120          public:
121            chain mapsTo(uint32_t l, uint32_t u = 0) const {
122                entry.lower = l;
123                entry.upper = u;
124                return *this;
125            }
126            chain res0(uint64_t mask) const {
127                entry._res0 = mask;
128                return *this;
129            }
130            chain res1(uint64_t mask) const {
131                entry._res1 = mask;
132                return *this;
133            }
134            chain raz(uint64_t mask) const {
135                entry._raz  = mask;
136                return *this;
137            }
138            chain rao(uint64_t mask) const {
139                entry._rao  = mask;
140                return *this;
141            }
142            MiscRegLUTEntryInitializer(struct MiscRegLUTEntry &e)
143                : entry(e)
144              {}
145        };
146
147        const MiscRegLUTEntryInitializer InitReg(uint32_t reg) {
148            return MiscRegLUTEntryInitializer(lookUpMiscReg[reg]);
149        }
150
151        void initializeMiscRegMetadata();
152
153        MiscReg miscRegs[NumMiscRegs];
154        const IntRegIndex *intRegMap;
155
156        void
157        updateRegMap(CPSR cpsr)
158        {
159            if (cpsr.width == 0) {
160                intRegMap = IntReg64Map;
161            } else {
162                switch (cpsr.mode) {
163                  case MODE_USER:
164                  case MODE_SYSTEM:
165                    intRegMap = IntRegUsrMap;
166                    break;
167                  case MODE_FIQ:
168                    intRegMap = IntRegFiqMap;
169                    break;
170                  case MODE_IRQ:
171                    intRegMap = IntRegIrqMap;
172                    break;
173                  case MODE_SVC:
174                    intRegMap = IntRegSvcMap;
175                    break;
176                  case MODE_MON:
177                    intRegMap = IntRegMonMap;
178                    break;
179                  case MODE_ABORT:
180                    intRegMap = IntRegAbtMap;
181                    break;
182                  case MODE_HYP:
183                    intRegMap = IntRegHypMap;
184                    break;
185                  case MODE_UNDEFINED:
186                    intRegMap = IntRegUndMap;
187                    break;
188                  default:
189                    panic("Unrecognized mode setting in CPSR.\n");
190                }
191            }
192        }
193
194        BaseISADevice &getGenericTimer(ThreadContext *tc);
195
196
197      private:
198        inline void assert32(ThreadContext *tc) {
199            CPSR cpsr M5_VAR_USED = readMiscReg(MISCREG_CPSR, tc);
200            assert(cpsr.width);
201        }
202
203        inline void assert64(ThreadContext *tc) {
204            CPSR cpsr M5_VAR_USED = readMiscReg(MISCREG_CPSR, tc);
205            assert(!cpsr.width);
206        }
207
208        void tlbiVA(ThreadContext *tc, MiscReg newVal, uint16_t asid,
209                    bool secure_lookup, uint8_t target_el);
210
211        void tlbiALL(ThreadContext *tc, bool secure_lookup, uint8_t target_el);
212
213        void tlbiALLN(ThreadContext *tc, bool hyp, uint8_t target_el);
214
215        void tlbiMVA(ThreadContext *tc, MiscReg newVal, bool secure_lookup,
216                     bool hyp, uint8_t target_el);
217
218      public:
219        void clear();
220        void clear64(const ArmISAParams *p);
221
222        MiscReg readMiscRegNoEffect(int misc_reg) const;
223        MiscReg readMiscReg(int misc_reg, ThreadContext *tc);
224        void setMiscRegNoEffect(int misc_reg, const MiscReg &val);
225        void setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc);
226
227        RegId
228        flattenRegId(const RegId& regId) const
229        {
230            switch (regId.classValue()) {
231              case IntRegClass:
232                return RegId(IntRegClass, flattenIntIndex(regId.index()));
233              case FloatRegClass:
234                return RegId(FloatRegClass, flattenFloatIndex(regId.index()));
235              case VecRegClass:
236                return RegId(VecRegClass, flattenVecIndex(regId.index()));
237              case VecElemClass:
238                return RegId(VecElemClass, flattenVecElemIndex(regId.index()));
239              case CCRegClass:
240                return RegId(CCRegClass, flattenCCIndex(regId.index()));
241              case MiscRegClass:
242                return RegId(MiscRegClass, flattenMiscIndex(regId.index()));
243            }
244            return RegId();
245        }
246
247        int
248        flattenIntIndex(int reg) const
249        {
250            assert(reg >= 0);
251            if (reg < NUM_ARCH_INTREGS) {
252                return intRegMap[reg];
253            } else if (reg < NUM_INTREGS) {
254                return reg;
255            } else if (reg == INTREG_SPX) {
256                CPSR cpsr = miscRegs[MISCREG_CPSR];
257                ExceptionLevel el = opModeToEL(
258                    (OperatingMode) (uint8_t) cpsr.mode);
259                if (!cpsr.sp && el != EL0)
260                    return INTREG_SP0;
261                switch (el) {
262                  case EL3:
263                    return INTREG_SP3;
264                  case EL2:
265                    return INTREG_SP2;
266                  case EL1:
267                    return INTREG_SP1;
268                  case EL0:
269                    return INTREG_SP0;
270                  default:
271                    panic("Invalid exception level");
272                    break;
273                }
274            } else {
275                return flattenIntRegModeIndex(reg);
276            }
277        }
278
279        int
280        flattenFloatIndex(int reg) const
281        {
282            assert(reg >= 0);
283            return reg;
284        }
285
286        int
287        flattenVecIndex(int reg) const
288        {
289            assert(reg >= 0);
290            return reg;
291        }
292
293        int
294        flattenVecElemIndex(int reg) const
295        {
296            assert(reg >= 0);
297            return reg;
298        }
299
300        int
301        flattenCCIndex(int reg) const
302        {
303            assert(reg >= 0);
304            return reg;
305        }
306
307        int
308        flattenMiscIndex(int reg) const
309        {
310            assert(reg >= 0);
311            int flat_idx = reg;
312
313            if (reg == MISCREG_SPSR) {
314                CPSR cpsr = miscRegs[MISCREG_CPSR];
315                switch (cpsr.mode) {
316                  case MODE_EL0T:
317                    warn("User mode does not have SPSR\n");
318                    flat_idx = MISCREG_SPSR;
319                    break;
320                  case MODE_EL1T:
321                  case MODE_EL1H:
322                    flat_idx = MISCREG_SPSR_EL1;
323                    break;
324                  case MODE_EL2T:
325                  case MODE_EL2H:
326                    flat_idx = MISCREG_SPSR_EL2;
327                    break;
328                  case MODE_EL3T:
329                  case MODE_EL3H:
330                    flat_idx = MISCREG_SPSR_EL3;
331                    break;
332                  case MODE_USER:
333                    warn("User mode does not have SPSR\n");
334                    flat_idx = MISCREG_SPSR;
335                    break;
336                  case MODE_FIQ:
337                    flat_idx = MISCREG_SPSR_FIQ;
338                    break;
339                  case MODE_IRQ:
340                    flat_idx = MISCREG_SPSR_IRQ;
341                    break;
342                  case MODE_SVC:
343                    flat_idx = MISCREG_SPSR_SVC;
344                    break;
345                  case MODE_MON:
346                    flat_idx = MISCREG_SPSR_MON;
347                    break;
348                  case MODE_ABORT:
349                    flat_idx = MISCREG_SPSR_ABT;
350                    break;
351                  case MODE_HYP:
352                    flat_idx = MISCREG_SPSR_HYP;
353                    break;
354                  case MODE_UNDEFINED:
355                    flat_idx = MISCREG_SPSR_UND;
356                    break;
357                  default:
358                    warn("Trying to access SPSR in an invalid mode: %d\n",
359                         cpsr.mode);
360                    flat_idx = MISCREG_SPSR;
361                    break;
362                }
363            } else if (miscRegInfo[reg][MISCREG_MUTEX]) {
364                // Mutually exclusive CP15 register
365                switch (reg) {
366                  case MISCREG_PRRR_MAIR0:
367                  case MISCREG_PRRR_MAIR0_NS:
368                  case MISCREG_PRRR_MAIR0_S:
369                    {
370                        TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
371                        // If the muxed reg has been flattened, work out the
372                        // offset and apply it to the unmuxed reg
373                        int idxOffset = reg - MISCREG_PRRR_MAIR0;
374                        if (ttbcr.eae)
375                            flat_idx = flattenMiscIndex(MISCREG_MAIR0 +
376                                                        idxOffset);
377                        else
378                            flat_idx = flattenMiscIndex(MISCREG_PRRR +
379                                                        idxOffset);
380                    }
381                    break;
382                  case MISCREG_NMRR_MAIR1:
383                  case MISCREG_NMRR_MAIR1_NS:
384                  case MISCREG_NMRR_MAIR1_S:
385                    {
386                        TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
387                        // If the muxed reg has been flattened, work out the
388                        // offset and apply it to the unmuxed reg
389                        int idxOffset = reg - MISCREG_NMRR_MAIR1;
390                        if (ttbcr.eae)
391                            flat_idx = flattenMiscIndex(MISCREG_MAIR1 +
392                                                        idxOffset);
393                        else
394                            flat_idx = flattenMiscIndex(MISCREG_NMRR +
395                                                        idxOffset);
396                    }
397                    break;
398                  case MISCREG_PMXEVTYPER_PMCCFILTR:
399                    {
400                        PMSELR pmselr = miscRegs[MISCREG_PMSELR];
401                        if (pmselr.sel == 31)
402                            flat_idx = flattenMiscIndex(MISCREG_PMCCFILTR);
403                        else
404                            flat_idx = flattenMiscIndex(MISCREG_PMXEVTYPER);
405                    }
406                    break;
407                  default:
408                    panic("Unrecognized misc. register.\n");
409                    break;
410                }
411            } else {
412                if (miscRegInfo[reg][MISCREG_BANKED]) {
413                    bool secureReg = haveSecurity && !highestELIs64 &&
414                                     inSecureState(miscRegs[MISCREG_SCR],
415                                                   miscRegs[MISCREG_CPSR]);
416                    flat_idx += secureReg ? 2 : 1;
417                }
418            }
419            return flat_idx;
420        }
421
422        std::pair<int,int> getMiscIndices(int misc_reg) const
423        {
424            // Note: indexes of AArch64 registers are left unchanged
425            int flat_idx = flattenMiscIndex(misc_reg);
426
427            if (lookUpMiscReg[flat_idx].lower == 0) {
428                return std::make_pair(flat_idx, 0);
429            }
430
431            // do additional S/NS flattenings if mapped to NS while in S
432            bool S = haveSecurity && !highestELIs64 &&
433                     inSecureState(miscRegs[MISCREG_SCR],
434                                   miscRegs[MISCREG_CPSR]);
435            int lower = lookUpMiscReg[flat_idx].lower;
436            int upper = lookUpMiscReg[flat_idx].upper;
437            // upper == 0, which is CPSR, is not MISCREG_BANKED_CHILD (no-op)
438            lower += S && miscRegInfo[lower][MISCREG_BANKED_CHILD];
439            upper += S && miscRegInfo[upper][MISCREG_BANKED_CHILD];
440            return std::make_pair(lower, upper);
441        }
442
443        void serialize(CheckpointOut &cp) const
444        {
445            DPRINTF(Checkpoint, "Serializing Arm Misc Registers\n");
446            SERIALIZE_ARRAY(miscRegs, NumMiscRegs);
447
448            SERIALIZE_SCALAR(highestELIs64);
449            SERIALIZE_SCALAR(haveSecurity);
450            SERIALIZE_SCALAR(haveLPAE);
451            SERIALIZE_SCALAR(haveVirtualization);
452            SERIALIZE_SCALAR(haveLargeAsid64);
453            SERIALIZE_SCALAR(physAddrRange64);
454        }
455        void unserialize(CheckpointIn &cp)
456        {
457            DPRINTF(Checkpoint, "Unserializing Arm Misc Registers\n");
458            UNSERIALIZE_ARRAY(miscRegs, NumMiscRegs);
459            CPSR tmp_cpsr = miscRegs[MISCREG_CPSR];
460            updateRegMap(tmp_cpsr);
461
462            UNSERIALIZE_SCALAR(highestELIs64);
463            UNSERIALIZE_SCALAR(haveSecurity);
464            UNSERIALIZE_SCALAR(haveLPAE);
465            UNSERIALIZE_SCALAR(haveVirtualization);
466            UNSERIALIZE_SCALAR(haveLargeAsid64);
467            UNSERIALIZE_SCALAR(physAddrRange64);
468        }
469
470        void startup(ThreadContext *tc) {}
471
472        Enums::DecoderFlavour decoderFlavour() const { return _decoderFlavour; }
473
474        Enums::VecRegRenameMode
475        vecRegRenameMode() const
476        {
477            return _vecRegRenameMode;
478        }
479
480        /// Explicitly import the otherwise hidden startup
481        using SimObject::startup;
482
483        typedef ArmISAParams Params;
484
485        const Params *params() const;
486
487        ISA(Params *p);
488    };
489}
490
491template<>
492struct initRenameMode<ArmISA::ISA>
493{
494    static Enums::VecRegRenameMode mode(const ArmISA::ISA* isa)
495    {
496        return isa->vecRegRenameMode();
497    }
498    static bool equals(const ArmISA::ISA* isa1, const ArmISA::ISA* isa2)
499    {
500        return mode(isa1) == mode(isa2);
501    }
502};
503
504#endif
505