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 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26#pragma ident "%Z%%M% %I% %E% SMI" 27 28/* 29 * This file is through cpp before being used as 30 * an inline. It contains support routines used 31 * only by DR for the copy-rename sequence. 32 */ 33 34#if defined(lint) 35#include <sys/types.h> 36#else 37#include "assym.h" 38#include "drmach_offsets.h" 39#endif /* lint */ 40 41#include <sys/asm_linkage.h> 42#include <sys/param.h> 43#include <sys/privregs.h> 44#include <sys/spitregs.h> 45#include <sys/mmu.h> 46#include <sys/machthread.h> 47#include <sys/pte.h> 48#include <sys/stack.h> 49#include <sys/vis.h> 50#include <sys/intreg.h> 51#include <sys/cheetahregs.h> 52#include <sys/drmach.h> 53 54#if !defined(lint) 55 56/* 57 * turn off speculative mode to prevent unwanted memory access 58 * when we are in the FMEM loops 59 */ 60 61#define FJSV_SPECULATIVE_OFF(reg, tmp1, tmp2) \ 62 rdpr %pstate, reg ;\ 63 andn reg, PSTATE_IE, tmp1 ;\ 64 wrpr %g0, tmp1, %pstate ;\ 65 ldxa [%g0]ASI_MCNTL, tmp1 ;\ 66 set 1, tmp2 ;\ 67 sllx tmp2, MCNTL_SPECULATIVE_SHIFT, tmp2 ;\ 68 or tmp1, tmp2, tmp1 ;\ 69 stxa tmp1, [%g0]ASI_MCNTL ;\ 70 membar #Sync 71#endif 72 73 74#if defined(lint) 75/*ARGSUSED*/ 76void 77drmach_fmem_loop_script(caddr_t critical, int size, caddr_t stat) 78{ return; } 79#else /* lint */ 80 .align 8 81 ENTRY_NP(drmach_fmem_loop_script) 82 /* turn off speculative mode */ 83 FJSV_SPECULATIVE_OFF(%o5, %o3, %o4); 84 85 /* read the critical region to get everything in the cache */ 86 mov %o0, %o3 870: 88 ldx [%o3], %o4 89 sub %o1, 8, %o1 90 brnz %o1, 0b 91 add %o3, 8, %o3 92 93 /* clear L2_CTRL_UGE_TRAP error bit */ 94 mov ASI_L2_CTRL_RW_ADDR, %o1 95 ldxa [%o1]ASI_L2_CTRL, %o3 96 sethi %hi(ASI_L2_CTRL_UGE_TRAP), %o4 97 btst %o3, %o4 98 bz,pn %xcc, 1f 99 nop 100 stxa %o4, [%o1]ASI_L2_CTRL 101 102 /* now tell the master CPU that we are ready */ 1031: 104 set FMEM_LOOP_FMEM_READY, %o3 105 stb %o3, [%o2] 106 membar #Sync 107 ba 5f 108 nop 109 110 /* 111 * note that we branch to 5f, which branches right back to 2 here. 112 * The trick is that when that branch instruction has already been 113 * patched to a branch to itself - an infinite loop. 114 * The master thread will patch it back to "ba 2b" when it 115 * completes. 116 */ 117 118 /* Once we are back, we first check if there has been any 119 * L2_CTRL_UGE_TRAP errors, if so we have to fail the 120 * operation. This will cause a panic because the system 121 * is already in inconsistent state. 122 */ 1232: 124 mov ASI_L2_CTRL_RW_ADDR, %o3 125 ldxa [%o3]ASI_L2_CTRL, %o3 126 sethi %hi(ASI_L2_CTRL_UGE_TRAP), %o4 127 btst %o3, %o4 128 bz,pn %xcc, 3f 129 mov %g0, %o4 130 set FMEM_HW_ERROR, %o4 131 132 /* set error code and stat code */ 1333: 134 set FMEM_LOOP_DONE, %o3 135 stb %o3, [%o2] 136 137 /* turn on speculative mode again */ 138 ldxa [%g0]ASI_MCNTL, %o0 139 set 1, %o1 140 sllx %o1, MCNTL_SPECULATIVE_SHIFT, %o1 141 andn %o0, %o1, %o0 142 ba 4f 143 nop 144.align 32 1454: 146 stxa %o0, [%g0]ASI_MCNTL 147 membar #Sync 148 wrpr %g0, %o5, %pstate 149 retl 150 mov %o4, %o0 151.align 8 1525: 153 ALTENTRY(drmach_fmem_loop_script_rtn) 154 /* 155 * busy wait will affect sibling strands so 156 * we put sleep instruction in the delay slot 157 */ 158 ba 2b 159.word 0x81b01060 160 SET_SIZE(drmach_fmem_loop_script) 161#endif /* lint */ 162 163#if defined(lint) 164/*ARGSUSED*/ 165void 166drmach_flush_icache(void) 167{ return; } 168#else /* lint */ 169 .align 8 170 ENTRY_NP(drmach_flush_icache) 171 stxa %g0, [%g0]ASI_ALL_FLUSH_L1I 172 membar #Sync 173 retl 174 nop 175 SET_SIZE(drmach_flush_icache) 176#endif 177 178#if defined(lint) 179/*ARGSUSED*/ 180int 181drmach_fmem_exec_script(caddr_t critical, int size) 182{ return (0); } 183#else /* lint */ 184.align 32 185 ENTRY_NP(drmach_fmem_exec_script) 186 /* turn off speculative mode */ 187 FJSV_SPECULATIVE_OFF(%o5, %o3, %o4); 188 /* save locals to save area */ 189 add %o0, SAVE_LOCAL, %o2 190 stx %l0, [%o2+8*0] 191 stx %l1, [%o2+8*1] 192 stx %l2, [%o2+8*2] 193 stx %l3, [%o2+8*3] 194 stx %l4, [%o2+8*4] 195 stx %l5, [%o2+8*5] 196 stx %l6, [%o2+8*6] 197 stx %l7, [%o2+8*7] 198 mov %o5, %l6 199 /* l7 is set only when FMEM cmd is issued to SCF */ 200 mov %g0, %l7 201 202 /* read the critical region to put everything in the cache */ 203 mov %o0, %o2 2040: 205 ldx [%o2], %o4 206 sub %o1, 8, %o1 207 brnz %o1, 0b 208 add %o2, 8, %o2 209 ba 4f 210 nop 211 212 /* we branch to 4f but eventually we branch back here to finish up */ 2131: 214 mov %l6, %o5 215 /* 216 * save some registers for debugging 217 * l0 - SCF_REG_BASE 218 * l1 - SCF_TD 219 * l2 - SCF_TD + 8 220 * l5 - DELAY 221 */ 222 add %o0, SAVE_LOG, %o1 223 stx %l0, [%o1+8*0] 224 stx %l1, [%o1+8*1] 225 stx %l2, [%o1+8*2] 226 stx %l5, [%o1+8*3] 227 228 add %o0, FMEM_ISSUED, %o1 229 st %l7, [%o1] 230 231 /* Check for L2_CTRL_UGE_TRAP error */ 232 mov ASI_L2_CTRL_RW_ADDR, %l0 233 ldxa [%l0]ASI_L2_CTRL, %l1 234 sethi %hi(ASI_L2_CTRL_UGE_TRAP), %l2 235 btst %l1, %l2 236 bz,pn %xcc, 2f 237 nop 238 mov FMEM_HW_ERROR, %o4 2392: 240 /* restore all locals */ 241 add %o0, SAVE_LOCAL, %o1 242 ldx [%o1+8*0], %l0 243 ldx [%o1+8*1], %l1 244 ldx [%o1+8*2], %l2 245 ldx [%o1+8*3], %l3 246 ldx [%o1+8*4], %l4 247 ldx [%o1+8*5], %l5 248 ldx [%o1+8*6], %l6 249 ldx [%o1+8*7], %l7 250 251 /* turn on speculative mode */ 252 ldxa [%g0]ASI_MCNTL, %o1 253 set 1, %o2 254 sllx %o2, MCNTL_SPECULATIVE_SHIFT, %o2 255 andn %o1, %o2, %o1 256 ba 3f 257 nop 258.align 32 2593: 260 stxa %o1, [%g0]ASI_MCNTL 261 membar #Sync 262 /* return error code here */ 263 mov %o4, %o0 264 retl 265 wrpr %g0, %o5, %pstate 266 267 /* clear L2_CTRL_UGE_TRAP error bit */ 2684: 269 mov ASI_L2_CTRL_RW_ADDR, %l0 270 ldxa [%l0]ASI_L2_CTRL, %l1 271 sethi %hi(ASI_L2_CTRL_UGE_TRAP), %l2 272 btst %l1, %l2 273 bz,pn %xcc, 5f 274 nop 275 stxa %l2, [%l0]ASI_L2_CTRL 2765: 277 /* set up the register locations and parameters */ 278 ldx [%o0 + SCF_REG_BASE], %l0 279 ldx [%o0 + SCF_TD], %l1 280 ldx [%o0 + SCF_TD+8], %l2 281 ldx [%o0 + DELAY], %l5 282 283 /* check if SCF is busy */ 284 add %l0, SCF_COMMAND, %o1 285 lduha [%o1]ASI_IO, %o2 286 sethi %hi(SCF_CMD_BUSY), %o3 287 btst %o2, %o3 288 be %xcc, 6f 289 nop 290 ba 1b 291 mov FMEM_SCF_BUSY, %o4 292 293 /* clear STATUS bit */ 2946: 295 add %l0, SCF_STATUS, %o1 296 lduha [%o1]ASI_IO, %o2 297 sethi %hi(SCF_STATUS_READY), %o3 298 btst %o2, %o3 299 be %xcc, 7f 300 nop 301 stha %o3, [%o1]ASI_IO 302 303 /* clear CMD_COMPLETE bit */ 3047: 305 mov SCF_STATUS_CMD_COMPLETE, %o3 306 btst %o2, %o3 307 be,a %xcc, 8f 308 nop 309 stha %o3, [%o1]ASI_IO 3108: 311 add %l0, (SCF_TDATA+0xe), %o1 312 mov %l2, %o4 313 mov SCF_RETRY_CNT, %o5 314 315 sethi %hi(0xffff), %l2 316 or %l2, %lo(0xffff), %l2 317 318 and %o4, %l2, %o3 319 320 /* 321 * o1 points to SCFBASE.SCF_TDATA[0xe] 322 * l0 points to SCFBASE 323 * crticial->SCF_TD[0] = source board # 324 * crticial->SCF_TD[1] = target board # 325 * l1 = critical->SCF_TD[0 - 7] 326 * l2 = 0xffff 327 * o4 = critical->SCF_TD[8 - 15] 328 * o3 = (*o4) & 0xffff 329 330 /* 331 * Because there is no parity protection on the ebus 332 * we read the data back after the write to verify 333 * we write 2 bytes at a time. 334 * If the data read is not the same as data written 335 * we retry up to a limit of FMEM_RETRY_OUT 336 */ 3379: 338 stha %o3, [%o1]ASI_IO 339 lduha [%o1]ASI_IO, %o2 340 sub %o5, 1, %o5 341 brz,a %o5, 1b 342 mov FMEM_RETRY_OUT, %o4 343 cmp %o2, %o3 344 bne,a 9b 345 nop 346 347 sub %o1, %l0, %o2 348 cmp %o2, (SCF_TDATA+0x8) 349 bne %xcc, 2f 350 srlx %o4, 16, %o4 351 mov %l1, %o4 352 353 /* if we have reach TDATA+8, we switch to l1 */ 354 /* XXX: Why we need 2 loops??? */ 3552: 356 sub %o1, 2, %o1 357 mov SCF_RETRY_CNT, %o5 358 and %o4, %l2, %o3 359 360 sub %o1, %l0, %o2 361 cmp %o2, (SCF_TDATA) 362 bge,a 9b 363 nop 364 365 /* if we reach TDATA, we are done */ 366 367 /* read from SCF back to our buffer for debugging */ 368 add %l0, (SCF_TDATA), %o1 369 ldxa [%o1]ASI_IO, %o2 370 stx %o2, [%o0+SCF_TD] 371 372 add %l0, (SCF_TDATA+8), %o1 373 ldxa [%o1]ASI_IO, %o2 374 stx %o2, [%o0+SCF_TD+8] 375 376 377 rd STICK, %l1 378 add %l5, %l1, %l5 379 380 /* Now tell SCF to do it */ 381 add %l0, SCF_COMMAND, %o1 382 383 /* 0x10A6 is the magic command */ 384 sethi %hi(0x10A6), %o2 385 or %o2, %lo(0x10A6), %o2 386 stha %o2, [%o1]ASI_IO 387 388 mov 1, %l7 ! FMEM is issued 389 390 add %l0, SCF_STATUS, %o1 391 sethi %hi(SCF_STATUS_READY), %o2 392 mov SCF_STATUS_CMD_COMPLETE, %o3 393 394 /* read STATUS_READY bit and clear it only if it is set */ 395 /* XXX: this STATUS_READY checking seems meaningless */ 3963: 397 lduha [%o1]ASI_IO, %o4 398 btst %o2, %o4 399 be %xcc, 4f ! STATUS_READY is not set 400 nop 401 stha %o2, [%o1]ASI_IO ! Clear if the bit is set 402 403 /* check CMD_COMPLETE bit and clear */ 4044: 405 btst %o3, %o4 406 be %xcc, 5f ! CMD_COMPLETE is not set 407 nop 408 stha %o3, [%o1]ASI_IO ! Now we are done and clear it 409 mov FMEM_NO_ERROR, %o4 410 ba %xcc, 6f 411 nop 412 413 /* timeout delay checking */ 4145: 415 rd STICK, %l2 416 cmp %l5, %l2 417 bge %xcc, 3b 418 nop 419 mov FMEM_TIMEOUT, %o4 420 421 /* we are done or timed out */ 4226: 423 ba,a 1b 424 nop 425 SET_SIZE(drmach_fmem_exec_script) 426#endif /* lint */ 427 428#if defined(lint) 429/*ARGSUSED*/ 430void 431drmach_fmem_exec_script_end(caddr_t critical, int size) 432{ return; } 433#else /* lint */ 434 ENTRY_NP(drmach_fmem_exec_script_end) 435 nop 436 SET_SIZE(drmach_fmem_exec_script_end) 437#endif /* lint */ 438 439#if defined(lint) 440uint64_t 441patch_inst(uint64_t *x, uint64_t y) 442{ 443 *x = y; 444 return (0); 445} 446 447#else /* lint */ 448 449 ENTRY_NP(patch_inst) 450 ldx [%o0], %o2 451 casx [%o0], %o2, %o1 452 flush %o0 453 membar #Sync 454 ldx [%o0], %o2 455 retl 456 mov %o2, %o0 457 SET_SIZE(patch_inst) 458 459#endif /* lint */ 460 461#if defined(lint) 462void 463drmach_sys_trap() 464{ 465} 466#else /* lint */ 467 ENTRY_NP(drmach_sys_trap) 468 mov -1, %g4 469 set sys_trap, %g5 470 jmp %g5 471 nop 472 SET_SIZE(drmach_sys_trap) 473#endif /* lint */ 474 475#if defined(lint) 476uint64_t 477drmach_get_stick() 478{ 479 return (0); 480} 481#else /* lint */ 482 ENTRY_NP(drmach_get_stick) 483 retl 484 rd STICK, %o0 485 SET_SIZE(drmach_get_stick) 486#endif /* lint */ 487 488#if defined(lint) 489/*ARGSUSED*/ 490void 491drmach_flush(void) 492{} 493 494#else /* lint */ 495 ENTRY_NP(drmach_flush) 496 mov %o0, %o2 4970: 498 flush %o2 499 sub %o1, 8, %o1 500 brnz %o1, 0b 501 add %o2, 8, %o2 502 retl 503 nop 504 SET_SIZE(drmach_flush) 505#endif /* lint */ 506