xref: /titanic_51/usr/src/uts/i86pc/ml/interrupt.s (revision 5cd376e8b7030707d78315f63adb4bb2b4d9963e)
17c478bd9Sstevel@tonic-gate/*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5c81508f4Sjhaslam * Common Development and Distribution License (the "License").
6c81508f4Sjhaslam * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate/*
22*5cd376e8SJimmy Vetayases * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate */
247c478bd9Sstevel@tonic-gate
257c478bd9Sstevel@tonic-gate/*	Copyright (c) 1990, 1991 UNIX System Laboratories, Inc.	*/
267c478bd9Sstevel@tonic-gate/*	Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T	*/
277c478bd9Sstevel@tonic-gate/*	  All Rights Reserved					*/
287c478bd9Sstevel@tonic-gate
297c478bd9Sstevel@tonic-gate/*	Copyright (c) 1987, 1988 Microsoft Corporation		*/
307c478bd9Sstevel@tonic-gate/*	  All Rights Reserved					*/
317c478bd9Sstevel@tonic-gate
327c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h>
337c478bd9Sstevel@tonic-gate#include <sys/asm_misc.h>
347c478bd9Sstevel@tonic-gate#include <sys/regset.h>
357c478bd9Sstevel@tonic-gate#include <sys/psw.h>
367c478bd9Sstevel@tonic-gate#include <sys/x86_archext.h>
377c478bd9Sstevel@tonic-gate
387c478bd9Sstevel@tonic-gate#if defined(__lint)
397c478bd9Sstevel@tonic-gate
407c478bd9Sstevel@tonic-gate#include <sys/types.h>
417c478bd9Sstevel@tonic-gate#include <sys/thread.h>
427c478bd9Sstevel@tonic-gate#include <sys/systm.h>
437c478bd9Sstevel@tonic-gate
447c478bd9Sstevel@tonic-gate#else   /* __lint */
457c478bd9Sstevel@tonic-gate
467c478bd9Sstevel@tonic-gate#include <sys/segments.h>
477c478bd9Sstevel@tonic-gate#include <sys/pcb.h>
487c478bd9Sstevel@tonic-gate#include <sys/trap.h>
497c478bd9Sstevel@tonic-gate#include <sys/ftrace.h>
507c478bd9Sstevel@tonic-gate#include <sys/traptrace.h>
517c478bd9Sstevel@tonic-gate#include <sys/clock.h>
527c478bd9Sstevel@tonic-gate#include <sys/panic.h>
537c478bd9Sstevel@tonic-gate#include "assym.h"
547c478bd9Sstevel@tonic-gate
557c478bd9Sstevel@tonic-gate#endif	/* lint */
567c478bd9Sstevel@tonic-gate
577c478bd9Sstevel@tonic-gate#if defined(__lint)
587c478bd9Sstevel@tonic-gate
597c478bd9Sstevel@tonic-gatevoid
607c478bd9Sstevel@tonic-gate_interrupt(void)
617c478bd9Sstevel@tonic-gate{}
627c478bd9Sstevel@tonic-gate
637c478bd9Sstevel@tonic-gate#else	/* __lint */
647c478bd9Sstevel@tonic-gate
657c478bd9Sstevel@tonic-gate#if defined(__amd64)
667c478bd9Sstevel@tonic-gate
677c478bd9Sstevel@tonic-gate	/*
687c478bd9Sstevel@tonic-gate	 * Common register usage:
697c478bd9Sstevel@tonic-gate	 *
70ae115bc7Smrj	 * %r12		trap trace pointer
717c478bd9Sstevel@tonic-gate	 */
727c478bd9Sstevel@tonic-gate	ENTRY_NP2(cmnint, _interrupt)
737c478bd9Sstevel@tonic-gate
747c478bd9Sstevel@tonic-gate	INTR_PUSH
75ae115bc7Smrj	INTGATE_INIT_KERNEL_FLAGS	/* (set kernel rflags values) */
767c478bd9Sstevel@tonic-gate
777c478bd9Sstevel@tonic-gate	/*
787c478bd9Sstevel@tonic-gate	 * At the end of TRACE_PTR %r12 points to the current TRAPTRACE entry
797c478bd9Sstevel@tonic-gate	 */
807c478bd9Sstevel@tonic-gate	TRACE_PTR(%r12, %rax, %eax, %rdx, $TT_INTERRUPT)
817c478bd9Sstevel@tonic-gate						/* Uses labels 8 and 9 */
827c478bd9Sstevel@tonic-gate	TRACE_REGS(%r12, %rsp, %rax, %rbx)	/* Uses label 9 */
837c478bd9Sstevel@tonic-gate	TRACE_STAMP(%r12)		/* Clobbers %eax, %edx, uses 9 */
847c478bd9Sstevel@tonic-gate
857c478bd9Sstevel@tonic-gate	movq	%rsp, %rbp
867c478bd9Sstevel@tonic-gate
877c478bd9Sstevel@tonic-gate	TRACE_STACK(%r12)
887c478bd9Sstevel@tonic-gate
897c478bd9Sstevel@tonic-gate#ifdef TRAPTRACE
90ae115bc7Smrj	LOADCPU(%rbx)				/* &cpu */
91ae115bc7Smrj	movl	CPU_PRI(%rbx), %r14d		/* old ipl */
927c478bd9Sstevel@tonic-gate	movl	$255, TTR_IPL(%r12)
937c478bd9Sstevel@tonic-gate	movl	%r14d, %edi
947c478bd9Sstevel@tonic-gate	movb	%dil, TTR_PRI(%r12)
957c478bd9Sstevel@tonic-gate	movl	CPU_BASE_SPL(%rbx), %edi
967c478bd9Sstevel@tonic-gate	movb	%dil, TTR_SPL(%r12)
977c478bd9Sstevel@tonic-gate	movb	$255, TTR_VECTOR(%r12)
98ae115bc7Smrj	movq	%r12, %rsi		/* pass traptrace record pointer */
997c478bd9Sstevel@tonic-gate#endif
1007c478bd9Sstevel@tonic-gate
101ae115bc7Smrj	movq	%rsp, %rdi		/* pass struct regs pointer */
1027ff178cdSJimmy Vetayases	call	*do_interrupt_common
103843e1988Sjohnlev
104843e1988Sjohnlev	jmp	_sys_rtt_ints_disabled
1057c478bd9Sstevel@tonic-gate	/*NOTREACHED*/
1067c478bd9Sstevel@tonic-gate
1077c478bd9Sstevel@tonic-gate	SET_SIZE(cmnint)
1087c478bd9Sstevel@tonic-gate	SET_SIZE(_interrupt)
1097c478bd9Sstevel@tonic-gate
1107c478bd9Sstevel@tonic-gate#elif defined(__i386)
1117c478bd9Sstevel@tonic-gate
1127c478bd9Sstevel@tonic-gate	ENTRY_NP2(cmnint, _interrupt)
1137c478bd9Sstevel@tonic-gate
1147c478bd9Sstevel@tonic-gate	INTR_PUSH
115ae115bc7Smrj	INTGATE_INIT_KERNEL_FLAGS
1167c478bd9Sstevel@tonic-gate
1177c478bd9Sstevel@tonic-gate	/*
1187c478bd9Sstevel@tonic-gate	 * At the end of TRACE_PTR %esi points to the current TRAPTRACE entry
1197c478bd9Sstevel@tonic-gate	 */
1207c478bd9Sstevel@tonic-gate	TRACE_PTR(%esi, %eax, %eax, %edx, $TT_INTERRUPT)
1217c478bd9Sstevel@tonic-gate						/* Uses labels 8 and 9 */
1227c478bd9Sstevel@tonic-gate	TRACE_REGS(%esi, %esp, %eax, %ebx)	/* Uses label 9 */
1237c478bd9Sstevel@tonic-gate	TRACE_STAMP(%esi)		/* Clobbers %eax, %edx, uses 9 */
1247c478bd9Sstevel@tonic-gate
1257c478bd9Sstevel@tonic-gate	movl	%esp, %ebp
1267c478bd9Sstevel@tonic-gate
127ae115bc7Smrj	TRACE_STACK(%esi)
1287c478bd9Sstevel@tonic-gate
129ae115bc7Smrj	pushl	%esi			/* pass traptrace record pointer */
130ae115bc7Smrj	pushl	%ebp			/* pass struct regs pointer */
1317ff178cdSJimmy Vetayases	call	*do_interrupt_common	/* interrupt service routine */
132ae115bc7Smrj	addl	$8, %esp		/* pop args off of stack */
1337c478bd9Sstevel@tonic-gate
134843e1988Sjohnlev	jmp	_sys_rtt_ints_disabled
135843e1988Sjohnlev	/*NOTREACHED*/
136843e1988Sjohnlev
1377c478bd9Sstevel@tonic-gate	SET_SIZE(cmnint)
1387c478bd9Sstevel@tonic-gate	SET_SIZE(_interrupt)
1397c478bd9Sstevel@tonic-gate
1407c478bd9Sstevel@tonic-gate#endif	/* __i386 */
1417c478bd9Sstevel@tonic-gate
1427c478bd9Sstevel@tonic-gate/*
1437c478bd9Sstevel@tonic-gate * Declare a uintptr_t which has the size of _interrupt to enable stack
1447c478bd9Sstevel@tonic-gate * traceback code to know when a regs structure is on the stack.
1457c478bd9Sstevel@tonic-gate */
1467c478bd9Sstevel@tonic-gate	.globl	_interrupt_size
1477c478bd9Sstevel@tonic-gate	.align	CLONGSIZE
1487c478bd9Sstevel@tonic-gate_interrupt_size:
1497c478bd9Sstevel@tonic-gate	.NWORD	. - _interrupt
1507c478bd9Sstevel@tonic-gate	.type	_interrupt_size, @object
1517c478bd9Sstevel@tonic-gate
1527c478bd9Sstevel@tonic-gate#endif	/* __lint */
1537c478bd9Sstevel@tonic-gate
1547c478bd9Sstevel@tonic-gate#if defined(__lint)
1557c478bd9Sstevel@tonic-gate
1567c478bd9Sstevel@tonic-gatevoid
1577c478bd9Sstevel@tonic-gatefakesoftint(void)
1587c478bd9Sstevel@tonic-gate{}
1597c478bd9Sstevel@tonic-gate
1607c478bd9Sstevel@tonic-gate#else	/* __lint */
1617c478bd9Sstevel@tonic-gate
1627c478bd9Sstevel@tonic-gate	/
1637c478bd9Sstevel@tonic-gate	/ If we're here, we're being called from splx() to fake a soft
1647c478bd9Sstevel@tonic-gate	/ interrupt (note that interrupts are still disabled from splx()).
1657c478bd9Sstevel@tonic-gate	/ We execute this code when a soft interrupt is posted at
1667c478bd9Sstevel@tonic-gate	/ level higher than the CPU's current spl; when spl is lowered in
1677c478bd9Sstevel@tonic-gate	/ splx(), it will see the softint and jump here.  We'll do exactly
1687c478bd9Sstevel@tonic-gate	/ what a trap would do:  push our flags, %cs, %eip, error code
1697c478bd9Sstevel@tonic-gate	/ and trap number (T_SOFTINT).  The cmnint() code will see T_SOFTINT
1707c478bd9Sstevel@tonic-gate	/ and branch to the dosoftint() code.
1717c478bd9Sstevel@tonic-gate	/
1727c478bd9Sstevel@tonic-gate#if defined(__amd64)
1737c478bd9Sstevel@tonic-gate
1747c478bd9Sstevel@tonic-gate	/*
1757c478bd9Sstevel@tonic-gate	 * In 64-bit mode, iretq -always- pops all five regs
1767c478bd9Sstevel@tonic-gate	 * Imitate the 16-byte auto-align of the stack, and the
1777c478bd9Sstevel@tonic-gate	 * zero-ed out %ss value.
1787c478bd9Sstevel@tonic-gate	 */
1797c478bd9Sstevel@tonic-gate	ENTRY_NP(fakesoftint)
1807c478bd9Sstevel@tonic-gate	movq	%rsp, %r11
1817c478bd9Sstevel@tonic-gate	andq	$-16, %rsp
1827c478bd9Sstevel@tonic-gate	pushq	$KDS_SEL	/* %ss */
1837c478bd9Sstevel@tonic-gate	pushq	%r11		/* %rsp */
1847c478bd9Sstevel@tonic-gate	pushf			/* rflags */
185843e1988Sjohnlev#if defined(__xpv)
186843e1988Sjohnlev	popq	%r11
187843e1988Sjohnlev	EVENT_MASK_TO_IE(%rdi, %r11)
188843e1988Sjohnlev	pushq	%r11
189843e1988Sjohnlev#endif
1907c478bd9Sstevel@tonic-gate	pushq	$KCS_SEL	/* %cs */
1917c478bd9Sstevel@tonic-gate	leaq	fakesoftint_return(%rip), %r11
1927c478bd9Sstevel@tonic-gate	pushq	%r11		/* %rip */
1937c478bd9Sstevel@tonic-gate	pushq	$0		/* err */
1947c478bd9Sstevel@tonic-gate	pushq	$T_SOFTINT	/* trap */
1957c478bd9Sstevel@tonic-gate	jmp	cmnint
196ae115bc7Smrj	ALTENTRY(fakesoftint_return)
197ae115bc7Smrj	ret
198ae115bc7Smrj	SET_SIZE(fakesoftint_return)
1997c478bd9Sstevel@tonic-gate	SET_SIZE(fakesoftint)
2007c478bd9Sstevel@tonic-gate
2017c478bd9Sstevel@tonic-gate#elif defined(__i386)
2027c478bd9Sstevel@tonic-gate
2037c478bd9Sstevel@tonic-gate	ENTRY_NP(fakesoftint)
204ae115bc7Smrj	pushfl
205843e1988Sjohnlev#if defined(__xpv)
206843e1988Sjohnlev	popl	%eax
207843e1988Sjohnlev	EVENT_MASK_TO_IE(%edx, %eax)
208843e1988Sjohnlev	pushl	%eax
209843e1988Sjohnlev#endif
210ae115bc7Smrj	pushl	%cs
211ae115bc7Smrj	pushl	$fakesoftint_return
212ae115bc7Smrj	pushl	$0
213ae115bc7Smrj	pushl	$T_SOFTINT
2147c478bd9Sstevel@tonic-gate	jmp	cmnint
215ae115bc7Smrj	ALTENTRY(fakesoftint_return)
216ae115bc7Smrj	ret
217ae115bc7Smrj	SET_SIZE(fakesoftint_return)
2187c478bd9Sstevel@tonic-gate	SET_SIZE(fakesoftint)
2197c478bd9Sstevel@tonic-gate
2207c478bd9Sstevel@tonic-gate#endif	/* __i386 */
2217c478bd9Sstevel@tonic-gate#endif	/* __lint */
222