Page MenuHomeFreeBSD

D20526.id58272.diff
No OneTemporary

D20526.id58272.diff

Index: sys/amd64/amd64/trap.c
===================================================================
--- sys/amd64/amd64/trap.c
+++ sys/amd64/amd64/trap.c
@@ -113,6 +113,10 @@
static int trap_pfault(struct trapframe *, int);
static void trap_fatal(struct trapframe *, vm_offset_t);
+#ifdef KDTRACE_HOOKS
+static bool trap_user_dtrace(struct trapframe *,
+ int (**hook)(struct trapframe *));
+#endif
#define MAX_TRAP_MSG 32
static char *trap_msg[] = {
@@ -284,11 +288,11 @@
break;
case T_BPTFLT: /* bpt instruction fault */
- enable_intr();
#ifdef KDTRACE_HOOKS
- if (dtrace_pid_probe_ptr != NULL &&
- dtrace_pid_probe_ptr(frame) == 0)
+ if (trap_user_dtrace(frame, &dtrace_pid_probe_ptr))
return;
+#else
+ enable_intr();
#endif
signo = SIGTRAP;
ucode = TRAP_BRKPT;
@@ -425,9 +429,7 @@
break;
#ifdef KDTRACE_HOOKS
case T_DTRACE_RET:
- enable_intr();
- if (dtrace_return_probe_ptr != NULL)
- dtrace_return_probe_ptr(frame);
+ (void)trap_user_dtrace(frame, &dtrace_return_probe_ptr);
return;
#endif
}
@@ -948,6 +950,25 @@
panic("unknown/reserved trap");
}
+#ifdef KDTRACE_HOOKS
+/*
+ * Invoke a userspace DTrace hook. The hook pointer is cleared when no
+ * userspace probes are enabled, so we must synchronize with DTrace to ensure
+ * that a trapping thread is able to call the hook before it is cleared.
+ */
+static bool
+trap_user_dtrace(struct trapframe *frame, int (**hookp)(struct trapframe *))
+{
+ int (*hook)(struct trapframe *);
+
+ hook = (int (*)(struct trapframe *))atomic_load_ptr(hookp);
+ enable_intr();
+ if (hook != NULL)
+ return ((hook)(frame) == 0);
+ return (false);
+}
+#endif
+
/*
* Double fault handler. Called when a fault occurs while writing
* a frame for a trap/exception onto the stack. This usually occurs
Index: sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c
+++ sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c
@@ -1125,31 +1125,17 @@
static void
fasttrap_disable_callbacks(void)
{
-#ifdef illumos
- ASSERT(MUTEX_HELD(&cpu_lock));
-#endif
-
-
mutex_enter(&fasttrap_count_mtx);
ASSERT(fasttrap_pid_count > 0);
fasttrap_pid_count--;
if (fasttrap_pid_count == 0) {
-#ifdef illumos
- cpu_t *cur, *cpu = CPU;
-
- for (cur = cpu->cpu_next_onln; cur != cpu;
- cur = cur->cpu_next_onln) {
- rw_enter(&cur->cpu_ft_lock, RW_WRITER);
- }
-#endif
+ /*
+ * Synchronize with the breakpoint handler, which is careful to
+ * enable interrupts only after loading the hook pointer.
+ */
+ dtrace_sync();
dtrace_pid_probe_ptr = NULL;
dtrace_return_probe_ptr = NULL;
-#ifdef illumos
- for (cur = cpu->cpu_next_onln; cur != cpu;
- cur = cur->cpu_next_onln) {
- rw_exit(&cur->cpu_ft_lock);
- }
-#endif
}
mutex_exit(&fasttrap_count_mtx);
}
Index: sys/i386/i386/trap.c
===================================================================
--- sys/i386/i386/trap.c
+++ sys/i386/i386/trap.c
@@ -116,6 +116,10 @@
static int trap_pfault(struct trapframe *, int, vm_offset_t);
static void trap_fatal(struct trapframe *, vm_offset_t);
+#ifdef KDTRACE_HOOKS
+static bool trap_user_dtrace(struct trapframe *,
+ int (**hook)(struct trapframe *));
+#endif
void dblfault_handler(void);
extern inthand_t IDTVEC(bpt), IDTVEC(dbg), IDTVEC(int0x80_syscall);
@@ -322,11 +326,11 @@
break;
case T_BPTFLT: /* bpt instruction fault */
- enable_intr();
#ifdef KDTRACE_HOOKS
- if (dtrace_pid_probe_ptr != NULL &&
- dtrace_pid_probe_ptr(frame) == 0)
+ if (trap_user_dtrace(frame, &dtrace_pid_probe_ptr))
return;
+#else
+ enable_intr();
#endif
signo = SIGTRAP;
ucode = TRAP_BRKPT;
@@ -504,9 +508,7 @@
break;
#ifdef KDTRACE_HOOKS
case T_DTRACE_RET:
- enable_intr();
- if (dtrace_return_probe_ptr != NULL)
- dtrace_return_probe_ptr(frame);
+ (void)trap_user_dtrace(frame, &dtrace_return_probe_ptr);
return;
#endif
}
@@ -991,6 +993,25 @@
panic("unknown/reserved trap");
}
+#ifdef KDTRACE_HOOKS
+/*
+ * Invoke a userspace DTrace hook. The hook pointer is cleared when no
+ * userspace probes are enabled, so we must synchronize with DTrace to ensure
+ * that a trapping thread is able to call the hook before it is cleared.
+ */
+static bool
+trap_user_dtrace(struct trapframe *frame, int (**hookp)(struct trapframe *))
+{
+ int (*hook)(struct trapframe *);
+
+ hook = (int (*)(struct trapframe *))atomic_load_ptr(hookp);
+ enable_intr();
+ if (hook != NULL)
+ return ((hook)(frame) == 0);
+ return (false);
+}
+#endif
+
/*
* Double fault handler. Called when a fault occurs while writing
* a frame for a trap/exception onto the stack. This usually occurs

File Metadata

Mime Type
text/plain
Expires
Sun, Nov 16, 10:28 PM (5 m, 57 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
25393282
Default Alt Text
D20526.id58272.diff (4 KB)

Event Timeline