interrupt.s revision ae115bc77f6fcde83175c75b4206dc2e50747966
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
/* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */
/* All Rights Reserved */
/* Copyright (c) 1987, 1988 Microsoft Corporation */
/* All Rights Reserved */
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/asm_linkage.h>
#include <sys/asm_misc.h>
#include <sys/regset.h>
#include <sys/psw.h>
#include <sys/x86_archext.h>
#if defined(__lint)
#include <sys/types.h>
#include <sys/thread.h>
#include <sys/systm.h>
#else /* __lint */
#include <sys/segments.h>
#include <sys/pcb.h>
#include <sys/trap.h>
#include <sys/ftrace.h>
#include <sys/traptrace.h>
#include <sys/clock.h>
#include <sys/panic.h>
#include "assym.h"
#endif /* lint */
#if defined(__i386)
#if defined(__lint)
void
patch_tsc(void)
{}
#else /* __lint */
/*
* To cope with processors that do not implement the rdtsc instruction,
* we patch the kernel to use rdtsc if that feature is detected on the CPU.
* On an unpatched kernel, all locations requiring rdtsc are nop's.
*
* This function patches the nop's to rdtsc.
*/
ENTRY_NP(patch_tsc)
movw _rdtsc_insn, %cx
movw %cx, _tsc_patch15
movw %cx, _tsc_patch16
ret
_rdtsc_insn:
rdtsc
SET_SIZE(patch_tsc)
#endif /* __lint */
#endif /* __i386 */
#if defined(__lint)
void
_interrupt(void)
{}
#else /* __lint */
#if defined(__amd64)
/*
* Common register usage:
*
* %r12 trap trace pointer
*/
ENTRY_NP2(cmnint, _interrupt)
INTR_PUSH
INTGATE_INIT_KERNEL_FLAGS /* (set kernel rflags values) */
/*
* At the end of TRACE_PTR %r12 points to the current TRAPTRACE entry
*/
TRACE_PTR(%r12, %rax, %eax, %rdx, $TT_INTERRUPT)
/* Uses labels 8 and 9 */
TRACE_REGS(%r12, %rsp, %rax, %rbx) /* Uses label 9 */
TRACE_STAMP(%r12) /* Clobbers %eax, %edx, uses 9 */
movq %rsp, %rbp
TRACE_STACK(%r12)
#ifdef TRAPTRACE
LOADCPU(%rbx) /* &cpu */
movl CPU_PRI(%rbx), %r14d /* old ipl */
movl $255, TTR_IPL(%r12)
movl %r14d, %edi
movb %dil, TTR_PRI(%r12)
movl CPU_BASE_SPL(%rbx), %edi
movb %dil, TTR_SPL(%r12)
movb $255, TTR_VECTOR(%r12)
movq %r12, %rsi /* pass traptrace record pointer */
#endif
movq %rsp, %rdi /* pass struct regs pointer */
call do_interrupt
jmp _sys_rtt
/*NOTREACHED*/
SET_SIZE(cmnint)
SET_SIZE(_interrupt)
#elif defined(__i386)
ENTRY_NP2(cmnint, _interrupt)
INTR_PUSH
INTGATE_INIT_KERNEL_FLAGS
/*
* At the end of TRACE_PTR %esi points to the current TRAPTRACE entry
*/
TRACE_PTR(%esi, %eax, %eax, %edx, $TT_INTERRUPT)
/* Uses labels 8 and 9 */
TRACE_REGS(%esi, %esp, %eax, %ebx) /* Uses label 9 */
TRACE_STAMP(%esi) /* Clobbers %eax, %edx, uses 9 */
movl %esp, %ebp
TRACE_STACK(%esi)
pushl %esi /* pass traptrace record pointer */
pushl %ebp /* pass struct regs pointer */
call do_interrupt /* interrupt service routine */
addl $8, %esp /* pop args off of stack */
jmp _sys_rtt
SET_SIZE(cmnint)
SET_SIZE(_interrupt)
#endif /* __i386 */
/*
* Declare a uintptr_t which has the size of _interrupt to enable stack
* traceback code to know when a regs structure is on the stack.
*/
.globl _interrupt_size
.align CLONGSIZE
_interrupt_size:
.NWORD . - _interrupt
.type _interrupt_size, @object
#endif /* __lint */
#if defined(__lint)
void
fakesoftint(void)
{}
#else /* __lint */
/
/ If we're here, we're being called from splx() to fake a soft
/ interrupt (note that interrupts are still disabled from splx()).
/ We execute this code when a soft interrupt is posted at
/ level higher than the CPU's current spl; when spl is lowered in
/ splx(), it will see the softint and jump here. We'll do exactly
/ what a trap would do: push our flags, %cs, %eip, error code
/ and trap number (T_SOFTINT). The cmnint() code will see T_SOFTINT
/ and branch to the dosoftint() code.
/
#if defined(__amd64)
/*
* In 64-bit mode, iretq -always- pops all five regs
* Imitate the 16-byte auto-align of the stack, and the
* zero-ed out %ss value.
*/
ENTRY_NP(fakesoftint)
movq %rsp, %r11
andq $-16, %rsp
pushq $KDS_SEL /* %ss */
pushq %r11 /* %rsp */
pushf /* rflags */
pushq $KCS_SEL /* %cs */
leaq fakesoftint_return(%rip), %r11
pushq %r11 /* %rip */
pushq $0 /* err */
pushq $T_SOFTINT /* trap */
jmp cmnint
ALTENTRY(fakesoftint_return)
ret
SET_SIZE(fakesoftint_return)
SET_SIZE(fakesoftint)
#elif defined(__i386)
ENTRY_NP(fakesoftint)
pushfl
pushl %cs
pushl $fakesoftint_return
pushl $0
pushl $T_SOFTINT
jmp cmnint
ALTENTRY(fakesoftint_return)
ret
SET_SIZE(fakesoftint_return)
SET_SIZE(fakesoftint)
#endif /* __i386 */
#endif /* __lint */