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 50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 70Sstevel@tonic-gate * with the License. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate * See the License for the specific language governing permissions 120Sstevel@tonic-gate * and limitations under the License. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * CDDL HEADER END 210Sstevel@tonic-gate */ 220Sstevel@tonic-gate/* 23*4567Sanbui * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate * 260Sstevel@tonic-gate * Assembly code support for the Cheetah module 270Sstevel@tonic-gate */ 280Sstevel@tonic-gate 290Sstevel@tonic-gate#pragma ident "%Z%%M% %I% %E% SMI" 300Sstevel@tonic-gate 310Sstevel@tonic-gate#if !defined(lint) 320Sstevel@tonic-gate#include "assym.h" 330Sstevel@tonic-gate#endif /* lint */ 340Sstevel@tonic-gate 350Sstevel@tonic-gate#include <sys/asm_linkage.h> 360Sstevel@tonic-gate#include <sys/mmu.h> 370Sstevel@tonic-gate#include <vm/hat_sfmmu.h> 380Sstevel@tonic-gate#include <sys/machparam.h> 390Sstevel@tonic-gate#include <sys/machcpuvar.h> 400Sstevel@tonic-gate#include <sys/machthread.h> 410Sstevel@tonic-gate#include <sys/machtrap.h> 420Sstevel@tonic-gate#include <sys/privregs.h> 430Sstevel@tonic-gate#include <sys/asm_linkage.h> 440Sstevel@tonic-gate#include <sys/trap.h> 450Sstevel@tonic-gate#include <sys/cheetahregs.h> 460Sstevel@tonic-gate#include <sys/us3_module.h> 470Sstevel@tonic-gate#include <sys/xc_impl.h> 480Sstevel@tonic-gate#include <sys/intreg.h> 490Sstevel@tonic-gate#include <sys/async.h> 500Sstevel@tonic-gate#include <sys/clock.h> 510Sstevel@tonic-gate#include <sys/cheetahasm.h> 520Sstevel@tonic-gate 530Sstevel@tonic-gate#ifdef TRAPTRACE 540Sstevel@tonic-gate#include <sys/traptrace.h> 550Sstevel@tonic-gate#endif /* TRAPTRACE */ 560Sstevel@tonic-gate 570Sstevel@tonic-gate#if !defined(lint) 580Sstevel@tonic-gate 590Sstevel@tonic-gate/* BEGIN CSTYLED */ 600Sstevel@tonic-gate 610Sstevel@tonic-gate/* 620Sstevel@tonic-gate * Cheetah version to flush an Ecache line by index (aliased address) 630Sstevel@tonic-gate */ 640Sstevel@tonic-gate#define ECACHE_REFLUSH_LINE(ecache_size, alias_address, scr2) \ 650Sstevel@tonic-gate ldxa [alias_address]ASI_MEM, %g0 660Sstevel@tonic-gate 670Sstevel@tonic-gate#define ECACHE_FLUSH_LINE(physaddr, ecache_size, scr1, scr2) \ 680Sstevel@tonic-gate xor physaddr, ecache_size, scr1; \ 690Sstevel@tonic-gate add ecache_size, ecache_size, scr2; \ 700Sstevel@tonic-gate sub scr2, 1, scr2; \ 710Sstevel@tonic-gate and scr1, scr2, scr1; \ 720Sstevel@tonic-gate ASM_LDX(scr2, ecache_flushaddr); \ 730Sstevel@tonic-gate add scr1, scr2, scr1; \ 740Sstevel@tonic-gate ECACHE_REFLUSH_LINE(ecache_size, scr1, scr2) 750Sstevel@tonic-gate 760Sstevel@tonic-gate/* END CSTYLED */ 770Sstevel@tonic-gate 780Sstevel@tonic-gate#endif /* !lint */ 790Sstevel@tonic-gate 800Sstevel@tonic-gate 810Sstevel@tonic-gate/* 820Sstevel@tonic-gate * Fast ECC error at TL>0 handler 830Sstevel@tonic-gate * We get here via trap 70 at TL>0->Software trap 0 at TL>0. We enter 840Sstevel@tonic-gate * this routine with %g1 and %g2 already saved in %tpc, %tnpc and %tstate. 850Sstevel@tonic-gate * For a complete description of the Fast ECC at TL>0 handling see the 860Sstevel@tonic-gate * comment block "Cheetah/Cheetah+ Fast ECC at TL>0 trap strategy" in 870Sstevel@tonic-gate * us3_common_asm.s 880Sstevel@tonic-gate */ 890Sstevel@tonic-gate#if defined(lint) 900Sstevel@tonic-gate 910Sstevel@tonic-gatevoid 920Sstevel@tonic-gatefast_ecc_tl1_err(void) 930Sstevel@tonic-gate{} 940Sstevel@tonic-gate 950Sstevel@tonic-gate#else /* lint */ 960Sstevel@tonic-gate 970Sstevel@tonic-gate .section ".text" 980Sstevel@tonic-gate .align 64 990Sstevel@tonic-gate ENTRY_NP(fast_ecc_tl1_err) 1000Sstevel@tonic-gate 1010Sstevel@tonic-gate /* 1020Sstevel@tonic-gate * This macro turns off the D$/I$ if they are on and saves their 1030Sstevel@tonic-gate * original state in ch_err_tl1_tmp, saves all the %g registers in the 1040Sstevel@tonic-gate * ch_err_tl1_data structure, updates the ch_err_tl1_flags and saves 1050Sstevel@tonic-gate * the %tpc in ch_err_tl1_tpc. At the end of this macro, %g1 will 1060Sstevel@tonic-gate * point to the ch_err_tl1_data structure and the original D$/I$ state 1070Sstevel@tonic-gate * will be saved in ch_err_tl1_tmp. All %g registers except for %g1 1080Sstevel@tonic-gate * will be available. 1090Sstevel@tonic-gate */ 1100Sstevel@tonic-gate CH_ERR_TL1_FECC_ENTER; 1110Sstevel@tonic-gate 1120Sstevel@tonic-gate /* 1130Sstevel@tonic-gate * Get the diagnostic logout data. %g4 must be initialized to 1140Sstevel@tonic-gate * current CEEN state, %g5 must point to logout structure in 1150Sstevel@tonic-gate * ch_err_tl1_data_t. %g3 will contain the nesting count upon 1160Sstevel@tonic-gate * return. 1170Sstevel@tonic-gate */ 1180Sstevel@tonic-gate ldxa [%g0]ASI_ESTATE_ERR, %g4 1190Sstevel@tonic-gate and %g4, EN_REG_CEEN, %g4 1200Sstevel@tonic-gate add %g1, CH_ERR_TL1_LOGOUT, %g5 1210Sstevel@tonic-gate DO_TL1_CPU_LOGOUT(%g3, %g2, %g4, %g5, %g6, %g3, %g4) 1220Sstevel@tonic-gate 1230Sstevel@tonic-gate /* 1240Sstevel@tonic-gate * If the logout nesting count is exceeded, we're probably 1250Sstevel@tonic-gate * not making any progress, try to panic instead. 1260Sstevel@tonic-gate */ 1270Sstevel@tonic-gate cmp %g3, CLO_NESTING_MAX 1280Sstevel@tonic-gate bge fecc_tl1_err 1290Sstevel@tonic-gate nop 1300Sstevel@tonic-gate 1310Sstevel@tonic-gate /* 1320Sstevel@tonic-gate * Save the current CEEN and NCEEN state in %g7 and turn them off 1330Sstevel@tonic-gate * before flushing the Ecache. 1340Sstevel@tonic-gate */ 1350Sstevel@tonic-gate ldxa [%g0]ASI_ESTATE_ERR, %g7 1360Sstevel@tonic-gate andn %g7, EN_REG_CEEN | EN_REG_NCEEN, %g5 1370Sstevel@tonic-gate stxa %g5, [%g0]ASI_ESTATE_ERR 1380Sstevel@tonic-gate membar #Sync 1390Sstevel@tonic-gate 1400Sstevel@tonic-gate /* 1410Sstevel@tonic-gate * Flush the Ecache, using the largest possible cache size with the 1420Sstevel@tonic-gate * smallest possible line size since we can't get the actual sizes 1430Sstevel@tonic-gate * from the cpu_node due to DTLB misses. 1440Sstevel@tonic-gate */ 1450Sstevel@tonic-gate set CH_ECACHE_8M_SIZE, %g4 1460Sstevel@tonic-gate set CH_ECACHE_MIN_LSIZE, %g5 1470Sstevel@tonic-gate 1480Sstevel@tonic-gate /* 1490Sstevel@tonic-gate * Use a different flush address to avoid recursion if the error 1500Sstevel@tonic-gate * exists in ecache_flushaddr. 1510Sstevel@tonic-gate */ 1520Sstevel@tonic-gate ASM_LDX(%g6, ecache_tl1_flushaddr) 1530Sstevel@tonic-gate cmp %g6, -1 ! check if address is valid 1540Sstevel@tonic-gate be %xcc, fecc_tl1_err 1550Sstevel@tonic-gate nop 1560Sstevel@tonic-gate CH_ECACHE_FLUSHALL(%g4, %g5, %g6) 1570Sstevel@tonic-gate 1580Sstevel@tonic-gate /* 1590Sstevel@tonic-gate * Restore CEEN and NCEEN to the previous state. 1600Sstevel@tonic-gate */ 1610Sstevel@tonic-gate stxa %g7, [%g0]ASI_ESTATE_ERR 1620Sstevel@tonic-gate membar #Sync 1630Sstevel@tonic-gate 1640Sstevel@tonic-gate /* 1650Sstevel@tonic-gate * If we turned off the D$, then flush it and turn it back on. 1660Sstevel@tonic-gate */ 1670Sstevel@tonic-gate ldxa [%g1 + CH_ERR_TL1_TMP]%asi, %g3 1680Sstevel@tonic-gate andcc %g3, CH_ERR_TSTATE_DC_ON, %g0 1690Sstevel@tonic-gate bz %xcc, 3f 1700Sstevel@tonic-gate nop 1710Sstevel@tonic-gate 1720Sstevel@tonic-gate /* 1730Sstevel@tonic-gate * Flush the D$. 1740Sstevel@tonic-gate */ 1750Sstevel@tonic-gate ASM_LD(%g4, dcache_size) 1760Sstevel@tonic-gate ASM_LD(%g5, dcache_linesize) 1770Sstevel@tonic-gate CH_DCACHE_FLUSHALL(%g4, %g5, %g6) 1780Sstevel@tonic-gate 1790Sstevel@tonic-gate /* 1800Sstevel@tonic-gate * Turn the D$ back on. 1810Sstevel@tonic-gate */ 1820Sstevel@tonic-gate ldxa [%g0]ASI_DCU, %g3 1830Sstevel@tonic-gate or %g3, DCU_DC, %g3 1840Sstevel@tonic-gate stxa %g3, [%g0]ASI_DCU 1850Sstevel@tonic-gate membar #Sync 1860Sstevel@tonic-gate3: 1870Sstevel@tonic-gate /* 1880Sstevel@tonic-gate * If we turned off the I$, then flush it and turn it back on. 1890Sstevel@tonic-gate */ 1900Sstevel@tonic-gate ldxa [%g1 + CH_ERR_TL1_TMP]%asi, %g3 1910Sstevel@tonic-gate andcc %g3, CH_ERR_TSTATE_IC_ON, %g0 1920Sstevel@tonic-gate bz %xcc, 4f 1930Sstevel@tonic-gate nop 1940Sstevel@tonic-gate 1950Sstevel@tonic-gate /* 1960Sstevel@tonic-gate * Flush the I$. 1970Sstevel@tonic-gate */ 1980Sstevel@tonic-gate ASM_LD(%g4, icache_size) 1990Sstevel@tonic-gate ASM_LD(%g5, icache_linesize) 2000Sstevel@tonic-gate CH_ICACHE_FLUSHALL(%g4, %g5, %g6, %g3) 2010Sstevel@tonic-gate 2020Sstevel@tonic-gate /* 2030Sstevel@tonic-gate * Turn the I$ back on. Changing DCU_IC requires flush. 2040Sstevel@tonic-gate */ 2050Sstevel@tonic-gate ldxa [%g0]ASI_DCU, %g3 2060Sstevel@tonic-gate or %g3, DCU_IC, %g3 2070Sstevel@tonic-gate stxa %g3, [%g0]ASI_DCU 2080Sstevel@tonic-gate flush %g0 2090Sstevel@tonic-gate4: 2100Sstevel@tonic-gate 2110Sstevel@tonic-gate#ifdef TRAPTRACE 2120Sstevel@tonic-gate /* 2130Sstevel@tonic-gate * Get current trap trace entry physical pointer. 2140Sstevel@tonic-gate */ 2150Sstevel@tonic-gate CPU_INDEX(%g6, %g5) 2160Sstevel@tonic-gate sll %g6, TRAPTR_SIZE_SHIFT, %g6 2170Sstevel@tonic-gate set trap_trace_ctl, %g5 2180Sstevel@tonic-gate add %g6, %g5, %g6 2190Sstevel@tonic-gate ld [%g6 + TRAPTR_LIMIT], %g5 2200Sstevel@tonic-gate tst %g5 2210Sstevel@tonic-gate be %icc, skip_traptrace 2220Sstevel@tonic-gate nop 2230Sstevel@tonic-gate ldx [%g6 + TRAPTR_PBASE], %g5 2240Sstevel@tonic-gate ld [%g6 + TRAPTR_OFFSET], %g4 2250Sstevel@tonic-gate add %g5, %g4, %g5 2260Sstevel@tonic-gate 2270Sstevel@tonic-gate /* 2280Sstevel@tonic-gate * Create trap trace entry. 2290Sstevel@tonic-gate */ 2300Sstevel@tonic-gate rd %asi, %g7 2310Sstevel@tonic-gate wr %g0, TRAPTR_ASI, %asi 2320Sstevel@tonic-gate rd STICK, %g4 2330Sstevel@tonic-gate stxa %g4, [%g5 + TRAP_ENT_TICK]%asi 2340Sstevel@tonic-gate rdpr %tl, %g4 2350Sstevel@tonic-gate stha %g4, [%g5 + TRAP_ENT_TL]%asi 2360Sstevel@tonic-gate rdpr %tt, %g4 2370Sstevel@tonic-gate stha %g4, [%g5 + TRAP_ENT_TT]%asi 2380Sstevel@tonic-gate rdpr %tpc, %g4 2390Sstevel@tonic-gate stna %g4, [%g5 + TRAP_ENT_TPC]%asi 2400Sstevel@tonic-gate rdpr %tstate, %g4 2410Sstevel@tonic-gate stxa %g4, [%g5 + TRAP_ENT_TSTATE]%asi 2420Sstevel@tonic-gate stna %sp, [%g5 + TRAP_ENT_SP]%asi 2430Sstevel@tonic-gate stna %g0, [%g5 + TRAP_ENT_TR]%asi 2440Sstevel@tonic-gate wr %g0, %g7, %asi 2450Sstevel@tonic-gate ldxa [%g1 + CH_ERR_TL1_SDW_AFAR]%asi, %g3 2460Sstevel@tonic-gate ldxa [%g1 + CH_ERR_TL1_SDW_AFSR]%asi, %g4 2470Sstevel@tonic-gate wr %g0, TRAPTR_ASI, %asi 2480Sstevel@tonic-gate stna %g3, [%g5 + TRAP_ENT_F1]%asi 2490Sstevel@tonic-gate stna %g4, [%g5 + TRAP_ENT_F2]%asi 2500Sstevel@tonic-gate wr %g0, %g7, %asi 2510Sstevel@tonic-gate ldxa [%g1 + CH_ERR_TL1_AFAR]%asi, %g3 2520Sstevel@tonic-gate ldxa [%g1 + CH_ERR_TL1_AFSR]%asi, %g4 2530Sstevel@tonic-gate wr %g0, TRAPTR_ASI, %asi 2540Sstevel@tonic-gate stna %g3, [%g5 + TRAP_ENT_F3]%asi 2550Sstevel@tonic-gate stna %g4, [%g5 + TRAP_ENT_F4]%asi 2560Sstevel@tonic-gate wr %g0, %g7, %asi 2570Sstevel@tonic-gate 2580Sstevel@tonic-gate /* 2590Sstevel@tonic-gate * Advance trap trace pointer. 2600Sstevel@tonic-gate */ 2610Sstevel@tonic-gate ld [%g6 + TRAPTR_OFFSET], %g5 2620Sstevel@tonic-gate ld [%g6 + TRAPTR_LIMIT], %g4 2630Sstevel@tonic-gate st %g5, [%g6 + TRAPTR_LAST_OFFSET] 2640Sstevel@tonic-gate add %g5, TRAP_ENT_SIZE, %g5 2650Sstevel@tonic-gate sub %g4, TRAP_ENT_SIZE, %g4 2660Sstevel@tonic-gate cmp %g5, %g4 2670Sstevel@tonic-gate movge %icc, 0, %g5 2680Sstevel@tonic-gate st %g5, [%g6 + TRAPTR_OFFSET] 2690Sstevel@tonic-gateskip_traptrace: 2700Sstevel@tonic-gate#endif /* TRAPTRACE */ 2710Sstevel@tonic-gate 2720Sstevel@tonic-gate /* 2730Sstevel@tonic-gate * If nesting count is not zero, skip all the AFSR/AFAR 2740Sstevel@tonic-gate * handling and just do the necessary cache-flushing. 2750Sstevel@tonic-gate */ 2760Sstevel@tonic-gate ldxa [%g1 + CH_ERR_TL1_NEST_CNT]%asi, %g2 2770Sstevel@tonic-gate brnz %g2, 6f 2780Sstevel@tonic-gate nop 2790Sstevel@tonic-gate 2800Sstevel@tonic-gate /* 2810Sstevel@tonic-gate * If a UCU followed by a WDU has occurred go ahead and panic 2820Sstevel@tonic-gate * since a UE will occur (on the retry) before the UCU and WDU 2830Sstevel@tonic-gate * messages are enqueued. 2840Sstevel@tonic-gate */ 2850Sstevel@tonic-gate ldxa [%g1 + CH_ERR_TL1_AFSR]%asi, %g3 2860Sstevel@tonic-gate set 1, %g4 2870Sstevel@tonic-gate sllx %g4, C_AFSR_UCU_SHIFT, %g4 2880Sstevel@tonic-gate btst %g4, %g3 ! UCU in original AFSR? 2890Sstevel@tonic-gate bz %xcc, 6f 2900Sstevel@tonic-gate nop 2910Sstevel@tonic-gate ldxa [%g0]ASI_AFSR, %g4 ! current AFSR 2920Sstevel@tonic-gate or %g3, %g4, %g3 ! %g3 = original + current AFSR 2930Sstevel@tonic-gate set 1, %g4 2940Sstevel@tonic-gate sllx %g4, C_AFSR_WDU_SHIFT, %g4 2950Sstevel@tonic-gate btst %g4, %g3 ! WDU in original or current AFSR? 2960Sstevel@tonic-gate bnz %xcc, fecc_tl1_err 2970Sstevel@tonic-gate nop 2980Sstevel@tonic-gate 2990Sstevel@tonic-gate6: 3000Sstevel@tonic-gate /* 3010Sstevel@tonic-gate * We fall into this macro if we've successfully logged the error in 3020Sstevel@tonic-gate * the ch_err_tl1_data structure and want the PIL15 softint to pick 3030Sstevel@tonic-gate * it up and log it. %g1 must point to the ch_err_tl1_data structure. 3040Sstevel@tonic-gate * Restores the %g registers and issues retry. 3050Sstevel@tonic-gate */ 3060Sstevel@tonic-gate CH_ERR_TL1_EXIT; 3070Sstevel@tonic-gate 3080Sstevel@tonic-gate /* 3090Sstevel@tonic-gate * Establish panic exit label. 3100Sstevel@tonic-gate */ 3110Sstevel@tonic-gate CH_ERR_TL1_PANIC_EXIT(fecc_tl1_err); 3120Sstevel@tonic-gate 3130Sstevel@tonic-gate SET_SIZE(fast_ecc_tl1_err) 3140Sstevel@tonic-gate 3150Sstevel@tonic-gate#endif /* lint */ 3160Sstevel@tonic-gate 3170Sstevel@tonic-gate 3180Sstevel@tonic-gate#if defined(lint) 3190Sstevel@tonic-gate/* 3200Sstevel@tonic-gate * scrubphys - Pass in the aligned physical memory address 3210Sstevel@tonic-gate * that you want to scrub, along with the ecache set size. 3220Sstevel@tonic-gate * 3230Sstevel@tonic-gate * 1) Displacement flush the E$ line corresponding to %addr. 3240Sstevel@tonic-gate * The first ldxa guarantees that the %addr is no longer in 3250Sstevel@tonic-gate * M, O, or E (goes to I or S (if instruction fetch also happens). 3260Sstevel@tonic-gate * 2) "Write" the data using a CAS %addr,%g0,%g0. 3270Sstevel@tonic-gate * The casxa guarantees a transition from I to M or S to M. 3280Sstevel@tonic-gate * 3) Displacement flush the E$ line corresponding to %addr. 3290Sstevel@tonic-gate * The second ldxa pushes the M line out of the ecache, into the 3300Sstevel@tonic-gate * writeback buffers, on the way to memory. 3310Sstevel@tonic-gate * 4) The "membar #Sync" pushes the cache line out of the writeback 3320Sstevel@tonic-gate * buffers onto the bus, on the way to dram finally. 3330Sstevel@tonic-gate * 3340Sstevel@tonic-gate * This is a modified version of the algorithm suggested by Gary Lauterbach. 3350Sstevel@tonic-gate * In theory the CAS %addr,%g0,%g0 is supposed to mark the addr's cache line 3360Sstevel@tonic-gate * as modified, but then we found out that for spitfire, if it misses in the 3370Sstevel@tonic-gate * E$ it will probably install as an M, but if it hits in the E$, then it 3380Sstevel@tonic-gate * will stay E, if the store doesn't happen. So the first displacement flush 3390Sstevel@tonic-gate * should ensure that the CAS will miss in the E$. Arrgh. 3400Sstevel@tonic-gate */ 3410Sstevel@tonic-gate/* ARGSUSED */ 3420Sstevel@tonic-gatevoid 3430Sstevel@tonic-gatescrubphys(uint64_t paddr, int ecache_set_size) 3440Sstevel@tonic-gate{} 3450Sstevel@tonic-gate 3460Sstevel@tonic-gate#else /* lint */ 3470Sstevel@tonic-gate ENTRY(scrubphys) 3480Sstevel@tonic-gate rdpr %pstate, %o4 3490Sstevel@tonic-gate andn %o4, PSTATE_IE | PSTATE_AM, %o5 3500Sstevel@tonic-gate wrpr %o5, %g0, %pstate ! clear IE, AM bits 3510Sstevel@tonic-gate 3520Sstevel@tonic-gate ECACHE_FLUSH_LINE(%o0, %o1, %o2, %o3) 3530Sstevel@tonic-gate casxa [%o0]ASI_MEM, %g0, %g0 3540Sstevel@tonic-gate ECACHE_REFLUSH_LINE(%o1, %o2, %o3) 3550Sstevel@tonic-gate 3560Sstevel@tonic-gate wrpr %g0, %o4, %pstate ! restore earlier pstate register value 3570Sstevel@tonic-gate 3580Sstevel@tonic-gate retl 3590Sstevel@tonic-gate membar #Sync ! move the data out of the load buffer 3600Sstevel@tonic-gate SET_SIZE(scrubphys) 3610Sstevel@tonic-gate 3620Sstevel@tonic-gate#endif /* lint */ 3630Sstevel@tonic-gate 3640Sstevel@tonic-gate 3650Sstevel@tonic-gate#if defined(lint) 366*4567Sanbui /* 367*4567Sanbui * clearphys - Pass in the physical memory address of the checkblock 368*4567Sanbui * that you want to push out, cleared with a recognizable pattern, 369*4567Sanbui * from the ecache. 370*4567Sanbui * 371*4567Sanbui * To ensure that the ecc gets recalculated after the bad data is cleared, 372*4567Sanbui * we must write out enough data to fill the w$ line (64 bytes). So we read 373*4567Sanbui * in an entire ecache subblock's worth of data, and write it back out. 374*4567Sanbui * Then we overwrite the 16 bytes of bad data with the pattern. 3750Sstevel@tonic-gate */ 3760Sstevel@tonic-gate/* ARGSUSED */ 3770Sstevel@tonic-gatevoid 3780Sstevel@tonic-gateclearphys(uint64_t paddr, int ecache_set_size, int ecache_linesize) 3790Sstevel@tonic-gate{ 3800Sstevel@tonic-gate} 3810Sstevel@tonic-gate 3820Sstevel@tonic-gate#else /* lint */ 3830Sstevel@tonic-gate ENTRY(clearphys) 3840Sstevel@tonic-gate /* turn off IE, AM bits */ 3850Sstevel@tonic-gate rdpr %pstate, %o4 3860Sstevel@tonic-gate andn %o4, PSTATE_IE | PSTATE_AM, %o5 3870Sstevel@tonic-gate wrpr %o5, %g0, %pstate 3880Sstevel@tonic-gate 3890Sstevel@tonic-gate /* turn off NCEEN */ 3900Sstevel@tonic-gate ldxa [%g0]ASI_ESTATE_ERR, %o5 3910Sstevel@tonic-gate andn %o5, EN_REG_NCEEN, %o3 3920Sstevel@tonic-gate stxa %o3, [%g0]ASI_ESTATE_ERR 3930Sstevel@tonic-gate membar #Sync 3940Sstevel@tonic-gate 395*4567Sanbui /* align address passed with 64 bytes subblock size */ 396*4567Sanbui mov CH_ECACHE_SUBBLK_SIZE, %o2 397*4567Sanbui andn %o0, (CH_ECACHE_SUBBLK_SIZE - 1), %g1 398*4567Sanbui 399*4567Sanbui /* move the good data into the W$ */ 4000Sstevel@tonic-gate1: 4010Sstevel@tonic-gate subcc %o2, 8, %o2 402*4567Sanbui ldxa [%g1 + %o2]ASI_MEM, %g2 4030Sstevel@tonic-gate bge 1b 404*4567Sanbui stxa %g2, [%g1 + %o2]ASI_MEM 4050Sstevel@tonic-gate 406*4567Sanbui /* now overwrite the bad data */ 407*4567Sanbui setx 0xbadecc00badecc01, %g1, %g2 408*4567Sanbui stxa %g2, [%o0]ASI_MEM 409*4567Sanbui mov 8, %g1 410*4567Sanbui stxa %g2, [%o0 + %g1]ASI_MEM 411*4567Sanbui 4120Sstevel@tonic-gate ECACHE_FLUSH_LINE(%o0, %o1, %o2, %o3) 4130Sstevel@tonic-gate casxa [%o0]ASI_MEM, %g0, %g0 4140Sstevel@tonic-gate ECACHE_REFLUSH_LINE(%o1, %o2, %o3) 4150Sstevel@tonic-gate 4160Sstevel@tonic-gate /* clear the AFSR */ 4170Sstevel@tonic-gate ldxa [%g0]ASI_AFSR, %o1 4180Sstevel@tonic-gate stxa %o1, [%g0]ASI_AFSR 4190Sstevel@tonic-gate membar #Sync 4200Sstevel@tonic-gate 4210Sstevel@tonic-gate /* turn NCEEN back on */ 4220Sstevel@tonic-gate stxa %o5, [%g0]ASI_ESTATE_ERR 4230Sstevel@tonic-gate membar #Sync 4240Sstevel@tonic-gate 4250Sstevel@tonic-gate /* return and re-enable IE and AM */ 4260Sstevel@tonic-gate retl 4270Sstevel@tonic-gate wrpr %g0, %o4, %pstate 4280Sstevel@tonic-gate SET_SIZE(clearphys) 4290Sstevel@tonic-gate 4300Sstevel@tonic-gate#endif /* lint */ 4310Sstevel@tonic-gate 4320Sstevel@tonic-gate 4330Sstevel@tonic-gate#if defined(lint) 4340Sstevel@tonic-gate/* 4350Sstevel@tonic-gate * Cheetah Ecache displacement flush the specified line from the E$ 4360Sstevel@tonic-gate * 4370Sstevel@tonic-gate * Register usage: 4380Sstevel@tonic-gate * %o0 - 64 bit physical address for flushing 4390Sstevel@tonic-gate * %o1 - Ecache set size 4400Sstevel@tonic-gate */ 4410Sstevel@tonic-gate/*ARGSUSED*/ 4420Sstevel@tonic-gatevoid 4430Sstevel@tonic-gateecache_flush_line(uint64_t flushaddr, int ec_set_size) 4440Sstevel@tonic-gate{ 4450Sstevel@tonic-gate} 4460Sstevel@tonic-gate#else /* lint */ 4470Sstevel@tonic-gate ENTRY(ecache_flush_line) 4480Sstevel@tonic-gate 4490Sstevel@tonic-gate ECACHE_FLUSH_LINE(%o0, %o1, %o2, %o3) 4500Sstevel@tonic-gate 4510Sstevel@tonic-gate retl 4520Sstevel@tonic-gate nop 4530Sstevel@tonic-gate SET_SIZE(ecache_flush_line) 4540Sstevel@tonic-gate#endif /* lint */ 4550Sstevel@tonic-gate 4560Sstevel@tonic-gate 4570Sstevel@tonic-gate#if defined(lint) 4580Sstevel@tonic-gate/* 4590Sstevel@tonic-gate * This routine will not be called in Cheetah systems. 4600Sstevel@tonic-gate */ 4610Sstevel@tonic-gatevoid 4620Sstevel@tonic-gateflush_ipb(void) 4630Sstevel@tonic-gate{ return; } 4640Sstevel@tonic-gate 4650Sstevel@tonic-gate#else /* lint */ 4660Sstevel@tonic-gate 4670Sstevel@tonic-gate ENTRY(flush_ipb) 4680Sstevel@tonic-gate retl 4690Sstevel@tonic-gate nop 4700Sstevel@tonic-gate SET_SIZE(flush_ipb) 4710Sstevel@tonic-gate 4720Sstevel@tonic-gate#endif /* lint */ 473