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.
34 #include <sys/asm_linkage.h>
35 #include <sys/async.h>
36 #include <sys/machthread.h>
38 #include <sys/machsig.h>
46 wrpr
%g0
, WSTATE_KERN
, %wstate
47 SET_SIZE
(set_trap_table
)
51 ! Store long word value at physical address
53 ! void stdphys
(uint64_t physaddr
, uint64_t value
)
57 * disable interrupts, clear Address Mask to access 64 bit physaddr
60 andn
%o4
, PSTATE_IE | PSTATE_AM
, %o5
62 stxa
%o1
, [%o0
]ASI_MEM
64 wrpr
%g0
, %o4
, %pstate
! restore earlier pstate register value
68 ! Store long word value at physical i
/o address
70 ! void stdphysio
(u_longlong_t physaddr
, u_longlong_t value
)
74 * disable interrupts, clear Address Mask to access 64 bit physaddr
77 andn
%o4
, PSTATE_IE | PSTATE_AM
, %o5
78 wrpr
%o5
, 0, %pstate
! clear IE
, AM bits
81 wrpr
%g0
, %o4
, %pstate
! restore earlier pstate register value
86 ! Load long word value at physical address
88 ! uint64_t lddphys
(uint64_t physaddr
)
92 andn
%o4
, PSTATE_IE | PSTATE_AM
, %o5
94 ldxa
[%o0
]ASI_MEM
, %o0
96 wrpr
%g0
, %o4
, %pstate
! restore earlier pstate register value
100 ! Load long word value at physical i
/o address
102 ! unsigned long long lddphysio
(u_longlong_t physaddr
)
106 andn
%o4
, PSTATE_IE | PSTATE_AM
, %o5
107 wrpr
%o5
, 0, %pstate
! clear IE
, AM bits
108 ldxa
[%o0
]ASI_IO
, %o0
110 wrpr
%g0
, %o4
, %pstate
! restore earlier pstate register value
114 ! Store value at physical address
116 ! void stphys
(uint64_t physaddr
, int value
)
120 andn
%o4
, PSTATE_IE | PSTATE_AM
, %o5
122 sta
%o1
, [%o0
]ASI_MEM
124 wrpr
%g0
, %o4
, %pstate
! restore earlier pstate register value
129 ! load value at physical address
131 ! int ldphys
(uint64_t physaddr
)
135 andn
%o4
, PSTATE_IE | PSTATE_AM
, %o5
137 lda
[%o0
]ASI_MEM
, %o0
138 srl
%o0
, 0, %o0
! clear upper
32 bits
140 wrpr
%g0
, %o4
, %pstate
! restore earlier pstate register value
144 ! Store value into physical address in I
/O space
146 ! void stphysio
(u_longlong_t physaddr
, uint_t value
)
149 rdpr
%pstate
, %o4
/* read PSTATE reg */
150 andn
%o4
, PSTATE_IE | PSTATE_AM
, %o5
152 stwa
%o1
, [%o0
]ASI_IO
/* store value via bypass ASI */
154 wrpr
%g0
, %o4
, %pstate
/* restore the PSTATE */
158 ! Store value into physical address in I
/O space
160 ! void sthphysio
(u_longlong_t physaddr
, ushort_t value
)
163 rdpr
%pstate
, %o4
/* read PSTATE reg */
164 andn
%o4
, PSTATE_IE | PSTATE_AM
, %o5
166 stha
%o1
, [%o0
]ASI_IO
/* store value via bypass ASI */
168 wrpr
%g0
, %o4
, %pstate
/* restore the PSTATE */
172 ! Store value into one byte physical address in I
/O space
174 ! void stbphysio
(u_longlong_t physaddr
, uchar_t value
)
177 rdpr
%pstate
, %o4
/* read PSTATE reg */
178 andn
%o4
, PSTATE_IE | PSTATE_AM
, %o5
180 stba
%o1
, [%o0
]ASI_IO
/* store byte via bypass ASI */
182 wrpr
%g0
, %o4
, %pstate
/* restore the PSTATE */
186 ! load value at physical address in I
/O space
188 ! uint_t ldphysio
(u_longlong_t physaddr
)
191 rdpr
%pstate
, %o4
/* read PSTATE reg */
192 andn
%o4
, PSTATE_IE | PSTATE_AM
, %o5
194 lduwa
[%o0
]ASI_IO
, %o0
/* load value via bypass ASI */
196 wrpr
%g0
, %o4
, %pstate
/* restore pstate */
200 ! load value at physical address in I
/O space
202 ! ushort_t ldhphysio
(u_longlong_t physaddr
)
205 rdpr
%pstate
, %o4
/* read PSTATE reg */
206 andn
%o4
, PSTATE_IE | PSTATE_AM
, %o5
208 lduha
[%o0
]ASI_IO
, %o0
/* load value via bypass ASI */
210 wrpr
%g0
, %o4
, %pstate
/* restore pstate */
214 ! load byte value at physical address in I
/O space
216 ! uchar_t ldbphysio
(u_longlong_t physaddr
)
219 rdpr
%pstate
, %o4
/* read PSTATE reg */
220 andn
%o4
, PSTATE_IE | PSTATE_AM
, %o5
222 lduba
[%o0
]ASI_IO
, %o0
/* load value via bypass ASI */
224 wrpr
%g0
, %o4
, %pstate
/* restore pstate */
228 * save_gsr(kfpu_t *fp)
229 * Store the graphics status register
234 rd
%gsr
, %g2
! save gsr
236 stx %g2
, [%o0
+ FPU_GSR
]
241 ENTRY_NP
(restore_gsr
)
242 ldx [%o0
+ FPU_GSR
], %g2
246 SET_SIZE
(restore_gsr
)
252 * Get the graphics status register info from fp and return it
256 ENTRY_NP
(_fp_read_pgsr
)
259 SET_SIZE
(_fp_read_pgsr
)
265 * get_gsr(kfpu_t *fp)
266 * Get the graphics status register info from fp and return it
272 ldx [%o0
+ FPU_GSR
], %o0
277 * _fp_write_pgsr(uint64_t *buf, kfpu_t *fp)
278 * Set the graphics status register info to fp from buf
282 ENTRY_NP
(_fp_write_pgsr
)
285 SET_SIZE
(_fp_write_pgsr
)
289 * set_gsr(uint64_t buf, kfpu_t *fp)
290 * Set the graphics status register info to fp from buf
296 stx %o0
, [%o1
+ FPU_GSR
]
301 ENTRY_NP
(kdi_cpu_index
)
305 SET_SIZE
(kdi_cpu_index
)
317 * The Spitfire floating point code has been changed not to use install/
318 * save/restore/fork/freectx() because of the special memcpy library
319 * routines, which will lose too much performance if they have to go
320 * through the fp_disabled trap (which used to call installctx()). So
321 * now fp_save/fp_restore are called from resume, and they don't care
322 * whether floating point was enabled from the user program via the
323 * fp_enabled trap or from the memcpy library, which just turns on floating
324 * point in the fprs register itself. The new routine lwp_freeregs is
325 * called everywhere freectx is called, and code was added to the sun4u-
326 * specific version of lwp_forkregs (which is called everywhere forkctx
327 * is called) to handle forking the floating point registers.
329 * Note that for the fprs dirty upper/lower bits are not used for now,
330 * because the #instructions to determine if we need to use them is probably
331 * greater than the #insructions just using them. This is a possible future
332 * optimization, only do it with very careful benchmarking!
334 * The fp_fksave and and fp_load were split into two routines for the
335 * sake of efficiency between the getfpregs/xregs_getfpregs and
336 * setfpregs/xregs_setfpregs. But note that for saving and restoring
337 * context, both *must* happen. For prmachdep, aka access from [k]adb,
338 * it's OK if only one part happens.
342 * fp_save(kfpu_t *fp)
343 * fp_fksave(kfpu_t *fp)
344 * Store the floating point registers.
350 BSTORE_FPREGS
(%o0
, %o1
) ! store V9 regs
352 stx %fsr
, [%o0
+ FPU_FSR
] ! store fsr
358 * fp_v8_fksave(kfpu_t *fp)
360 * This is like the above routine but only saves the lower half.
364 ENTRY_NP
(fp_v8_fksave
)
365 BSTORE_V8_FPREGS
(%o0
, %o1
) ! store V8 regs
367 stx %fsr
, [%o0
+ FPU_FSR
] ! store fsr
368 SET_SIZE
(fp_v8_fksave
)
372 * fp_v8p_fksave(kfpu_t *fp)
374 * This is like the above routine but only saves the upper half.
378 ENTRY_NP
(fp_v8p_fksave
)
379 BSTORE_V8P_FPREGS
(%o0
, %o1
) ! store V9 extra regs
381 stx %fsr
, [%o0
+ FPU_FSR
] ! store fsr
382 SET_SIZE
(fp_v8p_fksave
)
386 * fp_restore(kfpu_t *fp)
391 BLOAD_FPREGS
(%o0
, %o1
) ! load V9 regs
393 ldx [%o0
+ FPU_FSR
], %fsr
! restore fsr
398 * fp_v8_load(kfpu_t *fp)
403 BLOAD_V8_FPREGS
(%o0
, %o1
) ! load V8 regs
405 ldx [%o0
+ FPU_FSR
], %fsr
! restore fsr
410 * fp_v8p_load(kfpu_t *fp)
414 ENTRY_NP
(fp_v8p_load
)
415 BLOAD_V8P_FPREGS
(%o0
, %o1
) ! load V9 extra regs
417 ldx [%o0
+ FPU_FSR
], %fsr
! restore fsr
418 SET_SIZE
(fp_v8p_load
)