17c478bd9Sstevel@tonic-gate/* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate/* 23*750ba224Sanbui * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate * 267c478bd9Sstevel@tonic-gate * Assembly code support for the Cheetah module 277c478bd9Sstevel@tonic-gate */ 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate#pragma ident "%Z%%M% %I% %E% SMI" 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate#if !defined(lint) 327c478bd9Sstevel@tonic-gate#include "assym.h" 337c478bd9Sstevel@tonic-gate#endif /* lint */ 347c478bd9Sstevel@tonic-gate 357c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h> 367c478bd9Sstevel@tonic-gate#include <sys/mmu.h> 377c478bd9Sstevel@tonic-gate#include <vm/hat_sfmmu.h> 387c478bd9Sstevel@tonic-gate#include <sys/machparam.h> 397c478bd9Sstevel@tonic-gate#include <sys/machcpuvar.h> 407c478bd9Sstevel@tonic-gate#include <sys/machthread.h> 417c478bd9Sstevel@tonic-gate#include <sys/machtrap.h> 427c478bd9Sstevel@tonic-gate#include <sys/privregs.h> 437c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h> 447c478bd9Sstevel@tonic-gate#include <sys/trap.h> 457c478bd9Sstevel@tonic-gate#include <sys/cheetahregs.h> 467c478bd9Sstevel@tonic-gate#include <sys/us3_module.h> 477c478bd9Sstevel@tonic-gate#include <sys/xc_impl.h> 487c478bd9Sstevel@tonic-gate#include <sys/intreg.h> 497c478bd9Sstevel@tonic-gate#include <sys/async.h> 507c478bd9Sstevel@tonic-gate#include <sys/clock.h> 517c478bd9Sstevel@tonic-gate#include <sys/cheetahasm.h> 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate#ifdef TRAPTRACE 547c478bd9Sstevel@tonic-gate#include <sys/traptrace.h> 557c478bd9Sstevel@tonic-gate#endif /* TRAPTRACE */ 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate#if !defined(lint) 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate/* BEGIN CSTYLED */ 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate/* 627c478bd9Sstevel@tonic-gate * Cheetah version to flush an Ecache line by index (aliased address) 637c478bd9Sstevel@tonic-gate */ 647c478bd9Sstevel@tonic-gate#define ECACHE_REFLUSH_LINE(ecache_size, alias_address, scr2) \ 657c478bd9Sstevel@tonic-gate ldxa [alias_address]ASI_MEM, %g0 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate#define ECACHE_FLUSH_LINE(physaddr, ecache_size, scr1, scr2) \ 687c478bd9Sstevel@tonic-gate xor physaddr, ecache_size, scr1; \ 697c478bd9Sstevel@tonic-gate add ecache_size, ecache_size, scr2; \ 707c478bd9Sstevel@tonic-gate sub scr2, 1, scr2; \ 717c478bd9Sstevel@tonic-gate and scr1, scr2, scr1; \ 727c478bd9Sstevel@tonic-gate ASM_LDX(scr2, ecache_flushaddr); \ 737c478bd9Sstevel@tonic-gate add scr1, scr2, scr1; \ 747c478bd9Sstevel@tonic-gate ECACHE_REFLUSH_LINE(ecache_size, scr1, scr2) 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate/* END CSTYLED */ 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate#endif /* !lint */ 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate 817c478bd9Sstevel@tonic-gate/* 827c478bd9Sstevel@tonic-gate * Fast ECC error at TL>0 handler 837c478bd9Sstevel@tonic-gate * We get here via trap 70 at TL>0->Software trap 0 at TL>0. We enter 847c478bd9Sstevel@tonic-gate * this routine with %g1 and %g2 already saved in %tpc, %tnpc and %tstate. 857c478bd9Sstevel@tonic-gate * For a complete description of the Fast ECC at TL>0 handling see the 867c478bd9Sstevel@tonic-gate * comment block "Cheetah/Cheetah+ Fast ECC at TL>0 trap strategy" in 877c478bd9Sstevel@tonic-gate * us3_common_asm.s 887c478bd9Sstevel@tonic-gate */ 897c478bd9Sstevel@tonic-gate#if defined(lint) 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gatevoid 927c478bd9Sstevel@tonic-gatefast_ecc_tl1_err(void) 937c478bd9Sstevel@tonic-gate{} 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate#else /* lint */ 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate .section ".text" 987c478bd9Sstevel@tonic-gate .align 64 997c478bd9Sstevel@tonic-gate ENTRY_NP(fast_ecc_tl1_err) 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate /* 1027c478bd9Sstevel@tonic-gate * This macro turns off the D$/I$ if they are on and saves their 1037c478bd9Sstevel@tonic-gate * original state in ch_err_tl1_tmp, saves all the %g registers in the 1047c478bd9Sstevel@tonic-gate * ch_err_tl1_data structure, updates the ch_err_tl1_flags and saves 1057c478bd9Sstevel@tonic-gate * the %tpc in ch_err_tl1_tpc. At the end of this macro, %g1 will 1067c478bd9Sstevel@tonic-gate * point to the ch_err_tl1_data structure and the original D$/I$ state 1077c478bd9Sstevel@tonic-gate * will be saved in ch_err_tl1_tmp. All %g registers except for %g1 1087c478bd9Sstevel@tonic-gate * will be available. 1097c478bd9Sstevel@tonic-gate */ 1107c478bd9Sstevel@tonic-gate CH_ERR_TL1_FECC_ENTER; 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate /* 1137c478bd9Sstevel@tonic-gate * Get the diagnostic logout data. %g4 must be initialized to 1147c478bd9Sstevel@tonic-gate * current CEEN state, %g5 must point to logout structure in 1157c478bd9Sstevel@tonic-gate * ch_err_tl1_data_t. %g3 will contain the nesting count upon 1167c478bd9Sstevel@tonic-gate * return. 1177c478bd9Sstevel@tonic-gate */ 1187c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_ESTATE_ERR, %g4 1197c478bd9Sstevel@tonic-gate and %g4, EN_REG_CEEN, %g4 1207c478bd9Sstevel@tonic-gate add %g1, CH_ERR_TL1_LOGOUT, %g5 1217c478bd9Sstevel@tonic-gate DO_TL1_CPU_LOGOUT(%g3, %g2, %g4, %g5, %g6, %g3, %g4) 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate /* 1247c478bd9Sstevel@tonic-gate * If the logout nesting count is exceeded, we're probably 1257c478bd9Sstevel@tonic-gate * not making any progress, try to panic instead. 1267c478bd9Sstevel@tonic-gate */ 1277c478bd9Sstevel@tonic-gate cmp %g3, CLO_NESTING_MAX 1287c478bd9Sstevel@tonic-gate bge fecc_tl1_err 1297c478bd9Sstevel@tonic-gate nop 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate /* 1327c478bd9Sstevel@tonic-gate * Save the current CEEN and NCEEN state in %g7 and turn them off 1337c478bd9Sstevel@tonic-gate * before flushing the Ecache. 1347c478bd9Sstevel@tonic-gate */ 1357c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_ESTATE_ERR, %g7 1367c478bd9Sstevel@tonic-gate andn %g7, EN_REG_CEEN | EN_REG_NCEEN, %g5 1377c478bd9Sstevel@tonic-gate stxa %g5, [%g0]ASI_ESTATE_ERR 1387c478bd9Sstevel@tonic-gate membar #Sync 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate /* 1417c478bd9Sstevel@tonic-gate * Flush the Ecache, using the largest possible cache size with the 1427c478bd9Sstevel@tonic-gate * smallest possible line size since we can't get the actual sizes 1437c478bd9Sstevel@tonic-gate * from the cpu_node due to DTLB misses. 1447c478bd9Sstevel@tonic-gate */ 1457c478bd9Sstevel@tonic-gate set CH_ECACHE_8M_SIZE, %g4 1467c478bd9Sstevel@tonic-gate set CH_ECACHE_MIN_LSIZE, %g5 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate /* 1497c478bd9Sstevel@tonic-gate * Use a different flush address to avoid recursion if the error 1507c478bd9Sstevel@tonic-gate * exists in ecache_flushaddr. 1517c478bd9Sstevel@tonic-gate */ 1527c478bd9Sstevel@tonic-gate ASM_LDX(%g6, ecache_tl1_flushaddr) 1537c478bd9Sstevel@tonic-gate cmp %g6, -1 ! check if address is valid 1547c478bd9Sstevel@tonic-gate be %xcc, fecc_tl1_err 1557c478bd9Sstevel@tonic-gate nop 1567c478bd9Sstevel@tonic-gate CH_ECACHE_FLUSHALL(%g4, %g5, %g6) 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate /* 1597c478bd9Sstevel@tonic-gate * Restore CEEN and NCEEN to the previous state. 1607c478bd9Sstevel@tonic-gate */ 1617c478bd9Sstevel@tonic-gate stxa %g7, [%g0]ASI_ESTATE_ERR 1627c478bd9Sstevel@tonic-gate membar #Sync 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate /* 1657c478bd9Sstevel@tonic-gate * If we turned off the D$, then flush it and turn it back on. 1667c478bd9Sstevel@tonic-gate */ 1677c478bd9Sstevel@tonic-gate ldxa [%g1 + CH_ERR_TL1_TMP]%asi, %g3 1687c478bd9Sstevel@tonic-gate andcc %g3, CH_ERR_TSTATE_DC_ON, %g0 1697c478bd9Sstevel@tonic-gate bz %xcc, 3f 1707c478bd9Sstevel@tonic-gate nop 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate /* 1737c478bd9Sstevel@tonic-gate * Flush the D$. 1747c478bd9Sstevel@tonic-gate */ 1757c478bd9Sstevel@tonic-gate ASM_LD(%g4, dcache_size) 1767c478bd9Sstevel@tonic-gate ASM_LD(%g5, dcache_linesize) 1777c478bd9Sstevel@tonic-gate CH_DCACHE_FLUSHALL(%g4, %g5, %g6) 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate /* 1807c478bd9Sstevel@tonic-gate * Turn the D$ back on. 1817c478bd9Sstevel@tonic-gate */ 1827c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_DCU, %g3 1837c478bd9Sstevel@tonic-gate or %g3, DCU_DC, %g3 1847c478bd9Sstevel@tonic-gate stxa %g3, [%g0]ASI_DCU 1857c478bd9Sstevel@tonic-gate membar #Sync 1867c478bd9Sstevel@tonic-gate3: 1877c478bd9Sstevel@tonic-gate /* 1887c478bd9Sstevel@tonic-gate * If we turned off the I$, then flush it and turn it back on. 1897c478bd9Sstevel@tonic-gate */ 1907c478bd9Sstevel@tonic-gate ldxa [%g1 + CH_ERR_TL1_TMP]%asi, %g3 1917c478bd9Sstevel@tonic-gate andcc %g3, CH_ERR_TSTATE_IC_ON, %g0 1927c478bd9Sstevel@tonic-gate bz %xcc, 4f 1937c478bd9Sstevel@tonic-gate nop 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate /* 1967c478bd9Sstevel@tonic-gate * Flush the I$. 1977c478bd9Sstevel@tonic-gate */ 1987c478bd9Sstevel@tonic-gate ASM_LD(%g4, icache_size) 1997c478bd9Sstevel@tonic-gate ASM_LD(%g5, icache_linesize) 2007c478bd9Sstevel@tonic-gate CH_ICACHE_FLUSHALL(%g4, %g5, %g6, %g3) 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate /* 2037c478bd9Sstevel@tonic-gate * Turn the I$ back on. Changing DCU_IC requires flush. 2047c478bd9Sstevel@tonic-gate */ 2057c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_DCU, %g3 2067c478bd9Sstevel@tonic-gate or %g3, DCU_IC, %g3 2077c478bd9Sstevel@tonic-gate stxa %g3, [%g0]ASI_DCU 2087c478bd9Sstevel@tonic-gate flush %g0 2097c478bd9Sstevel@tonic-gate4: 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate#ifdef TRAPTRACE 2127c478bd9Sstevel@tonic-gate /* 2137c478bd9Sstevel@tonic-gate * Get current trap trace entry physical pointer. 2147c478bd9Sstevel@tonic-gate */ 2157c478bd9Sstevel@tonic-gate CPU_INDEX(%g6, %g5) 2167c478bd9Sstevel@tonic-gate sll %g6, TRAPTR_SIZE_SHIFT, %g6 2177c478bd9Sstevel@tonic-gate set trap_trace_ctl, %g5 2187c478bd9Sstevel@tonic-gate add %g6, %g5, %g6 2197c478bd9Sstevel@tonic-gate ld [%g6 + TRAPTR_LIMIT], %g5 2207c478bd9Sstevel@tonic-gate tst %g5 2217c478bd9Sstevel@tonic-gate be %icc, skip_traptrace 2227c478bd9Sstevel@tonic-gate nop 2237c478bd9Sstevel@tonic-gate ldx [%g6 + TRAPTR_PBASE], %g5 2247c478bd9Sstevel@tonic-gate ld [%g6 + TRAPTR_OFFSET], %g4 2257c478bd9Sstevel@tonic-gate add %g5, %g4, %g5 2267c478bd9Sstevel@tonic-gate 2277c478bd9Sstevel@tonic-gate /* 2287c478bd9Sstevel@tonic-gate * Create trap trace entry. 2297c478bd9Sstevel@tonic-gate */ 2307c478bd9Sstevel@tonic-gate rd %asi, %g7 2317c478bd9Sstevel@tonic-gate wr %g0, TRAPTR_ASI, %asi 2327c478bd9Sstevel@tonic-gate rd STICK, %g4 2337c478bd9Sstevel@tonic-gate stxa %g4, [%g5 + TRAP_ENT_TICK]%asi 2347c478bd9Sstevel@tonic-gate rdpr %tl, %g4 2357c478bd9Sstevel@tonic-gate stha %g4, [%g5 + TRAP_ENT_TL]%asi 2367c478bd9Sstevel@tonic-gate rdpr %tt, %g4 2377c478bd9Sstevel@tonic-gate stha %g4, [%g5 + TRAP_ENT_TT]%asi 2387c478bd9Sstevel@tonic-gate rdpr %tpc, %g4 2397c478bd9Sstevel@tonic-gate stna %g4, [%g5 + TRAP_ENT_TPC]%asi 2407c478bd9Sstevel@tonic-gate rdpr %tstate, %g4 2417c478bd9Sstevel@tonic-gate stxa %g4, [%g5 + TRAP_ENT_TSTATE]%asi 2427c478bd9Sstevel@tonic-gate stna %sp, [%g5 + TRAP_ENT_SP]%asi 2437c478bd9Sstevel@tonic-gate stna %g0, [%g5 + TRAP_ENT_TR]%asi 2447c478bd9Sstevel@tonic-gate wr %g0, %g7, %asi 2457c478bd9Sstevel@tonic-gate ldxa [%g1 + CH_ERR_TL1_SDW_AFAR]%asi, %g3 2467c478bd9Sstevel@tonic-gate ldxa [%g1 + CH_ERR_TL1_SDW_AFSR]%asi, %g4 2477c478bd9Sstevel@tonic-gate wr %g0, TRAPTR_ASI, %asi 2487c478bd9Sstevel@tonic-gate stna %g3, [%g5 + TRAP_ENT_F1]%asi 2497c478bd9Sstevel@tonic-gate stna %g4, [%g5 + TRAP_ENT_F2]%asi 2507c478bd9Sstevel@tonic-gate wr %g0, %g7, %asi 2517c478bd9Sstevel@tonic-gate ldxa [%g1 + CH_ERR_TL1_AFAR]%asi, %g3 2527c478bd9Sstevel@tonic-gate ldxa [%g1 + CH_ERR_TL1_AFSR]%asi, %g4 2537c478bd9Sstevel@tonic-gate wr %g0, TRAPTR_ASI, %asi 2547c478bd9Sstevel@tonic-gate stna %g3, [%g5 + TRAP_ENT_F3]%asi 2557c478bd9Sstevel@tonic-gate stna %g4, [%g5 + TRAP_ENT_F4]%asi 2567c478bd9Sstevel@tonic-gate wr %g0, %g7, %asi 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate /* 2597c478bd9Sstevel@tonic-gate * Advance trap trace pointer. 2607c478bd9Sstevel@tonic-gate */ 2617c478bd9Sstevel@tonic-gate ld [%g6 + TRAPTR_OFFSET], %g5 2627c478bd9Sstevel@tonic-gate ld [%g6 + TRAPTR_LIMIT], %g4 2637c478bd9Sstevel@tonic-gate st %g5, [%g6 + TRAPTR_LAST_OFFSET] 2647c478bd9Sstevel@tonic-gate add %g5, TRAP_ENT_SIZE, %g5 2657c478bd9Sstevel@tonic-gate sub %g4, TRAP_ENT_SIZE, %g4 2667c478bd9Sstevel@tonic-gate cmp %g5, %g4 2677c478bd9Sstevel@tonic-gate movge %icc, 0, %g5 2687c478bd9Sstevel@tonic-gate st %g5, [%g6 + TRAPTR_OFFSET] 2697c478bd9Sstevel@tonic-gateskip_traptrace: 2707c478bd9Sstevel@tonic-gate#endif /* TRAPTRACE */ 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate /* 2737c478bd9Sstevel@tonic-gate * If nesting count is not zero, skip all the AFSR/AFAR 2747c478bd9Sstevel@tonic-gate * handling and just do the necessary cache-flushing. 2757c478bd9Sstevel@tonic-gate */ 2767c478bd9Sstevel@tonic-gate ldxa [%g1 + CH_ERR_TL1_NEST_CNT]%asi, %g2 2777c478bd9Sstevel@tonic-gate brnz %g2, 6f 2787c478bd9Sstevel@tonic-gate nop 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate /* 2817c478bd9Sstevel@tonic-gate * If a UCU followed by a WDU has occurred go ahead and panic 2827c478bd9Sstevel@tonic-gate * since a UE will occur (on the retry) before the UCU and WDU 2837c478bd9Sstevel@tonic-gate * messages are enqueued. 2847c478bd9Sstevel@tonic-gate */ 2857c478bd9Sstevel@tonic-gate ldxa [%g1 + CH_ERR_TL1_AFSR]%asi, %g3 2867c478bd9Sstevel@tonic-gate set 1, %g4 2877c478bd9Sstevel@tonic-gate sllx %g4, C_AFSR_UCU_SHIFT, %g4 2887c478bd9Sstevel@tonic-gate btst %g4, %g3 ! UCU in original AFSR? 2897c478bd9Sstevel@tonic-gate bz %xcc, 6f 2907c478bd9Sstevel@tonic-gate nop 2917c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_AFSR, %g4 ! current AFSR 2927c478bd9Sstevel@tonic-gate or %g3, %g4, %g3 ! %g3 = original + current AFSR 2937c478bd9Sstevel@tonic-gate set 1, %g4 2947c478bd9Sstevel@tonic-gate sllx %g4, C_AFSR_WDU_SHIFT, %g4 2957c478bd9Sstevel@tonic-gate btst %g4, %g3 ! WDU in original or current AFSR? 2967c478bd9Sstevel@tonic-gate bnz %xcc, fecc_tl1_err 2977c478bd9Sstevel@tonic-gate nop 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate6: 3007c478bd9Sstevel@tonic-gate /* 3017c478bd9Sstevel@tonic-gate * We fall into this macro if we've successfully logged the error in 3027c478bd9Sstevel@tonic-gate * the ch_err_tl1_data structure and want the PIL15 softint to pick 3037c478bd9Sstevel@tonic-gate * it up and log it. %g1 must point to the ch_err_tl1_data structure. 3047c478bd9Sstevel@tonic-gate * Restores the %g registers and issues retry. 3057c478bd9Sstevel@tonic-gate */ 3067c478bd9Sstevel@tonic-gate CH_ERR_TL1_EXIT; 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate /* 3097c478bd9Sstevel@tonic-gate * Establish panic exit label. 3107c478bd9Sstevel@tonic-gate */ 3117c478bd9Sstevel@tonic-gate CH_ERR_TL1_PANIC_EXIT(fecc_tl1_err); 3127c478bd9Sstevel@tonic-gate 3137c478bd9Sstevel@tonic-gate SET_SIZE(fast_ecc_tl1_err) 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate#endif /* lint */ 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate#if defined(lint) 3197c478bd9Sstevel@tonic-gate/* 3207c478bd9Sstevel@tonic-gate * scrubphys - Pass in the aligned physical memory address 3217c478bd9Sstevel@tonic-gate * that you want to scrub, along with the ecache set size. 3227c478bd9Sstevel@tonic-gate * 3237c478bd9Sstevel@tonic-gate * 1) Displacement flush the E$ line corresponding to %addr. 3247c478bd9Sstevel@tonic-gate * The first ldxa guarantees that the %addr is no longer in 3257c478bd9Sstevel@tonic-gate * M, O, or E (goes to I or S (if instruction fetch also happens). 3267c478bd9Sstevel@tonic-gate * 2) "Write" the data using a CAS %addr,%g0,%g0. 3277c478bd9Sstevel@tonic-gate * The casxa guarantees a transition from I to M or S to M. 3287c478bd9Sstevel@tonic-gate * 3) Displacement flush the E$ line corresponding to %addr. 3297c478bd9Sstevel@tonic-gate * The second ldxa pushes the M line out of the ecache, into the 3307c478bd9Sstevel@tonic-gate * writeback buffers, on the way to memory. 3317c478bd9Sstevel@tonic-gate * 4) The "membar #Sync" pushes the cache line out of the writeback 3327c478bd9Sstevel@tonic-gate * buffers onto the bus, on the way to dram finally. 3337c478bd9Sstevel@tonic-gate * 3347c478bd9Sstevel@tonic-gate * This is a modified version of the algorithm suggested by Gary Lauterbach. 3357c478bd9Sstevel@tonic-gate * In theory the CAS %addr,%g0,%g0 is supposed to mark the addr's cache line 3367c478bd9Sstevel@tonic-gate * as modified, but then we found out that for spitfire, if it misses in the 3377c478bd9Sstevel@tonic-gate * E$ it will probably install as an M, but if it hits in the E$, then it 3387c478bd9Sstevel@tonic-gate * will stay E, if the store doesn't happen. So the first displacement flush 3397c478bd9Sstevel@tonic-gate * should ensure that the CAS will miss in the E$. Arrgh. 3407c478bd9Sstevel@tonic-gate */ 3417c478bd9Sstevel@tonic-gate/* ARGSUSED */ 3427c478bd9Sstevel@tonic-gatevoid 3437c478bd9Sstevel@tonic-gatescrubphys(uint64_t paddr, int ecache_set_size) 3447c478bd9Sstevel@tonic-gate{} 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate#else /* lint */ 3477c478bd9Sstevel@tonic-gate ENTRY(scrubphys) 3487c478bd9Sstevel@tonic-gate rdpr %pstate, %o4 3497c478bd9Sstevel@tonic-gate andn %o4, PSTATE_IE | PSTATE_AM, %o5 3507c478bd9Sstevel@tonic-gate wrpr %o5, %g0, %pstate ! clear IE, AM bits 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate ECACHE_FLUSH_LINE(%o0, %o1, %o2, %o3) 3537c478bd9Sstevel@tonic-gate casxa [%o0]ASI_MEM, %g0, %g0 3547c478bd9Sstevel@tonic-gate ECACHE_REFLUSH_LINE(%o1, %o2, %o3) 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate wrpr %g0, %o4, %pstate ! restore earlier pstate register value 3577c478bd9Sstevel@tonic-gate 3587c478bd9Sstevel@tonic-gate retl 3597c478bd9Sstevel@tonic-gate membar #Sync ! move the data out of the load buffer 3607c478bd9Sstevel@tonic-gate SET_SIZE(scrubphys) 3617c478bd9Sstevel@tonic-gate 3627c478bd9Sstevel@tonic-gate#endif /* lint */ 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate#if defined(lint) 3667c478bd9Sstevel@tonic-gate /* 367*750ba224Sanbui * clearphys - Pass in the physical memory address of the checkblock 368*750ba224Sanbui * that you want to push out, cleared with a recognizable pattern, 369*750ba224Sanbui * from the ecache. 370*750ba224Sanbui * 371*750ba224Sanbui * To ensure that the ecc gets recalculated after the bad data is cleared, 372*750ba224Sanbui * we must write out enough data to fill the w$ line (64 bytes). So we read 373*750ba224Sanbui * in an entire ecache subblock's worth of data, and write it back out. 374*750ba224Sanbui * Then we overwrite the 16 bytes of bad data with the pattern. 3757c478bd9Sstevel@tonic-gate */ 3767c478bd9Sstevel@tonic-gate/* ARGSUSED */ 3777c478bd9Sstevel@tonic-gatevoid 3787c478bd9Sstevel@tonic-gateclearphys(uint64_t paddr, int ecache_set_size, int ecache_linesize) 3797c478bd9Sstevel@tonic-gate{ 3807c478bd9Sstevel@tonic-gate} 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate#else /* lint */ 3837c478bd9Sstevel@tonic-gate ENTRY(clearphys) 3847c478bd9Sstevel@tonic-gate /* turn off IE, AM bits */ 3857c478bd9Sstevel@tonic-gate rdpr %pstate, %o4 3867c478bd9Sstevel@tonic-gate andn %o4, PSTATE_IE | PSTATE_AM, %o5 3877c478bd9Sstevel@tonic-gate wrpr %o5, %g0, %pstate 3887c478bd9Sstevel@tonic-gate 3897c478bd9Sstevel@tonic-gate /* turn off NCEEN */ 3907c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_ESTATE_ERR, %o5 3917c478bd9Sstevel@tonic-gate andn %o5, EN_REG_NCEEN, %o3 3927c478bd9Sstevel@tonic-gate stxa %o3, [%g0]ASI_ESTATE_ERR 3937c478bd9Sstevel@tonic-gate membar #Sync 3947c478bd9Sstevel@tonic-gate 395*750ba224Sanbui /* align address passed with 64 bytes subblock size */ 396*750ba224Sanbui mov CH_ECACHE_SUBBLK_SIZE, %o2 397*750ba224Sanbui andn %o0, (CH_ECACHE_SUBBLK_SIZE - 1), %g1 398*750ba224Sanbui 399*750ba224Sanbui /* move the good data into the W$ */ 4007c478bd9Sstevel@tonic-gate1: 4017c478bd9Sstevel@tonic-gate subcc %o2, 8, %o2 402*750ba224Sanbui ldxa [%g1 + %o2]ASI_MEM, %g2 4037c478bd9Sstevel@tonic-gate bge 1b 404*750ba224Sanbui stxa %g2, [%g1 + %o2]ASI_MEM 405*750ba224Sanbui 406*750ba224Sanbui /* now overwrite the bad data */ 407*750ba224Sanbui setx 0xbadecc00badecc01, %g1, %g2 408*750ba224Sanbui stxa %g2, [%o0]ASI_MEM 409*750ba224Sanbui mov 8, %g1 410*750ba224Sanbui stxa %g2, [%o0 + %g1]ASI_MEM 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate ECACHE_FLUSH_LINE(%o0, %o1, %o2, %o3) 4137c478bd9Sstevel@tonic-gate casxa [%o0]ASI_MEM, %g0, %g0 4147c478bd9Sstevel@tonic-gate ECACHE_REFLUSH_LINE(%o1, %o2, %o3) 4157c478bd9Sstevel@tonic-gate 4167c478bd9Sstevel@tonic-gate /* clear the AFSR */ 4177c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_AFSR, %o1 4187c478bd9Sstevel@tonic-gate stxa %o1, [%g0]ASI_AFSR 4197c478bd9Sstevel@tonic-gate membar #Sync 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate /* turn NCEEN back on */ 4227c478bd9Sstevel@tonic-gate stxa %o5, [%g0]ASI_ESTATE_ERR 4237c478bd9Sstevel@tonic-gate membar #Sync 4247c478bd9Sstevel@tonic-gate 4257c478bd9Sstevel@tonic-gate /* return and re-enable IE and AM */ 4267c478bd9Sstevel@tonic-gate retl 4277c478bd9Sstevel@tonic-gate wrpr %g0, %o4, %pstate 4287c478bd9Sstevel@tonic-gate SET_SIZE(clearphys) 4297c478bd9Sstevel@tonic-gate 4307c478bd9Sstevel@tonic-gate#endif /* lint */ 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate 4337c478bd9Sstevel@tonic-gate#if defined(lint) 4347c478bd9Sstevel@tonic-gate/* 4357c478bd9Sstevel@tonic-gate * Cheetah Ecache displacement flush the specified line from the E$ 4367c478bd9Sstevel@tonic-gate * 4377c478bd9Sstevel@tonic-gate * Register usage: 4387c478bd9Sstevel@tonic-gate * %o0 - 64 bit physical address for flushing 4397c478bd9Sstevel@tonic-gate * %o1 - Ecache set size 4407c478bd9Sstevel@tonic-gate */ 4417c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 4427c478bd9Sstevel@tonic-gatevoid 4437c478bd9Sstevel@tonic-gateecache_flush_line(uint64_t flushaddr, int ec_set_size) 4447c478bd9Sstevel@tonic-gate{ 4457c478bd9Sstevel@tonic-gate} 4467c478bd9Sstevel@tonic-gate#else /* lint */ 4477c478bd9Sstevel@tonic-gate ENTRY(ecache_flush_line) 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate ECACHE_FLUSH_LINE(%o0, %o1, %o2, %o3) 4507c478bd9Sstevel@tonic-gate 4517c478bd9Sstevel@tonic-gate retl 4527c478bd9Sstevel@tonic-gate nop 4537c478bd9Sstevel@tonic-gate SET_SIZE(ecache_flush_line) 4547c478bd9Sstevel@tonic-gate#endif /* lint */ 4557c478bd9Sstevel@tonic-gate 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate#if defined(lint) 4587c478bd9Sstevel@tonic-gate/* 4597c478bd9Sstevel@tonic-gate * This routine will not be called in Cheetah systems. 4607c478bd9Sstevel@tonic-gate */ 4617c478bd9Sstevel@tonic-gatevoid 4627c478bd9Sstevel@tonic-gateflush_ipb(void) 4637c478bd9Sstevel@tonic-gate{ return; } 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate#else /* lint */ 4667c478bd9Sstevel@tonic-gate 4677c478bd9Sstevel@tonic-gate ENTRY(flush_ipb) 4687c478bd9Sstevel@tonic-gate retl 4697c478bd9Sstevel@tonic-gate nop 4707c478bd9Sstevel@tonic-gate SET_SIZE(flush_ipb) 4717c478bd9Sstevel@tonic-gate 4727c478bd9Sstevel@tonic-gate#endif /* lint */ 473