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 /*
  28  * This file is through cpp before being used as
  29  * an inline.  It contains support routines used
  30  * only by DR for the copy-rename sequence.
  31  */
  32 
  33 #include "assym.h"
  34 
  35 #include <sys/asm_linkage.h>
  36 #include <sys/param.h>
  37 #include <sys/privregs.h>
  38 #include <sys/machasi.h>
  39 #include <sys/mmu.h>
  40 #include <sys/machthread.h>
  41 #include <sys/pte.h>
  42 #include <sys/stack.h>
  43 #include <sys/vis.h>
  44 #include <sys/param.h>
  45 #include <sys/errno.h>
  46 #include <sys/vtrace.h>
  47 #include <sys/clock.h>
  48 #include <sys/asi.h>
  49 #include <sys/fsr.h>
  50 #include <sys/cheetahregs.h>
  51 #include <sys/cheetahasm.h>
  52 
  53 /*
  54  * Invalidating the E$ tags is only needed on Cheetah following
  55  * the manual displacement flush.  The internal flush ASI used by
  56  * Cheetahplus, Jaguar, and Panther will invalidate the cache lines.
  57  *
  58  * arg1 = ecache_size
  59  * arg2 = ecache_linesize
  60  */
  61 #define ECACHE_FLUSHTAGS(arg1, arg2, tmp1)                      \
  62         GET_CPU_IMPL(tmp1)                                      ;\
  63         srlx    arg1, 1, arg1                                   ;\
  64         cmp     tmp1, CHEETAH_IMPL                              ;\
  65         bne     1f                                              ;\
  66         nop                                                     ;\
  67         sub     arg1, arg2, tmp1                                ;\
  68 0:                                                              ;\
  69         stxa    %g0, [tmp1]ASI_EC_DIAG                          ;\
  70         membar  #Sync                                           ;\
  71         cmp     %g0, tmp1                                       ;\
  72         bne,pt  %icc, 0b                                        ;\
  73         sub     tmp1, arg2, tmp1                                ;\
  74 1:
  75 
  76 
  77 #define SWITCH_STACK(estk)                                      \
  78         flushw                                                  ;\
  79         sub     estk, SA(KFPUSIZE+GSR_SIZE), estk              ;\
  80         andn    estk, 0x3f, estk                                ;\
  81         sub     estk, SA(MINFRAME) + STACK_BIAS, %sp            ;\
  82         mov     estk, %fp
  83 
  84 /*
  85  * Returns icache size and linesize in reg1 and reg2, respectively.
  86  * Panther has a larger icache compared to Cheetahplus and Jaguar.
  87  */
  88 #define GET_ICACHE_PARAMS(reg1, reg2)                           \
  89         GET_CPU_IMPL(reg1)                                      ;\
  90         cmp     reg1, PANTHER_IMPL                              ;\
  91         bne     %xcc, 1f                                        ;\
  92           nop                                                   ;\
  93         set     PN_ICACHE_SIZE, reg1                            ;\
  94         set     PN_ICACHE_LSIZE, reg2                           ;\
  95         ba      2f                                              ;\
  96           nop                                                   ;\
  97 1:                                                              ;\
  98         set     CH_ICACHE_SIZE, reg1                            ;\
  99         set     CH_ICACHE_LSIZE, reg2                           ;\
 100 2:
 101 
 102         ENTRY_NP(sbdp_shutdown_asm)
 103         ! %o0 = address of sbdp_shutdown_t structure passed in
 104         !
 105         ! struct sbdp_shutdown {
 106         !       uint64_t        estack;    -> %o0
 107         !       uint64_t        flushaddr; -> %o1
 108         !       uint32_t        size;      -> %o2
 109         !       uint32_t        linesize;  -> %g1
 110         !       uint64_t        physaddr;  -> %o0
 111         ! } sbdp_shutdown_t;
 112         !
 113         membar  #LoadStore
 114         mov     %o0, %o4
 115         ldx     [%o4], %o0
 116         ldx     [%o4 + 8], %o1
 117         ld      [%o4 + 16], %o2
 118         ld      [%o4 + 20], %g1
 119 
 120         !
 121         ! Switch stack pointer to bbsram
 122         !
 123         SWITCH_STACK(%o0)
 124 
 125         ldx     [%o4 + 24], %o0 !save physaddr in %o0
 126         !
 127         ! Get some globals
 128         !
 129         ! ecache_linesize already in %g1
 130 
 131         sethi   %hi(dcache_linesize), %g2
 132         ld      [%g2 + %lo(dcache_linesize)], %g2
 133 
 134         sethi   %hi(dcache_size), %g3
 135         ld      [%g3 + %lo(dcache_size)], %g3
 136 
 137         !
 138         ! Save the E$ size
 139         !
 140         mov     %o2, %o5
 141         !
 142         ! Flush E$
 143         !
 144         rdpr    %pstate, %o3
 145         andn    %o3, PSTATE_IE | PSTATE_AM, %o4
 146         wrpr    %g0, %o4, %pstate
 147 
 148         ! Panther needs to flush L2 before L3 cache. 
 149         PN_L2_FLUSHALL(%o4, %g4, %g5)
 150 
 151         ECACHE_FLUSHALL(%o2, %g1, %o1, %o4)
 152 
 153         wrpr    %g0, %o3, %pstate
 154 
 155         !
 156         ! Invalidate the E$ tags (Cheetah only).
 157         !
 158         ECACHE_FLUSHTAGS(%o5, %g1, %o3)
 159 
 160         !
 161         ! %o2 & %o3 now available
 162         !
 163 
 164         membar  #Sync
 165 
 166         !
 167         ! Flush D$
 168         !
 169         CH_DCACHE_FLUSHALL(%g3, %g2, %o3)
 170 
 171         !
 172         ! Flush I$
 173         !
 174         GET_ICACHE_PARAMS(%g5, %g4)
 175         CH_ICACHE_FLUSHALL(%g5, %g4, %o3, %o4)
 176 
 177         membar  #Sync
 178 
 179         !
 180         ! Flush all unlocked dtlb's & itlb's
 181         !
 182         sethi   %hi(FLUSH_ADDR), %g3
 183         set     DEMAP_ALL_TYPE, %g1
 184         stxa    %g0, [%g1]ASI_DTLB_DEMAP
 185         stxa    %g0, [%g1]ASI_ITLB_DEMAP
 186         flush   %g3
 187 
 188         sir     0
 189         SET_SIZE(sbdp_shutdown_asm)
 190 
 191         .global sbdp_shutdown_asm_end
 192 
 193         .skip   2048
 194 
 195 sbdp_shutdown_asm_end:
 196 
 197 
 198 #include "assym.h"
 199 
 200 #define TT_HSM  0x99
 201 
 202 !
 203 ! Move a single cache line of data.  Survive UE and CE on the read
 204 !
 205 ! i0 = src va
 206 ! i1 = dst va
 207 ! i2 = line count
 208 ! i3 = line size
 209 ! i4 = cache of fpu state
 210 !
 211         ENTRY(sgdr_mem_blkcopy)
 212 
 213         ! TODO: can we safely SAVE here
 214         save    %sp, -SA(MINFRAME + 2*64), %sp
 215 
 216         ! XXX do we need to save the state of the fpu?
 217         rd      %fprs, %i4
 218         btst    (FPRS_DU|FPRS_DL|FPRS_FEF), %i4
 219 
 220         ! always enable FPU
 221         wr      %g0, FPRS_FEF, %fprs
 222 
 223         bz,a    1f
 224          nop
 225 
 226         ! save in-use fpregs on stack
 227         membar  #Sync
 228         add     %fp, STACK_BIAS - 81, %o2
 229         and     %o2, -64, %o2
 230         stda    %d0, [%o2]ASI_BLK_P
 231         membar  #Sync
 232 
 233 1:
 234         brz,pn  %i2, 2f                         ! while (linecount) {
 235          nop
 236         ldda    [%i0]ASI_BLK_P, %d0             ! *dst = *src;
 237         membar  #Sync
 238         stda    %d0, [%i1]ASI_BLK_COMMIT_P
 239         membar  #Sync
 240 
 241         add     %i0, %i3, %i0                   ! dst++, src++;
 242         add     %i1, %i3, %i1
 243 
 244         ba      1b                              ! linecount-- }
 245          dec    %i2
 246 
 247 2:
 248         membar  #Sync
 249 
 250         ! restore fp to the way we got it
 251         btst    (FPRS_DU|FPRS_DL|FPRS_FEF), %i4
 252         bz,a    3f
 253          nop
 254 
 255         ! restore fpregs from stack
 256         add     %fp, STACK_BIAS - 81, %o2
 257         and     %o2, -64, %o2
 258         ldda    [%o2]ASI_BLK_P, %d0
 259         membar  #Sync
 260 
 261 3:
 262         wr      %g0, %i4, %fprs                 ! fpu back to the way it was
 263         ret
 264         restore
 265         SET_SIZE(sgdr_mem_blkcopy)
 266 
 267         ! Store long word value at mc regs
 268         !
 269         ! void  stdmcdecode(uint64_t physaddr, uint64_t value)
 270         !
 271         ENTRY(stdmcdecode)
 272         /*
 273          * disable interrupts, clear Address Mask to access 64 bit physaddr
 274          */
 275         rdpr    %pstate, %o4
 276         andn    %o4, PSTATE_IE | PSTATE_AM, %o5
 277         wrpr    %o5, 0, %pstate         ! clear IE, AM bits
 278         stxa    %o1, [%o0]ASI_MC_DECODE
 279         membar  #Sync
 280         retl
 281         wrpr    %g0, %o4, %pstate       ! restore earlier pstate register value
 282         SET_SIZE(stdmcdecode)
 283