1*142c9f13Sbala/* 2*142c9f13Sbala * CDDL HEADER START 3*142c9f13Sbala * 4*142c9f13Sbala * The contents of this file are subject to the terms of the 5*142c9f13Sbala * Common Development and Distribution License (the "License"). 6*142c9f13Sbala * You may not use this file except in compliance with the License. 7*142c9f13Sbala * 8*142c9f13Sbala * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*142c9f13Sbala * or http://www.opensolaris.org/os/licensing. 10*142c9f13Sbala * See the License for the specific language governing permissions 11*142c9f13Sbala * and limitations under the License. 12*142c9f13Sbala * 13*142c9f13Sbala * When distributing Covered Code, include this CDDL HEADER in each 14*142c9f13Sbala * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*142c9f13Sbala * If applicable, add the following below this CDDL HEADER, with the 16*142c9f13Sbala * fields enclosed by brackets "[]" replaced with your own identifying 17*142c9f13Sbala * information: Portions Copyright [yyyy] [name of copyright owner] 18*142c9f13Sbala * 19*142c9f13Sbala * CDDL HEADER END 20*142c9f13Sbala */ 21*142c9f13Sbala/* 22*142c9f13Sbala * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23*142c9f13Sbala * Use is subject to license terms. 24*142c9f13Sbala * 25*142c9f13Sbala * Assembly code support for the Cheetah+ module 26*142c9f13Sbala */ 27*142c9f13Sbala 28*142c9f13Sbala#pragma ident "%Z%%M% %I% %E% SMI" 29*142c9f13Sbala 30*142c9f13Sbala#if !defined(lint) 31*142c9f13Sbala#include "assym.h" 32*142c9f13Sbala#endif /* lint */ 33*142c9f13Sbala 34*142c9f13Sbala#include <sys/asm_linkage.h> 35*142c9f13Sbala#include <sys/mmu.h> 36*142c9f13Sbala#include <vm/hat_sfmmu.h> 37*142c9f13Sbala#include <sys/machparam.h> 38*142c9f13Sbala#include <sys/machcpuvar.h> 39*142c9f13Sbala#include <sys/machthread.h> 40*142c9f13Sbala#include <sys/machtrap.h> 41*142c9f13Sbala#include <sys/privregs.h> 42*142c9f13Sbala#include <sys/asm_linkage.h> 43*142c9f13Sbala#include <sys/trap.h> 44*142c9f13Sbala#include <sys/cheetahregs.h> 45*142c9f13Sbala#include <sys/xc_impl.h> 46*142c9f13Sbala#include <sys/intreg.h> 47*142c9f13Sbala#include <sys/async.h> 48*142c9f13Sbala#include <sys/clock.h> 49*142c9f13Sbala#include <sys/cheetahasm.h> 50*142c9f13Sbala#include <sys/cmpregs.h> 51*142c9f13Sbala 52*142c9f13Sbala#ifdef TRAPTRACE 53*142c9f13Sbala#include <sys/traptrace.h> 54*142c9f13Sbala#endif /* TRAPTRACE */ 55*142c9f13Sbala 56*142c9f13Sbala 57*142c9f13Sbala#if !defined(lint) 58*142c9f13Sbala 59*142c9f13Sbala .global retire_l2_start 60*142c9f13Sbala .global retire_l2_end 61*142c9f13Sbala .global unretire_l2_start 62*142c9f13Sbala .global unretire_l2_end 63*142c9f13Sbala .global retire_l3_start 64*142c9f13Sbala .global retire_l3_end 65*142c9f13Sbala .global unretire_l3_start 66*142c9f13Sbala .global unretire_l3_end 67*142c9f13Sbala 68*142c9f13Sbala/* 69*142c9f13Sbala * Panther version to reflush a line from both the L2 cache and L3 70*142c9f13Sbala * cache by the respective indexes. Flushes all ways of the line from 71*142c9f13Sbala * each cache. 72*142c9f13Sbala * 73*142c9f13Sbala * l2_index Index into the L2$ of the line to be flushed. This 74*142c9f13Sbala * register will not be modified by this routine. 75*142c9f13Sbala * l3_index Index into the L3$ of the line to be flushed. This 76*142c9f13Sbala * register will not be modified by this routine. 77*142c9f13Sbala * scr2 scratch register. 78*142c9f13Sbala * scr3 scratch register. 79*142c9f13Sbala * 80*142c9f13Sbala */ 81*142c9f13Sbala#define PN_ECACHE_REFLUSH_LINE(l2_index, l3_index, scr2, scr3) \ 82*142c9f13Sbala set PN_L2_MAX_SET, scr2; \ 83*142c9f13Sbala set PN_L2_SET_SIZE, scr3; \ 84*142c9f13Sbala1: \ 85*142c9f13Sbala ldxa [l2_index + scr2]ASI_L2_TAG, %g0; \ 86*142c9f13Sbala cmp scr2, %g0; \ 87*142c9f13Sbala bg,a 1b; \ 88*142c9f13Sbala sub scr2, scr3, scr2; \ 89*142c9f13Sbala mov 6, scr2; \ 90*142c9f13Sbala6: \ 91*142c9f13Sbala cmp scr2, %g0; \ 92*142c9f13Sbala bg,a 6b; \ 93*142c9f13Sbala sub scr2, 1, scr2; \ 94*142c9f13Sbala set PN_L3_MAX_SET, scr2; \ 95*142c9f13Sbala set PN_L3_SET_SIZE, scr3; \ 96*142c9f13Sbala2: \ 97*142c9f13Sbala ldxa [l3_index + scr2]ASI_EC_DIAG, %g0; \ 98*142c9f13Sbala cmp scr2, %g0; \ 99*142c9f13Sbala bg,a 2b; \ 100*142c9f13Sbala sub scr2, scr3, scr2; 101*142c9f13Sbala 102*142c9f13Sbala/* 103*142c9f13Sbala * Panther version of ecache_flush_line. Flushes the line corresponding 104*142c9f13Sbala * to physaddr from both the L2 cache and the L3 cache. 105*142c9f13Sbala * 106*142c9f13Sbala * physaddr Input: Physical address to flush. 107*142c9f13Sbala * Output: Physical address to flush (preserved). 108*142c9f13Sbala * l2_idx_out Input: scratch register. 109*142c9f13Sbala * Output: Index into the L2$ of the line to be flushed. 110*142c9f13Sbala * l3_idx_out Input: scratch register. 111*142c9f13Sbala * Output: Index into the L3$ of the line to be flushed. 112*142c9f13Sbala * scr3 scratch register. 113*142c9f13Sbala * scr4 scratch register. 114*142c9f13Sbala * 115*142c9f13Sbala */ 116*142c9f13Sbala#define PN_ECACHE_FLUSH_LINE(physaddr, l2_idx_out, l3_idx_out, scr3, scr4) \ 117*142c9f13Sbala set PN_L3_SET_SIZE, l2_idx_out; \ 118*142c9f13Sbala sub l2_idx_out, 1, l2_idx_out; \ 119*142c9f13Sbala and physaddr, l2_idx_out, l3_idx_out; \ 120*142c9f13Sbala set PN_L3_IDX_DISP_FLUSH, l2_idx_out; \ 121*142c9f13Sbala or l2_idx_out, l3_idx_out, l3_idx_out; \ 122*142c9f13Sbala set PN_L2_SET_SIZE, l2_idx_out; \ 123*142c9f13Sbala sub l2_idx_out, 1, l2_idx_out; \ 124*142c9f13Sbala and physaddr, l2_idx_out, l2_idx_out; \ 125*142c9f13Sbala set PN_L2_IDX_DISP_FLUSH, scr3; \ 126*142c9f13Sbala or l2_idx_out, scr3, l2_idx_out; \ 127*142c9f13Sbala PN_ECACHE_REFLUSH_LINE(l2_idx_out, l3_idx_out, scr3, scr4) 128*142c9f13Sbala 129*142c9f13Sbala 130*142c9f13Sbala#endif /* !lint */ 131*142c9f13Sbala 132*142c9f13Sbala#if defined(lint) 133*142c9f13Sbala 134*142c9f13Sbala/*ARGSUSED*/ 135*142c9f13Sbalaint 136*142c9f13Sbalaretire_l2(uint64_t tag_addr, uint64_t pattern) 137*142c9f13Sbala{return 0;} 138*142c9f13Sbala 139*142c9f13Sbala#else 140*142c9f13Sbala .align 4096 141*142c9f13Sbala ENTRY(retire_l2) 142*142c9f13Sbalaretire_l2_start: 143*142c9f13Sbala 144*142c9f13Sbala ! since we disable interrupts, we don't need to do kpreempt_disable() 145*142c9f13Sbala rdpr %pstate, %o2 146*142c9f13Sbala andn %o2, PSTATE_IE, %g1 147*142c9f13Sbala wrpr %g0, %g1, %pstate ! disable interrupts 148*142c9f13Sbala /* 149*142c9f13Sbala * Save current DCU state. Turn off IPS 150*142c9f13Sbala */ 151*142c9f13Sbala setx DCU_IPS_MASK, %g2, %o3 152*142c9f13Sbala ldxa [%g0]ASI_DCU, %g1 ! save DCU in %g1 153*142c9f13Sbala andn %g1, %o3, %g4 154*142c9f13Sbala stxa %g4, [%g0]ASI_DCU 155*142c9f13Sbala flush %g0 156*142c9f13Sbala PARK_SIBLING_CORE(%g1, %o3, %o4) ! %g1 has DCU value 157*142c9f13Sbala clr %o5 ! assume success 158*142c9f13Sbala8: 159*142c9f13Sbala PN_ECACHE_FLUSH_LINE(%o0, %o3, %o4, %g2, %g3) 160*142c9f13Sbala1: 161*142c9f13Sbala ! Check if line is invalid; if so, NA it. 162*142c9f13Sbala ldxa [%o0]ASI_L2_TAG, %o3 163*142c9f13Sbala btst 0x7, %o3 164*142c9f13Sbala bnz %xcc, 2f 165*142c9f13Sbala nop 166*142c9f13Sbala stxa %o1, [%o0]ASI_L2_TAG 167*142c9f13Sbala membar #Sync ! still on same cache line 168*142c9f13Sbala ! now delay 15 cycles so we don't have hazard when we return 169*142c9f13Sbala mov 16, %o1 170*142c9f13Sbala1: 171*142c9f13Sbala brnz,pt %o1, 1b 172*142c9f13Sbala dec %o1 173*142c9f13Sbala9: 174*142c9f13Sbala ! UNPARK-SIBLING_CORE is 7 instructions, so we cross a cache boundary 175*142c9f13Sbala UNPARK_SIBLING_CORE(%g1, %o3, %o4) ! 7 instructions 176*142c9f13Sbala /* 177*142c9f13Sbala * Restore the DCU 178*142c9f13Sbala */ 179*142c9f13Sbala stxa %g1, [%g0]ASI_DCU 180*142c9f13Sbala flush %g0 181*142c9f13Sbala wrpr %g0, %o2, %pstate !restore pstate 182*142c9f13Sbala retl 183*142c9f13Sbala mov %o5, %o0 184*142c9f13Sbala2: 185*142c9f13Sbala ! It is OK to have STATE as NA (if so, nothing to do!) 186*142c9f13Sbala and %o3, 0x7, %o3 187*142c9f13Sbala cmp %o3, 0x5 188*142c9f13Sbala be,a,pt %xcc, 9b 189*142c9f13Sbala mov 1, %o5 ! indicate was already NA 190*142c9f13Sbala ! Hmm. Not INV, not NA. 191*142c9f13Sbala cmp %o5, 0 192*142c9f13Sbala be,a,pt %xcc, 8b ! Flush the cacheline again 193*142c9f13Sbala mov 2, %o5 ! indicate retry was done 194*142c9f13Sbala ! We already Flushed cacheline second time. Return -1 195*142c9f13Sbala clr %o5 196*142c9f13Sbala ba 9b 197*142c9f13Sbala dec %o5 198*142c9f13Sbalaretire_l2_end: 199*142c9f13Sbala SET_SIZE(retire_l2) 200*142c9f13Sbala 201*142c9f13Sbala#endif /* lint */ 202*142c9f13Sbala 203*142c9f13Sbala#if defined(lint) 204*142c9f13Sbala 205*142c9f13Sbala/* 206*142c9f13Sbala */ 207*142c9f13Sbala/*ARGSUSED*/ 208*142c9f13Sbalaint 209*142c9f13Sbalaunretire_l2(uint64_t tag_addr, uint64_t pattern) 210*142c9f13Sbala{return 0;} 211*142c9f13Sbala 212*142c9f13Sbala#else 213*142c9f13Sbala ENTRY(unretire_l2) 214*142c9f13Sbalaunretire_l2_start: 215*142c9f13Sbala 216*142c9f13Sbala ! since we disable interrupts, we don't need to do kpreempt_disable() 217*142c9f13Sbala rdpr %pstate, %o2 218*142c9f13Sbala andn %o2, PSTATE_IE, %g1 219*142c9f13Sbala wrpr %g0, %g1, %pstate ! disable interrupts 220*142c9f13Sbala /* 221*142c9f13Sbala * Save current DCU state. Turn off IPS 222*142c9f13Sbala */ 223*142c9f13Sbala setx DCU_IPS_MASK, %g2, %o3 224*142c9f13Sbala ldxa [%g0]ASI_DCU, %g1 ! save DCU in %g1 225*142c9f13Sbala andn %g1, %o3, %g4 226*142c9f13Sbala stxa %g4, [%g0]ASI_DCU 227*142c9f13Sbala flush %g0 /* flush required after changing the IC bit */ 228*142c9f13Sbala PARK_SIBLING_CORE(%g1, %o3, %o4) ! %g1 has DCU value 229*142c9f13Sbala 230*142c9f13Sbala PN_ECACHE_FLUSH_LINE(%o0, %o3, %o4, %o5, %g2) 231*142c9f13Sbala1: 232*142c9f13Sbala clr %o5 ! assume success 233*142c9f13Sbala ! Check that line is in NA state; if so, INV it. 234*142c9f13Sbala ldxa [%o0]ASI_L2_TAG, %o3 235*142c9f13Sbala and %o3, 0x7, %o3 236*142c9f13Sbala cmp %o3, 0x5 237*142c9f13Sbala bne,a,pt %xcc, 9f ! Wasn't NA, so something is wrong 238*142c9f13Sbala dec %o5 ! indicate not NA 239*142c9f13Sbala stxa %g0, [%o0]ASI_L2_TAG 240*142c9f13Sbala membar #Sync 241*142c9f13Sbala ! now delay 15 cycles so we don't have hazard when we return 242*142c9f13Sbala mov 16, %o1 243*142c9f13Sbala1: 244*142c9f13Sbala brnz,pt %o1, 1b 245*142c9f13Sbala dec %o1 246*142c9f13Sbala9: 247*142c9f13Sbala ! UNPARK-SIBLING_CORE is 7 instructions 248*142c9f13Sbala UNPARK_SIBLING_CORE(%g1, %o3, %o4) ! 7 instructions 249*142c9f13Sbala /* 250*142c9f13Sbala * Restore the DCU 251*142c9f13Sbala */ 252*142c9f13Sbala stxa %g1, [%g0]ASI_DCU 253*142c9f13Sbala flush %g0 254*142c9f13Sbala wrpr %g0, %o2, %pstate !restore pstate 255*142c9f13Sbala retl 256*142c9f13Sbala mov %o5, %o0 257*142c9f13Sbalaunretire_l2_end: 258*142c9f13Sbala SET_SIZE(unretire_l2) 259*142c9f13Sbala 260*142c9f13Sbala#endif /* lint */ 261*142c9f13Sbala 262*142c9f13Sbala#if defined(lint) 263*142c9f13Sbala 264*142c9f13Sbala/*ARGSUSED*/ 265*142c9f13Sbalaint 266*142c9f13Sbalaretire_l3(uint64_t tag_addr, uint64_t pattern) 267*142c9f13Sbala{return 0;} 268*142c9f13Sbala 269*142c9f13Sbala#else 270*142c9f13Sbala ENTRY(retire_l3) 271*142c9f13Sbalaretire_l3_start: 272*142c9f13Sbala 273*142c9f13Sbala ! since we disable interrupts, we don't need to do kpreempt_disable() 274*142c9f13Sbala rdpr %pstate, %o2 275*142c9f13Sbala andn %o2, PSTATE_IE, %g1 276*142c9f13Sbala wrpr %g0, %g1, %pstate ! disable interrupts 277*142c9f13Sbala /* 278*142c9f13Sbala * Save current DCU state. Turn off IPS 279*142c9f13Sbala */ 280*142c9f13Sbala setx DCU_IPS_MASK, %g2, %o3 281*142c9f13Sbala ldxa [%g0]ASI_DCU, %g1 ! save DCU in %g1 282*142c9f13Sbala andn %g1, %o3, %g4 283*142c9f13Sbala stxa %g4, [%g0]ASI_DCU 284*142c9f13Sbala flush %g0 /* flush required after changing the IC bit */ 285*142c9f13Sbala PARK_SIBLING_CORE(%g1, %o3, %o4) ! %g1 has DCU value 286*142c9f13Sbala 287*142c9f13Sbala ! PN-ECACHE-FLUSH_LINE is 30 instructions 288*142c9f13Sbala PN_ECACHE_FLUSH_LINE(%o0, %o3, %o4, %o5, %g2) 289*142c9f13Sbala1: 290*142c9f13Sbala clr %o5 ! assume success 291*142c9f13Sbala ! Check if line is invalid; if so, NA it. 292*142c9f13Sbala ldxa [%o0]ASI_EC_DIAG, %o3 293*142c9f13Sbala btst 0x7, %o3 294*142c9f13Sbala bnz %xcc, 2f 295*142c9f13Sbala nop 296*142c9f13Sbala stxa %o1, [%o0]ASI_EC_DIAG 297*142c9f13Sbala membar #Sync ! still on same cache line 298*142c9f13Sbala ! now delay 15 cycles so we don't have hazard when we return 299*142c9f13Sbala mov 16, %o1 300*142c9f13Sbala1: 301*142c9f13Sbala brnz,pt %o1, 1b 302*142c9f13Sbala dec %o1 303*142c9f13Sbala9: 304*142c9f13Sbala ! UNPARK-SIBLING_CORE is 7 instructions, so we cross a cache boundary 305*142c9f13Sbala UNPARK_SIBLING_CORE(%g1, %o3, %o4) ! 7 instructions 306*142c9f13Sbala /* 307*142c9f13Sbala * Restore the DCU 308*142c9f13Sbala */ 309*142c9f13Sbala stxa %g1, [%g0]ASI_DCU 310*142c9f13Sbala flush %g0 311*142c9f13Sbala wrpr %g0, %o2, %pstate !restore pstate 312*142c9f13Sbala retl 313*142c9f13Sbala mov %o5, %o0 314*142c9f13Sbala2: 315*142c9f13Sbala ! It is OK to have STATE as NA (if so, nothing to do!) 316*142c9f13Sbala and %o3, 0x7, %o3 317*142c9f13Sbala cmp %o3, 0x5 318*142c9f13Sbala be,a,pt %xcc, 9b 319*142c9f13Sbala inc %o5 ! indicate was already NA 320*142c9f13Sbala ! Hmm. Not INV, not NA 321*142c9f13Sbala ba 9b 322*142c9f13Sbala dec %o5 323*142c9f13Sbalaretire_l3_end: 324*142c9f13Sbala SET_SIZE(retire_l3) 325*142c9f13Sbala 326*142c9f13Sbala#endif /* lint */ 327*142c9f13Sbala 328*142c9f13Sbala#if defined(lint) 329*142c9f13Sbala 330*142c9f13Sbala/* 331*142c9f13Sbala */ 332*142c9f13Sbala/*ARGSUSED*/ 333*142c9f13Sbalaint 334*142c9f13Sbalaunretire_l3(uint64_t tag_addr, uint64_t pattern) 335*142c9f13Sbala{return 0;} 336*142c9f13Sbala 337*142c9f13Sbala#else 338*142c9f13Sbala ENTRY(unretire_l3) 339*142c9f13Sbalaunretire_l3_start: 340*142c9f13Sbala 341*142c9f13Sbala ! since we disable interrupts, we don't need to do kpreempt_disable() 342*142c9f13Sbala rdpr %pstate, %o2 343*142c9f13Sbala andn %o2, PSTATE_IE, %g1 344*142c9f13Sbala wrpr %g0, %g1, %pstate ! disable interrupts 345*142c9f13Sbala /* 346*142c9f13Sbala * Save current DCU state. Turn off IPS 347*142c9f13Sbala */ 348*142c9f13Sbala setx DCU_IPS_MASK, %g2, %o3 349*142c9f13Sbala ldxa [%g0]ASI_DCU, %g1 ! save DCU in %g1 350*142c9f13Sbala andn %g1, %o3, %g4 351*142c9f13Sbala stxa %g4, [%g0]ASI_DCU 352*142c9f13Sbala flush %g0 /* flush required after changing the IC bit */ 353*142c9f13Sbala PARK_SIBLING_CORE(%g1, %o3, %o4) ! %g1 has DCU value 354*142c9f13Sbala 355*142c9f13Sbala PN_ECACHE_FLUSH_LINE(%o0, %o3, %o4, %o5, %g2) 356*142c9f13Sbala1: 357*142c9f13Sbala clr %o5 ! assume success 358*142c9f13Sbala ! Check that line is in NA state; if so, INV it. 359*142c9f13Sbala ldxa [%o0]ASI_EC_DIAG, %o3 360*142c9f13Sbala and %o3, 0x7, %o3 361*142c9f13Sbala cmp %o3, 0x5 362*142c9f13Sbala bne,a,pt %xcc, 9f ! Wasn't NA, so something is wrong 363*142c9f13Sbala dec %o5 ! indicate not NA 364*142c9f13Sbala stxa %g0, [%o0]ASI_EC_DIAG 365*142c9f13Sbala membar #Sync 366*142c9f13Sbala ! now delay 15 cycles so we don't have hazard when we return 367*142c9f13Sbala mov 16, %o1 368*142c9f13Sbala1: 369*142c9f13Sbala brnz,pt %o1, 1b 370*142c9f13Sbala dec %o1 371*142c9f13Sbala9: 372*142c9f13Sbala ! UNPARK-SIBLING_CORE is 7 instructions 373*142c9f13Sbala UNPARK_SIBLING_CORE(%g1, %o3, %o4) ! 7 instructions 374*142c9f13Sbala /* 375*142c9f13Sbala * Restore the DCU 376*142c9f13Sbala */ 377*142c9f13Sbala stxa %g1, [%g0]ASI_DCU 378*142c9f13Sbala flush %g0 379*142c9f13Sbala wrpr %g0, %o2, %pstate !restore pstate 380*142c9f13Sbala retl 381*142c9f13Sbala mov %o5, %o0 382*142c9f13Sbalaunretire_l3_end: 383*142c9f13Sbala SET_SIZE(unretire_l3) 384*142c9f13Sbala 385*142c9f13Sbala#endif /* lint */ 386*142c9f13Sbala 387*142c9f13Sbala#if defined(lint) 388*142c9f13Sbala 389*142c9f13Sbala/*ARGSUSED*/ 390*142c9f13Sbalaint 391*142c9f13Sbalaretire_l2_alternate(uint64_t tag_addr, uint64_t pattern) 392*142c9f13Sbala{return 0;} 393*142c9f13Sbala 394*142c9f13Sbala#else 395*142c9f13Sbala .align 2048 396*142c9f13Sbala 397*142c9f13Sbala ENTRY(retire_l2_alternate) 398*142c9f13Sbala 399*142c9f13Sbala ! since we disable interrupts, we don't need to do kpreempt_disable() 400*142c9f13Sbala rdpr %pstate, %o2 401*142c9f13Sbala andn %o2, PSTATE_IE, %g1 402*142c9f13Sbala wrpr %g0, %g1, %pstate ! disable interrupts 403*142c9f13Sbala /* 404*142c9f13Sbala * Save current DCU state. Turn off IPS 405*142c9f13Sbala */ 406*142c9f13Sbala setx DCU_IPS_MASK, %g2, %o3 407*142c9f13Sbala ldxa [%g0]ASI_DCU, %g1 ! save DCU in %g1 408*142c9f13Sbala andn %g1, %o3, %g4 409*142c9f13Sbala stxa %g4, [%g0]ASI_DCU 410*142c9f13Sbala flush %g0 411*142c9f13Sbala PARK_SIBLING_CORE(%g1, %o3, %o4) ! %g1 has DCU value 412*142c9f13Sbala clr %o5 ! assume success 413*142c9f13Sbala8: 414*142c9f13Sbala PN_ECACHE_FLUSH_LINE(%o0, %o3, %o4, %g2, %g3) 415*142c9f13Sbala1: 416*142c9f13Sbala ! Check if line is invalid; if so, NA it. 417*142c9f13Sbala ldxa [%o0]ASI_L2_TAG, %o3 418*142c9f13Sbala btst 0x7, %o3 419*142c9f13Sbala bnz %xcc, 2f 420*142c9f13Sbala nop 421*142c9f13Sbala stxa %o1, [%o0]ASI_L2_TAG 422*142c9f13Sbala membar #Sync ! still on same cache line 423*142c9f13Sbala ! now delay 15 cycles so we don't have hazard when we return 424*142c9f13Sbala mov 16, %o1 425*142c9f13Sbala1: 426*142c9f13Sbala brnz,pt %o1, 1b 427*142c9f13Sbala dec %o1 428*142c9f13Sbala9: 429*142c9f13Sbala ! UNPARK-SIBLING_CORE is 7 instructions, so we cross a cache boundary 430*142c9f13Sbala UNPARK_SIBLING_CORE(%g1, %o3, %o4) ! 7 instructions 431*142c9f13Sbala /* 432*142c9f13Sbala * Restore the DCU 433*142c9f13Sbala */ 434*142c9f13Sbala stxa %g1, [%g0]ASI_DCU 435*142c9f13Sbala flush %g0 436*142c9f13Sbala wrpr %g0, %o2, %pstate !restore pstate 437*142c9f13Sbala retl 438*142c9f13Sbala mov %o5, %o0 439*142c9f13Sbala2: 440*142c9f13Sbala ! It is OK to have STATE as NA (if so, nothing to do!) 441*142c9f13Sbala and %o3, 0x7, %o3 442*142c9f13Sbala cmp %o3, 0x5 443*142c9f13Sbala be,a,pt %xcc, 9b 444*142c9f13Sbala mov 1, %o5 ! indicate was already NA 445*142c9f13Sbala ! Hmm. Not INV, not NA. 446*142c9f13Sbala cmp %o5, 0 447*142c9f13Sbala be,a,pt %xcc, 8b ! Flush the cacheline again 448*142c9f13Sbala mov 2, %o5 ! indicate retry was done 449*142c9f13Sbala ! We already Flushed cacheline second time. Return -1 450*142c9f13Sbala clr %o5 451*142c9f13Sbala ba 9b 452*142c9f13Sbala dec %o5 453*142c9f13Sbala SET_SIZE(retire_l2_alternate) 454*142c9f13Sbala 455*142c9f13Sbala#endif /* lint */ 456*142c9f13Sbala 457*142c9f13Sbala#if defined(lint) 458*142c9f13Sbala 459*142c9f13Sbala/* 460*142c9f13Sbala */ 461*142c9f13Sbala/*ARGSUSED*/ 462*142c9f13Sbalaint 463*142c9f13Sbalaunretire_l2_alternate(uint64_t tag_addr, uint64_t pattern) 464*142c9f13Sbala{return 0;} 465*142c9f13Sbala 466*142c9f13Sbala#else 467*142c9f13Sbala ENTRY(unretire_l2_alternate) 468*142c9f13Sbala 469*142c9f13Sbala ! since we disable interrupts, we don't need to do kpreempt_disable() 470*142c9f13Sbala rdpr %pstate, %o2 471*142c9f13Sbala andn %o2, PSTATE_IE, %g1 472*142c9f13Sbala wrpr %g0, %g1, %pstate ! disable interrupts 473*142c9f13Sbala /* 474*142c9f13Sbala * Save current DCU state. Turn off IPS 475*142c9f13Sbala */ 476*142c9f13Sbala setx DCU_IPS_MASK, %g2, %o3 477*142c9f13Sbala ldxa [%g0]ASI_DCU, %g1 ! save DCU in %g1 478*142c9f13Sbala andn %g1, %o3, %g4 479*142c9f13Sbala stxa %g4, [%g0]ASI_DCU 480*142c9f13Sbala flush %g0 /* flush required after changing the IC bit */ 481*142c9f13Sbala PARK_SIBLING_CORE(%g1, %o3, %o4) ! %g1 has DCU value 482*142c9f13Sbala 483*142c9f13Sbala PN_ECACHE_FLUSH_LINE(%o0, %o3, %o4, %o5, %g2) 484*142c9f13Sbala1: 485*142c9f13Sbala clr %o5 ! assume success 486*142c9f13Sbala ! Check that line is in NA state; if so, INV it. 487*142c9f13Sbala ldxa [%o0]ASI_L2_TAG, %o3 488*142c9f13Sbala and %o3, 0x7, %o3 489*142c9f13Sbala cmp %o3, 0x5 490*142c9f13Sbala bne,a,pt %xcc, 9f ! Wasn't NA, so something is wrong 491*142c9f13Sbala dec %o5 ! indicate not NA 492*142c9f13Sbala stxa %g0, [%o0]ASI_L2_TAG 493*142c9f13Sbala membar #Sync 494*142c9f13Sbala ! now delay 15 cycles so we don't have hazard when we return 495*142c9f13Sbala mov 16, %o1 496*142c9f13Sbala1: 497*142c9f13Sbala brnz,pt %o1, 1b 498*142c9f13Sbala dec %o1 499*142c9f13Sbala9: 500*142c9f13Sbala ! UNPARK-SIBLING_CORE is 7 instructions 501*142c9f13Sbala UNPARK_SIBLING_CORE(%g1, %o3, %o4) ! 7 instructions 502*142c9f13Sbala /* 503*142c9f13Sbala * Restore the DCU 504*142c9f13Sbala */ 505*142c9f13Sbala stxa %g1, [%g0]ASI_DCU 506*142c9f13Sbala flush %g0 507*142c9f13Sbala wrpr %g0, %o2, %pstate !restore pstate 508*142c9f13Sbala retl 509*142c9f13Sbala mov %o5, %o0 510*142c9f13Sbala SET_SIZE(unretire_l2_alternate) 511*142c9f13Sbala 512*142c9f13Sbala#endif /* lint */ 513*142c9f13Sbala 514*142c9f13Sbala#if defined(lint) 515*142c9f13Sbala 516*142c9f13Sbala/*ARGSUSED*/ 517*142c9f13Sbalaint 518*142c9f13Sbalaretire_l3_alternate(uint64_t tag_addr, uint64_t pattern) 519*142c9f13Sbala{return 0;} 520*142c9f13Sbala 521*142c9f13Sbala#else 522*142c9f13Sbala ENTRY(retire_l3_alternate) 523*142c9f13Sbala 524*142c9f13Sbala ! since we disable interrupts, we don't need to do kpreempt_disable() 525*142c9f13Sbala rdpr %pstate, %o2 526*142c9f13Sbala andn %o2, PSTATE_IE, %g1 527*142c9f13Sbala wrpr %g0, %g1, %pstate ! disable interrupts 528*142c9f13Sbala /* 529*142c9f13Sbala * Save current DCU state. Turn off IPS 530*142c9f13Sbala */ 531*142c9f13Sbala setx DCU_IPS_MASK, %g2, %o3 532*142c9f13Sbala ldxa [%g0]ASI_DCU, %g1 ! save DCU in %g1 533*142c9f13Sbala andn %g1, %o3, %g4 534*142c9f13Sbala stxa %g4, [%g0]ASI_DCU 535*142c9f13Sbala flush %g0 /* flush required after changing the IC bit */ 536*142c9f13Sbala PARK_SIBLING_CORE(%g1, %o3, %o4) ! %g1 has DCU value 537*142c9f13Sbala 538*142c9f13Sbala ! PN-ECACHE-FLUSH_LINE is 30 instructions 539*142c9f13Sbala PN_ECACHE_FLUSH_LINE(%o0, %o3, %o4, %o5, %g2) 540*142c9f13Sbala1: 541*142c9f13Sbala clr %o5 ! assume success 542*142c9f13Sbala ! Check if line is invalid; if so, NA it. 543*142c9f13Sbala ldxa [%o0]ASI_EC_DIAG, %o3 544*142c9f13Sbala btst 0x7, %o3 545*142c9f13Sbala bnz %xcc, 2f 546*142c9f13Sbala nop 547*142c9f13Sbala stxa %o1, [%o0]ASI_EC_DIAG 548*142c9f13Sbala membar #Sync ! still on same cache line 549*142c9f13Sbala ! now delay 15 cycles so we don't have hazard when we return 550*142c9f13Sbala mov 16, %o1 551*142c9f13Sbala1: 552*142c9f13Sbala brnz,pt %o1, 1b 553*142c9f13Sbala dec %o1 554*142c9f13Sbala9: 555*142c9f13Sbala ! UNPARK-SIBLING_CORE is 7 instructions, so we cross a cache boundary 556*142c9f13Sbala UNPARK_SIBLING_CORE(%g1, %o3, %o4) ! 7 instructions 557*142c9f13Sbala /* 558*142c9f13Sbala * Restore the DCU 559*142c9f13Sbala */ 560*142c9f13Sbala stxa %g1, [%g0]ASI_DCU 561*142c9f13Sbala flush %g0 562*142c9f13Sbala wrpr %g0, %o2, %pstate !restore pstate 563*142c9f13Sbala retl 564*142c9f13Sbala mov %o5, %o0 565*142c9f13Sbala2: 566*142c9f13Sbala ! It is OK to have STATE as NA (if so, nothing to do!) 567*142c9f13Sbala and %o3, 0x7, %o3 568*142c9f13Sbala cmp %o3, 0x5 569*142c9f13Sbala be,a,pt %xcc, 9b 570*142c9f13Sbala inc %o5 ! indicate was already NA 571*142c9f13Sbala ! Hmm. Not INV, not NA 572*142c9f13Sbala ba 9b 573*142c9f13Sbala dec %o5 574*142c9f13Sbala SET_SIZE(retire_l3_alternate) 575*142c9f13Sbala 576*142c9f13Sbala#endif /* lint */ 577*142c9f13Sbala 578*142c9f13Sbala#if defined(lint) 579*142c9f13Sbala 580*142c9f13Sbala/* 581*142c9f13Sbala */ 582*142c9f13Sbala/*ARGSUSED*/ 583*142c9f13Sbalaint 584*142c9f13Sbalaunretire_l3_alternate(uint64_t tag_addr, uint64_t pattern) 585*142c9f13Sbala{return 0;} 586*142c9f13Sbala 587*142c9f13Sbala#else 588*142c9f13Sbala ENTRY(unretire_l3_alternate) 589*142c9f13Sbala 590*142c9f13Sbala ! since we disable interrupts, we don't need to do kpreempt_disable() 591*142c9f13Sbala rdpr %pstate, %o2 592*142c9f13Sbala andn %o2, PSTATE_IE, %g1 593*142c9f13Sbala wrpr %g0, %g1, %pstate ! disable interrupts 594*142c9f13Sbala /* 595*142c9f13Sbala * Save current DCU state. Turn off IPS 596*142c9f13Sbala */ 597*142c9f13Sbala setx DCU_IPS_MASK, %g2, %o3 598*142c9f13Sbala ldxa [%g0]ASI_DCU, %g1 ! save DCU in %g1 599*142c9f13Sbala andn %g1, %o3, %g4 600*142c9f13Sbala stxa %g4, [%g0]ASI_DCU 601*142c9f13Sbala flush %g0 /* flush required after changing the IC bit */ 602*142c9f13Sbala PARK_SIBLING_CORE(%g1, %o3, %o4) ! %g1 has DCU value 603*142c9f13Sbala 604*142c9f13Sbala PN_ECACHE_FLUSH_LINE(%o0, %o3, %o4, %o5, %g2) 605*142c9f13Sbala1: 606*142c9f13Sbala clr %o5 ! assume success 607*142c9f13Sbala ! Check that line is in NA state; if so, INV it. 608*142c9f13Sbala ldxa [%o0]ASI_EC_DIAG, %o3 609*142c9f13Sbala and %o3, 0x7, %o3 610*142c9f13Sbala cmp %o3, 0x5 611*142c9f13Sbala bne,a,pt %xcc, 9f ! Wasn't NA, so something is wrong 612*142c9f13Sbala dec %o5 ! indicate not NA 613*142c9f13Sbala stxa %g0, [%o0]ASI_EC_DIAG 614*142c9f13Sbala membar #Sync 615*142c9f13Sbala ! now delay 15 cycles so we don't have hazard when we return 616*142c9f13Sbala mov 16, %o1 617*142c9f13Sbala1: 618*142c9f13Sbala brnz,pt %o1, 1b 619*142c9f13Sbala dec %o1 620*142c9f13Sbala9: 621*142c9f13Sbala ! UNPARK-SIBLING_CORE is 7 instructions 622*142c9f13Sbala UNPARK_SIBLING_CORE(%g1, %o3, %o4) ! 7 instructions 623*142c9f13Sbala /* 624*142c9f13Sbala * Restore the DCU 625*142c9f13Sbala */ 626*142c9f13Sbala stxa %g1, [%g0]ASI_DCU 627*142c9f13Sbala flush %g0 628*142c9f13Sbala wrpr %g0, %o2, %pstate !restore pstate 629*142c9f13Sbala retl 630*142c9f13Sbala mov %o5, %o0 631*142c9f13Sbala SET_SIZE(unretire_l3_alternate) 632*142c9f13Sbala 633*142c9f13Sbala#endif /* lint */ 634*142c9f13Sbala 635*142c9f13Sbala#if defined(lint) 636*142c9f13Sbala 637*142c9f13Sbala/*ARGSUSED*/ 638*142c9f13Sbalavoid 639*142c9f13Sbalaget_ecache_dtags_tl1(uint64_t afar, ch_cpu_logout_t *clop) 640*142c9f13Sbala{ } 641*142c9f13Sbala 642*142c9f13Sbala#else 643*142c9f13Sbala ENTRY(get_ecache_dtags_tl1) 644*142c9f13Sbala 645*142c9f13Sbala 646*142c9f13Sbala PARK_SIBLING_CORE(%g3, %g4, %g5) 647*142c9f13Sbala add %g2, CH_CLO_DATA + CH_CHD_EC_DATA, %g2 648*142c9f13Sbala rd %asi, %g4 649*142c9f13Sbala wr %g0, ASI_N, %asi 650*142c9f13Sbala GET_ECACHE_DTAGS(%g1, %g2, %g5, %g6, %g7) 651*142c9f13Sbala wr %g4, %asi 652*142c9f13Sbala UNPARK_SIBLING_CORE(%g3, %g4, %g5) ! can use %g3 again 653*142c9f13Sbala 654*142c9f13Sbala retry 655*142c9f13Sbala SET_SIZE(get_ecache_dtags_tl1) 656*142c9f13Sbala 657*142c9f13Sbala#endif /* lint */ 658*142c9f13Sbala 659*142c9f13Sbala#if defined(lint) 660*142c9f13Sbala/*ARGSUSED*/ 661*142c9f13Sbalavoid 662*142c9f13Sbalaget_l2_tag_tl1(uint64_t tag_addr, uint64_t tag_data_ptr) 663*142c9f13Sbala{ } 664*142c9f13Sbala 665*142c9f13Sbala#else 666*142c9f13Sbala ENTRY(get_l2_tag_tl1) 667*142c9f13Sbala 668*142c9f13Sbala /* 669*142c9f13Sbala * Now read the tag data 670*142c9f13Sbala */ 671*142c9f13Sbala ldxa [%g1]ASI_L2_TAG, %g4 ! save tag_data 672*142c9f13Sbala stx %g4, [%g2] 673*142c9f13Sbala 674*142c9f13Sbala retry 675*142c9f13Sbala SET_SIZE(get_l2_tag_tl1) 676*142c9f13Sbala 677*142c9f13Sbala#endif /* lint */ 678*142c9f13Sbala 679*142c9f13Sbala#if defined(lint) 680*142c9f13Sbala/*ARGSUSED*/ 681*142c9f13Sbalavoid 682*142c9f13Sbalaget_l3_tag_tl1(uint64_t tag_addr, uint64_t tag_data_ptr) 683*142c9f13Sbala{ } 684*142c9f13Sbala 685*142c9f13Sbala#else 686*142c9f13Sbala ENTRY(get_l3_tag_tl1) 687*142c9f13Sbala 688*142c9f13Sbala /* 689*142c9f13Sbala * Now read the tag data 690*142c9f13Sbala */ 691*142c9f13Sbala ldxa [%g1]ASI_EC_DIAG, %g4 ! save tag_data 692*142c9f13Sbala stx %g4, [%g2] 693*142c9f13Sbala 694*142c9f13Sbala retry 695*142c9f13Sbala SET_SIZE(get_l3_tag_tl1) 696*142c9f13Sbala 697*142c9f13Sbala#endif /* lint */ 698*142c9f13Sbala 699