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 * General machine architecture & implementation specific 30 * assembly language routines. 31 */ 32 #if defined(lint) 33 #include <sys/types.h> 34 #include <sys/machsystm.h> 35 #include <sys/t_lock.h> 36 #else /* lint */ 37 #include "assym.h" 38 #endif /* lint */ 39 40 #include <sys/asm_linkage.h> 41 #include <sys/async.h> 42 #include <sys/machthread.h> 43 #include <sys/vis.h> 44 #include <sys/machsig.h> 45 46 #if defined(lint) 47 caddr_t 48 set_trap_table(void) 49 { 50 return ((caddr_t)0); 51 } 52 #else /* lint */ 53 54 ENTRY(set_trap_table) 55 set trap_table, %o1 56 rdpr %tba, %o0 57 wrpr %o1, %tba 58 retl 59 wrpr %g0, WSTATE_KERN, %wstate 60 SET_SIZE(set_trap_table) 61 62 #endif /* lint */ 63 64 #if defined(lint) 65 66 /*ARGSUSED*/ 67 void 68 stphys(uint64_t physaddr, int value) 69 {} 70 71 /*ARGSUSED*/ 72 int 73 ldphys(uint64_t physaddr) 74 { return (0); } 75 76 /*ARGSUSED*/ 77 void 78 stdphys(uint64_t physaddr, uint64_t value) 79 {} 80 81 /*ARGSUSED*/ 82 uint64_t 83 lddphys(uint64_t physaddr) 84 { return (0x0ull); } 85 86 /* ARGSUSED */ 87 void 88 stphysio(u_longlong_t physaddr, uint_t value) 89 {} 90 91 /* ARGSUSED */ 92 uint_t 93 ldphysio(u_longlong_t physaddr) 94 { return(0); } 95 96 /* ARGSUSED */ 97 void 98 sthphysio(u_longlong_t physaddr, ushort_t value) 99 {} 100 101 /* ARGSUSED */ 102 ushort_t 103 ldhphysio(u_longlong_t physaddr) 104 { return(0); } 105 106 /* ARGSUSED */ 107 void 108 stbphysio(u_longlong_t physaddr, uchar_t value) 109 {} 110 111 /* ARGSUSED */ 112 uchar_t 113 ldbphysio(u_longlong_t physaddr) 114 { return(0); } 115 116 /*ARGSUSED*/ 117 void 118 stdphysio(u_longlong_t physaddr, u_longlong_t value) 119 {} 120 121 /*ARGSUSED*/ 122 u_longlong_t 123 lddphysio(u_longlong_t physaddr) 124 { return (0ull); } 125 126 #else 127 128 ! Store long word value at physical address 129 ! 130 ! void stdphys(uint64_t physaddr, uint64_t value) 131 ! 132 ENTRY(stdphys) 133 /* 134 * disable interrupts, clear Address Mask to access 64 bit physaddr 135 */ 136 rdpr %pstate, %o4 137 andn %o4, PSTATE_IE | PSTATE_AM, %o5 138 wrpr %o5, 0, %pstate 139 stxa %o1, [%o0]ASI_MEM 140 retl 141 wrpr %g0, %o4, %pstate ! restore earlier pstate register value 142 SET_SIZE(stdphys) 143 144 145 ! Store long word value at physical i/o address 146 ! 147 ! void stdphysio(u_longlong_t physaddr, u_longlong_t value) 148 ! 149 ENTRY(stdphysio) 150 /* 151 * disable interrupts, clear Address Mask to access 64 bit physaddr 152 */ 153 rdpr %pstate, %o4 154 andn %o4, PSTATE_IE | PSTATE_AM, %o5 155 wrpr %o5, 0, %pstate ! clear IE, AM bits 156 stxa %o1, [%o0]ASI_IO 157 retl 158 wrpr %g0, %o4, %pstate ! restore earlier pstate register value 159 SET_SIZE(stdphysio) 160 161 162 ! 163 ! Load long word value at physical address 164 ! 165 ! uint64_t lddphys(uint64_t physaddr) 166 ! 167 ENTRY(lddphys) 168 rdpr %pstate, %o4 169 andn %o4, PSTATE_IE | PSTATE_AM, %o5 170 wrpr %o5, 0, %pstate 171 ldxa [%o0]ASI_MEM, %o0 172 retl 173 wrpr %g0, %o4, %pstate ! restore earlier pstate register value 174 SET_SIZE(lddphys) 175 176 ! 177 ! Load long word value at physical i/o address 178 ! 179 ! unsigned long long lddphysio(u_longlong_t physaddr) 180 ! 181 ENTRY(lddphysio) 182 rdpr %pstate, %o4 183 andn %o4, PSTATE_IE | PSTATE_AM, %o5 184 wrpr %o5, 0, %pstate ! clear IE, AM bits 185 ldxa [%o0]ASI_IO, %o0 186 retl 187 wrpr %g0, %o4, %pstate ! restore earlier pstate register value 188 SET_SIZE(lddphysio) 189 190 ! 191 ! Store value at physical address 192 ! 193 ! void stphys(uint64_t physaddr, int value) 194 ! 195 ENTRY(stphys) 196 rdpr %pstate, %o4 197 andn %o4, PSTATE_IE | PSTATE_AM, %o5 198 wrpr %o5, 0, %pstate 199 sta %o1, [%o0]ASI_MEM 200 retl 201 wrpr %g0, %o4, %pstate ! restore earlier pstate register value 202 SET_SIZE(stphys) 203 204 205 ! 206 ! load value at physical address 207 ! 208 ! int ldphys(uint64_t physaddr) 209 ! 210 ENTRY(ldphys) 211 rdpr %pstate, %o4 212 andn %o4, PSTATE_IE | PSTATE_AM, %o5 213 wrpr %o5, 0, %pstate 214 lda [%o0]ASI_MEM, %o0 215 srl %o0, 0, %o0 ! clear upper 32 bits 216 retl 217 wrpr %g0, %o4, %pstate ! restore earlier pstate register value 218 SET_SIZE(ldphys) 219 220 ! 221 ! Store value into physical address in I/O space 222 ! 223 ! void stphysio(u_longlong_t physaddr, uint_t value) 224 ! 225 ENTRY_NP(stphysio) 226 rdpr %pstate, %o4 /* read PSTATE reg */ 227 andn %o4, PSTATE_IE | PSTATE_AM, %o5 228 wrpr %o5, 0, %pstate 229 stwa %o1, [%o0]ASI_IO /* store value via bypass ASI */ 230 retl 231 wrpr %g0, %o4, %pstate /* restore the PSTATE */ 232 SET_SIZE(stphysio) 233 234 ! 235 ! Store value into physical address in I/O space 236 ! 237 ! void sthphysio(u_longlong_t physaddr, ushort_t value) 238 ! 239 ENTRY_NP(sthphysio) 240 rdpr %pstate, %o4 /* read PSTATE reg */ 241 andn %o4, PSTATE_IE | PSTATE_AM, %o5 242 wrpr %o5, 0, %pstate 243 stha %o1, [%o0]ASI_IO /* store value via bypass ASI */ 244 retl 245 wrpr %g0, %o4, %pstate /* restore the PSTATE */ 246 SET_SIZE(sthphysio) 247 248 ! 249 ! Store value into one byte physical address in I/O space 250 ! 251 ! void stbphysio(u_longlong_t physaddr, uchar_t value) 252 ! 253 ENTRY_NP(stbphysio) 254 rdpr %pstate, %o4 /* read PSTATE reg */ 255 andn %o4, PSTATE_IE | PSTATE_AM, %o5 256 wrpr %o5, 0, %pstate 257 stba %o1, [%o0]ASI_IO /* store byte via bypass ASI */ 258 retl 259 wrpr %g0, %o4, %pstate /* restore the PSTATE */ 260 SET_SIZE(stbphysio) 261 262 ! 263 ! load value at physical address in I/O space 264 ! 265 ! uint_t ldphysio(u_longlong_t physaddr) 266 ! 267 ENTRY_NP(ldphysio) 268 rdpr %pstate, %o4 /* read PSTATE reg */ 269 andn %o4, PSTATE_IE | PSTATE_AM, %o5 270 wrpr %o5, 0, %pstate 271 lduwa [%o0]ASI_IO, %o0 /* load value via bypass ASI */ 272 retl 273 wrpr %g0, %o4, %pstate /* restore pstate */ 274 SET_SIZE(ldphysio) 275 276 ! 277 ! load value at physical address in I/O space 278 ! 279 ! ushort_t ldhphysio(u_longlong_t physaddr) 280 ! 281 ENTRY_NP(ldhphysio) 282 rdpr %pstate, %o4 /* read PSTATE reg */ 283 andn %o4, PSTATE_IE | PSTATE_AM, %o5 284 wrpr %o5, 0, %pstate 285 lduha [%o0]ASI_IO, %o0 /* load value via bypass ASI */ 286 retl 287 wrpr %g0, %o4, %pstate /* restore pstate */ 288 SET_SIZE(ldhphysio) 289 290 ! 291 ! load byte value at physical address in I/O space 292 ! 293 ! uchar_t ldbphysio(u_longlong_t physaddr) 294 ! 295 ENTRY_NP(ldbphysio) 296 rdpr %pstate, %o4 /* read PSTATE reg */ 297 andn %o4, PSTATE_IE | PSTATE_AM, %o5 298 wrpr %o5, 0, %pstate 299 lduba [%o0]ASI_IO, %o0 /* load value via bypass ASI */ 300 retl 301 wrpr %g0, %o4, %pstate /* restore pstate */ 302 SET_SIZE(ldbphysio) 303 #endif /* lint */ 304 305 /* 306 * save_gsr(kfpu_t *fp) 307 * Store the graphics status register 308 */ 309 310 #if defined(lint) || defined(__lint) 311 312 /* ARGSUSED */ 313 void 314 save_gsr(kfpu_t *fp) 315 {} 316 317 #else /* lint */ 318 319 ENTRY_NP(save_gsr) 320 rd %gsr, %g2 ! save gsr 321 retl 322 stx %g2, [%o0 + FPU_GSR] 323 SET_SIZE(save_gsr) 324 325 #endif /* lint */ 326 327 #if defined(lint) || defined(__lint) 328 329 /* ARGSUSED */ 330 void 331 restore_gsr(kfpu_t *fp) 332 {} 333 334 #else /* lint */ 335 336 ENTRY_NP(restore_gsr) 337 ldx [%o0 + FPU_GSR], %g2 338 wr %g2, %g0, %gsr 339 retl 340 nop 341 SET_SIZE(restore_gsr) 342 343 #endif /* lint */ 344 345 /* 346 * uint64_t 347 * _fp_read_pgsr() 348 * Get the graphics status register info from fp and return it 349 */ 350 351 #if defined(lint) || defined(__lint) 352 353 /* ARGSUSED */ 354 uint64_t 355 _fp_read_pgsr(kfpu_t *fp) 356 { return 0; } 357 358 #else /* lint */ 359 360 ENTRY_NP(_fp_read_pgsr) 361 retl 362 rd %gsr, %o0 363 SET_SIZE(_fp_read_pgsr) 364 365 #endif /* lint */ 366 367 368 /* 369 * uint64_t 370 * get_gsr(kfpu_t *fp) 371 * Get the graphics status register info from fp and return it 372 */ 373 374 #if defined(lint) || defined(__lint) 375 376 /* ARGSUSED */ 377 uint64_t 378 get_gsr(kfpu_t *fp) 379 { return 0; } 380 381 #else /* lint */ 382 383 ENTRY_NP(get_gsr) 384 retl 385 ldx [%o0 + FPU_GSR], %o0 386 SET_SIZE(get_gsr) 387 388 #endif 389 390 /* 391 * _fp_write_pgsr(uint64_t *buf, kfpu_t *fp) 392 * Set the graphics status register info to fp from buf 393 */ 394 395 #if defined(lint) || defined(__lint) 396 397 /* ARGSUSED */ 398 void 399 _fp_write_pgsr(uint64_t buf, kfpu_t *fp) 400 {} 401 402 #else /* lint */ 403 404 ENTRY_NP(_fp_write_pgsr) 405 retl 406 mov %o0, %gsr 407 SET_SIZE(_fp_write_pgsr) 408 409 #endif /* lint */ 410 411 /* 412 * set_gsr(uint64_t buf, kfpu_t *fp) 413 * Set the graphics status register info to fp from buf 414 */ 415 416 #if defined(lint) || defined(__lint) 417 418 /* ARGSUSED */ 419 void 420 set_gsr(uint64_t buf, kfpu_t *fp) 421 {} 422 423 #else /* lint */ 424 425 ENTRY_NP(set_gsr) 426 retl 427 stx %o0, [%o1 + FPU_GSR] 428 SET_SIZE(set_gsr) 429 430 #endif /* lint */ 431 432 #if defined(lint) || defined(__lint) 433 void 434 kdi_cpu_index(void) 435 { 436 } 437 438 #else /* lint */ 439 440 ENTRY_NP(kdi_cpu_index) 441 CPU_INDEX(%g1, %g2) 442 jmp %g7 443 nop 444 SET_SIZE(kdi_cpu_index) 445 446 #endif /* lint */ 447 448 #if defined(lint) || defined(__lint) 449 void 450 kmdb_enter(void) 451 { 452 } 453 454 #else /* lint */ 455 456 ENTRY_NP(kmdb_enter) 457 t ST_KMDB_TRAP 458 retl 459 nop 460 SET_SIZE(kmdb_enter) 461 462 #endif /* lint */ 463 464 /* 465 * The Spitfire floating point code has been changed not to use install/ 466 * save/restore/fork/freectx() because of the special memcpy library 467 * routines, which will lose too much performance if they have to go 468 * through the fp_disabled trap (which used to call installctx()). So 469 * now fp_save/fp_restore are called from resume, and they don't care 470 * whether floating point was enabled from the user program via the 471 * fp_enabled trap or from the memcpy library, which just turns on floating 472 * point in the fprs register itself. The new routine lwp_freeregs is 473 * called everywhere freectx is called, and code was added to the sun4u- 474 * specific version of lwp_forkregs (which is called everywhere forkctx 475 * is called) to handle forking the floating point registers. 476 * 477 * Note that for the fprs dirty upper/lower bits are not used for now, 478 * because the #instructions to determine if we need to use them is probably 479 * greater than the #insructions just using them. This is a possible future 480 * optimization, only do it with very careful benchmarking! 481 * 482 * The fp_fksave and and fp_load were split into two routines for the 483 * sake of efficiency between the getfpregs/xregs_getfpregs and 484 * setfpregs/xregs_setfpregs. But note that for saving and restoring 485 * context, both *must* happen. For prmachdep, aka access from [k]adb, 486 * it's OK if only one part happens. 487 */ 488 489 /* 490 * fp_save(kfpu_t *fp) 491 * fp_fksave(kfpu_t *fp) 492 * Store the floating point registers. 493 */ 494 495 #if defined(lint) || defined(__lint) 496 497 /* ARGSUSED */ 498 void 499 fp_save(kfpu_t *fp) 500 {} 501 502 /* ARGSUSED */ 503 void 504 fp_fksave(kfpu_t *fp) 505 {} 506 507 #else /* lint */ 508 509 ENTRY_NP(fp_save) 510 ALTENTRY(fp_fksave) 511 BSTORE_FPREGS(%o0, %o1) ! store V9 regs 512 retl 513 stx %fsr, [%o0 + FPU_FSR] ! store fsr 514 SET_SIZE(fp_fksave) 515 SET_SIZE(fp_save) 516 517 #endif /* lint */ 518 519 /* 520 * fp_v8_fksave(kfpu_t *fp) 521 * 522 * This is like the above routine but only saves the lower half. 523 */ 524 525 #if defined(lint) || defined(__lint) 526 527 /* ARGSUSED */ 528 void 529 fp_v8_fksave(kfpu_t *fp) 530 {} 531 532 #else /* lint */ 533 534 ENTRY_NP(fp_v8_fksave) 535 BSTORE_V8_FPREGS(%o0, %o1) ! store V8 regs 536 retl 537 stx %fsr, [%o0 + FPU_FSR] ! store fsr 538 SET_SIZE(fp_v8_fksave) 539 540 #endif /* lint */ 541 542 /* 543 * fp_v8p_fksave(kfpu_t *fp) 544 * 545 * This is like the above routine but only saves the upper half. 546 */ 547 548 #if defined(lint) || defined(__lint) 549 550 /* ARGSUSED */ 551 void 552 fp_v8p_fksave(kfpu_t *fp) 553 {} 554 555 #else /* lint */ 556 557 ENTRY_NP(fp_v8p_fksave) 558 BSTORE_V8P_FPREGS(%o0, %o1) ! store V9 extra regs 559 retl 560 stx %fsr, [%o0 + FPU_FSR] ! store fsr 561 SET_SIZE(fp_v8p_fksave) 562 563 #endif /* lint */ 564 565 /* 566 * fp_restore(kfpu_t *fp) 567 */ 568 569 #if defined(lint) || defined(__lint) 570 571 /* ARGSUSED */ 572 void 573 fp_restore(kfpu_t *fp) 574 {} 575 576 #else /* lint */ 577 578 ENTRY_NP(fp_restore) 579 BLOAD_FPREGS(%o0, %o1) ! load V9 regs 580 retl 581 ldx [%o0 + FPU_FSR], %fsr ! restore fsr 582 SET_SIZE(fp_restore) 583 584 #endif /* lint */ 585 586 /* 587 * fp_v8_load(kfpu_t *fp) 588 */ 589 590 #if defined(lint) || defined(__lint) 591 592 /* ARGSUSED */ 593 void 594 fp_v8_load(kfpu_t *fp) 595 {} 596 597 #else /* lint */ 598 599 ENTRY_NP(fp_v8_load) 600 BLOAD_V8_FPREGS(%o0, %o1) ! load V8 regs 601 retl 602 ldx [%o0 + FPU_FSR], %fsr ! restore fsr 603 SET_SIZE(fp_v8_load) 604 605 #endif /* lint */ 606 607 /* 608 * fp_v8p_load(kfpu_t *fp) 609 */ 610 611 #if defined(lint) || defined(__lint) 612 613 /* ARGSUSED */ 614 void 615 fp_v8p_load(kfpu_t *fp) 616 {} 617 618 #else /* lint */ 619 620 ENTRY_NP(fp_v8p_load) 621 BLOAD_V8P_FPREGS(%o0, %o1) ! load V9 extra regs 622 retl 623 ldx [%o0 + FPU_FSR], %fsr ! restore fsr 624 SET_SIZE(fp_v8p_load) 625 626 #endif /* lint */