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 (the "License"). 691eaf3e1SJohn Birrell * You may not use this file except in compliance with the License. 791eaf3e1SJohn Birrell * 891eaf3e1SJohn Birrell * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 991eaf3e1SJohn Birrell * or http://www.opensolaris.org/os/licensing. 1091eaf3e1SJohn Birrell * See the License for the specific language governing permissions 1191eaf3e1SJohn Birrell * and limitations under the License. 1291eaf3e1SJohn Birrell * 1391eaf3e1SJohn Birrell * When distributing Covered Code, include this CDDL HEADER in each 1491eaf3e1SJohn Birrell * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1591eaf3e1SJohn Birrell * If applicable, add the following below this CDDL HEADER, with the 1691eaf3e1SJohn Birrell * fields enclosed by brackets "[]" replaced with your own identifying 1791eaf3e1SJohn Birrell * information: Portions Copyright [yyyy] [name of copyright owner] 1891eaf3e1SJohn Birrell * 1991eaf3e1SJohn Birrell * CDDL HEADER END 2091eaf3e1SJohn Birrell * 2191eaf3e1SJohn Birrell * Portions Copyright 2008 John Birrell <jb@freebsd.org> 2291eaf3e1SJohn Birrell * 2391eaf3e1SJohn Birrell * $FreeBSD$ 2491eaf3e1SJohn Birrell * 2591eaf3e1SJohn Birrell */ 2691eaf3e1SJohn Birrell/* 2791eaf3e1SJohn Birrell * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 2891eaf3e1SJohn Birrell * Use is subject to license terms. 2991eaf3e1SJohn Birrell */ 3091eaf3e1SJohn Birrell 3191eaf3e1SJohn Birrell#define _ASM 3291eaf3e1SJohn Birrell 3391eaf3e1SJohn Birrell#include <machine/asmacros.h> 3491eaf3e1SJohn Birrell#include <sys/cpuvar_defs.h> 3591eaf3e1SJohn Birrell#include <sys/dtrace.h> 3691eaf3e1SJohn Birrell 3791eaf3e1SJohn Birrell#include "assym.s" 3891eaf3e1SJohn Birrell 3991eaf3e1SJohn Birrell#define INTR_POP \ 4091eaf3e1SJohn Birrell MEXITCOUNT; \ 4191eaf3e1SJohn Birrell movq TF_RDI(%rsp),%rdi; \ 4291eaf3e1SJohn Birrell movq TF_RSI(%rsp),%rsi; \ 4391eaf3e1SJohn Birrell movq TF_RDX(%rsp),%rdx; \ 4491eaf3e1SJohn Birrell movq TF_RCX(%rsp),%rcx; \ 4591eaf3e1SJohn Birrell movq TF_R8(%rsp),%r8; \ 4691eaf3e1SJohn Birrell movq TF_R9(%rsp),%r9; \ 4791eaf3e1SJohn Birrell movq TF_RAX(%rsp),%rax; \ 4891eaf3e1SJohn Birrell movq TF_RBX(%rsp),%rbx; \ 4991eaf3e1SJohn Birrell movq TF_RBP(%rsp),%rbp; \ 5091eaf3e1SJohn Birrell movq TF_R10(%rsp),%r10; \ 5191eaf3e1SJohn Birrell movq TF_R11(%rsp),%r11; \ 5291eaf3e1SJohn Birrell movq TF_R12(%rsp),%r12; \ 5391eaf3e1SJohn Birrell movq TF_R13(%rsp),%r13; \ 5491eaf3e1SJohn Birrell movq TF_R14(%rsp),%r14; \ 5591eaf3e1SJohn Birrell movq TF_R15(%rsp),%r15; \ 5691eaf3e1SJohn Birrell testb $SEL_RPL_MASK,TF_CS(%rsp); \ 5791eaf3e1SJohn Birrell jz 1f; \ 5891eaf3e1SJohn Birrell cli; \ 5991eaf3e1SJohn Birrell swapgs; \ 6091eaf3e1SJohn Birrell1: addq $TF_RIP,%rsp; 6191eaf3e1SJohn Birrell 6291eaf3e1SJohn Birrell 6391eaf3e1SJohn Birrell .globl calltrap 6491eaf3e1SJohn Birrell .type calltrap,@function 6591eaf3e1SJohn Birrell ENTRY(dtrace_invop_start) 6691eaf3e1SJohn Birrell 6791eaf3e1SJohn Birrell /* 6891eaf3e1SJohn Birrell * #BP traps with %rip set to the next address. We need to decrement 6991eaf3e1SJohn Birrell * the value to indicate the address of the int3 (0xcc) instruction 7091eaf3e1SJohn Birrell * that we substituted. 7191eaf3e1SJohn Birrell */ 7291eaf3e1SJohn Birrell movq TF_RIP(%rsp), %rdi 7391eaf3e1SJohn Birrell decq %rdi 7491eaf3e1SJohn Birrell movq TF_RSP(%rsp), %rsi 7591eaf3e1SJohn Birrell movq TF_RAX(%rsp), %rdx 7691eaf3e1SJohn Birrell pushq (%rsi) 7791eaf3e1SJohn Birrell movq %rsp, %rsi 7891eaf3e1SJohn Birrell call dtrace_invop 7991eaf3e1SJohn Birrell ALTENTRY(dtrace_invop_callsite) 8091eaf3e1SJohn Birrell addq $8, %rsp 8191eaf3e1SJohn Birrell cmpl $DTRACE_INVOP_PUSHL_EBP, %eax 8291eaf3e1SJohn Birrell je bp_push 8391eaf3e1SJohn Birrell cmpl $DTRACE_INVOP_LEAVE, %eax 8491eaf3e1SJohn Birrell je bp_leave 8591eaf3e1SJohn Birrell cmpl $DTRACE_INVOP_NOP, %eax 8691eaf3e1SJohn Birrell je bp_nop 8791eaf3e1SJohn Birrell cmpl $DTRACE_INVOP_RET, %eax 8891eaf3e1SJohn Birrell je bp_ret 8991eaf3e1SJohn Birrell 9091eaf3e1SJohn Birrell /* When all else fails handle the trap in the usual way. */ 9191eaf3e1SJohn Birrell jmpq *dtrace_invop_calltrap_addr 9291eaf3e1SJohn Birrell 9391eaf3e1SJohn Birrellbp_push: 9491eaf3e1SJohn Birrell /* 9591eaf3e1SJohn Birrell * We must emulate a "pushq %rbp". To do this, we pull the stack 9691eaf3e1SJohn Birrell * down 8 bytes, and then store the base pointer. 9791eaf3e1SJohn Birrell */ 9891eaf3e1SJohn Birrell INTR_POP 9991eaf3e1SJohn Birrell subq $16, %rsp /* make room for %rbp */ 10091eaf3e1SJohn Birrell pushq %rax /* push temp */ 10191eaf3e1SJohn Birrell movq 24(%rsp), %rax /* load calling RIP */ 10291eaf3e1SJohn Birrell movq %rax, 8(%rsp) /* store calling RIP */ 10391eaf3e1SJohn Birrell movq 32(%rsp), %rax /* load calling CS */ 10491eaf3e1SJohn Birrell movq %rax, 16(%rsp) /* store calling CS */ 10591eaf3e1SJohn Birrell movq 40(%rsp), %rax /* load calling RFLAGS */ 10691eaf3e1SJohn Birrell movq %rax, 24(%rsp) /* store calling RFLAGS */ 10791eaf3e1SJohn Birrell movq 48(%rsp), %rax /* load calling RSP */ 10891eaf3e1SJohn Birrell subq $8, %rax /* make room for %rbp */ 10991eaf3e1SJohn Birrell movq %rax, 32(%rsp) /* store calling RSP */ 11091eaf3e1SJohn Birrell movq 56(%rsp), %rax /* load calling SS */ 11191eaf3e1SJohn Birrell movq %rax, 40(%rsp) /* store calling SS */ 11291eaf3e1SJohn Birrell movq 32(%rsp), %rax /* reload calling RSP */ 11391eaf3e1SJohn Birrell movq %rbp, (%rax) /* store %rbp there */ 11491eaf3e1SJohn Birrell popq %rax /* pop off temp */ 11591eaf3e1SJohn Birrell iretq /* return from interrupt */ 11691eaf3e1SJohn Birrell /*NOTREACHED*/ 11791eaf3e1SJohn Birrell 11891eaf3e1SJohn Birrellbp_leave: 11991eaf3e1SJohn Birrell /* 12091eaf3e1SJohn Birrell * We must emulate a "leave", which is the same as a "movq %rbp, %rsp" 12191eaf3e1SJohn Birrell * followed by a "popq %rbp". This is quite a bit simpler on amd64 12291eaf3e1SJohn Birrell * than it is on i386 -- we can exploit the fact that the %rsp is 12391eaf3e1SJohn Birrell * explicitly saved to effect the pop without having to reshuffle 12491eaf3e1SJohn Birrell * the other data pushed for the trap. 12591eaf3e1SJohn Birrell */ 12691eaf3e1SJohn Birrell INTR_POP 12791eaf3e1SJohn Birrell pushq %rax /* push temp */ 12891eaf3e1SJohn Birrell movq 8(%rsp), %rax /* load calling RIP */ 12991eaf3e1SJohn Birrell movq %rax, 8(%rsp) /* store calling RIP */ 13091eaf3e1SJohn Birrell movq (%rbp), %rax /* get new %rbp */ 13191eaf3e1SJohn Birrell addq $8, %rbp /* adjust new %rsp */ 13291eaf3e1SJohn Birrell movq %rbp, 32(%rsp) /* store new %rsp */ 13391eaf3e1SJohn Birrell movq %rax, %rbp /* set new %rbp */ 13491eaf3e1SJohn Birrell popq %rax /* pop off temp */ 13591eaf3e1SJohn Birrell iretq /* return from interrupt */ 13691eaf3e1SJohn Birrell /*NOTREACHED*/ 13791eaf3e1SJohn Birrell 13891eaf3e1SJohn Birrellbp_nop: 13991eaf3e1SJohn Birrell /* We must emulate a "nop". */ 14091eaf3e1SJohn Birrell INTR_POP 14191eaf3e1SJohn Birrell iretq 14291eaf3e1SJohn Birrell /*NOTREACHED*/ 14391eaf3e1SJohn Birrell 14491eaf3e1SJohn Birrellbp_ret: 14591eaf3e1SJohn Birrell INTR_POP 14691eaf3e1SJohn Birrell pushq %rax /* push temp */ 14791eaf3e1SJohn Birrell movq 32(%rsp), %rax /* load %rsp */ 14891eaf3e1SJohn Birrell movq (%rax), %rax /* load calling RIP */ 14991eaf3e1SJohn Birrell movq %rax, 8(%rsp) /* store calling RIP */ 15091eaf3e1SJohn Birrell addq $8, 32(%rsp) /* adjust new %rsp */ 15191eaf3e1SJohn Birrell popq %rax /* pop off temp */ 15291eaf3e1SJohn Birrell iretq /* return from interrupt */ 15391eaf3e1SJohn Birrell /*NOTREACHED*/ 15491eaf3e1SJohn Birrell 15591eaf3e1SJohn Birrell END(dtrace_invop_start) 15691eaf3e1SJohn Birrell 15791eaf3e1SJohn Birrell/* 15891eaf3e1SJohn Birrellvoid dtrace_invop_init(void) 15991eaf3e1SJohn Birrell*/ 16091eaf3e1SJohn Birrell ENTRY(dtrace_invop_init) 16191eaf3e1SJohn Birrell movq $dtrace_invop_start, dtrace_invop_jump_addr(%rip) 16291eaf3e1SJohn Birrell ret 16391eaf3e1SJohn Birrell END(dtrace_invop_init) 16491eaf3e1SJohn Birrell 16591eaf3e1SJohn Birrell/* 16691eaf3e1SJohn Birrellvoid dtrace_invop_uninit(void) 16791eaf3e1SJohn Birrell*/ 16891eaf3e1SJohn Birrell ENTRY(dtrace_invop_uninit) 16991eaf3e1SJohn Birrell movq $0, dtrace_invop_jump_addr(%rip) 17091eaf3e1SJohn Birrell ret 17191eaf3e1SJohn Birrell END(dtrace_invop_uninit) 17291eaf3e1SJohn Birrell 17391eaf3e1SJohn Birrell/* 17491eaf3e1SJohn Birrellgreg_t dtrace_getfp(void) 17591eaf3e1SJohn Birrell*/ 17691eaf3e1SJohn Birrell ENTRY(dtrace_getfp) 17791eaf3e1SJohn Birrell movq %rbp, %rax 17891eaf3e1SJohn Birrell ret 17991eaf3e1SJohn Birrell END(dtrace_getfp) 18091eaf3e1SJohn Birrell 18191eaf3e1SJohn Birrell/* 18291eaf3e1SJohn Birrelluint32_t 18391eaf3e1SJohn Birrelldtrace_cas32(uint32_t *target, uint32_t cmp, uint32_t new) 18491eaf3e1SJohn Birrell*/ 18591eaf3e1SJohn Birrell ENTRY(dtrace_cas32) 18691eaf3e1SJohn Birrell movl %esi, %eax 18791eaf3e1SJohn Birrell lock 18891eaf3e1SJohn Birrell cmpxchgl %edx, (%rdi) 18991eaf3e1SJohn Birrell ret 19091eaf3e1SJohn Birrell END(dtrace_cas32) 19191eaf3e1SJohn Birrell 19291eaf3e1SJohn Birrell/* 19391eaf3e1SJohn Birrellvoid * 19491eaf3e1SJohn Birrelldtrace_casptr(void *target, void *cmp, void *new) 19591eaf3e1SJohn Birrell*/ 19691eaf3e1SJohn Birrell ENTRY(dtrace_casptr) 19791eaf3e1SJohn Birrell movq %rsi, %rax 19891eaf3e1SJohn Birrell lock 19991eaf3e1SJohn Birrell cmpxchgq %rdx, (%rdi) 20091eaf3e1SJohn Birrell ret 20191eaf3e1SJohn Birrell END(dtrace_casptr) 20291eaf3e1SJohn Birrell 20391eaf3e1SJohn Birrell/* 20491eaf3e1SJohn Birrelluintptr_t 20591eaf3e1SJohn Birrelldtrace_caller(int aframes) 20691eaf3e1SJohn Birrell*/ 20791eaf3e1SJohn Birrell ENTRY(dtrace_caller) 20891eaf3e1SJohn Birrell movq $-1, %rax 20991eaf3e1SJohn Birrell ret 21091eaf3e1SJohn Birrell END(dtrace_caller) 21191eaf3e1SJohn Birrell 21291eaf3e1SJohn Birrell/* 21391eaf3e1SJohn Birrellvoid 21491eaf3e1SJohn Birrelldtrace_copy(uintptr_t src, uintptr_t dest, size_t size) 21591eaf3e1SJohn Birrell*/ 21691eaf3e1SJohn Birrell ENTRY(dtrace_copy) 21791eaf3e1SJohn Birrell pushq %rbp 21891eaf3e1SJohn Birrell movq %rsp, %rbp 21991eaf3e1SJohn Birrell 22091eaf3e1SJohn Birrell xchgq %rdi, %rsi /* make %rsi source, %rdi dest */ 22191eaf3e1SJohn Birrell movq %rdx, %rcx /* load count */ 22291eaf3e1SJohn Birrell repz /* repeat for count ... */ 22391eaf3e1SJohn Birrell smovb /* move from %ds:rsi to %ed:rdi */ 22491eaf3e1SJohn Birrell leave 22591eaf3e1SJohn Birrell ret 22691eaf3e1SJohn Birrell END(dtrace_copy) 22791eaf3e1SJohn Birrell 22891eaf3e1SJohn Birrell/* 22991eaf3e1SJohn Birrellvoid 23091eaf3e1SJohn Birrelldtrace_copystr(uintptr_t uaddr, uintptr_t kaddr, size_t size, 23191eaf3e1SJohn Birrell volatile uint16_t *flags) 23291eaf3e1SJohn Birrell*/ 23391eaf3e1SJohn Birrell ENTRY(dtrace_copystr) 23491eaf3e1SJohn Birrell pushq %rbp 23591eaf3e1SJohn Birrell movq %rsp, %rbp 23691eaf3e1SJohn Birrell 23791eaf3e1SJohn Birrell0: 23891eaf3e1SJohn Birrell movb (%rdi), %al /* load from source */ 23991eaf3e1SJohn Birrell movb %al, (%rsi) /* store to destination */ 24091eaf3e1SJohn Birrell addq $1, %rdi /* increment source pointer */ 24191eaf3e1SJohn Birrell addq $1, %rsi /* increment destination pointer */ 24291eaf3e1SJohn Birrell subq $1, %rdx /* decrement remaining count */ 24391eaf3e1SJohn Birrell cmpb $0, %al 24491eaf3e1SJohn Birrell je 2f 24591eaf3e1SJohn Birrell testq $0xfff, %rdx /* test if count is 4k-aligned */ 24691eaf3e1SJohn Birrell jnz 1f /* if not, continue with copying */ 24791eaf3e1SJohn Birrell testq $CPU_DTRACE_BADADDR, (%rcx) /* load and test dtrace flags */ 24891eaf3e1SJohn Birrell jnz 2f 24991eaf3e1SJohn Birrell1: 25091eaf3e1SJohn Birrell cmpq $0, %rdx 25191eaf3e1SJohn Birrell jne 0b 25291eaf3e1SJohn Birrell2: 25391eaf3e1SJohn Birrell leave 25491eaf3e1SJohn Birrell ret 25591eaf3e1SJohn Birrell 25691eaf3e1SJohn Birrell END(dtrace_copystr) 25791eaf3e1SJohn Birrell 25891eaf3e1SJohn Birrell/* 25991eaf3e1SJohn Birrelluintptr_t 26091eaf3e1SJohn Birrelldtrace_fulword(void *addr) 26191eaf3e1SJohn Birrell*/ 26291eaf3e1SJohn Birrell ENTRY(dtrace_fulword) 26391eaf3e1SJohn Birrell movq (%rdi), %rax 26491eaf3e1SJohn Birrell ret 26591eaf3e1SJohn Birrell END(dtrace_fulword) 26691eaf3e1SJohn Birrell 26791eaf3e1SJohn Birrell/* 26891eaf3e1SJohn Birrelluint8_t 26991eaf3e1SJohn Birrelldtrace_fuword8_nocheck(void *addr) 27091eaf3e1SJohn Birrell*/ 27191eaf3e1SJohn Birrell ENTRY(dtrace_fuword8_nocheck) 27291eaf3e1SJohn Birrell xorq %rax, %rax 27391eaf3e1SJohn Birrell movb (%rdi), %al 27491eaf3e1SJohn Birrell ret 27591eaf3e1SJohn Birrell END(dtrace_fuword8_nocheck) 27691eaf3e1SJohn Birrell 27791eaf3e1SJohn Birrell/* 27891eaf3e1SJohn Birrelluint16_t 27991eaf3e1SJohn Birrelldtrace_fuword16_nocheck(void *addr) 28091eaf3e1SJohn Birrell*/ 28191eaf3e1SJohn Birrell ENTRY(dtrace_fuword16_nocheck) 28291eaf3e1SJohn Birrell xorq %rax, %rax 28391eaf3e1SJohn Birrell movw (%rdi), %ax 28491eaf3e1SJohn Birrell ret 28591eaf3e1SJohn Birrell END(dtrace_fuword16_nocheck) 28691eaf3e1SJohn Birrell 28791eaf3e1SJohn Birrell/* 28891eaf3e1SJohn Birrelluint32_t 28991eaf3e1SJohn Birrelldtrace_fuword32_nocheck(void *addr) 29091eaf3e1SJohn Birrell*/ 29191eaf3e1SJohn Birrell ENTRY(dtrace_fuword32_nocheck) 29291eaf3e1SJohn Birrell xorq %rax, %rax 29391eaf3e1SJohn Birrell movl (%rdi), %eax 29491eaf3e1SJohn Birrell ret 29591eaf3e1SJohn Birrell END(dtrace_fuword32_nocheck) 29691eaf3e1SJohn Birrell 29791eaf3e1SJohn Birrell/* 29891eaf3e1SJohn Birrelluint64_t 29991eaf3e1SJohn Birrelldtrace_fuword64_nocheck(void *addr) 30091eaf3e1SJohn Birrell*/ 30191eaf3e1SJohn Birrell ENTRY(dtrace_fuword64_nocheck) 30291eaf3e1SJohn Birrell movq (%rdi), %rax 30391eaf3e1SJohn Birrell ret 30491eaf3e1SJohn Birrell END(dtrace_fuword64_nocheck) 30591eaf3e1SJohn Birrell 30691eaf3e1SJohn Birrell/* 30791eaf3e1SJohn Birrellvoid 30891eaf3e1SJohn Birrelldtrace_probe_error(dtrace_state_t *state, dtrace_epid_t epid, int which, 30991eaf3e1SJohn Birrell int fault, int fltoffs, uintptr_t illval) 31091eaf3e1SJohn Birrell*/ 31191eaf3e1SJohn Birrell ENTRY(dtrace_probe_error) 31291eaf3e1SJohn Birrell pushq %rbp 31391eaf3e1SJohn Birrell movq %rsp, %rbp 31491eaf3e1SJohn Birrell subq $0x8, %rsp 31591eaf3e1SJohn Birrell movq %r9, (%rsp) 31691eaf3e1SJohn Birrell movq %r8, %r9 31791eaf3e1SJohn Birrell movq %rcx, %r8 31891eaf3e1SJohn Birrell movq %rdx, %rcx 31991eaf3e1SJohn Birrell movq %rsi, %rdx 32091eaf3e1SJohn Birrell movq %rdi, %rsi 32191eaf3e1SJohn Birrell movl dtrace_probeid_error(%rip), %edi 32291eaf3e1SJohn Birrell call dtrace_probe 32391eaf3e1SJohn Birrell addq $0x8, %rsp 32491eaf3e1SJohn Birrell leave 32591eaf3e1SJohn Birrell ret 32691eaf3e1SJohn Birrell END(dtrace_probe_error) 32791eaf3e1SJohn Birrell 32891eaf3e1SJohn Birrell/* 32991eaf3e1SJohn Birrellvoid 33091eaf3e1SJohn Birrelldtrace_membar_producer(void) 33191eaf3e1SJohn Birrell*/ 33291eaf3e1SJohn Birrell ENTRY(dtrace_membar_producer) 33391eaf3e1SJohn Birrell rep; ret /* use 2 byte return instruction when branch target */ 33491eaf3e1SJohn Birrell /* AMD Software Optimization Guide - Section 6.2 */ 33591eaf3e1SJohn Birrell END(dtrace_membar_producer) 33691eaf3e1SJohn Birrell 33791eaf3e1SJohn Birrell/* 33891eaf3e1SJohn Birrellvoid 33991eaf3e1SJohn Birrelldtrace_membar_consumer(void) 34091eaf3e1SJohn Birrell*/ 34191eaf3e1SJohn Birrell ENTRY(dtrace_membar_consumer) 34291eaf3e1SJohn Birrell rep; ret /* use 2 byte return instruction when branch target */ 34391eaf3e1SJohn Birrell /* AMD Software Optimization Guide - Section 6.2 */ 34491eaf3e1SJohn Birrell END(dtrace_membar_consumer) 34591eaf3e1SJohn Birrell 34691eaf3e1SJohn Birrell/* 34791eaf3e1SJohn Birrelldtrace_icookie_t 34891eaf3e1SJohn Birrelldtrace_interrupt_disable(void) 34991eaf3e1SJohn Birrell*/ 35091eaf3e1SJohn Birrell ENTRY(dtrace_interrupt_disable) 35191eaf3e1SJohn Birrell pushfq 35291eaf3e1SJohn Birrell popq %rax 35391eaf3e1SJohn Birrell cli 35491eaf3e1SJohn Birrell ret 35591eaf3e1SJohn Birrell END(dtrace_interrupt_disable) 35691eaf3e1SJohn Birrell 35791eaf3e1SJohn Birrell/* 35891eaf3e1SJohn Birrellvoid 35991eaf3e1SJohn Birrelldtrace_interrupt_enable(dtrace_icookie_t cookie) 36091eaf3e1SJohn Birrell*/ 36191eaf3e1SJohn Birrell ENTRY(dtrace_interrupt_enable) 36291eaf3e1SJohn Birrell pushq %rdi 36391eaf3e1SJohn Birrell popfq 36491eaf3e1SJohn Birrell ret 36591eaf3e1SJohn Birrell END(dtrace_interrupt_enable) 36691eaf3e1SJohn Birrell 36791eaf3e1SJohn Birrell/* 36891eaf3e1SJohn Birrell * The panic() and cmn_err() functions invoke vpanic() as a common entry point 36991eaf3e1SJohn Birrell * into the panic code implemented in panicsys(). vpanic() is responsible 37091eaf3e1SJohn Birrell * for passing through the format string and arguments, and constructing a 37191eaf3e1SJohn Birrell * regs structure on the stack into which it saves the current register 37291eaf3e1SJohn Birrell * values. If we are not dying due to a fatal trap, these registers will 37391eaf3e1SJohn Birrell * then be preserved in panicbuf as the current processor state. Before 37491eaf3e1SJohn Birrell * invoking panicsys(), vpanic() activates the first panic trigger (see 37591eaf3e1SJohn Birrell * common/os/panic.c) and switches to the panic_stack if successful. Note that 37691eaf3e1SJohn Birrell * DTrace takes a slightly different panic path if it must panic from probe 37791eaf3e1SJohn Birrell * context. Instead of calling panic, it calls into dtrace_vpanic(), which 37891eaf3e1SJohn Birrell * sets up the initial stack as vpanic does, calls dtrace_panic_trigger(), and 37991eaf3e1SJohn Birrell * branches back into vpanic(). 38091eaf3e1SJohn Birrell */ 38191eaf3e1SJohn Birrell 38291eaf3e1SJohn Birrell/* 38391eaf3e1SJohn Birrellvoid 38491eaf3e1SJohn Birrellvpanic(const char *format, va_list alist) 38591eaf3e1SJohn Birrell*/ 38691eaf3e1SJohn Birrell ENTRY(vpanic) /* Initial stack layout: */ 38791eaf3e1SJohn Birrell 38891eaf3e1SJohn Birrell pushq %rbp /* | %rip | 0x60 */ 38991eaf3e1SJohn Birrell movq %rsp, %rbp /* | %rbp | 0x58 */ 39091eaf3e1SJohn Birrell pushfq /* | rfl | 0x50 */ 39191eaf3e1SJohn Birrell pushq %r11 /* | %r11 | 0x48 */ 39291eaf3e1SJohn Birrell pushq %r10 /* | %r10 | 0x40 */ 39391eaf3e1SJohn Birrell pushq %rbx /* | %rbx | 0x38 */ 39491eaf3e1SJohn Birrell pushq %rax /* | %rax | 0x30 */ 39591eaf3e1SJohn Birrell pushq %r9 /* | %r9 | 0x28 */ 39691eaf3e1SJohn Birrell pushq %r8 /* | %r8 | 0x20 */ 39791eaf3e1SJohn Birrell pushq %rcx /* | %rcx | 0x18 */ 39891eaf3e1SJohn Birrell pushq %rdx /* | %rdx | 0x10 */ 39991eaf3e1SJohn Birrell pushq %rsi /* | %rsi | 0x8 alist */ 40091eaf3e1SJohn Birrell pushq %rdi /* | %rdi | 0x0 format */ 40191eaf3e1SJohn Birrell 40291eaf3e1SJohn Birrell movq %rsp, %rbx /* %rbx = current %rsp */ 40391eaf3e1SJohn Birrell 40491eaf3e1SJohn Birrell leaq panic_quiesce(%rip), %rdi /* %rdi = &panic_quiesce */ 40591eaf3e1SJohn Birrell call panic_trigger /* %eax = panic_trigger() */ 40691eaf3e1SJohn Birrell 40791eaf3e1SJohn Birrellvpanic_common: 40891eaf3e1SJohn Birrell /* 40991eaf3e1SJohn Birrell * The panic_trigger result is in %eax from the call above, and 41091eaf3e1SJohn Birrell * dtrace_panic places it in %eax before branching here. 41191eaf3e1SJohn Birrell * The rdmsr instructions that follow below will clobber %eax so 41291eaf3e1SJohn Birrell * we stash the panic_trigger result in %r11d. 41391eaf3e1SJohn Birrell */ 41491eaf3e1SJohn Birrell movl %eax, %r11d 41591eaf3e1SJohn Birrell cmpl $0, %r11d 41691eaf3e1SJohn Birrell je 0f 41791eaf3e1SJohn Birrell 41891eaf3e1SJohn Birrell /* 41991eaf3e1SJohn Birrell * If panic_trigger() was successful, we are the first to initiate a 42091eaf3e1SJohn Birrell * panic: we now switch to the reserved panic_stack before continuing. 42191eaf3e1SJohn Birrell */ 42291eaf3e1SJohn Birrell leaq panic_stack(%rip), %rsp 42391eaf3e1SJohn Birrell addq $PANICSTKSIZE, %rsp 42491eaf3e1SJohn Birrell0: subq $REGSIZE, %rsp 42591eaf3e1SJohn Birrell /* 42691eaf3e1SJohn Birrell * Now that we've got everything set up, store the register values as 42791eaf3e1SJohn Birrell * they were when we entered vpanic() to the designated location in 42891eaf3e1SJohn Birrell * the regs structure we allocated on the stack. 42991eaf3e1SJohn Birrell */ 43091eaf3e1SJohn Birrell#ifdef notyet 43191eaf3e1SJohn Birrell movq 0x0(%rbx), %rcx 43291eaf3e1SJohn Birrell movq %rcx, REGOFF_RDI(%rsp) 43391eaf3e1SJohn Birrell movq 0x8(%rbx), %rcx 43491eaf3e1SJohn Birrell movq %rcx, REGOFF_RSI(%rsp) 43591eaf3e1SJohn Birrell movq 0x10(%rbx), %rcx 43691eaf3e1SJohn Birrell movq %rcx, REGOFF_RDX(%rsp) 43791eaf3e1SJohn Birrell movq 0x18(%rbx), %rcx 43891eaf3e1SJohn Birrell movq %rcx, REGOFF_RCX(%rsp) 43991eaf3e1SJohn Birrell movq 0x20(%rbx), %rcx 44091eaf3e1SJohn Birrell 44191eaf3e1SJohn Birrell movq %rcx, REGOFF_R8(%rsp) 44291eaf3e1SJohn Birrell movq 0x28(%rbx), %rcx 44391eaf3e1SJohn Birrell movq %rcx, REGOFF_R9(%rsp) 44491eaf3e1SJohn Birrell movq 0x30(%rbx), %rcx 44591eaf3e1SJohn Birrell movq %rcx, REGOFF_RAX(%rsp) 44691eaf3e1SJohn Birrell movq 0x38(%rbx), %rcx 44791eaf3e1SJohn Birrell movq %rcx, REGOFF_RBX(%rsp) 44891eaf3e1SJohn Birrell movq 0x58(%rbx), %rcx 44991eaf3e1SJohn Birrell 45091eaf3e1SJohn Birrell movq %rcx, REGOFF_RBP(%rsp) 45191eaf3e1SJohn Birrell movq 0x40(%rbx), %rcx 45291eaf3e1SJohn Birrell movq %rcx, REGOFF_R10(%rsp) 45391eaf3e1SJohn Birrell movq 0x48(%rbx), %rcx 45491eaf3e1SJohn Birrell movq %rcx, REGOFF_R11(%rsp) 45591eaf3e1SJohn Birrell movq %r12, REGOFF_R12(%rsp) 45691eaf3e1SJohn Birrell 45791eaf3e1SJohn Birrell movq %r13, REGOFF_R13(%rsp) 45891eaf3e1SJohn Birrell movq %r14, REGOFF_R14(%rsp) 45991eaf3e1SJohn Birrell movq %r15, REGOFF_R15(%rsp) 46091eaf3e1SJohn Birrell 46191eaf3e1SJohn Birrell xorl %ecx, %ecx 46291eaf3e1SJohn Birrell movw %ds, %cx 46391eaf3e1SJohn Birrell movq %rcx, REGOFF_DS(%rsp) 46491eaf3e1SJohn Birrell movw %es, %cx 46591eaf3e1SJohn Birrell movq %rcx, REGOFF_ES(%rsp) 46691eaf3e1SJohn Birrell movw %fs, %cx 46791eaf3e1SJohn Birrell movq %rcx, REGOFF_FS(%rsp) 46891eaf3e1SJohn Birrell movw %gs, %cx 46991eaf3e1SJohn Birrell movq %rcx, REGOFF_GS(%rsp) 47091eaf3e1SJohn Birrell 47191eaf3e1SJohn Birrell movq $0, REGOFF_TRAPNO(%rsp) 47291eaf3e1SJohn Birrell 47391eaf3e1SJohn Birrell movq $0, REGOFF_ERR(%rsp) 47491eaf3e1SJohn Birrell leaq vpanic(%rip), %rcx 47591eaf3e1SJohn Birrell movq %rcx, REGOFF_RIP(%rsp) 47691eaf3e1SJohn Birrell movw %cs, %cx 47791eaf3e1SJohn Birrell movzwq %cx, %rcx 47891eaf3e1SJohn Birrell movq %rcx, REGOFF_CS(%rsp) 47991eaf3e1SJohn Birrell movq 0x50(%rbx), %rcx 48091eaf3e1SJohn Birrell movq %rcx, REGOFF_RFL(%rsp) 48191eaf3e1SJohn Birrell movq %rbx, %rcx 48291eaf3e1SJohn Birrell addq $0x60, %rcx 48391eaf3e1SJohn Birrell movq %rcx, REGOFF_RSP(%rsp) 48491eaf3e1SJohn Birrell movw %ss, %cx 48591eaf3e1SJohn Birrell movzwq %cx, %rcx 48691eaf3e1SJohn Birrell movq %rcx, REGOFF_SS(%rsp) 48791eaf3e1SJohn Birrell 48891eaf3e1SJohn Birrell /* 48991eaf3e1SJohn Birrell * panicsys(format, alist, rp, on_panic_stack) 49091eaf3e1SJohn Birrell */ 49191eaf3e1SJohn Birrell movq REGOFF_RDI(%rsp), %rdi /* format */ 49291eaf3e1SJohn Birrell movq REGOFF_RSI(%rsp), %rsi /* alist */ 49391eaf3e1SJohn Birrell movq %rsp, %rdx /* struct regs */ 49491eaf3e1SJohn Birrell movl %r11d, %ecx /* on_panic_stack */ 49591eaf3e1SJohn Birrell call panicsys 49691eaf3e1SJohn Birrell addq $REGSIZE, %rsp 49791eaf3e1SJohn Birrell#endif 49891eaf3e1SJohn Birrell popq %rdi 49991eaf3e1SJohn Birrell popq %rsi 50091eaf3e1SJohn Birrell popq %rdx 50191eaf3e1SJohn Birrell popq %rcx 50291eaf3e1SJohn Birrell popq %r8 50391eaf3e1SJohn Birrell popq %r9 50491eaf3e1SJohn Birrell popq %rax 50591eaf3e1SJohn Birrell popq %rbx 50691eaf3e1SJohn Birrell popq %r10 50791eaf3e1SJohn Birrell popq %r11 50891eaf3e1SJohn Birrell popfq 50991eaf3e1SJohn Birrell leave 51091eaf3e1SJohn Birrell ret 51191eaf3e1SJohn Birrell END(vpanic) 51291eaf3e1SJohn Birrell 51391eaf3e1SJohn Birrell/* 51491eaf3e1SJohn Birrellvoid 51591eaf3e1SJohn Birrelldtrace_vpanic(const char *format, va_list alist) 51691eaf3e1SJohn Birrell*/ 51791eaf3e1SJohn Birrell ENTRY(dtrace_vpanic) /* Initial stack layout: */ 51891eaf3e1SJohn Birrell 51991eaf3e1SJohn Birrell pushq %rbp /* | %rip | 0x60 */ 52091eaf3e1SJohn Birrell movq %rsp, %rbp /* | %rbp | 0x58 */ 52191eaf3e1SJohn Birrell pushfq /* | rfl | 0x50 */ 52291eaf3e1SJohn Birrell pushq %r11 /* | %r11 | 0x48 */ 52391eaf3e1SJohn Birrell pushq %r10 /* | %r10 | 0x40 */ 52491eaf3e1SJohn Birrell pushq %rbx /* | %rbx | 0x38 */ 52591eaf3e1SJohn Birrell pushq %rax /* | %rax | 0x30 */ 52691eaf3e1SJohn Birrell pushq %r9 /* | %r9 | 0x28 */ 52791eaf3e1SJohn Birrell pushq %r8 /* | %r8 | 0x20 */ 52891eaf3e1SJohn Birrell pushq %rcx /* | %rcx | 0x18 */ 52991eaf3e1SJohn Birrell pushq %rdx /* | %rdx | 0x10 */ 53091eaf3e1SJohn Birrell pushq %rsi /* | %rsi | 0x8 alist */ 53191eaf3e1SJohn Birrell pushq %rdi /* | %rdi | 0x0 format */ 53291eaf3e1SJohn Birrell 53391eaf3e1SJohn Birrell movq %rsp, %rbx /* %rbx = current %rsp */ 53491eaf3e1SJohn Birrell 53591eaf3e1SJohn Birrell leaq panic_quiesce(%rip), %rdi /* %rdi = &panic_quiesce */ 53691eaf3e1SJohn Birrell call dtrace_panic_trigger /* %eax = dtrace_panic_trigger() */ 53791eaf3e1SJohn Birrell jmp vpanic_common 53891eaf3e1SJohn Birrell 53991eaf3e1SJohn Birrell END(dtrace_vpanic) 54091eaf3e1SJohn Birrell 54191eaf3e1SJohn Birrell/* 54291eaf3e1SJohn Birrellint 54391eaf3e1SJohn Birrellpanic_trigger(int *tp) 54491eaf3e1SJohn Birrell*/ 54591eaf3e1SJohn Birrell ENTRY(panic_trigger) 54691eaf3e1SJohn Birrell xorl %eax, %eax 54791eaf3e1SJohn Birrell movl $0xdefacedd, %edx 54891eaf3e1SJohn Birrell lock 54991eaf3e1SJohn Birrell xchgl %edx, (%rdi) 55091eaf3e1SJohn Birrell cmpl $0, %edx 55191eaf3e1SJohn Birrell je 0f 55291eaf3e1SJohn Birrell movl $0, %eax 55391eaf3e1SJohn Birrell ret 55491eaf3e1SJohn Birrell0: movl $1, %eax 55591eaf3e1SJohn Birrell ret 55691eaf3e1SJohn Birrell END(panic_trigger) 55791eaf3e1SJohn Birrell 55891eaf3e1SJohn Birrell/* 55991eaf3e1SJohn Birrellint 56091eaf3e1SJohn Birrelldtrace_panic_trigger(int *tp) 56191eaf3e1SJohn Birrell*/ 56291eaf3e1SJohn Birrell ENTRY(dtrace_panic_trigger) 56391eaf3e1SJohn Birrell xorl %eax, %eax 56491eaf3e1SJohn Birrell movl $0xdefacedd, %edx 56591eaf3e1SJohn Birrell lock 56691eaf3e1SJohn Birrell xchgl %edx, (%rdi) 56791eaf3e1SJohn Birrell cmpl $0, %edx 56891eaf3e1SJohn Birrell je 0f 56991eaf3e1SJohn Birrell movl $0, %eax 57091eaf3e1SJohn Birrell ret 57191eaf3e1SJohn Birrell0: movl $1, %eax 57291eaf3e1SJohn Birrell ret 57391eaf3e1SJohn Birrell END(dtrace_panic_trigger) 574