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