Invoke the DTrace trap handler before calling trap() on amd64. This matches
the upstream implementation and helps ensure that a trap induced by tracing fbt::trap:entry is handled without recursively generating another trap. This makes it possible to run most (but not all) of the DTrace tests under common/safety/ without triggering a kernel panic. Submitted by: Anton Rang <anton.rang@isilon.com> (original version) Phabric: D95
This commit is contained in:
parent
1dd381bf67
commit
291624fdf6
@ -228,7 +228,24 @@ alltraps_pushregs_no_rdi:
|
||||
.type calltrap,@function
|
||||
calltrap:
|
||||
movq %rsp,%rdi
|
||||
#ifdef KDTRACE_HOOKS
|
||||
/*
|
||||
* Give DTrace a chance to vet this trap and skip the call to trap() if
|
||||
* it turns out that it was caused by a DTrace probe.
|
||||
*/
|
||||
movq dtrace_trap_func,%rax
|
||||
testq %rax,%rax
|
||||
je skiphook
|
||||
call *%rax
|
||||
testq %rax,%rax
|
||||
jne skiptrap
|
||||
movq %rsp,%rdi
|
||||
skiphook:
|
||||
#endif
|
||||
call trap
|
||||
#ifdef KDTRACE_HOOKS
|
||||
skiptrap:
|
||||
#endif
|
||||
MEXITCOUNT
|
||||
jmp doreti /* Handle any pending ASTs */
|
||||
|
||||
|
@ -218,18 +218,6 @@ trap(struct trapframe *frame)
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef KDTRACE_HOOKS
|
||||
/*
|
||||
* A trap can occur while DTrace executes a probe. Before
|
||||
* executing the probe, DTrace blocks re-scheduling and sets
|
||||
* a flag in its per-cpu flags to indicate that it doesn't
|
||||
* want to fault. On returning from the probe, the no-fault
|
||||
* flag is cleared and finally re-scheduling is enabled.
|
||||
*/
|
||||
if (dtrace_trap_func != NULL && (*dtrace_trap_func)(frame, type))
|
||||
goto out;
|
||||
#endif
|
||||
|
||||
if ((frame->tf_rflags & PSL_I) == 0) {
|
||||
/*
|
||||
* Buggy application or kernel code has disabled
|
||||
|
@ -462,29 +462,27 @@ dtrace_gethrestime(void)
|
||||
return (current_time.tv_sec * 1000000000ULL + current_time.tv_nsec);
|
||||
}
|
||||
|
||||
/* Function to handle DTrace traps during probes. See amd64/amd64/trap.c */
|
||||
/*
|
||||
* Function to handle DTrace traps during probes. See amd64/amd64/exception.S.
|
||||
*/
|
||||
int
|
||||
dtrace_trap(struct trapframe *frame, u_int type)
|
||||
dtrace_trap(struct trapframe *frame)
|
||||
{
|
||||
/*
|
||||
* A trap can occur while DTrace executes a probe. Before
|
||||
* executing the probe, DTrace blocks re-scheduling and sets
|
||||
* a flag in it's per-cpu flags to indicate that it doesn't
|
||||
* a flag in its per-cpu flags to indicate that it doesn't
|
||||
* want to fault. On returning from the probe, the no-fault
|
||||
* flag is cleared and finally re-scheduling is enabled.
|
||||
*
|
||||
* Check if DTrace has enabled 'no-fault' mode:
|
||||
*
|
||||
*/
|
||||
if ((cpu_core[curcpu].cpuc_dtrace_flags & CPU_DTRACE_NOFAULT) != 0) {
|
||||
/*
|
||||
* There are only a couple of trap types that are expected.
|
||||
* All the rest will be handled in the usual way.
|
||||
*/
|
||||
switch (type) {
|
||||
/* Privilieged instruction fault. */
|
||||
case T_PRIVINFLT:
|
||||
break;
|
||||
switch (frame->tf_trapno) {
|
||||
/* General protection fault. */
|
||||
case T_PROTFLT:
|
||||
/* Flag an illegal operation. */
|
||||
|
@ -473,24 +473,23 @@ dtrace_gethrestime(void)
|
||||
|
||||
/* Function to handle DTrace traps during probes. See i386/i386/trap.c */
|
||||
int
|
||||
dtrace_trap(struct trapframe *frame, u_int type)
|
||||
dtrace_trap(struct trapframe *frame)
|
||||
{
|
||||
/*
|
||||
* A trap can occur while DTrace executes a probe. Before
|
||||
* executing the probe, DTrace blocks re-scheduling and sets
|
||||
* a flag in it's per-cpu flags to indicate that it doesn't
|
||||
* a flag in its per-cpu flags to indicate that it doesn't
|
||||
* want to fault. On returning from the probe, the no-fault
|
||||
* flag is cleared and finally re-scheduling is enabled.
|
||||
*
|
||||
* Check if DTrace has enabled 'no-fault' mode:
|
||||
*
|
||||
*/
|
||||
if ((cpu_core[curcpu].cpuc_dtrace_flags & CPU_DTRACE_NOFAULT) != 0) {
|
||||
/*
|
||||
* There are only a couple of trap types that are expected.
|
||||
* All the rest will be handled in the usual way.
|
||||
*/
|
||||
switch (type) {
|
||||
switch (frame->tf_trapno) {
|
||||
/* General protection fault. */
|
||||
case T_PROTFLT:
|
||||
/* Flag an illegal operation. */
|
||||
|
@ -137,17 +137,20 @@ dtrace_gethrestime(void)
|
||||
|
||||
/* Function to handle DTrace traps during probes. See amd64/amd64/trap.c */
|
||||
int
|
||||
dtrace_trap(struct trapframe *frame, u_int type)
|
||||
dtrace_trap(struct trapframe *frame)
|
||||
{
|
||||
u_int type;
|
||||
|
||||
type = (trapframe->cause & MIPS_CR_EXC_CODE) >> MIPS_CR_EXC_CODE_SHIFT;
|
||||
|
||||
/*
|
||||
* A trap can occur while DTrace executes a probe. Before
|
||||
* executing the probe, DTrace blocks re-scheduling and sets
|
||||
* a flag in it's per-cpu flags to indicate that it doesn't
|
||||
* a flag in its per-cpu flags to indicate that it doesn't
|
||||
* want to fault. On returning from the probe, the no-fault
|
||||
* flag is cleared and finally re-scheduling is enabled.
|
||||
*
|
||||
* Check if DTrace has enabled 'no-fault' mode:
|
||||
*
|
||||
*/
|
||||
if ((cpu_core[curcpu].cpuc_dtrace_flags & CPU_DTRACE_NOFAULT) != 0) {
|
||||
/*
|
||||
|
@ -262,24 +262,23 @@ dtrace_gethrestime(void)
|
||||
|
||||
/* Function to handle DTrace traps during probes. See powerpc/powerpc/trap.c */
|
||||
int
|
||||
dtrace_trap(struct trapframe *frame, u_int type)
|
||||
dtrace_trap(struct trapframe *frame)
|
||||
{
|
||||
/*
|
||||
* A trap can occur while DTrace executes a probe. Before
|
||||
* executing the probe, DTrace blocks re-scheduling and sets
|
||||
* a flag in it's per-cpu flags to indicate that it doesn't
|
||||
* a flag in its per-cpu flags to indicate that it doesn't
|
||||
* want to fault. On returning from the probe, the no-fault
|
||||
* flag is cleared and finally re-scheduling is enabled.
|
||||
*
|
||||
* Check if DTrace has enabled 'no-fault' mode:
|
||||
*
|
||||
*/
|
||||
if ((cpu_core[curcpu].cpuc_dtrace_flags & CPU_DTRACE_NOFAULT) != 0) {
|
||||
/*
|
||||
* There are only a couple of trap types that are expected.
|
||||
* All the rest will be handled in the usual way.
|
||||
*/
|
||||
switch (type) {
|
||||
switch (frame->exc) {
|
||||
/* Page fault. */
|
||||
case EXC_DSI:
|
||||
case EXC_DSE:
|
||||
|
@ -246,7 +246,7 @@ trap(struct trapframe *frame)
|
||||
* flag is cleared and finally re-scheduling is enabled.
|
||||
*/
|
||||
if ((type == T_PROTFLT || type == T_PAGEFLT) &&
|
||||
dtrace_trap_func != NULL && (*dtrace_trap_func)(frame, type))
|
||||
dtrace_trap_func != NULL && (*dtrace_trap_func)(frame))
|
||||
goto out;
|
||||
#endif
|
||||
|
||||
|
@ -605,7 +605,7 @@ trap(struct trapframe *trapframe)
|
||||
/*
|
||||
* A trap can occur while DTrace executes a probe. Before
|
||||
* executing the probe, DTrace blocks re-scheduling and sets
|
||||
* a flag in it's per-cpu flags to indicate that it doesn't
|
||||
* a flag in its per-cpu flags to indicate that it doesn't
|
||||
* want to fault. On returning from the probe, the no-fault
|
||||
* flag is cleared and finally re-scheduling is enabled.
|
||||
*
|
||||
@ -618,7 +618,7 @@ trap(struct trapframe *trapframe)
|
||||
* XXXDTRACE: add pid probe handler here (if ever)
|
||||
*/
|
||||
if (!usermode) {
|
||||
if (dtrace_trap_func != NULL && (*dtrace_trap_func)(trapframe, type))
|
||||
if (dtrace_trap_func != NULL && (*dtrace_trap_func)(trapframe))
|
||||
return (trapframe->pc);
|
||||
}
|
||||
#endif
|
||||
|
@ -167,7 +167,7 @@ trap(struct trapframe *frame)
|
||||
/*
|
||||
* A trap can occur while DTrace executes a probe. Before
|
||||
* executing the probe, DTrace blocks re-scheduling and sets
|
||||
* a flag in it's per-cpu flags to indicate that it doesn't
|
||||
* a flag in its per-cpu flags to indicate that it doesn't
|
||||
* want to fault. On returning from the probe, the no-fault
|
||||
* flag is cleared and finally re-scheduling is enabled.
|
||||
*
|
||||
@ -176,7 +176,7 @@ trap(struct trapframe *frame)
|
||||
* handled the trap and modified the trap frame so that this
|
||||
* function can return normally.
|
||||
*/
|
||||
if (dtrace_trap_func != NULL && (*dtrace_trap_func)(frame, type))
|
||||
if (dtrace_trap_func != NULL && (*dtrace_trap_func)(frame))
|
||||
return;
|
||||
#endif
|
||||
|
||||
|
@ -48,15 +48,14 @@ extern cyclic_clock_func_t cyclic_clock_func;
|
||||
|
||||
void clocksource_cyc_set(const struct bintime *t);
|
||||
|
||||
int dtrace_trap(struct trapframe *);
|
||||
|
||||
/*
|
||||
* The dtrace module handles traps that occur during a DTrace probe.
|
||||
* This type definition is used in the trap handler to provide a
|
||||
* hook for the dtrace module to register it's handler with.
|
||||
* hook for the dtrace module to register its handler with.
|
||||
*/
|
||||
typedef int (*dtrace_trap_func_t)(struct trapframe *, u_int);
|
||||
|
||||
int dtrace_trap(struct trapframe *, u_int);
|
||||
|
||||
typedef int (*dtrace_trap_func_t)(struct trapframe *);
|
||||
extern dtrace_trap_func_t dtrace_trap_func;
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user