isa.hh revision 11771:764eae95bbbb
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        int
181        flattenIntIndex(int reg) const
182        {
183            assert(reg >= 0);
184            if (reg < NUM_ARCH_INTREGS) {
185                return intRegMap[reg];
186            } else if (reg < NUM_INTREGS) {
187                return reg;
188            } else if (reg == INTREG_SPX) {
189                CPSR cpsr = miscRegs[MISCREG_CPSR];
190                ExceptionLevel el = opModeToEL(
191                    (OperatingMode) (uint8_t) cpsr.mode);
192                if (!cpsr.sp && el != EL0)
193                    return INTREG_SP0;
194                switch (el) {
195                  case EL3:
196                    return INTREG_SP3;
197                  case EL2:
198                    return INTREG_SP2;
199                  case EL1:
200                    return INTREG_SP1;
201                  case EL0:
202                    return INTREG_SP0;
203                  default:
204                    panic("Invalid exception level");
205                    break;
206                }
207            } else {
208                return flattenIntRegModeIndex(reg);
209            }
210        }
211
212        int
213        flattenFloatIndex(int reg) const
214        {
215            assert(reg >= 0);
216            return reg;
217        }
218
219        int
220        flattenCCIndex(int reg) const
221        {
222            assert(reg >= 0);
223            return reg;
224        }
225
226        int
227        flattenMiscIndex(int reg) const
228        {
229            assert(reg >= 0);
230            int flat_idx = reg;
231
232            if (reg == MISCREG_SPSR) {
233                CPSR cpsr = miscRegs[MISCREG_CPSR];
234                switch (cpsr.mode) {
235                  case MODE_EL0T:
236                    warn("User mode does not have SPSR\n");
237                    flat_idx = MISCREG_SPSR;
238                    break;
239                  case MODE_EL1T:
240                  case MODE_EL1H:
241                    flat_idx = MISCREG_SPSR_EL1;
242                    break;
243                  case MODE_EL2T:
244                  case MODE_EL2H:
245                    flat_idx = MISCREG_SPSR_EL2;
246                    break;
247                  case MODE_EL3T:
248                  case MODE_EL3H:
249                    flat_idx = MISCREG_SPSR_EL3;
250                    break;
251                  case MODE_USER:
252                    warn("User mode does not have SPSR\n");
253                    flat_idx = MISCREG_SPSR;
254                    break;
255                  case MODE_FIQ:
256                    flat_idx = MISCREG_SPSR_FIQ;
257                    break;
258                  case MODE_IRQ:
259                    flat_idx = MISCREG_SPSR_IRQ;
260                    break;
261                  case MODE_SVC:
262                    flat_idx = MISCREG_SPSR_SVC;
263                    break;
264                  case MODE_MON:
265                    flat_idx = MISCREG_SPSR_MON;
266                    break;
267                  case MODE_ABORT:
268                    flat_idx = MISCREG_SPSR_ABT;
269                    break;
270                  case MODE_HYP:
271                    flat_idx = MISCREG_SPSR_HYP;
272                    break;
273                  case MODE_UNDEFINED:
274                    flat_idx = MISCREG_SPSR_UND;
275                    break;
276                  default:
277                    warn("Trying to access SPSR in an invalid mode: %d\n",
278                         cpsr.mode);
279                    flat_idx = MISCREG_SPSR;
280                    break;
281                }
282            } else if (miscRegInfo[reg][MISCREG_MUTEX]) {
283                // Mutually exclusive CP15 register
284                switch (reg) {
285                  case MISCREG_PRRR_MAIR0:
286                  case MISCREG_PRRR_MAIR0_NS:
287                  case MISCREG_PRRR_MAIR0_S:
288                    {
289                        TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
290                        // If the muxed reg has been flattened, work out the
291                        // offset and apply it to the unmuxed reg
292                        int idxOffset = reg - MISCREG_PRRR_MAIR0;
293                        if (ttbcr.eae)
294                            flat_idx = flattenMiscIndex(MISCREG_MAIR0 +
295                                                        idxOffset);
296                        else
297                            flat_idx = flattenMiscIndex(MISCREG_PRRR +
298                                                        idxOffset);
299                    }
300                    break;
301                  case MISCREG_NMRR_MAIR1:
302                  case MISCREG_NMRR_MAIR1_NS:
303                  case MISCREG_NMRR_MAIR1_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_NMRR_MAIR1;
309                        if (ttbcr.eae)
310                            flat_idx = flattenMiscIndex(MISCREG_MAIR1 +
311                                                        idxOffset);
312                        else
313                            flat_idx = flattenMiscIndex(MISCREG_NMRR +
314                                                        idxOffset);
315                    }
316                    break;
317                  case MISCREG_PMXEVTYPER_PMCCFILTR:
318                    {
319                        PMSELR pmselr = miscRegs[MISCREG_PMSELR];
320                        if (pmselr.sel == 31)
321                            flat_idx = flattenMiscIndex(MISCREG_PMCCFILTR);
322                        else
323                            flat_idx = flattenMiscIndex(MISCREG_PMXEVTYPER);
324                    }
325                    break;
326                  default:
327                    panic("Unrecognized misc. register.\n");
328                    break;
329                }
330            } else {
331                if (miscRegInfo[reg][MISCREG_BANKED]) {
332                    bool secureReg = haveSecurity && !highestELIs64 &&
333                                     inSecureState(miscRegs[MISCREG_SCR],
334                                                   miscRegs[MISCREG_CPSR]);
335                    flat_idx += secureReg ? 2 : 1;
336                }
337            }
338            return flat_idx;
339        }
340
341        std::pair<int,int> getMiscIndices(int misc_reg) const
342        {
343            // Note: indexes of AArch64 registers are left unchanged
344            int flat_idx = flattenMiscIndex(misc_reg);
345
346            if (lookUpMiscReg[flat_idx].lower == 0) {
347                return std::make_pair(flat_idx, 0);
348            }
349
350            // do additional S/NS flattenings if mapped to NS while in S
351            bool S = haveSecurity && !highestELIs64 &&
352                     inSecureState(miscRegs[MISCREG_SCR],
353                                   miscRegs[MISCREG_CPSR]);
354            int lower = lookUpMiscReg[flat_idx].lower;
355            int upper = lookUpMiscReg[flat_idx].upper;
356            // upper == 0, which is CPSR, is not MISCREG_BANKED_CHILD (no-op)
357            lower += S && miscRegInfo[lower][MISCREG_BANKED_CHILD];
358            upper += S && miscRegInfo[upper][MISCREG_BANKED_CHILD];
359            return std::make_pair(lower, upper);
360        }
361
362        void serialize(CheckpointOut &cp) const
363        {
364            DPRINTF(Checkpoint, "Serializing Arm Misc Registers\n");
365            SERIALIZE_ARRAY(miscRegs, NumMiscRegs);
366
367            SERIALIZE_SCALAR(highestELIs64);
368            SERIALIZE_SCALAR(haveSecurity);
369            SERIALIZE_SCALAR(haveLPAE);
370            SERIALIZE_SCALAR(haveVirtualization);
371            SERIALIZE_SCALAR(haveLargeAsid64);
372            SERIALIZE_SCALAR(physAddrRange64);
373        }
374        void unserialize(CheckpointIn &cp)
375        {
376            DPRINTF(Checkpoint, "Unserializing Arm Misc Registers\n");
377            UNSERIALIZE_ARRAY(miscRegs, NumMiscRegs);
378            CPSR tmp_cpsr = miscRegs[MISCREG_CPSR];
379            updateRegMap(tmp_cpsr);
380
381            UNSERIALIZE_SCALAR(highestELIs64);
382            UNSERIALIZE_SCALAR(haveSecurity);
383            UNSERIALIZE_SCALAR(haveLPAE);
384            UNSERIALIZE_SCALAR(haveVirtualization);
385            UNSERIALIZE_SCALAR(haveLargeAsid64);
386            UNSERIALIZE_SCALAR(physAddrRange64);
387        }
388
389        void startup(ThreadContext *tc) {}
390
391        Enums::DecoderFlavour decoderFlavour() const { return _decoderFlavour; }
392
393        /// Explicitly import the otherwise hidden startup
394        using SimObject::startup;
395
396        typedef ArmISAParams Params;
397
398        const Params *params() const;
399
400        ISA(Params *p);
401    };
402}
403
404#endif
405