189051Sjake/*-
289051Sjake * Copyright (c) 2002 Jake Burkholder.
3182916Smarius * Copyright (c) 2008 Marius Strobl <marius@FreeBSD.org>
489051Sjake * All rights reserved.
589051Sjake *
689051Sjake * Redistribution and use in source and binary forms, with or without
789051Sjake * modification, are permitted provided that the following conditions
889051Sjake * are met:
989051Sjake * 1. Redistributions of source code must retain the above copyright
1089051Sjake *    notice, this list of conditions and the following disclaimer.
1189051Sjake * 2. Redistributions in binary form must reproduce the above copyright
1289051Sjake *    notice, this list of conditions and the following disclaimer in the
1389051Sjake *    documentation and/or other materials provided with the distribution.
1489051Sjake *
1589051Sjake * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1689051Sjake * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1789051Sjake * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1889051Sjake * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1989051Sjake * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2089051Sjake * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2189051Sjake * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2289051Sjake * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2389051Sjake * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2489051Sjake * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2589051Sjake * SUCH DAMAGE.
2689051Sjake */
2789051Sjake
28114188Sjake#include <machine/asm.h>
29114188Sjake__FBSDID("$FreeBSD$");
30114188Sjake
3189051Sjake#include <machine/asi.h>
3289051Sjake#include <machine/asmacros.h>
33207248Smarius#include <machine/intr_machdep.h>
3489051Sjake#include <machine/ktr.h>
3589051Sjake#include <machine/pstate.h>
36166105Smarius#include <machine/smp.h>
37182730Smarius#include <machine/ver.h>
3889051Sjake
3989051Sjake#include "assym.s"
4089051Sjake
4189051Sjake	.register	%g2, #ignore
4289051Sjake	.register	%g3, #ignore
4389051Sjake
4491617Sjake	.text
45100899Sjake	_ALIGN_TEXT
46182916Smarius	/*
47203833Smarius	 * Initialize misc. state to known values: interrupts disabled, normal
48207248Smarius	 * globals, windows flushed (cr = 0, cs = nwindows - 1), PIL_TICK and
49203833Smarius	 * floating point disabled.
50203833Smarius	 * Note that some firmware versions don't implement a clean window
51203833Smarius	 * trap handler so we unfortunately can't clear the windows by setting
52203833Smarius	 * %cleanwin to zero here.
53182916Smarius	 */
54182916Smarius1:	wrpr	%g0, PSTATE_NORMAL, %pstate
55207248Smarius	wrpr	%g0, PIL_TICK, %pil
56182916Smarius	wr	%g0, 0, %fprs
57182916Smarius
58182916Smarius	rdpr	%ver, %l7
59182916Smarius	srlx	%l7, VER_IMPL_SHIFT, %l7
60182916Smarius	sll	%l7, VER_IMPL_SIZE, %l7
61182916Smarius	srl	%l7, VER_IMPL_SIZE, %l7
62182916Smarius	cmp	%l7, CPU_IMPL_ULTRASPARCIIIp
63182916Smarius	bne	%icc, 3f
64182916Smarius	 nop
65182916Smarius
66182916Smarius	/*
67182916Smarius	 * Relocate the locked entry in it16 slot 0 (if existent)
68182916Smarius	 * as part of working around Cheetah+ erratum 34.
69182916Smarius	 */
70182916Smarius
71182916Smarius	setx	TD_V | TD_L, %l1, %l0
72182916Smarius	/*
73203833Smarius	 * We read ASI_ITLB_DATA_ACCESS_REG twice in order to work
74182916Smarius	 * around errata of USIII and beyond.
75182916Smarius	 */
76182916Smarius	ldxa	[%g0] ASI_ITLB_DATA_ACCESS_REG, %g0
77182916Smarius	ldxa	[%g0] ASI_ITLB_DATA_ACCESS_REG, %l6
78182916Smarius	and	%l6, %l0, %l1
79182916Smarius	cmp	%l0, %l1
80182916Smarius	bne	%xcc, 3f
81182916Smarius	 nop
82182916Smarius
83182916Smarius	/* Flush the mapping of slot 0. */
84182916Smarius	ldxa	[%g0] ASI_ITLB_TAG_READ_REG, %l5
85182916Smarius	srlx	%l5, TAR_VPN_SHIFT, %l0
86182916Smarius	sllx	%l0, TAR_VPN_SHIFT, %l0
87182916Smarius	or	%l0, TLB_DEMAP_PRIMARY | TLB_DEMAP_PAGE, %l0
88182916Smarius	stxa	%g0, [%l0] ASI_IMMU_DEMAP
89182916Smarius	/* The USIII-family ignores the address. */
90182916Smarius	flush	%g0
91182916Smarius
92182916Smarius	/*
93182916Smarius	 * Search a replacement slot != 0 and enter the data and tag
94182916Smarius	 * that formerly were in slot 0.
95182916Smarius	 */
96182916Smarius	mov	(1 << TLB_DAR_SLOT_SHIFT), %l4
97182916Smarius	setx	TD_V, %l1, %l0
98182916Smarius	/*
99203833Smarius	 * We read ASI_ITLB_DATA_ACCESS_REG twice in order to work
100182916Smarius	 * around errata of USIII and beyond.
101182916Smarius	 */
102182916Smarius2:	ldxa	[%l4] ASI_ITLB_DATA_ACCESS_REG, %g0
103182916Smarius	ldxa	[%l4] ASI_ITLB_DATA_ACCESS_REG, %l1
104182916Smarius	and	%l1, %l0, %l1
105182916Smarius	cmp	%l0, %l1
106182916Smarius	be,a	%xcc, 2b
107182916Smarius	 add	%l4, (1 << TLB_DAR_SLOT_SHIFT), %l4
108182916Smarius	wr	%g0, ASI_IMMU, %asi
109182916Smarius	stxa	%l5, [%g0 + AA_IMMU_TAR] %asi
110182916Smarius	stxa	%l6, [%l4] ASI_ITLB_DATA_ACCESS_REG
111182916Smarius	/* The USIII-family ignores the address. */
112182916Smarius	flush	%g0
113182916Smarius
114182916Smarius3:	rd	%pc, %l6
115182916Smarius	ldx	[%l6 + (9f-3b)], %l1
116182916Smarius	add	%l6, (11f-3b), %l2
11791617Sjake	clr	%l3
118182916Smarius4:	cmp	%l3, %l1
119182916Smarius	be	%xcc, 8f
12091617Sjake	 nop
12191617Sjake	ldx	[%l2 + TTE_VPN], %l4
12291617Sjake	ldx	[%l2 + TTE_DATA], %l5
123102040Sjake	srlx	%l4, TV_SIZE_BITS, %l4
124102040Sjake	sllx	%l4, PAGE_SHIFT_4M, %l4
12591617Sjake	wr	%g0, ASI_DMMU, %asi
12691617Sjake	stxa	%l4, [%g0 + AA_DMMU_TAR] %asi
12791617Sjake	stxa	%l5, [%g0] ASI_DTLB_DATA_IN_REG
128182916Smarius	membar	#Sync
129182916Smarius
130182916Smarius	cmp	%l7, CPU_IMPL_ULTRASPARCIIIp
131182916Smarius	bne	%icc, 6f
132182916Smarius	 wr	%g0, ASI_IMMU, %asi
133182916Smarius
134182916Smarius	/*
135182916Smarius	 * Search an unused slot != 0 and explicitly enter the data
136182916Smarius	 * and tag there in order to avoid Cheetah+ erratum 34.
137182916Smarius	 */
138182916Smarius	mov	(1 << TLB_DAR_SLOT_SHIFT), %l0
139182916Smarius	setx	TD_V, %o1, %o0
140182916Smarius	/*
141203833Smarius	 * We read ASI_ITLB_DATA_ACCESS_REG twice in order to work
142182916Smarius	 * around errata of USIII and beyond.
143182916Smarius	 */
144182916Smarius5:	ldxa	[%l0] ASI_ITLB_DATA_ACCESS_REG, %g0
145182916Smarius	ldxa	[%l0] ASI_ITLB_DATA_ACCESS_REG, %o1
146182916Smarius	and	%o1, %o0, %o1
147182916Smarius	cmp	%o0, %o1
148182916Smarius	be,a	%xcc, 5b
149182916Smarius	 add	%l0, (1 << TLB_DAR_SLOT_SHIFT), %l0
150182916Smarius	sethi	%hi(KERNBASE), %o0
15191617Sjake	stxa	%l4, [%g0 + AA_IMMU_TAR] %asi
152182916Smarius	stxa	%l5, [%l0] ASI_ITLB_DATA_ACCESS_REG
153182916Smarius	flush	%o0
154182916Smarius	ba	%xcc, 7f
155182916Smarius	 nop
156182916Smarius
157182916Smarius6:	sethi	%hi(KERNBASE), %l0
158182916Smarius	stxa	%l4, [%g0 + AA_IMMU_TAR] %asi
15991617Sjake	stxa	%l5, [%g0] ASI_ITLB_DATA_IN_REG
160182916Smarius	flush	%l0
161182916Smarius7:	add	%l2, 1 << TTE_SHIFT, %l2
16291617Sjake	add	%l3, 1, %l3
163182916Smarius	ba	%xcc, 4b
16491617Sjake	 nop
165182916Smarius8:	ldx	[%l6 + (10f-3b)], %l1
16691617Sjake	jmpl	%l1, %g0
16791617Sjake	 nop
168100899Sjake	_ALIGN_DATA
169182916Smarius9:	.xword	0x0
170182916Smarius10:	.xword	0x0
171182916Smarius11:
17291617Sjake
17391617SjakeDATA(mp_tramp_code)
17491617Sjake	.xword	1b
17591617SjakeDATA(mp_tramp_code_len)
176182916Smarius	.xword	11b-1b
17791617SjakeDATA(mp_tramp_tlb_slots)
178182916Smarius	.xword	9b-1b
17991617SjakeDATA(mp_tramp_func)
180182916Smarius	.xword	10b-1b
18191617Sjake
18289051Sjake/*
18391617Sjake * void mp_startup(void)
18489051Sjake */
18591617SjakeENTRY(mp_startup)
18691617Sjake	SET(cpu_start_args, %l1, %l0)
18791617Sjake
188182730Smarius	mov	CPU_TICKSYNC, %l1
18989051Sjake	membar	#StoreLoad
19091617Sjake	stw	%l1, [%l0 + CSA_STATE]
19189051Sjake
19291617Sjake1:	ldx	[%l0 + CSA_TICK], %l1
19391617Sjake	brz	%l1, 1b
19491617Sjake	 nop
19591617Sjake	wrpr	%l1, 0, %tick
19691617Sjake
197182730Smarius	rdpr	%ver, %l1
198182730Smarius	stx	%l1, [%l0 + CSA_VER]
19991617Sjake
200182730Smarius	srlx	%l1, VER_IMPL_SHIFT, %l1
201182730Smarius	sll	%l1, VER_IMPL_SIZE, %l1
202182730Smarius	srl	%l1, VER_IMPL_SIZE, %l1
203207537Smarius	cmp	%l1, CPU_IMPL_SPARC64V
204207537Smarius	bl	%icc, 4f
205207537Smarius	 nop
206207537Smarius	cmp	%l1, CPU_IMPL_ULTRASPARCI
207207537Smarius	bl	%icc, 2f
208207537Smarius	 nop
209182730Smarius	cmp	%l1, CPU_IMPL_ULTRASPARCIII
210209138Smarius	bl	%icc, 4f
211182730Smarius	 nop
212207537Smarius2:	mov	CPU_STICKSYNC, %l2
213182730Smarius	membar	#StoreLoad
214204152Smarius	stw	%l2, [%l0 + CSA_STATE]
215182730Smarius
216207537Smarius3:	ldx	[%l0 + CSA_STICK], %l2
217207537Smarius	brz	%l2, 3b
218182730Smarius	 nop
219204152Smarius	wr	%l2, 0, %asr24
220182730Smarius
221207537Smarius4:	call	cpu_get_mid
222204152Smarius	 mov	%l1, %o0
223182730Smarius
22489051Sjake	/*
22591617Sjake	 * Inform the boot processor we have inited.
22689051Sjake	 */
22791617Sjake	mov	CPU_INIT, %l1
22891617Sjake	membar	#LoadStore
22991617Sjake	stw	%l1, [%l0 + CSA_STATE]
23091617Sjake
23191617Sjake	/*
23291617Sjake	 * Wait till its our turn to bootstrap.
23391617Sjake	 */
234207537Smarius5:	lduw	[%l0 + CSA_MID], %l1
23591617Sjake	cmp	%l1, %o0
236207537Smarius	bne	%xcc, 5b
23789051Sjake	 nop
23889051Sjake
23991783Sjake	add	%l0, CSA_TTES, %l1
24091783Sjake	clr	%l2
24191783Sjake
24289051Sjake	/*
243181701Smarius	 * Map the per-CPU pages.
24489051Sjake	 */
245207537Smarius6:	sllx	%l2, TTE_SHIFT, %l3
24691783Sjake	add	%l1, %l3, %l3
24789051Sjake
24891783Sjake	ldx	[%l3 + TTE_VPN], %l4
24991783Sjake	ldx	[%l3 + TTE_DATA], %l5
25091783Sjake
25189051Sjake	wr	%g0, ASI_DMMU, %asi
252102040Sjake	srlx	%l4, TV_SIZE_BITS, %l4
253102040Sjake	sllx	%l4, PAGE_SHIFT_8K, %l4
25491783Sjake	stxa	%l4, [%g0 + AA_DMMU_TAR] %asi
25591783Sjake	stxa	%l5, [%g0] ASI_DTLB_DATA_IN_REG
25689051Sjake	membar	#Sync
25789051Sjake
25891783Sjake	add	%l2, 1, %l2
25991783Sjake	cmp	%l2, PCPU_PAGES
260207537Smarius	bne	%xcc, 6b
26191783Sjake	 nop
26291783Sjake
26389051Sjake	/*
264181701Smarius	 * Get onto our per-CPU panic stack, which precedes the struct pcpu
265181701Smarius	 * in the per-CPU page.
26689051Sjake	 */
26791783Sjake	ldx	[%l0 + CSA_PCPU], %l1
26891617Sjake	set	PCPU_PAGES * PAGE_SIZE - PC_SIZEOF, %l2
26991617Sjake	add	%l1, %l2, %l1
27091617Sjake	sub	%l1, SPOFF + CCFSZ, %sp
27189051Sjake
272222828Smarius	/* Initialize global registers. */
273222828Smarius	call	cpu_setregs
274222828Smarius	 mov	%l1, %o0
275222828Smarius
27689051Sjake#if KTR_COMPILE & KTR_SMP
27789051Sjake	CATR(KTR_SMP,
278203838Smarius	    "mp_startup: bootstrap cpuid=%d mid=%d pcpu=%#lx data=%#lx sp=%#lx"
27989051Sjake	    , %g1, %g2, %g3, 7, 8, 9)
280222828Smarius	lduw	[PCPU(CPUID)], %g2
28189051Sjake	stx	%g2, [%g1 + KTR_PARM1]
282222828Smarius	lduw	[PCPU(MID)], %g2
28389051Sjake	stx	%g2, [%g1 + KTR_PARM2]
28491783Sjake	stx	%l1, [%g1 + KTR_PARM3]
28589051Sjake	stx	%sp, [%g1 + KTR_PARM5]
28689051Sjake9:
28789051Sjake#endif
28889051Sjake
28989051Sjake	/*
29089051Sjake	 * And away we go.  This doesn't return.
29189051Sjake	 */
29289051Sjake	call	cpu_mp_bootstrap
29391617Sjake	 mov	%l1, %o0
29489051Sjake	sir
29589051Sjake	! NOTREACHED
29691617SjakeEND(mp_startup)
297