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