arch: cpu: Rename *FloatRegBits* to *FloatReg*.
[gem5.git] / src / arch / arm / utility.cc
1 /*
2 * Copyright (c) 2009-2014, 2016-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 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Authors: Ali Saidi
38 */
39
40 #include "arch/arm/utility.hh"
41
42 #include <memory>
43
44 #include "arch/arm/faults.hh"
45 #include "arch/arm/isa_traits.hh"
46 #include "arch/arm/system.hh"
47 #include "arch/arm/tlb.hh"
48 #include "arch/arm/vtophys.hh"
49 #include "cpu/base.hh"
50 #include "cpu/checker/cpu.hh"
51 #include "cpu/thread_context.hh"
52 #include "mem/fs_translating_port_proxy.hh"
53 #include "sim/full_system.hh"
54
55 namespace ArmISA {
56
57 void
58 initCPU(ThreadContext *tc, int cpuId)
59 {
60 // Reset CP15?? What does that mean -- ali
61
62 // FPEXC.EN = 0
63
64 static Fault reset = std::make_shared<Reset>();
65 reset->invoke(tc);
66 }
67
68 uint64_t
69 getArgument(ThreadContext *tc, int &number, uint16_t size, bool fp)
70 {
71 if (!FullSystem) {
72 panic("getArgument() only implemented for full system mode.\n");
73 M5_DUMMY_RETURN
74 }
75
76 if (fp)
77 panic("getArgument(): Floating point arguments not implemented\n");
78
79 if (inAArch64(tc)) {
80 if (size == (uint16_t)(-1))
81 size = sizeof(uint64_t);
82
83 if (number < 8 /*NumArgumentRegs64*/) {
84 return tc->readIntReg(number);
85 } else {
86 panic("getArgument(): No support reading stack args for AArch64\n");
87 }
88 } else {
89 if (size == (uint16_t)(-1))
90 // todo: should this not be sizeof(uint32_t) rather?
91 size = ArmISA::MachineBytes;
92
93 if (number < NumArgumentRegs) {
94 // If the argument is 64 bits, it must be in an even regiser
95 // number. Increment the number here if it isn't even.
96 if (size == sizeof(uint64_t)) {
97 if ((number % 2) != 0)
98 number++;
99 // Read the two halves of the data. Number is inc here to
100 // get the second half of the 64 bit reg.
101 uint64_t tmp;
102 tmp = tc->readIntReg(number++);
103 tmp |= tc->readIntReg(number) << 32;
104 return tmp;
105 } else {
106 return tc->readIntReg(number);
107 }
108 } else {
109 Addr sp = tc->readIntReg(StackPointerReg);
110 FSTranslatingPortProxy &vp = tc->getVirtProxy();
111 uint64_t arg;
112 if (size == sizeof(uint64_t)) {
113 // If the argument is even it must be aligned
114 if ((number % 2) != 0)
115 number++;
116 arg = vp.read<uint64_t>(sp +
117 (number-NumArgumentRegs) * sizeof(uint32_t));
118 // since two 32 bit args == 1 64 bit arg, increment number
119 number++;
120 } else {
121 arg = vp.read<uint32_t>(sp +
122 (number-NumArgumentRegs) * sizeof(uint32_t));
123 }
124 return arg;
125 }
126 }
127 panic("getArgument() should always return\n");
128 }
129
130 void
131 skipFunction(ThreadContext *tc)
132 {
133 PCState newPC = tc->pcState();
134 if (inAArch64(tc)) {
135 newPC.set(tc->readIntReg(INTREG_X30));
136 } else {
137 newPC.set(tc->readIntReg(ReturnAddressReg) & ~ULL(1));
138 }
139
140 CheckerCPU *checker = tc->getCheckerCpuPtr();
141 if (checker) {
142 tc->pcStateNoRecord(newPC);
143 } else {
144 tc->pcState(newPC);
145 }
146 }
147
148 static void
149 copyVecRegs(ThreadContext *src, ThreadContext *dest)
150 {
151 auto src_mode = RenameMode<ArmISA::ISA>::mode(src->pcState());
152
153 // The way vector registers are copied (VecReg vs VecElem) is relevant
154 // in the O3 model only.
155 if (src_mode == Enums::Full) {
156 for (auto idx = 0; idx < NumVecRegs; idx++)
157 dest->setVecRegFlat(idx, src->readVecRegFlat(idx));
158 } else {
159 for (auto idx = 0; idx < NumVecRegs; idx++)
160 for (auto elem_idx = 0; elem_idx < NumVecElemPerVecReg; elem_idx++)
161 dest->setVecElemFlat(
162 idx, elem_idx, src->readVecElemFlat(idx, elem_idx));
163 }
164 }
165
166 void
167 copyRegs(ThreadContext *src, ThreadContext *dest)
168 {
169 for (int i = 0; i < NumIntRegs; i++)
170 dest->setIntRegFlat(i, src->readIntRegFlat(i));
171
172 for (int i = 0; i < NumFloatRegs; i++)
173 dest->setFloatRegFlat(i, src->readFloatRegFlat(i));
174
175 for (int i = 0; i < NumCCRegs; i++)
176 dest->setCCReg(i, src->readCCReg(i));
177
178 for (int i = 0; i < NumMiscRegs; i++)
179 dest->setMiscRegNoEffect(i, src->readMiscRegNoEffect(i));
180
181 copyVecRegs(src, dest);
182
183 // setMiscReg "with effect" will set the misc register mapping correctly.
184 // e.g. updateRegMap(val)
185 dest->setMiscReg(MISCREG_CPSR, src->readMiscRegNoEffect(MISCREG_CPSR));
186
187 // Copy over the PC State
188 dest->pcState(src->pcState());
189
190 // Invalidate the tlb misc register cache
191 dynamic_cast<TLB *>(dest->getITBPtr())->invalidateMiscReg();
192 dynamic_cast<TLB *>(dest->getDTBPtr())->invalidateMiscReg();
193 }
194
195 bool
196 inSecureState(ThreadContext *tc)
197 {
198 SCR scr = inAArch64(tc) ? tc->readMiscReg(MISCREG_SCR_EL3) :
199 tc->readMiscReg(MISCREG_SCR);
200 return ArmSystem::haveSecurity(tc) && inSecureState(
201 scr, tc->readMiscReg(MISCREG_CPSR));
202 }
203
204 inline bool
205 isSecureBelowEL3(ThreadContext *tc)
206 {
207 SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
208 return ArmSystem::haveEL(tc, EL3) && scr.ns == 0;
209 }
210
211 bool
212 inAArch64(ThreadContext *tc)
213 {
214 CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
215 return opModeIs64((OperatingMode) (uint8_t) cpsr.mode);
216 }
217
218 bool
219 longDescFormatInUse(ThreadContext *tc)
220 {
221 TTBCR ttbcr = tc->readMiscReg(MISCREG_TTBCR);
222 return ArmSystem::haveLPAE(tc) && ttbcr.eae;
223 }
224
225 RegVal
226 readMPIDR(ArmSystem *arm_sys, ThreadContext *tc)
227 {
228 CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
229 const ExceptionLevel current_el =
230 opModeToEL((OperatingMode) (uint8_t) cpsr.mode);
231
232 const bool is_secure = isSecureBelowEL3(tc);
233
234 switch (current_el) {
235 case EL0:
236 // Note: in MsrMrs instruction we read the register value before
237 // checking access permissions. This means that EL0 entry must
238 // be part of the table even if MPIDR is not accessible in user
239 // mode.
240 warn_once("Trying to read MPIDR at EL0\n");
241 M5_FALLTHROUGH;
242 case EL1:
243 if (ArmSystem::haveEL(tc, EL2) && !is_secure)
244 return tc->readMiscReg(MISCREG_VMPIDR_EL2);
245 else
246 return getMPIDR(arm_sys, tc);
247 case EL2:
248 case EL3:
249 return getMPIDR(arm_sys, tc);
250 default:
251 panic("Invalid EL for reading MPIDR register\n");
252 }
253 }
254
255 RegVal
256 getMPIDR(ArmSystem *arm_sys, ThreadContext *tc)
257 {
258 // Multiprocessor Affinity Register MPIDR from Cortex(tm)-A15 Technical
259 // Reference Manual
260 //
261 // bit 31 - Multi-processor extensions available
262 // bit 30 - Uni-processor system
263 // bit 24 - Multi-threaded cores
264 // bit 11-8 - Cluster ID
265 // bit 1-0 - CPU ID
266 //
267 // We deliberately extend both the Cluster ID and CPU ID fields to allow
268 // for simulation of larger systems
269 assert((0 <= tc->cpuId()) && (tc->cpuId() < 256));
270 assert(tc->socketId() < 65536);
271 if (arm_sys->multiThread) {
272 return 0x80000000 | // multiprocessor extensions available
273 0x01000000 | // multi-threaded cores
274 tc->contextId();
275 } else if (arm_sys->multiProc) {
276 return 0x80000000 | // multiprocessor extensions available
277 tc->cpuId() | tc->socketId() << 8;
278 } else {
279 return 0x80000000 | // multiprocessor extensions available
280 0x40000000 | // in up system
281 tc->cpuId() | tc->socketId() << 8;
282 }
283 }
284
285 bool
286 ELIs64(ThreadContext *tc, ExceptionLevel el)
287 {
288 return !ELIs32(tc, el);
289 }
290
291 bool
292 ELIs32(ThreadContext *tc, ExceptionLevel el)
293 {
294 bool known, aarch32;
295 std::tie(known, aarch32) = ELUsingAArch32K(tc, el);
296 panic_if(!known, "EL state is UNKNOWN");
297 return aarch32;
298 }
299
300 std::pair<bool, bool>
301 ELUsingAArch32K(ThreadContext *tc, ExceptionLevel el)
302 {
303 // Return true if the specified EL is in aarch32 state.
304 const bool have_el3 = ArmSystem::haveSecurity(tc);
305 const bool have_el2 = ArmSystem::haveVirtualization(tc);
306
307 panic_if(el == EL2 && !have_el2, "Asking for EL2 when it doesn't exist");
308 panic_if(el == EL3 && !have_el3, "Asking for EL3 when it doesn't exist");
309
310 bool known, aarch32;
311 known = aarch32 = false;
312 if (ArmSystem::highestELIs64(tc) && ArmSystem::highestEL(tc) == el) {
313 // Target EL is the highest one in a system where
314 // the highest is using AArch64.
315 known = true; aarch32 = false;
316 } else if (!ArmSystem::highestELIs64(tc)) {
317 // All ELs are using AArch32:
318 known = true; aarch32 = true;
319 } else {
320 SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
321 bool aarch32_below_el3 = (have_el3 && scr.rw == 0);
322
323 HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
324 bool aarch32_at_el1 = (aarch32_below_el3
325 || (have_el2
326 && !isSecureBelowEL3(tc) && hcr.rw == 0));
327
328 // Only know if EL0 using AArch32 from PSTATE
329 if (el == EL0 && !aarch32_at_el1) {
330 // EL0 controlled by PSTATE
331 CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
332
333 known = (cpsr.el == EL0);
334 aarch32 = (cpsr.width == 1);
335 } else {
336 known = true;
337 aarch32 = (aarch32_below_el3 && el != EL3)
338 || (aarch32_at_el1 && (el == EL0 || el == EL1) );
339 }
340 }
341
342 return std::make_pair(known, aarch32);
343 }
344
345 bool
346 isBigEndian64(ThreadContext *tc)
347 {
348 switch (opModeToEL(currOpMode(tc))) {
349 case EL3:
350 return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL3)).ee;
351 case EL2:
352 return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL2)).ee;
353 case EL1:
354 return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL1)).ee;
355 case EL0:
356 return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL1)).e0e;
357 default:
358 panic("Invalid exception level");
359 break;
360 }
361 }
362
363 bool
364 badMode32(ThreadContext *tc, OperatingMode mode)
365 {
366 return unknownMode32(mode) || !ArmSystem::haveEL(tc, opModeToEL(mode));
367 }
368
369 bool
370 badMode(ThreadContext *tc, OperatingMode mode)
371 {
372 return unknownMode(mode) || !ArmSystem::haveEL(tc, opModeToEL(mode));
373 }
374
375 Addr
376 purifyTaggedAddr(Addr addr, ThreadContext *tc, ExceptionLevel el,
377 TTBCR tcr)
378 {
379 switch (el) {
380 case EL0:
381 case EL1:
382 if (bits(addr, 55, 48) == 0xFF && tcr.tbi1)
383 return addr | mask(63, 55);
384 else if (!bits(addr, 55, 48) && tcr.tbi0)
385 return bits(addr,55, 0);
386 break;
387 case EL2:
388 assert(ArmSystem::haveVirtualization(tc));
389 tcr = tc->readMiscReg(MISCREG_TCR_EL2);
390 if (tcr.tbi)
391 return addr & mask(56);
392 break;
393 case EL3:
394 assert(ArmSystem::haveSecurity(tc));
395 if (tcr.tbi)
396 return addr & mask(56);
397 break;
398 default:
399 panic("Invalid exception level");
400 break;
401 }
402
403 return addr; // Nothing to do if this is not a tagged address
404 }
405
406 Addr
407 purifyTaggedAddr(Addr addr, ThreadContext *tc, ExceptionLevel el)
408 {
409 TTBCR tcr;
410
411 switch (el) {
412 case EL0:
413 case EL1:
414 tcr = tc->readMiscReg(MISCREG_TCR_EL1);
415 if (bits(addr, 55, 48) == 0xFF && tcr.tbi1)
416 return addr | mask(63, 55);
417 else if (!bits(addr, 55, 48) && tcr.tbi0)
418 return bits(addr,55, 0);
419 break;
420 case EL2:
421 assert(ArmSystem::haveVirtualization(tc));
422 tcr = tc->readMiscReg(MISCREG_TCR_EL2);
423 if (tcr.tbi)
424 return addr & mask(56);
425 break;
426 case EL3:
427 assert(ArmSystem::haveSecurity(tc));
428 tcr = tc->readMiscReg(MISCREG_TCR_EL3);
429 if (tcr.tbi)
430 return addr & mask(56);
431 break;
432 default:
433 panic("Invalid exception level");
434 break;
435 }
436
437 return addr; // Nothing to do if this is not a tagged address
438 }
439
440 Addr
441 truncPage(Addr addr)
442 {
443 return addr & ~(PageBytes - 1);
444 }
445
446 Addr
447 roundPage(Addr addr)
448 {
449 return (addr + PageBytes - 1) & ~(PageBytes - 1);
450 }
451
452 bool
453 mcrMrc15TrapToHyp(const MiscRegIndex miscReg, HCR hcr, CPSR cpsr, SCR scr,
454 HDCR hdcr, HSTR hstr, HCPTR hcptr, uint32_t iss)
455 {
456 bool isRead;
457 uint32_t crm;
458 IntRegIndex rt;
459 uint32_t crn;
460 uint32_t opc1;
461 uint32_t opc2;
462 bool trapToHype = false;
463
464
465 if (!inSecureState(scr, cpsr) && (cpsr.mode != MODE_HYP)) {
466 mcrMrcIssExtract(iss, isRead, crm, rt, crn, opc1, opc2);
467 trapToHype = ((uint32_t) hstr) & (1 << crn);
468 trapToHype |= hdcr.tpm && (crn == 9) && (crm >= 12);
469 trapToHype |= hcr.tidcp && (
470 ((crn == 9) && ((crm <= 2) || ((crm >= 5) && (crm <= 8)))) ||
471 ((crn == 10) && ((crm <= 1) || (crm == 4) || (crm == 8))) ||
472 ((crn == 11) && ((crm <= 8) || (crm == 15))) );
473
474 if (!trapToHype) {
475 switch (unflattenMiscReg(miscReg)) {
476 case MISCREG_CPACR:
477 trapToHype = hcptr.tcpac;
478 break;
479 case MISCREG_REVIDR:
480 case MISCREG_TCMTR:
481 case MISCREG_TLBTR:
482 case MISCREG_AIDR:
483 trapToHype = hcr.tid1;
484 break;
485 case MISCREG_CTR:
486 case MISCREG_CCSIDR:
487 case MISCREG_CLIDR:
488 case MISCREG_CSSELR:
489 trapToHype = hcr.tid2;
490 break;
491 case MISCREG_ID_PFR0:
492 case MISCREG_ID_PFR1:
493 case MISCREG_ID_DFR0:
494 case MISCREG_ID_AFR0:
495 case MISCREG_ID_MMFR0:
496 case MISCREG_ID_MMFR1:
497 case MISCREG_ID_MMFR2:
498 case MISCREG_ID_MMFR3:
499 case MISCREG_ID_ISAR0:
500 case MISCREG_ID_ISAR1:
501 case MISCREG_ID_ISAR2:
502 case MISCREG_ID_ISAR3:
503 case MISCREG_ID_ISAR4:
504 case MISCREG_ID_ISAR5:
505 trapToHype = hcr.tid3;
506 break;
507 case MISCREG_DCISW:
508 case MISCREG_DCCSW:
509 case MISCREG_DCCISW:
510 trapToHype = hcr.tsw;
511 break;
512 case MISCREG_DCIMVAC:
513 case MISCREG_DCCIMVAC:
514 case MISCREG_DCCMVAC:
515 trapToHype = hcr.tpc;
516 break;
517 case MISCREG_ICIMVAU:
518 case MISCREG_ICIALLU:
519 case MISCREG_ICIALLUIS:
520 case MISCREG_DCCMVAU:
521 trapToHype = hcr.tpu;
522 break;
523 case MISCREG_TLBIALLIS:
524 case MISCREG_TLBIMVAIS:
525 case MISCREG_TLBIASIDIS:
526 case MISCREG_TLBIMVAAIS:
527 case MISCREG_TLBIMVALIS:
528 case MISCREG_TLBIMVAALIS:
529 case MISCREG_DTLBIALL:
530 case MISCREG_ITLBIALL:
531 case MISCREG_DTLBIMVA:
532 case MISCREG_ITLBIMVA:
533 case MISCREG_DTLBIASID:
534 case MISCREG_ITLBIASID:
535 case MISCREG_TLBIMVAA:
536 case MISCREG_TLBIALL:
537 case MISCREG_TLBIMVA:
538 case MISCREG_TLBIMVAL:
539 case MISCREG_TLBIMVAAL:
540 case MISCREG_TLBIASID:
541 trapToHype = hcr.ttlb;
542 break;
543 case MISCREG_ACTLR:
544 trapToHype = hcr.tac;
545 break;
546 case MISCREG_SCTLR:
547 case MISCREG_TTBR0:
548 case MISCREG_TTBR1:
549 case MISCREG_TTBCR:
550 case MISCREG_DACR:
551 case MISCREG_DFSR:
552 case MISCREG_IFSR:
553 case MISCREG_DFAR:
554 case MISCREG_IFAR:
555 case MISCREG_ADFSR:
556 case MISCREG_AIFSR:
557 case MISCREG_PRRR:
558 case MISCREG_NMRR:
559 case MISCREG_MAIR0:
560 case MISCREG_MAIR1:
561 case MISCREG_CONTEXTIDR:
562 trapToHype = hcr.tvm & !isRead;
563 break;
564 case MISCREG_PMCR:
565 trapToHype = hdcr.tpmcr;
566 break;
567 // No default action needed
568 default:
569 break;
570 }
571 }
572 }
573 return trapToHype;
574 }
575
576
577 bool
578 mcrMrc14TrapToHyp(const MiscRegIndex miscReg, HCR hcr, CPSR cpsr, SCR scr,
579 HDCR hdcr, HSTR hstr, HCPTR hcptr, uint32_t iss)
580 {
581 bool isRead;
582 uint32_t crm;
583 IntRegIndex rt;
584 uint32_t crn;
585 uint32_t opc1;
586 uint32_t opc2;
587 bool trapToHype = false;
588
589 if (!inSecureState(scr, cpsr) && (cpsr.mode != MODE_HYP)) {
590 mcrMrcIssExtract(iss, isRead, crm, rt, crn, opc1, opc2);
591 inform("trap check M:%x N:%x 1:%x 2:%x hdcr %x, hcptr %x, hstr %x\n",
592 crm, crn, opc1, opc2, hdcr, hcptr, hstr);
593 trapToHype = hdcr.tda && (opc1 == 0);
594 trapToHype |= hcptr.tta && (opc1 == 1);
595 if (!trapToHype) {
596 switch (unflattenMiscReg(miscReg)) {
597 case MISCREG_DBGOSLSR:
598 case MISCREG_DBGOSLAR:
599 case MISCREG_DBGOSDLR:
600 case MISCREG_DBGPRCR:
601 trapToHype = hdcr.tdosa;
602 break;
603 case MISCREG_DBGDRAR:
604 case MISCREG_DBGDSAR:
605 trapToHype = hdcr.tdra;
606 break;
607 case MISCREG_JIDR:
608 trapToHype = hcr.tid0;
609 break;
610 case MISCREG_JOSCR:
611 case MISCREG_JMCR:
612 trapToHype = hstr.tjdbx;
613 break;
614 case MISCREG_TEECR:
615 case MISCREG_TEEHBR:
616 trapToHype = hstr.ttee;
617 break;
618 // No default action needed
619 default:
620 break;
621 }
622 }
623 }
624 return trapToHype;
625 }
626
627 bool
628 mcrrMrrc15TrapToHyp(const MiscRegIndex miscReg, CPSR cpsr, SCR scr, HSTR hstr,
629 HCR hcr, uint32_t iss)
630 {
631 uint32_t crm;
632 IntRegIndex rt;
633 uint32_t crn;
634 uint32_t opc1;
635 uint32_t opc2;
636 bool isRead;
637 bool trapToHype = false;
638
639 if (!inSecureState(scr, cpsr) && (cpsr.mode != MODE_HYP)) {
640 // This is technically the wrong function, but we can re-use it for
641 // the moment because we only need one field, which overlaps with the
642 // mcrmrc layout
643 mcrMrcIssExtract(iss, isRead, crm, rt, crn, opc1, opc2);
644 trapToHype = ((uint32_t) hstr) & (1 << crm);
645
646 if (!trapToHype) {
647 switch (unflattenMiscReg(miscReg)) {
648 case MISCREG_SCTLR:
649 case MISCREG_TTBR0:
650 case MISCREG_TTBR1:
651 case MISCREG_TTBCR:
652 case MISCREG_DACR:
653 case MISCREG_DFSR:
654 case MISCREG_IFSR:
655 case MISCREG_DFAR:
656 case MISCREG_IFAR:
657 case MISCREG_ADFSR:
658 case MISCREG_AIFSR:
659 case MISCREG_PRRR:
660 case MISCREG_NMRR:
661 case MISCREG_MAIR0:
662 case MISCREG_MAIR1:
663 case MISCREG_CONTEXTIDR:
664 trapToHype = hcr.tvm & !isRead;
665 break;
666 // No default action needed
667 default:
668 break;
669 }
670 }
671 }
672 return trapToHype;
673 }
674
675 bool
676 decodeMrsMsrBankedReg(uint8_t sysM, bool r, bool &isIntReg, int &regIdx,
677 CPSR cpsr, SCR scr, NSACR nsacr, bool checkSecurity)
678 {
679 OperatingMode mode = MODE_UNDEFINED;
680 bool ok = true;
681
682 // R mostly indicates if its a int register or a misc reg, we override
683 // below if the few corner cases
684 isIntReg = !r;
685 // Loosely based on ARM ARM issue C section B9.3.10
686 if (r) {
687 switch (sysM)
688 {
689 case 0xE:
690 regIdx = MISCREG_SPSR_FIQ;
691 mode = MODE_FIQ;
692 break;
693 case 0x10:
694 regIdx = MISCREG_SPSR_IRQ;
695 mode = MODE_IRQ;
696 break;
697 case 0x12:
698 regIdx = MISCREG_SPSR_SVC;
699 mode = MODE_SVC;
700 break;
701 case 0x14:
702 regIdx = MISCREG_SPSR_ABT;
703 mode = MODE_ABORT;
704 break;
705 case 0x16:
706 regIdx = MISCREG_SPSR_UND;
707 mode = MODE_UNDEFINED;
708 break;
709 case 0x1C:
710 regIdx = MISCREG_SPSR_MON;
711 mode = MODE_MON;
712 break;
713 case 0x1E:
714 regIdx = MISCREG_SPSR_HYP;
715 mode = MODE_HYP;
716 break;
717 default:
718 ok = false;
719 break;
720 }
721 } else {
722 int sysM4To3 = bits(sysM, 4, 3);
723
724 if (sysM4To3 == 0) {
725 mode = MODE_USER;
726 regIdx = intRegInMode(mode, bits(sysM, 2, 0) + 8);
727 } else if (sysM4To3 == 1) {
728 mode = MODE_FIQ;
729 regIdx = intRegInMode(mode, bits(sysM, 2, 0) + 8);
730 } else if (sysM4To3 == 3) {
731 if (bits(sysM, 1) == 0) {
732 mode = MODE_MON;
733 regIdx = intRegInMode(mode, 14 - bits(sysM, 0));
734 } else {
735 mode = MODE_HYP;
736 if (bits(sysM, 0) == 1) {
737 regIdx = intRegInMode(mode, 13); // R13 in HYP
738 } else {
739 isIntReg = false;
740 regIdx = MISCREG_ELR_HYP;
741 }
742 }
743 } else { // Other Banked registers
744 int sysM2 = bits(sysM, 2);
745 int sysM1 = bits(sysM, 1);
746
747 mode = (OperatingMode) ( ((sysM2 || sysM1) << 0) |
748 (1 << 1) |
749 ((sysM2 && !sysM1) << 2) |
750 ((sysM2 && sysM1) << 3) |
751 (1 << 4) );
752 regIdx = intRegInMode(mode, 14 - bits(sysM, 0));
753 // Don't flatten the register here. This is going to go through
754 // setIntReg() which will do the flattening
755 ok &= mode != cpsr.mode;
756 }
757 }
758
759 // Check that the requested register is accessable from the current mode
760 if (ok && checkSecurity && mode != cpsr.mode) {
761 switch (cpsr.mode)
762 {
763 case MODE_USER:
764 ok = false;
765 break;
766 case MODE_FIQ:
767 ok &= mode != MODE_HYP;
768 ok &= (mode != MODE_MON) || !scr.ns;
769 break;
770 case MODE_HYP:
771 ok &= mode != MODE_MON;
772 ok &= (mode != MODE_FIQ) || !nsacr.rfr;
773 break;
774 case MODE_IRQ:
775 case MODE_SVC:
776 case MODE_ABORT:
777 case MODE_UNDEFINED:
778 case MODE_SYSTEM:
779 ok &= mode != MODE_HYP;
780 ok &= (mode != MODE_MON) || !scr.ns;
781 ok &= (mode != MODE_FIQ) || !nsacr.rfr;
782 break;
783 // can access everything, no further checks required
784 case MODE_MON:
785 break;
786 default:
787 panic("unknown Mode 0x%x\n", cpsr.mode);
788 break;
789 }
790 }
791 return (ok);
792 }
793
794 bool
795 SPAlignmentCheckEnabled(ThreadContext* tc)
796 {
797 switch (opModeToEL(currOpMode(tc))) {
798 case EL3:
799 return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL3)).sa;
800 case EL2:
801 return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL2)).sa;
802 case EL1:
803 return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL1)).sa;
804 case EL0:
805 return ((SCTLR) tc->readMiscReg(MISCREG_SCTLR_EL1)).sa0;
806 default:
807 panic("Invalid exception level");
808 break;
809 }
810 }
811
812 int
813 decodePhysAddrRange64(uint8_t pa_enc)
814 {
815 switch (pa_enc) {
816 case 0x0:
817 return 32;
818 case 0x1:
819 return 36;
820 case 0x2:
821 return 40;
822 case 0x3:
823 return 42;
824 case 0x4:
825 return 44;
826 case 0x5:
827 case 0x6:
828 case 0x7:
829 return 48;
830 default:
831 panic("Invalid phys. address range encoding");
832 }
833 }
834
835 uint8_t
836 encodePhysAddrRange64(int pa_size)
837 {
838 switch (pa_size) {
839 case 32:
840 return 0x0;
841 case 36:
842 return 0x1;
843 case 40:
844 return 0x2;
845 case 42:
846 return 0x3;
847 case 44:
848 return 0x4;
849 case 48:
850 return 0x5;
851 default:
852 panic("Invalid phys. address range");
853 }
854 }
855
856 } // namespace ArmISA