gem5  [DEVELOP-FOR-23.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) 2016 RISC-V Foundation
3  * Copyright (c) 2016 The University of Virginia
4  * Copyright (c) 2018 TU Dresden
5  * Copyright (c) 2020 Barkhausen Institut
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are
10  * met: redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer;
12  * redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution;
15  * neither the name of the copyright holders nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "arch/riscv/faults.hh"
33 
35 #include "arch/riscv/isa.hh"
36 #include "arch/riscv/mmu.hh"
37 #include "arch/riscv/pmp.hh"
38 #include "arch/riscv/regs/misc.hh"
39 #include "arch/riscv/utility.hh"
40 #include "cpu/base.hh"
41 #include "cpu/thread_context.hh"
42 #include "debug/Faults.hh"
43 #include "sim/debug.hh"
44 #include "sim/full_system.hh"
45 #include "sim/workload.hh"
46 
47 namespace gem5
48 {
49 
50 namespace RiscvISA
51 {
52 
53 void
55 {
56  panic("Fault %s encountered at pc %s.", name(), tc->pcState());
57 }
58 
59 void
61 {
62  auto pc_state = tc->pcState().as<PCState>();
63 
64  DPRINTFS(Faults, tc->getCpuPtr(), "Fault (%s) at PC: %s\n",
65  name(), pc_state);
66 
67  if (FullSystem) {
69  PrivilegeMode prv = PRV_M;
70  STATUS status = tc->readMiscReg(MISCREG_STATUS);
71 
72  // According to riscv-privileged-v1.11, if a NMI occurs at the middle
73  // of a M-mode trap handler, the state (epc/cause) will be overwritten
74  // and is not necessary recoverable. There's nothing we can do here so
75  // we'll just warn our user that the CPU state might be broken.
76  warn_if(isNonMaskableInterrupt() && pp == PRV_M && status.mie == 0,
77  "NMI overwriting M-mode trap handler state");
78 
79  // Set fault handler privilege mode
80  if (isNonMaskableInterrupt()) {
81  prv = PRV_M;
82  } else if (isInterrupt()) {
83  if (pp != PRV_M &&
84  bits(tc->readMiscReg(MISCREG_MIDELEG), _code) != 0) {
85  prv = PRV_S;
86  }
87  if (pp == PRV_U &&
88  bits(tc->readMiscReg(MISCREG_SIDELEG), _code) != 0) {
89  prv = PRV_U;
90  }
91  } else {
92  if (pp != PRV_M &&
93  bits(tc->readMiscReg(MISCREG_MEDELEG), _code) != 0) {
94  prv = PRV_S;
95  }
96  if (pp == PRV_U &&
97  bits(tc->readMiscReg(MISCREG_SEDELEG), _code) != 0) {
98  prv = PRV_U;
99  }
100  }
101 
102  // Set fault registers and status
103  MiscRegIndex cause, epc, tvec, tval;
104  switch (prv) {
105  case PRV_U:
106  cause = MISCREG_UCAUSE;
107  epc = MISCREG_UEPC;
108  tvec = MISCREG_UTVEC;
109  tval = MISCREG_UTVAL;
110 
111  status.upie = status.uie;
112  status.uie = 0;
113  break;
114  case PRV_S:
115  cause = MISCREG_SCAUSE;
116  epc = MISCREG_SEPC;
117  tvec = MISCREG_STVEC;
118  tval = MISCREG_STVAL;
119 
120  status.spp = pp;
121  status.spie = status.sie;
122  status.sie = 0;
123  break;
124  case PRV_M:
125  cause = MISCREG_MCAUSE;
126  epc = MISCREG_MEPC;
128  tval = MISCREG_MTVAL;
129 
130  status.mpp = pp;
131  status.mpie = status.mie;
132  status.mie = 0;
133  break;
134  default:
135  panic("Unknown privilege mode %d.", prv);
136  break;
137  }
138 
139  // Set fault cause, privilege, and return PC
140  uint64_t _cause = _code;
141  if (isInterrupt()) {
142  _cause |= CAUSE_INTERRUPT_MASKS[pc_state.rvType()];
143  }
144  tc->setMiscReg(cause, _cause);
145  tc->setMiscReg(epc, tc->pcState().instAddr());
146  tc->setMiscReg(tval, trap_value());
147  tc->setMiscReg(MISCREG_PRV, prv);
149  // Temporarily mask NMI while we're in NMI handler. Otherweise, the
150  // checkNonMaskableInterrupt will always return true and we'll be
151  // stucked in an infinite loop.
152  if (isNonMaskableInterrupt()) {
153  tc->setMiscReg(MISCREG_NMIE, 0);
154  }
155 
156  // Clear load reservation address
157  auto isa = static_cast<RiscvISA::ISA*>(tc->getIsaPtr());
158  isa->clearLoadReservation(tc->contextId());
159 
160  // Set PC to fault handler address
161  Addr addr = mbits(tc->readMiscReg(tvec), 63, 2);
162  if (isInterrupt() && bits(tc->readMiscReg(tvec), 1, 0) == 1)
163  addr += 4 * _code;
164  pc_state.set(addr);
165  tc->pcState(pc_state);
166  } else {
167  inst->advancePC(pc_state);
168  tc->pcState(pc_state);
169  invokeSE(tc, inst);
170  }
171 }
172 
173 void
175 {
177  STATUS status = tc->readMiscReg(MISCREG_STATUS);
178  status.mie = 0;
179  status.mprv = 0;
181  tc->setMiscReg(MISCREG_MCAUSE, 0);
182 
183  // Advance the PC to the implementation-defined reset vector
184  auto workload = dynamic_cast<Workload *>(tc->getSystemPtr()->workload);
185  std::unique_ptr<PCState> new_pc(dynamic_cast<PCState *>(
186  tc->getIsaPtr()->newPCState(workload->getEntry())));
187  panic_if(!new_pc, "Failed create new PCState from ISA pointer");
188  tc->pcState(*new_pc);
189 
190  // Reset PMP Cfg
191  auto* mmu = dynamic_cast<RiscvISA::MMU*>(tc->getMMUPtr());
192  if (mmu == nullptr) {
193  warn("MMU is not Riscv MMU instance, we can't reset PMP");
194  return;
195  }
196  mmu->getPMP()->pmpReset();
197 }
198 
199 void
201 {
202  auto *rsi = static_cast<RiscvStaticInst *>(inst.get());
203  panic("Unknown instruction 0x%08x at pc %s", rsi->machInst,
204  tc->pcState());
205 }
206 
207 void
209 {
210  auto *rsi = static_cast<RiscvStaticInst *>(inst.get());
211  panic("Illegal instruction 0x%08x at pc %s: %s", rsi->machInst,
212  tc->pcState(), reason.c_str());
213 }
214 
215 void
217 {
218  panic("Unimplemented instruction %s at pc %s", instName, tc->pcState());
219 }
220 
221 void
223 {
224  panic("Illegal floating-point rounding mode 0x%x at pc %s.",
225  frm, tc->pcState());
226 }
227 
228 void
230 {
231  schedRelBreak(0);
232 }
233 
234 void
236 {
237  tc->getSystemPtr()->workload->syscall(tc);
238 }
239 
240 } // namespace RiscvISA
241 } // namespace gem5
gem5::RiscvISA::PRV_S
@ PRV_S
Definition: isa.hh:58
gem5::RiscvISA::MISCREG_STATUS
@ MISCREG_STATUS
Definition: misc.hh:75
gem5::PCStateBase::instAddr
Addr instAddr() const
Returns the memory address of the instruction this PC points to.
Definition: pcstate.hh:107
gem5::RiscvISA::UnimplementedFault::instName
const std::string instName
Definition: faults.hh:206
gem5::ThreadContext::readMiscReg
virtual RegVal readMiscReg(RegIndex misc_reg)=0
gem5::ThreadContext::getSystemPtr
virtual System * getSystemPtr()=0
gem5::RiscvISA::PRV_M
@ PRV_M
Definition: isa.hh:59
warn
#define warn(...)
Definition: logging.hh:256
faults.hh
gem5::BaseISA::clearLoadReservation
virtual void clearLoadReservation(ContextID cid)
Definition: isa.hh:73
gem5::RiscvISA::MISCREG_SIDELEG
@ MISCREG_SIDELEG
Definition: misc.hh:177
gem5::RiscvISA::RiscvStaticInst
Base class for all RISC-V static instructions.
Definition: static_inst.hh:51
gem5::PCStateBase::as
Target & as()
Definition: pcstate.hh:72
gem5::ThreadContext::getMMUPtr
virtual BaseMMU * getMMUPtr()=0
gem5::RiscvISA::MMU
Definition: mmu.hh:54
gem5::ThreadContext::pcState
virtual const PCStateBase & pcState() const =0
gem5::RiscvISA::RiscvFault::invoke
void invoke(ThreadContext *tc, const StaticInstPtr &inst) override
Definition: faults.cc:60
gem5::RiscvISA::PrivilegeMode
PrivilegeMode
Definition: isa.hh:55
gem5::RiscvISA::MISCREG_MTVAL
@ MISCREG_MTVAL
Definition: misc.hh:154
gem5::RiscvISA::IllegalFrmFault::frm
const uint8_t frm
Definition: faults.hh:220
gem5::RiscvISA::MISCREG_SEDELEG
@ MISCREG_SEDELEG
Definition: misc.hh:176
gem5::ThreadContext::contextId
virtual ContextID contextId() const =0
gem5::System::workload
Workload * workload
OS kernel.
Definition: system.hh:326
gem5::RefCountingPtr::get
T * get() const
Directly access the pointer itself without taking a reference.
Definition: refcnt.hh:227
gem5::mbits
constexpr T mbits(T val, unsigned first, unsigned last)
Mask off the given bits in place like bits() but without shifting.
Definition: bitfield.hh:103
gem5::RiscvISA::RiscvFault::isInterrupt
bool isInterrupt() const
Definition: faults.hh:122
isa.hh
gem5::StaticInst::advancePC
virtual void advancePC(PCStateBase &pc_state) const =0
misc.hh
gem5::RefCountingPtr< StaticInst >
gem5::RiscvISA::MISCREG_SCAUSE
@ MISCREG_SCAUSE
Definition: misc.hh:182
gem5::RiscvISA::MISCREG_NMIE
@ MISCREG_NMIE
Definition: misc.hh:200
gem5::RiscvISA::MISCREG_MEDELEG
@ MISCREG_MEDELEG
Definition: misc.hh:147
gem5::RiscvISA::PCState
Definition: pcstate.hh:57
pmp.hh
gem5::schedRelBreak
void schedRelBreak(Tick delta)
Cause the simulator to execute a breakpoint relative to the current tick.
Definition: debug.cc:93
gem5::ThreadContext
ThreadContext is the external interface to all thread state for anything outside of the CPU.
Definition: thread_context.hh:88
gem5::BaseISA::newPCState
virtual PCStateBase * newPCState(Addr new_inst_addr=0) const =0
workload.hh
gem5::RiscvISA::MISCREG_SEPC
@ MISCREG_SEPC
Definition: misc.hh:181
debug.hh
gem5::RiscvISA::RiscvFault::name
FaultName name() const override
Definition: faults.hh:121
gem5::RiscvISA::IllegalInstFault::reason
const std::string reason
Definition: faults.hh:192
gem5::Workload
Definition: workload.hh:50
gem5::RiscvISA::MISCREG_MCAUSE
@ MISCREG_MCAUSE
Definition: misc.hh:153
gem5::RiscvISA::RiscvFault::_code
ExceptionCode _code
Definition: faults.hh:115
gem5::bits
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Definition: bitfield.hh:76
gem5::RiscvISA::Reset::invoke
void invoke(ThreadContext *tc, const StaticInstPtr &inst=nullStaticInstPtr) override
Definition: faults.cc:174
gem5::RiscvISA::MISCREG_NMIVEC
@ MISCREG_NMIVEC
Definition: misc.hh:198
static_inst.hh
gem5::Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
DPRINTFS
#define DPRINTFS(x, s,...)
Definition: trace.hh:217
gem5::RiscvISA::ISA
Definition: isa.hh:70
gem5::RiscvISA::MISCREG_MEPC
@ MISCREG_MEPC
Definition: misc.hh:152
full_system.hh
gem5::RiscvISA::UnknownInstFault::invokeSE
void invokeSE(ThreadContext *tc, const StaticInstPtr &inst) override
Definition: faults.cc:200
gem5::FullSystem
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
Definition: root.cc:220
warn_if
#define warn_if(cond,...)
Conditional warning macro that checks the supplied condition and only prints a warning if the conditi...
Definition: logging.hh:283
panic_if
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:214
gem5::RiscvISA::IllegalFrmFault::invokeSE
void invokeSE(ThreadContext *tc, const StaticInstPtr &inst) override
Definition: faults.cc:222
mmu.hh
gem5::RiscvISA::MISCREG_UTVEC
@ MISCREG_UTVEC
Definition: misc.hh:186
base.hh
gem5::RiscvISA::SyscallFault::invokeSE
void invokeSE(ThreadContext *tc, const StaticInstPtr &inst) override
Definition: faults.cc:235
gem5::ThreadContext::setMiscReg
virtual void setMiscReg(RegIndex misc_reg, RegVal val)=0
gem5::RiscvISA::BreakpointFault::invokeSE
void invokeSE(ThreadContext *tc, const StaticInstPtr &inst) override
Definition: faults.cc:229
gem5::RiscvISA::IllegalInstFault::invokeSE
void invokeSE(ThreadContext *tc, const StaticInstPtr &inst) override
Definition: faults.cc:208
gem5::RiscvISA::MISCREG_UEPC
@ MISCREG_UEPC
Definition: misc.hh:188
gem5::RiscvISA::MISCREG_MIDELEG
@ MISCREG_MIDELEG
Definition: misc.hh:148
utility.hh
gem5::ThreadContext::getCpuPtr
virtual BaseCPU * getCpuPtr()=0
gem5::RiscvISA::MISCREG_STVAL
@ MISCREG_STVAL
Definition: misc.hh:183
gem5::RiscvISA::PRV_U
@ PRV_U
Definition: isa.hh:57
gem5::RiscvISA::RiscvFault::trap_value
virtual RegVal trap_value() const
Definition: faults.hh:128
gem5::RiscvISA::MISCREG_UCAUSE
@ MISCREG_UCAUSE
Definition: misc.hh:189
gem5::ThreadContext::getIsaPtr
virtual BaseISA * getIsaPtr() const =0
gem5::RiscvISA::MiscRegIndex
MiscRegIndex
Definition: misc.hh:67
gem5::RiscvISA::MISCREG_UTVAL
@ MISCREG_UTVAL
Definition: misc.hh:190
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: gpu_translation_state.hh:37
gem5::RiscvISA::MISCREG_PRV
@ MISCREG_PRV
Definition: misc.hh:69
gem5::RiscvISA::UnimplementedFault::invokeSE
void invokeSE(ThreadContext *tc, const StaticInstPtr &inst) override
Definition: faults.cc:216
gem5::RiscvISA::MISCREG_STVEC
@ MISCREG_STVEC
Definition: misc.hh:178
thread_context.hh
gem5::RiscvISA::RiscvFault::invokeSE
virtual void invokeSE(ThreadContext *tc, const StaticInstPtr &inst)
Definition: faults.cc:54
gem5::RiscvISA::CAUSE_INTERRUPT_MASKS
const RegVal CAUSE_INTERRUPT_MASKS[enums::Num_RiscvType]
Definition: misc.hh:920
gem5::RiscvISA::MISCREG_MTVEC
@ MISCREG_MTVEC
Definition: misc.hh:149
gem5::RiscvISA::RiscvFault::isNonMaskableInterrupt
bool isNonMaskableInterrupt() const
Definition: faults.hh:123
gem5::Workload::syscall
virtual void syscall(ThreadContext *tc)
Definition: workload.hh:111
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:188
gem5::ArmISA::status
Bitfield< 5, 0 > status
Definition: misc_types.hh:480
gem5::X86ISA::addr
Bitfield< 3 > addr
Definition: types.hh:84

Generated on Sun Jul 30 2023 01:56:46 for gem5 by doxygen 1.8.17