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