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