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 "libos_v2_crashcat.h" 28 #include "utils/nvprintf.h" 29 #include "nv-crashcat-decoder.h" 30 31 static inline const char *crashcatReportModeToString_LIBOS2(NV_CRASHCAT_RISCV_MODE mode) 32 { 33 switch (mode) 34 { 35 case NV_CRASHCAT_RISCV_MODE_M: 36 case NV_CRASHCAT_RISCV_MODE_S: 37 return MAKE_NV_PRINTF_STR("kernel"); 38 case NV_CRASHCAT_RISCV_MODE_U: 39 return MAKE_NV_PRINTF_STR("task"); 40 default: 41 return MAKE_NV_PRINTF_STR("unspecified"); 42 } 43 } 44 45 static inline const char *crashcatReportPanicReasonToString_LIBOS2(LibosPanicReason reason) 46 { 47 #define LIBOS_PANIC_REASON_CASE(reason, str) \ 48 case LibosPanicReason ## reason: return MAKE_NV_PRINTF_STR(str) 49 switch (reason) 50 { 51 LIBOS_PANIC_REASON_CASE(UnrecoverableTaskCrash, "unrecoverable task crash"); 52 LIBOS_PANIC_REASON_CASE(UnhandledState, "unhandled state"); 53 LIBOS_PANIC_REASON_CASE(InvalidConfiguration, "invalid configuration"); 54 LIBOS_PANIC_REASON_CASE(FatalHardwareError, "fatal hardware error"); 55 LIBOS_PANIC_REASON_CASE(InsufficientResources, "insufficient resources"); 56 LIBOS_PANIC_REASON_CASE(Timeout, "timeout"); 57 LIBOS_PANIC_REASON_CASE(EnvCallFailed, "environment call failed"); 58 LIBOS_PANIC_REASON_CASE(SspStackCheckFailed, "stack smashing detected"); 59 LIBOS_PANIC_REASON_CASE(AsanMemoryError, "asan memory error detected"); 60 LIBOS_PANIC_REASON_CASE(Test, "test"); 61 LIBOS_PANIC_REASON_CASE(ProgrammingError, "programming error"); 62 LIBOS_PANIC_REASON_CASE(DebugAssertionFailed, "debug assertion failed"); 63 default: return MAKE_NV_PRINTF_STR("unknown error"); 64 } 65 } 66 67 void crashcatReportLogSource_V1_LIBOS2(CrashCatReport *pReport) 68 { 69 NvCrashCatReport_V1 *pReportV1 = &pReport->v1.report; 70 71 NvU8 taskId = crashcatReportV1SourceLibos2TaskId(pReportV1); 72 73 #define CRASHCAT_LOG_LIBOS2_SOURCE(fmt, ...) \ 74 if (taskId == NV_CRASHCAT_REPORT_V1_SOURCE_ID_LIBOS2_TASK_ID_UNSPECIFIED) \ 75 crashcatEnginePrintf(pReport->pEngine, NV_TRUE, fmt, __VA_ARGS__ ); \ 76 else \ 77 crashcatEnginePrintf(pReport->pEngine, NV_TRUE, fmt ", task:%u", __VA_ARGS__, taskId) 78 79 const char *pModeStr = crashcatReportModeToString_LIBOS2(crashcatReportV1SourceMode(pReportV1)); 80 switch (crashcatReportV1SourceCauseType(pReportV1)) 81 { 82 case NV_CRASHCAT_CAUSE_TYPE_EXCEPTION: 83 { 84 // Kernel or task unhandled exception - the sourceData is the xcause value 85 NvU64 xcause = pReportV1->sourceData; 86 CRASHCAT_LOG_LIBOS2_SOURCE( 87 "%s exception: %s (cause:0x%" NvU64_fmtx ") @ pc:0x%" NvU64_fmtx, 88 pModeStr, crashcatReportRiscvCauseToString(xcause), xcause, 89 pReportV1->sourcePc); 90 break; 91 } 92 case NV_CRASHCAT_CAUSE_TYPE_TIMEOUT: 93 { 94 // Task timeout (no way for libos2 to self-report kernel timeouts) 95 CRASHCAT_LOG_LIBOS2_SOURCE( 96 "%s timeout @ pc:0x%" NvU64_fmtx, pModeStr, pReportV1->sourcePc); 97 break; 98 } 99 case NV_CRASHCAT_CAUSE_TYPE_PANIC: 100 { 101 // Kernel or task panic 102 LibosPanicReason reason = crashcatReportV1SourceCauseLibos2Reason(pReportV1); 103 CRASHCAT_LOG_LIBOS2_SOURCE( 104 "%s panic: %s (%u) @ pc:0x%" NvU64_fmtx ", aux:0x%" NvU64_fmtx, 105 pModeStr, crashcatReportPanicReasonToString_LIBOS2(reason), 106 reason, pReportV1->sourcePc, pReportV1->sourceData); 107 break; 108 } 109 } 110 } 111 112 void crashcatReportLogReporter_V1_LIBOS2(CrashCatReport *pReport) 113 { 114 NvCrashCatReport_V1 *pReportV1 = &pReport->v1.report; 115 NvU8 taskId = crashcatReportV1ReporterLibos2TaskId(pReportV1); 116 117 if (taskId == NV_CRASHCAT_REPORT_V1_REPORTER_ID_LIBOS2_TASK_ID_UNSPECIFIED) 118 { 119 crashcatEnginePrintf(pReport->pEngine, NV_FALSE, 120 "Reported by libos kernel v%u.%u [%u] @ %u", 121 crashcatReportV1ReporterVersionLibos2Major(pReportV1), 122 crashcatReportV1ReporterVersionLibos2Minor(pReportV1), 123 crashcatReportV1ReporterVersionLibos2Cl(pReportV1), 124 crashcatReportV1ReporterTimestamp(pReportV1)); 125 } 126 else 127 { 128 crashcatEnginePrintf(pReport->pEngine, NV_FALSE, 129 "Reported by libos task:%u v%u.%u [%u] @ ts:%u", 130 taskId, crashcatReportV1ReporterVersionLibos2Major(pReportV1), 131 crashcatReportV1ReporterVersionLibos2Minor(pReportV1), 132 crashcatReportV1ReporterVersionLibos2Cl(pReportV1), 133 crashcatReportV1ReporterTimestamp(pReportV1)); 134 } 135 } 136