1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. 23 * Copyright 2019 Joyent, Inc. 24 */ 25 26 /* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */ 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */ 28 /* All Rights Reserved */ 29 30 /* Copyright (c) 1987, 1988 Microsoft Corporation */ 31 /* All Rights Reserved */ 32 33 #include <sys/asm_linkage.h> 34 #include <sys/asm_misc.h> 35 #include <sys/regset.h> 36 #include <sys/psw.h> 37 #include <sys/x86_archext.h> 38 39 #if defined(__lint) 40 41 #include <sys/types.h> 42 #include <sys/thread.h> 43 #include <sys/systm.h> 44 45 #else /* __lint */ 46 47 #include <sys/segments.h> 48 #include <sys/pcb.h> 49 #include <sys/trap.h> 50 #include <sys/ftrace.h> 51 #include <sys/traptrace.h> 52 #include <sys/clock.h> 53 #include <sys/panic.h> 54 #include "assym.h" 55 56 #endif /* lint */ 57 58 #if defined(__lint) 59 60 void 61 _interrupt(void) 62 {} 63 64 #else /* __lint */ 65 66 #if defined(__amd64) 67 68 /* 69 * Common register usage: 70 * 71 * %r12 trap trace pointer 72 */ 73 ENTRY_NP2(cmnint, _interrupt) 74 75 INTR_PUSH 76 INTGATE_INIT_KERNEL_FLAGS /* (set kernel rflags values) */ 77 78 /* 79 * At the end of TRACE_PTR %r12 points to the current TRAPTRACE entry 80 */ 81 TRACE_PTR(%r12, %rax, %eax, %rdx, $TT_INTERRUPT) 82 /* Uses labels 8 and 9 */ 83 TRACE_REGS(%r12, %rsp, %rax, %rbx) /* Uses label 9 */ 84 TRACE_STAMP(%r12) /* Clobbers %eax, %edx, uses 9 */ 85 86 movq %rsp, %rbp 87 88 TRACE_STACK(%r12) 89 90 #ifdef TRAPTRACE 91 LOADCPU(%rbx) /* &cpu */ 92 movl CPU_PRI(%rbx), %r14d /* old ipl */ 93 movl $255, TTR_IPL(%r12) 94 movl %r14d, %edi 95 movb %dil, TTR_PRI(%r12) 96 movl CPU_BASE_SPL(%rbx), %edi 97 movb %dil, TTR_SPL(%r12) 98 movb $255, TTR_VECTOR(%r12) 99 movq %r12, %rsi /* pass traptrace record pointer */ 100 #endif 101 102 movq %rsp, %rdi /* pass struct regs pointer */ 103 movq do_interrupt_common, %rax 104 INDIRECT_CALL_REG(rax) 105 106 jmp _sys_rtt_ints_disabled 107 /*NOTREACHED*/ 108 109 SET_SIZE(cmnint) 110 SET_SIZE(_interrupt) 111 112 #elif defined(__i386) 113 114 ENTRY_NP2(cmnint, _interrupt) 115 116 INTR_PUSH 117 INTGATE_INIT_KERNEL_FLAGS 118 119 /* 120 * At the end of TRACE_PTR %esi points to the current TRAPTRACE entry 121 */ 122 TRACE_PTR(%esi, %eax, %eax, %edx, $TT_INTERRUPT) 123 /* Uses labels 8 and 9 */ 124 TRACE_REGS(%esi, %esp, %eax, %ebx) /* Uses label 9 */ 125 TRACE_STAMP(%esi) /* Clobbers %eax, %edx, uses 9 */ 126 127 movl %esp, %ebp 128 129 TRACE_STACK(%esi) 130 131 pushl %esi /* pass traptrace record pointer */ 132 pushl %ebp /* pass struct regs pointer */ 133 call *do_interrupt_common /* interrupt service routine */ 134 addl $8, %esp /* pop args off of stack */ 135 136 jmp _sys_rtt_ints_disabled 137 /*NOTREACHED*/ 138 139 SET_SIZE(cmnint) 140 SET_SIZE(_interrupt) 141 142 #endif /* __i386 */ 143 144 /* 145 * Declare a uintptr_t which has the size of _interrupt to enable stack 146 * traceback code to know when a regs structure is on the stack. 147 */ 148 .globl _interrupt_size 149 .align CLONGSIZE 150 _interrupt_size: 151 .NWORD . - _interrupt 152 .type _interrupt_size, @object 153 154 #endif /* __lint */ 155 156 #if defined(__lint) 157 158 void 159 fakesoftint(void) 160 {} 161 162 #else /* __lint */ 163 164 / 165 / If we're here, we're being called from splx() to fake a soft 166 / interrupt (note that interrupts are still disabled from splx()). 167 / We execute this code when a soft interrupt is posted at 168 / level higher than the CPU's current spl; when spl is lowered in 169 / splx(), it will see the softint and jump here. We'll do exactly 170 / what a trap would do: push our flags, %cs, %eip, error code 171 / and trap number (T_SOFTINT). The cmnint() code will see T_SOFTINT 172 / and branch to the dosoftint() code. 173 / 174 #if defined(__amd64) 175 176 /* 177 * In 64-bit mode, iretq -always- pops all five regs 178 * Imitate the 16-byte auto-align of the stack, and the 179 * zero-ed out %ss value. 180 */ 181 ENTRY_NP(fakesoftint) 182 movq %rsp, %r11 183 andq $-16, %rsp 184 pushq $KDS_SEL /* %ss */ 185 pushq %r11 /* %rsp */ 186 pushf /* rflags */ 187 #if defined(__xpv) 188 popq %r11 189 EVENT_MASK_TO_IE(%rdi, %r11) 190 pushq %r11 191 #endif 192 pushq $KCS_SEL /* %cs */ 193 leaq fakesoftint_return(%rip), %r11 194 pushq %r11 /* %rip */ 195 pushq $0 /* err */ 196 pushq $T_SOFTINT /* trap */ 197 jmp cmnint 198 ALTENTRY(fakesoftint_return) 199 ret 200 SET_SIZE(fakesoftint_return) 201 SET_SIZE(fakesoftint) 202 203 #elif defined(__i386) 204 205 ENTRY_NP(fakesoftint) 206 pushfl 207 #if defined(__xpv) 208 popl %eax 209 EVENT_MASK_TO_IE(%edx, %eax) 210 pushl %eax 211 #endif 212 pushl %cs 213 pushl $fakesoftint_return 214 pushl $0 215 pushl $T_SOFTINT 216 jmp cmnint 217 ALTENTRY(fakesoftint_return) 218 ret 219 SET_SIZE(fakesoftint_return) 220 SET_SIZE(fakesoftint) 221 222 #endif /* __i386 */ 223 #endif /* __lint */