📄 big_copy.s
字号:
* kzero(addr, count) * caddr_t addr; * u_int count; */ ENTRY(kzero) sethi %hi(zeroerr), %o2 b do_zero or %o2, %lo(zeroerr), %o2/* * We got here because of a fault during kzero. */zeroerr: st %o5, [_u+U_LOFAULT] ! restore old u.u_lofault retl restore %g0, EIO, %o0 ! return (EIO)/* * Zero a block of storage. * * bzero(addr, length) * caddr_t addr; * u_int count; */ ENTRY2(bzero,blkclr) mov 0, %o2do_zero: ld [_u+U_LOFAULT], %o5 ! save u.u_lofault cmp %o1, 15 ! check for small counts bl byteclr ! just clear bytes st %o2, [_u+U_LOFAULT] ! install new vector ! ! Check for word alignment. ! btst 3, %o0 bz _bzero_probe mov 0x100, %o3 ! constant size of main loop ! ! ! clear bytes until word aligned !1: clrb [%o0] add %o0, 1, %o0 btst 3, %o0 bnz 1b sub %o1, 1, %o1 ! ! Word aligned. ! Probe to see if word access is allowed (i.e. not VME_D16) ! This assumes that the source will not change to VME_D16 ! during the bzero. This will get a data fault with ! be_vmeserr set if unsuccessful. Trap will ! then return to bzero_vme16. This is gross but fast. ! .global _bzero_probe, _ebzero_probe_bzero_probe: clr [%o0] ! clear word to probe_ebzero_probe: ! ! If needed move a word to become double-word aligned. ! btst 7, %o0 ! align to double-word boundary bz 2f clr %g1 ! clr g1 for second half of double %g0 sub %o1, 4, %o1 b 2f add %o0, 4, %o0 !std %g0, [%o0+0xf8]zeroblock: std %g0, [%o0+0xf0] std %g0, [%o0+0xe8] std %g0, [%o0+0xe0] std %g0, [%o0+0xd8] std %g0, [%o0+0xd0] std %g0, [%o0+0xc8] std %g0, [%o0+0xc0] std %g0, [%o0+0xb8] std %g0, [%o0+0xb0] std %g0, [%o0+0xa8] std %g0, [%o0+0xa0] std %g0, [%o0+0x98] std %g0, [%o0+0x90] std %g0, [%o0+0x88] std %g0, [%o0+0x80] std %g0, [%o0+0x78] std %g0, [%o0+0x70] std %g0, [%o0+0x68] std %g0, [%o0+0x60] std %g0, [%o0+0x58] std %g0, [%o0+0x50] std %g0, [%o0+0x48] std %g0, [%o0+0x40] std %g0, [%o0+0x38] std %g0, [%o0+0x30] std %g0, [%o0+0x28] std %g0, [%o0+0x20] std %g0, [%o0+0x18] std %g0, [%o0+0x10] std %g0, [%o0+0x08] std %g0, [%o0]zinst: add %o0, %o3, %o0 ! increment source address sub %o1, %o3, %o1 ! decrement count2: cmp %o1, 0x100 ! can we do whole chunk? bge,a zeroblock std %g0, [%o0+0xf8] ! do first double of chunk cmp %o1, 7 ! can we zero any more double words ble byteclr ! too small go zero bytes andn %o1, 7, %o3 ! %o3 bytes left, double-word aligned srl %o3, 1, %o2 ! using doubles, need 1 instr / 2 words set zinst, %o4 ! address of clr instructions sub %o4, %o2, %o4 ! jmp address relative to instr jmp %o4 nop ! ! do leftover bytes !3: add %o0, 1, %o0 ! increment addressbyteclr: subcc %o1, 1, %o1 ! decrement count bge,a 3b clrb [%o0] ! zero a byte st %o5, [_u+U_LOFAULT] ! restore old u.u_lofault retl mov 0, %o0 ! return (0)/* * bcopy_vme16(from, to, count) * Block copy to/from a 16 bit vme device. * There is little optimization because the VME is so slow. * We are only entered after a VME size error trap from within bcopy. * We get here with more than 3 bytes to copy. */ ENTRY(bcopy_vme16) xor %i0, %i1, %i4 ! test for mutually half word aligned btst 1, %i4 bnz bytecp ! misaligned, copy bytes .empty btst 1, %i0 ! test for initial byte bz,a 1f andn %i2, 1, %i3 ! count of aligned bytes to clear ldub [%i0], %i4 ! copy initial byte add %i0, 1, %i0 stb %i4, [%i1] add %i1, 1, %i1 sub %i2, 1, %i2 andn %i2, 1, %i3 ! count of aligned bytes to clear1: and %i2, 1, %i2 ! unaligned leftover count2: lduh [%i0], %i4 ! read from address add %i0, 2, %i0 ! inc from address sth %i4, [%i1] ! write at destination address subcc %i3, 2, %i3 ! dec count bg 2b add %i1, 2, %i1 ! delay slot, inc to address b,a bytecp ! copy remaining bytes, if any/* * bzero_vme16(addr, length) * Zero a block of VME_D16 memory. * There is little optimization because the VME is so slow. * We get here with more than 3 bytes to clear. */ ENTRY(bzero_vme16) ! ! clear memory until halfword aligned !1: btst 1, %o0 ! test for half word aligned bz,a 2f andn %o1, 1, %o3 ! count of aligned bytes to clear clrb [%o0] ! clear 1 byte sub %o1, 1, %o1 add %o0, 1, %o0 andn %o1, 1, %o3 ! count of aligned bytes to clear ! ! now half word aligned !2: and %o1, 1, %o1 ! unaligned leftover count3: clrh [%o0] ! zero word subcc %o3, 2, %o3 ! decrement count bg 3b add %o0, 2, %o0 ! increment address b,a byteclr ! zero remaining bytes, if any#endif never/* * Copy a null terminated string from one point to another in * the kernel address space. * NOTE - don't use %o5 in this routine as copy{in,out}str uses it. * * copystr(from, to, maxlength, lencopied) * caddr_t from, to; * u_int maxlength, *lencopied; */ ENTRY(copystr) tst %o2 bg 1f mov %o2, %o4 ! save original count ! ! maxlength <= 0 ! bz cs_out ! maxlength = 0 mov ENAMETOOLONG, %o0 retl ! maxlength < 0 mov EFAULT, %o0 ! return (EFAULT) ! ! Do a byte by byte loop. ! We do this instead of a word by word copy because most strings ! are small and this takes a small number of cache lines. !0: add %o0, 1, %o0 ! interlock slot, inc src addr stb %g1, [%o1] ! store byte tst %g1 ! null byte? bnz 1f add %o1, 1, %o1 ! incr dst addr b cs_out ! last byte in string mov 0, %o0 ! ret code = 01: subcc %o2, 1, %o2 ! test count bge,a 0b ldub [%o0], %g1 ! delay slot, get source byte mov 0, %o2 ! max number of bytes moved mov ENAMETOOLONG, %o0 ! ret code = ENAMETOOLONGcs_out: tst %o3 ! want length? bz 2f .empty sub %o4, %o2, %o4 ! compute length and store it st %o4, [%o3]2: retl nop ! return (ret code)#ifdef never/* * Transfer data to and from user space - * Note that these routines can cause faults * It is assumed that the kernel has nothing at * less than KERNELBASE in the virtual address space. *//* * Copy kernel data to user space. * * int * copyout(kaddr, uaddr, count) * caddr_t kaddr, uaddr; * u_int count; */ ENTRY(copyout) sethi %hi(KERNELBASE), %g1 ! test uaddr < KERNELBASE cmp %o1, %g1 sethi %hi(copyioerr), %o3 ! copyioerr is lofault value bleu do_copy ! common code or %o3, %lo(copyioerr), %o3 retl ! return (EFAULT) mov EFAULT, %o0/* * Copy user data to kernel space. * * int * copyin(uaddr, kaddr, count) * caddr_t uaddr, kaddr; * u_int count; */ ENTRY(copyin) sethi %hi(KERNELBASE), %g1 ! test uaddr < KERNELBASE cmp %o0, %g1 sethi %hi(copyioerr), %o3 ! copyioerr is lofault value bleu do_copy ! common code or %o3, %lo(copyioerr), %o3 retl ! return (EFAULT) mov EFAULT, %o0/* * We got here because of a fault during copy{in,out}. */copyioerr: st %l6, [_u+U_LOFAULT] ! restore old u.u_lofault ret restore %g0, EFAULT, %o0 ! return (EFAULT)/* * Copy a null terminated string from the user address space into * the kernel address space. * * copyinstr(uaddr, kaddr, maxlength, lencopied) * caddr_t uaddr, kaddr; * u_int maxlength, *lencopied; */ ENTRY(copyinstr) sethi %hi(KERNELBASE), %g1 ! test uaddr < KERNELBASE cmp %o0, %g1 bgeu copystrerr mov %o7, %o5 ! save return addresscs_common: set copystrerr, %g1 call _copystr st %g1, [_u+U_LOFAULT] ! catch faults jmp %o5 + 8 ! return (results of copystr) clr [_u+U_LOFAULT] ! clear fault catcher/* * Copy a null terminated string from the kernel * address space to the user address space. * * copyoutstr(kaddr, uaddr, maxlength, lencopied) * caddr_t kaddr, uaddr; * u_int maxlength, *lencopied; */ ENTRY(copyoutstr) sethi %hi(KERNELBASE), %g1 ! test uaddr < KERNELBASE cmp %o1, %g1 blu cs_common mov %o7, %o5 ! save return address ! fall through/* * Fault while trying to move from or to user space. * Set and return error code. */copystrerr: mov EFAULT, %o0 jmp %o5 + 8 ! return (EFAULT) clr [_u+U_LOFAULT]/* * Fetch user (long) word. * * int * fuword(addr) * caddr_t addr; */ ENTRY2(fuword,fuiword) sethi %hi(KERNELBASE), %o3 ! compare access addr to KERNELBASE cmp %o0, %o3 ! if (KERNELBASE >= addr) error bgeu fsuerr btst 0x3, %o0 ! test alignment bne fsuerr .empty set fsuerr, %o3 ! set u.u_lofault to catch any fault st %o3, [_u+U_LOFAULT] ld [%o0], %o0 ! get the word retl clr [_u+U_LOFAULT] ! clear u.u_lofault/* * Fetch user byte. * * int * fubyte(addr) * caddr_t addr; */ ENTRY2(fubyte,fuibyte) sethi %hi(KERNELBASE), %o3 ! compare access addr to KERNELBASE cmp %o0, %o3 ! if (KERNELBASE >= addr) error bgeu fsuerr .empty set fsuerr, %o3 ! set u.u_lofault to catch any fault st %o3, [_u+U_LOFAULT] ldub [%o0], %o0 ! get the byte retl clr [_u+U_LOFAULT] ! clear u.u_lofault/* * Set user (long) word. * * int * suword(addr, value) * caddr_t addr; * int value; */ ENTRY2(suword,suiword) sethi %hi(KERNELBASE), %o3 ! compare access addr to KERNELBASE cmp %o0, %o3 ! if (KERNELBASE >= addr) error bgeu fsuerr btst 0x3, %o0 ! test alignment bne fsuerr .empty set fsuerr, %o3 ! set u.u_lofault to catch any fault st %o3, [_u+U_LOFAULT] st %o1, [%o0] ! set the word b,a suret/* * Set user byte. * * int * subyte(addr, value) * caddr_t addr; * int value; */ ENTRY2(subyte,suibyte) sethi %hi(KERNELBASE), %o3 ! compare access addr to KERNELBASE cmp %o0, %o3 ! if (KERNELBASE >= addr) error bgeu fsuerr .empty set fsuerr, %o3 ! set u.u_lofault to catch any fault st %o3, [_u+U_LOFAULT] stb %o1, [%o0] ! set the bytesuret: mov 0, %o0 ! indicate success retl clr [_u+U_LOFAULT] ! clear u.u_lofault/* * Fetch user short (half) word. * * int * fusword(addr) * caddr_t addr; */ ENTRY(fusword) sethi %hi(KERNELBASE), %o3 ! compare access addr to KERNELBASE cmp %o0, %o3 ! if (KERNELBASE >= addr) error bgeu fsuerr btst 0x1, %o0 ! test alignment bne fsuerr .empty set fsuerr, %o3 ! set u.u_lofault to catch any fault st %o3, [_u+U_LOFAULT] lduh [%o0], %o0 ! get the half word retl clr [_u+U_LOFAULT] ! clear u.u_lofault/* * Set user short word. * * int * susword(addr, value) * caddr_t addr; * int value; */ ENTRY(susword) sethi %hi(KERNELBASE), %o3 ! compare access addr to KERNELBASE cmp %o0, %o3 ! if (KERNELBASE >= addr) error bgeu fsuerr btst 0x1, %o0 ! test alignment bne fsuerr .empty set fsuerr, %o3 ! set u.u_lofault to catch any fault st %o3, [_u+U_LOFAULT] sth %o1, [%o0] ! set the half word b,a suretfsuerr: mov -1, %o0 ! return error retl clr [_u+U_LOFAULT] ! clear u.u_lofault#endif never
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -