Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /* head.S: Initial boot code for the Sparc64 port of Linux.
0003  *
0004  * Copyright (C) 1996, 1997, 2007 David S. Miller (davem@davemloft.net)
0005  * Copyright (C) 1996 David Sitsky (David.Sitsky@anu.edu.au)
0006  * Copyright (C) 1997, 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
0007  * Copyright (C) 1997 Miguel de Icaza (miguel@nuclecu.unam.mx)
0008  */
0009 
0010 #include <linux/version.h>
0011 #include <linux/errno.h>
0012 #include <linux/threads.h>
0013 #include <linux/init.h>
0014 #include <linux/linkage.h>
0015 #include <linux/pgtable.h>
0016 #include <asm/thread_info.h>
0017 #include <asm/asi.h>
0018 #include <asm/pstate.h>
0019 #include <asm/ptrace.h>
0020 #include <asm/spitfire.h>
0021 #include <asm/page.h>
0022 #include <asm/errno.h>
0023 #include <asm/signal.h>
0024 #include <asm/processor.h>
0025 #include <asm/lsu.h>
0026 #include <asm/dcr.h>
0027 #include <asm/dcu.h>
0028 #include <asm/head.h>
0029 #include <asm/ttable.h>
0030 #include <asm/mmu.h>
0031 #include <asm/cpudata.h>
0032 #include <asm/pil.h>
0033 #include <asm/estate.h>
0034 #include <asm/sfafsr.h>
0035 #include <asm/unistd.h>
0036 #include <asm/export.h>
0037 
0038 /* This section from from _start to sparc64_boot_end should fit into
0039  * 0x0000000000404000 to 0x0000000000408000.
0040  */
0041     .text
0042     .globl  start, _start, stext, _stext
0043 _start:
0044 start:
0045 _stext:
0046 stext:
0047 ! 0x0000000000404000
0048     b   sparc64_boot
0049      flushw                 /* Flush register file.      */
0050 
0051 /* This stuff has to be in sync with SILO and other potential boot loaders
0052  * Fields should be kept upward compatible and whenever any change is made,
0053  * HdrS version should be incremented.
0054  */
0055         .global root_flags, ram_flags, root_dev
0056         .global sparc_ramdisk_image, sparc_ramdisk_size
0057     .global sparc_ramdisk_image64
0058 
0059         .ascii  "HdrS"
0060         .word   LINUX_VERSION_CODE
0061 
0062     /* History:
0063      *
0064      * 0x0300 : Supports being located at other than 0x4000
0065      * 0x0202 : Supports kernel params string
0066      * 0x0201 : Supports reboot_command
0067      */
0068     .half   0x0301          /* HdrS version */
0069 
0070 root_flags:
0071         .half   1
0072 root_dev:
0073         .half   0
0074 ram_flags:
0075         .half   0
0076 sparc_ramdisk_image:
0077         .word   0
0078 sparc_ramdisk_size:
0079         .word   0
0080         .xword  reboot_command
0081     .xword  bootstr_info
0082 sparc_ramdisk_image64:
0083     .xword  0
0084     .word   _end
0085 
0086     /* PROM cif handler code address is in %o4.  */
0087 sparc64_boot:
0088     mov %o4, %l7
0089 
0090     /* We need to remap the kernel.  Use position independent
0091      * code to remap us to KERNBASE.
0092      *
0093      * SILO can invoke us with 32-bit address masking enabled,
0094      * so make sure that's clear.
0095      */
0096     rdpr    %pstate, %g1
0097     andn    %g1, PSTATE_AM, %g1
0098     wrpr    %g1, 0x0, %pstate
0099     ba,a,pt %xcc, 1f
0100      nop
0101 
0102     .globl  prom_finddev_name, prom_chosen_path, prom_root_node
0103     .globl  prom_getprop_name, prom_mmu_name, prom_peer_name
0104     .globl  prom_callmethod_name, prom_translate_name, prom_root_compatible
0105     .globl  prom_map_name, prom_unmap_name, prom_mmu_ihandle_cache
0106     .globl  prom_boot_mapped_pc, prom_boot_mapping_mode
0107     .globl  prom_boot_mapping_phys_high, prom_boot_mapping_phys_low
0108     .globl  prom_compatible_name, prom_cpu_path, prom_cpu_compatible
0109     .globl  is_sun4v, sun4v_chip_type, prom_set_trap_table_name
0110 prom_peer_name:
0111     .asciz  "peer"
0112 prom_compatible_name:
0113     .asciz  "compatible"
0114 prom_finddev_name:
0115     .asciz  "finddevice"
0116 prom_chosen_path:
0117     .asciz  "/chosen"
0118 prom_cpu_path:
0119     .asciz  "/cpu"
0120 prom_getprop_name:
0121     .asciz  "getprop"
0122 prom_mmu_name:
0123     .asciz  "mmu"
0124 prom_callmethod_name:
0125     .asciz  "call-method"
0126 prom_translate_name:
0127     .asciz  "translate"
0128 prom_map_name:
0129     .asciz  "map"
0130 prom_unmap_name:
0131     .asciz  "unmap"
0132 prom_set_trap_table_name:
0133     .asciz  "SUNW,set-trap-table"
0134 prom_sun4v_name:
0135     .asciz  "sun4v"
0136 prom_niagara_prefix:
0137     .asciz  "SUNW,UltraSPARC-T"
0138 prom_sparc_prefix:
0139     .asciz  "SPARC-"
0140 prom_sparc64x_prefix:
0141     .asciz  "SPARC64-X"
0142     .align  4
0143 prom_root_compatible:
0144     .skip   64
0145 prom_cpu_compatible:
0146     .skip   64
0147 prom_root_node:
0148     .word   0
0149 EXPORT_SYMBOL(prom_root_node)
0150 prom_mmu_ihandle_cache:
0151     .word   0
0152 prom_boot_mapped_pc:
0153     .word   0
0154 prom_boot_mapping_mode:
0155     .word   0
0156     .align  8
0157 prom_boot_mapping_phys_high:
0158     .xword  0
0159 prom_boot_mapping_phys_low:
0160     .xword  0
0161 is_sun4v:
0162     .word   0
0163 sun4v_chip_type:
0164     .word   SUN4V_CHIP_INVALID
0165 EXPORT_SYMBOL(sun4v_chip_type)
0166 1:
0167     rd  %pc, %l0
0168 
0169     mov (1b - prom_peer_name), %l1
0170     sub %l0, %l1, %l1
0171     mov 0, %l2
0172 
0173     /* prom_root_node = prom_peer(0) */
0174     stx %l1, [%sp + 2047 + 128 + 0x00]  ! service, "peer"
0175     mov 1, %l3
0176     stx %l3, [%sp + 2047 + 128 + 0x08]  ! num_args, 1
0177     stx %l3, [%sp + 2047 + 128 + 0x10]  ! num_rets, 1
0178     stx %l2, [%sp + 2047 + 128 + 0x18]  ! arg1, 0
0179     stx %g0, [%sp + 2047 + 128 + 0x20]  ! ret1
0180     call    %l7
0181      add    %sp, (2047 + 128), %o0      ! argument array
0182 
0183     ldx [%sp + 2047 + 128 + 0x20], %l4  ! prom root node
0184     mov (1b - prom_root_node), %l1
0185     sub %l0, %l1, %l1
0186     stw %l4, [%l1]
0187 
0188     mov (1b - prom_getprop_name), %l1
0189     mov (1b - prom_compatible_name), %l2
0190     mov (1b - prom_root_compatible), %l5
0191     sub %l0, %l1, %l1
0192     sub %l0, %l2, %l2
0193     sub %l0, %l5, %l5
0194 
0195     /* prom_getproperty(prom_root_node, "compatible",
0196      *                  &prom_root_compatible, 64)
0197      */
0198     stx %l1, [%sp + 2047 + 128 + 0x00]  ! service, "getprop"
0199     mov 4, %l3
0200     stx %l3, [%sp + 2047 + 128 + 0x08]  ! num_args, 4
0201     mov 1, %l3
0202     stx %l3, [%sp + 2047 + 128 + 0x10]  ! num_rets, 1
0203     stx %l4, [%sp + 2047 + 128 + 0x18]  ! arg1, prom_root_node
0204     stx %l2, [%sp + 2047 + 128 + 0x20]  ! arg2, "compatible"
0205     stx %l5, [%sp + 2047 + 128 + 0x28]  ! arg3, &prom_root_compatible
0206     mov 64, %l3
0207     stx %l3, [%sp + 2047 + 128 + 0x30]  ! arg4, size
0208     stx %g0, [%sp + 2047 + 128 + 0x38]  ! ret1
0209     call    %l7
0210      add    %sp, (2047 + 128), %o0      ! argument array
0211 
0212     mov (1b - prom_finddev_name), %l1
0213     mov (1b - prom_chosen_path), %l2
0214     mov (1b - prom_boot_mapped_pc), %l3
0215     sub %l0, %l1, %l1
0216     sub %l0, %l2, %l2
0217     sub %l0, %l3, %l3
0218     stw %l0, [%l3]
0219     sub %sp, (192 + 128), %sp
0220 
0221     /* chosen_node = prom_finddevice("/chosen") */
0222     stx %l1, [%sp + 2047 + 128 + 0x00]  ! service, "finddevice"
0223     mov 1, %l3
0224     stx %l3, [%sp + 2047 + 128 + 0x08]  ! num_args, 1
0225     stx %l3, [%sp + 2047 + 128 + 0x10]  ! num_rets, 1
0226     stx %l2, [%sp + 2047 + 128 + 0x18]  ! arg1, "/chosen"
0227     stx %g0, [%sp + 2047 + 128 + 0x20]  ! ret1
0228     call    %l7
0229      add    %sp, (2047 + 128), %o0      ! argument array
0230 
0231     ldx [%sp + 2047 + 128 + 0x20], %l4  ! chosen device node
0232 
0233     mov (1b - prom_getprop_name), %l1
0234     mov (1b - prom_mmu_name), %l2
0235     mov (1b - prom_mmu_ihandle_cache), %l5
0236     sub %l0, %l1, %l1
0237     sub %l0, %l2, %l2
0238     sub %l0, %l5, %l5
0239 
0240     /* prom_mmu_ihandle_cache = prom_getint(chosen_node, "mmu") */
0241     stx %l1, [%sp + 2047 + 128 + 0x00]  ! service, "getprop"
0242     mov 4, %l3
0243     stx %l3, [%sp + 2047 + 128 + 0x08]  ! num_args, 4
0244     mov 1, %l3
0245     stx %l3, [%sp + 2047 + 128 + 0x10]  ! num_rets, 1
0246     stx %l4, [%sp + 2047 + 128 + 0x18]  ! arg1, chosen_node
0247     stx %l2, [%sp + 2047 + 128 + 0x20]  ! arg2, "mmu"
0248     stx %l5, [%sp + 2047 + 128 + 0x28]  ! arg3, &prom_mmu_ihandle_cache
0249     mov 4, %l3
0250     stx %l3, [%sp + 2047 + 128 + 0x30]  ! arg4, sizeof(arg3)
0251     stx %g0, [%sp + 2047 + 128 + 0x38]  ! ret1
0252     call    %l7
0253      add    %sp, (2047 + 128), %o0      ! argument array
0254 
0255     mov (1b - prom_callmethod_name), %l1
0256     mov (1b - prom_translate_name), %l2
0257     sub %l0, %l1, %l1
0258     sub %l0, %l2, %l2
0259     lduw    [%l5], %l5          ! prom_mmu_ihandle_cache
0260 
0261     stx %l1, [%sp + 2047 + 128 + 0x00]  ! service, "call-method"
0262     mov 3, %l3
0263     stx %l3, [%sp + 2047 + 128 + 0x08]  ! num_args, 3
0264     mov 5, %l3
0265     stx %l3, [%sp + 2047 + 128 + 0x10]  ! num_rets, 5
0266     stx %l2, [%sp + 2047 + 128 + 0x18]  ! arg1: "translate"
0267     stx %l5, [%sp + 2047 + 128 + 0x20]  ! arg2: prom_mmu_ihandle_cache
0268     /* PAGE align */
0269     srlx    %l0, 13, %l3
0270     sllx    %l3, 13, %l3
0271     stx %l3, [%sp + 2047 + 128 + 0x28]  ! arg3: vaddr, our PC
0272     stx %g0, [%sp + 2047 + 128 + 0x30]  ! res1
0273     stx %g0, [%sp + 2047 + 128 + 0x38]  ! res2
0274     stx %g0, [%sp + 2047 + 128 + 0x40]  ! res3
0275     stx %g0, [%sp + 2047 + 128 + 0x48]  ! res4
0276     stx %g0, [%sp + 2047 + 128 + 0x50]  ! res5
0277     call    %l7
0278      add    %sp, (2047 + 128), %o0      ! argument array
0279 
0280     ldx [%sp + 2047 + 128 + 0x40], %l1  ! translation mode
0281     mov (1b - prom_boot_mapping_mode), %l4
0282     sub %l0, %l4, %l4
0283     stw %l1, [%l4]
0284     mov (1b - prom_boot_mapping_phys_high), %l4
0285     sub %l0, %l4, %l4
0286     ldx [%sp + 2047 + 128 + 0x48], %l2  ! physaddr high
0287     stx %l2, [%l4 + 0x0]
0288     ldx [%sp + 2047 + 128 + 0x50], %l3  ! physaddr low
0289     /* 4MB align */
0290     srlx    %l3, ILOG2_4MB, %l3
0291     sllx    %l3, ILOG2_4MB, %l3
0292     stx %l3, [%l4 + 0x8]
0293 
0294     /* Leave service as-is, "call-method" */
0295     mov 7, %l3
0296     stx %l3, [%sp + 2047 + 128 + 0x08]  ! num_args, 7
0297     mov 1, %l3
0298     stx %l3, [%sp + 2047 + 128 + 0x10]  ! num_rets, 1
0299     mov (1b - prom_map_name), %l3
0300     sub %l0, %l3, %l3
0301     stx %l3, [%sp + 2047 + 128 + 0x18]  ! arg1: "map"
0302     /* Leave arg2 as-is, prom_mmu_ihandle_cache */
0303     mov -1, %l3
0304     stx %l3, [%sp + 2047 + 128 + 0x28]  ! arg3: mode (-1 default)
0305     /* 4MB align the kernel image size. */
0306     set (_end - KERNBASE), %l3
0307     set ((4 * 1024 * 1024) - 1), %l4
0308     add %l3, %l4, %l3
0309     andn    %l3, %l4, %l3
0310     stx %l3, [%sp + 2047 + 128 + 0x30]  ! arg4: roundup(ksize, 4MB)
0311     sethi   %hi(KERNBASE), %l3
0312     stx %l3, [%sp + 2047 + 128 + 0x38]  ! arg5: vaddr (KERNBASE)
0313     stx %g0, [%sp + 2047 + 128 + 0x40]  ! arg6: empty
0314     mov (1b - prom_boot_mapping_phys_low), %l3
0315     sub %l0, %l3, %l3
0316     ldx [%l3], %l3
0317     stx %l3, [%sp + 2047 + 128 + 0x48]  ! arg7: phys addr
0318     call    %l7
0319      add    %sp, (2047 + 128), %o0      ! argument array
0320 
0321     add %sp, (192 + 128), %sp
0322 
0323     sethi   %hi(prom_root_compatible), %g1
0324     or  %g1, %lo(prom_root_compatible), %g1
0325     sethi   %hi(prom_sun4v_name), %g7
0326     or  %g7, %lo(prom_sun4v_name), %g7
0327     mov 5, %g3
0328 90: ldub    [%g7], %g2
0329     ldub    [%g1], %g4
0330     cmp %g2, %g4
0331     bne,pn  %icc, 80f
0332      add    %g7, 1, %g7
0333     subcc   %g3, 1, %g3
0334     bne,pt  %xcc, 90b
0335      add    %g1, 1, %g1
0336 
0337     sethi   %hi(is_sun4v), %g1
0338     or  %g1, %lo(is_sun4v), %g1
0339     mov 1, %g7
0340     stw %g7, [%g1]
0341 
0342     /* cpu_node = prom_finddevice("/cpu") */
0343     mov (1b - prom_finddev_name), %l1
0344     mov (1b - prom_cpu_path), %l2
0345     sub %l0, %l1, %l1
0346     sub %l0, %l2, %l2
0347     sub %sp, (192 + 128), %sp
0348 
0349     stx %l1, [%sp + 2047 + 128 + 0x00]  ! service, "finddevice"
0350     mov 1, %l3
0351     stx %l3, [%sp + 2047 + 128 + 0x08]  ! num_args, 1
0352     stx %l3, [%sp + 2047 + 128 + 0x10]  ! num_rets, 1
0353     stx %l2, [%sp + 2047 + 128 + 0x18]  ! arg1, "/cpu"
0354     stx %g0, [%sp + 2047 + 128 + 0x20]  ! ret1
0355     call    %l7
0356      add    %sp, (2047 + 128), %o0      ! argument array
0357 
0358     ldx [%sp + 2047 + 128 + 0x20], %l4  ! cpu device node
0359 
0360     mov (1b - prom_getprop_name), %l1
0361     mov (1b - prom_compatible_name), %l2
0362     mov (1b - prom_cpu_compatible), %l5
0363     sub %l0, %l1, %l1
0364     sub %l0, %l2, %l2
0365     sub %l0, %l5, %l5
0366 
0367     /* prom_getproperty(cpu_node, "compatible",
0368      *                  &prom_cpu_compatible, 64)
0369      */
0370     stx %l1, [%sp + 2047 + 128 + 0x00]  ! service, "getprop"
0371     mov 4, %l3
0372     stx %l3, [%sp + 2047 + 128 + 0x08]  ! num_args, 4
0373     mov 1, %l3
0374     stx %l3, [%sp + 2047 + 128 + 0x10]  ! num_rets, 1
0375     stx %l4, [%sp + 2047 + 128 + 0x18]  ! arg1, cpu_node
0376     stx %l2, [%sp + 2047 + 128 + 0x20]  ! arg2, "compatible"
0377     stx %l5, [%sp + 2047 + 128 + 0x28]  ! arg3, &prom_cpu_compatible
0378     mov 64, %l3
0379     stx %l3, [%sp + 2047 + 128 + 0x30]  ! arg4, size
0380     stx %g0, [%sp + 2047 + 128 + 0x38]  ! ret1
0381     call    %l7
0382      add    %sp, (2047 + 128), %o0      ! argument array
0383 
0384     add %sp, (192 + 128), %sp
0385 
0386     sethi   %hi(prom_cpu_compatible), %g1
0387     or  %g1, %lo(prom_cpu_compatible), %g1
0388     sethi   %hi(prom_niagara_prefix), %g7
0389     or  %g7, %lo(prom_niagara_prefix), %g7
0390     mov 17, %g3
0391 90: ldub    [%g7], %g2
0392     ldub    [%g1], %g4
0393     cmp %g2, %g4
0394     bne,pn  %icc, 89f
0395      add    %g7, 1, %g7
0396     subcc   %g3, 1, %g3
0397     bne,pt  %xcc, 90b
0398      add    %g1, 1, %g1
0399     ba,pt   %xcc, 91f
0400      nop
0401 
0402 89: sethi   %hi(prom_cpu_compatible), %g1
0403     or  %g1, %lo(prom_cpu_compatible), %g1
0404     sethi   %hi(prom_sparc_prefix), %g7
0405     or  %g7, %lo(prom_sparc_prefix), %g7
0406     mov 6, %g3
0407 90: ldub    [%g7], %g2
0408     ldub    [%g1], %g4
0409     cmp %g2, %g4
0410     bne,pn  %icc, 4f
0411      add    %g7, 1, %g7
0412     subcc   %g3, 1, %g3
0413     bne,pt  %xcc, 90b
0414      add    %g1, 1, %g1
0415 
0416     sethi   %hi(prom_cpu_compatible), %g1
0417     or  %g1, %lo(prom_cpu_compatible), %g1
0418     ldub    [%g1 + 6], %g2
0419     cmp %g2, 'T'
0420     be,pt   %xcc, 70f
0421      cmp    %g2, 'M'
0422     be,pt   %xcc, 70f
0423      cmp    %g2, 'S'
0424     bne,pn  %xcc, 49f
0425      nop
0426 
0427 70: ldub    [%g1 + 7], %g2
0428     cmp %g2, CPU_ID_NIAGARA3
0429     be,pt   %xcc, 5f
0430      mov    SUN4V_CHIP_NIAGARA3, %g4
0431     cmp %g2, CPU_ID_NIAGARA4
0432     be,pt   %xcc, 5f
0433      mov    SUN4V_CHIP_NIAGARA4, %g4
0434     cmp %g2, CPU_ID_NIAGARA5
0435     be,pt   %xcc, 5f
0436      mov    SUN4V_CHIP_NIAGARA5, %g4
0437     cmp %g2, CPU_ID_M6
0438     be,pt   %xcc, 5f
0439      mov    SUN4V_CHIP_SPARC_M6, %g4
0440     cmp %g2, CPU_ID_M7
0441     be,pt   %xcc, 5f
0442      mov    SUN4V_CHIP_SPARC_M7, %g4
0443     cmp %g2, CPU_ID_M8
0444     be,pt   %xcc, 5f
0445      mov    SUN4V_CHIP_SPARC_M8, %g4
0446     cmp %g2, CPU_ID_SONOMA1
0447     be,pt   %xcc, 5f
0448      mov    SUN4V_CHIP_SPARC_SN, %g4
0449     ba,pt   %xcc, 49f
0450      nop
0451 
0452 91: sethi   %hi(prom_cpu_compatible), %g1
0453     or  %g1, %lo(prom_cpu_compatible), %g1
0454     ldub    [%g1 + 17], %g2
0455     cmp %g2, CPU_ID_NIAGARA1
0456     be,pt   %xcc, 5f
0457      mov    SUN4V_CHIP_NIAGARA1, %g4
0458     cmp %g2, CPU_ID_NIAGARA2
0459     be,pt   %xcc, 5f
0460      mov    SUN4V_CHIP_NIAGARA2, %g4
0461     
0462 4:
0463     /* Athena */
0464     sethi   %hi(prom_cpu_compatible), %g1
0465     or  %g1, %lo(prom_cpu_compatible), %g1
0466     sethi   %hi(prom_sparc64x_prefix), %g7
0467     or  %g7, %lo(prom_sparc64x_prefix), %g7
0468     mov 9, %g3
0469 41: ldub    [%g7], %g2
0470     ldub    [%g1], %g4
0471     cmp %g2, %g4
0472     bne,pn  %icc, 49f
0473     add %g7, 1, %g7
0474     subcc   %g3, 1, %g3
0475     bne,pt  %xcc, 41b
0476     add %g1, 1, %g1
0477     ba,pt   %xcc, 5f
0478      mov    SUN4V_CHIP_SPARC64X, %g4
0479 
0480 49:
0481     mov SUN4V_CHIP_UNKNOWN, %g4
0482 5:  sethi   %hi(sun4v_chip_type), %g2
0483     or  %g2, %lo(sun4v_chip_type), %g2
0484     stw %g4, [%g2]
0485 
0486 80:
0487     BRANCH_IF_SUN4V(g1, jump_to_sun4u_init)
0488     BRANCH_IF_CHEETAH_BASE(g1,g7,cheetah_boot)
0489     BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,cheetah_plus_boot)
0490     ba,pt   %xcc, spitfire_boot
0491      nop
0492 
0493 cheetah_plus_boot:
0494     /* Preserve OBP chosen DCU and DCR register settings.  */
0495     ba,pt   %xcc, cheetah_generic_boot
0496      nop
0497 
0498 cheetah_boot:
0499     mov DCR_BPE | DCR_RPE | DCR_SI | DCR_IFPOE | DCR_MS, %g1
0500     wr  %g1, %asr18
0501 
0502     sethi   %uhi(DCU_ME|DCU_RE|DCU_HPE|DCU_SPE|DCU_SL|DCU_WE), %g7
0503     or  %g7, %ulo(DCU_ME|DCU_RE|DCU_HPE|DCU_SPE|DCU_SL|DCU_WE), %g7
0504     sllx    %g7, 32, %g7
0505     or  %g7, DCU_DM | DCU_IM | DCU_DC | DCU_IC, %g7
0506     stxa    %g7, [%g0] ASI_DCU_CONTROL_REG
0507     membar  #Sync
0508 
0509 cheetah_generic_boot:
0510     mov TSB_EXTENSION_P, %g3
0511     stxa    %g0, [%g3] ASI_DMMU
0512     stxa    %g0, [%g3] ASI_IMMU
0513     membar  #Sync
0514 
0515     mov TSB_EXTENSION_S, %g3
0516     stxa    %g0, [%g3] ASI_DMMU
0517     membar  #Sync
0518 
0519     mov TSB_EXTENSION_N, %g3
0520     stxa    %g0, [%g3] ASI_DMMU
0521     stxa    %g0, [%g3] ASI_IMMU
0522     membar  #Sync
0523 
0524     ba,a,pt %xcc, jump_to_sun4u_init
0525 
0526 spitfire_boot:
0527     /* Typically PROM has already enabled both MMU's and both on-chip
0528      * caches, but we do it here anyway just to be paranoid.
0529      */
0530     mov (LSU_CONTROL_IC|LSU_CONTROL_DC|LSU_CONTROL_IM|LSU_CONTROL_DM), %g1
0531     stxa    %g1, [%g0] ASI_LSU_CONTROL
0532     membar  #Sync
0533 
0534 jump_to_sun4u_init:
0535     /*
0536      * Make sure we are in privileged mode, have address masking,
0537          * using the ordinary globals and have enabled floating
0538          * point.
0539      *
0540      * Again, typically PROM has left %pil at 13 or similar, and
0541      * (PSTATE_PRIV | PSTATE_PEF | PSTATE_IE) in %pstate.
0542          */
0543     wrpr    %g0, (PSTATE_PRIV|PSTATE_PEF|PSTATE_IE), %pstate
0544     wr  %g0, 0, %fprs
0545 
0546     set sun4u_init, %g2
0547     jmpl    %g2 + %g0, %g0
0548      nop
0549 
0550     __REF
0551 sun4u_init:
0552     BRANCH_IF_SUN4V(g1, sun4v_init)
0553 
0554     /* Set ctx 0 */
0555     mov     PRIMARY_CONTEXT, %g7
0556     stxa        %g0, [%g7] ASI_DMMU
0557     membar      #Sync
0558 
0559     mov     SECONDARY_CONTEXT, %g7
0560     stxa        %g0, [%g7] ASI_DMMU
0561     membar  #Sync
0562 
0563     ba,a,pt     %xcc, sun4u_continue
0564 
0565 sun4v_init:
0566     /* Set ctx 0 */
0567     mov     PRIMARY_CONTEXT, %g7
0568     stxa        %g0, [%g7] ASI_MMU
0569     membar      #Sync
0570 
0571     mov     SECONDARY_CONTEXT, %g7
0572     stxa        %g0, [%g7] ASI_MMU
0573     membar      #Sync
0574     ba,a,pt     %xcc, niagara_tlb_fixup
0575 
0576 sun4u_continue:
0577     BRANCH_IF_ANY_CHEETAH(g1, g7, cheetah_tlb_fixup)
0578 
0579     ba,a,pt %xcc, spitfire_tlb_fixup
0580 
0581 niagara_tlb_fixup:
0582     mov 3, %g2      /* Set TLB type to hypervisor. */
0583     sethi   %hi(tlb_type), %g1
0584     stw %g2, [%g1 + %lo(tlb_type)]
0585 
0586     /* Patch copy/clear ops.  */
0587     sethi   %hi(sun4v_chip_type), %g1
0588     lduw    [%g1 + %lo(sun4v_chip_type)], %g1
0589     cmp %g1, SUN4V_CHIP_NIAGARA1
0590     be,pt   %xcc, niagara_patch
0591      cmp    %g1, SUN4V_CHIP_NIAGARA2
0592     be,pt   %xcc, niagara2_patch
0593      nop
0594     cmp %g1, SUN4V_CHIP_NIAGARA3
0595     be,pt   %xcc, niagara2_patch
0596      nop
0597     cmp %g1, SUN4V_CHIP_NIAGARA4
0598     be,pt   %xcc, niagara4_patch
0599      nop
0600     cmp %g1, SUN4V_CHIP_NIAGARA5
0601     be,pt   %xcc, niagara4_patch
0602      nop
0603     cmp %g1, SUN4V_CHIP_SPARC_M6
0604     be,pt   %xcc, niagara4_patch
0605      nop
0606     cmp %g1, SUN4V_CHIP_SPARC_M7
0607     be,pt   %xcc, sparc_m7_patch
0608      nop
0609     cmp %g1, SUN4V_CHIP_SPARC_M8
0610     be,pt   %xcc, sparc_m7_patch
0611      nop
0612     cmp %g1, SUN4V_CHIP_SPARC_SN
0613     be,pt   %xcc, niagara4_patch
0614      nop
0615 
0616     call    generic_patch_copyops
0617      nop
0618     call    generic_patch_bzero
0619      nop
0620     call    generic_patch_pageops
0621      nop
0622 
0623     ba,a,pt %xcc, 80f
0624      nop
0625 
0626 sparc_m7_patch:
0627     call    m7_patch_copyops
0628      nop
0629     call    m7_patch_bzero
0630      nop
0631     call    m7_patch_pageops
0632      nop
0633 
0634     ba,a,pt %xcc, 80f
0635      nop
0636 
0637 niagara4_patch:
0638     call    niagara4_patch_copyops
0639      nop
0640     call    niagara4_patch_bzero
0641      nop
0642     call    niagara4_patch_pageops
0643      nop
0644     call    niagara4_patch_fls
0645      nop
0646 
0647     ba,a,pt %xcc, 80f
0648      nop
0649 
0650 niagara2_patch:
0651     call    niagara2_patch_copyops
0652      nop
0653     call    niagara_patch_bzero
0654      nop
0655     call    niagara_patch_pageops
0656      nop
0657 
0658     ba,a,pt %xcc, 80f
0659      nop
0660 
0661 niagara_patch:
0662     call    niagara_patch_copyops
0663      nop
0664     call    niagara_patch_bzero
0665      nop
0666     call    niagara_patch_pageops
0667      nop
0668 
0669 80:
0670     /* Patch TLB/cache ops.  */
0671     call    hypervisor_patch_cachetlbops
0672      nop
0673 
0674     ba,a,pt %xcc, tlb_fixup_done
0675 
0676 cheetah_tlb_fixup:
0677     mov 2, %g2      /* Set TLB type to cheetah+. */
0678     BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,1f)
0679 
0680     mov 1, %g2      /* Set TLB type to cheetah. */
0681 
0682 1:  sethi   %hi(tlb_type), %g1
0683     stw %g2, [%g1 + %lo(tlb_type)]
0684 
0685     /* Patch copy/page operations to cheetah optimized versions. */
0686     call    cheetah_patch_copyops
0687      nop
0688     call    cheetah_patch_copy_page
0689      nop
0690     call    cheetah_patch_cachetlbops
0691      nop
0692 
0693     ba,a,pt %xcc, tlb_fixup_done
0694 
0695 spitfire_tlb_fixup:
0696     /* Set TLB type to spitfire. */
0697     mov 0, %g2
0698     sethi   %hi(tlb_type), %g1
0699     stw %g2, [%g1 + %lo(tlb_type)]
0700 
0701 tlb_fixup_done:
0702     sethi   %hi(init_thread_union), %g6
0703     or  %g6, %lo(init_thread_union), %g6
0704     ldx [%g6 + TI_TASK], %g4
0705 
0706     wr  %g0, ASI_P, %asi
0707     mov 1, %g1
0708     sllx    %g1, THREAD_SHIFT, %g1
0709     sub %g1, (STACKFRAME_SZ + STACK_BIAS + TRACEREG_SZ), %g1
0710     add %g6, %g1, %sp
0711 
0712     /* Set per-cpu pointer initially to zero, this makes
0713      * the boot-cpu use the in-kernel-image per-cpu areas
0714      * before setup_per_cpu_area() is invoked.
0715      */
0716     clr %g5
0717 
0718     wrpr    %g0, 0, %wstate
0719     wrpr    %g0, 0x0, %tl
0720 
0721     /* Clear the bss */
0722     sethi   %hi(__bss_start), %o0
0723     or  %o0, %lo(__bss_start), %o0
0724     sethi   %hi(_end), %o1
0725     or  %o1, %lo(_end), %o1
0726     call    __bzero
0727      sub    %o1, %o0, %o1
0728 
0729     call    prom_init
0730      mov    %l7, %o0            ! OpenPROM cif handler
0731 
0732     /* To create a one-register-window buffer between the kernel's
0733      * initial stack and the last stack frame we use from the firmware,
0734      * do the rest of the boot from a C helper function.
0735      */
0736     call    start_early_boot
0737      nop
0738     /* Not reached... */
0739 
0740     .previous
0741 
0742     /* This is meant to allow the sharing of this code between
0743      * boot processor invocation (via setup_tba() below) and
0744      * secondary processor startup (via trampoline.S).  The
0745      * former does use this code, the latter does not yet due
0746      * to some complexities.  That should be fixed up at some
0747      * point.
0748      *
0749      * There used to be enormous complexity wrt. transferring
0750      * over from the firmware's trap table to the Linux kernel's.
0751      * For example, there was a chicken & egg problem wrt. building
0752      * the OBP page tables, yet needing to be on the Linux kernel
0753      * trap table (to translate PAGE_OFFSET addresses) in order to
0754      * do that.
0755      *
0756      * We now handle OBP tlb misses differently, via linear lookups
0757      * into the prom_trans[] array.  So that specific problem no
0758      * longer exists.  Yet, unfortunately there are still some issues
0759      * preventing trampoline.S from using this code... ho hum.
0760      */
0761     .globl  setup_trap_table
0762 setup_trap_table:
0763     save    %sp, -192, %sp
0764 
0765     /* Force interrupts to be disabled. */
0766     rdpr    %pstate, %l0
0767     andn    %l0, PSTATE_IE, %o1
0768     wrpr    %o1, 0x0, %pstate
0769     rdpr    %pil, %l1
0770     wrpr    %g0, PIL_NORMAL_MAX, %pil
0771 
0772     /* Make the firmware call to jump over to the Linux trap table.  */
0773     sethi   %hi(is_sun4v), %o0
0774     lduw    [%o0 + %lo(is_sun4v)], %o0
0775     brz,pt  %o0, 1f
0776      nop
0777 
0778     TRAP_LOAD_TRAP_BLOCK(%g2, %g3)
0779     add %g2, TRAP_PER_CPU_FAULT_INFO, %g2
0780     stxa    %g2, [%g0] ASI_SCRATCHPAD
0781 
0782     /* Compute physical address:
0783      *
0784      * paddr = kern_base + (mmfsa_vaddr - KERNBASE)
0785      */
0786     sethi   %hi(KERNBASE), %g3
0787     sub %g2, %g3, %g2
0788     sethi   %hi(kern_base), %g3
0789     ldx [%g3 + %lo(kern_base)], %g3
0790     add %g2, %g3, %o1
0791     sethi   %hi(sparc64_ttable_tl0), %o0
0792 
0793     set prom_set_trap_table_name, %g2
0794     stx %g2, [%sp + 2047 + 128 + 0x00]
0795     mov 2, %g2
0796     stx %g2, [%sp + 2047 + 128 + 0x08]
0797     mov 0, %g2
0798     stx %g2, [%sp + 2047 + 128 + 0x10]
0799     stx %o0, [%sp + 2047 + 128 + 0x18]
0800     stx %o1, [%sp + 2047 + 128 + 0x20]
0801     sethi   %hi(p1275buf), %g2
0802     or  %g2, %lo(p1275buf), %g2
0803     ldx [%g2 + 0x08], %o1
0804     call    %o1
0805      add    %sp, (2047 + 128), %o0
0806 
0807     ba,a,pt %xcc, 2f
0808 
0809 1:  sethi   %hi(sparc64_ttable_tl0), %o0
0810     set prom_set_trap_table_name, %g2
0811     stx %g2, [%sp + 2047 + 128 + 0x00]
0812     mov 1, %g2
0813     stx %g2, [%sp + 2047 + 128 + 0x08]
0814     mov 0, %g2
0815     stx %g2, [%sp + 2047 + 128 + 0x10]
0816     stx %o0, [%sp + 2047 + 128 + 0x18]
0817     sethi   %hi(p1275buf), %g2
0818     or  %g2, %lo(p1275buf), %g2
0819     ldx [%g2 + 0x08], %o1
0820     call    %o1
0821      add    %sp, (2047 + 128), %o0
0822 
0823     /* Start using proper page size encodings in ctx register.  */
0824 2:  sethi   %hi(sparc64_kern_pri_context), %g3
0825     ldx [%g3 + %lo(sparc64_kern_pri_context)], %g2
0826 
0827     mov     PRIMARY_CONTEXT, %g1
0828 
0829 661:    stxa        %g2, [%g1] ASI_DMMU
0830     .section    .sun4v_1insn_patch, "ax"
0831     .word       661b
0832     stxa        %g2, [%g1] ASI_MMU
0833     .previous
0834 
0835     membar  #Sync
0836 
0837     BRANCH_IF_SUN4V(o2, 1f)
0838 
0839     /* Kill PROM timer */
0840     sethi   %hi(0x80000000), %o2
0841     sllx    %o2, 32, %o2
0842     wr  %o2, 0, %tick_cmpr
0843 
0844     BRANCH_IF_ANY_CHEETAH(o2, o3, 1f)
0845 
0846     ba,a,pt %xcc, 2f
0847 
0848     /* Disable STICK_INT interrupts. */
0849 1:
0850     sethi   %hi(0x80000000), %o2
0851     sllx    %o2, 32, %o2
0852     wr  %o2, %asr25
0853 
0854 2:
0855     wrpr    %g0, %g0, %wstate
0856 
0857     call    init_irqwork_curcpu
0858      nop
0859 
0860     /* Now we can restore interrupt state. */
0861     wrpr    %l0, 0, %pstate
0862     wrpr    %l1, 0x0, %pil
0863 
0864     ret
0865      restore
0866 
0867     .globl  setup_tba
0868 setup_tba:
0869     save    %sp, -192, %sp
0870 
0871     /* The boot processor is the only cpu which invokes this
0872      * routine, the other cpus set things up via trampoline.S.
0873      * So save the OBP trap table address here.
0874      */
0875     rdpr    %tba, %g7
0876     sethi   %hi(prom_tba), %o1
0877     or  %o1, %lo(prom_tba), %o1
0878     stx %g7, [%o1]
0879 
0880     call    setup_trap_table
0881      nop
0882 
0883     ret
0884      restore
0885 sparc64_boot_end:
0886 
0887 #include "etrap_64.S"
0888 #include "rtrap_64.S"
0889 #include "winfixup.S"
0890 #include "fpu_traps.S"
0891 #include "ivec.S"
0892 #include "getsetcc.S"
0893 #include "utrap.S"
0894 #include "spiterrs.S"
0895 #include "cherrs.S"
0896 #include "misctrap.S"
0897 #include "syscalls.S"
0898 #include "helpers.S"
0899 #include "sun4v_tlb_miss.S"
0900 #include "sun4v_mcd.S"
0901 #include "sun4v_ivec.S"
0902 #include "ktlb.S"
0903 #include "tsb.S"
0904 
0905 /*
0906  * The following skip makes sure the trap table in ttable.S is aligned
0907  * on a 32K boundary as required by the v9 specs for TBA register.
0908  *
0909  * We align to a 32K boundary, then we have the 32K kernel TSB,
0910  * the 64K kernel 4MB TSB, and then the 32K aligned trap table.
0911  */
0912 1:
0913     .skip   0x4000 + _start - 1b
0914 
0915 ! 0x0000000000408000
0916 
0917     .globl  swapper_tsb
0918 swapper_tsb:
0919     .skip   (32 * 1024)
0920 
0921     .globl  swapper_4m_tsb
0922 swapper_4m_tsb:
0923     .skip   (64 * 1024)
0924 
0925 ! 0x0000000000420000
0926 
0927     /* Some care needs to be exercised if you try to move the
0928      * location of the trap table relative to other things.  For
0929      * one thing there are br* instructions in some of the
0930      * trap table entires which branch back to code in ktlb.S
0931      * Those instructions can only handle a signed 16-bit
0932      * displacement.
0933      *
0934      * There is a binutils bug (bugzilla #4558) which causes
0935      * the relocation overflow checks for such instructions to
0936      * not be done correctly.  So bintuils will not notice the
0937      * error and will instead write junk into the relocation and
0938      * you'll have an unbootable kernel.
0939      */
0940 #include "ttable_64.S"
0941 
0942 ! 0x0000000000428000
0943 
0944 #include "hvcalls.S"
0945 #include "systbls_64.S"
0946 
0947     .data
0948     .align  8
0949     .globl  prom_tba, tlb_type
0950 prom_tba:   .xword  0
0951 tlb_type:   .word   0   /* Must NOT end up in BSS */
0952 EXPORT_SYMBOL(tlb_type)
0953     .section    ".fixup",#alloc,#execinstr
0954 
0955 ENTRY(__retl_efault)
0956     retl
0957      mov    -EFAULT, %o0
0958 ENDPROC(__retl_efault)
0959 
0960 ENTRY(__retl_o1)
0961     retl
0962      mov    %o1, %o0
0963 ENDPROC(__retl_o1)
0964 
0965 ENTRY(__retl_o1_asi)
0966     wr      %o5, 0x0, %asi
0967     retl
0968      mov    %o1, %o0
0969 ENDPROC(__retl_o1_asi)