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