isa.hh revision 10037
110338SCurtis.Dunham@arm.com/*
210338SCurtis.Dunham@arm.com * Copyright (c) 2010, 2012-2013 ARM Limited
310338SCurtis.Dunham@arm.com * All rights reserved
410338SCurtis.Dunham@arm.com *
510338SCurtis.Dunham@arm.com * The license below extends only to copyright in the software and shall
610338SCurtis.Dunham@arm.com * not be construed as granting a license to any other intellectual
710338SCurtis.Dunham@arm.com * property including but not limited to intellectual property relating
810338SCurtis.Dunham@arm.com * to a hardware implementation of the functionality of the software
910338SCurtis.Dunham@arm.com * licensed hereunder.  You may use the software subject to the license
1010338SCurtis.Dunham@arm.com * terms below provided that you ensure that this notice is replicated
1110338SCurtis.Dunham@arm.com * unmodified and in its entirety in all distributions of the software,
1210338SCurtis.Dunham@arm.com * modified or unmodified, in source code or in binary form.
1310338SCurtis.Dunham@arm.com *
1410338SCurtis.Dunham@arm.com * Copyright (c) 2009 The Regents of The University of Michigan
1510338SCurtis.Dunham@arm.com * All rights reserved.
1610338SCurtis.Dunham@arm.com *
1710338SCurtis.Dunham@arm.com * Redistribution and use in source and binary forms, with or without
1810338SCurtis.Dunham@arm.com * modification, are permitted provided that the following conditions are
1910338SCurtis.Dunham@arm.com * met: redistributions of source code must retain the above copyright
2010338SCurtis.Dunham@arm.com * notice, this list of conditions and the following disclaimer;
2110338SCurtis.Dunham@arm.com * redistributions in binary form must reproduce the above copyright
2210338SCurtis.Dunham@arm.com * notice, this list of conditions and the following disclaimer in the
2310338SCurtis.Dunham@arm.com * documentation and/or other materials provided with the distribution;
2410338SCurtis.Dunham@arm.com * neither the name of the copyright holders nor the names of its
2510338SCurtis.Dunham@arm.com * contributors may be used to endorse or promote products derived from
2610338SCurtis.Dunham@arm.com * this software without specific prior written permission.
2710338SCurtis.Dunham@arm.com *
2810338SCurtis.Dunham@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2910338SCurtis.Dunham@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3010338SCurtis.Dunham@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3110338SCurtis.Dunham@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3210338SCurtis.Dunham@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3310338SCurtis.Dunham@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3410338SCurtis.Dunham@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3510338SCurtis.Dunham@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3610338SCurtis.Dunham@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3710338SCurtis.Dunham@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3810338SCurtis.Dunham@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3910338SCurtis.Dunham@arm.com *
4010338SCurtis.Dunham@arm.com * Authors: Gabe Black
4110338SCurtis.Dunham@arm.com */
4210338SCurtis.Dunham@arm.com
4310338SCurtis.Dunham@arm.com#ifndef __ARCH_ARM_ISA_HH__
4410338SCurtis.Dunham@arm.com#define __ARCH_ARM_ISA_HH__
4510338SCurtis.Dunham@arm.com
4610338SCurtis.Dunham@arm.com#include "arch/arm/registers.hh"
4710338SCurtis.Dunham@arm.com#include "arch/arm/system.hh"
4810338SCurtis.Dunham@arm.com#include "arch/arm/tlb.hh"
4910338SCurtis.Dunham@arm.com#include "arch/arm/types.hh"
5010338SCurtis.Dunham@arm.com#include "debug/Checkpoint.hh"
5110338SCurtis.Dunham@arm.com#include "dev/arm/generic_timer.hh"
5210338SCurtis.Dunham@arm.com#include "sim/sim_object.hh"
5310338SCurtis.Dunham@arm.com
5410338SCurtis.Dunham@arm.comstruct ArmISAParams;
5510338SCurtis.Dunham@arm.comclass ThreadContext;
5610338SCurtis.Dunham@arm.comclass Checkpoint;
5710338SCurtis.Dunham@arm.comclass EventManager;
5810338SCurtis.Dunham@arm.com
5910338SCurtis.Dunham@arm.comnamespace ArmISA
6010338SCurtis.Dunham@arm.com{
6110338SCurtis.Dunham@arm.com
6210338SCurtis.Dunham@arm.com    /**
6310338SCurtis.Dunham@arm.com     * At the moment there are 57 registers which need to be aliased/
6410338SCurtis.Dunham@arm.com     * translated with other registers in the ISA. This enum helps with that
6510338SCurtis.Dunham@arm.com     * translation.
6610338SCurtis.Dunham@arm.com     */
6710338SCurtis.Dunham@arm.com    enum translateTable {
6810338SCurtis.Dunham@arm.com        miscRegTranslateCSSELR_EL1,
6910338SCurtis.Dunham@arm.com        miscRegTranslateSCTLR_EL1,
7010338SCurtis.Dunham@arm.com        miscRegTranslateSCTLR_EL2,
7110338SCurtis.Dunham@arm.com        miscRegTranslateACTLR_EL1,
7210338SCurtis.Dunham@arm.com        miscRegTranslateACTLR_EL2,
7310338SCurtis.Dunham@arm.com        miscRegTranslateCPACR_EL1,
7410338SCurtis.Dunham@arm.com        miscRegTranslateCPTR_EL2,
7510338SCurtis.Dunham@arm.com        miscRegTranslateHCR_EL2,
7610338SCurtis.Dunham@arm.com        miscRegTranslateMDCR_EL2,
7710338SCurtis.Dunham@arm.com        miscRegTranslateHSTR_EL2,
7810338SCurtis.Dunham@arm.com        miscRegTranslateHACR_EL2,
7910338SCurtis.Dunham@arm.com        miscRegTranslateTTBR0_EL1,
8010338SCurtis.Dunham@arm.com        miscRegTranslateTTBR1_EL1,
8110338SCurtis.Dunham@arm.com        miscRegTranslateTTBR0_EL2,
8210338SCurtis.Dunham@arm.com        miscRegTranslateVTTBR_EL2,
8310338SCurtis.Dunham@arm.com        miscRegTranslateTCR_EL1,
8410338SCurtis.Dunham@arm.com        miscRegTranslateTCR_EL2,
8510338SCurtis.Dunham@arm.com        miscRegTranslateVTCR_EL2,
86        miscRegTranslateAFSR0_EL1,
87        miscRegTranslateAFSR1_EL1,
88        miscRegTranslateAFSR0_EL2,
89        miscRegTranslateAFSR1_EL2,
90        miscRegTranslateESR_EL2,
91        miscRegTranslateFAR_EL1,
92        miscRegTranslateFAR_EL2,
93        miscRegTranslateHPFAR_EL2,
94        miscRegTranslatePAR_EL1,
95        miscRegTranslateMAIR_EL1,
96        miscRegTranslateMAIR_EL2,
97        miscRegTranslateAMAIR_EL1,
98        miscRegTranslateVBAR_EL1,
99        miscRegTranslateVBAR_EL2,
100        miscRegTranslateCONTEXTIDR_EL1,
101        miscRegTranslateTPIDR_EL0,
102        miscRegTranslateTPIDRRO_EL0,
103        miscRegTranslateTPIDR_EL1,
104        miscRegTranslateTPIDR_EL2,
105        miscRegTranslateTEECR32_EL1,
106        miscRegTranslateCNTFRQ_EL0,
107        miscRegTranslateCNTPCT_EL0,
108        miscRegTranslateCNTVCT_EL0,
109        miscRegTranslateCNTVOFF_EL2,
110        miscRegTranslateCNTKCTL_EL1,
111        miscRegTranslateCNTHCTL_EL2,
112        miscRegTranslateCNTP_TVAL_EL0,
113        miscRegTranslateCNTP_CTL_EL0,
114        miscRegTranslateCNTP_CVAL_EL0,
115        miscRegTranslateCNTV_TVAL_EL0,
116        miscRegTranslateCNTV_CTL_EL0,
117        miscRegTranslateCNTV_CVAL_EL0,
118        miscRegTranslateCNTHP_TVAL_EL2,
119        miscRegTranslateCNTHP_CTL_EL2,
120        miscRegTranslateCNTHP_CVAL_EL2,
121        miscRegTranslateDACR32_EL2,
122        miscRegTranslateIFSR32_EL2,
123        miscRegTranslateTEEHBR32_EL1,
124        miscRegTranslateSDER32_EL3,
125        miscRegTranslateMax
126    };
127
128    class ISA : public SimObject
129    {
130      protected:
131        // Parent system
132        ArmSystem *system;
133
134        // Cached copies of system-level properties
135        bool haveSecurity;
136        bool haveLPAE;
137        bool haveVirtualization;
138        bool haveLargeAsid64;
139        uint8_t physAddrRange64;
140
141        /** Register translation entry used in lookUpMiscReg */
142        struct MiscRegLUTEntry {
143            uint32_t lower;
144            uint32_t upper;
145        };
146
147        struct MiscRegInitializerEntry {
148            uint32_t index;
149            struct MiscRegLUTEntry entry;
150        };
151
152        /** Register table noting all translations */
153        static const struct MiscRegInitializerEntry
154                            MiscRegSwitch[miscRegTranslateMax];
155
156        /** Translation table accessible via the value of the register */
157        std::vector<struct MiscRegLUTEntry> lookUpMiscReg;
158
159        MiscReg miscRegs[NumMiscRegs];
160        const IntRegIndex *intRegMap;
161
162        void
163        updateRegMap(CPSR cpsr)
164        {
165            if (cpsr.width == 0) {
166                intRegMap = IntReg64Map;
167            } else {
168                switch (cpsr.mode) {
169                  case MODE_USER:
170                  case MODE_SYSTEM:
171                    intRegMap = IntRegUsrMap;
172                    break;
173                  case MODE_FIQ:
174                    intRegMap = IntRegFiqMap;
175                    break;
176                  case MODE_IRQ:
177                    intRegMap = IntRegIrqMap;
178                    break;
179                  case MODE_SVC:
180                    intRegMap = IntRegSvcMap;
181                    break;
182                  case MODE_MON:
183                    intRegMap = IntRegMonMap;
184                    break;
185                  case MODE_ABORT:
186                    intRegMap = IntRegAbtMap;
187                    break;
188                  case MODE_HYP:
189                    intRegMap = IntRegHypMap;
190                    break;
191                  case MODE_UNDEFINED:
192                    intRegMap = IntRegUndMap;
193                    break;
194                  default:
195                    panic("Unrecognized mode setting in CPSR.\n");
196                }
197            }
198        }
199
200        ::GenericTimer::SystemCounter * getSystemCounter(ThreadContext *tc);
201        ::GenericTimer::ArchTimer * getArchTimer(ThreadContext *tc,
202                                                 int cpu_id);
203
204
205      private:
206        inline void assert32(ThreadContext *tc) {
207            CPSR cpsr M5_VAR_USED = readMiscReg(MISCREG_CPSR, tc);
208            assert(cpsr.width);
209        }
210
211        inline void assert64(ThreadContext *tc) {
212            CPSR cpsr M5_VAR_USED = readMiscReg(MISCREG_CPSR, tc);
213            assert(!cpsr.width);
214        }
215
216        void tlbiVA(ThreadContext *tc, MiscReg newVal, uint8_t asid,
217                    bool secure_lookup, uint8_t target_el);
218
219        void tlbiALL(ThreadContext *tc, bool secure_lookup, uint8_t target_el);
220
221        void tlbiALLN(ThreadContext *tc, bool hyp, uint8_t target_el);
222
223        void tlbiMVA(ThreadContext *tc, MiscReg newVal, bool secure_lookup,
224                     bool hyp, uint8_t target_el);
225
226      public:
227        void clear();
228        void clear64(const ArmISAParams *p);
229
230        MiscReg readMiscRegNoEffect(int misc_reg) const;
231        MiscReg readMiscReg(int misc_reg, ThreadContext *tc);
232        void setMiscRegNoEffect(int misc_reg, const MiscReg &val);
233        void setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc);
234
235        int
236        flattenIntIndex(int reg) const
237        {
238            assert(reg >= 0);
239            if (reg < NUM_ARCH_INTREGS) {
240                return intRegMap[reg];
241            } else if (reg < NUM_INTREGS) {
242                return reg;
243            } else if (reg == INTREG_SPX) {
244                CPSR cpsr = miscRegs[MISCREG_CPSR];
245                ExceptionLevel el = opModeToEL(
246                    (OperatingMode) (uint8_t) cpsr.mode);
247                if (!cpsr.sp && el != EL0)
248                    return INTREG_SP0;
249                switch (el) {
250                  case EL3:
251                    return INTREG_SP3;
252                  // @todo: uncomment this to enable Virtualization
253                  // case EL2:
254                  //   return INTREG_SP2;
255                  case EL1:
256                    return INTREG_SP1;
257                  case EL0:
258                    return INTREG_SP0;
259                  default:
260                    panic("Invalid exception level");
261                    break;
262                }
263            } else {
264                return flattenIntRegModeIndex(reg);
265            }
266        }
267
268        int
269        flattenFloatIndex(int reg) const
270        {
271            return reg;
272        }
273
274        // dummy
275        int
276        flattenCCIndex(int reg) const
277        {
278            return reg;
279        }
280
281        int
282        flattenMiscIndex(int reg) const
283        {
284            int flat_idx = reg;
285
286            if (reg == MISCREG_SPSR) {
287                CPSR cpsr = miscRegs[MISCREG_CPSR];
288                switch (cpsr.mode) {
289                  case MODE_EL0T:
290                    warn("User mode does not have SPSR\n");
291                    flat_idx = MISCREG_SPSR;
292                    break;
293                  case MODE_EL1T:
294                  case MODE_EL1H:
295                    flat_idx = MISCREG_SPSR_EL1;
296                    break;
297                  case MODE_EL2T:
298                  case MODE_EL2H:
299                    flat_idx = MISCREG_SPSR_EL2;
300                    break;
301                  case MODE_EL3T:
302                  case MODE_EL3H:
303                    flat_idx = MISCREG_SPSR_EL3;
304                    break;
305                  case MODE_USER:
306                    warn("User mode does not have SPSR\n");
307                    flat_idx = MISCREG_SPSR;
308                    break;
309                  case MODE_FIQ:
310                    flat_idx = MISCREG_SPSR_FIQ;
311                    break;
312                  case MODE_IRQ:
313                    flat_idx = MISCREG_SPSR_IRQ;
314                    break;
315                  case MODE_SVC:
316                    flat_idx = MISCREG_SPSR_SVC;
317                    break;
318                  case MODE_MON:
319                    flat_idx = MISCREG_SPSR_MON;
320                    break;
321                  case MODE_ABORT:
322                    flat_idx = MISCREG_SPSR_ABT;
323                    break;
324                  case MODE_HYP:
325                    flat_idx = MISCREG_SPSR_HYP;
326                    break;
327                  case MODE_UNDEFINED:
328                    flat_idx = MISCREG_SPSR_UND;
329                    break;
330                  default:
331                    warn("Trying to access SPSR in an invalid mode: %d\n",
332                         cpsr.mode);
333                    flat_idx = MISCREG_SPSR;
334                    break;
335                }
336            } else if (miscRegInfo[reg][MISCREG_MUTEX]) {
337                // Mutually exclusive CP15 register
338                switch (reg) {
339                  case MISCREG_PRRR_MAIR0:
340                  case MISCREG_PRRR_MAIR0_NS:
341                  case MISCREG_PRRR_MAIR0_S:
342                    {
343                        TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
344                        // If the muxed reg has been flattened, work out the
345                        // offset and apply it to the unmuxed reg
346                        int idxOffset = reg - MISCREG_PRRR_MAIR0;
347                        if (ttbcr.eae)
348                            flat_idx = flattenMiscIndex(MISCREG_MAIR0 +
349                                                        idxOffset);
350                        else
351                            flat_idx = flattenMiscIndex(MISCREG_PRRR +
352                                                        idxOffset);
353                    }
354                    break;
355                  case MISCREG_NMRR_MAIR1:
356                  case MISCREG_NMRR_MAIR1_NS:
357                  case MISCREG_NMRR_MAIR1_S:
358                    {
359                        TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
360                        // If the muxed reg has been flattened, work out the
361                        // offset and apply it to the unmuxed reg
362                        int idxOffset = reg - MISCREG_NMRR_MAIR1;
363                        if (ttbcr.eae)
364                            flat_idx = flattenMiscIndex(MISCREG_MAIR1 +
365                                                        idxOffset);
366                        else
367                            flat_idx = flattenMiscIndex(MISCREG_NMRR +
368                                                        idxOffset);
369                    }
370                    break;
371                  case MISCREG_PMXEVTYPER_PMCCFILTR:
372                    {
373                        PMSELR pmselr = miscRegs[MISCREG_PMSELR];
374                        if (pmselr.sel == 31)
375                            flat_idx = flattenMiscIndex(MISCREG_PMCCFILTR);
376                        else
377                            flat_idx = flattenMiscIndex(MISCREG_PMXEVTYPER);
378                    }
379                    break;
380                  default:
381                    panic("Unrecognized misc. register.\n");
382                    break;
383                }
384            } else {
385                if (miscRegInfo[reg][MISCREG_BANKED]) {
386                    bool secureReg = haveSecurity &&
387                                     inSecureState(miscRegs[MISCREG_SCR],
388                                                   miscRegs[MISCREG_CPSR]);
389                    flat_idx += secureReg ? 2 : 1;
390                }
391            }
392            return flat_idx;
393        }
394
395        void serialize(std::ostream &os)
396        {
397            DPRINTF(Checkpoint, "Serializing Arm Misc Registers\n");
398            SERIALIZE_ARRAY(miscRegs, NumMiscRegs);
399
400            SERIALIZE_SCALAR(haveSecurity);
401            SERIALIZE_SCALAR(haveLPAE);
402            SERIALIZE_SCALAR(haveVirtualization);
403            SERIALIZE_SCALAR(haveLargeAsid64);
404            SERIALIZE_SCALAR(physAddrRange64);
405        }
406        void unserialize(Checkpoint *cp, const std::string &section)
407        {
408            DPRINTF(Checkpoint, "Unserializing Arm Misc Registers\n");
409            UNSERIALIZE_ARRAY(miscRegs, NumMiscRegs);
410            CPSR tmp_cpsr = miscRegs[MISCREG_CPSR];
411            updateRegMap(tmp_cpsr);
412
413            UNSERIALIZE_SCALAR(haveSecurity);
414            UNSERIALIZE_SCALAR(haveLPAE);
415            UNSERIALIZE_SCALAR(haveVirtualization);
416            UNSERIALIZE_SCALAR(haveLargeAsid64);
417            UNSERIALIZE_SCALAR(physAddrRange64);
418        }
419
420        void startup(ThreadContext *tc) {}
421
422        /// Explicitly import the otherwise hidden startup
423        using SimObject::startup;
424
425        typedef ArmISAParams Params;
426
427        const Params *params() const;
428
429        ISA(Params *p);
430    };
431}
432
433#endif
434