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