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 independent 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" 135prom_sparc_prefix: 136 .asciz "SPARC-" 137 .align 4 138prom_root_compatible: 139 .skip 64 140prom_cpu_compatible: 141 .skip 64 142prom_root_node: 143 .word 0 144prom_mmu_ihandle_cache: 145 .word 0 146prom_boot_mapped_pc: 147 .word 0 148prom_boot_mapping_mode: 149 .word 0 150 .align 8 151prom_boot_mapping_phys_high: 152 .xword 0 153prom_boot_mapping_phys_low: 154 .xword 0 155is_sun4v: 156 .word 0 157sun4v_chip_type: 158 .word SUN4V_CHIP_INVALID 1591: 160 rd %pc, %l0 161 162 mov (1b - prom_peer_name), %l1 163 sub %l0, %l1, %l1 164 mov 0, %l2 165 166 /* prom_root_node = prom_peer(0) */ 167 stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "peer" 168 mov 1, %l3 169 stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 1 170 stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1 171 stx %l2, [%sp + 2047 + 128 + 0x18] ! arg1, 0 172 stx %g0, [%sp + 2047 + 128 + 0x20] ! ret1 173 call %l7 174 add %sp, (2047 + 128), %o0 ! argument array 175 176 ldx [%sp + 2047 + 128 + 0x20], %l4 ! prom root node 177 mov (1b - prom_root_node), %l1 178 sub %l0, %l1, %l1 179 stw %l4, [%l1] 180 181 mov (1b - prom_getprop_name), %l1 182 mov (1b - prom_compatible_name), %l2 183 mov (1b - prom_root_compatible), %l5 184 sub %l0, %l1, %l1 185 sub %l0, %l2, %l2 186 sub %l0, %l5, %l5 187 188 /* prom_getproperty(prom_root_node, "compatible", 189 * &prom_root_compatible, 64) 190 */ 191 stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "getprop" 192 mov 4, %l3 193 stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 4 194 mov 1, %l3 195 stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1 196 stx %l4, [%sp + 2047 + 128 + 0x18] ! arg1, prom_root_node 197 stx %l2, [%sp + 2047 + 128 + 0x20] ! arg2, "compatible" 198 stx %l5, [%sp + 2047 + 128 + 0x28] ! arg3, &prom_root_compatible 199 mov 64, %l3 200 stx %l3, [%sp + 2047 + 128 + 0x30] ! arg4, size 201 stx %g0, [%sp + 2047 + 128 + 0x38] ! ret1 202 call %l7 203 add %sp, (2047 + 128), %o0 ! argument array 204 205 mov (1b - prom_finddev_name), %l1 206 mov (1b - prom_chosen_path), %l2 207 mov (1b - prom_boot_mapped_pc), %l3 208 sub %l0, %l1, %l1 209 sub %l0, %l2, %l2 210 sub %l0, %l3, %l3 211 stw %l0, [%l3] 212 sub %sp, (192 + 128), %sp 213 214 /* chosen_node = prom_finddevice("/chosen") */ 215 stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "finddevice" 216 mov 1, %l3 217 stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 1 218 stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1 219 stx %l2, [%sp + 2047 + 128 + 0x18] ! arg1, "/chosen" 220 stx %g0, [%sp + 2047 + 128 + 0x20] ! ret1 221 call %l7 222 add %sp, (2047 + 128), %o0 ! argument array 223 224 ldx [%sp + 2047 + 128 + 0x20], %l4 ! chosen device node 225 226 mov (1b - prom_getprop_name), %l1 227 mov (1b - prom_mmu_name), %l2 228 mov (1b - prom_mmu_ihandle_cache), %l5 229 sub %l0, %l1, %l1 230 sub %l0, %l2, %l2 231 sub %l0, %l5, %l5 232 233 /* prom_mmu_ihandle_cache = prom_getint(chosen_node, "mmu") */ 234 stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "getprop" 235 mov 4, %l3 236 stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 4 237 mov 1, %l3 238 stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1 239 stx %l4, [%sp + 2047 + 128 + 0x18] ! arg1, chosen_node 240 stx %l2, [%sp + 2047 + 128 + 0x20] ! arg2, "mmu" 241 stx %l5, [%sp + 2047 + 128 + 0x28] ! arg3, &prom_mmu_ihandle_cache 242 mov 4, %l3 243 stx %l3, [%sp + 2047 + 128 + 0x30] ! arg4, sizeof(arg3) 244 stx %g0, [%sp + 2047 + 128 + 0x38] ! ret1 245 call %l7 246 add %sp, (2047 + 128), %o0 ! argument array 247 248 mov (1b - prom_callmethod_name), %l1 249 mov (1b - prom_translate_name), %l2 250 sub %l0, %l1, %l1 251 sub %l0, %l2, %l2 252 lduw [%l5], %l5 ! prom_mmu_ihandle_cache 253 254 stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "call-method" 255 mov 3, %l3 256 stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 3 257 mov 5, %l3 258 stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 5 259 stx %l2, [%sp + 2047 + 128 + 0x18] ! arg1: "translate" 260 stx %l5, [%sp + 2047 + 128 + 0x20] ! arg2: prom_mmu_ihandle_cache 261 /* PAGE align */ 262 srlx %l0, 13, %l3 263 sllx %l3, 13, %l3 264 stx %l3, [%sp + 2047 + 128 + 0x28] ! arg3: vaddr, our PC 265 stx %g0, [%sp + 2047 + 128 + 0x30] ! res1 266 stx %g0, [%sp + 2047 + 128 + 0x38] ! res2 267 stx %g0, [%sp + 2047 + 128 + 0x40] ! res3 268 stx %g0, [%sp + 2047 + 128 + 0x48] ! res4 269 stx %g0, [%sp + 2047 + 128 + 0x50] ! res5 270 call %l7 271 add %sp, (2047 + 128), %o0 ! argument array 272 273 ldx [%sp + 2047 + 128 + 0x40], %l1 ! translation mode 274 mov (1b - prom_boot_mapping_mode), %l4 275 sub %l0, %l4, %l4 276 stw %l1, [%l4] 277 mov (1b - prom_boot_mapping_phys_high), %l4 278 sub %l0, %l4, %l4 279 ldx [%sp + 2047 + 128 + 0x48], %l2 ! physaddr high 280 stx %l2, [%l4 + 0x0] 281 ldx [%sp + 2047 + 128 + 0x50], %l3 ! physaddr low 282 /* 4MB align */ 283 srlx %l3, 22, %l3 284 sllx %l3, 22, %l3 285 stx %l3, [%l4 + 0x8] 286 287 /* Leave service as-is, "call-method" */ 288 mov 7, %l3 289 stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 7 290 mov 1, %l3 291 stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1 292 mov (1b - prom_map_name), %l3 293 sub %l0, %l3, %l3 294 stx %l3, [%sp + 2047 + 128 + 0x18] ! arg1: "map" 295 /* Leave arg2 as-is, prom_mmu_ihandle_cache */ 296 mov -1, %l3 297 stx %l3, [%sp + 2047 + 128 + 0x28] ! arg3: mode (-1 default) 298 /* 4MB align the kernel image size. */ 299 set (_end - KERNBASE), %l3 300 set ((4 * 1024 * 1024) - 1), %l4 301 add %l3, %l4, %l3 302 andn %l3, %l4, %l3 303 stx %l3, [%sp + 2047 + 128 + 0x30] ! arg4: roundup(ksize, 4MB) 304 sethi %hi(KERNBASE), %l3 305 stx %l3, [%sp + 2047 + 128 + 0x38] ! arg5: vaddr (KERNBASE) 306 stx %g0, [%sp + 2047 + 128 + 0x40] ! arg6: empty 307 mov (1b - prom_boot_mapping_phys_low), %l3 308 sub %l0, %l3, %l3 309 ldx [%l3], %l3 310 stx %l3, [%sp + 2047 + 128 + 0x48] ! arg7: phys addr 311 call %l7 312 add %sp, (2047 + 128), %o0 ! argument array 313 314 add %sp, (192 + 128), %sp 315 316 sethi %hi(prom_root_compatible), %g1 317 or %g1, %lo(prom_root_compatible), %g1 318 sethi %hi(prom_sun4v_name), %g7 319 or %g7, %lo(prom_sun4v_name), %g7 320 mov 5, %g3 32190: ldub [%g7], %g2 322 ldub [%g1], %g4 323 cmp %g2, %g4 324 bne,pn %icc, 80f 325 add %g7, 1, %g7 326 subcc %g3, 1, %g3 327 bne,pt %xcc, 90b 328 add %g1, 1, %g1 329 330 sethi %hi(is_sun4v), %g1 331 or %g1, %lo(is_sun4v), %g1 332 mov 1, %g7 333 stw %g7, [%g1] 334 335 /* cpu_node = prom_finddevice("/cpu") */ 336 mov (1b - prom_finddev_name), %l1 337 mov (1b - prom_cpu_path), %l2 338 sub %l0, %l1, %l1 339 sub %l0, %l2, %l2 340 sub %sp, (192 + 128), %sp 341 342 stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "finddevice" 343 mov 1, %l3 344 stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 1 345 stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1 346 stx %l2, [%sp + 2047 + 128 + 0x18] ! arg1, "/cpu" 347 stx %g0, [%sp + 2047 + 128 + 0x20] ! ret1 348 call %l7 349 add %sp, (2047 + 128), %o0 ! argument array 350 351 ldx [%sp + 2047 + 128 + 0x20], %l4 ! cpu device node 352 353 mov (1b - prom_getprop_name), %l1 354 mov (1b - prom_compatible_name), %l2 355 mov (1b - prom_cpu_compatible), %l5 356 sub %l0, %l1, %l1 357 sub %l0, %l2, %l2 358 sub %l0, %l5, %l5 359 360 /* prom_getproperty(cpu_node, "compatible", 361 * &prom_cpu_compatible, 64) 362 */ 363 stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "getprop" 364 mov 4, %l3 365 stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 4 366 mov 1, %l3 367 stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1 368 stx %l4, [%sp + 2047 + 128 + 0x18] ! arg1, cpu_node 369 stx %l2, [%sp + 2047 + 128 + 0x20] ! arg2, "compatible" 370 stx %l5, [%sp + 2047 + 128 + 0x28] ! arg3, &prom_cpu_compatible 371 mov 64, %l3 372 stx %l3, [%sp + 2047 + 128 + 0x30] ! arg4, size 373 stx %g0, [%sp + 2047 + 128 + 0x38] ! ret1 374 call %l7 375 add %sp, (2047 + 128), %o0 ! argument array 376 377 add %sp, (192 + 128), %sp 378 379 sethi %hi(prom_cpu_compatible), %g1 380 or %g1, %lo(prom_cpu_compatible), %g1 381 sethi %hi(prom_niagara_prefix), %g7 382 or %g7, %lo(prom_niagara_prefix), %g7 383 mov 17, %g3 38490: ldub [%g7], %g2 385 ldub [%g1], %g4 386 cmp %g2, %g4 387 bne,pn %icc, 89f 388 add %g7, 1, %g7 389 subcc %g3, 1, %g3 390 bne,pt %xcc, 90b 391 add %g1, 1, %g1 392 ba,pt %xcc, 91f 393 nop 394 39589: sethi %hi(prom_cpu_compatible), %g1 396 or %g1, %lo(prom_cpu_compatible), %g1 397 sethi %hi(prom_sparc_prefix), %g7 398 or %g7, %lo(prom_sparc_prefix), %g7 399 mov 6, %g3 40090: ldub [%g7], %g2 401 ldub [%g1], %g4 402 cmp %g2, %g4 403 bne,pn %icc, 4f 404 add %g7, 1, %g7 405 subcc %g3, 1, %g3 406 bne,pt %xcc, 90b 407 add %g1, 1, %g1 408 409 sethi %hi(prom_cpu_compatible), %g1 410 or %g1, %lo(prom_cpu_compatible), %g1 411 ldub [%g1 + 6], %g2 412 cmp %g2, 'T' 413 be,pt %xcc, 70f 414 cmp %g2, 'M' 415 bne,pn %xcc, 4f 416 nop 417 41870: ldub [%g1 + 7], %g2 419 cmp %g2, '3' 420 be,pt %xcc, 5f 421 mov SUN4V_CHIP_NIAGARA3, %g4 422 cmp %g2, '4' 423 be,pt %xcc, 5f 424 mov SUN4V_CHIP_NIAGARA4, %g4 425 cmp %g2, '5' 426 be,pt %xcc, 5f 427 mov SUN4V_CHIP_NIAGARA5, %g4 428 ba,pt %xcc, 4f 429 nop 430 43191: sethi %hi(prom_cpu_compatible), %g1 432 or %g1, %lo(prom_cpu_compatible), %g1 433 ldub [%g1 + 17], %g2 434 cmp %g2, '1' 435 be,pt %xcc, 5f 436 mov SUN4V_CHIP_NIAGARA1, %g4 437 cmp %g2, '2' 438 be,pt %xcc, 5f 439 mov SUN4V_CHIP_NIAGARA2, %g4 440 4414: 442 mov SUN4V_CHIP_UNKNOWN, %g4 4435: sethi %hi(sun4v_chip_type), %g2 444 or %g2, %lo(sun4v_chip_type), %g2 445 stw %g4, [%g2] 446 44780: 448 BRANCH_IF_SUN4V(g1, jump_to_sun4u_init) 449 BRANCH_IF_CHEETAH_BASE(g1,g7,cheetah_boot) 450 BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,cheetah_plus_boot) 451 ba,pt %xcc, spitfire_boot 452 nop 453 454cheetah_plus_boot: 455 /* Preserve OBP chosen DCU and DCR register settings. */ 456 ba,pt %xcc, cheetah_generic_boot 457 nop 458 459cheetah_boot: 460 mov DCR_BPE | DCR_RPE | DCR_SI | DCR_IFPOE | DCR_MS, %g1 461 wr %g1, %asr18 462 463 sethi %uhi(DCU_ME|DCU_RE|DCU_HPE|DCU_SPE|DCU_SL|DCU_WE), %g7 464 or %g7, %ulo(DCU_ME|DCU_RE|DCU_HPE|DCU_SPE|DCU_SL|DCU_WE), %g7 465 sllx %g7, 32, %g7 466 or %g7, DCU_DM | DCU_IM | DCU_DC | DCU_IC, %g7 467 stxa %g7, [%g0] ASI_DCU_CONTROL_REG 468 membar #Sync 469 470cheetah_generic_boot: 471 mov TSB_EXTENSION_P, %g3 472 stxa %g0, [%g3] ASI_DMMU 473 stxa %g0, [%g3] ASI_IMMU 474 membar #Sync 475 476 mov TSB_EXTENSION_S, %g3 477 stxa %g0, [%g3] ASI_DMMU 478 membar #Sync 479 480 mov TSB_EXTENSION_N, %g3 481 stxa %g0, [%g3] ASI_DMMU 482 stxa %g0, [%g3] ASI_IMMU 483 membar #Sync 484 485 ba,a,pt %xcc, jump_to_sun4u_init 486 487spitfire_boot: 488 /* Typically PROM has already enabled both MMU's and both on-chip 489 * caches, but we do it here anyway just to be paranoid. 490 */ 491 mov (LSU_CONTROL_IC|LSU_CONTROL_DC|LSU_CONTROL_IM|LSU_CONTROL_DM), %g1 492 stxa %g1, [%g0] ASI_LSU_CONTROL 493 membar #Sync 494 495jump_to_sun4u_init: 496 /* 497 * Make sure we are in privileged mode, have address masking, 498 * using the ordinary globals and have enabled floating 499 * point. 500 * 501 * Again, typically PROM has left %pil at 13 or similar, and 502 * (PSTATE_PRIV | PSTATE_PEF | PSTATE_IE) in %pstate. 503 */ 504 wrpr %g0, (PSTATE_PRIV|PSTATE_PEF|PSTATE_IE), %pstate 505 wr %g0, 0, %fprs 506 507 set sun4u_init, %g2 508 jmpl %g2 + %g0, %g0 509 nop 510 511 __REF 512sun4u_init: 513 BRANCH_IF_SUN4V(g1, sun4v_init) 514 515 /* Set ctx 0 */ 516 mov PRIMARY_CONTEXT, %g7 517 stxa %g0, [%g7] ASI_DMMU 518 membar #Sync 519 520 mov SECONDARY_CONTEXT, %g7 521 stxa %g0, [%g7] ASI_DMMU 522 membar #Sync 523 524 ba,pt %xcc, sun4u_continue 525 nop 526 527sun4v_init: 528 /* Set ctx 0 */ 529 mov PRIMARY_CONTEXT, %g7 530 stxa %g0, [%g7] ASI_MMU 531 membar #Sync 532 533 mov SECONDARY_CONTEXT, %g7 534 stxa %g0, [%g7] ASI_MMU 535 membar #Sync 536 ba,pt %xcc, niagara_tlb_fixup 537 nop 538 539sun4u_continue: 540 BRANCH_IF_ANY_CHEETAH(g1, g7, cheetah_tlb_fixup) 541 542 ba,pt %xcc, spitfire_tlb_fixup 543 nop 544 545niagara_tlb_fixup: 546 mov 3, %g2 /* Set TLB type to hypervisor. */ 547 sethi %hi(tlb_type), %g1 548 stw %g2, [%g1 + %lo(tlb_type)] 549 550 /* Patch copy/clear ops. */ 551 sethi %hi(sun4v_chip_type), %g1 552 lduw [%g1 + %lo(sun4v_chip_type)], %g1 553 cmp %g1, SUN4V_CHIP_NIAGARA1 554 be,pt %xcc, niagara_patch 555 cmp %g1, SUN4V_CHIP_NIAGARA2 556 be,pt %xcc, niagara2_patch 557 nop 558 cmp %g1, SUN4V_CHIP_NIAGARA3 559 be,pt %xcc, niagara2_patch 560 nop 561 cmp %g1, SUN4V_CHIP_NIAGARA4 562 be,pt %xcc, niagara4_patch 563 nop 564 cmp %g1, SUN4V_CHIP_NIAGARA5 565 be,pt %xcc, niagara4_patch 566 nop 567 568 call generic_patch_copyops 569 nop 570 call generic_patch_bzero 571 nop 572 call generic_patch_pageops 573 nop 574 575 ba,a,pt %xcc, 80f 576niagara4_patch: 577 call niagara4_patch_copyops 578 nop 579 call niagara4_patch_bzero 580 nop 581 call niagara4_patch_pageops 582 nop 583 584 ba,a,pt %xcc, 80f 585 586niagara2_patch: 587 call niagara2_patch_copyops 588 nop 589 call niagara_patch_bzero 590 nop 591 call niagara_patch_pageops 592 nop 593 594 ba,a,pt %xcc, 80f 595 596niagara_patch: 597 call niagara_patch_copyops 598 nop 599 call niagara_patch_bzero 600 nop 601 call niagara_patch_pageops 602 nop 603 60480: 605 /* Patch TLB/cache ops. */ 606 call hypervisor_patch_cachetlbops 607 nop 608 609 ba,pt %xcc, tlb_fixup_done 610 nop 611 612cheetah_tlb_fixup: 613 mov 2, %g2 /* Set TLB type to cheetah+. */ 614 BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,1f) 615 616 mov 1, %g2 /* Set TLB type to cheetah. */ 617 6181: sethi %hi(tlb_type), %g1 619 stw %g2, [%g1 + %lo(tlb_type)] 620 621 /* Patch copy/page operations to cheetah optimized versions. */ 622 call cheetah_patch_copyops 623 nop 624 call cheetah_patch_copy_page 625 nop 626 call cheetah_patch_cachetlbops 627 nop 628 629 ba,pt %xcc, tlb_fixup_done 630 nop 631 632spitfire_tlb_fixup: 633 /* Set TLB type to spitfire. */ 634 mov 0, %g2 635 sethi %hi(tlb_type), %g1 636 stw %g2, [%g1 + %lo(tlb_type)] 637 638tlb_fixup_done: 639 sethi %hi(init_thread_union), %g6 640 or %g6, %lo(init_thread_union), %g6 641 ldx [%g6 + TI_TASK], %g4 642 mov %sp, %l6 643 644 wr %g0, ASI_P, %asi 645 mov 1, %g1 646 sllx %g1, THREAD_SHIFT, %g1 647 sub %g1, (STACKFRAME_SZ + STACK_BIAS), %g1 648 add %g6, %g1, %sp 649 mov 0, %fp 650 651 /* Set per-cpu pointer initially to zero, this makes 652 * the boot-cpu use the in-kernel-image per-cpu areas 653 * before setup_per_cpu_area() is invoked. 654 */ 655 clr %g5 656 657 wrpr %g0, 0, %wstate 658 wrpr %g0, 0x0, %tl 659 660 /* Clear the bss */ 661 sethi %hi(__bss_start), %o0 662 or %o0, %lo(__bss_start), %o0 663 sethi %hi(_end), %o1 664 or %o1, %lo(_end), %o1 665 call __bzero 666 sub %o1, %o0, %o1 667 668#ifdef CONFIG_LOCKDEP 669 /* We have this call this super early, as even prom_init can grab 670 * spinlocks and thus call into the lockdep code. 671 */ 672 call lockdep_init 673 nop 674#endif 675 676 mov %l6, %o1 ! OpenPROM stack 677 call prom_init 678 mov %l7, %o0 ! OpenPROM cif handler 679 680 /* Initialize current_thread_info()->cpu as early as possible. 681 * In order to do that accurately we have to patch up the get_cpuid() 682 * assembler sequences. And that, in turn, requires that we know 683 * if we are on a Starfire box or not. While we're here, patch up 684 * the sun4v sequences as well. 685 */ 686 call check_if_starfire 687 nop 688 call per_cpu_patch 689 nop 690 call sun4v_patch 691 nop 692 693#ifdef CONFIG_SMP 694 call hard_smp_processor_id 695 nop 696 cmp %o0, NR_CPUS 697 blu,pt %xcc, 1f 698 nop 699 call boot_cpu_id_too_large 700 nop 701 /* Not reached... */ 702 7031: 704#else 705 mov 0, %o0 706#endif 707 sth %o0, [%g6 + TI_CPU] 708 709 call prom_init_report 710 nop 711 712 /* Off we go.... */ 713 call start_kernel 714 nop 715 /* Not reached... */ 716 717 .previous 718 719 /* This is meant to allow the sharing of this code between 720 * boot processor invocation (via setup_tba() below) and 721 * secondary processor startup (via trampoline.S). The 722 * former does use this code, the latter does not yet due 723 * to some complexities. That should be fixed up at some 724 * point. 725 * 726 * There used to be enormous complexity wrt. transferring 727 * over from the firmware's trap table to the Linux kernel's. 728 * For example, there was a chicken & egg problem wrt. building 729 * the OBP page tables, yet needing to be on the Linux kernel 730 * trap table (to translate PAGE_OFFSET addresses) in order to 731 * do that. 732 * 733 * We now handle OBP tlb misses differently, via linear lookups 734 * into the prom_trans[] array. So that specific problem no 735 * longer exists. Yet, unfortunately there are still some issues 736 * preventing trampoline.S from using this code... ho hum. 737 */ 738 .globl setup_trap_table 739setup_trap_table: 740 save %sp, -192, %sp 741 742 /* Force interrupts to be disabled. */ 743 rdpr %pstate, %l0 744 andn %l0, PSTATE_IE, %o1 745 wrpr %o1, 0x0, %pstate 746 rdpr %pil, %l1 747 wrpr %g0, PIL_NORMAL_MAX, %pil 748 749 /* Make the firmware call to jump over to the Linux trap table. */ 750 sethi %hi(is_sun4v), %o0 751 lduw [%o0 + %lo(is_sun4v)], %o0 752 brz,pt %o0, 1f 753 nop 754 755 TRAP_LOAD_TRAP_BLOCK(%g2, %g3) 756 add %g2, TRAP_PER_CPU_FAULT_INFO, %g2 757 stxa %g2, [%g0] ASI_SCRATCHPAD 758 759 /* Compute physical address: 760 * 761 * paddr = kern_base + (mmfsa_vaddr - KERNBASE) 762 */ 763 sethi %hi(KERNBASE), %g3 764 sub %g2, %g3, %g2 765 sethi %hi(kern_base), %g3 766 ldx [%g3 + %lo(kern_base)], %g3 767 add %g2, %g3, %o1 768 sethi %hi(sparc64_ttable_tl0), %o0 769 770 set prom_set_trap_table_name, %g2 771 stx %g2, [%sp + 2047 + 128 + 0x00] 772 mov 2, %g2 773 stx %g2, [%sp + 2047 + 128 + 0x08] 774 mov 0, %g2 775 stx %g2, [%sp + 2047 + 128 + 0x10] 776 stx %o0, [%sp + 2047 + 128 + 0x18] 777 stx %o1, [%sp + 2047 + 128 + 0x20] 778 sethi %hi(p1275buf), %g2 779 or %g2, %lo(p1275buf), %g2 780 ldx [%g2 + 0x08], %o1 781 call %o1 782 add %sp, (2047 + 128), %o0 783 784 ba,pt %xcc, 2f 785 nop 786 7871: sethi %hi(sparc64_ttable_tl0), %o0 788 set prom_set_trap_table_name, %g2 789 stx %g2, [%sp + 2047 + 128 + 0x00] 790 mov 1, %g2 791 stx %g2, [%sp + 2047 + 128 + 0x08] 792 mov 0, %g2 793 stx %g2, [%sp + 2047 + 128 + 0x10] 794 stx %o0, [%sp + 2047 + 128 + 0x18] 795 sethi %hi(p1275buf), %g2 796 or %g2, %lo(p1275buf), %g2 797 ldx [%g2 + 0x08], %o1 798 call %o1 799 add %sp, (2047 + 128), %o0 800 801 /* Start using proper page size encodings in ctx register. */ 8022: sethi %hi(sparc64_kern_pri_context), %g3 803 ldx [%g3 + %lo(sparc64_kern_pri_context)], %g2 804 805 mov PRIMARY_CONTEXT, %g1 806 807661: stxa %g2, [%g1] ASI_DMMU 808 .section .sun4v_1insn_patch, "ax" 809 .word 661b 810 stxa %g2, [%g1] ASI_MMU 811 .previous 812 813 membar #Sync 814 815 BRANCH_IF_SUN4V(o2, 1f) 816 817 /* Kill PROM timer */ 818 sethi %hi(0x80000000), %o2 819 sllx %o2, 32, %o2 820 wr %o2, 0, %tick_cmpr 821 822 BRANCH_IF_ANY_CHEETAH(o2, o3, 1f) 823 824 ba,pt %xcc, 2f 825 nop 826 827 /* Disable STICK_INT interrupts. */ 8281: 829 sethi %hi(0x80000000), %o2 830 sllx %o2, 32, %o2 831 wr %o2, %asr25 832 8332: 834 wrpr %g0, %g0, %wstate 835 836 call init_irqwork_curcpu 837 nop 838 839 /* Now we can restore interrupt state. */ 840 wrpr %l0, 0, %pstate 841 wrpr %l1, 0x0, %pil 842 843 ret 844 restore 845 846 .globl setup_tba 847setup_tba: 848 save %sp, -192, %sp 849 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] 858 859 call setup_trap_table 860 nop 861 862 ret 863 restore 864sparc64_boot_end: 865 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" 883 884/* 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. 887 * 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 */ 8911: 892 .skip 0x4000 + _start - 1b 893 894! 0x0000000000408000 895 896 .globl swapper_tsb 897swapper_tsb: 898 .skip (32 * 1024) 899 900 .globl swapper_4m_tsb 901swapper_4m_tsb: 902 .skip (64 * 1024) 903 904! 0x0000000000420000 905 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" 920 921! 0x0000000000428000 922 923#include "systbls_64.S" 924 925 .data 926 .align 8 927 .globl prom_tba, tlb_type 928prom_tba: .xword 0 929tlb_type: .word 0 /* Must NOT end up in BSS */ 930 .section ".fixup",#alloc,#execinstr 931 932 .globl __ret_efault, __retl_efault, __ret_one, __retl_one 933ENTRY(__ret_efault) 934 ret 935 restore %g0, -EFAULT, %o0 936ENDPROC(__ret_efault) 937 938ENTRY(__retl_efault) 939 retl 940 mov -EFAULT, %o0 941ENDPROC(__retl_efault) 942 943ENTRY(__retl_one) 944 retl 945 mov 1, %o0 946ENDPROC(__retl_one) 947 948ENTRY(__ret_one_asi) 949 wr %g0, ASI_AIUS, %asi 950 ret 951 restore %g0, 1, %o0 952ENDPROC(__ret_one_asi) 953 954ENTRY(__retl_one_asi) 955 wr %g0, ASI_AIUS, %asi 956 retl 957 mov 1, %o0 958ENDPROC(__retl_one_asi) 959 960ENTRY(__retl_o1) 961 retl 962 mov %o1, %o0 963ENDPROC(__retl_o1) 964