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