xref: /titanic_50/usr/src/uts/sun4v/ml/mach_subr_asm.s (revision c77a61a72b5ecdc507d6cf104142edd371a16c84)
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 2006 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/t_lock.h>
35#else	/* lint */
36#include "assym.h"
37#endif	/* lint */
38
39#include <sys/asm_linkage.h>
40#include <sys/machsystm.h>
41#include <sys/machthread.h>
42#include <sys/privregs.h>
43#include <sys/cmpregs.h>
44#include <sys/clock.h>
45#include <sys/fpras.h>
46#include <sys/soft_state.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
78
79#if defined(lint)
80/* ARGSUSED */
81void
82cpu_intrq_unregister_powerdown(uint64_t doneflag_va)
83{}
84
85#else	/* lint */
86
87/*
88 * Called from a x-trap at tl1 must use %g1 as arg
89 * and save/restore %o0-%o5 after hypervisor calls
90 */
91
92	ENTRY(cpu_intrq_unregister_powerdown)
93
94	CPU_ADDR(%g2, %g3)
95	add %g2, CPU_MCPU, %g2
96	/*
97	 * Save %o regs
98	 */
99	mov %o0, %g3
100	mov %o1, %g4
101	mov %o2, %g5
102	mov %o5, %g6
103
104	ldx [%g2 + MCPU_CPU_Q_BASE], %o1
105	mov INTR_CPU_Q, %o0
106	call hv_cpu_qconf
107	mov %g0, %o2
108
109	ldx [%g2 + MCPU_DEV_Q_BASE], %o1
110	mov INTR_DEV_Q, %o0
111	call hv_cpu_qconf
112	mov %g0, %o2
113
114	ldx [%g2 + MCPU_RQ_BASE], %o1
115	mov CPU_RQ, %o0
116	call hv_cpu_qconf
117	mov %g0, %o2
118
119	ldx [%g2 + MCPU_NRQ_BASE], %o1
120	mov CPU_NRQ, %o0
121	call hv_cpu_qconf
122	mov %g0, %o2
123
124	/*
125	 * set done flag to 0
126	 */
127	stub %g0, [%g1]
128
129	/*
130	 * Restore %o regs
131	 */
132	mov %g3, %o0
133	mov %g4, %o1
134	mov %g5, %o2
135	mov %g6, %o5
136
137	/*
138	 * This CPU is on its way out. Spin here
139	 * until the DR unconfigure code stops it.
140	 * Returning would put it back in the OS
141	 * where it might grab resources like locks,
142	 * causing some nastiness to occur.
143	 */
1440:
145	ba,a	0b
146
147	SET_SIZE(cpu_intrq_unregister_powerdown)
148#endif	/* lint */
149
150
151#if defined(lint)
152/* ARGSUSED */
153int
154getprocessorid(void)
155{ return (0); }
156
157#else	/* lint */
158
159/*
160 * Get the processor ID.
161 * === MID reg as specified in 15dec89 sun4u spec, sec 5.4.3
162 */
163
164	ENTRY(getprocessorid)
165	CPU_INDEX(%o0, %o1)
166	retl
167	nop
168	SET_SIZE(getprocessorid)
169
170#endif	/* lint */
171
172#if defined(lint) || defined(__lint)
173
174/* ARGSUSED */
175hrtime_t
176tick2ns(hrtime_t tick, uint_t cpuid)
177{ return 0; }
178
179#else	/* lint */
180
181	ENTRY_NP(tick2ns)
182	sethi	%hi(cpunodes), %o4
183	or	%o4, %lo(cpunodes), %o4		! %o4 = &cpunodes
184	! Register usage:
185	!
186	! o0 = timestamp
187	! o2 = byte offset into cpunodes for tick_nsec_scale of this CPU
188	! o4 = &cpunodes
189	!
190	mulx	%o1, CPU_NODE_SIZE, %o2	! %o2 = byte offset into cpunodes
191	add	%o2, TICK_NSEC_SCALE, %o2
192	ld	[%o4 + %o2], %o2	! %o2 = cpunodes[cpuid].tick_nsec_scale
193	NATIVE_TIME_TO_NSEC_SCALE(%o0, %o2, %o3, TICK_NSEC_SHIFT)
194	retl
195	nop
196	SET_SIZE(tick2ns)
197
198#endif  /* lint */
199
200#if defined(lint)
201
202/* ARGSUSED */
203void
204set_cmp_error_steering(void)
205{}
206
207#else	/* lint */
208
209	ENTRY(set_cmp_error_steering)
210	retl
211	nop
212	SET_SIZE(set_cmp_error_steering)
213
214#endif	/* lint */
215
216#if defined(lint)
217
218/* ARGSUSED */
219uint64_t
220ultra_getver(void)
221{
222	return (0);
223}
224
225#else /* lint */
226
227	ENTRY(ultra_getver)
228	retl
229	mov	-1, %o0		! XXXQ no version available
230	SET_SIZE(ultra_getver)
231
232#endif /* lint */
233
234#if defined(lint)
235
236int
237fpras_chkfn_type1(void)
238{ return 0; }
239
240#else	/* lint */
241
242	/*
243	 * Check instructions using just the AX pipelines, designed by
244	 * C.B. Liaw of PNP.
245	 *
246	 * This function must match a struct fpras_chkfn and must be
247	 * block aligned.  A zero return means all was well.  These
248	 * instructions are chosen to be sensitive to bit corruptions
249	 * on the fpras rewrite, so if a bit corruption still produces
250	 * a valid instruction we should still get an incorrect result
251	 * here.  This function is never called directly - it is copied
252	 * into per-cpu and per-operation buffers;  it must therefore
253	 * be absolutely position independent.  If an illegal instruction
254	 * is encountered then the trap handler trampolines to the final
255	 * three instructions of this function.
256	 *
257	 * We want two instructions that are complements of one another,
258	 * and which can perform a calculation with a known result.
259	 *
260	 * SETHI:
261	 *
262	 * | 0 0 |  rd   | 1 0 0 |	imm22				|
263	 *  31 30 29   25 24   22 21				       0
264	 *
265	 * ADDCCC with two source registers:
266	 *
267	 * | 1 0 |  rd   | 0 1 1   0 0 0 |  rs1  | 0 |	   -	|  rs2  |
268	 *  31 30 29   25 24           19 18   14 13  12       5 4     0
269	 *
270	 * We can choose rd and imm2 of the SETHI and rd, rs1 and rs2 of
271	 * the ADDCCC to obtain instructions that are complements in all but
272	 * bit 30.
273	 *
274	 * Registers are numbered as follows:
275	 *
276	 * r[31]	%i7
277	 * r[30]	%i6
278	 * r[29]	%i5
279	 * r[28]	%i4
280	 * r[27]	%i3
281	 * r[26]	%i2
282	 * r[25]	%i1
283	 * r[24]	%i0
284	 * r[23]	%l7
285	 * r[22]	%l6
286	 * r[21]	%l5
287	 * r[20]	%l4
288	 * r[19]	%l3
289	 * r[18]	%l2
290	 * r[17]	%l1
291	 * r[16]	%l0
292	 * r[15]	%o7
293	 * r[14]	%o6
294	 * r[13]	%o5
295	 * r[12]	%o4
296	 * r[11]	%o3
297	 * r[10]	%o2
298	 * r[9]		%o1
299	 * r[8]		%o0
300	 * r[7]		%g7
301	 * r[6]		%g6
302	 * r[5]		%g5
303	 * r[4]		%g4
304	 * r[3]		%g3
305	 * r[2]		%g2
306	 * r[1]		%g1
307	 * r[0]		%g0
308	 *
309	 * For register r[n], register r[31-n] is the complement.  We must
310	 * avoid use of %i6/%i7 and %o6/%o7 as well as %g7.  Clearly we need
311	 * to use a local or input register as one half of the pair, which
312	 * requires us to obtain our own register window or take steps
313	 * to preserve any local or input we choose to use.  We choose
314	 * %o1 as rd for the SETHI, so rd of the ADDCCC must be %l6.
315	 * We'll use %o1 as rs1 and %l6 as rs2 of the ADDCCC, which then
316	 * requires that imm22 be 0b111 10110 1 11111111 01001 or 0x3dbfe9,
317	 * or %hi(0xf6ffa400).  This determines the value of the constant
318	 * CBV2 below.
319	 *
320	 * The constant CBV1 is chosen such that an initial subcc %g0, CBV1
321	 * will set the carry bit and every addccc thereafter will continue
322	 * to generate a carry.  Other values are possible for CBV1 - this
323	 * is just one that works this way.
324	 *
325	 * Finally CBV3 is the expected answer when we perform our repeated
326	 * calculations on CBV1 and CBV2 - it is not otherwise specially
327	 * derived.  If this result is not obtained then a corruption has
328	 * occured during the FPRAS_REWRITE of one of the two blocks of
329	 * 16 instructions.  A corruption could also result in an illegal
330	 * instruction or other unexpected trap - we catch illegal
331	 * instruction traps in the PC range and trampoline to the
332	 * last instructions of the function to return a failure indication.
333	 *
334	 */
335
336#define	CBV1		0xc11
337#define	CBV2		0xf6ffa400
338#define	CBV3		0x66f9d800
339#define	CBR1		%o1
340#define	CBR2		%l6
341#define	CBO2		%o2
342#define	SETHI_CBV2_CBR1		sethi %hi(CBV2), CBR1
343#define	ADDCCC_CBR1_CBR2_CBR2	addccc CBR1, CBR2, CBR2
344
345	.align	64
346	ENTRY_NP(fpras_chkfn_type1)
347	mov	CBR2, CBO2		! 1, preserve CBR2 of (callers) window
348	mov	FPRAS_OK, %o0		! 2, default return value
349	ba,pt	%icc, 1f		! 3
350	  subcc %g0, CBV1, CBR2		! 4
351					! 5 - 16
352	.align	64
3531:	SETHI_CBV2_CBR1			! 1
354	ADDCCC_CBR1_CBR2_CBR2		! 2
355	SETHI_CBV2_CBR1			! 3
356	ADDCCC_CBR1_CBR2_CBR2		! 4
357	SETHI_CBV2_CBR1			! 5
358	ADDCCC_CBR1_CBR2_CBR2		! 6
359	SETHI_CBV2_CBR1			! 7
360	ADDCCC_CBR1_CBR2_CBR2		! 8
361	SETHI_CBV2_CBR1			! 9
362	ADDCCC_CBR1_CBR2_CBR2		! 10
363	SETHI_CBV2_CBR1			! 11
364	ADDCCC_CBR1_CBR2_CBR2		! 12
365	SETHI_CBV2_CBR1			! 13
366	ADDCCC_CBR1_CBR2_CBR2		! 14
367	SETHI_CBV2_CBR1			! 15
368	ADDCCC_CBR1_CBR2_CBR2		! 16
369
370	ADDCCC_CBR1_CBR2_CBR2		! 1
371	SETHI_CBV2_CBR1			! 2
372	ADDCCC_CBR1_CBR2_CBR2		! 3
373	SETHI_CBV2_CBR1			! 4
374	ADDCCC_CBR1_CBR2_CBR2		! 5
375	SETHI_CBV2_CBR1			! 6
376	ADDCCC_CBR1_CBR2_CBR2		! 7
377	SETHI_CBV2_CBR1			! 8
378	ADDCCC_CBR1_CBR2_CBR2		! 9
379	SETHI_CBV2_CBR1			! 10
380	ADDCCC_CBR1_CBR2_CBR2		! 11
381	SETHI_CBV2_CBR1			! 12
382	ADDCCC_CBR1_CBR2_CBR2		! 13
383	SETHI_CBV2_CBR1			! 14
384	ADDCCC_CBR1_CBR2_CBR2		! 15
385	SETHI_CBV2_CBR1			! 16
386
387	addc	CBR1, CBR2, CBR2	! 1
388	sethi	%hi(CBV3), CBR1		! 2
389	cmp	CBR1, CBR2		! 3
390	movnz	%icc, FPRAS_BADCALC, %o0! 4, how detected
391	retl				! 5
392	  mov	CBO2, CBR2		! 6, restore borrowed register
393	.skip 4*(13-7+1)		! 7 - 13
394					!
395					! illegal instr'n trap comes here
396					!
397	mov	CBO2, CBR2		! 14, restore borrowed register
398	retl				! 15
399	  mov	FPRAS_BADTRAP, %o0	! 16, how detected
400	SET_SIZE(fpras_chkfn_type1)
401#endif	/* lint */
402
403#if defined(lint)
404char	soft_state_message_strings[SOLARIS_SOFT_STATE_MSG_CNT][SSM_SIZE];
405#else	/* lint */
406	.seg	".data"
407	.global soft_state_message_strings
408
409	.align	SSM_SIZE
410soft_state_message_strings:
411	.asciz	SOLARIS_SOFT_STATE_BOOT_MSG_STR
412	.align	SSM_SIZE
413	.asciz	SOLARIS_SOFT_STATE_RUN_MSG_STR
414	.align	SSM_SIZE
415	.asciz	SOLARIS_SOFT_STATE_HALT_MSG_STR
416	.align	SSM_SIZE
417	.asciz	SOLARIS_SOFT_STATE_POWER_MSG_STR
418	.align	SSM_SIZE
419	.asciz	SOLARIS_SOFT_STATE_PANIC_MSG_STR
420	.align	SSM_SIZE
421	.asciz	SOLARIS_SOFT_STATE_REBOOT_MSG_STR
422	.align	SSM_SIZE
423	.asciz	SOLARIS_SOFT_STATE_DEBUG_MSG_STR
424	.align	SSM_SIZE
425	.skip	SSM_SIZE			/* saved message */
426	.nword	0
427
428	.seg	".text"
429#endif	/* lint */
430