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 /*
  23  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #if defined(__lint)
  28 
  29 #include <sys/systm.h>
  30 
  31 #else   /* __lint */
  32 
  33 #include "genassym.h"
  34 #include "../common/brand_asm.h"
  35 
  36 #endif  /* __lint */
  37 
  38 #ifdef  __lint
  39 
  40 void
  41 lx_brand_int80_callback(void)
  42 {
  43 }
  44 
  45 #else   /* __lint */
  46 
  47 #if defined(__amd64)
  48 
  49 /*
  50  * See "64-BIT INTERPOSITION STACK" in brand_asm.h.
  51  */
  52 ENTRY(lx_brand_int80_callback)
  53         GET_PROCP(SP_REG, 0, %r15)
  54         movq    P_ZONE(%r15), %r15              /* grab the zone pointer */
  55         /* grab the 'max syscall num' for this process from 'zone brand data' */
  56         movq    ZONE_BRAND_DATA(%r15), %r15     /* grab the zone brand ptr */
  57         movl    LXZD_MAX_SYSCALL(%r15), %r15d   /* get the 'max sysnum' word */
  58         cmpq    %r15, %rax                      /* is 0 <= syscall <= MAX? */
  59         jbe     0f                              /* yes, syscall is OK */
  60         xorl    %eax, %eax                      /* no, zero syscall number */
  61 0:
  62 
  63 .lx_brand_int80_patch_point:
  64         jmp     .lx_brand_int80_notrace
  65 
  66 .lx_brand_int80_notrace:
  67         CALC_TABLE_ADDR(%r15, L_HANDLER)
  68 1:
  69         movq    %r15, %rax
  70         GET_V(%rsp, 0, V_SSP, %rsp)     /* restore intr. stack pointer */
  71         xchgq   (%rsp), %rax            /* swap %rax and return addr */
  72         jmp     sys_sysint_swapgs_iret
  73 
  74 .lx_brand_int80_trace:
  75         /*
  76          * If tracing is active, we vector to an alternate trace-enabling
  77          * handler table instead.
  78          */
  79         CALC_TABLE_ADDR(%r15, L_TRACEHANDLER)
  80         jmp     1b
  81 SET_SIZE(lx_brand_int80_callback)
  82 
  83 #define PATCH_POINT     _CONST(.lx_brand_int80_patch_point + 1)
  84 #define PATCH_VAL       _CONST(.lx_brand_int80_trace - .lx_brand_int80_notrace)
  85 
  86 ENTRY(lx_brand_int80_enable)
  87         movl    $1, lx_systrace_brand_enabled(%rip)
  88         movq    $PATCH_POINT, %r8
  89         movb    $PATCH_VAL, (%r8)
  90         ret
  91 SET_SIZE(lx_brand_int80_enable)
  92 
  93 ENTRY(lx_brand_int80_disable)
  94         movq    $PATCH_POINT, %r8
  95         movb    $0, (%r8)
  96         movl    $0, lx_systrace_brand_enabled(%rip)
  97         ret
  98 SET_SIZE(lx_brand_int80_disable)
  99 
 100 
 101 #elif defined(__i386)
 102 
 103 /*
 104  * See "32-BIT INTERPOSITION STACK" in brand_asm.h.
 105  */
 106 ENTRY(lx_brand_int80_callback)
 107         GET_PROCP(SP_REG, 0, %ebx)
 108         movl    P_ZONE(%ebx), %ebx              /* grab the zone pointer */
 109         /* grab the 'max syscall num' for this process from 'zone brand data' */
 110         movl    ZONE_BRAND_DATA(%ebx), %ebx     /* grab the zone brand data */
 111         movl    LXZD_MAX_SYSCALL(%ebx), %ebx    /* get the max sysnum */
 112 
 113         cmpl    %ebx, %eax                      /* is 0 <= syscall <= MAX? */
 114         jbe     0f                              /* yes, syscall is OK */
 115         xorl    %eax, %eax                      /* no, zero syscall number */   
 116 0:
 117 
 118 .lx_brand_int80_patch_point:
 119         jmp     .lx_brand_int80_notrace
 120 
 121 .lx_brand_int80_notrace:
 122         CALC_TABLE_ADDR(%ebx, L_HANDLER)
 123 
 124 1:
 125         movl    %ebx, %eax
 126         GET_V(%esp, 0, V_U_EBX, %ebx)           /* restore scratch register */
 127         addl    $V_END, %esp            /* restore intr. stack ptr */
 128         xchgl   (%esp), %eax            /* swap new and orig. return addrs */
 129         jmp     nopop_sys_rtt_syscall
 130 
 131 .lx_brand_int80_trace:
 132         CALC_TABLE_ADDR(%ebx, L_TRACEHANDLER)
 133         jmp     1b
 134 SET_SIZE(lx_brand_int80_callback)
 135 
 136 
 137 #define PATCH_POINT     _CONST(.lx_brand_int80_patch_point + 1)
 138 #define PATCH_VAL       _CONST(.lx_brand_int80_trace - .lx_brand_int80_notrace)
 139 
 140 ENTRY(lx_brand_int80_enable)
 141         pushl   %ebx
 142         pushl   %eax
 143         movl    $1, lx_systrace_brand_enabled
 144         movl    $PATCH_POINT, %ebx
 145         movl    $PATCH_VAL, %eax
 146         movb    %al, (%ebx)
 147         popl    %eax
 148         popl    %ebx
 149         ret
 150 SET_SIZE(lx_brand_int80_enable)
 151 
 152 ENTRY(lx_brand_int80_disable)
 153         pushl   %ebx
 154         movl    $PATCH_POINT, %ebx
 155         movb    $0, (%ebx)
 156         movl    $0, lx_systrace_brand_enabled
 157         popl    %ebx
 158         ret
 159 SET_SIZE(lx_brand_int80_disable)
 160 
 161 #endif  /* __i386 */
 162 #endif  /* __lint */