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