isa.hh revision 10709
1/*
2 * Copyright (c) 2010, 2012-2014 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 "dev/arm/generic_timer.hh"
53#include "sim/sim_object.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        /** Dummy device for to handle non-existing ISA devices */
137        DummyISADevice dummyDevice;
138
139        // PMU belonging to this ISA
140        BaseISADevice *pmu;
141
142        // Cached copies of system-level properties
143        bool haveSecurity;
144        bool haveLPAE;
145        bool haveVirtualization;
146        bool haveLargeAsid64;
147        uint8_t physAddrRange64;
148
149        /** Register translation entry used in lookUpMiscReg */
150        struct MiscRegLUTEntry {
151            uint32_t lower;
152            uint32_t upper;
153        };
154
155        struct MiscRegInitializerEntry {
156            uint32_t index;
157            struct MiscRegLUTEntry entry;
158        };
159
160        /** Register table noting all translations */
161        static const struct MiscRegInitializerEntry
162                            MiscRegSwitch[miscRegTranslateMax];
163
164        /** Translation table accessible via the value of the register */
165        std::vector<struct MiscRegLUTEntry> lookUpMiscReg;
166
167        MiscReg miscRegs[NumMiscRegs];
168        const IntRegIndex *intRegMap;
169
170        void
171        updateRegMap(CPSR cpsr)
172        {
173            if (cpsr.width == 0) {
174                intRegMap = IntReg64Map;
175            } else {
176                switch (cpsr.mode) {
177                  case MODE_USER:
178                  case MODE_SYSTEM:
179                    intRegMap = IntRegUsrMap;
180                    break;
181                  case MODE_FIQ:
182                    intRegMap = IntRegFiqMap;
183                    break;
184                  case MODE_IRQ:
185                    intRegMap = IntRegIrqMap;
186                    break;
187                  case MODE_SVC:
188                    intRegMap = IntRegSvcMap;
189                    break;
190                  case MODE_MON:
191                    intRegMap = IntRegMonMap;
192                    break;
193                  case MODE_ABORT:
194                    intRegMap = IntRegAbtMap;
195                    break;
196                  case MODE_HYP:
197                    intRegMap = IntRegHypMap;
198                    break;
199                  case MODE_UNDEFINED:
200                    intRegMap = IntRegUndMap;
201                    break;
202                  default:
203                    panic("Unrecognized mode setting in CPSR.\n");
204                }
205            }
206        }
207
208        ::GenericTimer::SystemCounter * getSystemCounter(ThreadContext *tc);
209        ::GenericTimer::ArchTimer * getArchTimer(ThreadContext *tc,
210                                                 int cpu_id);
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        /** Check if all CPUs have their caches enabled and if they do
433         * disable the bootAddrUncacheability flag because it's no longer
434         * needed.
435         * @s_idx the register number of the SCTLR that we are checking
436         * @tc Threadcontext to use to get access to the system and other cpus
437         */
438        void updateBootUncacheable(int sctlr_idx, ThreadContext *tc);
439
440        /// Explicitly import the otherwise hidden startup
441        using SimObject::startup;
442
443        typedef ArmISAParams Params;
444
445        const Params *params() const;
446
447        ISA(Params *p);
448    };
449}
450
451#endif
452