1 | // SPDX-License-Identifier: GPL-3.0-or-later |
2 | |
3 | #pragma once |
4 | |
5 | #include "mos/platform/platform_defs.h" |
6 | #include "mos/syslog/printk.h" |
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 | __BEGIN_DECLS |
39 | |
40 | __printf(3, 4) void mos_kwarn(const char *func, u32 line, const char *fmt, ...); |
41 | |
42 | void try_handle_kernel_panics(ptr_t ip); |
43 | void try_handle_kernel_panics_at(const panic_point_t *point); |
44 | |
45 | __END_DECLS |
46 | |
47 | #define MOS_MAKE_PANIC_POINT(panic_instruction, file, func, line) \ |
48 | __asm__ volatile("1: " panic_instruction "\n\t" \ |
49 | ".pushsection .mos.panic_list,\"aw\"\n\t" MOS_PLATFORM_PANIC_POINT_ASM ".popsection\n\t" \ |
50 | "\n\t" \ |
51 | : \ |
52 | : "i"(file), "i"(func), "i"(line) \ |
53 | : "memory") |
54 | |
55 | #define mos_panic(fmt, ...) \ |
56 | do \ |
57 | { \ |
58 | pr_emerg(fmt, ##__VA_ARGS__); \ |
59 | MOS_MAKE_PANIC_POINT(MOS_PLATFORM_PANIC_INSTR, __FILE__, __func__, __LINE__); \ |
60 | __builtin_unreachable(); \ |
61 | } while (0) |
62 | |
63 | #define mos_panic_inline(fmt, ...) \ |
64 | do \ |
65 | { \ |
66 | pr_emerg(fmt, ##__VA_ARGS__); \ |
67 | static const panic_point_t point = { .ip = 0, .file = __FILE__, .line = __LINE__, .func = __func__ }; \ |
68 | try_handle_kernel_panics_at(&point); \ |
69 | } while (0) |
70 | |