xref: /titanic_41/usr/src/uts/intel/amd64/ml/amd64.il (revision fd9cb95cbb2f626355a60efb9d02c5f0a33c10e6)
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, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#pragma ident	"%Z%%M%	%I%	%E% SMI"
28
29/
30/ In-line functions for amd64 kernels.
31/
32
33/
34/ return current thread pointer
35/
36/ NOTE: the "0x18" should be replaced by the computed value of the
37/	offset of "cpu_thread" from the beginning of the struct cpu.
38/	Including "assym.h" does not work, however, since that stuff
39/	is PSM-specific and is only visible to the 'unix' build anyway.
40/	Same with current cpu pointer, where "0xc" should be replaced
41/	by the computed value of the offset of "cpu_self".
42/	Ugh -- what a disaster.
43/
44	.inline	threadp,0
45	movq	%gs:0x18, %rax
46	.end
47
48/
49/ return current cpu pointer
50/
51	.inline	curcpup,0
52	movq	%gs:0x10, %rax
53	.end
54
55/
56/ return caller
57/
58	.inline caller,0
59	movq	8(%rbp), %rax
60	.end
61
62/
63/ return value of cr3 register
64/
65	.inline	getcr3,0
66	movq	%cr3, %rax
67	.end
68
69/
70/ reload cr3 register with its current value
71/
72	.inline	reload_cr3,0
73	movq	%cr3, %rdi
74	movq	%rdi, %cr3
75	.end
76
77/
78/ return value of cr8 register
79/
80	.inline	getcr8,0
81	movq	%cr8, %rax
82	.end
83
84/
85/ set cr8 register
86/
87	.inline	setcr8,0
88	movq	%rdi, %cr8
89	.end
90
91/
92/ convert ipl to spl.  This is the identity function for i86
93/
94	.inline	ipltospl,0
95	movq	%rdi, %rax
96	.end
97
98/
99/ enable interrupts
100/
101	.inline	sti,0
102	sti
103	.end
104
105/
106/ disable interrupts
107/
108	.inline cli,0
109	cli
110	.end
111
112/
113/ find the low order bit in a word
114/
115	.inline lowbit,4
116	movq	$-1, %rax
117	bsfq	%rdi, %rax
118	incq	%rax
119	.end
120
121/
122/ disable interrupts and return value describing if interrupts were enabled
123/
124	/* XX64 These don't work correctly with SOS9 build 13.0 yet
125	.inline	clear_int_flag,0
126	pushfq
127	cli
128	popq	%rax
129	.end
130
131	.inline	intr_clear,0
132	pushfq
133	cli
134	popq	%rax
135	.end
136	*/
137
138/
139/ restore interrupt enable flag to value returned from 'clear_int_flag' above
140/
141	/* XX64 These don't work correctly with SOS9 build 13.0 yet
142	.inline restore_int_flag,4
143	pushq	%rdi
144	popfq
145	.end
146
147	.inline intr_restore,4
148	pushq	%rdi
149	popfq
150	.end
151	*/
152
153/
154/ in and out
155/
156	.inline	inb,4
157	movq	%rdi, %rdx
158	xorq    %rax, %rax
159	inb	(%dx)
160	.end
161
162	.inline	inw,4
163	movq	%rdi, %rdx
164	xorq    %rax, %rax
165	inw	(%dx)
166	.end
167
168	.inline	inl,4
169	movq	%rdi, %rdx
170	xorq    %rax, %rax
171	inl	(%dx)
172	.end
173
174	.inline	outb,8
175	movq	%rdi, %rdx
176	movq	%rsi, %rax
177	outb	(%dx)
178	.end
179
180	.inline	outw,8
181	movq	%rdi, %rdx
182	movq	%rsi, %rax
183	outw	(%dx)
184	.end
185
186	.inline	outl,8
187	movq	%rdi, %rdx
188	movq	%rsi, %rax
189	outl	(%dx)
190	.end
191
192/
193/ Networking byte order functions (too bad, Intel has the wrong byte order)
194/
195
196	.inline	htonl,4
197	movl	%edi, %eax
198	bswap	%eax
199	.end
200
201	.inline	ntohl,4
202	movl	%edi, %eax
203	bswap	%eax
204	.end
205
206	.inline	htons,4
207	movl	%edi, %eax
208	bswap	%eax
209	shrl	$16, %eax
210	.end
211
212	.inline	ntohs,4
213	movl	%edi, %eax
214	bswap	%eax
215	shrl	$16, %eax
216	.end
217
218/*
219 * multiply two long numbers and yield a u_lonlong_t result
220 * Provided to manipulate hrtime_t values.
221 */
222	/* XX64 These don't work correctly with SOS9 build 13.0 yet
223	.inline mul32, 8
224	xorl	%edx, %edx
225	movl	%edi, %eax
226	mull	%esi
227	shlq	$32, %rdx
228	orq	%rdx, %rax
229	ret
230	.end
231	*/
232/*
233 * Unlock hres_lock and increment the count value. (See clock.h)
234 */
235	.inline unlock_hres_lock, 0
236	lock
237	incl	hres_lock
238	.end
239
240	.inline	atomic_orb,8
241	movl	%esi, %eax
242	lock
243	orb	%al,(%rdi)
244	.end
245
246	.inline	atomic_andb,8
247	movl	%esi, %eax
248	lock
249	andb	%al,(%rdi)
250	.end
251
252/*
253 * atomic inc/dec operations.
254 *	void atomic_inc16(uint16_t *addr) { ++*addr; }
255 *	void atomic_dec16(uint16_t *addr) { --*addr; }
256 */
257	.inline	atomic_inc16,4
258	lock
259	incw	(%rdi)
260	.end
261
262	.inline	atomic_dec16,4
263	lock
264	decw	(%rdi)
265	.end
266
267/*
268 * atomic bit clear
269 */
270	.inline atomic_btr32,8
271	lock
272	btrl %esi, (%rdi)
273	setc %al
274	.end
275
276/*
277 * Read Time Stamp Counter
278 * uint64_t tsc_read();
279 *
280 * usage:
281 * uint64_t cycles = tsc_read();
282 *
283 * PPro & PII take no less than 34 cycles to execute rdtsc + stores.
284 * Pentium takes about 16 cycles.
285 */
286	.inline	tsc_read, 0
287	rdtsc				/ %edx:%eax = RDTSC
288	shlq	$32, %rdx
289	orq	%rdx, %rax
290	.end
291
292/*
293 * Call the pause instruction.  To the Pentium 4 Xeon processor, it acts as
294 * a hint that the code sequence is a busy spin-wait loop.  Without a pause
295 * instruction in these loops, the P4 Xeon processor may suffer a severe
296 * penalty when exiting the loop because the processor detects a possible
297 * memory violation.  Inserting the pause instruction significantly reduces
298 * the likelihood of a memory order violation, improving performance.
299 * The pause instruction is a NOP on all other IA-32 processors.
300 */
301	.inline ht_pause, 0
302	pause
303	.end
304
305/*
306 * Call the halt instruction. This will put the CPU to sleep until
307 * it is again awoken via an interrupt.
308 * This function should be called with interrupts already disabled
309 * for the CPU.
310 * Note that "sti" will only enable interrupts at the end of the
311 * subsequent instruction...in this case: "hlt".
312 */
313	.inline i86_halt,0
314	sti
315	hlt
316	.end
317