10Sstevel@tonic-gate/* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 52241Shuah * Common Development and Distribution License (the "License"). 62241Shuah * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate/* 22*10724SEthindra.Ramamurthy@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate * 250Sstevel@tonic-gate * Assembly code support for Cheetah/Cheetah+ modules 260Sstevel@tonic-gate */ 270Sstevel@tonic-gate 280Sstevel@tonic-gate#if !defined(lint) 290Sstevel@tonic-gate#include "assym.h" 300Sstevel@tonic-gate#endif /* !lint */ 310Sstevel@tonic-gate 320Sstevel@tonic-gate#include <sys/asm_linkage.h> 330Sstevel@tonic-gate#include <sys/mmu.h> 340Sstevel@tonic-gate#include <vm/hat_sfmmu.h> 350Sstevel@tonic-gate#include <sys/machparam.h> 360Sstevel@tonic-gate#include <sys/machcpuvar.h> 370Sstevel@tonic-gate#include <sys/machthread.h> 380Sstevel@tonic-gate#include <sys/machtrap.h> 390Sstevel@tonic-gate#include <sys/privregs.h> 400Sstevel@tonic-gate#include <sys/trap.h> 410Sstevel@tonic-gate#include <sys/cheetahregs.h> 420Sstevel@tonic-gate#include <sys/us3_module.h> 430Sstevel@tonic-gate#include <sys/xc_impl.h> 440Sstevel@tonic-gate#include <sys/intreg.h> 450Sstevel@tonic-gate#include <sys/async.h> 460Sstevel@tonic-gate#include <sys/clock.h> 470Sstevel@tonic-gate#include <sys/cheetahasm.h> 480Sstevel@tonic-gate#include <sys/cmpregs.h> 490Sstevel@tonic-gate 500Sstevel@tonic-gate#ifdef TRAPTRACE 510Sstevel@tonic-gate#include <sys/traptrace.h> 520Sstevel@tonic-gate#endif /* TRAPTRACE */ 530Sstevel@tonic-gate 540Sstevel@tonic-gate#if !defined(lint) 550Sstevel@tonic-gate 560Sstevel@tonic-gate/* BEGIN CSTYLED */ 570Sstevel@tonic-gate 580Sstevel@tonic-gate#define DCACHE_FLUSHPAGE(arg1, arg2, tmp1, tmp2, tmp3) \ 590Sstevel@tonic-gate ldxa [%g0]ASI_DCU, tmp1 ;\ 600Sstevel@tonic-gate btst DCU_DC, tmp1 /* is dcache enabled? */ ;\ 610Sstevel@tonic-gate bz,pn %icc, 1f ;\ 620Sstevel@tonic-gate ASM_LD(tmp1, dcache_linesize) ;\ 630Sstevel@tonic-gate ASM_LD(tmp2, dflush_type) ;\ 640Sstevel@tonic-gate cmp tmp2, FLUSHPAGE_TYPE ;\ 650Sstevel@tonic-gate be,pt %icc, 2f ;\ 660Sstevel@tonic-gate nop ;\ 670Sstevel@tonic-gate sllx arg1, CHEETAH_DC_VBIT_SHIFT, arg1/* tag to compare */ ;\ 680Sstevel@tonic-gate ASM_LD(tmp3, dcache_size) ;\ 690Sstevel@tonic-gate cmp tmp2, FLUSHMATCH_TYPE ;\ 700Sstevel@tonic-gate be,pt %icc, 3f ;\ 710Sstevel@tonic-gate nop ;\ 720Sstevel@tonic-gate /* \ 730Sstevel@tonic-gate * flushtype = FLUSHALL_TYPE, flush the whole thing \ 740Sstevel@tonic-gate * tmp3 = cache size \ 750Sstevel@tonic-gate * tmp1 = cache line size \ 760Sstevel@tonic-gate */ \ 770Sstevel@tonic-gate sub tmp3, tmp1, tmp2 ;\ 780Sstevel@tonic-gate4: \ 790Sstevel@tonic-gate stxa %g0, [tmp2]ASI_DC_TAG ;\ 800Sstevel@tonic-gate membar #Sync ;\ 810Sstevel@tonic-gate cmp %g0, tmp2 ;\ 820Sstevel@tonic-gate bne,pt %icc, 4b ;\ 830Sstevel@tonic-gate sub tmp2, tmp1, tmp2 ;\ 840Sstevel@tonic-gate ba,pt %icc, 1f ;\ 850Sstevel@tonic-gate nop ;\ 860Sstevel@tonic-gate /* \ 870Sstevel@tonic-gate * flushtype = FLUSHPAGE_TYPE \ 880Sstevel@tonic-gate * arg1 = pfn \ 890Sstevel@tonic-gate * arg2 = virtual color \ 900Sstevel@tonic-gate * tmp1 = cache line size \ 910Sstevel@tonic-gate * tmp2 = tag from cache \ 920Sstevel@tonic-gate * tmp3 = counter \ 930Sstevel@tonic-gate */ \ 940Sstevel@tonic-gate2: \ 950Sstevel@tonic-gate set MMU_PAGESIZE, tmp3 ;\ 960Sstevel@tonic-gate sllx arg1, MMU_PAGESHIFT, arg1 /* pfn to 43 bit PA */ ;\ 970Sstevel@tonic-gate sub tmp3, tmp1, tmp3 ;\ 980Sstevel@tonic-gate4: \ 990Sstevel@tonic-gate stxa %g0, [arg1 + tmp3]ASI_DC_INVAL ;\ 1000Sstevel@tonic-gate membar #Sync ;\ 1010Sstevel@tonic-gate5: \ 1020Sstevel@tonic-gate cmp %g0, tmp3 ;\ 1030Sstevel@tonic-gate bnz,pt %icc, 4b /* branch if not done */ ;\ 1040Sstevel@tonic-gate sub tmp3, tmp1, tmp3 ;\ 1050Sstevel@tonic-gate ba,pt %icc, 1f ;\ 1060Sstevel@tonic-gate nop ;\ 1070Sstevel@tonic-gate /* \ 1080Sstevel@tonic-gate * flushtype = FLUSHMATCH_TYPE \ 1090Sstevel@tonic-gate * arg1 = tag to compare against \ 1100Sstevel@tonic-gate * tmp1 = cache line size \ 1110Sstevel@tonic-gate * tmp3 = cache size \ 1120Sstevel@tonic-gate * arg2 = counter \ 1130Sstevel@tonic-gate * tmp2 = cache tag \ 1140Sstevel@tonic-gate */ \ 1150Sstevel@tonic-gate3: \ 1160Sstevel@tonic-gate sub tmp3, tmp1, arg2 ;\ 1170Sstevel@tonic-gate4: \ 1180Sstevel@tonic-gate ldxa [arg2]ASI_DC_TAG, tmp2 /* read tag */ ;\ 1190Sstevel@tonic-gate btst CHEETAH_DC_VBIT_MASK, tmp2 ;\ 1200Sstevel@tonic-gate bz,pn %icc, 5f /* br if no valid sub-blocks */ ;\ 1210Sstevel@tonic-gate andn tmp2, CHEETAH_DC_VBIT_MASK, tmp2 /* clear out v bits */ ;\ 1220Sstevel@tonic-gate cmp tmp2, arg1 ;\ 1230Sstevel@tonic-gate bne,pn %icc, 5f /* branch if tag miss */ ;\ 1240Sstevel@tonic-gate nop ;\ 1250Sstevel@tonic-gate stxa %g0, [arg2]ASI_DC_TAG ;\ 1260Sstevel@tonic-gate membar #Sync ;\ 1270Sstevel@tonic-gate5: \ 1280Sstevel@tonic-gate cmp %g0, arg2 ;\ 1290Sstevel@tonic-gate bne,pt %icc, 4b /* branch if not done */ ;\ 1300Sstevel@tonic-gate sub arg2, tmp1, arg2 ;\ 1310Sstevel@tonic-gate1: 1320Sstevel@tonic-gate 1337393SDonghai.Qiao@Sun.COM/* 1347393SDonghai.Qiao@Sun.COM * macro that flushes the entire dcache color 1357393SDonghai.Qiao@Sun.COM * dcache size = 64K, one way 16K 136*10724SEthindra.Ramamurthy@Sun.COM * 137*10724SEthindra.Ramamurthy@Sun.COM * In: 138*10724SEthindra.Ramamurthy@Sun.COM * arg = virtual color register (not clobbered) 139*10724SEthindra.Ramamurthy@Sun.COM * way = way#, can either be a constant or a register (not clobbered) 140*10724SEthindra.Ramamurthy@Sun.COM * tmp1, tmp2, tmp3 = scratch registers 141*10724SEthindra.Ramamurthy@Sun.COM * 1427393SDonghai.Qiao@Sun.COM */ 1437393SDonghai.Qiao@Sun.COM#define DCACHE_FLUSHCOLOR(arg, way, tmp1, tmp2, tmp3) \ 1447393SDonghai.Qiao@Sun.COM ldxa [%g0]ASI_DCU, tmp1; \ 1457393SDonghai.Qiao@Sun.COM btst DCU_DC, tmp1; /* is dcache enabled? */ \ 1467393SDonghai.Qiao@Sun.COM bz,pn %icc, 1f; \ 1477393SDonghai.Qiao@Sun.COM ASM_LD(tmp1, dcache_linesize) \ 1487393SDonghai.Qiao@Sun.COM /* \ 1497393SDonghai.Qiao@Sun.COM * arg = virtual color \ 1507393SDonghai.Qiao@Sun.COM * tmp1 = cache line size \ 1517393SDonghai.Qiao@Sun.COM */ \ 152*10724SEthindra.Ramamurthy@Sun.COM sllx arg, MMU_PAGESHIFT, tmp2; /* color to dcache page */ \ 1537393SDonghai.Qiao@Sun.COM mov way, tmp3; \ 154*10724SEthindra.Ramamurthy@Sun.COM sllx tmp3, 14, tmp3; /* One way 16K */ \ 155*10724SEthindra.Ramamurthy@Sun.COM or tmp2, tmp3, tmp3; \ 156*10724SEthindra.Ramamurthy@Sun.COM set MMU_PAGESIZE, tmp2; \ 157*10724SEthindra.Ramamurthy@Sun.COM /* \ 158*10724SEthindra.Ramamurthy@Sun.COM * tmp2 = page size \ 159*10724SEthindra.Ramamurthy@Sun.COM * tmp3 = cached page in dcache \ 160*10724SEthindra.Ramamurthy@Sun.COM */ \ 1617393SDonghai.Qiao@Sun.COM sub tmp2, tmp1, tmp2; \ 1627393SDonghai.Qiao@Sun.COM2: \ 163*10724SEthindra.Ramamurthy@Sun.COM stxa %g0, [tmp3 + tmp2]ASI_DC_TAG; \ 1647393SDonghai.Qiao@Sun.COM membar #Sync; \ 1657393SDonghai.Qiao@Sun.COM cmp %g0, tmp2; \ 1667393SDonghai.Qiao@Sun.COM bne,pt %icc, 2b; \ 167*10724SEthindra.Ramamurthy@Sun.COM sub tmp2, tmp1, tmp2; \ 1687393SDonghai.Qiao@Sun.COM1: 1690Sstevel@tonic-gate 1700Sstevel@tonic-gate/* END CSTYLED */ 1710Sstevel@tonic-gate 1720Sstevel@tonic-gate#endif /* !lint */ 1730Sstevel@tonic-gate 1740Sstevel@tonic-gate/* 1750Sstevel@tonic-gate * Cheetah MMU and Cache operations. 1760Sstevel@tonic-gate */ 1770Sstevel@tonic-gate 1780Sstevel@tonic-gate#if defined(lint) 1790Sstevel@tonic-gate 1800Sstevel@tonic-gate/* ARGSUSED */ 1810Sstevel@tonic-gatevoid 1822241Shuahvtag_flushpage(caddr_t vaddr, uint64_t sfmmup) 1830Sstevel@tonic-gate{} 1840Sstevel@tonic-gate 1850Sstevel@tonic-gate#else /* lint */ 1860Sstevel@tonic-gate 1870Sstevel@tonic-gate ENTRY_NP(vtag_flushpage) 1880Sstevel@tonic-gate /* 1890Sstevel@tonic-gate * flush page from the tlb 1900Sstevel@tonic-gate * 1910Sstevel@tonic-gate * %o0 = vaddr 1922241Shuah * %o1 = sfmmup 1930Sstevel@tonic-gate */ 1940Sstevel@tonic-gate rdpr %pstate, %o5 1950Sstevel@tonic-gate#ifdef DEBUG 1962241Shuah PANIC_IF_INTR_DISABLED_PSTR(%o5, u3_di_label0, %g1) 1970Sstevel@tonic-gate#endif /* DEBUG */ 1980Sstevel@tonic-gate /* 1990Sstevel@tonic-gate * disable ints 2000Sstevel@tonic-gate */ 2010Sstevel@tonic-gate andn %o5, PSTATE_IE, %o4 2020Sstevel@tonic-gate wrpr %o4, 0, %pstate 2030Sstevel@tonic-gate 2040Sstevel@tonic-gate /* 2050Sstevel@tonic-gate * Then, blow out the tlb 2060Sstevel@tonic-gate * Interrupts are disabled to prevent the primary ctx register 2070Sstevel@tonic-gate * from changing underneath us. 2080Sstevel@tonic-gate */ 2092241Shuah sethi %hi(ksfmmup), %o3 2102241Shuah ldx [%o3 + %lo(ksfmmup)], %o3 2112241Shuah cmp %o3, %o1 2122241Shuah bne,pt %xcc, 1f ! if not kernel as, go to 1 2132241Shuah sethi %hi(FLUSH_ADDR), %o3 2140Sstevel@tonic-gate /* 2152241Shuah * For Kernel demaps use primary. type = page implicitly 2160Sstevel@tonic-gate */ 2170Sstevel@tonic-gate stxa %g0, [%o0]ASI_DTLB_DEMAP /* dmmu flush for KCONTEXT */ 2180Sstevel@tonic-gate stxa %g0, [%o0]ASI_ITLB_DEMAP /* immu flush for KCONTEXT */ 2190Sstevel@tonic-gate flush %o3 2202241Shuah retl 2212241Shuah wrpr %g0, %o5, %pstate /* enable interrupts */ 2220Sstevel@tonic-gate1: 2230Sstevel@tonic-gate /* 2240Sstevel@tonic-gate * User demap. We need to set the primary context properly. 2250Sstevel@tonic-gate * Secondary context cannot be used for Cheetah IMMU. 2260Sstevel@tonic-gate * %o0 = vaddr 2272241Shuah * %o1 = sfmmup 2280Sstevel@tonic-gate * %o3 = FLUSH_ADDR 2290Sstevel@tonic-gate */ 2302241Shuah SFMMU_CPU_CNUM(%o1, %g1, %g2) ! %g1 = sfmmu cnum on this CPU 2312241Shuah 2322241Shuah ldub [%o1 + SFMMU_CEXT], %o4 ! %o4 = sfmmup->sfmmu_cext 2330Sstevel@tonic-gate sll %o4, CTXREG_EXT_SHIFT, %o4 2345584Sjimand or %g1, %o4, %g1 ! %g1 = primary pgsz | cnum 2352241Shuah 2360Sstevel@tonic-gate wrpr %g0, 1, %tl 2370Sstevel@tonic-gate set MMU_PCONTEXT, %o4 2380Sstevel@tonic-gate or DEMAP_PRIMARY | DEMAP_PAGE_TYPE, %o0, %o0 2392241Shuah ldxa [%o4]ASI_DMMU, %o2 ! %o2 = save old ctxnum 2405584Sjimand srlx %o2, CTXREG_NEXT_SHIFT, %o1 ! need to preserve nucleus pgsz 2415584Sjimand sllx %o1, CTXREG_NEXT_SHIFT, %o1 ! %o1 = nucleus pgsz 2425584Sjimand or %g1, %o1, %g1 ! %g1 = nucleus pgsz | primary pgsz | cnum 2432241Shuah stxa %g1, [%o4]ASI_DMMU ! wr new ctxum 2442241Shuah 2450Sstevel@tonic-gate stxa %g0, [%o0]ASI_DTLB_DEMAP 2460Sstevel@tonic-gate stxa %g0, [%o0]ASI_ITLB_DEMAP 2470Sstevel@tonic-gate stxa %o2, [%o4]ASI_DMMU /* restore old ctxnum */ 2480Sstevel@tonic-gate flush %o3 2490Sstevel@tonic-gate wrpr %g0, 0, %tl 2502241Shuah 2510Sstevel@tonic-gate retl 2520Sstevel@tonic-gate wrpr %g0, %o5, %pstate /* enable interrupts */ 2530Sstevel@tonic-gate SET_SIZE(vtag_flushpage) 2540Sstevel@tonic-gate 2550Sstevel@tonic-gate#endif /* lint */ 2560Sstevel@tonic-gate 2570Sstevel@tonic-gate#if defined(lint) 2580Sstevel@tonic-gate 2590Sstevel@tonic-gatevoid 2600Sstevel@tonic-gatevtag_flushall(void) 2610Sstevel@tonic-gate{} 2620Sstevel@tonic-gate 2630Sstevel@tonic-gate#else /* lint */ 2640Sstevel@tonic-gate 2650Sstevel@tonic-gate ENTRY_NP2(vtag_flushall, demap_all) 2660Sstevel@tonic-gate /* 2670Sstevel@tonic-gate * flush the tlb 2680Sstevel@tonic-gate */ 2690Sstevel@tonic-gate sethi %hi(FLUSH_ADDR), %o3 2700Sstevel@tonic-gate set DEMAP_ALL_TYPE, %g1 2710Sstevel@tonic-gate stxa %g0, [%g1]ASI_DTLB_DEMAP 2720Sstevel@tonic-gate stxa %g0, [%g1]ASI_ITLB_DEMAP 2730Sstevel@tonic-gate flush %o3 2740Sstevel@tonic-gate retl 2750Sstevel@tonic-gate nop 2760Sstevel@tonic-gate SET_SIZE(demap_all) 2770Sstevel@tonic-gate SET_SIZE(vtag_flushall) 2780Sstevel@tonic-gate 2790Sstevel@tonic-gate#endif /* lint */ 2800Sstevel@tonic-gate 2810Sstevel@tonic-gate 2820Sstevel@tonic-gate#if defined(lint) 2830Sstevel@tonic-gate 2840Sstevel@tonic-gate/* ARGSUSED */ 2850Sstevel@tonic-gatevoid 2862241Shuahvtag_flushpage_tl1(uint64_t vaddr, uint64_t sfmmup) 2870Sstevel@tonic-gate{} 2880Sstevel@tonic-gate 2890Sstevel@tonic-gate#else /* lint */ 2900Sstevel@tonic-gate 2910Sstevel@tonic-gate ENTRY_NP(vtag_flushpage_tl1) 2920Sstevel@tonic-gate /* 2930Sstevel@tonic-gate * x-trap to flush page from tlb and tsb 2940Sstevel@tonic-gate * 2950Sstevel@tonic-gate * %g1 = vaddr, zero-extended on 32-bit kernel 2962241Shuah * %g2 = sfmmup 2970Sstevel@tonic-gate * 2980Sstevel@tonic-gate * assumes TSBE_TAG = 0 2990Sstevel@tonic-gate */ 3000Sstevel@tonic-gate srln %g1, MMU_PAGESHIFT, %g1 3012241Shuah 3022241Shuah sethi %hi(ksfmmup), %g3 3032241Shuah ldx [%g3 + %lo(ksfmmup)], %g3 3042241Shuah cmp %g3, %g2 3052241Shuah bne,pt %xcc, 1f ! if not kernel as, go to 1 3060Sstevel@tonic-gate slln %g1, MMU_PAGESHIFT, %g1 /* g1 = vaddr */ 3070Sstevel@tonic-gate 3080Sstevel@tonic-gate /* We need to demap in the kernel context */ 3090Sstevel@tonic-gate or DEMAP_NUCLEUS | DEMAP_PAGE_TYPE, %g1, %g1 3100Sstevel@tonic-gate stxa %g0, [%g1]ASI_DTLB_DEMAP 3110Sstevel@tonic-gate stxa %g0, [%g1]ASI_ITLB_DEMAP 3120Sstevel@tonic-gate retry 3130Sstevel@tonic-gate1: 3140Sstevel@tonic-gate /* We need to demap in a user context */ 3150Sstevel@tonic-gate or DEMAP_PRIMARY | DEMAP_PAGE_TYPE, %g1, %g1 3162241Shuah 3172241Shuah SFMMU_CPU_CNUM(%g2, %g6, %g3) ! %g6 = sfmmu cnum on this CPU 3182241Shuah 3192241Shuah ldub [%g2 + SFMMU_CEXT], %g4 ! %g4 = sfmmup->cext 3200Sstevel@tonic-gate sll %g4, CTXREG_EXT_SHIFT, %g4 3212241Shuah or %g6, %g4, %g6 ! %g6 = pgsz | cnum 3222241Shuah 3230Sstevel@tonic-gate set MMU_PCONTEXT, %g4 3240Sstevel@tonic-gate ldxa [%g4]ASI_DMMU, %g5 /* rd old ctxnum */ 3255584Sjimand srlx %g5, CTXREG_NEXT_SHIFT, %g2 /* %g2 = nucleus pgsz */ 3265584Sjimand sllx %g2, CTXREG_NEXT_SHIFT, %g2 /* preserve nucleus pgsz */ 3275584Sjimand or %g6, %g2, %g6 /* %g6 = nucleus pgsz | primary pgsz | cnum */ 3282241Shuah stxa %g6, [%g4]ASI_DMMU /* wr new ctxum */ 3290Sstevel@tonic-gate stxa %g0, [%g1]ASI_DTLB_DEMAP 3300Sstevel@tonic-gate stxa %g0, [%g1]ASI_ITLB_DEMAP 3310Sstevel@tonic-gate stxa %g5, [%g4]ASI_DMMU /* restore old ctxnum */ 3320Sstevel@tonic-gate retry 3330Sstevel@tonic-gate SET_SIZE(vtag_flushpage_tl1) 3340Sstevel@tonic-gate 3350Sstevel@tonic-gate#endif /* lint */ 3360Sstevel@tonic-gate 3370Sstevel@tonic-gate 3380Sstevel@tonic-gate#if defined(lint) 3390Sstevel@tonic-gate 3400Sstevel@tonic-gate/* ARGSUSED */ 3410Sstevel@tonic-gatevoid 3422241Shuahvtag_flush_pgcnt_tl1(uint64_t vaddr, uint64_t sfmmup_pgcnt) 3430Sstevel@tonic-gate{} 3440Sstevel@tonic-gate 3450Sstevel@tonic-gate#else /* lint */ 3460Sstevel@tonic-gate 3470Sstevel@tonic-gate ENTRY_NP(vtag_flush_pgcnt_tl1) 3480Sstevel@tonic-gate /* 3490Sstevel@tonic-gate * x-trap to flush pgcnt MMU_PAGESIZE pages from tlb 3500Sstevel@tonic-gate * 3510Sstevel@tonic-gate * %g1 = vaddr, zero-extended on 32-bit kernel 3522241Shuah * %g2 = <sfmmup58|pgcnt6>, (pgcnt - 1) is pass'ed in via pgcnt6 bits. 3530Sstevel@tonic-gate * 3540Sstevel@tonic-gate * NOTE: this handler relies on the fact that no 3550Sstevel@tonic-gate * interrupts or traps can occur during the loop 3560Sstevel@tonic-gate * issuing the TLB_DEMAP operations. It is assumed 3570Sstevel@tonic-gate * that interrupts are disabled and this code is 3580Sstevel@tonic-gate * fetching from the kernel locked text address. 3590Sstevel@tonic-gate * 3600Sstevel@tonic-gate * assumes TSBE_TAG = 0 3610Sstevel@tonic-gate */ 3622241Shuah set SFMMU_PGCNT_MASK, %g4 3632241Shuah and %g4, %g2, %g3 /* g3 = pgcnt - 1 */ 3642241Shuah add %g3, 1, %g3 /* g3 = pgcnt */ 3652241Shuah 3662241Shuah andn %g2, SFMMU_PGCNT_MASK, %g2 /* g2 = sfmmup */ 3670Sstevel@tonic-gate srln %g1, MMU_PAGESHIFT, %g1 3682241Shuah 3692241Shuah sethi %hi(ksfmmup), %g4 3702241Shuah ldx [%g4 + %lo(ksfmmup)], %g4 3712241Shuah cmp %g4, %g2 3722241Shuah bne,pn %xcc, 1f /* if not kernel as, go to 1 */ 3730Sstevel@tonic-gate slln %g1, MMU_PAGESHIFT, %g1 /* g1 = vaddr */ 3740Sstevel@tonic-gate 3750Sstevel@tonic-gate /* We need to demap in the kernel context */ 3760Sstevel@tonic-gate or DEMAP_NUCLEUS | DEMAP_PAGE_TYPE, %g1, %g1 3770Sstevel@tonic-gate set MMU_PAGESIZE, %g2 /* g2 = pgsize */ 3782241Shuah sethi %hi(FLUSH_ADDR), %g5 3790Sstevel@tonic-gate4: 3800Sstevel@tonic-gate stxa %g0, [%g1]ASI_DTLB_DEMAP 3810Sstevel@tonic-gate stxa %g0, [%g1]ASI_ITLB_DEMAP 3822241Shuah flush %g5 ! flush required by immu 3832241Shuah 3840Sstevel@tonic-gate deccc %g3 /* decr pgcnt */ 3850Sstevel@tonic-gate bnz,pt %icc,4b 3860Sstevel@tonic-gate add %g1, %g2, %g1 /* next page */ 3870Sstevel@tonic-gate retry 3880Sstevel@tonic-gate1: 3892241Shuah /* 3902241Shuah * We need to demap in a user context 3912241Shuah * 3922241Shuah * g2 = sfmmup 3932241Shuah * g3 = pgcnt 3942241Shuah */ 3952241Shuah SFMMU_CPU_CNUM(%g2, %g5, %g6) ! %g5 = sfmmu cnum on this CPU 3962241Shuah 3972241Shuah or DEMAP_PRIMARY | DEMAP_PAGE_TYPE, %g1, %g1 3982241Shuah 3992241Shuah ldub [%g2 + SFMMU_CEXT], %g4 ! %g4 = sfmmup->cext 4000Sstevel@tonic-gate sll %g4, CTXREG_EXT_SHIFT, %g4 4012241Shuah or %g5, %g4, %g5 4022241Shuah 4030Sstevel@tonic-gate set MMU_PCONTEXT, %g4 4042241Shuah ldxa [%g4]ASI_DMMU, %g6 /* rd old ctxnum */ 4055584Sjimand srlx %g6, CTXREG_NEXT_SHIFT, %g2 /* %g2 = nucleus pgsz */ 4065584Sjimand sllx %g2, CTXREG_NEXT_SHIFT, %g2 /* preserve nucleus pgsz */ 4075584Sjimand or %g5, %g2, %g5 /* %g5 = nucleus pgsz | primary pgsz | cnum */ 4082241Shuah stxa %g5, [%g4]ASI_DMMU /* wr new ctxum */ 4090Sstevel@tonic-gate 4100Sstevel@tonic-gate set MMU_PAGESIZE, %g2 /* g2 = pgsize */ 4112241Shuah sethi %hi(FLUSH_ADDR), %g5 4120Sstevel@tonic-gate3: 4130Sstevel@tonic-gate stxa %g0, [%g1]ASI_DTLB_DEMAP 4140Sstevel@tonic-gate stxa %g0, [%g1]ASI_ITLB_DEMAP 4152241Shuah flush %g5 ! flush required by immu 4162241Shuah 4170Sstevel@tonic-gate deccc %g3 /* decr pgcnt */ 4180Sstevel@tonic-gate bnz,pt %icc,3b 4190Sstevel@tonic-gate add %g1, %g2, %g1 /* next page */ 4200Sstevel@tonic-gate 4212241Shuah stxa %g6, [%g4]ASI_DMMU /* restore old ctxnum */ 4220Sstevel@tonic-gate retry 4230Sstevel@tonic-gate SET_SIZE(vtag_flush_pgcnt_tl1) 4240Sstevel@tonic-gate 4250Sstevel@tonic-gate#endif /* lint */ 4260Sstevel@tonic-gate 4270Sstevel@tonic-gate#if defined(lint) 4280Sstevel@tonic-gate 4290Sstevel@tonic-gate/*ARGSUSED*/ 4300Sstevel@tonic-gatevoid 4310Sstevel@tonic-gatevtag_flushall_tl1(uint64_t dummy1, uint64_t dummy2) 4320Sstevel@tonic-gate{} 4330Sstevel@tonic-gate 4340Sstevel@tonic-gate#else /* lint */ 4350Sstevel@tonic-gate 4360Sstevel@tonic-gate ENTRY_NP(vtag_flushall_tl1) 4370Sstevel@tonic-gate /* 4380Sstevel@tonic-gate * x-trap to flush tlb 4390Sstevel@tonic-gate */ 4400Sstevel@tonic-gate set DEMAP_ALL_TYPE, %g4 4410Sstevel@tonic-gate stxa %g0, [%g4]ASI_DTLB_DEMAP 4420Sstevel@tonic-gate stxa %g0, [%g4]ASI_ITLB_DEMAP 4430Sstevel@tonic-gate retry 4440Sstevel@tonic-gate SET_SIZE(vtag_flushall_tl1) 4450Sstevel@tonic-gate 4460Sstevel@tonic-gate#endif /* lint */ 4470Sstevel@tonic-gate 4480Sstevel@tonic-gate 4490Sstevel@tonic-gate#if defined(lint) 4500Sstevel@tonic-gate 4510Sstevel@tonic-gate/* ARGSUSED */ 4520Sstevel@tonic-gatevoid 4530Sstevel@tonic-gatevac_flushpage(pfn_t pfnum, int vcolor) 4540Sstevel@tonic-gate{} 4550Sstevel@tonic-gate 4560Sstevel@tonic-gate#else /* lint */ 4570Sstevel@tonic-gate 4580Sstevel@tonic-gate/* 4590Sstevel@tonic-gate * vac_flushpage(pfnum, color) 4600Sstevel@tonic-gate * Flush 1 8k page of the D-$ with physical page = pfnum 4610Sstevel@tonic-gate * Algorithm: 4620Sstevel@tonic-gate * The cheetah dcache is a 64k psuedo 4 way accaociative cache. 4630Sstevel@tonic-gate * It is virtual indexed, physically tagged cache. 4640Sstevel@tonic-gate */ 4650Sstevel@tonic-gate .seg ".data" 4660Sstevel@tonic-gate .align 8 4670Sstevel@tonic-gate .global dflush_type 4680Sstevel@tonic-gatedflush_type: 4690Sstevel@tonic-gate .word FLUSHPAGE_TYPE 4700Sstevel@tonic-gate 4710Sstevel@tonic-gate ENTRY(vac_flushpage) 4720Sstevel@tonic-gate /* 4730Sstevel@tonic-gate * flush page from the d$ 4740Sstevel@tonic-gate * 4750Sstevel@tonic-gate * %o0 = pfnum, %o1 = color 4760Sstevel@tonic-gate */ 4770Sstevel@tonic-gate DCACHE_FLUSHPAGE(%o0, %o1, %o2, %o3, %o4) 4780Sstevel@tonic-gate retl 4790Sstevel@tonic-gate nop 4800Sstevel@tonic-gate SET_SIZE(vac_flushpage) 4810Sstevel@tonic-gate 4820Sstevel@tonic-gate#endif /* lint */ 4830Sstevel@tonic-gate 4840Sstevel@tonic-gate 4850Sstevel@tonic-gate#if defined(lint) 4860Sstevel@tonic-gate 4870Sstevel@tonic-gate/* ARGSUSED */ 4880Sstevel@tonic-gatevoid 4890Sstevel@tonic-gatevac_flushpage_tl1(uint64_t pfnum, uint64_t vcolor) 4900Sstevel@tonic-gate{} 4910Sstevel@tonic-gate 4920Sstevel@tonic-gate#else /* lint */ 4930Sstevel@tonic-gate 4940Sstevel@tonic-gate ENTRY_NP(vac_flushpage_tl1) 4950Sstevel@tonic-gate /* 4960Sstevel@tonic-gate * x-trap to flush page from the d$ 4970Sstevel@tonic-gate * 4980Sstevel@tonic-gate * %g1 = pfnum, %g2 = color 4990Sstevel@tonic-gate */ 5000Sstevel@tonic-gate DCACHE_FLUSHPAGE(%g1, %g2, %g3, %g4, %g5) 5010Sstevel@tonic-gate retry 5020Sstevel@tonic-gate SET_SIZE(vac_flushpage_tl1) 5030Sstevel@tonic-gate 5040Sstevel@tonic-gate#endif /* lint */ 5050Sstevel@tonic-gate 5060Sstevel@tonic-gate 5070Sstevel@tonic-gate#if defined(lint) 5080Sstevel@tonic-gate 5090Sstevel@tonic-gate/* ARGSUSED */ 5100Sstevel@tonic-gatevoid 5110Sstevel@tonic-gatevac_flushcolor(int vcolor, pfn_t pfnum) 5120Sstevel@tonic-gate{} 5130Sstevel@tonic-gate 5140Sstevel@tonic-gate#else /* lint */ 5150Sstevel@tonic-gate 5160Sstevel@tonic-gate ENTRY(vac_flushcolor) 5170Sstevel@tonic-gate /* 5187393SDonghai.Qiao@Sun.COM * %o0 = vcolor 5190Sstevel@tonic-gate */ 5207393SDonghai.Qiao@Sun.COM DCACHE_FLUSHCOLOR(%o0, 0, %o1, %o2, %o3) 5217393SDonghai.Qiao@Sun.COM DCACHE_FLUSHCOLOR(%o0, 1, %o1, %o2, %o3) 5227393SDonghai.Qiao@Sun.COM DCACHE_FLUSHCOLOR(%o0, 2, %o1, %o2, %o3) 5237393SDonghai.Qiao@Sun.COM DCACHE_FLUSHCOLOR(%o0, 3, %o1, %o2, %o3) 5240Sstevel@tonic-gate retl 5250Sstevel@tonic-gate nop 5260Sstevel@tonic-gate SET_SIZE(vac_flushcolor) 5270Sstevel@tonic-gate 5280Sstevel@tonic-gate#endif /* lint */ 5290Sstevel@tonic-gate 5300Sstevel@tonic-gate 5310Sstevel@tonic-gate#if defined(lint) 5320Sstevel@tonic-gate 5330Sstevel@tonic-gate/* ARGSUSED */ 5340Sstevel@tonic-gatevoid 5350Sstevel@tonic-gatevac_flushcolor_tl1(uint64_t vcolor, uint64_t pfnum) 5360Sstevel@tonic-gate{} 5370Sstevel@tonic-gate 5380Sstevel@tonic-gate#else /* lint */ 5390Sstevel@tonic-gate 5400Sstevel@tonic-gate ENTRY(vac_flushcolor_tl1) 5410Sstevel@tonic-gate /* 5420Sstevel@tonic-gate * %g1 = vcolor 5430Sstevel@tonic-gate */ 5447393SDonghai.Qiao@Sun.COM DCACHE_FLUSHCOLOR(%g1, 0, %g2, %g3, %g4) 5457393SDonghai.Qiao@Sun.COM DCACHE_FLUSHCOLOR(%g1, 1, %g2, %g3, %g4) 5467393SDonghai.Qiao@Sun.COM DCACHE_FLUSHCOLOR(%g1, 2, %g2, %g3, %g4) 5477393SDonghai.Qiao@Sun.COM DCACHE_FLUSHCOLOR(%g1, 3, %g2, %g3, %g4) 5480Sstevel@tonic-gate retry 5490Sstevel@tonic-gate SET_SIZE(vac_flushcolor_tl1) 5500Sstevel@tonic-gate 5510Sstevel@tonic-gate#endif /* lint */ 5520Sstevel@tonic-gate 5530Sstevel@tonic-gate#if defined(lint) 5540Sstevel@tonic-gate 5550Sstevel@tonic-gateint 5560Sstevel@tonic-gateidsr_busy(void) 5570Sstevel@tonic-gate{ 5580Sstevel@tonic-gate return (0); 5590Sstevel@tonic-gate} 5600Sstevel@tonic-gate 5610Sstevel@tonic-gate#else /* lint */ 5620Sstevel@tonic-gate 5630Sstevel@tonic-gate/* 5640Sstevel@tonic-gate * Determine whether or not the IDSR is busy. 5650Sstevel@tonic-gate * Entry: no arguments 5660Sstevel@tonic-gate * Returns: 1 if busy, 0 otherwise 5670Sstevel@tonic-gate */ 5680Sstevel@tonic-gate ENTRY(idsr_busy) 5690Sstevel@tonic-gate ldxa [%g0]ASI_INTR_DISPATCH_STATUS, %g1 5700Sstevel@tonic-gate clr %o0 5710Sstevel@tonic-gate btst IDSR_BUSY, %g1 5720Sstevel@tonic-gate bz,a,pt %xcc, 1f 5730Sstevel@tonic-gate mov 1, %o0 5740Sstevel@tonic-gate1: 5750Sstevel@tonic-gate retl 5760Sstevel@tonic-gate nop 5770Sstevel@tonic-gate SET_SIZE(idsr_busy) 5780Sstevel@tonic-gate 5790Sstevel@tonic-gate#endif /* lint */ 5800Sstevel@tonic-gate 5810Sstevel@tonic-gate#if defined(lint) 5820Sstevel@tonic-gate 5830Sstevel@tonic-gate/* ARGSUSED */ 5840Sstevel@tonic-gatevoid 5850Sstevel@tonic-gateinit_mondo(xcfunc_t *func, uint64_t arg1, uint64_t arg2) 5860Sstevel@tonic-gate{} 5870Sstevel@tonic-gate 5880Sstevel@tonic-gate/* ARGSUSED */ 5890Sstevel@tonic-gatevoid 5900Sstevel@tonic-gateinit_mondo_nocheck(xcfunc_t *func, uint64_t arg1, uint64_t arg2) 5910Sstevel@tonic-gate{} 5920Sstevel@tonic-gate 5930Sstevel@tonic-gate#else /* lint */ 5940Sstevel@tonic-gate 5950Sstevel@tonic-gate .global _dispatch_status_busy 5960Sstevel@tonic-gate_dispatch_status_busy: 5970Sstevel@tonic-gate .asciz "ASI_INTR_DISPATCH_STATUS error: busy" 5980Sstevel@tonic-gate .align 4 5990Sstevel@tonic-gate 6000Sstevel@tonic-gate/* 6010Sstevel@tonic-gate * Setup interrupt dispatch data registers 6020Sstevel@tonic-gate * Entry: 6030Sstevel@tonic-gate * %o0 - function or inumber to call 6040Sstevel@tonic-gate * %o1, %o2 - arguments (2 uint64_t's) 6050Sstevel@tonic-gate */ 6060Sstevel@tonic-gate .seg "text" 6070Sstevel@tonic-gate 6080Sstevel@tonic-gate ENTRY(init_mondo) 6090Sstevel@tonic-gate#ifdef DEBUG 6100Sstevel@tonic-gate ! 6110Sstevel@tonic-gate ! IDSR should not be busy at the moment 6120Sstevel@tonic-gate ! 6130Sstevel@tonic-gate ldxa [%g0]ASI_INTR_DISPATCH_STATUS, %g1 6140Sstevel@tonic-gate btst IDSR_BUSY, %g1 6150Sstevel@tonic-gate bz,pt %xcc, 1f 6160Sstevel@tonic-gate nop 6170Sstevel@tonic-gate sethi %hi(_dispatch_status_busy), %o0 6180Sstevel@tonic-gate call panic 6190Sstevel@tonic-gate or %o0, %lo(_dispatch_status_busy), %o0 6200Sstevel@tonic-gate#endif /* DEBUG */ 6210Sstevel@tonic-gate 6220Sstevel@tonic-gate ALTENTRY(init_mondo_nocheck) 6230Sstevel@tonic-gate ! 6240Sstevel@tonic-gate ! interrupt vector dispatch data reg 0 6250Sstevel@tonic-gate ! 6260Sstevel@tonic-gate1: 6270Sstevel@tonic-gate mov IDDR_0, %g1 6280Sstevel@tonic-gate mov IDDR_1, %g2 6290Sstevel@tonic-gate mov IDDR_2, %g3 6300Sstevel@tonic-gate stxa %o0, [%g1]ASI_INTR_DISPATCH 6310Sstevel@tonic-gate 6320Sstevel@tonic-gate ! 6330Sstevel@tonic-gate ! interrupt vector dispatch data reg 1 6340Sstevel@tonic-gate ! 6350Sstevel@tonic-gate stxa %o1, [%g2]ASI_INTR_DISPATCH 6360Sstevel@tonic-gate 6370Sstevel@tonic-gate ! 6380Sstevel@tonic-gate ! interrupt vector dispatch data reg 2 6390Sstevel@tonic-gate ! 6400Sstevel@tonic-gate stxa %o2, [%g3]ASI_INTR_DISPATCH 6410Sstevel@tonic-gate 6420Sstevel@tonic-gate membar #Sync 6430Sstevel@tonic-gate retl 6440Sstevel@tonic-gate nop 6450Sstevel@tonic-gate SET_SIZE(init_mondo_nocheck) 6460Sstevel@tonic-gate SET_SIZE(init_mondo) 6470Sstevel@tonic-gate 6480Sstevel@tonic-gate#endif /* lint */ 6490Sstevel@tonic-gate 6500Sstevel@tonic-gate 6510Sstevel@tonic-gate#if !(defined(JALAPENO) || defined(SERRANO)) 6520Sstevel@tonic-gate 6530Sstevel@tonic-gate#if defined(lint) 6540Sstevel@tonic-gate 6550Sstevel@tonic-gate/* ARGSUSED */ 6560Sstevel@tonic-gatevoid 6570Sstevel@tonic-gateshipit(int upaid, int bn) 6580Sstevel@tonic-gate{ return; } 6590Sstevel@tonic-gate 6600Sstevel@tonic-gate#else /* lint */ 6610Sstevel@tonic-gate 6620Sstevel@tonic-gate/* 6630Sstevel@tonic-gate * Ship mondo to aid using busy/nack pair bn 6640Sstevel@tonic-gate */ 6650Sstevel@tonic-gate ENTRY_NP(shipit) 6660Sstevel@tonic-gate sll %o0, IDCR_PID_SHIFT, %g1 ! IDCR<18:14> = agent id 6670Sstevel@tonic-gate sll %o1, IDCR_BN_SHIFT, %g2 ! IDCR<28:24> = b/n pair 6680Sstevel@tonic-gate or %g1, IDCR_OFFSET, %g1 ! IDCR<13:0> = 0x70 6690Sstevel@tonic-gate or %g1, %g2, %g1 6700Sstevel@tonic-gate stxa %g0, [%g1]ASI_INTR_DISPATCH ! interrupt vector dispatch 6710Sstevel@tonic-gate membar #Sync 6720Sstevel@tonic-gate retl 6730Sstevel@tonic-gate nop 6740Sstevel@tonic-gate SET_SIZE(shipit) 6750Sstevel@tonic-gate 6760Sstevel@tonic-gate#endif /* lint */ 6770Sstevel@tonic-gate 6780Sstevel@tonic-gate#endif /* !(JALAPENO || SERRANO) */ 6790Sstevel@tonic-gate 6800Sstevel@tonic-gate 6810Sstevel@tonic-gate#if defined(lint) 6820Sstevel@tonic-gate 6830Sstevel@tonic-gate/* ARGSUSED */ 6840Sstevel@tonic-gatevoid 6850Sstevel@tonic-gateflush_instr_mem(caddr_t vaddr, size_t len) 6860Sstevel@tonic-gate{} 6870Sstevel@tonic-gate 6880Sstevel@tonic-gate#else /* lint */ 6890Sstevel@tonic-gate 6900Sstevel@tonic-gate/* 6910Sstevel@tonic-gate * flush_instr_mem: 6920Sstevel@tonic-gate * Flush 1 page of the I-$ starting at vaddr 6930Sstevel@tonic-gate * %o0 vaddr 6940Sstevel@tonic-gate * %o1 bytes to be flushed 6950Sstevel@tonic-gate * UltraSPARC-III maintains consistency of the on-chip Instruction Cache with 6960Sstevel@tonic-gate * the stores from all processors so that a FLUSH instruction is only needed 6970Sstevel@tonic-gate * to ensure pipeline is consistent. This means a single flush is sufficient at 6980Sstevel@tonic-gate * the end of a sequence of stores that updates the instruction stream to 6990Sstevel@tonic-gate * ensure correct operation. 7000Sstevel@tonic-gate */ 7010Sstevel@tonic-gate 7020Sstevel@tonic-gate ENTRY(flush_instr_mem) 7033517Smp204432 flush %o0 ! address irrelevant 7040Sstevel@tonic-gate retl 7050Sstevel@tonic-gate nop 7060Sstevel@tonic-gate SET_SIZE(flush_instr_mem) 7070Sstevel@tonic-gate 7080Sstevel@tonic-gate#endif /* lint */ 7090Sstevel@tonic-gate 7100Sstevel@tonic-gate 7110Sstevel@tonic-gate#if defined(CPU_IMP_ECACHE_ASSOC) 7120Sstevel@tonic-gate 7130Sstevel@tonic-gate#if defined(lint) 7140Sstevel@tonic-gate 7150Sstevel@tonic-gate/* ARGSUSED */ 7160Sstevel@tonic-gateuint64_t 7170Sstevel@tonic-gateget_ecache_ctrl(void) 7180Sstevel@tonic-gate{ return (0); } 7190Sstevel@tonic-gate 7200Sstevel@tonic-gate#else /* lint */ 7210Sstevel@tonic-gate 7220Sstevel@tonic-gate ENTRY(get_ecache_ctrl) 7230Sstevel@tonic-gate GET_CPU_IMPL(%o0) 7240Sstevel@tonic-gate cmp %o0, JAGUAR_IMPL 7250Sstevel@tonic-gate ! 7260Sstevel@tonic-gate ! Putting an ASI access in the delay slot may 7270Sstevel@tonic-gate ! cause it to be accessed, even when annulled. 7280Sstevel@tonic-gate ! 7290Sstevel@tonic-gate bne 1f 7300Sstevel@tonic-gate nop 7310Sstevel@tonic-gate ldxa [%g0]ASI_EC_CFG_TIMING, %o0 ! read Jaguar shared E$ ctrl reg 7320Sstevel@tonic-gate b 2f 7330Sstevel@tonic-gate nop 7340Sstevel@tonic-gate1: 7350Sstevel@tonic-gate ldxa [%g0]ASI_EC_CTRL, %o0 ! read Ch/Ch+ E$ control reg 7360Sstevel@tonic-gate2: 7370Sstevel@tonic-gate retl 7380Sstevel@tonic-gate nop 7390Sstevel@tonic-gate SET_SIZE(get_ecache_ctrl) 7400Sstevel@tonic-gate 7410Sstevel@tonic-gate#endif /* lint */ 7420Sstevel@tonic-gate 7430Sstevel@tonic-gate#endif /* CPU_IMP_ECACHE_ASSOC */ 7440Sstevel@tonic-gate 7450Sstevel@tonic-gate 7460Sstevel@tonic-gate#if !(defined(JALAPENO) || defined(SERRANO)) 7470Sstevel@tonic-gate 7480Sstevel@tonic-gate/* 7490Sstevel@tonic-gate * flush_ecache: 7500Sstevel@tonic-gate * %o0 - 64 bit physical address 7510Sstevel@tonic-gate * %o1 - ecache size 7520Sstevel@tonic-gate * %o2 - ecache linesize 7530Sstevel@tonic-gate */ 7540Sstevel@tonic-gate#if defined(lint) 7550Sstevel@tonic-gate 7560Sstevel@tonic-gate/*ARGSUSED*/ 7570Sstevel@tonic-gatevoid 7580Sstevel@tonic-gateflush_ecache(uint64_t physaddr, size_t ecache_size, size_t ecache_linesize) 7590Sstevel@tonic-gate{} 7600Sstevel@tonic-gate 7610Sstevel@tonic-gate#else /* !lint */ 7620Sstevel@tonic-gate 7630Sstevel@tonic-gate ENTRY(flush_ecache) 7640Sstevel@tonic-gate 7650Sstevel@tonic-gate /* 7660Sstevel@tonic-gate * For certain CPU implementations, we have to flush the L2 cache 7670Sstevel@tonic-gate * before flushing the ecache. 7680Sstevel@tonic-gate */ 7690Sstevel@tonic-gate PN_L2_FLUSHALL(%g3, %g4, %g5) 7700Sstevel@tonic-gate 7710Sstevel@tonic-gate /* 7720Sstevel@tonic-gate * Flush the entire Ecache using displacement flush. 7730Sstevel@tonic-gate */ 7740Sstevel@tonic-gate ECACHE_FLUSHALL(%o1, %o2, %o0, %o4) 7750Sstevel@tonic-gate 7760Sstevel@tonic-gate retl 7770Sstevel@tonic-gate nop 7780Sstevel@tonic-gate SET_SIZE(flush_ecache) 7790Sstevel@tonic-gate 7800Sstevel@tonic-gate#endif /* lint */ 7810Sstevel@tonic-gate 7820Sstevel@tonic-gate#endif /* !(JALAPENO || SERRANO) */ 7830Sstevel@tonic-gate 7840Sstevel@tonic-gate 7850Sstevel@tonic-gate#if defined(lint) 7860Sstevel@tonic-gate 7870Sstevel@tonic-gatevoid 7880Sstevel@tonic-gateflush_dcache(void) 7890Sstevel@tonic-gate{} 7900Sstevel@tonic-gate 7910Sstevel@tonic-gate#else /* lint */ 7920Sstevel@tonic-gate 7930Sstevel@tonic-gate ENTRY(flush_dcache) 7940Sstevel@tonic-gate ASM_LD(%o0, dcache_size) 7950Sstevel@tonic-gate ASM_LD(%o1, dcache_linesize) 7960Sstevel@tonic-gate CH_DCACHE_FLUSHALL(%o0, %o1, %o2) 7970Sstevel@tonic-gate retl 7980Sstevel@tonic-gate nop 7990Sstevel@tonic-gate SET_SIZE(flush_dcache) 8000Sstevel@tonic-gate 8010Sstevel@tonic-gate#endif /* lint */ 8020Sstevel@tonic-gate 8030Sstevel@tonic-gate 8040Sstevel@tonic-gate#if defined(lint) 8050Sstevel@tonic-gate 8060Sstevel@tonic-gatevoid 8070Sstevel@tonic-gateflush_icache(void) 8080Sstevel@tonic-gate{} 8090Sstevel@tonic-gate 8100Sstevel@tonic-gate#else /* lint */ 8110Sstevel@tonic-gate 8120Sstevel@tonic-gate ENTRY(flush_icache) 8130Sstevel@tonic-gate GET_CPU_PRIVATE_PTR(%g0, %o0, %o2, flush_icache_1); 8140Sstevel@tonic-gate ld [%o0 + CHPR_ICACHE_LINESIZE], %o1 8150Sstevel@tonic-gate ba,pt %icc, 2f 8160Sstevel@tonic-gate ld [%o0 + CHPR_ICACHE_SIZE], %o0 8170Sstevel@tonic-gateflush_icache_1: 8180Sstevel@tonic-gate ASM_LD(%o0, icache_size) 8190Sstevel@tonic-gate ASM_LD(%o1, icache_linesize) 8200Sstevel@tonic-gate2: 8210Sstevel@tonic-gate CH_ICACHE_FLUSHALL(%o0, %o1, %o2, %o4) 8220Sstevel@tonic-gate retl 8230Sstevel@tonic-gate nop 8240Sstevel@tonic-gate SET_SIZE(flush_icache) 8250Sstevel@tonic-gate 8260Sstevel@tonic-gate#endif /* lint */ 8270Sstevel@tonic-gate 8280Sstevel@tonic-gate#if defined(lint) 8290Sstevel@tonic-gate 8300Sstevel@tonic-gate/*ARGSUSED*/ 8310Sstevel@tonic-gatevoid 8320Sstevel@tonic-gatekdi_flush_idcache(int dcache_size, int dcache_lsize, int icache_size, 8330Sstevel@tonic-gate int icache_lsize) 8340Sstevel@tonic-gate{ 8350Sstevel@tonic-gate} 8360Sstevel@tonic-gate 8370Sstevel@tonic-gate#else /* lint */ 8380Sstevel@tonic-gate 8390Sstevel@tonic-gate ENTRY(kdi_flush_idcache) 8400Sstevel@tonic-gate CH_DCACHE_FLUSHALL(%o0, %o1, %g1) 8410Sstevel@tonic-gate CH_ICACHE_FLUSHALL(%o2, %o3, %g1, %g2) 8420Sstevel@tonic-gate membar #Sync 8430Sstevel@tonic-gate retl 8440Sstevel@tonic-gate nop 8450Sstevel@tonic-gate SET_SIZE(kdi_flush_idcache) 8460Sstevel@tonic-gate 8470Sstevel@tonic-gate#endif /* lint */ 8480Sstevel@tonic-gate 8490Sstevel@tonic-gate#if defined(lint) 8500Sstevel@tonic-gate 8510Sstevel@tonic-gatevoid 8520Sstevel@tonic-gateflush_pcache(void) 8530Sstevel@tonic-gate{} 8540Sstevel@tonic-gate 8550Sstevel@tonic-gate#else /* lint */ 8560Sstevel@tonic-gate 8570Sstevel@tonic-gate ENTRY(flush_pcache) 8580Sstevel@tonic-gate PCACHE_FLUSHALL(%o0, %o1, %o2) 8590Sstevel@tonic-gate retl 8600Sstevel@tonic-gate nop 8610Sstevel@tonic-gate SET_SIZE(flush_pcache) 8620Sstevel@tonic-gate 8630Sstevel@tonic-gate#endif /* lint */ 8640Sstevel@tonic-gate 8650Sstevel@tonic-gate 8660Sstevel@tonic-gate#if defined(CPU_IMP_L1_CACHE_PARITY) 8670Sstevel@tonic-gate 8680Sstevel@tonic-gate#if defined(lint) 8690Sstevel@tonic-gate 8700Sstevel@tonic-gate/* ARGSUSED */ 8710Sstevel@tonic-gatevoid 8720Sstevel@tonic-gateget_dcache_dtag(uint32_t dcache_idx, uint64_t *data) 8730Sstevel@tonic-gate{} 8740Sstevel@tonic-gate 8750Sstevel@tonic-gate#else /* lint */ 8760Sstevel@tonic-gate 8770Sstevel@tonic-gate/* 8780Sstevel@tonic-gate * Get dcache data and tag. The Dcache data is a pointer to a ch_dc_data_t 8790Sstevel@tonic-gate * structure (see cheetahregs.h): 8800Sstevel@tonic-gate * The Dcache *should* be turned off when this code is executed. 8810Sstevel@tonic-gate */ 8820Sstevel@tonic-gate .align 128 8830Sstevel@tonic-gate ENTRY(get_dcache_dtag) 8840Sstevel@tonic-gate rdpr %pstate, %o5 8850Sstevel@tonic-gate andn %o5, PSTATE_IE | PSTATE_AM, %o3 8860Sstevel@tonic-gate wrpr %g0, %o3, %pstate 8870Sstevel@tonic-gate b 1f 8880Sstevel@tonic-gate stx %o0, [%o1 + CH_DC_IDX] 8890Sstevel@tonic-gate 8900Sstevel@tonic-gate .align 128 8910Sstevel@tonic-gate1: 8920Sstevel@tonic-gate ldxa [%o0]ASI_DC_TAG, %o2 8930Sstevel@tonic-gate stx %o2, [%o1 + CH_DC_TAG] 8940Sstevel@tonic-gate membar #Sync 8950Sstevel@tonic-gate ldxa [%o0]ASI_DC_UTAG, %o2 8960Sstevel@tonic-gate membar #Sync 8970Sstevel@tonic-gate stx %o2, [%o1 + CH_DC_UTAG] 8980Sstevel@tonic-gate ldxa [%o0]ASI_DC_SNP_TAG, %o2 8990Sstevel@tonic-gate stx %o2, [%o1 + CH_DC_SNTAG] 9000Sstevel@tonic-gate add %o1, CH_DC_DATA, %o1 9010Sstevel@tonic-gate clr %o3 9020Sstevel@tonic-gate2: 9030Sstevel@tonic-gate membar #Sync ! required before ASI_DC_DATA 9040Sstevel@tonic-gate ldxa [%o0 + %o3]ASI_DC_DATA, %o2 9050Sstevel@tonic-gate membar #Sync ! required after ASI_DC_DATA 9060Sstevel@tonic-gate stx %o2, [%o1 + %o3] 9070Sstevel@tonic-gate cmp %o3, CH_DC_DATA_REG_SIZE - 8 9080Sstevel@tonic-gate blt 2b 9090Sstevel@tonic-gate add %o3, 8, %o3 9100Sstevel@tonic-gate 9110Sstevel@tonic-gate /* 9120Sstevel@tonic-gate * Unlike other CPUs in the family, D$ data parity bits for Panther 9130Sstevel@tonic-gate * do not reside in the microtag. Instead, we have to read them 9140Sstevel@tonic-gate * using the DC_data_parity bit of ASI_DCACHE_DATA. Also, instead 9150Sstevel@tonic-gate * of just having 8 parity bits to protect all 32 bytes of data 9160Sstevel@tonic-gate * per line, we now have 32 bits of parity. 9170Sstevel@tonic-gate */ 9180Sstevel@tonic-gate GET_CPU_IMPL(%o3) 9190Sstevel@tonic-gate cmp %o3, PANTHER_IMPL 9200Sstevel@tonic-gate bne 4f 9210Sstevel@tonic-gate clr %o3 9220Sstevel@tonic-gate 9230Sstevel@tonic-gate /* 9240Sstevel@tonic-gate * move our pointer to the next field where we store parity bits 9250Sstevel@tonic-gate * and add the offset of the last parity byte since we will be 9260Sstevel@tonic-gate * storing all 4 parity bytes within one 64 bit field like this: 9270Sstevel@tonic-gate * 9280Sstevel@tonic-gate * +------+------------+------------+------------+------------+ 9290Sstevel@tonic-gate * | - | DC_parity | DC_parity | DC_parity | DC_parity | 9300Sstevel@tonic-gate * | - | for word 3 | for word 2 | for word 1 | for word 0 | 9310Sstevel@tonic-gate * +------+------------+------------+------------+------------+ 9320Sstevel@tonic-gate * 63:32 31:24 23:16 15:8 7:0 9330Sstevel@tonic-gate */ 9340Sstevel@tonic-gate add %o1, CH_DC_PN_DATA_PARITY - CH_DC_DATA + 7, %o1 9350Sstevel@tonic-gate 9360Sstevel@tonic-gate /* add the DC_data_parity bit into our working index */ 9370Sstevel@tonic-gate mov 1, %o2 9380Sstevel@tonic-gate sll %o2, PN_DC_DATA_PARITY_BIT_SHIFT, %o2 9390Sstevel@tonic-gate or %o0, %o2, %o0 9400Sstevel@tonic-gate3: 9410Sstevel@tonic-gate membar #Sync ! required before ASI_DC_DATA 9420Sstevel@tonic-gate ldxa [%o0 + %o3]ASI_DC_DATA, %o2 9430Sstevel@tonic-gate membar #Sync ! required after ASI_DC_DATA 9440Sstevel@tonic-gate stb %o2, [%o1] 9450Sstevel@tonic-gate dec %o1 9460Sstevel@tonic-gate cmp %o3, CH_DC_DATA_REG_SIZE - 8 9470Sstevel@tonic-gate blt 3b 9480Sstevel@tonic-gate add %o3, 8, %o3 9490Sstevel@tonic-gate4: 9500Sstevel@tonic-gate retl 9510Sstevel@tonic-gate wrpr %g0, %o5, %pstate 9520Sstevel@tonic-gate SET_SIZE(get_dcache_dtag) 9530Sstevel@tonic-gate 9540Sstevel@tonic-gate#endif /* lint */ 9550Sstevel@tonic-gate 9560Sstevel@tonic-gate 9570Sstevel@tonic-gate#if defined(lint) 9580Sstevel@tonic-gate 9590Sstevel@tonic-gate/* ARGSUSED */ 9600Sstevel@tonic-gatevoid 9610Sstevel@tonic-gateget_icache_dtag(uint32_t ecache_idx, uint64_t *data) 9620Sstevel@tonic-gate{} 9630Sstevel@tonic-gate 9640Sstevel@tonic-gate#else /* lint */ 9650Sstevel@tonic-gate 9660Sstevel@tonic-gate/* 9670Sstevel@tonic-gate * Get icache data and tag. The data argument is a pointer to a ch_ic_data_t 9680Sstevel@tonic-gate * structure (see cheetahregs.h): 9690Sstevel@tonic-gate * The Icache *Must* be turned off when this function is called. 9700Sstevel@tonic-gate * This is because diagnostic accesses to the Icache interfere with cache 9710Sstevel@tonic-gate * consistency. 9720Sstevel@tonic-gate */ 9730Sstevel@tonic-gate .align 128 9740Sstevel@tonic-gate ENTRY(get_icache_dtag) 9750Sstevel@tonic-gate rdpr %pstate, %o5 9760Sstevel@tonic-gate andn %o5, PSTATE_IE | PSTATE_AM, %o3 9770Sstevel@tonic-gate wrpr %g0, %o3, %pstate 9780Sstevel@tonic-gate 9790Sstevel@tonic-gate stx %o0, [%o1 + CH_IC_IDX] 9800Sstevel@tonic-gate ldxa [%o0]ASI_IC_TAG, %o2 9810Sstevel@tonic-gate stx %o2, [%o1 + CH_IC_PATAG] 9820Sstevel@tonic-gate add %o0, CH_ICTAG_UTAG, %o0 9830Sstevel@tonic-gate ldxa [%o0]ASI_IC_TAG, %o2 9840Sstevel@tonic-gate add %o0, (CH_ICTAG_UPPER - CH_ICTAG_UTAG), %o0 9850Sstevel@tonic-gate stx %o2, [%o1 + CH_IC_UTAG] 9860Sstevel@tonic-gate ldxa [%o0]ASI_IC_TAG, %o2 9870Sstevel@tonic-gate add %o0, (CH_ICTAG_LOWER - CH_ICTAG_UPPER), %o0 9880Sstevel@tonic-gate stx %o2, [%o1 + CH_IC_UPPER] 9890Sstevel@tonic-gate ldxa [%o0]ASI_IC_TAG, %o2 9900Sstevel@tonic-gate andn %o0, CH_ICTAG_TMASK, %o0 9910Sstevel@tonic-gate stx %o2, [%o1 + CH_IC_LOWER] 9920Sstevel@tonic-gate ldxa [%o0]ASI_IC_SNP_TAG, %o2 9930Sstevel@tonic-gate stx %o2, [%o1 + CH_IC_SNTAG] 9940Sstevel@tonic-gate add %o1, CH_IC_DATA, %o1 9950Sstevel@tonic-gate clr %o3 9960Sstevel@tonic-gate2: 9970Sstevel@tonic-gate ldxa [%o0 + %o3]ASI_IC_DATA, %o2 9980Sstevel@tonic-gate stx %o2, [%o1 + %o3] 9990Sstevel@tonic-gate cmp %o3, PN_IC_DATA_REG_SIZE - 8 10000Sstevel@tonic-gate blt 2b 10010Sstevel@tonic-gate add %o3, 8, %o3 10020Sstevel@tonic-gate 10030Sstevel@tonic-gate retl 10040Sstevel@tonic-gate wrpr %g0, %o5, %pstate 10050Sstevel@tonic-gate SET_SIZE(get_icache_dtag) 10060Sstevel@tonic-gate 10070Sstevel@tonic-gate#endif /* lint */ 10080Sstevel@tonic-gate 10090Sstevel@tonic-gate#if defined(lint) 10100Sstevel@tonic-gate 10110Sstevel@tonic-gate/* ARGSUSED */ 10120Sstevel@tonic-gatevoid 10130Sstevel@tonic-gateget_pcache_dtag(uint32_t pcache_idx, uint64_t *data) 10140Sstevel@tonic-gate{} 10150Sstevel@tonic-gate 10160Sstevel@tonic-gate#else /* lint */ 10170Sstevel@tonic-gate 10180Sstevel@tonic-gate/* 10190Sstevel@tonic-gate * Get pcache data and tags. 10200Sstevel@tonic-gate * inputs: 10210Sstevel@tonic-gate * pcache_idx - fully constructed VA for for accessing P$ diagnostic 10220Sstevel@tonic-gate * registers. Contains PC_way and PC_addr shifted into 10230Sstevel@tonic-gate * the correct bit positions. See the PRM for more details. 10240Sstevel@tonic-gate * data - pointer to a ch_pc_data_t 10250Sstevel@tonic-gate * structure (see cheetahregs.h): 10260Sstevel@tonic-gate */ 10270Sstevel@tonic-gate .align 128 10280Sstevel@tonic-gate ENTRY(get_pcache_dtag) 10290Sstevel@tonic-gate rdpr %pstate, %o5 10300Sstevel@tonic-gate andn %o5, PSTATE_IE | PSTATE_AM, %o3 10310Sstevel@tonic-gate wrpr %g0, %o3, %pstate 10320Sstevel@tonic-gate 10330Sstevel@tonic-gate stx %o0, [%o1 + CH_PC_IDX] 10340Sstevel@tonic-gate ldxa [%o0]ASI_PC_STATUS_DATA, %o2 10350Sstevel@tonic-gate stx %o2, [%o1 + CH_PC_STATUS] 10360Sstevel@tonic-gate ldxa [%o0]ASI_PC_TAG, %o2 10370Sstevel@tonic-gate stx %o2, [%o1 + CH_PC_TAG] 10380Sstevel@tonic-gate ldxa [%o0]ASI_PC_SNP_TAG, %o2 10390Sstevel@tonic-gate stx %o2, [%o1 + CH_PC_SNTAG] 10400Sstevel@tonic-gate add %o1, CH_PC_DATA, %o1 10410Sstevel@tonic-gate clr %o3 10420Sstevel@tonic-gate2: 10430Sstevel@tonic-gate ldxa [%o0 + %o3]ASI_PC_DATA, %o2 10440Sstevel@tonic-gate stx %o2, [%o1 + %o3] 10450Sstevel@tonic-gate cmp %o3, CH_PC_DATA_REG_SIZE - 8 10460Sstevel@tonic-gate blt 2b 10470Sstevel@tonic-gate add %o3, 8, %o3 10480Sstevel@tonic-gate 10490Sstevel@tonic-gate retl 10500Sstevel@tonic-gate wrpr %g0, %o5, %pstate 10510Sstevel@tonic-gate SET_SIZE(get_pcache_dtag) 10520Sstevel@tonic-gate 10530Sstevel@tonic-gate#endif /* lint */ 10540Sstevel@tonic-gate 10550Sstevel@tonic-gate#endif /* CPU_IMP_L1_CACHE_PARITY */ 10560Sstevel@tonic-gate 10570Sstevel@tonic-gate#if defined(lint) 10580Sstevel@tonic-gate 10590Sstevel@tonic-gate/* ARGSUSED */ 10600Sstevel@tonic-gatevoid 10610Sstevel@tonic-gateset_dcu(uint64_t dcu) 10620Sstevel@tonic-gate{} 10630Sstevel@tonic-gate 10640Sstevel@tonic-gate#else /* lint */ 10650Sstevel@tonic-gate 10660Sstevel@tonic-gate/* 10670Sstevel@tonic-gate * re-enable the i$, d$, w$, and p$ according to bootup cache state. 10680Sstevel@tonic-gate * Turn on WE, HPE, SPE, PE, IC, and DC bits defined as DCU_CACHE. 10690Sstevel@tonic-gate * %o0 - 64 bit constant 10700Sstevel@tonic-gate */ 10710Sstevel@tonic-gate ENTRY(set_dcu) 10720Sstevel@tonic-gate stxa %o0, [%g0]ASI_DCU ! Store to DCU 10730Sstevel@tonic-gate flush %g0 /* flush required after changing the IC bit */ 10740Sstevel@tonic-gate retl 10750Sstevel@tonic-gate nop 10760Sstevel@tonic-gate SET_SIZE(set_dcu) 10770Sstevel@tonic-gate 10780Sstevel@tonic-gate#endif /* lint */ 10790Sstevel@tonic-gate 10800Sstevel@tonic-gate 10810Sstevel@tonic-gate#if defined(lint) 10820Sstevel@tonic-gate 10830Sstevel@tonic-gateuint64_t 10840Sstevel@tonic-gateget_dcu(void) 10850Sstevel@tonic-gate{ 10860Sstevel@tonic-gate return ((uint64_t)0); 10870Sstevel@tonic-gate} 10880Sstevel@tonic-gate 10890Sstevel@tonic-gate#else /* lint */ 10900Sstevel@tonic-gate 10910Sstevel@tonic-gate/* 10920Sstevel@tonic-gate * Return DCU register. 10930Sstevel@tonic-gate */ 10940Sstevel@tonic-gate ENTRY(get_dcu) 10950Sstevel@tonic-gate ldxa [%g0]ASI_DCU, %o0 /* DCU control register */ 10960Sstevel@tonic-gate retl 10970Sstevel@tonic-gate nop 10980Sstevel@tonic-gate SET_SIZE(get_dcu) 10990Sstevel@tonic-gate 11000Sstevel@tonic-gate#endif /* lint */ 11010Sstevel@tonic-gate 11020Sstevel@tonic-gate/* 11030Sstevel@tonic-gate * Cheetah/Cheetah+ level 15 interrupt handler trap table entry. 11040Sstevel@tonic-gate * 11050Sstevel@tonic-gate * This handler is used to check for softints generated by error trap 11060Sstevel@tonic-gate * handlers to report errors. On Cheetah, this mechanism is used by the 11070Sstevel@tonic-gate * Fast ECC at TL>0 error trap handler and, on Cheetah+, by both the Fast 11080Sstevel@tonic-gate * ECC at TL>0 error and the I$/D$ parity error at TL>0 trap handlers. 11090Sstevel@tonic-gate * NB: Must be 8 instructions or less to fit in trap table and code must 11100Sstevel@tonic-gate * be relocatable. 11110Sstevel@tonic-gate */ 11120Sstevel@tonic-gate#if defined(lint) 11130Sstevel@tonic-gate 11140Sstevel@tonic-gatevoid 11150Sstevel@tonic-gatech_pil15_interrupt_instr(void) 11160Sstevel@tonic-gate{} 11170Sstevel@tonic-gate 11180Sstevel@tonic-gate#else /* lint */ 11190Sstevel@tonic-gate 11200Sstevel@tonic-gate ENTRY_NP(ch_pil15_interrupt_instr) 11210Sstevel@tonic-gate ASM_JMP(%g1, ch_pil15_interrupt) 11220Sstevel@tonic-gate SET_SIZE(ch_pil15_interrupt_instr) 11230Sstevel@tonic-gate 11240Sstevel@tonic-gate#endif 11250Sstevel@tonic-gate 11260Sstevel@tonic-gate 11270Sstevel@tonic-gate#if defined(lint) 11280Sstevel@tonic-gate 11290Sstevel@tonic-gatevoid 11300Sstevel@tonic-gatech_pil15_interrupt(void) 11310Sstevel@tonic-gate{} 11320Sstevel@tonic-gate 11330Sstevel@tonic-gate#else /* lint */ 11340Sstevel@tonic-gate 11350Sstevel@tonic-gate ENTRY_NP(ch_pil15_interrupt) 11360Sstevel@tonic-gate 11370Sstevel@tonic-gate /* 11380Sstevel@tonic-gate * Since pil_interrupt is hacked to assume that every level 15 11390Sstevel@tonic-gate * interrupt is generated by the CPU to indicate a performance 11400Sstevel@tonic-gate * counter overflow this gets ugly. Before calling pil_interrupt 11410Sstevel@tonic-gate * the Error at TL>0 pending status is inspected. If it is 11420Sstevel@tonic-gate * non-zero, then an error has occurred and it is handled. 11430Sstevel@tonic-gate * Otherwise control is transfered to pil_interrupt. Note that if 11440Sstevel@tonic-gate * an error is detected pil_interrupt will not be called and 11450Sstevel@tonic-gate * overflow interrupts may be lost causing erroneous performance 11460Sstevel@tonic-gate * measurements. However, error-recovery will have a detrimental 11470Sstevel@tonic-gate * effect on performance anyway. 11480Sstevel@tonic-gate */ 11490Sstevel@tonic-gate CPU_INDEX(%g1, %g4) 11500Sstevel@tonic-gate set ch_err_tl1_pending, %g4 11510Sstevel@tonic-gate ldub [%g1 + %g4], %g2 11520Sstevel@tonic-gate brz %g2, 1f 11530Sstevel@tonic-gate nop 11540Sstevel@tonic-gate 11550Sstevel@tonic-gate /* 11560Sstevel@tonic-gate * We have a pending TL>0 error, clear the TL>0 pending status. 11570Sstevel@tonic-gate */ 11580Sstevel@tonic-gate stb %g0, [%g1 + %g4] 11590Sstevel@tonic-gate 11600Sstevel@tonic-gate /* 11610Sstevel@tonic-gate * Clear the softint. 11620Sstevel@tonic-gate */ 11630Sstevel@tonic-gate mov 1, %g5 11640Sstevel@tonic-gate sll %g5, PIL_15, %g5 11650Sstevel@tonic-gate wr %g5, CLEAR_SOFTINT 11660Sstevel@tonic-gate 11670Sstevel@tonic-gate /* 11680Sstevel@tonic-gate * For Cheetah*, call cpu_tl1_error via systrap at PIL 15 11690Sstevel@tonic-gate * to process the Fast ECC/Cache Parity at TL>0 error. Clear 11700Sstevel@tonic-gate * panic flag (%g2). 11710Sstevel@tonic-gate */ 11720Sstevel@tonic-gate set cpu_tl1_error, %g1 11730Sstevel@tonic-gate clr %g2 11740Sstevel@tonic-gate ba sys_trap 11750Sstevel@tonic-gate mov PIL_15, %g4 11760Sstevel@tonic-gate 11770Sstevel@tonic-gate1: 11780Sstevel@tonic-gate /* 11790Sstevel@tonic-gate * The logout is invalid. 11800Sstevel@tonic-gate * 11810Sstevel@tonic-gate * Call the default interrupt handler. 11820Sstevel@tonic-gate */ 11830Sstevel@tonic-gate sethi %hi(pil_interrupt), %g1 11840Sstevel@tonic-gate jmp %g1 + %lo(pil_interrupt) 11850Sstevel@tonic-gate mov PIL_15, %g4 11860Sstevel@tonic-gate 11870Sstevel@tonic-gate SET_SIZE(ch_pil15_interrupt) 11880Sstevel@tonic-gate#endif 11890Sstevel@tonic-gate 11900Sstevel@tonic-gate 11910Sstevel@tonic-gate/* 11920Sstevel@tonic-gate * Error Handling 11930Sstevel@tonic-gate * 11940Sstevel@tonic-gate * Cheetah provides error checking for all memory access paths between 11950Sstevel@tonic-gate * the CPU, External Cache, Cheetah Data Switch and system bus. Error 11960Sstevel@tonic-gate * information is logged in the AFSR, (also AFSR_EXT for Panther) and 11970Sstevel@tonic-gate * AFAR and one of the following traps is generated (provided that it 11980Sstevel@tonic-gate * is enabled in External Cache Error Enable Register) to handle that 11990Sstevel@tonic-gate * error: 12000Sstevel@tonic-gate * 1. trap 0x70: Precise trap 12010Sstevel@tonic-gate * tt0_fecc for errors at trap level(TL)>=0 12020Sstevel@tonic-gate * 2. trap 0x0A and 0x32: Deferred trap 12030Sstevel@tonic-gate * async_err for errors at TL>=0 12040Sstevel@tonic-gate * 3. trap 0x63: Disrupting trap 12050Sstevel@tonic-gate * ce_err for errors at TL=0 12060Sstevel@tonic-gate * (Note that trap 0x63 cannot happen at trap level > 0) 12070Sstevel@tonic-gate * 12080Sstevel@tonic-gate * Trap level one handlers panic the system except for the fast ecc 12090Sstevel@tonic-gate * error handler which tries to recover from certain errors. 12100Sstevel@tonic-gate */ 12110Sstevel@tonic-gate 12120Sstevel@tonic-gate/* 12130Sstevel@tonic-gate * FAST ECC TRAP STRATEGY: 12140Sstevel@tonic-gate * 12150Sstevel@tonic-gate * Software must handle single and multi bit errors which occur due to data 12160Sstevel@tonic-gate * or instruction cache reads from the external cache. A single or multi bit 12170Sstevel@tonic-gate * error occuring in one of these situations results in a precise trap. 12180Sstevel@tonic-gate * 12190Sstevel@tonic-gate * The basic flow of this trap handler is as follows: 12200Sstevel@tonic-gate * 12210Sstevel@tonic-gate * 1) Record the state and then turn off the Dcache and Icache. The Dcache 12220Sstevel@tonic-gate * is disabled because bad data could have been installed. The Icache is 12230Sstevel@tonic-gate * turned off because we want to capture the Icache line related to the 12240Sstevel@tonic-gate * AFAR. 12250Sstevel@tonic-gate * 2) Disable trapping on CEEN/NCCEN errors during TL=0 processing. 12260Sstevel@tonic-gate * 3) Park sibling core if caches are shared (to avoid race condition while 12270Sstevel@tonic-gate * accessing shared resources such as L3 data staging register during 12280Sstevel@tonic-gate * CPU logout. 12290Sstevel@tonic-gate * 4) Read the AFAR and AFSR. 12300Sstevel@tonic-gate * 5) If CPU logout structure is not being used, then: 12310Sstevel@tonic-gate * 6) Clear all errors from the AFSR. 12320Sstevel@tonic-gate * 7) Capture Ecache, Dcache and Icache lines in "CPU log out" structure. 12330Sstevel@tonic-gate * 8) Flush Ecache then Flush Dcache and Icache and restore to previous 12340Sstevel@tonic-gate * state. 12350Sstevel@tonic-gate * 9) Unpark sibling core if we parked it earlier. 12360Sstevel@tonic-gate * 10) call cpu_fast_ecc_error via systrap at PIL 14 unless we're already 12370Sstevel@tonic-gate * running at PIL 15. 12380Sstevel@tonic-gate * 6) Otherwise, if CPU logout structure is being used: 12390Sstevel@tonic-gate * 7) Incriment the "logout busy count". 12400Sstevel@tonic-gate * 8) Flush Ecache then Flush Dcache and Icache and restore to previous 12410Sstevel@tonic-gate * state. 12420Sstevel@tonic-gate * 9) Unpark sibling core if we parked it earlier. 12430Sstevel@tonic-gate * 10) Issue a retry since the other CPU error logging code will end up 12440Sstevel@tonic-gate * finding this error bit and logging information about it later. 12450Sstevel@tonic-gate * 7) Alternatively (to 5 and 6 above), if the cpu_private struct is not 12460Sstevel@tonic-gate * yet initialized such that we can't even check the logout struct, then 12470Sstevel@tonic-gate * we place the clo_flags data into %g2 (sys_trap->have_win arg #1) and 12480Sstevel@tonic-gate * call cpu_fast_ecc_error via systrap. The clo_flags parameter is used 1249815Sdilpreet * to determine information such as TL, TT, CEEN and NCEEN settings, etc 1250815Sdilpreet * in the high level trap handler since we don't have access to detailed 1251815Sdilpreet * logout information in cases where the cpu_private struct is not yet 12520Sstevel@tonic-gate * initialized. 12530Sstevel@tonic-gate * 12540Sstevel@tonic-gate * We flush the E$ and D$ here on TL=1 code to prevent getting nested 12550Sstevel@tonic-gate * Fast ECC traps in the TL=0 code. If we get a Fast ECC event here in 12560Sstevel@tonic-gate * the TL=1 code, we will go to the Fast ECC at TL>0 handler which, 12570Sstevel@tonic-gate * since it is uses different code/data from this handler, has a better 12580Sstevel@tonic-gate * chance of fixing things up than simply recursing through this code 12590Sstevel@tonic-gate * again (this would probably cause an eventual kernel stack overflow). 12600Sstevel@tonic-gate * If the Fast ECC at TL>0 handler encounters a Fast ECC error before it 12610Sstevel@tonic-gate * can flush the E$ (or the error is a stuck-at bit), we will recurse in 12620Sstevel@tonic-gate * the Fast ECC at TL>0 handler and eventually Red Mode. 12630Sstevel@tonic-gate * 12640Sstevel@tonic-gate * Note that for Cheetah (and only Cheetah), we use alias addresses for 12650Sstevel@tonic-gate * flushing rather than ASI accesses (which don't exist on Cheetah). 12660Sstevel@tonic-gate * Should we encounter a Fast ECC error within this handler on Cheetah, 12670Sstevel@tonic-gate * there's a good chance it's within the ecache_flushaddr buffer (since 12680Sstevel@tonic-gate * it's the largest piece of memory we touch in the handler and it is 12690Sstevel@tonic-gate * usually kernel text/data). For that reason the Fast ECC at TL>0 12700Sstevel@tonic-gate * handler for Cheetah uses an alternate buffer: ecache_tl1_flushaddr. 12710Sstevel@tonic-gate */ 12720Sstevel@tonic-gate 12730Sstevel@tonic-gate/* 12740Sstevel@tonic-gate * Cheetah ecc-protected E$ trap (Trap 70) at TL=0 12750Sstevel@tonic-gate * tt0_fecc is replaced by fecc_err_instr in cpu_init_trap of the various 12760Sstevel@tonic-gate * architecture-specific files. 12770Sstevel@tonic-gate * NB: Must be 8 instructions or less to fit in trap table and code must 12780Sstevel@tonic-gate * be relocatable. 12790Sstevel@tonic-gate */ 12800Sstevel@tonic-gate 12810Sstevel@tonic-gate#if defined(lint) 12820Sstevel@tonic-gate 12830Sstevel@tonic-gatevoid 12840Sstevel@tonic-gatefecc_err_instr(void) 12850Sstevel@tonic-gate{} 12860Sstevel@tonic-gate 12870Sstevel@tonic-gate#else /* lint */ 12880Sstevel@tonic-gate 12890Sstevel@tonic-gate ENTRY_NP(fecc_err_instr) 12900Sstevel@tonic-gate membar #Sync ! Cheetah requires membar #Sync 12910Sstevel@tonic-gate 12920Sstevel@tonic-gate /* 12930Sstevel@tonic-gate * Save current DCU state. Turn off the Dcache and Icache. 12940Sstevel@tonic-gate */ 12950Sstevel@tonic-gate ldxa [%g0]ASI_DCU, %g1 ! save DCU in %g1 12960Sstevel@tonic-gate andn %g1, DCU_DC + DCU_IC, %g4 12970Sstevel@tonic-gate stxa %g4, [%g0]ASI_DCU 12980Sstevel@tonic-gate flush %g0 /* flush required after changing the IC bit */ 12990Sstevel@tonic-gate 13000Sstevel@tonic-gate ASM_JMP(%g4, fast_ecc_err) 13010Sstevel@tonic-gate SET_SIZE(fecc_err_instr) 13020Sstevel@tonic-gate 13030Sstevel@tonic-gate#endif /* lint */ 13040Sstevel@tonic-gate 13050Sstevel@tonic-gate 13060Sstevel@tonic-gate#if !(defined(JALAPENO) || defined(SERRANO)) 13070Sstevel@tonic-gate 13080Sstevel@tonic-gate#if defined(lint) 13090Sstevel@tonic-gate 13100Sstevel@tonic-gatevoid 13110Sstevel@tonic-gatefast_ecc_err(void) 13120Sstevel@tonic-gate{} 13130Sstevel@tonic-gate 13140Sstevel@tonic-gate#else /* lint */ 13150Sstevel@tonic-gate 13160Sstevel@tonic-gate .section ".text" 13170Sstevel@tonic-gate .align 64 13180Sstevel@tonic-gate ENTRY_NP(fast_ecc_err) 13190Sstevel@tonic-gate 13200Sstevel@tonic-gate /* 13210Sstevel@tonic-gate * Turn off CEEN and NCEEN. 13220Sstevel@tonic-gate */ 13230Sstevel@tonic-gate ldxa [%g0]ASI_ESTATE_ERR, %g3 13240Sstevel@tonic-gate andn %g3, EN_REG_NCEEN + EN_REG_CEEN, %g4 13250Sstevel@tonic-gate stxa %g4, [%g0]ASI_ESTATE_ERR 13260Sstevel@tonic-gate membar #Sync ! membar sync required 13270Sstevel@tonic-gate 13280Sstevel@tonic-gate /* 13290Sstevel@tonic-gate * Check to see whether we need to park our sibling core 13300Sstevel@tonic-gate * before recording diagnostic information from caches 13310Sstevel@tonic-gate * which may be shared by both cores. 13320Sstevel@tonic-gate * We use %g1 to store information about whether or not 13330Sstevel@tonic-gate * we had to park the core (%g1 holds our DCUCR value and 13340Sstevel@tonic-gate * we only use bits from that register which are "reserved" 13350Sstevel@tonic-gate * to keep track of core parking) so that we know whether 13360Sstevel@tonic-gate * or not to unpark later. %g5 and %g4 are scratch registers. 13370Sstevel@tonic-gate */ 13380Sstevel@tonic-gate PARK_SIBLING_CORE(%g1, %g5, %g4) 13390Sstevel@tonic-gate 13400Sstevel@tonic-gate /* 13410Sstevel@tonic-gate * Do the CPU log out capture. 13420Sstevel@tonic-gate * %g3 = "failed?" return value. 13430Sstevel@tonic-gate * %g2 = Input = AFAR. Output the clo_flags info which is passed 13440Sstevel@tonic-gate * into this macro via %g4. Output only valid if cpu_private 13450Sstevel@tonic-gate * struct has not been initialized. 13460Sstevel@tonic-gate * CHPR_FECCTL0_LOGOUT = cpu logout structure offset input 13470Sstevel@tonic-gate * %g4 = Trap information stored in the cpu logout flags field 13480Sstevel@tonic-gate * %g5 = scr1 13490Sstevel@tonic-gate * %g6 = scr2 13500Sstevel@tonic-gate * %g3 = scr3 13510Sstevel@tonic-gate * %g4 = scr4 13520Sstevel@tonic-gate */ 1353815Sdilpreet /* store the CEEN and NCEEN values, TL=0 */ 1354815Sdilpreet and %g3, EN_REG_CEEN + EN_REG_NCEEN, %g4 13550Sstevel@tonic-gate set CHPR_FECCTL0_LOGOUT, %g6 13560Sstevel@tonic-gate DO_CPU_LOGOUT(%g3, %g2, %g6, %g4, %g5, %g6, %g3, %g4) 13570Sstevel@tonic-gate 13580Sstevel@tonic-gate /* 13590Sstevel@tonic-gate * Flush the Ecache (and L2 cache for Panther) to get the error out 13600Sstevel@tonic-gate * of the Ecache. If the UCC or UCU is on a dirty line, then the 13610Sstevel@tonic-gate * following flush will turn that into a WDC or WDU, respectively. 13620Sstevel@tonic-gate */ 13630Sstevel@tonic-gate PN_L2_FLUSHALL(%g4, %g5, %g6) 13640Sstevel@tonic-gate 13650Sstevel@tonic-gate CPU_INDEX(%g4, %g5) 13660Sstevel@tonic-gate mulx %g4, CPU_NODE_SIZE, %g4 13670Sstevel@tonic-gate set cpunodes, %g5 13680Sstevel@tonic-gate add %g4, %g5, %g4 13690Sstevel@tonic-gate ld [%g4 + ECACHE_LINESIZE], %g5 13700Sstevel@tonic-gate ld [%g4 + ECACHE_SIZE], %g4 13710Sstevel@tonic-gate 13720Sstevel@tonic-gate ASM_LDX(%g6, ecache_flushaddr) 13730Sstevel@tonic-gate ECACHE_FLUSHALL(%g4, %g5, %g6, %g7) 13740Sstevel@tonic-gate 13750Sstevel@tonic-gate /* 13760Sstevel@tonic-gate * Flush the Dcache. Since bad data could have been installed in 13770Sstevel@tonic-gate * the Dcache we must flush it before re-enabling it. 13780Sstevel@tonic-gate */ 13790Sstevel@tonic-gate ASM_LD(%g5, dcache_size) 13800Sstevel@tonic-gate ASM_LD(%g6, dcache_linesize) 13810Sstevel@tonic-gate CH_DCACHE_FLUSHALL(%g5, %g6, %g7) 13820Sstevel@tonic-gate 13830Sstevel@tonic-gate /* 13840Sstevel@tonic-gate * Flush the Icache. Since we turned off the Icache to capture the 13850Sstevel@tonic-gate * Icache line it is now stale or corrupted and we must flush it 13860Sstevel@tonic-gate * before re-enabling it. 13870Sstevel@tonic-gate */ 13880Sstevel@tonic-gate GET_CPU_PRIVATE_PTR(%g0, %g5, %g7, fast_ecc_err_5); 13890Sstevel@tonic-gate ld [%g5 + CHPR_ICACHE_LINESIZE], %g6 13900Sstevel@tonic-gate ba,pt %icc, 6f 13910Sstevel@tonic-gate ld [%g5 + CHPR_ICACHE_SIZE], %g5 13920Sstevel@tonic-gatefast_ecc_err_5: 13930Sstevel@tonic-gate ASM_LD(%g5, icache_size) 13940Sstevel@tonic-gate ASM_LD(%g6, icache_linesize) 13950Sstevel@tonic-gate6: 13960Sstevel@tonic-gate CH_ICACHE_FLUSHALL(%g5, %g6, %g7, %g4) 13970Sstevel@tonic-gate 13980Sstevel@tonic-gate /* 13990Sstevel@tonic-gate * check to see whether we parked our sibling core at the start 14000Sstevel@tonic-gate * of this handler. If so, we need to unpark it here. 14010Sstevel@tonic-gate * We use DCUCR reserved bits (stored in %g1) to keep track of 14020Sstevel@tonic-gate * whether or not we need to unpark. %g5 and %g4 are scratch registers. 14030Sstevel@tonic-gate */ 14040Sstevel@tonic-gate UNPARK_SIBLING_CORE(%g1, %g5, %g4) 14050Sstevel@tonic-gate 14060Sstevel@tonic-gate /* 14070Sstevel@tonic-gate * Restore the Dcache and Icache to the previous state. 14080Sstevel@tonic-gate */ 14090Sstevel@tonic-gate stxa %g1, [%g0]ASI_DCU 14100Sstevel@tonic-gate flush %g0 /* flush required after changing the IC bit */ 14110Sstevel@tonic-gate 14120Sstevel@tonic-gate /* 14130Sstevel@tonic-gate * Make sure our CPU logout operation was successful. 14140Sstevel@tonic-gate */ 14150Sstevel@tonic-gate cmp %g3, %g0 14160Sstevel@tonic-gate be 8f 14170Sstevel@tonic-gate nop 14180Sstevel@tonic-gate 14190Sstevel@tonic-gate /* 14200Sstevel@tonic-gate * If the logout structure had been busy, how many times have 14210Sstevel@tonic-gate * we tried to use it and failed (nesting count)? If we have 14220Sstevel@tonic-gate * already recursed a substantial number of times, then we can 14230Sstevel@tonic-gate * assume things are not going to get better by themselves and 14240Sstevel@tonic-gate * so it would be best to panic. 14250Sstevel@tonic-gate */ 14260Sstevel@tonic-gate cmp %g3, CLO_NESTING_MAX 14270Sstevel@tonic-gate blt 7f 14280Sstevel@tonic-gate nop 14290Sstevel@tonic-gate 14300Sstevel@tonic-gate call ptl1_panic 14310Sstevel@tonic-gate mov PTL1_BAD_ECC, %g1 14320Sstevel@tonic-gate 14330Sstevel@tonic-gate7: 14340Sstevel@tonic-gate /* 14350Sstevel@tonic-gate * Otherwise, if the logout structure was busy but we have not 14360Sstevel@tonic-gate * nested more times than our maximum value, then we simply 14370Sstevel@tonic-gate * issue a retry. Our TL=0 trap handler code will check and 14380Sstevel@tonic-gate * clear the AFSR after it is done logging what is currently 14390Sstevel@tonic-gate * in the logout struct and handle this event at that time. 14400Sstevel@tonic-gate */ 14410Sstevel@tonic-gate retry 14420Sstevel@tonic-gate8: 14430Sstevel@tonic-gate /* 14440Sstevel@tonic-gate * Call cpu_fast_ecc_error via systrap at PIL 14 unless we're 14450Sstevel@tonic-gate * already at PIL 15. 14460Sstevel@tonic-gate */ 14470Sstevel@tonic-gate set cpu_fast_ecc_error, %g1 14480Sstevel@tonic-gate rdpr %pil, %g4 14490Sstevel@tonic-gate cmp %g4, PIL_14 14500Sstevel@tonic-gate ba sys_trap 14510Sstevel@tonic-gate movl %icc, PIL_14, %g4 14520Sstevel@tonic-gate 14530Sstevel@tonic-gate SET_SIZE(fast_ecc_err) 14540Sstevel@tonic-gate 14550Sstevel@tonic-gate#endif /* lint */ 14560Sstevel@tonic-gate 14570Sstevel@tonic-gate#endif /* !(JALAPENO || SERRANO) */ 14580Sstevel@tonic-gate 14590Sstevel@tonic-gate 14600Sstevel@tonic-gate/* 14610Sstevel@tonic-gate * Cheetah/Cheetah+ Fast ECC at TL>0 trap strategy: 14620Sstevel@tonic-gate * 14630Sstevel@tonic-gate * The basic flow of this trap handler is as follows: 14640Sstevel@tonic-gate * 14650Sstevel@tonic-gate * 1) In the "trap 70" trap table code (fecc_err_tl1_instr), generate a 14660Sstevel@tonic-gate * software trap 0 ("ta 0") to buy an extra set of %tpc, etc. which we 14670Sstevel@tonic-gate * will use to save %g1 and %g2. 14680Sstevel@tonic-gate * 2) At the software trap 0 at TL>0 trap table code (fecc_err_tl1_cont_instr), 14690Sstevel@tonic-gate * we save %g1+%g2 using %tpc, %tnpc + %tstate and jump to the fast ecc 14700Sstevel@tonic-gate * handler (using the just saved %g1). 14710Sstevel@tonic-gate * 3) Turn off the Dcache if it was on and save the state of the Dcache 14720Sstevel@tonic-gate * (whether on or off) in Bit2 (CH_ERR_TSTATE_DC_ON) of %tstate. 14730Sstevel@tonic-gate * NB: we don't turn off the Icache because bad data is not installed nor 14740Sstevel@tonic-gate * will we be doing any diagnostic accesses. 14750Sstevel@tonic-gate * 4) compute physical address of the per-cpu/per-tl save area using %g1+%g2 14760Sstevel@tonic-gate * 5) Save %g1-%g7 into the per-cpu/per-tl save area (%g1 + %g2 from the 14770Sstevel@tonic-gate * %tpc, %tnpc, %tstate values previously saved). 14780Sstevel@tonic-gate * 6) set %tl to %tl - 1. 14790Sstevel@tonic-gate * 7) Save the appropriate flags and TPC in the ch_err_tl1_data structure. 14800Sstevel@tonic-gate * 8) Save the value of CH_ERR_TSTATE_DC_ON in the ch_err_tl1_tmp field. 14810Sstevel@tonic-gate * 9) For Cheetah and Jalapeno, read the AFAR and AFSR and clear. For 14820Sstevel@tonic-gate * Cheetah+ (and later), read the shadow AFAR and AFSR but don't clear. 14830Sstevel@tonic-gate * Save the values in ch_err_tl1_data. For Panther, read the shadow 14840Sstevel@tonic-gate * AFSR_EXT and save the value in ch_err_tl1_data. 14850Sstevel@tonic-gate * 10) Disable CEEN/NCEEN to prevent any disrupting/deferred errors from 14860Sstevel@tonic-gate * being queued. We'll report them via the AFSR/AFAR capture in step 13. 14870Sstevel@tonic-gate * 11) Flush the Ecache. 14880Sstevel@tonic-gate * NB: the Ecache is flushed assuming the largest possible size with 14890Sstevel@tonic-gate * the smallest possible line size since access to the cpu_nodes may 14900Sstevel@tonic-gate * cause an unrecoverable DTLB miss. 14910Sstevel@tonic-gate * 12) Reenable CEEN/NCEEN with the value saved from step 10. 14920Sstevel@tonic-gate * 13) For Cheetah and Jalapeno, read the AFAR and AFSR and clear again. 14930Sstevel@tonic-gate * For Cheetah+ (and later), read the primary AFAR and AFSR and now clear. 14940Sstevel@tonic-gate * Save the read AFSR/AFAR values in ch_err_tl1_data. For Panther, 14950Sstevel@tonic-gate * read and clear the primary AFSR_EXT and save it in ch_err_tl1_data. 14960Sstevel@tonic-gate * 14) Flush and re-enable the Dcache if it was on at step 3. 14970Sstevel@tonic-gate * 15) Do TRAPTRACE if enabled. 14980Sstevel@tonic-gate * 16) Check if a UCU->WDU (or L3_UCU->WDU for Panther) happened, panic if so. 14990Sstevel@tonic-gate * 17) Set the event pending flag in ch_err_tl1_pending[CPU] 15000Sstevel@tonic-gate * 18) Cause a softint 15. The pil15_interrupt handler will inspect the 15010Sstevel@tonic-gate * event pending flag and call cpu_tl1_error via systrap if set. 15020Sstevel@tonic-gate * 19) Restore the registers from step 5 and issue retry. 15030Sstevel@tonic-gate */ 15040Sstevel@tonic-gate 15050Sstevel@tonic-gate/* 15060Sstevel@tonic-gate * Cheetah ecc-protected E$ trap (Trap 70) at TL>0 15070Sstevel@tonic-gate * tt1_fecc is replaced by fecc_err_tl1_instr in cpu_init_trap of the various 15080Sstevel@tonic-gate * architecture-specific files. This generates a "Software Trap 0" at TL>0, 15090Sstevel@tonic-gate * which goes to fecc_err_tl1_cont_instr, and we continue the handling there. 15100Sstevel@tonic-gate * NB: Must be 8 instructions or less to fit in trap table and code must 15110Sstevel@tonic-gate * be relocatable. 15120Sstevel@tonic-gate */ 15130Sstevel@tonic-gate 15140Sstevel@tonic-gate#if defined(lint) 15150Sstevel@tonic-gate 15160Sstevel@tonic-gatevoid 15170Sstevel@tonic-gatefecc_err_tl1_instr(void) 15180Sstevel@tonic-gate{} 15190Sstevel@tonic-gate 15200Sstevel@tonic-gate#else /* lint */ 15210Sstevel@tonic-gate 15220Sstevel@tonic-gate ENTRY_NP(fecc_err_tl1_instr) 15230Sstevel@tonic-gate CH_ERR_TL1_TRAPENTRY(SWTRAP_0); 15240Sstevel@tonic-gate SET_SIZE(fecc_err_tl1_instr) 15250Sstevel@tonic-gate 15260Sstevel@tonic-gate#endif /* lint */ 15270Sstevel@tonic-gate 15280Sstevel@tonic-gate/* 15290Sstevel@tonic-gate * Software trap 0 at TL>0. 15300Sstevel@tonic-gate * tt1_swtrap0 is replaced by fecc_err_tl1_cont_instr in cpu_init_trap of 15310Sstevel@tonic-gate * the various architecture-specific files. This is used as a continuation 15320Sstevel@tonic-gate * of the fast ecc handling where we've bought an extra TL level, so we can 15330Sstevel@tonic-gate * use %tpc, %tnpc, %tstate to temporarily save the value of registers %g1 15340Sstevel@tonic-gate * and %g2. Note that %tstate has bits 0-2 and then bits 8-19 as r/w, 15350Sstevel@tonic-gate * there's a reserved hole from 3-7. We only use bits 0-1 and 8-9 (the low 15360Sstevel@tonic-gate * order two bits from %g1 and %g2 respectively). 15370Sstevel@tonic-gate * NB: Must be 8 instructions or less to fit in trap table and code must 15380Sstevel@tonic-gate * be relocatable. 15390Sstevel@tonic-gate */ 15400Sstevel@tonic-gate#if defined(lint) 15410Sstevel@tonic-gate 15420Sstevel@tonic-gatevoid 15430Sstevel@tonic-gatefecc_err_tl1_cont_instr(void) 15440Sstevel@tonic-gate{} 15450Sstevel@tonic-gate 15460Sstevel@tonic-gate#else /* lint */ 15470Sstevel@tonic-gate 15480Sstevel@tonic-gate ENTRY_NP(fecc_err_tl1_cont_instr) 15490Sstevel@tonic-gate CH_ERR_TL1_SWTRAPENTRY(fast_ecc_tl1_err) 15500Sstevel@tonic-gate SET_SIZE(fecc_err_tl1_cont_instr) 15510Sstevel@tonic-gate 15520Sstevel@tonic-gate#endif /* lint */ 15530Sstevel@tonic-gate 15540Sstevel@tonic-gate 15550Sstevel@tonic-gate#if defined(lint) 15560Sstevel@tonic-gate 15570Sstevel@tonic-gatevoid 15580Sstevel@tonic-gatece_err(void) 15590Sstevel@tonic-gate{} 15600Sstevel@tonic-gate 15610Sstevel@tonic-gate#else /* lint */ 15620Sstevel@tonic-gate 15630Sstevel@tonic-gate/* 15640Sstevel@tonic-gate * The ce_err function handles disrupting trap type 0x63 at TL=0. 15650Sstevel@tonic-gate * 15660Sstevel@tonic-gate * AFSR errors bits which cause this trap are: 15670Sstevel@tonic-gate * CE, EMC, EDU:ST, EDC, WDU, WDC, CPU, CPC, IVU, IVC 15680Sstevel@tonic-gate * 15690Sstevel@tonic-gate * NCEEN Bit of Cheetah External Cache Error Enable Register enables 15700Sstevel@tonic-gate * the following AFSR disrupting traps: EDU:ST, WDU, CPU, IVU 15710Sstevel@tonic-gate * 15720Sstevel@tonic-gate * CEEN Bit of Cheetah External Cache Error Enable Register enables 15730Sstevel@tonic-gate * the following AFSR disrupting traps: CE, EMC, EDC, WDC, CPC, IVC 15740Sstevel@tonic-gate * 15750Sstevel@tonic-gate * Cheetah+ also handles (No additional processing required): 15760Sstevel@tonic-gate * DUE, DTO, DBERR (NCEEN controlled) 15770Sstevel@tonic-gate * THCE (CEEN and ET_ECC_en controlled) 15780Sstevel@tonic-gate * TUE (ET_ECC_en controlled) 15790Sstevel@tonic-gate * 15800Sstevel@tonic-gate * Panther further adds: 15810Sstevel@tonic-gate * IMU, L3_EDU, L3_WDU, L3_CPU (NCEEN controlled) 15820Sstevel@tonic-gate * IMC, L3_EDC, L3_WDC, L3_CPC, L3_THCE (CEEN controlled) 15830Sstevel@tonic-gate * TUE_SH, TUE (NCEEN and L2_tag_ECC_en controlled) 15840Sstevel@tonic-gate * L3_TUE, L3_TUE_SH (NCEEN and ET_ECC_en controlled) 15850Sstevel@tonic-gate * THCE (CEEN and L2_tag_ECC_en controlled) 15860Sstevel@tonic-gate * L3_THCE (CEEN and ET_ECC_en controlled) 15870Sstevel@tonic-gate * 15880Sstevel@tonic-gate * Steps: 15890Sstevel@tonic-gate * 1. Disable hardware corrected disrupting errors only (CEEN) 15900Sstevel@tonic-gate * 2. Park sibling core if caches are shared (to avoid race 15910Sstevel@tonic-gate * condition while accessing shared resources such as L3 15920Sstevel@tonic-gate * data staging register during CPU logout. 15930Sstevel@tonic-gate * 3. If the CPU logout structure is not currently being used: 15940Sstevel@tonic-gate * 4. Clear AFSR error bits 15950Sstevel@tonic-gate * 5. Capture Ecache, Dcache and Icache lines associated 15960Sstevel@tonic-gate * with AFAR. 15970Sstevel@tonic-gate * 6. Unpark sibling core if we parked it earlier. 15980Sstevel@tonic-gate * 7. call cpu_disrupting_error via sys_trap at PIL 14 15990Sstevel@tonic-gate * unless we're already running at PIL 15. 16000Sstevel@tonic-gate * 4. Otherwise, if the CPU logout structure is busy: 16010Sstevel@tonic-gate * 5. Incriment "logout busy count" and place into %g3 16020Sstevel@tonic-gate * 6. Unpark sibling core if we parked it earlier. 16030Sstevel@tonic-gate * 7. Issue a retry since the other CPU error logging 16040Sstevel@tonic-gate * code will end up finding this error bit and logging 16050Sstevel@tonic-gate * information about it later. 16060Sstevel@tonic-gate * 5. Alternatively (to 3 and 4 above), if the cpu_private struct is 16070Sstevel@tonic-gate * not yet initialized such that we can't even check the logout 16080Sstevel@tonic-gate * struct, then we place the clo_flags data into %g2 16090Sstevel@tonic-gate * (sys_trap->have_win arg #1) and call cpu_disrupting_error via 16100Sstevel@tonic-gate * systrap. The clo_flags parameter is used to determine information 16110Sstevel@tonic-gate * such as TL, TT, CEEN settings, etc in the high level trap 16120Sstevel@tonic-gate * handler since we don't have access to detailed logout information 16130Sstevel@tonic-gate * in cases where the cpu_private struct is not yet initialized. 16140Sstevel@tonic-gate * 16150Sstevel@tonic-gate * %g3: [ logout busy count ] - arg #2 16160Sstevel@tonic-gate * %g2: [ clo_flags if cpu_private unavailable ] - sys_trap->have_win: arg #1 16170Sstevel@tonic-gate */ 16180Sstevel@tonic-gate 16190Sstevel@tonic-gate .align 128 16200Sstevel@tonic-gate ENTRY_NP(ce_err) 16210Sstevel@tonic-gate membar #Sync ! Cheetah requires membar #Sync 16220Sstevel@tonic-gate 16230Sstevel@tonic-gate /* 16240Sstevel@tonic-gate * Disable trap on hardware corrected errors (CEEN) while at TL=0 16250Sstevel@tonic-gate * to prevent recursion. 16260Sstevel@tonic-gate */ 16270Sstevel@tonic-gate ldxa [%g0]ASI_ESTATE_ERR, %g1 16280Sstevel@tonic-gate bclr EN_REG_CEEN, %g1 16290Sstevel@tonic-gate stxa %g1, [%g0]ASI_ESTATE_ERR 16300Sstevel@tonic-gate membar #Sync ! membar sync required 16310Sstevel@tonic-gate 16320Sstevel@tonic-gate /* 16330Sstevel@tonic-gate * Save current DCU state. Turn off Icache to allow capture of 16340Sstevel@tonic-gate * Icache data by DO_CPU_LOGOUT. 16350Sstevel@tonic-gate */ 16360Sstevel@tonic-gate ldxa [%g0]ASI_DCU, %g1 ! save DCU in %g1 16370Sstevel@tonic-gate andn %g1, DCU_IC, %g4 16380Sstevel@tonic-gate stxa %g4, [%g0]ASI_DCU 16390Sstevel@tonic-gate flush %g0 /* flush required after changing the IC bit */ 16400Sstevel@tonic-gate 16410Sstevel@tonic-gate /* 16420Sstevel@tonic-gate * Check to see whether we need to park our sibling core 16430Sstevel@tonic-gate * before recording diagnostic information from caches 16440Sstevel@tonic-gate * which may be shared by both cores. 16450Sstevel@tonic-gate * We use %g1 to store information about whether or not 16460Sstevel@tonic-gate * we had to park the core (%g1 holds our DCUCR value and 16470Sstevel@tonic-gate * we only use bits from that register which are "reserved" 16480Sstevel@tonic-gate * to keep track of core parking) so that we know whether 16490Sstevel@tonic-gate * or not to unpark later. %g5 and %g4 are scratch registers. 16500Sstevel@tonic-gate */ 16510Sstevel@tonic-gate PARK_SIBLING_CORE(%g1, %g5, %g4) 16520Sstevel@tonic-gate 16530Sstevel@tonic-gate /* 16540Sstevel@tonic-gate * Do the CPU log out capture. 16550Sstevel@tonic-gate * %g3 = "failed?" return value. 16560Sstevel@tonic-gate * %g2 = Input = AFAR. Output the clo_flags info which is passed 16570Sstevel@tonic-gate * into this macro via %g4. Output only valid if cpu_private 16580Sstevel@tonic-gate * struct has not been initialized. 16590Sstevel@tonic-gate * CHPR_CECC_LOGOUT = cpu logout structure offset input 16600Sstevel@tonic-gate * %g4 = Trap information stored in the cpu logout flags field 16610Sstevel@tonic-gate * %g5 = scr1 16620Sstevel@tonic-gate * %g6 = scr2 16630Sstevel@tonic-gate * %g3 = scr3 16640Sstevel@tonic-gate * %g4 = scr4 16650Sstevel@tonic-gate */ 16660Sstevel@tonic-gate clr %g4 ! TL=0 bit in afsr 16670Sstevel@tonic-gate set CHPR_CECC_LOGOUT, %g6 16680Sstevel@tonic-gate DO_CPU_LOGOUT(%g3, %g2, %g6, %g4, %g5, %g6, %g3, %g4) 16690Sstevel@tonic-gate 16700Sstevel@tonic-gate /* 16710Sstevel@tonic-gate * Flush the Icache. Since we turned off the Icache to capture the 16720Sstevel@tonic-gate * Icache line it is now stale or corrupted and we must flush it 16730Sstevel@tonic-gate * before re-enabling it. 16740Sstevel@tonic-gate */ 16750Sstevel@tonic-gate GET_CPU_PRIVATE_PTR(%g0, %g5, %g7, ce_err_1); 16760Sstevel@tonic-gate ld [%g5 + CHPR_ICACHE_LINESIZE], %g6 16770Sstevel@tonic-gate ba,pt %icc, 2f 16780Sstevel@tonic-gate ld [%g5 + CHPR_ICACHE_SIZE], %g5 16790Sstevel@tonic-gatece_err_1: 16800Sstevel@tonic-gate ASM_LD(%g5, icache_size) 16810Sstevel@tonic-gate ASM_LD(%g6, icache_linesize) 16820Sstevel@tonic-gate2: 16830Sstevel@tonic-gate CH_ICACHE_FLUSHALL(%g5, %g6, %g7, %g4) 16840Sstevel@tonic-gate 16850Sstevel@tonic-gate /* 16860Sstevel@tonic-gate * check to see whether we parked our sibling core at the start 16870Sstevel@tonic-gate * of this handler. If so, we need to unpark it here. 16880Sstevel@tonic-gate * We use DCUCR reserved bits (stored in %g1) to keep track of 16890Sstevel@tonic-gate * whether or not we need to unpark. %g5 and %g4 are scratch registers. 16900Sstevel@tonic-gate */ 16910Sstevel@tonic-gate UNPARK_SIBLING_CORE(%g1, %g5, %g4) 16920Sstevel@tonic-gate 16930Sstevel@tonic-gate /* 16940Sstevel@tonic-gate * Restore Icache to previous state. 16950Sstevel@tonic-gate */ 16960Sstevel@tonic-gate stxa %g1, [%g0]ASI_DCU 16970Sstevel@tonic-gate flush %g0 /* flush required after changing the IC bit */ 16980Sstevel@tonic-gate 16990Sstevel@tonic-gate /* 17000Sstevel@tonic-gate * Make sure our CPU logout operation was successful. 17010Sstevel@tonic-gate */ 17020Sstevel@tonic-gate cmp %g3, %g0 17030Sstevel@tonic-gate be 4f 17040Sstevel@tonic-gate nop 17050Sstevel@tonic-gate 17060Sstevel@tonic-gate /* 17070Sstevel@tonic-gate * If the logout structure had been busy, how many times have 17080Sstevel@tonic-gate * we tried to use it and failed (nesting count)? If we have 17090Sstevel@tonic-gate * already recursed a substantial number of times, then we can 17100Sstevel@tonic-gate * assume things are not going to get better by themselves and 17110Sstevel@tonic-gate * so it would be best to panic. 17120Sstevel@tonic-gate */ 17130Sstevel@tonic-gate cmp %g3, CLO_NESTING_MAX 17140Sstevel@tonic-gate blt 3f 17150Sstevel@tonic-gate nop 17160Sstevel@tonic-gate 17170Sstevel@tonic-gate call ptl1_panic 17180Sstevel@tonic-gate mov PTL1_BAD_ECC, %g1 17190Sstevel@tonic-gate 17200Sstevel@tonic-gate3: 17210Sstevel@tonic-gate /* 17220Sstevel@tonic-gate * Otherwise, if the logout structure was busy but we have not 17230Sstevel@tonic-gate * nested more times than our maximum value, then we simply 17240Sstevel@tonic-gate * issue a retry. Our TL=0 trap handler code will check and 17250Sstevel@tonic-gate * clear the AFSR after it is done logging what is currently 17260Sstevel@tonic-gate * in the logout struct and handle this event at that time. 17270Sstevel@tonic-gate */ 17280Sstevel@tonic-gate retry 17290Sstevel@tonic-gate4: 17300Sstevel@tonic-gate /* 17310Sstevel@tonic-gate * Call cpu_disrupting_error via systrap at PIL 14 unless we're 17320Sstevel@tonic-gate * already at PIL 15. 17330Sstevel@tonic-gate */ 17340Sstevel@tonic-gate set cpu_disrupting_error, %g1 17350Sstevel@tonic-gate rdpr %pil, %g4 17360Sstevel@tonic-gate cmp %g4, PIL_14 17370Sstevel@tonic-gate ba sys_trap 17380Sstevel@tonic-gate movl %icc, PIL_14, %g4 17390Sstevel@tonic-gate SET_SIZE(ce_err) 17400Sstevel@tonic-gate 17410Sstevel@tonic-gate#endif /* lint */ 17420Sstevel@tonic-gate 17430Sstevel@tonic-gate 17440Sstevel@tonic-gate#if defined(lint) 17450Sstevel@tonic-gate 17460Sstevel@tonic-gate/* 17470Sstevel@tonic-gate * This trap cannot happen at TL>0 which means this routine will never 17480Sstevel@tonic-gate * actually be called and so we treat this like a BAD TRAP panic. 17490Sstevel@tonic-gate */ 17500Sstevel@tonic-gatevoid 17510Sstevel@tonic-gatece_err_tl1(void) 17520Sstevel@tonic-gate{} 17530Sstevel@tonic-gate 17540Sstevel@tonic-gate#else /* lint */ 17550Sstevel@tonic-gate 17560Sstevel@tonic-gate .align 64 17570Sstevel@tonic-gate ENTRY_NP(ce_err_tl1) 17580Sstevel@tonic-gate 17590Sstevel@tonic-gate call ptl1_panic 17600Sstevel@tonic-gate mov PTL1_BAD_TRAP, %g1 17610Sstevel@tonic-gate 17620Sstevel@tonic-gate SET_SIZE(ce_err_tl1) 17630Sstevel@tonic-gate 17640Sstevel@tonic-gate#endif /* lint */ 17650Sstevel@tonic-gate 17660Sstevel@tonic-gate 17670Sstevel@tonic-gate#if defined(lint) 17680Sstevel@tonic-gate 17690Sstevel@tonic-gatevoid 17700Sstevel@tonic-gateasync_err(void) 17710Sstevel@tonic-gate{} 17720Sstevel@tonic-gate 17730Sstevel@tonic-gate#else /* lint */ 17740Sstevel@tonic-gate 17750Sstevel@tonic-gate/* 17760Sstevel@tonic-gate * The async_err function handles deferred trap types 0xA 17770Sstevel@tonic-gate * (instruction_access_error) and 0x32 (data_access_error) at TL>=0. 17780Sstevel@tonic-gate * 17790Sstevel@tonic-gate * AFSR errors bits which cause this trap are: 17800Sstevel@tonic-gate * UE, EMU, EDU:BLD, L3_EDU:BLD, TO, BERR 17810Sstevel@tonic-gate * On some platforms, EMU may causes cheetah to pull the error pin 17820Sstevel@tonic-gate * never giving Solaris a chance to take a trap. 17830Sstevel@tonic-gate * 17840Sstevel@tonic-gate * NCEEN Bit of Cheetah External Cache Error Enable Register enables 17850Sstevel@tonic-gate * the following AFSR deferred traps: UE, EMU, EDU:BLD, TO, BERR 17860Sstevel@tonic-gate * 17870Sstevel@tonic-gate * Steps: 17880Sstevel@tonic-gate * 1. Disable CEEN and NCEEN errors to prevent recursive errors. 17890Sstevel@tonic-gate * 2. Turn D$ off per Cheetah PRM P.5 Note 6, turn I$ off to capture 17900Sstevel@tonic-gate * I$ line in DO_CPU_LOGOUT. 17910Sstevel@tonic-gate * 3. Park sibling core if caches are shared (to avoid race 17920Sstevel@tonic-gate * condition while accessing shared resources such as L3 17930Sstevel@tonic-gate * data staging register during CPU logout. 17940Sstevel@tonic-gate * 4. If the CPU logout structure is not currently being used: 17950Sstevel@tonic-gate * 5. Clear AFSR error bits 17960Sstevel@tonic-gate * 6. Capture Ecache, Dcache and Icache lines associated 17970Sstevel@tonic-gate * with AFAR. 17980Sstevel@tonic-gate * 7. Unpark sibling core if we parked it earlier. 17990Sstevel@tonic-gate * 8. call cpu_deferred_error via sys_trap. 18000Sstevel@tonic-gate * 5. Otherwise, if the CPU logout structure is busy: 18010Sstevel@tonic-gate * 6. Incriment "logout busy count" 18020Sstevel@tonic-gate * 7. Unpark sibling core if we parked it earlier. 18030Sstevel@tonic-gate * 8) Issue a retry since the other CPU error logging 18040Sstevel@tonic-gate * code will end up finding this error bit and logging 18050Sstevel@tonic-gate * information about it later. 18060Sstevel@tonic-gate * 6. Alternatively (to 4 and 5 above), if the cpu_private struct is 18070Sstevel@tonic-gate * not yet initialized such that we can't even check the logout 18080Sstevel@tonic-gate * struct, then we place the clo_flags data into %g2 18090Sstevel@tonic-gate * (sys_trap->have_win arg #1) and call cpu_deferred_error via 18100Sstevel@tonic-gate * systrap. The clo_flags parameter is used to determine information 18110Sstevel@tonic-gate * such as TL, TT, CEEN settings, etc in the high level trap handler 18120Sstevel@tonic-gate * since we don't have access to detailed logout information in cases 18130Sstevel@tonic-gate * where the cpu_private struct is not yet initialized. 18140Sstevel@tonic-gate * 18150Sstevel@tonic-gate * %g2: [ clo_flags if cpu_private unavailable ] - sys_trap->have_win: arg #1 18160Sstevel@tonic-gate * %g3: [ logout busy count ] - arg #2 18170Sstevel@tonic-gate */ 18180Sstevel@tonic-gate 18190Sstevel@tonic-gate ENTRY_NP(async_err) 18200Sstevel@tonic-gate membar #Sync ! Cheetah requires membar #Sync 18210Sstevel@tonic-gate 18220Sstevel@tonic-gate /* 18230Sstevel@tonic-gate * Disable CEEN and NCEEN. 18240Sstevel@tonic-gate */ 18250Sstevel@tonic-gate ldxa [%g0]ASI_ESTATE_ERR, %g3 18260Sstevel@tonic-gate andn %g3, EN_REG_NCEEN + EN_REG_CEEN, %g4 18270Sstevel@tonic-gate stxa %g4, [%g0]ASI_ESTATE_ERR 18280Sstevel@tonic-gate membar #Sync ! membar sync required 18290Sstevel@tonic-gate 18300Sstevel@tonic-gate /* 18310Sstevel@tonic-gate * Save current DCU state. 18320Sstevel@tonic-gate * Disable Icache to allow capture of Icache data by DO_CPU_LOGOUT. 18330Sstevel@tonic-gate * Do this regardless of whether this is a Data Access Error or 18340Sstevel@tonic-gate * Instruction Access Error Trap. 18350Sstevel@tonic-gate * Disable Dcache for both Data Access Error and Instruction Access 18360Sstevel@tonic-gate * Error per Cheetah PRM P.5 Note 6. 18370Sstevel@tonic-gate */ 18380Sstevel@tonic-gate ldxa [%g0]ASI_DCU, %g1 ! save DCU in %g1 18390Sstevel@tonic-gate andn %g1, DCU_IC + DCU_DC, %g4 18400Sstevel@tonic-gate stxa %g4, [%g0]ASI_DCU 18410Sstevel@tonic-gate flush %g0 /* flush required after changing the IC bit */ 18420Sstevel@tonic-gate 18430Sstevel@tonic-gate /* 18440Sstevel@tonic-gate * Check to see whether we need to park our sibling core 18450Sstevel@tonic-gate * before recording diagnostic information from caches 18460Sstevel@tonic-gate * which may be shared by both cores. 18470Sstevel@tonic-gate * We use %g1 to store information about whether or not 18480Sstevel@tonic-gate * we had to park the core (%g1 holds our DCUCR value and 18490Sstevel@tonic-gate * we only use bits from that register which are "reserved" 18500Sstevel@tonic-gate * to keep track of core parking) so that we know whether 18510Sstevel@tonic-gate * or not to unpark later. %g6 and %g4 are scratch registers. 18520Sstevel@tonic-gate */ 18530Sstevel@tonic-gate PARK_SIBLING_CORE(%g1, %g6, %g4) 18540Sstevel@tonic-gate 18550Sstevel@tonic-gate /* 18560Sstevel@tonic-gate * Do the CPU logout capture. 18570Sstevel@tonic-gate * 18580Sstevel@tonic-gate * %g3 = "failed?" return value. 18590Sstevel@tonic-gate * %g2 = Input = AFAR. Output the clo_flags info which is passed 18600Sstevel@tonic-gate * into this macro via %g4. Output only valid if cpu_private 18610Sstevel@tonic-gate * struct has not been initialized. 18620Sstevel@tonic-gate * CHPR_ASYNC_LOGOUT = cpu logout structure offset input 18630Sstevel@tonic-gate * %g4 = Trap information stored in the cpu logout flags field 18640Sstevel@tonic-gate * %g5 = scr1 18650Sstevel@tonic-gate * %g6 = scr2 18660Sstevel@tonic-gate * %g3 = scr3 18670Sstevel@tonic-gate * %g4 = scr4 18680Sstevel@tonic-gate */ 18690Sstevel@tonic-gate andcc %g5, T_TL1, %g0 18700Sstevel@tonic-gate clr %g6 18710Sstevel@tonic-gate movnz %xcc, 1, %g6 ! set %g6 if T_TL1 set 18720Sstevel@tonic-gate sllx %g6, CLO_FLAGS_TL_SHIFT, %g6 18730Sstevel@tonic-gate sllx %g5, CLO_FLAGS_TT_SHIFT, %g4 18740Sstevel@tonic-gate set CLO_FLAGS_TT_MASK, %g2 18750Sstevel@tonic-gate and %g4, %g2, %g4 ! ttype 18760Sstevel@tonic-gate or %g6, %g4, %g4 ! TT and TL 18770Sstevel@tonic-gate and %g3, EN_REG_CEEN, %g3 ! CEEN value 18780Sstevel@tonic-gate or %g3, %g4, %g4 ! TT and TL and CEEN 18790Sstevel@tonic-gate set CHPR_ASYNC_LOGOUT, %g6 18800Sstevel@tonic-gate DO_CPU_LOGOUT(%g3, %g2, %g6, %g4, %g5, %g6, %g3, %g4) 18810Sstevel@tonic-gate 18820Sstevel@tonic-gate /* 18830Sstevel@tonic-gate * If the logout struct was busy, we may need to pass the 18840Sstevel@tonic-gate * TT, TL, and CEEN information to the TL=0 handler via 18850Sstevel@tonic-gate * systrap parameter so save it off here. 18860Sstevel@tonic-gate */ 18870Sstevel@tonic-gate cmp %g3, %g0 18880Sstevel@tonic-gate be 1f 18890Sstevel@tonic-gate nop 18900Sstevel@tonic-gate sllx %g4, 32, %g4 18910Sstevel@tonic-gate or %g4, %g3, %g3 18920Sstevel@tonic-gate1: 18930Sstevel@tonic-gate /* 18940Sstevel@tonic-gate * Flush the Icache. Since we turned off the Icache to capture the 18950Sstevel@tonic-gate * Icache line it is now stale or corrupted and we must flush it 18960Sstevel@tonic-gate * before re-enabling it. 18970Sstevel@tonic-gate */ 18980Sstevel@tonic-gate GET_CPU_PRIVATE_PTR(%g0, %g5, %g7, async_err_1); 18990Sstevel@tonic-gate ld [%g5 + CHPR_ICACHE_LINESIZE], %g6 19000Sstevel@tonic-gate ba,pt %icc, 2f 19010Sstevel@tonic-gate ld [%g5 + CHPR_ICACHE_SIZE], %g5 19020Sstevel@tonic-gateasync_err_1: 19030Sstevel@tonic-gate ASM_LD(%g5, icache_size) 19040Sstevel@tonic-gate ASM_LD(%g6, icache_linesize) 19050Sstevel@tonic-gate2: 19060Sstevel@tonic-gate CH_ICACHE_FLUSHALL(%g5, %g6, %g7, %g4) 19070Sstevel@tonic-gate 19080Sstevel@tonic-gate /* 19090Sstevel@tonic-gate * XXX - Don't we need to flush the Dcache before turning it back 19100Sstevel@tonic-gate * on to avoid stale or corrupt data? Was this broken? 19110Sstevel@tonic-gate */ 19120Sstevel@tonic-gate /* 19130Sstevel@tonic-gate * Flush the Dcache before turning it back on since it may now 19140Sstevel@tonic-gate * contain stale or corrupt data. 19150Sstevel@tonic-gate */ 19160Sstevel@tonic-gate ASM_LD(%g5, dcache_size) 19170Sstevel@tonic-gate ASM_LD(%g6, dcache_linesize) 19180Sstevel@tonic-gate CH_DCACHE_FLUSHALL(%g5, %g6, %g7) 19190Sstevel@tonic-gate 19200Sstevel@tonic-gate /* 19210Sstevel@tonic-gate * check to see whether we parked our sibling core at the start 19220Sstevel@tonic-gate * of this handler. If so, we need to unpark it here. 19230Sstevel@tonic-gate * We use DCUCR reserved bits (stored in %g1) to keep track of 19240Sstevel@tonic-gate * whether or not we need to unpark. %g5 and %g7 are scratch registers. 19250Sstevel@tonic-gate */ 19260Sstevel@tonic-gate UNPARK_SIBLING_CORE(%g1, %g5, %g7) 19270Sstevel@tonic-gate 19280Sstevel@tonic-gate /* 19290Sstevel@tonic-gate * Restore Icache and Dcache to previous state. 19300Sstevel@tonic-gate */ 19310Sstevel@tonic-gate stxa %g1, [%g0]ASI_DCU 19320Sstevel@tonic-gate flush %g0 /* flush required after changing the IC bit */ 19330Sstevel@tonic-gate 19340Sstevel@tonic-gate /* 19350Sstevel@tonic-gate * Make sure our CPU logout operation was successful. 19360Sstevel@tonic-gate */ 19370Sstevel@tonic-gate cmp %g3, %g0 19380Sstevel@tonic-gate be 4f 19390Sstevel@tonic-gate nop 19400Sstevel@tonic-gate 19410Sstevel@tonic-gate /* 19420Sstevel@tonic-gate * If the logout structure had been busy, how many times have 19430Sstevel@tonic-gate * we tried to use it and failed (nesting count)? If we have 19440Sstevel@tonic-gate * already recursed a substantial number of times, then we can 19450Sstevel@tonic-gate * assume things are not going to get better by themselves and 19460Sstevel@tonic-gate * so it would be best to panic. 19470Sstevel@tonic-gate */ 19480Sstevel@tonic-gate cmp %g3, CLO_NESTING_MAX 19490Sstevel@tonic-gate blt 3f 19500Sstevel@tonic-gate nop 19510Sstevel@tonic-gate 19520Sstevel@tonic-gate call ptl1_panic 19530Sstevel@tonic-gate mov PTL1_BAD_ECC, %g1 19540Sstevel@tonic-gate 19550Sstevel@tonic-gate3: 19560Sstevel@tonic-gate /* 19570Sstevel@tonic-gate * Otherwise, if the logout structure was busy but we have not 19580Sstevel@tonic-gate * nested more times than our maximum value, then we simply 19590Sstevel@tonic-gate * issue a retry. Our TL=0 trap handler code will check and 19600Sstevel@tonic-gate * clear the AFSR after it is done logging what is currently 19610Sstevel@tonic-gate * in the logout struct and handle this event at that time. 19620Sstevel@tonic-gate */ 19630Sstevel@tonic-gate retry 19640Sstevel@tonic-gate4: 19656553Sjimand RESET_USER_RTT_REGS(%g4, %g5, async_err_resetskip) 19666553Sjimandasync_err_resetskip: 19670Sstevel@tonic-gate set cpu_deferred_error, %g1 19680Sstevel@tonic-gate ba sys_trap 19690Sstevel@tonic-gate mov PIL_15, %g4 ! run at pil 15 19700Sstevel@tonic-gate SET_SIZE(async_err) 19710Sstevel@tonic-gate 19720Sstevel@tonic-gate#endif /* lint */ 19730Sstevel@tonic-gate 19740Sstevel@tonic-gate#if defined(CPU_IMP_L1_CACHE_PARITY) 19750Sstevel@tonic-gate 19760Sstevel@tonic-gate/* 19770Sstevel@tonic-gate * D$ parity error trap (trap 71) at TL=0. 19780Sstevel@tonic-gate * tt0_dperr is replaced by dcache_parity_instr in cpu_init_trap of 19790Sstevel@tonic-gate * the various architecture-specific files. This merely sets up the 19800Sstevel@tonic-gate * arguments for cpu_parity_error and calls it via sys_trap. 19810Sstevel@tonic-gate * NB: Must be 8 instructions or less to fit in trap table and code must 19820Sstevel@tonic-gate * be relocatable. 19830Sstevel@tonic-gate */ 19840Sstevel@tonic-gate#if defined(lint) 19850Sstevel@tonic-gate 19860Sstevel@tonic-gatevoid 19870Sstevel@tonic-gatedcache_parity_instr(void) 19880Sstevel@tonic-gate{} 19890Sstevel@tonic-gate 19900Sstevel@tonic-gate#else /* lint */ 19910Sstevel@tonic-gate ENTRY_NP(dcache_parity_instr) 19920Sstevel@tonic-gate membar #Sync ! Cheetah+ requires membar #Sync 19930Sstevel@tonic-gate set cpu_parity_error, %g1 19940Sstevel@tonic-gate or %g0, CH_ERR_DPE, %g2 19950Sstevel@tonic-gate rdpr %tpc, %g3 19960Sstevel@tonic-gate sethi %hi(sys_trap), %g7 19970Sstevel@tonic-gate jmp %g7 + %lo(sys_trap) 19980Sstevel@tonic-gate mov PIL_15, %g4 ! run at pil 15 19990Sstevel@tonic-gate SET_SIZE(dcache_parity_instr) 20000Sstevel@tonic-gate 20010Sstevel@tonic-gate#endif /* lint */ 20020Sstevel@tonic-gate 20030Sstevel@tonic-gate 20040Sstevel@tonic-gate/* 20050Sstevel@tonic-gate * D$ parity error trap (trap 71) at TL>0. 20060Sstevel@tonic-gate * tt1_dperr is replaced by dcache_parity_tl1_instr in cpu_init_trap of 20070Sstevel@tonic-gate * the various architecture-specific files. This generates a "Software 20080Sstevel@tonic-gate * Trap 1" at TL>0, which goes to dcache_parity_tl1_cont_instr, and we 20090Sstevel@tonic-gate * continue the handling there. 20100Sstevel@tonic-gate * NB: Must be 8 instructions or less to fit in trap table and code must 20110Sstevel@tonic-gate * be relocatable. 20120Sstevel@tonic-gate */ 20130Sstevel@tonic-gate#if defined(lint) 20140Sstevel@tonic-gate 20150Sstevel@tonic-gatevoid 20160Sstevel@tonic-gatedcache_parity_tl1_instr(void) 20170Sstevel@tonic-gate{} 20180Sstevel@tonic-gate 20190Sstevel@tonic-gate#else /* lint */ 20200Sstevel@tonic-gate ENTRY_NP(dcache_parity_tl1_instr) 20210Sstevel@tonic-gate CH_ERR_TL1_TRAPENTRY(SWTRAP_1); 20220Sstevel@tonic-gate SET_SIZE(dcache_parity_tl1_instr) 20230Sstevel@tonic-gate 20240Sstevel@tonic-gate#endif /* lint */ 20250Sstevel@tonic-gate 20260Sstevel@tonic-gate 20270Sstevel@tonic-gate/* 20280Sstevel@tonic-gate * Software trap 1 at TL>0. 20290Sstevel@tonic-gate * tt1_swtrap1 is replaced by dcache_parity_tl1_cont_instr in cpu_init_trap 20300Sstevel@tonic-gate * of the various architecture-specific files. This is used as a continuation 20310Sstevel@tonic-gate * of the dcache parity handling where we've bought an extra TL level, so we 20320Sstevel@tonic-gate * can use %tpc, %tnpc, %tstate to temporarily save the value of registers %g1 20330Sstevel@tonic-gate * and %g2. Note that %tstate has bits 0-2 and then bits 8-19 as r/w, 20340Sstevel@tonic-gate * there's a reserved hole from 3-7. We only use bits 0-1 and 8-9 (the low 20350Sstevel@tonic-gate * order two bits from %g1 and %g2 respectively). 20360Sstevel@tonic-gate * NB: Must be 8 instructions or less to fit in trap table and code must 20370Sstevel@tonic-gate * be relocatable. 20380Sstevel@tonic-gate */ 20390Sstevel@tonic-gate#if defined(lint) 20400Sstevel@tonic-gate 20410Sstevel@tonic-gatevoid 20420Sstevel@tonic-gatedcache_parity_tl1_cont_instr(void) 20430Sstevel@tonic-gate{} 20440Sstevel@tonic-gate 20450Sstevel@tonic-gate#else /* lint */ 20460Sstevel@tonic-gate ENTRY_NP(dcache_parity_tl1_cont_instr) 20470Sstevel@tonic-gate CH_ERR_TL1_SWTRAPENTRY(dcache_parity_tl1_err); 20480Sstevel@tonic-gate SET_SIZE(dcache_parity_tl1_cont_instr) 20490Sstevel@tonic-gate 20500Sstevel@tonic-gate#endif /* lint */ 20510Sstevel@tonic-gate 20520Sstevel@tonic-gate/* 20530Sstevel@tonic-gate * D$ parity error at TL>0 handler 20540Sstevel@tonic-gate * We get here via trap 71 at TL>0->Software trap 1 at TL>0. We enter 20550Sstevel@tonic-gate * this routine with %g1 and %g2 already saved in %tpc, %tnpc and %tstate. 20560Sstevel@tonic-gate */ 20570Sstevel@tonic-gate#if defined(lint) 20580Sstevel@tonic-gate 20590Sstevel@tonic-gatevoid 20600Sstevel@tonic-gatedcache_parity_tl1_err(void) 20610Sstevel@tonic-gate{} 20620Sstevel@tonic-gate 20630Sstevel@tonic-gate#else /* lint */ 20640Sstevel@tonic-gate 20650Sstevel@tonic-gate ENTRY_NP(dcache_parity_tl1_err) 20660Sstevel@tonic-gate 20670Sstevel@tonic-gate /* 20680Sstevel@tonic-gate * This macro saves all the %g registers in the ch_err_tl1_data 20690Sstevel@tonic-gate * structure, updates the ch_err_tl1_flags and saves the %tpc in 20700Sstevel@tonic-gate * ch_err_tl1_tpc. At the end of this macro, %g1 will point to 20710Sstevel@tonic-gate * the ch_err_tl1_data structure and %g2 will have the original 20720Sstevel@tonic-gate * flags in the ch_err_tl1_data structure. All %g registers 20730Sstevel@tonic-gate * except for %g1 and %g2 will be available. 20740Sstevel@tonic-gate */ 20750Sstevel@tonic-gate CH_ERR_TL1_ENTER(CH_ERR_DPE); 20760Sstevel@tonic-gate 20770Sstevel@tonic-gate#ifdef TRAPTRACE 20780Sstevel@tonic-gate /* 20790Sstevel@tonic-gate * Get current trap trace entry physical pointer. 20800Sstevel@tonic-gate */ 20810Sstevel@tonic-gate CPU_INDEX(%g6, %g5) 20820Sstevel@tonic-gate sll %g6, TRAPTR_SIZE_SHIFT, %g6 20830Sstevel@tonic-gate set trap_trace_ctl, %g5 20840Sstevel@tonic-gate add %g6, %g5, %g6 20850Sstevel@tonic-gate ld [%g6 + TRAPTR_LIMIT], %g5 20860Sstevel@tonic-gate tst %g5 20870Sstevel@tonic-gate be %icc, dpe_tl1_skip_tt 20880Sstevel@tonic-gate nop 20890Sstevel@tonic-gate ldx [%g6 + TRAPTR_PBASE], %g5 20900Sstevel@tonic-gate ld [%g6 + TRAPTR_OFFSET], %g4 20910Sstevel@tonic-gate add %g5, %g4, %g5 20920Sstevel@tonic-gate 20930Sstevel@tonic-gate /* 20940Sstevel@tonic-gate * Create trap trace entry. 20950Sstevel@tonic-gate */ 20960Sstevel@tonic-gate rd %asi, %g7 20970Sstevel@tonic-gate wr %g0, TRAPTR_ASI, %asi 20980Sstevel@tonic-gate rd STICK, %g4 20990Sstevel@tonic-gate stxa %g4, [%g5 + TRAP_ENT_TICK]%asi 21000Sstevel@tonic-gate rdpr %tl, %g4 21010Sstevel@tonic-gate stha %g4, [%g5 + TRAP_ENT_TL]%asi 21020Sstevel@tonic-gate rdpr %tt, %g4 21030Sstevel@tonic-gate stha %g4, [%g5 + TRAP_ENT_TT]%asi 21040Sstevel@tonic-gate rdpr %tpc, %g4 21050Sstevel@tonic-gate stna %g4, [%g5 + TRAP_ENT_TPC]%asi 21060Sstevel@tonic-gate rdpr %tstate, %g4 21070Sstevel@tonic-gate stxa %g4, [%g5 + TRAP_ENT_TSTATE]%asi 21080Sstevel@tonic-gate stna %sp, [%g5 + TRAP_ENT_SP]%asi 21090Sstevel@tonic-gate stna %g0, [%g5 + TRAP_ENT_TR]%asi 21100Sstevel@tonic-gate stna %g0, [%g5 + TRAP_ENT_F1]%asi 21110Sstevel@tonic-gate stna %g0, [%g5 + TRAP_ENT_F2]%asi 21120Sstevel@tonic-gate stna %g0, [%g5 + TRAP_ENT_F3]%asi 21130Sstevel@tonic-gate stna %g0, [%g5 + TRAP_ENT_F4]%asi 21140Sstevel@tonic-gate wr %g0, %g7, %asi 21150Sstevel@tonic-gate 21160Sstevel@tonic-gate /* 21170Sstevel@tonic-gate * Advance trap trace pointer. 21180Sstevel@tonic-gate */ 21190Sstevel@tonic-gate ld [%g6 + TRAPTR_OFFSET], %g5 21200Sstevel@tonic-gate ld [%g6 + TRAPTR_LIMIT], %g4 21210Sstevel@tonic-gate st %g5, [%g6 + TRAPTR_LAST_OFFSET] 21220Sstevel@tonic-gate add %g5, TRAP_ENT_SIZE, %g5 21230Sstevel@tonic-gate sub %g4, TRAP_ENT_SIZE, %g4 21240Sstevel@tonic-gate cmp %g5, %g4 21250Sstevel@tonic-gate movge %icc, 0, %g5 21260Sstevel@tonic-gate st %g5, [%g6 + TRAPTR_OFFSET] 21270Sstevel@tonic-gatedpe_tl1_skip_tt: 21280Sstevel@tonic-gate#endif /* TRAPTRACE */ 21290Sstevel@tonic-gate 21300Sstevel@tonic-gate /* 21310Sstevel@tonic-gate * I$ and D$ are automatically turned off by HW when the CPU hits 21320Sstevel@tonic-gate * a dcache or icache parity error so we will just leave those two 21330Sstevel@tonic-gate * off for now to avoid repeating this trap. 21340Sstevel@tonic-gate * For Panther, however, since we trap on P$ data parity errors 21350Sstevel@tonic-gate * and HW does not automatically disable P$, we need to disable it 21360Sstevel@tonic-gate * here so that we don't encounter any recursive traps when we 21370Sstevel@tonic-gate * issue the retry. 21380Sstevel@tonic-gate */ 21390Sstevel@tonic-gate ldxa [%g0]ASI_DCU, %g3 21400Sstevel@tonic-gate mov 1, %g4 21410Sstevel@tonic-gate sllx %g4, DCU_PE_SHIFT, %g4 21420Sstevel@tonic-gate andn %g3, %g4, %g3 21430Sstevel@tonic-gate stxa %g3, [%g0]ASI_DCU 21440Sstevel@tonic-gate membar #Sync 21450Sstevel@tonic-gate 21460Sstevel@tonic-gate /* 21470Sstevel@tonic-gate * We fall into this macro if we've successfully logged the error in 21480Sstevel@tonic-gate * the ch_err_tl1_data structure and want the PIL15 softint to pick 21490Sstevel@tonic-gate * it up and log it. %g1 must point to the ch_err_tl1_data structure. 21500Sstevel@tonic-gate * Restores the %g registers and issues retry. 21510Sstevel@tonic-gate */ 21520Sstevel@tonic-gate CH_ERR_TL1_EXIT; 21530Sstevel@tonic-gate SET_SIZE(dcache_parity_tl1_err) 21540Sstevel@tonic-gate 21550Sstevel@tonic-gate#endif /* lint */ 21560Sstevel@tonic-gate 21570Sstevel@tonic-gate/* 21580Sstevel@tonic-gate * I$ parity error trap (trap 72) at TL=0. 21590Sstevel@tonic-gate * tt0_iperr is replaced by icache_parity_instr in cpu_init_trap of 21600Sstevel@tonic-gate * the various architecture-specific files. This merely sets up the 21610Sstevel@tonic-gate * arguments for cpu_parity_error and calls it via sys_trap. 21620Sstevel@tonic-gate * NB: Must be 8 instructions or less to fit in trap table and code must 21630Sstevel@tonic-gate * be relocatable. 21640Sstevel@tonic-gate */ 21650Sstevel@tonic-gate#if defined(lint) 21660Sstevel@tonic-gate 21670Sstevel@tonic-gatevoid 21680Sstevel@tonic-gateicache_parity_instr(void) 21690Sstevel@tonic-gate{} 21700Sstevel@tonic-gate 21710Sstevel@tonic-gate#else /* lint */ 21720Sstevel@tonic-gate 21730Sstevel@tonic-gate ENTRY_NP(icache_parity_instr) 21740Sstevel@tonic-gate membar #Sync ! Cheetah+ requires membar #Sync 21750Sstevel@tonic-gate set cpu_parity_error, %g1 21760Sstevel@tonic-gate or %g0, CH_ERR_IPE, %g2 21770Sstevel@tonic-gate rdpr %tpc, %g3 21780Sstevel@tonic-gate sethi %hi(sys_trap), %g7 21790Sstevel@tonic-gate jmp %g7 + %lo(sys_trap) 21800Sstevel@tonic-gate mov PIL_15, %g4 ! run at pil 15 21810Sstevel@tonic-gate SET_SIZE(icache_parity_instr) 21820Sstevel@tonic-gate 21830Sstevel@tonic-gate#endif /* lint */ 21840Sstevel@tonic-gate 21850Sstevel@tonic-gate/* 21860Sstevel@tonic-gate * I$ parity error trap (trap 72) at TL>0. 21870Sstevel@tonic-gate * tt1_iperr is replaced by icache_parity_tl1_instr in cpu_init_trap of 21880Sstevel@tonic-gate * the various architecture-specific files. This generates a "Software 21890Sstevel@tonic-gate * Trap 2" at TL>0, which goes to icache_parity_tl1_cont_instr, and we 21900Sstevel@tonic-gate * continue the handling there. 21910Sstevel@tonic-gate * NB: Must be 8 instructions or less to fit in trap table and code must 21920Sstevel@tonic-gate * be relocatable. 21930Sstevel@tonic-gate */ 21940Sstevel@tonic-gate#if defined(lint) 21950Sstevel@tonic-gate 21960Sstevel@tonic-gatevoid 21970Sstevel@tonic-gateicache_parity_tl1_instr(void) 21980Sstevel@tonic-gate{} 21990Sstevel@tonic-gate 22000Sstevel@tonic-gate#else /* lint */ 22010Sstevel@tonic-gate ENTRY_NP(icache_parity_tl1_instr) 22020Sstevel@tonic-gate CH_ERR_TL1_TRAPENTRY(SWTRAP_2); 22030Sstevel@tonic-gate SET_SIZE(icache_parity_tl1_instr) 22040Sstevel@tonic-gate 22050Sstevel@tonic-gate#endif /* lint */ 22060Sstevel@tonic-gate 22070Sstevel@tonic-gate/* 22080Sstevel@tonic-gate * Software trap 2 at TL>0. 22090Sstevel@tonic-gate * tt1_swtrap2 is replaced by icache_parity_tl1_cont_instr in cpu_init_trap 22100Sstevel@tonic-gate * of the various architecture-specific files. This is used as a continuation 22110Sstevel@tonic-gate * of the icache parity handling where we've bought an extra TL level, so we 22120Sstevel@tonic-gate * can use %tpc, %tnpc, %tstate to temporarily save the value of registers %g1 22130Sstevel@tonic-gate * and %g2. Note that %tstate has bits 0-2 and then bits 8-19 as r/w, 22140Sstevel@tonic-gate * there's a reserved hole from 3-7. We only use bits 0-1 and 8-9 (the low 22150Sstevel@tonic-gate * order two bits from %g1 and %g2 respectively). 22160Sstevel@tonic-gate * NB: Must be 8 instructions or less to fit in trap table and code must 22170Sstevel@tonic-gate * be relocatable. 22180Sstevel@tonic-gate */ 22190Sstevel@tonic-gate#if defined(lint) 22200Sstevel@tonic-gate 22210Sstevel@tonic-gatevoid 22220Sstevel@tonic-gateicache_parity_tl1_cont_instr(void) 22230Sstevel@tonic-gate{} 22240Sstevel@tonic-gate 22250Sstevel@tonic-gate#else /* lint */ 22260Sstevel@tonic-gate ENTRY_NP(icache_parity_tl1_cont_instr) 22270Sstevel@tonic-gate CH_ERR_TL1_SWTRAPENTRY(icache_parity_tl1_err); 22280Sstevel@tonic-gate SET_SIZE(icache_parity_tl1_cont_instr) 22290Sstevel@tonic-gate 22300Sstevel@tonic-gate#endif /* lint */ 22310Sstevel@tonic-gate 22320Sstevel@tonic-gate 22330Sstevel@tonic-gate/* 22340Sstevel@tonic-gate * I$ parity error at TL>0 handler 22350Sstevel@tonic-gate * We get here via trap 72 at TL>0->Software trap 2 at TL>0. We enter 22360Sstevel@tonic-gate * this routine with %g1 and %g2 already saved in %tpc, %tnpc and %tstate. 22370Sstevel@tonic-gate */ 22380Sstevel@tonic-gate#if defined(lint) 22390Sstevel@tonic-gate 22400Sstevel@tonic-gatevoid 22410Sstevel@tonic-gateicache_parity_tl1_err(void) 22420Sstevel@tonic-gate{} 22430Sstevel@tonic-gate 22440Sstevel@tonic-gate#else /* lint */ 22450Sstevel@tonic-gate 22460Sstevel@tonic-gate ENTRY_NP(icache_parity_tl1_err) 22470Sstevel@tonic-gate 22480Sstevel@tonic-gate /* 22490Sstevel@tonic-gate * This macro saves all the %g registers in the ch_err_tl1_data 22500Sstevel@tonic-gate * structure, updates the ch_err_tl1_flags and saves the %tpc in 22510Sstevel@tonic-gate * ch_err_tl1_tpc. At the end of this macro, %g1 will point to 22520Sstevel@tonic-gate * the ch_err_tl1_data structure and %g2 will have the original 22530Sstevel@tonic-gate * flags in the ch_err_tl1_data structure. All %g registers 22540Sstevel@tonic-gate * except for %g1 and %g2 will be available. 22550Sstevel@tonic-gate */ 22560Sstevel@tonic-gate CH_ERR_TL1_ENTER(CH_ERR_IPE); 22570Sstevel@tonic-gate 22580Sstevel@tonic-gate#ifdef TRAPTRACE 22590Sstevel@tonic-gate /* 22600Sstevel@tonic-gate * Get current trap trace entry physical pointer. 22610Sstevel@tonic-gate */ 22620Sstevel@tonic-gate CPU_INDEX(%g6, %g5) 22630Sstevel@tonic-gate sll %g6, TRAPTR_SIZE_SHIFT, %g6 22640Sstevel@tonic-gate set trap_trace_ctl, %g5 22650Sstevel@tonic-gate add %g6, %g5, %g6 22660Sstevel@tonic-gate ld [%g6 + TRAPTR_LIMIT], %g5 22670Sstevel@tonic-gate tst %g5 22680Sstevel@tonic-gate be %icc, ipe_tl1_skip_tt 22690Sstevel@tonic-gate nop 22700Sstevel@tonic-gate ldx [%g6 + TRAPTR_PBASE], %g5 22710Sstevel@tonic-gate ld [%g6 + TRAPTR_OFFSET], %g4 22720Sstevel@tonic-gate add %g5, %g4, %g5 22730Sstevel@tonic-gate 22740Sstevel@tonic-gate /* 22750Sstevel@tonic-gate * Create trap trace entry. 22760Sstevel@tonic-gate */ 22770Sstevel@tonic-gate rd %asi, %g7 22780Sstevel@tonic-gate wr %g0, TRAPTR_ASI, %asi 22790Sstevel@tonic-gate rd STICK, %g4 22800Sstevel@tonic-gate stxa %g4, [%g5 + TRAP_ENT_TICK]%asi 22810Sstevel@tonic-gate rdpr %tl, %g4 22820Sstevel@tonic-gate stha %g4, [%g5 + TRAP_ENT_TL]%asi 22830Sstevel@tonic-gate rdpr %tt, %g4 22840Sstevel@tonic-gate stha %g4, [%g5 + TRAP_ENT_TT]%asi 22850Sstevel@tonic-gate rdpr %tpc, %g4 22860Sstevel@tonic-gate stna %g4, [%g5 + TRAP_ENT_TPC]%asi 22870Sstevel@tonic-gate rdpr %tstate, %g4 22880Sstevel@tonic-gate stxa %g4, [%g5 + TRAP_ENT_TSTATE]%asi 22890Sstevel@tonic-gate stna %sp, [%g5 + TRAP_ENT_SP]%asi 22900Sstevel@tonic-gate stna %g0, [%g5 + TRAP_ENT_TR]%asi 22910Sstevel@tonic-gate stna %g0, [%g5 + TRAP_ENT_F1]%asi 22920Sstevel@tonic-gate stna %g0, [%g5 + TRAP_ENT_F2]%asi 22930Sstevel@tonic-gate stna %g0, [%g5 + TRAP_ENT_F3]%asi 22940Sstevel@tonic-gate stna %g0, [%g5 + TRAP_ENT_F4]%asi 22950Sstevel@tonic-gate wr %g0, %g7, %asi 22960Sstevel@tonic-gate 22970Sstevel@tonic-gate /* 22980Sstevel@tonic-gate * Advance trap trace pointer. 22990Sstevel@tonic-gate */ 23000Sstevel@tonic-gate ld [%g6 + TRAPTR_OFFSET], %g5 23010Sstevel@tonic-gate ld [%g6 + TRAPTR_LIMIT], %g4 23020Sstevel@tonic-gate st %g5, [%g6 + TRAPTR_LAST_OFFSET] 23030Sstevel@tonic-gate add %g5, TRAP_ENT_SIZE, %g5 23040Sstevel@tonic-gate sub %g4, TRAP_ENT_SIZE, %g4 23050Sstevel@tonic-gate cmp %g5, %g4 23060Sstevel@tonic-gate movge %icc, 0, %g5 23070Sstevel@tonic-gate st %g5, [%g6 + TRAPTR_OFFSET] 23080Sstevel@tonic-gateipe_tl1_skip_tt: 23090Sstevel@tonic-gate#endif /* TRAPTRACE */ 23100Sstevel@tonic-gate 23110Sstevel@tonic-gate /* 23120Sstevel@tonic-gate * We fall into this macro if we've successfully logged the error in 23130Sstevel@tonic-gate * the ch_err_tl1_data structure and want the PIL15 softint to pick 23140Sstevel@tonic-gate * it up and log it. %g1 must point to the ch_err_tl1_data structure. 23150Sstevel@tonic-gate * Restores the %g registers and issues retry. 23160Sstevel@tonic-gate */ 23170Sstevel@tonic-gate CH_ERR_TL1_EXIT; 23180Sstevel@tonic-gate 23190Sstevel@tonic-gate SET_SIZE(icache_parity_tl1_err) 23200Sstevel@tonic-gate 23210Sstevel@tonic-gate#endif /* lint */ 23220Sstevel@tonic-gate 23230Sstevel@tonic-gate#endif /* CPU_IMP_L1_CACHE_PARITY */ 23240Sstevel@tonic-gate 23250Sstevel@tonic-gate 23260Sstevel@tonic-gate/* 23270Sstevel@tonic-gate * The itlb_rd_entry and dtlb_rd_entry functions return the tag portion of the 23280Sstevel@tonic-gate * tte, the virtual address, and the ctxnum of the specified tlb entry. They 23290Sstevel@tonic-gate * should only be used in places where you have no choice but to look at the 23300Sstevel@tonic-gate * tlb itself. 23310Sstevel@tonic-gate * 23320Sstevel@tonic-gate * Note: These two routines are required by the Estar "cpr" loadable module. 23330Sstevel@tonic-gate */ 23340Sstevel@tonic-gate 23350Sstevel@tonic-gate#if defined(lint) 23360Sstevel@tonic-gate 23370Sstevel@tonic-gate/* ARGSUSED */ 23380Sstevel@tonic-gatevoid 23390Sstevel@tonic-gateitlb_rd_entry(uint_t entry, tte_t *tte, uint64_t *va_tag) 23400Sstevel@tonic-gate{} 23410Sstevel@tonic-gate 23420Sstevel@tonic-gate#else /* lint */ 23430Sstevel@tonic-gate 23440Sstevel@tonic-gate ENTRY_NP(itlb_rd_entry) 23450Sstevel@tonic-gate sllx %o0, 3, %o0 23460Sstevel@tonic-gate ldxa [%o0]ASI_ITLB_ACCESS, %g1 23470Sstevel@tonic-gate stx %g1, [%o1] 23480Sstevel@tonic-gate ldxa [%o0]ASI_ITLB_TAGREAD, %g2 23490Sstevel@tonic-gate set TAGREAD_CTX_MASK, %o4 23500Sstevel@tonic-gate andn %g2, %o4, %o5 23510Sstevel@tonic-gate retl 23520Sstevel@tonic-gate stx %o5, [%o2] 23530Sstevel@tonic-gate SET_SIZE(itlb_rd_entry) 23540Sstevel@tonic-gate 23550Sstevel@tonic-gate#endif /* lint */ 23560Sstevel@tonic-gate 23570Sstevel@tonic-gate 23580Sstevel@tonic-gate#if defined(lint) 23590Sstevel@tonic-gate 23600Sstevel@tonic-gate/* ARGSUSED */ 23610Sstevel@tonic-gatevoid 23620Sstevel@tonic-gatedtlb_rd_entry(uint_t entry, tte_t *tte, uint64_t *va_tag) 23630Sstevel@tonic-gate{} 23640Sstevel@tonic-gate 23650Sstevel@tonic-gate#else /* lint */ 23660Sstevel@tonic-gate 23670Sstevel@tonic-gate ENTRY_NP(dtlb_rd_entry) 23680Sstevel@tonic-gate sllx %o0, 3, %o0 23690Sstevel@tonic-gate ldxa [%o0]ASI_DTLB_ACCESS, %g1 23700Sstevel@tonic-gate stx %g1, [%o1] 23710Sstevel@tonic-gate ldxa [%o0]ASI_DTLB_TAGREAD, %g2 23720Sstevel@tonic-gate set TAGREAD_CTX_MASK, %o4 23730Sstevel@tonic-gate andn %g2, %o4, %o5 23740Sstevel@tonic-gate retl 23750Sstevel@tonic-gate stx %o5, [%o2] 23760Sstevel@tonic-gate SET_SIZE(dtlb_rd_entry) 23770Sstevel@tonic-gate#endif /* lint */ 23780Sstevel@tonic-gate 23790Sstevel@tonic-gate 23800Sstevel@tonic-gate#if !(defined(JALAPENO) || defined(SERRANO)) 23810Sstevel@tonic-gate 23820Sstevel@tonic-gate#if defined(lint) 23830Sstevel@tonic-gate 23840Sstevel@tonic-gateuint64_t 23850Sstevel@tonic-gateget_safari_config(void) 23860Sstevel@tonic-gate{ return (0); } 23870Sstevel@tonic-gate 23880Sstevel@tonic-gate#else /* lint */ 23890Sstevel@tonic-gate 23900Sstevel@tonic-gate ENTRY(get_safari_config) 23910Sstevel@tonic-gate ldxa [%g0]ASI_SAFARI_CONFIG, %o0 23920Sstevel@tonic-gate retl 23930Sstevel@tonic-gate nop 23940Sstevel@tonic-gate SET_SIZE(get_safari_config) 23950Sstevel@tonic-gate 23960Sstevel@tonic-gate#endif /* lint */ 23970Sstevel@tonic-gate 23980Sstevel@tonic-gate 23990Sstevel@tonic-gate#if defined(lint) 24000Sstevel@tonic-gate 24010Sstevel@tonic-gate/* ARGSUSED */ 24020Sstevel@tonic-gatevoid 24030Sstevel@tonic-gateset_safari_config(uint64_t safari_config) 24040Sstevel@tonic-gate{} 24050Sstevel@tonic-gate 24060Sstevel@tonic-gate#else /* lint */ 24070Sstevel@tonic-gate 24080Sstevel@tonic-gate ENTRY(set_safari_config) 24090Sstevel@tonic-gate stxa %o0, [%g0]ASI_SAFARI_CONFIG 24100Sstevel@tonic-gate membar #Sync 24110Sstevel@tonic-gate retl 24120Sstevel@tonic-gate nop 24130Sstevel@tonic-gate SET_SIZE(set_safari_config) 24140Sstevel@tonic-gate 24150Sstevel@tonic-gate#endif /* lint */ 24160Sstevel@tonic-gate 24170Sstevel@tonic-gate#endif /* !(JALAPENO || SERRANO) */ 24180Sstevel@tonic-gate 24190Sstevel@tonic-gate 24200Sstevel@tonic-gate#if defined(lint) 24210Sstevel@tonic-gate 24220Sstevel@tonic-gatevoid 24230Sstevel@tonic-gatecpu_cleartickpnt(void) 24240Sstevel@tonic-gate{} 24250Sstevel@tonic-gate 24260Sstevel@tonic-gate#else /* lint */ 24270Sstevel@tonic-gate /* 24280Sstevel@tonic-gate * Clear the NPT (non-privileged trap) bit in the %tick/%stick 24290Sstevel@tonic-gate * registers. In an effort to make the change in the 24300Sstevel@tonic-gate * tick/stick counter as consistent as possible, we disable 24310Sstevel@tonic-gate * all interrupts while we're changing the registers. We also 24320Sstevel@tonic-gate * ensure that the read and write instructions are in the same 24330Sstevel@tonic-gate * line in the instruction cache. 24340Sstevel@tonic-gate */ 24350Sstevel@tonic-gate ENTRY_NP(cpu_clearticknpt) 24360Sstevel@tonic-gate rdpr %pstate, %g1 /* save processor state */ 24370Sstevel@tonic-gate andn %g1, PSTATE_IE, %g3 /* turn off */ 24380Sstevel@tonic-gate wrpr %g0, %g3, %pstate /* interrupts */ 24390Sstevel@tonic-gate rdpr %tick, %g2 /* get tick register */ 24400Sstevel@tonic-gate brgez,pn %g2, 1f /* if NPT bit off, we're done */ 24410Sstevel@tonic-gate mov 1, %g3 /* create mask */ 24420Sstevel@tonic-gate sllx %g3, 63, %g3 /* for NPT bit */ 24430Sstevel@tonic-gate ba,a,pt %xcc, 2f 24440Sstevel@tonic-gate .align 8 /* Ensure rd/wr in same i$ line */ 24450Sstevel@tonic-gate2: 24460Sstevel@tonic-gate rdpr %tick, %g2 /* get tick register */ 24470Sstevel@tonic-gate wrpr %g3, %g2, %tick /* write tick register, */ 24480Sstevel@tonic-gate /* clearing NPT bit */ 24490Sstevel@tonic-gate1: 24500Sstevel@tonic-gate rd STICK, %g2 /* get stick register */ 24510Sstevel@tonic-gate brgez,pn %g2, 3f /* if NPT bit off, we're done */ 24520Sstevel@tonic-gate mov 1, %g3 /* create mask */ 24530Sstevel@tonic-gate sllx %g3, 63, %g3 /* for NPT bit */ 24540Sstevel@tonic-gate ba,a,pt %xcc, 4f 24550Sstevel@tonic-gate .align 8 /* Ensure rd/wr in same i$ line */ 24560Sstevel@tonic-gate4: 24570Sstevel@tonic-gate rd STICK, %g2 /* get stick register */ 24580Sstevel@tonic-gate wr %g3, %g2, STICK /* write stick register, */ 24590Sstevel@tonic-gate /* clearing NPT bit */ 24600Sstevel@tonic-gate3: 24610Sstevel@tonic-gate jmp %g4 + 4 24620Sstevel@tonic-gate wrpr %g0, %g1, %pstate /* restore processor state */ 24630Sstevel@tonic-gate 24640Sstevel@tonic-gate SET_SIZE(cpu_clearticknpt) 24650Sstevel@tonic-gate 24660Sstevel@tonic-gate#endif /* lint */ 24670Sstevel@tonic-gate 24680Sstevel@tonic-gate 24690Sstevel@tonic-gate#if defined(CPU_IMP_L1_CACHE_PARITY) 24700Sstevel@tonic-gate 24710Sstevel@tonic-gate#if defined(lint) 24720Sstevel@tonic-gate/* 24730Sstevel@tonic-gate * correct_dcache_parity(size_t size, size_t linesize) 24740Sstevel@tonic-gate * 24750Sstevel@tonic-gate * Correct D$ data parity by zeroing the data and initializing microtag 24760Sstevel@tonic-gate * for all indexes and all ways of the D$. 24770Sstevel@tonic-gate * 24780Sstevel@tonic-gate */ 24790Sstevel@tonic-gate/* ARGSUSED */ 24800Sstevel@tonic-gatevoid 24810Sstevel@tonic-gatecorrect_dcache_parity(size_t size, size_t linesize) 24820Sstevel@tonic-gate{} 24830Sstevel@tonic-gate 24840Sstevel@tonic-gate#else /* lint */ 24850Sstevel@tonic-gate 24860Sstevel@tonic-gate ENTRY(correct_dcache_parity) 24870Sstevel@tonic-gate /* 24880Sstevel@tonic-gate * Register Usage: 24890Sstevel@tonic-gate * 24900Sstevel@tonic-gate * %o0 = input D$ size 24910Sstevel@tonic-gate * %o1 = input D$ line size 24920Sstevel@tonic-gate * %o2 = scratch 24930Sstevel@tonic-gate * %o3 = scratch 24940Sstevel@tonic-gate * %o4 = scratch 24950Sstevel@tonic-gate */ 24960Sstevel@tonic-gate 24970Sstevel@tonic-gate sub %o0, %o1, %o0 ! init cache line address 24980Sstevel@tonic-gate 24990Sstevel@tonic-gate /* 25000Sstevel@tonic-gate * For Panther CPUs, we also need to clear the data parity bits 25010Sstevel@tonic-gate * using DC_data_parity bit of the ASI_DCACHE_DATA register. 25020Sstevel@tonic-gate */ 25030Sstevel@tonic-gate GET_CPU_IMPL(%o3) 25040Sstevel@tonic-gate cmp %o3, PANTHER_IMPL 25050Sstevel@tonic-gate bne 1f 25060Sstevel@tonic-gate clr %o3 ! zero for non-Panther 25070Sstevel@tonic-gate mov 1, %o3 25080Sstevel@tonic-gate sll %o3, PN_DC_DATA_PARITY_BIT_SHIFT, %o3 25090Sstevel@tonic-gate 25100Sstevel@tonic-gate1: 25110Sstevel@tonic-gate /* 25120Sstevel@tonic-gate * Set utag = way since it must be unique within an index. 25130Sstevel@tonic-gate */ 25140Sstevel@tonic-gate srl %o0, 14, %o2 ! get cache way (DC_way) 25150Sstevel@tonic-gate membar #Sync ! required before ASI_DC_UTAG 25160Sstevel@tonic-gate stxa %o2, [%o0]ASI_DC_UTAG ! set D$ utag = cache way 25170Sstevel@tonic-gate membar #Sync ! required after ASI_DC_UTAG 25180Sstevel@tonic-gate 25190Sstevel@tonic-gate /* 25200Sstevel@tonic-gate * Zero line of D$ data (and data parity bits for Panther) 25210Sstevel@tonic-gate */ 25220Sstevel@tonic-gate sub %o1, 8, %o2 25230Sstevel@tonic-gate or %o0, %o3, %o4 ! same address + DC_data_parity 25240Sstevel@tonic-gate2: 25250Sstevel@tonic-gate membar #Sync ! required before ASI_DC_DATA 25260Sstevel@tonic-gate stxa %g0, [%o0 + %o2]ASI_DC_DATA ! zero 8 bytes of D$ data 25270Sstevel@tonic-gate membar #Sync ! required after ASI_DC_DATA 25280Sstevel@tonic-gate /* 25290Sstevel@tonic-gate * We also clear the parity bits if this is a panther. For non-Panther 25300Sstevel@tonic-gate * CPUs, we simply end up clearing the $data register twice. 25310Sstevel@tonic-gate */ 25320Sstevel@tonic-gate stxa %g0, [%o4 + %o2]ASI_DC_DATA 25330Sstevel@tonic-gate membar #Sync 25340Sstevel@tonic-gate 25350Sstevel@tonic-gate subcc %o2, 8, %o2 25360Sstevel@tonic-gate bge 2b 25370Sstevel@tonic-gate nop 25380Sstevel@tonic-gate 25390Sstevel@tonic-gate subcc %o0, %o1, %o0 25400Sstevel@tonic-gate bge 1b 25410Sstevel@tonic-gate nop 25420Sstevel@tonic-gate 25430Sstevel@tonic-gate retl 25440Sstevel@tonic-gate nop 25450Sstevel@tonic-gate SET_SIZE(correct_dcache_parity) 25460Sstevel@tonic-gate 25470Sstevel@tonic-gate#endif /* lint */ 25480Sstevel@tonic-gate 25490Sstevel@tonic-gate#endif /* CPU_IMP_L1_CACHE_PARITY */ 25500Sstevel@tonic-gate 25510Sstevel@tonic-gate 25520Sstevel@tonic-gate#if defined(lint) 25530Sstevel@tonic-gate/* 25540Sstevel@tonic-gate * Get timestamp (stick). 25550Sstevel@tonic-gate */ 25560Sstevel@tonic-gate/* ARGSUSED */ 25570Sstevel@tonic-gatevoid 25580Sstevel@tonic-gatestick_timestamp(int64_t *ts) 25590Sstevel@tonic-gate{ 25600Sstevel@tonic-gate} 25610Sstevel@tonic-gate 25620Sstevel@tonic-gate#else /* lint */ 25630Sstevel@tonic-gate 25640Sstevel@tonic-gate ENTRY_NP(stick_timestamp) 25650Sstevel@tonic-gate rd STICK, %g1 ! read stick reg 25660Sstevel@tonic-gate sllx %g1, 1, %g1 25670Sstevel@tonic-gate srlx %g1, 1, %g1 ! clear npt bit 25680Sstevel@tonic-gate 25690Sstevel@tonic-gate retl 25700Sstevel@tonic-gate stx %g1, [%o0] ! store the timestamp 25710Sstevel@tonic-gate SET_SIZE(stick_timestamp) 25720Sstevel@tonic-gate 25730Sstevel@tonic-gate#endif /* lint */ 25740Sstevel@tonic-gate 25750Sstevel@tonic-gate 25760Sstevel@tonic-gate#if defined(lint) 25770Sstevel@tonic-gate/* 25780Sstevel@tonic-gate * Set STICK adjusted by skew. 25790Sstevel@tonic-gate */ 25800Sstevel@tonic-gate/* ARGSUSED */ 25810Sstevel@tonic-gatevoid 25820Sstevel@tonic-gatestick_adj(int64_t skew) 25830Sstevel@tonic-gate{ 25840Sstevel@tonic-gate} 25850Sstevel@tonic-gate 25860Sstevel@tonic-gate#else /* lint */ 25870Sstevel@tonic-gate 25880Sstevel@tonic-gate ENTRY_NP(stick_adj) 25890Sstevel@tonic-gate rdpr %pstate, %g1 ! save processor state 25900Sstevel@tonic-gate andn %g1, PSTATE_IE, %g3 25910Sstevel@tonic-gate ba 1f ! cache align stick adj 25920Sstevel@tonic-gate wrpr %g0, %g3, %pstate ! turn off interrupts 25930Sstevel@tonic-gate 25940Sstevel@tonic-gate .align 16 25950Sstevel@tonic-gate1: nop 25960Sstevel@tonic-gate 25970Sstevel@tonic-gate rd STICK, %g4 ! read stick reg 25980Sstevel@tonic-gate add %g4, %o0, %o1 ! adjust stick with skew 25990Sstevel@tonic-gate wr %o1, %g0, STICK ! write stick reg 26000Sstevel@tonic-gate 26010Sstevel@tonic-gate retl 26020Sstevel@tonic-gate wrpr %g1, %pstate ! restore processor state 26030Sstevel@tonic-gate SET_SIZE(stick_adj) 26040Sstevel@tonic-gate 26050Sstevel@tonic-gate#endif /* lint */ 26060Sstevel@tonic-gate 26070Sstevel@tonic-gate#if defined(lint) 26080Sstevel@tonic-gate/* 26090Sstevel@tonic-gate * Debugger-specific stick retrieval 26100Sstevel@tonic-gate */ 26110Sstevel@tonic-gate/*ARGSUSED*/ 26120Sstevel@tonic-gateint 26130Sstevel@tonic-gatekdi_get_stick(uint64_t *stickp) 26140Sstevel@tonic-gate{ 26150Sstevel@tonic-gate return (0); 26160Sstevel@tonic-gate} 26170Sstevel@tonic-gate 26180Sstevel@tonic-gate#else /* lint */ 26190Sstevel@tonic-gate 26200Sstevel@tonic-gate ENTRY_NP(kdi_get_stick) 26210Sstevel@tonic-gate rd STICK, %g1 26220Sstevel@tonic-gate stx %g1, [%o0] 26230Sstevel@tonic-gate retl 26240Sstevel@tonic-gate mov %g0, %o0 26250Sstevel@tonic-gate SET_SIZE(kdi_get_stick) 26260Sstevel@tonic-gate 26270Sstevel@tonic-gate#endif /* lint */ 26280Sstevel@tonic-gate 26290Sstevel@tonic-gate#if defined(lint) 26300Sstevel@tonic-gate/* 26310Sstevel@tonic-gate * Invalidate the specified line from the D$. 26320Sstevel@tonic-gate * 26330Sstevel@tonic-gate * Register usage: 26340Sstevel@tonic-gate * %o0 - index for the invalidation, specifies DC_way and DC_addr 26350Sstevel@tonic-gate * 26360Sstevel@tonic-gate * ASI_DC_TAG, 0x47, is used in the following manner. A 64-bit value is 26370Sstevel@tonic-gate * stored to a particular DC_way and DC_addr in ASI_DC_TAG. 26380Sstevel@tonic-gate * 26390Sstevel@tonic-gate * The format of the stored 64-bit value is: 26400Sstevel@tonic-gate * 26410Sstevel@tonic-gate * +----------+--------+----------+ 26420Sstevel@tonic-gate * | Reserved | DC_tag | DC_valid | 26430Sstevel@tonic-gate * +----------+--------+----------+ 26440Sstevel@tonic-gate * 63 31 30 1 0 26450Sstevel@tonic-gate * 26460Sstevel@tonic-gate * DC_tag is the 30-bit physical tag of the associated line. 26470Sstevel@tonic-gate * DC_valid is the 1-bit valid field for both the physical and snoop tags. 26480Sstevel@tonic-gate * 26490Sstevel@tonic-gate * The format of the 64-bit DC_way and DC_addr into ASI_DC_TAG is: 26500Sstevel@tonic-gate * 26510Sstevel@tonic-gate * +----------+--------+----------+----------+ 26520Sstevel@tonic-gate * | Reserved | DC_way | DC_addr | Reserved | 26530Sstevel@tonic-gate * +----------+--------+----------+----------+ 26540Sstevel@tonic-gate * 63 16 15 14 13 5 4 0 26550Sstevel@tonic-gate * 26560Sstevel@tonic-gate * DC_way is a 2-bit index that selects one of the 4 ways. 26570Sstevel@tonic-gate * DC_addr is a 9-bit index that selects one of 512 tag/valid fields. 26580Sstevel@tonic-gate * 26590Sstevel@tonic-gate * Setting the DC_valid bit to zero for the specified DC_way and 26600Sstevel@tonic-gate * DC_addr index into the D$ results in an invalidation of a D$ line. 26610Sstevel@tonic-gate */ 26620Sstevel@tonic-gate/*ARGSUSED*/ 26630Sstevel@tonic-gatevoid 26640Sstevel@tonic-gatedcache_inval_line(int index) 26650Sstevel@tonic-gate{ 26660Sstevel@tonic-gate} 26670Sstevel@tonic-gate#else /* lint */ 26680Sstevel@tonic-gate ENTRY(dcache_inval_line) 26690Sstevel@tonic-gate sll %o0, 5, %o0 ! shift index into DC_way and DC_addr 26700Sstevel@tonic-gate stxa %g0, [%o0]ASI_DC_TAG ! zero the DC_valid and DC_tag bits 26710Sstevel@tonic-gate membar #Sync 26720Sstevel@tonic-gate retl 26730Sstevel@tonic-gate nop 26740Sstevel@tonic-gate SET_SIZE(dcache_inval_line) 26750Sstevel@tonic-gate#endif /* lint */ 26760Sstevel@tonic-gate 26770Sstevel@tonic-gate#if defined(lint) 26780Sstevel@tonic-gate/* 26790Sstevel@tonic-gate * Invalidate the entire I$ 26800Sstevel@tonic-gate * 26810Sstevel@tonic-gate * Register usage: 26820Sstevel@tonic-gate * %o0 - specifies IC_way, IC_addr, IC_tag 26830Sstevel@tonic-gate * %o1 - scratch 26840Sstevel@tonic-gate * %o2 - used to save and restore DCU value 26850Sstevel@tonic-gate * %o3 - scratch 26860Sstevel@tonic-gate * %o5 - used to save and restore PSTATE 26870Sstevel@tonic-gate * 26880Sstevel@tonic-gate * Due to the behavior of the I$ control logic when accessing ASI_IC_TAG, 26890Sstevel@tonic-gate * the I$ should be turned off. Accesses to ASI_IC_TAG may collide and 26900Sstevel@tonic-gate * block out snoops and invalidates to the I$, causing I$ consistency 26910Sstevel@tonic-gate * to be broken. Before turning on the I$, all I$ lines must be invalidated. 26920Sstevel@tonic-gate * 26930Sstevel@tonic-gate * ASI_IC_TAG, 0x67, is used in the following manner. A 64-bit value is 26940Sstevel@tonic-gate * stored to a particular IC_way, IC_addr, IC_tag in ASI_IC_TAG. The 26950Sstevel@tonic-gate * info below describes store (write) use of ASI_IC_TAG. Note that read 26960Sstevel@tonic-gate * use of ASI_IC_TAG behaves differently. 26970Sstevel@tonic-gate * 26980Sstevel@tonic-gate * The format of the stored 64-bit value is: 26990Sstevel@tonic-gate * 27000Sstevel@tonic-gate * +----------+--------+---------------+-----------+ 27010Sstevel@tonic-gate * | Reserved | Valid | IC_vpred<7:0> | Undefined | 27020Sstevel@tonic-gate * +----------+--------+---------------+-----------+ 27030Sstevel@tonic-gate * 63 55 54 53 46 45 0 27040Sstevel@tonic-gate * 27050Sstevel@tonic-gate * Valid is the 1-bit valid field for both the physical and snoop tags. 27060Sstevel@tonic-gate * IC_vpred is the 8-bit LPB bits for 8 instructions starting at 27070Sstevel@tonic-gate * the 32-byte boundary aligned address specified by IC_addr. 27080Sstevel@tonic-gate * 27090Sstevel@tonic-gate * The format of the 64-bit IC_way, IC_addr, IC_tag into ASI_IC_TAG is: 27100Sstevel@tonic-gate * 27110Sstevel@tonic-gate * +----------+--------+---------+--------+---------+ 27120Sstevel@tonic-gate * | Reserved | IC_way | IC_addr | IC_tag |Reserved | 27130Sstevel@tonic-gate * +----------+--------+---------+--------+---------+ 27140Sstevel@tonic-gate * 63 16 15 14 13 5 4 3 2 0 27150Sstevel@tonic-gate * 27160Sstevel@tonic-gate * IC_way is a 2-bit index that selects one of the 4 ways. 27170Sstevel@tonic-gate * IC_addr[13:6] is an 8-bit index that selects one of 256 valid fields. 27180Sstevel@tonic-gate * IC_addr[5] is a "don't care" for a store. 27190Sstevel@tonic-gate * IC_tag set to 2 specifies that the stored value is to be interpreted 27200Sstevel@tonic-gate * as containing Valid and IC_vpred as described above. 27210Sstevel@tonic-gate * 27220Sstevel@tonic-gate * Setting the Valid bit to zero for the specified IC_way and 27230Sstevel@tonic-gate * IC_addr index into the I$ results in an invalidation of an I$ line. 27240Sstevel@tonic-gate */ 27250Sstevel@tonic-gate/*ARGSUSED*/ 27260Sstevel@tonic-gatevoid 27270Sstevel@tonic-gateicache_inval_all(void) 27280Sstevel@tonic-gate{ 27290Sstevel@tonic-gate} 27300Sstevel@tonic-gate#else /* lint */ 27310Sstevel@tonic-gate ENTRY(icache_inval_all) 27320Sstevel@tonic-gate rdpr %pstate, %o5 27330Sstevel@tonic-gate andn %o5, PSTATE_IE, %o3 27340Sstevel@tonic-gate wrpr %g0, %o3, %pstate ! clear IE bit 27350Sstevel@tonic-gate 27360Sstevel@tonic-gate GET_CPU_PRIVATE_PTR(%g0, %o0, %o2, icache_inval_all_1); 27370Sstevel@tonic-gate ld [%o0 + CHPR_ICACHE_LINESIZE], %o1 27380Sstevel@tonic-gate ba,pt %icc, 2f 27390Sstevel@tonic-gate ld [%o0 + CHPR_ICACHE_SIZE], %o0 27400Sstevel@tonic-gateicache_inval_all_1: 27410Sstevel@tonic-gate ASM_LD(%o0, icache_size) 27420Sstevel@tonic-gate ASM_LD(%o1, icache_linesize) 27430Sstevel@tonic-gate2: 27440Sstevel@tonic-gate CH_ICACHE_FLUSHALL(%o0, %o1, %o2, %o4) 27450Sstevel@tonic-gate 27460Sstevel@tonic-gate retl 27470Sstevel@tonic-gate wrpr %g0, %o5, %pstate ! restore earlier pstate 27480Sstevel@tonic-gate SET_SIZE(icache_inval_all) 27490Sstevel@tonic-gate#endif /* lint */ 27500Sstevel@tonic-gate 27510Sstevel@tonic-gate 27520Sstevel@tonic-gate#if defined(lint) 27530Sstevel@tonic-gate/* ARGSUSED */ 27540Sstevel@tonic-gatevoid 27550Sstevel@tonic-gatecache_scrubreq_tl1(uint64_t inum, uint64_t index) 27560Sstevel@tonic-gate{ 27570Sstevel@tonic-gate} 27580Sstevel@tonic-gate 27590Sstevel@tonic-gate#else /* lint */ 27600Sstevel@tonic-gate/* 27610Sstevel@tonic-gate * cache_scrubreq_tl1 is the crosstrap handler called on offlined cpus via a 27620Sstevel@tonic-gate * crosstrap. It atomically increments the outstanding request counter and, 27630Sstevel@tonic-gate * if there was not already an outstanding request, branches to setsoftint_tl1 27642973Sgovinda * to enqueue an intr_vec for the given inum. 27650Sstevel@tonic-gate */ 27660Sstevel@tonic-gate 27670Sstevel@tonic-gate ! Register usage: 27680Sstevel@tonic-gate ! 27690Sstevel@tonic-gate ! Arguments: 27700Sstevel@tonic-gate ! %g1 - inum 27710Sstevel@tonic-gate ! %g2 - index into chsm_outstanding array 27720Sstevel@tonic-gate ! 27730Sstevel@tonic-gate ! Internal: 27740Sstevel@tonic-gate ! %g2, %g3, %g5 - scratch 27750Sstevel@tonic-gate ! %g4 - ptr. to scrub_misc chsm_outstanding[index]. 27760Sstevel@tonic-gate ! %g6 - setsoftint_tl1 address 27770Sstevel@tonic-gate 27780Sstevel@tonic-gate ENTRY_NP(cache_scrubreq_tl1) 27790Sstevel@tonic-gate mulx %g2, CHSM_OUTSTANDING_INCR, %g2 27800Sstevel@tonic-gate set CHPR_SCRUB_MISC + CHSM_OUTSTANDING, %g3 27810Sstevel@tonic-gate add %g2, %g3, %g2 27820Sstevel@tonic-gate GET_CPU_PRIVATE_PTR(%g2, %g4, %g5, 1f); 27830Sstevel@tonic-gate ld [%g4], %g2 ! cpu's chsm_outstanding[index] 27840Sstevel@tonic-gate ! 27850Sstevel@tonic-gate ! no need to use atomic instructions for the following 27860Sstevel@tonic-gate ! increment - we're at tl1 27870Sstevel@tonic-gate ! 27880Sstevel@tonic-gate add %g2, 0x1, %g3 27892973Sgovinda brnz,pn %g2, 1f ! no need to enqueue more intr_vec 27900Sstevel@tonic-gate st %g3, [%g4] ! delay - store incremented counter 27910Sstevel@tonic-gate ASM_JMP(%g6, setsoftint_tl1) 27920Sstevel@tonic-gate ! not reached 27930Sstevel@tonic-gate1: 27940Sstevel@tonic-gate retry 27950Sstevel@tonic-gate SET_SIZE(cache_scrubreq_tl1) 27960Sstevel@tonic-gate 27970Sstevel@tonic-gate#endif /* lint */ 27980Sstevel@tonic-gate 27990Sstevel@tonic-gate 28000Sstevel@tonic-gate#if defined(lint) 28010Sstevel@tonic-gate 28020Sstevel@tonic-gate/* ARGSUSED */ 28030Sstevel@tonic-gatevoid 28040Sstevel@tonic-gateget_cpu_error_state(ch_cpu_errors_t *cpu_error_regs) 28050Sstevel@tonic-gate{} 28060Sstevel@tonic-gate 28070Sstevel@tonic-gate#else /* lint */ 28080Sstevel@tonic-gate 28090Sstevel@tonic-gate/* 28100Sstevel@tonic-gate * Get the error state for the processor. 28110Sstevel@tonic-gate * Note that this must not be used at TL>0 28120Sstevel@tonic-gate */ 28130Sstevel@tonic-gate ENTRY(get_cpu_error_state) 28140Sstevel@tonic-gate#if defined(CHEETAH_PLUS) 28150Sstevel@tonic-gate set ASI_SHADOW_REG_VA, %o2 28160Sstevel@tonic-gate ldxa [%o2]ASI_AFSR, %o1 ! shadow afsr reg 28170Sstevel@tonic-gate stx %o1, [%o0 + CH_CPU_ERRORS_SHADOW_AFSR] 28180Sstevel@tonic-gate ldxa [%o2]ASI_AFAR, %o1 ! shadow afar reg 28190Sstevel@tonic-gate stx %o1, [%o0 + CH_CPU_ERRORS_SHADOW_AFAR] 28200Sstevel@tonic-gate GET_CPU_IMPL(%o3) ! Only panther has AFSR_EXT registers 28210Sstevel@tonic-gate cmp %o3, PANTHER_IMPL 28220Sstevel@tonic-gate bne,a 1f 28230Sstevel@tonic-gate stx %g0, [%o0 + CH_CPU_ERRORS_AFSR_EXT] ! zero for non-PN 28240Sstevel@tonic-gate set ASI_AFSR_EXT_VA, %o2 28250Sstevel@tonic-gate ldxa [%o2]ASI_AFSR, %o1 ! afsr_ext reg 28260Sstevel@tonic-gate stx %o1, [%o0 + CH_CPU_ERRORS_AFSR_EXT] 28270Sstevel@tonic-gate set ASI_SHADOW_AFSR_EXT_VA, %o2 28280Sstevel@tonic-gate ldxa [%o2]ASI_AFSR, %o1 ! shadow afsr_ext reg 28290Sstevel@tonic-gate stx %o1, [%o0 + CH_CPU_ERRORS_SHADOW_AFSR_EXT] 28300Sstevel@tonic-gate b 2f 28310Sstevel@tonic-gate nop 28320Sstevel@tonic-gate1: 28330Sstevel@tonic-gate stx %g0, [%o0 + CH_CPU_ERRORS_SHADOW_AFSR_EXT] ! zero for non-PN 28340Sstevel@tonic-gate2: 28350Sstevel@tonic-gate#else /* CHEETAH_PLUS */ 28360Sstevel@tonic-gate stx %g0, [%o0 + CH_CPU_ERRORS_SHADOW_AFSR] 28370Sstevel@tonic-gate stx %g0, [%o0 + CH_CPU_ERRORS_SHADOW_AFAR] 28380Sstevel@tonic-gate stx %g0, [%o0 + CH_CPU_ERRORS_AFSR_EXT] 28390Sstevel@tonic-gate stx %g0, [%o0 + CH_CPU_ERRORS_SHADOW_AFSR_EXT] 28400Sstevel@tonic-gate#endif /* CHEETAH_PLUS */ 28410Sstevel@tonic-gate#if defined(SERRANO) 28420Sstevel@tonic-gate /* 28430Sstevel@tonic-gate * Serrano has an afar2 which captures the address on FRC/FRU errors. 28440Sstevel@tonic-gate * We save this in the afar2 of the register save area. 28450Sstevel@tonic-gate */ 28460Sstevel@tonic-gate set ASI_MCU_AFAR2_VA, %o2 28470Sstevel@tonic-gate ldxa [%o2]ASI_MCU_CTRL, %o1 28480Sstevel@tonic-gate stx %o1, [%o0 + CH_CPU_ERRORS_AFAR2] 28490Sstevel@tonic-gate#endif /* SERRANO */ 28500Sstevel@tonic-gate ldxa [%g0]ASI_AFSR, %o1 ! primary afsr reg 28510Sstevel@tonic-gate stx %o1, [%o0 + CH_CPU_ERRORS_AFSR] 28520Sstevel@tonic-gate ldxa [%g0]ASI_AFAR, %o1 ! primary afar reg 28530Sstevel@tonic-gate retl 28540Sstevel@tonic-gate stx %o1, [%o0 + CH_CPU_ERRORS_AFAR] 28550Sstevel@tonic-gate SET_SIZE(get_cpu_error_state) 28560Sstevel@tonic-gate#endif /* lint */ 28570Sstevel@tonic-gate 28580Sstevel@tonic-gate#if defined(lint) 28590Sstevel@tonic-gate 28600Sstevel@tonic-gate/* 28610Sstevel@tonic-gate * Check a page of memory for errors. 28620Sstevel@tonic-gate * 28630Sstevel@tonic-gate * Load each 64 byte block from physical memory. 28640Sstevel@tonic-gate * Check AFSR after each load to see if an error 28650Sstevel@tonic-gate * was caused. If so, log/scrub that error. 28660Sstevel@tonic-gate * 28670Sstevel@tonic-gate * Used to determine if a page contains 28680Sstevel@tonic-gate * CEs when CEEN is disabled. 28690Sstevel@tonic-gate */ 28700Sstevel@tonic-gate/*ARGSUSED*/ 28710Sstevel@tonic-gatevoid 28720Sstevel@tonic-gatecpu_check_block(caddr_t va, uint_t psz) 28730Sstevel@tonic-gate{} 28740Sstevel@tonic-gate 28750Sstevel@tonic-gate#else /* lint */ 28760Sstevel@tonic-gate 28770Sstevel@tonic-gate ENTRY(cpu_check_block) 28780Sstevel@tonic-gate ! 28790Sstevel@tonic-gate ! get a new window with room for the error regs 28800Sstevel@tonic-gate ! 28810Sstevel@tonic-gate save %sp, -SA(MINFRAME + CH_CPU_ERROR_SIZE), %sp 28820Sstevel@tonic-gate srl %i1, 6, %l4 ! clear top bits of psz 28830Sstevel@tonic-gate ! and divide by 64 28840Sstevel@tonic-gate rd %fprs, %l2 ! store FP 28850Sstevel@tonic-gate wr %g0, FPRS_FEF, %fprs ! enable FP 28860Sstevel@tonic-gate1: 28870Sstevel@tonic-gate ldda [%i0]ASI_BLK_P, %d0 ! load a block 28880Sstevel@tonic-gate membar #Sync 28890Sstevel@tonic-gate ldxa [%g0]ASI_AFSR, %l3 ! read afsr reg 28900Sstevel@tonic-gate brz,a,pt %l3, 2f ! check for error 28910Sstevel@tonic-gate nop 28920Sstevel@tonic-gate 28930Sstevel@tonic-gate ! 28940Sstevel@tonic-gate ! if error, read the error regs and log it 28950Sstevel@tonic-gate ! 28960Sstevel@tonic-gate call get_cpu_error_state 28970Sstevel@tonic-gate add %fp, STACK_BIAS - CH_CPU_ERROR_SIZE, %o0 28980Sstevel@tonic-gate 28990Sstevel@tonic-gate ! 29000Sstevel@tonic-gate ! cpu_ce_detected(ch_cpu_errors_t *, flag) 29010Sstevel@tonic-gate ! 29020Sstevel@tonic-gate call cpu_ce_detected ! log the error 29030Sstevel@tonic-gate mov CE_CEEN_TIMEOUT, %o1 29040Sstevel@tonic-gate2: 29050Sstevel@tonic-gate dec %l4 ! next 64-byte block 29060Sstevel@tonic-gate brnz,a,pt %l4, 1b 29070Sstevel@tonic-gate add %i0, 64, %i0 ! increment block addr 29080Sstevel@tonic-gate 29090Sstevel@tonic-gate wr %l2, %g0, %fprs ! restore FP 29100Sstevel@tonic-gate ret 29110Sstevel@tonic-gate restore 29120Sstevel@tonic-gate 29130Sstevel@tonic-gate SET_SIZE(cpu_check_block) 29140Sstevel@tonic-gate 29150Sstevel@tonic-gate#endif /* lint */ 29160Sstevel@tonic-gate 29170Sstevel@tonic-gate#if defined(lint) 29180Sstevel@tonic-gate 29190Sstevel@tonic-gate/* 29200Sstevel@tonic-gate * Perform a cpu logout called from C. This is used where we did not trap 29210Sstevel@tonic-gate * for the error but still want to gather "what we can". Caller must make 29220Sstevel@tonic-gate * sure cpu private area exists and that the indicated logout area is free 29230Sstevel@tonic-gate * for use, and that we are unable to migrate cpus. 29240Sstevel@tonic-gate */ 29250Sstevel@tonic-gate/*ARGSUSED*/ 29260Sstevel@tonic-gatevoid 29270Sstevel@tonic-gatecpu_delayed_logout(uint64_t afar, ch_cpu_logout_t *clop) 29280Sstevel@tonic-gate{ } 29290Sstevel@tonic-gate 29300Sstevel@tonic-gate#else 29310Sstevel@tonic-gate ENTRY(cpu_delayed_logout) 29320Sstevel@tonic-gate rdpr %pstate, %o2 29330Sstevel@tonic-gate andn %o2, PSTATE_IE, %o2 29340Sstevel@tonic-gate wrpr %g0, %o2, %pstate ! disable interrupts 29350Sstevel@tonic-gate PARK_SIBLING_CORE(%o2, %o3, %o4) ! %o2 has DCU value 29360Sstevel@tonic-gate add %o1, CH_CLO_DATA + CH_CHD_EC_DATA, %o1 29370Sstevel@tonic-gate rd %asi, %g1 29380Sstevel@tonic-gate wr %g0, ASI_P, %asi 29390Sstevel@tonic-gate GET_ECACHE_DTAGS(%o0, %o1, %o3, %o4, %o5) 29400Sstevel@tonic-gate wr %g1, %asi 29410Sstevel@tonic-gate UNPARK_SIBLING_CORE(%o2, %o3, %o4) ! can use %o2 again 29420Sstevel@tonic-gate rdpr %pstate, %o2 29430Sstevel@tonic-gate or %o2, PSTATE_IE, %o2 29440Sstevel@tonic-gate wrpr %g0, %o2, %pstate 29450Sstevel@tonic-gate retl 29460Sstevel@tonic-gate nop 29470Sstevel@tonic-gate SET_SIZE(cpu_delayed_logout) 29480Sstevel@tonic-gate 29490Sstevel@tonic-gate#endif /* lint */ 29500Sstevel@tonic-gate 29510Sstevel@tonic-gate#if defined(lint) 29520Sstevel@tonic-gate 29530Sstevel@tonic-gate/*ARGSUSED*/ 29540Sstevel@tonic-gateint 29550Sstevel@tonic-gatedtrace_blksuword32(uintptr_t addr, uint32_t *data, int tryagain) 29560Sstevel@tonic-gate{ return (0); } 29570Sstevel@tonic-gate 29580Sstevel@tonic-gate#else 29590Sstevel@tonic-gate 29600Sstevel@tonic-gate ENTRY(dtrace_blksuword32) 29610Sstevel@tonic-gate save %sp, -SA(MINFRAME + 4), %sp 29620Sstevel@tonic-gate 29630Sstevel@tonic-gate rdpr %pstate, %l1 29640Sstevel@tonic-gate andn %l1, PSTATE_IE, %l2 ! disable interrupts to 29650Sstevel@tonic-gate wrpr %g0, %l2, %pstate ! protect our FPU diddling 29660Sstevel@tonic-gate 29670Sstevel@tonic-gate rd %fprs, %l0 29680Sstevel@tonic-gate andcc %l0, FPRS_FEF, %g0 29690Sstevel@tonic-gate bz,a,pt %xcc, 1f ! if the fpu is disabled 29700Sstevel@tonic-gate wr %g0, FPRS_FEF, %fprs ! ... enable the fpu 29710Sstevel@tonic-gate 29720Sstevel@tonic-gate st %f0, [%fp + STACK_BIAS - 4] ! save %f0 to the stack 29730Sstevel@tonic-gate1: 29740Sstevel@tonic-gate set 0f, %l5 29750Sstevel@tonic-gate /* 29760Sstevel@tonic-gate * We're about to write a block full or either total garbage 29770Sstevel@tonic-gate * (not kernel data, don't worry) or user floating-point data 29780Sstevel@tonic-gate * (so it only _looks_ like garbage). 29790Sstevel@tonic-gate */ 29800Sstevel@tonic-gate ld [%i1], %f0 ! modify the block 29810Sstevel@tonic-gate membar #Sync 29820Sstevel@tonic-gate stn %l5, [THREAD_REG + T_LOFAULT] ! set up the lofault handler 29830Sstevel@tonic-gate stda %d0, [%i0]ASI_BLK_COMMIT_S ! store the modified block 29840Sstevel@tonic-gate membar #Sync 29850Sstevel@tonic-gate stn %g0, [THREAD_REG + T_LOFAULT] ! remove the lofault handler 29860Sstevel@tonic-gate 29870Sstevel@tonic-gate bz,a,pt %xcc, 1f 29880Sstevel@tonic-gate wr %g0, %l0, %fprs ! restore %fprs 29890Sstevel@tonic-gate 29900Sstevel@tonic-gate ld [%fp + STACK_BIAS - 4], %f0 ! restore %f0 29910Sstevel@tonic-gate1: 29920Sstevel@tonic-gate 29930Sstevel@tonic-gate wrpr %g0, %l1, %pstate ! restore interrupts 29940Sstevel@tonic-gate 29950Sstevel@tonic-gate ret 29960Sstevel@tonic-gate restore %g0, %g0, %o0 29970Sstevel@tonic-gate 29980Sstevel@tonic-gate0: 29990Sstevel@tonic-gate membar #Sync 30000Sstevel@tonic-gate stn %g0, [THREAD_REG + T_LOFAULT] ! remove the lofault handler 30010Sstevel@tonic-gate 30020Sstevel@tonic-gate bz,a,pt %xcc, 1f 30030Sstevel@tonic-gate wr %g0, %l0, %fprs ! restore %fprs 30040Sstevel@tonic-gate 30050Sstevel@tonic-gate ld [%fp + STACK_BIAS - 4], %f0 ! restore %f0 30060Sstevel@tonic-gate1: 30070Sstevel@tonic-gate 30080Sstevel@tonic-gate wrpr %g0, %l1, %pstate ! restore interrupts 30090Sstevel@tonic-gate 30100Sstevel@tonic-gate /* 30110Sstevel@tonic-gate * If tryagain is set (%i2) we tail-call dtrace_blksuword32_err() 30120Sstevel@tonic-gate * which deals with watchpoints. Otherwise, just return -1. 30130Sstevel@tonic-gate */ 30140Sstevel@tonic-gate brnz,pt %i2, 1f 30150Sstevel@tonic-gate nop 30160Sstevel@tonic-gate ret 30170Sstevel@tonic-gate restore %g0, -1, %o0 30180Sstevel@tonic-gate1: 30190Sstevel@tonic-gate call dtrace_blksuword32_err 30200Sstevel@tonic-gate restore 30210Sstevel@tonic-gate 30220Sstevel@tonic-gate SET_SIZE(dtrace_blksuword32) 30230Sstevel@tonic-gate 30240Sstevel@tonic-gate#endif /* lint */ 30250Sstevel@tonic-gate 30260Sstevel@tonic-gate#ifdef CHEETAHPLUS_ERRATUM_25 30270Sstevel@tonic-gate 30280Sstevel@tonic-gate#if defined(lint) 30290Sstevel@tonic-gate/* 30300Sstevel@tonic-gate * Claim a chunk of physical address space. 30310Sstevel@tonic-gate */ 30320Sstevel@tonic-gate/*ARGSUSED*/ 30330Sstevel@tonic-gatevoid 30340Sstevel@tonic-gateclaimlines(uint64_t pa, size_t sz, int stride) 30350Sstevel@tonic-gate{} 30360Sstevel@tonic-gate#else /* lint */ 30370Sstevel@tonic-gate ENTRY(claimlines) 30380Sstevel@tonic-gate1: 30390Sstevel@tonic-gate subcc %o1, %o2, %o1 30400Sstevel@tonic-gate add %o0, %o1, %o3 30410Sstevel@tonic-gate bgeu,a,pt %xcc, 1b 30420Sstevel@tonic-gate casxa [%o3]ASI_MEM, %g0, %g0 30430Sstevel@tonic-gate membar #Sync 30440Sstevel@tonic-gate retl 30450Sstevel@tonic-gate nop 30460Sstevel@tonic-gate SET_SIZE(claimlines) 30470Sstevel@tonic-gate#endif /* lint */ 30480Sstevel@tonic-gate 30490Sstevel@tonic-gate#if defined(lint) 30500Sstevel@tonic-gate/* 30510Sstevel@tonic-gate * CPU feature initialization, 30520Sstevel@tonic-gate * turn BPE off, 30530Sstevel@tonic-gate * get device id. 30540Sstevel@tonic-gate */ 30550Sstevel@tonic-gate/*ARGSUSED*/ 30560Sstevel@tonic-gatevoid 30570Sstevel@tonic-gatecpu_feature_init(void) 30580Sstevel@tonic-gate{} 30590Sstevel@tonic-gate#else /* lint */ 30600Sstevel@tonic-gate ENTRY(cpu_feature_init) 30610Sstevel@tonic-gate save %sp, -SA(MINFRAME), %sp 30620Sstevel@tonic-gate sethi %hi(cheetah_bpe_off), %o0 30630Sstevel@tonic-gate ld [%o0 + %lo(cheetah_bpe_off)], %o0 30640Sstevel@tonic-gate brz %o0, 1f 30650Sstevel@tonic-gate nop 30660Sstevel@tonic-gate rd ASR_DISPATCH_CONTROL, %o0 30670Sstevel@tonic-gate andn %o0, ASR_DISPATCH_CONTROL_BPE, %o0 30680Sstevel@tonic-gate wr %o0, 0, ASR_DISPATCH_CONTROL 30690Sstevel@tonic-gate1: 30700Sstevel@tonic-gate ! 30710Sstevel@tonic-gate ! get the device_id and store the device_id 30720Sstevel@tonic-gate ! in the appropriate cpunodes structure 30730Sstevel@tonic-gate ! given the cpus index 30740Sstevel@tonic-gate ! 30750Sstevel@tonic-gate CPU_INDEX(%o0, %o1) 30760Sstevel@tonic-gate mulx %o0, CPU_NODE_SIZE, %o0 30770Sstevel@tonic-gate set cpunodes + DEVICE_ID, %o1 30780Sstevel@tonic-gate ldxa [%g0] ASI_DEVICE_SERIAL_ID, %o2 30790Sstevel@tonic-gate stx %o2, [%o0 + %o1] 30800Sstevel@tonic-gate#ifdef CHEETAHPLUS_ERRATUM_34 30810Sstevel@tonic-gate ! 30820Sstevel@tonic-gate ! apply Cheetah+ erratum 34 workaround 30830Sstevel@tonic-gate ! 30840Sstevel@tonic-gate call itlb_erratum34_fixup 30850Sstevel@tonic-gate nop 30866674Sjfrank call dtlb_erratum34_fixup 30876674Sjfrank nop 30880Sstevel@tonic-gate#endif /* CHEETAHPLUS_ERRATUM_34 */ 30890Sstevel@tonic-gate ret 30900Sstevel@tonic-gate restore 30910Sstevel@tonic-gate SET_SIZE(cpu_feature_init) 30920Sstevel@tonic-gate#endif /* lint */ 30930Sstevel@tonic-gate 30940Sstevel@tonic-gate#if defined(lint) 30950Sstevel@tonic-gate/* 30960Sstevel@tonic-gate * Copy a tsb entry atomically, from src to dest. 30970Sstevel@tonic-gate * src must be 128 bit aligned. 30980Sstevel@tonic-gate */ 30990Sstevel@tonic-gate/*ARGSUSED*/ 31000Sstevel@tonic-gatevoid 31010Sstevel@tonic-gatecopy_tsb_entry(uintptr_t src, uintptr_t dest) 31020Sstevel@tonic-gate{} 31030Sstevel@tonic-gate#else /* lint */ 31040Sstevel@tonic-gate ENTRY(copy_tsb_entry) 31050Sstevel@tonic-gate ldda [%o0]ASI_NQUAD_LD, %o2 ! %o2 = tag, %o3 = data 31060Sstevel@tonic-gate stx %o2, [%o1] 31070Sstevel@tonic-gate stx %o3, [%o1 + 8 ] 31080Sstevel@tonic-gate retl 31090Sstevel@tonic-gate nop 31100Sstevel@tonic-gate SET_SIZE(copy_tsb_entry) 31110Sstevel@tonic-gate#endif /* lint */ 31120Sstevel@tonic-gate 31130Sstevel@tonic-gate#endif /* CHEETAHPLUS_ERRATUM_25 */ 31140Sstevel@tonic-gate 31150Sstevel@tonic-gate#ifdef CHEETAHPLUS_ERRATUM_34 31160Sstevel@tonic-gate 31170Sstevel@tonic-gate#if defined(lint) 31180Sstevel@tonic-gate 31190Sstevel@tonic-gate/*ARGSUSED*/ 31200Sstevel@tonic-gatevoid 31210Sstevel@tonic-gateitlb_erratum34_fixup(void) 31220Sstevel@tonic-gate{} 31230Sstevel@tonic-gate 31240Sstevel@tonic-gate#else /* lint */ 31250Sstevel@tonic-gate 31260Sstevel@tonic-gate ! 31270Sstevel@tonic-gate ! In Cheetah+ erratum 34, under certain conditions an ITLB locked 31280Sstevel@tonic-gate ! index 0 TTE will erroneously be displaced when a new TTE is 31290Sstevel@tonic-gate ! loaded via ASI_ITLB_IN. In order to avoid cheetah+ erratum 34, 31300Sstevel@tonic-gate ! locked index 0 TTEs must be relocated. 31310Sstevel@tonic-gate ! 31320Sstevel@tonic-gate ! NOTE: Care must be taken to avoid an ITLB miss in this routine. 31330Sstevel@tonic-gate ! 31340Sstevel@tonic-gate ENTRY_NP(itlb_erratum34_fixup) 31350Sstevel@tonic-gate rdpr %pstate, %o3 31360Sstevel@tonic-gate#ifdef DEBUG 31372241Shuah PANIC_IF_INTR_DISABLED_PSTR(%o3, u3_di_label1, %g1) 31380Sstevel@tonic-gate#endif /* DEBUG */ 31390Sstevel@tonic-gate wrpr %o3, PSTATE_IE, %pstate ! Disable interrupts 31400Sstevel@tonic-gate ldxa [%g0]ASI_ITLB_ACCESS, %o1 ! %o1 = entry 0 data 31410Sstevel@tonic-gate ldxa [%g0]ASI_ITLB_TAGREAD, %o2 ! %o2 = entry 0 tag 31420Sstevel@tonic-gate 31430Sstevel@tonic-gate cmp %o1, %g0 ! Is this entry valid? 31440Sstevel@tonic-gate bge %xcc, 1f 31450Sstevel@tonic-gate andcc %o1, TTE_LCK_INT, %g0 ! Is this entry locked? 31460Sstevel@tonic-gate bnz %icc, 2f 31470Sstevel@tonic-gate nop 31480Sstevel@tonic-gate1: 31490Sstevel@tonic-gate retl ! Nope, outta here... 31500Sstevel@tonic-gate wrpr %g0, %o3, %pstate ! Enable interrupts 31510Sstevel@tonic-gate2: 31520Sstevel@tonic-gate sethi %hi(FLUSH_ADDR), %o4 31530Sstevel@tonic-gate stxa %g0, [%o2]ASI_ITLB_DEMAP ! Flush this mapping 31540Sstevel@tonic-gate flush %o4 ! Flush required for I-MMU 31550Sstevel@tonic-gate ! 31560Sstevel@tonic-gate ! Start search from index 1 up. This is because the kernel force 31570Sstevel@tonic-gate ! loads its text page at index 15 in sfmmu_kernel_remap() and we 31580Sstevel@tonic-gate ! don't want our relocated entry evicted later. 31590Sstevel@tonic-gate ! 31600Sstevel@tonic-gate ! NOTE: We assume that we'll be successful in finding an unlocked 31610Sstevel@tonic-gate ! or invalid entry. If that isn't the case there are bound to 31620Sstevel@tonic-gate ! bigger problems. 31630Sstevel@tonic-gate ! 31640Sstevel@tonic-gate set (1 << 3), %g3 31650Sstevel@tonic-gate3: 31660Sstevel@tonic-gate ldxa [%g3]ASI_ITLB_ACCESS, %o4 ! Load TTE from t16 31670Sstevel@tonic-gate ! 31680Sstevel@tonic-gate ! If this entry isn't valid, we'll choose to displace it (regardless 31690Sstevel@tonic-gate ! of the lock bit). 31700Sstevel@tonic-gate ! 31710Sstevel@tonic-gate cmp %o4, %g0 ! TTE is > 0 iff not valid 31720Sstevel@tonic-gate bge %xcc, 4f ! If invalid, go displace 31730Sstevel@tonic-gate andcc %o4, TTE_LCK_INT, %g0 ! Check for lock bit 31740Sstevel@tonic-gate bnz,a %icc, 3b ! If locked, look at next 31750Sstevel@tonic-gate add %g3, (1 << 3), %g3 ! entry 31760Sstevel@tonic-gate4: 31770Sstevel@tonic-gate ! 31780Sstevel@tonic-gate ! We found an unlocked or invalid entry; we'll explicitly load 31790Sstevel@tonic-gate ! the former index 0 entry here. 31800Sstevel@tonic-gate ! 31810Sstevel@tonic-gate sethi %hi(FLUSH_ADDR), %o4 31820Sstevel@tonic-gate set MMU_TAG_ACCESS, %g4 31830Sstevel@tonic-gate stxa %o2, [%g4]ASI_IMMU 31840Sstevel@tonic-gate stxa %o1, [%g3]ASI_ITLB_ACCESS 31850Sstevel@tonic-gate flush %o4 ! Flush required for I-MMU 31860Sstevel@tonic-gate retl 31870Sstevel@tonic-gate wrpr %g0, %o3, %pstate ! Enable interrupts 31880Sstevel@tonic-gate SET_SIZE(itlb_erratum34_fixup) 31890Sstevel@tonic-gate 31900Sstevel@tonic-gate#endif /* lint */ 31910Sstevel@tonic-gate 31926674Sjfrank#if defined(lint) 31936674Sjfrank 31946674Sjfrank/*ARGSUSED*/ 31956674Sjfrankvoid 31966674Sjfrankdtlb_erratum34_fixup(void) 31976674Sjfrank{} 31986674Sjfrank 31996674Sjfrank#else /* lint */ 32006674Sjfrank 32016674Sjfrank ! 32026674Sjfrank ! In Cheetah+ erratum 34, under certain conditions a DTLB locked 32036674Sjfrank ! index 0 TTE will erroneously be displaced when a new TTE is 32046674Sjfrank ! loaded. In order to avoid cheetah+ erratum 34, locked index 0 32056674Sjfrank ! TTEs must be relocated. 32066674Sjfrank ! 32076674Sjfrank ENTRY_NP(dtlb_erratum34_fixup) 32086674Sjfrank rdpr %pstate, %o3 32096674Sjfrank#ifdef DEBUG 32106674Sjfrank PANIC_IF_INTR_DISABLED_PSTR(%o3, u3_di_label2, %g1) 32116674Sjfrank#endif /* DEBUG */ 32126674Sjfrank wrpr %o3, PSTATE_IE, %pstate ! Disable interrupts 32136674Sjfrank ldxa [%g0]ASI_DTLB_ACCESS, %o1 ! %o1 = entry 0 data 32146674Sjfrank ldxa [%g0]ASI_DTLB_TAGREAD, %o2 ! %o2 = entry 0 tag 32156674Sjfrank 32166674Sjfrank cmp %o1, %g0 ! Is this entry valid? 32176674Sjfrank bge %xcc, 1f 32186674Sjfrank andcc %o1, TTE_LCK_INT, %g0 ! Is this entry locked? 32196674Sjfrank bnz %icc, 2f 32206674Sjfrank nop 32216674Sjfrank1: 32226674Sjfrank retl ! Nope, outta here... 32236674Sjfrank wrpr %g0, %o3, %pstate ! Enable interrupts 32246674Sjfrank2: 32256674Sjfrank stxa %g0, [%o2]ASI_DTLB_DEMAP ! Flush this mapping 32266674Sjfrank membar #Sync 32276674Sjfrank ! 32286674Sjfrank ! Start search from index 1 up. 32296674Sjfrank ! 32306674Sjfrank ! NOTE: We assume that we'll be successful in finding an unlocked 32316674Sjfrank ! or invalid entry. If that isn't the case there are bound to 32326674Sjfrank ! bigger problems. 32336674Sjfrank ! 32346674Sjfrank set (1 << 3), %g3 32356674Sjfrank3: 32366674Sjfrank ldxa [%g3]ASI_DTLB_ACCESS, %o4 ! Load TTE from t16 32376674Sjfrank ! 32386674Sjfrank ! If this entry isn't valid, we'll choose to displace it (regardless 32396674Sjfrank ! of the lock bit). 32406674Sjfrank ! 32416674Sjfrank cmp %o4, %g0 ! TTE is > 0 iff not valid 32426674Sjfrank bge %xcc, 4f ! If invalid, go displace 32436674Sjfrank andcc %o4, TTE_LCK_INT, %g0 ! Check for lock bit 32446674Sjfrank bnz,a %icc, 3b ! If locked, look at next 32456674Sjfrank add %g3, (1 << 3), %g3 ! entry 32466674Sjfrank4: 32476674Sjfrank ! 32486674Sjfrank ! We found an unlocked or invalid entry; we'll explicitly load 32496674Sjfrank ! the former index 0 entry here. 32506674Sjfrank ! 32516674Sjfrank set MMU_TAG_ACCESS, %g4 32526674Sjfrank stxa %o2, [%g4]ASI_DMMU 32536674Sjfrank stxa %o1, [%g3]ASI_DTLB_ACCESS 32546674Sjfrank membar #Sync 32556674Sjfrank retl 32566674Sjfrank wrpr %g0, %o3, %pstate ! Enable interrupts 32576674Sjfrank SET_SIZE(dtlb_erratum34_fixup) 32586674Sjfrank 32596674Sjfrank#endif /* lint */ 32606674Sjfrank 32610Sstevel@tonic-gate#endif /* CHEETAHPLUS_ERRATUM_34 */ 32620Sstevel@tonic-gate 3263