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