gem5 v24.0.0.0
Loading...
Searching...
No Matches
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"
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
47namespace gem5
48{
49
50namespace RiscvISA
51{
52
53void
55{
56 panic("Fault %s encountered at pc %s.", name(), tc->pcState());
57}
58
59void
61{
62 auto pc_state = tc->pcState().as<PCState>();
63
64 DPRINTFS(Faults, tc->getCpuPtr(), "Fault (%s, %u) at PC: %s\n",
65 name(), exception(), pc_state);
66
67 if (FullSystem) {
69 PrivilegeMode prv = PRV_M;
70 MISA misa = tc->readMiscRegNoEffect(MISCREG_ISA);
71 STATUS status = tc->readMiscReg(MISCREG_STATUS);
72
73 // According to riscv-privileged-v1.11, if a NMI occurs at the middle
74 // of a M-mode trap handler, the state (epc/cause) will be overwritten
75 // and is not necessary recoverable. There's nothing we can do here so
76 // we'll just warn our user that the CPU state might be broken.
77 warn_if(isNonMaskableInterrupt() && pp == PRV_M && status.mie == 0,
78 "NMI overwriting M-mode trap handler state");
79
80 // Set fault handler privilege mode
82 prv = PRV_M;
83 } else if (isInterrupt()) {
84 if (pp != PRV_M &&
86 prv = (misa.rvs) ? PRV_S : ((misa.rvn) ? PRV_U : PRV_M);
87 }
88 if (pp == PRV_U && misa.rvs && misa.rvn &&
90 prv = PRV_U;
91 }
92 } else {
93 if (pp != PRV_M &&
95 prv = (misa.rvs) ? PRV_S : ((misa.rvn) ? PRV_U : PRV_M);
96 }
97 if (pp == PRV_U && misa.rvs && misa.rvn &&
99 prv = PRV_U;
100 }
101 }
102
103 // Set fault registers and status
104 MiscRegIndex cause, epc, tvec, tval;
105 switch (prv) {
106 case PRV_U:
107 cause = MISCREG_UCAUSE;
108 epc = MISCREG_UEPC;
109 tvec = MISCREG_UTVEC;
110 tval = MISCREG_UTVAL;
111
112 status.upie = status.uie;
113 status.uie = 0;
114 break;
115 case PRV_S:
116 cause = MISCREG_SCAUSE;
117 epc = MISCREG_SEPC;
118 tvec = MISCREG_STVEC;
119 tval = MISCREG_STVAL;
120
121 status.spp = pp;
122 status.spie = status.sie;
123 status.sie = 0;
124 break;
125 case PRV_M:
126 cause = MISCREG_MCAUSE;
127 epc = MISCREG_MEPC;
129 tval = MISCREG_MTVAL;
130
131 status.mpp = pp;
132 status.mpie = status.mie;
133 status.mie = 0;
134 break;
135 default:
136 panic("Unknown privilege mode %d.", prv);
137 break;
138 }
139
140 // Set fault cause, privilege, and return PC
141 uint64_t _cause = _code;
142 if (isInterrupt()) {
143 _cause |= CAUSE_INTERRUPT_MASKS[pc_state.rvType()];
144 }
145 tc->setMiscReg(cause, _cause);
146 tc->setMiscReg(epc, tc->pcState().instAddr());
147 tc->setMiscReg(tval, trap_value());
148 tc->setMiscReg(MISCREG_PRV, prv);
150 // Temporarily mask NMI while we're in NMI handler. Otherweise, the
151 // checkNonMaskableInterrupt will always return true and we'll be
152 // stucked in an infinite loop.
154 tc->setMiscReg(MISCREG_NMIE, 0);
155 }
156
157 // Clear load reservation address
158 auto isa = static_cast<RiscvISA::ISA*>(tc->getIsaPtr());
160
161 // Set PC to fault handler address
162 Addr addr = isa->getFaultHandlerAddr(tvec, _code, isInterrupt());
163 pc_state.set(addr);
164 tc->pcState(pc_state);
165 } else {
166 invokeSE(tc, inst);
167 }
168}
169
170void
172{
174 STATUS status = tc->readMiscReg(MISCREG_STATUS);
175 status.mie = 0;
176 status.mprv = 0;
179
180 // Advance the PC to the implementation-defined reset vector
181 auto workload = dynamic_cast<Workload *>(tc->getSystemPtr()->workload);
182 std::unique_ptr<PCState> new_pc(dynamic_cast<PCState *>(
183 tc->getIsaPtr()->newPCState(workload->getEntry())));
184 panic_if(!new_pc, "Failed create new PCState from ISA pointer");
185 VTYPE vtype = 0;
186 vtype.vill = 1;
187 new_pc->vtype(vtype);
188 new_pc->vl(0);
189 tc->pcState(*new_pc);
190
191 // Reset PMP Cfg
192 auto* mmu = dynamic_cast<RiscvISA::MMU*>(tc->getMMUPtr());
193 if (mmu == nullptr) {
194 warn("MMU is not Riscv MMU instance, we can't reset PMP");
195 return;
196 }
197 mmu->getPMP()->pmpReset();
198}
199
200void
202{
203 auto *rsi = static_cast<RiscvStaticInst *>(inst.get());
204 panic("Unknown instruction 0x%08x at pc %s", rsi->machInst,
205 tc->pcState());
206}
207
208void
210{
211 if (! tc->getSystemPtr()->trapToGdb(GDBSignal::ILL, tc->contextId()) ) {
212 auto *rsi = static_cast<RiscvStaticInst *>(inst.get());
213 panic("Illegal instruction 0x%08x at pc %s: %s", rsi->machInst,
214 tc->pcState(), reason.c_str());
215 }
216}
217
218void
220{
221 panic("Unimplemented instruction %s at pc %s", instName, tc->pcState());
222}
223
224void
226{
227 panic("Illegal floating-point rounding mode 0x%x at pc %s.",
228 frm, tc->pcState());
229}
230
231void
233{
234 if (! tc->getSystemPtr()->trapToGdb(GDBSignal::TRAP, tc->contextId()) ) {
235 schedRelBreak(0);
236 }
237}
238
239void
241{
242 /* Advance the PC to next instruction so - once (simulated) syscall
243 is executed - execution continues. */
244 auto pc_state = tc->pcState().as<PCState>();
245 inst->advancePC(pc_state);
246 tc->pcState(pc_state);
247
248 tc->getSystemPtr()->workload->syscall(tc);
249}
250
251bool
253{
254 auto addr_fault = dynamic_cast<AddressFault *>(fault.get());
255 if (addr_fault) {
256 va = addr_fault->trap_value();
257 return true;
258 }
259
260 auto pgt_fault = dynamic_cast<GenericPageTableFault *>(fault.get());
261 if (pgt_fault) {
262 va = pgt_fault->getFaultVAddr();
263 return true;
264 }
265
266 return false;
267}
268
269} // namespace RiscvISA
270} // namespace gem5
#define DPRINTFS(x, s,...)
Definition trace.hh:217
virtual PCStateBase * newPCState(Addr new_inst_addr=0) const =0
Addr getFaultVAddr() const
Definition faults.hh:125
Target & as()
Definition pcstate.hh:73
Addr instAddr() const
Returns the memory address of the instruction this PC points to.
Definition pcstate.hh:108
T * get() const
Directly access the pointer itself without taking a reference.
Definition refcnt.hh:227
RegVal trap_value() const override
Definition faults.hh:290
void invokeSE(ThreadContext *tc, const StaticInstPtr &inst) override
Definition faults.cc:232
void clearLoadReservation(ContextID cid)
Definition isa.hh:158
void invokeSE(ThreadContext *tc, const StaticInstPtr &inst) override
Definition faults.cc:225
void invokeSE(ThreadContext *tc, const StaticInstPtr &inst) override
Definition faults.cc:209
void invoke(ThreadContext *tc, const StaticInstPtr &inst=nullStaticInstPtr) override
Definition faults.cc:171
bool isInterrupt() const
Definition faults.hh:171
virtual void invokeSE(ThreadContext *tc, const StaticInstPtr &inst)
Definition faults.cc:54
ExceptionCode exception() const
Definition faults.hh:176
void invoke(ThreadContext *tc, const StaticInstPtr &inst) override
Definition faults.cc:60
FaultName name() const override
Definition faults.hh:170
bool isNonMaskableInterrupt() const
Definition faults.hh:172
virtual RegVal trap_value() const
Definition faults.hh:177
Base class for all RISC-V static instructions.
void invokeSE(ThreadContext *tc, const StaticInstPtr &inst) override
Definition faults.cc:240
void invokeSE(ThreadContext *tc, const StaticInstPtr &inst) override
Definition faults.cc:219
void invokeSE(ThreadContext *tc, const StaticInstPtr &inst) override
Definition faults.cc:201
virtual void advancePC(PCStateBase &pc_state) const =0
Workload * workload
OS kernel.
Definition system.hh:326
bool trapToGdb(GDBSignal signal, ContextID ctx_id) const
Definition system.cc:394
ThreadContext is the external interface to all thread state for anything outside of the CPU.
virtual RegVal readMiscReg(RegIndex misc_reg)=0
virtual void setMiscReg(RegIndex misc_reg, RegVal val)=0
virtual System * getSystemPtr()=0
virtual BaseISA * getIsaPtr() const =0
virtual BaseCPU * getCpuPtr()=0
virtual const PCStateBase & pcState() const =0
virtual RegVal readMiscRegNoEffect(RegIndex misc_reg) const =0
virtual BaseMMU * getMMUPtr()=0
virtual ContextID contextId() const =0
virtual void syscall(ThreadContext *tc)
Definition workload.hh:113
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:79
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:188
#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
#define warn(...)
Definition logging.hh:256
#define warn_if(cond,...)
Conditional warning macro that checks the supplied condition and only prints a warning if the conditi...
Definition logging.hh:283
Bitfield< 5, 0 > status
Bitfield< 8 > va
const RegVal CAUSE_INTERRUPT_MASKS[enums::Num_RiscvType]
Definition misc.hh:1497
bool getFaultVAddr(Fault fault, Addr &va)
Returns true if the fault passed as a first argument was triggered by a memory access,...
Definition faults.cc:252
@ MISCREG_SIDELEG
Definition misc.hh:178
@ MISCREG_STATUS
Definition misc.hh:76
@ MISCREG_MEDELEG
Definition misc.hh:148
@ MISCREG_SEDELEG
Definition misc.hh:177
@ MISCREG_MIDELEG
Definition misc.hh:149
Bitfield< 3 > addr
Definition types.hh:84
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
std::shared_ptr< FaultBase > Fault
Definition types.hh:249
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
Definition root.cc:220
void schedRelBreak(Tick delta)
Cause the simulator to execute a breakpoint relative to the current tick.
Definition debug.cc:93
PMP header file.

Generated on Tue Jun 18 2024 16:23:57 for gem5 by doxygen 1.11.0