Major kernel build infrastructure changes, part 2/2 (user).
[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 $
afaa1d56 34 * $DragonFly: src/sys/platform/pc32/i386/support.s,v 1.15 2006/10/23 15:42:45 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 ovbcopy_vector
59ovbcopy_vector:
263541db 60 .long asm_generic_bcopy
984263bc
MD
61
62 .text
63
984263bc
MD
64/* fillw(pat, base, cnt) */
65ENTRY(fillw)
66 pushl %edi
67 movl 8(%esp),%eax
68 movl 12(%esp),%edi
69 movl 16(%esp),%ecx
70 cld
71 rep
72 stosw
73 popl %edi
74 ret
75
263541db
MD
76/*
77 * void bcopy(const void *s, void *d, size_t count)
78 *
79 * Normal bcopy() vector, an optimized bcopy may be installed in
80 * bcopy_vector.
81 */
82ENTRY(bcopy)
984263bc
MD
83 pushl %esi
84 pushl %edi
263541db
MD
85 movl 4+8(%esp),%esi /* caddr_t from */
86 movl 8+8(%esp),%edi /* caddr_t to */
87 movl 12+8(%esp),%ecx /* size_t len */
88 call *bcopy_vector
984263bc
MD
89 popl %edi
90 popl %esi
984263bc
MD
91 ret
92
984263bc 93/*
263541db 94 * Generic (integer-only) bcopy() vector.
984263bc
MD
95 */
96ENTRY(generic_bcopy)
97 pushl %esi
98 pushl %edi
263541db
MD
99 movl 4+8(%esp),%esi /* caddr_t from */
100 movl 8+8(%esp),%edi /* caddr_t to */
101 movl 12+8(%esp),%ecx /* size_t len */
102 call asm_generic_bcopy
984263bc
MD
103 popl %edi
104 popl %esi
105 ret
106
263541db 107ENTRY(ovbcopy)
984263bc
MD
108 pushl %esi
109 pushl %edi
263541db
MD
110 movl 4+8(%esp),%esi /* caddr_t from */
111 movl 8+8(%esp),%edi /* caddr_t to */
112 movl 12+8(%esp),%ecx /* size_t len */
113 call *ovbcopy_vector
984263bc
MD
114 popl %edi
115 popl %esi
116 ret
117
984263bc 118/*
263541db
MD
119 * void *memcpy(void *d, const void *s, size_t count)
120 *
121 * Note: memcpy does not have to support overlapping copies.
122 *
123 * Note: (d, s) arguments reversed from bcopy, and memcpy() returns d
124 * while bcopy() returns void.
984263bc
MD
125 */
126ENTRY(memcpy)
984263bc 127 pushl %esi
263541db
MD
128 pushl %edi
129 movl 4+8(%esp),%edi
130 movl 8+8(%esp),%esi
131 movl 12+8(%esp),%ecx
132 call *memcpy_vector
133 movl 4+8(%esp),%eax
984263bc 134 popl %edi
263541db 135 popl %esi
984263bc
MD
136 ret
137
263541db
MD
138/*
139 * A stack-based on-fault routine is used for more complex PCB_ONFAULT
140 * situations (such as memcpy/bcopy/bzero). In this case the on-fault
141 * routine must be pushed on the stack.
142 */
143stack_onfault:
144 ret
984263bc
MD
145
146/*****************************************************************************/
147/* copyout and fubyte family */
148/*****************************************************************************/
149/*
150 * Access user memory from inside the kernel. These routines and possibly
151 * the math- and DOS emulators should be the only places that do this.
152 *
153 * We have to access the memory with user's permissions, so use a segment
154 * selector with RPL 3. For writes to user space we have to additionally
155 * check the PTE for write permission, because the 386 does not check
156 * write permissions when we are executing with EPL 0. The 486 does check
157 * this if the WP bit is set in CR0, so we can use a simpler version here.
158 *
159 * These routines set curpcb->onfault for the time they execute. When a
160 * protection violation occurs inside the functions, the trap handler
161 * returns to *curpcb->onfault instead of the function.
162 */
163
164/*
165 * copyout(from_kernel, to_user, len) - MP SAFE (if not I386_CPU)
166 */
167ENTRY(copyout)
2954c92f 168 movl PCPU(curthread),%eax
b7c628e4 169 movl TD_PCB(%eax),%eax
984263bc
MD
170 pushl %esi
171 pushl %edi
172 pushl %ebx
3961a39d 173 pushl $copyout_fault2
263541db
MD
174 movl $stack_onfault,PCB_ONFAULT(%eax)
175 movl 4+16(%esp),%esi
176 movl 8+16(%esp),%edi
177 movl 12+16(%esp),%ebx
984263bc
MD
178 testl %ebx,%ebx /* anything to do? */
179 jz done_copyout
180
181 /*
182 * Check explicitly for non-user addresses. If 486 write protection
183 * is being used, this check is essential because we are in kernel
184 * mode so the h/w does not provide any protection against writing
185 * kernel addresses.
186 */
187
188 /*
189 * First, prevent address wrapping.
190 */
191 movl %edi,%eax
192 addl %ebx,%eax
3961a39d 193 jc copyout_fault1
984263bc
MD
194/*
195 * XXX STOP USING VM_MAXUSER_ADDRESS.
196 * It is an end address, not a max, so every time it is used correctly it
197 * looks like there is an off by one error, and of course it caused an off
198 * by one error in several places.
199 */
200 cmpl $VM_MAXUSER_ADDRESS,%eax
3961a39d 201 ja copyout_fault1
984263bc
MD
202
203#if defined(I386_CPU)
204
205#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
e38b98c0 206 cmpl $CPUCLASS_386,cpu_class
984263bc
MD
207 jne 3f
208#endif
209/*
210 * We have to check each PTE for user write permission.
211 * The checking may cause a page fault, so it is important to set
212 * up everything for return via copyout_fault before here.
213 */
214 /* compute number of pages */
215 movl %edi,%ecx
216 andl $PAGE_MASK,%ecx
217 addl %ebx,%ecx
218 decl %ecx
219 shrl $IDXSHIFT+2,%ecx
220 incl %ecx
221
222 /* compute PTE offset for start address */
223 movl %edi,%edx
224 shrl $IDXSHIFT,%edx
225 andb $0xfc,%dl
226
2271:
228 /* check PTE for each page */
2954c92f 229 leal PTmap(%edx),%eax
984263bc
MD
230 shrl $IDXSHIFT,%eax
231 andb $0xfc,%al
2954c92f 232 testb $PG_V,PTmap(%eax) /* PTE page must be valid */
984263bc 233 je 4f
2954c92f 234 movb PTmap(%edx),%al
984263bc
MD
235 andb $PG_V|PG_RW|PG_U,%al /* page must be valid and user writable */
236 cmpb $PG_V|PG_RW|PG_U,%al
237 je 2f
238
2394:
240 /* simulate a trap */
241 pushl %edx
242 pushl %ecx
243 shll $IDXSHIFT,%edx
244 pushl %edx
2954c92f 245 call trapwrite /* trapwrite(addr) */
984263bc
MD
246 popl %edx
247 popl %ecx
248 popl %edx
249
250 testl %eax,%eax /* if not ok, return EFAULT */
3961a39d 251 jnz copyout_fault1
984263bc
MD
252
2532:
254 addl $4,%edx
255 decl %ecx
256 jnz 1b /* check next page */
257#endif /* I386_CPU */
258
263541db
MD
259 /*
260 * Convert copyout to memcpy_vector(dest:%edi, src:%esi, conut:%ecx)
261 */
984263bc
MD
2623:
263 movl %ebx,%ecx
263541db 264 call *memcpy_vector
984263bc
MD
265
266done_copyout:
263541db
MD
267 /*
268 * non-error return
269 */
270 addl $4,%esp
271 movl PCPU(curthread),%edx
272 xorl %eax,%eax
273 movl TD_PCB(%edx),%edx
984263bc
MD
274 popl %ebx
275 popl %edi
276 popl %esi
984263bc
MD
277 movl %eax,PCB_ONFAULT(%edx)
278 ret
279
280 ALIGN_TEXT
3961a39d
MD
281copyout_fault1:
282 addl $4,%esp /* skip pushed copyout_fault vector */
283copyout_fault2:
984263bc
MD
284 popl %ebx
285 popl %edi
286 popl %esi
2954c92f 287 movl PCPU(curthread),%edx
b7c628e4 288 movl TD_PCB(%edx),%edx
984263bc
MD
289 movl $0,PCB_ONFAULT(%edx)
290 movl $EFAULT,%eax
291 ret
292
984263bc
MD
293/*
294 * copyin(from_user, to_kernel, len) - MP SAFE
295 */
984263bc 296
263541db 297ENTRY(copyin)
2954c92f 298 movl PCPU(curthread),%eax
b7c628e4 299 movl TD_PCB(%eax),%eax
984263bc
MD
300 pushl %esi
301 pushl %edi
3961a39d 302 pushl $copyin_fault2
263541db
MD
303 movl $stack_onfault,PCB_ONFAULT(%eax)
304 movl 4+12(%esp),%esi /* caddr_t from */
305 movl 8+12(%esp),%edi /* caddr_t to */
306 movl 12+12(%esp),%ecx /* size_t len */
984263bc
MD
307
308 /*
309 * make sure address is valid
310 */
311 movl %esi,%edx
312 addl %ecx,%edx
3961a39d 313 jc copyin_fault1
984263bc 314 cmpl $VM_MAXUSER_ADDRESS,%edx
3961a39d 315 ja copyin_fault1
984263bc 316
263541db
MD
317 /*
318 * Call memcpy(destination:%edi, source:%esi, bytes:%ecx)
319 */
320 call *memcpy_vector
984263bc 321
263541db
MD
322 /*
323 * return 0 (no error)
324 */
325 addl $4,%esp
2954c92f 326 movl PCPU(curthread),%edx
263541db 327 xorl %eax,%eax
b7c628e4 328 movl TD_PCB(%edx),%edx
984263bc
MD
329 popl %edi
330 popl %esi
263541db 331 movl %eax,PCB_ONFAULT(%edx)
984263bc
MD
332 ret
333
984263bc 334 /*
263541db 335 * return EFAULT
984263bc 336 */
984263bc 337 ALIGN_TEXT
3961a39d
MD
338copyin_fault1:
339 addl $4,%esp /* skip pushed copyin_fault vector */
340copyin_fault2:
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' */