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