root/arch/sparc/kernel/head_64.S

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

/* [<][>][^][v][top][bottom][index][help] */