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