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