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