diff --git a/share/man/man9/panic.9 b/share/man/man9/panic.9 --- a/share/man/man9/panic.9 +++ b/share/man/man9/panic.9 @@ -149,6 +149,10 @@ and .Fn vpanic functions do not return. +.Sh IMPLEMENTATION NOTES +For convinience, both functions are implememted as macros, which also +capture location of the call site in the source code. This is to provide +more context when generating error message. .Sh SEE ALSO .Xr printf 3 , .Xr ddb 4 , diff --git a/sys/amd64/amd64/efirt_machdep.c b/sys/amd64/amd64/efirt_machdep.c --- a/sys/amd64/amd64/efirt_machdep.c +++ b/sys/amd64/amd64/efirt_machdep.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -356,6 +357,15 @@ return (error); } +void +efi_panic(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + panic(fmt, ap); +} + SYSCTL_PROC(_debug, OID_AUTO, efi_time, CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, NULL, 0, efi_time_sysctl_handler, "I", diff --git a/sys/amd64/amd64/efirt_support.S b/sys/amd64/amd64/efirt_support.S --- a/sys/amd64/amd64/efirt_support.S +++ b/sys/amd64/amd64/efirt_support.S @@ -78,7 +78,7 @@ decl %ebx jz 1f movq $efi_rt_panic_str, %rdi - call panic + call efi_panic 1: movq EC_FPTR(%rdi), %rax movq $efi_rt_fault, PCB_ONFAULT(%rsi) callq *%rax diff --git a/sys/contrib/openzfs/include/os/freebsd/spl/sys/cmn_err.h b/sys/contrib/openzfs/include/os/freebsd/spl/sys/cmn_err.h --- a/sys/contrib/openzfs/include/os/freebsd/spl/sys/cmn_err.h +++ b/sys/contrib/openzfs/include/os/freebsd/spl/sys/cmn_err.h @@ -71,8 +71,10 @@ extern void vuprintf(const char *, __va_list) __attribute__((format(printf, 1, 0))); -extern void panic(const char *, ...) - __attribute__((format(printf, 1, 2), __noreturn__)); +struct panic_codeptr; + +extern void do_panic(const struct panic_codeptr *, const char *, ...) + __attribute__((format(printf, 2, 3), __noreturn__)); #define cmn_err_once(ce, ...) \ do { \ diff --git a/sys/contrib/openzfs/module/lua/lapi.c b/sys/contrib/openzfs/module/lua/lapi.c --- a/sys/contrib/openzfs/module/lua/lapi.c +++ b/sys/contrib/openzfs/module/lua/lapi.c @@ -123,8 +123,8 @@ LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { lua_CFunction old; lua_lock(L); - old = G(L)->panic; - G(L)->panic = panicf; + old = G(L)->on_panic; + G(L)->on_panic = panicf; lua_unlock(L); return old; } diff --git a/sys/contrib/openzfs/module/lua/ldo.c b/sys/contrib/openzfs/module/lua/ldo.c --- a/sys/contrib/openzfs/module/lua/ldo.c +++ b/sys/contrib/openzfs/module/lua/ldo.c @@ -190,9 +190,9 @@ luaD_throw(G(L)->mainthread, errcode); /* re-throw in main thread */ } else { /* no handler at all; abort */ - if (G(L)->panic) { /* panic function? */ + if (G(L)->on_panic) { /* panic function? */ lua_unlock(L); - G(L)->panic(L); /* call it (last chance to jump out) */ + G(L)->on_panic(L); /* call it (last chance to jump out) */ } panic("no error handler"); } diff --git a/sys/contrib/openzfs/module/lua/lstate.h b/sys/contrib/openzfs/module/lua/lstate.h --- a/sys/contrib/openzfs/module/lua/lstate.h +++ b/sys/contrib/openzfs/module/lua/lstate.h @@ -139,7 +139,7 @@ int gcpause; /* size of pause between successive GCs */ int gcmajorinc; /* pause between major collections (only in gen. mode) */ int gcstepmul; /* GC `granularity' */ - lua_CFunction panic; /* to be called in unprotected errors */ + lua_CFunction on_panic; /* to be called in unprotected errors */ struct lua_State *mainthread; const lua_Number *version; /* pointer to version number */ TString *memerrmsg; /* memory-error message */ diff --git a/sys/contrib/openzfs/module/lua/lstate.c b/sys/contrib/openzfs/module/lua/lstate.c --- a/sys/contrib/openzfs/module/lua/lstate.c +++ b/sys/contrib/openzfs/module/lua/lstate.c @@ -287,7 +287,7 @@ g->strt.hash = NULL; setnilvalue(&g->l_registry); luaZ_initbuffer(L, &g->buff); - g->panic = NULL; + g->on_panic = NULL; g->version = NULL; g->gcstate = GCSpause; g->allgc = NULL; diff --git a/sys/dev/mlx4/mlx4_core/mlx4_cmd.c b/sys/dev/mlx4/mlx4_core/mlx4_cmd.c --- a/sys/dev/mlx4/mlx4_core/mlx4_cmd.c +++ b/sys/dev/mlx4/mlx4_core/mlx4_cmd.c @@ -32,6 +32,10 @@ * SOFTWARE. */ +#include +#include +#include + #include #include #include diff --git a/sys/dev/mlx4/mlx4_core/mlx4_fw.c b/sys/dev/mlx4/mlx4_core/mlx4_fw.c --- a/sys/dev/mlx4/mlx4_core/mlx4_fw.c +++ b/sys/dev/mlx4/mlx4_core/mlx4_fw.c @@ -40,6 +40,7 @@ #include #include +#include #include "fw.h" #include "icm.h" diff --git a/sys/dev/mlx4/mlx4_ib/mlx4_ib_main.c b/sys/dev/mlx4/mlx4_ib/mlx4_ib_main.c --- a/sys/dev/mlx4/mlx4_ib/mlx4_ib_main.c +++ b/sys/dev/mlx4/mlx4_ib/mlx4_ib_main.c @@ -45,6 +45,7 @@ #include #include +#include #include #include diff --git a/sys/kern/kern_shutdown.c b/sys/kern/kern_shutdown.c --- a/sys/kern/kern_shutdown.c +++ b/sys/kern/kern_shutdown.c @@ -809,13 +809,32 @@ return (0); } +static const char * +trim_to_sys(const char *path) +{ + const char *tp, *cp = path; + + while ((tp = strstr(cp, "/sys/")) != NULL ) { + cp = tp + 1; + } + return (cp); +} + #ifdef KASSERT_PANIC_OPTIONAL +static void +kassert_print(const struct panic_codeptr *where, const char *buf) +{ + + printf("KASSERT failed at %s:%d (%s): %s\n", trim_to_sys(where->fname), + where->linen, where->funcn, buf); +} + /* * Called by KASSERT, this decides if we will panic * or if we will log via printf and/or ktr. */ void -kassert_panic(const char *fmt, ...) +do_kassert_panic(const struct panic_codeptr *where, const char *fmt, ...) { static char buf[256]; va_list ap; @@ -830,7 +849,7 @@ */ if (KERNEL_PANICKED() && kassert_suppress_in_panic) { if (kassert_do_log) { - printf("KASSERT failed: %s\n", buf); + kassert_print(where, buf); #ifdef KDB if (trace_all_panics && trace_on_panic) kdb_backtrace(); @@ -847,7 +866,7 @@ (kassert_log_panic_at > 0 && kassert_warnings >= kassert_log_panic_at)) { va_start(ap, fmt); - vpanic(fmt, ap); + do_vpanic(where, fmt, ap); /* NORETURN */ } #ifdef KTR @@ -864,7 +883,7 @@ static int curerr; if (ppsratecheck(&lasterr, &curerr, kassert_log_pps_limit)) { - printf("KASSERT failed: %s\n", buf); + kassert_print(where, buf); kdb_backtrace(); } } @@ -884,16 +903,16 @@ * the disks as this often leads to recursive panics. */ void -panic(const char *fmt, ...) +do_panic(const struct panic_codeptr *where, const char *fmt, ...) { va_list ap; va_start(ap, fmt); - vpanic(fmt, ap); + do_vpanic(where, fmt, ap); } void -vpanic(const char *fmt, va_list ap) +do_vpanic(const struct panic_codeptr *where, const char *fmt, va_list ap) { #ifdef SMP cpuset_t other_cpus; @@ -945,13 +964,15 @@ /* Unmute when panic */ cn_mute = 0; + if (newpanic) + cngrab(); + printf("panic at %s:%d (%s): ", trim_to_sys(where->fname), + where->linen, where->funcn); if (newpanic) { (void)vsnprintf(buf, sizeof(buf), fmt, ap); panicstr = buf; - cngrab(); - printf("panic: %s\n", buf); + printf("%s\n", buf); } else { - printf("panic: "); vprintf(fmt, ap); printf("\n"); } diff --git a/sys/sys/efi.h b/sys/sys/efi.h --- a/sys/sys/efi.h +++ b/sys/sys/efi.h @@ -364,6 +364,9 @@ int efi_status_to_errno(efi_status status); +void efi_panic(const char *, ...) __attribute__((format(printf, 1, 2), + __noreturn__)); + #endif /* _KERNEL */ #endif /* _SYS_EFI_H_ */ diff --git a/sys/sys/kassert.h b/sys/sys/kassert.h --- a/sys/sys/kassert.h +++ b/sys/sys/kassert.h @@ -112,14 +112,29 @@ #define CTASSERT(x) _Static_assert(x, "compile-time assertion failed") #endif +struct panic_codeptr { + const char * const fname; + const int linen; + const char * const funcn; +}; + +# define PANIC_CTX ({static const struct panic_codeptr _panic_ctx = { \ + .fname = __FILE__, .linen = __LINE__, .funcn = __func__}; \ + &_panic_ctx;}) + /* * These functions need to be declared before the KASSERT macro is invoked in * !KASSERT_PANIC_OPTIONAL builds, so their declarations are sort of out of * place compared to other function definitions in this header. On the other * hand, this header is a bit disorganized anyway. */ -void panic(const char *, ...) __dead2 __printflike(1, 2); -void vpanic(const char *, __va_list) __dead2 __printflike(1, 0); +void do_panic(const struct panic_codeptr *, const char *, ...) + __dead2 __printflike(2, 3); +void do_vpanic(const struct panic_codeptr *, const char *, __va_list) + __dead2 __printflike(2, 0); + +# define panic(args...) do_panic(PANIC_CTX, ## args) +# define vpanic(args...) do_vpanic(PANIC_CTX, ## args) #endif /* _KERNEL */ #if defined(_STANDALONE) @@ -135,7 +150,11 @@ #else /* !_STANDALONE */ # if defined(WITNESS) || defined(INVARIANT_SUPPORT) # ifdef KASSERT_PANIC_OPTIONAL -void kassert_panic(const char *fmt, ...) __printflike(1, 2); + +void do_kassert_panic(const struct panic_codeptr *, const char *fmt, ...) + __printflike(2, 3); +# define kassert_panic(args...) do_kassert_panic(PANIC_CTX, ## args) + # else # define kassert_panic panic # endif /* KASSERT_PANIC_OPTIONAL */