Prevent CPU migration when checking the DTrace nofault flag on x86.
dtrace_trap() consumes page and protection faults triggered by code running in DTrace probe context. Such faults occur with interrupts disabled and are detected using a per-CPU flag. Regular faults cause dtrace_trap() to be called with interrupts enabled, and nothing was ensuring that the flag was read from the correct CPU. This may result in dtrace_trap() consuming unrelated page and protection faults when DTrace is enabled, causing the fault handler to return without actually having handled the fault. Diagnosed by: Ryan Libby <rlibby@gmail.com> MFC after: 3 days Sponsored by: Dell EMC Isilon
This commit is contained in:
parent
5e6a848492
commit
2a3b2874a6
@ -384,6 +384,8 @@ dtrace_gethrestime(void)
|
||||
int
|
||||
dtrace_trap(struct trapframe *frame, u_int type)
|
||||
{
|
||||
uint16_t nofault;
|
||||
|
||||
/*
|
||||
* A trap can occur while DTrace executes a probe. Before
|
||||
* executing the probe, DTrace blocks re-scheduling and sets
|
||||
@ -393,7 +395,12 @@ dtrace_trap(struct trapframe *frame, u_int type)
|
||||
*
|
||||
* Check if DTrace has enabled 'no-fault' mode:
|
||||
*/
|
||||
if ((cpu_core[curcpu].cpuc_dtrace_flags & CPU_DTRACE_NOFAULT) != 0) {
|
||||
sched_pin();
|
||||
nofault = cpu_core[curcpu].cpuc_dtrace_flags & CPU_DTRACE_NOFAULT;
|
||||
sched_unpin();
|
||||
if (nofault) {
|
||||
KASSERT((read_rflags() & PSL_I) == 0, ("interrupts enabled"));
|
||||
|
||||
/*
|
||||
* There are only a couple of trap types that are expected.
|
||||
* All the rest will be handled in the usual way.
|
||||
|
@ -386,6 +386,8 @@ dtrace_gethrestime(void)
|
||||
int
|
||||
dtrace_trap(struct trapframe *frame, u_int type)
|
||||
{
|
||||
uint16_t nofault;
|
||||
|
||||
/*
|
||||
* A trap can occur while DTrace executes a probe. Before
|
||||
* executing the probe, DTrace blocks re-scheduling and sets
|
||||
@ -395,7 +397,12 @@ dtrace_trap(struct trapframe *frame, u_int type)
|
||||
*
|
||||
* Check if DTrace has enabled 'no-fault' mode:
|
||||
*/
|
||||
if ((cpu_core[curcpu].cpuc_dtrace_flags & CPU_DTRACE_NOFAULT) != 0) {
|
||||
sched_pin();
|
||||
nofault = cpu_core[curcpu].cpuc_dtrace_flags & CPU_DTRACE_NOFAULT;
|
||||
sched_unpin();
|
||||
if (nofault) {
|
||||
KASSERT((read_eflags() & PSL_I) == 0, ("interrupts enabled"));
|
||||
|
||||
/*
|
||||
* There are only a couple of trap types that are expected.
|
||||
* All the rest will be handled in the usual way.
|
||||
|
Loading…
Reference in New Issue
Block a user