xref: /titanic_51/usr/src/uts/i86pc/ml/interrupt.s (revision 672986541be54a7a471bb088e60780c37e371d7e)
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