From owner-p4-projects@FreeBSD.ORG Thu Dec 20 03:09:18 2007 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id E6F7E16A418; Thu, 20 Dec 2007 03:09:17 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 2330116A419 for ; Thu, 20 Dec 2007 03:09:17 +0000 (UTC) (envelope-from jb@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 1C8D713C43E for ; Thu, 20 Dec 2007 03:09:17 +0000 (UTC) (envelope-from jb@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.1/8.14.1) with ESMTP id lBK39GdZ022815 for ; Thu, 20 Dec 2007 03:09:16 GMT (envelope-from jb@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.1/8.14.1/Submit) id lBK39GHB022812 for perforce@freebsd.org; Thu, 20 Dec 2007 03:09:16 GMT (envelope-from jb@freebsd.org) Date: Thu, 20 Dec 2007 03:09:16 GMT Message-Id: <200712200309.lBK39GHB022812@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to jb@freebsd.org using -f From: John Birrell To: Perforce Change Reviews Cc: Subject: PERFORCE change 131281 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 20 Dec 2007 03:09:18 -0000 http://perforce.freebsd.org/chv.cgi?CH=131281 Change 131281 by jb@jb_freebsd1 on 2007/12/20 03:08:21 Add the hook for the 'systrace' (syscall) provider and the entry and return calls using it. The implementation is opaque. The sysent support for this was added to current prior to the RELENG_7 branch. Add a hook for the DTrace 'safety' implementation. This is an opaque implementation of the previous one I did which assumed that certain OpenSolaris headers would be relicensed. Now that I know that won't happen, the code that relies on them *must* be loaded as part of the dtrace kernel module. In OpenSolaris there is a 'cpu_core' array that is has fields that DTrace uses to flag the fact that it is executing a probe. If a trap occurs with that flag set, then it assumes that the trap was caused by it (by referencing an address that isn't mapped, for example) and it sets an error flag in the same array and just returns from the trap, expecting that the RISC engine executing the DIF (DTrace intermediate format) will detect the error and just abort the probe processing. The new DTrace port will still rely on the cpu_core array, but it will be private to the DTrace module, thereby keeping the CDDL licensed code together. Affected files ... .. //depot/projects/dtrace/src/sys/amd64/amd64/trap.c#19 edit .. //depot/projects/dtrace/src/sys/i386/i386/trap.c#24 edit .. //depot/projects/dtrace/src/sys/sys/dtrace_bsd.h#4 edit Differences ... ==== //depot/projects/dtrace/src/sys/amd64/amd64/trap.c#19 (text+ko) ==== @@ -49,6 +49,7 @@ #include "opt_hwpmc_hooks.h" #include "opt_isa.h" #include "opt_kdb.h" +#include "opt_kdtrace.h" #include "opt_ktrace.h" #include @@ -94,6 +95,24 @@ #endif #include +#ifdef KDTRACE_HOOKS +#include + +/* + * This is a hook which is initialised by the dtrace module + * to handle traps which might occur during DTrace probe + * execution. + */ +dtrace_trap_func_t dtrace_trap_func; + +/* + * This is a hook which is initialised by the systrace module + * when it is loaded. This keeps the DTrace syscall provider + * implementation opaque. + */ +systrace_probe_func_t systrace_probe_func; +#endif + extern void trap(struct trapframe *frame); extern void syscall(struct trapframe *frame); void dblfault_handler(struct trapframe *frame); @@ -199,6 +218,24 @@ goto out; #endif +#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 it's per-cpu flags to indicate that it doesn't + * want to fault. On returning from the the probe, the no-fault + * flag is cleared and finally re-scheduling is enabled. + * + * If the DTrace kernel module has registered a trap handler, + * call it and if it returns non-zero, assume that it has + * handled the trap and modified the trap frame so that this + * function can return normally. + */ + if (dtrace_trap_func != NULL) + if ((*dtrace_trap_func)(frame)) + goto out; +#endif + if ((frame->tf_rflags & PSL_I) == 0) { /* * Buggy application or kernel code has disabled @@ -847,9 +884,35 @@ PTRACESTOP_SC(p, td, S_PT_SCE); +#ifdef KDTRACE_HOOKS + /* + * If the systrace module has registered it's probe + * callback and if there is a probe active for the + * syscall 'entry', process the probe. + */ + if (systrace_probe_func != NULL && callp->sy_entry != 0) + (*systrace_probe_func)(callp->sy_entry, code, callp, + args); +#endif + AUDIT_SYSCALL_ENTER(code, td); error = (*callp->sy_call)(td, argp); AUDIT_SYSCALL_EXIT(error, td); + +#ifdef KDTRACE_HOOKS + /* Save the error return variable for DTrace to reference. */ + args[0] = error; + args[1] = error; + + /* + * If the systrace module has registered it's probe + * callback and if there is a probe active for the + * syscall 'return', process the probe. + */ + if (systrace_probe_func != NULL && callp->sy_return != 0) + (*systrace_probe_func)(callp->sy_return, code, callp, + args); +#endif } switch (error) { ==== //depot/projects/dtrace/src/sys/i386/i386/trap.c#24 (text+ko) ==== @@ -49,6 +49,7 @@ #include "opt_hwpmc_hooks.h" #include "opt_isa.h" #include "opt_kdb.h" +#include "opt_kdtrace.h" #include "opt_ktrace.h" #include "opt_npx.h" #include "opt_trap.h" @@ -102,6 +103,24 @@ #include #endif +#ifdef KDTRACE_HOOKS +#include + +/* + * This is a hook which is initialised by the dtrace module + * to handle traps which might occur during DTrace probe + * execution. + */ +dtrace_trap_func_t dtrace_trap_func; + +/* + * This is a hook which is initialised by the systrace module + * when it is loaded. This keeps the DTrace syscall provider + * implementation opaque. + */ +systrace_probe_func_t systrace_probe_func; +#endif + extern void trap(struct trapframe *frame); extern void syscall(struct trapframe *frame); @@ -218,6 +237,24 @@ goto out; #endif +#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 it's per-cpu flags to indicate that it doesn't + * want to fault. On returning from the the probe, the no-fault + * flag is cleared and finally re-scheduling is enabled. + * + * If the DTrace kernel module has registered a trap handler, + * call it and if it returns non-zero, assume that it has + * handled the trap and modified the trap frame so that this + * function can return normally. + */ + if (dtrace_trap_func != NULL) + if ((*dtrace_trap_func)(frame)) + goto out; +#endif + if ((frame->tf_eflags & PSL_I) == 0) { /* * Buggy application or kernel code has disabled @@ -1030,9 +1067,35 @@ PTRACESTOP_SC(p, td, S_PT_SCE); +#ifdef KDTRACE_HOOKS + /* + * If the systrace module has registered it's probe + * callback and if there is a probe active for the + * syscall 'entry', process the probe. + */ + if (systrace_probe_func != NULL && callp->sy_entry != 0) + (*systrace_probe_func)(callp->sy_entry, code, callp, + args); +#endif + AUDIT_SYSCALL_ENTER(code, td); error = (*callp->sy_call)(td, args); AUDIT_SYSCALL_EXIT(error, td); + +#ifdef KDTRACE_HOOKS + /* Save the error return variable for DTrace to reference. */ + args[0] = error; + args[1] = error; + + /* + * If the systrace module has registered it's probe + * callback and if there is a probe active for the + * syscall 'return', process the probe. + */ + if (systrace_probe_func != NULL && callp->sy_return != 0) + (*systrace_probe_func)(callp->sy_return, code, callp, + args); +#endif } switch (error) { ==== //depot/projects/dtrace/src/sys/sys/dtrace_bsd.h#4 (text+ko) ==== @@ -37,6 +37,13 @@ */ typedef void (*cyclic_clock_func_t)(void); +/* + * 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. + */ +typedef int (*dtrace_trap_func_t)(struct trapframe *); + /* Used by the machine dependent trap() code. */ typedef int (*dtrace_invop_func_t)(uintptr_t, uintptr_t *, uintptr_t);