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