MFC r281915:

Make vpanic() externally visible.

MFC r281916:
Fix DTrace's panic() action.
This commit is contained in:
markj 2015-05-29 04:01:39 +00:00
parent aff03409ef
commit 9bbe24351d
10 changed files with 13 additions and 463 deletions

View File

@ -1002,6 +1002,7 @@ MLINKS+=mutex.9 mtx_assert.9 \
mutex.9 mtx_unlock_spin_flags.9 mutex.9 mtx_unlock_spin_flags.9
MLINKS+=namei.9 NDFREE.9 \ MLINKS+=namei.9 NDFREE.9 \
namei.9 NDINIT.9 namei.9 NDINIT.9
MLINKS+=panic.9 vpanic.9
MLINKS+=pbuf.9 getpbuf.9 \ MLINKS+=pbuf.9 getpbuf.9 \
pbuf.9 relpbuf.9 \ pbuf.9 relpbuf.9 \
pbuf.9 trypbuf.9 pbuf.9 trypbuf.9

View File

@ -31,7 +31,7 @@
.\" .\"
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd August 11, 1995 .Dd April 23, 2015
.Dt PANIC 9 .Dt PANIC 9
.Os .Os
.Sh NAME .Sh NAME
@ -42,10 +42,14 @@
.In sys/systm.h .In sys/systm.h
.Ft void .Ft void
.Fn panic "const char *fmt" ... .Fn panic "const char *fmt" ...
.Ft void
.Fn vpanic "const char *fmt" "va_list ap"
.Sh DESCRIPTION .Sh DESCRIPTION
The The
.Fn panic .Fn panic
function terminates the running system. and
.Fn vpanic
functions terminate the running system.
The message The message
.Fa fmt .Fa fmt
is a is a

View File

@ -606,7 +606,11 @@ dtrace_panic(const char *format, ...)
va_list alist; va_list alist;
va_start(alist, format); va_start(alist, format);
#ifdef __FreeBSD__
vpanic(format, alist);
#else
dtrace_vpanic(format, alist); dtrace_vpanic(format, alist);
#endif
va_end(alist); va_end(alist);
} }

View File

@ -363,211 +363,3 @@ dtrace_interrupt_enable(dtrace_icookie_t cookie)
popfq popfq
ret ret
END(dtrace_interrupt_enable) END(dtrace_interrupt_enable)
/*
* The panic() and cmn_err() functions invoke vpanic() as a common entry point
* into the panic code implemented in panicsys(). vpanic() is responsible
* for passing through the format string and arguments, and constructing a
* regs structure on the stack into which it saves the current register
* values. If we are not dying due to a fatal trap, these registers will
* then be preserved in panicbuf as the current processor state. Before
* invoking panicsys(), vpanic() activates the first panic trigger (see
* common/os/panic.c) and switches to the panic_stack if successful. Note that
* DTrace takes a slightly different panic path if it must panic from probe
* context. Instead of calling panic, it calls into dtrace_vpanic(), which
* sets up the initial stack as vpanic does, calls dtrace_panic_trigger(), and
* branches back into vpanic().
*/
/*
void
vpanic(const char *format, va_list alist)
*/
ENTRY(vpanic) /* Initial stack layout: */
pushq %rbp /* | %rip | 0x60 */
movq %rsp, %rbp /* | %rbp | 0x58 */
pushfq /* | rfl | 0x50 */
pushq %r11 /* | %r11 | 0x48 */
pushq %r10 /* | %r10 | 0x40 */
pushq %rbx /* | %rbx | 0x38 */
pushq %rax /* | %rax | 0x30 */
pushq %r9 /* | %r9 | 0x28 */
pushq %r8 /* | %r8 | 0x20 */
pushq %rcx /* | %rcx | 0x18 */
pushq %rdx /* | %rdx | 0x10 */
pushq %rsi /* | %rsi | 0x8 alist */
pushq %rdi /* | %rdi | 0x0 format */
movq %rsp, %rbx /* %rbx = current %rsp */
leaq panic_quiesce(%rip), %rdi /* %rdi = &panic_quiesce */
call panic_trigger /* %eax = panic_trigger() */
vpanic_common:
/*
* The panic_trigger result is in %eax from the call above, and
* dtrace_panic places it in %eax before branching here.
* The rdmsr instructions that follow below will clobber %eax so
* we stash the panic_trigger result in %r11d.
*/
movl %eax, %r11d
cmpl $0, %r11d
je 0f
/*
* If panic_trigger() was successful, we are the first to initiate a
* panic: we now switch to the reserved panic_stack before continuing.
*/
leaq panic_stack(%rip), %rsp
addq $PANICSTKSIZE, %rsp
0: subq $REGSIZE, %rsp
/*
* Now that we've got everything set up, store the register values as
* they were when we entered vpanic() to the designated location in
* the regs structure we allocated on the stack.
*/
#ifdef notyet
movq 0x0(%rbx), %rcx
movq %rcx, REGOFF_RDI(%rsp)
movq 0x8(%rbx), %rcx
movq %rcx, REGOFF_RSI(%rsp)
movq 0x10(%rbx), %rcx
movq %rcx, REGOFF_RDX(%rsp)
movq 0x18(%rbx), %rcx
movq %rcx, REGOFF_RCX(%rsp)
movq 0x20(%rbx), %rcx
movq %rcx, REGOFF_R8(%rsp)
movq 0x28(%rbx), %rcx
movq %rcx, REGOFF_R9(%rsp)
movq 0x30(%rbx), %rcx
movq %rcx, REGOFF_RAX(%rsp)
movq 0x38(%rbx), %rcx
movq %rcx, REGOFF_RBX(%rsp)
movq 0x58(%rbx), %rcx
movq %rcx, REGOFF_RBP(%rsp)
movq 0x40(%rbx), %rcx
movq %rcx, REGOFF_R10(%rsp)
movq 0x48(%rbx), %rcx
movq %rcx, REGOFF_R11(%rsp)
movq %r12, REGOFF_R12(%rsp)
movq %r13, REGOFF_R13(%rsp)
movq %r14, REGOFF_R14(%rsp)
movq %r15, REGOFF_R15(%rsp)
xorl %ecx, %ecx
movw %ds, %cx
movq %rcx, REGOFF_DS(%rsp)
movw %es, %cx
movq %rcx, REGOFF_ES(%rsp)
movw %fs, %cx
movq %rcx, REGOFF_FS(%rsp)
movw %gs, %cx
movq %rcx, REGOFF_GS(%rsp)
movq $0, REGOFF_TRAPNO(%rsp)
movq $0, REGOFF_ERR(%rsp)
leaq vpanic(%rip), %rcx
movq %rcx, REGOFF_RIP(%rsp)
movw %cs, %cx
movzwq %cx, %rcx
movq %rcx, REGOFF_CS(%rsp)
movq 0x50(%rbx), %rcx
movq %rcx, REGOFF_RFL(%rsp)
movq %rbx, %rcx
addq $0x60, %rcx
movq %rcx, REGOFF_RSP(%rsp)
movw %ss, %cx
movzwq %cx, %rcx
movq %rcx, REGOFF_SS(%rsp)
/*
* panicsys(format, alist, rp, on_panic_stack)
*/
movq REGOFF_RDI(%rsp), %rdi /* format */
movq REGOFF_RSI(%rsp), %rsi /* alist */
movq %rsp, %rdx /* struct regs */
movl %r11d, %ecx /* on_panic_stack */
call panicsys
addq $REGSIZE, %rsp
#endif
popq %rdi
popq %rsi
popq %rdx
popq %rcx
popq %r8
popq %r9
popq %rax
popq %rbx
popq %r10
popq %r11
popfq
leave
ret
END(vpanic)
/*
void
dtrace_vpanic(const char *format, va_list alist)
*/
ENTRY(dtrace_vpanic) /* Initial stack layout: */
pushq %rbp /* | %rip | 0x60 */
movq %rsp, %rbp /* | %rbp | 0x58 */
pushfq /* | rfl | 0x50 */
pushq %r11 /* | %r11 | 0x48 */
pushq %r10 /* | %r10 | 0x40 */
pushq %rbx /* | %rbx | 0x38 */
pushq %rax /* | %rax | 0x30 */
pushq %r9 /* | %r9 | 0x28 */
pushq %r8 /* | %r8 | 0x20 */
pushq %rcx /* | %rcx | 0x18 */
pushq %rdx /* | %rdx | 0x10 */
pushq %rsi /* | %rsi | 0x8 alist */
pushq %rdi /* | %rdi | 0x0 format */
movq %rsp, %rbx /* %rbx = current %rsp */
leaq panic_quiesce(%rip), %rdi /* %rdi = &panic_quiesce */
call dtrace_panic_trigger /* %eax = dtrace_panic_trigger() */
jmp vpanic_common
END(dtrace_vpanic)
/*
int
panic_trigger(int *tp)
*/
ENTRY(panic_trigger)
xorl %eax, %eax
movl $0xdefacedd, %edx
lock
xchgl %edx, (%rdi)
cmpl $0, %edx
je 0f
movl $0, %eax
ret
0: movl $1, %eax
ret
END(panic_trigger)
/*
int
dtrace_panic_trigger(int *tp)
*/
ENTRY(dtrace_panic_trigger)
xorl %eax, %eax
movl $0xdefacedd, %edx
lock
xchgl %edx, (%rdi)
cmpl $0, %edx
je 0f
movl $0, %eax
ret
0: movl $1, %eax
ret
END(dtrace_panic_trigger)

View File

@ -3,9 +3,6 @@
dtrace_cacheid_t dtrace_predcache_id; dtrace_cacheid_t dtrace_predcache_id;
int panic_quiesce;
char panic_stack[PANICSTKSIZE];
boolean_t boolean_t
priv_policy_only(const cred_t *a, int b, boolean_t c) priv_policy_only(const cred_t *a, int b, boolean_t c)
{ {

View File

@ -355,167 +355,3 @@ void dtrace_interrupt_enable(dtrace_icookie_t cookie)
popfl popfl
ret ret
END(dtrace_interrupt_enable) END(dtrace_interrupt_enable)
/*
* The panic() and cmn_err() functions invoke vpanic() as a common entry point
* into the panic code implemented in panicsys(). vpanic() is responsible
* for passing through the format string and arguments, and constructing a
* regs structure on the stack into which it saves the current register
* values. If we are not dying due to a fatal trap, these registers will
* then be preserved in panicbuf as the current processor state. Before
* invoking panicsys(), vpanic() activates the first panic trigger (see
* common/os/panic.c) and switches to the panic_stack if successful. Note that
* DTrace takes a slightly different panic path if it must panic from probe
* context. Instead of calling panic, it calls into dtrace_vpanic(), which
* sets up the initial stack as vpanic does, calls dtrace_panic_trigger(), and
* branches back into vpanic().
*/
/*
void vpanic(const char *format, va_list alist)
*/
ENTRY(vpanic) /* Initial stack layout: */
pushl %ebp /* | %eip | 20 */
movl %esp, %ebp /* | %ebp | 16 */
pushl %eax /* | %eax | 12 */
pushl %ebx /* | %ebx | 8 */
pushl %ecx /* | %ecx | 4 */
pushl %edx /* | %edx | 0 */
movl %esp, %ebx /* %ebx = current stack pointer */
lea panic_quiesce, %eax /* %eax = &panic_quiesce */
pushl %eax /* push &panic_quiesce */
call panic_trigger /* %eax = panic_trigger() */
addl $4, %esp /* reset stack pointer */
vpanic_common:
cmpl $0, %eax /* if (%eax == 0) */
je 0f /* goto 0f; */
/*
* If panic_trigger() was successful, we are the first to initiate a
* panic: we now switch to the reserved panic_stack before continuing.
*/
lea panic_stack, %esp /* %esp = panic_stack */
addl $PANICSTKSIZE, %esp /* %esp += PANICSTKSIZE */
0: subl $REGSIZE, %esp /* allocate struct regs */
/*
* Now that we've got everything set up, store the register values as
* they were when we entered vpanic() to the designated location in
* the regs structure we allocated on the stack.
*/
#ifdef notyet
mov %gs, %edx
mov %edx, REGOFF_GS(%esp)
mov %fs, %edx
mov %edx, REGOFF_FS(%esp)
mov %es, %edx
mov %edx, REGOFF_ES(%esp)
mov %ds, %edx
mov %edx, REGOFF_DS(%esp)
movl %edi, REGOFF_EDI(%esp)
movl %esi, REGOFF_ESI(%esp)
movl 16(%ebx), %ecx
movl %ecx, REGOFF_EBP(%esp)
movl %ebx, %ecx
addl $20, %ecx
movl %ecx, REGOFF_ESP(%esp)
movl 8(%ebx), %ecx
movl %ecx, REGOFF_EBX(%esp)
movl 0(%ebx), %ecx
movl %ecx, REGOFF_EDX(%esp)
movl 4(%ebx), %ecx
movl %ecx, REGOFF_ECX(%esp)
movl 12(%ebx), %ecx
movl %ecx, REGOFF_EAX(%esp)
movl $0, REGOFF_TRAPNO(%esp)
movl $0, REGOFF_ERR(%esp)
lea vpanic, %ecx
movl %ecx, REGOFF_EIP(%esp)
mov %cs, %edx
movl %edx, REGOFF_CS(%esp)
pushfl
popl %ecx
movl %ecx, REGOFF_EFL(%esp)
movl $0, REGOFF_UESP(%esp)
mov %ss, %edx
movl %edx, REGOFF_SS(%esp)
movl %esp, %ecx /* %ecx = &regs */
pushl %eax /* push on_panic_stack */
pushl %ecx /* push &regs */
movl 12(%ebp), %ecx /* %ecx = alist */
pushl %ecx /* push alist */
movl 8(%ebp), %ecx /* %ecx = format */
pushl %ecx /* push format */
call panicsys /* panicsys(); */
addl $16, %esp /* pop arguments */
addl $REGSIZE, %esp
#endif
popl %edx
popl %ecx
popl %ebx
popl %eax
leave
ret
END(vpanic)
/*
void dtrace_vpanic(const char *format, va_list alist)
*/
ENTRY(dtrace_vpanic) /* Initial stack layout: */
pushl %ebp /* | %eip | 20 */
movl %esp, %ebp /* | %ebp | 16 */
pushl %eax /* | %eax | 12 */
pushl %ebx /* | %ebx | 8 */
pushl %ecx /* | %ecx | 4 */
pushl %edx /* | %edx | 0 */
movl %esp, %ebx /* %ebx = current stack pointer */
lea panic_quiesce, %eax /* %eax = &panic_quiesce */
pushl %eax /* push &panic_quiesce */
call dtrace_panic_trigger /* %eax = dtrace_panic_trigger() */
addl $4, %esp /* reset stack pointer */
jmp vpanic_common /* jump back to common code */
END(dtrace_vpanic)
/*
int
panic_trigger(int *tp)
*/
ENTRY(panic_trigger)
xorl %eax, %eax
movl $0xdefacedd, %edx
lock
xchgl %edx, (%edi)
cmpl $0, %edx
je 0f
movl $0, %eax
ret
0: movl $1, %eax
ret
END(panic_trigger)
/*
int
dtrace_panic_trigger(int *tp)
*/
ENTRY(dtrace_panic_trigger)
xorl %eax, %eax
movl $0xdefacedd, %edx
lock
xchgl %edx, (%edi)
cmpl $0, %edx
je 0f
movl $0, %eax
ret
0: movl $1, %eax
ret
END(dtrace_panic_trigger)

View File

@ -248,49 +248,6 @@ LEAF(dtrace_invop_uninit)
nop nop
END(dtrace_invop_uninit) END(dtrace_invop_uninit)
/*
* The panic() and cmn_err() functions invoke vpanic() as a common entry point
* into the panic code implemented in panicsys(). vpanic() is responsible
* for passing through the format string and arguments, and constructing a
* regs structure on the stack into which it saves the current register
* values. If we are not dying due to a fatal trap, these registers will
* then be preserved in panicbuf as the current processor state. Before
* invoking panicsys(), vpanic() activates the first panic trigger (see
* common/os/panic.c) and switches to the panic_stack if successful. Note that
* DTrace takes a slightly different panic path if it must panic from probe
* context. Instead of calling panic, it calls into dtrace_vpanic(), which
* sets up the initial stack as vpanic does, calls dtrace_panic_trigger(), and
* branches back into vpanic().
*/
/*
void
vpanic(const char *format, va_list alist)
*/
LEAF(vpanic) /* Initial stack layout: */
vpanic_common:
j ra
nop
END(vpanic)
/*
void
dtrace_vpanic(const char *format, va_list alist)
*/
LEAF(dtrace_vpanic) /* Initial stack layout: */
#if 0
jal dtrace_panic_trigger /* %eax = dtrace_panic_trigger() */
nop
#endif
j vpanic_common
nop
END(dtrace_vpanic)
/* /*
uintptr_t uintptr_t
dtrace_caller(int aframes) dtrace_caller(int aframes)
@ -300,4 +257,3 @@ LEAF(dtrace_caller)
j ra j ra
nop nop
END(dtrace_caller) END(dtrace_caller)

View File

@ -160,45 +160,6 @@ ASENTRY_NOPROF(dtrace_copystr)
blr blr
END(dtrace_copystr) END(dtrace_copystr)
/*
* The panic() and cmn_err() functions invoke vpanic() as a common entry point
* into the panic code implemented in panicsys(). vpanic() is responsible
* for passing through the format string and arguments, and constructing a
* regs structure on the stack into which it saves the current register
* values. If we are not dying due to a fatal trap, these registers will
* then be preserved in panicbuf as the current processor state. Before
* invoking panicsys(), vpanic() activates the first panic trigger (see
* common/os/panic.c) and switches to the panic_stack if successful. Note that
* DTrace takes a slightly different panic path if it must panic from probe
* context. Instead of calling panic, it calls into dtrace_vpanic(), which
* sets up the initial stack as vpanic does, calls dtrace_panic_trigger(), and
* branches back into vpanic().
*/
/*
void
vpanic(const char *format, va_list alist)
*/
ASENTRY_NOPROF(vpanic) /* Initial stack layout: */
vpanic_common:
blr
END(vpanic)
/*
void
dtrace_vpanic(const char *format, va_list alist)
*/
ASENTRY_NOPROF(dtrace_vpanic) /* Initial stack layout: */
#if 0
bl dtrace_panic_trigger /* %eax = dtrace_panic_trigger() */
#endif
b vpanic_common
END(dtrace_vpanic)
/* /*
uintptr_t uintptr_t
dtrace_caller(int aframes) dtrace_caller(int aframes)
@ -207,4 +168,3 @@ ASENTRY_NOPROF(dtrace_caller)
li %r3, -1 li %r3, -1
blr blr
END(dtrace_caller) END(dtrace_caller)

View File

@ -157,7 +157,6 @@ static void poweroff_wait(void *, int);
static void shutdown_halt(void *junk, int howto); static void shutdown_halt(void *junk, int howto);
static void shutdown_panic(void *junk, int howto); static void shutdown_panic(void *junk, int howto);
static void shutdown_reset(void *junk, int howto); static void shutdown_reset(void *junk, int howto);
static void vpanic(const char *fmt, va_list ap) __dead2;
/* register various local shutdown events */ /* register various local shutdown events */
static void static void
@ -688,7 +687,7 @@ panic(const char *fmt, ...)
vpanic(fmt, ap); vpanic(fmt, ap);
} }
static void void
vpanic(const char *fmt, va_list ap) vpanic(const char *fmt, va_list ap)
{ {
#ifdef SMP #ifdef SMP

View File

@ -187,6 +187,7 @@ void *phashinit(int count, struct malloc_type *type, u_long *nentries);
void g_waitidle(void); void g_waitidle(void);
void panic(const char *, ...) __dead2 __printflike(1, 2); void panic(const char *, ...) __dead2 __printflike(1, 2);
void vpanic(const char *, __va_list) __dead2 __printflike(1, 0);
void cpu_boot(int); void cpu_boot(int);
void cpu_flush_dcache(void *, size_t); void cpu_flush_dcache(void *, size_t);