root/usr/src/uts/i86pc/ml/interrupt.S
/*
 * 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 (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
 * Copyright 2019 Joyent, Inc.
 */

/*      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                                   */

#include <sys/asm_linkage.h>
#include <sys/asm_misc.h>
#include <sys/regset.h>
#include <sys/psw.h>
#include <sys/x86_archext.h>

#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"

        /*
         * 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 */
        movq    do_interrupt_common, %rax
        INDIRECT_CALL_REG(rax)

        jmp     _sys_rtt_ints_disabled
        /*NOTREACHED*/

        SET_SIZE(cmnint)
        SET_SIZE(_interrupt)

/*
 * 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

        /*
         * 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,
         * %rip, error code and trap number (T_SOFTINT).  The cmnint()
         * code will see T_SOFTINT and branch to the dosoftint() code.
         *
         * 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 */
#if defined(__xpv)
        popq    %r11
        EVENT_MASK_TO_IE(%rdi, %r11)
        pushq   %r11
#endif
        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)