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