1*03831d35Sstevel/* 2*03831d35Sstevel * CDDL HEADER START 3*03831d35Sstevel * 4*03831d35Sstevel * The contents of this file are subject to the terms of the 5*03831d35Sstevel * Common Development and Distribution License (the "License"). 6*03831d35Sstevel * You may not use this file except in compliance with the License. 7*03831d35Sstevel * 8*03831d35Sstevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*03831d35Sstevel * or http://www.opensolaris.org/os/licensing. 10*03831d35Sstevel * See the License for the specific language governing permissions 11*03831d35Sstevel * and limitations under the License. 12*03831d35Sstevel * 13*03831d35Sstevel * When distributing Covered Code, include this CDDL HEADER in each 14*03831d35Sstevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*03831d35Sstevel * If applicable, add the following below this CDDL HEADER, with the 16*03831d35Sstevel * fields enclosed by brackets "[]" replaced with your own identifying 17*03831d35Sstevel * information: Portions Copyright [yyyy] [name of copyright owner] 18*03831d35Sstevel * 19*03831d35Sstevel * CDDL HEADER END 20*03831d35Sstevel */ 21*03831d35Sstevel 22*03831d35Sstevel/* 23*03831d35Sstevel * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*03831d35Sstevel * Use is subject to license terms. 25*03831d35Sstevel */ 26*03831d35Sstevel 27*03831d35Sstevel#pragma ident "%Z%%M% %I% %E% SMI" 28*03831d35Sstevel 29*03831d35Sstevel/* 30*03831d35Sstevel * This file is through cpp before being used as 31*03831d35Sstevel * an inline. It contains support routines used 32*03831d35Sstevel * only by DR for the copy-rename sequence. 33*03831d35Sstevel */ 34*03831d35Sstevel 35*03831d35Sstevel#if defined(lint) 36*03831d35Sstevel#include <sys/types.h> 37*03831d35Sstevel#include <sys/sbd_ioctl.h> 38*03831d35Sstevel#include <sys/sbdp_priv.h> 39*03831d35Sstevel#else 40*03831d35Sstevel#include "assym.h" 41*03831d35Sstevel#endif /* lint */ 42*03831d35Sstevel 43*03831d35Sstevel#include <sys/asm_linkage.h> 44*03831d35Sstevel#include <sys/param.h> 45*03831d35Sstevel#include <sys/privregs.h> 46*03831d35Sstevel#include <sys/machasi.h> 47*03831d35Sstevel#include <sys/mmu.h> 48*03831d35Sstevel#include <sys/machthread.h> 49*03831d35Sstevel#include <sys/pte.h> 50*03831d35Sstevel#include <sys/stack.h> 51*03831d35Sstevel#include <sys/vis.h> 52*03831d35Sstevel#include <sys/param.h> 53*03831d35Sstevel#include <sys/errno.h> 54*03831d35Sstevel#include <sys/vtrace.h> 55*03831d35Sstevel#include <sys/clock.h> 56*03831d35Sstevel#include <sys/asi.h> 57*03831d35Sstevel#include <sys/fsr.h> 58*03831d35Sstevel#include <sys/cheetahregs.h> 59*03831d35Sstevel#include <sys/cheetahasm.h> 60*03831d35Sstevel 61*03831d35Sstevel#ifndef lint 62*03831d35Sstevel 63*03831d35Sstevel/* 64*03831d35Sstevel * Invalidating the E$ tags is only needed on Cheetah following 65*03831d35Sstevel * the manual displacement flush. The internal flush ASI used by 66*03831d35Sstevel * Cheetahplus, Jaguar, and Panther will invalidate the cache lines. 67*03831d35Sstevel * 68*03831d35Sstevel * arg1 = ecache_size 69*03831d35Sstevel * arg2 = ecache_linesize 70*03831d35Sstevel */ 71*03831d35Sstevel#define ECACHE_FLUSHTAGS(arg1, arg2, tmp1) \ 72*03831d35Sstevel GET_CPU_IMPL(tmp1) ;\ 73*03831d35Sstevel srlx arg1, 1, arg1 ;\ 74*03831d35Sstevel cmp tmp1, CHEETAH_IMPL ;\ 75*03831d35Sstevel bne 1f ;\ 76*03831d35Sstevel nop ;\ 77*03831d35Sstevel sub arg1, arg2, tmp1 ;\ 78*03831d35Sstevel0: ;\ 79*03831d35Sstevel stxa %g0, [tmp1]ASI_EC_DIAG ;\ 80*03831d35Sstevel membar #Sync ;\ 81*03831d35Sstevel cmp %g0, tmp1 ;\ 82*03831d35Sstevel bne,pt %icc, 0b ;\ 83*03831d35Sstevel sub tmp1, arg2, tmp1 ;\ 84*03831d35Sstevel1: 85*03831d35Sstevel 86*03831d35Sstevel 87*03831d35Sstevel#define SWITCH_STACK(estk) \ 88*03831d35Sstevel flushw ;\ 89*03831d35Sstevel sub estk, SA(KFPUSIZE+GSR_SIZE), estk ;\ 90*03831d35Sstevel andn estk, 0x3f, estk ;\ 91*03831d35Sstevel sub estk, SA(MINFRAME) + STACK_BIAS, %sp ;\ 92*03831d35Sstevel mov estk, %fp 93*03831d35Sstevel 94*03831d35Sstevel/* 95*03831d35Sstevel * Returns icache size and linesize in reg1 and reg2, respectively. 96*03831d35Sstevel * Panther has a larger icache compared to Cheetahplus and Jaguar. 97*03831d35Sstevel */ 98*03831d35Sstevel#define GET_ICACHE_PARAMS(reg1, reg2) \ 99*03831d35Sstevel GET_CPU_IMPL(reg1) ;\ 100*03831d35Sstevel cmp reg1, PANTHER_IMPL ;\ 101*03831d35Sstevel bne %xcc, 1f ;\ 102*03831d35Sstevel nop ;\ 103*03831d35Sstevel set PN_ICACHE_SIZE, reg1 ;\ 104*03831d35Sstevel set PN_ICACHE_LSIZE, reg2 ;\ 105*03831d35Sstevel ba 2f ;\ 106*03831d35Sstevel nop ;\ 107*03831d35Sstevel1: ;\ 108*03831d35Sstevel set CH_ICACHE_SIZE, reg1 ;\ 109*03831d35Sstevel set CH_ICACHE_LSIZE, reg2 ;\ 110*03831d35Sstevel2: 111*03831d35Sstevel 112*03831d35Sstevel#endif /* !lint */ 113*03831d35Sstevel 114*03831d35Sstevel#if defined(lint) 115*03831d35Sstevel 116*03831d35Sstevel/*ARGSUSED*/ 117*03831d35Sstevelvoid 118*03831d35Sstevelsbdp_shutdown_asm(sbdp_shutdown_t *shutshown) 119*03831d35Sstevel{} 120*03831d35Sstevel 121*03831d35Sstevel#else /* lint */ 122*03831d35Sstevel 123*03831d35Sstevel ENTRY_NP(sbdp_shutdown_asm) 124*03831d35Sstevel ! %o0 = address of sbdp_shutdown_t structure passed in 125*03831d35Sstevel ! 126*03831d35Sstevel ! struct sbdp_shutdown { 127*03831d35Sstevel ! uint64_t estack; -> %o0 128*03831d35Sstevel ! uint64_t flushaddr; -> %o1 129*03831d35Sstevel ! uint32_t size; -> %o2 130*03831d35Sstevel ! uint32_t linesize; -> %g1 131*03831d35Sstevel ! uint64_t physaddr; -> %o0 132*03831d35Sstevel ! } sbdp_shutdown_t; 133*03831d35Sstevel ! 134*03831d35Sstevel membar #LoadStore 135*03831d35Sstevel mov %o0, %o4 136*03831d35Sstevel ldx [%o4], %o0 137*03831d35Sstevel ldx [%o4 + 8], %o1 138*03831d35Sstevel ld [%o4 + 16], %o2 139*03831d35Sstevel ld [%o4 + 20], %g1 140*03831d35Sstevel 141*03831d35Sstevel ! 142*03831d35Sstevel ! Switch stack pointer to bbsram 143*03831d35Sstevel ! 144*03831d35Sstevel SWITCH_STACK(%o0) 145*03831d35Sstevel 146*03831d35Sstevel ldx [%o4 + 24], %o0 !save physaddr in %o0 147*03831d35Sstevel ! 148*03831d35Sstevel ! Get some globals 149*03831d35Sstevel ! 150*03831d35Sstevel ! ecache_linesize already in %g1 151*03831d35Sstevel 152*03831d35Sstevel sethi %hi(dcache_linesize), %g2 153*03831d35Sstevel ld [%g2 + %lo(dcache_linesize)], %g2 154*03831d35Sstevel 155*03831d35Sstevel sethi %hi(dcache_size), %g3 156*03831d35Sstevel ld [%g3 + %lo(dcache_size)], %g3 157*03831d35Sstevel 158*03831d35Sstevel ! 159*03831d35Sstevel ! Save the E$ size 160*03831d35Sstevel ! 161*03831d35Sstevel mov %o2, %o5 162*03831d35Sstevel ! 163*03831d35Sstevel ! Flush E$ 164*03831d35Sstevel ! 165*03831d35Sstevel rdpr %pstate, %o3 166*03831d35Sstevel andn %o3, PSTATE_IE | PSTATE_AM, %o4 167*03831d35Sstevel wrpr %g0, %o4, %pstate 168*03831d35Sstevel 169*03831d35Sstevel ! Panther needs to flush L2 before L3 cache. 170*03831d35Sstevel PN_L2_FLUSHALL(%o4, %g4, %g5) 171*03831d35Sstevel 172*03831d35Sstevel ECACHE_FLUSHALL(%o2, %g1, %o1, %o4) 173*03831d35Sstevel 174*03831d35Sstevel wrpr %g0, %o3, %pstate 175*03831d35Sstevel 176*03831d35Sstevel ! 177*03831d35Sstevel ! Invalidate the E$ tags (Cheetah only). 178*03831d35Sstevel ! 179*03831d35Sstevel ECACHE_FLUSHTAGS(%o5, %g1, %o3) 180*03831d35Sstevel 181*03831d35Sstevel ! 182*03831d35Sstevel ! %o2 & %o3 now available 183*03831d35Sstevel ! 184*03831d35Sstevel 185*03831d35Sstevel membar #Sync 186*03831d35Sstevel 187*03831d35Sstevel ! 188*03831d35Sstevel ! Flush D$ 189*03831d35Sstevel ! 190*03831d35Sstevel CH_DCACHE_FLUSHALL(%g3, %g2, %o3) 191*03831d35Sstevel 192*03831d35Sstevel ! 193*03831d35Sstevel ! Flush I$ 194*03831d35Sstevel ! 195*03831d35Sstevel GET_ICACHE_PARAMS(%g5, %g4) 196*03831d35Sstevel CH_ICACHE_FLUSHALL(%g5, %g4, %o3, %o4) 197*03831d35Sstevel 198*03831d35Sstevel membar #Sync 199*03831d35Sstevel 200*03831d35Sstevel ! 201*03831d35Sstevel ! Flush all unlocked dtlb's & itlb's 202*03831d35Sstevel ! 203*03831d35Sstevel sethi %hi(FLUSH_ADDR), %g3 204*03831d35Sstevel set DEMAP_ALL_TYPE, %g1 205*03831d35Sstevel stxa %g0, [%g1]ASI_DTLB_DEMAP 206*03831d35Sstevel stxa %g0, [%g1]ASI_ITLB_DEMAP 207*03831d35Sstevel flush %g3 208*03831d35Sstevel 209*03831d35Sstevel sir 0 210*03831d35Sstevel SET_SIZE(sbdp_shutdown_asm) 211*03831d35Sstevel 212*03831d35Sstevel .global sbdp_shutdown_asm_end 213*03831d35Sstevel 214*03831d35Sstevel .skip 2048 215*03831d35Sstevel 216*03831d35Sstevelsbdp_shutdown_asm_end: 217*03831d35Sstevel 218*03831d35Sstevel#endif /* lint */ 219*03831d35Sstevel 220*03831d35Sstevel 221*03831d35Sstevel#if defined(lint) 222*03831d35Sstevel 223*03831d35Sstevel#else /* lint */ 224*03831d35Sstevel#include "assym.h" 225*03831d35Sstevel#endif /* lint */ 226*03831d35Sstevel 227*03831d35Sstevel#define TT_HSM 0x99 228*03831d35Sstevel 229*03831d35Sstevel#if defined(lint) 230*03831d35Sstevel/* ARGSUSED */ 231*03831d35Sstevelvoid 232*03831d35Sstevelsgdr_mem_blkcopy(caddr_t src, caddr_t dst, u_int linecount, u_int linesize) 233*03831d35Sstevel{} 234*03831d35Sstevel 235*03831d35Sstevelvoid 236*03831d35Sstevelstdmcdecode(uint64_t physaddr, uint64_t value) 237*03831d35Sstevel{ 238*03831d35Sstevel physaddr = physaddr; 239*03831d35Sstevel value = value; 240*03831d35Sstevel} 241*03831d35Sstevel 242*03831d35Sstevel#else /* !lint */ 243*03831d35Sstevel! 244*03831d35Sstevel! Move a single cache line of data. Survive UE and CE on the read 245*03831d35Sstevel! 246*03831d35Sstevel! i0 = src va 247*03831d35Sstevel! i1 = dst va 248*03831d35Sstevel! i2 = line count 249*03831d35Sstevel! i3 = line size 250*03831d35Sstevel! i4 = cache of fpu state 251*03831d35Sstevel! 252*03831d35Sstevel ENTRY(sgdr_mem_blkcopy) 253*03831d35Sstevel 254*03831d35Sstevel ! TODO: can we safely SAVE here 255*03831d35Sstevel save %sp, -SA(MINFRAME + 2*64), %sp 256*03831d35Sstevel 257*03831d35Sstevel ! XXX do we need to save the state of the fpu? 258*03831d35Sstevel rd %fprs, %i4 259*03831d35Sstevel btst (FPRS_DU|FPRS_DL|FPRS_FEF), %i4 260*03831d35Sstevel 261*03831d35Sstevel ! always enable FPU 262*03831d35Sstevel wr %g0, FPRS_FEF, %fprs 263*03831d35Sstevel 264*03831d35Sstevel bz,a 1f 265*03831d35Sstevel nop 266*03831d35Sstevel 267*03831d35Sstevel ! save in-use fpregs on stack 268*03831d35Sstevel membar #Sync 269*03831d35Sstevel add %fp, STACK_BIAS - 81, %o2 270*03831d35Sstevel and %o2, -64, %o2 271*03831d35Sstevel stda %d0, [%o2]ASI_BLK_P 272*03831d35Sstevel membar #Sync 273*03831d35Sstevel 274*03831d35Sstevel1: 275*03831d35Sstevel brz,pn %i2, 2f ! while (linecount) { 276*03831d35Sstevel nop 277*03831d35Sstevel ldda [%i0]ASI_BLK_P, %d0 ! *dst = *src; 278*03831d35Sstevel membar #Sync 279*03831d35Sstevel stda %d0, [%i1]ASI_BLK_COMMIT_P 280*03831d35Sstevel membar #Sync 281*03831d35Sstevel 282*03831d35Sstevel add %i0, %i3, %i0 ! dst++, src++; 283*03831d35Sstevel add %i1, %i3, %i1 284*03831d35Sstevel 285*03831d35Sstevel ba 1b ! linecount-- } 286*03831d35Sstevel dec %i2 287*03831d35Sstevel 288*03831d35Sstevel2: 289*03831d35Sstevel membar #Sync 290*03831d35Sstevel 291*03831d35Sstevel ! restore fp to the way we got it 292*03831d35Sstevel btst (FPRS_DU|FPRS_DL|FPRS_FEF), %i4 293*03831d35Sstevel bz,a 3f 294*03831d35Sstevel nop 295*03831d35Sstevel 296*03831d35Sstevel ! restore fpregs from stack 297*03831d35Sstevel add %fp, STACK_BIAS - 81, %o2 298*03831d35Sstevel and %o2, -64, %o2 299*03831d35Sstevel ldda [%o2]ASI_BLK_P, %d0 300*03831d35Sstevel membar #Sync 301*03831d35Sstevel 302*03831d35Sstevel3: 303*03831d35Sstevel wr %g0, %i4, %fprs ! fpu back to the way it was 304*03831d35Sstevel ret 305*03831d35Sstevel restore 306*03831d35Sstevel SET_SIZE(sgdr_mem_blkcopy) 307*03831d35Sstevel 308*03831d35Sstevel ! Store long word value at mc regs 309*03831d35Sstevel ! 310*03831d35Sstevel ! void stdmcdecode(uint64_t physaddr, uint64_t value) 311*03831d35Sstevel ! 312*03831d35Sstevel ENTRY(stdmcdecode) 313*03831d35Sstevel /* 314*03831d35Sstevel * disable interrupts, clear Address Mask to access 64 bit physaddr 315*03831d35Sstevel */ 316*03831d35Sstevel rdpr %pstate, %o4 317*03831d35Sstevel andn %o4, PSTATE_IE | PSTATE_AM, %o5 318*03831d35Sstevel wrpr %o5, 0, %pstate ! clear IE, AM bits 319*03831d35Sstevel stxa %o1, [%o0]ASI_MC_DECODE 320*03831d35Sstevel membar #Sync 321*03831d35Sstevel retl 322*03831d35Sstevel wrpr %g0, %o4, %pstate ! restore earlier pstate register value 323*03831d35Sstevel SET_SIZE(stdmcdecode) 324*03831d35Sstevel 325*03831d35Sstevel#endif /* lint */ 326