1*0Sstevel@tonic-gate/* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate/* 23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate#pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate#include <sys/param.h> 30*0Sstevel@tonic-gate#include <sys/errno.h> 31*0Sstevel@tonic-gate#include <sys/asm_linkage.h> 32*0Sstevel@tonic-gate#include <sys/vtrace.h> 33*0Sstevel@tonic-gate#include <sys/machthread.h> 34*0Sstevel@tonic-gate#include <sys/clock.h> 35*0Sstevel@tonic-gate#include <sys/asi.h> 36*0Sstevel@tonic-gate#include <sys/fsr.h> 37*0Sstevel@tonic-gate#include <sys/privregs.h> 38*0Sstevel@tonic-gate 39*0Sstevel@tonic-gate#if !defined(lint) 40*0Sstevel@tonic-gate#include "assym.h" 41*0Sstevel@tonic-gate#endif /* lint */ 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gate#define FP_USED 1 44*0Sstevel@tonic-gate#define LOFAULT_SET 2 45*0Sstevel@tonic-gate 46*0Sstevel@tonic-gate/* 47*0Sstevel@tonic-gate * Error barrier: 48*0Sstevel@tonic-gate * We use membar sync to establish an error barrier for 49*0Sstevel@tonic-gate * deferred errors. Membar syncs are added before any update 50*0Sstevel@tonic-gate * to t_lofault to ensure that deferred errors from earlier 51*0Sstevel@tonic-gate * accesses will not be reported after the membar. This error 52*0Sstevel@tonic-gate * isolation is important when we try to recover from async 53*0Sstevel@tonic-gate * errors which tries to distinguish kernel accesses to user 54*0Sstevel@tonic-gate * data. 55*0Sstevel@tonic-gate */ 56*0Sstevel@tonic-gate 57*0Sstevel@tonic-gate/* 58*0Sstevel@tonic-gate * Zero a block of storage. 59*0Sstevel@tonic-gate * 60*0Sstevel@tonic-gate * uzero is used by the kernel to zero a block in user address space. 61*0Sstevel@tonic-gate */ 62*0Sstevel@tonic-gate 63*0Sstevel@tonic-gate#if defined(lint) 64*0Sstevel@tonic-gate 65*0Sstevel@tonic-gate/* ARGSUSED */ 66*0Sstevel@tonic-gateint 67*0Sstevel@tonic-gatekzero(void *addr, size_t count) 68*0Sstevel@tonic-gate{ return(0); } 69*0Sstevel@tonic-gate 70*0Sstevel@tonic-gate/* ARGSUSED */ 71*0Sstevel@tonic-gatevoid 72*0Sstevel@tonic-gateuzero(void *addr, size_t count) 73*0Sstevel@tonic-gate{} 74*0Sstevel@tonic-gate 75*0Sstevel@tonic-gate#else /* lint */ 76*0Sstevel@tonic-gate 77*0Sstevel@tonic-gate ENTRY(uzero) 78*0Sstevel@tonic-gate ! 79*0Sstevel@tonic-gate ! Set a new lo_fault handler only if we came in with one 80*0Sstevel@tonic-gate ! already specified. 81*0Sstevel@tonic-gate ! 82*0Sstevel@tonic-gate wr %g0, ASI_USER, %asi 83*0Sstevel@tonic-gate ldn [THREAD_REG + T_LOFAULT], %o5 84*0Sstevel@tonic-gate tst %o5 85*0Sstevel@tonic-gate bz,pt %ncc, .do_zero 86*0Sstevel@tonic-gate sethi %hi(.zeroerr), %o2 87*0Sstevel@tonic-gate or %o2, %lo(.zeroerr), %o2 88*0Sstevel@tonic-gate membar #Sync 89*0Sstevel@tonic-gate ba,pt %ncc, .do_zero 90*0Sstevel@tonic-gate stn %o2, [THREAD_REG + T_LOFAULT] 91*0Sstevel@tonic-gate 92*0Sstevel@tonic-gate ENTRY(kzero) 93*0Sstevel@tonic-gate ! 94*0Sstevel@tonic-gate ! Always set a lo_fault handler 95*0Sstevel@tonic-gate ! 96*0Sstevel@tonic-gate wr %g0, ASI_P, %asi 97*0Sstevel@tonic-gate ldn [THREAD_REG + T_LOFAULT], %o5 98*0Sstevel@tonic-gate sethi %hi(.zeroerr), %o2 99*0Sstevel@tonic-gate or %o5, LOFAULT_SET, %o5 100*0Sstevel@tonic-gate or %o2, %lo(.zeroerr), %o2 101*0Sstevel@tonic-gate membar #Sync 102*0Sstevel@tonic-gate ba,pt %ncc, .do_zero 103*0Sstevel@tonic-gate stn %o2, [THREAD_REG + T_LOFAULT] 104*0Sstevel@tonic-gate 105*0Sstevel@tonic-gate/* 106*0Sstevel@tonic-gate * We got here because of a fault during kzero or if 107*0Sstevel@tonic-gate * uzero or bzero was called with t_lofault non-zero. 108*0Sstevel@tonic-gate * Otherwise we've already run screaming from the room. 109*0Sstevel@tonic-gate * Errno value is in %g1. Note that we're here iff 110*0Sstevel@tonic-gate * we did set t_lofault. 111*0Sstevel@tonic-gate */ 112*0Sstevel@tonic-gate.zeroerr: 113*0Sstevel@tonic-gate ! 114*0Sstevel@tonic-gate ! Undo asi register setting. Just set it to be the 115*0Sstevel@tonic-gate ! kernel default without checking. 116*0Sstevel@tonic-gate ! 117*0Sstevel@tonic-gate wr %g0, ASI_P, %asi 118*0Sstevel@tonic-gate ! 119*0Sstevel@tonic-gate ! If saved t_lofault has FP_USED set, clear the %fprs register 120*0Sstevel@tonic-gate ! 121*0Sstevel@tonic-gate btst FP_USED, %o5 122*0Sstevel@tonic-gate bz,pt %ncc, 1f ! skip if not used 123*0Sstevel@tonic-gate nop 124*0Sstevel@tonic-gate membar #Sync 125*0Sstevel@tonic-gate wr %g0, %g0, %fprs ! clear fprs 126*0Sstevel@tonic-gate andn %o5, FP_USED, %o5 ! turn off flag bit 127*0Sstevel@tonic-gate ! 128*0Sstevel@tonic-gate ! We did set t_lofault. It may well have been zero coming in. 129*0Sstevel@tonic-gate ! 130*0Sstevel@tonic-gate1: 131*0Sstevel@tonic-gate tst %o5 132*0Sstevel@tonic-gate membar #Sync 133*0Sstevel@tonic-gate bne,pn %ncc, 3f 134*0Sstevel@tonic-gate andncc %o5, LOFAULT_SET, %o5 135*0Sstevel@tonic-gate2: 136*0Sstevel@tonic-gate ! 137*0Sstevel@tonic-gate ! Old handler was zero. Just return the error. 138*0Sstevel@tonic-gate ! 139*0Sstevel@tonic-gate retl ! return 140*0Sstevel@tonic-gate mov %g1, %o0 ! error code from %g1 141*0Sstevel@tonic-gate3: 142*0Sstevel@tonic-gate ! 143*0Sstevel@tonic-gate ! We're here because %o5 was non-zero. It was non-zero 144*0Sstevel@tonic-gate ! because either LOFAULT_SET was present, a previous fault 145*0Sstevel@tonic-gate ! handler was present or both. In all cases we need to reset 146*0Sstevel@tonic-gate ! T_LOFAULT to the value of %o5 after clearing LOFAULT_SET 147*0Sstevel@tonic-gate ! before we either simply return the error or we invoke the 148*0Sstevel@tonic-gate ! previously specified handler. 149*0Sstevel@tonic-gate ! 150*0Sstevel@tonic-gate be %ncc, 2b 151*0Sstevel@tonic-gate stn %o5, [THREAD_REG + T_LOFAULT] 152*0Sstevel@tonic-gate jmp %o5 ! goto real handler 153*0Sstevel@tonic-gate nop 154*0Sstevel@tonic-gate SET_SIZE(kzero) 155*0Sstevel@tonic-gate SET_SIZE(uzero) 156*0Sstevel@tonic-gate 157*0Sstevel@tonic-gate#endif /* lint */ 158*0Sstevel@tonic-gate 159*0Sstevel@tonic-gate/* 160*0Sstevel@tonic-gate * Zero a block of storage. 161*0Sstevel@tonic-gate */ 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gate#if defined(lint) 164*0Sstevel@tonic-gate 165*0Sstevel@tonic-gate/* ARGSUSED */ 166*0Sstevel@tonic-gatevoid 167*0Sstevel@tonic-gatebzero(void *addr, size_t count) 168*0Sstevel@tonic-gate{} 169*0Sstevel@tonic-gate 170*0Sstevel@tonic-gate#else /* lint */ 171*0Sstevel@tonic-gate 172*0Sstevel@tonic-gate ENTRY(bzero) 173*0Sstevel@tonic-gate wr %g0, ASI_P, %asi 174*0Sstevel@tonic-gate 175*0Sstevel@tonic-gate ldn [THREAD_REG + T_LOFAULT], %o5 ! save old vector 176*0Sstevel@tonic-gate tst %o5 177*0Sstevel@tonic-gate bz,pt %ncc, .do_zero 178*0Sstevel@tonic-gate sethi %hi(.zeroerr), %o2 179*0Sstevel@tonic-gate or %o2, %lo(.zeroerr), %o2 180*0Sstevel@tonic-gate membar #Sync ! sync error barrier 181*0Sstevel@tonic-gate stn %o2, [THREAD_REG + T_LOFAULT] ! install new vector 182*0Sstevel@tonic-gate 183*0Sstevel@tonic-gate.do_zero: 184*0Sstevel@tonic-gate cmp %o1, 15 ! check for small counts 185*0Sstevel@tonic-gate blu,pn %ncc, .byteclr ! just clear bytes 186*0Sstevel@tonic-gate nop 187*0Sstevel@tonic-gate 188*0Sstevel@tonic-gate cmp %o1, 192 ! check for large counts 189*0Sstevel@tonic-gate blu %ncc, .bzero_small 190*0Sstevel@tonic-gate nop 191*0Sstevel@tonic-gate 192*0Sstevel@tonic-gate sethi %hi(use_hw_bzero), %o2 193*0Sstevel@tonic-gate ld [%o2 + %lo(use_hw_bzero)], %o2 194*0Sstevel@tonic-gate tst %o2 195*0Sstevel@tonic-gate bz %icc, .bzero_small 196*0Sstevel@tonic-gate nop 197*0Sstevel@tonic-gate 198*0Sstevel@tonic-gate rd %fprs, %o2 ! check for unused fp 199*0Sstevel@tonic-gate btst FPRS_FEF, %o2 200*0Sstevel@tonic-gate bnz %icc, .bzero_small 201*0Sstevel@tonic-gate nop 202*0Sstevel@tonic-gate 203*0Sstevel@tonic-gate ldn [THREAD_REG + T_LWP], %o2 204*0Sstevel@tonic-gate tst %o2 205*0Sstevel@tonic-gate bz,pn %ncc, .bzero_small 206*0Sstevel@tonic-gate nop 207*0Sstevel@tonic-gate 208*0Sstevel@tonic-gate ! Check for block alignment 209*0Sstevel@tonic-gate btst (64-1), %o0 210*0Sstevel@tonic-gate bz %icc, .bzl_block 211*0Sstevel@tonic-gate nop 212*0Sstevel@tonic-gate 213*0Sstevel@tonic-gate ! Check for double-word alignment 214*0Sstevel@tonic-gate btst (8-1), %o0 215*0Sstevel@tonic-gate bz %icc, .bzl_dword 216*0Sstevel@tonic-gate nop 217*0Sstevel@tonic-gate 218*0Sstevel@tonic-gate ! Check for word alignment 219*0Sstevel@tonic-gate btst (4-1), %o0 220*0Sstevel@tonic-gate bz %icc, .bzl_word 221*0Sstevel@tonic-gate nop 222*0Sstevel@tonic-gate 223*0Sstevel@tonic-gate ! Clear bytes until word aligned 224*0Sstevel@tonic-gate.bzl_byte: 225*0Sstevel@tonic-gate stba %g0, [%o0]%asi 226*0Sstevel@tonic-gate add %o0, 1, %o0 227*0Sstevel@tonic-gate btst (4-1), %o0 228*0Sstevel@tonic-gate bnz %icc, .bzl_byte 229*0Sstevel@tonic-gate sub %o1, 1, %o1 230*0Sstevel@tonic-gate 231*0Sstevel@tonic-gate ! Check for dword-aligned 232*0Sstevel@tonic-gate btst (8-1), %o0 233*0Sstevel@tonic-gate bz %icc, .bzl_dword 234*0Sstevel@tonic-gate nop 235*0Sstevel@tonic-gate 236*0Sstevel@tonic-gate ! Clear words until double-word aligned 237*0Sstevel@tonic-gate.bzl_word: 238*0Sstevel@tonic-gate sta %g0, [%o0]%asi 239*0Sstevel@tonic-gate add %o0, 4, %o0 240*0Sstevel@tonic-gate btst (8-1), %o0 241*0Sstevel@tonic-gate bnz %icc, .bzl_word 242*0Sstevel@tonic-gate sub %o1, 4, %o1 243*0Sstevel@tonic-gate 244*0Sstevel@tonic-gate.bzl_dword: 245*0Sstevel@tonic-gate ! Clear dwords until block aligned 246*0Sstevel@tonic-gate stxa %g0, [%o0]%asi 247*0Sstevel@tonic-gate add %o0, 8, %o0 248*0Sstevel@tonic-gate btst (64-1), %o0 249*0Sstevel@tonic-gate bnz %icc, .bzl_dword 250*0Sstevel@tonic-gate sub %o1, 8, %o1 251*0Sstevel@tonic-gate 252*0Sstevel@tonic-gate.bzl_block: 253*0Sstevel@tonic-gate membar #StoreStore|#StoreLoad|#LoadStore 254*0Sstevel@tonic-gate wr %g0, FPRS_FEF, %fprs 255*0Sstevel@tonic-gate 256*0Sstevel@tonic-gate ! Set the lower bit in the saved t_lofault to indicate 257*0Sstevel@tonic-gate ! that we need to clear the %fprs register on the way 258*0Sstevel@tonic-gate ! out 259*0Sstevel@tonic-gate or %o5, FP_USED, %o5 260*0Sstevel@tonic-gate 261*0Sstevel@tonic-gate ! Clear block 262*0Sstevel@tonic-gate fzero %d0 263*0Sstevel@tonic-gate fzero %d2 264*0Sstevel@tonic-gate fzero %d4 265*0Sstevel@tonic-gate fzero %d6 266*0Sstevel@tonic-gate fzero %d8 267*0Sstevel@tonic-gate fzero %d10 268*0Sstevel@tonic-gate fzero %d12 269*0Sstevel@tonic-gate fzero %d14 270*0Sstevel@tonic-gate rd %asi, %o3 271*0Sstevel@tonic-gate wr %g0, ASI_BLK_P, %asi 272*0Sstevel@tonic-gate cmp %o3, ASI_P 273*0Sstevel@tonic-gate bne,a %icc, 1f 274*0Sstevel@tonic-gate wr %g0, ASI_BLK_AIUS, %asi 275*0Sstevel@tonic-gate1: 276*0Sstevel@tonic-gate mov 256, %o3 277*0Sstevel@tonic-gate ba,pt %ncc, .bzl_doblock 278*0Sstevel@tonic-gate nop 279*0Sstevel@tonic-gate 280*0Sstevel@tonic-gate.bzl_blkstart: 281*0Sstevel@tonic-gate ! stda %d0, [%o0+192]%asi ! in dly slot of branch that got us here 282*0Sstevel@tonic-gate stda %d0, [%o0+128]%asi 283*0Sstevel@tonic-gate stda %d0, [%o0+64]%asi 284*0Sstevel@tonic-gate stda %d0, [%o0]%asi 285*0Sstevel@tonic-gate.bzl_zinst: 286*0Sstevel@tonic-gate add %o0, %o3, %o0 287*0Sstevel@tonic-gate sub %o1, %o3, %o1 288*0Sstevel@tonic-gate.bzl_doblock: 289*0Sstevel@tonic-gate cmp %o1, 256 290*0Sstevel@tonic-gate bgeu,a %ncc, .bzl_blkstart 291*0Sstevel@tonic-gate stda %d0, [%o0+192]%asi 292*0Sstevel@tonic-gate 293*0Sstevel@tonic-gate cmp %o1, 64 294*0Sstevel@tonic-gate blu %ncc, .bzl_finish 295*0Sstevel@tonic-gate 296*0Sstevel@tonic-gate andn %o1, (64-1), %o3 297*0Sstevel@tonic-gate srl %o3, 4, %o2 ! using blocks, 1 instr / 16 words 298*0Sstevel@tonic-gate set .bzl_zinst, %o4 299*0Sstevel@tonic-gate sub %o4, %o2, %o4 300*0Sstevel@tonic-gate jmp %o4 301*0Sstevel@tonic-gate nop 302*0Sstevel@tonic-gate 303*0Sstevel@tonic-gate.bzl_finish: 304*0Sstevel@tonic-gate membar #StoreLoad|#StoreStore 305*0Sstevel@tonic-gate wr %g0, %g0, %fprs 306*0Sstevel@tonic-gate andn %o5, FP_USED, %o5 307*0Sstevel@tonic-gate 308*0Sstevel@tonic-gate rd %asi, %o4 309*0Sstevel@tonic-gate wr %g0, ASI_P, %asi 310*0Sstevel@tonic-gate cmp %o4, ASI_BLK_P 311*0Sstevel@tonic-gate bne,a %icc, 1f 312*0Sstevel@tonic-gate wr %g0, ASI_USER, %asi 313*0Sstevel@tonic-gate1: 314*0Sstevel@tonic-gate 315*0Sstevel@tonic-gate.bzlf_dword: 316*0Sstevel@tonic-gate ! double words 317*0Sstevel@tonic-gate cmp %o1, 8 318*0Sstevel@tonic-gate blu %ncc, .bzlf_word 319*0Sstevel@tonic-gate nop 320*0Sstevel@tonic-gate stxa %g0, [%o0]%asi 321*0Sstevel@tonic-gate add %o0, 8, %o0 322*0Sstevel@tonic-gate sub %o1, 8, %o1 323*0Sstevel@tonic-gate ba,pt %ncc, .bzlf_dword 324*0Sstevel@tonic-gate nop 325*0Sstevel@tonic-gate 326*0Sstevel@tonic-gate.bzlf_word: 327*0Sstevel@tonic-gate ! words 328*0Sstevel@tonic-gate cmp %o1, 4 329*0Sstevel@tonic-gate blu %ncc, .bzlf_byte 330*0Sstevel@tonic-gate nop 331*0Sstevel@tonic-gate sta %g0, [%o0]%asi 332*0Sstevel@tonic-gate add %o0, 4, %o0 333*0Sstevel@tonic-gate sub %o1, 4, %o1 334*0Sstevel@tonic-gate ba,pt %ncc, .bzlf_word 335*0Sstevel@tonic-gate nop 336*0Sstevel@tonic-gate 337*0Sstevel@tonic-gate1: 338*0Sstevel@tonic-gate add %o0, 1, %o0 ! increment address 339*0Sstevel@tonic-gate.bzlf_byte: 340*0Sstevel@tonic-gate subcc %o1, 1, %o1 ! decrement count 341*0Sstevel@tonic-gate bgeu,a %ncc, 1b 342*0Sstevel@tonic-gate stba %g0, [%o0]%asi ! zero a byte 343*0Sstevel@tonic-gate 344*0Sstevel@tonic-gate ! 345*0Sstevel@tonic-gate ! If we used the FP registers, that bit was turned 346*0Sstevel@tonic-gate ! off after we were finished. We're just concerned with 347*0Sstevel@tonic-gate ! whether t_lofault was set when we came in. We end up 348*0Sstevel@tonic-gate ! here from either kzero() or bzero(). kzero() *always* 349*0Sstevel@tonic-gate ! sets a lofault handler. It ors LOFAULT_SET into %o5 350*0Sstevel@tonic-gate ! to indicate it has done this even if the value of %o5 351*0Sstevel@tonic-gate ! is otherwise zero. bzero() sets a lofault handler *only* 352*0Sstevel@tonic-gate ! if one was previously set. Accordingly we need to examine 353*0Sstevel@tonic-gate ! %o5 and if it is non-zero be sure to clear LOFAULT_SET 354*0Sstevel@tonic-gate ! before resetting the error handler. 355*0Sstevel@tonic-gate ! 356*0Sstevel@tonic-gate tst %o5 357*0Sstevel@tonic-gate bz,pt %ncc, 1f 358*0Sstevel@tonic-gate andn %o5, LOFAULT_SET, %o5 359*0Sstevel@tonic-gate membar #Sync ! sync error barrier 360*0Sstevel@tonic-gate stn %o5, [THREAD_REG + T_LOFAULT] ! restore old t_lofault 361*0Sstevel@tonic-gate1: 362*0Sstevel@tonic-gate retl 363*0Sstevel@tonic-gate clr %o0 ! return (0) 364*0Sstevel@tonic-gate 365*0Sstevel@tonic-gate.bzero_small: 366*0Sstevel@tonic-gate 367*0Sstevel@tonic-gate ! 368*0Sstevel@tonic-gate ! Check for word alignment. 369*0Sstevel@tonic-gate ! 370*0Sstevel@tonic-gate btst 3, %o0 371*0Sstevel@tonic-gate bz .bzero_probe 372*0Sstevel@tonic-gate mov 0x100, %o3 ! constant size of main loop 373*0Sstevel@tonic-gate ! 374*0Sstevel@tonic-gate ! 375*0Sstevel@tonic-gate ! clear bytes until word aligned 376*0Sstevel@tonic-gate ! 377*0Sstevel@tonic-gate1: stba %g0,[%o0]%asi 378*0Sstevel@tonic-gate add %o0, 1, %o0 379*0Sstevel@tonic-gate btst 3, %o0 380*0Sstevel@tonic-gate bnz 1b 381*0Sstevel@tonic-gate sub %o1, 1, %o1 382*0Sstevel@tonic-gate.bzero_probe: 383*0Sstevel@tonic-gate 384*0Sstevel@tonic-gate ! 385*0Sstevel@tonic-gate ! if needed move a word to become double-word aligned. 386*0Sstevel@tonic-gate ! 387*0Sstevel@tonic-gate btst 7, %o0 ! is double aligned? 388*0Sstevel@tonic-gate bz %icc, .bzero_nobuf 389*0Sstevel@tonic-gate nop 390*0Sstevel@tonic-gate sta %g0, [%o0]%asi ! clr to double boundry 391*0Sstevel@tonic-gate sub %o1, 4, %o1 392*0Sstevel@tonic-gate ba,pt %ncc, .bzero_nobuf 393*0Sstevel@tonic-gate add %o0, 4, %o0 394*0Sstevel@tonic-gate 395*0Sstevel@tonic-gate !stxa %g0, [%o0+0xf8]%asi 396*0Sstevel@tonic-gate.bzero_blk: 397*0Sstevel@tonic-gate stxa %g0, [%o0+0xf0]%asi 398*0Sstevel@tonic-gate stxa %g0, [%o0+0xe8]%asi 399*0Sstevel@tonic-gate stxa %g0, [%o0+0xe0]%asi 400*0Sstevel@tonic-gate stxa %g0, [%o0+0xd8]%asi 401*0Sstevel@tonic-gate stxa %g0, [%o0+0xd0]%asi 402*0Sstevel@tonic-gate stxa %g0, [%o0+0xc8]%asi 403*0Sstevel@tonic-gate stxa %g0, [%o0+0xc0]%asi 404*0Sstevel@tonic-gate stxa %g0, [%o0+0xb8]%asi 405*0Sstevel@tonic-gate stxa %g0, [%o0+0xb0]%asi 406*0Sstevel@tonic-gate stxa %g0, [%o0+0xa8]%asi 407*0Sstevel@tonic-gate stxa %g0, [%o0+0xa0]%asi 408*0Sstevel@tonic-gate stxa %g0, [%o0+0x98]%asi 409*0Sstevel@tonic-gate stxa %g0, [%o0+0x90]%asi 410*0Sstevel@tonic-gate stxa %g0, [%o0+0x88]%asi 411*0Sstevel@tonic-gate stxa %g0, [%o0+0x80]%asi 412*0Sstevel@tonic-gate stxa %g0, [%o0+0x78]%asi 413*0Sstevel@tonic-gate stxa %g0, [%o0+0x70]%asi 414*0Sstevel@tonic-gate stxa %g0, [%o0+0x68]%asi 415*0Sstevel@tonic-gate stxa %g0, [%o0+0x60]%asi 416*0Sstevel@tonic-gate stxa %g0, [%o0+0x58]%asi 417*0Sstevel@tonic-gate stxa %g0, [%o0+0x50]%asi 418*0Sstevel@tonic-gate stxa %g0, [%o0+0x48]%asi 419*0Sstevel@tonic-gate stxa %g0, [%o0+0x40]%asi 420*0Sstevel@tonic-gate stxa %g0, [%o0+0x38]%asi 421*0Sstevel@tonic-gate stxa %g0, [%o0+0x30]%asi 422*0Sstevel@tonic-gate stxa %g0, [%o0+0x28]%asi 423*0Sstevel@tonic-gate stxa %g0, [%o0+0x20]%asi 424*0Sstevel@tonic-gate stxa %g0, [%o0+0x18]%asi 425*0Sstevel@tonic-gate stxa %g0, [%o0+0x10]%asi 426*0Sstevel@tonic-gate stxa %g0, [%o0+0x08]%asi 427*0Sstevel@tonic-gate stxa %g0, [%o0]%asi 428*0Sstevel@tonic-gate.zinst: 429*0Sstevel@tonic-gate add %o0, %o3, %o0 ! increment source address 430*0Sstevel@tonic-gate sub %o1, %o3, %o1 ! decrement count 431*0Sstevel@tonic-gate.bzero_nobuf: 432*0Sstevel@tonic-gate cmp %o1, 0x100 ! can we do whole chunk? 433*0Sstevel@tonic-gate bgeu,a %ncc, .bzero_blk 434*0Sstevel@tonic-gate stxa %g0, [%o0+0xf8]%asi ! do first double of chunk 435*0Sstevel@tonic-gate 436*0Sstevel@tonic-gate cmp %o1, 7 ! can we zero any more double words 437*0Sstevel@tonic-gate bleu %ncc, .byteclr ! too small go zero bytes 438*0Sstevel@tonic-gate 439*0Sstevel@tonic-gate andn %o1, 7, %o3 ! %o3 bytes left, double-word aligned 440*0Sstevel@tonic-gate srl %o3, 1, %o2 ! using doubles, need 1 instr / 2 words 441*0Sstevel@tonic-gate set .zinst, %o4 ! address of clr instructions 442*0Sstevel@tonic-gate sub %o4, %o2, %o4 ! jmp address relative to instr 443*0Sstevel@tonic-gate jmp %o4 444*0Sstevel@tonic-gate nop 445*0Sstevel@tonic-gate ! 446*0Sstevel@tonic-gate ! do leftover bytes 447*0Sstevel@tonic-gate ! 448*0Sstevel@tonic-gate3: 449*0Sstevel@tonic-gate add %o0, 1, %o0 ! increment address 450*0Sstevel@tonic-gate.byteclr: 451*0Sstevel@tonic-gate subcc %o1, 1, %o1 ! decrement count 452*0Sstevel@tonic-gate bgeu,a %ncc, 3b 453*0Sstevel@tonic-gate stba %g0, [%o0]%asi ! zero a byte 454*0Sstevel@tonic-gate 455*0Sstevel@tonic-gate.bzero_finished: 456*0Sstevel@tonic-gate ! 457*0Sstevel@tonic-gate ! We're just concerned with whether t_lofault was set 458*0Sstevel@tonic-gate ! when we came in. We end up here from either kzero() 459*0Sstevel@tonic-gate ! or bzero(). kzero() *always* sets a lofault handler. 460*0Sstevel@tonic-gate ! It ors LOFAULT_SET into %o5 to indicate it has done 461*0Sstevel@tonic-gate ! this even if the value of %o5 is otherwise zero. 462*0Sstevel@tonic-gate ! bzero() sets a lofault handler *only* if one was 463*0Sstevel@tonic-gate ! previously set. Accordingly we need to examine 464*0Sstevel@tonic-gate ! %o5 and if it is non-zero be sure to clear LOFAULT_SET 465*0Sstevel@tonic-gate ! before resetting the error handler. 466*0Sstevel@tonic-gate ! 467*0Sstevel@tonic-gate tst %o5 468*0Sstevel@tonic-gate bz %ncc, 1f 469*0Sstevel@tonic-gate andn %o5, LOFAULT_SET, %o5 470*0Sstevel@tonic-gate membar #Sync ! sync error barrier 471*0Sstevel@tonic-gate stn %o5, [THREAD_REG + T_LOFAULT] ! restore old t_lofault 472*0Sstevel@tonic-gate1: 473*0Sstevel@tonic-gate retl 474*0Sstevel@tonic-gate clr %o0 ! return (0) 475*0Sstevel@tonic-gate 476*0Sstevel@tonic-gate SET_SIZE(bzero) 477*0Sstevel@tonic-gate#endif /* lint */ 478