17c478bd9Sstevel@tonic-gate/* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*9acbbeafSnn35248 * Common Development and Distribution License (the "License"). 6*9acbbeafSnn35248 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate/* 22*9acbbeafSnn35248 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate#pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate#include <sys/param.h> 297c478bd9Sstevel@tonic-gate#include <sys/errno.h> 307c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h> 317c478bd9Sstevel@tonic-gate#include <sys/vtrace.h> 327c478bd9Sstevel@tonic-gate#include <sys/machthread.h> 337c478bd9Sstevel@tonic-gate#include <sys/clock.h> 347c478bd9Sstevel@tonic-gate#include <sys/asi.h> 357c478bd9Sstevel@tonic-gate#include <sys/fsr.h> 367c478bd9Sstevel@tonic-gate#include <sys/privregs.h> 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate#if !defined(lint) 397c478bd9Sstevel@tonic-gate#include "assym.h" 407c478bd9Sstevel@tonic-gate#endif /* lint */ 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate/* 437c478bd9Sstevel@tonic-gate * Error barrier: 447c478bd9Sstevel@tonic-gate * We use membar sync to establish an error barrier for 457c478bd9Sstevel@tonic-gate * deferred errors. Membar syncs are added before any update 467c478bd9Sstevel@tonic-gate * to t_lofault to ensure that deferred errors from earlier 477c478bd9Sstevel@tonic-gate * accesses will not be reported after the membar. This error 487c478bd9Sstevel@tonic-gate * isolation is important when we try to recover from async 497c478bd9Sstevel@tonic-gate * errors which tries to distinguish kernel accesses to user 507c478bd9Sstevel@tonic-gate * data. 517c478bd9Sstevel@tonic-gate */ 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate/* 547c478bd9Sstevel@tonic-gate * Copy a null terminated string from one point to another in 557c478bd9Sstevel@tonic-gate * the kernel address space. 567c478bd9Sstevel@tonic-gate * NOTE - don't use %o5 in this routine as copy{in,out}str uses it. 577c478bd9Sstevel@tonic-gate * 587c478bd9Sstevel@tonic-gate * copystr(from, to, maxlength, lencopied) 597c478bd9Sstevel@tonic-gate * caddr_t from, to; 607c478bd9Sstevel@tonic-gate * u_int maxlength, *lencopied; 617c478bd9Sstevel@tonic-gate */ 627c478bd9Sstevel@tonic-gate 637c478bd9Sstevel@tonic-gate#if defined(lint) 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate/* ARGSUSED */ 667c478bd9Sstevel@tonic-gateint 677c478bd9Sstevel@tonic-gatecopystr(const char *from, char *to, size_t maxlength, size_t *lencopied) 687c478bd9Sstevel@tonic-gate{ return(0); } 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate#else /* lint */ 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate ENTRY(copystr) 737c478bd9Sstevel@tonic-gate orcc %o2, %g0, %o4 ! save original count 747c478bd9Sstevel@tonic-gate bg,a %ncc, 1f 757c478bd9Sstevel@tonic-gate sub %o0, %o1, %o0 ! o0 gets the difference of src and dst 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate ! 787c478bd9Sstevel@tonic-gate ! maxlength <= 0 797c478bd9Sstevel@tonic-gate ! 807c478bd9Sstevel@tonic-gate bz %ncc, .cs_out ! maxlength = 0 817c478bd9Sstevel@tonic-gate mov ENAMETOOLONG, %o0 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate b 2f ! maxlength < 0 847c478bd9Sstevel@tonic-gate mov EFAULT, %o0 ! return failure 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate ! 877c478bd9Sstevel@tonic-gate ! Do a byte by byte loop. 887c478bd9Sstevel@tonic-gate ! We do this instead of a word by word copy because most strings 897c478bd9Sstevel@tonic-gate ! are small and this takes a small number of cache lines. 907c478bd9Sstevel@tonic-gate ! 917c478bd9Sstevel@tonic-gate0: 927c478bd9Sstevel@tonic-gate stb %g1, [%o1] ! store byte 937c478bd9Sstevel@tonic-gate tst %g1 947c478bd9Sstevel@tonic-gate bnz,pt %icc, 1f 957c478bd9Sstevel@tonic-gate add %o1, 1, %o1 ! incr dst addr 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate ba,pt %ncc, .cs_out ! last byte in string 987c478bd9Sstevel@tonic-gate mov 0, %o0 ! ret code = 0 997c478bd9Sstevel@tonic-gate1: 1007c478bd9Sstevel@tonic-gate subcc %o2, 1, %o2 ! test count 1017c478bd9Sstevel@tonic-gate bgeu,a %ncc, 0b 1027c478bd9Sstevel@tonic-gate ldub [%o0 + %o1], %g1 ! delay slot, get source byte 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate mov 0, %o2 ! max number of bytes moved 1057c478bd9Sstevel@tonic-gate mov ENAMETOOLONG, %o0 ! ret code = ENAMETOOLONG 1067c478bd9Sstevel@tonic-gate.cs_out: 1077c478bd9Sstevel@tonic-gate tst %o3 1087c478bd9Sstevel@tonic-gate bz %ncc, 2f 1097c478bd9Sstevel@tonic-gate sub %o4, %o2, %o4 ! compute length and store it 1107c478bd9Sstevel@tonic-gate stn %o4, [%o3] 1117c478bd9Sstevel@tonic-gate2: 1127c478bd9Sstevel@tonic-gate retl 1137c478bd9Sstevel@tonic-gate nop 1147c478bd9Sstevel@tonic-gate SET_SIZE(copystr) 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate#endif /* lint */ 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate/* 1207c478bd9Sstevel@tonic-gate * Copy a null terminated string from the user address space into 1217c478bd9Sstevel@tonic-gate * the kernel address space. 1227c478bd9Sstevel@tonic-gate */ 1237c478bd9Sstevel@tonic-gate#if defined(lint) 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate/* ARGSUSED */ 1267c478bd9Sstevel@tonic-gateint 1277c478bd9Sstevel@tonic-gatecopyinstr(const char *uaddr, char *kaddr, size_t maxlength, 1287c478bd9Sstevel@tonic-gate size_t *lencopied) 1297c478bd9Sstevel@tonic-gate{ return (0); } 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate#else /* lint */ 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate ENTRY(copyinstr) 1347c478bd9Sstevel@tonic-gate sethi %hi(.copyinstr_err), %o4 1357c478bd9Sstevel@tonic-gate ldn [THREAD_REG + T_LOFAULT], %o5 ! catch faults 1367c478bd9Sstevel@tonic-gate or %o4, %lo(.copyinstr_err), %o4 1377c478bd9Sstevel@tonic-gate membar #Sync ! sync error barrier 1387c478bd9Sstevel@tonic-gate stn %o4, [THREAD_REG + T_LOFAULT] 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate brz,a,pn %o2, .copyinstr_out 1417c478bd9Sstevel@tonic-gate mov ENAMETOOLONG, %o0 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate mov %o2, %g3 ! g3 is the current count 1447c478bd9Sstevel@tonic-gate mov %o1, %g4 ! g4 is the dest addr 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate b 1f 1477c478bd9Sstevel@tonic-gate sub %o0, %o1, %g2 ! g2 gets the difference of src and dst 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate ! 1507c478bd9Sstevel@tonic-gate ! Do a byte by byte loop. 1517c478bd9Sstevel@tonic-gate ! We do this instead of a word by word copy because most strings 1527c478bd9Sstevel@tonic-gate ! are small and this takes a small number of cache lines. 1537c478bd9Sstevel@tonic-gate ! 1547c478bd9Sstevel@tonic-gate0: 1557c478bd9Sstevel@tonic-gate stb %g1, [%g4] ! store byte 1567c478bd9Sstevel@tonic-gate tst %g1 1577c478bd9Sstevel@tonic-gate bnz,pt %icc, 1f 1587c478bd9Sstevel@tonic-gate add %g4, 1, %g4 ! incr dst addr 1597c478bd9Sstevel@tonic-gate 1607c478bd9Sstevel@tonic-gate ba,pt %ncc, .copyinstr_out ! last byte in string 1617c478bd9Sstevel@tonic-gate mov 0, %o0 ! ret code = 0 1627c478bd9Sstevel@tonic-gate1: 1637c478bd9Sstevel@tonic-gate subcc %g3, 1, %g3 ! test count 1647c478bd9Sstevel@tonic-gate bgeu,a %ncc, 0b 1657c478bd9Sstevel@tonic-gate lduba [%g2+%g4]ASI_USER, %g1 ! delay slot, get source byte 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate mov 0, %g3 ! max number of bytes moved 1687c478bd9Sstevel@tonic-gate ba,pt %ncc, .copyinstr_out 1697c478bd9Sstevel@tonic-gate mov ENAMETOOLONG, %o0 ! ret code = ENAMETOOLONG 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate/* 1727c478bd9Sstevel@tonic-gate * Fault while trying to move from or to user space. 1737c478bd9Sstevel@tonic-gate * Set and return error code. 1747c478bd9Sstevel@tonic-gate */ 1757c478bd9Sstevel@tonic-gate.copyinstr_err: 1767c478bd9Sstevel@tonic-gate membar #Sync ! sync error barrier 1777c478bd9Sstevel@tonic-gate stn %o5, [THREAD_REG + T_LOFAULT] 1787c478bd9Sstevel@tonic-gate ldn [THREAD_REG + T_COPYOPS], %o4 1797c478bd9Sstevel@tonic-gate brz %o4, 1f 1807c478bd9Sstevel@tonic-gate nop 1817c478bd9Sstevel@tonic-gate ldn [%o4 + CP_COPYINSTR], %g1 1827c478bd9Sstevel@tonic-gate jmp %g1 1837c478bd9Sstevel@tonic-gate nop 1847c478bd9Sstevel@tonic-gate1: 1857c478bd9Sstevel@tonic-gate retl 1867c478bd9Sstevel@tonic-gate mov EFAULT, %o0 1877c478bd9Sstevel@tonic-gate.copyinstr_out: 1887c478bd9Sstevel@tonic-gate tst %o3 ! want length? 1897c478bd9Sstevel@tonic-gate bz %ncc, 2f 1907c478bd9Sstevel@tonic-gate sub %o2, %g3, %o2 ! compute length and store it 1917c478bd9Sstevel@tonic-gate stn %o2, [%o3] 1927c478bd9Sstevel@tonic-gate2: 1937c478bd9Sstevel@tonic-gate membar #Sync ! sync error barrier 1947c478bd9Sstevel@tonic-gate retl 1957c478bd9Sstevel@tonic-gate stn %o5, [THREAD_REG + T_LOFAULT] ! stop catching faults 1967c478bd9Sstevel@tonic-gate SET_SIZE(copyinstr) 1977c478bd9Sstevel@tonic-gate#endif 1987c478bd9Sstevel@tonic-gate 1997c478bd9Sstevel@tonic-gate#if defined(lint) 2007c478bd9Sstevel@tonic-gate 2017c478bd9Sstevel@tonic-gate/* ARGSUSED */ 2027c478bd9Sstevel@tonic-gateint 2037c478bd9Sstevel@tonic-gatecopyinstr_noerr(const char *uaddr, char *kaddr, size_t maxlength, 2047c478bd9Sstevel@tonic-gate size_t *lencopied) 2057c478bd9Sstevel@tonic-gate{ return (0); } 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate#else /* lint */ 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate ENTRY(copyinstr_noerr) 2107c478bd9Sstevel@tonic-gate mov %o2, %o4 ! save original count 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate ! maxlength is unsigned so the only error is if it's 0 2137c478bd9Sstevel@tonic-gate brz,a,pn %o2, .copyinstr_noerr_out 2147c478bd9Sstevel@tonic-gate mov ENAMETOOLONG, %o0 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate b 1f 2177c478bd9Sstevel@tonic-gate sub %o0, %o1, %o0 ! o0 gets the difference of src and dst 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate ! 2207c478bd9Sstevel@tonic-gate ! Do a byte by byte loop. 2217c478bd9Sstevel@tonic-gate ! We do this instead of a word by word copy because most strings 2227c478bd9Sstevel@tonic-gate ! are small and this takes a small number of cache lines. 2237c478bd9Sstevel@tonic-gate ! 2247c478bd9Sstevel@tonic-gate0: 2257c478bd9Sstevel@tonic-gate stb %g1, [%o1] ! store byte 2267c478bd9Sstevel@tonic-gate tst %g1 ! null byte? 2277c478bd9Sstevel@tonic-gate bnz 1f 2287c478bd9Sstevel@tonic-gate add %o1, 1, %o1 ! incr dst addr 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate ba,pt %ncc, .copyinstr_noerr_out ! last byte in string 2317c478bd9Sstevel@tonic-gate mov 0, %o0 ! ret code = 0 2327c478bd9Sstevel@tonic-gate1: 2337c478bd9Sstevel@tonic-gate subcc %o2, 1, %o2 ! test count 2347c478bd9Sstevel@tonic-gate bgeu,a %ncc, 0b 2357c478bd9Sstevel@tonic-gate lduba [%o0 + %o1]ASI_USER, %g1 ! delay slot, get source byte 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate mov 0, %o2 ! max number of bytes moved 2387c478bd9Sstevel@tonic-gate b .copyinstr_noerr_out 2397c478bd9Sstevel@tonic-gate mov ENAMETOOLONG, %o0 ! ret code = ENAMETOOLONG 2407c478bd9Sstevel@tonic-gate.copyinstr_noerr_out: 2417c478bd9Sstevel@tonic-gate tst %o3 ! want length? 2427c478bd9Sstevel@tonic-gate bz %ncc, 2f 2437c478bd9Sstevel@tonic-gate sub %o4, %o2, %o4 2447c478bd9Sstevel@tonic-gate stn %o4, [%o3] 2457c478bd9Sstevel@tonic-gate2: 2467c478bd9Sstevel@tonic-gate retl 2477c478bd9Sstevel@tonic-gate nop 2487c478bd9Sstevel@tonic-gate SET_SIZE(copyinstr_noerr) 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate#endif /* lint */ 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate/* 2537c478bd9Sstevel@tonic-gate * Copy a null terminated string from the kernel 2547c478bd9Sstevel@tonic-gate * address space to the user address space. 2557c478bd9Sstevel@tonic-gate */ 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate#if defined(lint) 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate/* ARGSUSED */ 2607c478bd9Sstevel@tonic-gateint 2617c478bd9Sstevel@tonic-gatecopyoutstr(const char *kaddr, char *uaddr, size_t maxlength, 2627c478bd9Sstevel@tonic-gate size_t *lencopied) 2637c478bd9Sstevel@tonic-gate{ return (0); } 2647c478bd9Sstevel@tonic-gate 2657c478bd9Sstevel@tonic-gate#else /* lint */ 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate ENTRY(copyoutstr) 2687c478bd9Sstevel@tonic-gate sethi %hi(.copyoutstr_err), %o5 2697c478bd9Sstevel@tonic-gate ldn [THREAD_REG + T_LOFAULT], %o4 ! catch faults 2707c478bd9Sstevel@tonic-gate or %o5, %lo(.copyoutstr_err), %o5 2717c478bd9Sstevel@tonic-gate membar #Sync ! sync error barrier 2727c478bd9Sstevel@tonic-gate stn %o5, [THREAD_REG + T_LOFAULT] 2737c478bd9Sstevel@tonic-gate mov %o4, %o5 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate brz,a,pn %o2, .copyoutstr_out 2767c478bd9Sstevel@tonic-gate mov ENAMETOOLONG, %o0 2777c478bd9Sstevel@tonic-gate 2787c478bd9Sstevel@tonic-gate mov %o2, %g3 ! g3 is the current count 2797c478bd9Sstevel@tonic-gate mov %o1, %g4 ! g4 is the dest addr 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate b 1f 2827c478bd9Sstevel@tonic-gate sub %o0, %o1, %g2 ! g2 gets the difference of src and dst 2837c478bd9Sstevel@tonic-gate 2847c478bd9Sstevel@tonic-gate ! 2857c478bd9Sstevel@tonic-gate ! Do a byte by byte loop. 2867c478bd9Sstevel@tonic-gate ! We do this instead of a word by word copy because most strings 2877c478bd9Sstevel@tonic-gate ! are small and this takes a small number of cache lines. 2887c478bd9Sstevel@tonic-gate ! 2897c478bd9Sstevel@tonic-gate0: 2907c478bd9Sstevel@tonic-gate stba %g1, [%g4]ASI_USER ! store byte 2917c478bd9Sstevel@tonic-gate tst %g1 2927c478bd9Sstevel@tonic-gate bnz,pt %icc, 1f 2937c478bd9Sstevel@tonic-gate add %g4, 1, %g4 ! incr dst addr 2947c478bd9Sstevel@tonic-gate 2957c478bd9Sstevel@tonic-gate ba,pt %ncc, .copyoutstr_out ! last byte in string 2967c478bd9Sstevel@tonic-gate mov 0, %o0 ! ret code = 0 2977c478bd9Sstevel@tonic-gate1: 2987c478bd9Sstevel@tonic-gate subcc %g3, 1, %g3 ! test count 2997c478bd9Sstevel@tonic-gate bgeu,a %ncc, 0b 3007c478bd9Sstevel@tonic-gate ldub [%g2 + %g4], %g1 ! delay slot, get source byte 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate mov 0, %g3 ! max number of bytes moved 3037c478bd9Sstevel@tonic-gate ba,pt %ncc, .copyoutstr_out 3047c478bd9Sstevel@tonic-gate mov ENAMETOOLONG, %o0 ! ret code = ENAMETOOLONG 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate/* 3077c478bd9Sstevel@tonic-gate * Fault while trying to move from or to user space. 3087c478bd9Sstevel@tonic-gate * Set and return error code. 3097c478bd9Sstevel@tonic-gate */ 3107c478bd9Sstevel@tonic-gate.copyoutstr_err: 3117c478bd9Sstevel@tonic-gate membar #Sync ! sync error barrier 3127c478bd9Sstevel@tonic-gate stn %o5, [THREAD_REG + T_LOFAULT] 3137c478bd9Sstevel@tonic-gate ldn [THREAD_REG + T_COPYOPS], %o4 3147c478bd9Sstevel@tonic-gate brz %o4, 1f 3157c478bd9Sstevel@tonic-gate nop 3167c478bd9Sstevel@tonic-gate ldn [%o4 + CP_COPYOUTSTR], %g1 3177c478bd9Sstevel@tonic-gate jmp %g1 3187c478bd9Sstevel@tonic-gate nop 3197c478bd9Sstevel@tonic-gate1: 3207c478bd9Sstevel@tonic-gate retl 3217c478bd9Sstevel@tonic-gate mov EFAULT, %o0 3227c478bd9Sstevel@tonic-gate.copyoutstr_out: 3237c478bd9Sstevel@tonic-gate tst %o3 ! want length? 3247c478bd9Sstevel@tonic-gate bz %ncc, 2f 3257c478bd9Sstevel@tonic-gate sub %o2, %g3, %o2 ! compute length and store it 3267c478bd9Sstevel@tonic-gate stn %o2, [%o3] 3277c478bd9Sstevel@tonic-gate2: 3287c478bd9Sstevel@tonic-gate membar #Sync ! sync error barrier 3297c478bd9Sstevel@tonic-gate retl 3307c478bd9Sstevel@tonic-gate stn %o5, [THREAD_REG + T_LOFAULT] ! stop catching faults 3317c478bd9Sstevel@tonic-gate SET_SIZE(copyoutstr) 3327c478bd9Sstevel@tonic-gate 3337c478bd9Sstevel@tonic-gate#endif /* lint */ 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate#if defined(lint) 3367c478bd9Sstevel@tonic-gate 3377c478bd9Sstevel@tonic-gate/* ARGSUSED */ 3387c478bd9Sstevel@tonic-gateint 3397c478bd9Sstevel@tonic-gatecopyoutstr_noerr(const char *kaddr, char *uaddr, size_t maxlength, 3407c478bd9Sstevel@tonic-gate size_t *lencopied) 3417c478bd9Sstevel@tonic-gate{ return (0); } 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate#else /* lint */ 3447c478bd9Sstevel@tonic-gate 3457c478bd9Sstevel@tonic-gate ENTRY(copyoutstr_noerr) 3467c478bd9Sstevel@tonic-gate mov %o2, %o4 ! save original count 3477c478bd9Sstevel@tonic-gate 3487c478bd9Sstevel@tonic-gate brz,a,pn %o2, .copyoutstr_noerr_out 3497c478bd9Sstevel@tonic-gate mov ENAMETOOLONG, %o0 3507c478bd9Sstevel@tonic-gate 3517c478bd9Sstevel@tonic-gate b 1f 3527c478bd9Sstevel@tonic-gate sub %o0, %o1, %o0 ! o0 gets the difference of src and dst 3537c478bd9Sstevel@tonic-gate 3547c478bd9Sstevel@tonic-gate ! 3557c478bd9Sstevel@tonic-gate ! Do a byte by byte loop. 3567c478bd9Sstevel@tonic-gate ! We do this instead of a word by word copy because most strings 3577c478bd9Sstevel@tonic-gate ! are small and this takes a small number of cache lines. 3587c478bd9Sstevel@tonic-gate ! 3597c478bd9Sstevel@tonic-gate0: 3607c478bd9Sstevel@tonic-gate stba %g1, [%o1]ASI_USER ! store byte 3617c478bd9Sstevel@tonic-gate tst %g1 ! null byte? 3627c478bd9Sstevel@tonic-gate bnz 1f 3637c478bd9Sstevel@tonic-gate add %o1, 1, %o1 ! incr dst addr 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate b .copyoutstr_noerr_out ! last byte in string 3667c478bd9Sstevel@tonic-gate mov 0, %o0 ! ret code = 0 3677c478bd9Sstevel@tonic-gate1: 3687c478bd9Sstevel@tonic-gate subcc %o2, 1, %o2 ! test count 3697c478bd9Sstevel@tonic-gate bgeu,a %ncc, 0b 3707c478bd9Sstevel@tonic-gate ldub [%o0+%o1], %g1 ! delay slot, get source byte 3717c478bd9Sstevel@tonic-gate 3727c478bd9Sstevel@tonic-gate mov 0, %o2 ! max number of bytes moved 3737c478bd9Sstevel@tonic-gate b .copyoutstr_noerr_out 3747c478bd9Sstevel@tonic-gate mov ENAMETOOLONG, %o0 ! ret code = ENAMETOOLONG 3757c478bd9Sstevel@tonic-gate.copyoutstr_noerr_out: 3767c478bd9Sstevel@tonic-gate tst %o3 ! want length? 3777c478bd9Sstevel@tonic-gate bz %ncc, 2f 3787c478bd9Sstevel@tonic-gate sub %o4, %o2, %o4 3797c478bd9Sstevel@tonic-gate stn %o4, [%o3] 3807c478bd9Sstevel@tonic-gate2: 3817c478bd9Sstevel@tonic-gate retl 3827c478bd9Sstevel@tonic-gate nop 3837c478bd9Sstevel@tonic-gate SET_SIZE(copyoutstr_noerr) 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate#endif /* lint */ 3867c478bd9Sstevel@tonic-gate 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate/* 389*9acbbeafSnn35248 * Copy a block of storage. If the source and target regions overlap, 390*9acbbeafSnn35248 * one or both of the regions will be silently corrupted. 3917c478bd9Sstevel@tonic-gate * No fault handler installed (to be called under on_fault()) 3927c478bd9Sstevel@tonic-gate */ 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate#if defined(lint) 3957c478bd9Sstevel@tonic-gate 3967c478bd9Sstevel@tonic-gate/* ARGSUSED */ 3977c478bd9Sstevel@tonic-gatevoid 3987c478bd9Sstevel@tonic-gateucopy(const void *ufrom, void *uto, size_t ulength) 3997c478bd9Sstevel@tonic-gate{} 4007c478bd9Sstevel@tonic-gate 4017c478bd9Sstevel@tonic-gate#else /* lint */ 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate ENTRY(ucopy) 4047c478bd9Sstevel@tonic-gate save %sp, -SA(MINFRAME), %sp ! get another window 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate subcc %g0, %i2, %i3 4077c478bd9Sstevel@tonic-gate add %i0, %i2, %i0 4087c478bd9Sstevel@tonic-gate bz,pn %ncc, 5f 4097c478bd9Sstevel@tonic-gate add %i1, %i2, %i1 4107c478bd9Sstevel@tonic-gate lduba [%i0 + %i3]ASI_USER, %i4 4117c478bd9Sstevel@tonic-gate4: stba %i4, [%i1 + %i3]ASI_USER 4127c478bd9Sstevel@tonic-gate inccc %i3 4137c478bd9Sstevel@tonic-gate bcc,a,pt %ncc, 4b 4147c478bd9Sstevel@tonic-gate lduba [%i0 + %i3]ASI_USER, %i4 4157c478bd9Sstevel@tonic-gate5: 4167c478bd9Sstevel@tonic-gate ret 4177c478bd9Sstevel@tonic-gate restore %g0, 0, %o0 ! return (0) 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate SET_SIZE(ucopy) 4207c478bd9Sstevel@tonic-gate#endif /* lint */ 421*9acbbeafSnn35248 422*9acbbeafSnn35248/* 423*9acbbeafSnn35248 * Copy a user-land string. If the source and target regions overlap, 424*9acbbeafSnn35248 * one or both of the regions will be silently corrupted. 425*9acbbeafSnn35248 * No fault handler installed (to be called under on_fault()) 426*9acbbeafSnn35248 */ 427*9acbbeafSnn35248 428*9acbbeafSnn35248#if defined(lint) 429*9acbbeafSnn35248 430*9acbbeafSnn35248/* ARGSUSED */ 431*9acbbeafSnn35248void 432*9acbbeafSnn35248ucopystr(const char *ufrom, char *uto, size_t umaxlength, size_t *ulencopied) 433*9acbbeafSnn35248{} 434*9acbbeafSnn35248 435*9acbbeafSnn35248#else /* lint */ 436*9acbbeafSnn35248 437*9acbbeafSnn35248 ENTRY(ucopystr) 438*9acbbeafSnn35248 save %sp, -SA(MINFRAME), %sp ! get another window 439*9acbbeafSnn35248 440*9acbbeafSnn35248 brz %i2, 5f 441*9acbbeafSnn35248 clr %i5 442*9acbbeafSnn35248 443*9acbbeafSnn35248 lduba [%i0 + %i5]ASI_USER, %i4 444*9acbbeafSnn352484: stba %i4, [%i1 + %i5]ASI_USER 445*9acbbeafSnn35248 brz,pn %i4, 5f 446*9acbbeafSnn35248 inc %i5 447*9acbbeafSnn35248 deccc %i2 448*9acbbeafSnn35248 bnz,a,pt %ncc, 4b 449*9acbbeafSnn35248 lduba [%i0 + %i5]ASI_USER, %i4 450*9acbbeafSnn352485: 451*9acbbeafSnn35248 brnz,a,pt %i3, 6f 452*9acbbeafSnn35248 stn %i5, [%i3] 453*9acbbeafSnn352486: 454*9acbbeafSnn35248 ret 455*9acbbeafSnn35248 restore %g0, 0, %o0 ! return (0) 456*9acbbeafSnn35248 457*9acbbeafSnn35248 SET_SIZE(ucopystr) 458*9acbbeafSnn35248#endif /* lint */ 459