Fix a race in the FP copy code. If we setup our temporary FP save area
[dragonfly.git] / sys / platform / pc32 / i386 / support.s
CommitLineData
984263bc
MD
1/*-
2 * Copyright (c) 1993 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * $FreeBSD: src/sys/i386/i386/support.s,v 1.67.2.5 2001/08/15 01:23:50 peter Exp $
263541db 34 * $DragonFly: src/sys/platform/pc32/i386/support.s,v 1.11 2004/04/29 17:24:58 dillon Exp $
984263bc
MD
35 */
36
1f2de5d4 37#include "use_npx.h"
984263bc
MD
38
39#include <machine/asmacros.h>
40#include <machine/cputypes.h>
41#include <machine/pmap.h>
42#include <machine/specialreg.h>
43
44#include "assym.s"
45
46#define IDXSHIFT 10
47
48 .data
263541db
MD
49
50 .globl memcpy_vector
51memcpy_vector:
52 .long asm_generic_memcpy
53
2954c92f
MD
54 .globl bcopy_vector
55bcopy_vector:
263541db
MD
56 .long asm_generic_bcopy
57
2954c92f
MD
58 .globl bzero
59bzero:
60 .long generic_bzero
263541db 61
2954c92f
MD
62 .globl ovbcopy_vector
63ovbcopy_vector:
263541db 64 .long asm_generic_bcopy
984263bc
MD
65
66 .text
67
984263bc
MD
68/* fillw(pat, base, cnt) */
69ENTRY(fillw)
70 pushl %edi
71 movl 8(%esp),%eax
72 movl 12(%esp),%edi
73 movl 16(%esp),%ecx
74 cld
75 rep
76 stosw
77 popl %edi
78 ret
79
263541db
MD
80/*
81 * void bcopy(const void *s, void *d, size_t count)
82 *
83 * Normal bcopy() vector, an optimized bcopy may be installed in
84 * bcopy_vector.
85 */
86ENTRY(bcopy)
984263bc
MD
87 pushl %esi
88 pushl %edi
263541db
MD
89 movl 4+8(%esp),%esi /* caddr_t from */
90 movl 8+8(%esp),%edi /* caddr_t to */
91 movl 12+8(%esp),%ecx /* size_t len */
92 call *bcopy_vector
984263bc
MD
93 popl %edi
94 popl %esi
984263bc
MD
95 ret
96
984263bc 97/*
263541db 98 * Generic (integer-only) bcopy() vector.
984263bc
MD
99 */
100ENTRY(generic_bcopy)
101 pushl %esi
102 pushl %edi
263541db
MD
103 movl 4+8(%esp),%esi /* caddr_t from */
104 movl 8+8(%esp),%edi /* caddr_t to */
105 movl 12+8(%esp),%ecx /* size_t len */
106 call asm_generic_bcopy
984263bc
MD
107 popl %edi
108 popl %esi
109 ret
110
263541db 111ENTRY(ovbcopy)
984263bc
MD
112 pushl %esi
113 pushl %edi
263541db
MD
114 movl 4+8(%esp),%esi /* caddr_t from */
115 movl 8+8(%esp),%edi /* caddr_t to */
116 movl 12+8(%esp),%ecx /* size_t len */
117 call *ovbcopy_vector
984263bc
MD
118 popl %edi
119 popl %esi
120 ret
121
984263bc 122/*
263541db
MD
123 * void *memcpy(void *d, const void *s, size_t count)
124 *
125 * Note: memcpy does not have to support overlapping copies.
126 *
127 * Note: (d, s) arguments reversed from bcopy, and memcpy() returns d
128 * while bcopy() returns void.
984263bc
MD
129 */
130ENTRY(memcpy)
984263bc 131 pushl %esi
263541db
MD
132 pushl %edi
133 movl 4+8(%esp),%edi
134 movl 8+8(%esp),%esi
135 movl 12+8(%esp),%ecx
136 call *memcpy_vector
137 movl 4+8(%esp),%eax
984263bc 138 popl %edi
263541db 139 popl %esi
984263bc
MD
140 ret
141
263541db
MD
142/*
143 * A stack-based on-fault routine is used for more complex PCB_ONFAULT
144 * situations (such as memcpy/bcopy/bzero). In this case the on-fault
145 * routine must be pushed on the stack.
146 */
147stack_onfault:
148 ret
984263bc
MD
149
150/*****************************************************************************/
151/* copyout and fubyte family */
152/*****************************************************************************/
153/*
154 * Access user memory from inside the kernel. These routines and possibly
155 * the math- and DOS emulators should be the only places that do this.
156 *
157 * We have to access the memory with user's permissions, so use a segment
158 * selector with RPL 3. For writes to user space we have to additionally
159 * check the PTE for write permission, because the 386 does not check
160 * write permissions when we are executing with EPL 0. The 486 does check
161 * this if the WP bit is set in CR0, so we can use a simpler version here.
162 *
163 * These routines set curpcb->onfault for the time they execute. When a
164 * protection violation occurs inside the functions, the trap handler
165 * returns to *curpcb->onfault instead of the function.
166 */
167
168/*
169 * copyout(from_kernel, to_user, len) - MP SAFE (if not I386_CPU)
170 */
171ENTRY(copyout)
2954c92f 172 movl PCPU(curthread),%eax
b7c628e4 173 movl TD_PCB(%eax),%eax
984263bc
MD
174 pushl %esi
175 pushl %edi
176 pushl %ebx
263541db
MD
177 pushl $copyout_fault
178 movl $stack_onfault,PCB_ONFAULT(%eax)
179 movl 4+16(%esp),%esi
180 movl 8+16(%esp),%edi
181 movl 12+16(%esp),%ebx
984263bc
MD
182 testl %ebx,%ebx /* anything to do? */
183 jz done_copyout
184
185 /*
186 * Check explicitly for non-user addresses. If 486 write protection
187 * is being used, this check is essential because we are in kernel
188 * mode so the h/w does not provide any protection against writing
189 * kernel addresses.
190 */
191
192 /*
193 * First, prevent address wrapping.
194 */
195 movl %edi,%eax
196 addl %ebx,%eax
197 jc copyout_fault
198/*
199 * XXX STOP USING VM_MAXUSER_ADDRESS.
200 * It is an end address, not a max, so every time it is used correctly it
201 * looks like there is an off by one error, and of course it caused an off
202 * by one error in several places.
203 */
204 cmpl $VM_MAXUSER_ADDRESS,%eax
205 ja copyout_fault
206
207#if defined(I386_CPU)
208
209#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
e38b98c0 210 cmpl $CPUCLASS_386,cpu_class
984263bc
MD
211 jne 3f
212#endif
213/*
214 * We have to check each PTE for user write permission.
215 * The checking may cause a page fault, so it is important to set
216 * up everything for return via copyout_fault before here.
217 */
218 /* compute number of pages */
219 movl %edi,%ecx
220 andl $PAGE_MASK,%ecx
221 addl %ebx,%ecx
222 decl %ecx
223 shrl $IDXSHIFT+2,%ecx
224 incl %ecx
225
226 /* compute PTE offset for start address */
227 movl %edi,%edx
228 shrl $IDXSHIFT,%edx
229 andb $0xfc,%dl
230
2311:
232 /* check PTE for each page */
2954c92f 233 leal PTmap(%edx),%eax
984263bc
MD
234 shrl $IDXSHIFT,%eax
235 andb $0xfc,%al
2954c92f 236 testb $PG_V,PTmap(%eax) /* PTE page must be valid */
984263bc 237 je 4f
2954c92f 238 movb PTmap(%edx),%al
984263bc
MD
239 andb $PG_V|PG_RW|PG_U,%al /* page must be valid and user writable */
240 cmpb $PG_V|PG_RW|PG_U,%al
241 je 2f
242
2434:
244 /* simulate a trap */
245 pushl %edx
246 pushl %ecx
247 shll $IDXSHIFT,%edx
248 pushl %edx
2954c92f 249 call trapwrite /* trapwrite(addr) */
984263bc
MD
250 popl %edx
251 popl %ecx
252 popl %edx
253
254 testl %eax,%eax /* if not ok, return EFAULT */
255 jnz copyout_fault
256
2572:
258 addl $4,%edx
259 decl %ecx
260 jnz 1b /* check next page */
261#endif /* I386_CPU */
262
263541db
MD
263 /*
264 * Convert copyout to memcpy_vector(dest:%edi, src:%esi, conut:%ecx)
265 */
984263bc
MD
2663:
267 movl %ebx,%ecx
263541db 268 call *memcpy_vector
984263bc
MD
269
270done_copyout:
263541db
MD
271 /*
272 * non-error return
273 */
274 addl $4,%esp
275 movl PCPU(curthread),%edx
276 xorl %eax,%eax
277 movl TD_PCB(%edx),%edx
984263bc
MD
278 popl %ebx
279 popl %edi
280 popl %esi
984263bc
MD
281 movl %eax,PCB_ONFAULT(%edx)
282 ret
283
284 ALIGN_TEXT
285copyout_fault:
286 popl %ebx
287 popl %edi
288 popl %esi
2954c92f 289 movl PCPU(curthread),%edx
b7c628e4 290 movl TD_PCB(%edx),%edx
984263bc
MD
291 movl $0,PCB_ONFAULT(%edx)
292 movl $EFAULT,%eax
293 ret
294
984263bc
MD
295/*
296 * copyin(from_user, to_kernel, len) - MP SAFE
297 */
984263bc 298
263541db 299ENTRY(copyin)
2954c92f 300 movl PCPU(curthread),%eax
b7c628e4 301 movl TD_PCB(%eax),%eax
984263bc
MD
302 pushl %esi
303 pushl %edi
263541db
MD
304 pushl $copyin_fault
305 movl $stack_onfault,PCB_ONFAULT(%eax)
306 movl 4+12(%esp),%esi /* caddr_t from */
307 movl 8+12(%esp),%edi /* caddr_t to */
308 movl 12+12(%esp),%ecx /* size_t len */
984263bc
MD
309
310 /*
311 * make sure address is valid
312 */
313 movl %esi,%edx
314 addl %ecx,%edx
315 jc copyin_fault
316 cmpl $VM_MAXUSER_ADDRESS,%edx
317 ja copyin_fault
318
263541db
MD
319 /*
320 * Call memcpy(destination:%edi, source:%esi, bytes:%ecx)
321 */
322 call *memcpy_vector
984263bc 323
263541db
MD
324 /*
325 * return 0 (no error)
326 */
327 addl $4,%esp
2954c92f 328 movl PCPU(curthread),%edx
263541db 329 xorl %eax,%eax
b7c628e4 330 movl TD_PCB(%edx),%edx
984263bc
MD
331 popl %edi
332 popl %esi
263541db 333 movl %eax,PCB_ONFAULT(%edx)
984263bc
MD
334 ret
335
984263bc 336 /*
263541db 337 * return EFAULT
984263bc 338 */
984263bc 339 ALIGN_TEXT
263541db 340copyin_fault:
984263bc
MD
341 popl %edi
342 popl %esi
2954c92f 343 movl PCPU(curthread),%edx
b7c628e4 344 movl TD_PCB(%edx),%edx
984263bc
MD
345 movl $0,PCB_ONFAULT(%edx)
346 movl $EFAULT,%eax
347 ret
984263bc
MD
348
349/*
350 * fu{byte,sword,word} - MP SAFE
351 *
352 * Fetch a byte (sword, word) from user memory
353 */
354ENTRY(fuword)
2954c92f 355 movl PCPU(curthread),%ecx
b7c628e4 356 movl TD_PCB(%ecx),%ecx
984263bc
MD
357 movl $fusufault,PCB_ONFAULT(%ecx)
358 movl 4(%esp),%edx /* from */
359
360 cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address is valid */
361 ja fusufault
362
363 movl (%edx),%eax
364 movl $0,PCB_ONFAULT(%ecx)
365 ret
366
367/*
368 * These two routines are called from the profiling code, potentially
369 * at interrupt time. If they fail, that's okay, good things will
370 * happen later. Fail all the time for now - until the trap code is
371 * able to deal with this.
372 */
373ALTENTRY(suswintr)
374ENTRY(fuswintr)
375 movl $-1,%eax
376 ret
377
378/*
379 * fusword - MP SAFE
380 */
381ENTRY(fusword)
2954c92f 382 movl PCPU(curthread),%ecx
b7c628e4 383 movl TD_PCB(%ecx),%ecx
984263bc
MD
384 movl $fusufault,PCB_ONFAULT(%ecx)
385 movl 4(%esp),%edx
386
387 cmpl $VM_MAXUSER_ADDRESS-2,%edx
388 ja fusufault
389
390 movzwl (%edx),%eax
391 movl $0,PCB_ONFAULT(%ecx)
392 ret
393
394/*
395 * fubyte - MP SAFE
396 */
397ENTRY(fubyte)
2954c92f 398 movl PCPU(curthread),%ecx
b7c628e4 399 movl TD_PCB(%ecx),%ecx
984263bc
MD
400 movl $fusufault,PCB_ONFAULT(%ecx)
401 movl 4(%esp),%edx
402
403 cmpl $VM_MAXUSER_ADDRESS-1,%edx
404 ja fusufault
405
406 movzbl (%edx),%eax
407 movl $0,PCB_ONFAULT(%ecx)
408 ret
409
410 ALIGN_TEXT
411fusufault:
2954c92f 412 movl PCPU(curthread),%ecx
b7c628e4 413 movl TD_PCB(%ecx),%ecx
984263bc
MD
414 xorl %eax,%eax
415 movl %eax,PCB_ONFAULT(%ecx)
416 decl %eax
417 ret
418
419/*
420 * su{byte,sword,word} - MP SAFE (if not I386_CPU)
421 *
422 * Write a byte (word, longword) to user memory
423 */
424ENTRY(suword)
2954c92f 425 movl PCPU(curthread),%ecx
b7c628e4 426 movl TD_PCB(%ecx),%ecx
984263bc
MD
427 movl $fusufault,PCB_ONFAULT(%ecx)
428 movl 4(%esp),%edx
429
430#if defined(I386_CPU)
431
432#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
e38b98c0 433 cmpl $CPUCLASS_386,cpu_class
984263bc
MD
434 jne 2f /* we only have to set the right segment selector */
435#endif /* I486_CPU || I586_CPU || I686_CPU */
436
437 /* XXX - page boundary crossing is still not handled */
438 movl %edx,%eax
439 shrl $IDXSHIFT,%edx
440 andb $0xfc,%dl
441
e38b98c0 442 leal PTmap(%edx),%ecx
984263bc
MD
443 shrl $IDXSHIFT,%ecx
444 andb $0xfc,%cl
e38b98c0 445 testb $PG_V,PTmap(%ecx) /* PTE page must be valid */
984263bc 446 je 4f
e38b98c0 447 movb PTmap(%edx),%dl
984263bc
MD
448 andb $PG_V|PG_RW|PG_U,%dl /* page must be valid and user writable */
449 cmpb $PG_V|PG_RW|PG_U,%dl
450 je 1f
451
4524:
453 /* simulate a trap */
454 pushl %eax
e38b98c0 455 call trapwrite
984263bc
MD
456 popl %edx /* remove junk parameter from stack */
457 testl %eax,%eax
458 jnz fusufault
4591:
460 movl 4(%esp),%edx
461#endif
462
4632:
464 cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address validity */
465 ja fusufault
466
467 movl 8(%esp),%eax
468 movl %eax,(%edx)
469 xorl %eax,%eax
2954c92f 470 movl PCPU(curthread),%ecx
b7c628e4 471 movl TD_PCB(%ecx),%ecx
984263bc
MD
472 movl %eax,PCB_ONFAULT(%ecx)
473 ret
474
475/*
476 * susword - MP SAFE (if not I386_CPU)
477 */
478ENTRY(susword)
2954c92f 479 movl PCPU(curthread),%ecx
b7c628e4 480 movl TD_PCB(%ecx),%ecx
984263bc
MD
481 movl $fusufault,PCB_ONFAULT(%ecx)
482 movl 4(%esp),%edx
483
484#if defined(I386_CPU)
485
486#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
e38b98c0 487 cmpl $CPUCLASS_386,cpu_class
984263bc
MD
488 jne 2f
489#endif /* I486_CPU || I586_CPU || I686_CPU */
490
491 /* XXX - page boundary crossing is still not handled */
492 movl %edx,%eax
493 shrl $IDXSHIFT,%edx
494 andb $0xfc,%dl
495
e38b98c0 496 leal PTmap(%edx),%ecx
984263bc
MD
497 shrl $IDXSHIFT,%ecx
498 andb $0xfc,%cl
e38b98c0 499 testb $PG_V,PTmap(%ecx) /* PTE page must be valid */
984263bc 500 je 4f
e38b98c0 501 movb PTmap(%edx),%dl
984263bc
MD
502 andb $PG_V|PG_RW|PG_U,%dl /* page must be valid and user writable */
503 cmpb $PG_V|PG_RW|PG_U,%dl
504 je 1f
505
5064:
507 /* simulate a trap */
508 pushl %eax
e38b98c0 509 call trapwrite
984263bc
MD
510 popl %edx /* remove junk parameter from stack */
511 testl %eax,%eax
512 jnz fusufault
5131:
514 movl 4(%esp),%edx
515#endif
516
5172:
518 cmpl $VM_MAXUSER_ADDRESS-2,%edx /* verify address validity */
519 ja fusufault
520
521 movw 8(%esp),%ax
522 movw %ax,(%edx)
523 xorl %eax,%eax
2954c92f 524 movl PCPU(curthread),%ecx /* restore trashed register */
b7c628e4 525 movl TD_PCB(%ecx),%ecx
984263bc
MD
526 movl %eax,PCB_ONFAULT(%ecx)
527 ret
528
529/*
530 * su[i]byte - MP SAFE (if not I386_CPU)
531 */
532ALTENTRY(suibyte)
533ENTRY(subyte)
2954c92f 534 movl PCPU(curthread),%ecx
b7c628e4 535 movl TD_PCB(%ecx),%ecx
984263bc
MD
536 movl $fusufault,PCB_ONFAULT(%ecx)
537 movl 4(%esp),%edx
538
539#if defined(I386_CPU)
540
541#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
e38b98c0 542 cmpl $CPUCLASS_386,cpu_class
984263bc
MD
543 jne 2f
544#endif /* I486_CPU || I586_CPU || I686_CPU */
545
546 movl %edx,%eax
547 shrl $IDXSHIFT,%edx
548 andb $0xfc,%dl
549
e38b98c0 550 leal PTmap(%edx),%ecx
984263bc
MD
551 shrl $IDXSHIFT,%ecx
552 andb $0xfc,%cl
e38b98c0 553 testb $PG_V,PTmap(%ecx) /* PTE page must be valid */
984263bc 554 je 4f
e38b98c0 555 movb PTmap(%edx),%dl
984263bc
MD
556 andb $PG_V|PG_RW|PG_U,%dl /* page must be valid and user writable */
557 cmpb $PG_V|PG_RW|PG_U,%dl
558 je 1f
559
5604:
561 /* simulate a trap */
562 pushl %eax
e38b98c0 563 call trapwrite
984263bc
MD
564 popl %edx /* remove junk parameter from stack */
565 testl %eax,%eax
566 jnz fusufault
5671:
568 movl 4(%esp),%edx
569#endif
570
5712:
572 cmpl $VM_MAXUSER_ADDRESS-1,%edx /* verify address validity */
573 ja fusufault
574
575 movb 8(%esp),%al
576 movb %al,(%edx)
577 xorl %eax,%eax
2954c92f 578 movl PCPU(curthread),%ecx /* restore trashed register */
b7c628e4 579 movl TD_PCB(%ecx),%ecx
984263bc
MD
580 movl %eax,PCB_ONFAULT(%ecx)
581 ret
582
583/*
584 * copyinstr(from, to, maxlen, int *lencopied) - MP SAFE
585 *
586 * copy a string from from to to, stop when a 0 character is reached.
587 * return ENAMETOOLONG if string is longer than maxlen, and
588 * EFAULT on protection violations. If lencopied is non-zero,
589 * return the actual length in *lencopied.
590 */
591ENTRY(copyinstr)
592 pushl %esi
593 pushl %edi
2954c92f 594 movl PCPU(curthread),%ecx
b7c628e4 595 movl TD_PCB(%ecx),%ecx
984263bc
MD
596 movl $cpystrflt,PCB_ONFAULT(%ecx)
597
598 movl 12(%esp),%esi /* %esi = from */
599 movl 16(%esp),%edi /* %edi = to */
600 movl 20(%esp),%edx /* %edx = maxlen */
601
602 movl $VM_MAXUSER_ADDRESS,%eax
603
604 /* make sure 'from' is within bounds */
605 subl %esi,%eax
606 jbe cpystrflt
607
608 /* restrict maxlen to <= VM_MAXUSER_ADDRESS-from */
609 cmpl %edx,%eax
610 jae 1f
611 movl %eax,%edx
612 movl %eax,20(%esp)
6131:
614 incl %edx
615 cld
616
6172:
618 decl %edx
619 jz 3f
620
621 lodsb
622 stosb
623 orb %al,%al
624 jnz 2b
625
626 /* Success -- 0 byte reached */
627 decl %edx
628 xorl %eax,%eax
629 jmp cpystrflt_x
6303:
631 /* edx is zero - return ENAMETOOLONG or EFAULT */
632 cmpl $VM_MAXUSER_ADDRESS,%esi
633 jae cpystrflt
6344:
635 movl $ENAMETOOLONG,%eax
636 jmp cpystrflt_x
637
638cpystrflt:
639 movl $EFAULT,%eax
640
641cpystrflt_x:
642 /* set *lencopied and return %eax */
2954c92f 643 movl PCPU(curthread),%ecx
b7c628e4 644 movl TD_PCB(%ecx),%ecx
984263bc
MD
645 movl $0,PCB_ONFAULT(%ecx)
646 movl 20(%esp),%ecx
647 subl %edx,%ecx
648 movl 24(%esp),%edx
649 testl %edx,%edx
650 jz 1f
651 movl %ecx,(%edx)
6521:
653 popl %edi
654 popl %esi
655 ret
656
657
658/*
659 * copystr(from, to, maxlen, int *lencopied) - MP SAFE
660 */
661ENTRY(copystr)
662 pushl %esi
663 pushl %edi
664
665 movl 12(%esp),%esi /* %esi = from */
666 movl 16(%esp),%edi /* %edi = to */
667 movl 20(%esp),%edx /* %edx = maxlen */
668 incl %edx
669 cld
6701:
671 decl %edx
672 jz 4f
673 lodsb
674 stosb
675 orb %al,%al
676 jnz 1b
677
678 /* Success -- 0 byte reached */
679 decl %edx
680 xorl %eax,%eax
681 jmp 6f
6824:
683 /* edx is zero -- return ENAMETOOLONG */
684 movl $ENAMETOOLONG,%eax
685
6866:
687 /* set *lencopied and return %eax */
688 movl 20(%esp),%ecx
689 subl %edx,%ecx
690 movl 24(%esp),%edx
691 testl %edx,%edx
692 jz 7f
693 movl %ecx,(%edx)
6947:
695 popl %edi
696 popl %esi
697 ret
698
699ENTRY(bcmp)
700 pushl %edi
701 pushl %esi
702 movl 12(%esp),%edi
703 movl 16(%esp),%esi
704 movl 20(%esp),%edx
705 xorl %eax,%eax
706
707 movl %edx,%ecx
708 shrl $2,%ecx
709 cld /* compare forwards */
710 repe
711 cmpsl
712 jne 1f
713
714 movl %edx,%ecx
715 andl $3,%ecx
716 repe
717 cmpsb
718 je 2f
7191:
720 incl %eax
7212:
722 popl %esi
723 popl %edi
724 ret
725
726
727/*
728 * Handling of special 386 registers and descriptor tables etc
729 */
730/* void lgdt(struct region_descriptor *rdp); */
731ENTRY(lgdt)
732 /* reload the descriptor table */
733 movl 4(%esp),%eax
734 lgdt (%eax)
735
736 /* flush the prefetch q */
737 jmp 1f
738 nop
7391:
740 /* reload "stale" selectors */
741 movl $KDSEL,%eax
742 mov %ax,%ds
743 mov %ax,%es
744 mov %ax,%gs
745 mov %ax,%ss
984263bc 746 movl $KPSEL,%eax
984263bc
MD
747 mov %ax,%fs
748
749 /* reload code selector by turning return into intersegmental return */
750 movl (%esp),%eax
751 pushl %eax
752 movl $KCSEL,4(%esp)
753 lret
754
755/*
756 * void lidt(struct region_descriptor *rdp);
757 */
758ENTRY(lidt)
759 movl 4(%esp),%eax
760 lidt (%eax)
761 ret
762
763/*
764 * void lldt(u_short sel)
765 */
766ENTRY(lldt)
767 lldt 4(%esp)
768 ret
769
770/*
771 * void ltr(u_short sel)
772 */
773ENTRY(ltr)
774 ltr 4(%esp)
775 ret
776
777/* ssdtosd(*ssdp,*sdp) */
778ENTRY(ssdtosd)
779 pushl %ebx
780 movl 8(%esp),%ecx
781 movl 8(%ecx),%ebx
782 shll $16,%ebx
783 movl (%ecx),%edx
784 roll $16,%edx
785 movb %dh,%bl
786 movb %dl,%bh
787 rorl $8,%ebx
788 movl 4(%ecx),%eax
789 movw %ax,%dx
790 andl $0xf0000,%eax
791 orl %eax,%ebx
792 movl 12(%esp),%ecx
793 movl %edx,(%ecx)
794 movl %ebx,4(%ecx)
795 popl %ebx
796 ret
797
798/* load_cr0(cr0) */
799ENTRY(load_cr0)
800 movl 4(%esp),%eax
801 movl %eax,%cr0
802 ret
803
804/* rcr0() */
805ENTRY(rcr0)
806 movl %cr0,%eax
807 ret
808
809/* rcr3() */
810ENTRY(rcr3)
811 movl %cr3,%eax
812 ret
813
814/* void load_cr3(caddr_t cr3) */
815ENTRY(load_cr3)
816#if defined(SWTCH_OPTIM_STATS)
817 incl _tlb_flush_count
818#endif
819 movl 4(%esp),%eax
820 movl %eax,%cr3
821 ret
822
823/* rcr4() */
824ENTRY(rcr4)
825 movl %cr4,%eax
826 ret
827
828/* void load_cr4(caddr_t cr4) */
829ENTRY(load_cr4)
830 movl 4(%esp),%eax
831 movl %eax,%cr4
832 ret
833
834/* void reset_dbregs() */
835ENTRY(reset_dbregs)
836 movl $0,%eax
837 movl %eax,%dr7 /* disable all breapoints first */
838 movl %eax,%dr0
839 movl %eax,%dr1
840 movl %eax,%dr2
841 movl %eax,%dr3
842 movl %eax,%dr6
843 ret
844
845/*****************************************************************************/
846/* setjump, longjump */
847/*****************************************************************************/
848
849ENTRY(setjmp)
850 movl 4(%esp),%eax
851 movl %ebx,(%eax) /* save ebx */
852 movl %esp,4(%eax) /* save esp */
853 movl %ebp,8(%eax) /* save ebp */
854 movl %esi,12(%eax) /* save esi */
855 movl %edi,16(%eax) /* save edi */
856 movl (%esp),%edx /* get rta */
857 movl %edx,20(%eax) /* save eip */
858 xorl %eax,%eax /* return(0); */
859 ret
860
861ENTRY(longjmp)
862 movl 4(%esp),%eax
863 movl (%eax),%ebx /* restore ebx */
864 movl 4(%eax),%esp /* restore esp */
865 movl 8(%eax),%ebp /* restore ebp */
866 movl 12(%eax),%esi /* restore esi */
867 movl 16(%eax),%edi /* restore edi */
868 movl 20(%eax),%edx /* get rta */
869 movl %edx,(%esp) /* put in return frame */
870 xorl %eax,%eax /* return(1); */
871 incl %eax
872 ret
873
874/*
875 * Support for BB-profiling (gcc -a). The kernbb program will extract
876 * the data from the kernel.
877 */
878
879 .data
880 ALIGN_DATA
881 .globl bbhead
882bbhead:
883 .long 0
884
885 .text
886NON_GPROF_ENTRY(__bb_init_func)
887 movl 4(%esp),%eax
888 movl $1,(%eax)
889 movl bbhead,%edx
890 movl %edx,16(%eax)
891 movl %eax,bbhead
892 .byte 0xc3 /* avoid macro for `ret' */