From owner-p4-projects@FreeBSD.ORG Sun Feb 10 20:12:37 2008 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id C301116A523; Sun, 10 Feb 2008 20:12:36 +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 66BE616A421 for ; Sun, 10 Feb 2008 20:12:36 +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 7257813C4FF for ; Sun, 10 Feb 2008 20:12:36 +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 m1AKCaqs070975 for ; Sun, 10 Feb 2008 20:12:36 GMT (envelope-from jb@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.1/8.14.1/Submit) id m1AKCaGK070971 for perforce@freebsd.org; Sun, 10 Feb 2008 20:12:36 GMT (envelope-from jb@freebsd.org) Date: Sun, 10 Feb 2008 20:12:36 GMT Message-Id: <200802102012.m1AKCaGK070971@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 135169 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, 10 Feb 2008 20:12:37 -0000 http://perforce.freebsd.org/chv.cgi?CH=135169 Change 135169 by jb@jb_freebsd1 on 2008/02/10 20:12:28 Add the fbt exception handling code. Affected files ... .. //depot/projects/dtrace/src/sys/cddl/dev/dtrace/i386/dtrace_asm.S#6 edit .. //depot/projects/dtrace/src/sys/i386/i386/exception.s#14 edit Differences ... ==== //depot/projects/dtrace/src/sys/cddl/dev/dtrace/i386/dtrace_asm.S#6 (text+ko) ==== @@ -30,11 +30,120 @@ #include #include +#include "assym.s" + + .globl calltrap + .type calltrap,@function + ENTRY(dtrace_invop_start) + + pushl %eax /* push %eax -- may be return value */ + pushl %esp /* push stack pointer */ + addl $48, (%esp) /* adjust to incoming args */ + pushl 40(%esp) /* push calling EIP */ + + /* + * Call dtrace_invop to let it check if the exception was + * a fbt one. The return value in %eax will tell us what + * dtrace_invop wants us to do. + */ + call dtrace_invop + + /* + * We pushed 3 times for the arguments to dtrace_invop, + * so we need to increment the stack pointer to get rid of + * those values. + */ + addl $12, %esp + cmpl $DTRACE_INVOP_PUSHL_EBP, %eax + je invop_push + cmpl $DTRACE_INVOP_POPL_EBP, %eax + je invop_pop + cmpl $DTRACE_INVOP_LEAVE, %eax + je invop_leave + cmpl $DTRACE_INVOP_NOP, %eax + je invop_nop + + /* When all else fails handle the trap in the usual way. */ + jmpl *dtrace_invop_calltrap_addr + +invop_push: + /* + * 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. */ +invop_pop: + /* + * 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. */ +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. + */ + popa + 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 */ +invop_nop: + /* + * We must emulate a "nop". This is obviously not hard: we need only + * advance the %eip by one. + */ + popa + incl (%esp) + iret /* return from interrupt */ + + END(dtrace_invop_start) + /* void dtrace_invop_init(void) */ ENTRY(dtrace_invop_init) - /* XXX */ + movl $dtrace_invop_start, dtrace_invop_jump_addr ret END(dtrace_invop_init) @@ -42,7 +151,7 @@ void dtrace_invop_uninit(void) */ ENTRY(dtrace_invop_uninit) - /* XXX */ + movl $0, dtrace_invop_jump_addr ret END(dtrace_invop_uninit) ==== //depot/projects/dtrace/src/sys/i386/i386/exception.s#14 (text+ko) ==== @@ -36,6 +36,7 @@ #include "opt_apic.h" #include "opt_hwpmc_hooks.h" +#include "opt_kdtrace.h" #include "opt_npx.h" #include @@ -45,7 +46,23 @@ #include "assym.s" #define SEL_RPL_MASK 0x0003 +#define GSEL_KPL 0x0020 /* GSEL(GCODE_SEL, SEL_KPL) */ +#ifdef KDTRACE_HOOKS + .bss + .globl dtrace_invop_jump_addr + .align 4 + .type dtrace_invop_jump_addr, @object + .size dtrace_invop_jump_addr, 4 +dtrace_invop_jump_addr: + .zero 4 + .globl dtrace_invop_calltrap_addr + .align 4 + .type dtrace_invop_calltrap_addr, @object + .size dtrace_invop_calltrap_addr, 4 +dtrace_invop_calltrap_addr: + .zero 8 +#endif .text #ifdef HWPMC_HOOKS ENTRY(start_exceptions) @@ -95,8 +112,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) @@ -153,6 +168,43 @@ jmp doreti /* + * Privileged instruction fault. + */ + SUPERALIGN_TEXT +IDTVEC(ill) + /* Check if there is no DTrace hook registered. */ + cmpl $0,dtrace_invop_jump_addr + je 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. */ + + /* + * Set our jump address for the jump back in the event that + * the exception wasn't caused by DTrace at all. + */ + movl $norm_ill, dtrace_invop_calltrap_addr + + /* Jump to the code hooked in by DTrace. */ + jmpl *dtrace_invop_jump_addr + + /* + * Process the instruction fault in the normal way. + */ +norm_ill: + 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.