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