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 Cheetah/Cheetah+ modules 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/trap.h> 43#include <sys/cheetahregs.h> 44#include <sys/us3_module.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#if !defined(lint) 57 58/* BEGIN CSTYLED */ 59 60#define DCACHE_FLUSHPAGE(arg1, arg2, tmp1, tmp2, tmp3) \ 61 ldxa [%g0]ASI_DCU, tmp1 ;\ 62 btst DCU_DC, tmp1 /* is dcache enabled? */ ;\ 63 bz,pn %icc, 1f ;\ 64 ASM_LD(tmp1, dcache_linesize) ;\ 65 ASM_LD(tmp2, dflush_type) ;\ 66 cmp tmp2, FLUSHPAGE_TYPE ;\ 67 be,pt %icc, 2f ;\ 68 nop ;\ 69 sllx arg1, CHEETAH_DC_VBIT_SHIFT, arg1/* tag to compare */ ;\ 70 ASM_LD(tmp3, dcache_size) ;\ 71 cmp tmp2, FLUSHMATCH_TYPE ;\ 72 be,pt %icc, 3f ;\ 73 nop ;\ 74 /* \ 75 * flushtype = FLUSHALL_TYPE, flush the whole thing \ 76 * tmp3 = cache size \ 77 * tmp1 = cache line size \ 78 */ \ 79 sub tmp3, tmp1, tmp2 ;\ 804: \ 81 stxa %g0, [tmp2]ASI_DC_TAG ;\ 82 membar #Sync ;\ 83 cmp %g0, tmp2 ;\ 84 bne,pt %icc, 4b ;\ 85 sub tmp2, tmp1, tmp2 ;\ 86 ba,pt %icc, 1f ;\ 87 nop ;\ 88 /* \ 89 * flushtype = FLUSHPAGE_TYPE \ 90 * arg1 = pfn \ 91 * arg2 = virtual color \ 92 * tmp1 = cache line size \ 93 * tmp2 = tag from cache \ 94 * tmp3 = counter \ 95 */ \ 962: \ 97 set MMU_PAGESIZE, tmp3 ;\ 98 sllx arg1, MMU_PAGESHIFT, arg1 /* pfn to 43 bit PA */ ;\ 99 sub tmp3, tmp1, tmp3 ;\ 1004: \ 101 stxa %g0, [arg1 + tmp3]ASI_DC_INVAL ;\ 102 membar #Sync ;\ 1035: \ 104 cmp %g0, tmp3 ;\ 105 bnz,pt %icc, 4b /* branch if not done */ ;\ 106 sub tmp3, tmp1, tmp3 ;\ 107 ba,pt %icc, 1f ;\ 108 nop ;\ 109 /* \ 110 * flushtype = FLUSHMATCH_TYPE \ 111 * arg1 = tag to compare against \ 112 * tmp1 = cache line size \ 113 * tmp3 = cache size \ 114 * arg2 = counter \ 115 * tmp2 = cache tag \ 116 */ \ 1173: \ 118 sub tmp3, tmp1, arg2 ;\ 1194: \ 120 ldxa [arg2]ASI_DC_TAG, tmp2 /* read tag */ ;\ 121 btst CHEETAH_DC_VBIT_MASK, tmp2 ;\ 122 bz,pn %icc, 5f /* br if no valid sub-blocks */ ;\ 123 andn tmp2, CHEETAH_DC_VBIT_MASK, tmp2 /* clear out v bits */ ;\ 124 cmp tmp2, arg1 ;\ 125 bne,pn %icc, 5f /* branch if tag miss */ ;\ 126 nop ;\ 127 stxa %g0, [arg2]ASI_DC_TAG ;\ 128 membar #Sync ;\ 1295: \ 130 cmp %g0, arg2 ;\ 131 bne,pt %icc, 4b /* branch if not done */ ;\ 132 sub arg2, tmp1, arg2 ;\ 1331: 134 135 136/* END CSTYLED */ 137 138#endif /* !lint */ 139 140/* 141 * Cheetah MMU and Cache operations. 142 */ 143 144#if defined(lint) 145 146/* ARGSUSED */ 147void 148vtag_flushpage(caddr_t vaddr, uint64_t sfmmup) 149{} 150 151#else /* lint */ 152 153 ENTRY_NP(vtag_flushpage) 154 /* 155 * flush page from the tlb 156 * 157 * %o0 = vaddr 158 * %o1 = sfmmup 159 */ 160 rdpr %pstate, %o5 161#ifdef DEBUG 162 PANIC_IF_INTR_DISABLED_PSTR(%o5, u3_di_label0, %g1) 163#endif /* DEBUG */ 164 /* 165 * disable ints 166 */ 167 andn %o5, PSTATE_IE, %o4 168 wrpr %o4, 0, %pstate 169 170 /* 171 * Then, blow out the tlb 172 * Interrupts are disabled to prevent the primary ctx register 173 * from changing underneath us. 174 */ 175 sethi %hi(ksfmmup), %o3 176 ldx [%o3 + %lo(ksfmmup)], %o3 177 cmp %o3, %o1 178 bne,pt %xcc, 1f ! if not kernel as, go to 1 179 sethi %hi(FLUSH_ADDR), %o3 180 /* 181 * For Kernel demaps use primary. type = page implicitly 182 */ 183 stxa %g0, [%o0]ASI_DTLB_DEMAP /* dmmu flush for KCONTEXT */ 184 stxa %g0, [%o0]ASI_ITLB_DEMAP /* immu flush for KCONTEXT */ 185 flush %o3 186 retl 187 wrpr %g0, %o5, %pstate /* enable interrupts */ 1881: 189 /* 190 * User demap. We need to set the primary context properly. 191 * Secondary context cannot be used for Cheetah IMMU. 192 * %o0 = vaddr 193 * %o1 = sfmmup 194 * %o3 = FLUSH_ADDR 195 */ 196 SFMMU_CPU_CNUM(%o1, %g1, %g2) ! %g1 = sfmmu cnum on this CPU 197 198 ldub [%o1 + SFMMU_CEXT], %o4 ! %o4 = sfmmup->sfmmu_cext 199 sll %o4, CTXREG_EXT_SHIFT, %o4 200 or %g1, %o4, %g1 ! %g1 = primary pgsz | cnum 201 202 wrpr %g0, 1, %tl 203 set MMU_PCONTEXT, %o4 204 or DEMAP_PRIMARY | DEMAP_PAGE_TYPE, %o0, %o0 205 ldxa [%o4]ASI_DMMU, %o2 ! %o2 = save old ctxnum 206 srlx %o2, CTXREG_NEXT_SHIFT, %o1 ! need to preserve nucleus pgsz 207 sllx %o1, CTXREG_NEXT_SHIFT, %o1 ! %o1 = nucleus pgsz 208 or %g1, %o1, %g1 ! %g1 = nucleus pgsz | primary pgsz | cnum 209 stxa %g1, [%o4]ASI_DMMU ! wr new ctxum 210 211 stxa %g0, [%o0]ASI_DTLB_DEMAP 212 stxa %g0, [%o0]ASI_ITLB_DEMAP 213 stxa %o2, [%o4]ASI_DMMU /* restore old ctxnum */ 214 flush %o3 215 wrpr %g0, 0, %tl 216 217 retl 218 wrpr %g0, %o5, %pstate /* enable interrupts */ 219 SET_SIZE(vtag_flushpage) 220 221#endif /* lint */ 222 223#if defined(lint) 224 225void 226vtag_flushall(void) 227{} 228 229#else /* lint */ 230 231 ENTRY_NP2(vtag_flushall, demap_all) 232 /* 233 * flush the tlb 234 */ 235 sethi %hi(FLUSH_ADDR), %o3 236 set DEMAP_ALL_TYPE, %g1 237 stxa %g0, [%g1]ASI_DTLB_DEMAP 238 stxa %g0, [%g1]ASI_ITLB_DEMAP 239 flush %o3 240 retl 241 nop 242 SET_SIZE(demap_all) 243 SET_SIZE(vtag_flushall) 244 245#endif /* lint */ 246 247 248#if defined(lint) 249 250/* ARGSUSED */ 251void 252vtag_flushpage_tl1(uint64_t vaddr, uint64_t sfmmup) 253{} 254 255#else /* lint */ 256 257 ENTRY_NP(vtag_flushpage_tl1) 258 /* 259 * x-trap to flush page from tlb and tsb 260 * 261 * %g1 = vaddr, zero-extended on 32-bit kernel 262 * %g2 = sfmmup 263 * 264 * assumes TSBE_TAG = 0 265 */ 266 srln %g1, MMU_PAGESHIFT, %g1 267 268 sethi %hi(ksfmmup), %g3 269 ldx [%g3 + %lo(ksfmmup)], %g3 270 cmp %g3, %g2 271 bne,pt %xcc, 1f ! if not kernel as, go to 1 272 slln %g1, MMU_PAGESHIFT, %g1 /* g1 = vaddr */ 273 274 /* We need to demap in the kernel context */ 275 or DEMAP_NUCLEUS | DEMAP_PAGE_TYPE, %g1, %g1 276 stxa %g0, [%g1]ASI_DTLB_DEMAP 277 stxa %g0, [%g1]ASI_ITLB_DEMAP 278 retry 2791: 280 /* We need to demap in a user context */ 281 or DEMAP_PRIMARY | DEMAP_PAGE_TYPE, %g1, %g1 282 283 SFMMU_CPU_CNUM(%g2, %g6, %g3) ! %g6 = sfmmu cnum on this CPU 284 285 ldub [%g2 + SFMMU_CEXT], %g4 ! %g4 = sfmmup->cext 286 sll %g4, CTXREG_EXT_SHIFT, %g4 287 or %g6, %g4, %g6 ! %g6 = pgsz | cnum 288 289 set MMU_PCONTEXT, %g4 290 ldxa [%g4]ASI_DMMU, %g5 /* rd old ctxnum */ 291 srlx %g5, CTXREG_NEXT_SHIFT, %g2 /* %g2 = nucleus pgsz */ 292 sllx %g2, CTXREG_NEXT_SHIFT, %g2 /* preserve nucleus pgsz */ 293 or %g6, %g2, %g6 /* %g6 = nucleus pgsz | primary pgsz | cnum */ 294 stxa %g6, [%g4]ASI_DMMU /* wr new ctxum */ 295 stxa %g0, [%g1]ASI_DTLB_DEMAP 296 stxa %g0, [%g1]ASI_ITLB_DEMAP 297 stxa %g5, [%g4]ASI_DMMU /* restore old ctxnum */ 298 retry 299 SET_SIZE(vtag_flushpage_tl1) 300 301#endif /* lint */ 302 303 304#if defined(lint) 305 306/* ARGSUSED */ 307void 308vtag_flush_pgcnt_tl1(uint64_t vaddr, uint64_t sfmmup_pgcnt) 309{} 310 311#else /* lint */ 312 313 ENTRY_NP(vtag_flush_pgcnt_tl1) 314 /* 315 * x-trap to flush pgcnt MMU_PAGESIZE pages from tlb 316 * 317 * %g1 = vaddr, zero-extended on 32-bit kernel 318 * %g2 = <sfmmup58|pgcnt6>, (pgcnt - 1) is pass'ed in via pgcnt6 bits. 319 * 320 * NOTE: this handler relies on the fact that no 321 * interrupts or traps can occur during the loop 322 * issuing the TLB_DEMAP operations. It is assumed 323 * that interrupts are disabled and this code is 324 * fetching from the kernel locked text address. 325 * 326 * assumes TSBE_TAG = 0 327 */ 328 set SFMMU_PGCNT_MASK, %g4 329 and %g4, %g2, %g3 /* g3 = pgcnt - 1 */ 330 add %g3, 1, %g3 /* g3 = pgcnt */ 331 332 andn %g2, SFMMU_PGCNT_MASK, %g2 /* g2 = sfmmup */ 333 srln %g1, MMU_PAGESHIFT, %g1 334 335 sethi %hi(ksfmmup), %g4 336 ldx [%g4 + %lo(ksfmmup)], %g4 337 cmp %g4, %g2 338 bne,pn %xcc, 1f /* if not kernel as, go to 1 */ 339 slln %g1, MMU_PAGESHIFT, %g1 /* g1 = vaddr */ 340 341 /* We need to demap in the kernel context */ 342 or DEMAP_NUCLEUS | DEMAP_PAGE_TYPE, %g1, %g1 343 set MMU_PAGESIZE, %g2 /* g2 = pgsize */ 344 sethi %hi(FLUSH_ADDR), %g5 3454: 346 stxa %g0, [%g1]ASI_DTLB_DEMAP 347 stxa %g0, [%g1]ASI_ITLB_DEMAP 348 flush %g5 ! flush required by immu 349 350 deccc %g3 /* decr pgcnt */ 351 bnz,pt %icc,4b 352 add %g1, %g2, %g1 /* next page */ 353 retry 3541: 355 /* 356 * We need to demap in a user context 357 * 358 * g2 = sfmmup 359 * g3 = pgcnt 360 */ 361 SFMMU_CPU_CNUM(%g2, %g5, %g6) ! %g5 = sfmmu cnum on this CPU 362 363 or DEMAP_PRIMARY | DEMAP_PAGE_TYPE, %g1, %g1 364 365 ldub [%g2 + SFMMU_CEXT], %g4 ! %g4 = sfmmup->cext 366 sll %g4, CTXREG_EXT_SHIFT, %g4 367 or %g5, %g4, %g5 368 369 set MMU_PCONTEXT, %g4 370 ldxa [%g4]ASI_DMMU, %g6 /* rd old ctxnum */ 371 srlx %g6, CTXREG_NEXT_SHIFT, %g2 /* %g2 = nucleus pgsz */ 372 sllx %g2, CTXREG_NEXT_SHIFT, %g2 /* preserve nucleus pgsz */ 373 or %g5, %g2, %g5 /* %g5 = nucleus pgsz | primary pgsz | cnum */ 374 stxa %g5, [%g4]ASI_DMMU /* wr new ctxum */ 375 376 set MMU_PAGESIZE, %g2 /* g2 = pgsize */ 377 sethi %hi(FLUSH_ADDR), %g5 3783: 379 stxa %g0, [%g1]ASI_DTLB_DEMAP 380 stxa %g0, [%g1]ASI_ITLB_DEMAP 381 flush %g5 ! flush required by immu 382 383 deccc %g3 /* decr pgcnt */ 384 bnz,pt %icc,3b 385 add %g1, %g2, %g1 /* next page */ 386 387 stxa %g6, [%g4]ASI_DMMU /* restore old ctxnum */ 388 retry 389 SET_SIZE(vtag_flush_pgcnt_tl1) 390 391#endif /* lint */ 392 393#if defined(lint) 394 395/*ARGSUSED*/ 396void 397vtag_flushall_tl1(uint64_t dummy1, uint64_t dummy2) 398{} 399 400#else /* lint */ 401 402 ENTRY_NP(vtag_flushall_tl1) 403 /* 404 * x-trap to flush tlb 405 */ 406 set DEMAP_ALL_TYPE, %g4 407 stxa %g0, [%g4]ASI_DTLB_DEMAP 408 stxa %g0, [%g4]ASI_ITLB_DEMAP 409 retry 410 SET_SIZE(vtag_flushall_tl1) 411 412#endif /* lint */ 413 414 415#if defined(lint) 416 417/* ARGSUSED */ 418void 419vac_flushpage(pfn_t pfnum, int vcolor) 420{} 421 422#else /* lint */ 423 424/* 425 * vac_flushpage(pfnum, color) 426 * Flush 1 8k page of the D-$ with physical page = pfnum 427 * Algorithm: 428 * The cheetah dcache is a 64k psuedo 4 way accaociative cache. 429 * It is virtual indexed, physically tagged cache. 430 */ 431 .seg ".data" 432 .align 8 433 .global dflush_type 434dflush_type: 435 .word FLUSHPAGE_TYPE 436 437 ENTRY(vac_flushpage) 438 /* 439 * flush page from the d$ 440 * 441 * %o0 = pfnum, %o1 = color 442 */ 443 DCACHE_FLUSHPAGE(%o0, %o1, %o2, %o3, %o4) 444 retl 445 nop 446 SET_SIZE(vac_flushpage) 447 448#endif /* lint */ 449 450 451#if defined(lint) 452 453/* ARGSUSED */ 454void 455vac_flushpage_tl1(uint64_t pfnum, uint64_t vcolor) 456{} 457 458#else /* lint */ 459 460 ENTRY_NP(vac_flushpage_tl1) 461 /* 462 * x-trap to flush page from the d$ 463 * 464 * %g1 = pfnum, %g2 = color 465 */ 466 DCACHE_FLUSHPAGE(%g1, %g2, %g3, %g4, %g5) 467 retry 468 SET_SIZE(vac_flushpage_tl1) 469 470#endif /* lint */ 471 472 473#if defined(lint) 474 475/* ARGSUSED */ 476void 477vac_flushcolor(int vcolor, pfn_t pfnum) 478{} 479 480#else /* lint */ 481 /* 482 * In UltraSPARC III flushcolor is same as as flushpage. 483 * This is because we have an ASI to flush dcache using physical 484 * address. 485 * Flushing dcache using physical address is faster because we 486 * don't have to deal with associativity of dcache. 487 * The arguments to vac_flushpage() and vac_flushcolor() are same but 488 * the order is reversed. this is because we maintain compatibility 489 * with spitfire, in which vac_flushcolor has only one argument, namely 490 * vcolor. 491 */ 492 493 ENTRY(vac_flushcolor) 494 /* 495 * %o0 = vcolor, %o1 = pfnum 496 */ 497 DCACHE_FLUSHPAGE(%o1, %o0, %o2, %o3, %o4) 498 retl 499 nop 500 SET_SIZE(vac_flushcolor) 501 502#endif /* lint */ 503 504 505#if defined(lint) 506 507/* ARGSUSED */ 508void 509vac_flushcolor_tl1(uint64_t vcolor, uint64_t pfnum) 510{} 511 512#else /* lint */ 513 514 ENTRY(vac_flushcolor_tl1) 515 /* 516 * %g1 = vcolor 517 * %g2 = pfnum 518 */ 519 DCACHE_FLUSHPAGE(%g2, %g1, %g3, %g4, %g5) 520 retry 521 SET_SIZE(vac_flushcolor_tl1) 522 523#endif /* lint */ 524 525#if defined(lint) 526 527int 528idsr_busy(void) 529{ 530 return (0); 531} 532 533#else /* lint */ 534 535/* 536 * Determine whether or not the IDSR is busy. 537 * Entry: no arguments 538 * Returns: 1 if busy, 0 otherwise 539 */ 540 ENTRY(idsr_busy) 541 ldxa [%g0]ASI_INTR_DISPATCH_STATUS, %g1 542 clr %o0 543 btst IDSR_BUSY, %g1 544 bz,a,pt %xcc, 1f 545 mov 1, %o0 5461: 547 retl 548 nop 549 SET_SIZE(idsr_busy) 550 551#endif /* lint */ 552 553#if defined(lint) 554 555/* ARGSUSED */ 556void 557init_mondo(xcfunc_t *func, uint64_t arg1, uint64_t arg2) 558{} 559 560/* ARGSUSED */ 561void 562init_mondo_nocheck(xcfunc_t *func, uint64_t arg1, uint64_t arg2) 563{} 564 565#else /* lint */ 566 567 .global _dispatch_status_busy 568_dispatch_status_busy: 569 .asciz "ASI_INTR_DISPATCH_STATUS error: busy" 570 .align 4 571 572/* 573 * Setup interrupt dispatch data registers 574 * Entry: 575 * %o0 - function or inumber to call 576 * %o1, %o2 - arguments (2 uint64_t's) 577 */ 578 .seg "text" 579 580 ENTRY(init_mondo) 581#ifdef DEBUG 582 ! 583 ! IDSR should not be busy at the moment 584 ! 585 ldxa [%g0]ASI_INTR_DISPATCH_STATUS, %g1 586 btst IDSR_BUSY, %g1 587 bz,pt %xcc, 1f 588 nop 589 sethi %hi(_dispatch_status_busy), %o0 590 call panic 591 or %o0, %lo(_dispatch_status_busy), %o0 592#endif /* DEBUG */ 593 594 ALTENTRY(init_mondo_nocheck) 595 ! 596 ! interrupt vector dispatch data reg 0 597 ! 5981: 599 mov IDDR_0, %g1 600 mov IDDR_1, %g2 601 mov IDDR_2, %g3 602 stxa %o0, [%g1]ASI_INTR_DISPATCH 603 604 ! 605 ! interrupt vector dispatch data reg 1 606 ! 607 stxa %o1, [%g2]ASI_INTR_DISPATCH 608 609 ! 610 ! interrupt vector dispatch data reg 2 611 ! 612 stxa %o2, [%g3]ASI_INTR_DISPATCH 613 614 membar #Sync 615 retl 616 nop 617 SET_SIZE(init_mondo_nocheck) 618 SET_SIZE(init_mondo) 619 620#endif /* lint */ 621 622 623#if !(defined(JALAPENO) || defined(SERRANO)) 624 625#if defined(lint) 626 627/* ARGSUSED */ 628void 629shipit(int upaid, int bn) 630{ return; } 631 632#else /* lint */ 633 634/* 635 * Ship mondo to aid using busy/nack pair bn 636 */ 637 ENTRY_NP(shipit) 638 sll %o0, IDCR_PID_SHIFT, %g1 ! IDCR<18:14> = agent id 639 sll %o1, IDCR_BN_SHIFT, %g2 ! IDCR<28:24> = b/n pair 640 or %g1, IDCR_OFFSET, %g1 ! IDCR<13:0> = 0x70 641 or %g1, %g2, %g1 642 stxa %g0, [%g1]ASI_INTR_DISPATCH ! interrupt vector dispatch 643 membar #Sync 644 retl 645 nop 646 SET_SIZE(shipit) 647 648#endif /* lint */ 649 650#endif /* !(JALAPENO || SERRANO) */ 651 652 653#if defined(lint) 654 655/* ARGSUSED */ 656void 657flush_instr_mem(caddr_t vaddr, size_t len) 658{} 659 660#else /* lint */ 661 662/* 663 * flush_instr_mem: 664 * Flush 1 page of the I-$ starting at vaddr 665 * %o0 vaddr 666 * %o1 bytes to be flushed 667 * UltraSPARC-III maintains consistency of the on-chip Instruction Cache with 668 * the stores from all processors so that a FLUSH instruction is only needed 669 * to ensure pipeline is consistent. This means a single flush is sufficient at 670 * the end of a sequence of stores that updates the instruction stream to 671 * ensure correct operation. 672 */ 673 674 ENTRY(flush_instr_mem) 675 flush %o0 ! address irrelevant 676 retl 677 nop 678 SET_SIZE(flush_instr_mem) 679 680#endif /* lint */ 681 682 683#if defined(CPU_IMP_ECACHE_ASSOC) 684 685#if defined(lint) 686 687/* ARGSUSED */ 688uint64_t 689get_ecache_ctrl(void) 690{ return (0); } 691 692#else /* lint */ 693 694 ENTRY(get_ecache_ctrl) 695 GET_CPU_IMPL(%o0) 696 cmp %o0, JAGUAR_IMPL 697 ! 698 ! Putting an ASI access in the delay slot may 699 ! cause it to be accessed, even when annulled. 700 ! 701 bne 1f 702 nop 703 ldxa [%g0]ASI_EC_CFG_TIMING, %o0 ! read Jaguar shared E$ ctrl reg 704 b 2f 705 nop 7061: 707 ldxa [%g0]ASI_EC_CTRL, %o0 ! read Ch/Ch+ E$ control reg 7082: 709 retl 710 nop 711 SET_SIZE(get_ecache_ctrl) 712 713#endif /* lint */ 714 715#endif /* CPU_IMP_ECACHE_ASSOC */ 716 717 718#if !(defined(JALAPENO) || defined(SERRANO)) 719 720/* 721 * flush_ecache: 722 * %o0 - 64 bit physical address 723 * %o1 - ecache size 724 * %o2 - ecache linesize 725 */ 726#if defined(lint) 727 728/*ARGSUSED*/ 729void 730flush_ecache(uint64_t physaddr, size_t ecache_size, size_t ecache_linesize) 731{} 732 733#else /* !lint */ 734 735 ENTRY(flush_ecache) 736 737 /* 738 * For certain CPU implementations, we have to flush the L2 cache 739 * before flushing the ecache. 740 */ 741 PN_L2_FLUSHALL(%g3, %g4, %g5) 742 743 /* 744 * Flush the entire Ecache using displacement flush. 745 */ 746 ECACHE_FLUSHALL(%o1, %o2, %o0, %o4) 747 748 retl 749 nop 750 SET_SIZE(flush_ecache) 751 752#endif /* lint */ 753 754#endif /* !(JALAPENO || SERRANO) */ 755 756 757#if defined(lint) 758 759void 760flush_dcache(void) 761{} 762 763#else /* lint */ 764 765 ENTRY(flush_dcache) 766 ASM_LD(%o0, dcache_size) 767 ASM_LD(%o1, dcache_linesize) 768 CH_DCACHE_FLUSHALL(%o0, %o1, %o2) 769 retl 770 nop 771 SET_SIZE(flush_dcache) 772 773#endif /* lint */ 774 775 776#if defined(lint) 777 778void 779flush_icache(void) 780{} 781 782#else /* lint */ 783 784 ENTRY(flush_icache) 785 GET_CPU_PRIVATE_PTR(%g0, %o0, %o2, flush_icache_1); 786 ld [%o0 + CHPR_ICACHE_LINESIZE], %o1 787 ba,pt %icc, 2f 788 ld [%o0 + CHPR_ICACHE_SIZE], %o0 789flush_icache_1: 790 ASM_LD(%o0, icache_size) 791 ASM_LD(%o1, icache_linesize) 7922: 793 CH_ICACHE_FLUSHALL(%o0, %o1, %o2, %o4) 794 retl 795 nop 796 SET_SIZE(flush_icache) 797 798#endif /* lint */ 799 800#if defined(lint) 801 802/*ARGSUSED*/ 803void 804kdi_flush_idcache(int dcache_size, int dcache_lsize, int icache_size, 805 int icache_lsize) 806{ 807} 808 809#else /* lint */ 810 811 ENTRY(kdi_flush_idcache) 812 CH_DCACHE_FLUSHALL(%o0, %o1, %g1) 813 CH_ICACHE_FLUSHALL(%o2, %o3, %g1, %g2) 814 membar #Sync 815 retl 816 nop 817 SET_SIZE(kdi_flush_idcache) 818 819#endif /* lint */ 820 821#if defined(lint) 822 823void 824flush_pcache(void) 825{} 826 827#else /* lint */ 828 829 ENTRY(flush_pcache) 830 PCACHE_FLUSHALL(%o0, %o1, %o2) 831 retl 832 nop 833 SET_SIZE(flush_pcache) 834 835#endif /* lint */ 836 837 838#if defined(CPU_IMP_L1_CACHE_PARITY) 839 840#if defined(lint) 841 842/* ARGSUSED */ 843void 844get_dcache_dtag(uint32_t dcache_idx, uint64_t *data) 845{} 846 847#else /* lint */ 848 849/* 850 * Get dcache data and tag. The Dcache data is a pointer to a ch_dc_data_t 851 * structure (see cheetahregs.h): 852 * The Dcache *should* be turned off when this code is executed. 853 */ 854 .align 128 855 ENTRY(get_dcache_dtag) 856 rdpr %pstate, %o5 857 andn %o5, PSTATE_IE | PSTATE_AM, %o3 858 wrpr %g0, %o3, %pstate 859 b 1f 860 stx %o0, [%o1 + CH_DC_IDX] 861 862 .align 128 8631: 864 ldxa [%o0]ASI_DC_TAG, %o2 865 stx %o2, [%o1 + CH_DC_TAG] 866 membar #Sync 867 ldxa [%o0]ASI_DC_UTAG, %o2 868 membar #Sync 869 stx %o2, [%o1 + CH_DC_UTAG] 870 ldxa [%o0]ASI_DC_SNP_TAG, %o2 871 stx %o2, [%o1 + CH_DC_SNTAG] 872 add %o1, CH_DC_DATA, %o1 873 clr %o3 8742: 875 membar #Sync ! required before ASI_DC_DATA 876 ldxa [%o0 + %o3]ASI_DC_DATA, %o2 877 membar #Sync ! required after ASI_DC_DATA 878 stx %o2, [%o1 + %o3] 879 cmp %o3, CH_DC_DATA_REG_SIZE - 8 880 blt 2b 881 add %o3, 8, %o3 882 883 /* 884 * Unlike other CPUs in the family, D$ data parity bits for Panther 885 * do not reside in the microtag. Instead, we have to read them 886 * using the DC_data_parity bit of ASI_DCACHE_DATA. Also, instead 887 * of just having 8 parity bits to protect all 32 bytes of data 888 * per line, we now have 32 bits of parity. 889 */ 890 GET_CPU_IMPL(%o3) 891 cmp %o3, PANTHER_IMPL 892 bne 4f 893 clr %o3 894 895 /* 896 * move our pointer to the next field where we store parity bits 897 * and add the offset of the last parity byte since we will be 898 * storing all 4 parity bytes within one 64 bit field like this: 899 * 900 * +------+------------+------------+------------+------------+ 901 * | - | DC_parity | DC_parity | DC_parity | DC_parity | 902 * | - | for word 3 | for word 2 | for word 1 | for word 0 | 903 * +------+------------+------------+------------+------------+ 904 * 63:32 31:24 23:16 15:8 7:0 905 */ 906 add %o1, CH_DC_PN_DATA_PARITY - CH_DC_DATA + 7, %o1 907 908 /* add the DC_data_parity bit into our working index */ 909 mov 1, %o2 910 sll %o2, PN_DC_DATA_PARITY_BIT_SHIFT, %o2 911 or %o0, %o2, %o0 9123: 913 membar #Sync ! required before ASI_DC_DATA 914 ldxa [%o0 + %o3]ASI_DC_DATA, %o2 915 membar #Sync ! required after ASI_DC_DATA 916 stb %o2, [%o1] 917 dec %o1 918 cmp %o3, CH_DC_DATA_REG_SIZE - 8 919 blt 3b 920 add %o3, 8, %o3 9214: 922 retl 923 wrpr %g0, %o5, %pstate 924 SET_SIZE(get_dcache_dtag) 925 926#endif /* lint */ 927 928 929#if defined(lint) 930 931/* ARGSUSED */ 932void 933get_icache_dtag(uint32_t ecache_idx, uint64_t *data) 934{} 935 936#else /* lint */ 937 938/* 939 * Get icache data and tag. The data argument is a pointer to a ch_ic_data_t 940 * structure (see cheetahregs.h): 941 * The Icache *Must* be turned off when this function is called. 942 * This is because diagnostic accesses to the Icache interfere with cache 943 * consistency. 944 */ 945 .align 128 946 ENTRY(get_icache_dtag) 947 rdpr %pstate, %o5 948 andn %o5, PSTATE_IE | PSTATE_AM, %o3 949 wrpr %g0, %o3, %pstate 950 951 stx %o0, [%o1 + CH_IC_IDX] 952 ldxa [%o0]ASI_IC_TAG, %o2 953 stx %o2, [%o1 + CH_IC_PATAG] 954 add %o0, CH_ICTAG_UTAG, %o0 955 ldxa [%o0]ASI_IC_TAG, %o2 956 add %o0, (CH_ICTAG_UPPER - CH_ICTAG_UTAG), %o0 957 stx %o2, [%o1 + CH_IC_UTAG] 958 ldxa [%o0]ASI_IC_TAG, %o2 959 add %o0, (CH_ICTAG_LOWER - CH_ICTAG_UPPER), %o0 960 stx %o2, [%o1 + CH_IC_UPPER] 961 ldxa [%o0]ASI_IC_TAG, %o2 962 andn %o0, CH_ICTAG_TMASK, %o0 963 stx %o2, [%o1 + CH_IC_LOWER] 964 ldxa [%o0]ASI_IC_SNP_TAG, %o2 965 stx %o2, [%o1 + CH_IC_SNTAG] 966 add %o1, CH_IC_DATA, %o1 967 clr %o3 9682: 969 ldxa [%o0 + %o3]ASI_IC_DATA, %o2 970 stx %o2, [%o1 + %o3] 971 cmp %o3, PN_IC_DATA_REG_SIZE - 8 972 blt 2b 973 add %o3, 8, %o3 974 975 retl 976 wrpr %g0, %o5, %pstate 977 SET_SIZE(get_icache_dtag) 978 979#endif /* lint */ 980 981#if defined(lint) 982 983/* ARGSUSED */ 984void 985get_pcache_dtag(uint32_t pcache_idx, uint64_t *data) 986{} 987 988#else /* lint */ 989 990/* 991 * Get pcache data and tags. 992 * inputs: 993 * pcache_idx - fully constructed VA for for accessing P$ diagnostic 994 * registers. Contains PC_way and PC_addr shifted into 995 * the correct bit positions. See the PRM for more details. 996 * data - pointer to a ch_pc_data_t 997 * structure (see cheetahregs.h): 998 */ 999 .align 128 1000 ENTRY(get_pcache_dtag) 1001 rdpr %pstate, %o5 1002 andn %o5, PSTATE_IE | PSTATE_AM, %o3 1003 wrpr %g0, %o3, %pstate 1004 1005 stx %o0, [%o1 + CH_PC_IDX] 1006 ldxa [%o0]ASI_PC_STATUS_DATA, %o2 1007 stx %o2, [%o1 + CH_PC_STATUS] 1008 ldxa [%o0]ASI_PC_TAG, %o2 1009 stx %o2, [%o1 + CH_PC_TAG] 1010 ldxa [%o0]ASI_PC_SNP_TAG, %o2 1011 stx %o2, [%o1 + CH_PC_SNTAG] 1012 add %o1, CH_PC_DATA, %o1 1013 clr %o3 10142: 1015 ldxa [%o0 + %o3]ASI_PC_DATA, %o2 1016 stx %o2, [%o1 + %o3] 1017 cmp %o3, CH_PC_DATA_REG_SIZE - 8 1018 blt 2b 1019 add %o3, 8, %o3 1020 1021 retl 1022 wrpr %g0, %o5, %pstate 1023 SET_SIZE(get_pcache_dtag) 1024 1025#endif /* lint */ 1026 1027#endif /* CPU_IMP_L1_CACHE_PARITY */ 1028 1029#if defined(lint) 1030 1031/* ARGSUSED */ 1032void 1033set_dcu(uint64_t dcu) 1034{} 1035 1036#else /* lint */ 1037 1038/* 1039 * re-enable the i$, d$, w$, and p$ according to bootup cache state. 1040 * Turn on WE, HPE, SPE, PE, IC, and DC bits defined as DCU_CACHE. 1041 * %o0 - 64 bit constant 1042 */ 1043 ENTRY(set_dcu) 1044 stxa %o0, [%g0]ASI_DCU ! Store to DCU 1045 flush %g0 /* flush required after changing the IC bit */ 1046 retl 1047 nop 1048 SET_SIZE(set_dcu) 1049 1050#endif /* lint */ 1051 1052 1053#if defined(lint) 1054 1055uint64_t 1056get_dcu(void) 1057{ 1058 return ((uint64_t)0); 1059} 1060 1061#else /* lint */ 1062 1063/* 1064 * Return DCU register. 1065 */ 1066 ENTRY(get_dcu) 1067 ldxa [%g0]ASI_DCU, %o0 /* DCU control register */ 1068 retl 1069 nop 1070 SET_SIZE(get_dcu) 1071 1072#endif /* lint */ 1073 1074/* 1075 * Cheetah/Cheetah+ level 15 interrupt handler trap table entry. 1076 * 1077 * This handler is used to check for softints generated by error trap 1078 * handlers to report errors. On Cheetah, this mechanism is used by the 1079 * Fast ECC at TL>0 error trap handler and, on Cheetah+, by both the Fast 1080 * ECC at TL>0 error and the I$/D$ parity error at TL>0 trap handlers. 1081 * NB: Must be 8 instructions or less to fit in trap table and code must 1082 * be relocatable. 1083 */ 1084#if defined(lint) 1085 1086void 1087ch_pil15_interrupt_instr(void) 1088{} 1089 1090#else /* lint */ 1091 1092 ENTRY_NP(ch_pil15_interrupt_instr) 1093 ASM_JMP(%g1, ch_pil15_interrupt) 1094 SET_SIZE(ch_pil15_interrupt_instr) 1095 1096#endif 1097 1098 1099#if defined(lint) 1100 1101void 1102ch_pil15_interrupt(void) 1103{} 1104 1105#else /* lint */ 1106 1107 ENTRY_NP(ch_pil15_interrupt) 1108 1109 /* 1110 * Since pil_interrupt is hacked to assume that every level 15 1111 * interrupt is generated by the CPU to indicate a performance 1112 * counter overflow this gets ugly. Before calling pil_interrupt 1113 * the Error at TL>0 pending status is inspected. If it is 1114 * non-zero, then an error has occurred and it is handled. 1115 * Otherwise control is transfered to pil_interrupt. Note that if 1116 * an error is detected pil_interrupt will not be called and 1117 * overflow interrupts may be lost causing erroneous performance 1118 * measurements. However, error-recovery will have a detrimental 1119 * effect on performance anyway. 1120 */ 1121 CPU_INDEX(%g1, %g4) 1122 set ch_err_tl1_pending, %g4 1123 ldub [%g1 + %g4], %g2 1124 brz %g2, 1f 1125 nop 1126 1127 /* 1128 * We have a pending TL>0 error, clear the TL>0 pending status. 1129 */ 1130 stb %g0, [%g1 + %g4] 1131 1132 /* 1133 * Clear the softint. 1134 */ 1135 mov 1, %g5 1136 sll %g5, PIL_15, %g5 1137 wr %g5, CLEAR_SOFTINT 1138 1139 /* 1140 * For Cheetah*, call cpu_tl1_error via systrap at PIL 15 1141 * to process the Fast ECC/Cache Parity at TL>0 error. Clear 1142 * panic flag (%g2). 1143 */ 1144 set cpu_tl1_error, %g1 1145 clr %g2 1146 ba sys_trap 1147 mov PIL_15, %g4 1148 11491: 1150 /* 1151 * The logout is invalid. 1152 * 1153 * Call the default interrupt handler. 1154 */ 1155 sethi %hi(pil_interrupt), %g1 1156 jmp %g1 + %lo(pil_interrupt) 1157 mov PIL_15, %g4 1158 1159 SET_SIZE(ch_pil15_interrupt) 1160#endif 1161 1162 1163/* 1164 * Error Handling 1165 * 1166 * Cheetah provides error checking for all memory access paths between 1167 * the CPU, External Cache, Cheetah Data Switch and system bus. Error 1168 * information is logged in the AFSR, (also AFSR_EXT for Panther) and 1169 * AFAR and one of the following traps is generated (provided that it 1170 * is enabled in External Cache Error Enable Register) to handle that 1171 * error: 1172 * 1. trap 0x70: Precise trap 1173 * tt0_fecc for errors at trap level(TL)>=0 1174 * 2. trap 0x0A and 0x32: Deferred trap 1175 * async_err for errors at TL>=0 1176 * 3. trap 0x63: Disrupting trap 1177 * ce_err for errors at TL=0 1178 * (Note that trap 0x63 cannot happen at trap level > 0) 1179 * 1180 * Trap level one handlers panic the system except for the fast ecc 1181 * error handler which tries to recover from certain errors. 1182 */ 1183 1184/* 1185 * FAST ECC TRAP STRATEGY: 1186 * 1187 * Software must handle single and multi bit errors which occur due to data 1188 * or instruction cache reads from the external cache. A single or multi bit 1189 * error occuring in one of these situations results in a precise trap. 1190 * 1191 * The basic flow of this trap handler is as follows: 1192 * 1193 * 1) Record the state and then turn off the Dcache and Icache. The Dcache 1194 * is disabled because bad data could have been installed. The Icache is 1195 * turned off because we want to capture the Icache line related to the 1196 * AFAR. 1197 * 2) Disable trapping on CEEN/NCCEN errors during TL=0 processing. 1198 * 3) Park sibling core if caches are shared (to avoid race condition while 1199 * accessing shared resources such as L3 data staging register during 1200 * CPU logout. 1201 * 4) Read the AFAR and AFSR. 1202 * 5) If CPU logout structure is not being used, then: 1203 * 6) Clear all errors from the AFSR. 1204 * 7) Capture Ecache, Dcache and Icache lines in "CPU log out" structure. 1205 * 8) Flush Ecache then Flush Dcache and Icache and restore to previous 1206 * state. 1207 * 9) Unpark sibling core if we parked it earlier. 1208 * 10) call cpu_fast_ecc_error via systrap at PIL 14 unless we're already 1209 * running at PIL 15. 1210 * 6) Otherwise, if CPU logout structure is being used: 1211 * 7) Incriment the "logout busy count". 1212 * 8) Flush Ecache then Flush Dcache and Icache and restore to previous 1213 * state. 1214 * 9) Unpark sibling core if we parked it earlier. 1215 * 10) Issue a retry since the other CPU error logging code will end up 1216 * finding this error bit and logging information about it later. 1217 * 7) Alternatively (to 5 and 6 above), if the cpu_private struct is not 1218 * yet initialized such that we can't even check the logout struct, then 1219 * we place the clo_flags data into %g2 (sys_trap->have_win arg #1) and 1220 * call cpu_fast_ecc_error via systrap. The clo_flags parameter is used 1221 * to determine information such as TL, TT, CEEN and NCEEN settings, etc 1222 * in the high level trap handler since we don't have access to detailed 1223 * logout information in cases where the cpu_private struct is not yet 1224 * initialized. 1225 * 1226 * We flush the E$ and D$ here on TL=1 code to prevent getting nested 1227 * Fast ECC traps in the TL=0 code. If we get a Fast ECC event here in 1228 * the TL=1 code, we will go to the Fast ECC at TL>0 handler which, 1229 * since it is uses different code/data from this handler, has a better 1230 * chance of fixing things up than simply recursing through this code 1231 * again (this would probably cause an eventual kernel stack overflow). 1232 * If the Fast ECC at TL>0 handler encounters a Fast ECC error before it 1233 * can flush the E$ (or the error is a stuck-at bit), we will recurse in 1234 * the Fast ECC at TL>0 handler and eventually Red Mode. 1235 * 1236 * Note that for Cheetah (and only Cheetah), we use alias addresses for 1237 * flushing rather than ASI accesses (which don't exist on Cheetah). 1238 * Should we encounter a Fast ECC error within this handler on Cheetah, 1239 * there's a good chance it's within the ecache_flushaddr buffer (since 1240 * it's the largest piece of memory we touch in the handler and it is 1241 * usually kernel text/data). For that reason the Fast ECC at TL>0 1242 * handler for Cheetah uses an alternate buffer: ecache_tl1_flushaddr. 1243 */ 1244 1245/* 1246 * Cheetah ecc-protected E$ trap (Trap 70) at TL=0 1247 * tt0_fecc is replaced by fecc_err_instr in cpu_init_trap of the various 1248 * architecture-specific files. 1249 * NB: Must be 8 instructions or less to fit in trap table and code must 1250 * be relocatable. 1251 */ 1252 1253#if defined(lint) 1254 1255void 1256fecc_err_instr(void) 1257{} 1258 1259#else /* lint */ 1260 1261 ENTRY_NP(fecc_err_instr) 1262 membar #Sync ! Cheetah requires membar #Sync 1263 1264 /* 1265 * Save current DCU state. Turn off the Dcache and Icache. 1266 */ 1267 ldxa [%g0]ASI_DCU, %g1 ! save DCU in %g1 1268 andn %g1, DCU_DC + DCU_IC, %g4 1269 stxa %g4, [%g0]ASI_DCU 1270 flush %g0 /* flush required after changing the IC bit */ 1271 1272 ASM_JMP(%g4, fast_ecc_err) 1273 SET_SIZE(fecc_err_instr) 1274 1275#endif /* lint */ 1276 1277 1278#if !(defined(JALAPENO) || defined(SERRANO)) 1279 1280#if defined(lint) 1281 1282void 1283fast_ecc_err(void) 1284{} 1285 1286#else /* lint */ 1287 1288 .section ".text" 1289 .align 64 1290 ENTRY_NP(fast_ecc_err) 1291 1292 /* 1293 * Turn off CEEN and NCEEN. 1294 */ 1295 ldxa [%g0]ASI_ESTATE_ERR, %g3 1296 andn %g3, EN_REG_NCEEN + EN_REG_CEEN, %g4 1297 stxa %g4, [%g0]ASI_ESTATE_ERR 1298 membar #Sync ! membar sync required 1299 1300 /* 1301 * Check to see whether we need to park our sibling core 1302 * before recording diagnostic information from caches 1303 * which may be shared by both cores. 1304 * We use %g1 to store information about whether or not 1305 * we had to park the core (%g1 holds our DCUCR value and 1306 * we only use bits from that register which are "reserved" 1307 * to keep track of core parking) so that we know whether 1308 * or not to unpark later. %g5 and %g4 are scratch registers. 1309 */ 1310 PARK_SIBLING_CORE(%g1, %g5, %g4) 1311 1312 /* 1313 * Do the CPU log out capture. 1314 * %g3 = "failed?" return value. 1315 * %g2 = Input = AFAR. Output the clo_flags info which is passed 1316 * into this macro via %g4. Output only valid if cpu_private 1317 * struct has not been initialized. 1318 * CHPR_FECCTL0_LOGOUT = cpu logout structure offset input 1319 * %g4 = Trap information stored in the cpu logout flags field 1320 * %g5 = scr1 1321 * %g6 = scr2 1322 * %g3 = scr3 1323 * %g4 = scr4 1324 */ 1325 /* store the CEEN and NCEEN values, TL=0 */ 1326 and %g3, EN_REG_CEEN + EN_REG_NCEEN, %g4 1327 set CHPR_FECCTL0_LOGOUT, %g6 1328 DO_CPU_LOGOUT(%g3, %g2, %g6, %g4, %g5, %g6, %g3, %g4) 1329 1330 /* 1331 * Flush the Ecache (and L2 cache for Panther) to get the error out 1332 * of the Ecache. If the UCC or UCU is on a dirty line, then the 1333 * following flush will turn that into a WDC or WDU, respectively. 1334 */ 1335 PN_L2_FLUSHALL(%g4, %g5, %g6) 1336 1337 CPU_INDEX(%g4, %g5) 1338 mulx %g4, CPU_NODE_SIZE, %g4 1339 set cpunodes, %g5 1340 add %g4, %g5, %g4 1341 ld [%g4 + ECACHE_LINESIZE], %g5 1342 ld [%g4 + ECACHE_SIZE], %g4 1343 1344 ASM_LDX(%g6, ecache_flushaddr) 1345 ECACHE_FLUSHALL(%g4, %g5, %g6, %g7) 1346 1347 /* 1348 * Flush the Dcache. Since bad data could have been installed in 1349 * the Dcache we must flush it before re-enabling it. 1350 */ 1351 ASM_LD(%g5, dcache_size) 1352 ASM_LD(%g6, dcache_linesize) 1353 CH_DCACHE_FLUSHALL(%g5, %g6, %g7) 1354 1355 /* 1356 * Flush the Icache. Since we turned off the Icache to capture the 1357 * Icache line it is now stale or corrupted and we must flush it 1358 * before re-enabling it. 1359 */ 1360 GET_CPU_PRIVATE_PTR(%g0, %g5, %g7, fast_ecc_err_5); 1361 ld [%g5 + CHPR_ICACHE_LINESIZE], %g6 1362 ba,pt %icc, 6f 1363 ld [%g5 + CHPR_ICACHE_SIZE], %g5 1364fast_ecc_err_5: 1365 ASM_LD(%g5, icache_size) 1366 ASM_LD(%g6, icache_linesize) 13676: 1368 CH_ICACHE_FLUSHALL(%g5, %g6, %g7, %g4) 1369 1370 /* 1371 * check to see whether we parked our sibling core at the start 1372 * of this handler. If so, we need to unpark it here. 1373 * We use DCUCR reserved bits (stored in %g1) to keep track of 1374 * whether or not we need to unpark. %g5 and %g4 are scratch registers. 1375 */ 1376 UNPARK_SIBLING_CORE(%g1, %g5, %g4) 1377 1378 /* 1379 * Restore the Dcache and Icache to the previous state. 1380 */ 1381 stxa %g1, [%g0]ASI_DCU 1382 flush %g0 /* flush required after changing the IC bit */ 1383 1384 /* 1385 * Make sure our CPU logout operation was successful. 1386 */ 1387 cmp %g3, %g0 1388 be 8f 1389 nop 1390 1391 /* 1392 * If the logout structure had been busy, how many times have 1393 * we tried to use it and failed (nesting count)? If we have 1394 * already recursed a substantial number of times, then we can 1395 * assume things are not going to get better by themselves and 1396 * so it would be best to panic. 1397 */ 1398 cmp %g3, CLO_NESTING_MAX 1399 blt 7f 1400 nop 1401 1402 call ptl1_panic 1403 mov PTL1_BAD_ECC, %g1 1404 14057: 1406 /* 1407 * Otherwise, if the logout structure was busy but we have not 1408 * nested more times than our maximum value, then we simply 1409 * issue a retry. Our TL=0 trap handler code will check and 1410 * clear the AFSR after it is done logging what is currently 1411 * in the logout struct and handle this event at that time. 1412 */ 1413 retry 14148: 1415 /* 1416 * Call cpu_fast_ecc_error via systrap at PIL 14 unless we're 1417 * already at PIL 15. 1418 */ 1419 set cpu_fast_ecc_error, %g1 1420 rdpr %pil, %g4 1421 cmp %g4, PIL_14 1422 ba sys_trap 1423 movl %icc, PIL_14, %g4 1424 1425 SET_SIZE(fast_ecc_err) 1426 1427#endif /* lint */ 1428 1429#endif /* !(JALAPENO || SERRANO) */ 1430 1431 1432/* 1433 * Cheetah/Cheetah+ Fast ECC at TL>0 trap strategy: 1434 * 1435 * The basic flow of this trap handler is as follows: 1436 * 1437 * 1) In the "trap 70" trap table code (fecc_err_tl1_instr), generate a 1438 * software trap 0 ("ta 0") to buy an extra set of %tpc, etc. which we 1439 * will use to save %g1 and %g2. 1440 * 2) At the software trap 0 at TL>0 trap table code (fecc_err_tl1_cont_instr), 1441 * we save %g1+%g2 using %tpc, %tnpc + %tstate and jump to the fast ecc 1442 * handler (using the just saved %g1). 1443 * 3) Turn off the Dcache if it was on and save the state of the Dcache 1444 * (whether on or off) in Bit2 (CH_ERR_TSTATE_DC_ON) of %tstate. 1445 * NB: we don't turn off the Icache because bad data is not installed nor 1446 * will we be doing any diagnostic accesses. 1447 * 4) compute physical address of the per-cpu/per-tl save area using %g1+%g2 1448 * 5) Save %g1-%g7 into the per-cpu/per-tl save area (%g1 + %g2 from the 1449 * %tpc, %tnpc, %tstate values previously saved). 1450 * 6) set %tl to %tl - 1. 1451 * 7) Save the appropriate flags and TPC in the ch_err_tl1_data structure. 1452 * 8) Save the value of CH_ERR_TSTATE_DC_ON in the ch_err_tl1_tmp field. 1453 * 9) For Cheetah and Jalapeno, read the AFAR and AFSR and clear. For 1454 * Cheetah+ (and later), read the shadow AFAR and AFSR but don't clear. 1455 * Save the values in ch_err_tl1_data. For Panther, read the shadow 1456 * AFSR_EXT and save the value in ch_err_tl1_data. 1457 * 10) Disable CEEN/NCEEN to prevent any disrupting/deferred errors from 1458 * being queued. We'll report them via the AFSR/AFAR capture in step 13. 1459 * 11) Flush the Ecache. 1460 * NB: the Ecache is flushed assuming the largest possible size with 1461 * the smallest possible line size since access to the cpu_nodes may 1462 * cause an unrecoverable DTLB miss. 1463 * 12) Reenable CEEN/NCEEN with the value saved from step 10. 1464 * 13) For Cheetah and Jalapeno, read the AFAR and AFSR and clear again. 1465 * For Cheetah+ (and later), read the primary AFAR and AFSR and now clear. 1466 * Save the read AFSR/AFAR values in ch_err_tl1_data. For Panther, 1467 * read and clear the primary AFSR_EXT and save it in ch_err_tl1_data. 1468 * 14) Flush and re-enable the Dcache if it was on at step 3. 1469 * 15) Do TRAPTRACE if enabled. 1470 * 16) Check if a UCU->WDU (or L3_UCU->WDU for Panther) happened, panic if so. 1471 * 17) Set the event pending flag in ch_err_tl1_pending[CPU] 1472 * 18) Cause a softint 15. The pil15_interrupt handler will inspect the 1473 * event pending flag and call cpu_tl1_error via systrap if set. 1474 * 19) Restore the registers from step 5 and issue retry. 1475 */ 1476 1477/* 1478 * Cheetah ecc-protected E$ trap (Trap 70) at TL>0 1479 * tt1_fecc is replaced by fecc_err_tl1_instr in cpu_init_trap of the various 1480 * architecture-specific files. This generates a "Software Trap 0" at TL>0, 1481 * which goes to fecc_err_tl1_cont_instr, and we continue the handling there. 1482 * NB: Must be 8 instructions or less to fit in trap table and code must 1483 * be relocatable. 1484 */ 1485 1486#if defined(lint) 1487 1488void 1489fecc_err_tl1_instr(void) 1490{} 1491 1492#else /* lint */ 1493 1494 ENTRY_NP(fecc_err_tl1_instr) 1495 CH_ERR_TL1_TRAPENTRY(SWTRAP_0); 1496 SET_SIZE(fecc_err_tl1_instr) 1497 1498#endif /* lint */ 1499 1500/* 1501 * Software trap 0 at TL>0. 1502 * tt1_swtrap0 is replaced by fecc_err_tl1_cont_instr in cpu_init_trap of 1503 * the various architecture-specific files. This is used as a continuation 1504 * of the fast ecc handling where we've bought an extra TL level, so we can 1505 * use %tpc, %tnpc, %tstate to temporarily save the value of registers %g1 1506 * and %g2. Note that %tstate has bits 0-2 and then bits 8-19 as r/w, 1507 * there's a reserved hole from 3-7. We only use bits 0-1 and 8-9 (the low 1508 * order two bits from %g1 and %g2 respectively). 1509 * NB: Must be 8 instructions or less to fit in trap table and code must 1510 * be relocatable. 1511 */ 1512#if defined(lint) 1513 1514void 1515fecc_err_tl1_cont_instr(void) 1516{} 1517 1518#else /* lint */ 1519 1520 ENTRY_NP(fecc_err_tl1_cont_instr) 1521 CH_ERR_TL1_SWTRAPENTRY(fast_ecc_tl1_err) 1522 SET_SIZE(fecc_err_tl1_cont_instr) 1523 1524#endif /* lint */ 1525 1526 1527#if defined(lint) 1528 1529void 1530ce_err(void) 1531{} 1532 1533#else /* lint */ 1534 1535/* 1536 * The ce_err function handles disrupting trap type 0x63 at TL=0. 1537 * 1538 * AFSR errors bits which cause this trap are: 1539 * CE, EMC, EDU:ST, EDC, WDU, WDC, CPU, CPC, IVU, IVC 1540 * 1541 * NCEEN Bit of Cheetah External Cache Error Enable Register enables 1542 * the following AFSR disrupting traps: EDU:ST, WDU, CPU, IVU 1543 * 1544 * CEEN Bit of Cheetah External Cache Error Enable Register enables 1545 * the following AFSR disrupting traps: CE, EMC, EDC, WDC, CPC, IVC 1546 * 1547 * Cheetah+ also handles (No additional processing required): 1548 * DUE, DTO, DBERR (NCEEN controlled) 1549 * THCE (CEEN and ET_ECC_en controlled) 1550 * TUE (ET_ECC_en controlled) 1551 * 1552 * Panther further adds: 1553 * IMU, L3_EDU, L3_WDU, L3_CPU (NCEEN controlled) 1554 * IMC, L3_EDC, L3_WDC, L3_CPC, L3_THCE (CEEN controlled) 1555 * TUE_SH, TUE (NCEEN and L2_tag_ECC_en controlled) 1556 * L3_TUE, L3_TUE_SH (NCEEN and ET_ECC_en controlled) 1557 * THCE (CEEN and L2_tag_ECC_en controlled) 1558 * L3_THCE (CEEN and ET_ECC_en controlled) 1559 * 1560 * Steps: 1561 * 1. Disable hardware corrected disrupting errors only (CEEN) 1562 * 2. Park sibling core if caches are shared (to avoid race 1563 * condition while accessing shared resources such as L3 1564 * data staging register during CPU logout. 1565 * 3. If the CPU logout structure is not currently being used: 1566 * 4. Clear AFSR error bits 1567 * 5. Capture Ecache, Dcache and Icache lines associated 1568 * with AFAR. 1569 * 6. Unpark sibling core if we parked it earlier. 1570 * 7. call cpu_disrupting_error via sys_trap at PIL 14 1571 * unless we're already running at PIL 15. 1572 * 4. Otherwise, if the CPU logout structure is busy: 1573 * 5. Incriment "logout busy count" and place into %g3 1574 * 6. Unpark sibling core if we parked it earlier. 1575 * 7. Issue a retry since the other CPU error logging 1576 * code will end up finding this error bit and logging 1577 * information about it later. 1578 * 5. Alternatively (to 3 and 4 above), if the cpu_private struct is 1579 * not yet initialized such that we can't even check the logout 1580 * struct, then we place the clo_flags data into %g2 1581 * (sys_trap->have_win arg #1) and call cpu_disrupting_error via 1582 * systrap. The clo_flags parameter is used to determine information 1583 * such as TL, TT, CEEN settings, etc in the high level trap 1584 * handler since we don't have access to detailed logout information 1585 * in cases where the cpu_private struct is not yet initialized. 1586 * 1587 * %g3: [ logout busy count ] - arg #2 1588 * %g2: [ clo_flags if cpu_private unavailable ] - sys_trap->have_win: arg #1 1589 */ 1590 1591 .align 128 1592 ENTRY_NP(ce_err) 1593 membar #Sync ! Cheetah requires membar #Sync 1594 1595 /* 1596 * Disable trap on hardware corrected errors (CEEN) while at TL=0 1597 * to prevent recursion. 1598 */ 1599 ldxa [%g0]ASI_ESTATE_ERR, %g1 1600 bclr EN_REG_CEEN, %g1 1601 stxa %g1, [%g0]ASI_ESTATE_ERR 1602 membar #Sync ! membar sync required 1603 1604 /* 1605 * Save current DCU state. Turn off Icache to allow capture of 1606 * Icache data by DO_CPU_LOGOUT. 1607 */ 1608 ldxa [%g0]ASI_DCU, %g1 ! save DCU in %g1 1609 andn %g1, DCU_IC, %g4 1610 stxa %g4, [%g0]ASI_DCU 1611 flush %g0 /* flush required after changing the IC bit */ 1612 1613 /* 1614 * Check to see whether we need to park our sibling core 1615 * before recording diagnostic information from caches 1616 * which may be shared by both cores. 1617 * We use %g1 to store information about whether or not 1618 * we had to park the core (%g1 holds our DCUCR value and 1619 * we only use bits from that register which are "reserved" 1620 * to keep track of core parking) so that we know whether 1621 * or not to unpark later. %g5 and %g4 are scratch registers. 1622 */ 1623 PARK_SIBLING_CORE(%g1, %g5, %g4) 1624 1625 /* 1626 * Do the CPU log out capture. 1627 * %g3 = "failed?" return value. 1628 * %g2 = Input = AFAR. Output the clo_flags info which is passed 1629 * into this macro via %g4. Output only valid if cpu_private 1630 * struct has not been initialized. 1631 * CHPR_CECC_LOGOUT = cpu logout structure offset input 1632 * %g4 = Trap information stored in the cpu logout flags field 1633 * %g5 = scr1 1634 * %g6 = scr2 1635 * %g3 = scr3 1636 * %g4 = scr4 1637 */ 1638 clr %g4 ! TL=0 bit in afsr 1639 set CHPR_CECC_LOGOUT, %g6 1640 DO_CPU_LOGOUT(%g3, %g2, %g6, %g4, %g5, %g6, %g3, %g4) 1641 1642 /* 1643 * Flush the Icache. Since we turned off the Icache to capture the 1644 * Icache line it is now stale or corrupted and we must flush it 1645 * before re-enabling it. 1646 */ 1647 GET_CPU_PRIVATE_PTR(%g0, %g5, %g7, ce_err_1); 1648 ld [%g5 + CHPR_ICACHE_LINESIZE], %g6 1649 ba,pt %icc, 2f 1650 ld [%g5 + CHPR_ICACHE_SIZE], %g5 1651ce_err_1: 1652 ASM_LD(%g5, icache_size) 1653 ASM_LD(%g6, icache_linesize) 16542: 1655 CH_ICACHE_FLUSHALL(%g5, %g6, %g7, %g4) 1656 1657 /* 1658 * check to see whether we parked our sibling core at the start 1659 * of this handler. If so, we need to unpark it here. 1660 * We use DCUCR reserved bits (stored in %g1) to keep track of 1661 * whether or not we need to unpark. %g5 and %g4 are scratch registers. 1662 */ 1663 UNPARK_SIBLING_CORE(%g1, %g5, %g4) 1664 1665 /* 1666 * Restore Icache to previous state. 1667 */ 1668 stxa %g1, [%g0]ASI_DCU 1669 flush %g0 /* flush required after changing the IC bit */ 1670 1671 /* 1672 * Make sure our CPU logout operation was successful. 1673 */ 1674 cmp %g3, %g0 1675 be 4f 1676 nop 1677 1678 /* 1679 * If the logout structure had been busy, how many times have 1680 * we tried to use it and failed (nesting count)? If we have 1681 * already recursed a substantial number of times, then we can 1682 * assume things are not going to get better by themselves and 1683 * so it would be best to panic. 1684 */ 1685 cmp %g3, CLO_NESTING_MAX 1686 blt 3f 1687 nop 1688 1689 call ptl1_panic 1690 mov PTL1_BAD_ECC, %g1 1691 16923: 1693 /* 1694 * Otherwise, if the logout structure was busy but we have not 1695 * nested more times than our maximum value, then we simply 1696 * issue a retry. Our TL=0 trap handler code will check and 1697 * clear the AFSR after it is done logging what is currently 1698 * in the logout struct and handle this event at that time. 1699 */ 1700 retry 17014: 1702 /* 1703 * Call cpu_disrupting_error via systrap at PIL 14 unless we're 1704 * already at PIL 15. 1705 */ 1706 set cpu_disrupting_error, %g1 1707 rdpr %pil, %g4 1708 cmp %g4, PIL_14 1709 ba sys_trap 1710 movl %icc, PIL_14, %g4 1711 SET_SIZE(ce_err) 1712 1713#endif /* lint */ 1714 1715 1716#if defined(lint) 1717 1718/* 1719 * This trap cannot happen at TL>0 which means this routine will never 1720 * actually be called and so we treat this like a BAD TRAP panic. 1721 */ 1722void 1723ce_err_tl1(void) 1724{} 1725 1726#else /* lint */ 1727 1728 .align 64 1729 ENTRY_NP(ce_err_tl1) 1730 1731 call ptl1_panic 1732 mov PTL1_BAD_TRAP, %g1 1733 1734 SET_SIZE(ce_err_tl1) 1735 1736#endif /* lint */ 1737 1738 1739#if defined(lint) 1740 1741void 1742async_err(void) 1743{} 1744 1745#else /* lint */ 1746 1747/* 1748 * The async_err function handles deferred trap types 0xA 1749 * (instruction_access_error) and 0x32 (data_access_error) at TL>=0. 1750 * 1751 * AFSR errors bits which cause this trap are: 1752 * UE, EMU, EDU:BLD, L3_EDU:BLD, TO, BERR 1753 * On some platforms, EMU may causes cheetah to pull the error pin 1754 * never giving Solaris a chance to take a trap. 1755 * 1756 * NCEEN Bit of Cheetah External Cache Error Enable Register enables 1757 * the following AFSR deferred traps: UE, EMU, EDU:BLD, TO, BERR 1758 * 1759 * Steps: 1760 * 1. Disable CEEN and NCEEN errors to prevent recursive errors. 1761 * 2. Turn D$ off per Cheetah PRM P.5 Note 6, turn I$ off to capture 1762 * I$ line in DO_CPU_LOGOUT. 1763 * 3. Park sibling core if caches are shared (to avoid race 1764 * condition while accessing shared resources such as L3 1765 * data staging register during CPU logout. 1766 * 4. If the CPU logout structure is not currently being used: 1767 * 5. Clear AFSR error bits 1768 * 6. Capture Ecache, Dcache and Icache lines associated 1769 * with AFAR. 1770 * 7. Unpark sibling core if we parked it earlier. 1771 * 8. call cpu_deferred_error via sys_trap. 1772 * 5. Otherwise, if the CPU logout structure is busy: 1773 * 6. Incriment "logout busy count" 1774 * 7. Unpark sibling core if we parked it earlier. 1775 * 8) Issue a retry since the other CPU error logging 1776 * code will end up finding this error bit and logging 1777 * information about it later. 1778 * 6. Alternatively (to 4 and 5 above), if the cpu_private struct is 1779 * not yet initialized such that we can't even check the logout 1780 * struct, then we place the clo_flags data into %g2 1781 * (sys_trap->have_win arg #1) and call cpu_deferred_error via 1782 * systrap. The clo_flags parameter is used to determine information 1783 * such as TL, TT, CEEN settings, etc in the high level trap handler 1784 * since we don't have access to detailed logout information in cases 1785 * where the cpu_private struct is not yet initialized. 1786 * 1787 * %g2: [ clo_flags if cpu_private unavailable ] - sys_trap->have_win: arg #1 1788 * %g3: [ logout busy count ] - arg #2 1789 */ 1790 1791 ENTRY_NP(async_err) 1792 membar #Sync ! Cheetah requires membar #Sync 1793 1794 /* 1795 * Disable CEEN and NCEEN. 1796 */ 1797 ldxa [%g0]ASI_ESTATE_ERR, %g3 1798 andn %g3, EN_REG_NCEEN + EN_REG_CEEN, %g4 1799 stxa %g4, [%g0]ASI_ESTATE_ERR 1800 membar #Sync ! membar sync required 1801 1802 /* 1803 * Save current DCU state. 1804 * Disable Icache to allow capture of Icache data by DO_CPU_LOGOUT. 1805 * Do this regardless of whether this is a Data Access Error or 1806 * Instruction Access Error Trap. 1807 * Disable Dcache for both Data Access Error and Instruction Access 1808 * Error per Cheetah PRM P.5 Note 6. 1809 */ 1810 ldxa [%g0]ASI_DCU, %g1 ! save DCU in %g1 1811 andn %g1, DCU_IC + DCU_DC, %g4 1812 stxa %g4, [%g0]ASI_DCU 1813 flush %g0 /* flush required after changing the IC bit */ 1814 1815 /* 1816 * Check to see whether we need to park our sibling core 1817 * before recording diagnostic information from caches 1818 * which may be shared by both cores. 1819 * We use %g1 to store information about whether or not 1820 * we had to park the core (%g1 holds our DCUCR value and 1821 * we only use bits from that register which are "reserved" 1822 * to keep track of core parking) so that we know whether 1823 * or not to unpark later. %g6 and %g4 are scratch registers. 1824 */ 1825 PARK_SIBLING_CORE(%g1, %g6, %g4) 1826 1827 /* 1828 * Do the CPU logout capture. 1829 * 1830 * %g3 = "failed?" return value. 1831 * %g2 = Input = AFAR. Output the clo_flags info which is passed 1832 * into this macro via %g4. Output only valid if cpu_private 1833 * struct has not been initialized. 1834 * CHPR_ASYNC_LOGOUT = cpu logout structure offset input 1835 * %g4 = Trap information stored in the cpu logout flags field 1836 * %g5 = scr1 1837 * %g6 = scr2 1838 * %g3 = scr3 1839 * %g4 = scr4 1840 */ 1841 andcc %g5, T_TL1, %g0 1842 clr %g6 1843 movnz %xcc, 1, %g6 ! set %g6 if T_TL1 set 1844 sllx %g6, CLO_FLAGS_TL_SHIFT, %g6 1845 sllx %g5, CLO_FLAGS_TT_SHIFT, %g4 1846 set CLO_FLAGS_TT_MASK, %g2 1847 and %g4, %g2, %g4 ! ttype 1848 or %g6, %g4, %g4 ! TT and TL 1849 and %g3, EN_REG_CEEN, %g3 ! CEEN value 1850 or %g3, %g4, %g4 ! TT and TL and CEEN 1851 set CHPR_ASYNC_LOGOUT, %g6 1852 DO_CPU_LOGOUT(%g3, %g2, %g6, %g4, %g5, %g6, %g3, %g4) 1853 1854 /* 1855 * If the logout struct was busy, we may need to pass the 1856 * TT, TL, and CEEN information to the TL=0 handler via 1857 * systrap parameter so save it off here. 1858 */ 1859 cmp %g3, %g0 1860 be 1f 1861 nop 1862 sllx %g4, 32, %g4 1863 or %g4, %g3, %g3 18641: 1865 /* 1866 * Flush the Icache. Since we turned off the Icache to capture the 1867 * Icache line it is now stale or corrupted and we must flush it 1868 * before re-enabling it. 1869 */ 1870 GET_CPU_PRIVATE_PTR(%g0, %g5, %g7, async_err_1); 1871 ld [%g5 + CHPR_ICACHE_LINESIZE], %g6 1872 ba,pt %icc, 2f 1873 ld [%g5 + CHPR_ICACHE_SIZE], %g5 1874async_err_1: 1875 ASM_LD(%g5, icache_size) 1876 ASM_LD(%g6, icache_linesize) 18772: 1878 CH_ICACHE_FLUSHALL(%g5, %g6, %g7, %g4) 1879 1880 /* 1881 * XXX - Don't we need to flush the Dcache before turning it back 1882 * on to avoid stale or corrupt data? Was this broken? 1883 */ 1884 /* 1885 * Flush the Dcache before turning it back on since it may now 1886 * contain stale or corrupt data. 1887 */ 1888 ASM_LD(%g5, dcache_size) 1889 ASM_LD(%g6, dcache_linesize) 1890 CH_DCACHE_FLUSHALL(%g5, %g6, %g7) 1891 1892 /* 1893 * check to see whether we parked our sibling core at the start 1894 * of this handler. If so, we need to unpark it here. 1895 * We use DCUCR reserved bits (stored in %g1) to keep track of 1896 * whether or not we need to unpark. %g5 and %g7 are scratch registers. 1897 */ 1898 UNPARK_SIBLING_CORE(%g1, %g5, %g7) 1899 1900 /* 1901 * Restore Icache and Dcache to previous state. 1902 */ 1903 stxa %g1, [%g0]ASI_DCU 1904 flush %g0 /* flush required after changing the IC bit */ 1905 1906 /* 1907 * Make sure our CPU logout operation was successful. 1908 */ 1909 cmp %g3, %g0 1910 be 4f 1911 nop 1912 1913 /* 1914 * If the logout structure had been busy, how many times have 1915 * we tried to use it and failed (nesting count)? If we have 1916 * already recursed a substantial number of times, then we can 1917 * assume things are not going to get better by themselves and 1918 * so it would be best to panic. 1919 */ 1920 cmp %g3, CLO_NESTING_MAX 1921 blt 3f 1922 nop 1923 1924 call ptl1_panic 1925 mov PTL1_BAD_ECC, %g1 1926 19273: 1928 /* 1929 * Otherwise, if the logout structure was busy but we have not 1930 * nested more times than our maximum value, then we simply 1931 * issue a retry. Our TL=0 trap handler code will check and 1932 * clear the AFSR after it is done logging what is currently 1933 * in the logout struct and handle this event at that time. 1934 */ 1935 retry 19364: 1937 RESET_USER_RTT_REGS(%g4, %g5, async_err_resetskip) 1938async_err_resetskip: 1939 set cpu_deferred_error, %g1 1940 ba sys_trap 1941 mov PIL_15, %g4 ! run at pil 15 1942 SET_SIZE(async_err) 1943 1944#endif /* lint */ 1945 1946#if defined(CPU_IMP_L1_CACHE_PARITY) 1947 1948/* 1949 * D$ parity error trap (trap 71) at TL=0. 1950 * tt0_dperr is replaced by dcache_parity_instr in cpu_init_trap of 1951 * the various architecture-specific files. This merely sets up the 1952 * arguments for cpu_parity_error and calls it via sys_trap. 1953 * NB: Must be 8 instructions or less to fit in trap table and code must 1954 * be relocatable. 1955 */ 1956#if defined(lint) 1957 1958void 1959dcache_parity_instr(void) 1960{} 1961 1962#else /* lint */ 1963 ENTRY_NP(dcache_parity_instr) 1964 membar #Sync ! Cheetah+ requires membar #Sync 1965 set cpu_parity_error, %g1 1966 or %g0, CH_ERR_DPE, %g2 1967 rdpr %tpc, %g3 1968 sethi %hi(sys_trap), %g7 1969 jmp %g7 + %lo(sys_trap) 1970 mov PIL_15, %g4 ! run at pil 15 1971 SET_SIZE(dcache_parity_instr) 1972 1973#endif /* lint */ 1974 1975 1976/* 1977 * D$ parity error trap (trap 71) at TL>0. 1978 * tt1_dperr is replaced by dcache_parity_tl1_instr in cpu_init_trap of 1979 * the various architecture-specific files. This generates a "Software 1980 * Trap 1" at TL>0, which goes to dcache_parity_tl1_cont_instr, and we 1981 * continue the handling there. 1982 * NB: Must be 8 instructions or less to fit in trap table and code must 1983 * be relocatable. 1984 */ 1985#if defined(lint) 1986 1987void 1988dcache_parity_tl1_instr(void) 1989{} 1990 1991#else /* lint */ 1992 ENTRY_NP(dcache_parity_tl1_instr) 1993 CH_ERR_TL1_TRAPENTRY(SWTRAP_1); 1994 SET_SIZE(dcache_parity_tl1_instr) 1995 1996#endif /* lint */ 1997 1998 1999/* 2000 * Software trap 1 at TL>0. 2001 * tt1_swtrap1 is replaced by dcache_parity_tl1_cont_instr in cpu_init_trap 2002 * of the various architecture-specific files. This is used as a continuation 2003 * of the dcache parity handling where we've bought an extra TL level, so we 2004 * can use %tpc, %tnpc, %tstate to temporarily save the value of registers %g1 2005 * and %g2. Note that %tstate has bits 0-2 and then bits 8-19 as r/w, 2006 * there's a reserved hole from 3-7. We only use bits 0-1 and 8-9 (the low 2007 * order two bits from %g1 and %g2 respectively). 2008 * NB: Must be 8 instructions or less to fit in trap table and code must 2009 * be relocatable. 2010 */ 2011#if defined(lint) 2012 2013void 2014dcache_parity_tl1_cont_instr(void) 2015{} 2016 2017#else /* lint */ 2018 ENTRY_NP(dcache_parity_tl1_cont_instr) 2019 CH_ERR_TL1_SWTRAPENTRY(dcache_parity_tl1_err); 2020 SET_SIZE(dcache_parity_tl1_cont_instr) 2021 2022#endif /* lint */ 2023 2024/* 2025 * D$ parity error at TL>0 handler 2026 * We get here via trap 71 at TL>0->Software trap 1 at TL>0. We enter 2027 * this routine with %g1 and %g2 already saved in %tpc, %tnpc and %tstate. 2028 */ 2029#if defined(lint) 2030 2031void 2032dcache_parity_tl1_err(void) 2033{} 2034 2035#else /* lint */ 2036 2037 ENTRY_NP(dcache_parity_tl1_err) 2038 2039 /* 2040 * This macro saves all the %g registers in the ch_err_tl1_data 2041 * structure, updates the ch_err_tl1_flags and saves the %tpc in 2042 * ch_err_tl1_tpc. At the end of this macro, %g1 will point to 2043 * the ch_err_tl1_data structure and %g2 will have the original 2044 * flags in the ch_err_tl1_data structure. All %g registers 2045 * except for %g1 and %g2 will be available. 2046 */ 2047 CH_ERR_TL1_ENTER(CH_ERR_DPE); 2048 2049#ifdef TRAPTRACE 2050 /* 2051 * Get current trap trace entry physical pointer. 2052 */ 2053 CPU_INDEX(%g6, %g5) 2054 sll %g6, TRAPTR_SIZE_SHIFT, %g6 2055 set trap_trace_ctl, %g5 2056 add %g6, %g5, %g6 2057 ld [%g6 + TRAPTR_LIMIT], %g5 2058 tst %g5 2059 be %icc, dpe_tl1_skip_tt 2060 nop 2061 ldx [%g6 + TRAPTR_PBASE], %g5 2062 ld [%g6 + TRAPTR_OFFSET], %g4 2063 add %g5, %g4, %g5 2064 2065 /* 2066 * Create trap trace entry. 2067 */ 2068 rd %asi, %g7 2069 wr %g0, TRAPTR_ASI, %asi 2070 rd STICK, %g4 2071 stxa %g4, [%g5 + TRAP_ENT_TICK]%asi 2072 rdpr %tl, %g4 2073 stha %g4, [%g5 + TRAP_ENT_TL]%asi 2074 rdpr %tt, %g4 2075 stha %g4, [%g5 + TRAP_ENT_TT]%asi 2076 rdpr %tpc, %g4 2077 stna %g4, [%g5 + TRAP_ENT_TPC]%asi 2078 rdpr %tstate, %g4 2079 stxa %g4, [%g5 + TRAP_ENT_TSTATE]%asi 2080 stna %sp, [%g5 + TRAP_ENT_SP]%asi 2081 stna %g0, [%g5 + TRAP_ENT_TR]%asi 2082 stna %g0, [%g5 + TRAP_ENT_F1]%asi 2083 stna %g0, [%g5 + TRAP_ENT_F2]%asi 2084 stna %g0, [%g5 + TRAP_ENT_F3]%asi 2085 stna %g0, [%g5 + TRAP_ENT_F4]%asi 2086 wr %g0, %g7, %asi 2087 2088 /* 2089 * Advance trap trace pointer. 2090 */ 2091 ld [%g6 + TRAPTR_OFFSET], %g5 2092 ld [%g6 + TRAPTR_LIMIT], %g4 2093 st %g5, [%g6 + TRAPTR_LAST_OFFSET] 2094 add %g5, TRAP_ENT_SIZE, %g5 2095 sub %g4, TRAP_ENT_SIZE, %g4 2096 cmp %g5, %g4 2097 movge %icc, 0, %g5 2098 st %g5, [%g6 + TRAPTR_OFFSET] 2099dpe_tl1_skip_tt: 2100#endif /* TRAPTRACE */ 2101 2102 /* 2103 * I$ and D$ are automatically turned off by HW when the CPU hits 2104 * a dcache or icache parity error so we will just leave those two 2105 * off for now to avoid repeating this trap. 2106 * For Panther, however, since we trap on P$ data parity errors 2107 * and HW does not automatically disable P$, we need to disable it 2108 * here so that we don't encounter any recursive traps when we 2109 * issue the retry. 2110 */ 2111 ldxa [%g0]ASI_DCU, %g3 2112 mov 1, %g4 2113 sllx %g4, DCU_PE_SHIFT, %g4 2114 andn %g3, %g4, %g3 2115 stxa %g3, [%g0]ASI_DCU 2116 membar #Sync 2117 2118 /* 2119 * We fall into this macro if we've successfully logged the error in 2120 * the ch_err_tl1_data structure and want the PIL15 softint to pick 2121 * it up and log it. %g1 must point to the ch_err_tl1_data structure. 2122 * Restores the %g registers and issues retry. 2123 */ 2124 CH_ERR_TL1_EXIT; 2125 SET_SIZE(dcache_parity_tl1_err) 2126 2127#endif /* lint */ 2128 2129/* 2130 * I$ parity error trap (trap 72) at TL=0. 2131 * tt0_iperr is replaced by icache_parity_instr in cpu_init_trap of 2132 * the various architecture-specific files. This merely sets up the 2133 * arguments for cpu_parity_error and calls it via sys_trap. 2134 * NB: Must be 8 instructions or less to fit in trap table and code must 2135 * be relocatable. 2136 */ 2137#if defined(lint) 2138 2139void 2140icache_parity_instr(void) 2141{} 2142 2143#else /* lint */ 2144 2145 ENTRY_NP(icache_parity_instr) 2146 membar #Sync ! Cheetah+ requires membar #Sync 2147 set cpu_parity_error, %g1 2148 or %g0, CH_ERR_IPE, %g2 2149 rdpr %tpc, %g3 2150 sethi %hi(sys_trap), %g7 2151 jmp %g7 + %lo(sys_trap) 2152 mov PIL_15, %g4 ! run at pil 15 2153 SET_SIZE(icache_parity_instr) 2154 2155#endif /* lint */ 2156 2157/* 2158 * I$ parity error trap (trap 72) at TL>0. 2159 * tt1_iperr is replaced by icache_parity_tl1_instr in cpu_init_trap of 2160 * the various architecture-specific files. This generates a "Software 2161 * Trap 2" at TL>0, which goes to icache_parity_tl1_cont_instr, and we 2162 * continue the handling there. 2163 * NB: Must be 8 instructions or less to fit in trap table and code must 2164 * be relocatable. 2165 */ 2166#if defined(lint) 2167 2168void 2169icache_parity_tl1_instr(void) 2170{} 2171 2172#else /* lint */ 2173 ENTRY_NP(icache_parity_tl1_instr) 2174 CH_ERR_TL1_TRAPENTRY(SWTRAP_2); 2175 SET_SIZE(icache_parity_tl1_instr) 2176 2177#endif /* lint */ 2178 2179/* 2180 * Software trap 2 at TL>0. 2181 * tt1_swtrap2 is replaced by icache_parity_tl1_cont_instr in cpu_init_trap 2182 * of the various architecture-specific files. This is used as a continuation 2183 * of the icache parity handling where we've bought an extra TL level, so we 2184 * can use %tpc, %tnpc, %tstate to temporarily save the value of registers %g1 2185 * and %g2. Note that %tstate has bits 0-2 and then bits 8-19 as r/w, 2186 * there's a reserved hole from 3-7. We only use bits 0-1 and 8-9 (the low 2187 * order two bits from %g1 and %g2 respectively). 2188 * NB: Must be 8 instructions or less to fit in trap table and code must 2189 * be relocatable. 2190 */ 2191#if defined(lint) 2192 2193void 2194icache_parity_tl1_cont_instr(void) 2195{} 2196 2197#else /* lint */ 2198 ENTRY_NP(icache_parity_tl1_cont_instr) 2199 CH_ERR_TL1_SWTRAPENTRY(icache_parity_tl1_err); 2200 SET_SIZE(icache_parity_tl1_cont_instr) 2201 2202#endif /* lint */ 2203 2204 2205/* 2206 * I$ parity error at TL>0 handler 2207 * We get here via trap 72 at TL>0->Software trap 2 at TL>0. We enter 2208 * this routine with %g1 and %g2 already saved in %tpc, %tnpc and %tstate. 2209 */ 2210#if defined(lint) 2211 2212void 2213icache_parity_tl1_err(void) 2214{} 2215 2216#else /* lint */ 2217 2218 ENTRY_NP(icache_parity_tl1_err) 2219 2220 /* 2221 * This macro saves all the %g registers in the ch_err_tl1_data 2222 * structure, updates the ch_err_tl1_flags and saves the %tpc in 2223 * ch_err_tl1_tpc. At the end of this macro, %g1 will point to 2224 * the ch_err_tl1_data structure and %g2 will have the original 2225 * flags in the ch_err_tl1_data structure. All %g registers 2226 * except for %g1 and %g2 will be available. 2227 */ 2228 CH_ERR_TL1_ENTER(CH_ERR_IPE); 2229 2230#ifdef TRAPTRACE 2231 /* 2232 * Get current trap trace entry physical pointer. 2233 */ 2234 CPU_INDEX(%g6, %g5) 2235 sll %g6, TRAPTR_SIZE_SHIFT, %g6 2236 set trap_trace_ctl, %g5 2237 add %g6, %g5, %g6 2238 ld [%g6 + TRAPTR_LIMIT], %g5 2239 tst %g5 2240 be %icc, ipe_tl1_skip_tt 2241 nop 2242 ldx [%g6 + TRAPTR_PBASE], %g5 2243 ld [%g6 + TRAPTR_OFFSET], %g4 2244 add %g5, %g4, %g5 2245 2246 /* 2247 * Create trap trace entry. 2248 */ 2249 rd %asi, %g7 2250 wr %g0, TRAPTR_ASI, %asi 2251 rd STICK, %g4 2252 stxa %g4, [%g5 + TRAP_ENT_TICK]%asi 2253 rdpr %tl, %g4 2254 stha %g4, [%g5 + TRAP_ENT_TL]%asi 2255 rdpr %tt, %g4 2256 stha %g4, [%g5 + TRAP_ENT_TT]%asi 2257 rdpr %tpc, %g4 2258 stna %g4, [%g5 + TRAP_ENT_TPC]%asi 2259 rdpr %tstate, %g4 2260 stxa %g4, [%g5 + TRAP_ENT_TSTATE]%asi 2261 stna %sp, [%g5 + TRAP_ENT_SP]%asi 2262 stna %g0, [%g5 + TRAP_ENT_TR]%asi 2263 stna %g0, [%g5 + TRAP_ENT_F1]%asi 2264 stna %g0, [%g5 + TRAP_ENT_F2]%asi 2265 stna %g0, [%g5 + TRAP_ENT_F3]%asi 2266 stna %g0, [%g5 + TRAP_ENT_F4]%asi 2267 wr %g0, %g7, %asi 2268 2269 /* 2270 * Advance trap trace pointer. 2271 */ 2272 ld [%g6 + TRAPTR_OFFSET], %g5 2273 ld [%g6 + TRAPTR_LIMIT], %g4 2274 st %g5, [%g6 + TRAPTR_LAST_OFFSET] 2275 add %g5, TRAP_ENT_SIZE, %g5 2276 sub %g4, TRAP_ENT_SIZE, %g4 2277 cmp %g5, %g4 2278 movge %icc, 0, %g5 2279 st %g5, [%g6 + TRAPTR_OFFSET] 2280ipe_tl1_skip_tt: 2281#endif /* TRAPTRACE */ 2282 2283 /* 2284 * We fall into this macro if we've successfully logged the error in 2285 * the ch_err_tl1_data structure and want the PIL15 softint to pick 2286 * it up and log it. %g1 must point to the ch_err_tl1_data structure. 2287 * Restores the %g registers and issues retry. 2288 */ 2289 CH_ERR_TL1_EXIT; 2290 2291 SET_SIZE(icache_parity_tl1_err) 2292 2293#endif /* lint */ 2294 2295#endif /* CPU_IMP_L1_CACHE_PARITY */ 2296 2297 2298/* 2299 * The itlb_rd_entry and dtlb_rd_entry functions return the tag portion of the 2300 * tte, the virtual address, and the ctxnum of the specified tlb entry. They 2301 * should only be used in places where you have no choice but to look at the 2302 * tlb itself. 2303 * 2304 * Note: These two routines are required by the Estar "cpr" loadable module. 2305 */ 2306 2307#if defined(lint) 2308 2309/* ARGSUSED */ 2310void 2311itlb_rd_entry(uint_t entry, tte_t *tte, uint64_t *va_tag) 2312{} 2313 2314#else /* lint */ 2315 2316 ENTRY_NP(itlb_rd_entry) 2317 sllx %o0, 3, %o0 2318 ldxa [%o0]ASI_ITLB_ACCESS, %g1 2319 stx %g1, [%o1] 2320 ldxa [%o0]ASI_ITLB_TAGREAD, %g2 2321 set TAGREAD_CTX_MASK, %o4 2322 andn %g2, %o4, %o5 2323 retl 2324 stx %o5, [%o2] 2325 SET_SIZE(itlb_rd_entry) 2326 2327#endif /* lint */ 2328 2329 2330#if defined(lint) 2331 2332/* ARGSUSED */ 2333void 2334dtlb_rd_entry(uint_t entry, tte_t *tte, uint64_t *va_tag) 2335{} 2336 2337#else /* lint */ 2338 2339 ENTRY_NP(dtlb_rd_entry) 2340 sllx %o0, 3, %o0 2341 ldxa [%o0]ASI_DTLB_ACCESS, %g1 2342 stx %g1, [%o1] 2343 ldxa [%o0]ASI_DTLB_TAGREAD, %g2 2344 set TAGREAD_CTX_MASK, %o4 2345 andn %g2, %o4, %o5 2346 retl 2347 stx %o5, [%o2] 2348 SET_SIZE(dtlb_rd_entry) 2349#endif /* lint */ 2350 2351 2352#if !(defined(JALAPENO) || defined(SERRANO)) 2353 2354#if defined(lint) 2355 2356uint64_t 2357get_safari_config(void) 2358{ return (0); } 2359 2360#else /* lint */ 2361 2362 ENTRY(get_safari_config) 2363 ldxa [%g0]ASI_SAFARI_CONFIG, %o0 2364 retl 2365 nop 2366 SET_SIZE(get_safari_config) 2367 2368#endif /* lint */ 2369 2370 2371#if defined(lint) 2372 2373/* ARGSUSED */ 2374void 2375set_safari_config(uint64_t safari_config) 2376{} 2377 2378#else /* lint */ 2379 2380 ENTRY(set_safari_config) 2381 stxa %o0, [%g0]ASI_SAFARI_CONFIG 2382 membar #Sync 2383 retl 2384 nop 2385 SET_SIZE(set_safari_config) 2386 2387#endif /* lint */ 2388 2389#endif /* !(JALAPENO || SERRANO) */ 2390 2391 2392#if defined(lint) 2393 2394void 2395cpu_cleartickpnt(void) 2396{} 2397 2398#else /* lint */ 2399 /* 2400 * Clear the NPT (non-privileged trap) bit in the %tick/%stick 2401 * registers. In an effort to make the change in the 2402 * tick/stick counter as consistent as possible, we disable 2403 * all interrupts while we're changing the registers. We also 2404 * ensure that the read and write instructions are in the same 2405 * line in the instruction cache. 2406 */ 2407 ENTRY_NP(cpu_clearticknpt) 2408 rdpr %pstate, %g1 /* save processor state */ 2409 andn %g1, PSTATE_IE, %g3 /* turn off */ 2410 wrpr %g0, %g3, %pstate /* interrupts */ 2411 rdpr %tick, %g2 /* get tick register */ 2412 brgez,pn %g2, 1f /* if NPT bit off, we're done */ 2413 mov 1, %g3 /* create mask */ 2414 sllx %g3, 63, %g3 /* for NPT bit */ 2415 ba,a,pt %xcc, 2f 2416 .align 8 /* Ensure rd/wr in same i$ line */ 24172: 2418 rdpr %tick, %g2 /* get tick register */ 2419 wrpr %g3, %g2, %tick /* write tick register, */ 2420 /* clearing NPT bit */ 24211: 2422 rd STICK, %g2 /* get stick register */ 2423 brgez,pn %g2, 3f /* if NPT bit off, we're done */ 2424 mov 1, %g3 /* create mask */ 2425 sllx %g3, 63, %g3 /* for NPT bit */ 2426 ba,a,pt %xcc, 4f 2427 .align 8 /* Ensure rd/wr in same i$ line */ 24284: 2429 rd STICK, %g2 /* get stick register */ 2430 wr %g3, %g2, STICK /* write stick register, */ 2431 /* clearing NPT bit */ 24323: 2433 jmp %g4 + 4 2434 wrpr %g0, %g1, %pstate /* restore processor state */ 2435 2436 SET_SIZE(cpu_clearticknpt) 2437 2438#endif /* lint */ 2439 2440 2441#if defined(CPU_IMP_L1_CACHE_PARITY) 2442 2443#if defined(lint) 2444/* 2445 * correct_dcache_parity(size_t size, size_t linesize) 2446 * 2447 * Correct D$ data parity by zeroing the data and initializing microtag 2448 * for all indexes and all ways of the D$. 2449 * 2450 */ 2451/* ARGSUSED */ 2452void 2453correct_dcache_parity(size_t size, size_t linesize) 2454{} 2455 2456#else /* lint */ 2457 2458 ENTRY(correct_dcache_parity) 2459 /* 2460 * Register Usage: 2461 * 2462 * %o0 = input D$ size 2463 * %o1 = input D$ line size 2464 * %o2 = scratch 2465 * %o3 = scratch 2466 * %o4 = scratch 2467 */ 2468 2469 sub %o0, %o1, %o0 ! init cache line address 2470 2471 /* 2472 * For Panther CPUs, we also need to clear the data parity bits 2473 * using DC_data_parity bit of the ASI_DCACHE_DATA register. 2474 */ 2475 GET_CPU_IMPL(%o3) 2476 cmp %o3, PANTHER_IMPL 2477 bne 1f 2478 clr %o3 ! zero for non-Panther 2479 mov 1, %o3 2480 sll %o3, PN_DC_DATA_PARITY_BIT_SHIFT, %o3 2481 24821: 2483 /* 2484 * Set utag = way since it must be unique within an index. 2485 */ 2486 srl %o0, 14, %o2 ! get cache way (DC_way) 2487 membar #Sync ! required before ASI_DC_UTAG 2488 stxa %o2, [%o0]ASI_DC_UTAG ! set D$ utag = cache way 2489 membar #Sync ! required after ASI_DC_UTAG 2490 2491 /* 2492 * Zero line of D$ data (and data parity bits for Panther) 2493 */ 2494 sub %o1, 8, %o2 2495 or %o0, %o3, %o4 ! same address + DC_data_parity 24962: 2497 membar #Sync ! required before ASI_DC_DATA 2498 stxa %g0, [%o0 + %o2]ASI_DC_DATA ! zero 8 bytes of D$ data 2499 membar #Sync ! required after ASI_DC_DATA 2500 /* 2501 * We also clear the parity bits if this is a panther. For non-Panther 2502 * CPUs, we simply end up clearing the $data register twice. 2503 */ 2504 stxa %g0, [%o4 + %o2]ASI_DC_DATA 2505 membar #Sync 2506 2507 subcc %o2, 8, %o2 2508 bge 2b 2509 nop 2510 2511 subcc %o0, %o1, %o0 2512 bge 1b 2513 nop 2514 2515 retl 2516 nop 2517 SET_SIZE(correct_dcache_parity) 2518 2519#endif /* lint */ 2520 2521#endif /* CPU_IMP_L1_CACHE_PARITY */ 2522 2523 2524#if defined(lint) 2525/* 2526 * Get timestamp (stick). 2527 */ 2528/* ARGSUSED */ 2529void 2530stick_timestamp(int64_t *ts) 2531{ 2532} 2533 2534#else /* lint */ 2535 2536 ENTRY_NP(stick_timestamp) 2537 rd STICK, %g1 ! read stick reg 2538 sllx %g1, 1, %g1 2539 srlx %g1, 1, %g1 ! clear npt bit 2540 2541 retl 2542 stx %g1, [%o0] ! store the timestamp 2543 SET_SIZE(stick_timestamp) 2544 2545#endif /* lint */ 2546 2547 2548#if defined(lint) 2549/* 2550 * Set STICK adjusted by skew. 2551 */ 2552/* ARGSUSED */ 2553void 2554stick_adj(int64_t skew) 2555{ 2556} 2557 2558#else /* lint */ 2559 2560 ENTRY_NP(stick_adj) 2561 rdpr %pstate, %g1 ! save processor state 2562 andn %g1, PSTATE_IE, %g3 2563 ba 1f ! cache align stick adj 2564 wrpr %g0, %g3, %pstate ! turn off interrupts 2565 2566 .align 16 25671: nop 2568 2569 rd STICK, %g4 ! read stick reg 2570 add %g4, %o0, %o1 ! adjust stick with skew 2571 wr %o1, %g0, STICK ! write stick reg 2572 2573 retl 2574 wrpr %g1, %pstate ! restore processor state 2575 SET_SIZE(stick_adj) 2576 2577#endif /* lint */ 2578 2579#if defined(lint) 2580/* 2581 * Debugger-specific stick retrieval 2582 */ 2583/*ARGSUSED*/ 2584int 2585kdi_get_stick(uint64_t *stickp) 2586{ 2587 return (0); 2588} 2589 2590#else /* lint */ 2591 2592 ENTRY_NP(kdi_get_stick) 2593 rd STICK, %g1 2594 stx %g1, [%o0] 2595 retl 2596 mov %g0, %o0 2597 SET_SIZE(kdi_get_stick) 2598 2599#endif /* lint */ 2600 2601#if defined(lint) 2602/* 2603 * Invalidate the specified line from the D$. 2604 * 2605 * Register usage: 2606 * %o0 - index for the invalidation, specifies DC_way and DC_addr 2607 * 2608 * ASI_DC_TAG, 0x47, is used in the following manner. A 64-bit value is 2609 * stored to a particular DC_way and DC_addr in ASI_DC_TAG. 2610 * 2611 * The format of the stored 64-bit value is: 2612 * 2613 * +----------+--------+----------+ 2614 * | Reserved | DC_tag | DC_valid | 2615 * +----------+--------+----------+ 2616 * 63 31 30 1 0 2617 * 2618 * DC_tag is the 30-bit physical tag of the associated line. 2619 * DC_valid is the 1-bit valid field for both the physical and snoop tags. 2620 * 2621 * The format of the 64-bit DC_way and DC_addr into ASI_DC_TAG is: 2622 * 2623 * +----------+--------+----------+----------+ 2624 * | Reserved | DC_way | DC_addr | Reserved | 2625 * +----------+--------+----------+----------+ 2626 * 63 16 15 14 13 5 4 0 2627 * 2628 * DC_way is a 2-bit index that selects one of the 4 ways. 2629 * DC_addr is a 9-bit index that selects one of 512 tag/valid fields. 2630 * 2631 * Setting the DC_valid bit to zero for the specified DC_way and 2632 * DC_addr index into the D$ results in an invalidation of a D$ line. 2633 */ 2634/*ARGSUSED*/ 2635void 2636dcache_inval_line(int index) 2637{ 2638} 2639#else /* lint */ 2640 ENTRY(dcache_inval_line) 2641 sll %o0, 5, %o0 ! shift index into DC_way and DC_addr 2642 stxa %g0, [%o0]ASI_DC_TAG ! zero the DC_valid and DC_tag bits 2643 membar #Sync 2644 retl 2645 nop 2646 SET_SIZE(dcache_inval_line) 2647#endif /* lint */ 2648 2649#if defined(lint) 2650/* 2651 * Invalidate the entire I$ 2652 * 2653 * Register usage: 2654 * %o0 - specifies IC_way, IC_addr, IC_tag 2655 * %o1 - scratch 2656 * %o2 - used to save and restore DCU value 2657 * %o3 - scratch 2658 * %o5 - used to save and restore PSTATE 2659 * 2660 * Due to the behavior of the I$ control logic when accessing ASI_IC_TAG, 2661 * the I$ should be turned off. Accesses to ASI_IC_TAG may collide and 2662 * block out snoops and invalidates to the I$, causing I$ consistency 2663 * to be broken. Before turning on the I$, all I$ lines must be invalidated. 2664 * 2665 * ASI_IC_TAG, 0x67, is used in the following manner. A 64-bit value is 2666 * stored to a particular IC_way, IC_addr, IC_tag in ASI_IC_TAG. The 2667 * info below describes store (write) use of ASI_IC_TAG. Note that read 2668 * use of ASI_IC_TAG behaves differently. 2669 * 2670 * The format of the stored 64-bit value is: 2671 * 2672 * +----------+--------+---------------+-----------+ 2673 * | Reserved | Valid | IC_vpred<7:0> | Undefined | 2674 * +----------+--------+---------------+-----------+ 2675 * 63 55 54 53 46 45 0 2676 * 2677 * Valid is the 1-bit valid field for both the physical and snoop tags. 2678 * IC_vpred is the 8-bit LPB bits for 8 instructions starting at 2679 * the 32-byte boundary aligned address specified by IC_addr. 2680 * 2681 * The format of the 64-bit IC_way, IC_addr, IC_tag into ASI_IC_TAG is: 2682 * 2683 * +----------+--------+---------+--------+---------+ 2684 * | Reserved | IC_way | IC_addr | IC_tag |Reserved | 2685 * +----------+--------+---------+--------+---------+ 2686 * 63 16 15 14 13 5 4 3 2 0 2687 * 2688 * IC_way is a 2-bit index that selects one of the 4 ways. 2689 * IC_addr[13:6] is an 8-bit index that selects one of 256 valid fields. 2690 * IC_addr[5] is a "don't care" for a store. 2691 * IC_tag set to 2 specifies that the stored value is to be interpreted 2692 * as containing Valid and IC_vpred as described above. 2693 * 2694 * Setting the Valid bit to zero for the specified IC_way and 2695 * IC_addr index into the I$ results in an invalidation of an I$ line. 2696 */ 2697/*ARGSUSED*/ 2698void 2699icache_inval_all(void) 2700{ 2701} 2702#else /* lint */ 2703 ENTRY(icache_inval_all) 2704 rdpr %pstate, %o5 2705 andn %o5, PSTATE_IE, %o3 2706 wrpr %g0, %o3, %pstate ! clear IE bit 2707 2708 GET_CPU_PRIVATE_PTR(%g0, %o0, %o2, icache_inval_all_1); 2709 ld [%o0 + CHPR_ICACHE_LINESIZE], %o1 2710 ba,pt %icc, 2f 2711 ld [%o0 + CHPR_ICACHE_SIZE], %o0 2712icache_inval_all_1: 2713 ASM_LD(%o0, icache_size) 2714 ASM_LD(%o1, icache_linesize) 27152: 2716 CH_ICACHE_FLUSHALL(%o0, %o1, %o2, %o4) 2717 2718 retl 2719 wrpr %g0, %o5, %pstate ! restore earlier pstate 2720 SET_SIZE(icache_inval_all) 2721#endif /* lint */ 2722 2723 2724#if defined(lint) 2725/* ARGSUSED */ 2726void 2727cache_scrubreq_tl1(uint64_t inum, uint64_t index) 2728{ 2729} 2730 2731#else /* lint */ 2732/* 2733 * cache_scrubreq_tl1 is the crosstrap handler called on offlined cpus via a 2734 * crosstrap. It atomically increments the outstanding request counter and, 2735 * if there was not already an outstanding request, branches to setsoftint_tl1 2736 * to enqueue an intr_vec for the given inum. 2737 */ 2738 2739 ! Register usage: 2740 ! 2741 ! Arguments: 2742 ! %g1 - inum 2743 ! %g2 - index into chsm_outstanding array 2744 ! 2745 ! Internal: 2746 ! %g2, %g3, %g5 - scratch 2747 ! %g4 - ptr. to scrub_misc chsm_outstanding[index]. 2748 ! %g6 - setsoftint_tl1 address 2749 2750 ENTRY_NP(cache_scrubreq_tl1) 2751 mulx %g2, CHSM_OUTSTANDING_INCR, %g2 2752 set CHPR_SCRUB_MISC + CHSM_OUTSTANDING, %g3 2753 add %g2, %g3, %g2 2754 GET_CPU_PRIVATE_PTR(%g2, %g4, %g5, 1f); 2755 ld [%g4], %g2 ! cpu's chsm_outstanding[index] 2756 ! 2757 ! no need to use atomic instructions for the following 2758 ! increment - we're at tl1 2759 ! 2760 add %g2, 0x1, %g3 2761 brnz,pn %g2, 1f ! no need to enqueue more intr_vec 2762 st %g3, [%g4] ! delay - store incremented counter 2763 ASM_JMP(%g6, setsoftint_tl1) 2764 ! not reached 27651: 2766 retry 2767 SET_SIZE(cache_scrubreq_tl1) 2768 2769#endif /* lint */ 2770 2771 2772#if defined(lint) 2773 2774/* ARGSUSED */ 2775void 2776get_cpu_error_state(ch_cpu_errors_t *cpu_error_regs) 2777{} 2778 2779#else /* lint */ 2780 2781/* 2782 * Get the error state for the processor. 2783 * Note that this must not be used at TL>0 2784 */ 2785 ENTRY(get_cpu_error_state) 2786#if defined(CHEETAH_PLUS) 2787 set ASI_SHADOW_REG_VA, %o2 2788 ldxa [%o2]ASI_AFSR, %o1 ! shadow afsr reg 2789 stx %o1, [%o0 + CH_CPU_ERRORS_SHADOW_AFSR] 2790 ldxa [%o2]ASI_AFAR, %o1 ! shadow afar reg 2791 stx %o1, [%o0 + CH_CPU_ERRORS_SHADOW_AFAR] 2792 GET_CPU_IMPL(%o3) ! Only panther has AFSR_EXT registers 2793 cmp %o3, PANTHER_IMPL 2794 bne,a 1f 2795 stx %g0, [%o0 + CH_CPU_ERRORS_AFSR_EXT] ! zero for non-PN 2796 set ASI_AFSR_EXT_VA, %o2 2797 ldxa [%o2]ASI_AFSR, %o1 ! afsr_ext reg 2798 stx %o1, [%o0 + CH_CPU_ERRORS_AFSR_EXT] 2799 set ASI_SHADOW_AFSR_EXT_VA, %o2 2800 ldxa [%o2]ASI_AFSR, %o1 ! shadow afsr_ext reg 2801 stx %o1, [%o0 + CH_CPU_ERRORS_SHADOW_AFSR_EXT] 2802 b 2f 2803 nop 28041: 2805 stx %g0, [%o0 + CH_CPU_ERRORS_SHADOW_AFSR_EXT] ! zero for non-PN 28062: 2807#else /* CHEETAH_PLUS */ 2808 stx %g0, [%o0 + CH_CPU_ERRORS_SHADOW_AFSR] 2809 stx %g0, [%o0 + CH_CPU_ERRORS_SHADOW_AFAR] 2810 stx %g0, [%o0 + CH_CPU_ERRORS_AFSR_EXT] 2811 stx %g0, [%o0 + CH_CPU_ERRORS_SHADOW_AFSR_EXT] 2812#endif /* CHEETAH_PLUS */ 2813#if defined(SERRANO) 2814 /* 2815 * Serrano has an afar2 which captures the address on FRC/FRU errors. 2816 * We save this in the afar2 of the register save area. 2817 */ 2818 set ASI_MCU_AFAR2_VA, %o2 2819 ldxa [%o2]ASI_MCU_CTRL, %o1 2820 stx %o1, [%o0 + CH_CPU_ERRORS_AFAR2] 2821#endif /* SERRANO */ 2822 ldxa [%g0]ASI_AFSR, %o1 ! primary afsr reg 2823 stx %o1, [%o0 + CH_CPU_ERRORS_AFSR] 2824 ldxa [%g0]ASI_AFAR, %o1 ! primary afar reg 2825 retl 2826 stx %o1, [%o0 + CH_CPU_ERRORS_AFAR] 2827 SET_SIZE(get_cpu_error_state) 2828#endif /* lint */ 2829 2830#if defined(lint) 2831 2832/* 2833 * Check a page of memory for errors. 2834 * 2835 * Load each 64 byte block from physical memory. 2836 * Check AFSR after each load to see if an error 2837 * was caused. If so, log/scrub that error. 2838 * 2839 * Used to determine if a page contains 2840 * CEs when CEEN is disabled. 2841 */ 2842/*ARGSUSED*/ 2843void 2844cpu_check_block(caddr_t va, uint_t psz) 2845{} 2846 2847#else /* lint */ 2848 2849 ENTRY(cpu_check_block) 2850 ! 2851 ! get a new window with room for the error regs 2852 ! 2853 save %sp, -SA(MINFRAME + CH_CPU_ERROR_SIZE), %sp 2854 srl %i1, 6, %l4 ! clear top bits of psz 2855 ! and divide by 64 2856 rd %fprs, %l2 ! store FP 2857 wr %g0, FPRS_FEF, %fprs ! enable FP 28581: 2859 ldda [%i0]ASI_BLK_P, %d0 ! load a block 2860 membar #Sync 2861 ldxa [%g0]ASI_AFSR, %l3 ! read afsr reg 2862 brz,a,pt %l3, 2f ! check for error 2863 nop 2864 2865 ! 2866 ! if error, read the error regs and log it 2867 ! 2868 call get_cpu_error_state 2869 add %fp, STACK_BIAS - CH_CPU_ERROR_SIZE, %o0 2870 2871 ! 2872 ! cpu_ce_detected(ch_cpu_errors_t *, flag) 2873 ! 2874 call cpu_ce_detected ! log the error 2875 mov CE_CEEN_TIMEOUT, %o1 28762: 2877 dec %l4 ! next 64-byte block 2878 brnz,a,pt %l4, 1b 2879 add %i0, 64, %i0 ! increment block addr 2880 2881 wr %l2, %g0, %fprs ! restore FP 2882 ret 2883 restore 2884 2885 SET_SIZE(cpu_check_block) 2886 2887#endif /* lint */ 2888 2889#if defined(lint) 2890 2891/* 2892 * Perform a cpu logout called from C. This is used where we did not trap 2893 * for the error but still want to gather "what we can". Caller must make 2894 * sure cpu private area exists and that the indicated logout area is free 2895 * for use, and that we are unable to migrate cpus. 2896 */ 2897/*ARGSUSED*/ 2898void 2899cpu_delayed_logout(uint64_t afar, ch_cpu_logout_t *clop) 2900{ } 2901 2902#else 2903 ENTRY(cpu_delayed_logout) 2904 rdpr %pstate, %o2 2905 andn %o2, PSTATE_IE, %o2 2906 wrpr %g0, %o2, %pstate ! disable interrupts 2907 PARK_SIBLING_CORE(%o2, %o3, %o4) ! %o2 has DCU value 2908 add %o1, CH_CLO_DATA + CH_CHD_EC_DATA, %o1 2909 rd %asi, %g1 2910 wr %g0, ASI_P, %asi 2911 GET_ECACHE_DTAGS(%o0, %o1, %o3, %o4, %o5) 2912 wr %g1, %asi 2913 UNPARK_SIBLING_CORE(%o2, %o3, %o4) ! can use %o2 again 2914 rdpr %pstate, %o2 2915 or %o2, PSTATE_IE, %o2 2916 wrpr %g0, %o2, %pstate 2917 retl 2918 nop 2919 SET_SIZE(cpu_delayed_logout) 2920 2921#endif /* lint */ 2922 2923#if defined(lint) 2924 2925/*ARGSUSED*/ 2926int 2927dtrace_blksuword32(uintptr_t addr, uint32_t *data, int tryagain) 2928{ return (0); } 2929 2930#else 2931 2932 ENTRY(dtrace_blksuword32) 2933 save %sp, -SA(MINFRAME + 4), %sp 2934 2935 rdpr %pstate, %l1 2936 andn %l1, PSTATE_IE, %l2 ! disable interrupts to 2937 wrpr %g0, %l2, %pstate ! protect our FPU diddling 2938 2939 rd %fprs, %l0 2940 andcc %l0, FPRS_FEF, %g0 2941 bz,a,pt %xcc, 1f ! if the fpu is disabled 2942 wr %g0, FPRS_FEF, %fprs ! ... enable the fpu 2943 2944 st %f0, [%fp + STACK_BIAS - 4] ! save %f0 to the stack 29451: 2946 set 0f, %l5 2947 /* 2948 * We're about to write a block full or either total garbage 2949 * (not kernel data, don't worry) or user floating-point data 2950 * (so it only _looks_ like garbage). 2951 */ 2952 ld [%i1], %f0 ! modify the block 2953 membar #Sync 2954 stn %l5, [THREAD_REG + T_LOFAULT] ! set up the lofault handler 2955 stda %d0, [%i0]ASI_BLK_COMMIT_S ! store the modified block 2956 membar #Sync 2957 stn %g0, [THREAD_REG + T_LOFAULT] ! remove the lofault handler 2958 2959 bz,a,pt %xcc, 1f 2960 wr %g0, %l0, %fprs ! restore %fprs 2961 2962 ld [%fp + STACK_BIAS - 4], %f0 ! restore %f0 29631: 2964 2965 wrpr %g0, %l1, %pstate ! restore interrupts 2966 2967 ret 2968 restore %g0, %g0, %o0 2969 29700: 2971 membar #Sync 2972 stn %g0, [THREAD_REG + T_LOFAULT] ! remove the lofault handler 2973 2974 bz,a,pt %xcc, 1f 2975 wr %g0, %l0, %fprs ! restore %fprs 2976 2977 ld [%fp + STACK_BIAS - 4], %f0 ! restore %f0 29781: 2979 2980 wrpr %g0, %l1, %pstate ! restore interrupts 2981 2982 /* 2983 * If tryagain is set (%i2) we tail-call dtrace_blksuword32_err() 2984 * which deals with watchpoints. Otherwise, just return -1. 2985 */ 2986 brnz,pt %i2, 1f 2987 nop 2988 ret 2989 restore %g0, -1, %o0 29901: 2991 call dtrace_blksuword32_err 2992 restore 2993 2994 SET_SIZE(dtrace_blksuword32) 2995 2996#endif /* lint */ 2997 2998#ifdef CHEETAHPLUS_ERRATUM_25 2999 3000#if defined(lint) 3001/* 3002 * Claim a chunk of physical address space. 3003 */ 3004/*ARGSUSED*/ 3005void 3006claimlines(uint64_t pa, size_t sz, int stride) 3007{} 3008#else /* lint */ 3009 ENTRY(claimlines) 30101: 3011 subcc %o1, %o2, %o1 3012 add %o0, %o1, %o3 3013 bgeu,a,pt %xcc, 1b 3014 casxa [%o3]ASI_MEM, %g0, %g0 3015 membar #Sync 3016 retl 3017 nop 3018 SET_SIZE(claimlines) 3019#endif /* lint */ 3020 3021#if defined(lint) 3022/* 3023 * CPU feature initialization, 3024 * turn BPE off, 3025 * get device id. 3026 */ 3027/*ARGSUSED*/ 3028void 3029cpu_feature_init(void) 3030{} 3031#else /* lint */ 3032 ENTRY(cpu_feature_init) 3033 save %sp, -SA(MINFRAME), %sp 3034 sethi %hi(cheetah_bpe_off), %o0 3035 ld [%o0 + %lo(cheetah_bpe_off)], %o0 3036 brz %o0, 1f 3037 nop 3038 rd ASR_DISPATCH_CONTROL, %o0 3039 andn %o0, ASR_DISPATCH_CONTROL_BPE, %o0 3040 wr %o0, 0, ASR_DISPATCH_CONTROL 30411: 3042 ! 3043 ! get the device_id and store the device_id 3044 ! in the appropriate cpunodes structure 3045 ! given the cpus index 3046 ! 3047 CPU_INDEX(%o0, %o1) 3048 mulx %o0, CPU_NODE_SIZE, %o0 3049 set cpunodes + DEVICE_ID, %o1 3050 ldxa [%g0] ASI_DEVICE_SERIAL_ID, %o2 3051 stx %o2, [%o0 + %o1] 3052#ifdef CHEETAHPLUS_ERRATUM_34 3053 ! 3054 ! apply Cheetah+ erratum 34 workaround 3055 ! 3056 call itlb_erratum34_fixup 3057 nop 3058 call dtlb_erratum34_fixup 3059 nop 3060#endif /* CHEETAHPLUS_ERRATUM_34 */ 3061 ret 3062 restore 3063 SET_SIZE(cpu_feature_init) 3064#endif /* lint */ 3065 3066#if defined(lint) 3067/* 3068 * Copy a tsb entry atomically, from src to dest. 3069 * src must be 128 bit aligned. 3070 */ 3071/*ARGSUSED*/ 3072void 3073copy_tsb_entry(uintptr_t src, uintptr_t dest) 3074{} 3075#else /* lint */ 3076 ENTRY(copy_tsb_entry) 3077 ldda [%o0]ASI_NQUAD_LD, %o2 ! %o2 = tag, %o3 = data 3078 stx %o2, [%o1] 3079 stx %o3, [%o1 + 8 ] 3080 retl 3081 nop 3082 SET_SIZE(copy_tsb_entry) 3083#endif /* lint */ 3084 3085#endif /* CHEETAHPLUS_ERRATUM_25 */ 3086 3087#ifdef CHEETAHPLUS_ERRATUM_34 3088 3089#if defined(lint) 3090 3091/*ARGSUSED*/ 3092void 3093itlb_erratum34_fixup(void) 3094{} 3095 3096#else /* lint */ 3097 3098 ! 3099 ! In Cheetah+ erratum 34, under certain conditions an ITLB locked 3100 ! index 0 TTE will erroneously be displaced when a new TTE is 3101 ! loaded via ASI_ITLB_IN. In order to avoid cheetah+ erratum 34, 3102 ! locked index 0 TTEs must be relocated. 3103 ! 3104 ! NOTE: Care must be taken to avoid an ITLB miss in this routine. 3105 ! 3106 ENTRY_NP(itlb_erratum34_fixup) 3107 rdpr %pstate, %o3 3108#ifdef DEBUG 3109 PANIC_IF_INTR_DISABLED_PSTR(%o3, u3_di_label1, %g1) 3110#endif /* DEBUG */ 3111 wrpr %o3, PSTATE_IE, %pstate ! Disable interrupts 3112 ldxa [%g0]ASI_ITLB_ACCESS, %o1 ! %o1 = entry 0 data 3113 ldxa [%g0]ASI_ITLB_TAGREAD, %o2 ! %o2 = entry 0 tag 3114 3115 cmp %o1, %g0 ! Is this entry valid? 3116 bge %xcc, 1f 3117 andcc %o1, TTE_LCK_INT, %g0 ! Is this entry locked? 3118 bnz %icc, 2f 3119 nop 31201: 3121 retl ! Nope, outta here... 3122 wrpr %g0, %o3, %pstate ! Enable interrupts 31232: 3124 sethi %hi(FLUSH_ADDR), %o4 3125 stxa %g0, [%o2]ASI_ITLB_DEMAP ! Flush this mapping 3126 flush %o4 ! Flush required for I-MMU 3127 ! 3128 ! Start search from index 1 up. This is because the kernel force 3129 ! loads its text page at index 15 in sfmmu_kernel_remap() and we 3130 ! don't want our relocated entry evicted later. 3131 ! 3132 ! NOTE: We assume that we'll be successful in finding an unlocked 3133 ! or invalid entry. If that isn't the case there are bound to 3134 ! bigger problems. 3135 ! 3136 set (1 << 3), %g3 31373: 3138 ldxa [%g3]ASI_ITLB_ACCESS, %o4 ! Load TTE from t16 3139 ! 3140 ! If this entry isn't valid, we'll choose to displace it (regardless 3141 ! of the lock bit). 3142 ! 3143 cmp %o4, %g0 ! TTE is > 0 iff not valid 3144 bge %xcc, 4f ! If invalid, go displace 3145 andcc %o4, TTE_LCK_INT, %g0 ! Check for lock bit 3146 bnz,a %icc, 3b ! If locked, look at next 3147 add %g3, (1 << 3), %g3 ! entry 31484: 3149 ! 3150 ! We found an unlocked or invalid entry; we'll explicitly load 3151 ! the former index 0 entry here. 3152 ! 3153 sethi %hi(FLUSH_ADDR), %o4 3154 set MMU_TAG_ACCESS, %g4 3155 stxa %o2, [%g4]ASI_IMMU 3156 stxa %o1, [%g3]ASI_ITLB_ACCESS 3157 flush %o4 ! Flush required for I-MMU 3158 retl 3159 wrpr %g0, %o3, %pstate ! Enable interrupts 3160 SET_SIZE(itlb_erratum34_fixup) 3161 3162#endif /* lint */ 3163 3164#if defined(lint) 3165 3166/*ARGSUSED*/ 3167void 3168dtlb_erratum34_fixup(void) 3169{} 3170 3171#else /* lint */ 3172 3173 ! 3174 ! In Cheetah+ erratum 34, under certain conditions a DTLB locked 3175 ! index 0 TTE will erroneously be displaced when a new TTE is 3176 ! loaded. In order to avoid cheetah+ erratum 34, locked index 0 3177 ! TTEs must be relocated. 3178 ! 3179 ENTRY_NP(dtlb_erratum34_fixup) 3180 rdpr %pstate, %o3 3181#ifdef DEBUG 3182 PANIC_IF_INTR_DISABLED_PSTR(%o3, u3_di_label2, %g1) 3183#endif /* DEBUG */ 3184 wrpr %o3, PSTATE_IE, %pstate ! Disable interrupts 3185 ldxa [%g0]ASI_DTLB_ACCESS, %o1 ! %o1 = entry 0 data 3186 ldxa [%g0]ASI_DTLB_TAGREAD, %o2 ! %o2 = entry 0 tag 3187 3188 cmp %o1, %g0 ! Is this entry valid? 3189 bge %xcc, 1f 3190 andcc %o1, TTE_LCK_INT, %g0 ! Is this entry locked? 3191 bnz %icc, 2f 3192 nop 31931: 3194 retl ! Nope, outta here... 3195 wrpr %g0, %o3, %pstate ! Enable interrupts 31962: 3197 stxa %g0, [%o2]ASI_DTLB_DEMAP ! Flush this mapping 3198 membar #Sync 3199 ! 3200 ! Start search from index 1 up. 3201 ! 3202 ! NOTE: We assume that we'll be successful in finding an unlocked 3203 ! or invalid entry. If that isn't the case there are bound to 3204 ! bigger problems. 3205 ! 3206 set (1 << 3), %g3 32073: 3208 ldxa [%g3]ASI_DTLB_ACCESS, %o4 ! Load TTE from t16 3209 ! 3210 ! If this entry isn't valid, we'll choose to displace it (regardless 3211 ! of the lock bit). 3212 ! 3213 cmp %o4, %g0 ! TTE is > 0 iff not valid 3214 bge %xcc, 4f ! If invalid, go displace 3215 andcc %o4, TTE_LCK_INT, %g0 ! Check for lock bit 3216 bnz,a %icc, 3b ! If locked, look at next 3217 add %g3, (1 << 3), %g3 ! entry 32184: 3219 ! 3220 ! We found an unlocked or invalid entry; we'll explicitly load 3221 ! the former index 0 entry here. 3222 ! 3223 set MMU_TAG_ACCESS, %g4 3224 stxa %o2, [%g4]ASI_DMMU 3225 stxa %o1, [%g3]ASI_DTLB_ACCESS 3226 membar #Sync 3227 retl 3228 wrpr %g0, %o3, %pstate ! Enable interrupts 3229 SET_SIZE(dtlb_erratum34_fixup) 3230 3231#endif /* lint */ 3232 3233#endif /* CHEETAHPLUS_ERRATUM_34 */ 3234 3235