Files
jsix/src/kernel/assert.h
Justin C. Miller db23e4966e [kernel] Make panic noreturn
This keeps clang from complaining about other noreturn functions calling
panic::panic().
2022-02-03 19:51:19 -08:00

78 lines
1.9 KiB
C++

#pragma once
#include <stdint.h>
#include "cpu.h"
namespace panic {
constexpr uint32_t send_nmi_command =
(4 << 8) | // Delivery mode NMI
(1 << 14) | // assert level high
(2 << 18); // destination all
extern uint32_t *apic_icr;
extern void const *symbol_table;
[[ noreturn ]]
__attribute__ ((always_inline))
inline void panic(
const char *message = nullptr,
const cpu_state *user = nullptr,
const char *function = __builtin_FUNCTION(),
const char *file = __builtin_FILE(),
uint64_t line = __builtin_LINE())
{
cpu_data &cpu = current_cpu();
// Grab the global panic block for ourselves
cpu.panic = __atomic_exchange_n(&g_panic_data_p, nullptr, __ATOMIC_ACQ_REL);
// If we aren't the first CPU to panic, cpu.panic will be null
if (cpu.panic) {
cpu.panic->symbol_data = symbol_table;
cpu.panic->user_state = user;
cpu.panic->message = message;
cpu.panic->function = function;
cpu.panic->file = file;
cpu.panic->line = line;
cpu.panic->cpus = g_num_cpus;
*apic_icr = send_nmi_command;
}
while (1) asm ("hlt");
}
/// Install a panic handler.
/// \arg entrypoint Virtual address of the panic handler's entrypoint
/// \arg symbol_data Pointer to the symbol table data
void install(uintptr_t entrypoint, const void *symbol_data);
} // namespace panic
#ifndef NDEBUG
__attribute__ ((always_inline))
inline void kassert(
bool check,
const char *message = nullptr,
const cpu_state *user = nullptr,
const char *function = __builtin_FUNCTION(),
const char *file = __builtin_FILE(),
uint64_t line = __builtin_LINE())
{
if (!check)
panic::panic(message, user, function, file, line);
}
#define assert(x) kassert((x))
#else // NDEBUG
#define kassert(...) ((void)0)
#define assert(x) ((void)0)
#endif // NDEBUG