faults.cc revision 13547
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 (pp != PRV_M && 65 bits(tc->readMiscReg(MISCREG_MEDELEG), _code) != 0) { 66 prv = PRV_S; 67 } 68 if (pp == PRV_U && 69 bits(tc->readMiscReg(MISCREG_SEDELEG), _code) != 0) { 70 prv = PRV_U; 71 } 72 73 // Set fault registers and status 74 MiscRegIndex cause, epc, tvec, tval; 75 switch (prv) { 76 case PRV_U: 77 cause = MISCREG_UCAUSE; 78 epc = MISCREG_UEPC; 79 tvec = MISCREG_UTVEC; 80 tval = MISCREG_UTVAL; 81 82 status.upie = status.uie; 83 status.uie = 0; 84 break; 85 case PRV_S: 86 cause = MISCREG_SCAUSE; 87 epc = MISCREG_SEPC; 88 tvec = MISCREG_STVEC; 89 tval = MISCREG_STVAL; 90 91 status.spp = pp; 92 status.spie = status.sie; 93 status.sie = 0; 94 break; 95 case PRV_M: 96 cause = MISCREG_MCAUSE; 97 epc = MISCREG_MEPC; 98 tvec = MISCREG_MTVEC; 99 tval = MISCREG_MTVAL; 100 101 status.mpp = pp; 102 status.mpie = status.sie; 103 status.mie = 0; 104 break; 105 default: 106 panic("Unknown privilege mode %d.", prv); 107 break; 108 } 109 110 // Set fault cause, privilege, and return PC 111 tc->setMiscReg(cause, 112 (isInterrupt() << (sizeof(MiscReg) * 4 - 1)) | _code); 113 tc->setMiscReg(epc, tc->instAddr()); 114 tc->setMiscReg(tval, trap_value()); 115 tc->setMiscReg(MISCREG_PRV, prv); 116 tc->setMiscReg(MISCREG_STATUS, status); 117 118 // Set PC to fault handler address 119 pcState.set(tc->readMiscReg(tvec) >> 2); 120 } else { 121 invokeSE(tc, inst); 122 advancePC(pcState, inst); 123 } 124 tc->pcState(pcState); 125} 126 127void Reset::invoke(ThreadContext *tc, const StaticInstPtr &inst) 128{ 129 if (FullSystem) { 130 tc->getCpuPtr()->clearInterrupts(tc->threadId()); 131 tc->clearArchRegs(); 132 } 133 134 tc->setMiscReg(MISCREG_PRV, PRV_M); 135 STATUS status = tc->readMiscReg(MISCREG_STATUS); 136 status.mie = 0; 137 status.mprv = 0; 138 tc->setMiscReg(MISCREG_STATUS, status); 139 tc->setMiscReg(MISCREG_MCAUSE, 0); 140 141 // Advance the PC to the implementation-defined reset vector 142 PCState pc = static_cast<RiscvSystem *>(tc->getSystemPtr())->resetVect(); 143 tc->pcState(pc); 144} 145 146void 147UnknownInstFault::invokeSE(ThreadContext *tc, const StaticInstPtr &inst) 148{ 149 panic("Unknown instruction 0x%08x at pc 0x%016llx", inst->machInst, 150 tc->pcState().pc()); 151} 152 153void 154IllegalInstFault::invokeSE(ThreadContext *tc, const StaticInstPtr &inst) 155{ 156 panic("Illegal instruction 0x%08x at pc 0x%016llx: %s", inst->machInst, 157 tc->pcState().pc(), reason.c_str()); 158} 159 160void 161UnimplementedFault::invokeSE(ThreadContext *tc, 162 const StaticInstPtr &inst) 163{ 164 panic("Unimplemented instruction %s at pc 0x%016llx", instName, 165 tc->pcState().pc()); 166} 167 168void 169IllegalFrmFault::invokeSE(ThreadContext *tc, const StaticInstPtr &inst) 170{ 171 panic("Illegal floating-point rounding mode 0x%x at pc 0x%016llx.", 172 frm, tc->pcState().pc()); 173} 174 175void 176BreakpointFault::invokeSE(ThreadContext *tc, const StaticInstPtr &inst) 177{ 178 schedRelBreak(0); 179} 180 181void 182SyscallFault::invokeSE(ThreadContext *tc, const StaticInstPtr &inst) 183{ 184 Fault *fault = NoFault; 185 tc->syscall(tc->readIntReg(SyscallNumReg), fault); 186} 187 188} // namespace RiscvISA