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