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.
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.
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]
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
29 * General machine architecture & implementation specific
30 * assembly language routines.
33 #include <sys/types.h>
34 #include <sys/machsystm.h>
35 #include <sys/t_lock.h>
40 #include <sys/asm_linkage.h>
41 #include <sys/async.h>
42 #include <sys/machthread.h>
44 #include <sys/machsig.h>
59 wrpr
%g0
, WSTATE_KERN
, %wstate
60 SET_SIZE
(set_trap_table
)
68 stphys
(uint64_t physaddr
, int value
)
73 ldphys
(uint64_t physaddr
)
78 stdphys
(uint64_t physaddr
, uint64_t value
)
83 lddphys
(uint64_t physaddr
)
88 stphysio
(u_longlong_t physaddr
, uint_t value
)
93 ldphysio
(u_longlong_t physaddr
)
98 sthphysio
(u_longlong_t physaddr
, ushort_t value
)
103 ldhphysio
(u_longlong_t physaddr
)
108 stbphysio
(u_longlong_t physaddr
, uchar_t value
)
113 ldbphysio
(u_longlong_t physaddr
)
118 stdphysio
(u_longlong_t physaddr
, u_longlong_t value
)
123 lddphysio
(u_longlong_t physaddr
)
128 ! Store long word value at physical address
130 ! void stdphys
(uint64_t physaddr
, uint64_t value
)
134 * disable interrupts, clear Address Mask to access 64 bit physaddr
137 andn
%o4
, PSTATE_IE | PSTATE_AM
, %o5
139 stxa
%o1
, [%o0
]ASI_MEM
141 wrpr
%g0
, %o4
, %pstate
! restore earlier pstate register value
145 ! Store long word value at physical i
/o address
147 ! void stdphysio
(u_longlong_t physaddr
, u_longlong_t value
)
151 * disable interrupts, clear Address Mask to access 64 bit physaddr
154 andn
%o4
, PSTATE_IE | PSTATE_AM
, %o5
155 wrpr
%o5
, 0, %pstate
! clear IE
, AM bits
156 stxa
%o1
, [%o0
]ASI_IO
158 wrpr
%g0
, %o4
, %pstate
! restore earlier pstate register value
163 ! Load long word value at physical address
165 ! uint64_t lddphys
(uint64_t physaddr
)
169 andn
%o4
, PSTATE_IE | PSTATE_AM
, %o5
171 ldxa
[%o0
]ASI_MEM
, %o0
173 wrpr
%g0
, %o4
, %pstate
! restore earlier pstate register value
177 ! Load long word value at physical i
/o address
179 ! unsigned long long lddphysio
(u_longlong_t physaddr
)
183 andn
%o4
, PSTATE_IE | PSTATE_AM
, %o5
184 wrpr
%o5
, 0, %pstate
! clear IE
, AM bits
185 ldxa
[%o0
]ASI_IO
, %o0
187 wrpr
%g0
, %o4
, %pstate
! restore earlier pstate register value
191 ! Store value at physical address
193 ! void stphys
(uint64_t physaddr
, int value
)
197 andn
%o4
, PSTATE_IE | PSTATE_AM
, %o5
199 sta
%o1
, [%o0
]ASI_MEM
201 wrpr
%g0
, %o4
, %pstate
! restore earlier pstate register value
206 ! load value at physical address
208 ! int ldphys
(uint64_t physaddr
)
212 andn
%o4
, PSTATE_IE | PSTATE_AM
, %o5
214 lda
[%o0
]ASI_MEM
, %o0
215 srl
%o0
, 0, %o0
! clear upper
32 bits
217 wrpr
%g0
, %o4
, %pstate
! restore earlier pstate register value
221 ! Store value into physical address in I
/O space
223 ! void stphysio
(u_longlong_t physaddr
, uint_t value
)
226 rdpr
%pstate
, %o4
/* read PSTATE reg */
227 andn
%o4
, PSTATE_IE | PSTATE_AM
, %o5
229 stwa
%o1
, [%o0
]ASI_IO
/* store value via bypass ASI */
231 wrpr
%g0
, %o4
, %pstate
/* restore the PSTATE */
235 ! Store value into physical address in I
/O space
237 ! void sthphysio
(u_longlong_t physaddr
, ushort_t value
)
240 rdpr
%pstate
, %o4
/* read PSTATE reg */
241 andn
%o4
, PSTATE_IE | PSTATE_AM
, %o5
243 stha
%o1
, [%o0
]ASI_IO
/* store value via bypass ASI */
245 wrpr
%g0
, %o4
, %pstate
/* restore the PSTATE */
249 ! Store value into one byte physical address in I
/O space
251 ! void stbphysio
(u_longlong_t physaddr
, uchar_t value
)
254 rdpr
%pstate
, %o4
/* read PSTATE reg */
255 andn
%o4
, PSTATE_IE | PSTATE_AM
, %o5
257 stba
%o1
, [%o0
]ASI_IO
/* store byte via bypass ASI */
259 wrpr
%g0
, %o4
, %pstate
/* restore the PSTATE */
263 ! load value at physical address in I
/O space
265 ! uint_t ldphysio
(u_longlong_t physaddr
)
268 rdpr
%pstate
, %o4
/* read PSTATE reg */
269 andn
%o4
, PSTATE_IE | PSTATE_AM
, %o5
271 lduwa
[%o0
]ASI_IO
, %o0
/* load value via bypass ASI */
273 wrpr
%g0
, %o4
, %pstate
/* restore pstate */
277 ! load value at physical address in I
/O space
279 ! ushort_t ldhphysio
(u_longlong_t physaddr
)
282 rdpr
%pstate
, %o4
/* read PSTATE reg */
283 andn
%o4
, PSTATE_IE | PSTATE_AM
, %o5
285 lduha
[%o0
]ASI_IO
, %o0
/* load value via bypass ASI */
287 wrpr
%g0
, %o4
, %pstate
/* restore pstate */
291 ! load byte value at physical address in I
/O space
293 ! uchar_t ldbphysio
(u_longlong_t physaddr
)
296 rdpr
%pstate
, %o4
/* read PSTATE reg */
297 andn
%o4
, PSTATE_IE | PSTATE_AM
, %o5
299 lduba
[%o0
]ASI_IO
, %o0
/* load value via bypass ASI */
301 wrpr
%g0
, %o4
, %pstate
/* restore pstate */
306 * save_gsr(kfpu_t *fp)
307 * Store the graphics status register
310 #if defined(lint) || defined(__lint)
320 rd
%gsr
, %g2
! save gsr
322 stx %g2
, [%o0
+ FPU_GSR
]
327 #if defined(lint) || defined(__lint)
331 restore_gsr
(kfpu_t
*fp
)
336 ENTRY_NP
(restore_gsr
)
337 ldx [%o0
+ FPU_GSR
], %g2
341 SET_SIZE
(restore_gsr
)
348 * Get the graphics status register info from fp and return it
351 #if defined(lint) || defined(__lint)
355 _fp_read_pgsr
(kfpu_t
*fp
)
360 ENTRY_NP
(_fp_read_pgsr
)
363 SET_SIZE
(_fp_read_pgsr
)
370 * get_gsr(kfpu_t *fp)
371 * Get the graphics status register info from fp and return it
374 #if defined(lint) || defined(__lint)
385 ldx [%o0
+ FPU_GSR
], %o0
391 * _fp_write_pgsr(uint64_t *buf, kfpu_t *fp)
392 * Set the graphics status register info to fp from buf
395 #if defined(lint) || defined(__lint)
399 _fp_write_pgsr
(uint64_t buf
, kfpu_t
*fp
)
404 ENTRY_NP
(_fp_write_pgsr
)
407 SET_SIZE
(_fp_write_pgsr
)
412 * set_gsr(uint64_t buf, kfpu_t *fp)
413 * Set the graphics status register info to fp from buf
416 #if defined(lint) || defined(__lint)
420 set_gsr
(uint64_t buf
, kfpu_t
*fp
)
427 stx %o0
, [%o1
+ FPU_GSR
]
432 #if defined(lint) || defined(__lint)
440 ENTRY_NP
(kdi_cpu_index
)
444 SET_SIZE
(kdi_cpu_index
)
448 #if defined(lint) || defined(__lint)
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.
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!
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.
490 * fp_save(kfpu_t *fp)
491 * fp_fksave(kfpu_t *fp)
492 * Store the floating point registers.
495 #if defined(lint) || defined(__lint)
504 fp_fksave
(kfpu_t
*fp
)
511 BSTORE_FPREGS
(%o0
, %o1
) ! store V9 regs
513 stx %fsr
, [%o0
+ FPU_FSR
] ! store fsr
520 * fp_v8_fksave(kfpu_t *fp)
522 * This is like the above routine but only saves the lower half.
525 #if defined(lint) || defined(__lint)
529 fp_v8_fksave
(kfpu_t
*fp
)
534 ENTRY_NP
(fp_v8_fksave
)
535 BSTORE_V8_FPREGS
(%o0
, %o1
) ! store V8 regs
537 stx %fsr
, [%o0
+ FPU_FSR
] ! store fsr
538 SET_SIZE
(fp_v8_fksave
)
543 * fp_v8p_fksave(kfpu_t *fp)
545 * This is like the above routine but only saves the upper half.
548 #if defined(lint) || defined(__lint)
552 fp_v8p_fksave
(kfpu_t
*fp
)
557 ENTRY_NP
(fp_v8p_fksave
)
558 BSTORE_V8P_FPREGS
(%o0
, %o1
) ! store V9 extra regs
560 stx %fsr
, [%o0
+ FPU_FSR
] ! store fsr
561 SET_SIZE
(fp_v8p_fksave
)
566 * fp_restore(kfpu_t *fp)
569 #if defined(lint) || defined(__lint)
573 fp_restore
(kfpu_t
*fp
)
579 BLOAD_FPREGS
(%o0
, %o1
) ! load V9 regs
581 ldx [%o0
+ FPU_FSR
], %fsr
! restore fsr
587 * fp_v8_load(kfpu_t *fp)
590 #if defined(lint) || defined(__lint)
594 fp_v8_load
(kfpu_t
*fp
)
600 BLOAD_V8_FPREGS
(%o0
, %o1
) ! load V8 regs
602 ldx [%o0
+ FPU_FSR
], %fsr
! restore fsr
608 * fp_v8p_load(kfpu_t *fp)
611 #if defined(lint) || defined(__lint)
615 fp_v8p_load
(kfpu_t
*fp
)
620 ENTRY_NP
(fp_v8p_load
)
621 BLOAD_V8P_FPREGS
(%o0
, %o1
) ! load V9 extra regs
623 ldx [%o0
+ FPU_FSR
], %fsr
! restore fsr
624 SET_SIZE
(fp_v8p_load
)