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) 47caddr_t 48set_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*/ 67void 68stphys(uint64_t physaddr, int value) 69{} 70 71/*ARGSUSED*/ 72int 73ldphys(uint64_t physaddr) 74{ return (0); } 75 76/*ARGSUSED*/ 77void 78stdphys(uint64_t physaddr, uint64_t value) 79{} 80 81/*ARGSUSED*/ 82uint64_t 83lddphys(uint64_t physaddr) 84{ return (0x0ull); } 85 86/* ARGSUSED */ 87void 88stphysio(u_longlong_t physaddr, uint_t value) 89{} 90 91/* ARGSUSED */ 92uint_t 93ldphysio(u_longlong_t physaddr) 94{ return(0); } 95 96/* ARGSUSED */ 97void 98sthphysio(u_longlong_t physaddr, ushort_t value) 99{} 100 101/* ARGSUSED */ 102ushort_t 103ldhphysio(u_longlong_t physaddr) 104{ return(0); } 105 106/* ARGSUSED */ 107void 108stbphysio(u_longlong_t physaddr, uchar_t value) 109{} 110 111/* ARGSUSED */ 112uchar_t 113ldbphysio(u_longlong_t physaddr) 114{ return(0); } 115 116/*ARGSUSED*/ 117void 118stdphysio(u_longlong_t physaddr, u_longlong_t value) 119{} 120 121/*ARGSUSED*/ 122u_longlong_t 123lddphysio(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 */ 313void 314save_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 */ 330void 331restore_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 */ 354uint64_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 */ 377uint64_t 378get_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 */ 398void 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 */ 419void 420set_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) 433void 434kdi_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) 449void 450kmdb_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 */ 498void 499fp_save(kfpu_t *fp) 500{} 501 502/* ARGSUSED */ 503void 504fp_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 */ 528void 529fp_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 */ 551void 552fp_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 */ 572void 573fp_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 */ 593void 594fp_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 */ 614void 615fp_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 */ 627