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 2007 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25/*
26 * Copyright 2015 Joyent, Inc.
27 */
28
29#include <sys/asm_linkage.h>
30#include <sys/regset.h>
31
32#if defined(lint)
33#include <sys/dtrace_impl.h>
34#else
35#include "assym.h"
36#endif
37
38#if defined(lint) || defined(__lint)
39
40greg_t
41dtrace_getfp(void)
42{ return (0); }
43
44#else	/* lint */
45
46#if defined(__amd64)
47
48	ENTRY_NP(dtrace_getfp)
49	movq	%rbp, %rax
50	ret
51	SET_SIZE(dtrace_getfp)
52
53#elif defined(__i386)
54
55	ENTRY_NP(dtrace_getfp)
56	movl	%ebp, %eax
57	ret
58	SET_SIZE(dtrace_getfp)
59
60#endif	/* __i386 */
61#endif	/* lint */
62
63
64#if defined(lint) || defined(__lint)
65
66/*ARGSUSED*/
67uint64_t
68dtrace_getvmreg(uint32_t reg, volatile uint16_t *flags)
69{ return (0); }
70
71#else	/* lint */
72
73#if defined(__amd64)
74
75	ENTRY_NP(dtrace_getvmreg)
76
77	movq	%rdi, %rdx
78	vmread	%rdx, %rax
79	ret
80
81	SET_SIZE(dtrace_getvmreg)
82
83#elif defined(__i386)
84
85	ENTRY_NP(dtrace_getvmreg)
86	pushl	%ebp			/ Setup stack frame
87	movl	%esp, %ebp
88
89	movl	12(%ebp), %eax		/ Load flag pointer
90	movw	(%eax), %cx		/ Load flags
91	orw	$CPU_DTRACE_ILLOP, %cx	/ Set ILLOP
92	movw	%cx, (%eax)		/ Store flags
93
94	leave
95	ret
96	SET_SIZE(dtrace_getvmreg)
97
98#endif	/* __i386 */
99#endif	/* lint */
100
101
102#if defined(lint) || defined(__lint)
103
104uint32_t
105dtrace_cas32(uint32_t *target, uint32_t cmp, uint32_t new)
106{
107	uint32_t old;
108
109	if ((old = *target) == cmp)
110		*target = new;
111	return (old);
112}
113
114void *
115dtrace_casptr(void *target, void *cmp, void *new)
116{
117	void *old;
118
119	if ((old = *(void **)target) == cmp)
120		*(void **)target = new;
121	return (old);
122}
123
124#else	/* lint */
125
126#if defined(__amd64)
127
128	ENTRY(dtrace_cas32)
129	movl	%esi, %eax
130	lock
131	cmpxchgl %edx, (%rdi)
132	ret
133	SET_SIZE(dtrace_cas32)
134
135	ENTRY(dtrace_casptr)
136	movq	%rsi, %rax
137	lock
138	cmpxchgq %rdx, (%rdi)
139	ret
140	SET_SIZE(dtrace_casptr)
141
142#elif defined(__i386)
143
144	ENTRY(dtrace_cas32)
145	ALTENTRY(dtrace_casptr)
146	movl	4(%esp), %edx
147	movl	8(%esp), %eax
148	movl	12(%esp), %ecx
149	lock
150	cmpxchgl %ecx, (%edx)
151	ret
152	SET_SIZE(dtrace_casptr)
153	SET_SIZE(dtrace_cas32)
154
155#endif	/* __i386 */
156#endif	/* lint */
157
158#if defined(lint)
159
160/*ARGSUSED*/
161uintptr_t
162dtrace_caller(int aframes)
163{
164	return (0);
165}
166
167#else	/* lint */
168
169#if defined(__amd64)
170	ENTRY(dtrace_caller)
171	movq	$-1, %rax
172	ret
173	SET_SIZE(dtrace_caller)
174
175#elif defined(__i386)
176
177	ENTRY(dtrace_caller)
178	movl	$-1, %eax
179	ret
180	SET_SIZE(dtrace_caller)
181
182#endif	/* __i386 */
183#endif	/* lint */
184
185#if defined(lint)
186
187/*ARGSUSED*/
188void
189dtrace_copy(uintptr_t src, uintptr_t dest, size_t size)
190{}
191
192#else
193
194#if defined(__amd64)
195
196	ENTRY(dtrace_copy)
197	pushq	%rbp
198	call	smap_disable
199	movq	%rsp, %rbp
200
201	xchgq	%rdi, %rsi		/* make %rsi source, %rdi dest */
202	movq	%rdx, %rcx		/* load count */
203	repz				/* repeat for count ... */
204	smovb				/*   move from %ds:rsi to %ed:rdi */
205	call	smap_enable
206	leave
207	ret
208	SET_SIZE(dtrace_copy)
209
210#elif defined(__i386)
211
212	ENTRY(dtrace_copy)
213	pushl	%ebp
214	movl	%esp, %ebp
215	pushl	%esi
216	pushl	%edi
217
218	movl	8(%ebp), %esi		/ Load source address
219	movl	12(%ebp), %edi		/ Load destination address
220	movl	16(%ebp), %ecx		/ Load count
221	repz				/ Repeat for count...
222	smovb				/   move from %ds:si to %es:di
223
224	popl	%edi
225	popl	%esi
226	movl	%ebp, %esp
227	popl	%ebp
228	ret
229	SET_SIZE(dtrace_copy)
230
231#endif	/* __i386 */
232#endif
233
234#if defined(lint)
235
236/*ARGSUSED*/
237void
238dtrace_copystr(uintptr_t uaddr, uintptr_t kaddr, size_t size,
239    volatile uint16_t *flags)
240{}
241
242#else
243
244#if defined(__amd64)
245
246	ENTRY(dtrace_copystr)
247	pushq	%rbp
248	movq	%rsp, %rbp
249	call	smap_disable
2500:
251	movb	(%rdi), %al		/* load from source */
252	movb	%al, (%rsi)		/* store to destination */
253	addq	$1, %rdi		/* increment source pointer */
254	addq	$1, %rsi		/* increment destination pointer */
255	subq	$1, %rdx		/* decrement remaining count */
256	cmpb	$0, %al
257	je	2f
258	testq	$0xfff, %rdx		/* test if count is 4k-aligned */
259	jnz	1f			/* if not, continue with copying */
260	testq	$CPU_DTRACE_BADADDR, (%rcx) /* load and test dtrace flags */
261	jnz	2f
2621:
263	cmpq	$0, %rdx
264	jne	0b
2652:
266	call	smap_enable
267	leave
268	ret
269
270	SET_SIZE(dtrace_copystr)
271
272#elif defined(__i386)
273
274	ENTRY(dtrace_copystr)
275
276	pushl	%ebp			/ Setup stack frame
277	movl	%esp, %ebp
278	pushl	%ebx			/ Save registers
279
280	movl	8(%ebp), %ebx		/ Load source address
281	movl	12(%ebp), %edx		/ Load destination address
282	movl	16(%ebp), %ecx		/ Load count
283
2840:
285	movb	(%ebx), %al		/ Load from source
286	movb	%al, (%edx)		/ Store to destination
287	incl	%ebx			/ Increment source pointer
288	incl	%edx			/ Increment destination pointer
289	decl	%ecx			/ Decrement remaining count
290	cmpb	$0, %al
291	je	2f
292	testl	$0xfff, %ecx		/ Check if count is 4k-aligned
293	jnz	1f
294	movl	20(%ebp), %eax		/ load flags pointer
295	testl	$CPU_DTRACE_BADADDR, (%eax) / load and test dtrace flags
296	jnz	2f
2971:
298	cmpl	$0, %ecx
299	jne	0b
300
3012:
302	popl	%ebx
303	movl	%ebp, %esp
304	popl	%ebp
305	ret
306
307	SET_SIZE(dtrace_copystr)
308
309#endif	/* __i386 */
310#endif
311
312#if defined(lint)
313
314/*ARGSUSED*/
315uintptr_t
316dtrace_fulword(void *addr)
317{ return (0); }
318
319#else
320#if defined(__amd64)
321
322	ENTRY(dtrace_fulword)
323	call	smap_disable
324	movq	(%rdi), %rax
325	call	smap_enable
326	ret
327	SET_SIZE(dtrace_fulword)
328
329#elif defined(__i386)
330
331	ENTRY(dtrace_fulword)
332	movl	4(%esp), %ecx
333	xorl	%eax, %eax
334	movl	(%ecx), %eax
335	ret
336	SET_SIZE(dtrace_fulword)
337
338#endif	/* __i386 */
339#endif
340
341#if defined(lint)
342
343/*ARGSUSED*/
344uint8_t
345dtrace_fuword8_nocheck(void *addr)
346{ return (0); }
347
348#else
349#if defined(__amd64)
350
351	ENTRY(dtrace_fuword8_nocheck)
352	call	smap_disable
353	xorq	%rax, %rax
354	movb	(%rdi), %al
355	call	smap_enable
356	ret
357	SET_SIZE(dtrace_fuword8_nocheck)
358
359#elif defined(__i386)
360
361	ENTRY(dtrace_fuword8_nocheck)
362	movl	4(%esp), %ecx
363	xorl	%eax, %eax
364	movzbl	(%ecx), %eax
365	ret
366	SET_SIZE(dtrace_fuword8_nocheck)
367
368#endif	/* __i386 */
369#endif
370
371#if defined(lint)
372
373/*ARGSUSED*/
374uint16_t
375dtrace_fuword16_nocheck(void *addr)
376{ return (0); }
377
378#else
379#if defined(__amd64)
380
381	ENTRY(dtrace_fuword16_nocheck)
382	call	smap_disable
383	xorq	%rax, %rax
384	movw	(%rdi), %ax
385	call	smap_enable
386	ret
387	SET_SIZE(dtrace_fuword16_nocheck)
388
389#elif defined(__i386)
390
391	ENTRY(dtrace_fuword16_nocheck)
392	movl	4(%esp), %ecx
393	xorl	%eax, %eax
394	movzwl	(%ecx), %eax
395	ret
396	SET_SIZE(dtrace_fuword16_nocheck)
397
398#endif	/* __i386 */
399#endif
400
401#if defined(lint)
402
403/*ARGSUSED*/
404uint32_t
405dtrace_fuword32_nocheck(void *addr)
406{ return (0); }
407
408#else
409#if defined(__amd64)
410
411	ENTRY(dtrace_fuword32_nocheck)
412	call	smap_disable
413	xorq	%rax, %rax
414	movl	(%rdi), %eax
415	call	smap_enable
416	ret
417	SET_SIZE(dtrace_fuword32_nocheck)
418
419#elif defined(__i386)
420
421	ENTRY(dtrace_fuword32_nocheck)
422	movl	4(%esp), %ecx
423	xorl	%eax, %eax
424	movl	(%ecx), %eax
425	ret
426	SET_SIZE(dtrace_fuword32_nocheck)
427
428#endif	/* __i386 */
429#endif
430
431#if defined(lint)
432
433/*ARGSUSED*/
434uint64_t
435dtrace_fuword64_nocheck(void *addr)
436{ return (0); }
437
438#else
439#if defined(__amd64)
440
441	ENTRY(dtrace_fuword64_nocheck)
442	call	smap_disable
443	movq	(%rdi), %rax
444	call	smap_enable
445	ret
446	SET_SIZE(dtrace_fuword64_nocheck)
447
448#elif defined(__i386)
449
450	ENTRY(dtrace_fuword64_nocheck)
451	movl	4(%esp), %ecx
452	xorl	%eax, %eax
453	xorl	%edx, %edx
454	movl	(%ecx), %eax
455	movl	4(%ecx), %edx
456	ret
457	SET_SIZE(dtrace_fuword64_nocheck)
458
459#endif	/* __i386 */
460#endif
461
462#if defined(lint) || defined(__lint)
463
464/*ARGSUSED*/
465void
466dtrace_probe_error(dtrace_state_t *state, dtrace_epid_t epid, int which,
467    int fault, int fltoffs, uintptr_t illval)
468{}
469
470#else	/* lint */
471#if defined(__amd64)
472
473	ENTRY(dtrace_probe_error)
474	pushq	%rbp
475	movq	%rsp, %rbp
476	subq	$0x8, %rsp
477	movq	%r9, (%rsp)
478	movq	%r8, %r9
479	movq	%rcx, %r8
480	movq	%rdx, %rcx
481	movq	%rsi, %rdx
482	movq	%rdi, %rsi
483	movl	dtrace_probeid_error(%rip), %edi
484	call	dtrace_probe
485	addq	$0x8, %rsp
486	leave
487	ret
488	SET_SIZE(dtrace_probe_error)
489
490#elif defined(__i386)
491
492	ENTRY(dtrace_probe_error)
493	pushl	%ebp
494	movl	%esp, %ebp
495	pushl	0x1c(%ebp)
496	pushl	0x18(%ebp)
497	pushl	0x14(%ebp)
498	pushl	0x10(%ebp)
499	pushl	0xc(%ebp)
500	pushl	0x8(%ebp)
501	pushl	dtrace_probeid_error
502	call	dtrace_probe
503	movl	%ebp, %esp
504	popl	%ebp
505	ret
506	SET_SIZE(dtrace_probe_error)
507
508#endif	/* __i386 */
509#endif
510