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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 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#else 38#include "assym.h" 39#endif /* lint */ 40 41#include <sys/asm_linkage.h> 42#include <sys/param.h> 43#include <sys/privregs.h> 44#include <sys/machasi.h> 45#include <sys/spitregs.h> 46#include <sys/mmu.h> 47#include <sys/machthread.h> 48#include <sys/pte.h> 49#include <sys/stack.h> 50#include <sys/vis.h> 51 52#ifndef lint 53 54/* 55 * arg1 = icache_size 56 * arg2 = icache_linesize 57 */ 58#define ICACHE_FLUSHALL(lbl, arg1, arg2, tmp1) \ 59 ldxa [%g0]ASI_LSU, tmp1 ;\ 60 btst LSU_IC, tmp1 ;\ 61 bz,pn %icc, lbl/**/1 ;\ 62 sub arg1, arg2, tmp1 ;\ 63lbl/**/0: ;\ 64 stxa %g0, [tmp1]ASI_IC_TAG ;\ 65 membar #Sync ;\ 66 cmp %g0, tmp1 ;\ 67 bne,pt %icc, lbl/**/0 ;\ 68 sub tmp1, arg2, tmp1 ;\ 69lbl/**/1: 70 71/* 72 * arg1 = dcache_size 73 * arg2 = dcache_linesize 74 */ 75#define DCACHE_FLUSHALL(lbl, arg1, arg2, tmp1) \ 76 ldxa [%g0]ASI_LSU, tmp1 ;\ 77 btst LSU_DC, tmp1 ;\ 78 bz,pn %icc, lbl/**/1 ;\ 79 sub arg1, arg2, tmp1 ;\ 80lbl/**/0: ;\ 81 stxa %g0, [tmp1]ASI_DC_TAG ;\ 82 membar #Sync ;\ 83 cmp %g0, tmp1 ;\ 84 bne,pt %icc, lbl/**/0 ;\ 85 sub tmp1, arg2, tmp1 ;\ 86lbl/**/1: 87 88/* 89 * arg1 = ecache flush physaddr 90 * arg2 = size 91 * arg3 = ecache_linesize 92 */ 93#define ECACHE_FLUSHALL(lbl, arg1, arg2, arg3, tmp1, tmp2) \ 94 rdpr %pstate, tmp1 ;\ 95 andn tmp1, PSTATE_IE | PSTATE_AM, tmp2 ;\ 96 wrpr %g0, tmp2, %pstate ;\ 97 b lbl/**/1 ;\ 98lbl/**/0: ;\ 99 sub arg2, arg3, arg2 ;\ 100lbl/**/1: ;\ 101 brgez,a arg2, lbl/**/0 ;\ 102 ldxa [arg1 + arg2]ASI_MEM, %g0 ;\ 103 wrpr %g0, tmp1, %pstate 104 105#ifdef SF_ERRATA_32 106#define SF_WORKAROUND(tmp1, tmp2) \ 107 sethi %hi(FLUSH_ADDR), tmp2 ;\ 108 set MMU_PCONTEXT, tmp1 ;\ 109 stxa %g0, [tmp1]ASI_DMMU ;\ 110 flush tmp2 ; 111#else 112#define SF_WORKAROUND(tmp1, tmp2) 113#endif /* SF_ERRATA_32 */ 114 115/* 116 * arg1 = vaddr 117 * arg2 = ctxnum 118 * - disable interrupts and clear address mask 119 * to access 64 bit physaddr 120 * - Blow out the TLB. 121 * . If it's kernel context, then use primary context. 122 * . Otherwise, use secondary. 123 */ 124#define VTAG_FLUSHPAGE(lbl, arg1, arg2, tmp1, tmp2, tmp3, tmp4) \ 125 rdpr %pstate, tmp1 ;\ 126 andn tmp1, PSTATE_IE | PSTATE_AM, tmp2 ;\ 127 wrpr tmp2, 0, %pstate ;\ 128 brnz,pt arg2, lbl/**/1 ;\ 129 sethi %hi(FLUSH_ADDR), tmp2 ;\ 130 stxa %g0, [arg1]ASI_DTLB_DEMAP ;\ 131 stxa %g0, [arg1]ASI_ITLB_DEMAP ;\ 132 b lbl/**/5 ;\ 133 flush tmp2 ;\ 134lbl/**/1: ;\ 135 set MMU_SCONTEXT, tmp3 ;\ 136 ldxa [tmp3]ASI_DMMU, tmp4 ;\ 137 or DEMAP_SECOND | DEMAP_PAGE_TYPE, arg1, arg1 ;\ 138 cmp tmp4, arg2 ;\ 139 be,a,pt %icc, lbl/**/4 ;\ 140 nop ;\ 141 stxa arg2, [tmp3]ASI_DMMU ;\ 142lbl/**/4: ;\ 143 stxa %g0, [arg1]ASI_DTLB_DEMAP ;\ 144 stxa %g0, [arg1]ASI_ITLB_DEMAP ;\ 145 flush tmp2 ;\ 146 be,a,pt %icc, lbl/**/5 ;\ 147 nop ;\ 148 stxa tmp4, [tmp3]ASI_DMMU ;\ 149 flush tmp2 ;\ 150lbl/**/5: ;\ 151 wrpr %g0, tmp1, %pstate 152 153/* 154 * arg1 = dtlb entry 155 * - Before first compare: 156 * tmp4 = tte 157 * tmp5 = vaddr 158 * tmp6 = cntxnum 159 */ 160#define DTLB_FLUSH_UNLOCKED(lbl, arg1, tmp1, tmp2, tmp3, \ 161 tmp4, tmp5, tmp6) \ 162lbl/**/0: ;\ 163 sllx arg1, 3, tmp3 ;\ 164 SF_WORKAROUND(tmp1, tmp2) ;\ 165 ldxa [tmp3]ASI_DTLB_ACCESS, tmp4 ;\ 166 srlx tmp4, 6, tmp4 ;\ 167 andcc tmp4, 1, %g0 ;\ 168 bnz,pn %xcc, lbl/**/1 ;\ 169 srlx tmp4, 57, tmp4 ;\ 170 andcc tmp4, 1, %g0 ;\ 171 beq,pn %xcc, lbl/**/1 ;\ 172 nop ;\ 173 set TAGREAD_CTX_MASK, tmp1 ;\ 174 ldxa [tmp3]ASI_DTLB_TAGREAD, tmp2 ;\ 175 and tmp2, tmp1, tmp6 ;\ 176 andn tmp2, tmp1, tmp5 ;\ 177 VTAG_FLUSHPAGE(VD, tmp5, tmp6, tmp1, tmp2, tmp3, tmp4) ;\ 178lbl/**/1: ;\ 179 brgz,pt arg1, lbl/**/0 ;\ 180 sub arg1, 1, arg1 181 182/* 183 * arg1 = itlb entry 184 * - Before first compare: 185 * tmp4 = tte 186 * tmp5 = vaddr 187 * tmp6 = cntxnum 188 */ 189#define ITLB_FLUSH_UNLOCKED(lbl, arg1, tmp1, tmp2, tmp3, \ 190 tmp4, tmp5, tmp6) \ 191lbl/**/0: ;\ 192 sllx arg1, 3, tmp3 ;\ 193 SF_WORKAROUND(tmp1, tmp2) ;\ 194 ldxa [tmp3]ASI_ITLB_ACCESS, tmp4 ;\ 195 srlx tmp4, 6, tmp4 ;\ 196 andcc tmp4, 1, %g0 ;\ 197 bnz,pn %xcc, lbl/**/1 ;\ 198 srlx tmp4, 57, tmp4 ;\ 199 andcc tmp4, 1, %g0 ;\ 200 beq,pn %xcc, lbl/**/1 ;\ 201 nop ;\ 202 set TAGREAD_CTX_MASK, tmp1 ;\ 203 ldxa [tmp3]ASI_ITLB_TAGREAD, tmp2 ;\ 204 and tmp2, tmp1, tmp6 ;\ 205 andn tmp2, tmp1, tmp5 ;\ 206 VTAG_FLUSHPAGE(VI, tmp5, tmp6, tmp1, tmp2, tmp3, tmp4) ;\ 207lbl/**/1: ;\ 208 brgz,pt arg1, lbl/**/0 ;\ 209 sub arg1, 1, arg1 210 211#define CLEARTL(lvl) \ 212 wrpr %g0, lvl, %tl ;\ 213 wrpr %g0, %g0, %tpc ;\ 214 wrpr %g0, %g0, %tnpc ;\ 215 wrpr %g0, %g0, %tt 216 217#define SWITCH_STACK(estk) \ 218 flushw ;\ 219 sub estk, SA(KFPUSIZE+GSR_SIZE), estk ;\ 220 andn estk, 0x3f, estk ;\ 221 sub estk, SA(MINFRAME) + STACK_BIAS, %sp ;\ 222 mov estk, %fp 223 224#endif /* !lint */ 225 226#if defined(lint) 227 228/*ARGSUSED*/ 229void 230drmach_shutdown_asm(uint64_t mbox_addr) 231{} 232 233#else /* lint */ 234 235 ENTRY_NP(drmach_shutdown_asm) 236 mov %o0, %o5 237 238 ldxa [%o5]ASI_MEM, %o0 ! get 8-byte estack in o0 239 add %o5, 8, %o5 240 ldxa [%o5]ASI_MEM, %o1 ! get 8-byte flushaddr in o1 241 add %o5, 8, %o5 242 lda [%o5]ASI_MEM, %o2 ! get 4-byte size in o2 243 srl %o2, 0, %o2 244 add %o5, 4, %o5 245 lda [%o5]ASI_MEM, %o3 ! get 4-byte linesize in o3 246 srl %o3, 0, %o3 247 add %o5, 4, %o5 248 ldxa [%o5]ASI_MEM, %o4 ! get 8-byte physaddr in o4 249 250 251 ! %o0 = base (va mapping this code in bbsram) 252 ! %o1 = flushaddr for ecache 253 ! %o2 = size to use for ecache flush 254 ! %o3 = ecache linesize 255 ! %o4 = phys addr of byte to clear when finished 256 ! 257 ! output: Stores a zero at [%o4]ASI_MEM 258 259 membar #LoadStore 260 261 ! 262 ! Switch stack pointer to bbsram 263 ! 264 SWITCH_STACK(%o0) 265 266 ! 267 ! Get some globals 268 ! 269 mov %o3, %g1 ! ecache_linesize 270 mov %o4, %o0 ! physaddr byte to clear 271 272 sethi %hi(dcache_linesize), %g2 273 ld [%g2 + %lo(dcache_linesize)], %g2 274 275 sethi %hi(dcache_size), %g3 276 ld [%g3 + %lo(dcache_size)], %g3 277 278 sethi %hi(icache_linesize), %g4 279 ld [%g4 + %lo(icache_linesize)], %g4 280 281 sethi %hi(icache_size), %g5 282 ld [%g5 + %lo(icache_size)], %g5 283 284 sethi %hi(dtlb_entries), %o5 285 ld [%o5 + %lo(dtlb_entries)], %o5 286 sllx %o5, 32, %o5 287 srlx %o5, 32, %o5 288 289 sethi %hi(itlb_entries), %o3 290 ld [%o3 + %lo(itlb_entries)], %o3 291 ! 292 ! cram Xtlb_entries into a single register (%o5) 293 ! %o5 upper 32 = itlb_entries 294 ! lower 32 = dtlb_entries 295 ! 296 sllx %o3, 32, %o3 297 or %o5, %o3, %o5 298 299 ! 300 ! Flush E$ 301 ! 302 ECACHE_FLUSHALL(EC, %o1, %o2, %g1, %o3, %o4) 303 ! 304 ! %o1 & %o2 now available 305 ! 306 307 membar #Sync 308 309 ! 310 ! Flush D$ 311 ! 312 DCACHE_FLUSHALL(DC, %g3, %g2, %o3) 313 314 ! 315 ! Flush I$ 316 ! 317 ICACHE_FLUSHALL(IC, %g5, %g4, %o3) 318 319 membar #Sync 320 321 ! 322 ! Flush dtlb's 323 ! 324 srlx %o5, 32, %g5 ! %g5 = itlb_entries 325 sllx %o5, 32, %o5 326 srlx %o5, 32, %g1 327 sub %g1, 1, %g1 ! %g1 = dtlb_entries - 1 328 329 DTLB_FLUSH_UNLOCKED(D, %g1, %g3, %g4, %o2, %o3, %o4, %o5) 330 331 ! 332 ! Flush itlb's 333 ! 334 sub %g5, 1, %g1 ! %g1 = itlb_entries - 1 335 336 ITLB_FLUSH_UNLOCKED(I, %g1, %g3, %g4, %o2, %o3, %o4, %o5) 337 338 membar #Sync 339 340 ! 341 ! Clear byte to signal finished. 342 ! 343 stba %g0, [%o0]ASI_MEM 344 membar #Sync 345 346 ! 347 ! read ensures that last write completed (has left queue in the PC chip) 348 ! 349 lduba [%o0]ASI_MEM, %g0 3505: 351 ba 5b 352 nop 353 SET_SIZE(drmach_shutdown_asm) 354 355 .global drmach_shutdown_asm_end 356 357 .skip 2048 358 359drmach_shutdown_asm_end: 360 361#endif /* lint */ 362