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