mp_locore.S revision 203838
1/*-
2 * Copyright (c) 2002 Jake Burkholder.
3 * Copyright (c) 2008 Marius Strobl <marius@FreeBSD.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28#include <machine/asm.h>
29__FBSDID("$FreeBSD: head/sys/sparc64/sparc64/mp_locore.S 203838 2010-02-13 16:52:33Z marius $");
30
31#include <machine/asi.h>
32#include <machine/asmacros.h>
33#include <machine/ktr.h>
34#include <machine/pstate.h>
35#include <machine/smp.h>
36#include <machine/ver.h>
37
38#include "assym.s"
39
40	.register	%g2, #ignore
41	.register	%g3, #ignore
42
43	.text
44	_ALIGN_TEXT
45	/*
46	 * Initialize misc. state to known values: interrupts disabled, normal
47	 * globals, windows flushed (cr = 0, cs = nwindows - 1), PIL 0 and
48	 * floating point disabled.
49	 * Note that some firmware versions don't implement a clean window
50	 * trap handler so we unfortunately can't clear the windows by setting
51	 * %cleanwin to zero here.
52	 */
531:	wrpr	%g0, PSTATE_NORMAL, %pstate
54	wrpr	%g0, 0, %pil
55	wr	%g0, 0, %fprs
56
57	rdpr	%ver, %l7
58	srlx	%l7, VER_IMPL_SHIFT, %l7
59	sll	%l7, VER_IMPL_SIZE, %l7
60	srl	%l7, VER_IMPL_SIZE, %l7
61	cmp	%l7, CPU_IMPL_ULTRASPARCIIIp
62	bne	%icc, 3f
63	 nop
64
65	/*
66	 * Relocate the locked entry in it16 slot 0 (if existent)
67	 * as part of working around Cheetah+ erratum 34.
68	 */
69
70	setx	TD_V | TD_L, %l1, %l0
71	/*
72	 * We read ASI_ITLB_DATA_ACCESS_REG twice in order to work
73	 * around errata of USIII and beyond.
74	 */
75	ldxa	[%g0] ASI_ITLB_DATA_ACCESS_REG, %g0
76	ldxa	[%g0] ASI_ITLB_DATA_ACCESS_REG, %l6
77	and	%l6, %l0, %l1
78	cmp	%l0, %l1
79	bne	%xcc, 3f
80	 nop
81
82	/* Flush the mapping of slot 0. */
83	ldxa	[%g0] ASI_ITLB_TAG_READ_REG, %l5
84	srlx	%l5, TAR_VPN_SHIFT, %l0
85	sllx	%l0, TAR_VPN_SHIFT, %l0
86	or	%l0, TLB_DEMAP_PRIMARY | TLB_DEMAP_PAGE, %l0
87	stxa	%g0, [%l0] ASI_IMMU_DEMAP
88	/* The USIII-family ignores the address. */
89	flush	%g0
90
91	/*
92	 * Search a replacement slot != 0 and enter the data and tag
93	 * that formerly were in slot 0.
94	 */
95	mov	(1 << TLB_DAR_SLOT_SHIFT), %l4
96	setx	TD_V, %l1, %l0
97	/*
98	 * We read ASI_ITLB_DATA_ACCESS_REG twice in order to work
99	 * around errata of USIII and beyond.
100	 */
1012:	ldxa	[%l4] ASI_ITLB_DATA_ACCESS_REG, %g0
102	ldxa	[%l4] ASI_ITLB_DATA_ACCESS_REG, %l1
103	and	%l1, %l0, %l1
104	cmp	%l0, %l1
105	be,a	%xcc, 2b
106	 add	%l4, (1 << TLB_DAR_SLOT_SHIFT), %l4
107	wr	%g0, ASI_IMMU, %asi
108	stxa	%l5, [%g0 + AA_IMMU_TAR] %asi
109	stxa	%l6, [%l4] ASI_ITLB_DATA_ACCESS_REG
110	/* The USIII-family ignores the address. */
111	flush	%g0
112
1133:	rd	%pc, %l6
114	ldx	[%l6 + (9f-3b)], %l1
115	add	%l6, (11f-3b), %l2
116	clr	%l3
1174:	cmp	%l3, %l1
118	be	%xcc, 8f
119	 nop
120	ldx	[%l2 + TTE_VPN], %l4
121	ldx	[%l2 + TTE_DATA], %l5
122	srlx	%l4, TV_SIZE_BITS, %l4
123	sllx	%l4, PAGE_SHIFT_4M, %l4
124	wr	%g0, ASI_DMMU, %asi
125	stxa	%l4, [%g0 + AA_DMMU_TAR] %asi
126	stxa	%l5, [%g0] ASI_DTLB_DATA_IN_REG
127	membar	#Sync
128
129	cmp	%l7, CPU_IMPL_ULTRASPARCIIIp
130	bne	%icc, 6f
131	 wr	%g0, ASI_IMMU, %asi
132
133	/*
134	 * Search an unused slot != 0 and explicitly enter the data
135	 * and tag there in order to avoid Cheetah+ erratum 34.
136	 */
137	mov	(1 << TLB_DAR_SLOT_SHIFT), %l0
138	setx	TD_V, %o1, %o0
139	/*
140	 * We read ASI_ITLB_DATA_ACCESS_REG twice in order to work
141	 * around errata of USIII and beyond.
142	 */
1435:	ldxa	[%l0] ASI_ITLB_DATA_ACCESS_REG, %g0
144	ldxa	[%l0] ASI_ITLB_DATA_ACCESS_REG, %o1
145	and	%o1, %o0, %o1
146	cmp	%o0, %o1
147	be,a	%xcc, 5b
148	 add	%l0, (1 << TLB_DAR_SLOT_SHIFT), %l0
149	sethi	%hi(KERNBASE), %o0
150	stxa	%l4, [%g0 + AA_IMMU_TAR] %asi
151	stxa	%l5, [%l0] ASI_ITLB_DATA_ACCESS_REG
152	flush	%o0
153	ba	%xcc, 7f
154	 nop
155
1566:	sethi	%hi(KERNBASE), %l0
157	stxa	%l4, [%g0 + AA_IMMU_TAR] %asi
158	stxa	%l5, [%g0] ASI_ITLB_DATA_IN_REG
159	flush	%l0
1607:	add	%l2, 1 << TTE_SHIFT, %l2
161	add	%l3, 1, %l3
162	ba	%xcc, 4b
163	 nop
1648:	ldx	[%l6 + (10f-3b)], %l1
165	jmpl	%l1, %g0
166	 nop
167	_ALIGN_DATA
1689:	.xword	0x0
16910:	.xword	0x0
17011:
171
172DATA(mp_tramp_code)
173	.xword	1b
174DATA(mp_tramp_code_len)
175	.xword	11b-1b
176DATA(mp_tramp_tlb_slots)
177	.xword	9b-1b
178DATA(mp_tramp_func)
179	.xword	10b-1b
180
181/*
182 * void mp_startup(void)
183 */
184ENTRY(mp_startup)
185	SET(cpu_start_args, %l1, %l0)
186
187	mov	CPU_TICKSYNC, %l1
188	membar	#StoreLoad
189	stw	%l1, [%l0 + CSA_STATE]
190
1911:	ldx	[%l0 + CSA_TICK], %l1
192	brz	%l1, 1b
193	 nop
194	wrpr	%l1, 0, %tick
195
196	rdpr	%ver, %l1
197	stx	%l1, [%l0 + CSA_VER]
198
199	srlx	%l1, VER_IMPL_SHIFT, %l1
200	sll	%l1, VER_IMPL_SIZE, %l1
201	srl	%l1, VER_IMPL_SIZE, %l1
202	cmp	%l1, CPU_IMPL_ULTRASPARCIII
203	bl	%icc, 3f
204	 nop
205	mov	CPU_STICKSYNC, %l1
206	membar	#StoreLoad
207	stw	%l1, [%l0 + CSA_STATE]
208
2092:	ldx	[%l0 + CSA_STICK], %l1
210	brz	%l1, 2b
211	 nop
212	wr	%l1, 0, %asr24
213
2143:	call	cpu_get_mid
215	 nop
216
217	/*
218	 * Inform the boot processor we have inited.
219	 */
220	mov	CPU_INIT, %l1
221	membar	#LoadStore
222	stw	%l1, [%l0 + CSA_STATE]
223
224	/*
225	 * Wait till its our turn to bootstrap.
226	 */
2274:	lduw	[%l0 + CSA_MID], %l1
228	cmp	%l1, %o0
229	bne	%xcc, 4b
230	 nop
231
232	add	%l0, CSA_TTES, %l1
233	clr	%l2
234
235	/*
236	 * Map the per-CPU pages.
237	 */
2385:	sllx	%l2, TTE_SHIFT, %l3
239	add	%l1, %l3, %l3
240
241	ldx	[%l3 + TTE_VPN], %l4
242	ldx	[%l3 + TTE_DATA], %l5
243
244	wr	%g0, ASI_DMMU, %asi
245	srlx	%l4, TV_SIZE_BITS, %l4
246	sllx	%l4, PAGE_SHIFT_8K, %l4
247	stxa	%l4, [%g0 + AA_DMMU_TAR] %asi
248	stxa	%l5, [%g0] ASI_DTLB_DATA_IN_REG
249	membar	#Sync
250
251	add	%l2, 1, %l2
252	cmp	%l2, PCPU_PAGES
253	bne	%xcc, 5b
254	 nop
255
256	/*
257	 * Get onto our per-CPU panic stack, which precedes the struct pcpu
258	 * in the per-CPU page.
259	 */
260	ldx	[%l0 + CSA_PCPU], %l1
261	set	PCPU_PAGES * PAGE_SIZE - PC_SIZEOF, %l2
262	add	%l1, %l2, %l1
263	sub	%l1, SPOFF + CCFSZ, %sp
264
265	/*
266	 * Enable interrupts.
267	 */
268	wrpr	%g0, PSTATE_KERNEL, %pstate
269
270#if KTR_COMPILE & KTR_SMP
271	CATR(KTR_SMP,
272	    "mp_startup: bootstrap cpuid=%d mid=%d pcpu=%#lx data=%#lx sp=%#lx"
273	    , %g1, %g2, %g3, 7, 8, 9)
274	lduw	[%l1 + PC_CPUID], %g2
275	stx	%g2, [%g1 + KTR_PARM1]
276	lduw	[%l1 + PC_MID], %g2
277	stx	%g2, [%g1 + KTR_PARM2]
278	stx	%l1, [%g1 + KTR_PARM3]
279	stx	%sp, [%g1 + KTR_PARM5]
2809:
281#endif
282
283	/*
284	 * And away we go.  This doesn't return.
285	 */
286	call	cpu_mp_bootstrap
287	 mov	%l1, %o0
288	sir
289	! NOTREACHED
290END(mp_startup)
291