?? bcopy.s
字號:
fistpq 56(%edi) fistpq 48(%edi) fistpq 40(%edi) fistpq 32(%edi) fistpq 24(%edi) fistpq 16(%edi) fistpq 8(%edi) fistpq 0(%edi) addl $64,%esi addl $64,%edi subl $64,%ecx cmpl $64,%ecx jae large_i586_bcopy_loop popl %eax addl %eax,%ecx cmpl $64,%ecx jae 4b cmpl $0,_npxproc je i586_bc2 frstor 0(%esp) addl $108,%espi586_bc2: lmsw %dx movb $0xfe,kernel_fpu_lock/* * This is a duplicate of the main part of generic_bcopy. See the comments * there. Jumping into generic_bcopy would cost a whole 0-1 cycles and * would mess up high resolution profiling. */ ALIGN_TEXTsmall_i586_bcopy: shrl $2,%ecx cld rep movsl movl 20(%esp),%ecx andl $3,%ecx rep movsb popl %edi popl %esi ret ALIGN_TEXT1: addl %ecx,%edi addl %ecx,%esi decl %edi decl %esi andl $3,%ecx std rep movsb movl 20(%esp),%ecx shrl $2,%ecx subl $3,%esi subl $3,%edi rep movsl popl %edi popl %esi cld ret#endif /* I586_CPU && NNPX > 0 *//* * Note: memcpy does not support overlapping copies */ENTRY(memcpy) pushl %edi pushl %esi movl 12(%esp),%edi movl 16(%esp),%esi movl 20(%esp),%ecx movl %edi,%eax shrl $2,%ecx /* copy by 32-bit words */ cld /* nope, copy forwards */ rep movsl movl 20(%esp),%ecx andl $3,%ecx /* any bytes left? */ rep movsb popl %esi popl %edi ret/*****************************************************************************//* copyout and fubyte family *//*****************************************************************************//* * Access user memory from inside the kernel. These routines and possibly * the math- and DOS emulators should be the only places that do this. * * We have to access the memory with user's permissions, so use a segment * selector with RPL 3. For writes to user space we have to additionally * check the PTE for write permission, because the 386 does not check * write permissions when we are executing with EPL 0. The 486 does check * this if the WP bit is set in CR0, so we can use a simpler version here. * * These routines set curpcb->onfault for the time they execute. When a * protection violation occurs inside the functions, the trap handler * returns to *curpcb->onfault instead of the function. *//* copyout(from_kernel, to_user, len) */ENTRY(copyout) MEXITCOUNT jmp *_copyout_vectorENTRY(generic_copyout) movl _curpcb,%eax movl $copyout_fault,PCB_ONFAULT(%eax) pushl %esi pushl %edi pushl %ebx movl 16(%esp),%esi movl 20(%esp),%edi movl 24(%esp),%ebx testl %ebx,%ebx /* anything to do? */ jz done_copyout /* * Check explicitly for non-user addresses. If 486 write protection * is being used, this check is essential because we are in kernel * mode so the h/w does not provide any protection against writing * kernel addresses. */ /* * First, prevent address wrapping. */ movl %edi,%eax addl %ebx,%eax jc copyout_fault/* * XXX STOP USING VM_MAXUSER_ADDRESS. * It is an end address, not a max, so every time it is used correctly it * looks like there is an off by one error, and of course it caused an off * by one error in several places. */ cmpl $VM_MAXUSER_ADDRESS,%eax ja copyout_fault#if defined(I386_CPU)#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) cmpl $CPUCLASS_386,_cpu_class jne 3f#endif/* * We have to check each PTE for user write permission. * The checking may cause a page fault, so it is important to set * up everything for return via copyout_fault before here. */ /* compute number of pages */ movl %edi,%ecx andl $PAGE_MASK,%ecx addl %ebx,%ecx decl %ecx shrl $IDXSHIFT+2,%ecx incl %ecx /* compute PTE offset for start address */ movl %edi,%edx shrl $IDXSHIFT,%edx andb $0xfc,%dl1: /* check PTE for each page */ leal _PTmap(%edx),%eax shrl $IDXSHIFT,%eax andb $0xfc,%al testb $PG_V,_PTmap(%eax) /* PTE page must be valid */ je 4f movb _PTmap(%edx),%al andb $PG_V|PG_RW|PG_U,%al /* page must be valid and user writable */ cmpb $PG_V|PG_RW|PG_U,%al je 2f4: /* simulate a trap */ pushl %edx pushl %ecx shll $IDXSHIFT,%edx pushl %edx call _trapwrite /* trapwrite(addr) */ popl %edx popl %ecx popl %edx testl %eax,%eax /* if not ok, return EFAULT */ jnz copyout_fault2: addl $4,%edx decl %ecx jnz 1b /* check next page */#endif /* I386_CPU */ /* bcopy(%esi, %edi, %ebx) */3: movl %ebx,%ecx#if defined(I586_CPU) && NNPX > 0 ALIGN_TEXTslow_copyout:#endif shrl $2,%ecx cld rep movsl movb %bl,%cl andb $3,%cl rep movsbdone_copyout: popl %ebx popl %edi popl %esi xorl %eax,%eax movl _curpcb,%edx movl %eax,PCB_ONFAULT(%edx) ret ALIGN_TEXTcopyout_fault: popl %ebx popl %edi popl %esi movl _curpcb,%edx movl $0,PCB_ONFAULT(%edx) movl $EFAULT,%eax ret#if defined(I586_CPU) && NNPX > 0ENTRY(i586_copyout) /* * Duplicated from generic_copyout. Could be done a bit better. */ movl _curpcb,%eax movl $copyout_fault,PCB_ONFAULT(%eax) pushl %esi pushl %edi pushl %ebx movl 16(%esp),%esi movl 20(%esp),%edi movl 24(%esp),%ebx testl %ebx,%ebx /* anything to do? */ jz done_copyout /* * Check explicitly for non-user addresses. If 486 write protection * is being used, this check is essential because we are in kernel * mode so the h/w does not provide any protection against writing * kernel addresses. */ /* * First, prevent address wrapping. */ movl %edi,%eax addl %ebx,%eax jc copyout_fault/* * XXX STOP USING VM_MAXUSER_ADDRESS. * It is an end address, not a max, so every time it is used correctly it * looks like there is an off by one error, and of course it caused an off * by one error in several places. */ cmpl $VM_MAXUSER_ADDRESS,%eax ja copyout_fault /* bcopy(%esi, %edi, %ebx) */3: movl %ebx,%ecx /* * End of duplicated code. */ cmpl $1024,%ecx jb slow_copyout pushl %ecx call _fastmove addl $4,%esp jmp done_copyout#endif /* I586_CPU && NNPX > 0 *//* copyin(from_user, to_kernel, len) */ENTRY(copyin) MEXITCOUNT jmp *_copyin_vectorENTRY(generic_copyin) movl _curpcb,%eax movl $copyin_fault,PCB_ONFAULT(%eax) pushl %esi pushl %edi movl 12(%esp),%esi /* caddr_t from */ movl 16(%esp),%edi /* caddr_t to */ movl 20(%esp),%ecx /* size_t len */ /* * make sure address is valid */ movl %esi,%edx addl %ecx,%edx jc copyin_fault cmpl $VM_MAXUSER_ADDRESS,%edx ja copyin_fault#if defined(I586_CPU) && NNPX > 0 ALIGN_TEXTslow_copyin:#endif movb %cl,%al shrl $2,%ecx /* copy longword-wise */ cld rep movsl movb %al,%cl andb $3,%cl /* copy remaining bytes */ rep movsb#if defined(I586_CPU) && NNPX > 0 ALIGN_TEXTdone_copyin:#endif popl %edi popl %esi xorl %eax,%eax movl _curpcb,%edx movl %eax,PCB_ONFAULT(%edx) ret ALIGN_TEXTcopyin_fault: popl %edi popl %esi movl _curpcb,%edx movl $0,PCB_ONFAULT(%edx) movl $EFAULT,%eax ret#if defined(I586_CPU) && NNPX > 0ENTRY(i586_copyin) /* * Duplicated from generic_copyin. Could be done a bit better. */ movl _curpcb,%eax movl $copyin_fault,PCB_ONFAULT(%eax) pushl %esi pushl %edi movl 12(%esp),%esi /* caddr_t from */ movl 16(%esp),%edi /* caddr_t to */ movl 20(%esp),%ecx /* size_t len */ /* * make sure address is valid */ movl %esi,%edx addl %ecx,%edx jc copyin_fault cmpl $VM_MAXUSER_ADDRESS,%edx ja copyin_fault /* * End of duplicated code. */ cmpl $1024,%ecx jb slow_copyin pushl %ebx /* XXX prepare for fastmove_fault */ pushl %ecx call _fastmove addl $8,%esp jmp done_copyin#endif /* I586_CPU && NNPX > 0 */#if defined(I586_CPU) && NNPX > 0/* fastmove(src, dst, len) src in %esi dst in %edi len in %ecx XXX changed to on stack for profiling uses %eax and %edx for tmp. storage *//* XXX use ENTRY() to get profiling. fastmove() is actually a non-entry. */ENTRY(fastmove) pushl %ebp movl %esp,%ebp subl $PCB_SAVEFPU_SIZE+3*4,%esp movl 8(%ebp),%ecx cmpl $63,%ecx jbe fastmove_tail testl $7,%esi /* check if src addr is multiple of 8 */ jnz fastmove_tail testl $7,%edi /* check if dst addr is multiple of 8 */ jnz fastmove_tail/* if (npxproc != NULL) { */ cmpl $0,_npxproc je 6f/* fnsave(&curpcb->pcb_savefpu); */ movl _curpcb,%eax fnsave PCB_SAVEFPU(%eax)/* npxproc = NULL; */ movl $0,_npxproc/* } */6:/* now we own the FPU. *//* * The process' FP state is saved in the pcb, but if we get * switched, the cpu_switch() will store our FP state in the * pcb. It should be possible to avoid all the copying for * this, e.g., by setting a flag to tell cpu_switch() to * save the state somewhere else. *//* tmp = curpcb->pcb_savefpu; */ movl %ecx,-12(%ebp) movl %esi,-8(%ebp) movl %edi,-4(%ebp) movl %esp,%edi movl _curpcb,%esi addl $PCB_SAVEFPU,%esi cld movl $PCB_SAVEFPU_SIZE>>2,%ecx rep movsl movl -12(%ebp),%ecx movl -8(%ebp),%esi movl -4(%ebp),%edi/* stop_emulating(); */ clts/* npxproc = curproc; */ movl _curproc,%eax movl %eax,_npxproc movl _curpcb,%eax movl $fastmove_fault,PCB_ONFAULT(%eax)4: movl %ecx,-12(%ebp) cmpl $1792,%ecx jbe 2f movl $1792,%ecx2: subl %ecx,-12(%ebp) cmpl $256,%ecx jb 5f movl %ecx,-8(%ebp) movl %esi,-4(%ebp) ALIGN_TEXT3: movl 0(%esi),%eax movl 32(%esi),%eax movl 64(%esi),%eax movl 96(%esi),%eax movl 128(%esi),%eax movl 160(%esi),%eax movl 192(%esi),%eax movl 224(%esi),%eax addl $256,%esi subl $256,%ecx cmpl $256,%ecx jae 3b movl -8(%ebp),%ecx movl -4(%ebp),%esi5: ALIGN_TEXTfastmove_loop: fildq 0(%esi) fildq 8(%esi) fildq 16(%esi) fildq 24(%esi) fildq 32(%esi) fildq 40(%esi) fildq 48(%esi) fildq 56(%esi) fistpq 56(%edi) fistpq 48(%edi) fistpq 40(%edi) fistpq 32(%edi) fistpq 24(%edi) fistpq 16(%edi) fistpq 8(%edi) fistpq 0(%edi) addl $-64,%ecx addl $64,%esi addl $64,%edi cmpl $63,%ecx ja fastmove_loop movl -12(%ebp),%eax addl %eax,%ecx cmpl $64,%ecx jae 4b/* curpcb->pcb_savefpu = tmp; */ movl %ecx,-12(%ebp) movl %esi,-8(%ebp) movl %edi,-4(%ebp) movl _curpcb,%edi addl $PCB_SAVEFPU,%edi movl %esp,%esi cld movl $PCB_SAVEFPU_SIZE>>2,%ecx rep movsl movl -12(%ebp),%ecx movl -8(%ebp),%esi movl -4(%ebp),%edi/* start_emulating(); */ smsw %ax orb $CR0_TS,%al lmsw %ax/* npxproc = NULL; */ movl $0,_npxproc ALIGN_TEXT
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -