Deleted Added
sdiff udiff text old ( 13395:0f064dae9f6b ) new ( 13531:e6f1bf55d038 )
full compact
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;
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 privRead(bool v = true) const {
233 privSecureRead(v);
234 privNonSecureRead(v);
235 return *this;
236 }
237 chain hypRead(bool v = true) const {
238 info[MISCREG_HYP_RD] = v;
239 return *this;
240 }
241 chain hypWrite(bool v = true) const {
242 info[MISCREG_HYP_WR] = v;
243 return *this;
244 }
245 chain hyp(bool v = true) const {
246 hypRead(v);
247 hypWrite(v);
248 return *this;
249 }
250 chain monSecureRead(bool v = true) const {
251 info[MISCREG_MON_NS0_RD] = v;
252 return *this;
253 }
254 chain monSecureWrite(bool v = true) const {
255 info[MISCREG_MON_NS0_WR] = v;
256 return *this;
257 }
258 chain monNonSecureRead(bool v = true) const {
259 info[MISCREG_MON_NS1_RD] = v;
260 return *this;
261 }
262 chain monNonSecureWrite(bool v = true) const {
263 info[MISCREG_MON_NS1_WR] = v;
264 return *this;
265 }
266 chain mon(bool v = true) const {
267 monSecureRead(v);
268 monSecureWrite(v);
269 monNonSecureRead(v);
270 monNonSecureWrite(v);
271 return *this;
272 }
273 chain monSecure(bool v = true) const {
274 monSecureRead(v);
275 monSecureWrite(v);
276 return *this;
277 }
278 chain monNonSecure(bool v = true) const {
279 monNonSecureRead(v);
280 monNonSecureWrite(v);
281 return *this;
282 }
283 chain allPrivileges(bool v = true) const {
284 userNonSecureRead(v);
285 userNonSecureWrite(v);
286 userSecureRead(v);
287 userSecureWrite(v);
288 privNonSecureRead(v);
289 privNonSecureWrite(v);
290 privSecureRead(v);
291 privSecureWrite(v);
292 hypRead(v);
293 hypWrite(v);
294 monSecureRead(v);
295 monSecureWrite(v);
296 monNonSecureRead(v);
297 monNonSecureWrite(v);
298 return *this;
299 }
300 chain nonSecure(bool v = true) const {
301 userNonSecureRead(v);
302 userNonSecureWrite(v);
303 privNonSecureRead(v);
304 privNonSecureWrite(v);
305 hypRead(v);
306 hypWrite(v);
307 monNonSecureRead(v);
308 monNonSecureWrite(v);
309 return *this;
310 }
311 chain secure(bool v = true) const {
312 userSecureRead(v);
313 userSecureWrite(v);
314 privSecureRead(v);
315 privSecureWrite(v);
316 monSecureRead(v);
317 monSecureWrite(v);
318 return *this;
319 }
320 chain reads(bool v) const {
321 userNonSecureRead(v);
322 userSecureRead(v);
323 privNonSecureRead(v);
324 privSecureRead(v);
325 hypRead(v);
326 monSecureRead(v);
327 monNonSecureRead(v);
328 return *this;
329 }
330 chain writes(bool v) const {
331 userNonSecureWrite(v);
332 userSecureWrite(v);
333 privNonSecureWrite(v);
334 privSecureWrite(v);
335 hypWrite(v);
336 monSecureWrite(v);
337 monNonSecureWrite(v);
338 return *this;
339 }
340 chain exceptUserMode() const {
341 user(0);
342 return *this;
343 }
344 MiscRegLUTEntryInitializer(struct MiscRegLUTEntry &e,
345 std::bitset<NUM_MISCREG_INFOS> &i)
346 : entry(e),
347 info(i)
348 {
349 // force unimplemented registers to be thusly declared
350 implemented(1);
351 }
352 };
353
354 const MiscRegLUTEntryInitializer InitReg(uint32_t reg) {
355 return MiscRegLUTEntryInitializer(lookUpMiscReg[reg],
356 miscRegInfo[reg]);
357 }
358
359 void initializeMiscRegMetadata();
360
361 MiscReg miscRegs[NumMiscRegs];
362 const IntRegIndex *intRegMap;
363
364 void
365 updateRegMap(CPSR cpsr)
366 {
367 if (cpsr.width == 0) {
368 intRegMap = IntReg64Map;
369 } else {
370 switch (cpsr.mode) {
371 case MODE_USER:
372 case MODE_SYSTEM:
373 intRegMap = IntRegUsrMap;
374 break;
375 case MODE_FIQ:
376 intRegMap = IntRegFiqMap;
377 break;
378 case MODE_IRQ:
379 intRegMap = IntRegIrqMap;
380 break;
381 case MODE_SVC:
382 intRegMap = IntRegSvcMap;
383 break;
384 case MODE_MON:
385 intRegMap = IntRegMonMap;
386 break;
387 case MODE_ABORT:
388 intRegMap = IntRegAbtMap;
389 break;
390 case MODE_HYP:
391 intRegMap = IntRegHypMap;
392 break;
393 case MODE_UNDEFINED:
394 intRegMap = IntRegUndMap;
395 break;
396 default:
397 panic("Unrecognized mode setting in CPSR.\n");
398 }
399 }
400 }
401
402 BaseISADevice &getGenericTimer(ThreadContext *tc);
403
404
405 private:
406 inline void assert32(ThreadContext *tc) {
407 CPSR cpsr M5_VAR_USED = readMiscReg(MISCREG_CPSR, tc);
408 assert(cpsr.width);
409 }
410
411 inline void assert64(ThreadContext *tc) {
412 CPSR cpsr M5_VAR_USED = readMiscReg(MISCREG_CPSR, tc);
413 assert(!cpsr.width);
414 }
415
416 public:
417 void clear();
418
419 protected:
420 void clear32(const ArmISAParams *p, const SCTLR &sctlr_rst);
421 void clear64(const ArmISAParams *p);
422 void initID32(const ArmISAParams *p);
423 void initID64(const ArmISAParams *p);
424
425 public:
426 MiscReg readMiscRegNoEffect(int misc_reg) const;
427 MiscReg readMiscReg(int misc_reg, ThreadContext *tc);
428 void setMiscRegNoEffect(int misc_reg, const MiscReg &val);
429 void setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc);
430
431 RegId
432 flattenRegId(const RegId& regId) const
433 {
434 switch (regId.classValue()) {
435 case IntRegClass:
436 return RegId(IntRegClass, flattenIntIndex(regId.index()));
437 case FloatRegClass:
438 return RegId(FloatRegClass, flattenFloatIndex(regId.index()));
439 case VecRegClass:
440 return RegId(VecRegClass, flattenVecIndex(regId.index()));
441 case VecElemClass:
442 return RegId(VecElemClass, flattenVecElemIndex(regId.index()));
443 case CCRegClass:
444 return RegId(CCRegClass, flattenCCIndex(regId.index()));
445 case MiscRegClass:
446 return RegId(MiscRegClass, flattenMiscIndex(regId.index()));
447 }
448 return RegId();
449 }
450
451 int
452 flattenIntIndex(int reg) const
453 {
454 assert(reg >= 0);
455 if (reg < NUM_ARCH_INTREGS) {
456 return intRegMap[reg];
457 } else if (reg < NUM_INTREGS) {
458 return reg;
459 } else if (reg == INTREG_SPX) {
460 CPSR cpsr = miscRegs[MISCREG_CPSR];
461 ExceptionLevel el = opModeToEL(
462 (OperatingMode) (uint8_t) cpsr.mode);
463 if (!cpsr.sp && el != EL0)
464 return INTREG_SP0;
465 switch (el) {
466 case EL3:
467 return INTREG_SP3;
468 case EL2:
469 return INTREG_SP2;
470 case EL1:
471 return INTREG_SP1;
472 case EL0:
473 return INTREG_SP0;
474 default:
475 panic("Invalid exception level");
476 return 0; // Never happens.
477 }
478 } else {
479 return flattenIntRegModeIndex(reg);
480 }
481 }
482
483 int
484 flattenFloatIndex(int reg) const
485 {
486 assert(reg >= 0);
487 return reg;
488 }
489
490 int
491 flattenVecIndex(int reg) const
492 {
493 assert(reg >= 0);
494 return reg;
495 }
496
497 int
498 flattenVecElemIndex(int reg) const
499 {
500 assert(reg >= 0);
501 return reg;
502 }
503
504 int
505 flattenCCIndex(int reg) const
506 {
507 assert(reg >= 0);
508 return reg;
509 }
510
511 int
512 flattenMiscIndex(int reg) const
513 {
514 assert(reg >= 0);
515 int flat_idx = reg;
516
517 if (reg == MISCREG_SPSR) {
518 CPSR cpsr = miscRegs[MISCREG_CPSR];
519 switch (cpsr.mode) {
520 case MODE_EL0T:
521 warn("User mode does not have SPSR\n");
522 flat_idx = MISCREG_SPSR;
523 break;
524 case MODE_EL1T:
525 case MODE_EL1H:
526 flat_idx = MISCREG_SPSR_EL1;
527 break;
528 case MODE_EL2T:
529 case MODE_EL2H:
530 flat_idx = MISCREG_SPSR_EL2;
531 break;
532 case MODE_EL3T:
533 case MODE_EL3H:
534 flat_idx = MISCREG_SPSR_EL3;
535 break;
536 case MODE_USER:
537 warn("User mode does not have SPSR\n");
538 flat_idx = MISCREG_SPSR;
539 break;
540 case MODE_FIQ:
541 flat_idx = MISCREG_SPSR_FIQ;
542 break;
543 case MODE_IRQ:
544 flat_idx = MISCREG_SPSR_IRQ;
545 break;
546 case MODE_SVC:
547 flat_idx = MISCREG_SPSR_SVC;
548 break;
549 case MODE_MON:
550 flat_idx = MISCREG_SPSR_MON;
551 break;
552 case MODE_ABORT:
553 flat_idx = MISCREG_SPSR_ABT;
554 break;
555 case MODE_HYP:
556 flat_idx = MISCREG_SPSR_HYP;
557 break;
558 case MODE_UNDEFINED:
559 flat_idx = MISCREG_SPSR_UND;
560 break;
561 default:
562 warn("Trying to access SPSR in an invalid mode: %d\n",
563 cpsr.mode);
564 flat_idx = MISCREG_SPSR;
565 break;
566 }
567 } else if (miscRegInfo[reg][MISCREG_MUTEX]) {
568 // Mutually exclusive CP15 register
569 switch (reg) {
570 case MISCREG_PRRR_MAIR0:
571 case MISCREG_PRRR_MAIR0_NS:
572 case MISCREG_PRRR_MAIR0_S:
573 {
574 TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
575 // If the muxed reg has been flattened, work out the
576 // offset and apply it to the unmuxed reg
577 int idxOffset = reg - MISCREG_PRRR_MAIR0;
578 if (ttbcr.eae)
579 flat_idx = flattenMiscIndex(MISCREG_MAIR0 +
580 idxOffset);
581 else
582 flat_idx = flattenMiscIndex(MISCREG_PRRR +
583 idxOffset);
584 }
585 break;
586 case MISCREG_NMRR_MAIR1:
587 case MISCREG_NMRR_MAIR1_NS:
588 case MISCREG_NMRR_MAIR1_S:
589 {
590 TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
591 // If the muxed reg has been flattened, work out the
592 // offset and apply it to the unmuxed reg
593 int idxOffset = reg - MISCREG_NMRR_MAIR1;
594 if (ttbcr.eae)
595 flat_idx = flattenMiscIndex(MISCREG_MAIR1 +
596 idxOffset);
597 else
598 flat_idx = flattenMiscIndex(MISCREG_NMRR +
599 idxOffset);
600 }
601 break;
602 case MISCREG_PMXEVTYPER_PMCCFILTR:
603 {
604 PMSELR pmselr = miscRegs[MISCREG_PMSELR];
605 if (pmselr.sel == 31)
606 flat_idx = flattenMiscIndex(MISCREG_PMCCFILTR);
607 else
608 flat_idx = flattenMiscIndex(MISCREG_PMXEVTYPER);
609 }
610 break;
611 default:
612 panic("Unrecognized misc. register.\n");
613 break;
614 }
615 } else {
616 if (miscRegInfo[reg][MISCREG_BANKED]) {
617 bool secureReg = haveSecurity && !highestELIs64 &&
618 inSecureState(miscRegs[MISCREG_SCR],
619 miscRegs[MISCREG_CPSR]);
620 flat_idx += secureReg ? 2 : 1;
621 }
622 }
623 return flat_idx;
624 }
625
626 std::pair<int,int> getMiscIndices(int misc_reg) const
627 {
628 // Note: indexes of AArch64 registers are left unchanged
629 int flat_idx = flattenMiscIndex(misc_reg);
630
631 if (lookUpMiscReg[flat_idx].lower == 0) {
632 return std::make_pair(flat_idx, 0);
633 }
634
635 // do additional S/NS flattenings if mapped to NS while in S
636 bool S = haveSecurity && !highestELIs64 &&
637 inSecureState(miscRegs[MISCREG_SCR],
638 miscRegs[MISCREG_CPSR]);
639 int lower = lookUpMiscReg[flat_idx].lower;
640 int upper = lookUpMiscReg[flat_idx].upper;
641 // upper == 0, which is CPSR, is not MISCREG_BANKED_CHILD (no-op)
642 lower += S && miscRegInfo[lower][MISCREG_BANKED_CHILD];
643 upper += S && miscRegInfo[upper][MISCREG_BANKED_CHILD];
644 return std::make_pair(lower, upper);
645 }
646
647 void serialize(CheckpointOut &cp) const
648 {
649 DPRINTF(Checkpoint, "Serializing Arm Misc Registers\n");
650 SERIALIZE_ARRAY(miscRegs, NUM_PHYS_MISCREGS);
651
652 SERIALIZE_SCALAR(highestELIs64);
653 SERIALIZE_SCALAR(haveSecurity);
654 SERIALIZE_SCALAR(haveLPAE);
655 SERIALIZE_SCALAR(haveVirtualization);
656 SERIALIZE_SCALAR(haveLargeAsid64);
657 SERIALIZE_SCALAR(physAddrRange);
658 }
659 void unserialize(CheckpointIn &cp)
660 {
661 DPRINTF(Checkpoint, "Unserializing Arm Misc Registers\n");
662 UNSERIALIZE_ARRAY(miscRegs, NUM_PHYS_MISCREGS);
663 CPSR tmp_cpsr = miscRegs[MISCREG_CPSR];
664 updateRegMap(tmp_cpsr);
665
666 UNSERIALIZE_SCALAR(highestELIs64);
667 UNSERIALIZE_SCALAR(haveSecurity);
668 UNSERIALIZE_SCALAR(haveLPAE);
669 UNSERIALIZE_SCALAR(haveVirtualization);
670 UNSERIALIZE_SCALAR(haveLargeAsid64);
671 UNSERIALIZE_SCALAR(physAddrRange);
672 }
673
674 void startup(ThreadContext *tc);
675
676 Enums::DecoderFlavour decoderFlavour() const { return _decoderFlavour; }
677
678 Enums::VecRegRenameMode
679 vecRegRenameMode() const
680 {
681 return _vecRegRenameMode;
682 }
683
684 /// Explicitly import the otherwise hidden startup
685 using SimObject::startup;
686
687 typedef ArmISAParams Params;
688
689 const Params *params() const;
690
691 ISA(Params *p);
692 };
693}
694
695template<>
696struct initRenameMode<ArmISA::ISA>
697{
698 static Enums::VecRegRenameMode mode(const ArmISA::ISA* isa)
699 {
700 return isa->vecRegRenameMode();
701 }
702 static bool equals(const ArmISA::ISA* isa1, const ArmISA::ISA* isa2)
703 {
704 return mode(isa1) == mode(isa2);
705 }
706};
707
708#endif