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