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 #ifndef _CHEETAHASM_H 28*7c478bd9Sstevel@tonic-gate #define _CHEETAHASM_H 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 31*7c478bd9Sstevel@tonic-gate 32*7c478bd9Sstevel@tonic-gate #ifdef __cplusplus 33*7c478bd9Sstevel@tonic-gate extern "C" { 34*7c478bd9Sstevel@tonic-gate #endif 35*7c478bd9Sstevel@tonic-gate 36*7c478bd9Sstevel@tonic-gate #ifdef _ASM 37*7c478bd9Sstevel@tonic-gate /* BEGIN CSTYLED */ 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate #define ASM_LD(reg, symbol) \ 40*7c478bd9Sstevel@tonic-gate sethi %hi(symbol), reg; \ 41*7c478bd9Sstevel@tonic-gate ld [reg + %lo(symbol)], reg; \ 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate #define ASM_LDX(reg, symbol) \ 44*7c478bd9Sstevel@tonic-gate sethi %hi(symbol), reg; \ 45*7c478bd9Sstevel@tonic-gate ldx [reg + %lo(symbol)], reg; \ 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate #define ASM_JMP(reg, symbol) \ 48*7c478bd9Sstevel@tonic-gate sethi %hi(symbol), reg; \ 49*7c478bd9Sstevel@tonic-gate jmp reg + %lo(symbol); \ 50*7c478bd9Sstevel@tonic-gate nop 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate /* 53*7c478bd9Sstevel@tonic-gate * Macro for getting to offset from 'cpu_private' ptr. The 'cpu_private' 54*7c478bd9Sstevel@tonic-gate * ptr is in the machcpu structure. 55*7c478bd9Sstevel@tonic-gate * off_reg: Register offset from 'cpu_private' ptr. 56*7c478bd9Sstevel@tonic-gate * scr1: Scratch, ptr is returned in this register. 57*7c478bd9Sstevel@tonic-gate * scr2: Scratch 58*7c478bd9Sstevel@tonic-gate * label: Label to branch to if cpu_private ptr is null/zero. 59*7c478bd9Sstevel@tonic-gate */ 60*7c478bd9Sstevel@tonic-gate #define GET_CPU_PRIVATE_PTR(off_reg, scr1, scr2, label) \ 61*7c478bd9Sstevel@tonic-gate CPU_ADDR(scr1, scr2); \ 62*7c478bd9Sstevel@tonic-gate ldn [scr1 + CPU_PRIVATE], scr1; \ 63*7c478bd9Sstevel@tonic-gate cmp scr1, 0; \ 64*7c478bd9Sstevel@tonic-gate be label; \ 65*7c478bd9Sstevel@tonic-gate nop; \ 66*7c478bd9Sstevel@tonic-gate add scr1, off_reg, scr1 67*7c478bd9Sstevel@tonic-gate 68*7c478bd9Sstevel@tonic-gate /* 69*7c478bd9Sstevel@tonic-gate * Macro version of get_dcache_dtag. We use this macro in the 70*7c478bd9Sstevel@tonic-gate * CPU logout code. Since the Dcache is virtually indexed, only 71*7c478bd9Sstevel@tonic-gate * bits [12:5] of the AFAR can be used so we need to search through 72*7c478bd9Sstevel@tonic-gate * 8 indexes (4 ways + bit 13) in order to find the tag we want. 73*7c478bd9Sstevel@tonic-gate * afar: input AFAR, not modified. 74*7c478bd9Sstevel@tonic-gate * datap: input ptr to ch_dc_data_t, at end pts to end of ch_dc_data_t. 75*7c478bd9Sstevel@tonic-gate * scr1: scratch. 76*7c478bd9Sstevel@tonic-gate * scr2: scratch, will hold tag to look for. 77*7c478bd9Sstevel@tonic-gate * scr3: used for Dcache index, loops through 4 ways. 78*7c478bd9Sstevel@tonic-gate */ 79*7c478bd9Sstevel@tonic-gate #define GET_DCACHE_DTAG(afar, datap, scr1, scr2, scr3) \ 80*7c478bd9Sstevel@tonic-gate set CH_DCACHE_IDX_MASK, scr3; \ 81*7c478bd9Sstevel@tonic-gate and afar, scr3, scr3; \ 82*7c478bd9Sstevel@tonic-gate srlx afar, CH_DCTAG_PA_SHIFT, scr2; \ 83*7c478bd9Sstevel@tonic-gate b 1f; \ 84*7c478bd9Sstevel@tonic-gate or scr2, CH_DCTAG_VALID_BIT, scr2; /* tag we want */ \ 85*7c478bd9Sstevel@tonic-gate .align 128; \ 86*7c478bd9Sstevel@tonic-gate 1: \ 87*7c478bd9Sstevel@tonic-gate ldxa [scr3]ASI_DC_TAG, scr1; /* read tag */ \ 88*7c478bd9Sstevel@tonic-gate cmp scr1, scr2; \ 89*7c478bd9Sstevel@tonic-gate bne 4f; /* not found? */ \ 90*7c478bd9Sstevel@tonic-gate nop; \ 91*7c478bd9Sstevel@tonic-gate stxa scr3, [datap + CH_DC_IDX]%asi; /* store index */ \ 92*7c478bd9Sstevel@tonic-gate stxa scr1, [datap + CH_DC_TAG]%asi; /* store tag */ \ 93*7c478bd9Sstevel@tonic-gate membar #Sync; /* Cheetah PRM 10.6.3 */ \ 94*7c478bd9Sstevel@tonic-gate ldxa [scr3]ASI_DC_UTAG, scr1; /* read utag */ \ 95*7c478bd9Sstevel@tonic-gate membar #Sync; /* Cheetah PRM 10.6.3 */ \ 96*7c478bd9Sstevel@tonic-gate stxa scr1, [datap + CH_DC_UTAG]%asi; \ 97*7c478bd9Sstevel@tonic-gate ldxa [scr3]ASI_DC_SNP_TAG, scr1; /* read snoop tag */ \ 98*7c478bd9Sstevel@tonic-gate stxa scr1, [datap + CH_DC_SNTAG]%asi; \ 99*7c478bd9Sstevel@tonic-gate add datap, CH_DC_DATA, datap; \ 100*7c478bd9Sstevel@tonic-gate clr scr2; \ 101*7c478bd9Sstevel@tonic-gate 2: \ 102*7c478bd9Sstevel@tonic-gate membar #Sync; /* Cheetah PRM 10.6.1 */ \ 103*7c478bd9Sstevel@tonic-gate ldxa [scr3 + scr2]ASI_DC_DATA, scr1; /* read data */ \ 104*7c478bd9Sstevel@tonic-gate membar #Sync; /* Cheetah PRM 10.6.1 */ \ 105*7c478bd9Sstevel@tonic-gate stxa scr1, [datap]%asi; \ 106*7c478bd9Sstevel@tonic-gate add datap, 8, datap; \ 107*7c478bd9Sstevel@tonic-gate cmp scr2, CH_DC_DATA_REG_SIZE - 8; \ 108*7c478bd9Sstevel@tonic-gate blt 2b; \ 109*7c478bd9Sstevel@tonic-gate add scr2, 8, scr2; \ 110*7c478bd9Sstevel@tonic-gate \ 111*7c478bd9Sstevel@tonic-gate GET_CPU_IMPL(scr2); /* Parity bits are elsewhere for */ \ 112*7c478bd9Sstevel@tonic-gate cmp scr2, PANTHER_IMPL; /* panther processors. */ \ 113*7c478bd9Sstevel@tonic-gate bne,a 5f; /* Done if not panther. */ \ 114*7c478bd9Sstevel@tonic-gate add datap, 8, datap; /* Skip to the end of the struct. */ \ 115*7c478bd9Sstevel@tonic-gate clr scr2; \ 116*7c478bd9Sstevel@tonic-gate add datap, 7, datap; /* offset of the last parity byte */ \ 117*7c478bd9Sstevel@tonic-gate mov 1, scr1; \ 118*7c478bd9Sstevel@tonic-gate sll scr1, PN_DC_DATA_PARITY_BIT_SHIFT, scr1; \ 119*7c478bd9Sstevel@tonic-gate or scr3, scr1, scr3; /* add DC_data_parity bit to index */ \ 120*7c478bd9Sstevel@tonic-gate 3: \ 121*7c478bd9Sstevel@tonic-gate membar #Sync; /* Cheetah PRM 10.6.1 */ \ 122*7c478bd9Sstevel@tonic-gate ldxa [scr3 + scr2]ASI_DC_DATA, scr1; /* read parity bits */ \ 123*7c478bd9Sstevel@tonic-gate membar #Sync; /* Cheetah PRM 10.6.1 */ \ 124*7c478bd9Sstevel@tonic-gate stba scr1, [datap]%asi; \ 125*7c478bd9Sstevel@tonic-gate dec datap; \ 126*7c478bd9Sstevel@tonic-gate cmp scr2, CH_DC_DATA_REG_SIZE - 8; \ 127*7c478bd9Sstevel@tonic-gate blt 3b; \ 128*7c478bd9Sstevel@tonic-gate add scr2, 8, scr2; \ 129*7c478bd9Sstevel@tonic-gate b 5f; \ 130*7c478bd9Sstevel@tonic-gate add datap, 5, datap; /* set pointer to end of our struct */ \ 131*7c478bd9Sstevel@tonic-gate 4: \ 132*7c478bd9Sstevel@tonic-gate set CH_DCACHE_IDX_INCR, scr1; /* incr. idx (scr3) */ \ 133*7c478bd9Sstevel@tonic-gate add scr3, scr1, scr3; \ 134*7c478bd9Sstevel@tonic-gate set CH_DCACHE_IDX_LIMIT, scr1; /* done? */ \ 135*7c478bd9Sstevel@tonic-gate cmp scr3, scr1; \ 136*7c478bd9Sstevel@tonic-gate blt 1b; \ 137*7c478bd9Sstevel@tonic-gate nop; \ 138*7c478bd9Sstevel@tonic-gate add datap, CH_DC_DATA_SIZE, datap; \ 139*7c478bd9Sstevel@tonic-gate 5: 140*7c478bd9Sstevel@tonic-gate 141*7c478bd9Sstevel@tonic-gate /* 142*7c478bd9Sstevel@tonic-gate * Macro version of get_icache_dtag. We use this macro in the CPU 143*7c478bd9Sstevel@tonic-gate * logout code. If the Icache is on, we don't want to capture the data. 144*7c478bd9Sstevel@tonic-gate * afar: input AFAR, not modified. 145*7c478bd9Sstevel@tonic-gate * datap: input ptr to ch_ic_data_t, at end pts to end of ch_ic_data_t. 146*7c478bd9Sstevel@tonic-gate * scr1: scratch. 147*7c478bd9Sstevel@tonic-gate * scr2: scratch, will hold tag to look for. 148*7c478bd9Sstevel@tonic-gate * scr3: used for Icache index, loops through 4 ways. 149*7c478bd9Sstevel@tonic-gate * Note: For Panther, the Icache is virtually indexed and increases in 150*7c478bd9Sstevel@tonic-gate * size to 64KB (instead of 32KB) with a line size of 64 bytes (instead 151*7c478bd9Sstevel@tonic-gate * of 32). This means the IC_addr index bits[14:7] for Panther now 152*7c478bd9Sstevel@tonic-gate * correspond to VA bits[13:6]. But since it is virtually indexed, we 153*7c478bd9Sstevel@tonic-gate * still mask out only bits[12:5] from the AFAR (we have to manually 154*7c478bd9Sstevel@tonic-gate * check bit 13). In order to make this code work for all processors, 155*7c478bd9Sstevel@tonic-gate * we end up checking twice as many indexes (8 instead of 4) as required 156*7c478bd9Sstevel@tonic-gate * for non-Panther CPUs and saving off twice as much data (16 instructions 157*7c478bd9Sstevel@tonic-gate * instead of just 8). 158*7c478bd9Sstevel@tonic-gate */ 159*7c478bd9Sstevel@tonic-gate #define GET_ICACHE_DTAG(afar, datap, scr1, scr2, scr3) \ 160*7c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_DCU, scr1; \ 161*7c478bd9Sstevel@tonic-gate btst DCU_IC, scr1; /* is Icache enabled? */ \ 162*7c478bd9Sstevel@tonic-gate bne,a 6f; /* yes, don't capture */ \ 163*7c478bd9Sstevel@tonic-gate add datap, CH_IC_DATA_SIZE, datap; /* anul if no branch */ \ 164*7c478bd9Sstevel@tonic-gate GET_CPU_IMPL(scr2); /* Panther only uses VA[13:6] */ \ 165*7c478bd9Sstevel@tonic-gate cmp scr2, PANTHER_IMPL; /* and we also want to mask */ \ 166*7c478bd9Sstevel@tonic-gate be 1f; /* out bit 13 since the */ \ 167*7c478bd9Sstevel@tonic-gate nop; /* Panther I$ is VIPT. */ \ 168*7c478bd9Sstevel@tonic-gate set CH_ICACHE_IDX_MASK, scr3; \ 169*7c478bd9Sstevel@tonic-gate b 2f; \ 170*7c478bd9Sstevel@tonic-gate nop; \ 171*7c478bd9Sstevel@tonic-gate 1: \ 172*7c478bd9Sstevel@tonic-gate set PN_ICACHE_VA_IDX_MASK, scr3; \ 173*7c478bd9Sstevel@tonic-gate 2: \ 174*7c478bd9Sstevel@tonic-gate and afar, scr3, scr3; \ 175*7c478bd9Sstevel@tonic-gate sllx scr3, CH_ICACHE_IDX_SHIFT, scr3; \ 176*7c478bd9Sstevel@tonic-gate srlx afar, CH_ICPATAG_SHIFT, scr2; /* pa tag we want */ \ 177*7c478bd9Sstevel@tonic-gate andn scr2, CH_ICPATAG_LBITS, scr2; /* mask off lower */ \ 178*7c478bd9Sstevel@tonic-gate b 3f; \ 179*7c478bd9Sstevel@tonic-gate nop; \ 180*7c478bd9Sstevel@tonic-gate .align 128; \ 181*7c478bd9Sstevel@tonic-gate 3: \ 182*7c478bd9Sstevel@tonic-gate ldxa [scr3]ASI_IC_TAG, scr1; /* read pa tag */ \ 183*7c478bd9Sstevel@tonic-gate andn scr1, CH_ICPATAG_LBITS, scr1; /* mask off lower */ \ 184*7c478bd9Sstevel@tonic-gate cmp scr1, scr2; \ 185*7c478bd9Sstevel@tonic-gate bne 5f; /* not found? */ \ 186*7c478bd9Sstevel@tonic-gate nop; \ 187*7c478bd9Sstevel@tonic-gate stxa scr3, [datap + CH_IC_IDX]%asi; /* store index */ \ 188*7c478bd9Sstevel@tonic-gate stxa scr1, [datap + CH_IC_PATAG]%asi; /* store pa tag */ \ 189*7c478bd9Sstevel@tonic-gate add scr3, CH_ICTAG_UTAG, scr3; /* read utag */ \ 190*7c478bd9Sstevel@tonic-gate ldxa [scr3]ASI_IC_TAG, scr1; \ 191*7c478bd9Sstevel@tonic-gate add scr3, (CH_ICTAG_UPPER - CH_ICTAG_UTAG), scr3; \ 192*7c478bd9Sstevel@tonic-gate stxa scr1, [datap + CH_IC_UTAG]%asi; \ 193*7c478bd9Sstevel@tonic-gate ldxa [scr3]ASI_IC_TAG, scr1; /* read upper tag */ \ 194*7c478bd9Sstevel@tonic-gate add scr3, (CH_ICTAG_LOWER - CH_ICTAG_UPPER), scr3; \ 195*7c478bd9Sstevel@tonic-gate stxa scr1, [datap + CH_IC_UPPER]%asi; \ 196*7c478bd9Sstevel@tonic-gate ldxa [scr3]ASI_IC_TAG, scr1; /* read lower tag */ \ 197*7c478bd9Sstevel@tonic-gate andn scr3, CH_ICTAG_TMASK, scr3; \ 198*7c478bd9Sstevel@tonic-gate stxa scr1, [datap + CH_IC_LOWER]%asi; \ 199*7c478bd9Sstevel@tonic-gate ldxa [scr3]ASI_IC_SNP_TAG, scr1; /* read snoop tag */ \ 200*7c478bd9Sstevel@tonic-gate stxa scr1, [datap + CH_IC_SNTAG]%asi; \ 201*7c478bd9Sstevel@tonic-gate add datap, CH_IC_DATA, datap; \ 202*7c478bd9Sstevel@tonic-gate clr scr2; \ 203*7c478bd9Sstevel@tonic-gate 4: \ 204*7c478bd9Sstevel@tonic-gate ldxa [scr3 + scr2]ASI_IC_DATA, scr1; /* read ins. data */ \ 205*7c478bd9Sstevel@tonic-gate stxa scr1, [datap]%asi; \ 206*7c478bd9Sstevel@tonic-gate add datap, 8, datap; \ 207*7c478bd9Sstevel@tonic-gate cmp scr2, PN_IC_DATA_REG_SIZE - 8; \ 208*7c478bd9Sstevel@tonic-gate blt 4b; \ 209*7c478bd9Sstevel@tonic-gate add scr2, 8, scr2; \ 210*7c478bd9Sstevel@tonic-gate b 6f; \ 211*7c478bd9Sstevel@tonic-gate nop; \ 212*7c478bd9Sstevel@tonic-gate 5: \ 213*7c478bd9Sstevel@tonic-gate set CH_ICACHE_IDX_INCR, scr1; /* incr. idx (scr3) */ \ 214*7c478bd9Sstevel@tonic-gate add scr3, scr1, scr3; \ 215*7c478bd9Sstevel@tonic-gate set PN_ICACHE_IDX_LIMIT, scr1; /* done? */ \ 216*7c478bd9Sstevel@tonic-gate cmp scr3, scr1; \ 217*7c478bd9Sstevel@tonic-gate blt 3b; \ 218*7c478bd9Sstevel@tonic-gate nop; \ 219*7c478bd9Sstevel@tonic-gate add datap, CH_IC_DATA_SIZE, datap; \ 220*7c478bd9Sstevel@tonic-gate 6: 221*7c478bd9Sstevel@tonic-gate 222*7c478bd9Sstevel@tonic-gate #if defined(JALAPENO) || defined(SERRANO) 223*7c478bd9Sstevel@tonic-gate /* 224*7c478bd9Sstevel@tonic-gate * Macro version of get_ecache_dtag. We use this macro in the 225*7c478bd9Sstevel@tonic-gate * CPU logout code. 226*7c478bd9Sstevel@tonic-gate * afar: input AFAR, not modified 227*7c478bd9Sstevel@tonic-gate * datap: Ptr to ch_ec_data_t, at end pts just past ch_ec_data_t. 228*7c478bd9Sstevel@tonic-gate * ec_way: Constant value (way number) 229*7c478bd9Sstevel@tonic-gate * scr1: Scratch 230*7c478bd9Sstevel@tonic-gate * scr2: Scratch. 231*7c478bd9Sstevel@tonic-gate * scr3: Scratch. 232*7c478bd9Sstevel@tonic-gate */ 233*7c478bd9Sstevel@tonic-gate #define GET_ECACHE_DTAG(afar, datap, ec_way, scr1, scr2, scr3) \ 234*7c478bd9Sstevel@tonic-gate mov ec_way, scr1; \ 235*7c478bd9Sstevel@tonic-gate and scr1, JP_ECACHE_NWAY - 1, scr1; /* mask E$ way bits */ \ 236*7c478bd9Sstevel@tonic-gate sllx scr1, JP_EC_TAG_DATA_WAY_SHIFT, scr1; \ 237*7c478bd9Sstevel@tonic-gate set ((JP_ECACHE_MAX_SIZE / JP_ECACHE_NWAY) - 1), scr2; \ 238*7c478bd9Sstevel@tonic-gate and afar, scr2, scr3; /* get set offset */ \ 239*7c478bd9Sstevel@tonic-gate andn scr3, (JP_ECACHE_MAX_LSIZE - 1), scr3; /* VA<5:0>=0 */ \ 240*7c478bd9Sstevel@tonic-gate or scr3, scr1, scr3; /* or WAY bits */ \ 241*7c478bd9Sstevel@tonic-gate b 1f; \ 242*7c478bd9Sstevel@tonic-gate stxa scr3, [datap + CH_EC_IDX]%asi; /* store E$ index */ \ 243*7c478bd9Sstevel@tonic-gate .align 64; \ 244*7c478bd9Sstevel@tonic-gate 1: \ 245*7c478bd9Sstevel@tonic-gate JP_EC_DIAG_ACCESS_MEMBAR; \ 246*7c478bd9Sstevel@tonic-gate ldxa [scr3]ASI_EC_DIAG, scr1; /* get E$ tag */ \ 247*7c478bd9Sstevel@tonic-gate JP_EC_DIAG_ACCESS_MEMBAR; \ 248*7c478bd9Sstevel@tonic-gate stxa scr1, [datap + CH_EC_TAG]%asi; \ 249*7c478bd9Sstevel@tonic-gate add datap, CH_EC_DATA, datap; \ 250*7c478bd9Sstevel@tonic-gate 2: \ 251*7c478bd9Sstevel@tonic-gate ldxa [scr3]ASI_EC_R, %g0; /* ld E$ stging regs */ \ 252*7c478bd9Sstevel@tonic-gate clr scr1; \ 253*7c478bd9Sstevel@tonic-gate 3: /* loop thru 5 regs */ \ 254*7c478bd9Sstevel@tonic-gate ldxa [scr1]ASI_EC_DATA, scr2; \ 255*7c478bd9Sstevel@tonic-gate stxa scr2, [datap]%asi; \ 256*7c478bd9Sstevel@tonic-gate add datap, 8, datap; \ 257*7c478bd9Sstevel@tonic-gate cmp scr1, CH_ECACHE_STGREG_TOTALSIZE - 8; \ 258*7c478bd9Sstevel@tonic-gate bne 3b; \ 259*7c478bd9Sstevel@tonic-gate add scr1, 8, scr1; \ 260*7c478bd9Sstevel@tonic-gate btst CH_ECACHE_STGREG_SIZE, scr3; /* done? */ \ 261*7c478bd9Sstevel@tonic-gate beq 2b; \ 262*7c478bd9Sstevel@tonic-gate add scr3, CH_ECACHE_STGREG_SIZE, scr3 263*7c478bd9Sstevel@tonic-gate 264*7c478bd9Sstevel@tonic-gate #define GET_ECACHE_DTAGS(afar, datap, scr1, scr2, scr3) \ 265*7c478bd9Sstevel@tonic-gate GET_ECACHE_DTAG(afar, datap, 0, scr1, scr2, scr3); \ 266*7c478bd9Sstevel@tonic-gate GET_ECACHE_DTAG(afar, datap, 1, scr1, scr2, scr3); \ 267*7c478bd9Sstevel@tonic-gate GET_ECACHE_DTAG(afar, datap, 2, scr1, scr2, scr3); \ 268*7c478bd9Sstevel@tonic-gate GET_ECACHE_DTAG(afar, datap, 3, scr1, scr2, scr3); \ 269*7c478bd9Sstevel@tonic-gate add datap, (CHD_EC_DATA_SETS-4)*CH_EC_DATA_SIZE, datap; \ 270*7c478bd9Sstevel@tonic-gate add datap, CH_EC_DATA_SIZE * PN_L2_NWAYS, datap; \ 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate /* 273*7c478bd9Sstevel@tonic-gate * Jalapeno does not have cores so these macros are null. 274*7c478bd9Sstevel@tonic-gate */ 275*7c478bd9Sstevel@tonic-gate #define PARK_SIBLING_CORE(dcucr_reg, scr1, scr2) 276*7c478bd9Sstevel@tonic-gate #define UNPARK_SIBLING_CORE(dcucr_reg, scr1, scr2) 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate #if defined(JALAPENO) 279*7c478bd9Sstevel@tonic-gate /* 280*7c478bd9Sstevel@tonic-gate * Jalapeno gets primary AFSR and AFAR. All bits in the AFSR except 281*7c478bd9Sstevel@tonic-gate * the fatal error bits are cleared. 282*7c478bd9Sstevel@tonic-gate * datap: pointer to cpu logout structure. 283*7c478bd9Sstevel@tonic-gate * afar: returned primary AFAR value. 284*7c478bd9Sstevel@tonic-gate * scr1: scratch 285*7c478bd9Sstevel@tonic-gate * scr2: scratch 286*7c478bd9Sstevel@tonic-gate */ 287*7c478bd9Sstevel@tonic-gate #define GET_AFSR_AFAR(datap, afar, scr1, scr2) \ 288*7c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_AFAR, afar; \ 289*7c478bd9Sstevel@tonic-gate stxa afar, [datap + (CH_CLO_DATA + CH_CHD_AFAR)]%asi; \ 290*7c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_AFSR, scr2; \ 291*7c478bd9Sstevel@tonic-gate stxa scr2, [datap + (CH_CLO_DATA + CH_CHD_AFSR)]%asi; \ 292*7c478bd9Sstevel@tonic-gate sethi %hh(C_AFSR_FATAL_ERRS), scr1; \ 293*7c478bd9Sstevel@tonic-gate sllx scr1, 32, scr1; \ 294*7c478bd9Sstevel@tonic-gate bclr scr1, scr2; /* Clear fatal error bits here, so */ \ 295*7c478bd9Sstevel@tonic-gate stxa scr2, [%g0]ASI_AFSR; /* they're left as is in AFSR */ \ 296*7c478bd9Sstevel@tonic-gate membar #Sync 297*7c478bd9Sstevel@tonic-gate 298*7c478bd9Sstevel@tonic-gate /* 299*7c478bd9Sstevel@tonic-gate * Jalapeno has no shadow AFAR, null operation. 300*7c478bd9Sstevel@tonic-gate */ 301*7c478bd9Sstevel@tonic-gate #define GET_SHADOW_DATA(afar, datap, scr1, scr2, scr3) 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate #elif defined(SERRANO) 304*7c478bd9Sstevel@tonic-gate /* 305*7c478bd9Sstevel@tonic-gate * Serrano gets primary AFSR and AFAR. All bits in the AFSR except 306*7c478bd9Sstevel@tonic-gate * the fatal error bits are cleared. For Serrano, we also save the 307*7c478bd9Sstevel@tonic-gate * AFAR2 register. 308*7c478bd9Sstevel@tonic-gate * datap: pointer to cpu logout structure. 309*7c478bd9Sstevel@tonic-gate * afar: returned primary AFAR value. 310*7c478bd9Sstevel@tonic-gate * scr1: scratch 311*7c478bd9Sstevel@tonic-gate * scr2: scratch 312*7c478bd9Sstevel@tonic-gate */ 313*7c478bd9Sstevel@tonic-gate #define GET_AFSR_AFAR(datap, afar, scr1, scr2) \ 314*7c478bd9Sstevel@tonic-gate set ASI_MCU_AFAR2_VA, scr1; \ 315*7c478bd9Sstevel@tonic-gate ldxa [scr1]ASI_MCU_CTRL, afar; \ 316*7c478bd9Sstevel@tonic-gate stxa afar, [datap + (CH_CLO_DATA + CH_CHD_AFAR2)]%asi; \ 317*7c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_AFAR, afar; \ 318*7c478bd9Sstevel@tonic-gate stxa afar, [datap + (CH_CLO_DATA + CH_CHD_AFAR)]%asi; \ 319*7c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_AFSR, scr2; \ 320*7c478bd9Sstevel@tonic-gate stxa scr2, [datap + (CH_CLO_DATA + CH_CHD_AFSR)]%asi; \ 321*7c478bd9Sstevel@tonic-gate sethi %hh(C_AFSR_FATAL_ERRS), scr1; \ 322*7c478bd9Sstevel@tonic-gate sllx scr1, 32, scr1; \ 323*7c478bd9Sstevel@tonic-gate bclr scr1, scr2; /* Clear fatal error bits here, so */ \ 324*7c478bd9Sstevel@tonic-gate stxa scr2, [%g0]ASI_AFSR; /* they're left as is in AFSR */ \ 325*7c478bd9Sstevel@tonic-gate membar #Sync 326*7c478bd9Sstevel@tonic-gate 327*7c478bd9Sstevel@tonic-gate /* 328*7c478bd9Sstevel@tonic-gate * Serrano needs to capture E$, D$ and I$ lines associated with afar2. 329*7c478bd9Sstevel@tonic-gate * afar: scratch, holds afar2. 330*7c478bd9Sstevel@tonic-gate * datap: pointer to cpu logout structure 331*7c478bd9Sstevel@tonic-gate * scr1: scratch 332*7c478bd9Sstevel@tonic-gate * scr2: scratch 333*7c478bd9Sstevel@tonic-gate * scr3: scratch 334*7c478bd9Sstevel@tonic-gate */ 335*7c478bd9Sstevel@tonic-gate #define GET_SHADOW_DATA(afar, datap, scr1, scr2, scr3) \ 336*7c478bd9Sstevel@tonic-gate ldxa [datap + (CH_CLO_DATA + CH_CHD_AFAR2)]%asi, afar; \ 337*7c478bd9Sstevel@tonic-gate add datap, CH_CLO_SDW_DATA + CH_CHD_EC_DATA, datap; \ 338*7c478bd9Sstevel@tonic-gate GET_ECACHE_DTAGS(afar, datap, scr1, scr2, scr3); \ 339*7c478bd9Sstevel@tonic-gate GET_DCACHE_DTAG(afar, datap, scr1, scr2, scr3); \ 340*7c478bd9Sstevel@tonic-gate GET_ICACHE_DTAG(afar, datap, scr1, scr2, scr3); \ 341*7c478bd9Sstevel@tonic-gate sub datap, CH_CPU_LOGOUT_SIZE, datap 342*7c478bd9Sstevel@tonic-gate #endif /* SERRANO */ 343*7c478bd9Sstevel@tonic-gate 344*7c478bd9Sstevel@tonic-gate #elif defined(CHEETAH_PLUS) 345*7c478bd9Sstevel@tonic-gate /* 346*7c478bd9Sstevel@tonic-gate * Macro version of get_ecache_dtag. We use this macro in the 347*7c478bd9Sstevel@tonic-gate * CPU logout code. 348*7c478bd9Sstevel@tonic-gate * afar: input AFAR, not modified. 349*7c478bd9Sstevel@tonic-gate * datap: Ptr to ch_ec_data_t, at end pts just past ch_ec_data_t. 350*7c478bd9Sstevel@tonic-gate * pn_way: ecache way for panther (value = 0-3). For non-panther 351*7c478bd9Sstevel@tonic-gate * cpus, this macro will be called with pn_way = 0. 352*7c478bd9Sstevel@tonic-gate * scr1: Scratch. 353*7c478bd9Sstevel@tonic-gate * scr2: Scratch. 354*7c478bd9Sstevel@tonic-gate * scr3: Scratch. 355*7c478bd9Sstevel@tonic-gate */ 356*7c478bd9Sstevel@tonic-gate #define GET_ECACHE_DTAG(afar, datap, pn_way, scr1, scr2, scr3) \ 357*7c478bd9Sstevel@tonic-gate mov afar, scr3; \ 358*7c478bd9Sstevel@tonic-gate andn scr3, (CH_ECACHE_SUBBLK_SIZE - 1), scr3; /* VA<5:0>=0 */\ 359*7c478bd9Sstevel@tonic-gate set (CH_ECACHE_8M_SIZE - 1), scr2; \ 360*7c478bd9Sstevel@tonic-gate and scr3, scr2, scr3; /* VA<63:23>=0 */ \ 361*7c478bd9Sstevel@tonic-gate mov pn_way, scr1; /* panther L3$ is 4-way so we ... */ \ 362*7c478bd9Sstevel@tonic-gate sllx scr1, PN_L3_WAY_SHIFT, scr1; /* need to mask... */ \ 363*7c478bd9Sstevel@tonic-gate or scr3, scr1, scr3; /* in the way bits <24:23>. */ \ 364*7c478bd9Sstevel@tonic-gate b 1f; \ 365*7c478bd9Sstevel@tonic-gate stxa scr3, [datap + CH_EC_IDX]%asi; /* store E$ index */ \ 366*7c478bd9Sstevel@tonic-gate .align 64; \ 367*7c478bd9Sstevel@tonic-gate 1: \ 368*7c478bd9Sstevel@tonic-gate ldxa [scr3]ASI_EC_DIAG, scr1; /* get E$ tag */ \ 369*7c478bd9Sstevel@tonic-gate stxa scr1, [datap + CH_EC_TAG]%asi; \ 370*7c478bd9Sstevel@tonic-gate set CHP_ECACHE_IDX_TAG_ECC, scr1; \ 371*7c478bd9Sstevel@tonic-gate or scr3, scr1, scr1; \ 372*7c478bd9Sstevel@tonic-gate ldxa [scr1]ASI_EC_DIAG, scr1; /* get E$ tag ECC */ \ 373*7c478bd9Sstevel@tonic-gate stxa scr1, [datap + CH_EC_TAG_ECC]%asi; \ 374*7c478bd9Sstevel@tonic-gate add datap, CH_EC_DATA, datap; \ 375*7c478bd9Sstevel@tonic-gate 2: \ 376*7c478bd9Sstevel@tonic-gate ldxa [scr3]ASI_EC_R, %g0; /* ld E$ stging regs */ \ 377*7c478bd9Sstevel@tonic-gate clr scr1; \ 378*7c478bd9Sstevel@tonic-gate 3: /* loop thru 5 regs */ \ 379*7c478bd9Sstevel@tonic-gate ldxa [scr1]ASI_EC_DATA, scr2; \ 380*7c478bd9Sstevel@tonic-gate stxa scr2, [datap]%asi; \ 381*7c478bd9Sstevel@tonic-gate add datap, 8, datap; \ 382*7c478bd9Sstevel@tonic-gate cmp scr1, CH_ECACHE_STGREG_TOTALSIZE - 8; \ 383*7c478bd9Sstevel@tonic-gate bne 3b; \ 384*7c478bd9Sstevel@tonic-gate add scr1, 8, scr1; \ 385*7c478bd9Sstevel@tonic-gate btst CH_ECACHE_STGREG_SIZE, scr3; /* done? */ \ 386*7c478bd9Sstevel@tonic-gate beq 2b; \ 387*7c478bd9Sstevel@tonic-gate add scr3, CH_ECACHE_STGREG_SIZE, scr3 388*7c478bd9Sstevel@tonic-gate 389*7c478bd9Sstevel@tonic-gate /* 390*7c478bd9Sstevel@tonic-gate * If this is a panther, we need to make sure the sibling core is 391*7c478bd9Sstevel@tonic-gate * parked so that we avoid any race conditions during diagnostic 392*7c478bd9Sstevel@tonic-gate * accesses to the shared L2 and L3 caches. 393*7c478bd9Sstevel@tonic-gate * dcucr_reg: This register will be used to keep track of whether 394*7c478bd9Sstevel@tonic-gate * or not we need to unpark the core later. 395*7c478bd9Sstevel@tonic-gate * It just so happens that we also use this same register 396*7c478bd9Sstevel@tonic-gate * to keep track of our saved DCUCR value so we only touch 397*7c478bd9Sstevel@tonic-gate * bit 4 of the register (which is a "reserved" bit in the 398*7c478bd9Sstevel@tonic-gate * DCUCR) for keeping track of core parking. 399*7c478bd9Sstevel@tonic-gate * scr1: Scratch register. 400*7c478bd9Sstevel@tonic-gate * scr2: Scratch register. 401*7c478bd9Sstevel@tonic-gate */ 402*7c478bd9Sstevel@tonic-gate #define PARK_SIBLING_CORE(dcucr_reg, scr1, scr2) \ 403*7c478bd9Sstevel@tonic-gate GET_CPU_IMPL(scr1); \ 404*7c478bd9Sstevel@tonic-gate cmp scr1, PANTHER_IMPL; /* only park for panthers */ \ 405*7c478bd9Sstevel@tonic-gate bne,a %xcc, 2f; \ 406*7c478bd9Sstevel@tonic-gate andn dcucr_reg, PN_PARKED_OTHER_CORE, dcucr_reg; \ 407*7c478bd9Sstevel@tonic-gate set ASI_CORE_RUNNING_STATUS, scr1; /* check other core */ \ 408*7c478bd9Sstevel@tonic-gate ldxa [scr1]ASI_CMP_SHARED, scr2; /* is it running? */ \ 409*7c478bd9Sstevel@tonic-gate cmp scr2, PN_BOTH_CORES_RUNNING; \ 410*7c478bd9Sstevel@tonic-gate bne,a %xcc, 2f; /* if not running, we are done */ \ 411*7c478bd9Sstevel@tonic-gate andn dcucr_reg, PN_PARKED_OTHER_CORE, dcucr_reg; \ 412*7c478bd9Sstevel@tonic-gate or dcucr_reg, PN_PARKED_OTHER_CORE, dcucr_reg; \ 413*7c478bd9Sstevel@tonic-gate set ASI_CORE_ID, scr1; \ 414*7c478bd9Sstevel@tonic-gate ldxa [scr1]ASI_CMP_PER_CORE, scr2; \ 415*7c478bd9Sstevel@tonic-gate and scr2, COREID_MASK, scr2; \ 416*7c478bd9Sstevel@tonic-gate or %g0, 1, scr1; /* find out which core... */ \ 417*7c478bd9Sstevel@tonic-gate sll scr1, scr2, scr2; /* ... we need to park... */ \ 418*7c478bd9Sstevel@tonic-gate 1: \ 419*7c478bd9Sstevel@tonic-gate set ASI_CORE_RUNNING_RW, scr1; \ 420*7c478bd9Sstevel@tonic-gate stxa scr2, [scr1]ASI_CMP_SHARED; /* ... and park it. */ \ 421*7c478bd9Sstevel@tonic-gate membar #Sync; /* spin until the... */ \ 422*7c478bd9Sstevel@tonic-gate ldxa [scr1]ASI_CMP_SHARED, scr1; /* ... the other... */ \ 423*7c478bd9Sstevel@tonic-gate cmp scr1, scr2; /* ...core is parked according to... */ \ 424*7c478bd9Sstevel@tonic-gate bne,a %xcc, 1b; /* ...the core running status reg. */ \ 425*7c478bd9Sstevel@tonic-gate nop; \ 426*7c478bd9Sstevel@tonic-gate 2: 427*7c478bd9Sstevel@tonic-gate 428*7c478bd9Sstevel@tonic-gate /* 429*7c478bd9Sstevel@tonic-gate * The core running this code will unpark its sibling core if the 430*7c478bd9Sstevel@tonic-gate * sibling core had been parked by the current core earlier in this 431*7c478bd9Sstevel@tonic-gate * trap handler. 432*7c478bd9Sstevel@tonic-gate * dcucr_reg: This register is used to keep track of whether or not 433*7c478bd9Sstevel@tonic-gate * we need to unpark our sibling core. 434*7c478bd9Sstevel@tonic-gate * It just so happens that we also use this same register 435*7c478bd9Sstevel@tonic-gate * to keep track of our saved DCUCR value so we only touch 436*7c478bd9Sstevel@tonic-gate * bit 4 of the register (which is a "reserved" bit in the 437*7c478bd9Sstevel@tonic-gate * DCUCR) for keeping track of core parking. 438*7c478bd9Sstevel@tonic-gate * scr1: Scratch register. 439*7c478bd9Sstevel@tonic-gate * scr2: Scratch register. 440*7c478bd9Sstevel@tonic-gate */ 441*7c478bd9Sstevel@tonic-gate #define UNPARK_SIBLING_CORE(dcucr_reg, scr1, scr2) \ 442*7c478bd9Sstevel@tonic-gate btst PN_PARKED_OTHER_CORE, dcucr_reg; \ 443*7c478bd9Sstevel@tonic-gate bz,pt %xcc, 1f; /* if nothing to unpark, we are done */ \ 444*7c478bd9Sstevel@tonic-gate andn dcucr_reg, PN_PARKED_OTHER_CORE, dcucr_reg; \ 445*7c478bd9Sstevel@tonic-gate set ASI_CORE_RUNNING_RW, scr1; \ 446*7c478bd9Sstevel@tonic-gate set PN_BOTH_CORES_RUNNING, scr2; /* we want both... */ \ 447*7c478bd9Sstevel@tonic-gate stxa scr2, [scr1]ASI_CMP_SHARED; /* ...cores running. */ \ 448*7c478bd9Sstevel@tonic-gate membar #Sync; \ 449*7c478bd9Sstevel@tonic-gate 1: 450*7c478bd9Sstevel@tonic-gate 451*7c478bd9Sstevel@tonic-gate /* 452*7c478bd9Sstevel@tonic-gate * Cheetah+ and Jaguar get both primary and secondary AFSR/AFAR. All bits 453*7c478bd9Sstevel@tonic-gate * in the primary AFSR are cleared except the fatal error bits. For Panther, 454*7c478bd9Sstevel@tonic-gate * we also have to read and clear the AFSR_EXT, again leaving the fatal 455*7c478bd9Sstevel@tonic-gate * error bits alone. 456*7c478bd9Sstevel@tonic-gate * datap: pointer to cpu logout structure. 457*7c478bd9Sstevel@tonic-gate * afar: returned primary AFAR value. 458*7c478bd9Sstevel@tonic-gate * scr1: scratch 459*7c478bd9Sstevel@tonic-gate * scr2: scratch 460*7c478bd9Sstevel@tonic-gate */ 461*7c478bd9Sstevel@tonic-gate #define GET_AFSR_AFAR(datap, afar, scr1, scr2) \ 462*7c478bd9Sstevel@tonic-gate set ASI_SHADOW_REG_VA, scr1; \ 463*7c478bd9Sstevel@tonic-gate ldxa [scr1]ASI_AFAR, scr2; \ 464*7c478bd9Sstevel@tonic-gate stxa scr2, [datap + (CH_CLO_SDW_DATA + CH_CHD_AFAR)]%asi; \ 465*7c478bd9Sstevel@tonic-gate ldxa [scr1]ASI_AFSR, scr2; \ 466*7c478bd9Sstevel@tonic-gate stxa scr2, [datap + (CH_CLO_SDW_DATA + CH_CHD_AFSR)]%asi; \ 467*7c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_AFAR, afar; \ 468*7c478bd9Sstevel@tonic-gate stxa afar, [datap + (CH_CLO_DATA + CH_CHD_AFAR)]%asi; \ 469*7c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_AFSR, scr2; \ 470*7c478bd9Sstevel@tonic-gate stxa scr2, [datap + (CH_CLO_DATA + CH_CHD_AFSR)]%asi; \ 471*7c478bd9Sstevel@tonic-gate sethi %hh(C_AFSR_FATAL_ERRS), scr1; \ 472*7c478bd9Sstevel@tonic-gate sllx scr1, 32, scr1; \ 473*7c478bd9Sstevel@tonic-gate bclr scr1, scr2; /* Clear fatal error bits here, so */ \ 474*7c478bd9Sstevel@tonic-gate stxa scr2, [%g0]ASI_AFSR; /* they're left as is in AFSR */ \ 475*7c478bd9Sstevel@tonic-gate membar #Sync; \ 476*7c478bd9Sstevel@tonic-gate GET_CPU_IMPL(scr1); \ 477*7c478bd9Sstevel@tonic-gate cmp scr1, PANTHER_IMPL; \ 478*7c478bd9Sstevel@tonic-gate bne %xcc, 1f; \ 479*7c478bd9Sstevel@tonic-gate nop; \ 480*7c478bd9Sstevel@tonic-gate set ASI_SHADOW_AFSR_EXT_VA, scr1; /* shadow AFSR_EXT */ \ 481*7c478bd9Sstevel@tonic-gate ldxa [scr1]ASI_AFSR, scr2; \ 482*7c478bd9Sstevel@tonic-gate stxa scr2, [datap + (CH_CLO_SDW_DATA + CH_CHD_AFSR_EXT)]%asi; \ 483*7c478bd9Sstevel@tonic-gate set ASI_AFSR_EXT_VA, scr1; /* primary AFSR_EXT */ \ 484*7c478bd9Sstevel@tonic-gate ldxa [scr1]ASI_AFSR, scr2; \ 485*7c478bd9Sstevel@tonic-gate stxa scr2, [datap + (CH_CLO_DATA + CH_CHD_AFSR_EXT)]%asi; \ 486*7c478bd9Sstevel@tonic-gate set C_AFSR_EXT_FATAL_ERRS, scr1; \ 487*7c478bd9Sstevel@tonic-gate bclr scr1, scr2; /* Clear fatal error bits here, */ \ 488*7c478bd9Sstevel@tonic-gate set ASI_AFSR_EXT_VA, scr1; /* so they're left */ \ 489*7c478bd9Sstevel@tonic-gate stxa scr2, [scr1]ASI_AFSR; /* as is in AFSR_EXT */ \ 490*7c478bd9Sstevel@tonic-gate membar #Sync; \ 491*7c478bd9Sstevel@tonic-gate 1: 492*7c478bd9Sstevel@tonic-gate 493*7c478bd9Sstevel@tonic-gate /* 494*7c478bd9Sstevel@tonic-gate * This macro is used in the CPU logout code to capture diagnostic 495*7c478bd9Sstevel@tonic-gate * information from the L2 cache on panther processors. 496*7c478bd9Sstevel@tonic-gate * afar: input AFAR, not modified. 497*7c478bd9Sstevel@tonic-gate * datap: Ptr to pn_l2_data_t, at end pts just past pn_l2_data_t. 498*7c478bd9Sstevel@tonic-gate * scr1: Scratch. 499*7c478bd9Sstevel@tonic-gate * scr2: Scratch. 500*7c478bd9Sstevel@tonic-gate * scr3: Scratch. 501*7c478bd9Sstevel@tonic-gate */ 502*7c478bd9Sstevel@tonic-gate #define GET_PN_L2_CACHE_DTAGS(afar, datap, scr1, scr2, scr3) \ 503*7c478bd9Sstevel@tonic-gate mov afar, scr3; \ 504*7c478bd9Sstevel@tonic-gate set PN_L2_INDEX_MASK, scr1; \ 505*7c478bd9Sstevel@tonic-gate and scr3, scr1, scr3; \ 506*7c478bd9Sstevel@tonic-gate b 1f; /* code to read tags and data should be ... */ \ 507*7c478bd9Sstevel@tonic-gate nop; /* ...on the same cache line if possible. */ \ 508*7c478bd9Sstevel@tonic-gate .align 128; /* update this line if you add lines below. */ \ 509*7c478bd9Sstevel@tonic-gate 1: \ 510*7c478bd9Sstevel@tonic-gate stxa scr3, [datap + CH_EC_IDX]%asi; /* store L2$ index */ \ 511*7c478bd9Sstevel@tonic-gate ldxa [scr3]ASI_L2_TAG, scr1; /* read the L2$ tag */ \ 512*7c478bd9Sstevel@tonic-gate stxa scr1, [datap + CH_EC_TAG]%asi; \ 513*7c478bd9Sstevel@tonic-gate add datap, CH_EC_DATA, datap; \ 514*7c478bd9Sstevel@tonic-gate clr scr1; \ 515*7c478bd9Sstevel@tonic-gate 2: \ 516*7c478bd9Sstevel@tonic-gate ldxa [scr3 + scr1]ASI_L2_DATA, scr2; /* loop through */ \ 517*7c478bd9Sstevel@tonic-gate stxa scr2, [datap]%asi; /* <511:256> of L2 */ \ 518*7c478bd9Sstevel@tonic-gate add datap, 8, datap; /* data and record */ \ 519*7c478bd9Sstevel@tonic-gate cmp scr1, (PN_L2_LINESIZE / 2) - 8; /* it in the cpu */ \ 520*7c478bd9Sstevel@tonic-gate bne 2b; /* logout struct. */ \ 521*7c478bd9Sstevel@tonic-gate add scr1, 8, scr1; \ 522*7c478bd9Sstevel@tonic-gate set PN_L2_DATA_ECC_SEL, scr2; /* ECC_sel bit. */ \ 523*7c478bd9Sstevel@tonic-gate ldxa [scr3 + scr2]ASI_L2_DATA, scr2; /* Read and record */ \ 524*7c478bd9Sstevel@tonic-gate stxa scr2, [datap]%asi; /* ecc of <511:256> */ \ 525*7c478bd9Sstevel@tonic-gate add datap, 8, datap; \ 526*7c478bd9Sstevel@tonic-gate 3: \ 527*7c478bd9Sstevel@tonic-gate ldxa [scr3 + scr1]ASI_L2_DATA, scr2; /* loop through */ \ 528*7c478bd9Sstevel@tonic-gate stxa scr2, [datap]%asi; /* <255:0> of L2 */ \ 529*7c478bd9Sstevel@tonic-gate add datap, 8, datap; /* data and record */ \ 530*7c478bd9Sstevel@tonic-gate cmp scr1, PN_L2_LINESIZE - 8; /* it in the cpu */ \ 531*7c478bd9Sstevel@tonic-gate bne 3b; /* logout struct. */ \ 532*7c478bd9Sstevel@tonic-gate add scr1, 8, scr1; \ 533*7c478bd9Sstevel@tonic-gate set PN_L2_DATA_ECC_SEL, scr2; /* ECC_sel bit. */ \ 534*7c478bd9Sstevel@tonic-gate add scr2, PN_L2_ECC_LO_REG, scr2; \ 535*7c478bd9Sstevel@tonic-gate ldxa [scr3 + scr2]ASI_L2_DATA, scr2; /* Read and record */ \ 536*7c478bd9Sstevel@tonic-gate stxa scr2, [datap]%asi; /* ecc of <255:0>. */ \ 537*7c478bd9Sstevel@tonic-gate add datap, 8, datap; /* Advance pointer */ \ 538*7c478bd9Sstevel@tonic-gate set PN_L2_SET_SIZE, scr2; \ 539*7c478bd9Sstevel@tonic-gate set PN_L2_MAX_SET, scr1; \ 540*7c478bd9Sstevel@tonic-gate cmp scr1, scr3; /* more ways to try for this line? */ \ 541*7c478bd9Sstevel@tonic-gate bg,a %xcc, 1b; /* if so, start over with next way */ \ 542*7c478bd9Sstevel@tonic-gate add scr3, scr2, scr3 543*7c478bd9Sstevel@tonic-gate 544*7c478bd9Sstevel@tonic-gate /* 545*7c478bd9Sstevel@tonic-gate * Cheetah+ assumes E$ is 2-way and grabs both E$ lines associated with afar. 546*7c478bd9Sstevel@tonic-gate * afar: AFAR from access. 547*7c478bd9Sstevel@tonic-gate * datap: pointer to cpu logout structure. 548*7c478bd9Sstevel@tonic-gate * scr1: scratch 549*7c478bd9Sstevel@tonic-gate * scr2: scratch 550*7c478bd9Sstevel@tonic-gate * scr3: scratch 551*7c478bd9Sstevel@tonic-gate */ 552*7c478bd9Sstevel@tonic-gate #define GET_ECACHE_DTAGS(afar, datap, scr1, scr2, scr3) \ 553*7c478bd9Sstevel@tonic-gate GET_CPU_IMPL(scr1); \ 554*7c478bd9Sstevel@tonic-gate cmp scr1, PANTHER_IMPL; \ 555*7c478bd9Sstevel@tonic-gate bne %xcc, 4f; \ 556*7c478bd9Sstevel@tonic-gate nop; \ 557*7c478bd9Sstevel@tonic-gate GET_ECACHE_DTAG(afar, datap, 0, scr1, scr2, scr3); \ 558*7c478bd9Sstevel@tonic-gate GET_ECACHE_DTAG(afar, datap, 1, scr1, scr2, scr3); \ 559*7c478bd9Sstevel@tonic-gate GET_ECACHE_DTAG(afar, datap, 2, scr1, scr2, scr3); \ 560*7c478bd9Sstevel@tonic-gate GET_ECACHE_DTAG(afar, datap, 3, scr1, scr2, scr3); \ 561*7c478bd9Sstevel@tonic-gate add datap, (CHD_EC_DATA_SETS-4)*CH_EC_DATA_SIZE, datap; \ 562*7c478bd9Sstevel@tonic-gate GET_PN_L2_CACHE_DTAGS(afar, datap, scr1, scr2, scr3); \ 563*7c478bd9Sstevel@tonic-gate b 5f; \ 564*7c478bd9Sstevel@tonic-gate nop; \ 565*7c478bd9Sstevel@tonic-gate 4: \ 566*7c478bd9Sstevel@tonic-gate GET_ECACHE_DTAG(afar, datap, 0, scr1, scr2, scr3); \ 567*7c478bd9Sstevel@tonic-gate GET_ECACHE_WAY_BIT(scr1, scr2); \ 568*7c478bd9Sstevel@tonic-gate xor afar, scr1, afar; \ 569*7c478bd9Sstevel@tonic-gate GET_ECACHE_DTAG(afar, datap, 0, scr1, scr2, scr3); \ 570*7c478bd9Sstevel@tonic-gate GET_ECACHE_WAY_BIT(scr1, scr2); /* restore AFAR */ \ 571*7c478bd9Sstevel@tonic-gate xor afar, scr1, afar; \ 572*7c478bd9Sstevel@tonic-gate add datap, (CHD_EC_DATA_SETS-2)*CH_EC_DATA_SIZE, datap; \ 573*7c478bd9Sstevel@tonic-gate add datap, CH_EC_DATA_SIZE * PN_L2_NWAYS, datap; \ 574*7c478bd9Sstevel@tonic-gate 5: 575*7c478bd9Sstevel@tonic-gate 576*7c478bd9Sstevel@tonic-gate /* 577*7c478bd9Sstevel@tonic-gate * Cheetah+ needs to capture E$, D$ and I$ lines associated with 578*7c478bd9Sstevel@tonic-gate * shadow afar. 579*7c478bd9Sstevel@tonic-gate * afar: scratch, holds shadow afar. 580*7c478bd9Sstevel@tonic-gate * datap: pointer to cpu logout structure 581*7c478bd9Sstevel@tonic-gate * scr1: scratch 582*7c478bd9Sstevel@tonic-gate * scr2: scratch 583*7c478bd9Sstevel@tonic-gate * scr3: scratch 584*7c478bd9Sstevel@tonic-gate */ 585*7c478bd9Sstevel@tonic-gate #define GET_SHADOW_DATA(afar, datap, scr1, scr2, scr3) \ 586*7c478bd9Sstevel@tonic-gate ldxa [datap + (CH_CLO_SDW_DATA + CH_CHD_AFAR)]%asi, afar; \ 587*7c478bd9Sstevel@tonic-gate add datap, CH_CLO_SDW_DATA + CH_CHD_EC_DATA, datap; \ 588*7c478bd9Sstevel@tonic-gate GET_ECACHE_DTAGS(afar, datap, scr1, scr2, scr3); \ 589*7c478bd9Sstevel@tonic-gate GET_DCACHE_DTAG(afar, datap, scr1, scr2, scr3); \ 590*7c478bd9Sstevel@tonic-gate GET_ICACHE_DTAG(afar, datap, scr1, scr2, scr3); \ 591*7c478bd9Sstevel@tonic-gate sub datap, CH_CPU_LOGOUT_SIZE, datap 592*7c478bd9Sstevel@tonic-gate 593*7c478bd9Sstevel@tonic-gate /* 594*7c478bd9Sstevel@tonic-gate * Compute the "Way" bit for 2-way Ecache for Cheetah+. 595*7c478bd9Sstevel@tonic-gate */ 596*7c478bd9Sstevel@tonic-gate #define GET_ECACHE_WAY_BIT(scr1, scr2) \ 597*7c478bd9Sstevel@tonic-gate CPU_INDEX(scr1, scr2); \ 598*7c478bd9Sstevel@tonic-gate mulx scr1, CPU_NODE_SIZE, scr1; \ 599*7c478bd9Sstevel@tonic-gate add scr1, ECACHE_SIZE, scr1; \ 600*7c478bd9Sstevel@tonic-gate set cpunodes, scr2; \ 601*7c478bd9Sstevel@tonic-gate ld [scr1 + scr2], scr1; \ 602*7c478bd9Sstevel@tonic-gate srlx scr1, 1, scr1 603*7c478bd9Sstevel@tonic-gate 604*7c478bd9Sstevel@tonic-gate #else /* CHEETAH_PLUS */ 605*7c478bd9Sstevel@tonic-gate /* 606*7c478bd9Sstevel@tonic-gate * Macro version of get_ecache_dtag. We use this macro in the 607*7c478bd9Sstevel@tonic-gate * CPU logout code. 608*7c478bd9Sstevel@tonic-gate * afar: input AFAR, not modified. 609*7c478bd9Sstevel@tonic-gate * datap: Ptr to ch_ec_data_t, at end pts just past ch_ec_data_t. 610*7c478bd9Sstevel@tonic-gate * scr1: Scratch. 611*7c478bd9Sstevel@tonic-gate * scr2: Scratch. 612*7c478bd9Sstevel@tonic-gate * scr3: Scratch. 613*7c478bd9Sstevel@tonic-gate */ 614*7c478bd9Sstevel@tonic-gate #define GET_ECACHE_DTAG(afar, datap, scr1, scr2, scr3) \ 615*7c478bd9Sstevel@tonic-gate mov afar, scr3; \ 616*7c478bd9Sstevel@tonic-gate andn scr3, (CH_ECACHE_SUBBLK_SIZE - 1), scr3; /* VA<5:0>=0 */\ 617*7c478bd9Sstevel@tonic-gate set (CH_ECACHE_8M_SIZE - 1), scr2; \ 618*7c478bd9Sstevel@tonic-gate and scr3, scr2, scr3; /* VA<63:23>=0 */ \ 619*7c478bd9Sstevel@tonic-gate b 1f; \ 620*7c478bd9Sstevel@tonic-gate stxa scr3, [datap + CH_EC_IDX]%asi; /* store E$ index */ \ 621*7c478bd9Sstevel@tonic-gate .align 64; \ 622*7c478bd9Sstevel@tonic-gate 1: \ 623*7c478bd9Sstevel@tonic-gate ldxa [scr3]ASI_EC_DIAG, scr1; /* get E$ tag */ \ 624*7c478bd9Sstevel@tonic-gate stxa scr1, [datap + CH_EC_TAG]%asi; \ 625*7c478bd9Sstevel@tonic-gate add datap, CH_EC_DATA, datap; \ 626*7c478bd9Sstevel@tonic-gate 2: \ 627*7c478bd9Sstevel@tonic-gate ldxa [scr3]ASI_EC_R, %g0; /* ld E$ stging regs */ \ 628*7c478bd9Sstevel@tonic-gate clr scr1; \ 629*7c478bd9Sstevel@tonic-gate 3: /* loop thru 5 regs */ \ 630*7c478bd9Sstevel@tonic-gate ldxa [scr1]ASI_EC_DATA, scr2; \ 631*7c478bd9Sstevel@tonic-gate stxa scr2, [datap]%asi; \ 632*7c478bd9Sstevel@tonic-gate add datap, 8, datap; \ 633*7c478bd9Sstevel@tonic-gate cmp scr1, CH_ECACHE_STGREG_TOTALSIZE - 8; \ 634*7c478bd9Sstevel@tonic-gate bne 3b; \ 635*7c478bd9Sstevel@tonic-gate add scr1, 8, scr1; \ 636*7c478bd9Sstevel@tonic-gate btst CH_ECACHE_STGREG_SIZE, scr3; /* done? */ \ 637*7c478bd9Sstevel@tonic-gate beq 2b; \ 638*7c478bd9Sstevel@tonic-gate add scr3, CH_ECACHE_STGREG_SIZE, scr3 639*7c478bd9Sstevel@tonic-gate 640*7c478bd9Sstevel@tonic-gate /* 641*7c478bd9Sstevel@tonic-gate * Cheetah does not have cores so these macros are null. 642*7c478bd9Sstevel@tonic-gate */ 643*7c478bd9Sstevel@tonic-gate #define PARK_SIBLING_CORE(dcucr_reg, scr1, scr2) 644*7c478bd9Sstevel@tonic-gate #define UNPARK_SIBLING_CORE(dcucr_reg, scr1, scr2) 645*7c478bd9Sstevel@tonic-gate 646*7c478bd9Sstevel@tonic-gate /* 647*7c478bd9Sstevel@tonic-gate * Cheetah gets primary AFSR and AFAR and clears the AFSR, except for the 648*7c478bd9Sstevel@tonic-gate * fatal error bits. 649*7c478bd9Sstevel@tonic-gate * datap: pointer to cpu logout structure. 650*7c478bd9Sstevel@tonic-gate * afar: returned primary AFAR value. 651*7c478bd9Sstevel@tonic-gate * scr1: scratch 652*7c478bd9Sstevel@tonic-gate * scr2: scratch 653*7c478bd9Sstevel@tonic-gate */ 654*7c478bd9Sstevel@tonic-gate #define GET_AFSR_AFAR(datap, afar, scr1, scr2) \ 655*7c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_AFAR, afar; \ 656*7c478bd9Sstevel@tonic-gate stxa afar, [datap + (CH_CLO_DATA + CH_CHD_AFAR)]%asi; \ 657*7c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_AFSR, scr2; \ 658*7c478bd9Sstevel@tonic-gate stxa scr2, [datap + (CH_CLO_DATA + CH_CHD_AFSR)]%asi; \ 659*7c478bd9Sstevel@tonic-gate sethi %hh(C_AFSR_FATAL_ERRS), scr1; \ 660*7c478bd9Sstevel@tonic-gate sllx scr1, 32, scr1; \ 661*7c478bd9Sstevel@tonic-gate bclr scr1, scr2; /* Clear fatal error bits here, so */ \ 662*7c478bd9Sstevel@tonic-gate stxa scr2, [%g0]ASI_AFSR; /* they're left as is in AFSR */ \ 663*7c478bd9Sstevel@tonic-gate membar #Sync 664*7c478bd9Sstevel@tonic-gate 665*7c478bd9Sstevel@tonic-gate /* 666*7c478bd9Sstevel@tonic-gate * Cheetah E$ is direct-mapped, so we grab line data and skip second line. 667*7c478bd9Sstevel@tonic-gate * afar: AFAR from access. 668*7c478bd9Sstevel@tonic-gate * datap: pointer to cpu logout structure. 669*7c478bd9Sstevel@tonic-gate * scr1: scratch 670*7c478bd9Sstevel@tonic-gate * scr2: scratch 671*7c478bd9Sstevel@tonic-gate * scr3: scratch 672*7c478bd9Sstevel@tonic-gate */ 673*7c478bd9Sstevel@tonic-gate #define GET_ECACHE_DTAGS(afar, datap, scr1, scr2, scr3) \ 674*7c478bd9Sstevel@tonic-gate GET_ECACHE_DTAG(afar, datap, scr1, scr2, scr3); \ 675*7c478bd9Sstevel@tonic-gate add datap, (CHD_EC_DATA_SETS-1)*CH_EC_DATA_SIZE, datap; \ 676*7c478bd9Sstevel@tonic-gate add datap, CH_EC_DATA_SIZE * PN_L2_NWAYS, datap; \ 677*7c478bd9Sstevel@tonic-gate 678*7c478bd9Sstevel@tonic-gate /* 679*7c478bd9Sstevel@tonic-gate * Cheetah has no shadow AFAR, null operation. 680*7c478bd9Sstevel@tonic-gate */ 681*7c478bd9Sstevel@tonic-gate #define GET_SHADOW_DATA(afar, datap, scr1, scr2, scr3) 682*7c478bd9Sstevel@tonic-gate 683*7c478bd9Sstevel@tonic-gate #endif /* CHEETAH_PLUS */ 684*7c478bd9Sstevel@tonic-gate 685*7c478bd9Sstevel@tonic-gate /* 686*7c478bd9Sstevel@tonic-gate * Cheetah/(Cheetah+ Jaguar Panther)/Jalapeno Macro for capturing CPU 687*7c478bd9Sstevel@tonic-gate * logout data at TL>0. r_val is a register that returns the "failure count" 688*7c478bd9Sstevel@tonic-gate * to the caller, and may be used as a scratch register until the end of 689*7c478bd9Sstevel@tonic-gate * the macro. afar is used to return the primary AFAR value to the caller 690*7c478bd9Sstevel@tonic-gate * and it too can be used as a scratch register until the end. r_or_s is 691*7c478bd9Sstevel@tonic-gate * a reg or symbol that has the offset within the "cpu_private" data area 692*7c478bd9Sstevel@tonic-gate * to deposit the logout data. t_flags is a register that has the 693*7c478bd9Sstevel@tonic-gate * trap-type/trap-level/CEEN info. This t_flags register may be used after 694*7c478bd9Sstevel@tonic-gate * the GET_AFSR_AFAR macro. 695*7c478bd9Sstevel@tonic-gate * 696*7c478bd9Sstevel@tonic-gate * The CPU logout operation will fail (r_val > 0) if the logout 697*7c478bd9Sstevel@tonic-gate * structure in question is already being used. Otherwise, the CPU 698*7c478bd9Sstevel@tonic-gate * logout operation will succeed (r_val = 0). For failures, r_val 699*7c478bd9Sstevel@tonic-gate * returns the busy count (# of times we tried using this CPU logout 700*7c478bd9Sstevel@tonic-gate * structure when it was busy.) 701*7c478bd9Sstevel@tonic-gate * 702*7c478bd9Sstevel@tonic-gate * Register usage: 703*7c478bd9Sstevel@tonic-gate * %asi: Must be set to either ASI_MEM if the address in datap 704*7c478bd9Sstevel@tonic-gate * is a physical address or to ASI_N if the address in 705*7c478bd9Sstevel@tonic-gate * datap is a virtual address. 706*7c478bd9Sstevel@tonic-gate * r_val: This register is the return value which tells the 707*7c478bd9Sstevel@tonic-gate * caller whether or not the LOGOUT operation was successful. 708*7c478bd9Sstevel@tonic-gate * For failures, r_val returns the fail count (i.e. number of 709*7c478bd9Sstevel@tonic-gate * times we have tried to use this logout structure when it was 710*7c478bd9Sstevel@tonic-gate * already being used. 711*7c478bd9Sstevel@tonic-gate * afar: output: contains AFAR on exit 712*7c478bd9Sstevel@tonic-gate * t_flags: input trap type info, may be used as scratch after stored 713*7c478bd9Sstevel@tonic-gate * to cpu log out structure. 714*7c478bd9Sstevel@tonic-gate * datap: Points to log out data area. 715*7c478bd9Sstevel@tonic-gate * scr1: Scratch 716*7c478bd9Sstevel@tonic-gate * scr2: Scratch (may be r_val) 717*7c478bd9Sstevel@tonic-gate * scr3: Scratch (may be t_flags) 718*7c478bd9Sstevel@tonic-gate */ 719*7c478bd9Sstevel@tonic-gate #define DO_TL1_CPU_LOGOUT(r_val, afar, t_flags, datap, scr1, scr2, scr3) \ 720*7c478bd9Sstevel@tonic-gate setx LOGOUT_INVALID, scr2, scr1; \ 721*7c478bd9Sstevel@tonic-gate ldxa [datap + (CH_CLO_DATA + CH_CHD_AFAR)]%asi, scr2; \ 722*7c478bd9Sstevel@tonic-gate cmp scr2, scr1; \ 723*7c478bd9Sstevel@tonic-gate bne 8f; \ 724*7c478bd9Sstevel@tonic-gate nop; \ 725*7c478bd9Sstevel@tonic-gate stxa t_flags, [datap + CH_CLO_FLAGS]%asi; \ 726*7c478bd9Sstevel@tonic-gate GET_AFSR_AFAR(datap, afar, scr1, scr2); \ 727*7c478bd9Sstevel@tonic-gate add datap, CH_CLO_DATA + CH_CHD_EC_DATA, datap; \ 728*7c478bd9Sstevel@tonic-gate GET_ECACHE_DTAGS(afar, datap, scr1, scr2, scr3); \ 729*7c478bd9Sstevel@tonic-gate GET_DCACHE_DTAG(afar, datap, scr1, scr2, scr3); \ 730*7c478bd9Sstevel@tonic-gate GET_ICACHE_DTAG(afar, datap, scr1, scr2, scr3); \ 731*7c478bd9Sstevel@tonic-gate sub datap, CH_CLO_DATA + CH_DIAG_DATA_SIZE, datap; \ 732*7c478bd9Sstevel@tonic-gate GET_SHADOW_DATA(afar, datap, scr1, scr2, scr3); \ 733*7c478bd9Sstevel@tonic-gate ldxa [datap + (CH_CLO_DATA + CH_CHD_AFAR)]%asi, afar; \ 734*7c478bd9Sstevel@tonic-gate set 0, r_val; /* return value for success */ \ 735*7c478bd9Sstevel@tonic-gate ba 9f; \ 736*7c478bd9Sstevel@tonic-gate nop; \ 737*7c478bd9Sstevel@tonic-gate 8: \ 738*7c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_AFAR, afar; \ 739*7c478bd9Sstevel@tonic-gate ldxa [datap + CH_CLO_NEST_CNT]%asi, r_val; \ 740*7c478bd9Sstevel@tonic-gate inc r_val; /* return value for failure */ \ 741*7c478bd9Sstevel@tonic-gate stxa r_val, [datap + CH_CLO_NEST_CNT]%asi; \ 742*7c478bd9Sstevel@tonic-gate membar #Sync; \ 743*7c478bd9Sstevel@tonic-gate 9: 744*7c478bd9Sstevel@tonic-gate 745*7c478bd9Sstevel@tonic-gate /* 746*7c478bd9Sstevel@tonic-gate * Cheetah/(Cheetah+ Jaguar Panther)/Jalapeno Macro for capturing CPU 747*7c478bd9Sstevel@tonic-gate * logout data. Uses DO_TL1_CPU_LOGOUT macro defined above, and sets 748*7c478bd9Sstevel@tonic-gate * up the expected data pointer in the scr1 register and sets the %asi 749*7c478bd9Sstevel@tonic-gate * register to ASI_N for kernel virtual addresses instead of ASI_MEM as 750*7c478bd9Sstevel@tonic-gate * is used at TL>0. 751*7c478bd9Sstevel@tonic-gate * 752*7c478bd9Sstevel@tonic-gate * The CPU logout operation will fail (r_val > 0) if the logout 753*7c478bd9Sstevel@tonic-gate * structure in question is already being used. Otherwise, the CPU 754*7c478bd9Sstevel@tonic-gate * logout operation will succeed (r_val = 0). For failures, r_val 755*7c478bd9Sstevel@tonic-gate * returns the busy count (# of times we tried using this CPU logout 756*7c478bd9Sstevel@tonic-gate * structure when it was busy.) 757*7c478bd9Sstevel@tonic-gate * 758*7c478bd9Sstevel@tonic-gate * Register usage: 759*7c478bd9Sstevel@tonic-gate * r_val: This register is the return value which tells the 760*7c478bd9Sstevel@tonic-gate * caller whether or not the LOGOUT operation was successful. 761*7c478bd9Sstevel@tonic-gate * For failures, r_val returns the fail count (i.e. number of 762*7c478bd9Sstevel@tonic-gate * times we have tried to use this logout structure when it was 763*7c478bd9Sstevel@tonic-gate * already being used. 764*7c478bd9Sstevel@tonic-gate * afar: returns AFAR, used internally as afar value. 765*7c478bd9Sstevel@tonic-gate * output: if the cpu_private struct has not been initialized, 766*7c478bd9Sstevel@tonic-gate * then we return the t_flags value listed below. 767*7c478bd9Sstevel@tonic-gate * r_or_s: input offset, either register or constant (symbol). It's 768*7c478bd9Sstevel@tonic-gate * OK for r_or_s to be a register as long as it's not scr1 or 769*7c478bd9Sstevel@tonic-gate * scr3. 770*7c478bd9Sstevel@tonic-gate * t_flags: input trap type info, may be used as scratch after stored 771*7c478bd9Sstevel@tonic-gate * to cpu log out structure. 772*7c478bd9Sstevel@tonic-gate * scr1: Scratch, points to log out data area. 773*7c478bd9Sstevel@tonic-gate * scr2: Scratch (may be r_or_s) 774*7c478bd9Sstevel@tonic-gate * scr3: Scratch (may be r_val) 775*7c478bd9Sstevel@tonic-gate * scr4: Scratch (may be t_flags) 776*7c478bd9Sstevel@tonic-gate */ 777*7c478bd9Sstevel@tonic-gate #define DO_CPU_LOGOUT(r_val, afar, r_or_s, t_flags, scr1, scr2, scr3, scr4) \ 778*7c478bd9Sstevel@tonic-gate GET_CPU_PRIVATE_PTR(r_or_s, scr1, scr3, 7f); /* can't use scr2/4 */ \ 779*7c478bd9Sstevel@tonic-gate wr %g0, ASI_N, %asi; \ 780*7c478bd9Sstevel@tonic-gate DO_TL1_CPU_LOGOUT(r_val, afar, t_flags, scr1, scr2, scr3, scr4) \ 781*7c478bd9Sstevel@tonic-gate ba 6f; \ 782*7c478bd9Sstevel@tonic-gate nop; \ 783*7c478bd9Sstevel@tonic-gate 7: \ 784*7c478bd9Sstevel@tonic-gate mov t_flags, afar; /* depends on afar = %g2 */ \ 785*7c478bd9Sstevel@tonic-gate set 0, r_val; /* success in this case. */ \ 786*7c478bd9Sstevel@tonic-gate 6: 787*7c478bd9Sstevel@tonic-gate 788*7c478bd9Sstevel@tonic-gate /* 789*7c478bd9Sstevel@tonic-gate * The P$ is flushed as a side effect of writing to the Primary 790*7c478bd9Sstevel@tonic-gate * or Secondary Context Register. After writing to a context 791*7c478bd9Sstevel@tonic-gate * register, every line of the P$ in the Valid state is invalidated, 792*7c478bd9Sstevel@tonic-gate * regardless of which context it belongs to. 793*7c478bd9Sstevel@tonic-gate * This routine simply touches the Primary context register by 794*7c478bd9Sstevel@tonic-gate * reading the current value and writing it back. The Primary 795*7c478bd9Sstevel@tonic-gate * context is not changed. 796*7c478bd9Sstevel@tonic-gate */ 797*7c478bd9Sstevel@tonic-gate #define PCACHE_FLUSHALL(tmp1, tmp2, tmp3) \ 798*7c478bd9Sstevel@tonic-gate sethi %hi(FLUSH_ADDR), tmp1 ;\ 799*7c478bd9Sstevel@tonic-gate set MMU_PCONTEXT, tmp2 ;\ 800*7c478bd9Sstevel@tonic-gate ldxa [tmp2]ASI_DMMU, tmp3 ;\ 801*7c478bd9Sstevel@tonic-gate stxa tmp3, [tmp2]ASI_DMMU ;\ 802*7c478bd9Sstevel@tonic-gate flush tmp1 /* See Cheetah PRM 8.10.2 */ 803*7c478bd9Sstevel@tonic-gate 804*7c478bd9Sstevel@tonic-gate /* 805*7c478bd9Sstevel@tonic-gate * Macro that flushes the entire Dcache. 806*7c478bd9Sstevel@tonic-gate * 807*7c478bd9Sstevel@tonic-gate * arg1 = dcache size 808*7c478bd9Sstevel@tonic-gate * arg2 = dcache linesize 809*7c478bd9Sstevel@tonic-gate */ 810*7c478bd9Sstevel@tonic-gate #define CH_DCACHE_FLUSHALL(arg1, arg2, tmp1) \ 811*7c478bd9Sstevel@tonic-gate sub arg1, arg2, tmp1; \ 812*7c478bd9Sstevel@tonic-gate 1: \ 813*7c478bd9Sstevel@tonic-gate stxa %g0, [tmp1]ASI_DC_TAG; \ 814*7c478bd9Sstevel@tonic-gate membar #Sync; \ 815*7c478bd9Sstevel@tonic-gate cmp %g0, tmp1; \ 816*7c478bd9Sstevel@tonic-gate bne,pt %icc, 1b; \ 817*7c478bd9Sstevel@tonic-gate sub tmp1, arg2, tmp1; 818*7c478bd9Sstevel@tonic-gate 819*7c478bd9Sstevel@tonic-gate /* 820*7c478bd9Sstevel@tonic-gate * Macro that flushes the entire Icache. 821*7c478bd9Sstevel@tonic-gate * 822*7c478bd9Sstevel@tonic-gate * Note that we cannot access ASI 0x67 (ASI_IC_TAG) with the Icache on, 823*7c478bd9Sstevel@tonic-gate * because accesses to ASI 0x67 interfere with Icache coherency. We 824*7c478bd9Sstevel@tonic-gate * must make sure the Icache is off, then turn it back on after the entire 825*7c478bd9Sstevel@tonic-gate * cache has been invalidated. If the Icache is originally off, we'll just 826*7c478bd9Sstevel@tonic-gate * clear the tags but not turn the Icache on. 827*7c478bd9Sstevel@tonic-gate * 828*7c478bd9Sstevel@tonic-gate * arg1 = icache size 829*7c478bd9Sstevel@tonic-gate * arg2 = icache linesize 830*7c478bd9Sstevel@tonic-gate */ 831*7c478bd9Sstevel@tonic-gate #define CH_ICACHE_FLUSHALL(arg1, arg2, tmp1, tmp2) \ 832*7c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_DCU, tmp2; \ 833*7c478bd9Sstevel@tonic-gate andn tmp2, DCU_IC, tmp1; \ 834*7c478bd9Sstevel@tonic-gate stxa tmp1, [%g0]ASI_DCU; \ 835*7c478bd9Sstevel@tonic-gate flush %g0; /* flush required after changing the IC bit */ \ 836*7c478bd9Sstevel@tonic-gate sllx arg2, 1, arg2; /* arg2 = linesize * 2 */ \ 837*7c478bd9Sstevel@tonic-gate sllx arg1, 1, arg1; /* arg1 = size * 2 */ \ 838*7c478bd9Sstevel@tonic-gate sub arg1, arg2, arg1; \ 839*7c478bd9Sstevel@tonic-gate or arg1, CH_ICTAG_LOWER, arg1; /* "write" tag */ \ 840*7c478bd9Sstevel@tonic-gate 1: \ 841*7c478bd9Sstevel@tonic-gate stxa %g0, [arg1]ASI_IC_TAG; \ 842*7c478bd9Sstevel@tonic-gate membar #Sync; /* Cheetah PRM 8.9.3 */ \ 843*7c478bd9Sstevel@tonic-gate cmp arg1, CH_ICTAG_LOWER; \ 844*7c478bd9Sstevel@tonic-gate bne,pt %icc, 1b; \ 845*7c478bd9Sstevel@tonic-gate sub arg1, arg2, arg1; \ 846*7c478bd9Sstevel@tonic-gate stxa tmp2, [%g0]ASI_DCU; \ 847*7c478bd9Sstevel@tonic-gate flush %g0; /* flush required after changing the IC bit */ 848*7c478bd9Sstevel@tonic-gate 849*7c478bd9Sstevel@tonic-gate 850*7c478bd9Sstevel@tonic-gate #if defined(JALAPENO) || defined(SERRANO) 851*7c478bd9Sstevel@tonic-gate 852*7c478bd9Sstevel@tonic-gate /* 853*7c478bd9Sstevel@tonic-gate * ASI access to the L2 tag or L2 flush can hang the cpu when interacting 854*7c478bd9Sstevel@tonic-gate * with combinations of L2 snoops, victims and stores. 855*7c478bd9Sstevel@tonic-gate * 856*7c478bd9Sstevel@tonic-gate * A possible workaround is to surround each L2 ASI access with membars 857*7c478bd9Sstevel@tonic-gate * and make sure that the code is hitting in the Icache. This requires 858*7c478bd9Sstevel@tonic-gate * aligning code sequence at E$ boundary and forcing I$ fetch by 859*7c478bd9Sstevel@tonic-gate * jumping to selected offsets so that we don't take any I$ misses 860*7c478bd9Sstevel@tonic-gate * during ASI access to the L2 tag or L2 flush. This also requires 861*7c478bd9Sstevel@tonic-gate * making sure that we don't take any interrupts or traps (such as 862*7c478bd9Sstevel@tonic-gate * fast ECC trap, I$/D$ tag parity error) which can result in eviction 863*7c478bd9Sstevel@tonic-gate * of this code sequence from I$, thus causing a miss. 864*7c478bd9Sstevel@tonic-gate * 865*7c478bd9Sstevel@tonic-gate * Because of the complexity/risk, we have decided to do a partial fix 866*7c478bd9Sstevel@tonic-gate * of adding membar around each ASI access to the L2 tag or L2 flush. 867*7c478bd9Sstevel@tonic-gate */ 868*7c478bd9Sstevel@tonic-gate 869*7c478bd9Sstevel@tonic-gate #define JP_EC_DIAG_ACCESS_MEMBAR \ 870*7c478bd9Sstevel@tonic-gate membar #Sync 871*7c478bd9Sstevel@tonic-gate 872*7c478bd9Sstevel@tonic-gate /* 873*7c478bd9Sstevel@tonic-gate * Jalapeno version of macro that flushes the entire Ecache. 874*7c478bd9Sstevel@tonic-gate * 875*7c478bd9Sstevel@tonic-gate * Uses Jalapeno displacement flush feature of ASI_EC_DIAG. 876*7c478bd9Sstevel@tonic-gate * 877*7c478bd9Sstevel@tonic-gate * arg1 = ecache size 878*7c478bd9Sstevel@tonic-gate * arg2 = ecache linesize - not modified; can be an immediate constant. 879*7c478bd9Sstevel@tonic-gate */ 880*7c478bd9Sstevel@tonic-gate #define ECACHE_FLUSHALL(arg1, arg2, tmp1, tmp2) \ 881*7c478bd9Sstevel@tonic-gate CPU_INDEX(tmp1, tmp2); \ 882*7c478bd9Sstevel@tonic-gate set JP_ECACHE_IDX_DISP_FLUSH, tmp2; \ 883*7c478bd9Sstevel@tonic-gate sllx tmp1, JP_ECFLUSH_PORTID_SHIFT, tmp1; \ 884*7c478bd9Sstevel@tonic-gate or tmp1, tmp2, tmp1; \ 885*7c478bd9Sstevel@tonic-gate srlx arg1, JP_EC_TO_SET_SIZE_SHIFT, tmp2; \ 886*7c478bd9Sstevel@tonic-gate 1: \ 887*7c478bd9Sstevel@tonic-gate subcc tmp2, arg2, tmp2; \ 888*7c478bd9Sstevel@tonic-gate JP_EC_DIAG_ACCESS_MEMBAR; \ 889*7c478bd9Sstevel@tonic-gate ldxa [tmp1 + tmp2]ASI_EC_DIAG, %g0; \ 890*7c478bd9Sstevel@tonic-gate JP_EC_DIAG_ACCESS_MEMBAR; \ 891*7c478bd9Sstevel@tonic-gate bg,pt %xcc, 1b; \ 892*7c478bd9Sstevel@tonic-gate nop; \ 893*7c478bd9Sstevel@tonic-gate mov 1, tmp2; \ 894*7c478bd9Sstevel@tonic-gate sllx tmp2, JP_ECFLUSH_EC_WAY_SHIFT, tmp2; \ 895*7c478bd9Sstevel@tonic-gate add tmp1, tmp2, tmp1; \ 896*7c478bd9Sstevel@tonic-gate mov (JP_ECACHE_NWAY-1), tmp2; \ 897*7c478bd9Sstevel@tonic-gate sllx tmp2, JP_ECFLUSH_EC_WAY_SHIFT, tmp2; \ 898*7c478bd9Sstevel@tonic-gate andcc tmp1, tmp2, tmp2; \ 899*7c478bd9Sstevel@tonic-gate bnz,pt %xcc, 1b; \ 900*7c478bd9Sstevel@tonic-gate srlx arg1, JP_EC_TO_SET_SIZE_SHIFT, tmp2 901*7c478bd9Sstevel@tonic-gate 902*7c478bd9Sstevel@tonic-gate #else /* JALAPENO || SERRANO */ 903*7c478bd9Sstevel@tonic-gate 904*7c478bd9Sstevel@tonic-gate /* 905*7c478bd9Sstevel@tonic-gate * Cheetah version of macro that flushes the entire Ecache. 906*7c478bd9Sstevel@tonic-gate * 907*7c478bd9Sstevel@tonic-gate * Need to displacement flush 2x ecache size from Ecache flush area. 908*7c478bd9Sstevel@tonic-gate * 909*7c478bd9Sstevel@tonic-gate * arg1 = ecache size 910*7c478bd9Sstevel@tonic-gate * arg2 = ecache linesize 911*7c478bd9Sstevel@tonic-gate * arg3 = ecache flush address - for cheetah only 912*7c478bd9Sstevel@tonic-gate */ 913*7c478bd9Sstevel@tonic-gate #define CH_ECACHE_FLUSHALL(arg1, arg2, arg3) \ 914*7c478bd9Sstevel@tonic-gate sllx arg1, 1, arg1; \ 915*7c478bd9Sstevel@tonic-gate 1: \ 916*7c478bd9Sstevel@tonic-gate subcc arg1, arg2, arg1; \ 917*7c478bd9Sstevel@tonic-gate bg,pt %xcc, 1b; \ 918*7c478bd9Sstevel@tonic-gate ldxa [arg1 + arg3]ASI_MEM, %g0; 919*7c478bd9Sstevel@tonic-gate 920*7c478bd9Sstevel@tonic-gate /* 921*7c478bd9Sstevel@tonic-gate * Cheetah+ version of macro that flushes the entire Ecache. 922*7c478bd9Sstevel@tonic-gate * 923*7c478bd9Sstevel@tonic-gate * Uses the displacement flush feature. 924*7c478bd9Sstevel@tonic-gate * 925*7c478bd9Sstevel@tonic-gate * arg1 = ecache size 926*7c478bd9Sstevel@tonic-gate * arg2 = ecache linesize 927*7c478bd9Sstevel@tonic-gate * impl = CPU implementation as returned from GET_CPU_IMPL() 928*7c478bd9Sstevel@tonic-gate * The value in this register is destroyed during execution 929*7c478bd9Sstevel@tonic-gate * of the macro. 930*7c478bd9Sstevel@tonic-gate */ 931*7c478bd9Sstevel@tonic-gate #if defined(CHEETAH_PLUS) 932*7c478bd9Sstevel@tonic-gate #define CHP_ECACHE_FLUSHALL(arg1, arg2, impl) \ 933*7c478bd9Sstevel@tonic-gate cmp impl, PANTHER_IMPL; \ 934*7c478bd9Sstevel@tonic-gate bne %xcc, 1f; \ 935*7c478bd9Sstevel@tonic-gate nop; \ 936*7c478bd9Sstevel@tonic-gate set PN_L3_IDX_DISP_FLUSH, impl; \ 937*7c478bd9Sstevel@tonic-gate b 2f; \ 938*7c478bd9Sstevel@tonic-gate nop; \ 939*7c478bd9Sstevel@tonic-gate 1: \ 940*7c478bd9Sstevel@tonic-gate set CHP_ECACHE_IDX_DISP_FLUSH, impl; \ 941*7c478bd9Sstevel@tonic-gate 2: \ 942*7c478bd9Sstevel@tonic-gate subcc arg1, arg2, arg1; \ 943*7c478bd9Sstevel@tonic-gate bg,pt %xcc, 2b; \ 944*7c478bd9Sstevel@tonic-gate ldxa [arg1 + impl]ASI_EC_DIAG, %g0; 945*7c478bd9Sstevel@tonic-gate #else /* CHEETAH_PLUS */ 946*7c478bd9Sstevel@tonic-gate #define CHP_ECACHE_FLUSHALL(arg1, arg2, impl) 947*7c478bd9Sstevel@tonic-gate #endif /* CHEETAH_PLUS */ 948*7c478bd9Sstevel@tonic-gate 949*7c478bd9Sstevel@tonic-gate /* 950*7c478bd9Sstevel@tonic-gate * Macro that flushes the entire Ecache. 951*7c478bd9Sstevel@tonic-gate * 952*7c478bd9Sstevel@tonic-gate * arg1 = ecache size 953*7c478bd9Sstevel@tonic-gate * arg2 = ecache linesize 954*7c478bd9Sstevel@tonic-gate * arg3 = ecache flush address - for cheetah only 955*7c478bd9Sstevel@tonic-gate */ 956*7c478bd9Sstevel@tonic-gate #define ECACHE_FLUSHALL(arg1, arg2, arg3, tmp1) \ 957*7c478bd9Sstevel@tonic-gate GET_CPU_IMPL(tmp1); \ 958*7c478bd9Sstevel@tonic-gate cmp tmp1, CHEETAH_IMPL; \ 959*7c478bd9Sstevel@tonic-gate bne %xcc, 2f; \ 960*7c478bd9Sstevel@tonic-gate nop; \ 961*7c478bd9Sstevel@tonic-gate CH_ECACHE_FLUSHALL(arg1, arg2, arg3); \ 962*7c478bd9Sstevel@tonic-gate ba 3f; \ 963*7c478bd9Sstevel@tonic-gate nop; \ 964*7c478bd9Sstevel@tonic-gate 2: \ 965*7c478bd9Sstevel@tonic-gate CHP_ECACHE_FLUSHALL(arg1, arg2, tmp1); \ 966*7c478bd9Sstevel@tonic-gate 3: 967*7c478bd9Sstevel@tonic-gate 968*7c478bd9Sstevel@tonic-gate #endif /* JALAPENO || SERRANO */ 969*7c478bd9Sstevel@tonic-gate 970*7c478bd9Sstevel@tonic-gate /* 971*7c478bd9Sstevel@tonic-gate * Macro that flushes the Panther L2 cache. 972*7c478bd9Sstevel@tonic-gate */ 973*7c478bd9Sstevel@tonic-gate #if defined(CHEETAH_PLUS) 974*7c478bd9Sstevel@tonic-gate #define PN_L2_FLUSHALL(scr1, scr2, scr3) \ 975*7c478bd9Sstevel@tonic-gate GET_CPU_IMPL(scr3); \ 976*7c478bd9Sstevel@tonic-gate cmp scr3, PANTHER_IMPL; \ 977*7c478bd9Sstevel@tonic-gate bne %xcc, 2f; \ 978*7c478bd9Sstevel@tonic-gate nop; \ 979*7c478bd9Sstevel@tonic-gate set PN_L2_SIZE, scr1; \ 980*7c478bd9Sstevel@tonic-gate set PN_L2_LINESIZE, scr2; \ 981*7c478bd9Sstevel@tonic-gate set PN_L2_IDX_DISP_FLUSH, scr3; \ 982*7c478bd9Sstevel@tonic-gate 1: \ 983*7c478bd9Sstevel@tonic-gate subcc scr1, scr2, scr1; \ 984*7c478bd9Sstevel@tonic-gate bg,pt %xcc, 1b; \ 985*7c478bd9Sstevel@tonic-gate ldxa [scr1 + scr3]ASI_L2_TAG, %g0; \ 986*7c478bd9Sstevel@tonic-gate 2: 987*7c478bd9Sstevel@tonic-gate #else /* CHEETAH_PLUS */ 988*7c478bd9Sstevel@tonic-gate #define PN_L2_FLUSHALL(scr1, scr2, scr3) 989*7c478bd9Sstevel@tonic-gate #endif /* CHEETAH_PLUS */ 990*7c478bd9Sstevel@tonic-gate 991*7c478bd9Sstevel@tonic-gate /* 992*7c478bd9Sstevel@tonic-gate * Given a VA and page size (page size as encoded in ASI_MMU_TAG_ACCESS_EXT), 993*7c478bd9Sstevel@tonic-gate * this macro returns the TLB index for that mapping based on a 512 entry 994*7c478bd9Sstevel@tonic-gate * (2-way set associative) TLB. Aaside from the 16 entry fully associative 995*7c478bd9Sstevel@tonic-gate * TLBs, all TLBs in Panther are 512 entry, 2-way set associative. 996*7c478bd9Sstevel@tonic-gate * 997*7c478bd9Sstevel@tonic-gate * To find the index, we shift the VA right by 13 + (3 * pg_sz) and then 998*7c478bd9Sstevel@tonic-gate * mask out all but the lower 8 bits because: 999*7c478bd9Sstevel@tonic-gate * 1000*7c478bd9Sstevel@tonic-gate * ASI_[D|I]MMU_TAG_ACCESS_EXT.PgSz = 0 for 8K 1001*7c478bd9Sstevel@tonic-gate * ASI_[D|I]MMU_TAG_ACCESS_EXT.PgSz = 1 for 64K 1002*7c478bd9Sstevel@tonic-gate * ASI_[D|I]MMU_TAG_ACCESS_EXT.PgSz = 2 for 512K 1003*7c478bd9Sstevel@tonic-gate * ASI_[D|I]MMU_TAG_ACCESS_EXT.PgSz = 3 for 4M 1004*7c478bd9Sstevel@tonic-gate * ASI_[D|I]MMU_TAG_ACCESS_EXT.PgSz = 4 for 32M 1005*7c478bd9Sstevel@tonic-gate * ASI_[D|I]MMU_TAG_ACCESS_EXT.PgSz = 5 for 256M 1006*7c478bd9Sstevel@tonic-gate * 1007*7c478bd9Sstevel@tonic-gate * and 1008*7c478bd9Sstevel@tonic-gate * 1009*7c478bd9Sstevel@tonic-gate * array index for 8K pages = VA[20:13] 1010*7c478bd9Sstevel@tonic-gate * array index for 64K pages = VA[23:16] 1011*7c478bd9Sstevel@tonic-gate * array index for 512K pages = VA[26:19] 1012*7c478bd9Sstevel@tonic-gate * array index for 4M pages = VA[29:22] 1013*7c478bd9Sstevel@tonic-gate * array index for 32M pages = VA[32:25] 1014*7c478bd9Sstevel@tonic-gate * array index for 256M pages = VA[35:28] 1015*7c478bd9Sstevel@tonic-gate * 1016*7c478bd9Sstevel@tonic-gate * Inputs: 1017*7c478bd9Sstevel@tonic-gate * 1018*7c478bd9Sstevel@tonic-gate * va - Register. 1019*7c478bd9Sstevel@tonic-gate * Input: Virtual address in which we are interested. 1020*7c478bd9Sstevel@tonic-gate * Output: TLB index value. 1021*7c478bd9Sstevel@tonic-gate * pg_sz - Register. Page Size of the TLB in question as encoded 1022*7c478bd9Sstevel@tonic-gate * in the ASI_[D|I]MMU_TAG_ACCESS_EXT register. 1023*7c478bd9Sstevel@tonic-gate */ 1024*7c478bd9Sstevel@tonic-gate #if defined(CHEETAH_PLUS) 1025*7c478bd9Sstevel@tonic-gate #define PN_GET_TLB_INDEX(va, pg_sz) \ 1026*7c478bd9Sstevel@tonic-gate srlx va, 13, va; /* first shift the 13 bits and then */ \ 1027*7c478bd9Sstevel@tonic-gate srlx va, pg_sz, va; /* shift by pg_sz three times. */ \ 1028*7c478bd9Sstevel@tonic-gate srlx va, pg_sz, va; \ 1029*7c478bd9Sstevel@tonic-gate srlx va, pg_sz, va; \ 1030*7c478bd9Sstevel@tonic-gate and va, 0xff, va; /* mask out all but the lower 8 bits */ 1031*7c478bd9Sstevel@tonic-gate #endif /* CHEETAH_PLUS */ 1032*7c478bd9Sstevel@tonic-gate 1033*7c478bd9Sstevel@tonic-gate /* 1034*7c478bd9Sstevel@tonic-gate * The following macros are for error traps at TL>0. 1035*7c478bd9Sstevel@tonic-gate * The issue with error traps at TL>0 is that there are no safely 1036*7c478bd9Sstevel@tonic-gate * available global registers. So we use the trick of generating a 1037*7c478bd9Sstevel@tonic-gate * software trap, then using the %tpc, %tnpc and %tstate registers to 1038*7c478bd9Sstevel@tonic-gate * temporarily save the values of %g1 and %g2. 1039*7c478bd9Sstevel@tonic-gate */ 1040*7c478bd9Sstevel@tonic-gate 1041*7c478bd9Sstevel@tonic-gate /* 1042*7c478bd9Sstevel@tonic-gate * Macro to generate 8-instruction trap table entry for TL>0 trap handlers. 1043*7c478bd9Sstevel@tonic-gate * Does the following steps: 1044*7c478bd9Sstevel@tonic-gate * 1. membar #Sync - required for USIII family errors. 1045*7c478bd9Sstevel@tonic-gate * 2. Specified software trap. 1046*7c478bd9Sstevel@tonic-gate * NB: Must be 8 instructions or less to fit in trap table and code must 1047*7c478bd9Sstevel@tonic-gate * be relocatable. 1048*7c478bd9Sstevel@tonic-gate */ 1049*7c478bd9Sstevel@tonic-gate #define CH_ERR_TL1_TRAPENTRY(trapno) \ 1050*7c478bd9Sstevel@tonic-gate membar #Sync; \ 1051*7c478bd9Sstevel@tonic-gate ta trapno; \ 1052*7c478bd9Sstevel@tonic-gate nop; nop; nop; nop; nop; nop 1053*7c478bd9Sstevel@tonic-gate 1054*7c478bd9Sstevel@tonic-gate /* 1055*7c478bd9Sstevel@tonic-gate * Macro to generate 8-instruction trap table entry for TL>0 software trap. 1056*7c478bd9Sstevel@tonic-gate * We save the values of %g1 and %g2 in %tpc, %tnpc and %tstate (since 1057*7c478bd9Sstevel@tonic-gate * the low-order two bits of %tpc/%tnpc are reserved and read as zero, 1058*7c478bd9Sstevel@tonic-gate * we need to put the low-order two bits of %g1 and %g2 in %tstate). 1059*7c478bd9Sstevel@tonic-gate * Note that %tstate has a reserved hole from bits 3-7, so we put the 1060*7c478bd9Sstevel@tonic-gate * low-order two bits of %g1 in bits 0-1 and the low-order two bits of 1061*7c478bd9Sstevel@tonic-gate * %g2 in bits 10-11 (insuring bits 8-9 are zero for use by the D$/I$ 1062*7c478bd9Sstevel@tonic-gate * state bits). Note that we must do a jmp instruction, since this 1063*7c478bd9Sstevel@tonic-gate * is moved into the trap table entry. 1064*7c478bd9Sstevel@tonic-gate * NB: Must be 8 instructions or less to fit in trap table and code must 1065*7c478bd9Sstevel@tonic-gate * be relocatable. 1066*7c478bd9Sstevel@tonic-gate */ 1067*7c478bd9Sstevel@tonic-gate #define CH_ERR_TL1_SWTRAPENTRY(label) \ 1068*7c478bd9Sstevel@tonic-gate wrpr %g1, %tpc; \ 1069*7c478bd9Sstevel@tonic-gate and %g1, 3, %g1; \ 1070*7c478bd9Sstevel@tonic-gate wrpr %g2, %tnpc; \ 1071*7c478bd9Sstevel@tonic-gate sllx %g2, CH_ERR_G2_TO_TSTATE_SHFT, %g2; \ 1072*7c478bd9Sstevel@tonic-gate or %g1, %g2, %g2; \ 1073*7c478bd9Sstevel@tonic-gate sethi %hi(label), %g1; \ 1074*7c478bd9Sstevel@tonic-gate jmp %g1+%lo(label); \ 1075*7c478bd9Sstevel@tonic-gate wrpr %g2, %tstate 1076*7c478bd9Sstevel@tonic-gate 1077*7c478bd9Sstevel@tonic-gate /* 1078*7c478bd9Sstevel@tonic-gate * Macro to get ptr to ch_err_tl1_data. 1079*7c478bd9Sstevel@tonic-gate * reg1 will either point to a physaddr with ASI_MEM in %asi OR it 1080*7c478bd9Sstevel@tonic-gate * will point to a kernel nucleus virtual address with ASI_N in %asi. 1081*7c478bd9Sstevel@tonic-gate * This allows us to: 1082*7c478bd9Sstevel@tonic-gate * 1. Avoid getting MMU misses. We may have gotten the original 1083*7c478bd9Sstevel@tonic-gate * Fast ECC error in an MMU handler and if we get an MMU trap 1084*7c478bd9Sstevel@tonic-gate * in the TL>0 handlers, we'll scribble on the MMU regs. 1085*7c478bd9Sstevel@tonic-gate * 2. Allows us to use the same code in the TL>0 handlers whether 1086*7c478bd9Sstevel@tonic-gate * we're accessing kernel nucleus virtual addresses or physical 1087*7c478bd9Sstevel@tonic-gate * addresses. 1088*7c478bd9Sstevel@tonic-gate * pseudo-code: 1089*7c478bd9Sstevel@tonic-gate * reg1 <- ch_err_tl1_paddrs[CPUID]; 1090*7c478bd9Sstevel@tonic-gate * if (reg1 == NULL) { 1091*7c478bd9Sstevel@tonic-gate * reg1 <- &ch_err_tl1_data 1092*7c478bd9Sstevel@tonic-gate * %asi <- ASI_N 1093*7c478bd9Sstevel@tonic-gate * } else { 1094*7c478bd9Sstevel@tonic-gate * reg1 <- reg1 + offset + 1095*7c478bd9Sstevel@tonic-gate * sizeof (ch_err_tl1_data) * (%tl - 3) 1096*7c478bd9Sstevel@tonic-gate * %asi <- ASI_MEM 1097*7c478bd9Sstevel@tonic-gate * } 1098*7c478bd9Sstevel@tonic-gate */ 1099*7c478bd9Sstevel@tonic-gate #define GET_CH_ERR_TL1_PTR(reg1, reg2, offset) \ 1100*7c478bd9Sstevel@tonic-gate CPU_INDEX(reg1, reg2); \ 1101*7c478bd9Sstevel@tonic-gate sllx reg1, 3, reg1; \ 1102*7c478bd9Sstevel@tonic-gate set ch_err_tl1_paddrs, reg2; \ 1103*7c478bd9Sstevel@tonic-gate ldx [reg1+reg2], reg1; \ 1104*7c478bd9Sstevel@tonic-gate brnz reg1, 1f; \ 1105*7c478bd9Sstevel@tonic-gate add reg1, offset, reg1; \ 1106*7c478bd9Sstevel@tonic-gate set ch_err_tl1_data, reg1; \ 1107*7c478bd9Sstevel@tonic-gate ba 2f; \ 1108*7c478bd9Sstevel@tonic-gate wr %g0, ASI_N, %asi; \ 1109*7c478bd9Sstevel@tonic-gate 1: rdpr %tl, reg2; \ 1110*7c478bd9Sstevel@tonic-gate sub reg2, 3, reg2; \ 1111*7c478bd9Sstevel@tonic-gate mulx reg2, CH_ERR_TL1_DATA_SIZE, reg2; \ 1112*7c478bd9Sstevel@tonic-gate add reg1, reg2, reg1; \ 1113*7c478bd9Sstevel@tonic-gate wr %g0, ASI_MEM, %asi; \ 1114*7c478bd9Sstevel@tonic-gate 2: 1115*7c478bd9Sstevel@tonic-gate 1116*7c478bd9Sstevel@tonic-gate /* 1117*7c478bd9Sstevel@tonic-gate * Macro to generate entry code for TL>0 error handlers. 1118*7c478bd9Sstevel@tonic-gate * At the end of this macro, %g1 will point to the ch_err_tl1_data 1119*7c478bd9Sstevel@tonic-gate * structure and %g2 will have the original flags in the ch_err_tl1_data 1120*7c478bd9Sstevel@tonic-gate * structure and %g5 will have the value of %tstate where the Fast ECC 1121*7c478bd9Sstevel@tonic-gate * routines will save the state of the D$ in Bit2 CH_ERR_TSTATE_DC_ON. 1122*7c478bd9Sstevel@tonic-gate * All %g registers except for %g1, %g2 and %g5 will be available after 1123*7c478bd9Sstevel@tonic-gate * this macro. 1124*7c478bd9Sstevel@tonic-gate * Does the following steps: 1125*7c478bd9Sstevel@tonic-gate * 1. Compute physical address of per-cpu/per-tl save area using 1126*7c478bd9Sstevel@tonic-gate * only %g1+%g2 (which we've saved in %tpc, %tnpc, %tstate) 1127*7c478bd9Sstevel@tonic-gate * leaving address in %g1 and updating the %asi register. 1128*7c478bd9Sstevel@tonic-gate * If there is no data area available, we branch to label. 1129*7c478bd9Sstevel@tonic-gate * 2. Save %g3-%g7 in save area. 1130*7c478bd9Sstevel@tonic-gate * 3. Save %tpc->%g3, %tnpc->%g4, %tstate->%g5, which contain 1131*7c478bd9Sstevel@tonic-gate * original %g1+%g2 values (because we're going to change %tl). 1132*7c478bd9Sstevel@tonic-gate * 4. set %tl <- %tl - 1. We do this ASAP to make window of 1133*7c478bd9Sstevel@tonic-gate * running at %tl+1 as small as possible. 1134*7c478bd9Sstevel@tonic-gate * 5. Reconstitute %g1+%g2 from %tpc (%g3), %tnpc (%g4), 1135*7c478bd9Sstevel@tonic-gate * %tstate (%g5) and save in save area, carefully preserving %g5 1136*7c478bd9Sstevel@tonic-gate * because it has the CH_ERR_TSTATE_DC_ON value. 1137*7c478bd9Sstevel@tonic-gate * 6. Load existing ch_err_tl1_data flags in %g2 1138*7c478bd9Sstevel@tonic-gate * 7. Compute the new flags 1139*7c478bd9Sstevel@tonic-gate * 8. If %g2 is non-zero (the structure was busy), shift the new 1140*7c478bd9Sstevel@tonic-gate * flags by CH_ERR_ME_SHIFT and or them with the old flags. 1141*7c478bd9Sstevel@tonic-gate * 9. Store the updated flags into ch_err_tl1_data flags. 1142*7c478bd9Sstevel@tonic-gate * 10. If %g2 is non-zero, read the %tpc and store it in 1143*7c478bd9Sstevel@tonic-gate * ch_err_tl1_data. 1144*7c478bd9Sstevel@tonic-gate */ 1145*7c478bd9Sstevel@tonic-gate #define CH_ERR_TL1_ENTER(flags) \ 1146*7c478bd9Sstevel@tonic-gate GET_CH_ERR_TL1_PTR(%g1, %g2, CHPR_TL1_ERR_DATA); \ 1147*7c478bd9Sstevel@tonic-gate stxa %g3, [%g1 + CH_ERR_TL1_G3]%asi; \ 1148*7c478bd9Sstevel@tonic-gate stxa %g4, [%g1 + CH_ERR_TL1_G4]%asi; \ 1149*7c478bd9Sstevel@tonic-gate stxa %g5, [%g1 + CH_ERR_TL1_G5]%asi; \ 1150*7c478bd9Sstevel@tonic-gate stxa %g6, [%g1 + CH_ERR_TL1_G6]%asi; \ 1151*7c478bd9Sstevel@tonic-gate stxa %g7, [%g1 + CH_ERR_TL1_G7]%asi; \ 1152*7c478bd9Sstevel@tonic-gate rdpr %tpc, %g3; \ 1153*7c478bd9Sstevel@tonic-gate rdpr %tnpc, %g4; \ 1154*7c478bd9Sstevel@tonic-gate rdpr %tstate, %g5; \ 1155*7c478bd9Sstevel@tonic-gate rdpr %tl, %g6; \ 1156*7c478bd9Sstevel@tonic-gate sub %g6, 1, %g6; \ 1157*7c478bd9Sstevel@tonic-gate wrpr %g6, %tl; \ 1158*7c478bd9Sstevel@tonic-gate and %g5, 3, %g6; \ 1159*7c478bd9Sstevel@tonic-gate andn %g3, 3, %g3; \ 1160*7c478bd9Sstevel@tonic-gate or %g3, %g6, %g3; \ 1161*7c478bd9Sstevel@tonic-gate stxa %g3, [%g1 + CH_ERR_TL1_G1]%asi; \ 1162*7c478bd9Sstevel@tonic-gate srlx %g5, CH_ERR_G2_TO_TSTATE_SHFT, %g6; \ 1163*7c478bd9Sstevel@tonic-gate and %g6, 3, %g6; \ 1164*7c478bd9Sstevel@tonic-gate andn %g4, 3, %g4; \ 1165*7c478bd9Sstevel@tonic-gate or %g6, %g4, %g4; \ 1166*7c478bd9Sstevel@tonic-gate stxa %g4, [%g1 + CH_ERR_TL1_G2]%asi; \ 1167*7c478bd9Sstevel@tonic-gate ldxa [%g1 + CH_ERR_TL1_FLAGS]%asi, %g2; \ 1168*7c478bd9Sstevel@tonic-gate set flags | CH_ERR_TL, %g3; \ 1169*7c478bd9Sstevel@tonic-gate brz %g2, 9f; \ 1170*7c478bd9Sstevel@tonic-gate sllx %g3, CH_ERR_ME_SHIFT, %g4; \ 1171*7c478bd9Sstevel@tonic-gate or %g2, %g4, %g3; \ 1172*7c478bd9Sstevel@tonic-gate 9: stxa %g3, [%g1 + CH_ERR_TL1_FLAGS]%asi; \ 1173*7c478bd9Sstevel@tonic-gate brnz %g2, 8f; \ 1174*7c478bd9Sstevel@tonic-gate rdpr %tpc, %g4; \ 1175*7c478bd9Sstevel@tonic-gate stxa %g4, [%g1 + CH_ERR_TL1_TPC]%asi; \ 1176*7c478bd9Sstevel@tonic-gate 8: 1177*7c478bd9Sstevel@tonic-gate 1178*7c478bd9Sstevel@tonic-gate /* 1179*7c478bd9Sstevel@tonic-gate * Turns off D$/I$ and saves the state of DCU_DC+DCU_IC in %tstate Bits 8+9 1180*7c478bd9Sstevel@tonic-gate * (CH_ERR_TSTATE_DC_ON/CH_ERR_TSTATE_IC_ON). This is invoked on Fast ECC 1181*7c478bd9Sstevel@tonic-gate * at TL>0 handlers because the D$ may have corrupted data and we need to 1182*7c478bd9Sstevel@tonic-gate * turn off the I$ to allow for diagnostic accesses. We then invoke 1183*7c478bd9Sstevel@tonic-gate * the normal entry macro and after it is done we save the values of 1184*7c478bd9Sstevel@tonic-gate * the original D$/I$ state, which is in %g5 bits CH_ERR_TSTATE_DC_ON/ 1185*7c478bd9Sstevel@tonic-gate * CH_ERR_TSTATE_IC_ON in ch_err_tl1_tmp. 1186*7c478bd9Sstevel@tonic-gate */ 1187*7c478bd9Sstevel@tonic-gate #define CH_ERR_TL1_FECC_ENTER \ 1188*7c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_DCU, %g1; \ 1189*7c478bd9Sstevel@tonic-gate andn %g1, DCU_DC + DCU_IC, %g2; \ 1190*7c478bd9Sstevel@tonic-gate stxa %g2, [%g0]ASI_DCU; \ 1191*7c478bd9Sstevel@tonic-gate flush %g0; /* DCU_IC need flush */ \ 1192*7c478bd9Sstevel@tonic-gate rdpr %tstate, %g2; \ 1193*7c478bd9Sstevel@tonic-gate and %g1, DCU_DC + DCU_IC, %g1; \ 1194*7c478bd9Sstevel@tonic-gate sllx %g1, CH_ERR_DCU_TO_TSTATE_SHFT, %g1; \ 1195*7c478bd9Sstevel@tonic-gate or %g1, %g2, %g2; \ 1196*7c478bd9Sstevel@tonic-gate wrpr %g2, %tstate; \ 1197*7c478bd9Sstevel@tonic-gate CH_ERR_TL1_ENTER(CH_ERR_FECC); \ 1198*7c478bd9Sstevel@tonic-gate and %g5, CH_ERR_TSTATE_DC_ON + CH_ERR_TSTATE_IC_ON, %g5; \ 1199*7c478bd9Sstevel@tonic-gate stxa %g5, [%g1 + CH_ERR_TL1_TMP]%asi 1200*7c478bd9Sstevel@tonic-gate 1201*7c478bd9Sstevel@tonic-gate /* 1202*7c478bd9Sstevel@tonic-gate * Macro to generate exit code for TL>0 error handlers. 1203*7c478bd9Sstevel@tonic-gate * We fall into this macro if we've successfully logged the error in 1204*7c478bd9Sstevel@tonic-gate * the ch_err_tl1_data structure and want the PIL15 softint to pick 1205*7c478bd9Sstevel@tonic-gate * it up and log it. 1206*7c478bd9Sstevel@tonic-gate * Does the following steps: 1207*7c478bd9Sstevel@tonic-gate * 1. Set pending flag for this cpu in ch_err_tl1_pending. 1208*7c478bd9Sstevel@tonic-gate * 2. Write %set_softint with (1<<pil) to cause a pil level trap 1209*7c478bd9Sstevel@tonic-gate * 3. Restore registers from ch_err_tl1_data, which is pointed to 1210*7c478bd9Sstevel@tonic-gate * by %g1, last register to restore is %g1 since it's pointing 1211*7c478bd9Sstevel@tonic-gate * to the save area. 1212*7c478bd9Sstevel@tonic-gate * 4. Execute retry 1213*7c478bd9Sstevel@tonic-gate */ 1214*7c478bd9Sstevel@tonic-gate #define CH_ERR_TL1_EXIT \ 1215*7c478bd9Sstevel@tonic-gate CPU_INDEX(%g2, %g3); \ 1216*7c478bd9Sstevel@tonic-gate set ch_err_tl1_pending, %g3; \ 1217*7c478bd9Sstevel@tonic-gate set -1, %g4; \ 1218*7c478bd9Sstevel@tonic-gate stb %g4, [%g2 + %g3]; \ 1219*7c478bd9Sstevel@tonic-gate mov 1, %g2; \ 1220*7c478bd9Sstevel@tonic-gate sll %g2, PIL_15, %g2; \ 1221*7c478bd9Sstevel@tonic-gate wr %g2, SET_SOFTINT; \ 1222*7c478bd9Sstevel@tonic-gate ldxa [%g1 + CH_ERR_TL1_G7]%asi, %g7; \ 1223*7c478bd9Sstevel@tonic-gate ldxa [%g1 + CH_ERR_TL1_G6]%asi, %g6; \ 1224*7c478bd9Sstevel@tonic-gate ldxa [%g1 + CH_ERR_TL1_G5]%asi, %g5; \ 1225*7c478bd9Sstevel@tonic-gate ldxa [%g1 + CH_ERR_TL1_G4]%asi, %g4; \ 1226*7c478bd9Sstevel@tonic-gate ldxa [%g1 + CH_ERR_TL1_G3]%asi, %g3; \ 1227*7c478bd9Sstevel@tonic-gate ldxa [%g1 + CH_ERR_TL1_G2]%asi, %g2; \ 1228*7c478bd9Sstevel@tonic-gate ldxa [%g1 + CH_ERR_TL1_G1]%asi, %g1; \ 1229*7c478bd9Sstevel@tonic-gate retry 1230*7c478bd9Sstevel@tonic-gate 1231*7c478bd9Sstevel@tonic-gate /* 1232*7c478bd9Sstevel@tonic-gate * Generates unrecoverable error label for TL>0 handlers. 1233*7c478bd9Sstevel@tonic-gate * At label (Unrecoverable error routine) 1234*7c478bd9Sstevel@tonic-gate * 1. Sets flags in ch_err_tl1_data and leaves in %g2 (first 1235*7c478bd9Sstevel@tonic-gate * argument to cpu_tl1_err_panic). 1236*7c478bd9Sstevel@tonic-gate * 2. Call cpu_tl1_err_panic via systrap at PIL 15 1237*7c478bd9Sstevel@tonic-gate */ 1238*7c478bd9Sstevel@tonic-gate #define CH_ERR_TL1_PANIC_EXIT(label) \ 1239*7c478bd9Sstevel@tonic-gate label: ldxa [%g1 + CH_ERR_TL1_FLAGS]%asi, %g2; \ 1240*7c478bd9Sstevel@tonic-gate or %g2, CH_ERR_TL | CH_ERR_PANIC, %g2; \ 1241*7c478bd9Sstevel@tonic-gate stxa %g2, [%g1 + CH_ERR_TL1_FLAGS]%asi; \ 1242*7c478bd9Sstevel@tonic-gate set cpu_tl1_err_panic, %g1; \ 1243*7c478bd9Sstevel@tonic-gate ba sys_trap; \ 1244*7c478bd9Sstevel@tonic-gate mov PIL_15, %g4 1245*7c478bd9Sstevel@tonic-gate 1246*7c478bd9Sstevel@tonic-gate 1247*7c478bd9Sstevel@tonic-gate 1248*7c478bd9Sstevel@tonic-gate /* END CSTYLED */ 1249*7c478bd9Sstevel@tonic-gate #endif /* _ASM */ 1250*7c478bd9Sstevel@tonic-gate 1251*7c478bd9Sstevel@tonic-gate #ifdef __cplusplus 1252*7c478bd9Sstevel@tonic-gate } 1253*7c478bd9Sstevel@tonic-gate #endif 1254*7c478bd9Sstevel@tonic-gate 1255*7c478bd9Sstevel@tonic-gate #endif /* _CHEETAHASM_H */ 1256