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