#include <linux/vmalloc.h>
#include <net/ipv6.h>
#include <asm/byteorder.h>
+#include <asm/traps.h>
#include <linux/mount.h>
* no way for a global variable key signature to match a thread-local key
* signature.
*/
+#ifdef CONFIG_X86_64
+# define DTRACE_IN_IRQ() \
+ ((this_cpu_core->cpu_dtrace_regs && \
+ this_cpu_core->cpu_dtrace_regs->orig_ax == X86_TRAP_BP) \
+ ? (hardirq_count() - HARDIRQ_OFFSET) \
+ : in_irq())
+#else
+# define DTRACE_IN_IRQ() in_irq()
+#endif
#define DTRACE_TLS_THRKEY(where) \
{ \
- uint_t intr = in_irq() ? 1 : 0; \
+ uint_t intr = DTRACE_IN_IRQ() ? 1 : 0; \
\
(where) = ((current->pid + DIF_VARIABLE_MAX) & \
(((uint64_t)1 << 63) - 1)) | \
*/
#include <linux/dtrace_fbt.h>
+#include <asm/traps.h>
#include <asm/dtrace_util.h>
#include "dtrace.h"
for (; fbp != NULL; fbp = fbp->fbp_hashnext) {
if ((uintptr_t)fbp->fbp_patchpoint == regs->ip) {
+ unsigned long orig_ax;
+
+ /*
+ * We (ab)use regs->orig_ax to store the trapno since
+ * int3 (used for return probes) causes HARDIRQ to be
+ * incremented in the preempt_count, which messes with
+ * the TLS thread key calculation.
+ *
+ * This is not pretty, but neither is the fact that
+ * int3 cause handlers to think they are called from
+ * within an interrupt.
+ */
this_cpu_core->cpu_dtrace_regs = regs;
+ orig_ax = regs->orig_ax;
+
if (fbp->fbp_roffset == 0) {
+ regs->orig_ax = X86_TRAP_UD;
dtrace_probe(fbp->fbp_id, regs->di, regs->si,
regs->dx, regs->cx, regs->r8);
} else {
+ regs->orig_ax = X86_TRAP_BP;
dtrace_probe(fbp->fbp_id, fbp->fbp_roffset,
regs->ax, 0, 0, 0);
}
+ regs->orig_ax = orig_ax;
this_cpu_core->cpu_dtrace_regs = NULL;
return fbp->fbp_rval;