gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
faults.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2003-2005 The Regents of The University of Michigan
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met: redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer;
9  * redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution;
12  * neither the name of the copyright holders nor the names of its
13  * contributors may be used to endorse or promote products derived from
14  * this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  * Authors: Gabe Black
29  * Kevin Lim
30  */
31 
32 #include "arch/sparc/faults.hh"
33 
34 #include <algorithm>
35 
36 #include "arch/sparc/isa_traits.hh"
37 #include "arch/sparc/process.hh"
38 #include "arch/sparc/types.hh"
39 #include "base/bitfield.hh"
40 #include "base/trace.hh"
41 #include "cpu/base.hh"
42 #include "cpu/thread_context.hh"
43 #include "mem/page_table.hh"
44 #include "sim/full_system.hh"
45 #include "sim/process.hh"
46 
47 using namespace std;
48 
49 namespace SparcISA
50 {
51 
54 {"power_on_reset", 0x001, 0, {H, H, H}, FaultStat()};
55 
58 {"watch_dog_reset", 0x002, 120, {H, H, H}, FaultStat()};
59 
62 {"externally_initiated_reset", 0x003, 110, {H, H, H}, FaultStat()};
63 
66 {"software_initiated_reset", 0x004, 130, {SH, SH, H}, FaultStat()};
67 
70 {"RED_state_exception", 0x005, 1, {H, H, H}, FaultStat()};
71 
74 {"store_error", 0x007, 201, {H, H, H}, FaultStat()};
75 
78 {"instruction_access_exception", 0x008, 300, {H, H, H}, FaultStat()};
79 
80 //XXX This trap is apparently dropped from ua2005
81 /*template<> SparcFaultBase::FaultVals
82  SparcFault<InstructionAccessMMUMiss>::vals =
83  {"inst_mmu", 0x009, 2, {H, H, H}};*/
84 
87 {"instruction_access_error", 0x00A, 400, {H, H, H}, FaultStat()};
88 
91 {"illegal_instruction", 0x010, 620, {H, H, H}, FaultStat()};
92 
95 {"privileged_opcode", 0x011, 700, {P, SH, SH}, FaultStat()};
96 
97 //XXX This trap is apparently dropped from ua2005
98 /*template<> SparcFaultBase::FaultVals
99  SparcFault<UnimplementedLDD>::vals =
100  {"unimp_ldd", 0x012, 6, {H, H, H}};*/
101 
102 //XXX This trap is apparently dropped from ua2005
103 /*template<> SparcFaultBase::FaultVals
104  SparcFault<UnimplementedSTD>::vals =
105  {"unimp_std", 0x013, 6, {H, H, H}};*/
106 
107 template<> SparcFaultBase::FaultVals
109 {"fp_disabled", 0x020, 800, {P, P, H}, FaultStat()};
110 
111 template<> SparcFaultBase::FaultVals
113 {"fp_exception_ieee_754", 0x021, 1110, {P, P, H}, FaultStat()};
114 
115 template<> SparcFaultBase::FaultVals
117 {"fp_exception_other", 0x022, 1110, {P, P, H}, FaultStat()};
118 
119 template<> SparcFaultBase::FaultVals
121 {"tag_overflow", 0x023, 1400, {P, P, H}, FaultStat()};
122 
123 template<> SparcFaultBase::FaultVals
125 {"clean_window", 0x024, 1010, {P, P, H}, FaultStat()};
126 
127 template<> SparcFaultBase::FaultVals
129 {"division_by_zero", 0x028, 1500, {P, P, H}, FaultStat()};
130 
131 template<> SparcFaultBase::FaultVals
133 {"internal_processor_error", 0x029, 4, {H, H, H}, FaultStat()};
134 
135 template<> SparcFaultBase::FaultVals
137 {"instruction_invalid_tsb_entry", 0x02A, 210, {H, H, SH}, FaultStat()};
138 
139 template<> SparcFaultBase::FaultVals
141 {"data_invalid_tsb_entry", 0x02B, 1203, {H, H, H}, FaultStat()};
142 
143 template<> SparcFaultBase::FaultVals
145 {"data_access_exception", 0x030, 1201, {H, H, H}, FaultStat()};
146 
147 //XXX This trap is apparently dropped from ua2005
148 /*template<> SparcFaultBase::FaultVals
149  SparcFault<DataAccessMMUMiss>::vals =
150  {"data_mmu", 0x031, 12, {H, H, H}};*/
151 
152 template<> SparcFaultBase::FaultVals
154 {"data_access_error", 0x032, 1210, {H, H, H}, FaultStat()};
155 
156 template<> SparcFaultBase::FaultVals
158 {"data_access_protection", 0x033, 1207, {H, H, H}, FaultStat()};
159 
160 template<> SparcFaultBase::FaultVals
162 {"mem_address_not_aligned", 0x034, 1020, {H, H, H}, FaultStat()};
163 
164 template<> SparcFaultBase::FaultVals
166 {"LDDF_mem_address_not_aligned", 0x035, 1010, {H, H, H}, FaultStat()};
167 
168 template<> SparcFaultBase::FaultVals
170 {"STDF_mem_address_not_aligned", 0x036, 1010, {H, H, H}, FaultStat()};
171 
172 template<> SparcFaultBase::FaultVals
174 {"privileged_action", 0x037, 1110, {H, H, SH}, FaultStat()};
175 
176 template<> SparcFaultBase::FaultVals
178 {"LDQF_mem_address_not_aligned", 0x038, 1010, {H, H, H}, FaultStat()};
179 
180 template<> SparcFaultBase::FaultVals
182 {"STQF_mem_address_not_aligned", 0x039, 1010, {H, H, H}, FaultStat()};
183 
184 template<> SparcFaultBase::FaultVals
186 {"instruction_real_translation_miss", 0x03E, 208, {H, H, SH}, FaultStat()};
187 
188 template<> SparcFaultBase::FaultVals
190 {"data_real_translation_miss", 0x03F, 1203, {H, H, H}, FaultStat()};
191 
192 //XXX This trap is apparently dropped from ua2005
193 /*template<> SparcFaultBase::FaultVals
194  SparcFault<AsyncDataError>::vals =
195  {"async_data", 0x040, 2, {H, H, H}};*/
196 
197 template<> SparcFaultBase::FaultVals
199 {"interrupt_level_n", 0x040, 0, {P, P, SH}, FaultStat()};
200 
201 template<> SparcFaultBase::FaultVals
203 {"hstick_match", 0x05E, 1601, {H, H, H}, FaultStat()};
204 
205 template<> SparcFaultBase::FaultVals
207 {"trap_level_zero", 0x05F, 202, {H, H, SH}, FaultStat()};
208 
209 template<> SparcFaultBase::FaultVals
211 {"interrupt_vector", 0x060, 2630, {H, H, H}, FaultStat()};
212 
213 template<> SparcFaultBase::FaultVals
215 {"PA_watchpoint", 0x061, 1209, {H, H, H}, FaultStat()};
216 
217 template<> SparcFaultBase::FaultVals
219 {"VA_watchpoint", 0x062, 1120, {P, P, SH}, FaultStat()};
220 
221 template<> SparcFaultBase::FaultVals
223 {"fast_instruction_access_MMU_miss", 0x064, 208, {H, H, SH}, FaultStat()};
224 
225 template<> SparcFaultBase::FaultVals
227 {"fast_data_access_MMU_miss", 0x068, 1203, {H, H, H}, FaultStat()};
228 
229 template<> SparcFaultBase::FaultVals
231 {"fast_data_access_protection", 0x06C, 1207, {H, H, H}, FaultStat()};
232 
233 template<> SparcFaultBase::FaultVals
235 {"instruction_break", 0x076, 610, {H, H, H}, FaultStat()};
236 
237 template<> SparcFaultBase::FaultVals
239 {"cpu_mondo", 0x07C, 1608, {P, P, SH}, FaultStat()};
240 
241 template<> SparcFaultBase::FaultVals
243 {"dev_mondo", 0x07D, 1611, {P, P, SH}, FaultStat()};
244 
245 template<> SparcFaultBase::FaultVals
247 {"resume_error", 0x07E, 3330, {P, P, SH}, FaultStat()};
248 
249 template<> SparcFaultBase::FaultVals
251 {"spill_n_normal", 0x080, 900, {P, P, H}, FaultStat()};
252 
253 template<> SparcFaultBase::FaultVals
255 {"spill_n_other", 0x0A0, 900, {P, P, H}, FaultStat()};
256 
257 template<> SparcFaultBase::FaultVals
259 {"fill_n_normal", 0x0C0, 900, {P, P, H}, FaultStat()};
260 
261 template<> SparcFaultBase::FaultVals
263 {"fill_n_other", 0x0E0, 900, {P, P, H}, FaultStat()};
264 
265 template<> SparcFaultBase::FaultVals
267 {"trap_instruction", 0x100, 1602, {P, P, H}, FaultStat()};
268 
274 void
276 {
277  //@todo Disable the mmu?
278  //@todo Disable watchpoints?
279  HPSTATE hpstate= tc->readMiscRegNoEffect(MISCREG_HPSTATE);
280  hpstate.red = 1;
281  hpstate.hpriv = 1;
282  tc->setMiscReg(MISCREG_HPSTATE, hpstate);
283  // PSTATE.priv is set to 1 here. The manual says it should be 0, but
284  // Legion sets it to 1.
285  PSTATE pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE);
286  pstate.priv = 1;
287  tc->setMiscReg(MISCREG_PSTATE, pstate);
288 }
289 
295 void
297 {
300  PSTATE pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE);
301  HPSTATE hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE);
302  MiscReg CCR = tc->readIntReg(NumIntArchRegs + 2);
305  MiscReg CANSAVE = tc->readMiscRegNoEffect(NumIntArchRegs + 3);
307  PCState pc = tc->pcState();
308 
309  TL++;
310 
311  Addr pcMask = pstate.am ? mask(32) : mask(64);
312 
313  // set TSTATE.gl to gl
314  replaceBits(TSTATE, 42, 40, GL);
315  // set TSTATE.ccr to ccr
316  replaceBits(TSTATE, 39, 32, CCR);
317  // set TSTATE.asi to asi
318  replaceBits(TSTATE, 31, 24, ASI);
319  // set TSTATE.pstate to pstate
320  replaceBits(TSTATE, 20, 8, pstate);
321  // set TSTATE.cwp to cwp
322  replaceBits(TSTATE, 4, 0, CWP);
323 
324  // Write back TSTATE
325  tc->setMiscRegNoEffect(MISCREG_TSTATE, TSTATE);
326 
327  // set TPC to PC
328  tc->setMiscRegNoEffect(MISCREG_TPC, pc.pc() & pcMask);
329  // set TNPC to NPC
330  tc->setMiscRegNoEffect(MISCREG_TNPC, pc.npc() & pcMask);
331 
332  // set HTSTATE.hpstate to hpstate
333  tc->setMiscRegNoEffect(MISCREG_HTSTATE, hpstate);
334 
335  // TT = trap type;
337 
338  // Update GL
339  tc->setMiscReg(MISCREG_GL, min<int>(GL+1, MaxGL));
340 
341  bool priv = pstate.priv; // just save the priv bit
342  pstate = 0;
343  pstate.priv = priv;
344  pstate.pef = 1;
345  tc->setMiscRegNoEffect(MISCREG_PSTATE, pstate);
346 
347  hpstate.red = 1;
348  hpstate.hpriv = 1;
349  hpstate.ibe = 0;
350  hpstate.tlz = 0;
351  tc->setMiscRegNoEffect(MISCREG_HPSTATE, hpstate);
352 
353  bool changedCWP = true;
354  if (tt == 0x24)
355  CWP++;
356  else if (0x80 <= tt && tt <= 0xbf)
357  CWP += (CANSAVE + 2);
358  else if (0xc0 <= tt && tt <= 0xff)
359  CWP--;
360  else
361  changedCWP = false;
362 
363  if (changedCWP) {
364  CWP = (CWP + NWindows) % NWindows;
365  tc->setMiscReg(MISCREG_CWP, CWP);
366  }
367 }
368 
374 void
375 doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv)
376 {
379  PSTATE pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE);
380  HPSTATE hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE);
381  MiscReg CCR = tc->readIntReg(NumIntArchRegs + 2);
384  MiscReg CANSAVE = tc->readIntReg(NumIntArchRegs + 3);
386  PCState pc = tc->pcState();
387 
388  // Increment the trap level
389  TL++;
391 
392  Addr pcMask = pstate.am ? mask(32) : mask(64);
393 
394  // Save off state
395 
396  // set TSTATE.gl to gl
397  replaceBits(TSTATE, 42, 40, GL);
398  // set TSTATE.ccr to ccr
399  replaceBits(TSTATE, 39, 32, CCR);
400  // set TSTATE.asi to asi
401  replaceBits(TSTATE, 31, 24, ASI);
402  // set TSTATE.pstate to pstate
403  replaceBits(TSTATE, 20, 8, pstate);
404  // set TSTATE.cwp to cwp
405  replaceBits(TSTATE, 4, 0, CWP);
406 
407  // Write back TSTATE
408  tc->setMiscRegNoEffect(MISCREG_TSTATE, TSTATE);
409 
410  // set TPC to PC
411  tc->setMiscRegNoEffect(MISCREG_TPC, pc.pc() & pcMask);
412  // set TNPC to NPC
413  tc->setMiscRegNoEffect(MISCREG_TNPC, pc.npc() & pcMask);
414 
415  // set HTSTATE.hpstate to hpstate
416  tc->setMiscRegNoEffect(MISCREG_HTSTATE, hpstate);
417 
418  // TT = trap type;
420 
421  // Update the global register level
422  if (!gotoHpriv)
423  tc->setMiscReg(MISCREG_GL, min<int>(GL + 1, MaxPGL));
424  else
425  tc->setMiscReg(MISCREG_GL, min<int>(GL + 1, MaxGL));
426 
427  // pstate.mm is unchanged
428  pstate.pef = 1; // PSTATE.pef = whether or not an fpu is present
429  pstate.am = 0;
430  pstate.ie = 0;
431  // pstate.tle is unchanged
432  // pstate.tct = 0
433 
434  if (gotoHpriv) {
435  pstate.cle = 0;
436  // The manual says PSTATE.priv should be 0, but Legion leaves it alone
437  hpstate.red = 0;
438  hpstate.hpriv = 1;
439  hpstate.ibe = 0;
440  // hpstate.tlz is unchanged
441  tc->setMiscRegNoEffect(MISCREG_HPSTATE, hpstate);
442  } else { // we are going to priv
443  pstate.priv = 1;
444  pstate.cle = pstate.tle;
445  }
446  tc->setMiscRegNoEffect(MISCREG_PSTATE, pstate);
447 
448 
449  bool changedCWP = true;
450  if (tt == 0x24)
451  CWP++;
452  else if (0x80 <= tt && tt <= 0xbf)
453  CWP += (CANSAVE + 2);
454  else if (0xc0 <= tt && tt <= 0xff)
455  CWP--;
456  else
457  changedCWP = false;
458 
459  if (changedCWP) {
460  CWP = (CWP + NWindows) % NWindows;
461  tc->setMiscReg(MISCREG_CWP, CWP);
462  }
463 }
464 
465 void
467 {
468  //XXX The following constant might belong in a header file.
469  const Addr RSTVAddr = 0xFFF0000000ULL;
470  PC = RSTVAddr | ((TT << 5) & 0xFF);
471  NPC = PC + sizeof(MachInst);
472 }
473 
474 void
476 {
478  PC = (HTBA & ~mask(14)) | ((TT << 5) & mask(14));
479  NPC = PC + sizeof(MachInst);
480 }
481 
482 void
484 {
486  PC = (TBA & ~mask(15)) |
487  (TL > 1 ? (1 << 14) : 0) |
488  ((TT << 5) & mask(14));
489  NPC = PC + sizeof(MachInst);
490 }
491 
492 void
493 SparcFaultBase::invoke(ThreadContext * tc, const StaticInstPtr &inst)
494 {
495  FaultBase::invoke(tc);
496  if (!FullSystem)
497  return;
498 
499  countStat()++;
500 
501  // We can refer to this to see what the trap level -was-, but something
502  // in the middle could change it in the regfile out from under us.
505  PSTATE pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE);
506  HPSTATE hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE);
507 
508  Addr PC, NPC;
509 
510  PrivilegeLevel current;
511  if (hpstate.hpriv)
512  current = Hyperprivileged;
513  else if (pstate.priv)
514  current = Privileged;
515  else
516  current = User;
517 
518  PrivilegeLevel level = getNextLevel(current);
519 
520  if (hpstate.red || (tl == MaxTL - 1)) {
521  getREDVector(5, PC, NPC);
522  doREDFault(tc, tt);
523  // This changes the hpstate and pstate, so we need to make sure we
524  // save the old version on the trap stack in doREDFault.
525  enterREDState(tc);
526  } else if (tl == MaxTL) {
527  panic("Should go to error state here.. crap\n");
528  // Do error_state somehow?
529  // Probably inject a WDR fault using the interrupt mechanism.
530  // What should the PC and NPC be set to?
531  } else if (tl > MaxPTL && level == Privileged) {
532  // guest_watchdog fault
533  doNormalFault(tc, trapType(), true);
534  getHyperVector(tc, PC, NPC, 2);
535  } else if (level == Hyperprivileged ||
536  (level == Privileged && trapType() >= 384)) {
537  doNormalFault(tc, trapType(), true);
538  getHyperVector(tc, PC, NPC, trapType());
539  } else {
540  doNormalFault(tc, trapType(), false);
541  getPrivVector(tc, PC, NPC, trapType(), tl + 1);
542  }
543 
544  PCState pc;
545  pc.pc(PC);
546  pc.npc(NPC);
547  pc.nnpc(NPC + sizeof(MachInst));
548  pc.upc(0);
549  pc.nupc(1);
550  tc->pcState(pc);
551 }
552 
553 void
554 PowerOnReset::invoke(ThreadContext *tc, const StaticInstPtr &inst)
555 {
556  // For SPARC, when a system is first started, there is a power
557  // on reset Trap which sets the processor into the following state.
558  // Bits that aren't set aren't defined on startup.
559 
561  tc->setMiscRegNoEffect(MISCREG_TT, trapType());
563 
564  PSTATE pstate = 0;
565  pstate.pef = 1;
566  pstate.priv = 1;
567  tc->setMiscRegNoEffect(MISCREG_PSTATE, pstate);
568 
569  // Turn on red and hpriv, set everything else to 0
570  HPSTATE hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE);
571  hpstate.red = 1;
572  hpstate.hpriv = 1;
573  hpstate.ibe = 0;
574  hpstate.tlz = 0;
575  tc->setMiscRegNoEffect(MISCREG_HPSTATE, hpstate);
576 
577  // The tick register is unreadable by nonprivileged software
578  tc->setMiscRegNoEffect(MISCREG_TICK, 1ULL << 63);
579 
580  // Enter RED state. We do this last so that the actual state preserved in
581  // the trap stack is the state from before this fault.
582  enterREDState(tc);
583 
584  Addr PC, NPC;
585  getREDVector(trapType(), PC, NPC);
586 
587  PCState pc;
588  pc.pc(PC);
589  pc.npc(NPC);
590  pc.nnpc(NPC + sizeof(MachInst));
591  pc.upc(0);
592  pc.nupc(1);
593  tc->pcState(pc);
594 
595  // These registers are specified as "undefined" after a POR, and they
596  // should have reasonable values after the miscregfile is reset
597  /*
598  // Clear all the soft interrupt bits
599  softint = 0;
600  // disable timer compare interrupts, reset tick_cmpr
601  tc->setMiscRegNoEffect(MISCREG_
602  tick_cmprFields.int_dis = 1;
603  tick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing
604  stickFields.npt = 1; // The TICK register is unreadable by by !priv
605  stick_cmprFields.int_dis = 1; // disable timer compare interrupts
606  stick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing
607 
608  tt[tl] = _trapType;
609 
610  hintp = 0; // no interrupts pending
611  hstick_cmprFields.int_dis = 1; // disable timer compare interrupts
612  hstick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing
613  */
614 }
615 
616 void
617 FastInstructionAccessMMUMiss::invoke(ThreadContext *tc,
618  const StaticInstPtr &inst)
619 {
620  if (FullSystem) {
621  SparcFaultBase::invoke(tc, inst);
622  return;
623  }
624 
625  Process *p = tc->getProcessPtr();
626  TlbEntry entry;
627  bool success = p->pTable->lookup(vaddr, entry);
628  if (!success) {
629  panic("Tried to execute unmapped address %#x.\n", vaddr);
630  } else {
631  Addr alignedvaddr = p->pTable->pageAlign(vaddr);
632 
633  // Grab fields used during instruction translation to figure out
634  // which context to use.
635  uint64_t tlbdata = tc->readMiscRegNoEffect(MISCREG_TLB_DATA);
636 
637  // Inside a VM, a real address is the address that guest OS would
638  // interpret to be a physical address. To map to the physical address,
639  // it still needs to undergo a translation. The instruction
640  // translation code in the SPARC ITLB code assumes that the context is
641  // zero (kernel-level) if real addressing is being used.
642  bool is_real_address = !bits(tlbdata, 4);
643 
644  // The SPARC ITLB code assumes that traps are executed in context
645  // zero so we carry that assumption through here.
646  bool trapped = bits(tlbdata, 18, 16) > 0;
647 
648  // The primary context acts as a PASID. It allows the MMU to
649  // distinguish between virtual addresses that would alias to the
650  // same physical address (if two or more processes shared the same
651  // virtual address mapping).
652  int primary_context = bits(tlbdata, 47, 32);
653 
654  // The partition id distinguishes between virtualized environments.
655  int const partition_id = 0;
656 
657  // Given the assumptions in the translateInst code in the SPARC ITLB,
658  // the logic works out to the following for the context.
659  int context_id = (is_real_address || trapped) ? 0 : primary_context;
660 
661  // Insert the TLB entry.
662  // The entry specifying whether the address is "real" is set to
663  // false for syscall emulation mode regardless of whether the
664  // address is real in preceding code. Not sure sure that this is
665  // correct, but also not sure if it matters at all.
666  tc->getITBPtr()->insert(alignedvaddr, partition_id, context_id,
667  false, entry.pte);
668  }
669 }
670 
671 void
672 FastDataAccessMMUMiss::invoke(ThreadContext *tc, const StaticInstPtr &inst)
673 {
674  if (FullSystem) {
675  SparcFaultBase::invoke(tc, inst);
676  return;
677  }
678 
679  Process *p = tc->getProcessPtr();
680  TlbEntry entry;
681  bool success = p->pTable->lookup(vaddr, entry);
682  if (!success) {
683  if (p->fixupStackFault(vaddr))
684  success = p->pTable->lookup(vaddr, entry);
685  }
686  if (!success) {
687  panic("Tried to access unmapped address %#x.\n", vaddr);
688  } else {
689  Addr alignedvaddr = p->pTable->pageAlign(vaddr);
690 
691  // Grab fields used during data translation to figure out
692  // which context to use.
693  uint64_t tlbdata = tc->readMiscRegNoEffect(MISCREG_TLB_DATA);
694 
695  // The primary context acts as a PASID. It allows the MMU to
696  // distinguish between virtual addresses that would alias to the
697  // same physical address (if two or more processes shared the same
698  // virtual address mapping). There's a secondary context used in the
699  // DTLB translation code, but it should __probably__ be zero for
700  // syscall emulation code. (The secondary context is used by Solaris
701  // to allow kernel privilege code to access user space code:
702  // [ISBN 0-13-022496-0]:PG199.)
703  int primary_context = bits(tlbdata, 47, 32);
704 
705  // "Hyper-Privileged Mode" is in use. There are three main modes of
706  // operation for Sparc: Hyper-Privileged Mode, Privileged Mode, and
707  // User Mode.
708  int hpriv = bits(tlbdata, 0);
709 
710  // Reset, Error and Debug state is in use. Something horrible has
711  // happened or the system is operating in Reset Mode.
712  int red = bits(tlbdata, 1);
713 
714  // Inside a VM, a real address is the address that guest OS would
715  // interpret to be a physical address. To map to the physical address,
716  // it still needs to undergo a translation. The instruction
717  // translation code in the SPARC ITLB code assumes that the context is
718  // zero (kernel-level) if real addressing is being used.
719  int is_real_address = !bits(tlbdata, 5);
720 
721  // Grab the address space identifier register from the thread context.
722  // XXX: Inspecting how setMiscReg and setMiscRegNoEffect behave for
723  // MISCREG_ASI causes me to think that the ASI register implementation
724  // might be bugged. The NoEffect variant changes the ASI register
725  // value in the architectural state while the normal variant changes
726  // the context field in the thread context's currently decoded request
727  // but does not directly affect the ASI register value in the
728  // architectural state. The ASI values and the context field in the
729  // request packet seem to have completely different uses.
730  MiscReg reg_asi = tc->readMiscRegNoEffect(MISCREG_ASI);
731  ASI asi = static_cast<ASI>(reg_asi);
732 
733  // The SPARC DTLB code assumes that traps are executed in context
734  // zero if the asi value is ASI_IMPLICIT (which is 0x0). There's also
735  // an assumption that the nucleus address space is being used, but
736  // the context is the relevant issue since we need to pass it to TLB.
737  bool trapped = bits(tlbdata, 18, 16) > 0;
738 
739  // Given the assumptions in the translateData code in the SPARC DTLB,
740  // the logic works out to the following for the context.
741  int context_id = ((!hpriv && !red && is_real_address) ||
742  asiIsReal(asi) ||
743  (trapped && asi == ASI_IMPLICIT))
744  ? 0 : primary_context;
745 
746  // The partition id distinguishes between virtualized environments.
747  int const partition_id = 0;
748 
749  // Insert the TLB entry.
750  // The entry specifying whether the address is "real" is set to
751  // false for syscall emulation mode regardless of whether the
752  // address is real in preceding code. Not sure sure that this is
753  // correct, but also not sure if it matters at all.
754  tc->getDTBPtr()->insert(alignedvaddr, partition_id, context_id,
755  false, entry.pte);
756  }
757 }
758 
759 void
760 SpillNNormal::invoke(ThreadContext *tc, const StaticInstPtr &inst)
761 {
762  if (FullSystem) {
763  SparcFaultBase::invoke(tc, inst);
764  return;
765  }
766 
767  doNormalFault(tc, trapType(), false);
768 
769  Process *p = tc->getProcessPtr();
770 
771  SparcProcess *sp = dynamic_cast<SparcProcess *>(p);
772  assert(sp);
773 
774  // Then adjust the PC and NPC
775  tc->pcState(sp->readSpillStart());
776 }
777 
778 void
779 FillNNormal::invoke(ThreadContext *tc, const StaticInstPtr &inst)
780 {
781  if (FullSystem) {
782  SparcFaultBase::invoke(tc, inst);
783  return;
784  }
785 
786  doNormalFault(tc, trapType(), false);
787 
788  Process *p = tc->getProcessPtr();
789 
790  SparcProcess *sp = dynamic_cast<SparcProcess *>(p);
791  assert(sp);
792 
793  // Then adjust the PC and NPC
794  tc->pcState(sp->readFillStart());
795 }
796 
797 void
798 TrapInstruction::invoke(ThreadContext *tc, const StaticInstPtr &inst)
799 {
800  if (FullSystem) {
801  SparcFaultBase::invoke(tc, inst);
802  return;
803  }
804 
805  // In SE, this mechanism is how the process requests a service from
806  // the operating system. We'll get the process object from the thread
807  // context and let it service the request.
808 
809  Process *p = tc->getProcessPtr();
810 
811  SparcProcess *sp = dynamic_cast<SparcProcess *>(p);
812  assert(sp);
813 
814  Fault fault;
815  sp->handleTrap(_n, tc, &fault);
816 
817  // We need to explicitly advance the pc, since that's not done for us
818  // on a faulting instruction
819  PCState pc = tc->pcState();
820  pc.advance();
821  tc->pcState(pc);
822 }
823 
824 } // namespace SparcISA
825 
bool asiIsReal(ASI asi)
Definition: asi.cc:142
#define panic(...)
Definition: misc.hh:153
void getHyperVector(ThreadContext *tc, Addr &PC, Addr &NPC, MiscReg TT)
Definition: faults.cc:475
uint32_t MachInst
Definition: types.hh:41
uint32_t TrapType
Definition: faults.hh:43
const int MaxGL
Definition: sparc_traits.hh:39
void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv)
This sets everything up for a normal trap except for actually jumping to the handler.
Definition: faults.cc:375
Addr pageAlign(Addr a)
Definition: page_table.hh:109
virtual MiscReg readMiscRegNoEffect(int misc_reg) const =0
Bitfield< 0 > sp
Definition: miscregs.hh:1386
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
Definition: root.cc:146
Stats::Scalar FaultStat
Definition: faults.hh:42
Bitfield< 15, 8 > H
Definition: int.hh:57
virtual void setMiscReg(int misc_reg, const MiscReg &val)=0
virtual Process * getProcessPtr()=0
virtual TheISA::PCState pcState()=0
ThreadContext is the external interface to all thread state for anything outside of the CPU...
uint32_t MachInst
Definition: types.hh:40
Bitfield< 2 > hpriv
Definition: miscregs.hh:121
Addr pc() const
Definition: types.hh:138
Bitfield< 23, 20 > tl
virtual uint64_t readIntReg(int reg_idx)=0
virtual TheISA::TLB * getDTBPtr()=0
MicroPC upc() const
Definition: types.hh:373
Hyper privileged registers.
Definition: miscregs.hh:77
void replaceBits(T &val, int first, int last, B bit_val)
A convenience function to replace bits first to last of val with bit_val in place.
Definition: bitfield.hh:145
Addr readSpillStart()
Definition: process.hh:68
void enterREDState(ThreadContext *tc)
This causes the thread context to enter RED state.
Definition: faults.cc:275
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
MicroPC nupc() const
Definition: types.hh:376
#define ULL(N)
uint64_t constant
Definition: types.hh:50
PageTableBase * pTable
Definition: process.hh:178
Ancillary State Registers.
Definition: miscregs.hh:45
const int MaxPGL
Definition: sparc_traits.hh:40
Bitfield< 20 > level
Definition: intmessage.hh:48
SignedBitfield< 15, 8 > SH
Definition: int.hh:58
bool fixupStackFault(Addr vaddr)
Attempt to fix up a fault at vaddr by allocating a page on the stack.
Definition: process.cc:338
const int NumIntArchRegs
Definition: registers.hh:91
Declarations of a non-full system Page Table.
const int MaxTL
Definition: sparc_traits.hh:38
Addr npc() const
Definition: types.hh:141
Privilged Registers.
Definition: miscregs.hh:59
MipsFaultBase::FaultVals FaultVals
Definition: faults.cc:49
virtual void handleTrap(int trapNum, ThreadContext *tc, Fault *fault)
Definition: process.cc:66
const int NWindows
Definition: sparc_traits.hh:43
void doREDFault(ThreadContext *tc, TrapType tt)
This sets everything up for a RED state trap except for actually jumping to the handler.
Definition: faults.cc:296
uint64_t MiscReg
Definition: registers.hh:48
void getREDVector(MiscReg TT, Addr &PC, Addr &NPC)
Definition: faults.cc:466
virtual bool lookup(Addr vaddr, TheISA::TlbEntry &entry)=0
Lookup function.
Bitfield< 5 > red
Definition: miscregs.hh:122
void getPrivVector(ThreadContext *tc, Addr &PC, Addr &NPC, MiscReg TT, MiscReg TL)
Definition: faults.cc:483
Bitfield< 2 > priv
Definition: miscregs.hh:129
const int MaxPTL
Definition: sparc_traits.hh:37
IntReg pc
Definition: remote_gdb.hh:91
Bitfield< 3, 0 > mask
Definition: types.hh:64
PageTableEntry pte
Definition: pagetable.hh:264
T bits(T val, int first, int last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it...
Definition: bitfield.hh:67
virtual void setMiscRegNoEffect(int misc_reg, const MiscReg &val)=0
Bitfield< 0 > p
std::shared_ptr< FaultBase > Fault
Definition: types.hh:184
virtual TheISA::TLB * getITBPtr()=0
ASI
Definition: asi.hh:38
virtual void invoke(ThreadContext *tc, const StaticInstPtr &inst=StaticInst::nullStaticInstPtr)
Definition: faults.cc:43
Addr readFillStart()
Definition: process.hh:67

Generated on Fri Jun 9 2017 13:03:34 for gem5 by doxygen 1.8.6