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 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #if defined(lint) || defined(DS_DDICT)
27 #include <sys/types.h>
28 #include <sys/param.h>
29 #else
30 #include "assym.h" /* Determine value of CPU_THREAD */
31 #include <sys/asm_linkage.h>
32 #endif
33
34 #ifdef DS_DDICT
35 #define uint8_t uchar_t
36 #endif
37
38
39 /*
40 * Special support routines that can't be done with C
41 * x86 variant
42 */
43
44 /*
45 * uint8_t nsc_ldstub(uint8_t *cp)
46 *
47 * Store 0xFF at the specified location, and return its previous content.
48 */
49
50 #if defined(lint) || defined(DS_DDICT)
51 uint8_t
52 nsc_ldstub(uint8_t *cp)
53 {
54 uint8_t rv;
55 rv = *cp;
56 *cp = 0xFF;
57 return (rv);
58 }
59 #else
60 ENTRY(nsc_ldstub)
61 #if defined(__amd64)
62 movl $0xff,%eax
63 lock
64 xchgb %al, (%rdi) /* rdi = lock addr */
65 ret
66 #elif defined(__i386)
67 movl 4(%esp), %ecx /* ecx = lock addr */
68 movl $0xff, %eax /* eax = 0xff */
69 lock
70 xchgb %al, (%ecx) /* atomic swap eax <-> *ecx */
71 ret
72 #else
73 #error "port this routine"
74 #endif
75 SET_SIZE(nsc_ldstub)
76 #endif
77
78 /*
79 * nsc_membar_stld(void)
80 *
81 * On SPARC this is a C callable interface to SPARC asm membar instruction.
82 * For x86 we brute force it with a #LOCK instruction.
83 */
84
85 #if defined(lint) || defined(DS_DDICT)
86 void
87 nsc_membar_stld(void)
88 {}
89 #else
90
91 ENTRY(nsc_membar_stld)
92 #if defined(__amd64)
93 mfence
94 ret
95 #elif defined(__i386)
96 lock
97 xorl $0, (%esp)
98 ret
99 #else
100 #error "port this routine"
101 #endif
102 SET_SIZE(nsc_membar_stld)
103
104 #endif /* lint || DS_DDICT */
105
106
107 /*
108 * if a() calls b() calls nsc_caller(),
109 * nsc_caller() returns return address in a().
110 */
111
112 #if defined(lint) || defined(DS_DDICT)
113 caddr_t
114 nsc_caller(void)
115 {
116 return (0);
117 }
118 #else
119
120 ENTRY(nsc_caller)
121 #if defined(__amd64)
122 movq 8(%rbp), %rax /* b()'s return pc, in a() */
123 ret
124 #elif defined(__i386)
125 movl 4(%ebp), %eax /* b()'s return pc, in a() */
126 ret
127 #else
128 #error "port this routine"
129 #endif
130 SET_SIZE(nsc_caller)
131
132 #endif /* lint || DS_DDICT */
133
134
135 /*
136 * if a() calls nsc_callee(), nsc_callee() returns the
137 * return address in a();
138 */
139
140 #if defined(lint) || defined(DS_DDICT)
141 caddr_t
142 nsc_callee(void)
143 {
144 return (0);
145 }
146 #else
147
148 ENTRY(nsc_callee)
149 #if defined(__amd64)
150 movq (%rsp), %rax /* callee()'s return pc, in a() */
151 ret
152 #elif defined(__i386)
153 movl (%esp), %eax /* callee()'s return pc, in a() */
154 ret
155 #else
156 #error "port this routine"
157 #endif
158 SET_SIZE(nsc_callee)
159
160 #endif /* lint || DS_DDICT */
161
162
163 /*
164 * nsc_threadp(void)
165 *
166 * C callable interface to get the current thread pointer.
167 */
168
169 #if defined(lint) || defined(DS_DDICT)
170 void *
171 nsc_threadp(void)
172 {
173 return (NULL);
174 }
175 #else
176
177 ENTRY(nsc_threadp)
178 #if defined(__amd64)
179 movq %gs:CPU_THREAD, %rax
180 ret
181 #elif defined(__i386)
182 movl %gs:CPU_THREAD,%eax
183 ret
184 #else
185 #error "port this routine"
186 #endif
187 SET_SIZE(nsc_threadp)
188
189 #endif /* lint || DS_DDICT */