PERFORCE change 109253 for review
John Birrell
jb at FreeBSD.org
Sun Nov 5 01:04:47 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=109253
Change 109253 by jb at jb_freebsd8 on 2006/11/05 01:04:21
Merge the DTrace code back in.
Affected files ...
.. //depot/projects/dtrace/src/sys/i386/i386/exception.s#9 edit
.. //depot/projects/dtrace/src/sys/i386/i386/local_apic.c#9 edit
Differences ...
==== //depot/projects/dtrace/src/sys/i386/i386/exception.s#9 (text+ko) ====
@@ -30,16 +30,27 @@
* $FreeBSD: src/sys/i386/i386/exception.s,v 1.116 2006/04/04 02:26:45 jkoshy Exp $
*/
+/*
+ * The DTrace parts of this file are:
+ *
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
#include "opt_apic.h"
#include "opt_npx.h"
#include <machine/asmacros.h>
#include <machine/psl.h>
#include <machine/trap.h>
+#ifdef KDTRACE
+#include <machine/dtrace_asm.h>
+#endif
#include "assym.s"
#define SEL_RPL_MASK 0x0003
+#define GSEL_KPL 0x0020 /* GSEL(GCODE_SEL, SEL_KPL) */
.text
@@ -88,8 +99,6 @@
pushl $0; TRAP(T_OFLOW)
IDTVEC(bnd)
pushl $0; TRAP(T_BOUND)
-IDTVEC(ill)
- pushl $0; TRAP(T_PRIVINFLT)
IDTVEC(dna)
pushl $0; TRAP(T_DNA)
IDTVEC(fpusegm)
@@ -144,6 +153,164 @@
jmp doreti
/*
+ * Privileged instruction fault.
+ */
+ SUPERALIGN_TEXT
+IDTVEC(ill)
+#ifdef KDTRACE
+ /*
+ * DTrace uses invalid instructions to hook itself into
+ * the executable code. A privileged instruction fault in
+ * kernel code probably is the result of a 'Function Boundary
+ * Tracing' (FBT) or 'Statically Defined Tracing' (SDT)
+ * probe.
+ *
+ * Check if there is an invalid instruction function registered.
+ * (see trap.c for the global variable referenced)
+ */
+ cmpl $0, (dtrace_invop_func)
+
+ /* If not, just handle it as a normal trap. */
+ jz norm_ill
+
+ /* Check if this is a user fault. */
+ cmpl $GSEL_KPL, 4(%esp) /* Check the code segment. */
+
+ /* If so, just handle it as a normal trap. */
+ jne norm_ill
+
+ /*
+ * This is a kernel instruction fault that might have been caused
+ * by a DTrace provider.
+ */
+ pushal /* Push all registers onto the stack. */
+
+ /*
+ * Setup the stack to contain the arguments to:
+ * int dtrace_invop(uintptr_t addr, uintptr_t *stack, uintptr_t eax);
+ */
+ pushl %eax /* Push %eax -- may contain the return value. */
+ pushl %esp /* Push the stack pointer. */
+ addl $48, (%esp) /* Adjust to incoming args. */
+ pushl 40(%esp) /* Push the calling EIP. */
+
+ /* Call the registered function (dtrace_invop). */
+ call *dtrace_invop_func /* Call the registered function. */
+
+ALTENTRY(dtrace_invop_callsite)
+ /*
+ * Drop the arguments to dtrace_invop from the stack, leaving
+ * the registers.
+ */
+ addl $12, %esp
+
+ /* Process according to the return value from dtrace_invop. */
+ cmpl $DTRACE_INVOP_PUSHL_EBP, %eax
+ je __dtrace_invop_pushl_ebp
+ cmpl $DTRACE_INVOP_POPL_EBP, %eax
+ je __dtrace_invop_popl_ebp
+ cmpl $DTRACE_INVOP_LEAVE, %eax
+ je __dtrace_invop_leave
+ cmpl $DTRACE_INVOP_NOP, %eax
+ je __dtrace_invop_nop
+
+ /*
+ * The registered DTrace invalid instruction functions didn't
+ * match the fault address to a probe, so process the trap in
+ * the normal way.
+ &/
+ * normal way because the registered DTrace invalid instruction
+ * functions didn't match it to a probe.
+ */
+ jmp norm_ill
+
+ /* case DTRACE_INVOP_PUSHL_EBP: */
+__dtrace_invop_pushl_ebp:
+ /*
+ * We must emulate a "pushl %ebp". To do this, we pull the stack
+ * down 4 bytes, and then store the base pointer.
+ */
+ popal
+ subl $4, %esp /* make room for %ebp */
+ pushl %eax /* push temp */
+ movl 8(%esp), %eax /* load calling EIP */
+ incl %eax /* increment over LOCK prefix */
+ movl %eax, 4(%esp) /* store calling EIP */
+ movl 12(%esp), %eax /* load calling CS */
+ movl %eax, 8(%esp) /* store calling CS */
+ movl 16(%esp), %eax /* load calling EFLAGS */
+ movl %eax, 12(%esp) /* store calling EFLAGS */
+ movl %ebp, 16(%esp) /* push %ebp */
+ popl %eax /* pop off temp */
+ iret /* return from interrupt */
+
+ /* case DTRACE_INVOP_POPL_EBP: */
+__dtrace_invop_popl_ebp:
+ /*
+ * We must emulate a "popl %ebp". To do this, we do the opposite of
+ * the above: we remove the %ebp from the stack, and squeeze up the
+ * saved state from the trap.
+ */
+ popal
+ pushl %eax /* push temp */
+ movl 16(%esp), %ebp /* pop %ebp */
+ movl 12(%esp), %eax /* load calling EFLAGS */
+ movl %eax, 16(%esp) /* store calling EFLAGS */
+ movl 8(%esp), %eax /* load calling CS */
+ movl %eax, 12(%esp) /* store calling CS */
+ movl 4(%esp), %eax /* load calling EIP */
+ incl %eax /* increment over LOCK prefix */
+ movl %eax, 8(%esp) /* store calling EIP */
+ popl %eax /* pop off temp */
+ addl $4, %esp /* adjust stack pointer */
+ iret /* return from interrupt */
+
+ /* case DTRACE_INVOP_LEAVE: */
+__dtrace_invop_leave:
+ /*
+ * We must emulate a "leave", which is the same as a "movl %ebp, %esp"
+ * followed by a "popl %ebp". This looks similar to the above, but
+ * requires two temporaries: one for the new base pointer, and one
+ * for the staging register.
+ */
+ popal
+ pushl %eax /* push temp */
+ pushl %ebx /* push temp */
+ movl %ebp, %ebx /* set temp to old %ebp */
+ movl (%ebx), %ebp /* pop %ebp */
+ movl 16(%esp), %eax /* load calling EFLAGS */
+ movl %eax, (%ebx) /* store calling EFLAGS */
+ movl 12(%esp), %eax /* load calling CS */
+ movl %eax, -4(%ebx) /* store calling CS */
+ movl 8(%esp), %eax /* load calling EIP */
+ incl %eax /* increment over LOCK prefix */
+ movl %eax, -8(%ebx) /* store calling EIP */
+ movl %ebx, -4(%esp) /* temporarily store new %esp */
+ popl %ebx /* pop off temp */
+ popl %eax /* pop off temp */
+ movl -12(%esp), %esp /* set stack pointer */
+ subl $8, %esp /* adjust for three pushes, one pop */
+ iret /* return from interrupt */
+
+ /* case DTRACE_INVOP_NOP: */
+__dtrace_invop_nop:
+ /*
+ * We must emulate a "nop". This is obviously not hard: we need only
+ * advance the %eip by one.
+ */
+ popal
+ incl (%esp)
+ iret
+
+norm_ill:
+#endif
+ /*
+ * Process the instruction fault in the normal way.
+ */
+ pushl $0
+ TRAP(T_PRIVINFLT)
+
+/*
* SYSCALL CALL GATE (old entry point for a.out binaries)
*
* The intersegment call has been set up to specify one dummy parameter.
==== //depot/projects/dtrace/src/sys/i386/i386/local_apic.c#9 (text+ko) ====
@@ -36,6 +36,7 @@
#include "opt_hwpmc_hooks.h"
+#include "opt_cyclic.h"
#include "opt_ddb.h"
#include <sys/param.h>
@@ -65,6 +66,10 @@
#include <ddb/ddb.h>
#endif
+#if defined(CYCLIC) || defined(KDTRACE)
+cyclic_clock_func_t lapic_cyclic_clock_func;
+#endif
+
/*
* We can handle up to 60 APICs via our logical cluster IDs, but currently
* the physical IDs on Intel processors up to the Pentium 4 are limited to
@@ -659,6 +664,19 @@
hardclock(TRAPF_USERMODE(&frame), TRAPF_PC(&frame));
else
hardclock_cpu(TRAPF_USERMODE(&frame));
+
+ /*
+ * If the cyclic subsystem is configured and a callback
+ * function has been registered, then call it to process
+ * the high speed timers. If this function is registered
+ * here, then there mustn't be a High Performance Event
+ * Timer (HPET) on the CPU. A HPET provides higher
+ * performance timer interrupts.
+ */
+#if defined(CYCLIC) || defined(KDTRACE)
+ if (lapic_cyclic_clock_func != NULL)
+ (*lapic_cyclic_clock_func)();
+#endif
}
/* Fire statclock at stathz. */
More information about the p4-projects
mailing list