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