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 2004 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 #ifndef _SYS_FPRAS_IMPL_H 28*7c478bd9Sstevel@tonic-gate #define _SYS_FPRAS_IMPL_H 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 31*7c478bd9Sstevel@tonic-gate 32*7c478bd9Sstevel@tonic-gate #include <sys/fpras.h> 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate #if !defined(_ASM) 35*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 36*7c478bd9Sstevel@tonic-gate #else 37*7c478bd9Sstevel@tonic-gate #include <sys/intreg.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 39*7c478bd9Sstevel@tonic-gate #endif /* _ASM */ 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate #ifdef __cplusplus 42*7c478bd9Sstevel@tonic-gate extern "C" { 43*7c478bd9Sstevel@tonic-gate #endif 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate /* 46*7c478bd9Sstevel@tonic-gate * sun4u/cheetah fpRAS implementation. Arrays etc will be allocated in sun4u 47*7c478bd9Sstevel@tonic-gate * post_startup() if fpras_implemented is set. This file may belong at 48*7c478bd9Sstevel@tonic-gate * the cpu level (eg, cheetahregs.h) but most of it should be common 49*7c478bd9Sstevel@tonic-gate * when fpRAS support is added for additional cpu types so we introduce 50*7c478bd9Sstevel@tonic-gate * it at the sun4u level (and set fpras_implemented in cpu_setup). 51*7c478bd9Sstevel@tonic-gate * 52*7c478bd9Sstevel@tonic-gate * If fpRAS is implemented on a sun4u/cpu combination that does not use 53*7c478bd9Sstevel@tonic-gate * an ASR for %stick then the FPRAS_INTERVAL macro will need some 54*7c478bd9Sstevel@tonic-gate * modification. 55*7c478bd9Sstevel@tonic-gate */ 56*7c478bd9Sstevel@tonic-gate 57*7c478bd9Sstevel@tonic-gate /* 58*7c478bd9Sstevel@tonic-gate * Upper bound for check frequency per cpu and per operation. For example, if 59*7c478bd9Sstevel@tonic-gate * this is 100 then for cpuid N performing a bcopy if that cpu has not 60*7c478bd9Sstevel@tonic-gate * performed a checked bcopy in the the last 1/100th of a second then 61*7c478bd9Sstevel@tonic-gate * we'll check the current operation. A value of 0 will check every operation. 62*7c478bd9Sstevel@tonic-gate * Modifying fpras_frequency from its default is not recommended. 63*7c478bd9Sstevel@tonic-gate * fpras_interval is computed from fpras_frequency. 64*7c478bd9Sstevel@tonic-gate */ 65*7c478bd9Sstevel@tonic-gate #if !defined(_ASM) 66*7c478bd9Sstevel@tonic-gate extern int fpras_frequency; 67*7c478bd9Sstevel@tonic-gate extern int64_t fpras_interval; 68*7c478bd9Sstevel@tonic-gate #endif /* _ASM */ 69*7c478bd9Sstevel@tonic-gate #define FPRAS_DEFAULT_FREQUENCY 100 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate #if !defined(_ASM) 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate /* 74*7c478bd9Sstevel@tonic-gate * Structure of a check function. The preamble prepares registers for the 75*7c478bd9Sstevel@tonic-gate * upcoming calculation that is performed in blk0 and blk1. One of those 76*7c478bd9Sstevel@tonic-gate * blocks will be rewritten as part of an FPRAS_REWRITE operation. Finally 77*7c478bd9Sstevel@tonic-gate * the result checked in chkresult should be as predetermined, and we should 78*7c478bd9Sstevel@tonic-gate * return zero on success and nonzero on failure. If an illegal instruction 79*7c478bd9Sstevel@tonic-gate * is encountered in the execution of the check function then we trampoline 80*7c478bd9Sstevel@tonic-gate * to the final three instructions to return a different value. 81*7c478bd9Sstevel@tonic-gate * 82*7c478bd9Sstevel@tonic-gate * Note that the size of this structure is a power of 2 as is the 83*7c478bd9Sstevel@tonic-gate * size of a struct fpras_chkfngrp. The asm macros below rely on this 84*7c478bd9Sstevel@tonic-gate * in performing bit shifts instead of mulx. 85*7c478bd9Sstevel@tonic-gate */ 86*7c478bd9Sstevel@tonic-gate struct fpras_chkfn { 87*7c478bd9Sstevel@tonic-gate uint32_t fpras_preamble[16]; 88*7c478bd9Sstevel@tonic-gate uint32_t fpras_blk0[16]; 89*7c478bd9Sstevel@tonic-gate uint32_t fpras_blk1[16]; 90*7c478bd9Sstevel@tonic-gate uint32_t fpras_chkresult[13]; 91*7c478bd9Sstevel@tonic-gate uint32_t fpras_trampoline[3]; 92*7c478bd9Sstevel@tonic-gate }; 93*7c478bd9Sstevel@tonic-gate 94*7c478bd9Sstevel@tonic-gate /* 95*7c478bd9Sstevel@tonic-gate * Check function constructed to match a struct fpras_chkfn 96*7c478bd9Sstevel@tonic-gate */ 97*7c478bd9Sstevel@tonic-gate extern int fpras_chkfn_type1(void); 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate /* 100*7c478bd9Sstevel@tonic-gate * A group of check functions, one for each operation type. These will 101*7c478bd9Sstevel@tonic-gate * be the check functions for copy operations on a particular processor. 102*7c478bd9Sstevel@tonic-gate */ 103*7c478bd9Sstevel@tonic-gate struct fpras_chkfngrp { 104*7c478bd9Sstevel@tonic-gate struct fpras_chkfn fpras_fn[FPRAS_NCOPYOPS]; 105*7c478bd9Sstevel@tonic-gate }; 106*7c478bd9Sstevel@tonic-gate 107*7c478bd9Sstevel@tonic-gate /* 108*7c478bd9Sstevel@tonic-gate * Where we store check functions for execution. Indexed by cpuid and 109*7c478bd9Sstevel@tonic-gate * function within that for cacheline friendliness. Startup code 110*7c478bd9Sstevel@tonic-gate * copies the check function into this array. The fpRAS mechanism will 111*7c478bd9Sstevel@tonic-gate * rewrite one of fpras_blk0 or fpras_blk1 before calling the check function 112*7c478bd9Sstevel@tonic-gate * for a cpuid & copy function combination. 113*7c478bd9Sstevel@tonic-gate */ 114*7c478bd9Sstevel@tonic-gate extern struct fpras_chkfngrp *fpras_chkfngrps; 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate #endif /* !_ASM */ 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate #if defined(_ASM) 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate /* BEGIN CSTYLED */ 121*7c478bd9Sstevel@tonic-gate 122*7c478bd9Sstevel@tonic-gate /* 123*7c478bd9Sstevel@tonic-gate * The INTERVAL macro decides whether we will check this copy operation, 124*7c478bd9Sstevel@tonic-gate * based on performing no more than 1 check per cpu & operation in a specified 125*7c478bd9Sstevel@tonic-gate * time interval. If it decides to abort this check (ie, we have checked 126*7c478bd9Sstevel@tonic-gate * recently) then it returns doex NULL, otherwise doex is the address of the 127*7c478bd9Sstevel@tonic-gate * check function to execute later. Migration must have been prevented before 128*7c478bd9Sstevel@tonic-gate * calling this macro. Args: 129*7c478bd9Sstevel@tonic-gate * 130*7c478bd9Sstevel@tonic-gate * operation (immediate): one of FPRAS_BCOPY etc 131*7c478bd9Sstevel@tonic-gate * blk (immediate): which block to copy 132*7c478bd9Sstevel@tonic-gate * doex (register): register in which to return check function address 133*7c478bd9Sstevel@tonic-gate * tmp1 (register): used for scratch, not preserved 134*7c478bd9Sstevel@tonic-gate * tmp2 (register): used for scratch, not preserved 135*7c478bd9Sstevel@tonic-gate * tmp3 (register): used for scratch, not preserved 136*7c478bd9Sstevel@tonic-gate * tmp4 (register): used for scratch, not preserved 137*7c478bd9Sstevel@tonic-gate * label: free local numeric label 138*7c478bd9Sstevel@tonic-gate */ 139*7c478bd9Sstevel@tonic-gate 140*7c478bd9Sstevel@tonic-gate #define FPRAS_INTERVAL(operation, blk, doex, tmp1, tmp2, tmp3, tmp4, label) \ 141*7c478bd9Sstevel@tonic-gate sethi %hi(fpras_interval), tmp1 ;\ 142*7c478bd9Sstevel@tonic-gate ldx [tmp1 + %lo(fpras_interval)], tmp1 ;\ 143*7c478bd9Sstevel@tonic-gate brlz,pn tmp1, label/**/f /* not initialized? */ ;\ 144*7c478bd9Sstevel@tonic-gate clr doex ;\ 145*7c478bd9Sstevel@tonic-gate sethi %hi(fpras_disableids), tmp2 ;\ 146*7c478bd9Sstevel@tonic-gate ld [tmp2 + %lo(fpras_disableids)], tmp2 ;\ 147*7c478bd9Sstevel@tonic-gate mov 0x1, tmp3 ;\ 148*7c478bd9Sstevel@tonic-gate sll tmp3, operation, tmp3 ;\ 149*7c478bd9Sstevel@tonic-gate btst tmp3, tmp2 ;\ 150*7c478bd9Sstevel@tonic-gate bnz,a,pn %icc, label/**/f /* disabled for this op? */ ;\ 151*7c478bd9Sstevel@tonic-gate nop ;\ 152*7c478bd9Sstevel@tonic-gate set fpras_chkfn_type1, tmp2 ;\ 153*7c478bd9Sstevel@tonic-gate prefetch [tmp2 + (FPRAS_BLK0 + blk * 64)], #one_read ;\ 154*7c478bd9Sstevel@tonic-gate ldn [THREAD_REG + T_CPU], tmp2 ;\ 155*7c478bd9Sstevel@tonic-gate ldn [tmp2 + CPU_PRIVATE], tmp2 ;\ 156*7c478bd9Sstevel@tonic-gate brz,pn tmp2, label/**/f /* early in startup? */ ;\ 157*7c478bd9Sstevel@tonic-gate mov operation, tmp3 ;\ 158*7c478bd9Sstevel@tonic-gate sll tmp3, 3, tmp3 ;\ 159*7c478bd9Sstevel@tonic-gate set CHPR_FPRAS_TIMESTAMP, tmp4 ;\ 160*7c478bd9Sstevel@tonic-gate add tmp2, tmp4, tmp2 ;\ 161*7c478bd9Sstevel@tonic-gate add tmp2, tmp3, tmp2 /* keep ptr for update */ ;\ 162*7c478bd9Sstevel@tonic-gate ldx [tmp2], tmp3 /* last timestamp */ ;\ 163*7c478bd9Sstevel@tonic-gate rd STICK, doex /* doex is a scratch here */ ;\ 164*7c478bd9Sstevel@tonic-gate sub doex, tmp3, tmp4 /* delta since last check */ ;\ 165*7c478bd9Sstevel@tonic-gate cmp tmp4, tmp1 /* compare delta to interval */ ;\ 166*7c478bd9Sstevel@tonic-gate blu,a,pn %xcc, label/**/f ;\ 167*7c478bd9Sstevel@tonic-gate clr doex ;\ 168*7c478bd9Sstevel@tonic-gate stx doex, [tmp2] /* updated timestamp */ ;\ 169*7c478bd9Sstevel@tonic-gate ldn [THREAD_REG + T_CPU], tmp1 ;\ 170*7c478bd9Sstevel@tonic-gate ld [tmp1 + CPU_ID], tmp1 ;\ 171*7c478bd9Sstevel@tonic-gate sethi %hi(fpras_chkfngrps), doex ;\ 172*7c478bd9Sstevel@tonic-gate ldn [doex + %lo(fpras_chkfngrps)], doex ;\ 173*7c478bd9Sstevel@tonic-gate sll tmp1, FPRAS_CHKFNGRP_SIZE_SHIFT, tmp1 ;\ 174*7c478bd9Sstevel@tonic-gate add doex, tmp1, doex ;\ 175*7c478bd9Sstevel@tonic-gate mov operation, tmp1 ;\ 176*7c478bd9Sstevel@tonic-gate sll tmp1, FPRAS_CHKFN_SIZE_SHIFT, tmp1 ;\ 177*7c478bd9Sstevel@tonic-gate add doex, tmp1, doex /* address of check function */ ;\ 178*7c478bd9Sstevel@tonic-gate label: 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate /* 181*7c478bd9Sstevel@tonic-gate * The REWRITE macro copies an instruction block from fpras_chkfn_type1 182*7c478bd9Sstevel@tonic-gate * into a per-cpu fpras check function. 183*7c478bd9Sstevel@tonic-gate * If doex is NULL it must not attempt any copy, and must leave doex NULL. 184*7c478bd9Sstevel@tonic-gate * CPU migration of this thread must be prevented before we call this macro. 185*7c478bd9Sstevel@tonic-gate * We must have checked for fp in use (and saved state, including the 186*7c478bd9Sstevel@tonic-gate * quadrant of registers indicated by the fpq argument and fp enabled before 187*7c478bd9Sstevel@tonic-gate * using this macro. Args: 188*7c478bd9Sstevel@tonic-gate * 189*7c478bd9Sstevel@tonic-gate * blk (immediate): as above 190*7c478bd9Sstevel@tonic-gate * doex (register): register in which to return check function addr 191*7c478bd9Sstevel@tonic-gate * [fpq (fp register): frf quadrant to be used (%f0/%f16/%f32/%f48)] 192*7c478bd9Sstevel@tonic-gate * This is used on type 1 rewrite only - on others the 193*7c478bd9Sstevel@tonic-gate * quadrant is implicit/hardcoded in the macro name. 194*7c478bd9Sstevel@tonic-gate * tmp1 (register): used for scratch, not preserved 195*7c478bd9Sstevel@tonic-gate * label1: free local numeric label 196*7c478bd9Sstevel@tonic-gate * [label2: free local numeric label] 197*7c478bd9Sstevel@tonic-gate * This is used in type 2 only. 198*7c478bd9Sstevel@tonic-gate * 199*7c478bd9Sstevel@tonic-gate * Note that the REWRITE macros do not perform a flush instruction - 200*7c478bd9Sstevel@tonic-gate * flush is not necessary on Cheetah derivative processors in which 201*7c478bd9Sstevel@tonic-gate * i$ snoops for invalidations. 202*7c478bd9Sstevel@tonic-gate */ 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate /* 205*7c478bd9Sstevel@tonic-gate * Rewrite type 1 will work with any instruction pattern - it just block 206*7c478bd9Sstevel@tonic-gate * loads and block stores the given block. A membar after block store 207*7c478bd9Sstevel@tonic-gate * forces the block store to complete before upcoming reuse of the 208*7c478bd9Sstevel@tonic-gate * fpregs in the block; the block load is blocking on sun4u/cheetah 209*7c478bd9Sstevel@tonic-gate * so no need for a membar after it. 210*7c478bd9Sstevel@tonic-gate */ 211*7c478bd9Sstevel@tonic-gate 212*7c478bd9Sstevel@tonic-gate #define FPRAS_REWRITE_TYPE1(blk, doex, fpq, tmp1, label) \ 213*7c478bd9Sstevel@tonic-gate brz,pn doex, label/**/f ;\ 214*7c478bd9Sstevel@tonic-gate sethi %hi(fpras_chkfn_type1), tmp1 ;\ 215*7c478bd9Sstevel@tonic-gate add tmp1, %lo(fpras_chkfn_type1), tmp1 ;\ 216*7c478bd9Sstevel@tonic-gate add tmp1, FPRAS_BLK0 + blk * 64, tmp1 ;\ 217*7c478bd9Sstevel@tonic-gate ldda [tmp1]ASI_BLK_P, fpq ;\ 218*7c478bd9Sstevel@tonic-gate add doex, FPRAS_BLK0 + blk * 64, tmp1 ;\ 219*7c478bd9Sstevel@tonic-gate stda fpq, [tmp1]ASI_BLK_P ;\ 220*7c478bd9Sstevel@tonic-gate membar #Sync ;\ 221*7c478bd9Sstevel@tonic-gate label: 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate /* 224*7c478bd9Sstevel@tonic-gate * Rewrite type 2 will only work with instruction blocks that satisfy 225*7c478bd9Sstevel@tonic-gate * this particular repeat pattern. Note that the frf quadrant to 226*7c478bd9Sstevel@tonic-gate * use is implicit in the macro name and had better match what the 227*7c478bd9Sstevel@tonic-gate * copy function is preserving. 228*7c478bd9Sstevel@tonic-gate * 229*7c478bd9Sstevel@tonic-gate * The odd looking repetition in the initial loop is designed to open 230*7c478bd9Sstevel@tonic-gate * up boths paths from prefetch cache to the frf - unrolling the loop 231*7c478bd9Sstevel@tonic-gate * would defeat this. In addition we perform idempotent faligndata 232*7c478bd9Sstevel@tonic-gate * manipulations using %tick as a randomly aligned address (this only 233*7c478bd9Sstevel@tonic-gate * works for address that aren't doubleword aligned). 234*7c478bd9Sstevel@tonic-gate */ 235*7c478bd9Sstevel@tonic-gate #define FPRAS_REWRITE_TYPE2Q1(blk, doex, tmp1, tmp2, label1, label2) \ 236*7c478bd9Sstevel@tonic-gate brz,pn doex, label1/**/f ;\ 237*7c478bd9Sstevel@tonic-gate mov 0x2, tmp1 ;\ 238*7c478bd9Sstevel@tonic-gate set fpras_chkfn_type1, tmp2 ;\ 239*7c478bd9Sstevel@tonic-gate label2: ;\ 240*7c478bd9Sstevel@tonic-gate deccc tmp1 ;\ 241*7c478bd9Sstevel@tonic-gate ldd [tmp2 + (FPRAS_BLK0 + blk * 64)], %f4 ;\ 242*7c478bd9Sstevel@tonic-gate ldd [tmp2 + (FPRAS_BLK0 + blk * 64) + 8], %f2 ;\ 243*7c478bd9Sstevel@tonic-gate bnz,a,pt %icc, label2/**/b ;\ 244*7c478bd9Sstevel@tonic-gate fsrc1 %f4, %f0 ;\ 245*7c478bd9Sstevel@tonic-gate rdpr %tick, tmp1 ;\ 246*7c478bd9Sstevel@tonic-gate fsrc1 %f4, %f8 ;\ 247*7c478bd9Sstevel@tonic-gate fsrc1 %f2, %f10 ;\ 248*7c478bd9Sstevel@tonic-gate btst 0x7, tmp1 ;\ 249*7c478bd9Sstevel@tonic-gate alignaddr tmp1, %g0, %g0 /* changes %gsr */ ;\ 250*7c478bd9Sstevel@tonic-gate bz,pn %icc, label2/**/f ;\ 251*7c478bd9Sstevel@tonic-gate faligndata %f2, %f4, %f6 ;\ 252*7c478bd9Sstevel@tonic-gate faligndata %f0, %f2, %f12 ;\ 253*7c478bd9Sstevel@tonic-gate alignaddrl tmp1, %g0, %g0 ;\ 254*7c478bd9Sstevel@tonic-gate faligndata %f12, %f6, %f6 ;\ 255*7c478bd9Sstevel@tonic-gate label2: ;\ 256*7c478bd9Sstevel@tonic-gate add doex, FPRAS_BLK0 + blk * 64, tmp1 ;\ 257*7c478bd9Sstevel@tonic-gate fsrc2 %f8, %f12 ;\ 258*7c478bd9Sstevel@tonic-gate fsrc1 %f6, %f14 ;\ 259*7c478bd9Sstevel@tonic-gate stda %f0, [tmp1]ASI_BLK_P ;\ 260*7c478bd9Sstevel@tonic-gate membar #Sync ;\ 261*7c478bd9Sstevel@tonic-gate label1: 262*7c478bd9Sstevel@tonic-gate 263*7c478bd9Sstevel@tonic-gate #define FPRAS_REWRITE_TYPE2Q2(blk, doex, tmp1, tmp2, label1, label2) \ 264*7c478bd9Sstevel@tonic-gate brz,pn doex, label1/**/f ;\ 265*7c478bd9Sstevel@tonic-gate mov 0x2, tmp1 ;\ 266*7c478bd9Sstevel@tonic-gate set fpras_chkfn_type1, tmp2 ;\ 267*7c478bd9Sstevel@tonic-gate label2: ;\ 268*7c478bd9Sstevel@tonic-gate deccc tmp1 ;\ 269*7c478bd9Sstevel@tonic-gate ldd [tmp2 + (FPRAS_BLK0 + blk * 64)], %f20 ;\ 270*7c478bd9Sstevel@tonic-gate ldd [tmp2 + (FPRAS_BLK0 + blk * 64) + 8], %f18 ;\ 271*7c478bd9Sstevel@tonic-gate bnz,a,pt %icc, label2/**/b ;\ 272*7c478bd9Sstevel@tonic-gate fsrc1 %f20, %f16 ;\ 273*7c478bd9Sstevel@tonic-gate rdpr %tick, tmp1 ;\ 274*7c478bd9Sstevel@tonic-gate fsrc1 %f20, %f24 ;\ 275*7c478bd9Sstevel@tonic-gate fsrc1 %f18, %f26 ;\ 276*7c478bd9Sstevel@tonic-gate btst 0x7, tmp1 ;\ 277*7c478bd9Sstevel@tonic-gate alignaddr tmp1, %g0, %g0 /* changes %gsr */ ;\ 278*7c478bd9Sstevel@tonic-gate bz,pn %icc, label2/**/f ;\ 279*7c478bd9Sstevel@tonic-gate faligndata %f18, %f20, %f22 ;\ 280*7c478bd9Sstevel@tonic-gate faligndata %f16, %f18, %f28 ;\ 281*7c478bd9Sstevel@tonic-gate alignaddrl tmp1, %g0, %g0 ;\ 282*7c478bd9Sstevel@tonic-gate faligndata %f28, %f22, %f22 ;\ 283*7c478bd9Sstevel@tonic-gate label2: ;\ 284*7c478bd9Sstevel@tonic-gate add doex, FPRAS_BLK0 + blk * 64, tmp1 ;\ 285*7c478bd9Sstevel@tonic-gate fsrc2 %f24, %f28 ;\ 286*7c478bd9Sstevel@tonic-gate fsrc1 %f22, %f30 ;\ 287*7c478bd9Sstevel@tonic-gate stda %f16, [tmp1]ASI_BLK_P ;\ 288*7c478bd9Sstevel@tonic-gate membar #Sync ;\ 289*7c478bd9Sstevel@tonic-gate label1: 290*7c478bd9Sstevel@tonic-gate 291*7c478bd9Sstevel@tonic-gate /* 292*7c478bd9Sstevel@tonic-gate * The CHECK macro takes the 'doex' address of the check function to 293*7c478bd9Sstevel@tonic-gate * execute and jumps to it (if not NULL). If the check function returns 294*7c478bd9Sstevel@tonic-gate * nonzero then the check has failed and the CHECK macro must initiate 295*7c478bd9Sstevel@tonic-gate * an appropriate failure action. Illegal instruction trap handlers 296*7c478bd9Sstevel@tonic-gate * will also recognise traps in this PC range as fp failures. Thread 297*7c478bd9Sstevel@tonic-gate * migration must only be reallowed after completion of this check. The 298*7c478bd9Sstevel@tonic-gate * CHECK macro should be treated as a CALL/JMPL - output registers are 299*7c478bd9Sstevel@tonic-gate * forfeit after using it. If the call to fpras_failure returns 300*7c478bd9Sstevel@tonic-gate * (it may decide to panic) then invoke lofault handler (which must exist) 301*7c478bd9Sstevel@tonic-gate * to return an error (be sure to use this macro before restoring original 302*7c478bd9Sstevel@tonic-gate * lofault setup in copy functions). Note that the lofault handler is the 303*7c478bd9Sstevel@tonic-gate * copyops aware proxy handler which will perform other tidy up operations 304*7c478bd9Sstevel@tonic-gate * (unbind, fp state restore) that would normally have been done in the tail 305*7c478bd9Sstevel@tonic-gate * of the copy function. 306*7c478bd9Sstevel@tonic-gate * 307*7c478bd9Sstevel@tonic-gate * operation (immedidate): as above 308*7c478bd9Sstevel@tonic-gate * doex (register): doex value returned from the REWRITE 309*7c478bd9Sstevel@tonic-gate * label: free local numeric label 310*7c478bd9Sstevel@tonic-gate */ 311*7c478bd9Sstevel@tonic-gate 312*7c478bd9Sstevel@tonic-gate #define FPRAS_CHECK(operation, doex, label) \ 313*7c478bd9Sstevel@tonic-gate brz,pn doex, label/**/f ;\ 314*7c478bd9Sstevel@tonic-gate nop ;\ 315*7c478bd9Sstevel@tonic-gate jmpl doex, %o7 ;\ 316*7c478bd9Sstevel@tonic-gate nop ;\ 317*7c478bd9Sstevel@tonic-gate cmp %o0, FPRAS_OK ;\ 318*7c478bd9Sstevel@tonic-gate be %icc, label/**/f ;\ 319*7c478bd9Sstevel@tonic-gate nop ;\ 320*7c478bd9Sstevel@tonic-gate mov %o0, %o1 /* how detected */ ;\ 321*7c478bd9Sstevel@tonic-gate call fpras_failure /* take failure action */ ;\ 322*7c478bd9Sstevel@tonic-gate mov operation, %o0 ;\ 323*7c478bd9Sstevel@tonic-gate ldn [THREAD_REG + T_LOFAULT], doex ;\ 324*7c478bd9Sstevel@tonic-gate jmp doex ;\ 325*7c478bd9Sstevel@tonic-gate mov EFAULT, %g1 ;\ 326*7c478bd9Sstevel@tonic-gate label: 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate /* END CSTYLED */ 329*7c478bd9Sstevel@tonic-gate 330*7c478bd9Sstevel@tonic-gate #endif /* _ASM */ 331*7c478bd9Sstevel@tonic-gate 332*7c478bd9Sstevel@tonic-gate #ifdef __cplusplus 333*7c478bd9Sstevel@tonic-gate } 334*7c478bd9Sstevel@tonic-gate #endif 335*7c478bd9Sstevel@tonic-gate 336*7c478bd9Sstevel@tonic-gate #endif /* _SYS_FPRAS_IMPL_H */ 337