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 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 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#pragma ident "%Z%%M% %I% %E% SMI" 34 35#include <sys/asm_linkage.h> 36#include <sys/asm_misc.h> 37#include <sys/regset.h> 38#include <sys/psw.h> 39#include <sys/x86_archext.h> 40 41#if defined(__lint) 42 43#include <sys/types.h> 44#include <sys/thread.h> 45#include <sys/systm.h> 46 47#else /* __lint */ 48 49#include <sys/segments.h> 50#include <sys/pcb.h> 51#include <sys/trap.h> 52#include <sys/ftrace.h> 53#include <sys/traptrace.h> 54#include <sys/clock.h> 55#include <sys/panic.h> 56#include "assym.h" 57 58#endif /* lint */ 59 60#if defined(__i386) 61 62#if defined(__lint) 63 64void 65patch_tsc(void) 66{} 67 68#else /* __lint */ 69 70/* 71 * To cope with processors that do not implement the rdtsc instruction, 72 * we patch the kernel to use rdtsc if that feature is detected on the CPU. 73 * On an unpatched kernel, all locations requiring rdtsc are nop's. 74 * 75 * This function patches the nop's to rdtsc. 76 */ 77 ENTRY_NP(patch_tsc) 78 movw _rdtsc_insn, %cx 79 movw %cx, _tsc_patch15 80 movw %cx, _tsc_patch16 81 ret 82_rdtsc_insn: 83 rdtsc 84 SET_SIZE(patch_tsc) 85 86#endif /* __lint */ 87 88#endif /* __i386 */ 89 90 91#if defined(__lint) 92 93void 94_interrupt(void) 95{} 96 97#else /* __lint */ 98 99#if defined(__amd64) 100 101 /* 102 * Common register usage: 103 * 104 * %r12 trap trace pointer 105 */ 106 ENTRY_NP2(cmnint, _interrupt) 107 108 INTR_PUSH 109 INTGATE_INIT_KERNEL_FLAGS /* (set kernel rflags values) */ 110 111 /* 112 * At the end of TRACE_PTR %r12 points to the current TRAPTRACE entry 113 */ 114 TRACE_PTR(%r12, %rax, %eax, %rdx, $TT_INTERRUPT) 115 /* Uses labels 8 and 9 */ 116 TRACE_REGS(%r12, %rsp, %rax, %rbx) /* Uses label 9 */ 117 TRACE_STAMP(%r12) /* Clobbers %eax, %edx, uses 9 */ 118 119 movq %rsp, %rbp 120 121 TRACE_STACK(%r12) 122 123#ifdef TRAPTRACE 124 LOADCPU(%rbx) /* &cpu */ 125 movl CPU_PRI(%rbx), %r14d /* old ipl */ 126 movl $255, TTR_IPL(%r12) 127 movl %r14d, %edi 128 movb %dil, TTR_PRI(%r12) 129 movl CPU_BASE_SPL(%rbx), %edi 130 movb %dil, TTR_SPL(%r12) 131 movb $255, TTR_VECTOR(%r12) 132 movq %r12, %rsi /* pass traptrace record pointer */ 133#endif 134 135 movq %rsp, %rdi /* pass struct regs pointer */ 136 call do_interrupt 137 jmp _sys_rtt 138 /*NOTREACHED*/ 139 140 SET_SIZE(cmnint) 141 SET_SIZE(_interrupt) 142 143#elif defined(__i386) 144 145 ENTRY_NP2(cmnint, _interrupt) 146 147 INTR_PUSH 148 INTGATE_INIT_KERNEL_FLAGS 149 150 /* 151 * At the end of TRACE_PTR %esi points to the current TRAPTRACE entry 152 */ 153 TRACE_PTR(%esi, %eax, %eax, %edx, $TT_INTERRUPT) 154 /* Uses labels 8 and 9 */ 155 TRACE_REGS(%esi, %esp, %eax, %ebx) /* Uses label 9 */ 156 TRACE_STAMP(%esi) /* Clobbers %eax, %edx, uses 9 */ 157 158 movl %esp, %ebp 159 160 TRACE_STACK(%esi) 161 162 pushl %esi /* pass traptrace record pointer */ 163 pushl %ebp /* pass struct regs pointer */ 164 call do_interrupt /* interrupt service routine */ 165 addl $8, %esp /* pop args off of stack */ 166 167 jmp _sys_rtt 168 SET_SIZE(cmnint) 169 SET_SIZE(_interrupt) 170 171#endif /* __i386 */ 172 173/* 174 * Declare a uintptr_t which has the size of _interrupt to enable stack 175 * traceback code to know when a regs structure is on the stack. 176 */ 177 .globl _interrupt_size 178 .align CLONGSIZE 179_interrupt_size: 180 .NWORD . - _interrupt 181 .type _interrupt_size, @object 182 183#endif /* __lint */ 184 185#if defined(__lint) 186 187void 188fakesoftint(void) 189{} 190 191#else /* __lint */ 192 193 / 194 / If we're here, we're being called from splx() to fake a soft 195 / interrupt (note that interrupts are still disabled from splx()). 196 / We execute this code when a soft interrupt is posted at 197 / level higher than the CPU's current spl; when spl is lowered in 198 / splx(), it will see the softint and jump here. We'll do exactly 199 / what a trap would do: push our flags, %cs, %eip, error code 200 / and trap number (T_SOFTINT). The cmnint() code will see T_SOFTINT 201 / and branch to the dosoftint() code. 202 / 203#if defined(__amd64) 204 205 /* 206 * In 64-bit mode, iretq -always- pops all five regs 207 * Imitate the 16-byte auto-align of the stack, and the 208 * zero-ed out %ss value. 209 */ 210 ENTRY_NP(fakesoftint) 211 movq %rsp, %r11 212 andq $-16, %rsp 213 pushq $KDS_SEL /* %ss */ 214 pushq %r11 /* %rsp */ 215 pushf /* rflags */ 216 pushq $KCS_SEL /* %cs */ 217 leaq fakesoftint_return(%rip), %r11 218 pushq %r11 /* %rip */ 219 pushq $0 /* err */ 220 pushq $T_SOFTINT /* trap */ 221 jmp cmnint 222 ALTENTRY(fakesoftint_return) 223 ret 224 SET_SIZE(fakesoftint_return) 225 SET_SIZE(fakesoftint) 226 227#elif defined(__i386) 228 229 ENTRY_NP(fakesoftint) 230 pushfl 231 pushl %cs 232 pushl $fakesoftint_return 233 pushl $0 234 pushl $T_SOFTINT 235 jmp cmnint 236 ALTENTRY(fakesoftint_return) 237 ret 238 SET_SIZE(fakesoftint_return) 239 SET_SIZE(fakesoftint) 240 241#endif /* __i386 */ 242#endif /* __lint */ 243