1 /* 2 * SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 * SPDX-License-Identifier: MIT 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in 13 * all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24 #define NVOC_CRASHCAT_REPORT_H_PRIVATE_ACCESS_ALLOWED 25 #include "crashcat/crashcat_report.h" 26 #include "crashcat/crashcat_engine.h" 27 #include "utils/nvassert.h" 28 29 NV_STATUS crashcatReportConstruct_IMPL 30 ( 31 CrashCatReport *pReport, 32 void **ppReportBytes, 33 NvLength numBytes 34 ) 35 { 36 // Cache the CrashCatEngine pointer for quick access during logging 37 pReport->pEngine = CRASHCAT_GET_ENGINE(pReport); 38 39 // Extract the report bytes into our structured report record 40 void *pBufferStart = *ppReportBytes; 41 *ppReportBytes = crashcatReportExtract_HAL(pReport, pBufferStart, numBytes); 42 if (pBufferStart == *ppReportBytes) 43 { 44 NV_PRINTF(LEVEL_ERROR, "no report data extracted from %" NvUPtr_fmtu " bytes\n", numBytes); 45 return NV_ERR_INVALID_DATA; 46 } 47 48 return NV_OK; 49 } 50 51 void crashcatReportLog_IMPL(CrashCatReport *pReport) 52 { 53 NV_CRASHCAT_PACKET_TYPE packetType; 54 55 NV_ASSERT_OR_RETURN_VOID((pReport->validTags & NVBIT(NV_CRASHCAT_PACKET_TYPE_REPORT)) != 0); 56 57 // TODO: acquire mutex to prevent multi-line reports interleaving 58 59 crashcatReportLogSource_HAL(pReport); 60 crashcatReportLogReporter_HAL(pReport); 61 62 // Log additional data associated with the report 63 FOR_EACH_INDEX_IN_MASK(32, packetType, 64 pReport->validTags & ~NVBIT(NV_CRASHCAT_PACKET_TYPE_REPORT)) 65 { 66 switch (packetType) 67 { 68 case NV_CRASHCAT_PACKET_TYPE_RISCV64_CSR_STATE: 69 crashcatReportLogRiscv64CsrState_HAL(pReport); 70 break; 71 case NV_CRASHCAT_PACKET_TYPE_RISCV64_GPR_STATE: 72 crashcatReportLogRiscv64GprState_HAL(pReport); 73 break; 74 case NV_CRASHCAT_PACKET_TYPE_RISCV64_TRACE: 75 crashcatReportLogRiscv64Trace_HAL(pReport); 76 break; 77 case NV_CRASHCAT_PACKET_TYPE_IO32_STATE: 78 crashcatReportLogIo32State_HAL(pReport); 79 break; 80 default: 81 NV_PRINTF(LEVEL_WARNING, "unrecognized packet type 0x%02x\n", packetType); 82 break; 83 } 84 } 85 FOR_EACH_INDEX_IN_MASK_END; 86 87 crashcatEnginePrintf(pReport->pEngine, NV_FALSE, 88 CRASHCAT_LOG_PREFIX "------------[ end crash report ]------------"); 89 } 90 91 // xcause CSR format and codes are a backward-compatible part of the RISC-V standard 92 #define RISCV_CSR_XCAUSE_EXCODE 4:0 93 #define RISCV_CSR_XCAUSE_EXCODE_IAMA 0x00000000 94 #define RISCV_CSR_XCAUSE_EXCODE_IACC_FAULT 0x00000001 95 #define RISCV_CSR_XCAUSE_EXCODE_ILL 0x00000002 96 #define RISCV_CSR_XCAUSE_EXCODE_BKPT 0x00000003 97 #define RISCV_CSR_XCAUSE_EXCODE_LAMA 0x00000004 98 #define RISCV_CSR_XCAUSE_EXCODE_LACC_FAULT 0x00000005 99 #define RISCV_CSR_XCAUSE_EXCODE_SAMA 0x00000006 100 #define RISCV_CSR_XCAUSE_EXCODE_SACC_FAULT 0x00000007 101 #define RISCV_CSR_XCAUSE_EXCODE_UCALL 0x00000008 102 #define RISCV_CSR_XCAUSE_EXCODE_SCALL 0x00000009 103 #define RISCV_CSR_XCAUSE_EXCODE_MCALL 0x0000000b 104 #define RISCV_CSR_XCAUSE_EXCODE_IPAGE_FAULT 0x0000000c 105 #define RISCV_CSR_XCAUSE_EXCODE_LPAGE_FAULT 0x0000000d 106 #define RISCV_CSR_XCAUSE_EXCODE_SPAGE_FAULT 0x0000000f 107 #define RISCV_CSR_XCAUSE_EXCODE_U_SWINT 0x00000000 108 #define RISCV_CSR_XCAUSE_EXCODE_S_SWINT 0x00000001 109 #define RISCV_CSR_XCAUSE_EXCODE_M_SWINT 0x00000003 110 #define RISCV_CSR_XCAUSE_EXCODE_U_TINT 0x00000004 111 #define RISCV_CSR_XCAUSE_EXCODE_S_TINT 0x00000005 112 #define RISCV_CSR_XCAUSE_EXCODE_M_TINT 0x00000007 113 #define RISCV_CSR_XCAUSE_EXCODE_U_EINT 0x00000008 114 #define RISCV_CSR_XCAUSE_EXCODE_S_EINT 0x00000009 115 #define RISCV_CSR_XCAUSE_EXCODE_M_EINT 0x0000000b 116 #define RISCV_CSR_XCAUSE_INT 63:63 117 118 #define RISCV_CSR_XCAUSE_EXCODE_CASE(code, str) \ 119 case RISCV_CSR_XCAUSE_EXCODE_ ## code: return MAKE_NV_PRINTF_STR(str) 120 121 const char *crashcatReportRiscvCauseToString(NvU64 xcause) 122 { 123 NvBool bIntr = (NvBool)REF_VAL64(RISCV_CSR_XCAUSE_INT, xcause); 124 NvU8 excode = (NvU8)REF_VAL64(RISCV_CSR_XCAUSE_EXCODE, xcause); 125 126 if (bIntr) 127 { 128 switch (excode) 129 { 130 RISCV_CSR_XCAUSE_EXCODE_CASE(U_SWINT, "user software interrupt"); 131 RISCV_CSR_XCAUSE_EXCODE_CASE(S_SWINT, "supervisor software interrupt"); 132 RISCV_CSR_XCAUSE_EXCODE_CASE(M_SWINT, "machine software interrupt"); 133 RISCV_CSR_XCAUSE_EXCODE_CASE(U_TINT, "user timer interrupt"); 134 RISCV_CSR_XCAUSE_EXCODE_CASE(S_TINT, "supervisor timer interrupt"); 135 RISCV_CSR_XCAUSE_EXCODE_CASE(M_TINT, "machine timer interrupt"); 136 RISCV_CSR_XCAUSE_EXCODE_CASE(U_EINT, "user external interrupt"); 137 RISCV_CSR_XCAUSE_EXCODE_CASE(S_EINT, "supervisor external interrupt"); 138 RISCV_CSR_XCAUSE_EXCODE_CASE(M_EINT, "machine external interrupt"); 139 default: return MAKE_NV_PRINTF_STR("unknown interrupt"); 140 } 141 } 142 else 143 { 144 switch (excode) 145 { 146 RISCV_CSR_XCAUSE_EXCODE_CASE(IAMA, "instruction address misaligned"); 147 RISCV_CSR_XCAUSE_EXCODE_CASE(IACC_FAULT, "instruction access fault"); 148 RISCV_CSR_XCAUSE_EXCODE_CASE(ILL, "illegal instruction"); 149 RISCV_CSR_XCAUSE_EXCODE_CASE(BKPT, "breakpoint"); 150 RISCV_CSR_XCAUSE_EXCODE_CASE(LAMA, "load address misaligned"); 151 RISCV_CSR_XCAUSE_EXCODE_CASE(LACC_FAULT, "load access fault"); 152 RISCV_CSR_XCAUSE_EXCODE_CASE(SAMA, "store address misaligned"); 153 RISCV_CSR_XCAUSE_EXCODE_CASE(SACC_FAULT, "store access fault"); 154 RISCV_CSR_XCAUSE_EXCODE_CASE(UCALL, "environment call from U-mode"); 155 RISCV_CSR_XCAUSE_EXCODE_CASE(SCALL, "environment call from S-mode"); 156 RISCV_CSR_XCAUSE_EXCODE_CASE(MCALL, "environment call from M-mode"); 157 RISCV_CSR_XCAUSE_EXCODE_CASE(IPAGE_FAULT, "instruction access page fault"); 158 RISCV_CSR_XCAUSE_EXCODE_CASE(LPAGE_FAULT, "load access page fault"); 159 RISCV_CSR_XCAUSE_EXCODE_CASE(SPAGE_FAULT, "store access page fault"); 160 default: return MAKE_NV_PRINTF_STR("unknown exception"); 161 } 162 } 163 } 164 #undef RISCV_CSR_MCAUSE_EXCODE_CASE 165