1757Sdg/*-
2757Sdg * Copyright (c) 1993 The Regents of the University of California.
3757Sdg * All rights reserved.
4757Sdg *
5757Sdg * Redistribution and use in source and binary forms, with or without
6757Sdg * modification, are permitted provided that the following conditions
7757Sdg * are met:
8757Sdg * 1. Redistributions of source code must retain the above copyright
9757Sdg *    notice, this list of conditions and the following disclaimer.
10757Sdg * 2. Redistributions in binary form must reproduce the above copyright
11757Sdg *    notice, this list of conditions and the following disclaimer in the
12757Sdg *    documentation and/or other materials provided with the distribution.
13757Sdg * 4. Neither the name of the University nor the names of its contributors
14757Sdg *    may be used to endorse or promote products derived from this software
15757Sdg *    without specific prior written permission.
16757Sdg *
17757Sdg * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18757Sdg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19757Sdg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20757Sdg * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21757Sdg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22757Sdg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23757Sdg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24757Sdg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25757Sdg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26757Sdg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27757Sdg * SUCH DAMAGE.
28757Sdg *
2950477Speter * $FreeBSD$
30757Sdg */
31757Sdg
3271257Speter#include "opt_npx.h"
33757Sdg
3418207Sbde#include <machine/asmacros.h>
3518207Sbde#include <machine/cputypes.h>
36121983Sjhb#include <machine/intr_machdep.h>
3721979Sbde#include <machine/pmap.h>
3818207Sbde#include <machine/specialreg.h>
3918207Sbde
4018207Sbde#include "assym.s"
4118207Sbde
42757Sdg#define IDXSHIFT	10
43757Sdg
4413085Sdg	.text
4513085Sdg
46757Sdg/*
47757Sdg * bcopy family
4818428Sbde * void bzero(void *buf, u_int len)
491247Sdg */
50113090SdesENTRY(bzero)
51757Sdg	pushl	%edi
52757Sdg	movl	8(%esp),%edi
53757Sdg	movl	12(%esp),%ecx
54757Sdg	xorl	%eax,%eax
55757Sdg	shrl	$2,%ecx
56757Sdg	cld
57757Sdg	rep
58757Sdg	stosl
59757Sdg	movl	12(%esp),%ecx
60757Sdg	andl	$3,%ecx
61757Sdg	rep
62757Sdg	stosb
63757Sdg	popl	%edi
64757Sdg	ret
65209460SkibEND(bzero)
66171916Sjkoshy
67120620SjeffENTRY(sse2_pagezero)
68120620Sjeff	pushl	%ebx
69120620Sjeff	movl	8(%esp),%ecx
70120620Sjeff	movl	%ecx,%eax
71120620Sjeff	addl	$4096,%eax
72120620Sjeff	xor	%ebx,%ebx
73120620Sjeff1:
74120620Sjeff	movnti	%ebx,(%ecx)
75120620Sjeff	addl	$4,%ecx
76120620Sjeff	cmpl	%ecx,%eax
77120620Sjeff	jne	1b
78120627Sjeff	sfence
79120620Sjeff	popl	%ebx
80120620Sjeff	ret
81171916SjkoshyEND(sse2_pagezero)
82120620Sjeff
8335933SdysonENTRY(i686_pagezero)
8435933Sdyson	pushl	%edi
8535933Sdyson	pushl	%ebx
8635933Sdyson
87168088Sjkim	movl	12(%esp),%edi
88168088Sjkim	movl	$1024,%ecx
8935933Sdyson	cld
9035933Sdyson
9135933Sdyson	ALIGN_TEXT
9235933Sdyson1:
93168088Sjkim	xorl	%eax,%eax
9435933Sdyson	repe
95113090Sdes	scasl
9635933Sdyson	jnz	2f
9735933Sdyson
9835933Sdyson	popl	%ebx
9935933Sdyson	popl	%edi
10035933Sdyson	ret
10135933Sdyson
10235933Sdyson	ALIGN_TEXT
10335933Sdyson
10435933Sdyson2:
10535933Sdyson	incl	%ecx
106168088Sjkim	subl	$4,%edi
10735933Sdyson
108168088Sjkim	movl	%ecx,%edx
109168088Sjkim	cmpl	$16,%ecx
11035933Sdyson
11135933Sdyson	jge	3f
11235933Sdyson
113168088Sjkim	movl	%edi,%ebx
114168088Sjkim	andl	$0x3f,%ebx
11535933Sdyson	shrl	%ebx
11635933Sdyson	shrl	%ebx
117168088Sjkim	movl	$16,%ecx
118168088Sjkim	subl	%ebx,%ecx
11935933Sdyson
12035933Sdyson3:
121168088Sjkim	subl	%ecx,%edx
12235933Sdyson	rep
12335933Sdyson	stosl
12435933Sdyson
125168088Sjkim	movl	%edx,%ecx
126168088Sjkim	testl	%edx,%edx
12735933Sdyson	jnz	1b
12835933Sdyson
12935933Sdyson	popl	%ebx
13035933Sdyson	popl	%edi
13135933Sdyson	ret
132171916SjkoshyEND(i686_pagezero)
13335933Sdyson
134757Sdg/* fillw(pat, base, cnt) */
135757SdgENTRY(fillw)
136757Sdg	pushl	%edi
137757Sdg	movl	8(%esp),%eax
138757Sdg	movl	12(%esp),%edi
139757Sdg	movl	16(%esp),%ecx
140757Sdg	cld
141757Sdg	rep
142757Sdg	stosw
143757Sdg	popl	%edi
144757Sdg	ret
145171916SjkoshyEND(fillw)
146757Sdg
147757SdgENTRY(bcopyb)
148757Sdg	pushl	%esi
149757Sdg	pushl	%edi
150757Sdg	movl	12(%esp),%esi
151757Sdg	movl	16(%esp),%edi
152757Sdg	movl	20(%esp),%ecx
15313065Sdg	movl	%edi,%eax
15413065Sdg	subl	%esi,%eax
15518835Sbde	cmpl	%ecx,%eax			/* overlapping && src < dst? */
15613065Sdg	jb	1f
157757Sdg	cld					/* nope, copy forwards */
158757Sdg	rep
159757Sdg	movsb
160757Sdg	popl	%edi
161757Sdg	popl	%esi
162757Sdg	ret
163757Sdg
164757Sdg	ALIGN_TEXT
165757Sdg1:
166757Sdg	addl	%ecx,%edi			/* copy backwards. */
167757Sdg	addl	%ecx,%esi
168757Sdg	decl	%edi
169757Sdg	decl	%esi
17013065Sdg	std
171757Sdg	rep
172757Sdg	movsb
173757Sdg	popl	%edi
174757Sdg	popl	%esi
175757Sdg	cld
176757Sdg	ret
177171916SjkoshyEND(bcopyb)
178757Sdg
179757Sdg/*
180209460Skib * bcopy(src, dst, cnt)
181757Sdg *  ws@tools.de     (Wolfgang Solfrank, TooLs GmbH) +49-228-985800
182757Sdg */
183209460SkibENTRY(bcopy)
184253328Skib	pushl	%ebp
185253328Skib	movl	%esp,%ebp
186757Sdg	pushl	%esi
187757Sdg	pushl	%edi
188253328Skib	movl	8(%ebp),%esi
189253328Skib	movl	12(%ebp),%edi
190253328Skib	movl	16(%ebp),%ecx
19113065Sdg
19213065Sdg	movl	%edi,%eax
19313065Sdg	subl	%esi,%eax
19418835Sbde	cmpl	%ecx,%eax			/* overlapping && src < dst? */
19513065Sdg	jb	1f
19618428Sbde
1971691Sdg	shrl	$2,%ecx				/* copy by 32-bit words */
1981689Sdg	cld					/* nope, copy forwards */
199757Sdg	rep
200757Sdg	movsl
201253328Skib	movl	16(%ebp),%ecx
202757Sdg	andl	$3,%ecx				/* any bytes left? */
203757Sdg	rep
204757Sdg	movsb
205757Sdg	popl	%edi
206757Sdg	popl	%esi
207253328Skib	popl	%ebp
208757Sdg	ret
209757Sdg
210757Sdg	ALIGN_TEXT
211757Sdg1:
212757Sdg	addl	%ecx,%edi			/* copy backwards */
213757Sdg	addl	%ecx,%esi
214757Sdg	decl	%edi
215757Sdg	decl	%esi
21613065Sdg	andl	$3,%ecx				/* any fractional bytes? */
2171691Sdg	std
218757Sdg	rep
219757Sdg	movsb
220253328Skib	movl	16(%ebp),%ecx			/* copy remainder by 32-bit words */
221757Sdg	shrl	$2,%ecx
222757Sdg	subl	$3,%esi
223757Sdg	subl	$3,%edi
224757Sdg	rep
225757Sdg	movsl
226757Sdg	popl	%edi
227757Sdg	popl	%esi
228757Sdg	cld
229253328Skib	popl	%ebp
230757Sdg	ret
231209460SkibEND(bcopy)
232757Sdg
2338214Sdg/*
2348214Sdg * Note: memcpy does not support overlapping copies
2358214Sdg */
2368214SdgENTRY(memcpy)
2378214Sdg	pushl	%edi
2388214Sdg	pushl	%esi
2398214Sdg	movl	12(%esp),%edi
2408214Sdg	movl	16(%esp),%esi
2418214Sdg	movl	20(%esp),%ecx
2428214Sdg	movl	%edi,%eax
2438214Sdg	shrl	$2,%ecx				/* copy by 32-bit words */
2448214Sdg	cld					/* nope, copy forwards */
2458214Sdg	rep
2468214Sdg	movsl
2478214Sdg	movl	20(%esp),%ecx
2488214Sdg	andl	$3,%ecx				/* any bytes left? */
2498214Sdg	rep
2508214Sdg	movsb
2518214Sdg	popl	%esi
2528214Sdg	popl	%edi
2538214Sdg	ret
254171916SjkoshyEND(memcpy)
2558214Sdg
256757Sdg/*****************************************************************************/
257757Sdg/* copyout and fubyte family                                                 */
258757Sdg/*****************************************************************************/
259757Sdg/*
260757Sdg * Access user memory from inside the kernel. These routines and possibly
261757Sdg * the math- and DOS emulators should be the only places that do this.
262757Sdg *
263757Sdg * We have to access the memory with user's permissions, so use a segment
264757Sdg * selector with RPL 3. For writes to user space we have to additionally
265757Sdg * check the PTE for write permission, because the 386 does not check
266757Sdg * write permissions when we are executing with EPL 0. The 486 does check
267757Sdg * this if the WP bit is set in CR0, so we can use a simpler version here.
268757Sdg *
269249439Skib * These routines set curpcb->pcb_onfault for the time they execute. When a
270757Sdg * protection violation occurs inside the functions, the trap handler
271249439Skib * returns to *curpcb->pcb_onfault instead of the function.
272757Sdg */
273757Sdg
27458941Sdillon/*
275137784Sjhb * copyout(from_kernel, to_user, len)  - MP SAFE
27658941Sdillon */
27719653SbdeENTRY(copyout)
27869971Sjake	movl	PCPU(CURPCB),%eax
279757Sdg	movl	$copyout_fault,PCB_ONFAULT(%eax)
280757Sdg	pushl	%esi
281757Sdg	pushl	%edi
282757Sdg	pushl	%ebx
283757Sdg	movl	16(%esp),%esi
284757Sdg	movl	20(%esp),%edi
285757Sdg	movl	24(%esp),%ebx
2866325Sdg	testl	%ebx,%ebx			/* anything to do? */
287757Sdg	jz	done_copyout
288757Sdg
289757Sdg	/*
290757Sdg	 * Check explicitly for non-user addresses.  If 486 write protection
291757Sdg	 * is being used, this check is essential because we are in kernel
292757Sdg	 * mode so the h/w does not provide any protection against writing
293757Sdg	 * kernel addresses.
294757Sdg	 */
2956325Sdg
2966325Sdg	/*
2976325Sdg	 * First, prevent address wrapping.
2986325Sdg	 */
299757Sdg	movl	%edi,%eax
300757Sdg	addl	%ebx,%eax
301757Sdg	jc	copyout_fault
3021321Sdg/*
3031321Sdg * XXX STOP USING VM_MAXUSER_ADDRESS.
3041321Sdg * It is an end address, not a max, so every time it is used correctly it
3051321Sdg * looks like there is an off by one error, and of course it caused an off
3061321Sdg * by one error in several places.
3071321Sdg */
308974Sdg	cmpl	$VM_MAXUSER_ADDRESS,%eax
309757Sdg	ja	copyout_fault
310757Sdg
311757Sdg	/* bcopy(%esi, %edi, %ebx) */
312757Sdg	movl	%ebx,%ecx
31316344Sasami
314757Sdg	shrl	$2,%ecx
3151691Sdg	cld
316757Sdg	rep
317757Sdg	movsl
318757Sdg	movb	%bl,%cl
3191321Sdg	andb	$3,%cl
320757Sdg	rep
321757Sdg	movsb
322757Sdg
323757Sdgdone_copyout:
324757Sdg	popl	%ebx
325757Sdg	popl	%edi
326757Sdg	popl	%esi
327757Sdg	xorl	%eax,%eax
32869971Sjake	movl	PCPU(CURPCB),%edx
329757Sdg	movl	%eax,PCB_ONFAULT(%edx)
330757Sdg	ret
331209460SkibEND(copyout)
332757Sdg
333757Sdg	ALIGN_TEXT
334757Sdgcopyout_fault:
335757Sdg	popl	%ebx
336757Sdg	popl	%edi
337757Sdg	popl	%esi
33869971Sjake	movl	PCPU(CURPCB),%edx
339757Sdg	movl	$0,PCB_ONFAULT(%edx)
340757Sdg	movl	$EFAULT,%eax
341757Sdg	ret
342757Sdg
34319653Sbde/*
34458941Sdillon * copyin(from_user, to_kernel, len) - MP SAFE
34558717Sdillon */
346757SdgENTRY(copyin)
34769971Sjake	movl	PCPU(CURPCB),%eax
348757Sdg	movl	$copyin_fault,PCB_ONFAULT(%eax)
349757Sdg	pushl	%esi
350757Sdg	pushl	%edi
351757Sdg	movl	12(%esp),%esi			/* caddr_t from */
352757Sdg	movl	16(%esp),%edi			/* caddr_t to */
353757Sdg	movl	20(%esp),%ecx			/* size_t  len */
354757Sdg
3551690Sdg	/*
3561690Sdg	 * make sure address is valid
3571690Sdg	 */
3581690Sdg	movl	%esi,%edx
3591690Sdg	addl	%ecx,%edx
3601690Sdg	jc	copyin_fault
3611690Sdg	cmpl	$VM_MAXUSER_ADDRESS,%edx
3621690Sdg	ja	copyin_fault
3631690Sdg
364757Sdg	movb	%cl,%al
365757Sdg	shrl	$2,%ecx				/* copy longword-wise */
366757Sdg	cld
367757Sdg	rep
368757Sdg	movsl
369757Sdg	movb	%al,%cl
370757Sdg	andb	$3,%cl				/* copy remaining bytes */
371757Sdg	rep
372757Sdg	movsb
373757Sdg
374757Sdg	popl	%edi
375757Sdg	popl	%esi
376757Sdg	xorl	%eax,%eax
37769971Sjake	movl	PCPU(CURPCB),%edx
378757Sdg	movl	%eax,PCB_ONFAULT(%edx)
379757Sdg	ret
380209460SkibEND(copyin)
381757Sdg
382757Sdg	ALIGN_TEXT
383757Sdgcopyin_fault:
384757Sdg	popl	%edi
385757Sdg	popl	%esi
38669971Sjake	movl	PCPU(CURPCB),%edx
387757Sdg	movl	$0,PCB_ONFAULT(%edx)
388757Sdg	movl	$EFAULT,%eax
389757Sdg	ret
390757Sdg
391757Sdg/*
392163449Sdavidxu * casuword.  Compare and set user word.  Returns -1 or the current value.
393112898Sjeff */
394161675Sdavidxu
395161675SdavidxuALTENTRY(casuword32)
396163449SdavidxuENTRY(casuword)
397112898Sjeff	movl	PCPU(CURPCB),%ecx
398112898Sjeff	movl	$fusufault,PCB_ONFAULT(%ecx)
399112898Sjeff	movl	4(%esp),%edx			/* dst */
400112898Sjeff	movl	8(%esp),%eax			/* old */
401112898Sjeff	movl	12(%esp),%ecx			/* new */
402112898Sjeff
403112898Sjeff	cmpl	$VM_MAXUSER_ADDRESS-4,%edx	/* verify address is valid */
404112898Sjeff	ja	fusufault
405112898Sjeff
406118951Sjhb#ifdef SMP
407118951Sjhb	lock
408118951Sjhb#endif
409168088Sjkim	cmpxchgl %ecx,(%edx)			/* Compare and set. */
410112898Sjeff
411112898Sjeff	/*
412112967Sjake	 * The old value is in %eax.  If the store succeeded it will be the
413112967Sjake	 * value we expected (old) from before the store, otherwise it will
414112967Sjake	 * be the current value.
415112898Sjeff	 */
416112967Sjake
417112898Sjeff	movl	PCPU(CURPCB),%ecx
418112898Sjeff	movl	$0,PCB_ONFAULT(%ecx)
419112898Sjeff	ret
420171916SjkoshyEND(casuword32)
421171916SjkoshyEND(casuword)
422112898Sjeff
423112898Sjeff/*
424129550Sbde * Fetch (load) a 32-bit word, a 16-bit word, or an 8-bit byte from user
425129550Sbde * memory.  All these functions are MPSAFE.
426757Sdg */
427129550Sbde
428129549SbdeALTENTRY(fuword32)
429757SdgENTRY(fuword)
43069971Sjake	movl	PCPU(CURPCB),%ecx
431757Sdg	movl	$fusufault,PCB_ONFAULT(%ecx)
4321690Sdg	movl	4(%esp),%edx			/* from */
4331690Sdg
4341690Sdg	cmpl	$VM_MAXUSER_ADDRESS-4,%edx	/* verify address is valid */
4351690Sdg	ja	fusufault
4361690Sdg
437757Sdg	movl	(%edx),%eax
438757Sdg	movl	$0,PCB_ONFAULT(%ecx)
439757Sdg	ret
440171916SjkoshyEND(fuword32)
441171916SjkoshyEND(fuword)
442757Sdg
4431549Srgrimes/*
444129550Sbde * fuswintr() and suswintr() are specialized variants of fuword16() and
445129550Sbde * suword16(), respectively.  They are called from the profiling code,
446129550Sbde * potentially at interrupt time.  If they fail, that's okay; good things
447129550Sbde * will happen later.  They always fail for now, until the trap code is
4481549Srgrimes * able to deal with this.
4491549Srgrimes */
4501549SrgrimesALTENTRY(suswintr)
4511549SrgrimesENTRY(fuswintr)
4521549Srgrimes	movl	$-1,%eax
4531549Srgrimes	ret
454171916SjkoshyEND(suswintr)
455171916SjkoshyEND(fuswintr)
4561549Srgrimes
45798480SpeterENTRY(fuword16)
45869971Sjake	movl	PCPU(CURPCB),%ecx
45912713Sbde	movl	$fusufault,PCB_ONFAULT(%ecx)
46012713Sbde	movl	4(%esp),%edx
46112713Sbde
46212713Sbde	cmpl	$VM_MAXUSER_ADDRESS-2,%edx
46312713Sbde	ja	fusufault
46412713Sbde
46512713Sbde	movzwl	(%edx),%eax
46612713Sbde	movl	$0,PCB_ONFAULT(%ecx)
46712713Sbde	ret
468171916SjkoshyEND(fuword16)
46912713Sbde
470757SdgENTRY(fubyte)
47169971Sjake	movl	PCPU(CURPCB),%ecx
472757Sdg	movl	$fusufault,PCB_ONFAULT(%ecx)
473757Sdg	movl	4(%esp),%edx
4741690Sdg
4751703Sdg	cmpl	$VM_MAXUSER_ADDRESS-1,%edx
4761690Sdg	ja	fusufault
4771690Sdg
478757Sdg	movzbl	(%edx),%eax
479757Sdg	movl	$0,PCB_ONFAULT(%ecx)
480757Sdg	ret
481171916SjkoshyEND(fubyte)
482757Sdg
483757Sdg	ALIGN_TEXT
484757Sdgfusufault:
48569971Sjake	movl	PCPU(CURPCB),%ecx
486757Sdg	xorl	%eax,%eax
487757Sdg	movl	%eax,PCB_ONFAULT(%ecx)
488757Sdg	decl	%eax
489757Sdg	ret
490757Sdg
491757Sdg/*
492129550Sbde * Store a 32-bit word, a 16-bit word, or an 8-bit byte to user memory.
493137784Sjhb * All these functions are MPSAFE.
494757Sdg */
495129550Sbde
496129549SbdeALTENTRY(suword32)
497757SdgENTRY(suword)
49869971Sjake	movl	PCPU(CURPCB),%ecx
499757Sdg	movl	$fusufault,PCB_ONFAULT(%ecx)
500757Sdg	movl	4(%esp),%edx
501757Sdg
5021690Sdg	cmpl	$VM_MAXUSER_ADDRESS-4,%edx	/* verify address validity */
5031690Sdg	ja	fusufault
5041690Sdg
505757Sdg	movl	8(%esp),%eax
5061058Sdg	movl	%eax,(%edx)
507757Sdg	xorl	%eax,%eax
50869971Sjake	movl	PCPU(CURPCB),%ecx
509757Sdg	movl	%eax,PCB_ONFAULT(%ecx)
510757Sdg	ret
511171916SjkoshyEND(suword32)
512171916SjkoshyEND(suword)
513757Sdg
51498480SpeterENTRY(suword16)
51569971Sjake	movl	PCPU(CURPCB),%ecx
516757Sdg	movl	$fusufault,PCB_ONFAULT(%ecx)
517757Sdg	movl	4(%esp),%edx
5181058Sdg
5191690Sdg	cmpl	$VM_MAXUSER_ADDRESS-2,%edx	/* verify address validity */
5201690Sdg	ja	fusufault
5211690Sdg
5221058Sdg	movw	8(%esp),%ax
523757Sdg	movw	%ax,(%edx)
524757Sdg	xorl	%eax,%eax
52569971Sjake	movl	PCPU(CURPCB),%ecx		/* restore trashed register */
526757Sdg	movl	%eax,PCB_ONFAULT(%ecx)
527757Sdg	ret
528171916SjkoshyEND(suword16)
529757Sdg
5301058SdgENTRY(subyte)
53169971Sjake	movl	PCPU(CURPCB),%ecx
532757Sdg	movl	$fusufault,PCB_ONFAULT(%ecx)
533757Sdg	movl	4(%esp),%edx
5341058Sdg
5351690Sdg	cmpl	$VM_MAXUSER_ADDRESS-1,%edx	/* verify address validity */
5361690Sdg	ja	fusufault
5371690Sdg
5381058Sdg	movb	8(%esp),%al
5391058Sdg	movb	%al,(%edx)
540757Sdg	xorl	%eax,%eax
54169971Sjake	movl	PCPU(CURPCB),%ecx		/* restore trashed register */
542757Sdg	movl	%eax,PCB_ONFAULT(%ecx)
543757Sdg	ret
544171916SjkoshyEND(subyte)
545757Sdg
546757Sdg/*
54758941Sdillon * copyinstr(from, to, maxlen, int *lencopied) - MP SAFE
54858941Sdillon *
549757Sdg *	copy a string from from to to, stop when a 0 character is reached.
550757Sdg *	return ENAMETOOLONG if string is longer than maxlen, and
551757Sdg *	EFAULT on protection violations. If lencopied is non-zero,
552757Sdg *	return the actual length in *lencopied.
553757Sdg */
554757SdgENTRY(copyinstr)
555757Sdg	pushl	%esi
556757Sdg	pushl	%edi
55769971Sjake	movl	PCPU(CURPCB),%ecx
5582493Sdg	movl	$cpystrflt,PCB_ONFAULT(%ecx)
559757Sdg
560757Sdg	movl	12(%esp),%esi			/* %esi = from */
561757Sdg	movl	16(%esp),%edi			/* %edi = to */
562757Sdg	movl	20(%esp),%edx			/* %edx = maxlen */
5632493Sdg
5642493Sdg	movl	$VM_MAXUSER_ADDRESS,%eax
5652493Sdg
5662493Sdg	/* make sure 'from' is within bounds */
5672493Sdg	subl	%esi,%eax
5682493Sdg	jbe	cpystrflt
5692493Sdg
5702493Sdg	/* restrict maxlen to <= VM_MAXUSER_ADDRESS-from */
5712493Sdg	cmpl	%edx,%eax
5722493Sdg	jae	1f
5732493Sdg	movl	%eax,%edx
5742493Sdg	movl	%eax,20(%esp)
5752493Sdg1:
576757Sdg	incl	%edx
5771691Sdg	cld
5782493Sdg
5792493Sdg2:
580757Sdg	decl	%edx
5812493Sdg	jz	3f
5822493Sdg
583757Sdg	lodsb
584757Sdg	stosb
585757Sdg	orb	%al,%al
5862493Sdg	jnz	2b
587757Sdg
588757Sdg	/* Success -- 0 byte reached */
589757Sdg	decl	%edx
590757Sdg	xorl	%eax,%eax
5912493Sdg	jmp	cpystrflt_x
5922493Sdg3:
5932493Sdg	/* edx is zero - return ENAMETOOLONG or EFAULT */
5942493Sdg	cmpl	$VM_MAXUSER_ADDRESS,%esi
5952493Sdg	jae	cpystrflt
5962493Sdg4:
597757Sdg	movl	$ENAMETOOLONG,%eax
5982493Sdg	jmp	cpystrflt_x
599757Sdg
6002493Sdgcpystrflt:
601757Sdg	movl	$EFAULT,%eax
6022493Sdg
6032493Sdgcpystrflt_x:
604757Sdg	/* set *lencopied and return %eax */
60569971Sjake	movl	PCPU(CURPCB),%ecx
606757Sdg	movl	$0,PCB_ONFAULT(%ecx)
6072493Sdg	movl	20(%esp),%ecx
608757Sdg	subl	%edx,%ecx
6092493Sdg	movl	24(%esp),%edx
6102493Sdg	testl	%edx,%edx
6112493Sdg	jz	1f
612757Sdg	movl	%ecx,(%edx)
6132493Sdg1:
614757Sdg	popl	%edi
615757Sdg	popl	%esi
616757Sdg	ret
617171916SjkoshyEND(copyinstr)
618757Sdg
619757Sdg/*
62058941Sdillon * copystr(from, to, maxlen, int *lencopied) - MP SAFE
621757Sdg */
622757SdgENTRY(copystr)
623757Sdg	pushl	%esi
624757Sdg	pushl	%edi
625757Sdg
626757Sdg	movl	12(%esp),%esi			/* %esi = from */
627757Sdg	movl	16(%esp),%edi			/* %edi = to */
628757Sdg	movl	20(%esp),%edx			/* %edx = maxlen */
629757Sdg	incl	%edx
6301691Sdg	cld
631757Sdg1:
632757Sdg	decl	%edx
633757Sdg	jz	4f
634757Sdg	lodsb
635757Sdg	stosb
636757Sdg	orb	%al,%al
637757Sdg	jnz	1b
638757Sdg
639757Sdg	/* Success -- 0 byte reached */
640757Sdg	decl	%edx
641757Sdg	xorl	%eax,%eax
642757Sdg	jmp	6f
643757Sdg4:
644757Sdg	/* edx is zero -- return ENAMETOOLONG */
645757Sdg	movl	$ENAMETOOLONG,%eax
646757Sdg
647757Sdg6:
648757Sdg	/* set *lencopied and return %eax */
649757Sdg	movl	20(%esp),%ecx
650757Sdg	subl	%edx,%ecx
651757Sdg	movl	24(%esp),%edx
6526325Sdg	testl	%edx,%edx
653757Sdg	jz	7f
654757Sdg	movl	%ecx,(%edx)
655757Sdg7:
656757Sdg	popl	%edi
657757Sdg	popl	%esi
658757Sdg	ret
659171916SjkoshyEND(copystr)
660757Sdg
6611838SdgENTRY(bcmp)
6621838Sdg	pushl	%edi
6631838Sdg	pushl	%esi
6641838Sdg	movl	12(%esp),%edi
6651838Sdg	movl	16(%esp),%esi
6661838Sdg	movl	20(%esp),%edx
6671838Sdg
6681838Sdg	movl	%edx,%ecx
6691838Sdg	shrl	$2,%ecx
6701838Sdg	cld					/* compare forwards */
6711838Sdg	repe
6721838Sdg	cmpsl
6731838Sdg	jne	1f
6741838Sdg
6751838Sdg	movl	%edx,%ecx
6761838Sdg	andl	$3,%ecx
6771838Sdg	repe
6781838Sdg	cmpsb
6791838Sdg1:
680145383Salc	setne	%al
681145383Salc	movsbl	%al,%eax
6821838Sdg	popl	%esi
6831838Sdg	popl	%edi
6841838Sdg	ret
685171916SjkoshyEND(bcmp)
6861838Sdg
6871838Sdg/*
688757Sdg * Handling of special 386 registers and descriptor tables etc
689757Sdg */
690757Sdg/* void lgdt(struct region_descriptor *rdp); */
691757SdgENTRY(lgdt)
692181775Skmacy#ifndef XEN
693757Sdg	/* reload the descriptor table */
694757Sdg	movl	4(%esp),%eax
695757Sdg	lgdt	(%eax)
696181775Skmacy#endif
697181775Skmacy
698757Sdg	/* flush the prefetch q */
699757Sdg	jmp	1f
700757Sdg	nop
701757Sdg1:
702757Sdg	/* reload "stale" selectors */
703757Sdg	movl	$KDSEL,%eax
704128328Sjhb	movl	%eax,%ds
705128328Sjhb	movl	%eax,%es
706128328Sjhb	movl	%eax,%gs
707128328Sjhb	movl	%eax,%ss
70846129Sluoqi	movl	$KPSEL,%eax
709128328Sjhb	movl	%eax,%fs
710757Sdg
711757Sdg	/* reload code selector by turning return into intersegmental return */
712757Sdg	movl	(%esp),%eax
713757Sdg	pushl	%eax
71425164Speter	movl	$KCSEL,4(%esp)
715129615Sbde	MEXITCOUNT
716757Sdg	lret
717171916SjkoshyEND(lgdt)
718757Sdg
719757Sdg/* ssdtosd(*ssdp,*sdp) */
720757SdgENTRY(ssdtosd)
721757Sdg	pushl	%ebx
722757Sdg	movl	8(%esp),%ecx
723757Sdg	movl	8(%ecx),%ebx
724757Sdg	shll	$16,%ebx
725757Sdg	movl	(%ecx),%edx
726757Sdg	roll	$16,%edx
727757Sdg	movb	%dh,%bl
728757Sdg	movb	%dl,%bh
729757Sdg	rorl	$8,%ebx
730757Sdg	movl	4(%ecx),%eax
731757Sdg	movw	%ax,%dx
732757Sdg	andl	$0xf0000,%eax
733757Sdg	orl	%eax,%ebx
734757Sdg	movl	12(%esp),%ecx
735757Sdg	movl	%edx,(%ecx)
736757Sdg	movl	%ebx,4(%ecx)
737757Sdg	popl	%ebx
738757Sdg	ret
739171916SjkoshyEND(ssdtosd)
740757Sdg
74157362Sbsd/* void reset_dbregs() */
74257362SbsdENTRY(reset_dbregs)
74357362Sbsd	movl    $0,%eax
74457362Sbsd	movl    %eax,%dr7     /* disable all breapoints first */
74557362Sbsd	movl    %eax,%dr0
74657362Sbsd	movl    %eax,%dr1
74757362Sbsd	movl    %eax,%dr2
74857362Sbsd	movl    %eax,%dr3
74957362Sbsd	movl    %eax,%dr6
75057362Sbsd	ret
751171916SjkoshyEND(reset_dbregs)
75257362Sbsd
753757Sdg/*****************************************************************************/
754757Sdg/* setjump, longjump                                                         */
755757Sdg/*****************************************************************************/
756757Sdg
757757SdgENTRY(setjmp)
758757Sdg	movl	4(%esp),%eax
759757Sdg	movl	%ebx,(%eax)			/* save ebx */
760757Sdg	movl	%esp,4(%eax)			/* save esp */
761757Sdg	movl	%ebp,8(%eax)			/* save ebp */
762757Sdg	movl	%esi,12(%eax)			/* save esi */
763757Sdg	movl	%edi,16(%eax)			/* save edi */
764757Sdg	movl	(%esp),%edx			/* get rta */
765757Sdg	movl	%edx,20(%eax)			/* save eip */
766757Sdg	xorl	%eax,%eax			/* return(0); */
767757Sdg	ret
768171916SjkoshyEND(setjmp)
769757Sdg
770757SdgENTRY(longjmp)
771757Sdg	movl	4(%esp),%eax
772757Sdg	movl	(%eax),%ebx			/* restore ebx */
773757Sdg	movl	4(%eax),%esp			/* restore esp */
774757Sdg	movl	8(%eax),%ebp			/* restore ebp */
775757Sdg	movl	12(%eax),%esi			/* restore esi */
776757Sdg	movl	16(%eax),%edi			/* restore edi */
777757Sdg	movl	20(%eax),%edx			/* get rta */
778757Sdg	movl	%edx,(%esp)			/* put in return frame */
779757Sdg	xorl	%eax,%eax			/* return(1); */
780757Sdg	incl	%eax
781757Sdg	ret
782171916SjkoshyEND(longjmp)
7836995Sphk
784168109Sjkim/*
785181430Sstas * Support for reading MSRs in the safe manner.
786181430Sstas */
787181430SstasENTRY(rdmsr_safe)
788181430Sstas/* int rdmsr_safe(u_int msr, uint64_t *data) */
789181430Sstas	movl	PCPU(CURPCB),%ecx
790181430Sstas	movl	$msr_onfault,PCB_ONFAULT(%ecx)
791181430Sstas
792181430Sstas	movl	4(%esp),%ecx
793181430Sstas	rdmsr
794181430Sstas	movl	8(%esp),%ecx
795181430Sstas	movl	%eax,(%ecx)
796181430Sstas	movl	%edx,4(%ecx)
797181430Sstas	xorl	%eax,%eax
798181430Sstas
799181430Sstas	movl	PCPU(CURPCB),%ecx
800181430Sstas	movl	%eax,PCB_ONFAULT(%ecx)
801181430Sstas
802181430Sstas	ret
803181430Sstas
804181430Sstas/*
805181430Sstas * Support for writing MSRs in the safe manner.
806181430Sstas */
807181430SstasENTRY(wrmsr_safe)
808181430Sstas/* int wrmsr_safe(u_int msr, uint64_t data) */
809181430Sstas	movl	PCPU(CURPCB),%ecx
810181430Sstas	movl	$msr_onfault,PCB_ONFAULT(%ecx)
811181430Sstas
812181430Sstas	movl	4(%esp),%ecx
813181430Sstas	movl	8(%esp),%eax
814181430Sstas	movl	12(%esp),%edx
815181430Sstas	wrmsr
816181430Sstas	xorl	%eax,%eax
817181430Sstas
818181430Sstas	movl	PCPU(CURPCB),%ecx
819181430Sstas	movl	%eax,PCB_ONFAULT(%ecx)
820181430Sstas
821181430Sstas	ret
822181430Sstas
823181430Sstas/*
824181430Sstas * MSR operations fault handler
825181430Sstas */
826181430Sstas	ALIGN_TEXT
827181430Sstasmsr_onfault:
828181430Sstas	movl	PCPU(CURPCB),%ecx
829181430Sstas	movl	$0,PCB_ONFAULT(%ecx)
830181430Sstas	movl	$EFAULT,%eax
831181430Sstas	ret
832