From owner-p4-projects@FreeBSD.ORG Sun Nov 5 01:04:47 2006 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id DA14F16A412; Sun, 5 Nov 2006 01:04:46 +0000 (UTC) X-Original-To: perforce@freebsd.org Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 91FA516A407 for ; Sun, 5 Nov 2006 01:04:46 +0000 (UTC) (envelope-from jb@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 5259B43D46 for ; Sun, 5 Nov 2006 01:04:46 +0000 (GMT) (envelope-from jb@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.6/8.13.6) with ESMTP id kA514kaM004885 for ; Sun, 5 Nov 2006 01:04:46 GMT (envelope-from jb@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.6/8.13.4/Submit) id kA514jII004882 for perforce@freebsd.org; Sun, 5 Nov 2006 01:04:45 GMT (envelope-from jb@freebsd.org) Date: Sun, 5 Nov 2006 01:04:45 GMT Message-Id: <200611050104.kA514jII004882@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 109253 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: Sun, 05 Nov 2006 01:04:47 -0000 http://perforce.freebsd.org/chv.cgi?CH=109253 Change 109253 by jb@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 #include #include +#ifdef KDTRACE +#include +#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 @@ -65,6 +66,10 @@ #include #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. */