xref: /titanic_50/usr/src/uts/sun4v/ml/mach_xc.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#if defined(lint)
30#include <sys/types.h>
31#include <sys/cpuvar.h>
32#else	/*lint */
33#include "assym.h"
34#endif	/* lint */
35
36#include <sys/asm_linkage.h>
37#include <sys/privregs.h>
38#include <sys/x_call.h>
39#include <sys/xc_impl.h>
40#include <sys/machthread.h>
41#include <sys/hypervisor_api.h>
42
43#ifdef TRAPTRACE
44#include <sys/traptrace.h>
45#endif /* TRAPTRACE */
46
47
48#if defined(lint)
49
50/* ARGSUSED */
51void
52self_xcall(struct cpu *cpu, uint64_t arg1, uint64_t arg2, xcfunc_t *func)
53{}
54
55#else
56
57/*
58 * Entered by the software trap (TT=ST_SELFXCALL, TL>0) thru send_self_xcall().
59 * Emulate the mondo handler - vec_interrupt().
60 *
61 * Global registers are the Alternate Globals.
62 * Arguments:
63 * 	%o0 - CPU
64 * 	ILP32 kernel:
65 * 		%o5 - function to call
66 * 		%o1, %o2, %o3, %o4  - arguments
67 * 	LP64 kernel:
68 * 		%o3 - function to call
69 * 		%o1, %o2 - arguments
70 */
71	ENTRY_NP(self_xcall)
72	!
73	! TL>0 handlers are expected to do "retry"
74	! prepare their return PC and nPC now
75	!
76	rdpr	%tnpc, %g1
77	wrpr	%g1, %tpc			!  PC <- TNPC[TL]
78 	add	%g1, 4, %g1
79	wrpr	%g1, %tnpc			! nPC <- TNPC[TL] + 4
80
81#ifdef TRAPTRACE
82	TRACE_PTR(%g4, %g6)
83	GET_TRACE_TICK(%g6)
84	stxa	%g6, [%g4 + TRAP_ENT_TICK]%asi
85	rdpr	%tl, %g6
86	stha	%g6, [%g4 + TRAP_ENT_TL]%asi
87	rdpr	%tt, %g6
88	stha	%g6, [%g4 + TRAP_ENT_TT]%asi
89	stna	%o3, [%g4 + TRAP_ENT_TR]%asi ! pc of the TL>0 handler
90	rdpr	%tpc, %g6
91	stna	%g6, [%g4 + TRAP_ENT_TPC]%asi
92	rdpr	%tstate, %g6
93	stxa	%g6, [%g4 + TRAP_ENT_TSTATE]%asi
94	stna	%sp, [%g4 + TRAP_ENT_SP]%asi
95	stna	%o1, [%g4 + TRAP_ENT_F1]%asi ! arg 1
96	stna	%o2, [%g4 + TRAP_ENT_F2]%asi ! arg 2
97	stna	%g0, [%g4 + TRAP_ENT_F3]%asi
98	stna	%g0, [%g4 + TRAP_ENT_F4]%asi
99	TRACE_NEXT(%g4, %g6, %g3)
100#endif /* TRAPTRACE */
101	!
102	! Load the arguments for the fast trap handler.
103	!
104	mov	%o1, %g1
105	jmp	%o3				! call the fast trap handler
106	mov	%o2, %g2
107	/* Not Reached */
108	SET_SIZE(self_xcall)
109
110#endif	/* lint */
111
112#ifdef  TRAPTRACE
113#if defined(lint)
114
115/* ARGSUSED */
116void
117xc_trace(u_int traptype, cpuset_t *cpu_set, xcfunc_t *func,
118	uint64_t arg1, uint64_t arg2)
119{}
120
121#else	/* lint */
122	ENTRY(xc_trace)
123	rdpr	%pstate, %g1
124	andn	%g1, PSTATE_IE | PSTATE_AM, %g2
125	wrpr	%g0, %g2, %pstate			/* disable interrupts */
126	TRACE_PTR(%g3, %g4)
127	GET_TRACE_TICK(%g6)
128	stxa	%g6, [%g3 + TRAP_ENT_TICK]%asi
129	stha	%g0, [%g3 + TRAP_ENT_TL]%asi
130	set	TT_XCALL, %g2
131	or	%o0, %g2, %g4
132	stha	%g4, [%g3 + TRAP_ENT_TT]%asi
133	stna	%o7, [%g3 + TRAP_ENT_TPC]%asi
134	ldn	[%o1], %g2
135	stna	%g2, [%g3 + TRAP_ENT_SP]%asi		/* sp = cpuset */
136	stna	%o2, [%g3 + TRAP_ENT_TR]%asi		/* tr = func */
137	stna	%o3, [%g3 + TRAP_ENT_F1]%asi		/* f1 = arg1 */
138	stna	%o4, [%g3 + TRAP_ENT_F2]%asi		/* f2 = arg2 */
139	stna	%g0, [%g3 + TRAP_ENT_F3]%asi		/* f3 = 0 */
140	stna	%i7, [%g3 + TRAP_ENT_F4]%asi		/* f4 = xcall caller */
141	stxa	%g1, [%g3 + TRAP_ENT_TSTATE]%asi	/* tstate = pstate */
142	TRACE_NEXT(%g2, %g3, %g4)
143/*
144 * In the case of a cpuset of greater size than a long we
145 * grab extra trace buffers just to store the cpuset.
146 * Seems like a waste but popular opinion opted for this
147 * rather than increase the size of the buffer.
148 */
149#if CPUSET_SIZE > CLONGSIZE
150	add	%o1, CPUSET_SIZE, %g5			/* end of cpuset */
151	clr	%o2
1521:
153	TRACE_PTR(%g3, %g4)
154	stha	%g0, [%g3 + TRAP_ENT_TL]%asi
155	set	TT_XCALL_CONT, %g2
156	or	%g2, %o2, %g2				/* continuation # */
157	stha	%g2, [%g3 + TRAP_ENT_TT]%asi
158	stxa	%g6, [%g3 + TRAP_ENT_TICK]%asi		/* same tick */
159	stna	%g0, [%g3 + TRAP_ENT_TPC]%asi		/* clr unused fields */
160	stna	%g0, [%g3 + TRAP_ENT_SP]%asi
161	stna	%g0, [%g3 + TRAP_ENT_TR]%asi
162	stxa	%g0, [%g3 + TRAP_ENT_TSTATE]%asi
163	stna	%g0, [%g3 + TRAP_ENT_F2]%asi
164	stna	%g0, [%g3 + TRAP_ENT_F3]%asi
165	stna	%g0, [%g3 + TRAP_ENT_F4]%asi
166	ldn	[%o1], %g2
167	stna	%g2, [%g3 + TRAP_ENT_F1]%asi
168	add	%o1, CLONGSIZE, %o1
169	cmp	%o1, %g5
170	bge	2f
171	ldn	[%o1], %g2
172	stna	%g2, [%g3 + TRAP_ENT_F2]%asi
173	add	%o1, CLONGSIZE, %o1
174	cmp	%o1, %g5
175	bge	2f
176	ldn	[%o1], %g2
177	stna	%g2, [%g3 + TRAP_ENT_F3]%asi
178	add	%o1, CLONGSIZE, %o1
179	cmp	%o1, %g5
180	bge	2f
181	ldn	[%o1], %g2
182	stna	%g2, [%g3 + TRAP_ENT_F4]%asi
183	add	%o1, CLONGSIZE, %o1
1842:
185	TRACE_NEXT(%g2, %g3, %g4)
186	cmp	%o1, %g5
187	bl	1b
188	inc	%o2
189#endif	/* CPUSET_SIZE */
190	retl
191	wrpr	%g0, %g1, %pstate			/* enable interrupts */
192	SET_SIZE(xc_trace)
193
194#endif	/* lint */
195#endif	/* TRAPTRACE */
196
197#if defined(lint)
198
199/*ARGSUSED*/
200void
201init_mondo(xcfunc_t *func, uint64_t arg1, uint64_t arg2)
202{}
203
204/*ARGSUSED*/
205int
206shipit(int n, uint64_t cpuid)
207{ return(0); }
208
209#else	/* lint */
210/*
211 * Setup interrupt dispatch data registers
212 * Entry:
213 *	%o0 - function or inumber to call
214 *	%o1, %o2 - arguments (2 uint64_t's)
215 */
216	ENTRY(init_mondo)
217	ALTENTRY(init_mondo_nocheck)
218	CPU_ADDR(%g1, %g4)			! load CPU struct addr
219	add	%g1, CPU_MCPU, %g1
220	ldx	[%g1 + MCPU_MONDO_DATA], %g1
221	stx	%o0, [%g1]
222	stx	%o1, [%g1+8]
223	stx	%o2, [%g1+0x10]
224	stx	%g0, [%g1+0x18]
225	stx	%g0, [%g1+0x20]
226	stx	%g0, [%g1+0x28]
227	stx	%g0, [%g1+0x30]
228	stx	%g0, [%g1+0x38]
229	retl
230	membar	#Sync			! allowed to be in the delay slot
231	SET_SIZE(init_mondo)
232
233/*
234 * Ship mondo to cpuid
235 */
236	ENTRY_NP(shipit)
237	/* For now use dummy interface:  cpu# func arg1 arg2 */
238	CPU_ADDR(%g1, %g4)
239	add	%g1, CPU_MCPU, %g1
240	ldx	[%g1 + MCPU_MONDO_DATA_RA],	%o2
241	mov	HV_INTR_SEND, %o5
242	ta	FAST_TRAP
243	retl
244	membar	#Sync
245	SET_SIZE(shipit)
246
247#endif	/* lint */
248
249#if defined(lint)
250
251/*ARGSUSED*/
252uint64_t
253get_cpuaddr(uint64_t reg, uint64_t scr)
254{ return (0);}
255
256#else	/* lint */
257/*
258 * Get cpu structure
259 * Entry:
260 *      %o0 - register for CPU_ADDR macro
261 *      %o1 - scratch for CPU_ADDR macro
262 */
263	ENTRY(get_cpuaddr)
264	CPU_ADDR(%o0, %o1)	! %o0 == CPU struct addr
265	retl
266	nop
267	SET_SIZE(get_cpuaddr)
268
269#endif	/* lint */
270
271#if defined(lint)
272/* ARGSUSED */
273void
274xt_sync_tl1(uint64_t *cpu_sync_addr)
275{}
276
277#else /* lint */
278/*
279 * This is to ensure that previously called xtrap handlers have executed on
280 * sun4v. We zero out the byte corresponding to its cpuid in the
281 * array passed to us from xt_sync(), so the sender knows the previous
282 * mondo has been executed.
283 * Register:
284 *		%g1 - Addr of the cpu_sync array.
285 */
286	ENTRY_NP(xt_sync_tl1)
287	CPU_INDEX(%g3, %g4)		/* %g3 = cpu id */
288	stb	%g0, [%g1 + %g3]
289	retry
290	SET_SIZE(xt_sync_tl1)
291
292#endif  /* lint */
293