Home | History | Annotate | Download | only in ml
      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 */
    627