gem5  v19.0.0.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
faults.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010, 2012-2014, 2016-2019 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) 2003-2005 The Regents of The University of Michigan
15  * Copyright (c) 2007-2008 The Florida State University
16  * All rights reserved.
17  *
18  * Redistribution and use in source and binary forms, with or without
19  * modification, are permitted provided that the following conditions are
20  * met: redistributions of source code must retain the above copyright
21  * notice, this list of conditions and the following disclaimer;
22  * redistributions in binary form must reproduce the above copyright
23  * notice, this list of conditions and the following disclaimer in the
24  * documentation and/or other materials provided with the distribution;
25  * neither the name of the copyright holders nor the names of its
26  * contributors may be used to endorse or promote products derived from
27  * this software without specific prior written permission.
28  *
29  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40  *
41  * Authors: Ali Saidi
42  * Gabe Black
43  * Giacomo Gabrielli
44  * Thomas Grocutt
45  */
46 
47 #include "arch/arm/faults.hh"
48 
50 #include "arch/arm/system.hh"
51 #include "arch/arm/utility.hh"
52 #include "base/compiler.hh"
53 #include "base/trace.hh"
54 #include "cpu/base.hh"
55 #include "cpu/thread_context.hh"
56 #include "debug/Faults.hh"
57 #include "sim/full_system.hh"
58 
59 namespace ArmISA
60 {
61 
63  0x01, // AlignmentFault
64  0x04, // InstructionCacheMaintenance
65  0xff, // SynchExtAbtOnTranslTableWalkL0 (INVALID)
66  0x0c, // SynchExtAbtOnTranslTableWalkL1
67  0x0e, // SynchExtAbtOnTranslTableWalkL2
68  0xff, // SynchExtAbtOnTranslTableWalkL3 (INVALID)
69  0xff, // SynchPtyErrOnTranslTableWalkL0 (INVALID)
70  0x1c, // SynchPtyErrOnTranslTableWalkL1
71  0x1e, // SynchPtyErrOnTranslTableWalkL2
72  0xff, // SynchPtyErrOnTranslTableWalkL3 (INVALID)
73  0xff, // TranslationL0 (INVALID)
74  0x05, // TranslationL1
75  0x07, // TranslationL2
76  0xff, // TranslationL3 (INVALID)
77  0xff, // AccessFlagL0 (INVALID)
78  0x03, // AccessFlagL1
79  0x06, // AccessFlagL2
80  0xff, // AccessFlagL3 (INVALID)
81  0xff, // DomainL0 (INVALID)
82  0x09, // DomainL1
83  0x0b, // DomainL2
84  0xff, // DomainL3 (INVALID)
85  0xff, // PermissionL0 (INVALID)
86  0x0d, // PermissionL1
87  0x0f, // PermissionL2
88  0xff, // PermissionL3 (INVALID)
89  0x02, // DebugEvent
90  0x08, // SynchronousExternalAbort
91  0x10, // TLBConflictAbort
92  0x19, // SynchPtyErrOnMemoryAccess
93  0x16, // AsynchronousExternalAbort
94  0x18, // AsynchPtyErrOnMemoryAccess
95  0xff, // AddressSizeL0 (INVALID)
96  0xff, // AddressSizeL1 (INVALID)
97  0xff, // AddressSizeL2 (INVALID)
98  0xff, // AddressSizeL3 (INVALID)
99  0x40, // PrefetchTLBMiss
100  0x80 // PrefetchUncacheable
101 };
102 
103 static_assert(sizeof(ArmFault::shortDescFaultSources) ==
105  "Invalid size of ArmFault::shortDescFaultSources[]");
106 
107 uint8_t ArmFault::longDescFaultSources[] = {
108  0x21, // AlignmentFault
109  0xff, // InstructionCacheMaintenance (INVALID)
110  0xff, // SynchExtAbtOnTranslTableWalkL0 (INVALID)
111  0x15, // SynchExtAbtOnTranslTableWalkL1
112  0x16, // SynchExtAbtOnTranslTableWalkL2
113  0x17, // SynchExtAbtOnTranslTableWalkL3
114  0xff, // SynchPtyErrOnTranslTableWalkL0 (INVALID)
115  0x1d, // SynchPtyErrOnTranslTableWalkL1
116  0x1e, // SynchPtyErrOnTranslTableWalkL2
117  0x1f, // SynchPtyErrOnTranslTableWalkL3
118  0xff, // TranslationL0 (INVALID)
119  0x05, // TranslationL1
120  0x06, // TranslationL2
121  0x07, // TranslationL3
122  0xff, // AccessFlagL0 (INVALID)
123  0x09, // AccessFlagL1
124  0x0a, // AccessFlagL2
125  0x0b, // AccessFlagL3
126  0xff, // DomainL0 (INVALID)
127  0x3d, // DomainL1
128  0x3e, // DomainL2
129  0xff, // DomainL3 (RESERVED)
130  0xff, // PermissionL0 (INVALID)
131  0x0d, // PermissionL1
132  0x0e, // PermissionL2
133  0x0f, // PermissionL3
134  0x22, // DebugEvent
135  0x10, // SynchronousExternalAbort
136  0x30, // TLBConflictAbort
137  0x18, // SynchPtyErrOnMemoryAccess
138  0x11, // AsynchronousExternalAbort
139  0x19, // AsynchPtyErrOnMemoryAccess
140  0xff, // AddressSizeL0 (INVALID)
141  0xff, // AddressSizeL1 (INVALID)
142  0xff, // AddressSizeL2 (INVALID)
143  0xff, // AddressSizeL3 (INVALID)
144  0x40, // PrefetchTLBMiss
145  0x80 // PrefetchUncacheable
146 };
147 
148 static_assert(sizeof(ArmFault::longDescFaultSources) ==
150  "Invalid size of ArmFault::longDescFaultSources[]");
151 
152 uint8_t ArmFault::aarch64FaultSources[] = {
153  0x21, // AlignmentFault
154  0xff, // InstructionCacheMaintenance (INVALID)
155  0x14, // SynchExtAbtOnTranslTableWalkL0
156  0x15, // SynchExtAbtOnTranslTableWalkL1
157  0x16, // SynchExtAbtOnTranslTableWalkL2
158  0x17, // SynchExtAbtOnTranslTableWalkL3
159  0x1c, // SynchPtyErrOnTranslTableWalkL0
160  0x1d, // SynchPtyErrOnTranslTableWalkL1
161  0x1e, // SynchPtyErrOnTranslTableWalkL2
162  0x1f, // SynchPtyErrOnTranslTableWalkL3
163  0x04, // TranslationL0
164  0x05, // TranslationL1
165  0x06, // TranslationL2
166  0x07, // TranslationL3
167  0x08, // AccessFlagL0
168  0x09, // AccessFlagL1
169  0x0a, // AccessFlagL2
170  0x0b, // AccessFlagL3
171  // @todo: Section & Page Domain Fault in AArch64?
172  0xff, // DomainL0 (INVALID)
173  0xff, // DomainL1 (INVALID)
174  0xff, // DomainL2 (INVALID)
175  0xff, // DomainL3 (INVALID)
176  0x0c, // PermissionL0
177  0x0d, // PermissionL1
178  0x0e, // PermissionL2
179  0x0f, // PermissionL3
180  0x22, // DebugEvent
181  0x10, // SynchronousExternalAbort
182  0x30, // TLBConflictAbort
183  0x18, // SynchPtyErrOnMemoryAccess
184  0xff, // AsynchronousExternalAbort (INVALID)
185  0xff, // AsynchPtyErrOnMemoryAccess (INVALID)
186  0x00, // AddressSizeL0
187  0x01, // AddressSizeL1
188  0x02, // AddressSizeL2
189  0x03, // AddressSizeL3
190  0x40, // PrefetchTLBMiss
191  0x80 // PrefetchUncacheable
192 };
193 
194 static_assert(sizeof(ArmFault::aarch64FaultSources) ==
196  "Invalid size of ArmFault::aarch64FaultSources[]");
197 
198 // Fields: name, offset, cur{ELT,ELH}Offset, lowerEL{64,32}Offset, next mode,
199 // {ARM, Thumb, ARM_ELR, Thumb_ELR} PC offset, hyp trap,
200 // {A, F} disable, class, stat
202  // Some dummy values (the reset vector has an IMPLEMENTATION DEFINED
203  // location in AArch64)
204  "Reset", 0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC,
205  0, 0, 0, 0, false, true, true, EC_UNKNOWN
206 );
208  "Undefined Instruction", 0x004, 0x000, 0x200, 0x400, 0x600, MODE_UNDEFINED,
209  4, 2, 0, 0, true, false, false, EC_UNKNOWN
210 );
212  "Supervisor Call", 0x008, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
213  4, 2, 4, 2, true, false, false, EC_SVC_TO_HYP
214 );
216  "Secure Monitor Call", 0x008, 0x000, 0x200, 0x400, 0x600, MODE_MON,
217  4, 4, 4, 4, false, true, true, EC_SMC_TO_HYP
218 );
220  "Hypervisor Call", 0x008, 0x000, 0x200, 0x400, 0x600, MODE_HYP,
221  4, 4, 4, 4, true, false, false, EC_HVC
222 );
224  "Prefetch Abort", 0x00C, 0x000, 0x200, 0x400, 0x600, MODE_ABORT,
225  4, 4, 0, 0, true, true, false, EC_PREFETCH_ABORT_TO_HYP
226 );
228  "Data Abort", 0x010, 0x000, 0x200, 0x400, 0x600, MODE_ABORT,
229  8, 8, 0, 0, true, true, false, EC_DATA_ABORT_TO_HYP
230 );
232  "Virtual Data Abort", 0x010, 0x000, 0x200, 0x400, 0x600, MODE_ABORT,
233  8, 8, 0, 0, true, true, false, EC_INVALID
234 );
236  // @todo: double check these values
237  "Hypervisor Trap", 0x014, 0x000, 0x200, 0x400, 0x600, MODE_HYP,
238  0, 0, 0, 0, false, false, false, EC_UNKNOWN
239 );
241  "Secure Monitor Trap", 0x004, 0x000, 0x200, 0x400, 0x600, MODE_MON,
242  4, 2, 0, 0, false, false, false, EC_UNKNOWN
243 );
245  "IRQ", 0x018, 0x080, 0x280, 0x480, 0x680, MODE_IRQ,
246  4, 4, 0, 0, false, true, false, EC_UNKNOWN
247 );
249  "Virtual IRQ", 0x018, 0x080, 0x280, 0x480, 0x680, MODE_IRQ,
250  4, 4, 0, 0, false, true, false, EC_INVALID
251 );
253  "FIQ", 0x01C, 0x100, 0x300, 0x500, 0x700, MODE_FIQ,
254  4, 4, 0, 0, false, true, true, EC_UNKNOWN
255 );
257  "Virtual FIQ", 0x01C, 0x100, 0x300, 0x500, 0x700, MODE_FIQ,
258  4, 4, 0, 0, false, true, true, EC_INVALID
259 );
261  "Illegal Inst Set State Fault", 0x004, 0x000, 0x200, 0x400, 0x600, MODE_UNDEFINED,
262  4, 2, 0, 0, true, false, false, EC_ILLEGAL_INST
263 );
265  // Some dummy values (SupervisorTrap is AArch64-only)
266  "Supervisor Trap", 0x014, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
267  0, 0, 0, 0, false, false, false, EC_UNKNOWN
268 );
270  // Some dummy values (PCAlignmentFault is AArch64-only)
271  "PC Alignment Fault", 0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
272  0, 0, 0, 0, true, false, false, EC_PC_ALIGNMENT
273 );
275  // Some dummy values (SPAlignmentFault is AArch64-only)
276  "SP Alignment Fault", 0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
277  0, 0, 0, 0, true, false, false, EC_STACK_PTR_ALIGNMENT
278 );
280  // Some dummy values (SError is AArch64-only)
281  "SError", 0x000, 0x180, 0x380, 0x580, 0x780, MODE_SVC,
282  0, 0, 0, 0, false, true, true, EC_SERROR
283 );
285  // Some dummy values (SoftwareBreakpoint is AArch64-only)
286  "Software Breakpoint", 0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
287  0, 0, 0, 0, true, false, false, EC_SOFTWARE_BREAKPOINT
288 );
290  // Some dummy values
291  "ArmSev Flush", 0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC,
292  0, 0, 0, 0, false, true, true, EC_UNKNOWN
293 );
294 
295 Addr
297 {
298  Addr base;
299 
300  // Check for invalid modes
301  CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
302  assert(ArmSystem::haveSecurity(tc) || cpsr.mode != MODE_MON);
303  assert(ArmSystem::haveVirtualization(tc) || cpsr.mode != MODE_HYP);
304 
305  switch (cpsr.mode)
306  {
307  case MODE_MON:
308  base = tc->readMiscReg(MISCREG_MVBAR);
309  break;
310  case MODE_HYP:
311  base = tc->readMiscReg(MISCREG_HVBAR);
312  break;
313  default:
314  SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
315  if (sctlr.v) {
316  base = HighVecs;
317  } else {
318  base = ArmSystem::haveSecurity(tc) ?
319  tc->readMiscReg(MISCREG_VBAR) : 0;
320  }
321  break;
322  }
323 
324  return base + offset(tc);
325 }
326 
327 Addr
329 {
330  Addr vbar;
331  switch (toEL) {
332  case EL3:
333  assert(ArmSystem::haveSecurity(tc));
334  vbar = tc->readMiscReg(MISCREG_VBAR_EL3);
335  break;
336  case EL2:
337  assert(ArmSystem::haveVirtualization(tc));
338  vbar = tc->readMiscReg(MISCREG_VBAR_EL2);
339  break;
340  case EL1:
341  vbar = tc->readMiscReg(MISCREG_VBAR_EL1);
342  break;
343  default:
344  panic("Invalid target exception level");
345  break;
346  }
347  return vbar + offset64(tc);
348 }
349 
352 {
353  switch (toEL) {
354  case EL1:
355  return MISCREG_ESR_EL1;
356  case EL2:
357  return MISCREG_ESR_EL2;
358  case EL3:
359  return MISCREG_ESR_EL3;
360  default:
361  panic("Invalid exception level");
362  break;
363  }
364 }
365 
368 {
369  switch (toEL) {
370  case EL1:
371  return MISCREG_FAR_EL1;
372  case EL2:
373  return MISCREG_FAR_EL2;
374  case EL3:
375  return MISCREG_FAR_EL3;
376  default:
377  panic("Invalid exception level");
378  break;
379  }
380 }
381 
382 void
384 {
385  uint32_t value;
386  uint32_t exc_class = (uint32_t) ec(tc);
387  uint32_t issVal = iss();
388 
389  assert(!from64 || ArmSystem::highestELIs64(tc));
390 
391  value = exc_class << 26;
392 
393  // HSR.IL not valid for Prefetch Aborts (0x20, 0x21) and Data Aborts (0x24,
394  // 0x25) for which the ISS information is not valid (ARMv7).
395  // @todo: ARMv8 revises AArch32 functionality: when HSR.IL is not
396  // valid it is treated as RES1.
397  if (to64) {
398  value |= 1 << 25;
399  } else if ((bits(exc_class, 5, 3) != 4) ||
400  (bits(exc_class, 2) && bits(issVal, 24))) {
401  if (!machInst.thumb || machInst.bigThumb)
402  value |= 1 << 25;
403  }
404  // Condition code valid for EC[5:4] nonzero
405  if (!from64 && ((bits(exc_class, 5, 4) == 0) &&
406  (bits(exc_class, 3, 0) != 0))) {
407  if (!machInst.thumb) {
408  uint32_t cond;
409  ConditionCode condCode = (ConditionCode) (uint32_t) machInst.condCode;
410  // If its on unconditional instruction report with a cond code of
411  // 0xE, ie the unconditional code
412  cond = (condCode == COND_UC) ? COND_AL : condCode;
413  value |= cond << 20;
414  value |= 1 << 24;
415  }
416  value |= bits(issVal, 19, 0);
417  } else {
418  value |= issVal;
419  }
420  tc->setMiscReg(syndrome_reg, value);
421 }
422 
423 void
425 {
426  CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
427 
428  // Determine source exception level and mode
429  fromMode = (OperatingMode) (uint8_t) cpsr.mode;
431  if (opModeIs64(fromMode))
432  from64 = true;
433 
434  // Determine target exception level (aarch64) or target execution
435  // mode (aarch32).
436  if (ArmSystem::haveSecurity(tc) && routeToMonitor(tc)) {
437  toMode = MODE_MON;
438  toEL = EL3;
439  } else if (ArmSystem::haveVirtualization(tc) && routeToHyp(tc)) {
440  toMode = MODE_HYP;
441  toEL = EL2;
442  hypRouted = true;
443  } else {
444  toMode = nextMode();
446  }
447 
448  if (fromEL > toEL)
449  toEL = fromEL;
450 
451  // Check for Set Priviledge Access Never, if PAN is supported
452  AA64MMFR1 mmfr1 = tc->readMiscReg(MISCREG_ID_AA64MMFR1_EL1);
453  if (mmfr1.pan) {
454  if (toEL == EL1) {
455  const SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR_EL1);
456  span = !sctlr.span;
457  }
458 
459  const HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR_EL2);
460  if (toEL == EL2 && hcr.e2h && hcr.tge) {
461  const SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR_EL2);
462  span = !sctlr.span;
463  }
464  }
465 
466  to64 = ELIs64(tc, toEL);
467 
468  // The fault specific informations have been updated; it is
469  // now possible to use them inside the fault.
470  faultUpdated = true;
471 }
472 
473 void
475 {
476 
477  // Update fault state informations, like the starting mode (aarch32)
478  // or EL (aarch64) and the ending mode or EL.
479  // From the update function we are also evaluating if the fault must
480  // be handled in AArch64 mode (to64).
481  update(tc);
482 
483  if (to64) {
484  // Invoke exception handler in AArch64 state
485  invoke64(tc, inst);
486  return;
487  }
488 
489  // ARMv7 (ARM ARM issue C B1.9)
490 
491  bool have_security = ArmSystem::haveSecurity(tc);
492 
493  FaultBase::invoke(tc);
494  if (!FullSystem)
495  return;
496  countStat()++;
497 
498  SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
499  SCR scr = tc->readMiscReg(MISCREG_SCR);
500  CPSR saved_cpsr = tc->readMiscReg(MISCREG_CPSR);
501  saved_cpsr.nz = tc->readCCReg(CCREG_NZ);
502  saved_cpsr.c = tc->readCCReg(CCREG_C);
503  saved_cpsr.v = tc->readCCReg(CCREG_V);
504  saved_cpsr.ge = tc->readCCReg(CCREG_GE);
505 
506  Addr curPc M5_VAR_USED = tc->pcState().pc();
507  ITSTATE it = tc->pcState().itstate();
508  saved_cpsr.it2 = it.top6;
509  saved_cpsr.it1 = it.bottom2;
510 
511  // if we have a valid instruction then use it to annotate this fault with
512  // extra information. This is used to generate the correct fault syndrome
513  // information
514  ArmStaticInst *arm_inst M5_VAR_USED = instrAnnotate(inst);
515 
516  // Ensure Secure state if initially in Monitor mode
517  if (have_security && saved_cpsr.mode == MODE_MON) {
518  SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
519  if (scr.ns) {
520  scr.ns = 0;
522  }
523  }
524 
525  CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
526  cpsr.mode = toMode;
527 
528  // some bits are set differently if we have been routed to hyp mode
529  if (cpsr.mode == MODE_HYP) {
530  SCTLR hsctlr = tc->readMiscReg(MISCREG_HSCTLR);
531  cpsr.t = hsctlr.te;
532  cpsr.e = hsctlr.ee;
533  if (!scr.ea) {cpsr.a = 1;}
534  if (!scr.fiq) {cpsr.f = 1;}
535  if (!scr.irq) {cpsr.i = 1;}
536  } else if (cpsr.mode == MODE_MON) {
537  // Special case handling when entering monitor mode
538  cpsr.t = sctlr.te;
539  cpsr.e = sctlr.ee;
540  cpsr.a = 1;
541  cpsr.f = 1;
542  cpsr.i = 1;
543  } else {
544  cpsr.t = sctlr.te;
545  cpsr.e = sctlr.ee;
546 
547  // The *Disable functions are virtual and different per fault
548  cpsr.a = cpsr.a | abortDisable(tc);
549  cpsr.f = cpsr.f | fiqDisable(tc);
550  cpsr.i = 1;
551  }
552  cpsr.it1 = cpsr.it2 = 0;
553  cpsr.j = 0;
554  cpsr.pan = span ? 1 : saved_cpsr.pan;
555  tc->setMiscReg(MISCREG_CPSR, cpsr);
556 
557  // Make sure mailbox sets to one always
559 
560  // Clear the exclusive monitor
562 
563  if (cpsr.mode == MODE_HYP) {
564  tc->setMiscReg(MISCREG_ELR_HYP, curPc +
565  (saved_cpsr.t ? thumbPcOffset(true) : armPcOffset(true)));
566  } else {
567  tc->setIntReg(INTREG_LR, curPc +
568  (saved_cpsr.t ? thumbPcOffset(false) : armPcOffset(false)));
569  }
570 
571  switch (cpsr.mode) {
572  case MODE_FIQ:
573  tc->setMiscReg(MISCREG_SPSR_FIQ, saved_cpsr);
574  break;
575  case MODE_IRQ:
576  tc->setMiscReg(MISCREG_SPSR_IRQ, saved_cpsr);
577  break;
578  case MODE_SVC:
579  tc->setMiscReg(MISCREG_SPSR_SVC, saved_cpsr);
580  break;
581  case MODE_MON:
582  assert(have_security);
583  tc->setMiscReg(MISCREG_SPSR_MON, saved_cpsr);
584  break;
585  case MODE_ABORT:
586  tc->setMiscReg(MISCREG_SPSR_ABT, saved_cpsr);
587  break;
588  case MODE_UNDEFINED:
589  tc->setMiscReg(MISCREG_SPSR_UND, saved_cpsr);
590  if (ec(tc) != EC_UNKNOWN)
592  break;
593  case MODE_HYP:
594  assert(ArmSystem::haveVirtualization(tc));
595  tc->setMiscReg(MISCREG_SPSR_HYP, saved_cpsr);
597  break;
598  default:
599  panic("unknown Mode\n");
600  }
601 
602  Addr newPc = getVector(tc);
603  DPRINTF(Faults, "Invoking Fault:%s cpsr:%#x PC:%#x lr:%#x newVec: %#x "
604  "%s\n", name(), cpsr, curPc, tc->readIntReg(INTREG_LR),
605  newPc, arm_inst ? csprintf("inst: %#x", arm_inst->encoding()) :
606  std::string());
607  PCState pc(newPc);
608  pc.thumb(cpsr.t);
609  pc.nextThumb(pc.thumb());
610  pc.jazelle(cpsr.j);
611  pc.nextJazelle(pc.jazelle());
612  pc.aarch64(!cpsr.width);
613  pc.nextAArch64(!cpsr.width);
614  pc.illegalExec(false);
615  tc->pcState(pc);
616 }
617 
618 void
620 {
621  // Determine actual misc. register indices for ELR_ELx and SPSR_ELx
622  MiscRegIndex elr_idx, spsr_idx;
623  switch (toEL) {
624  case EL1:
625  elr_idx = MISCREG_ELR_EL1;
626  spsr_idx = MISCREG_SPSR_EL1;
627  break;
628  case EL2:
629  assert(ArmSystem::haveVirtualization(tc));
630  elr_idx = MISCREG_ELR_EL2;
631  spsr_idx = MISCREG_SPSR_EL2;
632  break;
633  case EL3:
634  assert(ArmSystem::haveSecurity(tc));
635  elr_idx = MISCREG_ELR_EL3;
636  spsr_idx = MISCREG_SPSR_EL3;
637  break;
638  default:
639  panic("Invalid target exception level");
640  break;
641  }
642 
643  // Save process state into SPSR_ELx
644  CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
645  CPSR spsr = cpsr;
646  spsr.nz = tc->readCCReg(CCREG_NZ);
647  spsr.c = tc->readCCReg(CCREG_C);
648  spsr.v = tc->readCCReg(CCREG_V);
649  if (from64) {
650  // Force some bitfields to 0
651  spsr.q = 0;
652  spsr.it1 = 0;
653  spsr.j = 0;
654  spsr.ge = 0;
655  spsr.it2 = 0;
656  spsr.t = 0;
657  } else {
658  spsr.ge = tc->readCCReg(CCREG_GE);
659  ITSTATE it = tc->pcState().itstate();
660  spsr.it2 = it.top6;
661  spsr.it1 = it.bottom2;
662  // Force some bitfields to 0
663  spsr.ss = 0;
664  }
665  tc->setMiscReg(spsr_idx, spsr);
666 
667  // Save preferred return address into ELR_ELx
668  Addr curr_pc = tc->pcState().pc();
669  Addr ret_addr = curr_pc;
670  if (from64)
671  ret_addr += armPcElrOffset();
672  else
673  ret_addr += spsr.t ? thumbPcElrOffset() : armPcElrOffset();
674  tc->setMiscReg(elr_idx, ret_addr);
675 
676  Addr vec_address = getVector64(tc);
677 
678  // Update process state
679  OperatingMode64 mode = 0;
680  mode.spX = 1;
681  mode.el = toEL;
682  mode.width = 0;
683  cpsr.mode = mode;
684  cpsr.daif = 0xf;
685  cpsr.il = 0;
686  cpsr.ss = 0;
687  cpsr.pan = span ? 1 : spsr.pan;
688  tc->setMiscReg(MISCREG_CPSR, cpsr);
689 
690  // If we have a valid instruction then use it to annotate this fault with
691  // extra information. This is used to generate the correct fault syndrome
692  // information
693  ArmStaticInst *arm_inst M5_VAR_USED = instrAnnotate(inst);
694 
695  // Set PC to start of exception handler
696  Addr new_pc = purifyTaggedAddr(vec_address, tc, toEL, true);
697  DPRINTF(Faults, "Invoking Fault (AArch64 target EL):%s cpsr:%#x PC:%#x "
698  "elr:%#x newVec: %#x %s\n", name(), cpsr, curr_pc, ret_addr,
699  new_pc, arm_inst ? csprintf("inst: %#x", arm_inst->encoding()) :
700  std::string());
701  PCState pc(new_pc);
702  pc.aarch64(!cpsr.width);
703  pc.nextAArch64(!cpsr.width);
704  pc.illegalExec(false);
705  tc->pcState(pc);
706 
707  // Save exception syndrome
708  if ((nextMode() != MODE_IRQ) && (nextMode() != MODE_FIQ))
710 }
711 
714 {
715  if (inst) {
716  auto arm_inst = static_cast<ArmStaticInst *>(inst.get());
717  arm_inst->annotateFault(this);
718  return arm_inst;
719  } else {
720  return nullptr;
721  }
722 }
723 
724 Addr
726 {
727  Addr base;
728 
729  // Check for invalid modes
731  assert(ArmSystem::haveSecurity(tc) || cpsr.mode != MODE_MON);
732  assert(ArmSystem::haveVirtualization(tc) || cpsr.mode != MODE_HYP);
733 
734  // RVBAR is aliased (implemented as) MVBAR in gem5, since the two
735  // are mutually exclusive; there is no need to check here for
736  // which register to use since they hold the same value
737  base = tc->readMiscReg(MISCREG_MVBAR);
738 
739  return base + offset(tc);
740 }
741 
742 void
744 {
745  if (FullSystem) {
746  tc->getCpuPtr()->clearInterrupts(tc->threadId());
747  tc->clearArchRegs();
748  }
749  if (!ArmSystem::highestELIs64(tc)) {
750  ArmFault::invoke(tc, inst);
752  getMPIDR(dynamic_cast<ArmSystem*>(tc->getSystemPtr()), tc));
753 
754  // Unless we have SMC code to get us there, boot in HYP!
757  CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
758  cpsr.mode = MODE_HYP;
759  tc->setMiscReg(MISCREG_CPSR, cpsr);
760  }
761  } else {
762  // Advance the PC to the IMPLEMENTATION DEFINED reset value
764  pc.aarch64(true);
765  pc.nextAArch64(true);
766  tc->pcState(pc);
767  }
768 }
769 
770 void
772 {
773  if (FullSystem) {
774  ArmFault::invoke(tc, inst);
775  return;
776  }
777 
778  // If the mnemonic isn't defined this has to be an unknown instruction.
779  assert(unknown || mnemonic != NULL);
780  auto arm_inst = static_cast<ArmStaticInst *>(inst.get());
781  if (disabled) {
782  panic("Attempted to execute disabled instruction "
783  "'%s' (inst 0x%08x)", mnemonic, arm_inst->encoding());
784  } else if (unknown) {
785  panic("Attempted to execute unknown instruction (inst 0x%08x)",
786  arm_inst->encoding());
787  } else {
788  panic("Attempted to execute unimplemented instruction "
789  "'%s' (inst 0x%08x)", mnemonic, arm_inst->encoding());
790  }
791 }
792 
793 bool
795 {
796  bool toHyp;
797 
798  SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
799  HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR);
800  CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
801 
802  // if in Hyp mode then stay in Hyp mode
803  toHyp = scr.ns && (currEL(tc) == EL2);
804  // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector
805  toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (currEL(tc) == EL0);
806  return toHyp;
807 }
808 
809 uint32_t
811 {
812 
813  // If UndefinedInstruction is routed to hypervisor, iss field is 0.
814  if (hypRouted) {
815  return 0;
816  }
817 
818  if (overrideEc == EC_INVALID)
819  return issRaw;
820 
821  uint32_t new_iss = 0;
822  uint32_t op0, op1, op2, CRn, CRm, Rt, dir;
823 
824  dir = bits(machInst, 21, 21);
825  op0 = bits(machInst, 20, 19);
826  op1 = bits(machInst, 18, 16);
827  CRn = bits(machInst, 15, 12);
828  CRm = bits(machInst, 11, 8);
829  op2 = bits(machInst, 7, 5);
830  Rt = bits(machInst, 4, 0);
831 
832  new_iss = op0 << 20 | op2 << 17 | op1 << 14 | CRn << 10 |
833  Rt << 5 | CRm << 1 | dir;
834 
835  return new_iss;
836 }
837 
838 void
840 {
841  if (FullSystem) {
842  ArmFault::invoke(tc, inst);
843  return;
844  }
845 
846  // As of now, there isn't a 32 bit thumb version of this instruction.
847  assert(!machInst.bigThumb);
848  Fault fault;
849  tc->syscall(&fault);
850 
851  // Advance the PC since that won't happen automatically.
852  PCState pc = tc->pcState();
853  assert(inst);
854  inst->advancePC(pc);
855  tc->pcState(pc);
856 }
857 
858 bool
860 {
861  bool toHyp;
862 
863  SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
864  HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR);
865  CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
866 
867  // if in Hyp mode then stay in Hyp mode
868  toHyp = scr.ns && (cpsr.mode == MODE_HYP);
869  // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector
870  toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (currEL(tc) == EL0);
871  return toHyp;
872 }
873 
876 {
877  return (overrideEc != EC_INVALID) ? overrideEc :
878  (from64 ? EC_SVC_64 : vals.ec);
879 }
880 
881 uint32_t
883 {
884  // Even if we have a 24 bit imm from an arm32 instruction then we only use
885  // the bottom 16 bits for the ISS value (it doesn't hurt for AArch64 SVC).
886  return issRaw & 0xFFFF;
887 }
888 
889 uint32_t
891 {
892  if (from64)
893  return bits(machInst, 20, 5);
894  return 0;
895 }
896 
899 {
900  // If UndefinedInstruction is routed to hypervisor,
901  // HSR.EC field is 0.
902  if (hypRouted)
903  return EC_UNKNOWN;
904  else
905  return (overrideEc != EC_INVALID) ? overrideEc : vals.ec;
906 }
907 
908 
909 HypervisorCall::HypervisorCall(ExtMachInst _machInst, uint32_t _imm) :
910  ArmFaultVals<HypervisorCall>(_machInst, _imm)
911 {}
912 
915 {
916  return from64 ? EC_HVC_64 : vals.ec;
917 }
918 
921 {
922  return (overrideEc != EC_INVALID) ? overrideEc : vals.ec;
923 }
924 
925 template<class T>
928 {
929  bool isHypTrap = false;
930 
931  // Normally we just use the exception vector from the table at the top if
932  // this file, however if this exception has caused a transition to hype
933  // mode, and its an exception type that would only do this if it has been
934  // trapped then we use the hyp trap vector instead of the normal vector
935  if (vals.hypTrappable) {
936  CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
937  if (cpsr.mode == MODE_HYP) {
938  CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP);
939  isHypTrap = spsr.mode != MODE_HYP;
940  }
941  }
942  return isHypTrap ? 0x14 : vals.offset;
943 }
944 
945 template<class T>
948 {
949  if (toEL == fromEL) {
950  if (opModeIsT(fromMode))
951  return vals.currELTOffset;
952  return vals.currELHOffset;
953  } else {
954  bool lower_32 = false;
955  if (toEL == EL3) {
956  if (!inSecureState(tc) && ArmSystem::haveEL(tc, EL2))
957  lower_32 = ELIs32(tc, EL2);
958  else
959  lower_32 = ELIs32(tc, EL1);
960  } else {
961  lower_32 = ELIs32(tc, static_cast<ExceptionLevel>(toEL - 1));
962  }
963 
964  if (lower_32)
965  return vals.lowerEL32Offset;
966  return vals.lowerEL64Offset;
967  }
968 }
969 
970 // void
971 // SupervisorCall::setSyndrome64(ThreadContext *tc, MiscRegIndex esr_idx)
972 // {
973 // ESR esr = 0;
974 // esr.ec = machInst.aarch64 ? SvcAArch64 : SvcAArch32;
975 // esr.il = !machInst.thumb;
976 // if (machInst.aarch64)
977 // esr.imm16 = bits(machInst.instBits, 20, 5);
978 // else if (machInst.thumb)
979 // esr.imm16 = bits(machInst.instBits, 7, 0);
980 // else
981 // esr.imm16 = bits(machInst.instBits, 15, 0);
982 // tc->setMiscReg(esr_idx, esr);
983 // }
984 
985 void
987 {
988  if (FullSystem) {
989  ArmFault::invoke(tc, inst);
990  return;
991  }
992 }
993 
996 {
997  return (from64 ? EC_SMC_64 : vals.ec);
998 }
999 
1000 bool
1002 {
1003  bool toHyp = false;
1004 
1005  SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1006  HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR_EL2);
1007  CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
1008 
1009  // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector
1010  toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (currEL(tc) == EL0);
1011  return toHyp;
1012 }
1013 
1014 uint32_t
1016 {
1017  // If SupervisorTrap is routed to hypervisor, iss field is 0.
1018  if (hypRouted) {
1019  return 0;
1020  }
1021  return issRaw;
1022 }
1023 
1026 {
1027  if (hypRouted)
1028  return EC_UNKNOWN;
1029  else
1030  return (overrideEc != EC_INVALID) ? overrideEc : vals.ec;
1031 }
1032 
1035 {
1036  return (overrideEc != EC_INVALID) ? overrideEc :
1037  (from64 ? EC_SMC_64 : vals.ec);
1038 }
1039 
1040 template<class T>
1041 void
1043 {
1044  if (tranMethod == ArmFault::UnknownTran) {
1045  tranMethod = longDescFormatInUse(tc) ? ArmFault::LpaeTran
1047 
1048  if ((tranMethod == ArmFault::VmsaTran) && this->routeToMonitor(tc)) {
1049  // See ARM ARM B3-1416
1050  bool override_LPAE = false;
1051  TTBCR ttbcr_s = tc->readMiscReg(MISCREG_TTBCR_S);
1052  TTBCR M5_VAR_USED ttbcr_ns = tc->readMiscReg(MISCREG_TTBCR_NS);
1053  if (ttbcr_s.eae) {
1054  override_LPAE = true;
1055  } else {
1056  // Unimplemented code option, not seen in testing. May need
1057  // extension according to the manual exceprt above.
1058  DPRINTF(Faults, "Warning: Incomplete translation method "
1059  "override detected.\n");
1060  }
1061  if (override_LPAE)
1062  tranMethod = ArmFault::LpaeTran;
1063  }
1064  }
1065 
1066  if (source == ArmFault::AsynchronousExternalAbort) {
1067  tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_ABT, 0);
1068  }
1069  // Get effective fault source encoding
1070  CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
1071 
1072  // source must be determined BEFORE invoking generic routines which will
1073  // try to set hsr etc. and are based upon source!
1074  ArmFaultVals<T>::invoke(tc, inst);
1075 
1076  if (!this->to64) { // AArch32
1077  FSR fsr = getFsr(tc);
1078  if (cpsr.mode == MODE_HYP) {
1079  tc->setMiscReg(T::HFarIndex, faultAddr);
1080  } else if (stage2) {
1081  tc->setMiscReg(MISCREG_HPFAR, (faultAddr >> 8) & ~0xf);
1082  tc->setMiscReg(T::HFarIndex, OVAddr);
1083  } else {
1084  tc->setMiscReg(T::FsrIndex, fsr);
1085  tc->setMiscReg(T::FarIndex, faultAddr);
1086  }
1087  DPRINTF(Faults, "Abort Fault source=%#x fsr=%#x faultAddr=%#x "\
1088  "tranMethod=%#x\n", source, fsr, faultAddr, tranMethod);
1089  } else { // AArch64
1090  // Set the FAR register. Nothing else to do if we are in AArch64 state
1091  // because the syndrome register has already been set inside invoke64()
1092  if (stage2) {
1093  // stage 2 fault, set HPFAR_EL2 to the faulting IPA
1094  // and FAR_EL2 to the Original VA
1096  tc->setMiscReg(MISCREG_HPFAR_EL2, bits(faultAddr, 47, 12) << 4);
1097 
1098  DPRINTF(Faults, "Abort Fault (Stage 2) VA: 0x%x IPA: 0x%x\n",
1099  OVAddr, faultAddr);
1100  } else {
1101  tc->setMiscReg(AbortFault<T>::getFaultAddrReg64(), faultAddr);
1102  }
1103  }
1104 }
1105 
1106 template<class T>
1107 void
1109 {
1110  srcEncoded = getFaultStatusCode(tc);
1111  if (srcEncoded == ArmFault::FaultSourceInvalid) {
1112  panic("Invalid fault source\n");
1113  }
1114  ArmFault::setSyndrome(tc, syndrome_reg);
1115 }
1116 
1117 template<class T>
1118 uint8_t
1120 {
1121 
1122  panic_if(!this->faultUpdated,
1123  "Trying to use un-updated ArmFault internal variables\n");
1124 
1125  uint8_t fsc = 0;
1126 
1127  if (!this->to64) {
1128  // AArch32
1129  assert(tranMethod != ArmFault::UnknownTran);
1130  if (tranMethod == ArmFault::LpaeTran) {
1131  fsc = ArmFault::longDescFaultSources[source];
1132  } else {
1133  fsc = ArmFault::shortDescFaultSources[source];
1134  }
1135  } else {
1136  // AArch64
1137  fsc = ArmFault::aarch64FaultSources[source];
1138  }
1139 
1140  return fsc;
1141 }
1142 
1143 template<class T>
1144 FSR
1146 {
1147  FSR fsr = 0;
1148 
1149  auto fsc = getFaultStatusCode(tc);
1150 
1151  // AArch32
1152  assert(tranMethod != ArmFault::UnknownTran);
1153  if (tranMethod == ArmFault::LpaeTran) {
1154  fsr.status = fsc;
1155  fsr.lpae = 1;
1156  } else {
1157  fsr.fsLow = bits(fsc, 3, 0);
1158  fsr.fsHigh = bits(fsc, 4);
1159  fsr.domain = static_cast<uint8_t>(domain);
1160  }
1161 
1162  fsr.wnr = (write ? 1 : 0);
1163  fsr.ext = 0;
1164 
1165  return fsr;
1166 }
1167 
1168 template<class T>
1169 bool
1171 {
1172  if (ArmSystem::haveSecurity(tc)) {
1173  SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1174  return (!scr.ns || scr.aw);
1175  }
1176  return true;
1177 }
1178 
1179 template<class T>
1180 void
1182 {
1183  switch (id)
1184  {
1185  case ArmFault::S1PTW:
1186  s1ptw = val;
1187  break;
1188  case ArmFault::OVA:
1189  OVAddr = val;
1190  break;
1191 
1192  // Just ignore unknown ID's
1193  default:
1194  break;
1195  }
1196 }
1197 
1198 template<class T>
1199 uint32_t
1201 {
1202  uint32_t val;
1203 
1204  val = srcEncoded & 0x3F;
1205  val |= write << 6;
1206  val |= s1ptw << 7;
1207  return (val);
1208 }
1209 
1210 template<class T>
1211 bool
1213 {
1214  // NOTE: Not relying on LL information being aligned to lowest bits here
1215  return
1216  (source == ArmFault::AlignmentFault) ||
1217  ((source >= ArmFault::TranslationLL) &&
1218  (source < ArmFault::TranslationLL + 4)) ||
1219  ((source >= ArmFault::AccessFlagLL) &&
1220  (source < ArmFault::AccessFlagLL + 4)) ||
1221  ((source >= ArmFault::DomainLL) &&
1222  (source < ArmFault::DomainLL + 4)) ||
1223  ((source >= ArmFault::PermissionLL) &&
1224  (source < ArmFault::PermissionLL + 4));
1225 }
1226 
1227 template<class T>
1228 bool
1230 {
1231  va = (stage2 ? OVAddr : faultAddr);
1232  return true;
1233 }
1234 
1237 {
1238  if (to64) {
1239  // AArch64
1240  if (toEL == fromEL)
1242  else
1244  } else {
1245  // AArch32
1246  // Abort faults have different EC codes depending on whether
1247  // the fault originated within HYP mode, or not. So override
1248  // the method and add the extra adjustment of the EC value.
1249 
1251 
1252  CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP);
1253  if (spsr.mode == MODE_HYP) {
1254  ec = ((ExceptionClass) (((uint32_t) ec) + 1));
1255  }
1256  return ec;
1257  }
1258 }
1259 
1260 bool
1262 {
1263  SCR scr = 0;
1264  if (from64)
1266  else
1267  scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1268 
1269  return scr.ea && !isMMUFault();
1270 }
1271 
1272 bool
1274 {
1275  bool toHyp;
1276 
1277  SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1278  HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR);
1279  HDCR hdcr = tc->readMiscRegNoEffect(MISCREG_HDCR);
1280 
1281  // if in Hyp mode then stay in Hyp mode
1282  toHyp = scr.ns && (currEL(tc) == EL2);
1283  // otherwise, check whether to take to Hyp mode through Hyp Trap vector
1284  toHyp |= (stage2 ||
1285  ((source == DebugEvent) && hdcr.tde && (currEL(tc) != EL2)) ||
1286  ((source == SynchronousExternalAbort) && hcr.tge &&
1287  (currEL(tc) == EL0))) && !inSecureState(tc);
1288  return toHyp;
1289 }
1290 
1293 {
1294  if (to64) {
1295  // AArch64
1296  if (source == ArmFault::AsynchronousExternalAbort) {
1297  panic("Asynchronous External Abort should be handled with "
1298  "SystemErrors (SErrors)!");
1299  }
1300  if (toEL == fromEL)
1301  return EC_DATA_ABORT_CURR_EL;
1302  else
1303  return EC_DATA_ABORT_LOWER_EL;
1304  } else {
1305  // AArch32
1306  // Abort faults have different EC codes depending on whether
1307  // the fault originated within HYP mode, or not. So override
1308  // the method and add the extra adjustment of the EC value.
1309 
1311 
1312  CPSR spsr = tc->readMiscReg(MISCREG_SPSR_HYP);
1313  if (spsr.mode == MODE_HYP) {
1314  ec = ((ExceptionClass) (((uint32_t) ec) + 1));
1315  }
1316  return ec;
1317  }
1318 }
1319 
1320 bool
1322 {
1323  SCR scr = 0;
1324  if (from64)
1326  else
1327  scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1328 
1329  return scr.ea && !isMMUFault();
1330 }
1331 
1332 bool
1334 {
1335  bool toHyp;
1336 
1337  SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1338  HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR);
1339  HDCR hdcr = tc->readMiscRegNoEffect(MISCREG_HDCR);
1340 
1341  // if in Hyp mode then stay in Hyp mode
1342  toHyp = scr.ns && (currEL(tc) == EL2);
1343  // otherwise, check whether to take to Hyp mode through Hyp Trap vector
1344  toHyp |= (stage2 ||
1345  ((currEL(tc) != EL2) &&
1346  (((source == AsynchronousExternalAbort) && hcr.amo) ||
1347  ((source == DebugEvent) && hdcr.tde))) ||
1348  ((currEL(tc) == EL0) && hcr.tge &&
1349  ((source == AlignmentFault) ||
1350  (source == SynchronousExternalAbort)))) && !inSecureState(tc);
1351  return toHyp;
1352 }
1353 
1354 uint32_t
1356 {
1357  uint32_t val;
1358 
1359  // Add on the data abort specific fields to the generic abort ISS value
1361 
1362  val |= cm << 8;
1363 
1364  // ISS is valid if not caused by a stage 1 page table walk, and when taken
1365  // to AArch64 only when directed to EL2
1366  if (!s1ptw && stage2 && (!to64 || toEL == EL2)) {
1367  val |= isv << 24;
1368  if (isv) {
1369  val |= sas << 22;
1370  val |= sse << 21;
1371  val |= srt << 16;
1372  // AArch64 only. These assignments are safe on AArch32 as well
1373  // because these vars are initialized to false
1374  val |= sf << 15;
1375  val |= ar << 14;
1376  }
1377  }
1378  return (val);
1379 }
1380 
1381 void
1383 {
1385  switch (id)
1386  {
1387  case SAS:
1388  isv = true;
1389  sas = val;
1390  break;
1391  case SSE:
1392  isv = true;
1393  sse = val;
1394  break;
1395  case SRT:
1396  isv = true;
1397  srt = val;
1398  break;
1399  case SF:
1400  isv = true;
1401  sf = val;
1402  break;
1403  case AR:
1404  isv = true;
1405  ar = val;
1406  break;
1407  case CM:
1408  cm = val;
1409  break;
1410  case OFA:
1411  faultAddr = val;
1412  break;
1413  // Just ignore unknown ID's
1414  default:
1415  break;
1416  }
1417 }
1418 
1419 void
1421 {
1423  HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR);
1424  hcr.va = 0;
1425  tc->setMiscRegNoEffect(MISCREG_HCR, hcr);
1426 }
1427 
1428 bool
1430 {
1431  assert(ArmSystem::haveSecurity(tc));
1432  SCR scr = 0;
1433  if (from64)
1435  else
1436  scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1437  return scr.irq;
1438 }
1439 
1440 bool
1442 {
1443  bool toHyp;
1444 
1445  SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1446  HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR);
1447  CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
1448  // Determine whether IRQs are routed to Hyp mode.
1449  toHyp = (!scr.irq && hcr.imo && !inSecureState(tc)) ||
1450  (cpsr.mode == MODE_HYP);
1451  return toHyp;
1452 }
1453 
1454 bool
1456 {
1457  if (ArmSystem::haveSecurity(tc)) {
1458  SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1459  return (!scr.ns || scr.aw);
1460  }
1461  return true;
1462 }
1463 
1465 {}
1466 
1467 bool
1469 {
1470  assert(ArmSystem::haveSecurity(tc));
1471  SCR scr = 0;
1472  if (from64)
1474  else
1475  scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1476  return scr.fiq;
1477 }
1478 
1479 bool
1481 {
1482  bool toHyp;
1483 
1484  SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1485  HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR);
1486  CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
1487  // Determine whether IRQs are routed to Hyp mode.
1488  toHyp = (!scr.fiq && hcr.fmo && !inSecureState(tc)) ||
1489  (cpsr.mode == MODE_HYP);
1490  return toHyp;
1491 }
1492 
1493 bool
1495 {
1496  if (ArmSystem::haveSecurity(tc)) {
1497  SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1498  return (!scr.ns || scr.aw);
1499  }
1500  return true;
1501 }
1502 
1503 bool
1505 {
1507  return true;
1508  } else if (ArmSystem::haveSecurity(tc)) {
1509  SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR);
1510  return (!scr.ns || scr.fw);
1511  }
1512  return true;
1513 }
1514 
1516 {}
1517 
1518 void
1520 {
1522  assert(from64);
1523  // Set the FAR
1524  tc->setMiscReg(getFaultAddrReg64(), faultPC);
1525 }
1526 
1527 bool
1529 {
1530  bool toHyp = false;
1531 
1532  SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1533  HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR_EL2);
1534  CPSR cpsr = tc->readMiscRegNoEffect(MISCREG_CPSR);
1535 
1536  // if HCR.TGE is set to 1, take to Hyp mode through Hyp Trap vector
1537  toHyp |= !inSecureState(scr, cpsr) && hcr.tge && (currEL(tc) == EL0);
1538  return toHyp;
1539 }
1540 
1542 {}
1543 
1544 bool
1546 {
1547  assert(from64);
1548  HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR_EL2);
1549  return EL2Enabled(tc) && hcr.tge==1;
1550 }
1551 
1553 {}
1554 
1555 void
1557 {
1558  tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_ABT, 0);
1559  ArmFault::invoke(tc, inst);
1560 }
1561 
1562 bool
1564 {
1565  assert(ArmSystem::haveSecurity(tc));
1566  assert(from64);
1567  SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1568  return scr.ea;
1569 }
1570 
1571 bool
1573 {
1574  bool toHyp;
1575  assert(from64);
1576 
1577  SCR scr = tc->readMiscRegNoEffect(MISCREG_SCR_EL3);
1578  HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR);
1579 
1580  toHyp = (!scr.ea && hcr.amo && !inSecureState(tc)) ||
1581  (!scr.ea && !scr.rw && !hcr.amo && !inSecureState(tc));
1582  return toHyp;
1583 }
1584 
1585 
1587  : ArmFaultVals<SoftwareBreakpoint>(_mach_inst, _iss)
1588 {}
1589 
1590 bool
1592 {
1593  const bool have_el2 = ArmSystem::haveVirtualization(tc);
1594 
1595  const HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR_EL2);
1596  const HDCR mdcr = tc->readMiscRegNoEffect(MISCREG_MDCR_EL2);
1597 
1598  return have_el2 && !inSecureState(tc) && fromEL <= EL1 &&
1599  (hcr.tge || mdcr.tde);
1600 }
1601 
1604 {
1606 }
1607 
1608 void
1610  DPRINTF(Faults, "Invoking ArmSev Fault\n");
1611  if (!FullSystem)
1612  return;
1613 
1614  // Set sev_mailbox to 1, clear the pending interrupt from remote
1615  // SEV execution and let pipeline continue as pcState is still
1616  // valid.
1618  tc->getCpuPtr()->clearInterrupt(tc->threadId(), INT_SEV, 0);
1619 }
1620 
1621 // Instantiate all the templates to make the linker happy
1622 template class ArmFaultVals<Reset>;
1623 template class ArmFaultVals<UndefinedInstruction>;
1624 template class ArmFaultVals<SupervisorCall>;
1625 template class ArmFaultVals<SecureMonitorCall>;
1626 template class ArmFaultVals<HypervisorCall>;
1627 template class ArmFaultVals<PrefetchAbort>;
1628 template class ArmFaultVals<DataAbort>;
1629 template class ArmFaultVals<VirtualDataAbort>;
1630 template class ArmFaultVals<HypervisorTrap>;
1631 template class ArmFaultVals<Interrupt>;
1632 template class ArmFaultVals<VirtualInterrupt>;
1633 template class ArmFaultVals<FastInterrupt>;
1634 template class ArmFaultVals<VirtualFastInterrupt>;
1635 template class ArmFaultVals<SupervisorTrap>;
1636 template class ArmFaultVals<SecureMonitorTrap>;
1637 template class ArmFaultVals<PCAlignmentFault>;
1638 template class ArmFaultVals<SPAlignmentFault>;
1639 template class ArmFaultVals<SystemError>;
1640 template class ArmFaultVals<SoftwareBreakpoint>;
1641 template class ArmFaultVals<ArmSev>;
1642 template class AbortFault<PrefetchAbort>;
1643 template class AbortFault<DataAbort>;
1644 template class AbortFault<VirtualDataAbort>;
1645 
1646 
1648 {}
1649 
1650 bool
1652 {
1653  auto arm_fault = dynamic_cast<ArmFault *>(fault.get());
1654 
1655  if (arm_fault) {
1656  return arm_fault->getFaultVAddr(va);
1657  } else {
1658  auto pgt_fault = dynamic_cast<GenericPageTableFault *>(fault.get());
1659  if (pgt_fault) {
1660  va = pgt_fault->getFaultVAddr();
1661  return true;
1662  }
1663 
1664  auto align_fault = dynamic_cast<GenericAlignmentFault *>(fault.get());
1665  if (align_fault) {
1666  va = align_fault->getFaultVAddr();
1667  return true;
1668  }
1669 
1670  // Return false since it's not an address triggered exception
1671  return false;
1672  }
1673 }
1674 
1675 } // namespace ArmISA
bool routeToHyp(ThreadContext *tc) const override
Definition: faults.cc:1333
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:167
void invoke(ThreadContext *tc, const StaticInstPtr &inst=StaticInst::nullStaticInstPtr) override
Definition: faults.cc:1519
#define DPRINTF(x,...)
Definition: trace.hh:229
static uint8_t aarch64FaultSources[NumFaultSources]
Encodings of the fault sources in AArch64 state.
Definition: faults.hh:130
virtual uint8_t armPcElrOffset()=0
uint32_t iss() const override
Definition: faults.cc:890
virtual void setMiscReg(RegIndex misc_reg, RegVal val)=0
bool routeToHyp(ThreadContext *tc) const override
Definition: faults.cc:1480
virtual System * getSystemPtr()=0
MiscRegIndex
Definition: miscregs.hh:57
static ExceptionLevel currEL(ThreadContext *tc)
Definition: utility.hh:144
virtual void syscall(Fault *fault)=0
ExceptionClass ec(ThreadContext *tc) const override
Definition: faults.cc:1034
MiscRegIndex getFaultAddrReg64() const
Definition: faults.cc:367
bool haveSecurity() const
Returns true if this system implements the Security Extensions.
Definition: system.hh:185
const uint16_t currELTOffset
Definition: faults.hh:164
uint32_t issRaw
Definition: faults.hh:69
System error (AArch64 only)
Definition: faults.hh:589
virtual TheISA::PCState pcState() const =0
virtual FaultOffset offset(ThreadContext *tc)=0
virtual RegVal readIntReg(RegIndex reg_idx) const =0
void setSyndrome(ThreadContext *tc, MiscRegIndex syndrome_reg) override
Definition: faults.cc:1108
virtual void setMiscRegNoEffect(RegIndex misc_reg, RegVal val)=0
void annotate(AnnotationIDs id, uint64_t val) override
Definition: faults.cc:1382
static bool opModeIsT(OperatingMode mode)
Definition: types.hh:683
ExceptionClass ec(ThreadContext *tc) const override
Definition: faults.hh:278
void clearInterrupt(ThreadID tid, int int_num, int index)
Definition: base.hh:246
void invoke(ThreadContext *tc, const StaticInstPtr &inst=StaticInst::nullStaticInstPtr) override
Definition: faults.cc:743
OperatingMode
Definition: types.hh:592
bool highestELIs64() const
Returns true if the register width of the highest implemented exception level is 64 bits (ARMv8) ...
Definition: system.hh:221
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
Definition: root.cc:136
virtual void annotateFault(ArmFault *fault)
Definition: static_inst.hh:511
ExceptionClass ec(ThreadContext *tc) const override
Definition: faults.cc:1292
virtual BaseCPU * getCpuPtr()=0
Definition: ccregs.hh:42
void clearInterrupts(ThreadID tid)
Definition: base.hh:252
virtual FSR getFsr(ThreadContext *tc) const
Definition: faults.hh:241
ExceptionClass ec(ThreadContext *tc) const override
Definition: faults.cc:995
Bitfield< 4, 0 > mode
const uint16_t currELHOffset
Definition: faults.hh:165
virtual RegVal readCCReg(RegIndex reg_idx) const =0
ExceptionLevel fromEL
Definition: faults.hh:74
bool fiqDisable(ThreadContext *tc) override
Definition: faults.cc:1504
Addr purifyTaggedAddr(Addr addr, ThreadContext *tc, ExceptionLevel el, TCR tcr, bool isInstr)
Removes the tag from tagged addresses if that mode is enabled.
Definition: utility.cc:477
ThreadContext is the external interface to all thread state for anything outside of the CPU...
virtual bool fiqDisable(ThreadContext *tc)=0
RegVal getMPIDR(ArmSystem *arm_sys, ThreadContext *tc)
This helper function is returing the value of MPIDR_EL1.
Definition: utility.cc:253
virtual FaultName name() const =0
virtual bool routeToHyp(ThreadContext *tc) const
Definition: faults.hh:231
Bitfield< 63 > val
Definition: misc.hh:771
static bool haveEL(ThreadContext *tc, ExceptionLevel el)
Return true if the system implements a specific exception level.
Definition: system.cc:250
ExceptionClass ec(ThreadContext *tc) const override
Definition: faults.cc:1025
virtual FaultOffset offset64(ThreadContext *tc)=0
Bitfield< 31, 28 > condCode
Definition: types.hh:121
void invoke(ThreadContext *tc, const StaticInstPtr &inst=StaticInst::nullStaticInstPtr) override
Definition: faults.cc:839
static uint8_t shortDescFaultSources[NumFaultSources]
Encodings of the fault sources when the short-desc.
Definition: faults.hh:125
virtual bool getFaultVAddr(Addr &va) const
Definition: faults.hh:243
ConditionCode
Definition: ccregs.hh:64
Bitfield< 7 > sf
Definition: misc.hh:547
bool routeToHyp(ThreadContext *tc) const override
Definition: faults.cc:794
bool ELIs64(ThreadContext *tc, ExceptionLevel el)
Definition: utility.cc:333
uint32_t iss() const override
Definition: faults.cc:1015
Addr FaultOffset
Definition: faults.hh:61
Bitfield< 12, 10 > ar
Bitfield< 4 > pc
static uint8_t longDescFaultSources[NumFaultSources]
Encodings of the fault sources when the long-desc.
Definition: faults.hh:128
void invoke(ThreadContext *tc, const StaticInstPtr &inst=StaticInst::nullStaticInstPtr) override
Definition: faults.cc:1556
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:162
void invoke(ThreadContext *tc, const StaticInstPtr &inst=StaticInst::nullStaticInstPtr) override
Definition: faults.cc:1609
uint32_t iss() const override
Definition: faults.cc:1200
bool routeToHyp(ThreadContext *tc) const override
Definition: faults.cc:1572
const uint16_t lowerEL32Offset
Definition: faults.hh:167
ArmStaticInst * instrAnnotate(const StaticInstPtr &inst)
Definition: faults.cc:713
bool abortDisable(ThreadContext *tc) override
Definition: faults.cc:1494
virtual bool routeToMonitor(ThreadContext *tc) const override
Definition: faults.hh:263
ArmFault::FaultVals vals
Definition: faults.hh:618
virtual bool abortDisable(ThreadContext *tc)=0
Bitfield< 51, 12 > base
Definition: pagetable.hh:142
static ExceptionLevel opModeToEL(OperatingMode mode)
Definition: types.hh:690
const uint16_t lowerEL64Offset
Definition: faults.hh:166
bool ELIs32(ThreadContext *tc, ExceptionLevel el)
Definition: utility.cc:339
bool routeToHyp(ThreadContext *tc) const override
Definition: faults.cc:1273
HypervisorCall(ExtMachInst _machInst, uint32_t _imm)
Definition: faults.cc:909
void invoke(ThreadContext *tc, const StaticInstPtr &inst) override
Definition: faults.cc:1420
virtual FaultStat & countStat()=0
virtual bool routeToMonitor(ThreadContext *tc) const =0
SoftwareBreakpoint(ExtMachInst _mach_inst, uint32_t _iss)
Definition: faults.cc:1586
virtual uint8_t thumbPcOffset(bool isHyp)=0
Addr getVector64(ThreadContext *tc)
Definition: faults.cc:328
virtual void setIntReg(RegIndex reg_idx, RegVal val)=0
Addr getFaultVAddr() const
Definition: faults.hh:114
bool haveVirtualization() const
Returns true if this system implements the virtualization Extensions.
Definition: system.hh:194
ExtMachInst machInst
Definition: faults.hh:68
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
uint64_t ExtMachInst
Definition: types.hh:41
bool routeToHyp(ThreadContext *tc) const override
Definition: faults.cc:1441
ExceptionClass ec(ThreadContext *tc) const override
Definition: faults.cc:914
MiscRegIndex getSyndromeReg64() const
Definition: faults.cc:351
void invoke64(ThreadContext *tc, const StaticInstPtr &inst=StaticInst::nullStaticInstPtr)
Definition: faults.cc:619
bool routeToMonitor(ThreadContext *tc) const override
Definition: faults.cc:1261
bool isMMUFault() const
Definition: faults.cc:1212
uint32_t iss() const override
Definition: faults.cc:1355
Bitfield< 8 > va
void invoke(ThreadContext *tc, const StaticInstPtr &inst=StaticInst::nullStaticInstPtr) override
Definition: faults.cc:771
ExceptionClass ec(ThreadContext *tc) const override
Definition: faults.cc:875
const ExceptionClass ec
Definition: faults.hh:185
bool getFaultVAddr(Addr &va) const override
Definition: faults.cc:1229
virtual OperatingMode nextMode()=0
void invoke(ThreadContext *tc, const StaticInstPtr &inst=StaticInst::nullStaticInstPtr) override
Definition: faults.cc:986
virtual uint8_t thumbPcElrOffset()=0
ExceptionClass
Definition: types.hh:612
bool abortDisable(ThreadContext *tc) override
Definition: faults.cc:1455
virtual uint32_t iss() const =0
virtual RegVal readMiscRegNoEffect(RegIndex misc_reg) const =0
virtual Addr getVector(ThreadContext *tc)
Definition: faults.cc:296
bool longDescFormatInUse(ThreadContext *tc)
Definition: utility.cc:218
bool routeToHyp(ThreadContext *tc) const override
Definition: faults.cc:859
Addr getVector(ThreadContext *tc) override
Definition: faults.cc:725
Bitfield< 7, 4 > domain
bool hypRouted
Definition: faults.hh:84
const FaultOffset offset
Definition: faults.hh:161
virtual void advancePC(TheISA::PCState &pcState) const =0
bool faultUpdated
Definition: faults.hh:82
GenericISA::SimplePCState< MachInst > PCState
Definition: types.hh:43
void invoke(ThreadContext *tc, const StaticInstPtr &inst=StaticInst::nullStaticInstPtr) override
Definition: faults.cc:474
const uint32_t HighVecs
Definition: isa_traits.hh:96
bool routeToMonitor(ThreadContext *tc) const override
Definition: faults.cc:1563
void invoke(ThreadContext *tc, const StaticInstPtr &inst=StaticInst::nullStaticInstPtr) override
Definition: faults.cc:1042
virtual int threadId() const =0
bool routeToHyp(ThreadContext *tc) const override
Definition: faults.cc:1591
bool routeToHyp(ThreadContext *tc) const override
Definition: faults.cc:1545
FSR getFsr(ThreadContext *tc) const override
Definition: faults.cc:1145
ExceptionLevel toEL
Definition: faults.hh:75
OperatingMode toMode
Definition: faults.hh:77
bool routeToHyp(ThreadContext *tc) const override
Definition: faults.cc:1528
uint32_t iss() const override
Definition: faults.cc:882
bool abortDisable(ThreadContext *tc) override
Definition: faults.cc:1170
Bitfield< 13 > cm
virtual void clearArchRegs()=0
virtual uint8_t armPcOffset(bool isHyp)=0
void update(ThreadContext *tc)
Definition: faults.cc:424
void annotate(ArmFault::AnnotationIDs id, uint64_t val) override
Definition: faults.cc:1181
bool routeToMonitor(ThreadContext *tc) const override
Definition: faults.cc:1468
virtual void setSyndrome(ThreadContext *tc, MiscRegIndex syndrome_reg)
Definition: faults.cc:383
bool routeToHyp(ThreadContext *tc) const override
Definition: faults.cc:1001
bool inSecureState(ThreadContext *tc)
Definition: utility.cc:195
virtual ExceptionClass ec(ThreadContext *tc) const =0
ExceptionClass ec(ThreadContext *tc) const override
Definition: faults.cc:1236
FaultOffset offset64(ThreadContext *tc) override
Definition: faults.cc:947
static const int NumArgumentRegs M5_VAR_USED
Definition: process.cc:84
T bits(T val, int first, int last)
Extract the bitfield from position &#39;first&#39; to &#39;last&#39; (inclusive) from &#39;val&#39; and right justify it...
Definition: bitfield.hh:72
bool EL2Enabled(ThreadContext *tc)
Definition: utility.cc:325
ExceptionClass ec(ThreadContext *tc) const override
Definition: faults.cc:920
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:185
Addr resetAddr() const
Returns the reset address if the highest implemented exception level is 64 bits (ARMv8) ...
Definition: system.hh:235
T * get() const
Directly access the pointer itself without taking a reference.
Definition: refcnt.hh:221
virtual RegVal readMiscReg(RegIndex misc_reg)=0
ExceptionClass ec(ThreadContext *tc) const override
Definition: faults.cc:1603
std::shared_ptr< FaultBase > Fault
Definition: types.hh:240
FaultOffset offset(ThreadContext *tc) override
Definition: faults.cc:927
OperatingMode fromMode
Definition: faults.hh:76
bool routeToMonitor(ThreadContext *tc) const override
Definition: faults.cc:1429
bool routeToMonitor(ThreadContext *tc) const override
Definition: faults.cc:1321
cond
Definition: types.hh:63
virtual void invoke(ThreadContext *tc, const StaticInstPtr &inst=StaticInst::nullStaticInstPtr)
Definition: faults.cc:43
Addr getFaultVAddr() const
Definition: faults.hh:102
ExceptionClass ec(ThreadContext *tc) const override
Definition: faults.cc:898
uint32_t iss() const override
Definition: faults.cc:810
uint8_t getFaultStatusCode(ThreadContext *tc) const
Definition: faults.cc:1119

Generated on Fri Feb 28 2020 16:26:55 for gem5 by doxygen 1.8.13