| 1 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 2 | |
| 3 | #pragma once |
| 4 | |
| 5 | #include "mos/platform/platform_defs.hpp" |
| 6 | #include "mos/syslog/printk.hpp" |
| 7 | |
| 8 | #include <mos/types.h> |
| 9 | #include <stdarg.h> |
| 10 | |
| 11 | typedef void(kmsg_handler_t)(const char *func, u32 line, const char *fmt, va_list args); |
| 12 | |
| 13 | typedef struct |
| 14 | { |
| 15 | bool *enabled; |
| 16 | void (*hook)(void); |
| 17 | const char *const name; |
| 18 | long long __padding; |
| 19 | } panic_hook_t; |
| 20 | |
| 21 | MOS_STATIC_ASSERT(sizeof(panic_hook_t) == 32, "panic_hook_t size mismatch" ); |
| 22 | |
| 23 | typedef struct |
| 24 | { |
| 25 | ptr_t ip; |
| 26 | const char *file, *func; |
| 27 | u64 line; |
| 28 | } panic_point_t; |
| 29 | |
| 30 | #define MOS_EMIT_PANIC_HOOK(e, f, n) MOS_PUT_IN_SECTION(".mos.panic_hooks", panic_hook_t, f##_hook, { .enabled = e, .hook = f, .name = n }) |
| 31 | |
| 32 | #define MOS_PANIC_HOOK_FEAT(_feat, _f, _n) MOS_EMIT_PANIC_HOOK(mos_debug_enabled_ptr(_feat), _f, _n) |
| 33 | #define MOS_PANIC_HOOK(_f, _name) MOS_EMIT_PANIC_HOOK(NULL, _f, _name) |
| 34 | |
| 35 | void kwarn_handler_set(kmsg_handler_t *handler); |
| 36 | void kwarn_handler_remove(void); |
| 37 | |
| 38 | __printf(3, 4) void mos_kwarn(const char *func, u32 line, const char *fmt, ...); |
| 39 | |
| 40 | void try_handle_kernel_panics(ptr_t ip); |
| 41 | [[__noreturn__]] void handle_kernel_panic(const panic_point_t *point); |
| 42 | |
| 43 | #define MOS_MAKE_PANIC_POINT(panic_instruction, file, func, line) \ |
| 44 | __asm__ volatile("1: " panic_instruction "\n\t" \ |
| 45 | ".pushsection .mos.panic_list,\"aw\"\n\t" MOS_PLATFORM_PANIC_POINT_ASM ".popsection\n\t" \ |
| 46 | "\n\t" \ |
| 47 | : \ |
| 48 | : "i"(file), "i"(func), "i"(line) \ |
| 49 | : "memory") |
| 50 | |
| 51 | #define mos_panic(fmt, ...) \ |
| 52 | do \ |
| 53 | { \ |
| 54 | pr_emerg(fmt, ##__VA_ARGS__); \ |
| 55 | MOS_MAKE_PANIC_POINT(MOS_PLATFORM_PANIC_INSTR, __FILE__, __func__, __LINE__); \ |
| 56 | __builtin_unreachable(); \ |
| 57 | } while (0) |
| 58 | |
| 59 | #define mos_panic_inline(fmt, ...) \ |
| 60 | do \ |
| 61 | { \ |
| 62 | pr_emerg(fmt, ##__VA_ARGS__); \ |
| 63 | static const panic_point_t point = { .ip = 0, .file = __FILE__, .func = __func__, .line = __LINE__ }; \ |
| 64 | handle_kernel_panic(&point); \ |
| 65 | } while (0) |
| 66 | |