isa.hh revision 11165
1/*
2 * Copyright (c) 2010, 2012-2015 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                  // @todo: uncomment this to enable Virtualization
265                  // case EL2:
266                  //   return INTREG_SP2;
267                  case EL1:
268                    return INTREG_SP1;
269                  case EL0:
270                    return INTREG_SP0;
271                  default:
272                    panic("Invalid exception level");
273                    break;
274                }
275            } else {
276                return flattenIntRegModeIndex(reg);
277            }
278        }
279
280        int
281        flattenFloatIndex(int reg) const
282        {
283            assert(reg >= 0);
284            return reg;
285        }
286
287        int
288        flattenCCIndex(int reg) const
289        {
290            assert(reg >= 0);
291            return reg;
292        }
293
294        int
295        flattenMiscIndex(int reg) const
296        {
297            assert(reg >= 0);
298            int flat_idx = reg;
299
300            if (reg == MISCREG_SPSR) {
301                CPSR cpsr = miscRegs[MISCREG_CPSR];
302                switch (cpsr.mode) {
303                  case MODE_EL0T:
304                    warn("User mode does not have SPSR\n");
305                    flat_idx = MISCREG_SPSR;
306                    break;
307                  case MODE_EL1T:
308                  case MODE_EL1H:
309                    flat_idx = MISCREG_SPSR_EL1;
310                    break;
311                  case MODE_EL2T:
312                  case MODE_EL2H:
313                    flat_idx = MISCREG_SPSR_EL2;
314                    break;
315                  case MODE_EL3T:
316                  case MODE_EL3H:
317                    flat_idx = MISCREG_SPSR_EL3;
318                    break;
319                  case MODE_USER:
320                    warn("User mode does not have SPSR\n");
321                    flat_idx = MISCREG_SPSR;
322                    break;
323                  case MODE_FIQ:
324                    flat_idx = MISCREG_SPSR_FIQ;
325                    break;
326                  case MODE_IRQ:
327                    flat_idx = MISCREG_SPSR_IRQ;
328                    break;
329                  case MODE_SVC:
330                    flat_idx = MISCREG_SPSR_SVC;
331                    break;
332                  case MODE_MON:
333                    flat_idx = MISCREG_SPSR_MON;
334                    break;
335                  case MODE_ABORT:
336                    flat_idx = MISCREG_SPSR_ABT;
337                    break;
338                  case MODE_HYP:
339                    flat_idx = MISCREG_SPSR_HYP;
340                    break;
341                  case MODE_UNDEFINED:
342                    flat_idx = MISCREG_SPSR_UND;
343                    break;
344                  default:
345                    warn("Trying to access SPSR in an invalid mode: %d\n",
346                         cpsr.mode);
347                    flat_idx = MISCREG_SPSR;
348                    break;
349                }
350            } else if (miscRegInfo[reg][MISCREG_MUTEX]) {
351                // Mutually exclusive CP15 register
352                switch (reg) {
353                  case MISCREG_PRRR_MAIR0:
354                  case MISCREG_PRRR_MAIR0_NS:
355                  case MISCREG_PRRR_MAIR0_S:
356                    {
357                        TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
358                        // If the muxed reg has been flattened, work out the
359                        // offset and apply it to the unmuxed reg
360                        int idxOffset = reg - MISCREG_PRRR_MAIR0;
361                        if (ttbcr.eae)
362                            flat_idx = flattenMiscIndex(MISCREG_MAIR0 +
363                                                        idxOffset);
364                        else
365                            flat_idx = flattenMiscIndex(MISCREG_PRRR +
366                                                        idxOffset);
367                    }
368                    break;
369                  case MISCREG_NMRR_MAIR1:
370                  case MISCREG_NMRR_MAIR1_NS:
371                  case MISCREG_NMRR_MAIR1_S:
372                    {
373                        TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
374                        // If the muxed reg has been flattened, work out the
375                        // offset and apply it to the unmuxed reg
376                        int idxOffset = reg - MISCREG_NMRR_MAIR1;
377                        if (ttbcr.eae)
378                            flat_idx = flattenMiscIndex(MISCREG_MAIR1 +
379                                                        idxOffset);
380                        else
381                            flat_idx = flattenMiscIndex(MISCREG_NMRR +
382                                                        idxOffset);
383                    }
384                    break;
385                  case MISCREG_PMXEVTYPER_PMCCFILTR:
386                    {
387                        PMSELR pmselr = miscRegs[MISCREG_PMSELR];
388                        if (pmselr.sel == 31)
389                            flat_idx = flattenMiscIndex(MISCREG_PMCCFILTR);
390                        else
391                            flat_idx = flattenMiscIndex(MISCREG_PMXEVTYPER);
392                    }
393                    break;
394                  default:
395                    panic("Unrecognized misc. register.\n");
396                    break;
397                }
398            } else {
399                if (miscRegInfo[reg][MISCREG_BANKED]) {
400                    bool secureReg = haveSecurity &&
401                                     inSecureState(miscRegs[MISCREG_SCR],
402                                                   miscRegs[MISCREG_CPSR]);
403                    flat_idx += secureReg ? 2 : 1;
404                }
405            }
406            return flat_idx;
407        }
408
409        void serialize(CheckpointOut &cp) const
410        {
411            DPRINTF(Checkpoint, "Serializing Arm Misc Registers\n");
412            SERIALIZE_ARRAY(miscRegs, NumMiscRegs);
413
414            SERIALIZE_SCALAR(haveSecurity);
415            SERIALIZE_SCALAR(haveLPAE);
416            SERIALIZE_SCALAR(haveVirtualization);
417            SERIALIZE_SCALAR(haveLargeAsid64);
418            SERIALIZE_SCALAR(physAddrRange64);
419        }
420        void unserialize(CheckpointIn &cp)
421        {
422            DPRINTF(Checkpoint, "Unserializing Arm Misc Registers\n");
423            UNSERIALIZE_ARRAY(miscRegs, NumMiscRegs);
424            CPSR tmp_cpsr = miscRegs[MISCREG_CPSR];
425            updateRegMap(tmp_cpsr);
426
427            UNSERIALIZE_SCALAR(haveSecurity);
428            UNSERIALIZE_SCALAR(haveLPAE);
429            UNSERIALIZE_SCALAR(haveVirtualization);
430            UNSERIALIZE_SCALAR(haveLargeAsid64);
431            UNSERIALIZE_SCALAR(physAddrRange64);
432        }
433
434        void startup(ThreadContext *tc) {}
435
436        Enums::DecoderFlavour decoderFlavour() const { return _decoderFlavour; }
437
438        /// Explicitly import the otherwise hidden startup
439        using SimObject::startup;
440
441        typedef ArmISAParams Params;
442
443        const Params *params() const;
444
445        ISA(Params *p);
446    };
447}
448
449#endif
450