Date: Thu, 16 Feb 2017 23:05:21 +0000 (UTC) From: Mark Johnston <markj@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r313841 - in head/sys/cddl/dev/dtrace: amd64 i386 Message-ID: <201702162305.v1GN5LjX071961@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: markj Date: Thu Feb 16 23:05:20 2017 New Revision: 313841 URL: https://svnweb.freebsd.org/changeset/base/313841 Log: 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 Modified: head/sys/cddl/dev/dtrace/amd64/dtrace_subr.c head/sys/cddl/dev/dtrace/i386/dtrace_subr.c Modified: head/sys/cddl/dev/dtrace/amd64/dtrace_subr.c ============================================================================== --- head/sys/cddl/dev/dtrace/amd64/dtrace_subr.c Thu Feb 16 22:29:37 2017 (r313840) +++ head/sys/cddl/dev/dtrace/amd64/dtrace_subr.c Thu Feb 16 23:05:20 2017 (r313841) @@ -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_i * * 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. Modified: head/sys/cddl/dev/dtrace/i386/dtrace_subr.c ============================================================================== --- head/sys/cddl/dev/dtrace/i386/dtrace_subr.c Thu Feb 16 22:29:37 2017 (r313840) +++ head/sys/cddl/dev/dtrace/i386/dtrace_subr.c Thu Feb 16 23:05:20 2017 (r313841) @@ -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_i * * 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.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201702162305.v1GN5LjX071961>