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 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * General machine architecture & implementation specific
28 * assembly language routines.
31 #include <sys/types.h>
32 #include <sys/t_lock.h>
37 #include <sys/asm_linkage.h>
38 #include <sys/machsystm.h>
39 #include <sys/machthread.h>
40 #include <sys/privregs.h>
41 #include <sys/cmpregs.h>
42 #include <sys/clock.h>
43 #include <sys/fpras.h>
54 * This isn't the routine you're looking for.
56 * The routine simply returns the value of %tick on the *current* processor.
57 * Most of the time, gettick() [which in turn maps to %stick on platforms
58 * that have different CPU %tick rates] is what you want.
64 SET_SIZE
(ultra_gettick
)
78 * Get the processor ID.
79 * === MID reg as specified in 15dec89 sun4u spec, sec 5.4.3
86 SET_SIZE
(getprocessorid
)
93 set_error_enable_tl1
(uint64_t neer
, uint64_t action
)
98 set_error_enable
(uint64_t neer
)
104 return
((uint64_t
)0);
108 ENTRY
(set_error_enable_tl1
)
109 cmp %g2
, EER_SET_ABSOLUTE
112 ldxa
[%g0
]ASI_ESTATE_ERR
, %g3
114 cmp %g2
, EER_SET_SETBITS
117 andn
%g3
, %g1
, %g1
/* EER_SET_CLRBITS */
119 stxa
%g1
, [%g0
]ASI_ESTATE_ERR
/* ecache error enable reg */
122 SET_SIZE
(set_error_enable_tl1
)
124 ENTRY
(set_error_enable
)
125 stxa
%o0
, [%g0
]ASI_ESTATE_ERR
/* ecache error enable reg */
129 SET_SIZE
(set_error_enable
)
131 ENTRY
(get_error_enable
)
133 ldxa
[%g0
]ASI_ESTATE_ERR
, %o0
/* ecache error enable reg */
134 SET_SIZE
(get_error_enable
)
140 get_asyncflt
(uint64_t
*afsr
)
147 ldxa
[%g0
]ASI_AFSR
, %o1
! afsr reg
150 SET_SIZE
(get_asyncflt
)
156 set_asyncflt
(uint64_t afsr
)
163 stxa
%o0
, [%g0
]ASI_AFSR
! afsr reg
167 SET_SIZE
(set_asyncflt
)
173 get_asyncaddr
(uint64_t
*afar
)
180 ldxa
[%g0
]ASI_AFAR
, %o1
! afar reg
183 SET_SIZE
(get_asyncaddr
)
187 #if defined(lint) || defined(__lint)
191 tick2ns
(hrtime_t tick
, uint_t cpuid
)
197 sethi
%hi
(cpunodes
), %o4
198 or %o4
, %lo
(cpunodes
), %o4
! %o4
= &cpunodes
202 ! o2
= byte offset into cpunodes for tick_nsec_scale of this CPU
205 mulx
%o1
, CPU_NODE_SIZE
, %o2
! %o2
= byte offset into cpunodes
206 add %o2
, TICK_NSEC_SCALE
, %o2
207 ld [%o4
+ %o2
], %o2
! %o2
= cpunodes
[cpuid
].tick_nsec_scale
208 NATIVE_TIME_TO_NSEC_SCALE
(%o0
, %o2
, %o3
, TICK_NSEC_SHIFT
)
219 set_cmp_error_steering
(void
)
224 ENTRY
(set_cmp_error_steering
)
226 set ASI_CORE_ID
, %o0
! %o0
= ASI_CORE_ID
227 ldxa
[%o0
]ASI_CMP_PER_CORE
, %o0
! get ASI_CORE_ID
228 and %o0
, COREID_MASK
, %o0
229 set ASI_CMP_ERROR_STEERING
, %o1
! %o1
= ERROR_STEERING_REG
230 stxa
%o0
, [%o1
]ASI_CMP_SHARED
! this core now hadles
231 membar
#Sync ! non-core specific errors
234 SET_SIZE
(set_cmp_error_steering
)
252 SET_SIZE
(ultra_getver
)
259 fpras_chkfn_type1
(void
)
265 * Check instructions using just the AX pipelines, designed by
268 * This function must match a struct fpras_chkfn and must be
269 * block aligned. A zero return means all was well. These
270 * instructions are chosen to be sensitive to bit corruptions
271 * on the fpras rewrite, so if a bit corruption still produces
272 * a valid instruction we should still get an incorrect result
273 * here. This function is never called directly - it is copied
274 * into per-cpu and per-operation buffers; it must therefore
275 * be absolutely position independent. If an illegal instruction
276 * is encountered then the trap handler trampolines to the final
277 * three instructions of this function.
279 * We want two instructions that are complements of one another,
280 * and which can perform a calculation with a known result.
284 * | 0 0 | rd | 1 0 0 | imm22 |
285 * 31 30 29 25 24 22 21 0
287 * ADDCCC with two source registers:
289 * | 1 0 | rd | 0 1 1 0 0 0 | rs1 | 0 | - | rs2 |
290 * 31 30 29 25 24 19 18 14 13 12 5 4 0
292 * We can choose rd and imm2 of the SETHI and rd, rs1 and rs2 of
293 * the ADDCCC to obtain instructions that are complements in all but
296 * Registers are numbered as follows:
331 * For register r[n], register r[31-n] is the complement. We must
332 * avoid use of %i6/%i7 and %o6/%o7 as well as %g7. Clearly we need
333 * to use a local or input register as one half of the pair, which
334 * requires us to obtain our own register window or take steps
335 * to preserve any local or input we choose to use. We choose
336 * %o1 as rd for the SETHI, so rd of the ADDCCC must be %l6.
337 * We'll use %o1 as rs1 and %l6 as rs2 of the ADDCCC, which then
338 * requires that imm22 be 0b111 10110 1 11111111 01001 or 0x3dbfe9,
339 * or %hi(0xf6ffa400). This determines the value of the constant
342 * The constant CBV1 is chosen such that an initial subcc %g0, CBV1
343 * will set the carry bit and every addccc thereafter will continue
344 * to generate a carry. Other values are possible for CBV1 - this
345 * is just one that works this way.
347 * Finally CBV3 is the expected answer when we perform our repeated
348 * calculations on CBV1 and CBV2 - it is not otherwise specially
349 * derived. If this result is not obtained then a corruption has
350 * occured during the FPRAS_REWRITE of one of the two blocks of
351 * 16 instructions. A corruption could also result in an illegal
352 * instruction or other unexpected trap - we catch illegal
353 * instruction traps in the PC range and trampoline to the
354 * last instructions of the function to return a failure indication.
359 #define CBV2 0xf6ffa400
360 #define CBV3 0x66f9d800
364 #define SETHI_CBV2_CBR1 sethi %hi(CBV2), CBR1
365 #define ADDCCC_CBR1_CBR2_CBR2 addccc CBR1, CBR2, CBR2
368 ENTRY_NP
(fpras_chkfn_type1
)
369 mov CBR2
, CBO2
! 1, preserve CBR2 of
(callers
) window
370 mov FPRAS_OK
, %o0
! 2, default return value
372 subcc
%g0
, CBV1
, CBR2
! 4
375 1: SETHI_CBV2_CBR1
! 1
376 ADDCCC_CBR1_CBR2_CBR2
! 2
378 ADDCCC_CBR1_CBR2_CBR2
! 4
380 ADDCCC_CBR1_CBR2_CBR2
! 6
382 ADDCCC_CBR1_CBR2_CBR2
! 8
384 ADDCCC_CBR1_CBR2_CBR2
! 10
386 ADDCCC_CBR1_CBR2_CBR2
! 12
388 ADDCCC_CBR1_CBR2_CBR2
! 14
390 ADDCCC_CBR1_CBR2_CBR2
! 16
392 ADDCCC_CBR1_CBR2_CBR2
! 1
394 ADDCCC_CBR1_CBR2_CBR2
! 3
396 ADDCCC_CBR1_CBR2_CBR2
! 5
398 ADDCCC_CBR1_CBR2_CBR2
! 7
400 ADDCCC_CBR1_CBR2_CBR2
! 9
402 ADDCCC_CBR1_CBR2_CBR2
! 11
404 ADDCCC_CBR1_CBR2_CBR2
! 13
406 ADDCCC_CBR1_CBR2_CBR2
! 15
409 addc CBR1
, CBR2
, CBR2
! 1
410 sethi
%hi
(CBV3
), CBR1
! 2
412 movnz
%icc
, FPRAS_BADCALC
, %o0
! 4, how detected
414 mov CBO2
, CBR2
! 6, restore borrowed register
415 .skip 4*(13-7+1) ! 7 - 13
417 ! illegal instr
'n trap comes here
419 mov CBO2, CBR2 ! 14, restore borrowed register
421 mov FPRAS_BADTRAP, %o0 ! 16, how detected
422 SET_SIZE(fpras_chkfn_type1)
427 * fp_zero() - clear all fp data registers and the fsr
430 #if defined(lint) || defined(__lint)
439 std %g0, [%sp + ARGPUSH + STACK_BIAS]
442 ldd [%sp + ARGPUSH + STACK_BIAS], %fsr