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