include/console/crash.h View source View on GitHub
struct crash_regs {
union {
struct {
uint64_t rip;
uint64_t rax;
uint64_t r8;
uint64_t rsp;
};
uint64_t regs[CRASH_REG_COUNT];
};
};
struct crash_payload {
enum crash_code code;
void *data;
uintptr_t params[4];
};
struct crash_facility {
uint16_t prefix;
const char *name;
const char *desc;
uint16_t hookable_threshold;
const char *(*const to_str)(uint16_t delta);
void (*const dump)(uint16_t delta, struct crash_payload pl);
void (*const emit_ndjson)(uint16_t delta, struct crash_payload pl);
};
struct crash_unwind_node_data {
uintptr_t arg;
union {
void *ptr;
size_t rcu_lock_times;
enum irql irql;
uintptr_t raw;
};
};
struct crash_unwind_node {
enum crash_unwind_type type;
struct list_head list;
struct crash_unwind_node_data data;
};
struct crash_unwind_perthread {
struct list_head free_list;
struct list_head in_use;
struct crash_unwind_node nodes[CRASH_UNWIND_NODES];
};
struct crash_perthread {
struct crash_unwind_perthread unwind;
struct list_head crash_hooks;
bool unwinding;
bool in_hook;
jmp_buf env;
};
struct crash_hook {
char *name;
struct list_head list;
enum crash_code code;
enum crash_source source_mask;
};
struct crash_context {
struct crash_payload payload;
enum crash_source source;
enum crash_format_flags formats;
const char *file;
int line;
const char *func;
const char *msg;
const struct crash_regs *regs;
void *source_data;
};
enum qemu_exit_codes {
QEMU_EXIT_OK = 0,
QEMU_EXIT_FAIL = 1,
QEMU_EXIT_PANIC = 2,
};
enum crash_code {
CRASH_CODE_GENERIC,
};
enum crash_source {
CRASH_SOURCE_PANIC = 0,
CRASH_SOURCE_ASSERT,
CRASH_SOURCE_KASAN,
CRASH_SOURCE_UBSAN,
CRASH_SOURCE_NMI_WATCHDOG,
CRASH_SOURCE_CPU_EXCEPTION,
CRASH_SOURCE_NIGHTMARE,
CRASH_SOURCE_LOCK_CHK,
};
enum crash_format_flags {
CRASH_FMT_RAW_SERIAL = 1 << 0,
CRASH_FMT_VISUAL_PANES = 1 << 1,
CRASH_FMT_NDJSON = 1 << 2,
CRASH_FMT_DUMP_LOGS = 1 << 3,
CRASH_FMT_PEER_CPUS = 1 << 4,
CRASH_FMT_DEFAULT = CRASH_FMT_RAW_SERIAL | CRASH_FMT_VISUAL_PANES | CRASH_FMT_NDJSON | CRASH_FMT_DUMP_LOGS | CRASH_FMT_PEER_CPUS,
CRASH_FMT_MINIMAL = CRASH_FMT_RAW_SERIAL | CRASH_FMT_NDJSON,
};
enum crash_hook_flags {
CRASH_HOOK_DEFAULT = 0,
CRASH_HOOK_FACILITY = 1 << 0,
CRASH_HOOK_NO_UNWIND = 1 << 1,
};
enum crash_unwind_type {
CRASH_UNWIND_NONE,
CRASH_UNWIND_RCU,
CRASH_UNWIND_MUTEX,
CRASH_UNWIND_RWLOCK,
CRASH_UNWIND_SPINLOCK,
CRASH_UNWIND_QSPINLOCK,
CRASH_UNWIND_MAX,
};
__noreturn void assert_impl_default(struct crash_payload payload, const char *file, int line, const char *func, const char *fmt);
__noreturn void assert_impl_assertion(struct crash_payload payload, const char *file, int line, const char *func, const char *prefix, const char *assertion, const char *fmt);
__noreturn void crash_full(const struct crash_context *ctx);
bool crash_cpu_is_owner(uint64_t id);
void crash_broadcast_nmi(void);
void crash_facilities_init(void);
const char * crash_code_from_facility_to_str(enum crash_code code);
__noreturn void crash_nmi_handoff(void *p, struct irq_context *ctx);
void debug_print_stack(void);
void crash_facility_printf(const char *fmt);
void crash_perthread_init(struct thread *t);
void crash_unwind(void);
void crash_unwind_enter_rcu(void);
void crash_unwind_exit_rcu(void);
void crash_unwind_enter_mutex(struct mutex *m);
void crash_unwind_exit_mutex(struct mutex *m);
void crash_unwind_enter_rwlock(struct rwlock *r);
void crash_unwind_exit_rwlock(struct rwlock *r);
void crash_unwind_enter_spinlock(struct spinlock *s, enum irql old);
void crash_unwind_exit_spinlock(struct spinlock *s);
void crash_unwind_enter_qspinlock(struct qspinlock *q, enum irql old);
void crash_unwind_exit_qspinlock(struct qspinlock *q);
void qemu_exit(int code);
char crash_code_to_str(enum crash_code code);
#define CRASH_REG_COUNT 20
#define CRASH_UNWIND_NODES 128
#define CRASH_WAIT_US MS_TO_US(500)
#define CRASH_SPIN_ONE_US 5
#define CRASH_MAX_DEPTH 2
#define CRASH_MSG_MAX 256
#define CRASH_PAYLOAD(c, d) ((struct crash_payload) {.code = c, .data = d})
#define CRASH_PARAMS(c, p0, p1, p2, p3) \
((struct crash_payload) {.code = (c), \
.params = {(uintptr_t) (p0), (uintptr_t) (p1), \
(uintptr_t) (p2), (uintptr_t) (p3)}})
#define CRASH_CODE_TO_PAYLOAD(c) ((struct crash_payload) {.code = c})
#define CRASH_CODE_CREATE(pre, del) \
({ ((((int) (pre)) << 16) | (((int) (del)) & 0xFFFF)); })
#define CRASH_CODE_GET_FACILITY(c) ({ (((c)) >> 16) & 0xFFFF; })
#define CRASH_CODE_GET_DELTA(c) ({ (((c)) & 0xFFFF); })
#define CRASH_CODE_PREFIX(n) ((__crash_facility_##n).prefix)
#define CRASH_CODE_DELTA_START (1)
#define CRASH_CODE(n, d) CRASH_CODE_CREATE(CRASH_CODE_PREFIX(n), d)
#define CRASH_FACILITY(n) __crash_facility_##n
#define CRASH_FACILITY_EXTERN(n) \
extern struct crash_facility __crash_facility_##n
#define CRASH_FACILITY_DECLARE(n, ...) \
LINKER_SECTION_OBJECT(struct crash_facility, crash_facilities) \
__crash_facility_##n = {.name = #n, __VA_ARGS__}