faults.cc (13548:b76f99d052bb) faults.cc (13612:12ae022f3a30)
1/*
2 * Copyright (c) 2016 RISC-V Foundation
3 * Copyright (c) 2016 The University of Virginia
4 * Copyright (c) 2018 TU Dresden
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met: redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer;
11 * redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution;
14 * neither the name of the copyright holders nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * Authors: Alec Roelke
31 * Robert Scheffel
32 */
33#include "arch/riscv/faults.hh"
34
35#include "arch/riscv/isa.hh"
36#include "arch/riscv/registers.hh"
37#include "arch/riscv/system.hh"
38#include "arch/riscv/utility.hh"
39#include "cpu/base.hh"
40#include "cpu/thread_context.hh"
41#include "sim/debug.hh"
42#include "sim/full_system.hh"
43
44namespace RiscvISA
45{
46
47void
48RiscvFault::invokeSE(ThreadContext *tc, const StaticInstPtr &inst)
49{
50 panic("Fault %s encountered at pc 0x%016llx.", name(), tc->pcState().pc());
51}
52
53void
54RiscvFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
55{
56 PCState pcState = tc->pcState();
57
58 if (FullSystem) {
59 PrivilegeMode pp = (PrivilegeMode)tc->readMiscReg(MISCREG_PRV);
60 PrivilegeMode prv = PRV_M;
61 STATUS status = tc->readMiscReg(MISCREG_STATUS);
62
63 // Set fault handler privilege mode
64 if (isInterrupt()) {
65 if (pp != PRV_M &&
66 bits(tc->readMiscReg(MISCREG_MIDELEG), _code) != 0) {
67 prv = PRV_S;
68 }
69 if (pp == PRV_U &&
70 bits(tc->readMiscReg(MISCREG_SIDELEG), _code) != 0) {
71 prv = PRV_U;
72 }
73 } else {
74 if (pp != PRV_M &&
75 bits(tc->readMiscReg(MISCREG_MEDELEG), _code) != 0) {
76 prv = PRV_S;
77 }
78 if (pp == PRV_U &&
79 bits(tc->readMiscReg(MISCREG_SEDELEG), _code) != 0) {
80 prv = PRV_U;
81 }
82 }
83
84 // Set fault registers and status
85 MiscRegIndex cause, epc, tvec, tval;
86 switch (prv) {
87 case PRV_U:
88 cause = MISCREG_UCAUSE;
89 epc = MISCREG_UEPC;
90 tvec = MISCREG_UTVEC;
91 tval = MISCREG_UTVAL;
92
93 status.upie = status.uie;
94 status.uie = 0;
95 break;
96 case PRV_S:
97 cause = MISCREG_SCAUSE;
98 epc = MISCREG_SEPC;
99 tvec = MISCREG_STVEC;
100 tval = MISCREG_STVAL;
101
102 status.spp = pp;
103 status.spie = status.sie;
104 status.sie = 0;
105 break;
106 case PRV_M:
107 cause = MISCREG_MCAUSE;
108 epc = MISCREG_MEPC;
109 tvec = MISCREG_MTVEC;
110 tval = MISCREG_MTVAL;
111
112 status.mpp = pp;
113 status.mpie = status.sie;
114 status.mie = 0;
115 break;
116 default:
117 panic("Unknown privilege mode %d.", prv);
118 break;
119 }
120
121 // Set fault cause, privilege, and return PC
122 tc->setMiscReg(cause,
1/*
2 * Copyright (c) 2016 RISC-V Foundation
3 * Copyright (c) 2016 The University of Virginia
4 * Copyright (c) 2018 TU Dresden
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met: redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer;
11 * redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution;
14 * neither the name of the copyright holders nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * Authors: Alec Roelke
31 * Robert Scheffel
32 */
33#include "arch/riscv/faults.hh"
34
35#include "arch/riscv/isa.hh"
36#include "arch/riscv/registers.hh"
37#include "arch/riscv/system.hh"
38#include "arch/riscv/utility.hh"
39#include "cpu/base.hh"
40#include "cpu/thread_context.hh"
41#include "sim/debug.hh"
42#include "sim/full_system.hh"
43
44namespace RiscvISA
45{
46
47void
48RiscvFault::invokeSE(ThreadContext *tc, const StaticInstPtr &inst)
49{
50 panic("Fault %s encountered at pc 0x%016llx.", name(), tc->pcState().pc());
51}
52
53void
54RiscvFault::invoke(ThreadContext *tc, const StaticInstPtr &inst)
55{
56 PCState pcState = tc->pcState();
57
58 if (FullSystem) {
59 PrivilegeMode pp = (PrivilegeMode)tc->readMiscReg(MISCREG_PRV);
60 PrivilegeMode prv = PRV_M;
61 STATUS status = tc->readMiscReg(MISCREG_STATUS);
62
63 // Set fault handler privilege mode
64 if (isInterrupt()) {
65 if (pp != PRV_M &&
66 bits(tc->readMiscReg(MISCREG_MIDELEG), _code) != 0) {
67 prv = PRV_S;
68 }
69 if (pp == PRV_U &&
70 bits(tc->readMiscReg(MISCREG_SIDELEG), _code) != 0) {
71 prv = PRV_U;
72 }
73 } else {
74 if (pp != PRV_M &&
75 bits(tc->readMiscReg(MISCREG_MEDELEG), _code) != 0) {
76 prv = PRV_S;
77 }
78 if (pp == PRV_U &&
79 bits(tc->readMiscReg(MISCREG_SEDELEG), _code) != 0) {
80 prv = PRV_U;
81 }
82 }
83
84 // Set fault registers and status
85 MiscRegIndex cause, epc, tvec, tval;
86 switch (prv) {
87 case PRV_U:
88 cause = MISCREG_UCAUSE;
89 epc = MISCREG_UEPC;
90 tvec = MISCREG_UTVEC;
91 tval = MISCREG_UTVAL;
92
93 status.upie = status.uie;
94 status.uie = 0;
95 break;
96 case PRV_S:
97 cause = MISCREG_SCAUSE;
98 epc = MISCREG_SEPC;
99 tvec = MISCREG_STVEC;
100 tval = MISCREG_STVAL;
101
102 status.spp = pp;
103 status.spie = status.sie;
104 status.sie = 0;
105 break;
106 case PRV_M:
107 cause = MISCREG_MCAUSE;
108 epc = MISCREG_MEPC;
109 tvec = MISCREG_MTVEC;
110 tval = MISCREG_MTVAL;
111
112 status.mpp = pp;
113 status.mpie = status.sie;
114 status.mie = 0;
115 break;
116 default:
117 panic("Unknown privilege mode %d.", prv);
118 break;
119 }
120
121 // Set fault cause, privilege, and return PC
122 tc->setMiscReg(cause,
123 (isInterrupt() << (sizeof(MiscReg) * 4 - 1)) | _code);
123 (isInterrupt() << (sizeof(uint64_t) * 4 - 1)) | _code);
124 tc->setMiscReg(epc, tc->instAddr());
125 tc->setMiscReg(tval, trap_value());
126 tc->setMiscReg(MISCREG_PRV, prv);
127 tc->setMiscReg(MISCREG_STATUS, status);
128
129 // Set PC to fault handler address
130 Addr addr = tc->readMiscReg(tvec) >> 2;
131 if (isInterrupt() && bits(tc->readMiscReg(tvec), 1, 0) == 1)
132 addr += 4 * _code;
133 pcState.set(addr);
134 } else {
135 invokeSE(tc, inst);
136 advancePC(pcState, inst);
137 }
138 tc->pcState(pcState);
139}
140
141void Reset::invoke(ThreadContext *tc, const StaticInstPtr &inst)
142{
143 tc->setMiscReg(MISCREG_PRV, PRV_M);
144 STATUS status = tc->readMiscReg(MISCREG_STATUS);
145 status.mie = 0;
146 status.mprv = 0;
147 tc->setMiscReg(MISCREG_STATUS, status);
148 tc->setMiscReg(MISCREG_MCAUSE, 0);
149
150 // Advance the PC to the implementation-defined reset vector
151 PCState pc = static_cast<RiscvSystem *>(tc->getSystemPtr())->resetVect();
152 tc->pcState(pc);
153}
154
155void
156UnknownInstFault::invokeSE(ThreadContext *tc, const StaticInstPtr &inst)
157{
158 panic("Unknown instruction 0x%08x at pc 0x%016llx", inst->machInst,
159 tc->pcState().pc());
160}
161
162void
163IllegalInstFault::invokeSE(ThreadContext *tc, const StaticInstPtr &inst)
164{
165 panic("Illegal instruction 0x%08x at pc 0x%016llx: %s", inst->machInst,
166 tc->pcState().pc(), reason.c_str());
167}
168
169void
170UnimplementedFault::invokeSE(ThreadContext *tc,
171 const StaticInstPtr &inst)
172{
173 panic("Unimplemented instruction %s at pc 0x%016llx", instName,
174 tc->pcState().pc());
175}
176
177void
178IllegalFrmFault::invokeSE(ThreadContext *tc, const StaticInstPtr &inst)
179{
180 panic("Illegal floating-point rounding mode 0x%x at pc 0x%016llx.",
181 frm, tc->pcState().pc());
182}
183
184void
185BreakpointFault::invokeSE(ThreadContext *tc, const StaticInstPtr &inst)
186{
187 schedRelBreak(0);
188}
189
190void
191SyscallFault::invokeSE(ThreadContext *tc, const StaticInstPtr &inst)
192{
193 Fault *fault = NoFault;
194 tc->syscall(tc->readIntReg(SyscallNumReg), fault);
195}
196
197} // namespace RiscvISA
124 tc->setMiscReg(epc, tc->instAddr());
125 tc->setMiscReg(tval, trap_value());
126 tc->setMiscReg(MISCREG_PRV, prv);
127 tc->setMiscReg(MISCREG_STATUS, status);
128
129 // Set PC to fault handler address
130 Addr addr = tc->readMiscReg(tvec) >> 2;
131 if (isInterrupt() && bits(tc->readMiscReg(tvec), 1, 0) == 1)
132 addr += 4 * _code;
133 pcState.set(addr);
134 } else {
135 invokeSE(tc, inst);
136 advancePC(pcState, inst);
137 }
138 tc->pcState(pcState);
139}
140
141void Reset::invoke(ThreadContext *tc, const StaticInstPtr &inst)
142{
143 tc->setMiscReg(MISCREG_PRV, PRV_M);
144 STATUS status = tc->readMiscReg(MISCREG_STATUS);
145 status.mie = 0;
146 status.mprv = 0;
147 tc->setMiscReg(MISCREG_STATUS, status);
148 tc->setMiscReg(MISCREG_MCAUSE, 0);
149
150 // Advance the PC to the implementation-defined reset vector
151 PCState pc = static_cast<RiscvSystem *>(tc->getSystemPtr())->resetVect();
152 tc->pcState(pc);
153}
154
155void
156UnknownInstFault::invokeSE(ThreadContext *tc, const StaticInstPtr &inst)
157{
158 panic("Unknown instruction 0x%08x at pc 0x%016llx", inst->machInst,
159 tc->pcState().pc());
160}
161
162void
163IllegalInstFault::invokeSE(ThreadContext *tc, const StaticInstPtr &inst)
164{
165 panic("Illegal instruction 0x%08x at pc 0x%016llx: %s", inst->machInst,
166 tc->pcState().pc(), reason.c_str());
167}
168
169void
170UnimplementedFault::invokeSE(ThreadContext *tc,
171 const StaticInstPtr &inst)
172{
173 panic("Unimplemented instruction %s at pc 0x%016llx", instName,
174 tc->pcState().pc());
175}
176
177void
178IllegalFrmFault::invokeSE(ThreadContext *tc, const StaticInstPtr &inst)
179{
180 panic("Illegal floating-point rounding mode 0x%x at pc 0x%016llx.",
181 frm, tc->pcState().pc());
182}
183
184void
185BreakpointFault::invokeSE(ThreadContext *tc, const StaticInstPtr &inst)
186{
187 schedRelBreak(0);
188}
189
190void
191SyscallFault::invokeSE(ThreadContext *tc, const StaticInstPtr &inst)
192{
193 Fault *fault = NoFault;
194 tc->syscall(tc->readIntReg(SyscallNumReg), fault);
195}
196
197} // namespace RiscvISA