struct log_dump_options {
uint8_t min_level;
bool show_args : 1;
bool show_cpu : 1;
bool show_tid : 1;
bool show_irql : 1;
bool show_caller : 1;
bool resolve_symbols : 1;
bool clear_after_dump : 1;
};
struct log_handle {
const char *msg;
enum log_flags flags;
_Atomic uint32_t seen_internal;
_Atomic uint64_t last_ts_internal;
};
struct log_record {
time_t timestamp;
cpu_id_t cpu;
uint32_t tid;
const struct log_handle *handle;
enum log_level level;
enum bootstage boostage;
uint16_t msg_len;
const char *fmt;
uint8_t nargs;
uint64_t args[8];
char *caller_fn;
char *caller_file;
int32_t caller_line;
uintptr_t caller_pc;
enum log_record_flags flags;
enum irql logged_at_irql;
};
struct log_ring_slot {
_Atomic uint64_t seq;
struct log_record rec;
};
struct log_ringbuf {
struct log_ring_slot *slots;
_Atomic uint64_t head;
_Atomic uint64_t tail;
};
struct log_site_options {
char *name;
enum log_site_flags flags;
size_t capacity;
uint32_t enabled_mask;
struct log_dump_options dump_opts;
};
struct log_site {
struct list_head list;
char *name;
struct log_ringbuf rb;
uint32_t enabled_mask;
size_t capacity;
refcount_t refcount;
atomic_bool enabled;
uint32_t dropped;
enum log_site_flags flags;
struct log_dump_options dump_opts;
};
enum log_flags : uint32_t {
LOG_PRINT = 1 << 0,
LOG_IMPORTANT = 1 << 1,
LOG_RATELIMIT = 1 << 2,
LOG_ONCE = 1 << 3,
LOG_PANIC = 1 << 5,
LOG_NO_NEWLINE = 1 << 6,
LOG_DEFAULT = 0,
};
enum log_level : uint8_t {
LOG_TRACE,
LOG_DEBUG,
LOG_INFO,
LOG_WARN,
LOG_ERROR,
};
enum log_site_flags : uint32_t {
LOG_SITE_PRINT = 1 << 0,
LOG_SITE_DROP_OLD = 1 << 1,
LOG_SITE_NO_IRQ = 1 << 2,
LOG_SITE_PANIC_VISIBLE = 1 << 3,
LOG_SITE_NONE = 0,
LOG_SITE_DEFAULT = LOG_SITE_DROP_OLD,
};
enum log_record_flags : uint16_t {
LOG_REC_FROM_IRQ = 1 << 0,
LOG_REC_TRUNCATED = 1 << 1,
};
char log_level_color(enum log_level l);
bool log_handle_should_print(const struct log_handle *h, const struct log_site *s, uint8_t level);
bool log_site_accepts(struct log_site *s);
bool log_site_enabled(const struct log_site *ss, uint8_t level);
void log_emit_internal(struct log_site * *, struct log_handle * *, enum log_level, const char *func, const char *fname, int32_t line, uintptr_t ip, uint8_t nargs, char *fmt);
void log_dump_site_with_opts(struct log_site * *, struct log_dump_options opts);
void log_dump_site(struct log_site *site);
void log_dump_site_default(struct log_site * *);
void log_dump_all(void);
void log_sites_init(void);
void log_site_free(struct log_site *site);
struct log_site * log_site_create(struct log_site_options opts);
bool log_site_get(struct log_site *site);
void log_site_put(struct log_site *site);
size_t log_site_message_count(struct log_site *site);
#define LOG_DUMP_DEFAULT \
(struct log_dump_options) { \
.min_level = LOG_TRACE, .show_args = true, .show_cpu = true, \
.show_tid = true, .show_irql = true, .show_caller = true, \
.resolve_symbols = true, .clear_after_dump = false, \
}
#define LOG_DUMP_CONSOLE \
(struct log_dump_options) { \
.min_level = LOG_TRACE, .show_args = true, .show_cpu = false, \
.show_tid = false, .show_irql = false, .show_caller = false, \
.resolve_symbols = false, .clear_after_dump = false, \
}
#define log_msg(lvl, fmt, ...) \
log_emit_internal(LOG_SITE(global), LOG_HANDLE(global), lvl, __func__, \
__FILE__, __LINE__, \
(uintptr_t) __builtin_return_address(0), \
PP_NARG(__VA_ARGS__), fmt, ##__VA_ARGS__)
#define log_warn_once(fmt, ...) \
do { \
static bool done_internal_log = false; \
if (!done_internal_log) { \
log_msg(LOG_WARN, fmt, ##__VA_ARGS__); \
done_internal_log = true; \
} \
} while (0)
#define log_global(handle, lvl, fmt, ...) \
log_emit_internal(LOG_SITE(global), handle, lvl, __func__, __FILE__, \
__LINE__, (uintptr_t) __builtin_return_address(0), \
PP_NARG(__VA_ARGS__), fmt, ##__VA_ARGS__)
#define log(site, handle, lvl, fmt, ...) \
log_emit_internal(site, handle, lvl, __func__, __FILE__, __LINE__, \
(uintptr_t) __builtin_return_address(0), \
PP_NARG(__VA_ARGS__), fmt, ##__VA_ARGS__)
#define log_err(site, handle, fmt, ...) \
log(site, handle, LOG_ERROR, fmt, ##__VA_ARGS__)
#define log_warn(site, handle, fmt, ...) \
log(site, handle, LOG_WARN, fmt, ##__VA_ARGS__)
#define log_info(site, handle, fmt, ...) \
log(site, handle, LOG_INFO, fmt, ##__VA_ARGS__)
#define log_debug(site, handle, fmt, ...) \
log(site, handle, LOG_DEBUG, fmt, ##__VA_ARGS__)
#define log_trace(site, handle, fmt, ...) \
log(site, handle, LOG_TRACE, fmt, ##__VA_ARGS__)
#define log_err_global(handle, fmt, ...) \
log_global(handle, LOG_ERROR, fmt, ##__VA_ARGS__)
#define log_warn_global(handle, fmt, ...) \
log_global(handle, LOG_WARN, fmt, ##__VA_ARGS__)
#define log_info_global(handle, fmt, ...) \
log_global(handle, LOG_INFO, fmt, ##__VA_ARGS__)
#define log_debug_global(handle, fmt, ...) \
log_global(handle, LOG_DEBUG, fmt, ##__VA_ARGS__)
#define log_trace_global(handle, fmt, ...) \
log_global(handle, LOG_TRACE, fmt, ##__VA_ARGS__)
#define LOG_SITE_CAPACITY_DEFAULT 128
#define LOG_SITE_EXTERN(name) extern struct log_site __log_site_##name
#define LOG_SITE_LEVEL(l) (1u << l)
#define LOG_SITE_ALL UINT32_MAX
#define LOG_SITE_DECLARE(_name, ...) \
LINKER_SECTION_ATTRIBUTE(log_sites) \
struct log_site __log_site_##_name = {.name = #_name, __VA_ARGS__}
#define LOG_SITE_DECLARE_DEFAULT(_name, ...) \
LINKER_SECTION_ATTRIBUTE(log_sites) \
struct log_site __log_site_##_name = { \
.name = #_name, \
.flags = LOG_SITE_DEFAULT, \
.capacity = LOG_SITE_CAPACITY_DEFAULT, \
.enabled_mask = LOG_SITE_ALL, \
.dump_opts = LOG_DUMP_CONSOLE, \
__VA_ARGS__}
#define LOG_SITE(name) &(__log_site_##name)
#define LOG_HANDLE_DEFAULT \
(struct log_handle){.msg = "", \
.flags = LOG_DEFAULT, \
.seen_internal = 0, \
.last_ts_internal = 0}
#define LOG_HANDLE_SUBSYSTEM_NONE NULL
#define LOG_HANDLE_EXTERN(name) extern struct log_handle __log_handle_##name
#define LOG_HANDLE_DECLARE(_name, ...) \
struct log_handle __log_handle_##_name = { \
.msg = #_name, .seen_internal = 0, .last_ts_internal = 0, __VA_ARGS__}
#define LOG_HANDLE_DECLARE_DEFAULT(n, ...) \
struct log_handle __log_handle_##n = {.msg = #n, \
.flags = LOG_PRINT, \
.seen_internal = 0, \
.last_ts_internal = 0, \
__VA_ARGS__}
#define LOG_HANDLE(name) &(__log_handle_##name)