191eaf3e1SJohn Birrell/* 291eaf3e1SJohn Birrell * CDDL HEADER START 391eaf3e1SJohn Birrell * 491eaf3e1SJohn Birrell * The contents of this file are subject to the terms of the 591eaf3e1SJohn Birrell * Common Development and Distribution License, Version 1.0 only 691eaf3e1SJohn Birrell * (the "License"). You may not use this file except in compliance 791eaf3e1SJohn Birrell * with the License. 891eaf3e1SJohn Birrell * 991eaf3e1SJohn Birrell * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 1091eaf3e1SJohn Birrell * or http://www.opensolaris.org/os/licensing. 1191eaf3e1SJohn Birrell * See the License for the specific language governing permissions 1291eaf3e1SJohn Birrell * and limitations under the License. 1391eaf3e1SJohn Birrell * 1491eaf3e1SJohn Birrell * When distributing Covered Code, include this CDDL HEADER in each 1591eaf3e1SJohn Birrell * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1691eaf3e1SJohn Birrell * If applicable, add the following below this CDDL HEADER, with the 1791eaf3e1SJohn Birrell * fields enclosed by brackets "[]" replaced with your own identifying 1891eaf3e1SJohn Birrell * information: Portions Copyright [yyyy] [name of copyright owner] 1991eaf3e1SJohn Birrell * 2091eaf3e1SJohn Birrell * CDDL HEADER END 2191eaf3e1SJohn Birrell * 2291eaf3e1SJohn Birrell * $FreeBSD$ 2391eaf3e1SJohn Birrell */ 2491eaf3e1SJohn Birrell/* 2591eaf3e1SJohn Birrell * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 2691eaf3e1SJohn Birrell * Use is subject to license terms. 2791eaf3e1SJohn Birrell */ 2891eaf3e1SJohn Birrell 2991eaf3e1SJohn Birrell#define _ASM 3091eaf3e1SJohn Birrell 3191eaf3e1SJohn Birrell#include <machine/asmacros.h> 3291eaf3e1SJohn Birrell#include <sys/cpuvar_defs.h> 3391eaf3e1SJohn Birrell#include <sys/dtrace.h> 3491eaf3e1SJohn Birrell 3591eaf3e1SJohn Birrell#include "assym.s" 3691eaf3e1SJohn Birrell 3791eaf3e1SJohn Birrell .globl calltrap 3891eaf3e1SJohn Birrell .type calltrap,@function 3991eaf3e1SJohn Birrell ENTRY(dtrace_invop_start) 4091eaf3e1SJohn Birrell 4191eaf3e1SJohn Birrell pushl %eax /* push %eax -- may be return value */ 4291eaf3e1SJohn Birrell pushl %esp /* push stack pointer */ 4391eaf3e1SJohn Birrell addl $48, (%esp) /* adjust to incoming args */ 4491eaf3e1SJohn Birrell pushl 40(%esp) /* push calling EIP */ 4591eaf3e1SJohn Birrell 4691eaf3e1SJohn Birrell /* 4791eaf3e1SJohn Birrell * Call dtrace_invop to let it check if the exception was 4891eaf3e1SJohn Birrell * a fbt one. The return value in %eax will tell us what 4991eaf3e1SJohn Birrell * dtrace_invop wants us to do. 5091eaf3e1SJohn Birrell */ 5191eaf3e1SJohn Birrell call dtrace_invop 5291eaf3e1SJohn Birrell 5391eaf3e1SJohn Birrell /* 5491eaf3e1SJohn Birrell * We pushed 3 times for the arguments to dtrace_invop, 5591eaf3e1SJohn Birrell * so we need to increment the stack pointer to get rid of 5691eaf3e1SJohn Birrell * those values. 5791eaf3e1SJohn Birrell */ 5891eaf3e1SJohn Birrell addl $12, %esp 5991eaf3e1SJohn Birrell ALTENTRY(dtrace_invop_callsite) 6091eaf3e1SJohn Birrell cmpl $DTRACE_INVOP_PUSHL_EBP, %eax 6191eaf3e1SJohn Birrell je invop_push 6291eaf3e1SJohn Birrell cmpl $DTRACE_INVOP_POPL_EBP, %eax 6391eaf3e1SJohn Birrell je invop_pop 6491eaf3e1SJohn Birrell cmpl $DTRACE_INVOP_LEAVE, %eax 6591eaf3e1SJohn Birrell je invop_leave 6691eaf3e1SJohn Birrell cmpl $DTRACE_INVOP_NOP, %eax 6791eaf3e1SJohn Birrell je invop_nop 6891eaf3e1SJohn Birrell 6991eaf3e1SJohn Birrell /* When all else fails handle the trap in the usual way. */ 7091eaf3e1SJohn Birrell jmpl *dtrace_invop_calltrap_addr 7191eaf3e1SJohn Birrell 7291eaf3e1SJohn Birrellinvop_push: 7391eaf3e1SJohn Birrell /* 7491eaf3e1SJohn Birrell * We must emulate a "pushl %ebp". To do this, we pull the stack 7591eaf3e1SJohn Birrell * down 4 bytes, and then store the base pointer. 7691eaf3e1SJohn Birrell */ 7791eaf3e1SJohn Birrell popal 7891eaf3e1SJohn Birrell subl $4, %esp /* make room for %ebp */ 7991eaf3e1SJohn Birrell pushl %eax /* push temp */ 8091eaf3e1SJohn Birrell movl 8(%esp), %eax /* load calling EIP */ 8191eaf3e1SJohn Birrell incl %eax /* increment over LOCK prefix */ 8291eaf3e1SJohn Birrell movl %eax, 4(%esp) /* store calling EIP */ 8391eaf3e1SJohn Birrell movl 12(%esp), %eax /* load calling CS */ 8491eaf3e1SJohn Birrell movl %eax, 8(%esp) /* store calling CS */ 8591eaf3e1SJohn Birrell movl 16(%esp), %eax /* load calling EFLAGS */ 8691eaf3e1SJohn Birrell movl %eax, 12(%esp) /* store calling EFLAGS */ 8791eaf3e1SJohn Birrell movl %ebp, 16(%esp) /* push %ebp */ 8891eaf3e1SJohn Birrell popl %eax /* pop off temp */ 8991eaf3e1SJohn Birrell iret /* Return from interrupt. */ 9091eaf3e1SJohn Birrellinvop_pop: 9191eaf3e1SJohn Birrell /* 9291eaf3e1SJohn Birrell * We must emulate a "popl %ebp". To do this, we do the opposite of 9391eaf3e1SJohn Birrell * the above: we remove the %ebp from the stack, and squeeze up the 9491eaf3e1SJohn Birrell * saved state from the trap. 9591eaf3e1SJohn Birrell */ 9691eaf3e1SJohn Birrell popal 9791eaf3e1SJohn Birrell pushl %eax /* push temp */ 9891eaf3e1SJohn Birrell movl 16(%esp), %ebp /* pop %ebp */ 9991eaf3e1SJohn Birrell movl 12(%esp), %eax /* load calling EFLAGS */ 10091eaf3e1SJohn Birrell movl %eax, 16(%esp) /* store calling EFLAGS */ 10191eaf3e1SJohn Birrell movl 8(%esp), %eax /* load calling CS */ 10291eaf3e1SJohn Birrell movl %eax, 12(%esp) /* store calling CS */ 10391eaf3e1SJohn Birrell movl 4(%esp), %eax /* load calling EIP */ 10491eaf3e1SJohn Birrell incl %eax /* increment over LOCK prefix */ 10591eaf3e1SJohn Birrell movl %eax, 8(%esp) /* store calling EIP */ 10691eaf3e1SJohn Birrell popl %eax /* pop off temp */ 10791eaf3e1SJohn Birrell addl $4, %esp /* adjust stack pointer */ 10891eaf3e1SJohn Birrell iret /* Return from interrupt. */ 10991eaf3e1SJohn Birrellinvop_leave: 11091eaf3e1SJohn Birrell /* 11191eaf3e1SJohn Birrell * We must emulate a "leave", which is the same as a "movl %ebp, %esp" 11291eaf3e1SJohn Birrell * followed by a "popl %ebp". This looks similar to the above, but 11391eaf3e1SJohn Birrell * requires two temporaries: one for the new base pointer, and one 11491eaf3e1SJohn Birrell * for the staging register. 11591eaf3e1SJohn Birrell */ 11691eaf3e1SJohn Birrell popa 11791eaf3e1SJohn Birrell pushl %eax /* push temp */ 11891eaf3e1SJohn Birrell pushl %ebx /* push temp */ 11991eaf3e1SJohn Birrell movl %ebp, %ebx /* set temp to old %ebp */ 12091eaf3e1SJohn Birrell movl (%ebx), %ebp /* pop %ebp */ 12191eaf3e1SJohn Birrell movl 16(%esp), %eax /* load calling EFLAGS */ 12291eaf3e1SJohn Birrell movl %eax, (%ebx) /* store calling EFLAGS */ 12391eaf3e1SJohn Birrell movl 12(%esp), %eax /* load calling CS */ 12491eaf3e1SJohn Birrell movl %eax, -4(%ebx) /* store calling CS */ 12591eaf3e1SJohn Birrell movl 8(%esp), %eax /* load calling EIP */ 12691eaf3e1SJohn Birrell incl %eax /* increment over LOCK prefix */ 12791eaf3e1SJohn Birrell movl %eax, -8(%ebx) /* store calling EIP */ 12891eaf3e1SJohn Birrell movl %ebx, -4(%esp) /* temporarily store new %esp */ 12991eaf3e1SJohn Birrell popl %ebx /* pop off temp */ 13091eaf3e1SJohn Birrell popl %eax /* pop off temp */ 13191eaf3e1SJohn Birrell movl -12(%esp), %esp /* set stack pointer */ 13291eaf3e1SJohn Birrell subl $8, %esp /* adjust for three pushes, one pop */ 13391eaf3e1SJohn Birrell iret /* return from interrupt */ 13491eaf3e1SJohn Birrellinvop_nop: 13591eaf3e1SJohn Birrell /* 13691eaf3e1SJohn Birrell * We must emulate a "nop". This is obviously not hard: we need only 13791eaf3e1SJohn Birrell * advance the %eip by one. 13891eaf3e1SJohn Birrell */ 13991eaf3e1SJohn Birrell popa 14091eaf3e1SJohn Birrell incl (%esp) 14191eaf3e1SJohn Birrell iret /* return from interrupt */ 14291eaf3e1SJohn Birrell 14391eaf3e1SJohn Birrell END(dtrace_invop_start) 14491eaf3e1SJohn Birrell 14591eaf3e1SJohn Birrell/* 14691eaf3e1SJohn Birrellvoid dtrace_invop_init(void) 14791eaf3e1SJohn Birrell*/ 14891eaf3e1SJohn Birrell ENTRY(dtrace_invop_init) 14991eaf3e1SJohn Birrell movl $dtrace_invop_start, dtrace_invop_jump_addr 15091eaf3e1SJohn Birrell ret 15191eaf3e1SJohn Birrell END(dtrace_invop_init) 15291eaf3e1SJohn Birrell 15391eaf3e1SJohn Birrell/* 15491eaf3e1SJohn Birrellvoid dtrace_invop_uninit(void) 15591eaf3e1SJohn Birrell*/ 15691eaf3e1SJohn Birrell ENTRY(dtrace_invop_uninit) 15791eaf3e1SJohn Birrell movl $0, dtrace_invop_jump_addr 15891eaf3e1SJohn Birrell ret 15991eaf3e1SJohn Birrell END(dtrace_invop_uninit) 16091eaf3e1SJohn Birrell 16191eaf3e1SJohn Birrell/* 16291eaf3e1SJohn Birrellgreg_t dtrace_getfp(void) 16391eaf3e1SJohn Birrell*/ 16491eaf3e1SJohn Birrell 16591eaf3e1SJohn Birrell ENTRY(dtrace_getfp) 16691eaf3e1SJohn Birrell movl %ebp, %eax 16791eaf3e1SJohn Birrell ret 16891eaf3e1SJohn Birrell END(dtrace_getfp) 16991eaf3e1SJohn Birrell 17091eaf3e1SJohn Birrell/* 17191eaf3e1SJohn Birrelluint32_t dtrace_cas32(uint32_t *target, uint32_t cmp, uint32_t new) 17291eaf3e1SJohn Birrell*/ 17391eaf3e1SJohn Birrell 17491eaf3e1SJohn Birrell ENTRY(dtrace_cas32) 17591eaf3e1SJohn Birrell ALTENTRY(dtrace_casptr) 17691eaf3e1SJohn Birrell movl 4(%esp), %edx 17791eaf3e1SJohn Birrell movl 8(%esp), %eax 17891eaf3e1SJohn Birrell movl 12(%esp), %ecx 17991eaf3e1SJohn Birrell lock 18091eaf3e1SJohn Birrell cmpxchgl %ecx, (%edx) 18191eaf3e1SJohn Birrell ret 18291eaf3e1SJohn Birrell END(dtrace_casptr) 18391eaf3e1SJohn Birrell END(dtrace_cas32) 18491eaf3e1SJohn Birrell 18591eaf3e1SJohn Birrell/* 18691eaf3e1SJohn Birrelluintptr_t dtrace_caller(int aframes) 18791eaf3e1SJohn Birrell*/ 18891eaf3e1SJohn Birrell 18991eaf3e1SJohn Birrell ENTRY(dtrace_caller) 19091eaf3e1SJohn Birrell movl $-1, %eax 19191eaf3e1SJohn Birrell ret 19291eaf3e1SJohn Birrell END(dtrace_caller) 19391eaf3e1SJohn Birrell 19491eaf3e1SJohn Birrell/* 19591eaf3e1SJohn Birrellvoid dtrace_copy(uintptr_t src, uintptr_t dest, size_t size) 19691eaf3e1SJohn Birrell*/ 19791eaf3e1SJohn Birrell 19891eaf3e1SJohn Birrell ENTRY(dtrace_copy) 19991eaf3e1SJohn Birrell pushl %ebp 20091eaf3e1SJohn Birrell movl %esp, %ebp 20191eaf3e1SJohn Birrell pushl %esi 20291eaf3e1SJohn Birrell pushl %edi 20391eaf3e1SJohn Birrell 20491eaf3e1SJohn Birrell movl 8(%ebp), %esi /* Load source address */ 20591eaf3e1SJohn Birrell movl 12(%ebp), %edi /* Load destination address */ 20691eaf3e1SJohn Birrell movl 16(%ebp), %ecx /* Load count */ 20791eaf3e1SJohn Birrell repz /* Repeat for count... */ 20891eaf3e1SJohn Birrell smovb /* move from %ds:si to %es:di */ 20991eaf3e1SJohn Birrell 21091eaf3e1SJohn Birrell popl %edi 21191eaf3e1SJohn Birrell popl %esi 21291eaf3e1SJohn Birrell movl %ebp, %esp 21391eaf3e1SJohn Birrell popl %ebp 21491eaf3e1SJohn Birrell ret 21591eaf3e1SJohn Birrell END(dtrace_copy) 21691eaf3e1SJohn Birrell 21791eaf3e1SJohn Birrell/* 21891eaf3e1SJohn Birrellvoid dtrace_copystr(uintptr_t uaddr, uintptr_t kaddr, size_t size) 21991eaf3e1SJohn Birrell*/ 22091eaf3e1SJohn Birrell 22191eaf3e1SJohn Birrell ENTRY(dtrace_copystr) 22291eaf3e1SJohn Birrell 22391eaf3e1SJohn Birrell pushl %ebp /* Setup stack frame */ 22491eaf3e1SJohn Birrell movl %esp, %ebp 22591eaf3e1SJohn Birrell pushl %ebx /* Save registers */ 22691eaf3e1SJohn Birrell 22791eaf3e1SJohn Birrell movl 8(%ebp), %ebx /* Load source address */ 22891eaf3e1SJohn Birrell movl 12(%ebp), %edx /* Load destination address */ 22991eaf3e1SJohn Birrell movl 16(%ebp), %ecx /* Load count */ 23091eaf3e1SJohn Birrell 23191eaf3e1SJohn Birrell0: 23291eaf3e1SJohn Birrell movb (%ebx), %al /* Load from source */ 23391eaf3e1SJohn Birrell movb %al, (%edx) /* Store to destination */ 23491eaf3e1SJohn Birrell incl %ebx /* Increment source pointer */ 23591eaf3e1SJohn Birrell incl %edx /* Increment destination pointer */ 23691eaf3e1SJohn Birrell decl %ecx /* Decrement remaining count */ 23791eaf3e1SJohn Birrell cmpb $0, %al 23891eaf3e1SJohn Birrell je 1f 23991eaf3e1SJohn Birrell cmpl $0, %ecx 24091eaf3e1SJohn Birrell jne 0b 24191eaf3e1SJohn Birrell 24291eaf3e1SJohn Birrell1: 24391eaf3e1SJohn Birrell popl %ebx 24491eaf3e1SJohn Birrell movl %ebp, %esp 24591eaf3e1SJohn Birrell popl %ebp 24691eaf3e1SJohn Birrell ret 24791eaf3e1SJohn Birrell 24891eaf3e1SJohn Birrell END(dtrace_copystr) 24991eaf3e1SJohn Birrell 25091eaf3e1SJohn Birrell/* 25191eaf3e1SJohn Birrelluintptr_t dtrace_fulword(void *addr) 25291eaf3e1SJohn Birrell*/ 25391eaf3e1SJohn Birrell 25491eaf3e1SJohn Birrell ENTRY(dtrace_fulword) 25591eaf3e1SJohn Birrell movl 4(%esp), %ecx 25691eaf3e1SJohn Birrell xorl %eax, %eax 25791eaf3e1SJohn Birrell movl (%ecx), %eax 25891eaf3e1SJohn Birrell ret 25991eaf3e1SJohn Birrell END(dtrace_fulword) 26091eaf3e1SJohn Birrell 26191eaf3e1SJohn Birrell/* 26291eaf3e1SJohn Birrelluint8_t dtrace_fuword8_nocheck(void *addr) 26391eaf3e1SJohn Birrell*/ 26491eaf3e1SJohn Birrell 26591eaf3e1SJohn Birrell ENTRY(dtrace_fuword8_nocheck) 26691eaf3e1SJohn Birrell movl 4(%esp), %ecx 26791eaf3e1SJohn Birrell xorl %eax, %eax 26891eaf3e1SJohn Birrell movzbl (%ecx), %eax 26991eaf3e1SJohn Birrell ret 27091eaf3e1SJohn Birrell END(dtrace_fuword8_nocheck) 27191eaf3e1SJohn Birrell 27291eaf3e1SJohn Birrell/* 27391eaf3e1SJohn Birrelluint16_t dtrace_fuword16_nocheck(void *addr) 27491eaf3e1SJohn Birrell*/ 27591eaf3e1SJohn Birrell 27691eaf3e1SJohn Birrell ENTRY(dtrace_fuword16_nocheck) 27791eaf3e1SJohn Birrell movl 4(%esp), %ecx 27891eaf3e1SJohn Birrell xorl %eax, %eax 27991eaf3e1SJohn Birrell movzwl (%ecx), %eax 28091eaf3e1SJohn Birrell ret 28191eaf3e1SJohn Birrell END(dtrace_fuword16_nocheck) 28291eaf3e1SJohn Birrell 28391eaf3e1SJohn Birrell/* 28491eaf3e1SJohn Birrelluint32_t dtrace_fuword32_nocheck(void *addr) 28591eaf3e1SJohn Birrell*/ 28691eaf3e1SJohn Birrell 28791eaf3e1SJohn Birrell ENTRY(dtrace_fuword32_nocheck) 28891eaf3e1SJohn Birrell movl 4(%esp), %ecx 28991eaf3e1SJohn Birrell xorl %eax, %eax 29091eaf3e1SJohn Birrell movl (%ecx), %eax 29191eaf3e1SJohn Birrell ret 29291eaf3e1SJohn Birrell END(dtrace_fuword32_nocheck) 29391eaf3e1SJohn Birrell 29491eaf3e1SJohn Birrell/* 29591eaf3e1SJohn Birrelluint64_t dtrace_fuword64_nocheck(void *addr) 29691eaf3e1SJohn Birrell*/ 29791eaf3e1SJohn Birrell 29891eaf3e1SJohn Birrell ENTRY(dtrace_fuword64_nocheck) 29991eaf3e1SJohn Birrell movl 4(%esp), %ecx 30091eaf3e1SJohn Birrell xorl %eax, %eax 30191eaf3e1SJohn Birrell xorl %edx, %edx 30291eaf3e1SJohn Birrell movl (%ecx), %eax 30391eaf3e1SJohn Birrell movl 4(%ecx), %edx 30491eaf3e1SJohn Birrell ret 30591eaf3e1SJohn Birrell END(dtrace_fuword64_nocheck) 30691eaf3e1SJohn Birrell 30791eaf3e1SJohn Birrell/* 30891eaf3e1SJohn Birrellvoid dtrace_probe_error(dtrace_state_t *state, dtrace_epid_t epid, int which, int fault, int fltoffs, uintptr_t illval) 30991eaf3e1SJohn Birrell*/ 31091eaf3e1SJohn Birrell 31191eaf3e1SJohn Birrell ENTRY(dtrace_probe_error) 31291eaf3e1SJohn Birrell pushl %ebp 31391eaf3e1SJohn Birrell movl %esp, %ebp 31491eaf3e1SJohn Birrell pushl 0x1c(%ebp) 31591eaf3e1SJohn Birrell pushl 0x18(%ebp) 31691eaf3e1SJohn Birrell pushl 0x14(%ebp) 31791eaf3e1SJohn Birrell pushl 0x10(%ebp) 31891eaf3e1SJohn Birrell pushl 0xc(%ebp) 31991eaf3e1SJohn Birrell pushl 0x8(%ebp) 32091eaf3e1SJohn Birrell pushl dtrace_probeid_error 32191eaf3e1SJohn Birrell call dtrace_probe 32291eaf3e1SJohn Birrell movl %ebp, %esp 32391eaf3e1SJohn Birrell popl %ebp 32491eaf3e1SJohn Birrell ret 32591eaf3e1SJohn Birrell END(dtrace_probe_error) 32691eaf3e1SJohn Birrell 32791eaf3e1SJohn Birrell/* 32891eaf3e1SJohn Birrellvoid dtrace_membar_producer(void) 32991eaf3e1SJohn Birrell*/ 33091eaf3e1SJohn Birrell 33191eaf3e1SJohn Birrell ENTRY(dtrace_membar_producer) 33291eaf3e1SJohn Birrell rep; ret /* use 2 byte return instruction when branch target */ 33391eaf3e1SJohn Birrell /* AMD Software Optimization Guide - Section 6.2 */ 33491eaf3e1SJohn Birrell END(dtrace_membar_producer) 33591eaf3e1SJohn Birrell 33691eaf3e1SJohn Birrell/* 33791eaf3e1SJohn Birrellvoid dtrace_membar_consumer(void) 33891eaf3e1SJohn Birrell*/ 33991eaf3e1SJohn Birrell 34091eaf3e1SJohn Birrell ENTRY(dtrace_membar_consumer) 34191eaf3e1SJohn Birrell rep; ret /* use 2 byte return instruction when branch target */ 34291eaf3e1SJohn Birrell /* AMD Software Optimization Guide - Section 6.2 */ 34391eaf3e1SJohn Birrell END(dtrace_membar_consumer) 34491eaf3e1SJohn Birrell 34591eaf3e1SJohn Birrell/* 34691eaf3e1SJohn Birrelldtrace_icookie_t dtrace_interrupt_disable(void) 34791eaf3e1SJohn Birrell*/ 34891eaf3e1SJohn Birrell ENTRY(dtrace_interrupt_disable) 34991eaf3e1SJohn Birrell pushfl 35091eaf3e1SJohn Birrell popl %eax 35191eaf3e1SJohn Birrell cli 35291eaf3e1SJohn Birrell ret 35391eaf3e1SJohn Birrell END(dtrace_interrupt_disable) 35491eaf3e1SJohn Birrell 35591eaf3e1SJohn Birrell/* 35691eaf3e1SJohn Birrellvoid dtrace_interrupt_enable(dtrace_icookie_t cookie) 35791eaf3e1SJohn Birrell*/ 35891eaf3e1SJohn Birrell ENTRY(dtrace_interrupt_enable) 35991eaf3e1SJohn Birrell movl 4(%esp), %eax 36091eaf3e1SJohn Birrell pushl %eax 36191eaf3e1SJohn Birrell popfl 36291eaf3e1SJohn Birrell ret 36391eaf3e1SJohn Birrell END(dtrace_interrupt_enable) 36491eaf3e1SJohn Birrell 36591eaf3e1SJohn Birrell/* 36691eaf3e1SJohn Birrell * The panic() and cmn_err() functions invoke vpanic() as a common entry point 36791eaf3e1SJohn Birrell * into the panic code implemented in panicsys(). vpanic() is responsible 36891eaf3e1SJohn Birrell * for passing through the format string and arguments, and constructing a 36991eaf3e1SJohn Birrell * regs structure on the stack into which it saves the current register 37091eaf3e1SJohn Birrell * values. If we are not dying due to a fatal trap, these registers will 37191eaf3e1SJohn Birrell * then be preserved in panicbuf as the current processor state. Before 37291eaf3e1SJohn Birrell * invoking panicsys(), vpanic() activates the first panic trigger (see 37391eaf3e1SJohn Birrell * common/os/panic.c) and switches to the panic_stack if successful. Note that 37491eaf3e1SJohn Birrell * DTrace takes a slightly different panic path if it must panic from probe 37591eaf3e1SJohn Birrell * context. Instead of calling panic, it calls into dtrace_vpanic(), which 37691eaf3e1SJohn Birrell * sets up the initial stack as vpanic does, calls dtrace_panic_trigger(), and 37791eaf3e1SJohn Birrell * branches back into vpanic(). 37891eaf3e1SJohn Birrell */ 37991eaf3e1SJohn Birrell/* 38091eaf3e1SJohn Birrellvoid vpanic(const char *format, va_list alist) 38191eaf3e1SJohn Birrell*/ 38291eaf3e1SJohn Birrell ENTRY(vpanic) /* Initial stack layout: */ 38391eaf3e1SJohn Birrell 38491eaf3e1SJohn Birrell pushl %ebp /* | %eip | 20 */ 38591eaf3e1SJohn Birrell movl %esp, %ebp /* | %ebp | 16 */ 38691eaf3e1SJohn Birrell pushl %eax /* | %eax | 12 */ 38791eaf3e1SJohn Birrell pushl %ebx /* | %ebx | 8 */ 38891eaf3e1SJohn Birrell pushl %ecx /* | %ecx | 4 */ 38991eaf3e1SJohn Birrell pushl %edx /* | %edx | 0 */ 39091eaf3e1SJohn Birrell 39191eaf3e1SJohn Birrell movl %esp, %ebx /* %ebx = current stack pointer */ 39291eaf3e1SJohn Birrell 39391eaf3e1SJohn Birrell lea panic_quiesce, %eax /* %eax = &panic_quiesce */ 39491eaf3e1SJohn Birrell pushl %eax /* push &panic_quiesce */ 39591eaf3e1SJohn Birrell call panic_trigger /* %eax = panic_trigger() */ 39691eaf3e1SJohn Birrell addl $4, %esp /* reset stack pointer */ 39791eaf3e1SJohn Birrell 39891eaf3e1SJohn Birrellvpanic_common: 39991eaf3e1SJohn Birrell cmpl $0, %eax /* if (%eax == 0) */ 40091eaf3e1SJohn Birrell je 0f /* goto 0f; */ 40191eaf3e1SJohn Birrell 40291eaf3e1SJohn Birrell /* 40391eaf3e1SJohn Birrell * If panic_trigger() was successful, we are the first to initiate a 40491eaf3e1SJohn Birrell * panic: we now switch to the reserved panic_stack before continuing. 40591eaf3e1SJohn Birrell */ 40691eaf3e1SJohn Birrell lea panic_stack, %esp /* %esp = panic_stack */ 40791eaf3e1SJohn Birrell addl $PANICSTKSIZE, %esp /* %esp += PANICSTKSIZE */ 40891eaf3e1SJohn Birrell 40991eaf3e1SJohn Birrell0: subl $REGSIZE, %esp /* allocate struct regs */ 41091eaf3e1SJohn Birrell 41191eaf3e1SJohn Birrell /* 41291eaf3e1SJohn Birrell * Now that we've got everything set up, store the register values as 41391eaf3e1SJohn Birrell * they were when we entered vpanic() to the designated location in 41491eaf3e1SJohn Birrell * the regs structure we allocated on the stack. 41591eaf3e1SJohn Birrell */ 41691eaf3e1SJohn Birrell#ifdef notyet 41791eaf3e1SJohn Birrell mov %gs, %edx 41891eaf3e1SJohn Birrell mov %edx, REGOFF_GS(%esp) 41991eaf3e1SJohn Birrell mov %fs, %edx 42091eaf3e1SJohn Birrell mov %edx, REGOFF_FS(%esp) 42191eaf3e1SJohn Birrell mov %es, %edx 42291eaf3e1SJohn Birrell mov %edx, REGOFF_ES(%esp) 42391eaf3e1SJohn Birrell mov %ds, %edx 42491eaf3e1SJohn Birrell mov %edx, REGOFF_DS(%esp) 42591eaf3e1SJohn Birrell movl %edi, REGOFF_EDI(%esp) 42691eaf3e1SJohn Birrell movl %esi, REGOFF_ESI(%esp) 42791eaf3e1SJohn Birrell movl 16(%ebx), %ecx 42891eaf3e1SJohn Birrell movl %ecx, REGOFF_EBP(%esp) 42991eaf3e1SJohn Birrell movl %ebx, %ecx 43091eaf3e1SJohn Birrell addl $20, %ecx 43191eaf3e1SJohn Birrell movl %ecx, REGOFF_ESP(%esp) 43291eaf3e1SJohn Birrell movl 8(%ebx), %ecx 43391eaf3e1SJohn Birrell movl %ecx, REGOFF_EBX(%esp) 43491eaf3e1SJohn Birrell movl 0(%ebx), %ecx 43591eaf3e1SJohn Birrell movl %ecx, REGOFF_EDX(%esp) 43691eaf3e1SJohn Birrell movl 4(%ebx), %ecx 43791eaf3e1SJohn Birrell movl %ecx, REGOFF_ECX(%esp) 43891eaf3e1SJohn Birrell movl 12(%ebx), %ecx 43991eaf3e1SJohn Birrell movl %ecx, REGOFF_EAX(%esp) 44091eaf3e1SJohn Birrell movl $0, REGOFF_TRAPNO(%esp) 44191eaf3e1SJohn Birrell movl $0, REGOFF_ERR(%esp) 44291eaf3e1SJohn Birrell lea vpanic, %ecx 44391eaf3e1SJohn Birrell movl %ecx, REGOFF_EIP(%esp) 44491eaf3e1SJohn Birrell mov %cs, %edx 44591eaf3e1SJohn Birrell movl %edx, REGOFF_CS(%esp) 44691eaf3e1SJohn Birrell pushfl 44791eaf3e1SJohn Birrell popl %ecx 44891eaf3e1SJohn Birrell movl %ecx, REGOFF_EFL(%esp) 44991eaf3e1SJohn Birrell movl $0, REGOFF_UESP(%esp) 45091eaf3e1SJohn Birrell mov %ss, %edx 45191eaf3e1SJohn Birrell movl %edx, REGOFF_SS(%esp) 45291eaf3e1SJohn Birrell 45391eaf3e1SJohn Birrell movl %esp, %ecx /* %ecx = ®s */ 45491eaf3e1SJohn Birrell pushl %eax /* push on_panic_stack */ 45591eaf3e1SJohn Birrell pushl %ecx /* push ®s */ 45691eaf3e1SJohn Birrell movl 12(%ebp), %ecx /* %ecx = alist */ 45791eaf3e1SJohn Birrell pushl %ecx /* push alist */ 45891eaf3e1SJohn Birrell movl 8(%ebp), %ecx /* %ecx = format */ 45991eaf3e1SJohn Birrell pushl %ecx /* push format */ 46091eaf3e1SJohn Birrell call panicsys /* panicsys(); */ 46191eaf3e1SJohn Birrell addl $16, %esp /* pop arguments */ 46291eaf3e1SJohn Birrell 46391eaf3e1SJohn Birrell addl $REGSIZE, %esp 46491eaf3e1SJohn Birrell#endif 46591eaf3e1SJohn Birrell popl %edx 46691eaf3e1SJohn Birrell popl %ecx 46791eaf3e1SJohn Birrell popl %ebx 46891eaf3e1SJohn Birrell popl %eax 46991eaf3e1SJohn Birrell leave 47091eaf3e1SJohn Birrell ret 47191eaf3e1SJohn Birrell END(vpanic) 47291eaf3e1SJohn Birrell 47391eaf3e1SJohn Birrell/* 47491eaf3e1SJohn Birrellvoid dtrace_vpanic(const char *format, va_list alist) 47591eaf3e1SJohn Birrell*/ 47691eaf3e1SJohn Birrell ENTRY(dtrace_vpanic) /* Initial stack layout: */ 47791eaf3e1SJohn Birrell 47891eaf3e1SJohn Birrell pushl %ebp /* | %eip | 20 */ 47991eaf3e1SJohn Birrell movl %esp, %ebp /* | %ebp | 16 */ 48091eaf3e1SJohn Birrell pushl %eax /* | %eax | 12 */ 48191eaf3e1SJohn Birrell pushl %ebx /* | %ebx | 8 */ 48291eaf3e1SJohn Birrell pushl %ecx /* | %ecx | 4 */ 48391eaf3e1SJohn Birrell pushl %edx /* | %edx | 0 */ 48491eaf3e1SJohn Birrell 48591eaf3e1SJohn Birrell movl %esp, %ebx /* %ebx = current stack pointer */ 48691eaf3e1SJohn Birrell 48791eaf3e1SJohn Birrell lea panic_quiesce, %eax /* %eax = &panic_quiesce */ 48891eaf3e1SJohn Birrell pushl %eax /* push &panic_quiesce */ 48991eaf3e1SJohn Birrell call dtrace_panic_trigger /* %eax = dtrace_panic_trigger() */ 49091eaf3e1SJohn Birrell addl $4, %esp /* reset stack pointer */ 49191eaf3e1SJohn Birrell jmp vpanic_common /* jump back to common code */ 49291eaf3e1SJohn Birrell 49391eaf3e1SJohn Birrell END(dtrace_vpanic) 49491eaf3e1SJohn Birrell 49591eaf3e1SJohn Birrell/* 49691eaf3e1SJohn Birrellint 49791eaf3e1SJohn Birrellpanic_trigger(int *tp) 49891eaf3e1SJohn Birrell*/ 49991eaf3e1SJohn Birrell ENTRY(panic_trigger) 50091eaf3e1SJohn Birrell xorl %eax, %eax 50191eaf3e1SJohn Birrell movl $0xdefacedd, %edx 50291eaf3e1SJohn Birrell lock 50391eaf3e1SJohn Birrell xchgl %edx, (%edi) 50491eaf3e1SJohn Birrell cmpl $0, %edx 50591eaf3e1SJohn Birrell je 0f 50691eaf3e1SJohn Birrell movl $0, %eax 50791eaf3e1SJohn Birrell ret 50891eaf3e1SJohn Birrell0: movl $1, %eax 50991eaf3e1SJohn Birrell ret 51091eaf3e1SJohn Birrell END(panic_trigger) 51191eaf3e1SJohn Birrell 51291eaf3e1SJohn Birrell/* 51391eaf3e1SJohn Birrellint 51491eaf3e1SJohn Birrelldtrace_panic_trigger(int *tp) 51591eaf3e1SJohn Birrell*/ 51691eaf3e1SJohn Birrell ENTRY(dtrace_panic_trigger) 51791eaf3e1SJohn Birrell xorl %eax, %eax 51891eaf3e1SJohn Birrell movl $0xdefacedd, %edx 51991eaf3e1SJohn Birrell lock 52091eaf3e1SJohn Birrell xchgl %edx, (%edi) 52191eaf3e1SJohn Birrell cmpl $0, %edx 52291eaf3e1SJohn Birrell je 0f 52391eaf3e1SJohn Birrell movl $0, %eax 52491eaf3e1SJohn Birrell ret 52591eaf3e1SJohn Birrell0: movl $1, %eax 52691eaf3e1SJohn Birrell ret 52791eaf3e1SJohn Birrell END(dtrace_panic_trigger) 528