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#include <sys/sbd_ioctl.h> 54 55#if !defined(lint) 56 57/* 58 * turn off speculative mode to prevent unwanted memory access 59 * when we are in the FMEM loops 60 */ 61 62#define FJSV_SPECULATIVE_OFF(reg, tmp1, tmp2) \ 63 rdpr %pstate, reg ;\ 64 andn reg, PSTATE_IE, tmp1 ;\ 65 wrpr %g0, tmp1, %pstate ;\ 66 ldxa [%g0]ASI_MCNTL, tmp1 ;\ 67 set 1, tmp2 ;\ 68 sllx tmp2, MCNTL_SPECULATIVE_SHIFT, tmp2 ;\ 69 or tmp1, tmp2, tmp1 ;\ 70 stxa tmp1, [%g0]ASI_MCNTL ;\ 71 membar #Sync 72#endif 73 74 75#if defined(lint) 76/*ARGSUSED*/ 77void 78drmach_fmem_loop_script(caddr_t critical, int size, caddr_t stat) 79{ return; } 80#else /* lint */ 81 .align 8 82 ENTRY_NP(drmach_fmem_loop_script) 83 /* turn off speculative mode */ 84 FJSV_SPECULATIVE_OFF(%o5, %o3, %o4); 85 86 /* read the critical region to get everything in the cache */ 87 mov %o0, %o3 880: 89 ldx [%o3], %o4 90 sub %o1, 8, %o1 91 brnz %o1, 0b 92 add %o3, 8, %o3 93 94 /* clear L2_CTRL_UGE_TRAP error bit */ 95 mov ASI_L2_CTRL_RW_ADDR, %o1 96 ldxa [%o1]ASI_L2_CTRL, %o3 97 sethi %hi(ASI_L2_CTRL_UGE_TRAP), %o4 98 btst %o3, %o4 99 bz,pn %xcc, 1f 100 nop 101 stxa %o4, [%o1]ASI_L2_CTRL 102 103 /* now tell the master CPU that we are ready */ 1041: 105 set FMEM_LOOP_FMEM_READY, %o3 106 stb %o3, [%o2] 107 membar #Sync 108 ba 5f 109 nop 110 111 /* 112 * note that we branch to 5f, which branches right back to 2 here. 113 * The trick is that when that branch instruction has already been 114 * patched to a branch to itself - an infinite loop. 115 * The master thread will patch it back to "ba 2b" when it 116 * completes. 117 */ 118 119 /* Once we are back, we first check if there has been any 120 * L2_CTRL_UGE_TRAP errors, if so we have to fail the 121 * operation. This will cause a panic because the system 122 * is already in inconsistent state. 123 */ 1242: 125 mov ASI_L2_CTRL_RW_ADDR, %o3 126 ldxa [%o3]ASI_L2_CTRL, %o3 127 sethi %hi(ASI_L2_CTRL_UGE_TRAP), %o4 128 btst %o3, %o4 129 bz,pn %xcc, 3f 130 mov %g0, %o4 131 set EOPL_FMEM_HW_ERROR, %o4 132 133 /* set error code and stat code */ 1343: 135 set FMEM_LOOP_DONE, %o3 136 stb %o3, [%o2] 137 138 /* turn on speculative mode again */ 139 ldxa [%g0]ASI_MCNTL, %o0 140 set 1, %o1 141 sllx %o1, MCNTL_SPECULATIVE_SHIFT, %o1 142 andn %o0, %o1, %o0 143 ba 4f 144 nop 145.align 32 1464: 147 stxa %o0, [%g0]ASI_MCNTL 148 membar #Sync 149 wrpr %g0, %o5, %pstate 150 retl 151 mov %o4, %o0 152.align 8 1535: 154 ALTENTRY(drmach_fmem_loop_script_rtn) 155 /* 156 * busy wait will affect sibling strands so 157 * we put sleep instruction in the delay slot 158 */ 159 ba 2b 160.word 0x81b01060 161 SET_SIZE(drmach_fmem_loop_script) 162#endif /* lint */ 163 164#if defined(lint) 165/*ARGSUSED*/ 166void 167drmach_flush_icache(void) 168{ return; } 169#else /* lint */ 170 .align 8 171 ENTRY_NP(drmach_flush_icache) 172 stxa %g0, [%g0]ASI_ALL_FLUSH_L1I 173 membar #Sync 174 retl 175 nop 176 SET_SIZE(drmach_flush_icache) 177#endif 178 179#if defined(lint) 180/*ARGSUSED*/ 181int 182drmach_fmem_exec_script(caddr_t critical, int size) 183{ return (0); } 184#else /* lint */ 185.align 32 186 ENTRY_NP(drmach_fmem_exec_script) 187 /* turn off speculative mode */ 188 FJSV_SPECULATIVE_OFF(%o5, %o3, %o4); 189 /* save locals to save area */ 190 add %o0, SAVE_LOCAL, %o2 191 stx %l0, [%o2+8*0] 192 stx %l1, [%o2+8*1] 193 stx %l2, [%o2+8*2] 194 stx %l3, [%o2+8*3] 195 stx %l4, [%o2+8*4] 196 stx %l5, [%o2+8*5] 197 stx %l6, [%o2+8*6] 198 stx %l7, [%o2+8*7] 199 mov %o5, %l6 200 /* l7 is set only when FMEM cmd is issued to SCF */ 201 mov %g0, %l7 202 203 /* read the critical region to put everything in the cache */ 204 mov %o0, %o2 2050: 206 ldx [%o2], %o4 207 sub %o1, 8, %o1 208 brnz %o1, 0b 209 add %o2, 8, %o2 210 ba 4f 211 nop 212 213 /* we branch to 4f but eventually we branch back here to finish up */ 2141: 215 mov %l6, %o5 216 /* 217 * save some registers for debugging 218 * l0 - SCF_REG_BASE 219 * l1 - SCF_TD 220 * l2 - SCF_TD + 8 221 * l5 - DELAY 222 */ 223 add %o0, SAVE_LOG, %o1 224 stx %l0, [%o1+8*0] 225 stx %l1, [%o1+8*1] 226 stx %l2, [%o1+8*2] 227 stx %l5, [%o1+8*3] 228 229 add %o0, FMEM_ISSUED, %o1 230 st %l7, [%o1] 231 232 /* Check for L2_CTRL_UGE_TRAP error */ 233 mov ASI_L2_CTRL_RW_ADDR, %l0 234 ldxa [%l0]ASI_L2_CTRL, %l1 235 sethi %hi(ASI_L2_CTRL_UGE_TRAP), %l2 236 btst %l1, %l2 237 bz,pn %xcc, 2f 238 nop 239 set EOPL_FMEM_HW_ERROR, %o4 2402: 241 /* restore all locals */ 242 add %o0, SAVE_LOCAL, %o1 243 ldx [%o1+8*0], %l0 244 ldx [%o1+8*1], %l1 245 ldx [%o1+8*2], %l2 246 ldx [%o1+8*3], %l3 247 ldx [%o1+8*4], %l4 248 ldx [%o1+8*5], %l5 249 ldx [%o1+8*6], %l6 250 ldx [%o1+8*7], %l7 251 252 /* turn on speculative mode */ 253 ldxa [%g0]ASI_MCNTL, %o1 254 set 1, %o2 255 sllx %o2, MCNTL_SPECULATIVE_SHIFT, %o2 256 andn %o1, %o2, %o1 257 ba 3f 258 nop 259.align 32 2603: 261 stxa %o1, [%g0]ASI_MCNTL 262 membar #Sync 263 /* return error code here */ 264 mov %o4, %o0 265 retl 266 wrpr %g0, %o5, %pstate 267 268 /* clear L2_CTRL_UGE_TRAP error bit */ 2694: 270 mov ASI_L2_CTRL_RW_ADDR, %l0 271 ldxa [%l0]ASI_L2_CTRL, %l1 272 sethi %hi(ASI_L2_CTRL_UGE_TRAP), %l2 273 btst %l1, %l2 274 bz,pn %xcc, 5f 275 nop 276 stxa %l2, [%l0]ASI_L2_CTRL 2775: 278 /* set up the register locations and parameters */ 279 ldx [%o0 + SCF_REG_BASE], %l0 280 ldx [%o0 + SCF_TD], %l1 281 ldx [%o0 + SCF_TD+8], %l2 282 ldx [%o0 + DELAY], %l5 283 284 /* check if SCF is busy */ 285 add %l0, SCF_COMMAND, %o1 286 lduha [%o1]ASI_IO, %o2 287 sethi %hi(SCF_CMD_BUSY), %o3 288 btst %o2, %o3 289 be %xcc, 6f 290 nop 291 set EOPL_FMEM_SCF_BUSY, %o4 292 ba 1b 293 nop 294 295 /* clear STATUS bit */ 2966: 297 add %l0, SCF_STATUS, %o1 298 lduha [%o1]ASI_IO, %o2 299 sethi %hi(SCF_STATUS_READY), %o3 300 btst %o2, %o3 301 be %xcc, 7f 302 nop 303 stha %o3, [%o1]ASI_IO 304 305 /* clear CMD_COMPLETE bit */ 3067: 307 mov SCF_STATUS_CMD_COMPLETE, %o3 308 btst %o2, %o3 309 be,a %xcc, 8f 310 nop 311 stha %o3, [%o1]ASI_IO 3128: 313 add %l0, (SCF_TDATA+0xe), %o1 314 mov %l2, %o4 315 mov SCF_RETRY_CNT, %o5 316 317 sethi %hi(0xffff), %l2 318 or %l2, %lo(0xffff), %l2 319 320 and %o4, %l2, %o3 321 322 /* 323 * o1 points to SCFBASE.SCF_TDATA[0xe] 324 * l0 points to SCFBASE 325 * crticial->SCF_TD[0] = source board # 326 * crticial->SCF_TD[1] = target board # 327 * l1 = critical->SCF_TD[0 - 7] 328 * l2 = 0xffff 329 * o4 = critical->SCF_TD[8 - 15] 330 * o3 = (*o4) & 0xffff 331 332 /* 333 * Because there is no parity protection on the ebus 334 * we read the data back after the write to verify 335 * we write 2 bytes at a time. 336 * If the data read is not the same as data written 337 * we retry up to a limit of SCF_RETRY_CNT 338 */ 3399: 340 stha %o3, [%o1]ASI_IO 341 lduha [%o1]ASI_IO, %o2 342 sub %o5, 1, %o5 343 brnz %o5, 7f 344 nop 345 set EOPL_FMEM_RETRY_OUT, %o4 346 ba 1b 347 nop 3487: 349 cmp %o2, %o3 350 bne,a 9b 351 nop 352 353 sub %o1, %l0, %o2 354 cmp %o2, (SCF_TDATA+0x8) 355 bne %xcc, 2f 356 srlx %o4, 16, %o4 357 mov %l1, %o4 358 359 /* if we have reach TDATA+8, we switch to l1 */ 360 /* XXX: Why we need 2 loops??? */ 3612: 362 sub %o1, 2, %o1 363 mov SCF_RETRY_CNT, %o5 364 and %o4, %l2, %o3 365 366 sub %o1, %l0, %o2 367 cmp %o2, (SCF_TDATA) 368 bge,a 9b 369 nop 370 371 /* if we reach TDATA, we are done */ 372 373 /* read from SCF back to our buffer for debugging */ 374 add %l0, (SCF_TDATA), %o1 375 ldxa [%o1]ASI_IO, %o2 376 stx %o2, [%o0+SCF_TD] 377 378 add %l0, (SCF_TDATA+8), %o1 379 ldxa [%o1]ASI_IO, %o2 380 stx %o2, [%o0+SCF_TD+8] 381 382 /* The following code conforms to the FMEM 383 sequence (4) as described in the Columbus2 384 logical spec section 4.6 385 */ 386 387 /* read from SCF SB INFO register */ 388 sethi %hi(SCF_SB_INFO_OFFSET), %o2 389 or %o2, %lo(SCF_SB_INFO_OFFSET), %o2 390 add %l0, %o2, %o1 391 lduba [%o1]ASI_IO, %o2 392 393 /* If BUSY bit is set, abort */ 394 or %g0, (SCF_SB_INFO_BUSY), %o1 395 btst %o1, %o2 396 set EOPL_FMEM_SCF_BUSY, %o4 397 bne 1b 398 nop 399 400 rd STICK, %l1 401 add %l5, %l1, %l5 402 403 /* Now tell SCF to do it */ 404 add %l0, SCF_COMMAND, %o1 405 406 /* 0x10A6 is the magic command */ 407 sethi %hi(0x10A6), %o2 408 or %o2, %lo(0x10A6), %o2 409 stha %o2, [%o1]ASI_IO 410 411 mov 1, %l7 ! FMEM is issued 412 413 add %l0, SCF_STATUS, %o1 414 sethi %hi(SCF_STATUS_READY), %o2 415 mov SCF_STATUS_CMD_COMPLETE, %o3 416 417 /* read STATUS_READY bit and clear it only if it is set */ 418 /* XXX: this STATUS_READY checking seems meaningless */ 4193: 420 lduha [%o1]ASI_IO, %o4 421 btst %o2, %o4 422 be %xcc, 4f ! STATUS_READY is not set 423 nop 424 stha %o2, [%o1]ASI_IO ! Clear if the bit is set 425 426 /* check CMD_COMPLETE bit and clear */ 4274: 428 btst %o3, %o4 429 be %xcc, 5f ! CMD_COMPLETE is not set 430 nop 431 stha %o3, [%o1]ASI_IO ! Now we are done and clear it 432 ba %xcc, 6f 433 mov ESBD_NOERROR, %o4 434 435 /* timeout delay checking */ 4365: 437 rd STICK, %l2 438 cmp %l5, %l2 439 bge %xcc, 3b 440 nop 441 set EOPL_FMEM_TIMEOUT, %o4 442 443 /* we are done or timed out */ 4446: 445 ba,a 1b 446 nop 447 SET_SIZE(drmach_fmem_exec_script) 448#endif /* lint */ 449 450#if defined(lint) 451/*ARGSUSED*/ 452void 453drmach_fmem_exec_script_end(caddr_t critical, int size) 454{ return; } 455#else /* lint */ 456 ENTRY_NP(drmach_fmem_exec_script_end) 457 nop 458 SET_SIZE(drmach_fmem_exec_script_end) 459#endif /* lint */ 460 461#if defined(lint) 462uint64_t 463patch_inst(uint64_t *x, uint64_t y) 464{ 465 *x = y; 466 return (0); 467} 468 469#else /* lint */ 470 471 ENTRY_NP(patch_inst) 472 ldx [%o0], %o2 473 casx [%o0], %o2, %o1 474 flush %o0 475 membar #Sync 476 ldx [%o0], %o2 477 retl 478 mov %o2, %o0 479 SET_SIZE(patch_inst) 480 481#endif /* lint */ 482 483#if defined(lint) 484void 485drmach_sys_trap() 486{ 487} 488#else /* lint */ 489 ENTRY_NP(drmach_sys_trap) 490 mov -1, %g4 491 set sys_trap, %g5 492 jmp %g5 493 nop 494 SET_SIZE(drmach_sys_trap) 495#endif /* lint */ 496 497#if defined(lint) 498uint64_t 499drmach_get_stick() 500{ 501 return (0); 502} 503#else /* lint */ 504 ENTRY_NP(drmach_get_stick) 505 retl 506 rd STICK, %o0 507 SET_SIZE(drmach_get_stick) 508#endif /* lint */ 509 510#if defined(lint) 511/*ARGSUSED*/ 512void 513drmach_flush(void) 514{} 515 516#else /* lint */ 517 ENTRY_NP(drmach_flush) 518 mov %o0, %o2 5190: 520 flush %o2 521 sub %o1, 8, %o1 522 brnz %o1, 0b 523 add %o2, 8, %o2 524 retl 525 nop 526 SET_SIZE(drmach_flush) 527#endif /* lint */ 528