xref: /titanic_50/usr/src/uts/sun4u/ml/cpr_resume_setup.s (revision 0e42dee69ed771bf604dd1789fca9d77b5bbe302)
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#else   /* lint */
32#include "assym.h"
33#endif  /* lint */
34
35#include <sys/asm_linkage.h>
36#include <sys/machthread.h>		/* for reg definition */
37
38#include <sys/machasi.h>		/* sun4u ASI */
39#include <sys/mmu.h>
40#include <sys/privregs.h>
41#include <sys/machparam.h>
42#include <vm/hat_sfmmu.h>
43#include <sys/cpr_impl.h>
44#include <sys/intreg.h>
45#include <sys/clock.h>
46
47/*
48 * resume kernel entry point from cprboot
49 * 	1. restore I/D TSB registers
50 *	2. restore primary and secondary context registers
51 *	3. initialize cpu state registers
52 *	4. set up the thread and lwp registers for the cpr process
53 *	5. switch to kernel trap
54 *	6. restore checkpoint pc and stack pointer
55 *	7. longjmp back to kernel
56 *
57 * registers from cprboot:exit_to_kernel()
58 *	%o0	prom cookie
59 *	%o1	struct sun4u_machdep *mdp
60 *
61 * Any change to this register assignment
62 * require changes to cprboot_srt0.s
63 */
64
65#if defined(lint)
66
67/* ARGSUSED */
68void
69i_cpr_resume_setup(void *cookie, csu_md_t *mdp)
70{}
71
72/* ARGSUSED */
73int
74i_cpr_cif_wrapper(void *args)
75{ return (0); }
76
77/* ARGSUSED */
78void
79dtlb_wr_entry(uint_t index, tte_t *tte, uint64_t *va_tag)
80{}
81
82/* ARGSUSED */
83void
84itlb_wr_entry(uint_t index, tte_t *tte, uint64_t *va_tag)
85{}
86
87#else	/* lint */
88
89	!
90	! reserve 4k for cpr tmp stack; tstack should be first,
91	! any new data symbols should be added after tstack.
92	!
93	.seg	".data"
94	.global	i_cpr_data_page, i_cpr_tstack_size
95	.global	i_cpr_orig_cif
96
97	.align	MMU_PAGESIZE
98i_cpr_data_page:
99	.skip	4096
100i_cpr_tstack:
101	.word	0
102i_cpr_tstack_size:
103	.word	4096
104
105	.align	8
106prom_tba:
107	.word	0, 0
108i_cpr_orig_cif:
109	.nword	0
110i_cpr_tmp_cif:
111	.nword	0
112
113
114	!
115	! set text to begin at a page boundary so we can
116	! map this one page and jump to it from cprboot
117	!
118	.seg	".text"
119	.align	MMU_PAGESIZE
120
121	ENTRY(i_cpr_resume_setup)
122	!
123	! save %o args to locals
124	!
125	mov	%o0, %l4
126	mov	%o1, %l5
127
128	!
129	! Restore PCONTEXT
130	!
131	sethi	%hi(FLUSH_ADDR), %g3
132	ld	[%l5 + CPR_MD_PRI], %g1		! mdp->mmu_ctx_pri
133	set	MMU_PCONTEXT, %g2
134	stxa	%g1, [%g2]ASI_DMMU
135	flush	%g3
136
137	!
138	! Restore SCONTEXT.  We do not need to set up the TSB
139	! registers.  Since we are restoring INVALID_CONTEXT into
140	! the secondary context the HAT will do that for us.
141	!
142	ld	[%l5 + CPR_MD_SEC], %g1		! mdp->mmu_ctx_sec
143	set	MMU_SCONTEXT, %g2
144	stxa	%g1, [%g2]ASI_DMMU
145	flush	%g3
146
147	!
148	! Allow user rdtick, and rdstick if applicable
149	!
150	CLEARTICKNPT
151
152	!
153	! copy saved thread pointer to %g7
154	!
155	ldx	[%l5 + CPR_MD_THRP], THREAD_REG		! mdp->thrp
156
157	!
158	! since csu_md_t lives in a cprboot data page,
159	! copy select data to registers for later use
160	! before freeing cprboot text/data pages
161	!
162	ldx	[%l5 + CPR_MD_QSAV_PC], %l7	! l7 = mdp->qsav_pc
163	ldx	[%l5 + CPR_MD_QSAV_SP], %l6	! l6 = mdp->qsav_sp
164
165	!
166	! save cookie from the new/tmp prom
167	!
168	set	i_cpr_tmp_cif, %g1
169	stn	%l4, [%g1]
170
171	!
172	! save prom tba
173	!
174	set	prom_tba, %g1
175	rdpr	%tba, %g2
176	stx	%g2, [%g1]
177
178	!
179	! start slave cpus, pause them within kernel text,
180	! and restore the original prom pages
181	!
182	call	i_cpr_mp_setup
183	nop
184
185	!
186	! since this routine is entered only by a jmp from cprboot,
187	! we can set cpr_suspend_succeeded here
188	!
189	set	cpr_suspend_succeeded, %l0
190	mov	1, %l1
191	st	%l1, [%l0]
192
193	!
194	! special shortened version of longjmp
195	! Don't need to flushw
196	!
197	mov	%l7, %i7		! i7 = saved pc
198	mov	%l6, %fp		! i6 = saved sp
199	ret				! return 1
200	restore	%g0, 1, %o0		! takes underflow, switches stack
201	SET_SIZE(i_cpr_resume_setup)
202
203
204	!
205	! while running on the new/tmp prom, the prom's trap table
206	! must be used to handle translations within prom space
207	! since the kernel's mappings may not match this prom.
208	!
209	! always set %tba to the prom's trap table before calling
210	! any prom service; after returning, read %tba again;
211	! if the %tba wasn't changed by the prom service,
212	! restore the original %tba.
213	!
214	! a call stack looks like this:
215	!
216	! current prom cookie
217	! [i_cpr_cif_wrapper]
218	! client_handler
219	! p1275_sparc_cif_handler
220	! prom_xxx
221	!
222	ENTRY(i_cpr_cif_wrapper)
223	save	%sp, -SA64(MINFRAME64 + 8), %sp
224	rdpr	%tba, %o5		! read original %tba
225	stx	%o5, [%fp + V9BIAS64 - 8]
226	set	prom_tba, %l4
227	ldx	[%l4], %o4		! read prom_tba
228	wrpr	%o4, %tba		! switch to prom trap table
229
230	set	i_cpr_tmp_cif, %g3	! cookie for new/tmp prom
231	ldn	[%g3], %g4
232	jmpl	%g4, %o7		! call prom service
233	mov	%i0, %o0
234
235	ldx	[%l4], %o4		! read prom_tba
236	rdpr	%tba, %o3		! read current %tba
237	cmp	%o3, %o4		! did prom change %tba ?
238	bne,pn	%xcc, 1f		! yes, dont reset %tba
239	nop
240	ldx	[%fp + V9BIAS64 - 8], %o5
241	wrpr	%o5, %tba		! no change, restore orignal
2421:
243	ret
244	restore	%g0, %o0, %o0
245	SET_SIZE(i_cpr_cif_wrapper)
246
247
248	!
249	! write dtlb entry at index
250	!
251	ENTRY(dtlb_wr_entry)
252	sllx    %o0, 3, %o0			! index << 3
253	ldx	[%o1], %o5			! o5 = tte.ll
254	ldx	[%o2], %o4			! o4 = va_tag
255	srlx	%o4, MMU_PAGESHIFT, %o4		! clear any page offset
256	sllx	%o4, MMU_PAGESHIFT, %o4		! o4 = va_tag & PAGEMASK
257	set	MMU_TAG_ACCESS, %o3
258	stxa	%o4, [%o3]ASI_DMMU
259	stxa	%o5, [%o0]ASI_DTLB_ACCESS
260	membar	#Sync
261	retl
262	nop
263	SET_SIZE(dtlb_wr_entry)
264
265
266	!
267	! write itlb entry at index
268	!
269	ENTRY(itlb_wr_entry)
270	sllx    %o0, 3, %o0			! index << 3
271	ldx	[%o1], %o5			! o5 = tte.ll
272	ldx	[%o2], %o4			! o4 = va_tag
273	srlx	%o4, MMU_PAGESHIFT, %o4		! clear any page offset
274	sllx	%o4, MMU_PAGESHIFT, %o4		! o4 = va_tag & PAGEMASK
275	set	MMU_TAG_ACCESS, %o3
276	stxa	%o4, [%o3]ASI_IMMU
277	stxa	%o5, [%o0]ASI_ITLB_ACCESS
278	membar	#Sync
279	retl
280	nop
281	SET_SIZE(itlb_wr_entry)
282
283#endif /* !lint */
284