1*7c478bd9Sstevel@tonic-gate/* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate/* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate#pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate#include <sys/param.h> 30*7c478bd9Sstevel@tonic-gate#include <sys/errno.h> 31*7c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h> 32*7c478bd9Sstevel@tonic-gate#include <sys/vtrace.h> 33*7c478bd9Sstevel@tonic-gate#include <sys/machthread.h> 34*7c478bd9Sstevel@tonic-gate#include <sys/clock.h> 35*7c478bd9Sstevel@tonic-gate#include <sys/asi.h> 36*7c478bd9Sstevel@tonic-gate#include <sys/fsr.h> 37*7c478bd9Sstevel@tonic-gate#include <sys/privregs.h> 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate#if !defined(lint) 40*7c478bd9Sstevel@tonic-gate#include "assym.h" 41*7c478bd9Sstevel@tonic-gate#endif /* lint */ 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate/* 44*7c478bd9Sstevel@tonic-gate * Error barrier: 45*7c478bd9Sstevel@tonic-gate * We use membar sync to establish an error barrier for 46*7c478bd9Sstevel@tonic-gate * deferred errors. Membar syncs are added before any update 47*7c478bd9Sstevel@tonic-gate * to t_lofault to ensure that deferred errors from earlier 48*7c478bd9Sstevel@tonic-gate * accesses will not be reported after the membar. This error 49*7c478bd9Sstevel@tonic-gate * isolation is important when we try to recover from async 50*7c478bd9Sstevel@tonic-gate * errors which tries to distinguish kernel accesses to user 51*7c478bd9Sstevel@tonic-gate * data. 52*7c478bd9Sstevel@tonic-gate */ 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate/* 55*7c478bd9Sstevel@tonic-gate * Copy a null terminated string from one point to another in 56*7c478bd9Sstevel@tonic-gate * the kernel address space. 57*7c478bd9Sstevel@tonic-gate * NOTE - don't use %o5 in this routine as copy{in,out}str uses it. 58*7c478bd9Sstevel@tonic-gate * 59*7c478bd9Sstevel@tonic-gate * copystr(from, to, maxlength, lencopied) 60*7c478bd9Sstevel@tonic-gate * caddr_t from, to; 61*7c478bd9Sstevel@tonic-gate * u_int maxlength, *lencopied; 62*7c478bd9Sstevel@tonic-gate */ 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate#if defined(lint) 65*7c478bd9Sstevel@tonic-gate 66*7c478bd9Sstevel@tonic-gate/* ARGSUSED */ 67*7c478bd9Sstevel@tonic-gateint 68*7c478bd9Sstevel@tonic-gatecopystr(const char *from, char *to, size_t maxlength, size_t *lencopied) 69*7c478bd9Sstevel@tonic-gate{ return(0); } 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate#else /* lint */ 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate ENTRY(copystr) 74*7c478bd9Sstevel@tonic-gate orcc %o2, %g0, %o4 ! save original count 75*7c478bd9Sstevel@tonic-gate bg,a %ncc, 1f 76*7c478bd9Sstevel@tonic-gate sub %o0, %o1, %o0 ! o0 gets the difference of src and dst 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate ! 79*7c478bd9Sstevel@tonic-gate ! maxlength <= 0 80*7c478bd9Sstevel@tonic-gate ! 81*7c478bd9Sstevel@tonic-gate bz %ncc, .cs_out ! maxlength = 0 82*7c478bd9Sstevel@tonic-gate mov ENAMETOOLONG, %o0 83*7c478bd9Sstevel@tonic-gate 84*7c478bd9Sstevel@tonic-gate b 2f ! maxlength < 0 85*7c478bd9Sstevel@tonic-gate mov EFAULT, %o0 ! return failure 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate ! 88*7c478bd9Sstevel@tonic-gate ! Do a byte by byte loop. 89*7c478bd9Sstevel@tonic-gate ! We do this instead of a word by word copy because most strings 90*7c478bd9Sstevel@tonic-gate ! are small and this takes a small number of cache lines. 91*7c478bd9Sstevel@tonic-gate ! 92*7c478bd9Sstevel@tonic-gate0: 93*7c478bd9Sstevel@tonic-gate stb %g1, [%o1] ! store byte 94*7c478bd9Sstevel@tonic-gate tst %g1 95*7c478bd9Sstevel@tonic-gate bnz,pt %icc, 1f 96*7c478bd9Sstevel@tonic-gate add %o1, 1, %o1 ! incr dst addr 97*7c478bd9Sstevel@tonic-gate 98*7c478bd9Sstevel@tonic-gate ba,pt %ncc, .cs_out ! last byte in string 99*7c478bd9Sstevel@tonic-gate mov 0, %o0 ! ret code = 0 100*7c478bd9Sstevel@tonic-gate1: 101*7c478bd9Sstevel@tonic-gate subcc %o2, 1, %o2 ! test count 102*7c478bd9Sstevel@tonic-gate bgeu,a %ncc, 0b 103*7c478bd9Sstevel@tonic-gate ldub [%o0 + %o1], %g1 ! delay slot, get source byte 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate mov 0, %o2 ! max number of bytes moved 106*7c478bd9Sstevel@tonic-gate mov ENAMETOOLONG, %o0 ! ret code = ENAMETOOLONG 107*7c478bd9Sstevel@tonic-gate.cs_out: 108*7c478bd9Sstevel@tonic-gate tst %o3 109*7c478bd9Sstevel@tonic-gate bz %ncc, 2f 110*7c478bd9Sstevel@tonic-gate sub %o4, %o2, %o4 ! compute length and store it 111*7c478bd9Sstevel@tonic-gate stn %o4, [%o3] 112*7c478bd9Sstevel@tonic-gate2: 113*7c478bd9Sstevel@tonic-gate retl 114*7c478bd9Sstevel@tonic-gate nop 115*7c478bd9Sstevel@tonic-gate SET_SIZE(copystr) 116*7c478bd9Sstevel@tonic-gate 117*7c478bd9Sstevel@tonic-gate#endif /* lint */ 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate/* 121*7c478bd9Sstevel@tonic-gate * Copy a null terminated string from the user address space into 122*7c478bd9Sstevel@tonic-gate * the kernel address space. 123*7c478bd9Sstevel@tonic-gate */ 124*7c478bd9Sstevel@tonic-gate#if defined(lint) 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate/* ARGSUSED */ 127*7c478bd9Sstevel@tonic-gateint 128*7c478bd9Sstevel@tonic-gatecopyinstr(const char *uaddr, char *kaddr, size_t maxlength, 129*7c478bd9Sstevel@tonic-gate size_t *lencopied) 130*7c478bd9Sstevel@tonic-gate{ return (0); } 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate#else /* lint */ 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate ENTRY(copyinstr) 135*7c478bd9Sstevel@tonic-gate sethi %hi(.copyinstr_err), %o4 136*7c478bd9Sstevel@tonic-gate ldn [THREAD_REG + T_LOFAULT], %o5 ! catch faults 137*7c478bd9Sstevel@tonic-gate or %o4, %lo(.copyinstr_err), %o4 138*7c478bd9Sstevel@tonic-gate membar #Sync ! sync error barrier 139*7c478bd9Sstevel@tonic-gate stn %o4, [THREAD_REG + T_LOFAULT] 140*7c478bd9Sstevel@tonic-gate 141*7c478bd9Sstevel@tonic-gate brz,a,pn %o2, .copyinstr_out 142*7c478bd9Sstevel@tonic-gate mov ENAMETOOLONG, %o0 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate mov %o2, %g3 ! g3 is the current count 145*7c478bd9Sstevel@tonic-gate mov %o1, %g4 ! g4 is the dest addr 146*7c478bd9Sstevel@tonic-gate 147*7c478bd9Sstevel@tonic-gate b 1f 148*7c478bd9Sstevel@tonic-gate sub %o0, %o1, %g2 ! g2 gets the difference of src and dst 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate ! 151*7c478bd9Sstevel@tonic-gate ! Do a byte by byte loop. 152*7c478bd9Sstevel@tonic-gate ! We do this instead of a word by word copy because most strings 153*7c478bd9Sstevel@tonic-gate ! are small and this takes a small number of cache lines. 154*7c478bd9Sstevel@tonic-gate ! 155*7c478bd9Sstevel@tonic-gate0: 156*7c478bd9Sstevel@tonic-gate stb %g1, [%g4] ! store byte 157*7c478bd9Sstevel@tonic-gate tst %g1 158*7c478bd9Sstevel@tonic-gate bnz,pt %icc, 1f 159*7c478bd9Sstevel@tonic-gate add %g4, 1, %g4 ! incr dst addr 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate ba,pt %ncc, .copyinstr_out ! last byte in string 162*7c478bd9Sstevel@tonic-gate mov 0, %o0 ! ret code = 0 163*7c478bd9Sstevel@tonic-gate1: 164*7c478bd9Sstevel@tonic-gate subcc %g3, 1, %g3 ! test count 165*7c478bd9Sstevel@tonic-gate bgeu,a %ncc, 0b 166*7c478bd9Sstevel@tonic-gate lduba [%g2+%g4]ASI_USER, %g1 ! delay slot, get source byte 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate mov 0, %g3 ! max number of bytes moved 169*7c478bd9Sstevel@tonic-gate ba,pt %ncc, .copyinstr_out 170*7c478bd9Sstevel@tonic-gate mov ENAMETOOLONG, %o0 ! ret code = ENAMETOOLONG 171*7c478bd9Sstevel@tonic-gate 172*7c478bd9Sstevel@tonic-gate/* 173*7c478bd9Sstevel@tonic-gate * Fault while trying to move from or to user space. 174*7c478bd9Sstevel@tonic-gate * Set and return error code. 175*7c478bd9Sstevel@tonic-gate */ 176*7c478bd9Sstevel@tonic-gate.copyinstr_err: 177*7c478bd9Sstevel@tonic-gate membar #Sync ! sync error barrier 178*7c478bd9Sstevel@tonic-gate stn %o5, [THREAD_REG + T_LOFAULT] 179*7c478bd9Sstevel@tonic-gate ldn [THREAD_REG + T_COPYOPS], %o4 180*7c478bd9Sstevel@tonic-gate brz %o4, 1f 181*7c478bd9Sstevel@tonic-gate nop 182*7c478bd9Sstevel@tonic-gate ldn [%o4 + CP_COPYINSTR], %g1 183*7c478bd9Sstevel@tonic-gate jmp %g1 184*7c478bd9Sstevel@tonic-gate nop 185*7c478bd9Sstevel@tonic-gate1: 186*7c478bd9Sstevel@tonic-gate retl 187*7c478bd9Sstevel@tonic-gate mov EFAULT, %o0 188*7c478bd9Sstevel@tonic-gate.copyinstr_out: 189*7c478bd9Sstevel@tonic-gate tst %o3 ! want length? 190*7c478bd9Sstevel@tonic-gate bz %ncc, 2f 191*7c478bd9Sstevel@tonic-gate sub %o2, %g3, %o2 ! compute length and store it 192*7c478bd9Sstevel@tonic-gate stn %o2, [%o3] 193*7c478bd9Sstevel@tonic-gate2: 194*7c478bd9Sstevel@tonic-gate membar #Sync ! sync error barrier 195*7c478bd9Sstevel@tonic-gate retl 196*7c478bd9Sstevel@tonic-gate stn %o5, [THREAD_REG + T_LOFAULT] ! stop catching faults 197*7c478bd9Sstevel@tonic-gate SET_SIZE(copyinstr) 198*7c478bd9Sstevel@tonic-gate#endif 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate#if defined(lint) 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate/* ARGSUSED */ 203*7c478bd9Sstevel@tonic-gateint 204*7c478bd9Sstevel@tonic-gatecopyinstr_noerr(const char *uaddr, char *kaddr, size_t maxlength, 205*7c478bd9Sstevel@tonic-gate size_t *lencopied) 206*7c478bd9Sstevel@tonic-gate{ return (0); } 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate#else /* lint */ 209*7c478bd9Sstevel@tonic-gate 210*7c478bd9Sstevel@tonic-gate ENTRY(copyinstr_noerr) 211*7c478bd9Sstevel@tonic-gate mov %o2, %o4 ! save original count 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate ! maxlength is unsigned so the only error is if it's 0 214*7c478bd9Sstevel@tonic-gate brz,a,pn %o2, .copyinstr_noerr_out 215*7c478bd9Sstevel@tonic-gate mov ENAMETOOLONG, %o0 216*7c478bd9Sstevel@tonic-gate 217*7c478bd9Sstevel@tonic-gate b 1f 218*7c478bd9Sstevel@tonic-gate sub %o0, %o1, %o0 ! o0 gets the difference of src and dst 219*7c478bd9Sstevel@tonic-gate 220*7c478bd9Sstevel@tonic-gate ! 221*7c478bd9Sstevel@tonic-gate ! Do a byte by byte loop. 222*7c478bd9Sstevel@tonic-gate ! We do this instead of a word by word copy because most strings 223*7c478bd9Sstevel@tonic-gate ! are small and this takes a small number of cache lines. 224*7c478bd9Sstevel@tonic-gate ! 225*7c478bd9Sstevel@tonic-gate0: 226*7c478bd9Sstevel@tonic-gate stb %g1, [%o1] ! store byte 227*7c478bd9Sstevel@tonic-gate tst %g1 ! null byte? 228*7c478bd9Sstevel@tonic-gate bnz 1f 229*7c478bd9Sstevel@tonic-gate add %o1, 1, %o1 ! incr dst addr 230*7c478bd9Sstevel@tonic-gate 231*7c478bd9Sstevel@tonic-gate ba,pt %ncc, .copyinstr_noerr_out ! last byte in string 232*7c478bd9Sstevel@tonic-gate mov 0, %o0 ! ret code = 0 233*7c478bd9Sstevel@tonic-gate1: 234*7c478bd9Sstevel@tonic-gate subcc %o2, 1, %o2 ! test count 235*7c478bd9Sstevel@tonic-gate bgeu,a %ncc, 0b 236*7c478bd9Sstevel@tonic-gate lduba [%o0 + %o1]ASI_USER, %g1 ! delay slot, get source byte 237*7c478bd9Sstevel@tonic-gate 238*7c478bd9Sstevel@tonic-gate mov 0, %o2 ! max number of bytes moved 239*7c478bd9Sstevel@tonic-gate b .copyinstr_noerr_out 240*7c478bd9Sstevel@tonic-gate mov ENAMETOOLONG, %o0 ! ret code = ENAMETOOLONG 241*7c478bd9Sstevel@tonic-gate.copyinstr_noerr_out: 242*7c478bd9Sstevel@tonic-gate tst %o3 ! want length? 243*7c478bd9Sstevel@tonic-gate bz %ncc, 2f 244*7c478bd9Sstevel@tonic-gate sub %o4, %o2, %o4 245*7c478bd9Sstevel@tonic-gate stn %o4, [%o3] 246*7c478bd9Sstevel@tonic-gate2: 247*7c478bd9Sstevel@tonic-gate retl 248*7c478bd9Sstevel@tonic-gate nop 249*7c478bd9Sstevel@tonic-gate SET_SIZE(copyinstr_noerr) 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate#endif /* lint */ 252*7c478bd9Sstevel@tonic-gate 253*7c478bd9Sstevel@tonic-gate/* 254*7c478bd9Sstevel@tonic-gate * Copy a null terminated string from the kernel 255*7c478bd9Sstevel@tonic-gate * address space to the user address space. 256*7c478bd9Sstevel@tonic-gate */ 257*7c478bd9Sstevel@tonic-gate 258*7c478bd9Sstevel@tonic-gate#if defined(lint) 259*7c478bd9Sstevel@tonic-gate 260*7c478bd9Sstevel@tonic-gate/* ARGSUSED */ 261*7c478bd9Sstevel@tonic-gateint 262*7c478bd9Sstevel@tonic-gatecopyoutstr(const char *kaddr, char *uaddr, size_t maxlength, 263*7c478bd9Sstevel@tonic-gate size_t *lencopied) 264*7c478bd9Sstevel@tonic-gate{ return (0); } 265*7c478bd9Sstevel@tonic-gate 266*7c478bd9Sstevel@tonic-gate#else /* lint */ 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate ENTRY(copyoutstr) 269*7c478bd9Sstevel@tonic-gate sethi %hi(.copyoutstr_err), %o5 270*7c478bd9Sstevel@tonic-gate ldn [THREAD_REG + T_LOFAULT], %o4 ! catch faults 271*7c478bd9Sstevel@tonic-gate or %o5, %lo(.copyoutstr_err), %o5 272*7c478bd9Sstevel@tonic-gate membar #Sync ! sync error barrier 273*7c478bd9Sstevel@tonic-gate stn %o5, [THREAD_REG + T_LOFAULT] 274*7c478bd9Sstevel@tonic-gate mov %o4, %o5 275*7c478bd9Sstevel@tonic-gate 276*7c478bd9Sstevel@tonic-gate brz,a,pn %o2, .copyoutstr_out 277*7c478bd9Sstevel@tonic-gate mov ENAMETOOLONG, %o0 278*7c478bd9Sstevel@tonic-gate 279*7c478bd9Sstevel@tonic-gate mov %o2, %g3 ! g3 is the current count 280*7c478bd9Sstevel@tonic-gate mov %o1, %g4 ! g4 is the dest addr 281*7c478bd9Sstevel@tonic-gate 282*7c478bd9Sstevel@tonic-gate b 1f 283*7c478bd9Sstevel@tonic-gate sub %o0, %o1, %g2 ! g2 gets the difference of src and dst 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate ! 286*7c478bd9Sstevel@tonic-gate ! Do a byte by byte loop. 287*7c478bd9Sstevel@tonic-gate ! We do this instead of a word by word copy because most strings 288*7c478bd9Sstevel@tonic-gate ! are small and this takes a small number of cache lines. 289*7c478bd9Sstevel@tonic-gate ! 290*7c478bd9Sstevel@tonic-gate0: 291*7c478bd9Sstevel@tonic-gate stba %g1, [%g4]ASI_USER ! store byte 292*7c478bd9Sstevel@tonic-gate tst %g1 293*7c478bd9Sstevel@tonic-gate bnz,pt %icc, 1f 294*7c478bd9Sstevel@tonic-gate add %g4, 1, %g4 ! incr dst addr 295*7c478bd9Sstevel@tonic-gate 296*7c478bd9Sstevel@tonic-gate ba,pt %ncc, .copyoutstr_out ! last byte in string 297*7c478bd9Sstevel@tonic-gate mov 0, %o0 ! ret code = 0 298*7c478bd9Sstevel@tonic-gate1: 299*7c478bd9Sstevel@tonic-gate subcc %g3, 1, %g3 ! test count 300*7c478bd9Sstevel@tonic-gate bgeu,a %ncc, 0b 301*7c478bd9Sstevel@tonic-gate ldub [%g2 + %g4], %g1 ! delay slot, get source byte 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate mov 0, %g3 ! max number of bytes moved 304*7c478bd9Sstevel@tonic-gate ba,pt %ncc, .copyoutstr_out 305*7c478bd9Sstevel@tonic-gate mov ENAMETOOLONG, %o0 ! ret code = ENAMETOOLONG 306*7c478bd9Sstevel@tonic-gate 307*7c478bd9Sstevel@tonic-gate/* 308*7c478bd9Sstevel@tonic-gate * Fault while trying to move from or to user space. 309*7c478bd9Sstevel@tonic-gate * Set and return error code. 310*7c478bd9Sstevel@tonic-gate */ 311*7c478bd9Sstevel@tonic-gate.copyoutstr_err: 312*7c478bd9Sstevel@tonic-gate membar #Sync ! sync error barrier 313*7c478bd9Sstevel@tonic-gate stn %o5, [THREAD_REG + T_LOFAULT] 314*7c478bd9Sstevel@tonic-gate ldn [THREAD_REG + T_COPYOPS], %o4 315*7c478bd9Sstevel@tonic-gate brz %o4, 1f 316*7c478bd9Sstevel@tonic-gate nop 317*7c478bd9Sstevel@tonic-gate ldn [%o4 + CP_COPYOUTSTR], %g1 318*7c478bd9Sstevel@tonic-gate jmp %g1 319*7c478bd9Sstevel@tonic-gate nop 320*7c478bd9Sstevel@tonic-gate1: 321*7c478bd9Sstevel@tonic-gate retl 322*7c478bd9Sstevel@tonic-gate mov EFAULT, %o0 323*7c478bd9Sstevel@tonic-gate.copyoutstr_out: 324*7c478bd9Sstevel@tonic-gate tst %o3 ! want length? 325*7c478bd9Sstevel@tonic-gate bz %ncc, 2f 326*7c478bd9Sstevel@tonic-gate sub %o2, %g3, %o2 ! compute length and store it 327*7c478bd9Sstevel@tonic-gate stn %o2, [%o3] 328*7c478bd9Sstevel@tonic-gate2: 329*7c478bd9Sstevel@tonic-gate membar #Sync ! sync error barrier 330*7c478bd9Sstevel@tonic-gate retl 331*7c478bd9Sstevel@tonic-gate stn %o5, [THREAD_REG + T_LOFAULT] ! stop catching faults 332*7c478bd9Sstevel@tonic-gate SET_SIZE(copyoutstr) 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate#endif /* lint */ 335*7c478bd9Sstevel@tonic-gate 336*7c478bd9Sstevel@tonic-gate#if defined(lint) 337*7c478bd9Sstevel@tonic-gate 338*7c478bd9Sstevel@tonic-gate/* ARGSUSED */ 339*7c478bd9Sstevel@tonic-gateint 340*7c478bd9Sstevel@tonic-gatecopyoutstr_noerr(const char *kaddr, char *uaddr, size_t maxlength, 341*7c478bd9Sstevel@tonic-gate size_t *lencopied) 342*7c478bd9Sstevel@tonic-gate{ return (0); } 343*7c478bd9Sstevel@tonic-gate 344*7c478bd9Sstevel@tonic-gate#else /* lint */ 345*7c478bd9Sstevel@tonic-gate 346*7c478bd9Sstevel@tonic-gate ENTRY(copyoutstr_noerr) 347*7c478bd9Sstevel@tonic-gate mov %o2, %o4 ! save original count 348*7c478bd9Sstevel@tonic-gate 349*7c478bd9Sstevel@tonic-gate brz,a,pn %o2, .copyoutstr_noerr_out 350*7c478bd9Sstevel@tonic-gate mov ENAMETOOLONG, %o0 351*7c478bd9Sstevel@tonic-gate 352*7c478bd9Sstevel@tonic-gate b 1f 353*7c478bd9Sstevel@tonic-gate sub %o0, %o1, %o0 ! o0 gets the difference of src and dst 354*7c478bd9Sstevel@tonic-gate 355*7c478bd9Sstevel@tonic-gate ! 356*7c478bd9Sstevel@tonic-gate ! Do a byte by byte loop. 357*7c478bd9Sstevel@tonic-gate ! We do this instead of a word by word copy because most strings 358*7c478bd9Sstevel@tonic-gate ! are small and this takes a small number of cache lines. 359*7c478bd9Sstevel@tonic-gate ! 360*7c478bd9Sstevel@tonic-gate0: 361*7c478bd9Sstevel@tonic-gate stba %g1, [%o1]ASI_USER ! store byte 362*7c478bd9Sstevel@tonic-gate tst %g1 ! null byte? 363*7c478bd9Sstevel@tonic-gate bnz 1f 364*7c478bd9Sstevel@tonic-gate add %o1, 1, %o1 ! incr dst addr 365*7c478bd9Sstevel@tonic-gate 366*7c478bd9Sstevel@tonic-gate b .copyoutstr_noerr_out ! last byte in string 367*7c478bd9Sstevel@tonic-gate mov 0, %o0 ! ret code = 0 368*7c478bd9Sstevel@tonic-gate1: 369*7c478bd9Sstevel@tonic-gate subcc %o2, 1, %o2 ! test count 370*7c478bd9Sstevel@tonic-gate bgeu,a %ncc, 0b 371*7c478bd9Sstevel@tonic-gate ldub [%o0+%o1], %g1 ! delay slot, get source byte 372*7c478bd9Sstevel@tonic-gate 373*7c478bd9Sstevel@tonic-gate mov 0, %o2 ! max number of bytes moved 374*7c478bd9Sstevel@tonic-gate b .copyoutstr_noerr_out 375*7c478bd9Sstevel@tonic-gate mov ENAMETOOLONG, %o0 ! ret code = ENAMETOOLONG 376*7c478bd9Sstevel@tonic-gate.copyoutstr_noerr_out: 377*7c478bd9Sstevel@tonic-gate tst %o3 ! want length? 378*7c478bd9Sstevel@tonic-gate bz %ncc, 2f 379*7c478bd9Sstevel@tonic-gate sub %o4, %o2, %o4 380*7c478bd9Sstevel@tonic-gate stn %o4, [%o3] 381*7c478bd9Sstevel@tonic-gate2: 382*7c478bd9Sstevel@tonic-gate retl 383*7c478bd9Sstevel@tonic-gate nop 384*7c478bd9Sstevel@tonic-gate SET_SIZE(copyoutstr_noerr) 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate#endif /* lint */ 387*7c478bd9Sstevel@tonic-gate 388*7c478bd9Sstevel@tonic-gate 389*7c478bd9Sstevel@tonic-gate/* 390*7c478bd9Sstevel@tonic-gate * Copy a block of storage - must not overlap (from + len <= to). 391*7c478bd9Sstevel@tonic-gate * No fault handler installed (to be called under on_fault()) 392*7c478bd9Sstevel@tonic-gate */ 393*7c478bd9Sstevel@tonic-gate 394*7c478bd9Sstevel@tonic-gate#if defined(lint) 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate/* ARGSUSED */ 397*7c478bd9Sstevel@tonic-gatevoid 398*7c478bd9Sstevel@tonic-gateucopy(const void *ufrom, void *uto, size_t ulength) 399*7c478bd9Sstevel@tonic-gate{} 400*7c478bd9Sstevel@tonic-gate 401*7c478bd9Sstevel@tonic-gate#else /* lint */ 402*7c478bd9Sstevel@tonic-gate 403*7c478bd9Sstevel@tonic-gate ENTRY(ucopy) 404*7c478bd9Sstevel@tonic-gate save %sp, -SA(MINFRAME), %sp ! get another window 405*7c478bd9Sstevel@tonic-gate 406*7c478bd9Sstevel@tonic-gate subcc %g0, %i2, %i3 407*7c478bd9Sstevel@tonic-gate add %i0, %i2, %i0 408*7c478bd9Sstevel@tonic-gate bz,pn %ncc, 5f 409*7c478bd9Sstevel@tonic-gate add %i1, %i2, %i1 410*7c478bd9Sstevel@tonic-gate lduba [%i0 + %i3]ASI_USER, %i4 411*7c478bd9Sstevel@tonic-gate4: stba %i4, [%i1 + %i3]ASI_USER 412*7c478bd9Sstevel@tonic-gate inccc %i3 413*7c478bd9Sstevel@tonic-gate bcc,a,pt %ncc, 4b 414*7c478bd9Sstevel@tonic-gate lduba [%i0 + %i3]ASI_USER, %i4 415*7c478bd9Sstevel@tonic-gate5: 416*7c478bd9Sstevel@tonic-gate ret 417*7c478bd9Sstevel@tonic-gate restore %g0, 0, %o0 ! return (0) 418*7c478bd9Sstevel@tonic-gate 419*7c478bd9Sstevel@tonic-gate SET_SIZE(ucopy) 420*7c478bd9Sstevel@tonic-gate#endif /* lint */ 421