1142c9f13Sbala/* 2142c9f13Sbala * CDDL HEADER START 3142c9f13Sbala * 4142c9f13Sbala * The contents of this file are subject to the terms of the 5142c9f13Sbala * Common Development and Distribution License (the "License"). 6142c9f13Sbala * You may not use this file except in compliance with the License. 7142c9f13Sbala * 8142c9f13Sbala * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9142c9f13Sbala * or http://www.opensolaris.org/os/licensing. 10142c9f13Sbala * See the License for the specific language governing permissions 11142c9f13Sbala * and limitations under the License. 12142c9f13Sbala * 13142c9f13Sbala * When distributing Covered Code, include this CDDL HEADER in each 14142c9f13Sbala * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15142c9f13Sbala * If applicable, add the following below this CDDL HEADER, with the 16142c9f13Sbala * fields enclosed by brackets "[]" replaced with your own identifying 17142c9f13Sbala * information: Portions Copyright [yyyy] [name of copyright owner] 18142c9f13Sbala * 19142c9f13Sbala * CDDL HEADER END 20142c9f13Sbala */ 21142c9f13Sbala/* 22142c9f13Sbala * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23142c9f13Sbala * Use is subject to license terms. 24142c9f13Sbala * 25142c9f13Sbala * Assembly code support for the Cheetah+ module 26142c9f13Sbala */ 27142c9f13Sbala 28142c9f13Sbala#include "assym.h" 29142c9f13Sbala 30142c9f13Sbala#include <sys/asm_linkage.h> 31142c9f13Sbala#include <sys/mmu.h> 32142c9f13Sbala#include <vm/hat_sfmmu.h> 33142c9f13Sbala#include <sys/machparam.h> 34142c9f13Sbala#include <sys/machcpuvar.h> 35142c9f13Sbala#include <sys/machthread.h> 36142c9f13Sbala#include <sys/machtrap.h> 37142c9f13Sbala#include <sys/privregs.h> 38142c9f13Sbala#include <sys/asm_linkage.h> 39142c9f13Sbala#include <sys/trap.h> 40142c9f13Sbala#include <sys/cheetahregs.h> 41142c9f13Sbala#include <sys/xc_impl.h> 42142c9f13Sbala#include <sys/intreg.h> 43142c9f13Sbala#include <sys/async.h> 44142c9f13Sbala#include <sys/clock.h> 45142c9f13Sbala#include <sys/cheetahasm.h> 46142c9f13Sbala#include <sys/cmpregs.h> 47142c9f13Sbala 48142c9f13Sbala#ifdef TRAPTRACE 49142c9f13Sbala#include <sys/traptrace.h> 50142c9f13Sbala#endif /* TRAPTRACE */ 51142c9f13Sbala 52142c9f13Sbala 53142c9f13Sbala .global retire_l2_start 54142c9f13Sbala .global retire_l2_end 55142c9f13Sbala .global unretire_l2_start 56142c9f13Sbala .global unretire_l2_end 57142c9f13Sbala .global retire_l3_start 58142c9f13Sbala .global retire_l3_end 59142c9f13Sbala .global unretire_l3_start 60142c9f13Sbala .global unretire_l3_end 61142c9f13Sbala 62142c9f13Sbala/* 63142c9f13Sbala * Panther version to reflush a line from both the L2 cache and L3 64142c9f13Sbala * cache by the respective indexes. Flushes all ways of the line from 65142c9f13Sbala * each cache. 66142c9f13Sbala * 67142c9f13Sbala * l2_index Index into the L2$ of the line to be flushed. This 68142c9f13Sbala * register will not be modified by this routine. 69142c9f13Sbala * l3_index Index into the L3$ of the line to be flushed. This 70142c9f13Sbala * register will not be modified by this routine. 71142c9f13Sbala * scr2 scratch register. 72142c9f13Sbala * scr3 scratch register. 73142c9f13Sbala * 74142c9f13Sbala */ 75142c9f13Sbala#define PN_ECACHE_REFLUSH_LINE(l2_index, l3_index, scr2, scr3) \ 76142c9f13Sbala set PN_L2_MAX_SET, scr2; \ 77142c9f13Sbala set PN_L2_SET_SIZE, scr3; \ 78142c9f13Sbala1: \ 79142c9f13Sbala ldxa [l2_index + scr2]ASI_L2_TAG, %g0; \ 80142c9f13Sbala cmp scr2, %g0; \ 81142c9f13Sbala bg,a 1b; \ 82142c9f13Sbala sub scr2, scr3, scr2; \ 83142c9f13Sbala mov 6, scr2; \ 84142c9f13Sbala6: \ 85142c9f13Sbala cmp scr2, %g0; \ 86142c9f13Sbala bg,a 6b; \ 87142c9f13Sbala sub scr2, 1, scr2; \ 88142c9f13Sbala set PN_L3_MAX_SET, scr2; \ 89142c9f13Sbala set PN_L3_SET_SIZE, scr3; \ 90142c9f13Sbala2: \ 91142c9f13Sbala ldxa [l3_index + scr2]ASI_EC_DIAG, %g0; \ 92142c9f13Sbala cmp scr2, %g0; \ 93142c9f13Sbala bg,a 2b; \ 94142c9f13Sbala sub scr2, scr3, scr2; 95142c9f13Sbala 96142c9f13Sbala/* 97142c9f13Sbala * Panther version of ecache_flush_line. Flushes the line corresponding 98142c9f13Sbala * to physaddr from both the L2 cache and the L3 cache. 99142c9f13Sbala * 100142c9f13Sbala * physaddr Input: Physical address to flush. 101142c9f13Sbala * Output: Physical address to flush (preserved). 102142c9f13Sbala * l2_idx_out Input: scratch register. 103142c9f13Sbala * Output: Index into the L2$ of the line to be flushed. 104142c9f13Sbala * l3_idx_out Input: scratch register. 105142c9f13Sbala * Output: Index into the L3$ of the line to be flushed. 106142c9f13Sbala * scr3 scratch register. 107142c9f13Sbala * scr4 scratch register. 108142c9f13Sbala * 109142c9f13Sbala */ 110142c9f13Sbala#define PN_ECACHE_FLUSH_LINE(physaddr, l2_idx_out, l3_idx_out, scr3, scr4) \ 111142c9f13Sbala set PN_L3_SET_SIZE, l2_idx_out; \ 112142c9f13Sbala sub l2_idx_out, 1, l2_idx_out; \ 113142c9f13Sbala and physaddr, l2_idx_out, l3_idx_out; \ 114142c9f13Sbala set PN_L3_IDX_DISP_FLUSH, l2_idx_out; \ 115142c9f13Sbala or l2_idx_out, l3_idx_out, l3_idx_out; \ 116142c9f13Sbala set PN_L2_SET_SIZE, l2_idx_out; \ 117142c9f13Sbala sub l2_idx_out, 1, l2_idx_out; \ 118142c9f13Sbala and physaddr, l2_idx_out, l2_idx_out; \ 119142c9f13Sbala set PN_L2_IDX_DISP_FLUSH, scr3; \ 120142c9f13Sbala or l2_idx_out, scr3, l2_idx_out; \ 121142c9f13Sbala PN_ECACHE_REFLUSH_LINE(l2_idx_out, l3_idx_out, scr3, scr4) 122142c9f13Sbala 123142c9f13Sbala 124142c9f13Sbala .align 4096 125142c9f13Sbala ENTRY(retire_l2) 126142c9f13Sbalaretire_l2_start: 127142c9f13Sbala 128142c9f13Sbala ! since we disable interrupts, we don't need to do kpreempt_disable() 129142c9f13Sbala rdpr %pstate, %o2 130142c9f13Sbala andn %o2, PSTATE_IE, %g1 131142c9f13Sbala wrpr %g0, %g1, %pstate ! disable interrupts 132142c9f13Sbala /* 133142c9f13Sbala * Save current DCU state. Turn off IPS 134142c9f13Sbala */ 135142c9f13Sbala setx DCU_IPS_MASK, %g2, %o3 136142c9f13Sbala ldxa [%g0]ASI_DCU, %g1 ! save DCU in %g1 137142c9f13Sbala andn %g1, %o3, %g4 138142c9f13Sbala stxa %g4, [%g0]ASI_DCU 139142c9f13Sbala flush %g0 140142c9f13Sbala PARK_SIBLING_CORE(%g1, %o3, %o4) ! %g1 has DCU value 141142c9f13Sbala clr %o5 ! assume success 142142c9f13Sbala8: 143142c9f13Sbala PN_ECACHE_FLUSH_LINE(%o0, %o3, %o4, %g2, %g3) 144142c9f13Sbala1: 145142c9f13Sbala ! Check if line is invalid; if so, NA it. 146142c9f13Sbala ldxa [%o0]ASI_L2_TAG, %o3 147142c9f13Sbala btst 0x7, %o3 148142c9f13Sbala bnz %xcc, 2f 149142c9f13Sbala nop 150142c9f13Sbala stxa %o1, [%o0]ASI_L2_TAG 151*55fea89dSDan Cross membar #Sync ! still on same cache line 152142c9f13Sbala ! now delay 15 cycles so we don't have hazard when we return 153142c9f13Sbala mov 16, %o1 154142c9f13Sbala1: 155142c9f13Sbala brnz,pt %o1, 1b 156142c9f13Sbala dec %o1 157142c9f13Sbala9: 158142c9f13Sbala ! UNPARK-SIBLING_CORE is 7 instructions, so we cross a cache boundary 159142c9f13Sbala UNPARK_SIBLING_CORE(%g1, %o3, %o4) ! 7 instructions 160142c9f13Sbala /* 161142c9f13Sbala * Restore the DCU 162142c9f13Sbala */ 163142c9f13Sbala stxa %g1, [%g0]ASI_DCU 164142c9f13Sbala flush %g0 165142c9f13Sbala wrpr %g0, %o2, %pstate !restore pstate 166142c9f13Sbala retl 167142c9f13Sbala mov %o5, %o0 168142c9f13Sbala2: 169142c9f13Sbala ! It is OK to have STATE as NA (if so, nothing to do!) 170142c9f13Sbala and %o3, 0x7, %o3 171142c9f13Sbala cmp %o3, 0x5 172142c9f13Sbala be,a,pt %xcc, 9b 173142c9f13Sbala mov 1, %o5 ! indicate was already NA 174142c9f13Sbala ! Hmm. Not INV, not NA. 175142c9f13Sbala cmp %o5, 0 176142c9f13Sbala be,a,pt %xcc, 8b ! Flush the cacheline again 177142c9f13Sbala mov 2, %o5 ! indicate retry was done 178142c9f13Sbala ! We already Flushed cacheline second time. Return -1 179142c9f13Sbala clr %o5 180142c9f13Sbala ba 9b 181142c9f13Sbala dec %o5 182142c9f13Sbalaretire_l2_end: 183142c9f13Sbala SET_SIZE(retire_l2) 184142c9f13Sbala 185142c9f13Sbala ENTRY(unretire_l2) 186142c9f13Sbalaunretire_l2_start: 187142c9f13Sbala 188142c9f13Sbala ! since we disable interrupts, we don't need to do kpreempt_disable() 189142c9f13Sbala rdpr %pstate, %o2 190142c9f13Sbala andn %o2, PSTATE_IE, %g1 191142c9f13Sbala wrpr %g0, %g1, %pstate ! disable interrupts 192142c9f13Sbala /* 193142c9f13Sbala * Save current DCU state. Turn off IPS 194142c9f13Sbala */ 195142c9f13Sbala setx DCU_IPS_MASK, %g2, %o3 196142c9f13Sbala ldxa [%g0]ASI_DCU, %g1 ! save DCU in %g1 197142c9f13Sbala andn %g1, %o3, %g4 198142c9f13Sbala stxa %g4, [%g0]ASI_DCU 199142c9f13Sbala flush %g0 /* flush required after changing the IC bit */ 200142c9f13Sbala PARK_SIBLING_CORE(%g1, %o3, %o4) ! %g1 has DCU value 201142c9f13Sbala 202142c9f13Sbala PN_ECACHE_FLUSH_LINE(%o0, %o3, %o4, %o5, %g2) 203142c9f13Sbala1: 204142c9f13Sbala clr %o5 ! assume success 205142c9f13Sbala ! Check that line is in NA state; if so, INV it. 206142c9f13Sbala ldxa [%o0]ASI_L2_TAG, %o3 207142c9f13Sbala and %o3, 0x7, %o3 208142c9f13Sbala cmp %o3, 0x5 209142c9f13Sbala bne,a,pt %xcc, 9f ! Wasn't NA, so something is wrong 210142c9f13Sbala dec %o5 ! indicate not NA 211142c9f13Sbala stxa %g0, [%o0]ASI_L2_TAG 212142c9f13Sbala membar #Sync 213142c9f13Sbala ! now delay 15 cycles so we don't have hazard when we return 214142c9f13Sbala mov 16, %o1 215142c9f13Sbala1: 216142c9f13Sbala brnz,pt %o1, 1b 217142c9f13Sbala dec %o1 218142c9f13Sbala9: 219142c9f13Sbala ! UNPARK-SIBLING_CORE is 7 instructions 220142c9f13Sbala UNPARK_SIBLING_CORE(%g1, %o3, %o4) ! 7 instructions 221142c9f13Sbala /* 222142c9f13Sbala * Restore the DCU 223142c9f13Sbala */ 224142c9f13Sbala stxa %g1, [%g0]ASI_DCU 225142c9f13Sbala flush %g0 226142c9f13Sbala wrpr %g0, %o2, %pstate !restore pstate 227142c9f13Sbala retl 228142c9f13Sbala mov %o5, %o0 229142c9f13Sbalaunretire_l2_end: 230142c9f13Sbala SET_SIZE(unretire_l2) 231142c9f13Sbala 232142c9f13Sbala ENTRY(retire_l3) 233142c9f13Sbalaretire_l3_start: 234142c9f13Sbala 235142c9f13Sbala ! since we disable interrupts, we don't need to do kpreempt_disable() 236142c9f13Sbala rdpr %pstate, %o2 237142c9f13Sbala andn %o2, PSTATE_IE, %g1 238142c9f13Sbala wrpr %g0, %g1, %pstate ! disable interrupts 239142c9f13Sbala /* 240142c9f13Sbala * Save current DCU state. Turn off IPS 241142c9f13Sbala */ 242142c9f13Sbala setx DCU_IPS_MASK, %g2, %o3 243142c9f13Sbala ldxa [%g0]ASI_DCU, %g1 ! save DCU in %g1 244142c9f13Sbala andn %g1, %o3, %g4 245142c9f13Sbala stxa %g4, [%g0]ASI_DCU 246142c9f13Sbala flush %g0 /* flush required after changing the IC bit */ 247142c9f13Sbala PARK_SIBLING_CORE(%g1, %o3, %o4) ! %g1 has DCU value 248142c9f13Sbala 249142c9f13Sbala ! PN-ECACHE-FLUSH_LINE is 30 instructions 250142c9f13Sbala PN_ECACHE_FLUSH_LINE(%o0, %o3, %o4, %o5, %g2) 251142c9f13Sbala1: 252142c9f13Sbala clr %o5 ! assume success 253142c9f13Sbala ! Check if line is invalid; if so, NA it. 254142c9f13Sbala ldxa [%o0]ASI_EC_DIAG, %o3 255142c9f13Sbala btst 0x7, %o3 256142c9f13Sbala bnz %xcc, 2f 257142c9f13Sbala nop 258142c9f13Sbala stxa %o1, [%o0]ASI_EC_DIAG 259*55fea89dSDan Cross membar #Sync ! still on same cache line 260142c9f13Sbala ! now delay 15 cycles so we don't have hazard when we return 261142c9f13Sbala mov 16, %o1 262142c9f13Sbala1: 263142c9f13Sbala brnz,pt %o1, 1b 264142c9f13Sbala dec %o1 265142c9f13Sbala9: 266142c9f13Sbala ! UNPARK-SIBLING_CORE is 7 instructions, so we cross a cache boundary 267142c9f13Sbala UNPARK_SIBLING_CORE(%g1, %o3, %o4) ! 7 instructions 268142c9f13Sbala /* 269142c9f13Sbala * Restore the DCU 270142c9f13Sbala */ 271142c9f13Sbala stxa %g1, [%g0]ASI_DCU 272142c9f13Sbala flush %g0 273142c9f13Sbala wrpr %g0, %o2, %pstate !restore pstate 274142c9f13Sbala retl 275142c9f13Sbala mov %o5, %o0 276142c9f13Sbala2: 277142c9f13Sbala ! It is OK to have STATE as NA (if so, nothing to do!) 278142c9f13Sbala and %o3, 0x7, %o3 279142c9f13Sbala cmp %o3, 0x5 280142c9f13Sbala be,a,pt %xcc, 9b 281142c9f13Sbala inc %o5 ! indicate was already NA 282142c9f13Sbala ! Hmm. Not INV, not NA 283142c9f13Sbala ba 9b 284142c9f13Sbala dec %o5 285142c9f13Sbalaretire_l3_end: 286142c9f13Sbala SET_SIZE(retire_l3) 287142c9f13Sbala 288142c9f13Sbala ENTRY(unretire_l3) 289142c9f13Sbalaunretire_l3_start: 290142c9f13Sbala 291142c9f13Sbala ! since we disable interrupts, we don't need to do kpreempt_disable() 292142c9f13Sbala rdpr %pstate, %o2 293142c9f13Sbala andn %o2, PSTATE_IE, %g1 294142c9f13Sbala wrpr %g0, %g1, %pstate ! disable interrupts 295142c9f13Sbala /* 296142c9f13Sbala * Save current DCU state. Turn off IPS 297142c9f13Sbala */ 298142c9f13Sbala setx DCU_IPS_MASK, %g2, %o3 299142c9f13Sbala ldxa [%g0]ASI_DCU, %g1 ! save DCU in %g1 300142c9f13Sbala andn %g1, %o3, %g4 301142c9f13Sbala stxa %g4, [%g0]ASI_DCU 302142c9f13Sbala flush %g0 /* flush required after changing the IC bit */ 303142c9f13Sbala PARK_SIBLING_CORE(%g1, %o3, %o4) ! %g1 has DCU value 304142c9f13Sbala 305142c9f13Sbala PN_ECACHE_FLUSH_LINE(%o0, %o3, %o4, %o5, %g2) 306142c9f13Sbala1: 307142c9f13Sbala clr %o5 ! assume success 308142c9f13Sbala ! Check that line is in NA state; if so, INV it. 309142c9f13Sbala ldxa [%o0]ASI_EC_DIAG, %o3 310142c9f13Sbala and %o3, 0x7, %o3 311142c9f13Sbala cmp %o3, 0x5 312142c9f13Sbala bne,a,pt %xcc, 9f ! Wasn't NA, so something is wrong 313142c9f13Sbala dec %o5 ! indicate not NA 314142c9f13Sbala stxa %g0, [%o0]ASI_EC_DIAG 315142c9f13Sbala membar #Sync 316142c9f13Sbala ! now delay 15 cycles so we don't have hazard when we return 317142c9f13Sbala mov 16, %o1 318142c9f13Sbala1: 319142c9f13Sbala brnz,pt %o1, 1b 320142c9f13Sbala dec %o1 321142c9f13Sbala9: 322142c9f13Sbala ! UNPARK-SIBLING_CORE is 7 instructions 323142c9f13Sbala UNPARK_SIBLING_CORE(%g1, %o3, %o4) ! 7 instructions 324142c9f13Sbala /* 325142c9f13Sbala * Restore the DCU 326142c9f13Sbala */ 327142c9f13Sbala stxa %g1, [%g0]ASI_DCU 328142c9f13Sbala flush %g0 329142c9f13Sbala wrpr %g0, %o2, %pstate !restore pstate 330142c9f13Sbala retl 331142c9f13Sbala mov %o5, %o0 332142c9f13Sbalaunretire_l3_end: 333142c9f13Sbala SET_SIZE(unretire_l3) 334142c9f13Sbala 335142c9f13Sbala .align 2048 336142c9f13Sbala 337142c9f13Sbala ENTRY(retire_l2_alternate) 338142c9f13Sbala 339142c9f13Sbala ! since we disable interrupts, we don't need to do kpreempt_disable() 340142c9f13Sbala rdpr %pstate, %o2 341142c9f13Sbala andn %o2, PSTATE_IE, %g1 342142c9f13Sbala wrpr %g0, %g1, %pstate ! disable interrupts 343142c9f13Sbala /* 344142c9f13Sbala * Save current DCU state. Turn off IPS 345142c9f13Sbala */ 346142c9f13Sbala setx DCU_IPS_MASK, %g2, %o3 347142c9f13Sbala ldxa [%g0]ASI_DCU, %g1 ! save DCU in %g1 348142c9f13Sbala andn %g1, %o3, %g4 349142c9f13Sbala stxa %g4, [%g0]ASI_DCU 350142c9f13Sbala flush %g0 351142c9f13Sbala PARK_SIBLING_CORE(%g1, %o3, %o4) ! %g1 has DCU value 352142c9f13Sbala clr %o5 ! assume success 353142c9f13Sbala8: 354142c9f13Sbala PN_ECACHE_FLUSH_LINE(%o0, %o3, %o4, %g2, %g3) 355142c9f13Sbala1: 356142c9f13Sbala ! Check if line is invalid; if so, NA it. 357142c9f13Sbala ldxa [%o0]ASI_L2_TAG, %o3 358142c9f13Sbala btst 0x7, %o3 359142c9f13Sbala bnz %xcc, 2f 360142c9f13Sbala nop 361142c9f13Sbala stxa %o1, [%o0]ASI_L2_TAG 362*55fea89dSDan Cross membar #Sync ! still on same cache line 363142c9f13Sbala ! now delay 15 cycles so we don't have hazard when we return 364142c9f13Sbala mov 16, %o1 365142c9f13Sbala1: 366142c9f13Sbala brnz,pt %o1, 1b 367142c9f13Sbala dec %o1 368142c9f13Sbala9: 369142c9f13Sbala ! UNPARK-SIBLING_CORE is 7 instructions, so we cross a cache boundary 370142c9f13Sbala UNPARK_SIBLING_CORE(%g1, %o3, %o4) ! 7 instructions 371142c9f13Sbala /* 372142c9f13Sbala * Restore the DCU 373142c9f13Sbala */ 374142c9f13Sbala stxa %g1, [%g0]ASI_DCU 375142c9f13Sbala flush %g0 376142c9f13Sbala wrpr %g0, %o2, %pstate !restore pstate 377142c9f13Sbala retl 378142c9f13Sbala mov %o5, %o0 379142c9f13Sbala2: 380142c9f13Sbala ! It is OK to have STATE as NA (if so, nothing to do!) 381142c9f13Sbala and %o3, 0x7, %o3 382142c9f13Sbala cmp %o3, 0x5 383142c9f13Sbala be,a,pt %xcc, 9b 384142c9f13Sbala mov 1, %o5 ! indicate was already NA 385142c9f13Sbala ! Hmm. Not INV, not NA. 386142c9f13Sbala cmp %o5, 0 387142c9f13Sbala be,a,pt %xcc, 8b ! Flush the cacheline again 388142c9f13Sbala mov 2, %o5 ! indicate retry was done 389142c9f13Sbala ! We already Flushed cacheline second time. Return -1 390142c9f13Sbala clr %o5 391142c9f13Sbala ba 9b 392142c9f13Sbala dec %o5 393142c9f13Sbala SET_SIZE(retire_l2_alternate) 394142c9f13Sbala 395142c9f13Sbala ENTRY(unretire_l2_alternate) 396142c9f13Sbala 397142c9f13Sbala ! since we disable interrupts, we don't need to do kpreempt_disable() 398142c9f13Sbala rdpr %pstate, %o2 399142c9f13Sbala andn %o2, PSTATE_IE, %g1 400142c9f13Sbala wrpr %g0, %g1, %pstate ! disable interrupts 401142c9f13Sbala /* 402142c9f13Sbala * Save current DCU state. Turn off IPS 403142c9f13Sbala */ 404142c9f13Sbala setx DCU_IPS_MASK, %g2, %o3 405142c9f13Sbala ldxa [%g0]ASI_DCU, %g1 ! save DCU in %g1 406142c9f13Sbala andn %g1, %o3, %g4 407142c9f13Sbala stxa %g4, [%g0]ASI_DCU 408142c9f13Sbala flush %g0 /* flush required after changing the IC bit */ 409142c9f13Sbala PARK_SIBLING_CORE(%g1, %o3, %o4) ! %g1 has DCU value 410142c9f13Sbala 411142c9f13Sbala PN_ECACHE_FLUSH_LINE(%o0, %o3, %o4, %o5, %g2) 412142c9f13Sbala1: 413142c9f13Sbala clr %o5 ! assume success 414142c9f13Sbala ! Check that line is in NA state; if so, INV it. 415142c9f13Sbala ldxa [%o0]ASI_L2_TAG, %o3 416142c9f13Sbala and %o3, 0x7, %o3 417142c9f13Sbala cmp %o3, 0x5 418142c9f13Sbala bne,a,pt %xcc, 9f ! Wasn't NA, so something is wrong 419142c9f13Sbala dec %o5 ! indicate not NA 420142c9f13Sbala stxa %g0, [%o0]ASI_L2_TAG 421142c9f13Sbala membar #Sync 422142c9f13Sbala ! now delay 15 cycles so we don't have hazard when we return 423142c9f13Sbala mov 16, %o1 424142c9f13Sbala1: 425142c9f13Sbala brnz,pt %o1, 1b 426142c9f13Sbala dec %o1 427142c9f13Sbala9: 428142c9f13Sbala ! UNPARK-SIBLING_CORE is 7 instructions 429142c9f13Sbala UNPARK_SIBLING_CORE(%g1, %o3, %o4) ! 7 instructions 430142c9f13Sbala /* 431142c9f13Sbala * Restore the DCU 432142c9f13Sbala */ 433142c9f13Sbala stxa %g1, [%g0]ASI_DCU 434142c9f13Sbala flush %g0 435142c9f13Sbala wrpr %g0, %o2, %pstate !restore pstate 436142c9f13Sbala retl 437142c9f13Sbala mov %o5, %o0 438142c9f13Sbala SET_SIZE(unretire_l2_alternate) 439142c9f13Sbala 440142c9f13Sbala ENTRY(retire_l3_alternate) 441142c9f13Sbala 442142c9f13Sbala ! since we disable interrupts, we don't need to do kpreempt_disable() 443142c9f13Sbala rdpr %pstate, %o2 444142c9f13Sbala andn %o2, PSTATE_IE, %g1 445142c9f13Sbala wrpr %g0, %g1, %pstate ! disable interrupts 446142c9f13Sbala /* 447142c9f13Sbala * Save current DCU state. Turn off IPS 448142c9f13Sbala */ 449142c9f13Sbala setx DCU_IPS_MASK, %g2, %o3 450142c9f13Sbala ldxa [%g0]ASI_DCU, %g1 ! save DCU in %g1 451142c9f13Sbala andn %g1, %o3, %g4 452142c9f13Sbala stxa %g4, [%g0]ASI_DCU 453142c9f13Sbala flush %g0 /* flush required after changing the IC bit */ 454142c9f13Sbala PARK_SIBLING_CORE(%g1, %o3, %o4) ! %g1 has DCU value 455142c9f13Sbala 456142c9f13Sbala ! PN-ECACHE-FLUSH_LINE is 30 instructions 457142c9f13Sbala PN_ECACHE_FLUSH_LINE(%o0, %o3, %o4, %o5, %g2) 458142c9f13Sbala1: 459142c9f13Sbala clr %o5 ! assume success 460142c9f13Sbala ! Check if line is invalid; if so, NA it. 461142c9f13Sbala ldxa [%o0]ASI_EC_DIAG, %o3 462142c9f13Sbala btst 0x7, %o3 463142c9f13Sbala bnz %xcc, 2f 464142c9f13Sbala nop 465142c9f13Sbala stxa %o1, [%o0]ASI_EC_DIAG 466*55fea89dSDan Cross membar #Sync ! still on same cache line 467142c9f13Sbala ! now delay 15 cycles so we don't have hazard when we return 468142c9f13Sbala mov 16, %o1 469142c9f13Sbala1: 470142c9f13Sbala brnz,pt %o1, 1b 471142c9f13Sbala dec %o1 472142c9f13Sbala9: 473142c9f13Sbala ! UNPARK-SIBLING_CORE is 7 instructions, so we cross a cache boundary 474142c9f13Sbala UNPARK_SIBLING_CORE(%g1, %o3, %o4) ! 7 instructions 475142c9f13Sbala /* 476142c9f13Sbala * Restore the DCU 477142c9f13Sbala */ 478142c9f13Sbala stxa %g1, [%g0]ASI_DCU 479142c9f13Sbala flush %g0 480142c9f13Sbala wrpr %g0, %o2, %pstate !restore pstate 481142c9f13Sbala retl 482142c9f13Sbala mov %o5, %o0 483142c9f13Sbala2: 484142c9f13Sbala ! It is OK to have STATE as NA (if so, nothing to do!) 485142c9f13Sbala and %o3, 0x7, %o3 486142c9f13Sbala cmp %o3, 0x5 487142c9f13Sbala be,a,pt %xcc, 9b 488142c9f13Sbala inc %o5 ! indicate was already NA 489142c9f13Sbala ! Hmm. Not INV, not NA 490142c9f13Sbala ba 9b 491142c9f13Sbala dec %o5 492142c9f13Sbala SET_SIZE(retire_l3_alternate) 493142c9f13Sbala 494142c9f13Sbala ENTRY(unretire_l3_alternate) 495142c9f13Sbala 496142c9f13Sbala ! since we disable interrupts, we don't need to do kpreempt_disable() 497142c9f13Sbala rdpr %pstate, %o2 498142c9f13Sbala andn %o2, PSTATE_IE, %g1 499142c9f13Sbala wrpr %g0, %g1, %pstate ! disable interrupts 500142c9f13Sbala /* 501142c9f13Sbala * Save current DCU state. Turn off IPS 502142c9f13Sbala */ 503142c9f13Sbala setx DCU_IPS_MASK, %g2, %o3 504142c9f13Sbala ldxa [%g0]ASI_DCU, %g1 ! save DCU in %g1 505142c9f13Sbala andn %g1, %o3, %g4 506142c9f13Sbala stxa %g4, [%g0]ASI_DCU 507142c9f13Sbala flush %g0 /* flush required after changing the IC bit */ 508142c9f13Sbala PARK_SIBLING_CORE(%g1, %o3, %o4) ! %g1 has DCU value 509142c9f13Sbala 510142c9f13Sbala PN_ECACHE_FLUSH_LINE(%o0, %o3, %o4, %o5, %g2) 511142c9f13Sbala1: 512142c9f13Sbala clr %o5 ! assume success 513142c9f13Sbala ! Check that line is in NA state; if so, INV it. 514142c9f13Sbala ldxa [%o0]ASI_EC_DIAG, %o3 515142c9f13Sbala and %o3, 0x7, %o3 516142c9f13Sbala cmp %o3, 0x5 517142c9f13Sbala bne,a,pt %xcc, 9f ! Wasn't NA, so something is wrong 518142c9f13Sbala dec %o5 ! indicate not NA 519142c9f13Sbala stxa %g0, [%o0]ASI_EC_DIAG 520142c9f13Sbala membar #Sync 521142c9f13Sbala ! now delay 15 cycles so we don't have hazard when we return 522142c9f13Sbala mov 16, %o1 523142c9f13Sbala1: 524142c9f13Sbala brnz,pt %o1, 1b 525142c9f13Sbala dec %o1 526142c9f13Sbala9: 527142c9f13Sbala ! UNPARK-SIBLING_CORE is 7 instructions 528142c9f13Sbala UNPARK_SIBLING_CORE(%g1, %o3, %o4) ! 7 instructions 529142c9f13Sbala /* 530142c9f13Sbala * Restore the DCU 531142c9f13Sbala */ 532142c9f13Sbala stxa %g1, [%g0]ASI_DCU 533142c9f13Sbala flush %g0 534142c9f13Sbala wrpr %g0, %o2, %pstate !restore pstate 535142c9f13Sbala retl 536142c9f13Sbala mov %o5, %o0 537142c9f13Sbala SET_SIZE(unretire_l3_alternate) 538142c9f13Sbala 539142c9f13Sbala ENTRY(get_ecache_dtags_tl1) 540142c9f13Sbala 541142c9f13Sbala 542*55fea89dSDan Cross PARK_SIBLING_CORE(%g3, %g4, %g5) 543142c9f13Sbala add %g2, CH_CLO_DATA + CH_CHD_EC_DATA, %g2 544142c9f13Sbala rd %asi, %g4 545142c9f13Sbala wr %g0, ASI_N, %asi 546142c9f13Sbala GET_ECACHE_DTAGS(%g1, %g2, %g5, %g6, %g7) 547142c9f13Sbala wr %g4, %asi 548142c9f13Sbala UNPARK_SIBLING_CORE(%g3, %g4, %g5) ! can use %g3 again 549142c9f13Sbala 550142c9f13Sbala retry 551142c9f13Sbala SET_SIZE(get_ecache_dtags_tl1) 552142c9f13Sbala 553142c9f13Sbala ENTRY(get_l2_tag_tl1) 554142c9f13Sbala 555142c9f13Sbala /* 556142c9f13Sbala * Now read the tag data 557142c9f13Sbala */ 558142c9f13Sbala ldxa [%g1]ASI_L2_TAG, %g4 ! save tag_data 559142c9f13Sbala stx %g4, [%g2] 560142c9f13Sbala 561142c9f13Sbala retry 562142c9f13Sbala SET_SIZE(get_l2_tag_tl1) 563142c9f13Sbala 564142c9f13Sbala ENTRY(get_l3_tag_tl1) 565142c9f13Sbala 566142c9f13Sbala /* 567142c9f13Sbala * Now read the tag data 568142c9f13Sbala */ 569142c9f13Sbala ldxa [%g1]ASI_EC_DIAG, %g4 ! save tag_data 570142c9f13Sbala stx %g4, [%g2] 571142c9f13Sbala 572142c9f13Sbala retry 573142c9f13Sbala SET_SIZE(get_l3_tag_tl1) 574142c9f13Sbala 575