isa.hh (13114:777d445423d6) isa.hh (13173:210b6fc57533)
1/*
2 * Copyright (c) 2010, 2012-2018 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/miscregs.hh"
48#include "arch/arm/registers.hh"
49#include "arch/arm/system.hh"
50#include "arch/arm/tlb.hh"
51#include "arch/arm/types.hh"
52#include "arch/generic/traits.hh"
53#include "debug/Checkpoint.hh"
54#include "enums/VecRegRenameMode.hh"
55#include "sim/sim_object.hh"
56#include "enums/DecoderFlavour.hh"
57
58struct ArmISAParams;
59struct DummyArmISADeviceParams;
60class ThreadContext;
61class Checkpoint;
62class EventManager;
63
64namespace ArmISA
65{
66 class ISA : public SimObject
67 {
68 protected:
69 // Parent system
70 ArmSystem *system;
71
72 // Micro Architecture
73 const Enums::DecoderFlavour _decoderFlavour;
74 const Enums::VecRegRenameMode _vecRegRenameMode;
75
76 /** Dummy device for to handle non-existing ISA devices */
77 DummyISADevice dummyDevice;
78
79 // PMU belonging to this ISA
80 BaseISADevice *pmu;
81
82 // Generic timer interface belonging to this ISA
83 std::unique_ptr<BaseISADevice> timer;
84
85 // Cached copies of system-level properties
86 bool highestELIs64;
87 bool haveSecurity;
88 bool haveLPAE;
89 bool haveVirtualization;
1/*
2 * Copyright (c) 2010, 2012-2018 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/miscregs.hh"
48#include "arch/arm/registers.hh"
49#include "arch/arm/system.hh"
50#include "arch/arm/tlb.hh"
51#include "arch/arm/types.hh"
52#include "arch/generic/traits.hh"
53#include "debug/Checkpoint.hh"
54#include "enums/VecRegRenameMode.hh"
55#include "sim/sim_object.hh"
56#include "enums/DecoderFlavour.hh"
57
58struct ArmISAParams;
59struct DummyArmISADeviceParams;
60class ThreadContext;
61class Checkpoint;
62class EventManager;
63
64namespace ArmISA
65{
66 class ISA : public SimObject
67 {
68 protected:
69 // Parent system
70 ArmSystem *system;
71
72 // Micro Architecture
73 const Enums::DecoderFlavour _decoderFlavour;
74 const Enums::VecRegRenameMode _vecRegRenameMode;
75
76 /** Dummy device for to handle non-existing ISA devices */
77 DummyISADevice dummyDevice;
78
79 // PMU belonging to this ISA
80 BaseISADevice *pmu;
81
82 // Generic timer interface belonging to this ISA
83 std::unique_ptr<BaseISADevice> timer;
84
85 // Cached copies of system-level properties
86 bool highestELIs64;
87 bool haveSecurity;
88 bool haveLPAE;
89 bool haveVirtualization;
90 bool haveCrypto;
90 bool haveLargeAsid64;
91 uint8_t physAddrRange;
92
93 /**
94 * If true, accesses to IMPLEMENTATION DEFINED registers are treated
95 * as NOP hence not causing UNDEFINED INSTRUCTION.
96 */
97 bool impdefAsNop;
98
99 /** MiscReg metadata **/
100 struct MiscRegLUTEntry {
101 uint32_t lower; // Lower half mapped to this register
102 uint32_t upper; // Upper half mapped to this register
103 uint64_t _reset; // value taken on reset (i.e. initialization)
104 uint64_t _res0; // reserved
105 uint64_t _res1; // reserved
106 uint64_t _raz; // read as zero (fixed at 0)
107 uint64_t _rao; // read as one (fixed at 1)
108 public:
109 MiscRegLUTEntry() :
110 lower(0), upper(0),
111 _reset(0), _res0(0), _res1(0), _raz(0), _rao(0) {}
112 uint64_t reset() const { return _reset; }
113 uint64_t res0() const { return _res0; }
114 uint64_t res1() const { return _res1; }
115 uint64_t raz() const { return _raz; }
116 uint64_t rao() const { return _rao; }
117 // raz/rao implies writes ignored
118 uint64_t wi() const { return _raz | _rao; }
119 };
120
121 /** Metadata table accessible via the value of the register */
122 static std::vector<struct MiscRegLUTEntry> lookUpMiscReg;
123
124 class MiscRegLUTEntryInitializer {
125 struct MiscRegLUTEntry &entry;
126 std::bitset<NUM_MISCREG_INFOS> &info;
127 typedef const MiscRegLUTEntryInitializer& chain;
128 public:
129 chain mapsTo(uint32_t l, uint32_t u = 0) const {
130 entry.lower = l;
131 entry.upper = u;
132 return *this;
133 }
134 chain res0(uint64_t mask) const {
135 entry._res0 = mask;
136 return *this;
137 }
138 chain res1(uint64_t mask) const {
139 entry._res1 = mask;
140 return *this;
141 }
142 chain raz(uint64_t mask) const {
143 entry._raz = mask;
144 return *this;
145 }
146 chain rao(uint64_t mask) const {
147 entry._rao = mask;
148 return *this;
149 }
150 chain implemented(bool v = true) const {
151 info[MISCREG_IMPLEMENTED] = v;
152 return *this;
153 }
154 chain unimplemented() const {
155 return implemented(false);
156 }
157 chain unverifiable(bool v = true) const {
158 info[MISCREG_UNVERIFIABLE] = v;
159 return *this;
160 }
161 chain warnNotFail(bool v = true) const {
162 info[MISCREG_WARN_NOT_FAIL] = v;
163 return *this;
164 }
165 chain mutex(bool v = true) const {
166 info[MISCREG_MUTEX] = v;
167 return *this;
168 }
169 chain banked(bool v = true) const {
170 info[MISCREG_BANKED] = v;
171 return *this;
172 }
173 chain bankedChild(bool v = true) const {
174 info[MISCREG_BANKED_CHILD] = v;
175 return *this;
176 }
177 chain userNonSecureRead(bool v = true) const {
178 info[MISCREG_USR_NS_RD] = v;
179 return *this;
180 }
181 chain userNonSecureWrite(bool v = true) const {
182 info[MISCREG_USR_NS_WR] = v;
183 return *this;
184 }
185 chain userSecureRead(bool v = true) const {
186 info[MISCREG_USR_S_RD] = v;
187 return *this;
188 }
189 chain userSecureWrite(bool v = true) const {
190 info[MISCREG_USR_S_WR] = v;
191 return *this;
192 }
193 chain user(bool v = true) const {
194 userNonSecureRead(v);
195 userNonSecureWrite(v);
196 userSecureRead(v);
197 userSecureWrite(v);
198 return *this;
199 }
200 chain privNonSecureRead(bool v = true) const {
201 info[MISCREG_PRI_NS_RD] = v;
202 return *this;
203 }
204 chain privNonSecureWrite(bool v = true) const {
205 info[MISCREG_PRI_NS_WR] = v;
206 return *this;
207 }
208 chain privNonSecure(bool v = true) const {
209 privNonSecureRead(v);
210 privNonSecureWrite(v);
211 return *this;
212 }
213 chain privSecureRead(bool v = true) const {
214 info[MISCREG_PRI_S_RD] = v;
215 return *this;
216 }
217 chain privSecureWrite(bool v = true) const {
218 info[MISCREG_PRI_S_WR] = v;
219 return *this;
220 }
221 chain privSecure(bool v = true) const {
222 privSecureRead(v);
223 privSecureWrite(v);
224 return *this;
225 }
226 chain priv(bool v = true) const {
227 privSecure(v);
228 privNonSecure(v);
229 return *this;
230 }
231 chain hypRead(bool v = true) const {
232 info[MISCREG_HYP_RD] = v;
233 return *this;
234 }
235 chain hypWrite(bool v = true) const {
236 info[MISCREG_HYP_WR] = v;
237 return *this;
238 }
239 chain hyp(bool v = true) const {
240 hypRead(v);
241 hypWrite(v);
242 return *this;
243 }
244 chain monSecureRead(bool v = true) const {
245 info[MISCREG_MON_NS0_RD] = v;
246 return *this;
247 }
248 chain monSecureWrite(bool v = true) const {
249 info[MISCREG_MON_NS0_WR] = v;
250 return *this;
251 }
252 chain monNonSecureRead(bool v = true) const {
253 info[MISCREG_MON_NS1_RD] = v;
254 return *this;
255 }
256 chain monNonSecureWrite(bool v = true) const {
257 info[MISCREG_MON_NS1_WR] = v;
258 return *this;
259 }
260 chain mon(bool v = true) const {
261 monSecureRead(v);
262 monSecureWrite(v);
263 monNonSecureRead(v);
264 monNonSecureWrite(v);
265 return *this;
266 }
267 chain monSecure(bool v = true) const {
268 monSecureRead(v);
269 monSecureWrite(v);
270 return *this;
271 }
272 chain monNonSecure(bool v = true) const {
273 monNonSecureRead(v);
274 monNonSecureWrite(v);
275 return *this;
276 }
277 chain allPrivileges(bool v = true) const {
278 userNonSecureRead(v);
279 userNonSecureWrite(v);
280 userSecureRead(v);
281 userSecureWrite(v);
282 privNonSecureRead(v);
283 privNonSecureWrite(v);
284 privSecureRead(v);
285 privSecureWrite(v);
286 hypRead(v);
287 hypWrite(v);
288 monSecureRead(v);
289 monSecureWrite(v);
290 monNonSecureRead(v);
291 monNonSecureWrite(v);
292 return *this;
293 }
294 chain nonSecure(bool v = true) const {
295 userNonSecureRead(v);
296 userNonSecureWrite(v);
297 privNonSecureRead(v);
298 privNonSecureWrite(v);
299 hypRead(v);
300 hypWrite(v);
301 monNonSecureRead(v);
302 monNonSecureWrite(v);
303 return *this;
304 }
305 chain secure(bool v = true) const {
306 userSecureRead(v);
307 userSecureWrite(v);
308 privSecureRead(v);
309 privSecureWrite(v);
310 monSecureRead(v);
311 monSecureWrite(v);
312 return *this;
313 }
314 chain reads(bool v) const {
315 userNonSecureRead(v);
316 userSecureRead(v);
317 privNonSecureRead(v);
318 privSecureRead(v);
319 hypRead(v);
320 monSecureRead(v);
321 monNonSecureRead(v);
322 return *this;
323 }
324 chain writes(bool v) const {
325 userNonSecureWrite(v);
326 userSecureWrite(v);
327 privNonSecureWrite(v);
328 privSecureWrite(v);
329 hypWrite(v);
330 monSecureWrite(v);
331 monNonSecureWrite(v);
332 return *this;
333 }
334 chain exceptUserMode() const {
335 user(0);
336 return *this;
337 }
338 MiscRegLUTEntryInitializer(struct MiscRegLUTEntry &e,
339 std::bitset<NUM_MISCREG_INFOS> &i)
340 : entry(e),
341 info(i)
342 {
343 // force unimplemented registers to be thusly declared
344 implemented(1);
345 }
346 };
347
348 const MiscRegLUTEntryInitializer InitReg(uint32_t reg) {
349 return MiscRegLUTEntryInitializer(lookUpMiscReg[reg],
350 miscRegInfo[reg]);
351 }
352
353 void initializeMiscRegMetadata();
354
355 MiscReg miscRegs[NumMiscRegs];
356 const IntRegIndex *intRegMap;
357
358 void
359 updateRegMap(CPSR cpsr)
360 {
361 if (cpsr.width == 0) {
362 intRegMap = IntReg64Map;
363 } else {
364 switch (cpsr.mode) {
365 case MODE_USER:
366 case MODE_SYSTEM:
367 intRegMap = IntRegUsrMap;
368 break;
369 case MODE_FIQ:
370 intRegMap = IntRegFiqMap;
371 break;
372 case MODE_IRQ:
373 intRegMap = IntRegIrqMap;
374 break;
375 case MODE_SVC:
376 intRegMap = IntRegSvcMap;
377 break;
378 case MODE_MON:
379 intRegMap = IntRegMonMap;
380 break;
381 case MODE_ABORT:
382 intRegMap = IntRegAbtMap;
383 break;
384 case MODE_HYP:
385 intRegMap = IntRegHypMap;
386 break;
387 case MODE_UNDEFINED:
388 intRegMap = IntRegUndMap;
389 break;
390 default:
391 panic("Unrecognized mode setting in CPSR.\n");
392 }
393 }
394 }
395
396 BaseISADevice &getGenericTimer(ThreadContext *tc);
397
398
399 private:
400 inline void assert32(ThreadContext *tc) {
401 CPSR cpsr M5_VAR_USED = readMiscReg(MISCREG_CPSR, tc);
402 assert(cpsr.width);
403 }
404
405 inline void assert64(ThreadContext *tc) {
406 CPSR cpsr M5_VAR_USED = readMiscReg(MISCREG_CPSR, tc);
407 assert(!cpsr.width);
408 }
409
410 public:
411 void clear();
412
413 protected:
414 void clear64(const ArmISAParams *p);
415 void initID32(const ArmISAParams *p);
416 void initID64(const ArmISAParams *p);
417
418 public:
419 MiscReg readMiscRegNoEffect(int misc_reg) const;
420 MiscReg readMiscReg(int misc_reg, ThreadContext *tc);
421 void setMiscRegNoEffect(int misc_reg, const MiscReg &val);
422 void setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc);
423
424 RegId
425 flattenRegId(const RegId& regId) const
426 {
427 switch (regId.classValue()) {
428 case IntRegClass:
429 return RegId(IntRegClass, flattenIntIndex(regId.index()));
430 case FloatRegClass:
431 return RegId(FloatRegClass, flattenFloatIndex(regId.index()));
432 case VecRegClass:
433 return RegId(VecRegClass, flattenVecIndex(regId.index()));
434 case VecElemClass:
435 return RegId(VecElemClass, flattenVecElemIndex(regId.index()));
436 case CCRegClass:
437 return RegId(CCRegClass, flattenCCIndex(regId.index()));
438 case MiscRegClass:
439 return RegId(MiscRegClass, flattenMiscIndex(regId.index()));
440 }
441 return RegId();
442 }
443
444 int
445 flattenIntIndex(int reg) const
446 {
447 assert(reg >= 0);
448 if (reg < NUM_ARCH_INTREGS) {
449 return intRegMap[reg];
450 } else if (reg < NUM_INTREGS) {
451 return reg;
452 } else if (reg == INTREG_SPX) {
453 CPSR cpsr = miscRegs[MISCREG_CPSR];
454 ExceptionLevel el = opModeToEL(
455 (OperatingMode) (uint8_t) cpsr.mode);
456 if (!cpsr.sp && el != EL0)
457 return INTREG_SP0;
458 switch (el) {
459 case EL3:
460 return INTREG_SP3;
461 case EL2:
462 return INTREG_SP2;
463 case EL1:
464 return INTREG_SP1;
465 case EL0:
466 return INTREG_SP0;
467 default:
468 panic("Invalid exception level");
469 return 0; // Never happens.
470 }
471 } else {
472 return flattenIntRegModeIndex(reg);
473 }
474 }
475
476 int
477 flattenFloatIndex(int reg) const
478 {
479 assert(reg >= 0);
480 return reg;
481 }
482
483 int
484 flattenVecIndex(int reg) const
485 {
486 assert(reg >= 0);
487 return reg;
488 }
489
490 int
491 flattenVecElemIndex(int reg) const
492 {
493 assert(reg >= 0);
494 return reg;
495 }
496
497 int
498 flattenCCIndex(int reg) const
499 {
500 assert(reg >= 0);
501 return reg;
502 }
503
504 int
505 flattenMiscIndex(int reg) const
506 {
507 assert(reg >= 0);
508 int flat_idx = reg;
509
510 if (reg == MISCREG_SPSR) {
511 CPSR cpsr = miscRegs[MISCREG_CPSR];
512 switch (cpsr.mode) {
513 case MODE_EL0T:
514 warn("User mode does not have SPSR\n");
515 flat_idx = MISCREG_SPSR;
516 break;
517 case MODE_EL1T:
518 case MODE_EL1H:
519 flat_idx = MISCREG_SPSR_EL1;
520 break;
521 case MODE_EL2T:
522 case MODE_EL2H:
523 flat_idx = MISCREG_SPSR_EL2;
524 break;
525 case MODE_EL3T:
526 case MODE_EL3H:
527 flat_idx = MISCREG_SPSR_EL3;
528 break;
529 case MODE_USER:
530 warn("User mode does not have SPSR\n");
531 flat_idx = MISCREG_SPSR;
532 break;
533 case MODE_FIQ:
534 flat_idx = MISCREG_SPSR_FIQ;
535 break;
536 case MODE_IRQ:
537 flat_idx = MISCREG_SPSR_IRQ;
538 break;
539 case MODE_SVC:
540 flat_idx = MISCREG_SPSR_SVC;
541 break;
542 case MODE_MON:
543 flat_idx = MISCREG_SPSR_MON;
544 break;
545 case MODE_ABORT:
546 flat_idx = MISCREG_SPSR_ABT;
547 break;
548 case MODE_HYP:
549 flat_idx = MISCREG_SPSR_HYP;
550 break;
551 case MODE_UNDEFINED:
552 flat_idx = MISCREG_SPSR_UND;
553 break;
554 default:
555 warn("Trying to access SPSR in an invalid mode: %d\n",
556 cpsr.mode);
557 flat_idx = MISCREG_SPSR;
558 break;
559 }
560 } else if (miscRegInfo[reg][MISCREG_MUTEX]) {
561 // Mutually exclusive CP15 register
562 switch (reg) {
563 case MISCREG_PRRR_MAIR0:
564 case MISCREG_PRRR_MAIR0_NS:
565 case MISCREG_PRRR_MAIR0_S:
566 {
567 TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
568 // If the muxed reg has been flattened, work out the
569 // offset and apply it to the unmuxed reg
570 int idxOffset = reg - MISCREG_PRRR_MAIR0;
571 if (ttbcr.eae)
572 flat_idx = flattenMiscIndex(MISCREG_MAIR0 +
573 idxOffset);
574 else
575 flat_idx = flattenMiscIndex(MISCREG_PRRR +
576 idxOffset);
577 }
578 break;
579 case MISCREG_NMRR_MAIR1:
580 case MISCREG_NMRR_MAIR1_NS:
581 case MISCREG_NMRR_MAIR1_S:
582 {
583 TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
584 // If the muxed reg has been flattened, work out the
585 // offset and apply it to the unmuxed reg
586 int idxOffset = reg - MISCREG_NMRR_MAIR1;
587 if (ttbcr.eae)
588 flat_idx = flattenMiscIndex(MISCREG_MAIR1 +
589 idxOffset);
590 else
591 flat_idx = flattenMiscIndex(MISCREG_NMRR +
592 idxOffset);
593 }
594 break;
595 case MISCREG_PMXEVTYPER_PMCCFILTR:
596 {
597 PMSELR pmselr = miscRegs[MISCREG_PMSELR];
598 if (pmselr.sel == 31)
599 flat_idx = flattenMiscIndex(MISCREG_PMCCFILTR);
600 else
601 flat_idx = flattenMiscIndex(MISCREG_PMXEVTYPER);
602 }
603 break;
604 default:
605 panic("Unrecognized misc. register.\n");
606 break;
607 }
608 } else {
609 if (miscRegInfo[reg][MISCREG_BANKED]) {
610 bool secureReg = haveSecurity && !highestELIs64 &&
611 inSecureState(miscRegs[MISCREG_SCR],
612 miscRegs[MISCREG_CPSR]);
613 flat_idx += secureReg ? 2 : 1;
614 }
615 }
616 return flat_idx;
617 }
618
619 std::pair<int,int> getMiscIndices(int misc_reg) const
620 {
621 // Note: indexes of AArch64 registers are left unchanged
622 int flat_idx = flattenMiscIndex(misc_reg);
623
624 if (lookUpMiscReg[flat_idx].lower == 0) {
625 return std::make_pair(flat_idx, 0);
626 }
627
628 // do additional S/NS flattenings if mapped to NS while in S
629 bool S = haveSecurity && !highestELIs64 &&
630 inSecureState(miscRegs[MISCREG_SCR],
631 miscRegs[MISCREG_CPSR]);
632 int lower = lookUpMiscReg[flat_idx].lower;
633 int upper = lookUpMiscReg[flat_idx].upper;
634 // upper == 0, which is CPSR, is not MISCREG_BANKED_CHILD (no-op)
635 lower += S && miscRegInfo[lower][MISCREG_BANKED_CHILD];
636 upper += S && miscRegInfo[upper][MISCREG_BANKED_CHILD];
637 return std::make_pair(lower, upper);
638 }
639
640 void serialize(CheckpointOut &cp) const
641 {
642 DPRINTF(Checkpoint, "Serializing Arm Misc Registers\n");
643 SERIALIZE_ARRAY(miscRegs, NUM_PHYS_MISCREGS);
644
645 SERIALIZE_SCALAR(highestELIs64);
646 SERIALIZE_SCALAR(haveSecurity);
647 SERIALIZE_SCALAR(haveLPAE);
648 SERIALIZE_SCALAR(haveVirtualization);
649 SERIALIZE_SCALAR(haveLargeAsid64);
650 SERIALIZE_SCALAR(physAddrRange);
651 }
652 void unserialize(CheckpointIn &cp)
653 {
654 DPRINTF(Checkpoint, "Unserializing Arm Misc Registers\n");
655 UNSERIALIZE_ARRAY(miscRegs, NUM_PHYS_MISCREGS);
656 CPSR tmp_cpsr = miscRegs[MISCREG_CPSR];
657 updateRegMap(tmp_cpsr);
658
659 UNSERIALIZE_SCALAR(highestELIs64);
660 UNSERIALIZE_SCALAR(haveSecurity);
661 UNSERIALIZE_SCALAR(haveLPAE);
662 UNSERIALIZE_SCALAR(haveVirtualization);
663 UNSERIALIZE_SCALAR(haveLargeAsid64);
664 UNSERIALIZE_SCALAR(physAddrRange);
665 }
666
667 void startup(ThreadContext *tc);
668
669 Enums::DecoderFlavour decoderFlavour() const { return _decoderFlavour; }
670
671 Enums::VecRegRenameMode
672 vecRegRenameMode() const
673 {
674 return _vecRegRenameMode;
675 }
676
677 /// Explicitly import the otherwise hidden startup
678 using SimObject::startup;
679
680 typedef ArmISAParams Params;
681
682 const Params *params() const;
683
684 ISA(Params *p);
685 };
686}
687
688template<>
689struct initRenameMode<ArmISA::ISA>
690{
691 static Enums::VecRegRenameMode mode(const ArmISA::ISA* isa)
692 {
693 return isa->vecRegRenameMode();
694 }
695 static bool equals(const ArmISA::ISA* isa1, const ArmISA::ISA* isa2)
696 {
697 return mode(isa1) == mode(isa2);
698 }
699};
700
701#endif
91 bool haveLargeAsid64;
92 uint8_t physAddrRange;
93
94 /**
95 * If true, accesses to IMPLEMENTATION DEFINED registers are treated
96 * as NOP hence not causing UNDEFINED INSTRUCTION.
97 */
98 bool impdefAsNop;
99
100 /** MiscReg metadata **/
101 struct MiscRegLUTEntry {
102 uint32_t lower; // Lower half mapped to this register
103 uint32_t upper; // Upper half mapped to this register
104 uint64_t _reset; // value taken on reset (i.e. initialization)
105 uint64_t _res0; // reserved
106 uint64_t _res1; // reserved
107 uint64_t _raz; // read as zero (fixed at 0)
108 uint64_t _rao; // read as one (fixed at 1)
109 public:
110 MiscRegLUTEntry() :
111 lower(0), upper(0),
112 _reset(0), _res0(0), _res1(0), _raz(0), _rao(0) {}
113 uint64_t reset() const { return _reset; }
114 uint64_t res0() const { return _res0; }
115 uint64_t res1() const { return _res1; }
116 uint64_t raz() const { return _raz; }
117 uint64_t rao() const { return _rao; }
118 // raz/rao implies writes ignored
119 uint64_t wi() const { return _raz | _rao; }
120 };
121
122 /** Metadata table accessible via the value of the register */
123 static std::vector<struct MiscRegLUTEntry> lookUpMiscReg;
124
125 class MiscRegLUTEntryInitializer {
126 struct MiscRegLUTEntry &entry;
127 std::bitset<NUM_MISCREG_INFOS> &info;
128 typedef const MiscRegLUTEntryInitializer& chain;
129 public:
130 chain mapsTo(uint32_t l, uint32_t u = 0) const {
131 entry.lower = l;
132 entry.upper = u;
133 return *this;
134 }
135 chain res0(uint64_t mask) const {
136 entry._res0 = mask;
137 return *this;
138 }
139 chain res1(uint64_t mask) const {
140 entry._res1 = mask;
141 return *this;
142 }
143 chain raz(uint64_t mask) const {
144 entry._raz = mask;
145 return *this;
146 }
147 chain rao(uint64_t mask) const {
148 entry._rao = mask;
149 return *this;
150 }
151 chain implemented(bool v = true) const {
152 info[MISCREG_IMPLEMENTED] = v;
153 return *this;
154 }
155 chain unimplemented() const {
156 return implemented(false);
157 }
158 chain unverifiable(bool v = true) const {
159 info[MISCREG_UNVERIFIABLE] = v;
160 return *this;
161 }
162 chain warnNotFail(bool v = true) const {
163 info[MISCREG_WARN_NOT_FAIL] = v;
164 return *this;
165 }
166 chain mutex(bool v = true) const {
167 info[MISCREG_MUTEX] = v;
168 return *this;
169 }
170 chain banked(bool v = true) const {
171 info[MISCREG_BANKED] = v;
172 return *this;
173 }
174 chain bankedChild(bool v = true) const {
175 info[MISCREG_BANKED_CHILD] = v;
176 return *this;
177 }
178 chain userNonSecureRead(bool v = true) const {
179 info[MISCREG_USR_NS_RD] = v;
180 return *this;
181 }
182 chain userNonSecureWrite(bool v = true) const {
183 info[MISCREG_USR_NS_WR] = v;
184 return *this;
185 }
186 chain userSecureRead(bool v = true) const {
187 info[MISCREG_USR_S_RD] = v;
188 return *this;
189 }
190 chain userSecureWrite(bool v = true) const {
191 info[MISCREG_USR_S_WR] = v;
192 return *this;
193 }
194 chain user(bool v = true) const {
195 userNonSecureRead(v);
196 userNonSecureWrite(v);
197 userSecureRead(v);
198 userSecureWrite(v);
199 return *this;
200 }
201 chain privNonSecureRead(bool v = true) const {
202 info[MISCREG_PRI_NS_RD] = v;
203 return *this;
204 }
205 chain privNonSecureWrite(bool v = true) const {
206 info[MISCREG_PRI_NS_WR] = v;
207 return *this;
208 }
209 chain privNonSecure(bool v = true) const {
210 privNonSecureRead(v);
211 privNonSecureWrite(v);
212 return *this;
213 }
214 chain privSecureRead(bool v = true) const {
215 info[MISCREG_PRI_S_RD] = v;
216 return *this;
217 }
218 chain privSecureWrite(bool v = true) const {
219 info[MISCREG_PRI_S_WR] = v;
220 return *this;
221 }
222 chain privSecure(bool v = true) const {
223 privSecureRead(v);
224 privSecureWrite(v);
225 return *this;
226 }
227 chain priv(bool v = true) const {
228 privSecure(v);
229 privNonSecure(v);
230 return *this;
231 }
232 chain hypRead(bool v = true) const {
233 info[MISCREG_HYP_RD] = v;
234 return *this;
235 }
236 chain hypWrite(bool v = true) const {
237 info[MISCREG_HYP_WR] = v;
238 return *this;
239 }
240 chain hyp(bool v = true) const {
241 hypRead(v);
242 hypWrite(v);
243 return *this;
244 }
245 chain monSecureRead(bool v = true) const {
246 info[MISCREG_MON_NS0_RD] = v;
247 return *this;
248 }
249 chain monSecureWrite(bool v = true) const {
250 info[MISCREG_MON_NS0_WR] = v;
251 return *this;
252 }
253 chain monNonSecureRead(bool v = true) const {
254 info[MISCREG_MON_NS1_RD] = v;
255 return *this;
256 }
257 chain monNonSecureWrite(bool v = true) const {
258 info[MISCREG_MON_NS1_WR] = v;
259 return *this;
260 }
261 chain mon(bool v = true) const {
262 monSecureRead(v);
263 monSecureWrite(v);
264 monNonSecureRead(v);
265 monNonSecureWrite(v);
266 return *this;
267 }
268 chain monSecure(bool v = true) const {
269 monSecureRead(v);
270 monSecureWrite(v);
271 return *this;
272 }
273 chain monNonSecure(bool v = true) const {
274 monNonSecureRead(v);
275 monNonSecureWrite(v);
276 return *this;
277 }
278 chain allPrivileges(bool v = true) const {
279 userNonSecureRead(v);
280 userNonSecureWrite(v);
281 userSecureRead(v);
282 userSecureWrite(v);
283 privNonSecureRead(v);
284 privNonSecureWrite(v);
285 privSecureRead(v);
286 privSecureWrite(v);
287 hypRead(v);
288 hypWrite(v);
289 monSecureRead(v);
290 monSecureWrite(v);
291 monNonSecureRead(v);
292 monNonSecureWrite(v);
293 return *this;
294 }
295 chain nonSecure(bool v = true) const {
296 userNonSecureRead(v);
297 userNonSecureWrite(v);
298 privNonSecureRead(v);
299 privNonSecureWrite(v);
300 hypRead(v);
301 hypWrite(v);
302 monNonSecureRead(v);
303 monNonSecureWrite(v);
304 return *this;
305 }
306 chain secure(bool v = true) const {
307 userSecureRead(v);
308 userSecureWrite(v);
309 privSecureRead(v);
310 privSecureWrite(v);
311 monSecureRead(v);
312 monSecureWrite(v);
313 return *this;
314 }
315 chain reads(bool v) const {
316 userNonSecureRead(v);
317 userSecureRead(v);
318 privNonSecureRead(v);
319 privSecureRead(v);
320 hypRead(v);
321 monSecureRead(v);
322 monNonSecureRead(v);
323 return *this;
324 }
325 chain writes(bool v) const {
326 userNonSecureWrite(v);
327 userSecureWrite(v);
328 privNonSecureWrite(v);
329 privSecureWrite(v);
330 hypWrite(v);
331 monSecureWrite(v);
332 monNonSecureWrite(v);
333 return *this;
334 }
335 chain exceptUserMode() const {
336 user(0);
337 return *this;
338 }
339 MiscRegLUTEntryInitializer(struct MiscRegLUTEntry &e,
340 std::bitset<NUM_MISCREG_INFOS> &i)
341 : entry(e),
342 info(i)
343 {
344 // force unimplemented registers to be thusly declared
345 implemented(1);
346 }
347 };
348
349 const MiscRegLUTEntryInitializer InitReg(uint32_t reg) {
350 return MiscRegLUTEntryInitializer(lookUpMiscReg[reg],
351 miscRegInfo[reg]);
352 }
353
354 void initializeMiscRegMetadata();
355
356 MiscReg miscRegs[NumMiscRegs];
357 const IntRegIndex *intRegMap;
358
359 void
360 updateRegMap(CPSR cpsr)
361 {
362 if (cpsr.width == 0) {
363 intRegMap = IntReg64Map;
364 } else {
365 switch (cpsr.mode) {
366 case MODE_USER:
367 case MODE_SYSTEM:
368 intRegMap = IntRegUsrMap;
369 break;
370 case MODE_FIQ:
371 intRegMap = IntRegFiqMap;
372 break;
373 case MODE_IRQ:
374 intRegMap = IntRegIrqMap;
375 break;
376 case MODE_SVC:
377 intRegMap = IntRegSvcMap;
378 break;
379 case MODE_MON:
380 intRegMap = IntRegMonMap;
381 break;
382 case MODE_ABORT:
383 intRegMap = IntRegAbtMap;
384 break;
385 case MODE_HYP:
386 intRegMap = IntRegHypMap;
387 break;
388 case MODE_UNDEFINED:
389 intRegMap = IntRegUndMap;
390 break;
391 default:
392 panic("Unrecognized mode setting in CPSR.\n");
393 }
394 }
395 }
396
397 BaseISADevice &getGenericTimer(ThreadContext *tc);
398
399
400 private:
401 inline void assert32(ThreadContext *tc) {
402 CPSR cpsr M5_VAR_USED = readMiscReg(MISCREG_CPSR, tc);
403 assert(cpsr.width);
404 }
405
406 inline void assert64(ThreadContext *tc) {
407 CPSR cpsr M5_VAR_USED = readMiscReg(MISCREG_CPSR, tc);
408 assert(!cpsr.width);
409 }
410
411 public:
412 void clear();
413
414 protected:
415 void clear64(const ArmISAParams *p);
416 void initID32(const ArmISAParams *p);
417 void initID64(const ArmISAParams *p);
418
419 public:
420 MiscReg readMiscRegNoEffect(int misc_reg) const;
421 MiscReg readMiscReg(int misc_reg, ThreadContext *tc);
422 void setMiscRegNoEffect(int misc_reg, const MiscReg &val);
423 void setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc);
424
425 RegId
426 flattenRegId(const RegId& regId) const
427 {
428 switch (regId.classValue()) {
429 case IntRegClass:
430 return RegId(IntRegClass, flattenIntIndex(regId.index()));
431 case FloatRegClass:
432 return RegId(FloatRegClass, flattenFloatIndex(regId.index()));
433 case VecRegClass:
434 return RegId(VecRegClass, flattenVecIndex(regId.index()));
435 case VecElemClass:
436 return RegId(VecElemClass, flattenVecElemIndex(regId.index()));
437 case CCRegClass:
438 return RegId(CCRegClass, flattenCCIndex(regId.index()));
439 case MiscRegClass:
440 return RegId(MiscRegClass, flattenMiscIndex(regId.index()));
441 }
442 return RegId();
443 }
444
445 int
446 flattenIntIndex(int reg) const
447 {
448 assert(reg >= 0);
449 if (reg < NUM_ARCH_INTREGS) {
450 return intRegMap[reg];
451 } else if (reg < NUM_INTREGS) {
452 return reg;
453 } else if (reg == INTREG_SPX) {
454 CPSR cpsr = miscRegs[MISCREG_CPSR];
455 ExceptionLevel el = opModeToEL(
456 (OperatingMode) (uint8_t) cpsr.mode);
457 if (!cpsr.sp && el != EL0)
458 return INTREG_SP0;
459 switch (el) {
460 case EL3:
461 return INTREG_SP3;
462 case EL2:
463 return INTREG_SP2;
464 case EL1:
465 return INTREG_SP1;
466 case EL0:
467 return INTREG_SP0;
468 default:
469 panic("Invalid exception level");
470 return 0; // Never happens.
471 }
472 } else {
473 return flattenIntRegModeIndex(reg);
474 }
475 }
476
477 int
478 flattenFloatIndex(int reg) const
479 {
480 assert(reg >= 0);
481 return reg;
482 }
483
484 int
485 flattenVecIndex(int reg) const
486 {
487 assert(reg >= 0);
488 return reg;
489 }
490
491 int
492 flattenVecElemIndex(int reg) const
493 {
494 assert(reg >= 0);
495 return reg;
496 }
497
498 int
499 flattenCCIndex(int reg) const
500 {
501 assert(reg >= 0);
502 return reg;
503 }
504
505 int
506 flattenMiscIndex(int reg) const
507 {
508 assert(reg >= 0);
509 int flat_idx = reg;
510
511 if (reg == MISCREG_SPSR) {
512 CPSR cpsr = miscRegs[MISCREG_CPSR];
513 switch (cpsr.mode) {
514 case MODE_EL0T:
515 warn("User mode does not have SPSR\n");
516 flat_idx = MISCREG_SPSR;
517 break;
518 case MODE_EL1T:
519 case MODE_EL1H:
520 flat_idx = MISCREG_SPSR_EL1;
521 break;
522 case MODE_EL2T:
523 case MODE_EL2H:
524 flat_idx = MISCREG_SPSR_EL2;
525 break;
526 case MODE_EL3T:
527 case MODE_EL3H:
528 flat_idx = MISCREG_SPSR_EL3;
529 break;
530 case MODE_USER:
531 warn("User mode does not have SPSR\n");
532 flat_idx = MISCREG_SPSR;
533 break;
534 case MODE_FIQ:
535 flat_idx = MISCREG_SPSR_FIQ;
536 break;
537 case MODE_IRQ:
538 flat_idx = MISCREG_SPSR_IRQ;
539 break;
540 case MODE_SVC:
541 flat_idx = MISCREG_SPSR_SVC;
542 break;
543 case MODE_MON:
544 flat_idx = MISCREG_SPSR_MON;
545 break;
546 case MODE_ABORT:
547 flat_idx = MISCREG_SPSR_ABT;
548 break;
549 case MODE_HYP:
550 flat_idx = MISCREG_SPSR_HYP;
551 break;
552 case MODE_UNDEFINED:
553 flat_idx = MISCREG_SPSR_UND;
554 break;
555 default:
556 warn("Trying to access SPSR in an invalid mode: %d\n",
557 cpsr.mode);
558 flat_idx = MISCREG_SPSR;
559 break;
560 }
561 } else if (miscRegInfo[reg][MISCREG_MUTEX]) {
562 // Mutually exclusive CP15 register
563 switch (reg) {
564 case MISCREG_PRRR_MAIR0:
565 case MISCREG_PRRR_MAIR0_NS:
566 case MISCREG_PRRR_MAIR0_S:
567 {
568 TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
569 // If the muxed reg has been flattened, work out the
570 // offset and apply it to the unmuxed reg
571 int idxOffset = reg - MISCREG_PRRR_MAIR0;
572 if (ttbcr.eae)
573 flat_idx = flattenMiscIndex(MISCREG_MAIR0 +
574 idxOffset);
575 else
576 flat_idx = flattenMiscIndex(MISCREG_PRRR +
577 idxOffset);
578 }
579 break;
580 case MISCREG_NMRR_MAIR1:
581 case MISCREG_NMRR_MAIR1_NS:
582 case MISCREG_NMRR_MAIR1_S:
583 {
584 TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
585 // If the muxed reg has been flattened, work out the
586 // offset and apply it to the unmuxed reg
587 int idxOffset = reg - MISCREG_NMRR_MAIR1;
588 if (ttbcr.eae)
589 flat_idx = flattenMiscIndex(MISCREG_MAIR1 +
590 idxOffset);
591 else
592 flat_idx = flattenMiscIndex(MISCREG_NMRR +
593 idxOffset);
594 }
595 break;
596 case MISCREG_PMXEVTYPER_PMCCFILTR:
597 {
598 PMSELR pmselr = miscRegs[MISCREG_PMSELR];
599 if (pmselr.sel == 31)
600 flat_idx = flattenMiscIndex(MISCREG_PMCCFILTR);
601 else
602 flat_idx = flattenMiscIndex(MISCREG_PMXEVTYPER);
603 }
604 break;
605 default:
606 panic("Unrecognized misc. register.\n");
607 break;
608 }
609 } else {
610 if (miscRegInfo[reg][MISCREG_BANKED]) {
611 bool secureReg = haveSecurity && !highestELIs64 &&
612 inSecureState(miscRegs[MISCREG_SCR],
613 miscRegs[MISCREG_CPSR]);
614 flat_idx += secureReg ? 2 : 1;
615 }
616 }
617 return flat_idx;
618 }
619
620 std::pair<int,int> getMiscIndices(int misc_reg) const
621 {
622 // Note: indexes of AArch64 registers are left unchanged
623 int flat_idx = flattenMiscIndex(misc_reg);
624
625 if (lookUpMiscReg[flat_idx].lower == 0) {
626 return std::make_pair(flat_idx, 0);
627 }
628
629 // do additional S/NS flattenings if mapped to NS while in S
630 bool S = haveSecurity && !highestELIs64 &&
631 inSecureState(miscRegs[MISCREG_SCR],
632 miscRegs[MISCREG_CPSR]);
633 int lower = lookUpMiscReg[flat_idx].lower;
634 int upper = lookUpMiscReg[flat_idx].upper;
635 // upper == 0, which is CPSR, is not MISCREG_BANKED_CHILD (no-op)
636 lower += S && miscRegInfo[lower][MISCREG_BANKED_CHILD];
637 upper += S && miscRegInfo[upper][MISCREG_BANKED_CHILD];
638 return std::make_pair(lower, upper);
639 }
640
641 void serialize(CheckpointOut &cp) const
642 {
643 DPRINTF(Checkpoint, "Serializing Arm Misc Registers\n");
644 SERIALIZE_ARRAY(miscRegs, NUM_PHYS_MISCREGS);
645
646 SERIALIZE_SCALAR(highestELIs64);
647 SERIALIZE_SCALAR(haveSecurity);
648 SERIALIZE_SCALAR(haveLPAE);
649 SERIALIZE_SCALAR(haveVirtualization);
650 SERIALIZE_SCALAR(haveLargeAsid64);
651 SERIALIZE_SCALAR(physAddrRange);
652 }
653 void unserialize(CheckpointIn &cp)
654 {
655 DPRINTF(Checkpoint, "Unserializing Arm Misc Registers\n");
656 UNSERIALIZE_ARRAY(miscRegs, NUM_PHYS_MISCREGS);
657 CPSR tmp_cpsr = miscRegs[MISCREG_CPSR];
658 updateRegMap(tmp_cpsr);
659
660 UNSERIALIZE_SCALAR(highestELIs64);
661 UNSERIALIZE_SCALAR(haveSecurity);
662 UNSERIALIZE_SCALAR(haveLPAE);
663 UNSERIALIZE_SCALAR(haveVirtualization);
664 UNSERIALIZE_SCALAR(haveLargeAsid64);
665 UNSERIALIZE_SCALAR(physAddrRange);
666 }
667
668 void startup(ThreadContext *tc);
669
670 Enums::DecoderFlavour decoderFlavour() const { return _decoderFlavour; }
671
672 Enums::VecRegRenameMode
673 vecRegRenameMode() const
674 {
675 return _vecRegRenameMode;
676 }
677
678 /// Explicitly import the otherwise hidden startup
679 using SimObject::startup;
680
681 typedef ArmISAParams Params;
682
683 const Params *params() const;
684
685 ISA(Params *p);
686 };
687}
688
689template<>
690struct initRenameMode<ArmISA::ISA>
691{
692 static Enums::VecRegRenameMode mode(const ArmISA::ISA* isa)
693 {
694 return isa->vecRegRenameMode();
695 }
696 static bool equals(const ArmISA::ISA* isa1, const ArmISA::ISA* isa2)
697 {
698 return mode(isa1) == mode(isa2);
699 }
700};
701
702#endif