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