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