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