xref: /titanic_50/usr/src/uts/sun4v/ml/mach_subr_asm.s (revision fa9e4066f08beec538e775443c5be79dd423fcab)
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, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#pragma ident	"%Z%%M%	%I%	%E% SMI"
28
29/*
30 * General machine architecture & implementation specific
31 * assembly language routines.
32 */
33#if defined(lint)
34#include <sys/types.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/machsystm.h>
42#include <sys/machthread.h>
43#include <sys/privregs.h>
44#include <sys/cmpregs.h>
45#include <sys/clock.h>
46#include <sys/fpras.h>
47
48#if defined(lint)
49/* ARGSUSED */
50void
51set_mmfsa_scratchpad(caddr_t vaddr)
52{ }
53
54#else	/* lint */
55
56	ENTRY(set_mmfsa_scratchpad)
57	stxa	%o0, [%g0]ASI_SCRATCHPAD
58	retl
59	nop
60	SET_SIZE(set_mmfsa_scratchpad)
61#endif	/* lint */
62
63#if defined(lint)
64caddr_t
65get_mmfsa_scratchpad()
66{  return (0); }
67
68#else	/* lint */
69
70	ENTRY(get_mmfsa_scratchpad)
71	ldxa	[%g0]ASI_SCRATCHPAD, %o0
72	retl
73	nop
74	SET_SIZE(get_mmfsa_scratchpad)
75#endif	/* lint */
76
77#if defined(lint)
78/* ARGSUSED */
79int
80getprocessorid(void)
81{ return (0); }
82
83#else	/* lint */
84
85/*
86 * Get the processor ID.
87 * === MID reg as specified in 15dec89 sun4u spec, sec 5.4.3
88 */
89
90	ENTRY(getprocessorid)
91	CPU_INDEX(%o0, %o1)
92	retl
93	nop
94	SET_SIZE(getprocessorid)
95
96#endif	/* lint */
97
98#if defined(lint) || defined(__lint)
99
100/* ARGSUSED */
101hrtime_t
102tick2ns(hrtime_t tick, uint_t cpuid)
103{ return 0; }
104
105#else	/* lint */
106
107	ENTRY_NP(tick2ns)
108	sethi	%hi(cpunodes), %o4
109	or	%o4, %lo(cpunodes), %o4		! %o4 = &cpunodes
110	! Register usage:
111	!
112	! o0 = timestamp
113	! o2 = byte offset into cpunodes for tick_nsec_scale of this CPU
114	! o4 = &cpunodes
115	!
116	mulx	%o1, CPU_NODE_SIZE, %o2	! %o2 = byte offset into cpunodes
117	add	%o2, TICK_NSEC_SCALE, %o2
118	ld	[%o4 + %o2], %o2	! %o2 = cpunodes[cpuid].tick_nsec_scale
119	NATIVE_TIME_TO_NSEC_SCALE(%o0, %o2, %o3, TICK_NSEC_SHIFT)
120	retl
121	nop
122	SET_SIZE(tick2ns)
123
124#endif  /* lint */
125
126#if defined(lint)
127
128/* ARGSUSED */
129void
130set_cmp_error_steering(void)
131{}
132
133#else	/* lint */
134
135	ENTRY(set_cmp_error_steering)
136	retl
137	nop
138	SET_SIZE(set_cmp_error_steering)
139
140#endif	/* lint */
141
142#if defined(lint)
143
144/* ARGSUSED */
145uint64_t
146ultra_getver(void)
147{
148	return (0);
149}
150
151#else /* lint */
152
153	ENTRY(ultra_getver)
154	retl
155	mov	-1, %o0		! XXXQ no version available
156	SET_SIZE(ultra_getver)
157
158#endif /* lint */
159
160#if defined(lint)
161
162int
163fpras_chkfn_type1(void)
164{ return 0; }
165
166#else	/* lint */
167
168	/*
169	 * Check instructions using just the AX pipelines, designed by
170	 * C.B. Liaw of PNP.
171	 *
172	 * This function must match a struct fpras_chkfn and must be
173	 * block aligned.  A zero return means all was well.  These
174	 * instructions are chosen to be sensitive to bit corruptions
175	 * on the fpras rewrite, so if a bit corruption still produces
176	 * a valid instruction we should still get an incorrect result
177	 * here.  This function is never called directly - it is copied
178	 * into per-cpu and per-operation buffers;  it must therefore
179	 * be absolutely position independent.  If an illegal instruction
180	 * is encountered then the trap handler trampolines to the final
181	 * three instructions of this function.
182	 *
183	 * We want two instructions that are complements of one another,
184	 * and which can perform a calculation with a known result.
185	 *
186	 * SETHI:
187	 *
188	 * | 0 0 |  rd   | 1 0 0 |	imm22				|
189	 *  31 30 29   25 24   22 21				       0
190	 *
191	 * ADDCCC with two source registers:
192	 *
193	 * | 1 0 |  rd   | 0 1 1   0 0 0 |  rs1  | 0 |	   -	|  rs2  |
194	 *  31 30 29   25 24           19 18   14 13  12       5 4     0
195	 *
196	 * We can choose rd and imm2 of the SETHI and rd, rs1 and rs2 of
197	 * the ADDCCC to obtain instructions that are complements in all but
198	 * bit 30.
199	 *
200	 * Registers are numbered as follows:
201	 *
202	 * r[31]	%i7
203	 * r[30]	%i6
204	 * r[29]	%i5
205	 * r[28]	%i4
206	 * r[27]	%i3
207	 * r[26]	%i2
208	 * r[25]	%i1
209	 * r[24]	%i0
210	 * r[23]	%l7
211	 * r[22]	%l6
212	 * r[21]	%l5
213	 * r[20]	%l4
214	 * r[19]	%l3
215	 * r[18]	%l2
216	 * r[17]	%l1
217	 * r[16]	%l0
218	 * r[15]	%o7
219	 * r[14]	%o6
220	 * r[13]	%o5
221	 * r[12]	%o4
222	 * r[11]	%o3
223	 * r[10]	%o2
224	 * r[9]		%o1
225	 * r[8]		%o0
226	 * r[7]		%g7
227	 * r[6]		%g6
228	 * r[5]		%g5
229	 * r[4]		%g4
230	 * r[3]		%g3
231	 * r[2]		%g2
232	 * r[1]		%g1
233	 * r[0]		%g0
234	 *
235	 * For register r[n], register r[31-n] is the complement.  We must
236	 * avoid use of %i6/%i7 and %o6/%o7 as well as %g7.  Clearly we need
237	 * to use a local or input register as one half of the pair, which
238	 * requires us to obtain our own register window or take steps
239	 * to preserve any local or input we choose to use.  We choose
240	 * %o1 as rd for the SETHI, so rd of the ADDCCC must be %l6.
241	 * We'll use %o1 as rs1 and %l6 as rs2 of the ADDCCC, which then
242	 * requires that imm22 be 0b111 10110 1 11111111 01001 or 0x3dbfe9,
243	 * or %hi(0xf6ffa400).  This determines the value of the constant
244	 * CBV2 below.
245	 *
246	 * The constant CBV1 is chosen such that an initial subcc %g0, CBV1
247	 * will set the carry bit and every addccc thereafter will continue
248	 * to generate a carry.  Other values are possible for CBV1 - this
249	 * is just one that works this way.
250	 *
251	 * Finally CBV3 is the expected answer when we perform our repeated
252	 * calculations on CBV1 and CBV2 - it is not otherwise specially
253	 * derived.  If this result is not obtained then a corruption has
254	 * occured during the FPRAS_REWRITE of one of the two blocks of
255	 * 16 instructions.  A corruption could also result in an illegal
256	 * instruction or other unexpected trap - we catch illegal
257	 * instruction traps in the PC range and trampoline to the
258	 * last instructions of the function to return a failure indication.
259	 *
260	 */
261
262#define	CBV1		0xc11
263#define	CBV2		0xf6ffa400
264#define	CBV3		0x66f9d800
265#define	CBR1		%o1
266#define	CBR2		%l6
267#define	CBO2		%o2
268#define	SETHI_CBV2_CBR1		sethi %hi(CBV2), CBR1
269#define	ADDCCC_CBR1_CBR2_CBR2	addccc CBR1, CBR2, CBR2
270
271	.align	64
272	ENTRY_NP(fpras_chkfn_type1)
273	mov	CBR2, CBO2		! 1, preserve CBR2 of (callers) window
274	mov	FPRAS_OK, %o0		! 2, default return value
275	ba,pt	%icc, 1f		! 3
276	  subcc %g0, CBV1, CBR2		! 4
277					! 5 - 16
278	.align	64
2791:	SETHI_CBV2_CBR1			! 1
280	ADDCCC_CBR1_CBR2_CBR2		! 2
281	SETHI_CBV2_CBR1			! 3
282	ADDCCC_CBR1_CBR2_CBR2		! 4
283	SETHI_CBV2_CBR1			! 5
284	ADDCCC_CBR1_CBR2_CBR2		! 6
285	SETHI_CBV2_CBR1			! 7
286	ADDCCC_CBR1_CBR2_CBR2		! 8
287	SETHI_CBV2_CBR1			! 9
288	ADDCCC_CBR1_CBR2_CBR2		! 10
289	SETHI_CBV2_CBR1			! 11
290	ADDCCC_CBR1_CBR2_CBR2		! 12
291	SETHI_CBV2_CBR1			! 13
292	ADDCCC_CBR1_CBR2_CBR2		! 14
293	SETHI_CBV2_CBR1			! 15
294	ADDCCC_CBR1_CBR2_CBR2		! 16
295
296	ADDCCC_CBR1_CBR2_CBR2		! 1
297	SETHI_CBV2_CBR1			! 2
298	ADDCCC_CBR1_CBR2_CBR2		! 3
299	SETHI_CBV2_CBR1			! 4
300	ADDCCC_CBR1_CBR2_CBR2		! 5
301	SETHI_CBV2_CBR1			! 6
302	ADDCCC_CBR1_CBR2_CBR2		! 7
303	SETHI_CBV2_CBR1			! 8
304	ADDCCC_CBR1_CBR2_CBR2		! 9
305	SETHI_CBV2_CBR1			! 10
306	ADDCCC_CBR1_CBR2_CBR2		! 11
307	SETHI_CBV2_CBR1			! 12
308	ADDCCC_CBR1_CBR2_CBR2		! 13
309	SETHI_CBV2_CBR1			! 14
310	ADDCCC_CBR1_CBR2_CBR2		! 15
311	SETHI_CBV2_CBR1			! 16
312
313	addc	CBR1, CBR2, CBR2	! 1
314	sethi	%hi(CBV3), CBR1		! 2
315	cmp	CBR1, CBR2		! 3
316	movnz	%icc, FPRAS_BADCALC, %o0! 4, how detected
317	retl				! 5
318	  mov	CBO2, CBR2		! 6, restore borrowed register
319	.skip 4*(13-7+1)		! 7 - 13
320					!
321					! illegal instr'n trap comes here
322					!
323	mov	CBO2, CBR2		! 14, restore borrowed register
324	retl				! 15
325	  mov	FPRAS_BADTRAP, %o0	! 16, how detected
326	SET_SIZE(fpras_chkfn_type1)
327
328#endif	/* lint */
329