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