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 
  59 void
  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 
 156 void
 157 fakesoftint(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 */