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 51e2e7a75Shuah * Common Development and Distribution License (the "License"). 61e2e7a75Shuah * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate/* 22*2dd3029aSjimand * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate#pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate#if !defined(lint) 297c478bd9Sstevel@tonic-gate#include "assym.h" 307c478bd9Sstevel@tonic-gate#endif /* lint */ 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h> 337c478bd9Sstevel@tonic-gate#include <sys/mmu.h> 347c478bd9Sstevel@tonic-gate#include <vm/hat_sfmmu.h> 357c478bd9Sstevel@tonic-gate#include <sys/machparam.h> 367c478bd9Sstevel@tonic-gate#include <sys/machcpuvar.h> 377c478bd9Sstevel@tonic-gate#include <sys/machthread.h> 387c478bd9Sstevel@tonic-gate#include <sys/privregs.h> 397c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h> 407c478bd9Sstevel@tonic-gate#include <sys/machasi.h> 417c478bd9Sstevel@tonic-gate#include <sys/trap.h> 427c478bd9Sstevel@tonic-gate#include <sys/spitregs.h> 437c478bd9Sstevel@tonic-gate#include <sys/xc_impl.h> 447c478bd9Sstevel@tonic-gate#include <sys/intreg.h> 457c478bd9Sstevel@tonic-gate#include <sys/async.h> 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate#ifdef TRAPTRACE 487c478bd9Sstevel@tonic-gate#include <sys/traptrace.h> 497c478bd9Sstevel@tonic-gate#endif /* TRAPTRACE */ 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate#ifndef lint 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate/* BEGIN CSTYLED */ 547c478bd9Sstevel@tonic-gate#define DCACHE_FLUSHPAGE(arg1, arg2, tmp1, tmp2, tmp3) \ 557c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_LSU, tmp1 ;\ 567c478bd9Sstevel@tonic-gate btst LSU_DC, tmp1 /* is dcache enabled? */ ;\ 577c478bd9Sstevel@tonic-gate bz,pn %icc, 1f ;\ 587c478bd9Sstevel@tonic-gate sethi %hi(dcache_linesize), tmp1 ;\ 597c478bd9Sstevel@tonic-gate ld [tmp1 + %lo(dcache_linesize)], tmp1 ;\ 607c478bd9Sstevel@tonic-gate sethi %hi(dflush_type), tmp2 ;\ 617c478bd9Sstevel@tonic-gate ld [tmp2 + %lo(dflush_type)], tmp2 ;\ 627c478bd9Sstevel@tonic-gate cmp tmp2, FLUSHPAGE_TYPE ;\ 637c478bd9Sstevel@tonic-gate be,pt %icc, 2f ;\ 647c478bd9Sstevel@tonic-gate sllx arg1, SF_DC_VBIT_SHIFT, arg1 /* tag to compare */ ;\ 657c478bd9Sstevel@tonic-gate sethi %hi(dcache_size), tmp3 ;\ 667c478bd9Sstevel@tonic-gate ld [tmp3 + %lo(dcache_size)], tmp3 ;\ 677c478bd9Sstevel@tonic-gate cmp tmp2, FLUSHMATCH_TYPE ;\ 687c478bd9Sstevel@tonic-gate be,pt %icc, 3f ;\ 697c478bd9Sstevel@tonic-gate nop ;\ 707c478bd9Sstevel@tonic-gate /* \ 717c478bd9Sstevel@tonic-gate * flushtype = FLUSHALL_TYPE, flush the whole thing \ 727c478bd9Sstevel@tonic-gate * tmp3 = cache size \ 737c478bd9Sstevel@tonic-gate * tmp1 = cache line size \ 747c478bd9Sstevel@tonic-gate */ \ 757c478bd9Sstevel@tonic-gate sub tmp3, tmp1, tmp2 ;\ 767c478bd9Sstevel@tonic-gate4: \ 777c478bd9Sstevel@tonic-gate stxa %g0, [tmp2]ASI_DC_TAG ;\ 787c478bd9Sstevel@tonic-gate membar #Sync ;\ 797c478bd9Sstevel@tonic-gate cmp %g0, tmp2 ;\ 807c478bd9Sstevel@tonic-gate bne,pt %icc, 4b ;\ 817c478bd9Sstevel@tonic-gate sub tmp2, tmp1, tmp2 ;\ 827c478bd9Sstevel@tonic-gate ba,pt %icc, 1f ;\ 837c478bd9Sstevel@tonic-gate nop ;\ 847c478bd9Sstevel@tonic-gate /* \ 857c478bd9Sstevel@tonic-gate * flushtype = FLUSHPAGE_TYPE \ 867c478bd9Sstevel@tonic-gate * arg1 = tag to compare against \ 877c478bd9Sstevel@tonic-gate * arg2 = virtual color \ 887c478bd9Sstevel@tonic-gate * tmp1 = cache line size \ 897c478bd9Sstevel@tonic-gate * tmp2 = tag from cache \ 907c478bd9Sstevel@tonic-gate * tmp3 = counter \ 917c478bd9Sstevel@tonic-gate */ \ 927c478bd9Sstevel@tonic-gate2: \ 937c478bd9Sstevel@tonic-gate set MMU_PAGESIZE, tmp3 ;\ 947c478bd9Sstevel@tonic-gate sllx arg2, MMU_PAGESHIFT, arg2 /* color to dcache page */ ;\ 957c478bd9Sstevel@tonic-gate sub tmp3, tmp1, tmp3 ;\ 967c478bd9Sstevel@tonic-gate4: \ 977c478bd9Sstevel@tonic-gate ldxa [arg2 + tmp3]ASI_DC_TAG, tmp2 /* read tag */ ;\ 987c478bd9Sstevel@tonic-gate btst SF_DC_VBIT_MASK, tmp2 ;\ 997c478bd9Sstevel@tonic-gate bz,pn %icc, 5f /* branch if no valid sub-blocks */ ;\ 1007c478bd9Sstevel@tonic-gate andn tmp2, SF_DC_VBIT_MASK, tmp2 /* clear out v bits */ ;\ 1017c478bd9Sstevel@tonic-gate cmp tmp2, arg1 ;\ 1027c478bd9Sstevel@tonic-gate bne,pn %icc, 5f /* br if tag miss */ ;\ 1037c478bd9Sstevel@tonic-gate nop ;\ 1047c478bd9Sstevel@tonic-gate stxa %g0, [arg2 + tmp3]ASI_DC_TAG ;\ 1057c478bd9Sstevel@tonic-gate membar #Sync ;\ 1067c478bd9Sstevel@tonic-gate5: \ 1077c478bd9Sstevel@tonic-gate cmp %g0, tmp3 ;\ 1087c478bd9Sstevel@tonic-gate bnz,pt %icc, 4b /* branch if not done */ ;\ 1097c478bd9Sstevel@tonic-gate sub tmp3, tmp1, tmp3 ;\ 1107c478bd9Sstevel@tonic-gate ba,pt %icc, 1f ;\ 1117c478bd9Sstevel@tonic-gate nop ;\ 1127c478bd9Sstevel@tonic-gate /* \ 1137c478bd9Sstevel@tonic-gate * flushtype = FLUSHMATCH_TYPE \ 1147c478bd9Sstevel@tonic-gate * arg1 = tag to compare against \ 1157c478bd9Sstevel@tonic-gate * tmp1 = cache line size \ 1167c478bd9Sstevel@tonic-gate * tmp3 = cache size \ 1177c478bd9Sstevel@tonic-gate * arg2 = counter \ 1187c478bd9Sstevel@tonic-gate * tmp2 = cache tag \ 1197c478bd9Sstevel@tonic-gate */ \ 1207c478bd9Sstevel@tonic-gate3: \ 1217c478bd9Sstevel@tonic-gate sub tmp3, tmp1, arg2 ;\ 1227c478bd9Sstevel@tonic-gate4: \ 1237c478bd9Sstevel@tonic-gate ldxa [arg2]ASI_DC_TAG, tmp2 /* read tag */ ;\ 1247c478bd9Sstevel@tonic-gate btst SF_DC_VBIT_MASK, tmp2 ;\ 1257c478bd9Sstevel@tonic-gate bz,pn %icc, 5f /* br if no valid sub-blocks */ ;\ 1267c478bd9Sstevel@tonic-gate andn tmp2, SF_DC_VBIT_MASK, tmp2 /* clear out v bits */ ;\ 1277c478bd9Sstevel@tonic-gate cmp tmp2, arg1 ;\ 1287c478bd9Sstevel@tonic-gate bne,pn %icc, 5f /* branch if tag miss */ ;\ 1297c478bd9Sstevel@tonic-gate nop ;\ 1307c478bd9Sstevel@tonic-gate stxa %g0, [arg2]ASI_DC_TAG ;\ 1317c478bd9Sstevel@tonic-gate membar #Sync ;\ 1327c478bd9Sstevel@tonic-gate5: \ 1337c478bd9Sstevel@tonic-gate cmp %g0, arg2 ;\ 1347c478bd9Sstevel@tonic-gate bne,pt %icc, 4b /* branch if not done */ ;\ 1357c478bd9Sstevel@tonic-gate sub arg2, tmp1, arg2 ;\ 1367c478bd9Sstevel@tonic-gate1: 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate/* 1397c478bd9Sstevel@tonic-gate * macro that flushes the entire dcache color 1407c478bd9Sstevel@tonic-gate */ 1417c478bd9Sstevel@tonic-gate#define DCACHE_FLUSHCOLOR(arg, tmp1, tmp2) \ 1427c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_LSU, tmp1; \ 1437c478bd9Sstevel@tonic-gate btst LSU_DC, tmp1; /* is dcache enabled? */ \ 1447c478bd9Sstevel@tonic-gate bz,pn %icc, 1f; \ 1457c478bd9Sstevel@tonic-gate sethi %hi(dcache_linesize), tmp1; \ 1467c478bd9Sstevel@tonic-gate ld [tmp1 + %lo(dcache_linesize)], tmp1; \ 1477c478bd9Sstevel@tonic-gate set MMU_PAGESIZE, tmp2; \ 1487c478bd9Sstevel@tonic-gate /* \ 1497c478bd9Sstevel@tonic-gate * arg = virtual color \ 1507c478bd9Sstevel@tonic-gate * tmp2 = page size \ 1517c478bd9Sstevel@tonic-gate * tmp1 = cache line size \ 1527c478bd9Sstevel@tonic-gate */ \ 1537c478bd9Sstevel@tonic-gate sllx arg, MMU_PAGESHIFT, arg; /* color to dcache page */ \ 1547c478bd9Sstevel@tonic-gate sub tmp2, tmp1, tmp2; \ 1557c478bd9Sstevel@tonic-gate2: \ 1567c478bd9Sstevel@tonic-gate stxa %g0, [arg + tmp2]ASI_DC_TAG; \ 1577c478bd9Sstevel@tonic-gate membar #Sync; \ 1587c478bd9Sstevel@tonic-gate cmp %g0, tmp2; \ 1597c478bd9Sstevel@tonic-gate bne,pt %icc, 2b; \ 1607c478bd9Sstevel@tonic-gate sub tmp2, tmp1, tmp2; \ 1617c478bd9Sstevel@tonic-gate1: 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate/* 1647c478bd9Sstevel@tonic-gate * macro that flushes the entire dcache 1657c478bd9Sstevel@tonic-gate */ 1667c478bd9Sstevel@tonic-gate#define DCACHE_FLUSHALL(size, linesize, tmp) \ 1677c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_LSU, tmp; \ 1687c478bd9Sstevel@tonic-gate btst LSU_DC, tmp; /* is dcache enabled? */ \ 1697c478bd9Sstevel@tonic-gate bz,pn %icc, 1f; \ 1707c478bd9Sstevel@tonic-gate \ 1717c478bd9Sstevel@tonic-gate sub size, linesize, tmp; \ 1727c478bd9Sstevel@tonic-gate2: \ 1737c478bd9Sstevel@tonic-gate stxa %g0, [tmp]ASI_DC_TAG; \ 1747c478bd9Sstevel@tonic-gate membar #Sync; \ 1757c478bd9Sstevel@tonic-gate cmp %g0, tmp; \ 1767c478bd9Sstevel@tonic-gate bne,pt %icc, 2b; \ 1777c478bd9Sstevel@tonic-gate sub tmp, linesize, tmp; \ 1787c478bd9Sstevel@tonic-gate1: 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate/* 1817c478bd9Sstevel@tonic-gate * macro that flushes the entire icache 1827c478bd9Sstevel@tonic-gate */ 1837c478bd9Sstevel@tonic-gate#define ICACHE_FLUSHALL(size, linesize, tmp) \ 1847c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_LSU, tmp; \ 1857c478bd9Sstevel@tonic-gate btst LSU_IC, tmp; \ 1867c478bd9Sstevel@tonic-gate bz,pn %icc, 1f; \ 1877c478bd9Sstevel@tonic-gate \ 1887c478bd9Sstevel@tonic-gate sub size, linesize, tmp; \ 1897c478bd9Sstevel@tonic-gate2: \ 1907c478bd9Sstevel@tonic-gate stxa %g0, [tmp]ASI_IC_TAG; \ 1917c478bd9Sstevel@tonic-gate membar #Sync; \ 1927c478bd9Sstevel@tonic-gate cmp %g0, tmp; \ 1937c478bd9Sstevel@tonic-gate bne,pt %icc, 2b; \ 1947c478bd9Sstevel@tonic-gate sub tmp, linesize, tmp; \ 1957c478bd9Sstevel@tonic-gate1: 1967c478bd9Sstevel@tonic-gate 1971e2e7a75Shuah#ifdef SF_ERRATA_32 1981e2e7a75Shuah#define SF_WORKAROUND(tmp1, tmp2) \ 1991e2e7a75Shuah sethi %hi(FLUSH_ADDR), tmp2 ;\ 2001e2e7a75Shuah set MMU_PCONTEXT, tmp1 ;\ 2011e2e7a75Shuah stxa %g0, [tmp1]ASI_DMMU ;\ 2021e2e7a75Shuah flush tmp2 ; 2031e2e7a75Shuah#else 2041e2e7a75Shuah#define SF_WORKAROUND(tmp1, tmp2) 2051e2e7a75Shuah#endif /* SF_ERRATA_32 */ 2061e2e7a75Shuah 2071e2e7a75Shuah/* 2081e2e7a75Shuah * arg1 = vaddr 2091e2e7a75Shuah * arg2 = ctxnum 2101e2e7a75Shuah * - disable interrupts and clear address mask 2111e2e7a75Shuah * to access 64 bit physaddr 2121e2e7a75Shuah * - Blow out the TLB, flush user page. 2131e2e7a75Shuah * . use secondary context. 2141e2e7a75Shuah */ 2151e2e7a75Shuah#define VTAG_FLUSHUPAGE(lbl, arg1, arg2, tmp1, tmp2, tmp3, tmp4) \ 2161e2e7a75Shuah rdpr %pstate, tmp1 ;\ 2171e2e7a75Shuah andn tmp1, PSTATE_IE, tmp2 ;\ 2181e2e7a75Shuah wrpr tmp2, 0, %pstate ;\ 2191e2e7a75Shuah sethi %hi(FLUSH_ADDR), tmp2 ;\ 2201e2e7a75Shuah set MMU_SCONTEXT, tmp3 ;\ 2211e2e7a75Shuah ldxa [tmp3]ASI_DMMU, tmp4 ;\ 2221e2e7a75Shuah or DEMAP_SECOND | DEMAP_PAGE_TYPE, arg1, arg1 ;\ 2231e2e7a75Shuah cmp tmp4, arg2 ;\ 2241e2e7a75Shuah be,a,pt %icc, lbl/**/4 ;\ 2251e2e7a75Shuah nop ;\ 2261e2e7a75Shuah stxa arg2, [tmp3]ASI_DMMU ;\ 2271e2e7a75Shuahlbl/**/4: ;\ 2281e2e7a75Shuah stxa %g0, [arg1]ASI_DTLB_DEMAP ;\ 2291e2e7a75Shuah stxa %g0, [arg1]ASI_ITLB_DEMAP ;\ 2301e2e7a75Shuah flush tmp2 ;\ 2311e2e7a75Shuah be,a,pt %icc, lbl/**/5 ;\ 2321e2e7a75Shuah nop ;\ 2331e2e7a75Shuah stxa tmp4, [tmp3]ASI_DMMU ;\ 2341e2e7a75Shuah flush tmp2 ;\ 2351e2e7a75Shuahlbl/**/5: ;\ 2361e2e7a75Shuah wrpr %g0, tmp1, %pstate 2371e2e7a75Shuah 2381e2e7a75Shuah 2391e2e7a75Shuah/* 2401e2e7a75Shuah * macro that flushes all the user entries in dtlb 2411e2e7a75Shuah * arg1 = dtlb entries 2421e2e7a75Shuah * - Before first compare: 2431e2e7a75Shuah * tmp4 = tte 2441e2e7a75Shuah * tmp5 = vaddr 2451e2e7a75Shuah * tmp6 = cntxnum 2461e2e7a75Shuah */ 2471e2e7a75Shuah#define DTLB_FLUSH_UNLOCKED_UCTXS(lbl, arg1, tmp1, tmp2, tmp3, \ 2481e2e7a75Shuah tmp4, tmp5, tmp6) \ 2491e2e7a75Shuahlbl/**/0: ;\ 2501e2e7a75Shuah sllx arg1, 3, tmp3 ;\ 2511e2e7a75Shuah SF_WORKAROUND(tmp1, tmp2) ;\ 2521e2e7a75Shuah ldxa [tmp3]ASI_DTLB_ACCESS, tmp4 ;\ 2531e2e7a75Shuah srlx tmp4, 6, tmp4 ;\ 2541e2e7a75Shuah andcc tmp4, 1, %g0 ;\ 2551e2e7a75Shuah bnz,pn %xcc, lbl/**/1 ;\ 2561e2e7a75Shuah srlx tmp4, 57, tmp4 ;\ 2571e2e7a75Shuah andcc tmp4, 1, %g0 ;\ 2581e2e7a75Shuah beq,pn %xcc, lbl/**/1 ;\ 2591e2e7a75Shuah nop ;\ 2601e2e7a75Shuah set TAGREAD_CTX_MASK, tmp1 ;\ 2611e2e7a75Shuah ldxa [tmp3]ASI_DTLB_TAGREAD, tmp2 ;\ 2621e2e7a75Shuah and tmp2, tmp1, tmp6 ;\ 2631e2e7a75Shuah andn tmp2, tmp1, tmp5 ;\ 2641e2e7a75Shuah set KCONTEXT, tmp4 ;\ 2651e2e7a75Shuah cmp tmp6, tmp4 ;\ 2661e2e7a75Shuah be lbl/**/1 ;\ 2671e2e7a75Shuah nop ;\ 2681e2e7a75Shuah VTAG_FLUSHUPAGE(VD/**/lbl, tmp5, tmp6, tmp1, tmp2, tmp3, tmp4) ;\ 2691e2e7a75Shuahlbl/**/1: ;\ 2701e2e7a75Shuah brgz,pt arg1, lbl/**/0 ;\ 2711e2e7a75Shuah sub arg1, 1, arg1 2721e2e7a75Shuah 2731e2e7a75Shuah 2741e2e7a75Shuah/* 2751e2e7a75Shuah * macro that flushes all the user entries in itlb 2761e2e7a75Shuah * arg1 = itlb entries 2771e2e7a75Shuah * - Before first compare: 2781e2e7a75Shuah * tmp4 = tte 2791e2e7a75Shuah * tmp5 = vaddr 2801e2e7a75Shuah * tmp6 = cntxnum 2811e2e7a75Shuah */ 2821e2e7a75Shuah#define ITLB_FLUSH_UNLOCKED_UCTXS(lbl, arg1, tmp1, tmp2, tmp3, \ 2831e2e7a75Shuah tmp4, tmp5, tmp6) \ 2841e2e7a75Shuahlbl/**/0: ;\ 2851e2e7a75Shuah sllx arg1, 3, tmp3 ;\ 2861e2e7a75Shuah SF_WORKAROUND(tmp1, tmp2) ;\ 2871e2e7a75Shuah ldxa [tmp3]ASI_ITLB_ACCESS, tmp4 ;\ 2881e2e7a75Shuah srlx tmp4, 6, tmp4 ;\ 2891e2e7a75Shuah andcc tmp4, 1, %g0 ;\ 2901e2e7a75Shuah bnz,pn %xcc, lbl/**/1 ;\ 2911e2e7a75Shuah srlx tmp4, 57, tmp4 ;\ 2921e2e7a75Shuah andcc tmp4, 1, %g0 ;\ 2931e2e7a75Shuah beq,pn %xcc, lbl/**/1 ;\ 2941e2e7a75Shuah nop ;\ 2951e2e7a75Shuah set TAGREAD_CTX_MASK, tmp1 ;\ 2961e2e7a75Shuah ldxa [tmp3]ASI_ITLB_TAGREAD, tmp2 ;\ 2971e2e7a75Shuah and tmp2, tmp1, tmp6 ;\ 2981e2e7a75Shuah andn tmp2, tmp1, tmp5 ;\ 2991e2e7a75Shuah set KCONTEXT, tmp4 ;\ 3001e2e7a75Shuah cmp tmp6, tmp4 ;\ 3011e2e7a75Shuah be lbl/**/1 ;\ 3021e2e7a75Shuah nop ;\ 3031e2e7a75Shuah VTAG_FLUSHUPAGE(VI/**/lbl, tmp5, tmp6, tmp1, tmp2, tmp3, tmp4) ;\ 3041e2e7a75Shuahlbl/**/1: ;\ 3051e2e7a75Shuah brgz,pt arg1, lbl/**/0 ;\ 3061e2e7a75Shuah sub arg1, 1, arg1 3071e2e7a75Shuah 3081e2e7a75Shuah 3091e2e7a75Shuah 3107c478bd9Sstevel@tonic-gate/* 3117c478bd9Sstevel@tonic-gate * Macro for getting to offset from 'cpu_private' ptr. The 'cpu_private' 3127c478bd9Sstevel@tonic-gate * ptr is in the machcpu structure. 3137c478bd9Sstevel@tonic-gate * r_or_s: Register or symbol off offset from 'cpu_private' ptr. 3147c478bd9Sstevel@tonic-gate * scr1: Scratch, ptr is returned in this register. 3157c478bd9Sstevel@tonic-gate * scr2: Scratch 3167c478bd9Sstevel@tonic-gate */ 3177c478bd9Sstevel@tonic-gate#define GET_CPU_PRIVATE_PTR(r_or_s, scr1, scr2, label) \ 3187c478bd9Sstevel@tonic-gate CPU_ADDR(scr1, scr2); \ 3197c478bd9Sstevel@tonic-gate ldn [scr1 + CPU_PRIVATE], scr1; \ 3207c478bd9Sstevel@tonic-gate cmp scr1, 0; \ 3217c478bd9Sstevel@tonic-gate be label; \ 3227c478bd9Sstevel@tonic-gate nop; \ 3237c478bd9Sstevel@tonic-gate add scr1, r_or_s, scr1; \ 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate#ifdef HUMMINGBIRD 3267c478bd9Sstevel@tonic-gate/* 3277c478bd9Sstevel@tonic-gate * UltraSPARC-IIe processor supports both 4-way set associative and 3287c478bd9Sstevel@tonic-gate * direct map E$. For performance reasons, we flush E$ by placing it 3297c478bd9Sstevel@tonic-gate * in direct map mode for data load/store and restore the state after 3307c478bd9Sstevel@tonic-gate * we are done flushing it. Keep interrupts off while flushing in this 3317c478bd9Sstevel@tonic-gate * manner. 3327c478bd9Sstevel@tonic-gate * 3337c478bd9Sstevel@tonic-gate * We flush the entire ecache by starting at one end and loading each 3347c478bd9Sstevel@tonic-gate * successive ecache line for the 2*ecache-size range. We have to repeat 3357c478bd9Sstevel@tonic-gate * the flush operation to guarantee that the entire ecache has been 3367c478bd9Sstevel@tonic-gate * flushed. 3377c478bd9Sstevel@tonic-gate * 3387c478bd9Sstevel@tonic-gate * For flushing a specific physical address, we start at the aliased 3397c478bd9Sstevel@tonic-gate * address and load at set-size stride, wrapping around at 2*ecache-size 3407c478bd9Sstevel@tonic-gate * boundary and skipping the physical address being flushed. It takes 3417c478bd9Sstevel@tonic-gate * 10 loads to guarantee that the physical address has been flushed. 3427c478bd9Sstevel@tonic-gate */ 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate#define HB_ECACHE_FLUSH_CNT 2 3457c478bd9Sstevel@tonic-gate#define HB_PHYS_FLUSH_CNT 10 /* #loads to flush specific paddr */ 3467c478bd9Sstevel@tonic-gate#endif /* HUMMINGBIRD */ 3477c478bd9Sstevel@tonic-gate 3487c478bd9Sstevel@tonic-gate/* END CSTYLED */ 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate#endif /* !lint */ 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate/* 3537c478bd9Sstevel@tonic-gate * Spitfire MMU and Cache operations. 3547c478bd9Sstevel@tonic-gate */ 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate#if defined(lint) 3577c478bd9Sstevel@tonic-gate 3587c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 3597c478bd9Sstevel@tonic-gatevoid 3601e2e7a75Shuahvtag_flushpage(caddr_t vaddr, uint64_t sfmmup) 3617c478bd9Sstevel@tonic-gate{} 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 3647c478bd9Sstevel@tonic-gatevoid 3657c478bd9Sstevel@tonic-gatevtag_flushall(void) 3667c478bd9Sstevel@tonic-gate{} 3677c478bd9Sstevel@tonic-gate 3687c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 3697c478bd9Sstevel@tonic-gatevoid 3701e2e7a75Shuahvtag_flushall_uctxs(void) 3717c478bd9Sstevel@tonic-gate{} 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 3747c478bd9Sstevel@tonic-gatevoid 3751e2e7a75Shuahvtag_flushpage_tl1(uint64_t vaddr, uint64_t sfmmup) 3767c478bd9Sstevel@tonic-gate{} 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 3797c478bd9Sstevel@tonic-gatevoid 3801e2e7a75Shuahvtag_flush_pgcnt_tl1(uint64_t vaddr, uint64_t sfmmup_pgcnt) 3817c478bd9Sstevel@tonic-gate{} 3827c478bd9Sstevel@tonic-gate 3837c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 3847c478bd9Sstevel@tonic-gatevoid 3857c478bd9Sstevel@tonic-gatevtag_flushall_tl1(uint64_t dummy1, uint64_t dummy2) 3867c478bd9Sstevel@tonic-gate{} 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 3897c478bd9Sstevel@tonic-gatevoid 3907c478bd9Sstevel@tonic-gatevac_flushpage(pfn_t pfnum, int vcolor) 3917c478bd9Sstevel@tonic-gate{} 3927c478bd9Sstevel@tonic-gate 3937c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 3947c478bd9Sstevel@tonic-gatevoid 3957c478bd9Sstevel@tonic-gatevac_flushpage_tl1(uint64_t pfnum, uint64_t vcolor) 3967c478bd9Sstevel@tonic-gate{} 3977c478bd9Sstevel@tonic-gate 3987c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 3997c478bd9Sstevel@tonic-gatevoid 4007c478bd9Sstevel@tonic-gateinit_mondo(xcfunc_t *func, uint64_t arg1, uint64_t arg2) 4017c478bd9Sstevel@tonic-gate{} 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 4047c478bd9Sstevel@tonic-gatevoid 4057c478bd9Sstevel@tonic-gateinit_mondo_nocheck(xcfunc_t *func, uint64_t arg1, uint64_t arg2) 4067c478bd9Sstevel@tonic-gate{} 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 4097c478bd9Sstevel@tonic-gatevoid 4107c478bd9Sstevel@tonic-gateflush_instr_mem(caddr_t vaddr, size_t len) 4117c478bd9Sstevel@tonic-gate{} 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 4147c478bd9Sstevel@tonic-gatevoid 4157c478bd9Sstevel@tonic-gateflush_ecache(uint64_t physaddr, size_t size, size_t linesize) 4167c478bd9Sstevel@tonic-gate{} 4177c478bd9Sstevel@tonic-gate 4187c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 4197c478bd9Sstevel@tonic-gatevoid 4207c478bd9Sstevel@tonic-gateget_ecache_dtag(uint32_t ecache_idx, uint64_t *ecache_data, 4217c478bd9Sstevel@tonic-gate uint64_t *ecache_tag, uint64_t *oafsr, uint64_t *acc_afsr) 4227c478bd9Sstevel@tonic-gate{} 4237c478bd9Sstevel@tonic-gate 4247c478bd9Sstevel@tonic-gate/* ARGSUSED */ 4257c478bd9Sstevel@tonic-gateuint64_t 4267c478bd9Sstevel@tonic-gateget_ecache_tag(uint32_t id, uint64_t *nafsr, uint64_t *acc_afsr) 4277c478bd9Sstevel@tonic-gate{ 4287c478bd9Sstevel@tonic-gate return ((uint64_t)0); 4297c478bd9Sstevel@tonic-gate} 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate/* ARGSUSED */ 4327c478bd9Sstevel@tonic-gateuint64_t 4337c478bd9Sstevel@tonic-gatecheck_ecache_line(uint32_t id, uint64_t *acc_afsr) 4347c478bd9Sstevel@tonic-gate{ 4357c478bd9Sstevel@tonic-gate return ((uint64_t)0); 4367c478bd9Sstevel@tonic-gate} 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 4397c478bd9Sstevel@tonic-gatevoid 4407c478bd9Sstevel@tonic-gatekdi_flush_idcache(int dcache_size, int dcache_lsize, 4417c478bd9Sstevel@tonic-gate int icache_size, int icache_lsize) 4427c478bd9Sstevel@tonic-gate{} 4437c478bd9Sstevel@tonic-gate 4447c478bd9Sstevel@tonic-gate#else /* lint */ 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate ENTRY_NP(vtag_flushpage) 4477c478bd9Sstevel@tonic-gate /* 4487c478bd9Sstevel@tonic-gate * flush page from the tlb 4497c478bd9Sstevel@tonic-gate * 4507c478bd9Sstevel@tonic-gate * %o0 = vaddr 4511e2e7a75Shuah * %o1 = sfmmup 4527c478bd9Sstevel@tonic-gate */ 4537c478bd9Sstevel@tonic-gate rdpr %pstate, %o5 4547c478bd9Sstevel@tonic-gate#ifdef DEBUG 4551e2e7a75Shuah PANIC_IF_INTR_DISABLED_PSTR(%o5, sfdi_label1, %g1) 4567c478bd9Sstevel@tonic-gate#endif /* DEBUG */ 4577c478bd9Sstevel@tonic-gate /* 4587c478bd9Sstevel@tonic-gate * disable ints 4597c478bd9Sstevel@tonic-gate */ 4607c478bd9Sstevel@tonic-gate andn %o5, PSTATE_IE, %o4 4617c478bd9Sstevel@tonic-gate wrpr %o4, 0, %pstate 4627c478bd9Sstevel@tonic-gate 4637c478bd9Sstevel@tonic-gate /* 4647c478bd9Sstevel@tonic-gate * Then, blow out the tlb 4657c478bd9Sstevel@tonic-gate * Interrupts are disabled to prevent the secondary ctx register 4667c478bd9Sstevel@tonic-gate * from changing underneath us. 4677c478bd9Sstevel@tonic-gate */ 4681e2e7a75Shuah sethi %hi(ksfmmup), %o3 4691e2e7a75Shuah ldx [%o3 + %lo(ksfmmup)], %o3 4701e2e7a75Shuah cmp %o3, %o1 4711e2e7a75Shuah bne,pt %xcc, 1f ! if not kernel as, go to 1 4727c478bd9Sstevel@tonic-gate sethi %hi(FLUSH_ADDR), %o3 4737c478bd9Sstevel@tonic-gate /* 4747c478bd9Sstevel@tonic-gate * For KCONTEXT demaps use primary. type = page implicitly 4757c478bd9Sstevel@tonic-gate */ 4767c478bd9Sstevel@tonic-gate stxa %g0, [%o0]ASI_DTLB_DEMAP /* dmmu flush for KCONTEXT */ 4777c478bd9Sstevel@tonic-gate stxa %g0, [%o0]ASI_ITLB_DEMAP /* immu flush for KCONTEXT */ 4787c478bd9Sstevel@tonic-gate flush %o3 4791e2e7a75Shuah b 5f 4801e2e7a75Shuah nop 4817c478bd9Sstevel@tonic-gate1: 4827c478bd9Sstevel@tonic-gate /* 4837c478bd9Sstevel@tonic-gate * User demap. We need to set the secondary context properly. 4847c478bd9Sstevel@tonic-gate * %o0 = vaddr 4851e2e7a75Shuah * %o1 = sfmmup 4867c478bd9Sstevel@tonic-gate * %o3 = FLUSH_ADDR 4877c478bd9Sstevel@tonic-gate */ 4881e2e7a75Shuah SFMMU_CPU_CNUM(%o1, %g1, %g2) /* %g1 = sfmmu cnum on this CPU */ 4891e2e7a75Shuah 4907c478bd9Sstevel@tonic-gate set MMU_SCONTEXT, %o4 4917c478bd9Sstevel@tonic-gate ldxa [%o4]ASI_DMMU, %o2 /* rd old ctxnum */ 4927c478bd9Sstevel@tonic-gate or DEMAP_SECOND | DEMAP_PAGE_TYPE, %o0, %o0 4931e2e7a75Shuah cmp %o2, %g1 4941e2e7a75Shuah be,pt %icc, 4f 4957c478bd9Sstevel@tonic-gate nop 4961e2e7a75Shuah stxa %g1, [%o4]ASI_DMMU /* wr new ctxum */ 4977c478bd9Sstevel@tonic-gate4: 4987c478bd9Sstevel@tonic-gate stxa %g0, [%o0]ASI_DTLB_DEMAP 4997c478bd9Sstevel@tonic-gate stxa %g0, [%o0]ASI_ITLB_DEMAP 5007c478bd9Sstevel@tonic-gate flush %o3 5011e2e7a75Shuah be,pt %icc, 5f 5027c478bd9Sstevel@tonic-gate nop 5037c478bd9Sstevel@tonic-gate stxa %o2, [%o4]ASI_DMMU /* restore old ctxnum */ 5047c478bd9Sstevel@tonic-gate flush %o3 5057c478bd9Sstevel@tonic-gate5: 5067c478bd9Sstevel@tonic-gate retl 5077c478bd9Sstevel@tonic-gate wrpr %g0, %o5, %pstate /* enable interrupts */ 5087c478bd9Sstevel@tonic-gate SET_SIZE(vtag_flushpage) 5097c478bd9Sstevel@tonic-gate 5107c478bd9Sstevel@tonic-gate .seg ".text" 5117c478bd9Sstevel@tonic-gate.flushallmsg: 5127c478bd9Sstevel@tonic-gate .asciz "sfmmu_asm: unimplemented flush operation" 5137c478bd9Sstevel@tonic-gate 5147c478bd9Sstevel@tonic-gate ENTRY_NP(vtag_flushall) 5157c478bd9Sstevel@tonic-gate sethi %hi(.flushallmsg), %o0 5167c478bd9Sstevel@tonic-gate call panic 5177c478bd9Sstevel@tonic-gate or %o0, %lo(.flushallmsg), %o0 5187c478bd9Sstevel@tonic-gate SET_SIZE(vtag_flushall) 5197c478bd9Sstevel@tonic-gate 5201e2e7a75Shuah ENTRY_NP(vtag_flushall_uctxs) 5211e2e7a75Shuah /* 5221e2e7a75Shuah * flush entire DTLB/ITLB. 5231e2e7a75Shuah */ 5241e2e7a75Shuah CPU_INDEX(%g1, %g2) 5251e2e7a75Shuah mulx %g1, CPU_NODE_SIZE, %g1 5261e2e7a75Shuah set cpunodes, %g2 5271e2e7a75Shuah add %g1, %g2, %g1 5281e2e7a75Shuah lduh [%g1 + ITLB_SIZE], %g2 ! %g2 = # entries in ITLB 5291e2e7a75Shuah lduh [%g1 + DTLB_SIZE], %g1 ! %g1 = # entries in DTLB 5301e2e7a75Shuah sub %g2, 1, %g2 ! %g2 = # entries in ITLB - 1 5311e2e7a75Shuah sub %g1, 1, %g1 ! %g1 = # entries in DTLB - 1 5321e2e7a75Shuah 5331e2e7a75Shuah ! 5341e2e7a75Shuah ! Flush itlb's 5351e2e7a75Shuah ! 5361e2e7a75Shuah ITLB_FLUSH_UNLOCKED_UCTXS(I, %g2, %g3, %g4, %o2, %o3, %o4, %o5) 5371e2e7a75Shuah 5381e2e7a75Shuah ! 5391e2e7a75Shuah ! Flush dtlb's 5401e2e7a75Shuah ! 5411e2e7a75Shuah DTLB_FLUSH_UNLOCKED_UCTXS(D, %g1, %g3, %g4, %o2, %o3, %o4, %o5) 5421e2e7a75Shuah 5431e2e7a75Shuah membar #Sync 5441e2e7a75Shuah retl 5451e2e7a75Shuah nop 5461e2e7a75Shuah 5471e2e7a75Shuah SET_SIZE(vtag_flushall_uctxs) 5481e2e7a75Shuah 5497c478bd9Sstevel@tonic-gate ENTRY_NP(vtag_flushpage_tl1) 5507c478bd9Sstevel@tonic-gate /* 5517c478bd9Sstevel@tonic-gate * x-trap to flush page from tlb and tsb 5527c478bd9Sstevel@tonic-gate * 5537c478bd9Sstevel@tonic-gate * %g1 = vaddr, zero-extended on 32-bit kernel 5541e2e7a75Shuah * %g2 = sfmmup 5557c478bd9Sstevel@tonic-gate * 5567c478bd9Sstevel@tonic-gate * assumes TSBE_TAG = 0 5577c478bd9Sstevel@tonic-gate */ 5587c478bd9Sstevel@tonic-gate srln %g1, MMU_PAGESHIFT, %g1 5597c478bd9Sstevel@tonic-gate slln %g1, MMU_PAGESHIFT, %g1 /* g1 = vaddr */ 5601e2e7a75Shuah 5611e2e7a75Shuah SFMMU_CPU_CNUM(%g2, %g3, %g4) /* %g3 = sfmmu cnum on this CPU */ 5621e2e7a75Shuah 5637c478bd9Sstevel@tonic-gate /* We need to set the secondary context properly. */ 5647c478bd9Sstevel@tonic-gate set MMU_SCONTEXT, %g4 5657c478bd9Sstevel@tonic-gate ldxa [%g4]ASI_DMMU, %g5 /* rd old ctxnum */ 5667c478bd9Sstevel@tonic-gate or DEMAP_SECOND | DEMAP_PAGE_TYPE, %g1, %g1 5671e2e7a75Shuah stxa %g3, [%g4]ASI_DMMU /* wr new ctxum */ 5687c478bd9Sstevel@tonic-gate stxa %g0, [%g1]ASI_DTLB_DEMAP 5697c478bd9Sstevel@tonic-gate stxa %g0, [%g1]ASI_ITLB_DEMAP 5707c478bd9Sstevel@tonic-gate stxa %g5, [%g4]ASI_DMMU /* restore old ctxnum */ 5717c478bd9Sstevel@tonic-gate membar #Sync 5727c478bd9Sstevel@tonic-gate retry 5737c478bd9Sstevel@tonic-gate SET_SIZE(vtag_flushpage_tl1) 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate ENTRY_NP(vtag_flush_pgcnt_tl1) 5767c478bd9Sstevel@tonic-gate /* 5777c478bd9Sstevel@tonic-gate * x-trap to flush pgcnt MMU_PAGESIZE pages from tlb 5787c478bd9Sstevel@tonic-gate * 5797c478bd9Sstevel@tonic-gate * %g1 = vaddr, zero-extended on 32-bit kernel 5801e2e7a75Shuah * %g2 = <sfmmup58 | pgcnt6> 5817c478bd9Sstevel@tonic-gate * 5827c478bd9Sstevel@tonic-gate * NOTE: this handler relies on the fact that no 5837c478bd9Sstevel@tonic-gate * interrupts or traps can occur during the loop 5847c478bd9Sstevel@tonic-gate * issuing the TLB_DEMAP operations. It is assumed 5857c478bd9Sstevel@tonic-gate * that interrupts are disabled and this code is 5867c478bd9Sstevel@tonic-gate * fetching from the kernel locked text address. 5877c478bd9Sstevel@tonic-gate * 5887c478bd9Sstevel@tonic-gate * assumes TSBE_TAG = 0 5897c478bd9Sstevel@tonic-gate */ 5907c478bd9Sstevel@tonic-gate srln %g1, MMU_PAGESHIFT, %g1 5917c478bd9Sstevel@tonic-gate slln %g1, MMU_PAGESHIFT, %g1 /* g1 = vaddr */ 5927c478bd9Sstevel@tonic-gate or DEMAP_SECOND | DEMAP_PAGE_TYPE, %g1, %g1 5931e2e7a75Shuah 5941e2e7a75Shuah set SFMMU_PGCNT_MASK, %g4 5951e2e7a75Shuah and %g4, %g2, %g3 /* g3 = pgcnt - 1 */ 5961e2e7a75Shuah add %g3, 1, %g3 /* g3 = pgcnt */ 5971e2e7a75Shuah 5981e2e7a75Shuah andn %g2, SFMMU_PGCNT_MASK, %g2 /* g2 = sfmmup */ 5991e2e7a75Shuah 6001e2e7a75Shuah SFMMU_CPU_CNUM(%g2, %g5, %g6) ! %g5 = sfmmu cnum on this CPU 6011e2e7a75Shuah 6027c478bd9Sstevel@tonic-gate /* We need to set the secondary context properly. */ 6037c478bd9Sstevel@tonic-gate set MMU_SCONTEXT, %g4 6041e2e7a75Shuah ldxa [%g4]ASI_DMMU, %g6 /* read old ctxnum */ 6051e2e7a75Shuah stxa %g5, [%g4]ASI_DMMU /* write new ctxum */ 6067c478bd9Sstevel@tonic-gate 6077c478bd9Sstevel@tonic-gate set MMU_PAGESIZE, %g2 /* g2 = pgsize */ 6081e2e7a75Shuah sethi %hi(FLUSH_ADDR), %g5 6097c478bd9Sstevel@tonic-gate1: 6107c478bd9Sstevel@tonic-gate stxa %g0, [%g1]ASI_DTLB_DEMAP 6117c478bd9Sstevel@tonic-gate stxa %g0, [%g1]ASI_ITLB_DEMAP 6121e2e7a75Shuah flush %g5 6137c478bd9Sstevel@tonic-gate deccc %g3 /* decr pgcnt */ 6147c478bd9Sstevel@tonic-gate bnz,pt %icc,1b 6157c478bd9Sstevel@tonic-gate add %g1, %g2, %g1 /* go to nextpage */ 6167c478bd9Sstevel@tonic-gate 6171e2e7a75Shuah stxa %g6, [%g4]ASI_DMMU /* restore old ctxnum */ 6187c478bd9Sstevel@tonic-gate membar #Sync 6197c478bd9Sstevel@tonic-gate retry 6207c478bd9Sstevel@tonic-gate SET_SIZE(vtag_flush_pgcnt_tl1) 6217c478bd9Sstevel@tonic-gate 6227c478bd9Sstevel@tonic-gate ! Not implemented on US1/US2 6237c478bd9Sstevel@tonic-gate ENTRY_NP(vtag_flushall_tl1) 6247c478bd9Sstevel@tonic-gate retry 6257c478bd9Sstevel@tonic-gate SET_SIZE(vtag_flushall_tl1) 6267c478bd9Sstevel@tonic-gate 6277c478bd9Sstevel@tonic-gate/* 6287c478bd9Sstevel@tonic-gate * vac_flushpage(pfnum, color) 6297c478bd9Sstevel@tonic-gate * Flush 1 8k page of the D-$ with physical page = pfnum 6307c478bd9Sstevel@tonic-gate * Algorithm: 6317c478bd9Sstevel@tonic-gate * The spitfire dcache is a 16k direct mapped virtual indexed, 6327c478bd9Sstevel@tonic-gate * physically tagged cache. Given the pfnum we read all cache 6337c478bd9Sstevel@tonic-gate * lines for the corresponding page in the cache (determined by 6347c478bd9Sstevel@tonic-gate * the color). Each cache line is compared with 6357c478bd9Sstevel@tonic-gate * the tag created from the pfnum. If the tags match we flush 6367c478bd9Sstevel@tonic-gate * the line. 6377c478bd9Sstevel@tonic-gate */ 6387c478bd9Sstevel@tonic-gate .seg ".data" 6397c478bd9Sstevel@tonic-gate .align 8 6407c478bd9Sstevel@tonic-gate .global dflush_type 6417c478bd9Sstevel@tonic-gatedflush_type: 6427c478bd9Sstevel@tonic-gate .word FLUSHPAGE_TYPE 6437c478bd9Sstevel@tonic-gate .seg ".text" 6447c478bd9Sstevel@tonic-gate 6457c478bd9Sstevel@tonic-gate ENTRY(vac_flushpage) 6467c478bd9Sstevel@tonic-gate /* 6477c478bd9Sstevel@tonic-gate * flush page from the d$ 6487c478bd9Sstevel@tonic-gate * 6497c478bd9Sstevel@tonic-gate * %o0 = pfnum, %o1 = color 6507c478bd9Sstevel@tonic-gate */ 6517c478bd9Sstevel@tonic-gate DCACHE_FLUSHPAGE(%o0, %o1, %o2, %o3, %o4) 6527c478bd9Sstevel@tonic-gate retl 6537c478bd9Sstevel@tonic-gate nop 6547c478bd9Sstevel@tonic-gate SET_SIZE(vac_flushpage) 6557c478bd9Sstevel@tonic-gate 6567c478bd9Sstevel@tonic-gate ENTRY_NP(vac_flushpage_tl1) 6577c478bd9Sstevel@tonic-gate /* 6587c478bd9Sstevel@tonic-gate * x-trap to flush page from the d$ 6597c478bd9Sstevel@tonic-gate * 6607c478bd9Sstevel@tonic-gate * %g1 = pfnum, %g2 = color 6617c478bd9Sstevel@tonic-gate */ 6627c478bd9Sstevel@tonic-gate DCACHE_FLUSHPAGE(%g1, %g2, %g3, %g4, %g5) 6637c478bd9Sstevel@tonic-gate retry 6647c478bd9Sstevel@tonic-gate SET_SIZE(vac_flushpage_tl1) 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate ENTRY(vac_flushcolor) 6677c478bd9Sstevel@tonic-gate /* 6687c478bd9Sstevel@tonic-gate * %o0 = vcolor 6697c478bd9Sstevel@tonic-gate */ 6707c478bd9Sstevel@tonic-gate DCACHE_FLUSHCOLOR(%o0, %o1, %o2) 6717c478bd9Sstevel@tonic-gate retl 6727c478bd9Sstevel@tonic-gate nop 6737c478bd9Sstevel@tonic-gate SET_SIZE(vac_flushcolor) 6747c478bd9Sstevel@tonic-gate 6757c478bd9Sstevel@tonic-gate ENTRY(vac_flushcolor_tl1) 6767c478bd9Sstevel@tonic-gate /* 6777c478bd9Sstevel@tonic-gate * %g1 = vcolor 6787c478bd9Sstevel@tonic-gate */ 6797c478bd9Sstevel@tonic-gate DCACHE_FLUSHCOLOR(%g1, %g2, %g3) 6807c478bd9Sstevel@tonic-gate retry 6817c478bd9Sstevel@tonic-gate SET_SIZE(vac_flushcolor_tl1) 6827c478bd9Sstevel@tonic-gate 6837c478bd9Sstevel@tonic-gate 6847c478bd9Sstevel@tonic-gate .global _dispatch_status_busy 6857c478bd9Sstevel@tonic-gate_dispatch_status_busy: 6867c478bd9Sstevel@tonic-gate .asciz "ASI_INTR_DISPATCH_STATUS error: busy" 6877c478bd9Sstevel@tonic-gate .align 4 6887c478bd9Sstevel@tonic-gate 6897c478bd9Sstevel@tonic-gate/* 6907c478bd9Sstevel@tonic-gate * Determine whether or not the IDSR is busy. 6917c478bd9Sstevel@tonic-gate * Entry: no arguments 6927c478bd9Sstevel@tonic-gate * Returns: 1 if busy, 0 otherwise 6937c478bd9Sstevel@tonic-gate */ 6947c478bd9Sstevel@tonic-gate ENTRY(idsr_busy) 6957c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_INTR_DISPATCH_STATUS, %g1 6967c478bd9Sstevel@tonic-gate clr %o0 6977c478bd9Sstevel@tonic-gate btst IDSR_BUSY, %g1 6987c478bd9Sstevel@tonic-gate bz,a,pt %xcc, 1f 6997c478bd9Sstevel@tonic-gate mov 1, %o0 7007c478bd9Sstevel@tonic-gate1: 7017c478bd9Sstevel@tonic-gate retl 7027c478bd9Sstevel@tonic-gate nop 7037c478bd9Sstevel@tonic-gate SET_SIZE(idsr_busy) 7047c478bd9Sstevel@tonic-gate 7057c478bd9Sstevel@tonic-gate/* 7067c478bd9Sstevel@tonic-gate * Setup interrupt dispatch data registers 7077c478bd9Sstevel@tonic-gate * Entry: 7087c478bd9Sstevel@tonic-gate * %o0 - function or inumber to call 7097c478bd9Sstevel@tonic-gate * %o1, %o2 - arguments (2 uint64_t's) 7107c478bd9Sstevel@tonic-gate */ 7117c478bd9Sstevel@tonic-gate .seg "text" 7127c478bd9Sstevel@tonic-gate 7137c478bd9Sstevel@tonic-gate ENTRY(init_mondo) 7147c478bd9Sstevel@tonic-gate#ifdef DEBUG 7157c478bd9Sstevel@tonic-gate ! 7167c478bd9Sstevel@tonic-gate ! IDSR should not be busy at the moment 7177c478bd9Sstevel@tonic-gate ! 7187c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_INTR_DISPATCH_STATUS, %g1 7197c478bd9Sstevel@tonic-gate btst IDSR_BUSY, %g1 7207c478bd9Sstevel@tonic-gate bz,pt %xcc, 1f 7217c478bd9Sstevel@tonic-gate nop 7227c478bd9Sstevel@tonic-gate 7237c478bd9Sstevel@tonic-gate sethi %hi(_dispatch_status_busy), %o0 7247c478bd9Sstevel@tonic-gate call panic 7257c478bd9Sstevel@tonic-gate or %o0, %lo(_dispatch_status_busy), %o0 7267c478bd9Sstevel@tonic-gate#endif /* DEBUG */ 7277c478bd9Sstevel@tonic-gate 7287c478bd9Sstevel@tonic-gate ALTENTRY(init_mondo_nocheck) 7297c478bd9Sstevel@tonic-gate ! 7307c478bd9Sstevel@tonic-gate ! interrupt vector dispach data reg 0 7317c478bd9Sstevel@tonic-gate ! 7327c478bd9Sstevel@tonic-gate1: 7337c478bd9Sstevel@tonic-gate mov IDDR_0, %g1 7347c478bd9Sstevel@tonic-gate mov IDDR_1, %g2 7357c478bd9Sstevel@tonic-gate mov IDDR_2, %g3 7367c478bd9Sstevel@tonic-gate stxa %o0, [%g1]ASI_INTR_DISPATCH 7377c478bd9Sstevel@tonic-gate 7387c478bd9Sstevel@tonic-gate ! 7397c478bd9Sstevel@tonic-gate ! interrupt vector dispach data reg 1 7407c478bd9Sstevel@tonic-gate ! 7417c478bd9Sstevel@tonic-gate stxa %o1, [%g2]ASI_INTR_DISPATCH 7427c478bd9Sstevel@tonic-gate 7437c478bd9Sstevel@tonic-gate ! 7447c478bd9Sstevel@tonic-gate ! interrupt vector dispach data reg 2 7457c478bd9Sstevel@tonic-gate ! 7467c478bd9Sstevel@tonic-gate stxa %o2, [%g3]ASI_INTR_DISPATCH 7477c478bd9Sstevel@tonic-gate 7487c478bd9Sstevel@tonic-gate retl 7497c478bd9Sstevel@tonic-gate membar #Sync ! allowed to be in the delay slot 7507c478bd9Sstevel@tonic-gate SET_SIZE(init_mondo) 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate/* 7537c478bd9Sstevel@tonic-gate * Ship mondo to upaid 7547c478bd9Sstevel@tonic-gate */ 7557c478bd9Sstevel@tonic-gate ENTRY_NP(shipit) 7567c478bd9Sstevel@tonic-gate sll %o0, IDCR_PID_SHIFT, %g1 ! IDCR<18:14> = upa id 7577c478bd9Sstevel@tonic-gate or %g1, IDCR_OFFSET, %g1 ! IDCR<13:0> = 0x70 7587c478bd9Sstevel@tonic-gate stxa %g0, [%g1]ASI_INTR_DISPATCH ! interrupt vector dispatch 7597c478bd9Sstevel@tonic-gate#if defined(SF_ERRATA_54) 7607c478bd9Sstevel@tonic-gate membar #Sync ! store must occur before load 7617c478bd9Sstevel@tonic-gate mov 0x20, %g3 ! UDBH Control Register Read 7627c478bd9Sstevel@tonic-gate ldxa [%g3]ASI_SDB_INTR_R, %g0 7637c478bd9Sstevel@tonic-gate#endif 7647c478bd9Sstevel@tonic-gate retl 7657c478bd9Sstevel@tonic-gate membar #Sync 7667c478bd9Sstevel@tonic-gate SET_SIZE(shipit) 7677c478bd9Sstevel@tonic-gate 7687c478bd9Sstevel@tonic-gate 7697c478bd9Sstevel@tonic-gate/* 7707c478bd9Sstevel@tonic-gate * flush_instr_mem: 7717c478bd9Sstevel@tonic-gate * Flush a portion of the I-$ starting at vaddr 7727c478bd9Sstevel@tonic-gate * %o0 vaddr 7737c478bd9Sstevel@tonic-gate * %o1 bytes to be flushed 7747c478bd9Sstevel@tonic-gate */ 7757c478bd9Sstevel@tonic-gate 7767c478bd9Sstevel@tonic-gate ENTRY(flush_instr_mem) 7777c478bd9Sstevel@tonic-gate membar #StoreStore ! Ensure the stores 7787c478bd9Sstevel@tonic-gate ! are globally visible 7797c478bd9Sstevel@tonic-gate1: 7807c478bd9Sstevel@tonic-gate flush %o0 7817c478bd9Sstevel@tonic-gate subcc %o1, ICACHE_FLUSHSZ, %o1 ! bytes = bytes-0x20 7827c478bd9Sstevel@tonic-gate bgu,pt %ncc, 1b 7837c478bd9Sstevel@tonic-gate add %o0, ICACHE_FLUSHSZ, %o0 ! vaddr = vaddr+0x20 7847c478bd9Sstevel@tonic-gate 7857c478bd9Sstevel@tonic-gate retl 7867c478bd9Sstevel@tonic-gate nop 7877c478bd9Sstevel@tonic-gate SET_SIZE(flush_instr_mem) 7887c478bd9Sstevel@tonic-gate 7897c478bd9Sstevel@tonic-gate/* 7907c478bd9Sstevel@tonic-gate * flush_ecache: 7917c478bd9Sstevel@tonic-gate * Flush the entire e$ using displacement flush by reading through a 7927c478bd9Sstevel@tonic-gate * physically contiguous area. We use mmu bypass asi (ASI_MEM) while 7937c478bd9Sstevel@tonic-gate * reading this physical address range so that data doesn't go to d$. 7947c478bd9Sstevel@tonic-gate * incoming arguments: 7957c478bd9Sstevel@tonic-gate * %o0 - 64 bit physical address 7967c478bd9Sstevel@tonic-gate * %o1 - size of address range to read 7977c478bd9Sstevel@tonic-gate * %o2 - ecache linesize 7987c478bd9Sstevel@tonic-gate */ 7997c478bd9Sstevel@tonic-gate ENTRY(flush_ecache) 8007c478bd9Sstevel@tonic-gate#ifndef HUMMINGBIRD 8017c478bd9Sstevel@tonic-gate b 2f 8027c478bd9Sstevel@tonic-gate nop 8037c478bd9Sstevel@tonic-gate1: 8047c478bd9Sstevel@tonic-gate ldxa [%o0 + %o1]ASI_MEM, %g0 ! start reading from physaddr + size 8057c478bd9Sstevel@tonic-gate2: 8067c478bd9Sstevel@tonic-gate subcc %o1, %o2, %o1 8077c478bd9Sstevel@tonic-gate bcc,a,pt %ncc, 1b 8087c478bd9Sstevel@tonic-gate nop 8097c478bd9Sstevel@tonic-gate 8107c478bd9Sstevel@tonic-gate#else /* HUMMINGBIRD */ 8117c478bd9Sstevel@tonic-gate /* 8127c478bd9Sstevel@tonic-gate * UltraSPARC-IIe processor supports both 4-way set associative 8137c478bd9Sstevel@tonic-gate * and direct map E$. For performance reasons, we flush E$ by 8147c478bd9Sstevel@tonic-gate * placing it in direct map mode for data load/store and restore 8157c478bd9Sstevel@tonic-gate * the state after we are done flushing it. It takes 2 iterations 8167c478bd9Sstevel@tonic-gate * to guarantee that the entire ecache has been flushed. 8177c478bd9Sstevel@tonic-gate * 8187c478bd9Sstevel@tonic-gate * Keep the interrupts disabled while flushing E$ in this manner. 8197c478bd9Sstevel@tonic-gate */ 8207c478bd9Sstevel@tonic-gate rdpr %pstate, %g4 ! current pstate (restored later) 8217c478bd9Sstevel@tonic-gate andn %g4, PSTATE_IE, %g5 8227c478bd9Sstevel@tonic-gate wrpr %g0, %g5, %pstate ! disable interrupts 8237c478bd9Sstevel@tonic-gate 8247c478bd9Sstevel@tonic-gate ! Place E$ in direct map mode for data access 8257c478bd9Sstevel@tonic-gate or %g0, 1, %g5 8267c478bd9Sstevel@tonic-gate sllx %g5, HB_UPA_DMAP_DATA_BIT, %g5 8277c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_UPA_CONFIG, %g1 ! current UPA config (restored later) 8287c478bd9Sstevel@tonic-gate or %g1, %g5, %g5 8297c478bd9Sstevel@tonic-gate membar #Sync 8307c478bd9Sstevel@tonic-gate stxa %g5, [%g0]ASI_UPA_CONFIG ! enable direct map for data access 8317c478bd9Sstevel@tonic-gate membar #Sync 8327c478bd9Sstevel@tonic-gate 8337c478bd9Sstevel@tonic-gate ! flush entire ecache HB_ECACHE_FLUSH_CNT times 8347c478bd9Sstevel@tonic-gate mov HB_ECACHE_FLUSH_CNT-1, %g5 8357c478bd9Sstevel@tonic-gate2: 8367c478bd9Sstevel@tonic-gate sub %o1, %o2, %g3 ! start from last entry 8377c478bd9Sstevel@tonic-gate1: 8387c478bd9Sstevel@tonic-gate ldxa [%o0 + %g3]ASI_MEM, %g0 ! start reading from physaddr + size 8397c478bd9Sstevel@tonic-gate subcc %g3, %o2, %g3 8407c478bd9Sstevel@tonic-gate bgeu,a,pt %ncc, 1b 8417c478bd9Sstevel@tonic-gate nop 8427c478bd9Sstevel@tonic-gate brgz,a,pt %g5, 2b 8437c478bd9Sstevel@tonic-gate dec %g5 8447c478bd9Sstevel@tonic-gate 8457c478bd9Sstevel@tonic-gate membar #Sync 8467c478bd9Sstevel@tonic-gate stxa %g1, [%g0]ASI_UPA_CONFIG ! restore UPA config reg 8477c478bd9Sstevel@tonic-gate membar #Sync 8487c478bd9Sstevel@tonic-gate wrpr %g0, %g4, %pstate ! restore earlier pstate 8497c478bd9Sstevel@tonic-gate#endif /* HUMMINGBIRD */ 8507c478bd9Sstevel@tonic-gate 8517c478bd9Sstevel@tonic-gate retl 8527c478bd9Sstevel@tonic-gate nop 8537c478bd9Sstevel@tonic-gate SET_SIZE(flush_ecache) 8547c478bd9Sstevel@tonic-gate 8557c478bd9Sstevel@tonic-gate/* 8567c478bd9Sstevel@tonic-gate * void kdi_flush_idcache(int dcache_size, int dcache_linesize, 8577c478bd9Sstevel@tonic-gate * int icache_size, int icache_linesize) 8587c478bd9Sstevel@tonic-gate */ 8597c478bd9Sstevel@tonic-gate ENTRY(kdi_flush_idcache) 8607c478bd9Sstevel@tonic-gate DCACHE_FLUSHALL(%o0, %o1, %g1) 8617c478bd9Sstevel@tonic-gate ICACHE_FLUSHALL(%o2, %o3, %g1) 8627c478bd9Sstevel@tonic-gate membar #Sync 8637c478bd9Sstevel@tonic-gate retl 8647c478bd9Sstevel@tonic-gate nop 8657c478bd9Sstevel@tonic-gate SET_SIZE(kdi_flush_idcache) 8667c478bd9Sstevel@tonic-gate 8677c478bd9Sstevel@tonic-gate 8687c478bd9Sstevel@tonic-gate/* 8697c478bd9Sstevel@tonic-gate * void get_ecache_dtag(uint32_t ecache_idx, uint64_t *data, uint64_t *tag, 8707c478bd9Sstevel@tonic-gate * uint64_t *oafsr, uint64_t *acc_afsr) 8717c478bd9Sstevel@tonic-gate * 8727c478bd9Sstevel@tonic-gate * Get ecache data and tag. The ecache_idx argument is assumed to be aligned 8737c478bd9Sstevel@tonic-gate * on a 64-byte boundary. The corresponding AFSR value is also read for each 8747c478bd9Sstevel@tonic-gate * 8 byte ecache data obtained. The ecache data is assumed to be a pointer 8757c478bd9Sstevel@tonic-gate * to an array of 16 uint64_t's (e$data & afsr value). The action to read the 8767c478bd9Sstevel@tonic-gate * data and tag should be atomic to make sense. We will be executing at PIL15 8777c478bd9Sstevel@tonic-gate * and will disable IE, so nothing can occur between the two reads. We also 8787c478bd9Sstevel@tonic-gate * assume that the execution of this code does not interfere with what we are 8797c478bd9Sstevel@tonic-gate * reading - not really possible, but we'll live with it for now. 8807c478bd9Sstevel@tonic-gate * We also pass the old AFSR value before clearing it, and caller will take 8817c478bd9Sstevel@tonic-gate * appropriate actions if the important bits are non-zero. 8827c478bd9Sstevel@tonic-gate * 8837c478bd9Sstevel@tonic-gate * If the caller wishes to track the AFSR in cases where the CP bit is 8847c478bd9Sstevel@tonic-gate * set, an address should be passed in for acc_afsr. Otherwise, this 8857c478bd9Sstevel@tonic-gate * argument may be null. 8867c478bd9Sstevel@tonic-gate * 8877c478bd9Sstevel@tonic-gate * Register Usage: 8887c478bd9Sstevel@tonic-gate * i0: In: 32-bit e$ index 8897c478bd9Sstevel@tonic-gate * i1: In: addr of e$ data 8907c478bd9Sstevel@tonic-gate * i2: In: addr of e$ tag 8917c478bd9Sstevel@tonic-gate * i3: In: addr of old afsr 8927c478bd9Sstevel@tonic-gate * i4: In: addr of accumulated afsr - may be null 8937c478bd9Sstevel@tonic-gate */ 8947c478bd9Sstevel@tonic-gate ENTRY(get_ecache_dtag) 8957c478bd9Sstevel@tonic-gate save %sp, -SA(MINFRAME), %sp 8967c478bd9Sstevel@tonic-gate or %g0, 1, %l4 8977c478bd9Sstevel@tonic-gate sllx %l4, 39, %l4 ! set bit 39 for e$ data access 8987c478bd9Sstevel@tonic-gate or %i0, %l4, %g6 ! %g6 = e$ addr for data read 8997c478bd9Sstevel@tonic-gate sllx %l4, 1, %l4 ! set bit 40 for e$ tag access 9007c478bd9Sstevel@tonic-gate or %i0, %l4, %l4 ! %l4 = e$ addr for tag read 9017c478bd9Sstevel@tonic-gate 9027c478bd9Sstevel@tonic-gate rdpr %pstate, %i5 9037c478bd9Sstevel@tonic-gate andn %i5, PSTATE_IE | PSTATE_AM, %i0 9047c478bd9Sstevel@tonic-gate wrpr %i0, %g0, %pstate ! clear IE, AM bits 9057c478bd9Sstevel@tonic-gate 9067c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_ESTATE_ERR, %g1 9077c478bd9Sstevel@tonic-gate stxa %g0, [%g0]ASI_ESTATE_ERR ! disable errors 9087c478bd9Sstevel@tonic-gate membar #Sync 9097c478bd9Sstevel@tonic-gate 9107c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_AFSR, %i0 ! grab the old-afsr before tag read 9117c478bd9Sstevel@tonic-gate stx %i0, [%i3] ! write back the old-afsr 9127c478bd9Sstevel@tonic-gate 9137c478bd9Sstevel@tonic-gate ldxa [%l4]ASI_EC_R, %g0 ! read tag into E$ tag reg 9147c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_EC_DIAG, %i0 ! read tag from E$ tag reg 9157c478bd9Sstevel@tonic-gate stx %i0, [%i2] ! write back tag result 9167c478bd9Sstevel@tonic-gate 9177c478bd9Sstevel@tonic-gate clr %i2 ! loop count 9187c478bd9Sstevel@tonic-gate 9197c478bd9Sstevel@tonic-gate brz %i4, 1f ! acc_afsr == NULL? 9207c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_AFSR, %i0 ! grab the old-afsr before clearing 9217c478bd9Sstevel@tonic-gate srlx %i0, P_AFSR_CP_SHIFT, %l0 9227c478bd9Sstevel@tonic-gate btst 1, %l0 9237c478bd9Sstevel@tonic-gate bz 1f 9247c478bd9Sstevel@tonic-gate nop 9257c478bd9Sstevel@tonic-gate ldx [%i4], %g4 9267c478bd9Sstevel@tonic-gate or %g4, %i0, %g4 ! aggregate AFSR in cpu private 9277c478bd9Sstevel@tonic-gate stx %g4, [%i4] 9287c478bd9Sstevel@tonic-gate1: 9297c478bd9Sstevel@tonic-gate stxa %i0, [%g0]ASI_AFSR ! clear AFSR 9307c478bd9Sstevel@tonic-gate membar #Sync 9317c478bd9Sstevel@tonic-gate ldxa [%g6]ASI_EC_R, %i0 ! read the 8byte E$data 9327c478bd9Sstevel@tonic-gate stx %i0, [%i1] ! save the E$data 9337c478bd9Sstevel@tonic-gate add %g6, 8, %g6 9347c478bd9Sstevel@tonic-gate add %i1, 8, %i1 9357c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_AFSR, %i0 ! read AFSR for this 16byte read 9367c478bd9Sstevel@tonic-gate srlx %i0, P_AFSR_CP_SHIFT, %l0 9377c478bd9Sstevel@tonic-gate btst 1, %l0 9387c478bd9Sstevel@tonic-gate bz 2f 9397c478bd9Sstevel@tonic-gate stx %i0, [%i1] ! save the AFSR 9407c478bd9Sstevel@tonic-gate 9417c478bd9Sstevel@tonic-gate brz %i4, 2f ! acc_afsr == NULL? 9427c478bd9Sstevel@tonic-gate nop 9437c478bd9Sstevel@tonic-gate ldx [%i4], %g4 9447c478bd9Sstevel@tonic-gate or %g4, %i0, %g4 ! aggregate AFSR in cpu private 9457c478bd9Sstevel@tonic-gate stx %g4, [%i4] 9467c478bd9Sstevel@tonic-gate2: 9477c478bd9Sstevel@tonic-gate add %i2, 8, %i2 9487c478bd9Sstevel@tonic-gate cmp %i2, 64 9497c478bd9Sstevel@tonic-gate bl,a 1b 9507c478bd9Sstevel@tonic-gate add %i1, 8, %i1 9517c478bd9Sstevel@tonic-gate stxa %i0, [%g0]ASI_AFSR ! clear AFSR 9527c478bd9Sstevel@tonic-gate membar #Sync 9537c478bd9Sstevel@tonic-gate stxa %g1, [%g0]ASI_ESTATE_ERR ! restore error enable 9547c478bd9Sstevel@tonic-gate membar #Sync 9557c478bd9Sstevel@tonic-gate wrpr %g0, %i5, %pstate 9567c478bd9Sstevel@tonic-gate ret 9577c478bd9Sstevel@tonic-gate restore 9587c478bd9Sstevel@tonic-gate SET_SIZE(get_ecache_dtag) 9597c478bd9Sstevel@tonic-gate#endif /* lint */ 9607c478bd9Sstevel@tonic-gate 9617c478bd9Sstevel@tonic-gate#if defined(lint) 9627c478bd9Sstevel@tonic-gate/* 9637c478bd9Sstevel@tonic-gate * The ce_err function handles trap type 0x63 (corrected_ECC_error) at tl=0. 9647c478bd9Sstevel@tonic-gate * Steps: 1. GET AFSR 2. Get AFAR <40:4> 3. Get datapath error status 9657c478bd9Sstevel@tonic-gate * 4. Clear datapath error bit(s) 5. Clear AFSR error bit 9667c478bd9Sstevel@tonic-gate * 6. package data in %g2 and %g3 7. call cpu_ce_error vis sys_trap 9677c478bd9Sstevel@tonic-gate * %g2: [ 52:43 UDB lower | 42:33 UDB upper | 32:0 afsr ] - arg #3/arg #1 9687c478bd9Sstevel@tonic-gate * %g3: [ 40:4 afar ] - sys_trap->have_win: arg #4/arg #2 9697c478bd9Sstevel@tonic-gate */ 9707c478bd9Sstevel@tonic-gatevoid 9717c478bd9Sstevel@tonic-gatece_err(void) 9727c478bd9Sstevel@tonic-gate{} 9737c478bd9Sstevel@tonic-gate 9747c478bd9Sstevel@tonic-gatevoid 9757c478bd9Sstevel@tonic-gatece_err_tl1(void) 9767c478bd9Sstevel@tonic-gate{} 9777c478bd9Sstevel@tonic-gate 9787c478bd9Sstevel@tonic-gate 9797c478bd9Sstevel@tonic-gate/* 9807c478bd9Sstevel@tonic-gate * The async_err function handles trap types 0x0A (instruction_access_error) 9817c478bd9Sstevel@tonic-gate * and 0x32 (data_access_error) at TL = 0 and TL > 0. When we branch here, 9827c478bd9Sstevel@tonic-gate * %g5 will have the trap type (with 0x200 set if we're at TL > 0). 9837c478bd9Sstevel@tonic-gate * 9847c478bd9Sstevel@tonic-gate * Steps: 1. Get AFSR 2. Get AFAR <40:4> 3. If not UE error skip UDP registers. 9857c478bd9Sstevel@tonic-gate * 4. Else get and clear datapath error bit(s) 4. Clear AFSR error bits 9867c478bd9Sstevel@tonic-gate * 6. package data in %g2 and %g3 7. disable all cpu errors, because 9877c478bd9Sstevel@tonic-gate * trap is likely to be fatal 8. call cpu_async_error vis sys_trap 9887c478bd9Sstevel@tonic-gate * 9897c478bd9Sstevel@tonic-gate * %g3: [ 63:53 tt | 52:43 UDB_L | 42:33 UDB_U | 32:0 afsr ] - arg #3/arg #1 9907c478bd9Sstevel@tonic-gate * %g2: [ 40:4 afar ] - sys_trap->have_win: arg #4/arg #2 9917c478bd9Sstevel@tonic-gate */ 9927c478bd9Sstevel@tonic-gatevoid 9937c478bd9Sstevel@tonic-gateasync_err(void) 9947c478bd9Sstevel@tonic-gate{} 9957c478bd9Sstevel@tonic-gate 9967c478bd9Sstevel@tonic-gate/* 9977c478bd9Sstevel@tonic-gate * The clr_datapath function clears any error bits set in the UDB regs. 9987c478bd9Sstevel@tonic-gate */ 9997c478bd9Sstevel@tonic-gatevoid 10007c478bd9Sstevel@tonic-gateclr_datapath(void) 10017c478bd9Sstevel@tonic-gate{} 10027c478bd9Sstevel@tonic-gate 10037c478bd9Sstevel@tonic-gate/* 10047c478bd9Sstevel@tonic-gate * The get_udb_errors() function gets the current value of the 10057c478bd9Sstevel@tonic-gate * Datapath Error Registers. 10067c478bd9Sstevel@tonic-gate */ 10077c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 10087c478bd9Sstevel@tonic-gatevoid 10097c478bd9Sstevel@tonic-gateget_udb_errors(uint64_t *udbh, uint64_t *udbl) 10107c478bd9Sstevel@tonic-gate{ 10117c478bd9Sstevel@tonic-gate *udbh = 0; 10127c478bd9Sstevel@tonic-gate *udbl = 0; 10137c478bd9Sstevel@tonic-gate} 10147c478bd9Sstevel@tonic-gate 10157c478bd9Sstevel@tonic-gate#else /* lint */ 10167c478bd9Sstevel@tonic-gate 10177c478bd9Sstevel@tonic-gate ENTRY_NP(ce_err) 10187c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_AFSR, %g3 ! save afsr in g3 10197c478bd9Sstevel@tonic-gate 10207c478bd9Sstevel@tonic-gate ! 10217c478bd9Sstevel@tonic-gate ! Check for a UE... From Kevin.Normoyle: 10227c478bd9Sstevel@tonic-gate ! We try to switch to the trap for the UE, but since that's 10237c478bd9Sstevel@tonic-gate ! a hardware pipeline, we might get to the CE trap before we 10247c478bd9Sstevel@tonic-gate ! can switch. The UDB and AFSR registers will have both the 10257c478bd9Sstevel@tonic-gate ! UE and CE bits set but the UDB syndrome and the AFAR will be 10267c478bd9Sstevel@tonic-gate ! for the UE. 10277c478bd9Sstevel@tonic-gate ! 10287c478bd9Sstevel@tonic-gate or %g0, 1, %g1 ! put 1 in g1 10297c478bd9Sstevel@tonic-gate sllx %g1, 21, %g1 ! shift left to <21> afsr UE 10307c478bd9Sstevel@tonic-gate andcc %g1, %g3, %g0 ! check for UE in afsr 10317c478bd9Sstevel@tonic-gate bnz async_err ! handle the UE, not the CE 10327c478bd9Sstevel@tonic-gate or %g0, 0x63, %g5 ! pass along the CE ttype 10337c478bd9Sstevel@tonic-gate ! 10347c478bd9Sstevel@tonic-gate ! Disable further CE traps to avoid recursion (stack overflow) 10357c478bd9Sstevel@tonic-gate ! and staying above XCALL_PIL for extended periods. 10367c478bd9Sstevel@tonic-gate ! 10377c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_ESTATE_ERR, %g2 10387c478bd9Sstevel@tonic-gate andn %g2, 0x1, %g2 ! clear bit 0 - CEEN 10397c478bd9Sstevel@tonic-gate stxa %g2, [%g0]ASI_ESTATE_ERR 10407c478bd9Sstevel@tonic-gate membar #Sync ! required 10417c478bd9Sstevel@tonic-gate ! 10427c478bd9Sstevel@tonic-gate ! handle the CE 10437c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_AFAR, %g2 ! save afar in g2 10447c478bd9Sstevel@tonic-gate 10457c478bd9Sstevel@tonic-gate set P_DER_H, %g4 ! put P_DER_H in g4 10467c478bd9Sstevel@tonic-gate ldxa [%g4]ASI_SDB_INTR_R, %g5 ! read sdb upper half into g5 10477c478bd9Sstevel@tonic-gate or %g0, 1, %g6 ! put 1 in g6 10487c478bd9Sstevel@tonic-gate sllx %g6, 8, %g6 ! shift g6 to <8> sdb CE 10497c478bd9Sstevel@tonic-gate andcc %g5, %g6, %g1 ! check for CE in upper half 10507c478bd9Sstevel@tonic-gate sllx %g5, 33, %g5 ! shift upper bits to <42:33> 10517c478bd9Sstevel@tonic-gate or %g3, %g5, %g3 ! or with afsr bits 10527c478bd9Sstevel@tonic-gate bz,a 1f ! no error, goto 1f 10537c478bd9Sstevel@tonic-gate nop 10547c478bd9Sstevel@tonic-gate stxa %g1, [%g4]ASI_SDB_INTR_W ! clear sdb reg error bit 10557c478bd9Sstevel@tonic-gate membar #Sync ! membar sync required 10567c478bd9Sstevel@tonic-gate1: 10577c478bd9Sstevel@tonic-gate set P_DER_L, %g4 ! put P_DER_L in g4 10587c478bd9Sstevel@tonic-gate ldxa [%g4]ASI_SDB_INTR_R, %g5 ! read sdb lower half into g6 10597c478bd9Sstevel@tonic-gate andcc %g5, %g6, %g1 ! check for CE in lower half 10607c478bd9Sstevel@tonic-gate sllx %g5, 43, %g5 ! shift upper bits to <52:43> 10617c478bd9Sstevel@tonic-gate or %g3, %g5, %g3 ! or with afsr bits 10627c478bd9Sstevel@tonic-gate bz,a 2f ! no error, goto 2f 10637c478bd9Sstevel@tonic-gate nop 10647c478bd9Sstevel@tonic-gate stxa %g1, [%g4]ASI_SDB_INTR_W ! clear sdb reg error bit 10657c478bd9Sstevel@tonic-gate membar #Sync ! membar sync required 10667c478bd9Sstevel@tonic-gate2: 10677c478bd9Sstevel@tonic-gate or %g0, 1, %g4 ! put 1 in g4 10687c478bd9Sstevel@tonic-gate sllx %g4, 20, %g4 ! shift left to <20> afsr CE 10697c478bd9Sstevel@tonic-gate stxa %g4, [%g0]ASI_AFSR ! use g4 to clear afsr CE error 10707c478bd9Sstevel@tonic-gate membar #Sync ! membar sync required 10717c478bd9Sstevel@tonic-gate 10727c478bd9Sstevel@tonic-gate set cpu_ce_error, %g1 ! put *cpu_ce_error() in g1 10737c478bd9Sstevel@tonic-gate rdpr %pil, %g6 ! read pil into %g6 10747c478bd9Sstevel@tonic-gate subcc %g6, PIL_15, %g0 10757c478bd9Sstevel@tonic-gate movneg %icc, PIL_14, %g4 ! run at pil 14 unless already at 15 10767c478bd9Sstevel@tonic-gate sethi %hi(sys_trap), %g5 10777c478bd9Sstevel@tonic-gate jmp %g5 + %lo(sys_trap) ! goto sys_trap 10787c478bd9Sstevel@tonic-gate movge %icc, PIL_15, %g4 ! already at pil 15 10797c478bd9Sstevel@tonic-gate SET_SIZE(ce_err) 10807c478bd9Sstevel@tonic-gate 10817c478bd9Sstevel@tonic-gate ENTRY_NP(ce_err_tl1) 10827c478bd9Sstevel@tonic-gate#ifndef TRAPTRACE 10837c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_AFSR, %g7 10847c478bd9Sstevel@tonic-gate stxa %g7, [%g0]ASI_AFSR 10857c478bd9Sstevel@tonic-gate membar #Sync 10867c478bd9Sstevel@tonic-gate retry 10877c478bd9Sstevel@tonic-gate#else 10887c478bd9Sstevel@tonic-gate set ce_trap_tl1, %g1 10897c478bd9Sstevel@tonic-gate sethi %hi(dis_err_panic1), %g4 10907c478bd9Sstevel@tonic-gate jmp %g4 + %lo(dis_err_panic1) 10917c478bd9Sstevel@tonic-gate nop 10927c478bd9Sstevel@tonic-gate#endif 10937c478bd9Sstevel@tonic-gate SET_SIZE(ce_err_tl1) 10947c478bd9Sstevel@tonic-gate 10957c478bd9Sstevel@tonic-gate#ifdef TRAPTRACE 10967c478bd9Sstevel@tonic-gate.celevel1msg: 10977c478bd9Sstevel@tonic-gate .asciz "Softerror with trap tracing at tl1: AFAR 0x%08x.%08x AFSR 0x%08x.%08x"; 10987c478bd9Sstevel@tonic-gate 10997c478bd9Sstevel@tonic-gate ENTRY_NP(ce_trap_tl1) 11007c478bd9Sstevel@tonic-gate ! upper 32 bits of AFSR already in o3 11017c478bd9Sstevel@tonic-gate mov %o4, %o0 ! save AFAR upper 32 bits 11027c478bd9Sstevel@tonic-gate mov %o2, %o4 ! lower 32 bits of AFSR 11037c478bd9Sstevel@tonic-gate mov %o1, %o2 ! lower 32 bits of AFAR 11047c478bd9Sstevel@tonic-gate mov %o0, %o1 ! upper 32 bits of AFAR 11057c478bd9Sstevel@tonic-gate set .celevel1msg, %o0 11067c478bd9Sstevel@tonic-gate call panic 11077c478bd9Sstevel@tonic-gate nop 11087c478bd9Sstevel@tonic-gate SET_SIZE(ce_trap_tl1) 11097c478bd9Sstevel@tonic-gate#endif 11107c478bd9Sstevel@tonic-gate 11117c478bd9Sstevel@tonic-gate ! 11127c478bd9Sstevel@tonic-gate ! async_err is the assembly glue code to get us from the actual trap 11137c478bd9Sstevel@tonic-gate ! into the CPU module's C error handler. Note that we also branch 11147c478bd9Sstevel@tonic-gate ! here from ce_err() above. 11157c478bd9Sstevel@tonic-gate ! 11167c478bd9Sstevel@tonic-gate ENTRY_NP(async_err) 11177c478bd9Sstevel@tonic-gate stxa %g0, [%g0]ASI_ESTATE_ERR ! disable ecc and other cpu errors 11187c478bd9Sstevel@tonic-gate membar #Sync ! membar sync required 11197c478bd9Sstevel@tonic-gate 11207c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_AFSR, %g3 ! save afsr in g3 11217c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_AFAR, %g2 ! save afar in g2 11227c478bd9Sstevel@tonic-gate 11237c478bd9Sstevel@tonic-gate sllx %g5, 53, %g5 ! move ttype to <63:53> 11247c478bd9Sstevel@tonic-gate or %g3, %g5, %g3 ! or to afsr in g3 11257c478bd9Sstevel@tonic-gate 11267c478bd9Sstevel@tonic-gate or %g0, 1, %g1 ! put 1 in g1 11277c478bd9Sstevel@tonic-gate sllx %g1, 21, %g1 ! shift left to <21> afsr UE 11287c478bd9Sstevel@tonic-gate andcc %g1, %g3, %g0 ! check for UE in afsr 11297c478bd9Sstevel@tonic-gate bz,a,pn %icc, 2f ! if !UE skip sdb read/clear 11307c478bd9Sstevel@tonic-gate nop 11317c478bd9Sstevel@tonic-gate 11327c478bd9Sstevel@tonic-gate set P_DER_H, %g4 ! put P_DER_H in g4 11337c478bd9Sstevel@tonic-gate ldxa [%g4]ASI_SDB_INTR_R, %g5 ! read sdb upper half into 56 11347c478bd9Sstevel@tonic-gate or %g0, 1, %g6 ! put 1 in g6 11357c478bd9Sstevel@tonic-gate sllx %g6, 9, %g6 ! shift g6 to <9> sdb UE 11367c478bd9Sstevel@tonic-gate andcc %g5, %g6, %g1 ! check for UE in upper half 11377c478bd9Sstevel@tonic-gate sllx %g5, 33, %g5 ! shift upper bits to <42:33> 11387c478bd9Sstevel@tonic-gate or %g3, %g5, %g3 ! or with afsr bits 11397c478bd9Sstevel@tonic-gate bz,a 1f ! no error, goto 1f 11407c478bd9Sstevel@tonic-gate nop 11417c478bd9Sstevel@tonic-gate stxa %g1, [%g4]ASI_SDB_INTR_W ! clear sdb reg UE error bit 11427c478bd9Sstevel@tonic-gate membar #Sync ! membar sync required 11437c478bd9Sstevel@tonic-gate1: 11447c478bd9Sstevel@tonic-gate set P_DER_L, %g4 ! put P_DER_L in g4 11457c478bd9Sstevel@tonic-gate ldxa [%g4]ASI_SDB_INTR_R, %g5 ! read sdb lower half into g5 11467c478bd9Sstevel@tonic-gate andcc %g5, %g6, %g1 ! check for UE in lower half 11477c478bd9Sstevel@tonic-gate sllx %g5, 43, %g5 ! shift upper bits to <52:43> 11487c478bd9Sstevel@tonic-gate or %g3, %g5, %g3 ! or with afsr bits 11497c478bd9Sstevel@tonic-gate bz,a 2f ! no error, goto 2f 11507c478bd9Sstevel@tonic-gate nop 11517c478bd9Sstevel@tonic-gate stxa %g1, [%g4]ASI_SDB_INTR_W ! clear sdb reg UE error bit 11527c478bd9Sstevel@tonic-gate membar #Sync ! membar sync required 11537c478bd9Sstevel@tonic-gate2: 11547c478bd9Sstevel@tonic-gate stxa %g3, [%g0]ASI_AFSR ! clear all the sticky bits 11557c478bd9Sstevel@tonic-gate membar #Sync ! membar sync required 11567c478bd9Sstevel@tonic-gate 1157*2dd3029aSjimand RESET_USER_RTT_REGS(%g4, %g5, async_err_resetskip) 1158*2dd3029aSjimandasync_err_resetskip: 11598f230a59Sbs21162 11607c478bd9Sstevel@tonic-gate set cpu_async_error, %g1 ! put cpu_async_error in g1 11617c478bd9Sstevel@tonic-gate sethi %hi(sys_trap), %g5 11627c478bd9Sstevel@tonic-gate jmp %g5 + %lo(sys_trap) ! goto sys_trap 11637c478bd9Sstevel@tonic-gate or %g0, PIL_15, %g4 ! run at pil 15 11647c478bd9Sstevel@tonic-gate SET_SIZE(async_err) 11657c478bd9Sstevel@tonic-gate 11667c478bd9Sstevel@tonic-gate ENTRY_NP(dis_err_panic1) 11677c478bd9Sstevel@tonic-gate stxa %g0, [%g0]ASI_ESTATE_ERR ! disable all error traps 11687c478bd9Sstevel@tonic-gate membar #Sync 11697c478bd9Sstevel@tonic-gate ! save destination routine is in g1 11707c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_AFAR, %g2 ! read afar 11717c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_AFSR, %g3 ! read afsr 11727c478bd9Sstevel@tonic-gate set P_DER_H, %g4 ! put P_DER_H in g4 11737c478bd9Sstevel@tonic-gate ldxa [%g4]ASI_SDB_INTR_R, %g5 ! read sdb upper half into g5 11747c478bd9Sstevel@tonic-gate sllx %g5, 33, %g5 ! shift upper bits to <42:33> 11757c478bd9Sstevel@tonic-gate or %g3, %g5, %g3 ! or with afsr bits 11767c478bd9Sstevel@tonic-gate set P_DER_L, %g4 ! put P_DER_L in g4 11777c478bd9Sstevel@tonic-gate ldxa [%g4]ASI_SDB_INTR_R, %g5 ! read sdb lower half into g5 11787c478bd9Sstevel@tonic-gate sllx %g5, 43, %g5 ! shift upper bits to <52:43> 11797c478bd9Sstevel@tonic-gate or %g3, %g5, %g3 ! or with afsr bits 11808f230a59Sbs21162 1181*2dd3029aSjimand RESET_USER_RTT_REGS(%g4, %g5, dis_err_panic1_resetskip) 1182*2dd3029aSjimanddis_err_panic1_resetskip: 11838f230a59Sbs21162 11847c478bd9Sstevel@tonic-gate sethi %hi(sys_trap), %g5 11857c478bd9Sstevel@tonic-gate jmp %g5 + %lo(sys_trap) ! goto sys_trap 11867c478bd9Sstevel@tonic-gate sub %g0, 1, %g4 11877c478bd9Sstevel@tonic-gate SET_SIZE(dis_err_panic1) 11887c478bd9Sstevel@tonic-gate 11897c478bd9Sstevel@tonic-gate ENTRY(clr_datapath) 11907c478bd9Sstevel@tonic-gate set P_DER_H, %o4 ! put P_DER_H in o4 11917c478bd9Sstevel@tonic-gate ldxa [%o4]ASI_SDB_INTR_R, %o5 ! read sdb upper half into o3 11927c478bd9Sstevel@tonic-gate or %g0, 0x3, %o2 ! put 0x3 in o2 11937c478bd9Sstevel@tonic-gate sllx %o2, 8, %o2 ! shift o2 to <9:8> sdb 11947c478bd9Sstevel@tonic-gate andcc %o5, %o2, %o1 ! check for UE,CE in upper half 11957c478bd9Sstevel@tonic-gate bz,a 1f ! no error, goto 1f 11967c478bd9Sstevel@tonic-gate nop 11977c478bd9Sstevel@tonic-gate stxa %o1, [%o4]ASI_SDB_INTR_W ! clear sdb reg UE,CE error bits 11987c478bd9Sstevel@tonic-gate membar #Sync ! membar sync required 11997c478bd9Sstevel@tonic-gate1: 12007c478bd9Sstevel@tonic-gate set P_DER_L, %o4 ! put P_DER_L in o4 12017c478bd9Sstevel@tonic-gate ldxa [%o4]ASI_SDB_INTR_R, %o5 ! read sdb lower half into o5 12027c478bd9Sstevel@tonic-gate andcc %o5, %o2, %o1 ! check for UE,CE in lower half 12037c478bd9Sstevel@tonic-gate bz,a 2f ! no error, goto 2f 12047c478bd9Sstevel@tonic-gate nop 12057c478bd9Sstevel@tonic-gate stxa %o1, [%o4]ASI_SDB_INTR_W ! clear sdb reg UE,CE error bits 12067c478bd9Sstevel@tonic-gate membar #Sync 12077c478bd9Sstevel@tonic-gate2: 12087c478bd9Sstevel@tonic-gate retl 12097c478bd9Sstevel@tonic-gate nop 12107c478bd9Sstevel@tonic-gate SET_SIZE(clr_datapath) 12117c478bd9Sstevel@tonic-gate 12127c478bd9Sstevel@tonic-gate ENTRY(get_udb_errors) 12137c478bd9Sstevel@tonic-gate set P_DER_H, %o3 12147c478bd9Sstevel@tonic-gate ldxa [%o3]ASI_SDB_INTR_R, %o2 12157c478bd9Sstevel@tonic-gate stx %o2, [%o0] 12167c478bd9Sstevel@tonic-gate set P_DER_L, %o3 12177c478bd9Sstevel@tonic-gate ldxa [%o3]ASI_SDB_INTR_R, %o2 12187c478bd9Sstevel@tonic-gate retl 12197c478bd9Sstevel@tonic-gate stx %o2, [%o1] 12207c478bd9Sstevel@tonic-gate SET_SIZE(get_udb_errors) 12217c478bd9Sstevel@tonic-gate 12227c478bd9Sstevel@tonic-gate#endif /* lint */ 12237c478bd9Sstevel@tonic-gate 12247c478bd9Sstevel@tonic-gate#if defined(lint) 12257c478bd9Sstevel@tonic-gate/* 12267c478bd9Sstevel@tonic-gate * The itlb_rd_entry and dtlb_rd_entry functions return the tag portion of the 12277c478bd9Sstevel@tonic-gate * tte, the virtual address, and the ctxnum of the specified tlb entry. They 12287c478bd9Sstevel@tonic-gate * should only be used in places where you have no choice but to look at the 12297c478bd9Sstevel@tonic-gate * tlb itself. 12307c478bd9Sstevel@tonic-gate * 12317c478bd9Sstevel@tonic-gate * Note: These two routines are required by the Estar "cpr" loadable module. 12327c478bd9Sstevel@tonic-gate */ 12337c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 12347c478bd9Sstevel@tonic-gatevoid 12357c478bd9Sstevel@tonic-gateitlb_rd_entry(uint_t entry, tte_t *tte, uint64_t *va_tag) 12367c478bd9Sstevel@tonic-gate{} 12377c478bd9Sstevel@tonic-gate 12387c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 12397c478bd9Sstevel@tonic-gatevoid 12407c478bd9Sstevel@tonic-gatedtlb_rd_entry(uint_t entry, tte_t *tte, uint64_t *va_tag) 12417c478bd9Sstevel@tonic-gate{} 12427c478bd9Sstevel@tonic-gate#else /* lint */ 12437c478bd9Sstevel@tonic-gate/* 12447c478bd9Sstevel@tonic-gate * NB - In Spitfire cpus, when reading a tte from the hardware, we 12457c478bd9Sstevel@tonic-gate * need to clear [42-41] because the general definitions in pte.h 12467c478bd9Sstevel@tonic-gate * define the PA to be [42-13] whereas Spitfire really uses [40-13]. 12477c478bd9Sstevel@tonic-gate * When cloning these routines for other cpus the "andn" below is not 12487c478bd9Sstevel@tonic-gate * necessary. 12497c478bd9Sstevel@tonic-gate */ 12507c478bd9Sstevel@tonic-gate ENTRY_NP(itlb_rd_entry) 12517c478bd9Sstevel@tonic-gate sllx %o0, 3, %o0 12527c478bd9Sstevel@tonic-gate#if defined(SF_ERRATA_32) 12537c478bd9Sstevel@tonic-gate sethi %hi(FLUSH_ADDR), %g2 12547c478bd9Sstevel@tonic-gate set MMU_PCONTEXT, %g1 12557c478bd9Sstevel@tonic-gate stxa %g0, [%g1]ASI_DMMU ! KCONTEXT 12567c478bd9Sstevel@tonic-gate flush %g2 12577c478bd9Sstevel@tonic-gate#endif 12587c478bd9Sstevel@tonic-gate ldxa [%o0]ASI_ITLB_ACCESS, %g1 12597c478bd9Sstevel@tonic-gate set TTE_SPITFIRE_PFNHI_CLEAR, %g2 ! spitfire only 12607c478bd9Sstevel@tonic-gate sllx %g2, TTE_SPITFIRE_PFNHI_SHIFT, %g2 ! see comment above 12617c478bd9Sstevel@tonic-gate andn %g1, %g2, %g1 ! for details 12627c478bd9Sstevel@tonic-gate stx %g1, [%o1] 12637c478bd9Sstevel@tonic-gate ldxa [%o0]ASI_ITLB_TAGREAD, %g2 12647c478bd9Sstevel@tonic-gate set TAGREAD_CTX_MASK, %o4 12657c478bd9Sstevel@tonic-gate andn %g2, %o4, %o5 12667c478bd9Sstevel@tonic-gate retl 12677c478bd9Sstevel@tonic-gate stx %o5, [%o2] 12687c478bd9Sstevel@tonic-gate SET_SIZE(itlb_rd_entry) 12697c478bd9Sstevel@tonic-gate 12707c478bd9Sstevel@tonic-gate ENTRY_NP(dtlb_rd_entry) 12717c478bd9Sstevel@tonic-gate sllx %o0, 3, %o0 12727c478bd9Sstevel@tonic-gate#if defined(SF_ERRATA_32) 12737c478bd9Sstevel@tonic-gate sethi %hi(FLUSH_ADDR), %g2 12747c478bd9Sstevel@tonic-gate set MMU_PCONTEXT, %g1 12757c478bd9Sstevel@tonic-gate stxa %g0, [%g1]ASI_DMMU ! KCONTEXT 12767c478bd9Sstevel@tonic-gate flush %g2 12777c478bd9Sstevel@tonic-gate#endif 12787c478bd9Sstevel@tonic-gate ldxa [%o0]ASI_DTLB_ACCESS, %g1 12797c478bd9Sstevel@tonic-gate set TTE_SPITFIRE_PFNHI_CLEAR, %g2 ! spitfire only 12807c478bd9Sstevel@tonic-gate sllx %g2, TTE_SPITFIRE_PFNHI_SHIFT, %g2 ! see comment above 12817c478bd9Sstevel@tonic-gate andn %g1, %g2, %g1 ! itlb_rd_entry 12827c478bd9Sstevel@tonic-gate stx %g1, [%o1] 12837c478bd9Sstevel@tonic-gate ldxa [%o0]ASI_DTLB_TAGREAD, %g2 12847c478bd9Sstevel@tonic-gate set TAGREAD_CTX_MASK, %o4 12857c478bd9Sstevel@tonic-gate andn %g2, %o4, %o5 12867c478bd9Sstevel@tonic-gate retl 12877c478bd9Sstevel@tonic-gate stx %o5, [%o2] 12887c478bd9Sstevel@tonic-gate SET_SIZE(dtlb_rd_entry) 12897c478bd9Sstevel@tonic-gate#endif /* lint */ 12907c478bd9Sstevel@tonic-gate 12917c478bd9Sstevel@tonic-gate#if defined(lint) 12927c478bd9Sstevel@tonic-gate 12937c478bd9Sstevel@tonic-gate/* 12947c478bd9Sstevel@tonic-gate * routines to get and set the LSU register 12957c478bd9Sstevel@tonic-gate */ 12967c478bd9Sstevel@tonic-gateuint64_t 12977c478bd9Sstevel@tonic-gateget_lsu(void) 12987c478bd9Sstevel@tonic-gate{ 12997c478bd9Sstevel@tonic-gate return ((uint64_t)0); 13007c478bd9Sstevel@tonic-gate} 13017c478bd9Sstevel@tonic-gate 13027c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 13037c478bd9Sstevel@tonic-gatevoid 13047c478bd9Sstevel@tonic-gateset_lsu(uint64_t lsu) 13057c478bd9Sstevel@tonic-gate{} 13067c478bd9Sstevel@tonic-gate 13077c478bd9Sstevel@tonic-gate#else /* lint */ 13087c478bd9Sstevel@tonic-gate 13097c478bd9Sstevel@tonic-gate ENTRY(set_lsu) 13107c478bd9Sstevel@tonic-gate stxa %o0, [%g0]ASI_LSU ! store to LSU 13117c478bd9Sstevel@tonic-gate retl 13127c478bd9Sstevel@tonic-gate membar #Sync 13137c478bd9Sstevel@tonic-gate SET_SIZE(set_lsu) 13147c478bd9Sstevel@tonic-gate 13157c478bd9Sstevel@tonic-gate ENTRY(get_lsu) 13167c478bd9Sstevel@tonic-gate retl 13177c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_LSU, %o0 ! load LSU 13187c478bd9Sstevel@tonic-gate SET_SIZE(get_lsu) 13197c478bd9Sstevel@tonic-gate 13207c478bd9Sstevel@tonic-gate#endif /* lint */ 13217c478bd9Sstevel@tonic-gate 13227c478bd9Sstevel@tonic-gate#ifndef lint 13237c478bd9Sstevel@tonic-gate /* 13247c478bd9Sstevel@tonic-gate * Clear the NPT (non-privileged trap) bit in the %tick 13257c478bd9Sstevel@tonic-gate * registers. In an effort to make the change in the 13267c478bd9Sstevel@tonic-gate * tick counter as consistent as possible, we disable 13277c478bd9Sstevel@tonic-gate * all interrupts while we're changing the registers. We also 13287c478bd9Sstevel@tonic-gate * ensure that the read and write instructions are in the same 13297c478bd9Sstevel@tonic-gate * line in the instruction cache. 13307c478bd9Sstevel@tonic-gate */ 13317c478bd9Sstevel@tonic-gate ENTRY_NP(cpu_clearticknpt) 13327c478bd9Sstevel@tonic-gate rdpr %pstate, %g1 /* save processor state */ 13337c478bd9Sstevel@tonic-gate andn %g1, PSTATE_IE, %g3 /* turn off */ 13347c478bd9Sstevel@tonic-gate wrpr %g0, %g3, %pstate /* interrupts */ 13357c478bd9Sstevel@tonic-gate rdpr %tick, %g2 /* get tick register */ 13367c478bd9Sstevel@tonic-gate brgez,pn %g2, 1f /* if NPT bit off, we're done */ 13377c478bd9Sstevel@tonic-gate mov 1, %g3 /* create mask */ 13387c478bd9Sstevel@tonic-gate sllx %g3, 63, %g3 /* for NPT bit */ 13397c478bd9Sstevel@tonic-gate ba,a,pt %xcc, 2f 13407c478bd9Sstevel@tonic-gate .align 64 /* Align to I$ boundary */ 13417c478bd9Sstevel@tonic-gate2: 13427c478bd9Sstevel@tonic-gate rdpr %tick, %g2 /* get tick register */ 13437c478bd9Sstevel@tonic-gate wrpr %g3, %g2, %tick /* write tick register, */ 13447c478bd9Sstevel@tonic-gate /* clearing NPT bit */ 13457c478bd9Sstevel@tonic-gate#if defined(BB_ERRATA_1) 13467c478bd9Sstevel@tonic-gate rdpr %tick, %g0 /* read (s)tick (BB_ERRATA_1) */ 13477c478bd9Sstevel@tonic-gate#endif 13487c478bd9Sstevel@tonic-gate1: 13497c478bd9Sstevel@tonic-gate jmp %g4 + 4 13507c478bd9Sstevel@tonic-gate wrpr %g0, %g1, %pstate /* restore processor state */ 13517c478bd9Sstevel@tonic-gate SET_SIZE(cpu_clearticknpt) 13527c478bd9Sstevel@tonic-gate 13537c478bd9Sstevel@tonic-gate /* 13547c478bd9Sstevel@tonic-gate * get_ecache_tag() 13557c478bd9Sstevel@tonic-gate * Register Usage: 13567c478bd9Sstevel@tonic-gate * %o0: In: 32-bit E$ index 13577c478bd9Sstevel@tonic-gate * Out: 64-bit E$ tag value 13587c478bd9Sstevel@tonic-gate * %o1: In: 64-bit AFSR value after clearing sticky bits 13597c478bd9Sstevel@tonic-gate * %o2: In: address of cpu private afsr storage 13607c478bd9Sstevel@tonic-gate */ 13617c478bd9Sstevel@tonic-gate ENTRY(get_ecache_tag) 13627c478bd9Sstevel@tonic-gate or %g0, 1, %o4 13637c478bd9Sstevel@tonic-gate sllx %o4, 40, %o4 ! set bit 40 for e$ tag access 13647c478bd9Sstevel@tonic-gate or %o0, %o4, %o4 ! %o4 = e$ addr for tag read 13657c478bd9Sstevel@tonic-gate rdpr %pstate, %o5 13667c478bd9Sstevel@tonic-gate andn %o5, PSTATE_IE | PSTATE_AM, %o0 13677c478bd9Sstevel@tonic-gate wrpr %o0, %g0, %pstate ! clear IE, AM bits 13687c478bd9Sstevel@tonic-gate 13697c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_ESTATE_ERR, %g1 13707c478bd9Sstevel@tonic-gate stxa %g0, [%g0]ASI_ESTATE_ERR ! Turn off Error enable 13717c478bd9Sstevel@tonic-gate membar #Sync 13727c478bd9Sstevel@tonic-gate 13737c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_AFSR, %o0 13747c478bd9Sstevel@tonic-gate srlx %o0, P_AFSR_CP_SHIFT, %o3 13757c478bd9Sstevel@tonic-gate btst 1, %o3 13767c478bd9Sstevel@tonic-gate bz 1f 13777c478bd9Sstevel@tonic-gate nop 13787c478bd9Sstevel@tonic-gate ldx [%o2], %g4 13797c478bd9Sstevel@tonic-gate or %g4, %o0, %g4 ! aggregate AFSR in cpu private 13807c478bd9Sstevel@tonic-gate stx %g4, [%o2] 13817c478bd9Sstevel@tonic-gate1: 13827c478bd9Sstevel@tonic-gate stxa %o0, [%g0]ASI_AFSR ! clear AFSR 13837c478bd9Sstevel@tonic-gate membar #Sync 13847c478bd9Sstevel@tonic-gate 13857c478bd9Sstevel@tonic-gate ldxa [%o4]ASI_EC_R, %g0 13867c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_EC_DIAG, %o0 ! read tag from e$ tag reg 13877c478bd9Sstevel@tonic-gate 13887c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_AFSR, %o3 13897c478bd9Sstevel@tonic-gate srlx %o3, P_AFSR_CP_SHIFT, %o4 13907c478bd9Sstevel@tonic-gate btst 1, %o4 13917c478bd9Sstevel@tonic-gate bz 2f 13927c478bd9Sstevel@tonic-gate stx %o3, [%o1] ! AFSR after sticky clear 13937c478bd9Sstevel@tonic-gate ldx [%o2], %g4 13947c478bd9Sstevel@tonic-gate or %g4, %o3, %g4 ! aggregate AFSR in cpu private 13957c478bd9Sstevel@tonic-gate stx %g4, [%o2] 13967c478bd9Sstevel@tonic-gate2: 13977c478bd9Sstevel@tonic-gate membar #Sync 13987c478bd9Sstevel@tonic-gate 13997c478bd9Sstevel@tonic-gate stxa %g1, [%g0]ASI_ESTATE_ERR ! Turn error enable back on 14007c478bd9Sstevel@tonic-gate membar #Sync 14017c478bd9Sstevel@tonic-gate retl 14027c478bd9Sstevel@tonic-gate wrpr %g0, %o5, %pstate 14037c478bd9Sstevel@tonic-gate SET_SIZE(get_ecache_tag) 14047c478bd9Sstevel@tonic-gate 14057c478bd9Sstevel@tonic-gate /* 14067c478bd9Sstevel@tonic-gate * check_ecache_line() 14077c478bd9Sstevel@tonic-gate * Register Usage: 14087c478bd9Sstevel@tonic-gate * %o0: In: 32-bit E$ index 14097c478bd9Sstevel@tonic-gate * Out: 64-bit accumulated AFSR 14107c478bd9Sstevel@tonic-gate * %o1: In: address of cpu private afsr storage 14117c478bd9Sstevel@tonic-gate */ 14127c478bd9Sstevel@tonic-gate ENTRY(check_ecache_line) 14137c478bd9Sstevel@tonic-gate or %g0, 1, %o4 14147c478bd9Sstevel@tonic-gate sllx %o4, 39, %o4 ! set bit 39 for e$ data access 14157c478bd9Sstevel@tonic-gate or %o0, %o4, %o4 ! %o4 = e$ addr for data read 14167c478bd9Sstevel@tonic-gate 14177c478bd9Sstevel@tonic-gate rdpr %pstate, %o5 14187c478bd9Sstevel@tonic-gate andn %o5, PSTATE_IE | PSTATE_AM, %o0 14197c478bd9Sstevel@tonic-gate wrpr %o0, %g0, %pstate ! clear IE, AM bits 14207c478bd9Sstevel@tonic-gate 14217c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_ESTATE_ERR, %g1 14227c478bd9Sstevel@tonic-gate stxa %g0, [%g0]ASI_ESTATE_ERR ! Turn off Error enable 14237c478bd9Sstevel@tonic-gate membar #Sync 14247c478bd9Sstevel@tonic-gate 14257c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_AFSR, %o0 14267c478bd9Sstevel@tonic-gate srlx %o0, P_AFSR_CP_SHIFT, %o2 14277c478bd9Sstevel@tonic-gate btst 1, %o2 14287c478bd9Sstevel@tonic-gate bz 1f 14297c478bd9Sstevel@tonic-gate clr %o2 ! loop count 14307c478bd9Sstevel@tonic-gate ldx [%o1], %o3 14317c478bd9Sstevel@tonic-gate or %o3, %o0, %o3 ! aggregate AFSR in cpu private 14327c478bd9Sstevel@tonic-gate stx %o3, [%o1] 14337c478bd9Sstevel@tonic-gate1: 14347c478bd9Sstevel@tonic-gate stxa %o0, [%g0]ASI_AFSR ! clear AFSR 14357c478bd9Sstevel@tonic-gate membar #Sync 14367c478bd9Sstevel@tonic-gate 14377c478bd9Sstevel@tonic-gate2: 14387c478bd9Sstevel@tonic-gate ldxa [%o4]ASI_EC_R, %g0 ! Read the E$ data 8bytes each 14397c478bd9Sstevel@tonic-gate add %o2, 1, %o2 14407c478bd9Sstevel@tonic-gate cmp %o2, 8 14417c478bd9Sstevel@tonic-gate bl,a 2b 14427c478bd9Sstevel@tonic-gate add %o4, 8, %o4 14437c478bd9Sstevel@tonic-gate 14447c478bd9Sstevel@tonic-gate membar #Sync 14457c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_AFSR, %o0 ! read accumulated AFSR 14467c478bd9Sstevel@tonic-gate srlx %o0, P_AFSR_CP_SHIFT, %o2 14477c478bd9Sstevel@tonic-gate btst 1, %o2 14487c478bd9Sstevel@tonic-gate bz 3f 14497c478bd9Sstevel@tonic-gate nop 14507c478bd9Sstevel@tonic-gate ldx [%o1], %o3 14517c478bd9Sstevel@tonic-gate or %o3, %o0, %o3 ! aggregate AFSR in cpu private 14527c478bd9Sstevel@tonic-gate stx %o3, [%o1] 14537c478bd9Sstevel@tonic-gate3: 14547c478bd9Sstevel@tonic-gate stxa %o0, [%g0]ASI_AFSR ! clear AFSR 14557c478bd9Sstevel@tonic-gate membar #Sync 14567c478bd9Sstevel@tonic-gate stxa %g1, [%g0]ASI_ESTATE_ERR ! Turn error enable back on 14577c478bd9Sstevel@tonic-gate membar #Sync 14587c478bd9Sstevel@tonic-gate retl 14597c478bd9Sstevel@tonic-gate wrpr %g0, %o5, %pstate 14607c478bd9Sstevel@tonic-gate SET_SIZE(check_ecache_line) 14617c478bd9Sstevel@tonic-gate#endif /* lint */ 14627c478bd9Sstevel@tonic-gate 14637c478bd9Sstevel@tonic-gate#if defined(lint) 14647c478bd9Sstevel@tonic-gateuint64_t 14657c478bd9Sstevel@tonic-gateread_and_clear_afsr() 14667c478bd9Sstevel@tonic-gate{ 14677c478bd9Sstevel@tonic-gate return ((uint64_t)0); 14687c478bd9Sstevel@tonic-gate} 14697c478bd9Sstevel@tonic-gate#else /* lint */ 14707c478bd9Sstevel@tonic-gate ENTRY(read_and_clear_afsr) 14717c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_AFSR, %o0 14727c478bd9Sstevel@tonic-gate retl 14737c478bd9Sstevel@tonic-gate stxa %o0, [%g0]ASI_AFSR ! clear AFSR 14747c478bd9Sstevel@tonic-gate SET_SIZE(read_and_clear_afsr) 14757c478bd9Sstevel@tonic-gate#endif /* lint */ 14767c478bd9Sstevel@tonic-gate 14777c478bd9Sstevel@tonic-gate#if defined(lint) 14787c478bd9Sstevel@tonic-gate/* ARGSUSED */ 14797c478bd9Sstevel@tonic-gatevoid 14807c478bd9Sstevel@tonic-gatescrubphys(uint64_t paddr, int ecache_size) 14817c478bd9Sstevel@tonic-gate{ 14827c478bd9Sstevel@tonic-gate} 14837c478bd9Sstevel@tonic-gate 14847c478bd9Sstevel@tonic-gate#else /* lint */ 14857c478bd9Sstevel@tonic-gate 14867c478bd9Sstevel@tonic-gate/* 14877c478bd9Sstevel@tonic-gate * scrubphys - Pass in the aligned physical memory address that you want 14887c478bd9Sstevel@tonic-gate * to scrub, along with the ecache size. 14897c478bd9Sstevel@tonic-gate * 14907c478bd9Sstevel@tonic-gate * 1) Displacement flush the E$ line corresponding to %addr. 14917c478bd9Sstevel@tonic-gate * The first ldxa guarantees that the %addr is no longer in 14927c478bd9Sstevel@tonic-gate * M, O, or E (goes to I or S (if instruction fetch also happens). 14937c478bd9Sstevel@tonic-gate * 2) "Write" the data using a CAS %addr,%g0,%g0. 14947c478bd9Sstevel@tonic-gate * The casxa guarantees a transition from I to M or S to M. 14957c478bd9Sstevel@tonic-gate * 3) Displacement flush the E$ line corresponding to %addr. 14967c478bd9Sstevel@tonic-gate * The second ldxa pushes the M line out of the ecache, into the 14977c478bd9Sstevel@tonic-gate * writeback buffers, on the way to memory. 14987c478bd9Sstevel@tonic-gate * 4) The "membar #Sync" pushes the cache line out of the writeback 14997c478bd9Sstevel@tonic-gate * buffers onto the bus, on the way to dram finally. 15007c478bd9Sstevel@tonic-gate * 15017c478bd9Sstevel@tonic-gate * This is a modified version of the algorithm suggested by Gary Lauterbach. 15027c478bd9Sstevel@tonic-gate * In theory the CAS %addr,%g0,%g0 is supposed to mark the addr's cache line 15037c478bd9Sstevel@tonic-gate * as modified, but then we found out that for spitfire, if it misses in the 15047c478bd9Sstevel@tonic-gate * E$ it will probably install as an M, but if it hits in the E$, then it 15057c478bd9Sstevel@tonic-gate * will stay E, if the store doesn't happen. So the first displacement flush 15067c478bd9Sstevel@tonic-gate * should ensure that the CAS will miss in the E$. Arrgh. 15077c478bd9Sstevel@tonic-gate */ 15087c478bd9Sstevel@tonic-gate 15097c478bd9Sstevel@tonic-gate ENTRY(scrubphys) 15107c478bd9Sstevel@tonic-gate or %o1, %g0, %o2 ! put ecache size in %o2 15117c478bd9Sstevel@tonic-gate#ifndef HUMMINGBIRD 15127c478bd9Sstevel@tonic-gate xor %o0, %o2, %o1 ! calculate alias address 15137c478bd9Sstevel@tonic-gate add %o2, %o2, %o3 ! 2 * ecachesize in case 15147c478bd9Sstevel@tonic-gate ! addr == ecache_flushaddr 15157c478bd9Sstevel@tonic-gate sub %o3, 1, %o3 ! -1 == mask 15167c478bd9Sstevel@tonic-gate and %o1, %o3, %o1 ! and with xor'd address 15177c478bd9Sstevel@tonic-gate set ecache_flushaddr, %o3 15187c478bd9Sstevel@tonic-gate ldx [%o3], %o3 15197c478bd9Sstevel@tonic-gate 15207c478bd9Sstevel@tonic-gate rdpr %pstate, %o4 15217c478bd9Sstevel@tonic-gate andn %o4, PSTATE_IE | PSTATE_AM, %o5 15227c478bd9Sstevel@tonic-gate wrpr %o5, %g0, %pstate ! clear IE, AM bits 15237c478bd9Sstevel@tonic-gate 15247c478bd9Sstevel@tonic-gate ldxa [%o1 + %o3]ASI_MEM, %g0 ! load ecache_flushaddr + alias 15257c478bd9Sstevel@tonic-gate casxa [%o0]ASI_MEM, %g0, %g0 15267c478bd9Sstevel@tonic-gate ldxa [%o1 + %o3]ASI_MEM, %g0 ! load ecache_flushaddr + alias 15277c478bd9Sstevel@tonic-gate 15287c478bd9Sstevel@tonic-gate#else /* HUMMINGBIRD */ 15297c478bd9Sstevel@tonic-gate /* 15307c478bd9Sstevel@tonic-gate * UltraSPARC-IIe processor supports both 4-way set associative 15317c478bd9Sstevel@tonic-gate * and direct map E$. We need to reconfigure E$ to direct map 15327c478bd9Sstevel@tonic-gate * mode for data load/store before displacement flush. Also, we 15337c478bd9Sstevel@tonic-gate * need to flush all 4 sets of the E$ to ensure that the physaddr 15347c478bd9Sstevel@tonic-gate * has been flushed. Keep the interrupts disabled while flushing 15357c478bd9Sstevel@tonic-gate * E$ in this manner. 15367c478bd9Sstevel@tonic-gate * 15377c478bd9Sstevel@tonic-gate * For flushing a specific physical address, we start at the 15387c478bd9Sstevel@tonic-gate * aliased address and load at set-size stride, wrapping around 15397c478bd9Sstevel@tonic-gate * at 2*ecache-size boundary and skipping fault physical address. 15407c478bd9Sstevel@tonic-gate * It takes 10 loads to guarantee that the physical address has 15417c478bd9Sstevel@tonic-gate * been flushed. 15427c478bd9Sstevel@tonic-gate * 15437c478bd9Sstevel@tonic-gate * Usage: 15447c478bd9Sstevel@tonic-gate * %o0 physaddr 15457c478bd9Sstevel@tonic-gate * %o5 physaddr - ecache_flushaddr 15467c478bd9Sstevel@tonic-gate * %g1 UPA config (restored later) 15477c478bd9Sstevel@tonic-gate * %g2 E$ set size 15487c478bd9Sstevel@tonic-gate * %g3 E$ flush address range mask (i.e. 2 * E$ -1) 15497c478bd9Sstevel@tonic-gate * %g4 #loads to flush phys address 15507c478bd9Sstevel@tonic-gate * %g5 temp 15517c478bd9Sstevel@tonic-gate */ 15527c478bd9Sstevel@tonic-gate 15537c478bd9Sstevel@tonic-gate sethi %hi(ecache_associativity), %g5 15547c478bd9Sstevel@tonic-gate ld [%g5 + %lo(ecache_associativity)], %g5 15557c478bd9Sstevel@tonic-gate udivx %o2, %g5, %g2 ! set size (i.e. ecache_size/#sets) 15567c478bd9Sstevel@tonic-gate xor %o0, %o2, %o1 ! calculate alias address 15577c478bd9Sstevel@tonic-gate add %o2, %o2, %g3 ! 2 * ecachesize in case 15587c478bd9Sstevel@tonic-gate ! addr == ecache_flushaddr 15597c478bd9Sstevel@tonic-gate sub %g3, 1, %g3 ! 2 * ecachesize -1 == mask 15607c478bd9Sstevel@tonic-gate and %o1, %g3, %o1 ! and with xor'd address 15617c478bd9Sstevel@tonic-gate sethi %hi(ecache_flushaddr), %o3 15627c478bd9Sstevel@tonic-gate ldx [%o3 + %lo(ecache_flushaddr)], %o3 15637c478bd9Sstevel@tonic-gate 15647c478bd9Sstevel@tonic-gate rdpr %pstate, %o4 15657c478bd9Sstevel@tonic-gate andn %o4, PSTATE_IE | PSTATE_AM, %o5 15667c478bd9Sstevel@tonic-gate wrpr %o5, %g0, %pstate ! clear IE, AM bits 15677c478bd9Sstevel@tonic-gate 15687c478bd9Sstevel@tonic-gate ! Place E$ in direct map mode for data access 15697c478bd9Sstevel@tonic-gate or %g0, 1, %g5 15707c478bd9Sstevel@tonic-gate sllx %g5, HB_UPA_DMAP_DATA_BIT, %g5 15717c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_UPA_CONFIG, %g1 ! current UPA config (restored later) 15727c478bd9Sstevel@tonic-gate or %g1, %g5, %g5 15737c478bd9Sstevel@tonic-gate membar #Sync 15747c478bd9Sstevel@tonic-gate stxa %g5, [%g0]ASI_UPA_CONFIG ! enable direct map for data access 15757c478bd9Sstevel@tonic-gate membar #Sync 15767c478bd9Sstevel@tonic-gate 15777c478bd9Sstevel@tonic-gate ! Displace cache line from each set of E$ starting at the 15787c478bd9Sstevel@tonic-gate ! aliased address. at set-size stride, wrapping at 2*ecache_size 15797c478bd9Sstevel@tonic-gate ! and skipping load from physaddr. We need 10 loads to flush the 15807c478bd9Sstevel@tonic-gate ! physaddr from E$. 15817c478bd9Sstevel@tonic-gate mov HB_PHYS_FLUSH_CNT-1, %g4 ! #loads to flush phys addr 15827c478bd9Sstevel@tonic-gate sub %o0, %o3, %o5 ! physaddr - ecache_flushaddr 15837c478bd9Sstevel@tonic-gate or %o1, %g0, %g5 ! starting aliased offset 15847c478bd9Sstevel@tonic-gate2: 15857c478bd9Sstevel@tonic-gate ldxa [%g5 + %o3]ASI_MEM, %g0 ! load ecache_flushaddr + alias 15867c478bd9Sstevel@tonic-gate1: 15877c478bd9Sstevel@tonic-gate add %g5, %g2, %g5 ! calculate offset in next set 15887c478bd9Sstevel@tonic-gate and %g5, %g3, %g5 ! force offset within aliased range 15897c478bd9Sstevel@tonic-gate cmp %g5, %o5 ! skip loads from physaddr 15907c478bd9Sstevel@tonic-gate be,pn %ncc, 1b 15917c478bd9Sstevel@tonic-gate nop 15927c478bd9Sstevel@tonic-gate brgz,pt %g4, 2b 15937c478bd9Sstevel@tonic-gate dec %g4 15947c478bd9Sstevel@tonic-gate 15957c478bd9Sstevel@tonic-gate casxa [%o0]ASI_MEM, %g0, %g0 15967c478bd9Sstevel@tonic-gate 15977c478bd9Sstevel@tonic-gate ! Flush %o0 from ecahe again. 15987c478bd9Sstevel@tonic-gate ! Need single displacement flush at offset %o1 this time as 15997c478bd9Sstevel@tonic-gate ! the E$ is already in direct map mode. 16007c478bd9Sstevel@tonic-gate ldxa [%o1 + %o3]ASI_MEM, %g0 ! load ecache_flushaddr + alias 16017c478bd9Sstevel@tonic-gate 16027c478bd9Sstevel@tonic-gate membar #Sync 16037c478bd9Sstevel@tonic-gate stxa %g1, [%g0]ASI_UPA_CONFIG ! restore UPA config (DM bits) 16047c478bd9Sstevel@tonic-gate membar #Sync 16057c478bd9Sstevel@tonic-gate#endif /* HUMMINGBIRD */ 16067c478bd9Sstevel@tonic-gate wrpr %g0, %o4, %pstate ! restore earlier pstate register value 16077c478bd9Sstevel@tonic-gate 16087c478bd9Sstevel@tonic-gate retl 16097c478bd9Sstevel@tonic-gate membar #Sync ! move the data out of the load buffer 16107c478bd9Sstevel@tonic-gate SET_SIZE(scrubphys) 16117c478bd9Sstevel@tonic-gate 16127c478bd9Sstevel@tonic-gate#endif /* lint */ 16137c478bd9Sstevel@tonic-gate 16147c478bd9Sstevel@tonic-gate#if defined(lint) 16157c478bd9Sstevel@tonic-gate 16167c478bd9Sstevel@tonic-gate/* 16177c478bd9Sstevel@tonic-gate * clearphys - Pass in the aligned physical memory address that you want 16187c478bd9Sstevel@tonic-gate * to push out, as a 64 byte block of zeros, from the ecache zero-filled. 16197c478bd9Sstevel@tonic-gate * Since this routine does not bypass the ecache, it is possible that 16207c478bd9Sstevel@tonic-gate * it could generate a UE error while trying to clear the a bad line. 16217c478bd9Sstevel@tonic-gate * This routine clears and restores the error enable flag. 16227c478bd9Sstevel@tonic-gate * TBD - Hummingbird may need similar protection 16237c478bd9Sstevel@tonic-gate */ 16247c478bd9Sstevel@tonic-gate/* ARGSUSED */ 16257c478bd9Sstevel@tonic-gatevoid 16267c478bd9Sstevel@tonic-gateclearphys(uint64_t paddr, int ecache_size, int ecache_linesize) 16277c478bd9Sstevel@tonic-gate{ 16287c478bd9Sstevel@tonic-gate} 16297c478bd9Sstevel@tonic-gate 16307c478bd9Sstevel@tonic-gate#else /* lint */ 16317c478bd9Sstevel@tonic-gate 16327c478bd9Sstevel@tonic-gate ENTRY(clearphys) 16337c478bd9Sstevel@tonic-gate or %o2, %g0, %o3 ! ecache linesize 16347c478bd9Sstevel@tonic-gate or %o1, %g0, %o2 ! ecache size 16357c478bd9Sstevel@tonic-gate#ifndef HUMMINGBIRD 16367c478bd9Sstevel@tonic-gate or %o3, %g0, %o4 ! save ecache linesize 16377c478bd9Sstevel@tonic-gate xor %o0, %o2, %o1 ! calculate alias address 16387c478bd9Sstevel@tonic-gate add %o2, %o2, %o3 ! 2 * ecachesize 16397c478bd9Sstevel@tonic-gate sub %o3, 1, %o3 ! -1 == mask 16407c478bd9Sstevel@tonic-gate and %o1, %o3, %o1 ! and with xor'd address 16417c478bd9Sstevel@tonic-gate set ecache_flushaddr, %o3 16427c478bd9Sstevel@tonic-gate ldx [%o3], %o3 16437c478bd9Sstevel@tonic-gate or %o4, %g0, %o2 ! saved ecache linesize 16447c478bd9Sstevel@tonic-gate 16457c478bd9Sstevel@tonic-gate rdpr %pstate, %o4 16467c478bd9Sstevel@tonic-gate andn %o4, PSTATE_IE | PSTATE_AM, %o5 16477c478bd9Sstevel@tonic-gate wrpr %o5, %g0, %pstate ! clear IE, AM bits 16487c478bd9Sstevel@tonic-gate 16497c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_ESTATE_ERR, %g1 16507c478bd9Sstevel@tonic-gate stxa %g0, [%g0]ASI_ESTATE_ERR ! disable errors 16517c478bd9Sstevel@tonic-gate membar #Sync 16527c478bd9Sstevel@tonic-gate 16537c478bd9Sstevel@tonic-gate ! need to put zeros in the cache line before displacing it 16547c478bd9Sstevel@tonic-gate 16557c478bd9Sstevel@tonic-gate sub %o2, 8, %o2 ! get offset of last double word in ecache line 16567c478bd9Sstevel@tonic-gate1: 16577c478bd9Sstevel@tonic-gate stxa %g0, [%o0 + %o2]ASI_MEM ! put zeros in the ecache line 16587c478bd9Sstevel@tonic-gate sub %o2, 8, %o2 16597c478bd9Sstevel@tonic-gate brgez,a,pt %o2, 1b 16607c478bd9Sstevel@tonic-gate nop 16617c478bd9Sstevel@tonic-gate ldxa [%o1 + %o3]ASI_MEM, %g0 ! load ecache_flushaddr + alias 16627c478bd9Sstevel@tonic-gate casxa [%o0]ASI_MEM, %g0, %g0 16637c478bd9Sstevel@tonic-gate ldxa [%o1 + %o3]ASI_MEM, %g0 ! load ecache_flushaddr + alias 16647c478bd9Sstevel@tonic-gate 16657c478bd9Sstevel@tonic-gate stxa %g1, [%g0]ASI_ESTATE_ERR ! restore error enable 16667c478bd9Sstevel@tonic-gate membar #Sync 16677c478bd9Sstevel@tonic-gate 16687c478bd9Sstevel@tonic-gate#else /* HUMMINGBIRD... */ 16697c478bd9Sstevel@tonic-gate /* 16707c478bd9Sstevel@tonic-gate * UltraSPARC-IIe processor supports both 4-way set associative 16717c478bd9Sstevel@tonic-gate * and direct map E$. We need to reconfigure E$ to direct map 16727c478bd9Sstevel@tonic-gate * mode for data load/store before displacement flush. Also, we 16737c478bd9Sstevel@tonic-gate * need to flush all 4 sets of the E$ to ensure that the physaddr 16747c478bd9Sstevel@tonic-gate * has been flushed. Keep the interrupts disabled while flushing 16757c478bd9Sstevel@tonic-gate * E$ in this manner. 16767c478bd9Sstevel@tonic-gate * 16777c478bd9Sstevel@tonic-gate * For flushing a specific physical address, we start at the 16787c478bd9Sstevel@tonic-gate * aliased address and load at set-size stride, wrapping around 16797c478bd9Sstevel@tonic-gate * at 2*ecache-size boundary and skipping fault physical address. 16807c478bd9Sstevel@tonic-gate * It takes 10 loads to guarantee that the physical address has 16817c478bd9Sstevel@tonic-gate * been flushed. 16827c478bd9Sstevel@tonic-gate * 16837c478bd9Sstevel@tonic-gate * Usage: 16847c478bd9Sstevel@tonic-gate * %o0 physaddr 16857c478bd9Sstevel@tonic-gate * %o5 physaddr - ecache_flushaddr 16867c478bd9Sstevel@tonic-gate * %g1 UPA config (restored later) 16877c478bd9Sstevel@tonic-gate * %g2 E$ set size 16887c478bd9Sstevel@tonic-gate * %g3 E$ flush address range mask (i.e. 2 * E$ -1) 16897c478bd9Sstevel@tonic-gate * %g4 #loads to flush phys address 16907c478bd9Sstevel@tonic-gate * %g5 temp 16917c478bd9Sstevel@tonic-gate */ 16927c478bd9Sstevel@tonic-gate 16937c478bd9Sstevel@tonic-gate or %o3, %g0, %o4 ! save ecache linesize 16947c478bd9Sstevel@tonic-gate sethi %hi(ecache_associativity), %g5 16957c478bd9Sstevel@tonic-gate ld [%g5 + %lo(ecache_associativity)], %g5 16967c478bd9Sstevel@tonic-gate udivx %o2, %g5, %g2 ! set size (i.e. ecache_size/#sets) 16977c478bd9Sstevel@tonic-gate 16987c478bd9Sstevel@tonic-gate xor %o0, %o2, %o1 ! calculate alias address 16997c478bd9Sstevel@tonic-gate add %o2, %o2, %g3 ! 2 * ecachesize 17007c478bd9Sstevel@tonic-gate sub %g3, 1, %g3 ! 2 * ecachesize -1 == mask 17017c478bd9Sstevel@tonic-gate and %o1, %g3, %o1 ! and with xor'd address 17027c478bd9Sstevel@tonic-gate sethi %hi(ecache_flushaddr), %o3 17037c478bd9Sstevel@tonic-gate ldx [%o3 +%lo(ecache_flushaddr)], %o3 17047c478bd9Sstevel@tonic-gate or %o4, %g0, %o2 ! saved ecache linesize 17057c478bd9Sstevel@tonic-gate 17067c478bd9Sstevel@tonic-gate rdpr %pstate, %o4 17077c478bd9Sstevel@tonic-gate andn %o4, PSTATE_IE | PSTATE_AM, %o5 17087c478bd9Sstevel@tonic-gate wrpr %o5, %g0, %pstate ! clear IE, AM bits 17097c478bd9Sstevel@tonic-gate 17107c478bd9Sstevel@tonic-gate ! Place E$ in direct map mode for data access 17117c478bd9Sstevel@tonic-gate or %g0, 1, %g5 17127c478bd9Sstevel@tonic-gate sllx %g5, HB_UPA_DMAP_DATA_BIT, %g5 17137c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_UPA_CONFIG, %g1 ! current UPA config (restored later) 17147c478bd9Sstevel@tonic-gate or %g1, %g5, %g5 17157c478bd9Sstevel@tonic-gate membar #Sync 17167c478bd9Sstevel@tonic-gate stxa %g5, [%g0]ASI_UPA_CONFIG ! enable direct map for data access 17177c478bd9Sstevel@tonic-gate membar #Sync 17187c478bd9Sstevel@tonic-gate 17197c478bd9Sstevel@tonic-gate ! need to put zeros in the cache line before displacing it 17207c478bd9Sstevel@tonic-gate 17217c478bd9Sstevel@tonic-gate sub %o2, 8, %o2 ! get offset of last double word in ecache line 17227c478bd9Sstevel@tonic-gate1: 17237c478bd9Sstevel@tonic-gate stxa %g0, [%o0 + %o2]ASI_MEM ! put zeros in the ecache line 17247c478bd9Sstevel@tonic-gate sub %o2, 8, %o2 17257c478bd9Sstevel@tonic-gate brgez,a,pt %o2, 1b 17267c478bd9Sstevel@tonic-gate nop 17277c478bd9Sstevel@tonic-gate 17287c478bd9Sstevel@tonic-gate ! Displace cache line from each set of E$ starting at the 17297c478bd9Sstevel@tonic-gate ! aliased address. at set-size stride, wrapping at 2*ecache_size 17307c478bd9Sstevel@tonic-gate ! and skipping load from physaddr. We need 10 loads to flush the 17317c478bd9Sstevel@tonic-gate ! physaddr from E$. 17327c478bd9Sstevel@tonic-gate mov HB_PHYS_FLUSH_CNT-1, %g4 ! #loads to flush phys addr 17337c478bd9Sstevel@tonic-gate sub %o0, %o3, %o5 ! physaddr - ecache_flushaddr 17347c478bd9Sstevel@tonic-gate or %o1, %g0, %g5 ! starting offset 17357c478bd9Sstevel@tonic-gate2: 17367c478bd9Sstevel@tonic-gate ldxa [%g5 + %o3]ASI_MEM, %g0 ! load ecache_flushaddr + alias 17377c478bd9Sstevel@tonic-gate3: 17387c478bd9Sstevel@tonic-gate add %g5, %g2, %g5 ! calculate offset in next set 17397c478bd9Sstevel@tonic-gate and %g5, %g3, %g5 ! force offset within aliased range 17407c478bd9Sstevel@tonic-gate cmp %g5, %o5 ! skip loads from physaddr 17417c478bd9Sstevel@tonic-gate be,pn %ncc, 3b 17427c478bd9Sstevel@tonic-gate nop 17437c478bd9Sstevel@tonic-gate brgz,pt %g4, 2b 17447c478bd9Sstevel@tonic-gate dec %g4 17457c478bd9Sstevel@tonic-gate 17467c478bd9Sstevel@tonic-gate casxa [%o0]ASI_MEM, %g0, %g0 17477c478bd9Sstevel@tonic-gate 17487c478bd9Sstevel@tonic-gate ! Flush %o0 from ecahe again. 17497c478bd9Sstevel@tonic-gate ! Need single displacement flush at offset %o1 this time as 17507c478bd9Sstevel@tonic-gate ! the E$ is already in direct map mode. 17517c478bd9Sstevel@tonic-gate ldxa [%o1 + %o3]ASI_MEM, %g0 ! load ecache_flushaddr + alias 17527c478bd9Sstevel@tonic-gate 17537c478bd9Sstevel@tonic-gate membar #Sync 17547c478bd9Sstevel@tonic-gate stxa %g1, [%g0]ASI_UPA_CONFIG ! restore UPA config (DM bits) 17557c478bd9Sstevel@tonic-gate membar #Sync 17567c478bd9Sstevel@tonic-gate#endif /* HUMMINGBIRD... */ 17577c478bd9Sstevel@tonic-gate 17587c478bd9Sstevel@tonic-gate retl 17597c478bd9Sstevel@tonic-gate wrpr %g0, %o4, %pstate ! restore earlier pstate register value 17607c478bd9Sstevel@tonic-gate SET_SIZE(clearphys) 17617c478bd9Sstevel@tonic-gate 17627c478bd9Sstevel@tonic-gate#endif /* lint */ 17637c478bd9Sstevel@tonic-gate 17647c478bd9Sstevel@tonic-gate#if defined(lint) 17657c478bd9Sstevel@tonic-gate/* ARGSUSED */ 17667c478bd9Sstevel@tonic-gatevoid 17677c478bd9Sstevel@tonic-gateflushecacheline(uint64_t paddr, int ecache_size) 17687c478bd9Sstevel@tonic-gate{ 17697c478bd9Sstevel@tonic-gate} 17707c478bd9Sstevel@tonic-gate 17717c478bd9Sstevel@tonic-gate#else /* lint */ 17727c478bd9Sstevel@tonic-gate/* 17737c478bd9Sstevel@tonic-gate * flushecacheline - This is a simpler version of scrubphys 17747c478bd9Sstevel@tonic-gate * which simply does a displacement flush of the line in 17757c478bd9Sstevel@tonic-gate * question. This routine is mainly used in handling async 17767c478bd9Sstevel@tonic-gate * errors where we want to get rid of a bad line in ecache. 17777c478bd9Sstevel@tonic-gate * Note that if the line is modified and it has suffered 17787c478bd9Sstevel@tonic-gate * data corruption - we are guarantee that the hw will write 17797c478bd9Sstevel@tonic-gate * a UE back to mark the page poisoned. 17807c478bd9Sstevel@tonic-gate */ 17817c478bd9Sstevel@tonic-gate ENTRY(flushecacheline) 17827c478bd9Sstevel@tonic-gate or %o1, %g0, %o2 ! put ecache size in %o2 17837c478bd9Sstevel@tonic-gate#ifndef HUMMINGBIRD 17847c478bd9Sstevel@tonic-gate xor %o0, %o2, %o1 ! calculate alias address 17857c478bd9Sstevel@tonic-gate add %o2, %o2, %o3 ! 2 * ecachesize in case 17867c478bd9Sstevel@tonic-gate ! addr == ecache_flushaddr 17877c478bd9Sstevel@tonic-gate sub %o3, 1, %o3 ! -1 == mask 17887c478bd9Sstevel@tonic-gate and %o1, %o3, %o1 ! and with xor'd address 17897c478bd9Sstevel@tonic-gate set ecache_flushaddr, %o3 17907c478bd9Sstevel@tonic-gate ldx [%o3], %o3 17917c478bd9Sstevel@tonic-gate 17927c478bd9Sstevel@tonic-gate rdpr %pstate, %o4 17937c478bd9Sstevel@tonic-gate andn %o4, PSTATE_IE | PSTATE_AM, %o5 17947c478bd9Sstevel@tonic-gate wrpr %o5, %g0, %pstate ! clear IE, AM bits 17957c478bd9Sstevel@tonic-gate 17967c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_ESTATE_ERR, %g1 17977c478bd9Sstevel@tonic-gate stxa %g0, [%g0]ASI_ESTATE_ERR ! disable errors 17987c478bd9Sstevel@tonic-gate membar #Sync 17997c478bd9Sstevel@tonic-gate 18007c478bd9Sstevel@tonic-gate ldxa [%o1 + %o3]ASI_MEM, %g0 ! load ecache_flushaddr + alias 18017c478bd9Sstevel@tonic-gate membar #Sync 18027c478bd9Sstevel@tonic-gate stxa %g1, [%g0]ASI_ESTATE_ERR ! restore error enable 18037c478bd9Sstevel@tonic-gate membar #Sync 18047c478bd9Sstevel@tonic-gate#else /* HUMMINGBIRD */ 18057c478bd9Sstevel@tonic-gate /* 18067c478bd9Sstevel@tonic-gate * UltraSPARC-IIe processor supports both 4-way set associative 18077c478bd9Sstevel@tonic-gate * and direct map E$. We need to reconfigure E$ to direct map 18087c478bd9Sstevel@tonic-gate * mode for data load/store before displacement flush. Also, we 18097c478bd9Sstevel@tonic-gate * need to flush all 4 sets of the E$ to ensure that the physaddr 18107c478bd9Sstevel@tonic-gate * has been flushed. Keep the interrupts disabled while flushing 18117c478bd9Sstevel@tonic-gate * E$ in this manner. 18127c478bd9Sstevel@tonic-gate * 18137c478bd9Sstevel@tonic-gate * For flushing a specific physical address, we start at the 18147c478bd9Sstevel@tonic-gate * aliased address and load at set-size stride, wrapping around 18157c478bd9Sstevel@tonic-gate * at 2*ecache-size boundary and skipping fault physical address. 18167c478bd9Sstevel@tonic-gate * It takes 10 loads to guarantee that the physical address has 18177c478bd9Sstevel@tonic-gate * been flushed. 18187c478bd9Sstevel@tonic-gate * 18197c478bd9Sstevel@tonic-gate * Usage: 18207c478bd9Sstevel@tonic-gate * %o0 physaddr 18217c478bd9Sstevel@tonic-gate * %o5 physaddr - ecache_flushaddr 18227c478bd9Sstevel@tonic-gate * %g1 error enable register 18237c478bd9Sstevel@tonic-gate * %g2 E$ set size 18247c478bd9Sstevel@tonic-gate * %g3 E$ flush address range mask (i.e. 2 * E$ -1) 18257c478bd9Sstevel@tonic-gate * %g4 UPA config (restored later) 18267c478bd9Sstevel@tonic-gate * %g5 temp 18277c478bd9Sstevel@tonic-gate */ 18287c478bd9Sstevel@tonic-gate 18297c478bd9Sstevel@tonic-gate sethi %hi(ecache_associativity), %g5 18307c478bd9Sstevel@tonic-gate ld [%g5 + %lo(ecache_associativity)], %g5 18317c478bd9Sstevel@tonic-gate udivx %o2, %g5, %g2 ! set size (i.e. ecache_size/#sets) 18327c478bd9Sstevel@tonic-gate xor %o0, %o2, %o1 ! calculate alias address 18337c478bd9Sstevel@tonic-gate add %o2, %o2, %g3 ! 2 * ecachesize in case 18347c478bd9Sstevel@tonic-gate ! addr == ecache_flushaddr 18357c478bd9Sstevel@tonic-gate sub %g3, 1, %g3 ! 2 * ecachesize -1 == mask 18367c478bd9Sstevel@tonic-gate and %o1, %g3, %o1 ! and with xor'd address 18377c478bd9Sstevel@tonic-gate sethi %hi(ecache_flushaddr), %o3 18387c478bd9Sstevel@tonic-gate ldx [%o3 + %lo(ecache_flushaddr)], %o3 18397c478bd9Sstevel@tonic-gate 18407c478bd9Sstevel@tonic-gate rdpr %pstate, %o4 18417c478bd9Sstevel@tonic-gate andn %o4, PSTATE_IE | PSTATE_AM, %o5 18427c478bd9Sstevel@tonic-gate wrpr %o5, %g0, %pstate ! clear IE, AM bits 18437c478bd9Sstevel@tonic-gate 18447c478bd9Sstevel@tonic-gate ! Place E$ in direct map mode for data access 18457c478bd9Sstevel@tonic-gate or %g0, 1, %g5 18467c478bd9Sstevel@tonic-gate sllx %g5, HB_UPA_DMAP_DATA_BIT, %g5 18477c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_UPA_CONFIG, %g4 ! current UPA config (restored later) 18487c478bd9Sstevel@tonic-gate or %g4, %g5, %g5 18497c478bd9Sstevel@tonic-gate membar #Sync 18507c478bd9Sstevel@tonic-gate stxa %g5, [%g0]ASI_UPA_CONFIG ! enable direct map for data access 18517c478bd9Sstevel@tonic-gate membar #Sync 18527c478bd9Sstevel@tonic-gate 18537c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_ESTATE_ERR, %g1 18547c478bd9Sstevel@tonic-gate stxa %g0, [%g0]ASI_ESTATE_ERR ! disable errors 18557c478bd9Sstevel@tonic-gate membar #Sync 18567c478bd9Sstevel@tonic-gate 18577c478bd9Sstevel@tonic-gate ! Displace cache line from each set of E$ starting at the 18587c478bd9Sstevel@tonic-gate ! aliased address. at set-size stride, wrapping at 2*ecache_size 18597c478bd9Sstevel@tonic-gate ! and skipping load from physaddr. We need 10 loads to flush the 18607c478bd9Sstevel@tonic-gate ! physaddr from E$. 18617c478bd9Sstevel@tonic-gate mov HB_PHYS_FLUSH_CNT-1, %g5 ! #loads to flush physaddr 18627c478bd9Sstevel@tonic-gate sub %o0, %o3, %o5 ! physaddr - ecache_flushaddr 18637c478bd9Sstevel@tonic-gate2: 18647c478bd9Sstevel@tonic-gate ldxa [%o1 + %o3]ASI_MEM, %g0 ! load ecache_flushaddr + alias 18657c478bd9Sstevel@tonic-gate3: 18667c478bd9Sstevel@tonic-gate add %o1, %g2, %o1 ! calculate offset in next set 18677c478bd9Sstevel@tonic-gate and %o1, %g3, %o1 ! force offset within aliased range 18687c478bd9Sstevel@tonic-gate cmp %o1, %o5 ! skip loads from physaddr 18697c478bd9Sstevel@tonic-gate be,pn %ncc, 3b 18707c478bd9Sstevel@tonic-gate nop 18717c478bd9Sstevel@tonic-gate brgz,pt %g5, 2b 18727c478bd9Sstevel@tonic-gate dec %g5 18737c478bd9Sstevel@tonic-gate 18747c478bd9Sstevel@tonic-gate membar #Sync 18757c478bd9Sstevel@tonic-gate stxa %g1, [%g0]ASI_ESTATE_ERR ! restore error enable 18767c478bd9Sstevel@tonic-gate membar #Sync 18777c478bd9Sstevel@tonic-gate 18787c478bd9Sstevel@tonic-gate stxa %g4, [%g0]ASI_UPA_CONFIG ! restore UPA config (DM bits) 18797c478bd9Sstevel@tonic-gate membar #Sync 18807c478bd9Sstevel@tonic-gate#endif /* HUMMINGBIRD */ 18817c478bd9Sstevel@tonic-gate retl 18827c478bd9Sstevel@tonic-gate wrpr %g0, %o4, %pstate 18837c478bd9Sstevel@tonic-gate SET_SIZE(flushecacheline) 18847c478bd9Sstevel@tonic-gate 18857c478bd9Sstevel@tonic-gate#endif /* lint */ 18867c478bd9Sstevel@tonic-gate 18877c478bd9Sstevel@tonic-gate#if defined(lint) 18887c478bd9Sstevel@tonic-gate/* ARGSUSED */ 18897c478bd9Sstevel@tonic-gatevoid 18907c478bd9Sstevel@tonic-gateecache_scrubreq_tl1(uint64_t inum, uint64_t dummy) 18917c478bd9Sstevel@tonic-gate{ 18927c478bd9Sstevel@tonic-gate} 18937c478bd9Sstevel@tonic-gate 18947c478bd9Sstevel@tonic-gate#else /* lint */ 18957c478bd9Sstevel@tonic-gate/* 18967c478bd9Sstevel@tonic-gate * ecache_scrubreq_tl1 is the crosstrap handler called at ecache_calls_a_sec Hz 18977c478bd9Sstevel@tonic-gate * from the clock CPU. It atomically increments the outstanding request 18987c478bd9Sstevel@tonic-gate * counter and, if there was not already an outstanding request, 1899b0fc0e77Sgovinda * branches to setsoftint_tl1 to enqueue an intr_vec for the given inum. 19007c478bd9Sstevel@tonic-gate */ 19017c478bd9Sstevel@tonic-gate 19027c478bd9Sstevel@tonic-gate ! Register usage: 19037c478bd9Sstevel@tonic-gate ! 19047c478bd9Sstevel@tonic-gate ! Arguments: 19057c478bd9Sstevel@tonic-gate ! %g1 - inum 19067c478bd9Sstevel@tonic-gate ! 19077c478bd9Sstevel@tonic-gate ! Internal: 19087c478bd9Sstevel@tonic-gate ! %g2, %g3, %g5 - scratch 19097c478bd9Sstevel@tonic-gate ! %g4 - ptr. to spitfire_scrub_misc ec_scrub_outstanding. 19107c478bd9Sstevel@tonic-gate ! %g6 - setsoftint_tl1 address 19117c478bd9Sstevel@tonic-gate 19127c478bd9Sstevel@tonic-gate ENTRY_NP(ecache_scrubreq_tl1) 19137c478bd9Sstevel@tonic-gate set SFPR_SCRUB_MISC + EC_SCRUB_OUTSTANDING, %g2 19147c478bd9Sstevel@tonic-gate GET_CPU_PRIVATE_PTR(%g2, %g4, %g5, 1f); 19157c478bd9Sstevel@tonic-gate ld [%g4], %g2 ! cpu's ec_scrub_outstanding. 19167c478bd9Sstevel@tonic-gate set setsoftint_tl1, %g6 19177c478bd9Sstevel@tonic-gate ! 19187c478bd9Sstevel@tonic-gate ! no need to use atomic instructions for the following 19197c478bd9Sstevel@tonic-gate ! increment - we're at tl1 19207c478bd9Sstevel@tonic-gate ! 19217c478bd9Sstevel@tonic-gate add %g2, 0x1, %g3 1922b0fc0e77Sgovinda brnz,pn %g2, 1f ! no need to enqueue more intr_vec 19237c478bd9Sstevel@tonic-gate st %g3, [%g4] ! delay - store incremented counter 1924b0fc0e77Sgovinda jmp %g6 ! setsoftint_tl1(%g1) - queue intr_vec 19257c478bd9Sstevel@tonic-gate nop 19267c478bd9Sstevel@tonic-gate ! not reached 19277c478bd9Sstevel@tonic-gate1: 19287c478bd9Sstevel@tonic-gate retry 19297c478bd9Sstevel@tonic-gate SET_SIZE(ecache_scrubreq_tl1) 19307c478bd9Sstevel@tonic-gate 19317c478bd9Sstevel@tonic-gate#endif /* lint */ 19327c478bd9Sstevel@tonic-gate 19337c478bd9Sstevel@tonic-gate#if defined(lint) 19347c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 19357c478bd9Sstevel@tonic-gatevoid 19367c478bd9Sstevel@tonic-gatewrite_ec_tag_parity(uint32_t id) 19377c478bd9Sstevel@tonic-gate{} 19387c478bd9Sstevel@tonic-gate#else /* lint */ 19397c478bd9Sstevel@tonic-gate 19407c478bd9Sstevel@tonic-gate /* 19417c478bd9Sstevel@tonic-gate * write_ec_tag_parity(), which zero's the ecache tag, 19427c478bd9Sstevel@tonic-gate * marks the state as invalid and writes good parity to the tag. 19437c478bd9Sstevel@tonic-gate * Input %o1= 32 bit E$ index 19447c478bd9Sstevel@tonic-gate */ 19457c478bd9Sstevel@tonic-gate ENTRY(write_ec_tag_parity) 19467c478bd9Sstevel@tonic-gate or %g0, 1, %o4 19477c478bd9Sstevel@tonic-gate sllx %o4, 39, %o4 ! set bit 40 for e$ tag access 19487c478bd9Sstevel@tonic-gate or %o0, %o4, %o4 ! %o4 = ecache addr for tag write 19497c478bd9Sstevel@tonic-gate 19507c478bd9Sstevel@tonic-gate rdpr %pstate, %o5 19517c478bd9Sstevel@tonic-gate andn %o5, PSTATE_IE | PSTATE_AM, %o1 19527c478bd9Sstevel@tonic-gate wrpr %o1, %g0, %pstate ! clear IE, AM bits 19537c478bd9Sstevel@tonic-gate 19547c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_ESTATE_ERR, %g1 19557c478bd9Sstevel@tonic-gate stxa %g0, [%g0]ASI_ESTATE_ERR ! Turn off Error enable 19567c478bd9Sstevel@tonic-gate membar #Sync 19577c478bd9Sstevel@tonic-gate 19587c478bd9Sstevel@tonic-gate ba 1f 19597c478bd9Sstevel@tonic-gate nop 19607c478bd9Sstevel@tonic-gate /* 19617c478bd9Sstevel@tonic-gate * Align on the ecache boundary in order to force 19627c478bd9Sstevel@tonic-gate * ciritical code section onto the same ecache line. 19637c478bd9Sstevel@tonic-gate */ 19647c478bd9Sstevel@tonic-gate .align 64 19657c478bd9Sstevel@tonic-gate 19667c478bd9Sstevel@tonic-gate1: 19677c478bd9Sstevel@tonic-gate set S_EC_PARITY, %o3 ! clear tag, state invalid 19687c478bd9Sstevel@tonic-gate sllx %o3, S_ECPAR_SHIFT, %o3 ! and with good tag parity 19697c478bd9Sstevel@tonic-gate stxa %o3, [%g0]ASI_EC_DIAG ! update with the above info 19707c478bd9Sstevel@tonic-gate stxa %g0, [%o4]ASI_EC_W 19717c478bd9Sstevel@tonic-gate membar #Sync 19727c478bd9Sstevel@tonic-gate 19737c478bd9Sstevel@tonic-gate stxa %g1, [%g0]ASI_ESTATE_ERR ! Turn error enable back on 19747c478bd9Sstevel@tonic-gate membar #Sync 19757c478bd9Sstevel@tonic-gate retl 19767c478bd9Sstevel@tonic-gate wrpr %g0, %o5, %pstate 19777c478bd9Sstevel@tonic-gate SET_SIZE(write_ec_tag_parity) 19787c478bd9Sstevel@tonic-gate 19797c478bd9Sstevel@tonic-gate#endif /* lint */ 19807c478bd9Sstevel@tonic-gate 19817c478bd9Sstevel@tonic-gate#if defined(lint) 19827c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 19837c478bd9Sstevel@tonic-gatevoid 19847c478bd9Sstevel@tonic-gatewrite_hb_ec_tag_parity(uint32_t id) 19857c478bd9Sstevel@tonic-gate{} 19867c478bd9Sstevel@tonic-gate#else /* lint */ 19877c478bd9Sstevel@tonic-gate 19887c478bd9Sstevel@tonic-gate /* 19897c478bd9Sstevel@tonic-gate * write_hb_ec_tag_parity(), which zero's the ecache tag, 19907c478bd9Sstevel@tonic-gate * marks the state as invalid and writes good parity to the tag. 19917c478bd9Sstevel@tonic-gate * Input %o1= 32 bit E$ index 19927c478bd9Sstevel@tonic-gate */ 19937c478bd9Sstevel@tonic-gate ENTRY(write_hb_ec_tag_parity) 19947c478bd9Sstevel@tonic-gate or %g0, 1, %o4 19957c478bd9Sstevel@tonic-gate sllx %o4, 39, %o4 ! set bit 40 for e$ tag access 19967c478bd9Sstevel@tonic-gate or %o0, %o4, %o4 ! %o4 = ecache addr for tag write 19977c478bd9Sstevel@tonic-gate 19987c478bd9Sstevel@tonic-gate rdpr %pstate, %o5 19997c478bd9Sstevel@tonic-gate andn %o5, PSTATE_IE | PSTATE_AM, %o1 20007c478bd9Sstevel@tonic-gate wrpr %o1, %g0, %pstate ! clear IE, AM bits 20017c478bd9Sstevel@tonic-gate 20027c478bd9Sstevel@tonic-gate ldxa [%g0]ASI_ESTATE_ERR, %g1 20037c478bd9Sstevel@tonic-gate stxa %g0, [%g0]ASI_ESTATE_ERR ! Turn off Error enable 20047c478bd9Sstevel@tonic-gate membar #Sync 20057c478bd9Sstevel@tonic-gate 20067c478bd9Sstevel@tonic-gate ba 1f 20077c478bd9Sstevel@tonic-gate nop 20087c478bd9Sstevel@tonic-gate /* 20097c478bd9Sstevel@tonic-gate * Align on the ecache boundary in order to force 20107c478bd9Sstevel@tonic-gate * ciritical code section onto the same ecache line. 20117c478bd9Sstevel@tonic-gate */ 20127c478bd9Sstevel@tonic-gate .align 64 20137c478bd9Sstevel@tonic-gate1: 20147c478bd9Sstevel@tonic-gate#ifdef HUMMINGBIRD 20157c478bd9Sstevel@tonic-gate set HB_EC_PARITY, %o3 ! clear tag, state invalid 20167c478bd9Sstevel@tonic-gate sllx %o3, HB_ECPAR_SHIFT, %o3 ! and with good tag parity 20177c478bd9Sstevel@tonic-gate#else /* !HUMMINGBIRD */ 20187c478bd9Sstevel@tonic-gate set SB_EC_PARITY, %o3 ! clear tag, state invalid 20197c478bd9Sstevel@tonic-gate sllx %o3, SB_ECPAR_SHIFT, %o3 ! and with good tag parity 20207c478bd9Sstevel@tonic-gate#endif /* !HUMMINGBIRD */ 20217c478bd9Sstevel@tonic-gate 20227c478bd9Sstevel@tonic-gate stxa %o3, [%g0]ASI_EC_DIAG ! update with the above info 20237c478bd9Sstevel@tonic-gate stxa %g0, [%o4]ASI_EC_W 20247c478bd9Sstevel@tonic-gate membar #Sync 20257c478bd9Sstevel@tonic-gate 20267c478bd9Sstevel@tonic-gate stxa %g1, [%g0]ASI_ESTATE_ERR ! Turn error enable back on 20277c478bd9Sstevel@tonic-gate membar #Sync 20287c478bd9Sstevel@tonic-gate retl 20297c478bd9Sstevel@tonic-gate wrpr %g0, %o5, %pstate 20307c478bd9Sstevel@tonic-gate SET_SIZE(write_hb_ec_tag_parity) 20317c478bd9Sstevel@tonic-gate 20327c478bd9Sstevel@tonic-gate#endif /* lint */ 20337c478bd9Sstevel@tonic-gate 20347c478bd9Sstevel@tonic-gate#define VIS_BLOCKSIZE 64 20357c478bd9Sstevel@tonic-gate 20367c478bd9Sstevel@tonic-gate#if defined(lint) 20377c478bd9Sstevel@tonic-gate 20387c478bd9Sstevel@tonic-gate/*ARGSUSED*/ 20397c478bd9Sstevel@tonic-gateint 20407c478bd9Sstevel@tonic-gatedtrace_blksuword32(uintptr_t addr, uint32_t *data, int tryagain) 20417c478bd9Sstevel@tonic-gate{ return (0); } 20427c478bd9Sstevel@tonic-gate 20437c478bd9Sstevel@tonic-gate#else 20447c478bd9Sstevel@tonic-gate 20457c478bd9Sstevel@tonic-gate ENTRY(dtrace_blksuword32) 20467c478bd9Sstevel@tonic-gate save %sp, -SA(MINFRAME + 4), %sp 20477c478bd9Sstevel@tonic-gate 20487c478bd9Sstevel@tonic-gate rdpr %pstate, %l1 20497c478bd9Sstevel@tonic-gate andn %l1, PSTATE_IE, %l2 ! disable interrupts to 20507c478bd9Sstevel@tonic-gate wrpr %g0, %l2, %pstate ! protect our FPU diddling 20517c478bd9Sstevel@tonic-gate 20527c478bd9Sstevel@tonic-gate rd %fprs, %l0 20537c478bd9Sstevel@tonic-gate andcc %l0, FPRS_FEF, %g0 20547c478bd9Sstevel@tonic-gate bz,a,pt %xcc, 1f ! if the fpu is disabled 20557c478bd9Sstevel@tonic-gate wr %g0, FPRS_FEF, %fprs ! ... enable the fpu 20567c478bd9Sstevel@tonic-gate 20577c478bd9Sstevel@tonic-gate st %f0, [%fp + STACK_BIAS - 4] ! save %f0 to the stack 20587c478bd9Sstevel@tonic-gate1: 20597c478bd9Sstevel@tonic-gate set 0f, %l5 20607c478bd9Sstevel@tonic-gate /* 20617c478bd9Sstevel@tonic-gate * We're about to write a block full or either total garbage 20627c478bd9Sstevel@tonic-gate * (not kernel data, don't worry) or user floating-point data 20637c478bd9Sstevel@tonic-gate * (so it only _looks_ like garbage). 20647c478bd9Sstevel@tonic-gate */ 20657c478bd9Sstevel@tonic-gate ld [%i1], %f0 ! modify the block 20667c478bd9Sstevel@tonic-gate membar #Sync 20677c478bd9Sstevel@tonic-gate stn %l5, [THREAD_REG + T_LOFAULT] ! set up the lofault handler 20687c478bd9Sstevel@tonic-gate stda %d0, [%i0]ASI_BLK_COMMIT_S ! store the modified block 20697c478bd9Sstevel@tonic-gate membar #Sync 20707c478bd9Sstevel@tonic-gate stn %g0, [THREAD_REG + T_LOFAULT] ! remove the lofault handler 20717c478bd9Sstevel@tonic-gate 20727c478bd9Sstevel@tonic-gate bz,a,pt %xcc, 1f 20737c478bd9Sstevel@tonic-gate wr %g0, %l0, %fprs ! restore %fprs 20747c478bd9Sstevel@tonic-gate 20757c478bd9Sstevel@tonic-gate ld [%fp + STACK_BIAS - 4], %f0 ! restore %f0 20767c478bd9Sstevel@tonic-gate1: 20777c478bd9Sstevel@tonic-gate 20787c478bd9Sstevel@tonic-gate wrpr %g0, %l1, %pstate ! restore interrupts 20797c478bd9Sstevel@tonic-gate 20807c478bd9Sstevel@tonic-gate ret 20817c478bd9Sstevel@tonic-gate restore %g0, %g0, %o0 20827c478bd9Sstevel@tonic-gate 20837c478bd9Sstevel@tonic-gate0: 20847c478bd9Sstevel@tonic-gate membar #Sync 20857c478bd9Sstevel@tonic-gate stn %g0, [THREAD_REG + T_LOFAULT] ! remove the lofault handler 20867c478bd9Sstevel@tonic-gate 20877c478bd9Sstevel@tonic-gate bz,a,pt %xcc, 1f 20887c478bd9Sstevel@tonic-gate wr %g0, %l0, %fprs ! restore %fprs 20897c478bd9Sstevel@tonic-gate 20907c478bd9Sstevel@tonic-gate ld [%fp + STACK_BIAS - 4], %f0 ! restore %f0 20917c478bd9Sstevel@tonic-gate1: 20927c478bd9Sstevel@tonic-gate 20937c478bd9Sstevel@tonic-gate wrpr %g0, %l1, %pstate ! restore interrupts 20947c478bd9Sstevel@tonic-gate 20957c478bd9Sstevel@tonic-gate /* 20967c478bd9Sstevel@tonic-gate * If tryagain is set (%i2) we tail-call dtrace_blksuword32_err() 20977c478bd9Sstevel@tonic-gate * which deals with watchpoints. Otherwise, just return -1. 20987c478bd9Sstevel@tonic-gate */ 20997c478bd9Sstevel@tonic-gate brnz,pt %i2, 1f 21007c478bd9Sstevel@tonic-gate nop 21017c478bd9Sstevel@tonic-gate ret 21027c478bd9Sstevel@tonic-gate restore %g0, -1, %o0 21037c478bd9Sstevel@tonic-gate1: 21047c478bd9Sstevel@tonic-gate call dtrace_blksuword32_err 21057c478bd9Sstevel@tonic-gate restore 21067c478bd9Sstevel@tonic-gate 21077c478bd9Sstevel@tonic-gate SET_SIZE(dtrace_blksuword32) 21087c478bd9Sstevel@tonic-gate 21097c478bd9Sstevel@tonic-gate#endif /* lint */ 2110