support.s revision 1691
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 * $Id: support.s,v 1.10 1994/06/06 14:23:49 davidg Exp $ 34 */ 35 36#include "assym.s" /* system definitions */ 37#include "errno.h" /* error return codes */ 38#include "machine/asmacros.h" /* miscellaneous asm macros */ 39#include "machine/cputypes.h" /* types of CPUs */ 40 41#define KDSEL 0x10 /* kernel data selector */ 42#define IDXSHIFT 10 43 44/* 45 * Support routines for GCC, general C-callable functions 46 */ 47ENTRY(__udivsi3) 48 movl 4(%esp),%eax 49 xorl %edx,%edx 50 divl 8(%esp) 51 ret 52 53ENTRY(__divsi3) 54 movl 4(%esp),%eax 55 cltd 56 idivl 8(%esp) 57 ret 58 59 /* 60 * I/O bus instructions via C 61 */ 62ENTRY(inb) /* val = inb(port) */ 63 movl 4(%esp),%edx 64 subl %eax,%eax 65 inb %dx,%al 66 NOP 67 ret 68 69ENTRY(inw) /* val = inw(port) */ 70 movl 4(%esp),%edx 71 subl %eax,%eax 72 inw %dx,%ax 73 NOP 74 ret 75 76ENTRY(insb) /* insb(port, addr, cnt) */ 77 pushl %edi 78 movw 8(%esp),%dx 79 movl 12(%esp),%edi 80 movl 16(%esp),%ecx 81 cld 82 rep 83 insb 84 NOP 85 movl %edi,%eax 86 popl %edi 87 ret 88 89ENTRY(insw) /* insw(port, addr, cnt) */ 90 pushl %edi 91 movw 8(%esp),%dx 92 movl 12(%esp),%edi 93 movl 16(%esp),%ecx 94 cld 95 rep 96 insw 97 NOP 98 movl %edi,%eax 99 popl %edi 100 ret 101 102ENTRY(insl) /* insl(port, addr, cnt) */ 103 pushl %edi 104 movw 8(%esp),%dx 105 movl 12(%esp),%edi 106 movl 16(%esp),%ecx 107 cld 108 rep 109 insl 110 NOP 111 movl %edi,%eax 112 popl %edi 113 ret 114 115ENTRY(rtcin) /* rtcin(val) */ 116 movl 4(%esp),%eax 117 outb %al,$0x70 118 NOP 119 xorl %eax,%eax 120 inb $0x71,%al 121 NOP 122 ret 123 124ENTRY(outb) /* outb(port, val) */ 125 movl 4(%esp),%edx 126 movl 8(%esp),%eax 127 outb %al,%dx 128 NOP 129 ret 130 131ENTRY(outw) /* outw(port, val) */ 132 movl 4(%esp),%edx 133 movl 8(%esp),%eax 134 outw %ax,%dx 135 NOP 136 ret 137 138ENTRY(outsb) /* outsb(port, addr, cnt) */ 139 pushl %esi 140 movw 8(%esp),%dx 141 movl 12(%esp),%esi 142 movl 16(%esp),%ecx 143 cld 144 rep 145 outsb 146 NOP 147 movl %esi,%eax 148 popl %esi 149 ret 150 151ENTRY(outsw) /* outsw(port, addr, cnt) */ 152 pushl %esi 153 movw 8(%esp),%dx 154 movl 12(%esp),%esi 155 movl 16(%esp),%ecx 156 cld 157 rep 158 outsw 159 NOP 160 movl %esi,%eax 161 popl %esi 162 ret 163 164ENTRY(outsl) /* outsl(port, addr, cnt) */ 165 pushl %esi 166 movw 8(%esp),%dx 167 movl 12(%esp),%esi 168 movl 16(%esp),%ecx 169 cld 170 rep 171 outsl 172 NOP 173 movl %esi,%eax 174 popl %esi 175 ret 176 177/* 178 * bcopy family 179 */ 180/* 181 * void bzero(void *base, u_int cnt) 182 * Special code for I486 because stosl uses lots 183 * of clocks. Makes little or no difference on DX2 type 184 * machines, but about stosl is about 1/2 as fast as 185 * memory moves on standard DX !!!!! 186 */ 187 188ALTENTRY(blkclr) 189ENTRY(bzero) 190#if defined(I486_CPU) && (defined(I386_CPU) || defined(I586_CPU)) 191 cmpl $CPUCLASS_486,_cpu_class 192 jz 1f 193#endif 194#if defined(I386_CPU) || defined(I586_CPU) 195 pushl %edi 196 movl 8(%esp),%edi 197 movl 12(%esp),%ecx 198 xorl %eax,%eax 199 shrl $2,%ecx 200 cld 201 rep 202 stosl 203 movl 12(%esp),%ecx 204 andl $3,%ecx 205 rep 206 stosb 207 popl %edi 208 ret 209 .align 4 210#endif 211#if defined(I486_CPU) 2121: 213 movl 4(%esp),%edx 214 movl 8(%esp),%ecx 215 xorl %eax,%eax 216/ 217/ do 64 byte chunks first 218/ 2192: 220 cmpl $64,%ecx 221 jb 3f 222 movl %eax,(%edx) 223 movl %eax,4(%edx) 224 movl %eax,8(%edx) 225 movl %eax,12(%edx) 226 movl %eax,16(%edx) 227 movl %eax,20(%edx) 228 movl %eax,24(%edx) 229 movl %eax,28(%edx) 230 movl %eax,32(%edx) 231 movl %eax,36(%edx) 232 movl %eax,40(%edx) 233 movl %eax,44(%edx) 234 movl %eax,48(%edx) 235 movl %eax,52(%edx) 236 movl %eax,56(%edx) 237 movl %eax,60(%edx) 238 addl $64,%edx 239 subl $64,%ecx 240 jnz 2b 241 ret 242 .align 4 243/ 244/ do 16 byte chunks 245/ 2463: 247 cmpl $16,%ecx 248 jb 4f 249 movl %eax,(%edx) 250 movl %eax,4(%edx) 251 movl %eax,8(%edx) 252 movl %eax,12(%edx) 253 addl $16,%edx 254 subl $16,%ecx 255 jnz 3b 256 ret 257 .align 4 258/ 259/ do 4 byte chunks 260/ 2614: cmpl $4,%ecx 262 jb 5f 263 movl %eax,(%edx) 264 addl $4,%edx 265 subl $4,%ecx 266 jnz 4b 267 ret 268/ 269/ do 1 byte chunks -- this appears to be faster than a loop 270/ 271 .align 4 272jtab: .long do0 273 .long do1 274 .long do2 275 .long do3 276 277 .align 4 2785: jmp jtab(,%ecx,4) 279 280 .align 2 281do3: movb $0,(%edx) 282 incl %edx 283 movw $0,(%edx) 284 ret 285 .align 2 286do2: movw $0,(%edx) 287 ret 288 .align 2 289do1: movb $0,(%edx) 290do0: ret 291 292#endif 293 294/* fillw(pat, base, cnt) */ 295ENTRY(fillw) 296 pushl %edi 297 movl 8(%esp),%eax 298 movl 12(%esp),%edi 299 movl 16(%esp),%ecx 300 cld 301 rep 302 stosw 303 popl %edi 304 ret 305 306/* filli(pat, base, cnt) */ 307ENTRY(filli) 308 pushl %edi 309 movl 8(%esp),%eax 310 movl 12(%esp),%edi 311 movl 16(%esp),%ecx 312 cld 313 rep 314 stosl 315 popl %edi 316 ret 317 318ENTRY(bcopyb) 319bcopyb: 320 pushl %esi 321 pushl %edi 322 movl 12(%esp),%esi 323 movl 16(%esp),%edi 324 movl 20(%esp),%ecx 325 cmpl %esi,%edi /* potentially overlapping? */ 326 jnb 1f 327 cld /* nope, copy forwards */ 328 rep 329 movsb 330 popl %edi 331 popl %esi 332 ret 333 334 ALIGN_TEXT 3351: 336 addl %ecx,%edi /* copy backwards. */ 337 addl %ecx,%esi 338 std 339 decl %edi 340 decl %esi 341 rep 342 movsb 343 popl %edi 344 popl %esi 345 cld 346 ret 347 348ENTRY(bcopyw) 349bcopyw: 350 pushl %esi 351 pushl %edi 352 movl 12(%esp),%esi 353 movl 16(%esp),%edi 354 movl 20(%esp),%ecx 355 cmpl %esi,%edi /* potentially overlapping? */ 356 jnb 1f 357 shrl $1,%ecx /* copy by 16-bit words */ 358 cld /* nope, copy forwards */ 359 rep 360 movsw 361 adc %ecx,%ecx /* any bytes left? */ 362 rep 363 movsb 364 popl %edi 365 popl %esi 366 ret 367 368 ALIGN_TEXT 3691: 370 addl %ecx,%edi /* copy backwards */ 371 addl %ecx,%esi 372 andl $1,%ecx /* any fractional bytes? */ 373 decl %edi 374 decl %esi 375 std 376 rep 377 movsb 378 movl 20(%esp),%ecx /* copy remainder by 16-bit words */ 379 shrl $1,%ecx 380 decl %esi 381 decl %edi 382 rep 383 movsw 384 popl %edi 385 popl %esi 386 cld 387 ret 388 389ENTRY(bcopyx) 390 movl 16(%esp),%eax 391 cmpl $2,%eax 392 je bcopyw /* not _bcopyw, to avoid multiple mcounts */ 393 cmpl $4,%eax 394 je bcopy /* XXX the shared ret's break mexitcount */ 395 jmp bcopyb 396 397/* 398 * (ov)bcopy(src, dst, cnt) 399 * ws@tools.de (Wolfgang Solfrank, TooLs GmbH) +49-228-985800 400 */ 401ALTENTRY(ovbcopy) 402ENTRY(bcopy) 403bcopy: 404 pushl %esi 405 pushl %edi 406 movl 12(%esp),%esi 407 movl 16(%esp),%edi 408 movl 20(%esp),%ecx 409 cmpl %esi,%edi /* potentially overlapping? */ 410 jnb 1f 411 shrl $2,%ecx /* copy by 32-bit words */ 412 cld /* nope, copy forwards */ 413 rep 414 movsl 415 movl 20(%esp),%ecx 416 andl $3,%ecx /* any bytes left? */ 417 rep 418 movsb 419 popl %edi 420 popl %esi 421 ret 422 423 ALIGN_TEXT 4241: 425 addl %ecx,%edi /* copy backwards */ 426 addl %ecx,%esi 427 andl $3,%ecx /* any fractional bytes? */ 428 decl %edi 429 decl %esi 430 std 431 rep 432 movsb 433 movl 20(%esp),%ecx /* copy remainder by 32-bit words */ 434 shrl $2,%ecx 435 subl $3,%esi 436 subl $3,%edi 437 rep 438 movsl 439 popl %edi 440 popl %esi 441 cld 442 ret 443 444ALTENTRY(ntohl) 445ENTRY(htonl) 446 movl 4(%esp),%eax 447#ifdef i486 448/* XXX */ 449/* Since Gas 1.38 does not grok bswap this has been coded as the 450 * equivalent bytes. This can be changed back to bswap when we 451 * upgrade to a newer version of Gas 452 */ 453 /* bswap %eax */ 454 .byte 0x0f 455 .byte 0xc8 456#else 457 xchgb %al,%ah 458 roll $16,%eax 459 xchgb %al,%ah 460#endif 461 ret 462 463ALTENTRY(ntohs) 464ENTRY(htons) 465 movzwl 4(%esp),%eax 466 xchgb %al,%ah 467 ret 468 469/*****************************************************************************/ 470/* copyout and fubyte family */ 471/*****************************************************************************/ 472/* 473 * Access user memory from inside the kernel. These routines and possibly 474 * the math- and DOS emulators should be the only places that do this. 475 * 476 * We have to access the memory with user's permissions, so use a segment 477 * selector with RPL 3. For writes to user space we have to additionally 478 * check the PTE for write permission, because the 386 does not check 479 * write permissions when we are executing with EPL 0. The 486 does check 480 * this if the WP bit is set in CR0, so we can use a simpler version here. 481 * 482 * These routines set curpcb->onfault for the time they execute. When a 483 * protection violation occurs inside the functions, the trap handler 484 * returns to *curpcb->onfault instead of the function. 485 */ 486 487 488ENTRY(copyout) /* copyout(from_kernel, to_user, len) */ 489 movl _curpcb,%eax 490 movl $copyout_fault,PCB_ONFAULT(%eax) 491 pushl %esi 492 pushl %edi 493 pushl %ebx 494 movl 16(%esp),%esi 495 movl 20(%esp),%edi 496 movl 24(%esp),%ebx 497 orl %ebx,%ebx /* anything to do? */ 498 jz done_copyout 499 500 /* 501 * Check explicitly for non-user addresses. If 486 write protection 502 * is being used, this check is essential because we are in kernel 503 * mode so the h/w does not provide any protection against writing 504 * kernel addresses. 505 * 506 * Otherwise, it saves having to load and restore %es to get the 507 * usual segment-based protection (the destination segment for movs 508 * is always %es). The other explicit checks for user-writablility 509 * are not quite sufficient. They fail for the user area because 510 * we mapped the user area read/write to avoid having an #ifdef in 511 * vm_machdep.c. They fail for user PTEs and/or PTDs! (107 512 * addresses including 0xff800000 and 0xfc000000). I'm not sure if 513 * this can be fixed. Marking the PTEs supervisor mode and the 514 * PDE's user mode would almost work, but there may be a problem 515 * with the self-referential PDE. 516 */ 517 movl %edi,%eax 518 addl %ebx,%eax 519 jc copyout_fault 520/* 521 * XXX STOP USING VM_MAXUSER_ADDRESS. 522 * It is an end address, not a max, so every time it is used correctly it 523 * looks like there is an off by one error, and of course it caused an off 524 * by one error in several places. 525 */ 526 cmpl $VM_MAXUSER_ADDRESS,%eax 527 ja copyout_fault 528 529#if defined(I386_CPU) 530 531#if defined(I486_CPU) || defined(I586_CPU) 532 cmpl $CPUCLASS_386,_cpu_class 533 jne 3f 534#endif 535/* 536 * We have to check each PTE for user write permission. 537 * The checking may cause a page fault, so it is important to set 538 * up everything for return via copyout_fault before here. 539 */ 540 /* compute number of pages */ 541 movl %edi,%ecx 542 andl $NBPG-1,%ecx 543 addl %ebx,%ecx 544 decl %ecx 545 shrl $IDXSHIFT+2,%ecx 546 incl %ecx 547 548 /* compute PTE offset for start address */ 549 movl %edi,%edx 550 shrl $IDXSHIFT,%edx 551 andb $0xfc,%dl 552 5531: /* check PTE for each page */ 554 movb _PTmap(%edx),%al 555 andb $0x07,%al /* Pages must be VALID + USERACC + WRITABLE */ 556 cmpb $0x07,%al 557 je 2f 558 559 /* simulate a trap */ 560 pushl %edx 561 pushl %ecx 562 shll $IDXSHIFT,%edx 563 pushl %edx 564 call _trapwrite /* trapwrite(addr) */ 565 popl %edx 566 popl %ecx 567 popl %edx 568 569 orl %eax,%eax /* if not ok, return EFAULT */ 570 jnz copyout_fault 571 5722: 573 addl $4,%edx 574 decl %ecx 575 jnz 1b /* check next page */ 576#endif /* I386_CPU */ 577 578 /* bcopy(%esi, %edi, %ebx) */ 5793: 580 movl %ebx,%ecx 581 shrl $2,%ecx 582 cld 583 rep 584 movsl 585 movb %bl,%cl 586 andb $3,%cl 587 rep 588 movsb 589 590done_copyout: 591 popl %ebx 592 popl %edi 593 popl %esi 594 xorl %eax,%eax 595 movl _curpcb,%edx 596 movl %eax,PCB_ONFAULT(%edx) 597 ret 598 599 ALIGN_TEXT 600copyout_fault: 601 popl %ebx 602 popl %edi 603 popl %esi 604 movl _curpcb,%edx 605 movl $0,PCB_ONFAULT(%edx) 606 movl $EFAULT,%eax 607 ret 608 609/* copyin(from_user, to_kernel, len) */ 610ENTRY(copyin) 611 movl _curpcb,%eax 612 movl $copyin_fault,PCB_ONFAULT(%eax) 613 pushl %esi 614 pushl %edi 615 movl 12(%esp),%esi /* caddr_t from */ 616 movl 16(%esp),%edi /* caddr_t to */ 617 movl 20(%esp),%ecx /* size_t len */ 618 619 /* 620 * make sure address is valid 621 */ 622 movl %esi,%edx 623 addl %ecx,%edx 624 jc copyin_fault 625 cmpl $VM_MAXUSER_ADDRESS,%edx 626 ja copyin_fault 627 628 movb %cl,%al 629 shrl $2,%ecx /* copy longword-wise */ 630 cld 631 rep 632 movsl 633 movb %al,%cl 634 andb $3,%cl /* copy remaining bytes */ 635 rep 636 movsb 637 638 popl %edi 639 popl %esi 640 xorl %eax,%eax 641 movl _curpcb,%edx 642 movl %eax,PCB_ONFAULT(%edx) 643 ret 644 645 ALIGN_TEXT 646copyin_fault: 647 popl %edi 648 popl %esi 649 movl _curpcb,%edx 650 movl $0,PCB_ONFAULT(%edx) 651 movl $EFAULT,%eax 652 ret 653 654/* 655 * fu{byte,sword,word} : fetch a byte (sword, word) from user memory 656 */ 657ALTENTRY(fuiword) 658ENTRY(fuword) 659 movl _curpcb,%ecx 660 movl $fusufault,PCB_ONFAULT(%ecx) 661 movl 4(%esp),%edx /* from */ 662 663 cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address is valid */ 664 ja fusufault 665 666 movl (%edx),%eax 667 movl $0,PCB_ONFAULT(%ecx) 668 ret 669 670/* 671 * These two routines are called from the profiling code, potentially 672 * at interrupt time. If they fail, that's okay, good things will 673 * happen later. Fail all the time for now - until the trap code is 674 * able to deal with this. 675 */ 676ALTENTRY(suswintr) 677ENTRY(fuswintr) 678 movl $-1,%eax 679 ret 680 681ENTRY(fusword) 682 movl _curpcb,%ecx 683 movl $fusufault,PCB_ONFAULT(%ecx) 684 movl 4(%esp),%edx 685 686 cmpl $VM_MAXUSER_ADDRESS-2,%edx 687 ja fusufault 688 689 movzwl (%edx),%eax 690 movl $0,PCB_ONFAULT(%ecx) 691 ret 692 693ALTENTRY(fuibyte) 694ENTRY(fubyte) 695 movl _curpcb,%ecx 696 movl $fusufault,PCB_ONFAULT(%ecx) 697 movl 4(%esp),%edx 698 699 cmpl $VM_MAXUSER_ADDRESS-1,%eax 700 ja fusufault 701 702 movzbl (%edx),%eax 703 movl $0,PCB_ONFAULT(%ecx) 704 ret 705 706 ALIGN_TEXT 707fusufault: 708 movl _curpcb,%ecx 709 xorl %eax,%eax 710 movl %eax,PCB_ONFAULT(%ecx) 711 decl %eax 712 ret 713 714/* 715 * su{byte,sword,word}: write a byte (word, longword) to user memory 716 */ 717ALTENTRY(suiword) 718ENTRY(suword) 719 movl _curpcb,%ecx 720 movl $fusufault,PCB_ONFAULT(%ecx) 721 movl 4(%esp),%edx 722 723#if defined(I386_CPU) 724 725#if defined(I486_CPU) || defined(I586_CPU) 726 cmpl $CPUCLASS_386,_cpu_class 727 jne 2f /* we only have to set the right segment selector */ 728#endif /* I486_CPU || I586_CPU */ 729 730 /* XXX - page boundary crossing is still not handled */ 731 movl %edx,%eax 732 shrl $IDXSHIFT,%edx 733 andb $0xfc,%dl 734 movb _PTmap(%edx),%dl 735 andb $0x7,%dl /* must be VALID + USERACC + WRITE */ 736 cmpb $0x7,%dl 737 je 1f 738 739 /* simulate a trap */ 740 pushl %eax 741 call _trapwrite 742 popl %edx /* remove junk parameter from stack */ 743 movl _curpcb,%ecx /* restore trashed register */ 744 orl %eax,%eax 745 jnz fusufault 7461: 747 movl 4(%esp),%edx 748#endif 749 7502: 751 cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address validity */ 752 ja fusufault 753 754 movl 8(%esp),%eax 755 movl %eax,(%edx) 756 xorl %eax,%eax 757 movl %eax,PCB_ONFAULT(%ecx) 758 ret 759 760ENTRY(susword) 761 movl _curpcb,%ecx 762 movl $fusufault,PCB_ONFAULT(%ecx) 763 movl 4(%esp),%edx 764 765#if defined(I386_CPU) 766 767#if defined(I486_CPU) || defined(I586_CPU) 768 cmpl $CPUCLASS_386,_cpu_class 769 jne 2f 770#endif /* I486_CPU || I586_CPU */ 771 772 /* XXX - page boundary crossing is still not handled */ 773 movl %edx,%eax 774 shrl $IDXSHIFT,%edx 775 andb $0xfc,%dl 776 movb _PTmap(%edx),%dl 777 andb $0x7,%dl /* must be VALID + USERACC + WRITE */ 778 cmpb $0x7,%dl 779 je 1f 780 781 /* simulate a trap */ 782 pushl %eax 783 call _trapwrite 784 popl %edx /* remove junk parameter from stack */ 785 movl _curpcb,%ecx /* restore trashed register */ 786 orl %eax,%eax 787 jnz fusufault 7881: 789 movl 4(%esp),%edx 790#endif 791 7922: 793 cmpl $VM_MAXUSER_ADDRESS-2,%edx /* verify address validity */ 794 ja fusufault 795 796 movw 8(%esp),%ax 797 movw %ax,(%edx) 798 xorl %eax,%eax 799 movl %eax,PCB_ONFAULT(%ecx) 800 ret 801 802ALTENTRY(suibyte) 803ENTRY(subyte) 804 movl _curpcb,%ecx 805 movl $fusufault,PCB_ONFAULT(%ecx) 806 movl 4(%esp),%edx 807 808#if defined(I386_CPU) 809 810#if defined(I486_CPU) || defined(I586_CPU) 811 cmpl $CPUCLASS_386,_cpu_class 812 jne 2f 813#endif /* I486_CPU || I586_CPU */ 814 815 movl %edx,%eax 816 shrl $IDXSHIFT,%edx 817 andb $0xfc,%dl 818 movb _PTmap(%edx),%dl 819 andb $0x7,%dl /* must be VALID + USERACC + WRITE */ 820 cmpb $0x7,%dl 821 je 1f 822 823 /* simulate a trap */ 824 pushl %eax 825 call _trapwrite 826 popl %edx /* remove junk parameter from stack */ 827 movl _curpcb,%ecx /* restore trashed register */ 828 orl %eax,%eax 829 jnz fusufault 8301: 831 movl 4(%esp),%edx 832#endif 833 8342: 835 cmpl $VM_MAXUSER_ADDRESS-1,%edx /* verify address validity */ 836 ja fusufault 837 838 movb 8(%esp),%al 839 movb %al,(%edx) 840 xorl %eax,%eax 841 movl %eax,PCB_ONFAULT(%ecx) 842 ret 843 844/* 845 * copyoutstr(from, to, maxlen, int *lencopied) 846 * copy a string from from to to, stop when a 0 character is reached. 847 * return ENAMETOOLONG if string is longer than maxlen, and 848 * EFAULT on protection violations. If lencopied is non-zero, 849 * return the actual length in *lencopied. 850 */ 851ENTRY(copyoutstr) 852 pushl %esi 853 pushl %edi 854 movl _curpcb,%ecx 855 movl $cpystrflt,PCB_ONFAULT(%ecx) 856 857 movl 12(%esp),%esi /* %esi = from */ 858 movl 16(%esp),%edi /* %edi = to */ 859 movl 20(%esp),%edx /* %edx = maxlen */ 860 cld 861 862#if defined(I386_CPU) 863 864#if defined(I486_CPU) || defined(I586_CPU) 865 cmpl $CPUCLASS_386,_cpu_class 866 jne 5f 867#endif /* I486_CPU || I586_CPU */ 868 8691: 870 /* 871 * It suffices to check that the first byte is in user space, because 872 * we look at a page at a time and the end address is on a page 873 * boundary. 874 */ 875 cmpl $VM_MAXUSER_ADDRESS-1,%edi 876 ja cpystrflt 877 878 movl %edi,%eax 879 shrl $IDXSHIFT,%eax 880 andb $0xfc,%al 881 movb _PTmap(%eax),%al 882 andb $7,%al 883 cmpb $7,%al 884 je 2f 885 886 /* simulate trap */ 887 pushl %edx 888 pushl %edi 889 call _trapwrite 890 cld 891 popl %edi 892 popl %edx 893 orl %eax,%eax 894 jnz cpystrflt 895 8962: /* copy up to end of this page */ 897 movl %edi,%eax 898 andl $NBPG-1,%eax 899 movl $NBPG,%ecx 900 subl %eax,%ecx /* ecx = NBPG - (src % NBPG) */ 901 cmpl %ecx,%edx 902 jae 3f 903 movl %edx,%ecx /* ecx = min(ecx, edx) */ 9043: 905 orl %ecx,%ecx 906 jz 4f 907 decl %ecx 908 decl %edx 909 lodsb 910 stosb 911 orb %al,%al 912 jnz 3b 913 914 /* Success -- 0 byte reached */ 915 decl %edx 916 xorl %eax,%eax 917 jmp 6f 918 9194: /* next page */ 920 orl %edx,%edx 921 jnz 1b 922 923 /* edx is zero -- return ENAMETOOLONG */ 924 movl $ENAMETOOLONG,%eax 925 jmp cpystrflt_x 926#endif /* I386_CPU */ 927 928#if defined(I486_CPU) || defined(I586_CPU) 9295: 930 incl %edx 9311: 932 decl %edx 933 jz 2f 934 /* 935 * XXX - would be faster to rewrite this function to use 936 * strlen() and copyout(). 937 */ 938 cmpl $VM_MAXUSER_ADDRESS-1,%edi 939 ja cpystrflt 940 941 lodsb 942 stosb 943 orb %al,%al 944 jnz 1b 945 946 /* Success -- 0 byte reached */ 947 decl %edx 948 xorl %eax,%eax 949 jmp cpystrflt_x 9502: 951 /* edx is zero -- return ENAMETOOLONG */ 952 movl $ENAMETOOLONG,%eax 953 jmp cpystrflt_x 954 955#endif /* I486_CPU || I586_CPU */ 956 957cpystrflt: 958 movl $EFAULT,%eax 959cpystrflt_x: 960 /* set *lencopied and return %eax */ 961 movl _curpcb,%ecx 962 movl $0,PCB_ONFAULT(%ecx) 963 movl 20(%esp),%ecx 964 subl %edx,%ecx 965 movl 24(%esp),%edx 966 orl %edx,%edx 967 jz 1f 968 movl %ecx,(%edx) 9691: 970 popl %edi 971 popl %esi 972 ret 973 974 975/* 976 * copyinstr(from, to, maxlen, int *lencopied) 977 * copy a string from from to to, stop when a 0 character is reached. 978 * return ENAMETOOLONG if string is longer than maxlen, and 979 * EFAULT on protection violations. If lencopied is non-zero, 980 * return the actual length in *lencopied. 981 */ 982ENTRY(copyinstr) 983 pushl %esi 984 pushl %edi 985 movl _curpcb,%ecx 986 movl $copyinstr_fault,PCB_ONFAULT(%ecx) 987 988 movl 12(%esp),%esi /* %esi = from */ 989 movl 16(%esp),%edi /* %edi = to */ 990 movl 20(%esp),%edx /* %edx = maxlen */ 991 pushl %gs 992 movl __udatasel,%eax 993 movl %ax,%gs 994 incl %edx 995 cld 9961: 997 decl %edx 998 jz 2f 999 gs 1000 lodsb 1001 stosb 1002 orb %al,%al 1003 jnz 1b 1004 1005 /* Success -- 0 byte reached */ 1006 decl %edx 1007 xorl %eax,%eax 1008 jmp 3f 10092: 1010 /* edx is zero -- return ENAMETOOLONG */ 1011 movl $ENAMETOOLONG,%eax 1012 jmp 3f 1013 1014copyinstr_fault: 1015 movl $EFAULT,%eax 10163: 1017 /* set *lencopied and return %eax */ 1018 movl _curpcb,%ecx 1019 movl $0,PCB_ONFAULT(%ecx) 1020 movl 24(%esp),%ecx 1021 subl %edx,%ecx 1022 movl 28(%esp),%edx 1023 orl %edx,%edx 1024 jz 4f 1025 movl %ecx,(%edx) 10264: 1027 popl %gs 1028 popl %edi 1029 popl %esi 1030 ret 1031 1032 1033/* 1034 * copystr(from, to, maxlen, int *lencopied) 1035 */ 1036ENTRY(copystr) 1037 pushl %esi 1038 pushl %edi 1039 1040 movl 12(%esp),%esi /* %esi = from */ 1041 movl 16(%esp),%edi /* %edi = to */ 1042 movl 20(%esp),%edx /* %edx = maxlen */ 1043 incl %edx 1044 cld 10451: 1046 decl %edx 1047 jz 4f 1048 lodsb 1049 stosb 1050 orb %al,%al 1051 jnz 1b 1052 1053 /* Success -- 0 byte reached */ 1054 decl %edx 1055 xorl %eax,%eax 1056 jmp 6f 10574: 1058 /* edx is zero -- return ENAMETOOLONG */ 1059 movl $ENAMETOOLONG,%eax 1060 10616: 1062 /* set *lencopied and return %eax */ 1063 movl 20(%esp),%ecx 1064 subl %edx,%ecx 1065 movl 24(%esp),%edx 1066 orl %edx,%edx 1067 jz 7f 1068 movl %ecx,(%edx) 10697: 1070 popl %edi 1071 popl %esi 1072 ret 1073 1074/* 1075 * Handling of special 386 registers and descriptor tables etc 1076 */ 1077/* void lgdt(struct region_descriptor *rdp); */ 1078ENTRY(lgdt) 1079 /* reload the descriptor table */ 1080 movl 4(%esp),%eax 1081 lgdt (%eax) 1082 1083 /* flush the prefetch q */ 1084 jmp 1f 1085 nop 10861: 1087 /* reload "stale" selectors */ 1088 movl $KDSEL,%eax 1089 movl %ax,%ds 1090 movl %ax,%es 1091 movl %ax,%ss 1092 1093 /* reload code selector by turning return into intersegmental return */ 1094 movl (%esp),%eax 1095 pushl %eax 1096# movl $KCSEL,4(%esp) 1097 movl $8,4(%esp) 1098 lret 1099 1100/* 1101 * void lidt(struct region_descriptor *rdp); 1102 */ 1103ENTRY(lidt) 1104 movl 4(%esp),%eax 1105 lidt (%eax) 1106 ret 1107 1108/* 1109 * void lldt(u_short sel) 1110 */ 1111ENTRY(lldt) 1112 lldt 4(%esp) 1113 ret 1114 1115/* 1116 * void ltr(u_short sel) 1117 */ 1118ENTRY(ltr) 1119 ltr 4(%esp) 1120 ret 1121 1122/* ssdtosd(*ssdp,*sdp) */ 1123ENTRY(ssdtosd) 1124 pushl %ebx 1125 movl 8(%esp),%ecx 1126 movl 8(%ecx),%ebx 1127 shll $16,%ebx 1128 movl (%ecx),%edx 1129 roll $16,%edx 1130 movb %dh,%bl 1131 movb %dl,%bh 1132 rorl $8,%ebx 1133 movl 4(%ecx),%eax 1134 movw %ax,%dx 1135 andl $0xf0000,%eax 1136 orl %eax,%ebx 1137 movl 12(%esp),%ecx 1138 movl %edx,(%ecx) 1139 movl %ebx,4(%ecx) 1140 popl %ebx 1141 ret 1142 1143/* load_cr0(cr0) */ 1144ENTRY(load_cr0) 1145 movl 4(%esp),%eax 1146 movl %eax,%cr0 1147 ret 1148 1149/* rcr0() */ 1150ENTRY(rcr0) 1151 movl %cr0,%eax 1152 ret 1153 1154/* rcr3() */ 1155ENTRY(rcr3) 1156 movl %cr3,%eax 1157 ret 1158 1159/* void load_cr3(caddr_t cr3) */ 1160ENTRY(load_cr3) 1161 movl 4(%esp),%eax 1162 orl $I386_CR3PAT,%eax 1163 movl %eax,%cr3 1164 ret 1165 1166 1167/*****************************************************************************/ 1168/* setjump, longjump */ 1169/*****************************************************************************/ 1170 1171ENTRY(setjmp) 1172 movl 4(%esp),%eax 1173 movl %ebx,(%eax) /* save ebx */ 1174 movl %esp,4(%eax) /* save esp */ 1175 movl %ebp,8(%eax) /* save ebp */ 1176 movl %esi,12(%eax) /* save esi */ 1177 movl %edi,16(%eax) /* save edi */ 1178 movl (%esp),%edx /* get rta */ 1179 movl %edx,20(%eax) /* save eip */ 1180 xorl %eax,%eax /* return(0); */ 1181 ret 1182 1183ENTRY(longjmp) 1184 movl 4(%esp),%eax 1185 movl (%eax),%ebx /* restore ebx */ 1186 movl 4(%eax),%esp /* restore esp */ 1187 movl 8(%eax),%ebp /* restore ebp */ 1188 movl 12(%eax),%esi /* restore esi */ 1189 movl 16(%eax),%edi /* restore edi */ 1190 movl 20(%eax),%edx /* get rta */ 1191 movl %edx,(%esp) /* put in return frame */ 1192 xorl %eax,%eax /* return(1); */ 1193 incl %eax 1194 ret 1195