xref: /openbmc/linux/arch/sparc/kernel/head_64.S (revision 82003e04)
1/* head.S: Initial boot code for the Sparc64 port of Linux.
2 *
3 * Copyright (C) 1996, 1997, 2007 David S. Miller (davem@davemloft.net)
4 * Copyright (C) 1996 David Sitsky (David.Sitsky@anu.edu.au)
5 * Copyright (C) 1997, 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
6 * Copyright (C) 1997 Miguel de Icaza (miguel@nuclecu.unam.mx)
7 */
8
9#include <linux/version.h>
10#include <linux/errno.h>
11#include <linux/threads.h>
12#include <linux/init.h>
13#include <linux/linkage.h>
14#include <asm/thread_info.h>
15#include <asm/asi.h>
16#include <asm/pstate.h>
17#include <asm/ptrace.h>
18#include <asm/spitfire.h>
19#include <asm/page.h>
20#include <asm/pgtable.h>
21#include <asm/errno.h>
22#include <asm/signal.h>
23#include <asm/processor.h>
24#include <asm/lsu.h>
25#include <asm/dcr.h>
26#include <asm/dcu.h>
27#include <asm/head.h>
28#include <asm/ttable.h>
29#include <asm/mmu.h>
30#include <asm/cpudata.h>
31#include <asm/pil.h>
32#include <asm/estate.h>
33#include <asm/sfafsr.h>
34#include <asm/unistd.h>
35#include <asm/export.h>
36
37/* This section from from _start to sparc64_boot_end should fit into
38 * 0x0000000000404000 to 0x0000000000408000.
39 */
40	.text
41	.globl	start, _start, stext, _stext
42_start:
43start:
44_stext:
45stext:
46! 0x0000000000404000
47	b	sparc64_boot
48	 flushw					/* Flush register file.      */
49
50/* This stuff has to be in sync with SILO and other potential boot loaders
51 * Fields should be kept upward compatible and whenever any change is made,
52 * HdrS version should be incremented.
53 */
54        .global root_flags, ram_flags, root_dev
55        .global sparc_ramdisk_image, sparc_ramdisk_size
56	.global sparc_ramdisk_image64
57
58        .ascii  "HdrS"
59        .word   LINUX_VERSION_CODE
60
61	/* History:
62	 *
63	 * 0x0300 : Supports being located at other than 0x4000
64	 * 0x0202 : Supports kernel params string
65	 * 0x0201 : Supports reboot_command
66	 */
67	.half   0x0301          /* HdrS version */
68
69root_flags:
70        .half   1
71root_dev:
72        .half   0
73ram_flags:
74        .half   0
75sparc_ramdisk_image:
76        .word   0
77sparc_ramdisk_size:
78        .word   0
79        .xword  reboot_command
80	.xword	bootstr_info
81sparc_ramdisk_image64:
82	.xword	0
83	.word	_end
84
85	/* PROM cif handler code address is in %o4.  */
86sparc64_boot:
87	mov	%o4, %l7
88
89	/* We need to remap the kernel.  Use position independent
90	 * code to remap us to KERNBASE.
91	 *
92	 * SILO can invoke us with 32-bit address masking enabled,
93	 * so make sure that's clear.
94	 */
95	rdpr	%pstate, %g1
96	andn	%g1, PSTATE_AM, %g1
97	wrpr	%g1, 0x0, %pstate
98	ba,a,pt	%xcc, 1f
99
100	.globl	prom_finddev_name, prom_chosen_path, prom_root_node
101	.globl	prom_getprop_name, prom_mmu_name, prom_peer_name
102	.globl	prom_callmethod_name, prom_translate_name, prom_root_compatible
103	.globl	prom_map_name, prom_unmap_name, prom_mmu_ihandle_cache
104	.globl	prom_boot_mapped_pc, prom_boot_mapping_mode
105	.globl	prom_boot_mapping_phys_high, prom_boot_mapping_phys_low
106	.globl	prom_compatible_name, prom_cpu_path, prom_cpu_compatible
107	.globl	is_sun4v, sun4v_chip_type, prom_set_trap_table_name
108prom_peer_name:
109	.asciz	"peer"
110prom_compatible_name:
111	.asciz	"compatible"
112prom_finddev_name:
113	.asciz	"finddevice"
114prom_chosen_path:
115	.asciz	"/chosen"
116prom_cpu_path:
117	.asciz	"/cpu"
118prom_getprop_name:
119	.asciz	"getprop"
120prom_mmu_name:
121	.asciz	"mmu"
122prom_callmethod_name:
123	.asciz	"call-method"
124prom_translate_name:
125	.asciz	"translate"
126prom_map_name:
127	.asciz	"map"
128prom_unmap_name:
129	.asciz	"unmap"
130prom_set_trap_table_name:
131	.asciz	"SUNW,set-trap-table"
132prom_sun4v_name:
133	.asciz	"sun4v"
134prom_niagara_prefix:
135	.asciz	"SUNW,UltraSPARC-T"
136prom_sparc_prefix:
137	.asciz	"SPARC-"
138prom_sparc64x_prefix:
139	.asciz	"SPARC64-X"
140	.align	4
141prom_root_compatible:
142	.skip	64
143prom_cpu_compatible:
144	.skip	64
145prom_root_node:
146	.word	0
147EXPORT_SYMBOL(prom_root_node)
148prom_mmu_ihandle_cache:
149	.word	0
150prom_boot_mapped_pc:
151	.word	0
152prom_boot_mapping_mode:
153	.word	0
154	.align	8
155prom_boot_mapping_phys_high:
156	.xword	0
157prom_boot_mapping_phys_low:
158	.xword	0
159is_sun4v:
160	.word	0
161sun4v_chip_type:
162	.word	SUN4V_CHIP_INVALID
163EXPORT_SYMBOL(sun4v_chip_type)
1641:
165	rd	%pc, %l0
166
167	mov	(1b - prom_peer_name), %l1
168	sub	%l0, %l1, %l1
169	mov	0, %l2
170
171	/* prom_root_node = prom_peer(0) */
172	stx	%l1, [%sp + 2047 + 128 + 0x00]	! service, "peer"
173	mov	1, %l3
174	stx	%l3, [%sp + 2047 + 128 + 0x08]	! num_args, 1
175	stx	%l3, [%sp + 2047 + 128 + 0x10]	! num_rets, 1
176	stx	%l2, [%sp + 2047 + 128 + 0x18]	! arg1, 0
177	stx	%g0, [%sp + 2047 + 128 + 0x20]	! ret1
178	call	%l7
179	 add	%sp, (2047 + 128), %o0		! argument array
180
181	ldx	[%sp + 2047 + 128 + 0x20], %l4	! prom root node
182	mov	(1b - prom_root_node), %l1
183	sub	%l0, %l1, %l1
184	stw	%l4, [%l1]
185
186	mov	(1b - prom_getprop_name), %l1
187	mov	(1b - prom_compatible_name), %l2
188	mov	(1b - prom_root_compatible), %l5
189	sub	%l0, %l1, %l1
190	sub	%l0, %l2, %l2
191	sub	%l0, %l5, %l5
192
193	/* prom_getproperty(prom_root_node, "compatible",
194	 *                  &prom_root_compatible, 64)
195	 */
196	stx	%l1, [%sp + 2047 + 128 + 0x00]	! service, "getprop"
197	mov	4, %l3
198	stx	%l3, [%sp + 2047 + 128 + 0x08]	! num_args, 4
199	mov	1, %l3
200	stx	%l3, [%sp + 2047 + 128 + 0x10]	! num_rets, 1
201	stx	%l4, [%sp + 2047 + 128 + 0x18]	! arg1, prom_root_node
202	stx	%l2, [%sp + 2047 + 128 + 0x20]	! arg2, "compatible"
203	stx	%l5, [%sp + 2047 + 128 + 0x28]	! arg3, &prom_root_compatible
204	mov	64, %l3
205	stx	%l3, [%sp + 2047 + 128 + 0x30]	! arg4, size
206	stx	%g0, [%sp + 2047 + 128 + 0x38]	! ret1
207	call	%l7
208	 add	%sp, (2047 + 128), %o0		! argument array
209
210	mov	(1b - prom_finddev_name), %l1
211	mov	(1b - prom_chosen_path), %l2
212	mov	(1b - prom_boot_mapped_pc), %l3
213	sub	%l0, %l1, %l1
214	sub	%l0, %l2, %l2
215	sub	%l0, %l3, %l3
216	stw	%l0, [%l3]
217	sub	%sp, (192 + 128), %sp
218
219	/* chosen_node = prom_finddevice("/chosen") */
220	stx	%l1, [%sp + 2047 + 128 + 0x00]	! service, "finddevice"
221	mov	1, %l3
222	stx	%l3, [%sp + 2047 + 128 + 0x08]	! num_args, 1
223	stx	%l3, [%sp + 2047 + 128 + 0x10]	! num_rets, 1
224	stx	%l2, [%sp + 2047 + 128 + 0x18]	! arg1, "/chosen"
225	stx	%g0, [%sp + 2047 + 128 + 0x20]	! ret1
226	call	%l7
227	 add	%sp, (2047 + 128), %o0		! argument array
228
229	ldx	[%sp + 2047 + 128 + 0x20], %l4	! chosen device node
230
231	mov	(1b - prom_getprop_name), %l1
232	mov	(1b - prom_mmu_name), %l2
233	mov	(1b - prom_mmu_ihandle_cache), %l5
234	sub	%l0, %l1, %l1
235	sub	%l0, %l2, %l2
236	sub	%l0, %l5, %l5
237
238	/* prom_mmu_ihandle_cache = prom_getint(chosen_node, "mmu") */
239	stx	%l1, [%sp + 2047 + 128 + 0x00]	! service, "getprop"
240	mov	4, %l3
241	stx	%l3, [%sp + 2047 + 128 + 0x08]	! num_args, 4
242	mov	1, %l3
243	stx	%l3, [%sp + 2047 + 128 + 0x10]	! num_rets, 1
244	stx	%l4, [%sp + 2047 + 128 + 0x18]	! arg1, chosen_node
245	stx	%l2, [%sp + 2047 + 128 + 0x20]	! arg2, "mmu"
246	stx	%l5, [%sp + 2047 + 128 + 0x28]	! arg3, &prom_mmu_ihandle_cache
247	mov	4, %l3
248	stx	%l3, [%sp + 2047 + 128 + 0x30]	! arg4, sizeof(arg3)
249	stx	%g0, [%sp + 2047 + 128 + 0x38]	! ret1
250	call	%l7
251	 add	%sp, (2047 + 128), %o0		! argument array
252
253	mov	(1b - prom_callmethod_name), %l1
254	mov	(1b - prom_translate_name), %l2
255	sub	%l0, %l1, %l1
256	sub	%l0, %l2, %l2
257	lduw	[%l5], %l5			! prom_mmu_ihandle_cache
258
259	stx	%l1, [%sp + 2047 + 128 + 0x00]	! service, "call-method"
260	mov	3, %l3
261	stx	%l3, [%sp + 2047 + 128 + 0x08]	! num_args, 3
262	mov	5, %l3
263	stx	%l3, [%sp + 2047 + 128 + 0x10]	! num_rets, 5
264	stx	%l2, [%sp + 2047 + 128 + 0x18]	! arg1: "translate"
265	stx	%l5, [%sp + 2047 + 128 + 0x20]	! arg2: prom_mmu_ihandle_cache
266	/* PAGE align */
267	srlx	%l0, 13, %l3
268	sllx	%l3, 13, %l3
269	stx	%l3, [%sp + 2047 + 128 + 0x28]	! arg3: vaddr, our PC
270	stx	%g0, [%sp + 2047 + 128 + 0x30]	! res1
271	stx	%g0, [%sp + 2047 + 128 + 0x38]	! res2
272	stx	%g0, [%sp + 2047 + 128 + 0x40]	! res3
273	stx	%g0, [%sp + 2047 + 128 + 0x48]	! res4
274	stx	%g0, [%sp + 2047 + 128 + 0x50]	! res5
275	call	%l7
276	 add	%sp, (2047 + 128), %o0		! argument array
277
278	ldx	[%sp + 2047 + 128 + 0x40], %l1	! translation mode
279	mov	(1b - prom_boot_mapping_mode), %l4
280	sub	%l0, %l4, %l4
281	stw	%l1, [%l4]
282	mov	(1b - prom_boot_mapping_phys_high), %l4
283	sub	%l0, %l4, %l4
284	ldx	[%sp + 2047 + 128 + 0x48], %l2	! physaddr high
285	stx	%l2, [%l4 + 0x0]
286	ldx	[%sp + 2047 + 128 + 0x50], %l3	! physaddr low
287	/* 4MB align */
288	srlx	%l3, ILOG2_4MB, %l3
289	sllx	%l3, ILOG2_4MB, %l3
290	stx	%l3, [%l4 + 0x8]
291
292	/* Leave service as-is, "call-method" */
293	mov	7, %l3
294	stx	%l3, [%sp + 2047 + 128 + 0x08]	! num_args, 7
295	mov	1, %l3
296	stx	%l3, [%sp + 2047 + 128 + 0x10]	! num_rets, 1
297	mov	(1b - prom_map_name), %l3
298	sub	%l0, %l3, %l3
299	stx	%l3, [%sp + 2047 + 128 + 0x18]	! arg1: "map"
300	/* Leave arg2 as-is, prom_mmu_ihandle_cache */
301	mov	-1, %l3
302	stx	%l3, [%sp + 2047 + 128 + 0x28]	! arg3: mode (-1 default)
303	/* 4MB align the kernel image size. */
304	set	(_end - KERNBASE), %l3
305	set	((4 * 1024 * 1024) - 1), %l4
306	add	%l3, %l4, %l3
307	andn	%l3, %l4, %l3
308	stx	%l3, [%sp + 2047 + 128 + 0x30]	! arg4: roundup(ksize, 4MB)
309	sethi	%hi(KERNBASE), %l3
310	stx	%l3, [%sp + 2047 + 128 + 0x38]	! arg5: vaddr (KERNBASE)
311	stx	%g0, [%sp + 2047 + 128 + 0x40]	! arg6: empty
312	mov	(1b - prom_boot_mapping_phys_low), %l3
313	sub	%l0, %l3, %l3
314	ldx	[%l3], %l3
315	stx	%l3, [%sp + 2047 + 128 + 0x48]	! arg7: phys addr
316	call	%l7
317	 add	%sp, (2047 + 128), %o0		! argument array
318
319	add	%sp, (192 + 128), %sp
320
321	sethi	%hi(prom_root_compatible), %g1
322	or	%g1, %lo(prom_root_compatible), %g1
323	sethi	%hi(prom_sun4v_name), %g7
324	or	%g7, %lo(prom_sun4v_name), %g7
325	mov	5, %g3
32690:	ldub	[%g7], %g2
327	ldub	[%g1], %g4
328	cmp	%g2, %g4
329	bne,pn	%icc, 80f
330	 add	%g7, 1, %g7
331	subcc	%g3, 1, %g3
332	bne,pt	%xcc, 90b
333	 add	%g1, 1, %g1
334
335	sethi	%hi(is_sun4v), %g1
336	or	%g1, %lo(is_sun4v), %g1
337	mov	1, %g7
338	stw	%g7, [%g1]
339
340	/* cpu_node = prom_finddevice("/cpu") */
341	mov	(1b - prom_finddev_name), %l1
342	mov	(1b - prom_cpu_path), %l2
343	sub	%l0, %l1, %l1
344	sub	%l0, %l2, %l2
345	sub	%sp, (192 + 128), %sp
346
347	stx	%l1, [%sp + 2047 + 128 + 0x00]	! service, "finddevice"
348	mov	1, %l3
349	stx	%l3, [%sp + 2047 + 128 + 0x08]	! num_args, 1
350	stx	%l3, [%sp + 2047 + 128 + 0x10]	! num_rets, 1
351	stx	%l2, [%sp + 2047 + 128 + 0x18]	! arg1, "/cpu"
352	stx	%g0, [%sp + 2047 + 128 + 0x20]	! ret1
353	call	%l7
354	 add	%sp, (2047 + 128), %o0		! argument array
355
356	ldx	[%sp + 2047 + 128 + 0x20], %l4	! cpu device node
357
358	mov	(1b - prom_getprop_name), %l1
359	mov	(1b - prom_compatible_name), %l2
360	mov	(1b - prom_cpu_compatible), %l5
361	sub	%l0, %l1, %l1
362	sub	%l0, %l2, %l2
363	sub	%l0, %l5, %l5
364
365	/* prom_getproperty(cpu_node, "compatible",
366	 *                  &prom_cpu_compatible, 64)
367	 */
368	stx	%l1, [%sp + 2047 + 128 + 0x00]	! service, "getprop"
369	mov	4, %l3
370	stx	%l3, [%sp + 2047 + 128 + 0x08]	! num_args, 4
371	mov	1, %l3
372	stx	%l3, [%sp + 2047 + 128 + 0x10]	! num_rets, 1
373	stx	%l4, [%sp + 2047 + 128 + 0x18]	! arg1, cpu_node
374	stx	%l2, [%sp + 2047 + 128 + 0x20]	! arg2, "compatible"
375	stx	%l5, [%sp + 2047 + 128 + 0x28]	! arg3, &prom_cpu_compatible
376	mov	64, %l3
377	stx	%l3, [%sp + 2047 + 128 + 0x30]	! arg4, size
378	stx	%g0, [%sp + 2047 + 128 + 0x38]	! ret1
379	call	%l7
380	 add	%sp, (2047 + 128), %o0		! argument array
381
382	add	%sp, (192 + 128), %sp
383
384	sethi	%hi(prom_cpu_compatible), %g1
385	or	%g1, %lo(prom_cpu_compatible), %g1
386	sethi	%hi(prom_niagara_prefix), %g7
387	or	%g7, %lo(prom_niagara_prefix), %g7
388	mov	17, %g3
38990:	ldub	[%g7], %g2
390	ldub	[%g1], %g4
391	cmp	%g2, %g4
392	bne,pn	%icc, 89f
393	 add	%g7, 1, %g7
394	subcc	%g3, 1, %g3
395	bne,pt	%xcc, 90b
396	 add	%g1, 1, %g1
397	ba,pt	%xcc, 91f
398	 nop
399
40089:	sethi	%hi(prom_cpu_compatible), %g1
401	or	%g1, %lo(prom_cpu_compatible), %g1
402	sethi	%hi(prom_sparc_prefix), %g7
403	or	%g7, %lo(prom_sparc_prefix), %g7
404	mov	6, %g3
40590:	ldub	[%g7], %g2
406	ldub	[%g1], %g4
407	cmp	%g2, %g4
408	bne,pn	%icc, 4f
409	 add	%g7, 1, %g7
410	subcc	%g3, 1, %g3
411	bne,pt	%xcc, 90b
412	 add	%g1, 1, %g1
413
414	sethi	%hi(prom_cpu_compatible), %g1
415	or	%g1, %lo(prom_cpu_compatible), %g1
416	ldub	[%g1 + 6], %g2
417	cmp	%g2, 'T'
418	be,pt	%xcc, 70f
419	 cmp	%g2, 'M'
420	be,pt	%xcc, 70f
421	 cmp	%g2, 'S'
422	bne,pn	%xcc, 49f
423	 nop
424
42570:	ldub	[%g1 + 7], %g2
426	cmp	%g2, '3'
427	be,pt	%xcc, 5f
428	 mov	SUN4V_CHIP_NIAGARA3, %g4
429	cmp	%g2, '4'
430	be,pt	%xcc, 5f
431	 mov	SUN4V_CHIP_NIAGARA4, %g4
432	cmp	%g2, '5'
433	be,pt	%xcc, 5f
434	 mov	SUN4V_CHIP_NIAGARA5, %g4
435	cmp	%g2, '6'
436	be,pt	%xcc, 5f
437	 mov	SUN4V_CHIP_SPARC_M6, %g4
438	cmp	%g2, '7'
439	be,pt	%xcc, 5f
440	 mov	SUN4V_CHIP_SPARC_M7, %g4
441	cmp	%g2, 'N'
442	be,pt	%xcc, 5f
443	 mov	SUN4V_CHIP_SPARC_SN, %g4
444	ba,pt	%xcc, 49f
445	 nop
446
44791:	sethi	%hi(prom_cpu_compatible), %g1
448	or	%g1, %lo(prom_cpu_compatible), %g1
449	ldub	[%g1 + 17], %g2
450	cmp	%g2, '1'
451	be,pt	%xcc, 5f
452	 mov	SUN4V_CHIP_NIAGARA1, %g4
453	cmp	%g2, '2'
454	be,pt	%xcc, 5f
455	 mov	SUN4V_CHIP_NIAGARA2, %g4
456
4574:
458	/* Athena */
459	sethi	%hi(prom_cpu_compatible), %g1
460	or	%g1, %lo(prom_cpu_compatible), %g1
461	sethi	%hi(prom_sparc64x_prefix), %g7
462	or	%g7, %lo(prom_sparc64x_prefix), %g7
463	mov	9, %g3
46441:	ldub	[%g7], %g2
465	ldub	[%g1], %g4
466	cmp	%g2, %g4
467	bne,pn	%icc, 49f
468	add	%g7, 1, %g7
469	subcc	%g3, 1, %g3
470	bne,pt	%xcc, 41b
471	add	%g1, 1, %g1
472	ba,pt	%xcc, 5f
473	 mov	SUN4V_CHIP_SPARC64X, %g4
474
47549:
476	mov	SUN4V_CHIP_UNKNOWN, %g4
4775:	sethi	%hi(sun4v_chip_type), %g2
478	or	%g2, %lo(sun4v_chip_type), %g2
479	stw	%g4, [%g2]
480
48180:
482	BRANCH_IF_SUN4V(g1, jump_to_sun4u_init)
483	BRANCH_IF_CHEETAH_BASE(g1,g7,cheetah_boot)
484	BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,cheetah_plus_boot)
485	ba,pt	%xcc, spitfire_boot
486	 nop
487
488cheetah_plus_boot:
489	/* Preserve OBP chosen DCU and DCR register settings.  */
490	ba,pt	%xcc, cheetah_generic_boot
491	 nop
492
493cheetah_boot:
494	mov	DCR_BPE | DCR_RPE | DCR_SI | DCR_IFPOE | DCR_MS, %g1
495	wr	%g1, %asr18
496
497	sethi	%uhi(DCU_ME|DCU_RE|DCU_HPE|DCU_SPE|DCU_SL|DCU_WE), %g7
498	or	%g7, %ulo(DCU_ME|DCU_RE|DCU_HPE|DCU_SPE|DCU_SL|DCU_WE), %g7
499	sllx	%g7, 32, %g7
500	or	%g7, DCU_DM | DCU_IM | DCU_DC | DCU_IC, %g7
501	stxa	%g7, [%g0] ASI_DCU_CONTROL_REG
502	membar	#Sync
503
504cheetah_generic_boot:
505	mov	TSB_EXTENSION_P, %g3
506	stxa	%g0, [%g3] ASI_DMMU
507	stxa	%g0, [%g3] ASI_IMMU
508	membar	#Sync
509
510	mov	TSB_EXTENSION_S, %g3
511	stxa	%g0, [%g3] ASI_DMMU
512	membar	#Sync
513
514	mov	TSB_EXTENSION_N, %g3
515	stxa	%g0, [%g3] ASI_DMMU
516	stxa	%g0, [%g3] ASI_IMMU
517	membar	#Sync
518
519	ba,a,pt	%xcc, jump_to_sun4u_init
520
521spitfire_boot:
522	/* Typically PROM has already enabled both MMU's and both on-chip
523	 * caches, but we do it here anyway just to be paranoid.
524	 */
525	mov	(LSU_CONTROL_IC|LSU_CONTROL_DC|LSU_CONTROL_IM|LSU_CONTROL_DM), %g1
526	stxa	%g1, [%g0] ASI_LSU_CONTROL
527	membar	#Sync
528
529jump_to_sun4u_init:
530	/*
531	 * Make sure we are in privileged mode, have address masking,
532         * using the ordinary globals and have enabled floating
533         * point.
534	 *
535	 * Again, typically PROM has left %pil at 13 or similar, and
536	 * (PSTATE_PRIV | PSTATE_PEF | PSTATE_IE) in %pstate.
537         */
538	wrpr    %g0, (PSTATE_PRIV|PSTATE_PEF|PSTATE_IE), %pstate
539	wr	%g0, 0, %fprs
540
541	set	sun4u_init, %g2
542	jmpl    %g2 + %g0, %g0
543	 nop
544
545	__REF
546sun4u_init:
547	BRANCH_IF_SUN4V(g1, sun4v_init)
548
549	/* Set ctx 0 */
550	mov		PRIMARY_CONTEXT, %g7
551	stxa		%g0, [%g7] ASI_DMMU
552	membar		#Sync
553
554	mov		SECONDARY_CONTEXT, %g7
555	stxa		%g0, [%g7] ASI_DMMU
556	membar	#Sync
557
558	ba,a,pt		%xcc, sun4u_continue
559
560sun4v_init:
561	/* Set ctx 0 */
562	mov		PRIMARY_CONTEXT, %g7
563	stxa		%g0, [%g7] ASI_MMU
564	membar		#Sync
565
566	mov		SECONDARY_CONTEXT, %g7
567	stxa		%g0, [%g7] ASI_MMU
568	membar		#Sync
569	ba,a,pt		%xcc, niagara_tlb_fixup
570
571sun4u_continue:
572	BRANCH_IF_ANY_CHEETAH(g1, g7, cheetah_tlb_fixup)
573
574	ba,a,pt	%xcc, spitfire_tlb_fixup
575
576niagara_tlb_fixup:
577	mov	3, %g2		/* Set TLB type to hypervisor. */
578	sethi	%hi(tlb_type), %g1
579	stw	%g2, [%g1 + %lo(tlb_type)]
580
581	/* Patch copy/clear ops.  */
582	sethi	%hi(sun4v_chip_type), %g1
583	lduw	[%g1 + %lo(sun4v_chip_type)], %g1
584	cmp	%g1, SUN4V_CHIP_NIAGARA1
585	be,pt	%xcc, niagara_patch
586	 cmp	%g1, SUN4V_CHIP_NIAGARA2
587	be,pt	%xcc, niagara2_patch
588	 nop
589	cmp	%g1, SUN4V_CHIP_NIAGARA3
590	be,pt	%xcc, niagara2_patch
591	 nop
592	cmp	%g1, SUN4V_CHIP_NIAGARA4
593	be,pt	%xcc, niagara4_patch
594	 nop
595	cmp	%g1, SUN4V_CHIP_NIAGARA5
596	be,pt	%xcc, niagara4_patch
597	 nop
598	cmp	%g1, SUN4V_CHIP_SPARC_M6
599	be,pt	%xcc, niagara4_patch
600	 nop
601	cmp	%g1, SUN4V_CHIP_SPARC_M7
602	be,pt	%xcc, niagara4_patch
603	 nop
604	cmp	%g1, SUN4V_CHIP_SPARC_SN
605	be,pt	%xcc, niagara4_patch
606	 nop
607
608	call	generic_patch_copyops
609	 nop
610	call	generic_patch_bzero
611	 nop
612	call	generic_patch_pageops
613	 nop
614
615	ba,a,pt	%xcc, 80f
616niagara4_patch:
617	call	niagara4_patch_copyops
618	 nop
619	call	niagara4_patch_bzero
620	 nop
621	call	niagara4_patch_pageops
622	 nop
623
624	ba,a,pt	%xcc, 80f
625
626niagara2_patch:
627	call	niagara2_patch_copyops
628	 nop
629	call	niagara_patch_bzero
630	 nop
631	call	niagara_patch_pageops
632	 nop
633
634	ba,a,pt	%xcc, 80f
635
636niagara_patch:
637	call	niagara_patch_copyops
638	 nop
639	call	niagara_patch_bzero
640	 nop
641	call	niagara_patch_pageops
642	 nop
643
64480:
645	/* Patch TLB/cache ops.  */
646	call	hypervisor_patch_cachetlbops
647	 nop
648
649	ba,a,pt	%xcc, tlb_fixup_done
650
651cheetah_tlb_fixup:
652	mov	2, %g2		/* Set TLB type to cheetah+. */
653	BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,1f)
654
655	mov	1, %g2		/* Set TLB type to cheetah. */
656
6571:	sethi	%hi(tlb_type), %g1
658	stw	%g2, [%g1 + %lo(tlb_type)]
659
660	/* Patch copy/page operations to cheetah optimized versions. */
661	call	cheetah_patch_copyops
662	 nop
663	call	cheetah_patch_copy_page
664	 nop
665	call	cheetah_patch_cachetlbops
666	 nop
667
668	ba,a,pt	%xcc, tlb_fixup_done
669
670spitfire_tlb_fixup:
671	/* Set TLB type to spitfire. */
672	mov	0, %g2
673	sethi	%hi(tlb_type), %g1
674	stw	%g2, [%g1 + %lo(tlb_type)]
675
676tlb_fixup_done:
677	sethi	%hi(init_thread_union), %g6
678	or	%g6, %lo(init_thread_union), %g6
679	ldx	[%g6 + TI_TASK], %g4
680
681	wr	%g0, ASI_P, %asi
682	mov	1, %g1
683	sllx	%g1, THREAD_SHIFT, %g1
684	sub	%g1, (STACKFRAME_SZ + STACK_BIAS), %g1
685	add	%g6, %g1, %sp
686
687	/* Set per-cpu pointer initially to zero, this makes
688	 * the boot-cpu use the in-kernel-image per-cpu areas
689	 * before setup_per_cpu_area() is invoked.
690	 */
691	clr	%g5
692
693	wrpr	%g0, 0, %wstate
694	wrpr	%g0, 0x0, %tl
695
696	/* Clear the bss */
697	sethi	%hi(__bss_start), %o0
698	or	%o0, %lo(__bss_start), %o0
699	sethi	%hi(_end), %o1
700	or	%o1, %lo(_end), %o1
701	call	__bzero
702	 sub	%o1, %o0, %o1
703
704	call	prom_init
705	 mov	%l7, %o0			! OpenPROM cif handler
706
707	/* To create a one-register-window buffer between the kernel's
708	 * initial stack and the last stack frame we use from the firmware,
709	 * do the rest of the boot from a C helper function.
710	 */
711	call	start_early_boot
712	 nop
713	/* Not reached... */
714
715	.previous
716
717	/* This is meant to allow the sharing of this code between
718	 * boot processor invocation (via setup_tba() below) and
719	 * secondary processor startup (via trampoline.S).  The
720	 * former does use this code, the latter does not yet due
721	 * to some complexities.  That should be fixed up at some
722	 * point.
723	 *
724	 * There used to be enormous complexity wrt. transferring
725	 * over from the firmware's trap table to the Linux kernel's.
726	 * For example, there was a chicken & egg problem wrt. building
727	 * the OBP page tables, yet needing to be on the Linux kernel
728	 * trap table (to translate PAGE_OFFSET addresses) in order to
729	 * do that.
730	 *
731	 * We now handle OBP tlb misses differently, via linear lookups
732	 * into the prom_trans[] array.  So that specific problem no
733	 * longer exists.  Yet, unfortunately there are still some issues
734	 * preventing trampoline.S from using this code... ho hum.
735	 */
736	.globl	setup_trap_table
737setup_trap_table:
738	save	%sp, -192, %sp
739
740	/* Force interrupts to be disabled. */
741	rdpr	%pstate, %l0
742	andn	%l0, PSTATE_IE, %o1
743	wrpr	%o1, 0x0, %pstate
744	rdpr	%pil, %l1
745	wrpr	%g0, PIL_NORMAL_MAX, %pil
746
747	/* Make the firmware call to jump over to the Linux trap table.  */
748	sethi	%hi(is_sun4v), %o0
749	lduw	[%o0 + %lo(is_sun4v)], %o0
750	brz,pt	%o0, 1f
751	 nop
752
753	TRAP_LOAD_TRAP_BLOCK(%g2, %g3)
754	add	%g2, TRAP_PER_CPU_FAULT_INFO, %g2
755	stxa	%g2, [%g0] ASI_SCRATCHPAD
756
757	/* Compute physical address:
758	 *
759	 * paddr = kern_base + (mmfsa_vaddr - KERNBASE)
760	 */
761	sethi	%hi(KERNBASE), %g3
762	sub	%g2, %g3, %g2
763	sethi	%hi(kern_base), %g3
764	ldx	[%g3 + %lo(kern_base)], %g3
765	add	%g2, %g3, %o1
766	sethi	%hi(sparc64_ttable_tl0), %o0
767
768	set	prom_set_trap_table_name, %g2
769	stx	%g2, [%sp + 2047 + 128 + 0x00]
770	mov	2, %g2
771	stx	%g2, [%sp + 2047 + 128 + 0x08]
772	mov	0, %g2
773	stx	%g2, [%sp + 2047 + 128 + 0x10]
774	stx	%o0, [%sp + 2047 + 128 + 0x18]
775	stx	%o1, [%sp + 2047 + 128 + 0x20]
776	sethi	%hi(p1275buf), %g2
777	or	%g2, %lo(p1275buf), %g2
778	ldx	[%g2 + 0x08], %o1
779	call	%o1
780	 add	%sp, (2047 + 128), %o0
781
782	ba,a,pt	%xcc, 2f
783
7841:	sethi	%hi(sparc64_ttable_tl0), %o0
785	set	prom_set_trap_table_name, %g2
786	stx	%g2, [%sp + 2047 + 128 + 0x00]
787	mov	1, %g2
788	stx	%g2, [%sp + 2047 + 128 + 0x08]
789	mov	0, %g2
790	stx	%g2, [%sp + 2047 + 128 + 0x10]
791	stx	%o0, [%sp + 2047 + 128 + 0x18]
792	sethi	%hi(p1275buf), %g2
793	or	%g2, %lo(p1275buf), %g2
794	ldx	[%g2 + 0x08], %o1
795	call	%o1
796	 add	%sp, (2047 + 128), %o0
797
798	/* Start using proper page size encodings in ctx register.  */
7992:	sethi	%hi(sparc64_kern_pri_context), %g3
800	ldx	[%g3 + %lo(sparc64_kern_pri_context)], %g2
801
802	mov		PRIMARY_CONTEXT, %g1
803
804661:	stxa		%g2, [%g1] ASI_DMMU
805	.section	.sun4v_1insn_patch, "ax"
806	.word		661b
807	stxa		%g2, [%g1] ASI_MMU
808	.previous
809
810	membar	#Sync
811
812	BRANCH_IF_SUN4V(o2, 1f)
813
814	/* Kill PROM timer */
815	sethi	%hi(0x80000000), %o2
816	sllx	%o2, 32, %o2
817	wr	%o2, 0, %tick_cmpr
818
819	BRANCH_IF_ANY_CHEETAH(o2, o3, 1f)
820
821	ba,a,pt	%xcc, 2f
822
823	/* Disable STICK_INT interrupts. */
8241:
825	sethi	%hi(0x80000000), %o2
826	sllx	%o2, 32, %o2
827	wr	%o2, %asr25
828
8292:
830	wrpr	%g0, %g0, %wstate
831
832	call	init_irqwork_curcpu
833	 nop
834
835	/* Now we can restore interrupt state. */
836	wrpr	%l0, 0, %pstate
837	wrpr	%l1, 0x0, %pil
838
839	ret
840	 restore
841
842	.globl	setup_tba
843setup_tba:
844	save	%sp, -192, %sp
845
846	/* The boot processor is the only cpu which invokes this
847	 * routine, the other cpus set things up via trampoline.S.
848	 * So save the OBP trap table address here.
849	 */
850	rdpr	%tba, %g7
851	sethi	%hi(prom_tba), %o1
852	or	%o1, %lo(prom_tba), %o1
853	stx	%g7, [%o1]
854
855	call	setup_trap_table
856	 nop
857
858	ret
859	 restore
860sparc64_boot_end:
861
862#include "etrap_64.S"
863#include "rtrap_64.S"
864#include "winfixup.S"
865#include "fpu_traps.S"
866#include "ivec.S"
867#include "getsetcc.S"
868#include "utrap.S"
869#include "spiterrs.S"
870#include "cherrs.S"
871#include "misctrap.S"
872#include "syscalls.S"
873#include "helpers.S"
874#include "hvcalls.S"
875#include "sun4v_tlb_miss.S"
876#include "sun4v_ivec.S"
877#include "ktlb.S"
878#include "tsb.S"
879
880/*
881 * The following skip makes sure the trap table in ttable.S is aligned
882 * on a 32K boundary as required by the v9 specs for TBA register.
883 *
884 * We align to a 32K boundary, then we have the 32K kernel TSB,
885 * the 64K kernel 4MB TSB, and then the 32K aligned trap table.
886 */
8871:
888	.skip	0x4000 + _start - 1b
889
890! 0x0000000000408000
891
892	.globl	swapper_tsb
893swapper_tsb:
894	.skip	(32 * 1024)
895
896	.globl	swapper_4m_tsb
897swapper_4m_tsb:
898	.skip	(64 * 1024)
899
900! 0x0000000000420000
901
902	/* Some care needs to be exercised if you try to move the
903	 * location of the trap table relative to other things.  For
904	 * one thing there are br* instructions in some of the
905	 * trap table entires which branch back to code in ktlb.S
906	 * Those instructions can only handle a signed 16-bit
907	 * displacement.
908	 *
909	 * There is a binutils bug (bugzilla #4558) which causes
910	 * the relocation overflow checks for such instructions to
911	 * not be done correctly.  So bintuils will not notice the
912	 * error and will instead write junk into the relocation and
913	 * you'll have an unbootable kernel.
914	 */
915#include "ttable_64.S"
916
917! 0x0000000000428000
918
919#include "systbls_64.S"
920
921	.data
922	.align	8
923	.globl	prom_tba, tlb_type
924prom_tba:	.xword	0
925tlb_type:	.word	0	/* Must NOT end up in BSS */
926EXPORT_SYMBOL(tlb_type)
927	.section	".fixup",#alloc,#execinstr
928
929ENTRY(__retl_efault)
930	retl
931	 mov	-EFAULT, %o0
932ENDPROC(__retl_efault)
933
934ENTRY(__retl_o1)
935	retl
936	 mov	%o1, %o0
937ENDPROC(__retl_o1)
938