diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2007-08-08 20:11:39 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-08-08 20:33:45 -0400 |
commit | 6c70b6fc7b6fc321636a014082d9e32333da1f80 (patch) | |
tree | ff0e52bb7ba43b058b7cbb88b952fd268fbe3ad2 /arch/sparc64/kernel/head.S | |
parent | 68c9f9fd336dc7e793cecad25f8ac40ccaa7a256 (diff) |
[SPARC64]: Do not assume sun4v chips have load-twin/store-init support.
Check the cpu type in the OBP device tree before committing to
using the optimized Niagara memcpy and memset implementation.
If we don't recognize the cpu type, use a completely generic
version.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/kernel/head.S')
-rw-r--r-- | arch/sparc64/kernel/head.S | 111 |
1 files changed, 106 insertions, 5 deletions
diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S index 9dbd833d79d6..ac18bd8e273f 100644 --- a/arch/sparc64/kernel/head.S +++ b/arch/sparc64/kernel/head.S | |||
@@ -97,7 +97,8 @@ sparc64_boot: | |||
97 | .globl prom_map_name, prom_unmap_name, prom_mmu_ihandle_cache | 97 | .globl prom_map_name, prom_unmap_name, prom_mmu_ihandle_cache |
98 | .globl prom_boot_mapped_pc, prom_boot_mapping_mode | 98 | .globl prom_boot_mapped_pc, prom_boot_mapping_mode |
99 | .globl prom_boot_mapping_phys_high, prom_boot_mapping_phys_low | 99 | .globl prom_boot_mapping_phys_high, prom_boot_mapping_phys_low |
100 | .globl is_sun4v | 100 | .globl prom_compatible_name, prom_cpu_path, prom_cpu_compatible |
101 | .globl is_sun4v, sun4v_chip_type | ||
101 | prom_peer_name: | 102 | prom_peer_name: |
102 | .asciz "peer" | 103 | .asciz "peer" |
103 | prom_compatible_name: | 104 | prom_compatible_name: |
@@ -106,6 +107,8 @@ prom_finddev_name: | |||
106 | .asciz "finddevice" | 107 | .asciz "finddevice" |
107 | prom_chosen_path: | 108 | prom_chosen_path: |
108 | .asciz "/chosen" | 109 | .asciz "/chosen" |
110 | prom_cpu_path: | ||
111 | .asciz "/cpu" | ||
109 | prom_getprop_name: | 112 | prom_getprop_name: |
110 | .asciz "getprop" | 113 | .asciz "getprop" |
111 | prom_mmu_name: | 114 | prom_mmu_name: |
@@ -120,9 +123,13 @@ prom_unmap_name: | |||
120 | .asciz "unmap" | 123 | .asciz "unmap" |
121 | prom_sun4v_name: | 124 | prom_sun4v_name: |
122 | .asciz "sun4v" | 125 | .asciz "sun4v" |
126 | prom_niagara_prefix: | ||
127 | .asciz "SUNW,UltraSPARC-T" | ||
123 | .align 4 | 128 | .align 4 |
124 | prom_root_compatible: | 129 | prom_root_compatible: |
125 | .skip 64 | 130 | .skip 64 |
131 | prom_cpu_compatible: | ||
132 | .skip 64 | ||
126 | prom_root_node: | 133 | prom_root_node: |
127 | .word 0 | 134 | .word 0 |
128 | prom_mmu_ihandle_cache: | 135 | prom_mmu_ihandle_cache: |
@@ -138,6 +145,8 @@ prom_boot_mapping_phys_low: | |||
138 | .xword 0 | 145 | .xword 0 |
139 | is_sun4v: | 146 | is_sun4v: |
140 | .word 0 | 147 | .word 0 |
148 | sun4v_chip_type: | ||
149 | .word SUN4V_CHIP_INVALID | ||
141 | 1: | 150 | 1: |
142 | rd %pc, %l0 | 151 | rd %pc, %l0 |
143 | 152 | ||
@@ -296,13 +305,13 @@ is_sun4v: | |||
296 | sethi %hi(prom_sun4v_name), %g7 | 305 | sethi %hi(prom_sun4v_name), %g7 |
297 | or %g7, %lo(prom_sun4v_name), %g7 | 306 | or %g7, %lo(prom_sun4v_name), %g7 |
298 | mov 5, %g3 | 307 | mov 5, %g3 |
299 | 1: ldub [%g7], %g2 | 308 | 90: ldub [%g7], %g2 |
300 | ldub [%g1], %g4 | 309 | ldub [%g1], %g4 |
301 | cmp %g2, %g4 | 310 | cmp %g2, %g4 |
302 | bne,pn %icc, 2f | 311 | bne,pn %icc, 80f |
303 | add %g7, 1, %g7 | 312 | add %g7, 1, %g7 |
304 | subcc %g3, 1, %g3 | 313 | subcc %g3, 1, %g3 |
305 | bne,pt %xcc, 1b | 314 | bne,pt %xcc, 90b |
306 | add %g1, 1, %g1 | 315 | add %g1, 1, %g1 |
307 | 316 | ||
308 | sethi %hi(is_sun4v), %g1 | 317 | sethi %hi(is_sun4v), %g1 |
@@ -310,7 +319,80 @@ is_sun4v: | |||
310 | mov 1, %g7 | 319 | mov 1, %g7 |
311 | stw %g7, [%g1] | 320 | stw %g7, [%g1] |
312 | 321 | ||
313 | 2: | 322 | /* cpu_node = prom_finddevice("/cpu") */ |
323 | mov (1b - prom_finddev_name), %l1 | ||
324 | mov (1b - prom_cpu_path), %l2 | ||
325 | sub %l0, %l1, %l1 | ||
326 | sub %l0, %l2, %l2 | ||
327 | sub %sp, (192 + 128), %sp | ||
328 | |||
329 | stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "finddevice" | ||
330 | mov 1, %l3 | ||
331 | stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 1 | ||
332 | stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1 | ||
333 | stx %l2, [%sp + 2047 + 128 + 0x18] ! arg1, "/cpu" | ||
334 | stx %g0, [%sp + 2047 + 128 + 0x20] ! ret1 | ||
335 | call %l7 | ||
336 | add %sp, (2047 + 128), %o0 ! argument array | ||
337 | |||
338 | ldx [%sp + 2047 + 128 + 0x20], %l4 ! cpu device node | ||
339 | |||
340 | mov (1b - prom_getprop_name), %l1 | ||
341 | mov (1b - prom_compatible_name), %l2 | ||
342 | mov (1b - prom_cpu_compatible), %l5 | ||
343 | sub %l0, %l1, %l1 | ||
344 | sub %l0, %l2, %l2 | ||
345 | sub %l0, %l5, %l5 | ||
346 | |||
347 | /* prom_getproperty(cpu_node, "compatible", | ||
348 | * &prom_cpu_compatible, 64) | ||
349 | */ | ||
350 | stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "getprop" | ||
351 | mov 4, %l3 | ||
352 | stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 4 | ||
353 | mov 1, %l3 | ||
354 | stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1 | ||
355 | stx %l4, [%sp + 2047 + 128 + 0x18] ! arg1, cpu_node | ||
356 | stx %l2, [%sp + 2047 + 128 + 0x20] ! arg2, "compatible" | ||
357 | stx %l5, [%sp + 2047 + 128 + 0x28] ! arg3, &prom_cpu_compatible | ||
358 | mov 64, %l3 | ||
359 | stx %l3, [%sp + 2047 + 128 + 0x30] ! arg4, size | ||
360 | stx %g0, [%sp + 2047 + 128 + 0x38] ! ret1 | ||
361 | call %l7 | ||
362 | add %sp, (2047 + 128), %o0 ! argument array | ||
363 | |||
364 | add %sp, (192 + 128), %sp | ||
365 | |||
366 | sethi %hi(prom_cpu_compatible), %g1 | ||
367 | or %g1, %lo(prom_cpu_compatible), %g1 | ||
368 | sethi %hi(prom_niagara_prefix), %g7 | ||
369 | or %g7, %lo(prom_niagara_prefix), %g7 | ||
370 | mov 17, %g3 | ||
371 | 90: ldub [%g7], %g2 | ||
372 | ldub [%g1], %g4 | ||
373 | cmp %g2, %g4 | ||
374 | bne,pn %icc, 4f | ||
375 | add %g7, 1, %g7 | ||
376 | subcc %g3, 1, %g3 | ||
377 | bne,pt %xcc, 90b | ||
378 | add %g1, 1, %g1 | ||
379 | |||
380 | sethi %hi(prom_cpu_compatible), %g1 | ||
381 | or %g1, %lo(prom_cpu_compatible), %g1 | ||
382 | ldub [%g1 + 17], %g2 | ||
383 | cmp %g2, '1' | ||
384 | be,pt %xcc, 5f | ||
385 | mov SUN4V_CHIP_NIAGARA1, %g4 | ||
386 | cmp %g2, '2' | ||
387 | be,pt %xcc, 5f | ||
388 | mov SUN4V_CHIP_NIAGARA2, %g4 | ||
389 | 4: | ||
390 | mov SUN4V_CHIP_UNKNOWN, %g4 | ||
391 | 5: sethi %hi(sun4v_chip_type), %g2 | ||
392 | or %g2, %lo(sun4v_chip_type), %g2 | ||
393 | stw %g4, [%g2] | ||
394 | |||
395 | 80: | ||
314 | BRANCH_IF_SUN4V(g1, jump_to_sun4u_init) | 396 | BRANCH_IF_SUN4V(g1, jump_to_sun4u_init) |
315 | BRANCH_IF_CHEETAH_BASE(g1,g7,cheetah_boot) | 397 | BRANCH_IF_CHEETAH_BASE(g1,g7,cheetah_boot) |
316 | BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,cheetah_plus_boot) | 398 | BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,cheetah_plus_boot) |
@@ -414,6 +496,24 @@ niagara_tlb_fixup: | |||
414 | stw %g2, [%g1 + %lo(tlb_type)] | 496 | stw %g2, [%g1 + %lo(tlb_type)] |
415 | 497 | ||
416 | /* Patch copy/clear ops. */ | 498 | /* Patch copy/clear ops. */ |
499 | sethi %hi(sun4v_chip_type), %g1 | ||
500 | lduw [%g1 + %lo(sun4v_chip_type)], %g1 | ||
501 | cmp %g1, SUN4V_CHIP_NIAGARA1 | ||
502 | be,pt %xcc, niagara_patch | ||
503 | cmp %g1, SUN4V_CHIP_NIAGARA2 | ||
504 | be,pt %xcc, niagara_patch | ||
505 | nop | ||
506 | |||
507 | call generic_patch_copyops | ||
508 | nop | ||
509 | call generic_patch_bzero | ||
510 | nop | ||
511 | call generic_patch_pageops | ||
512 | nop | ||
513 | |||
514 | ba,a,pt %xcc, 80f | ||
515 | |||
516 | niagara_patch: | ||
417 | call niagara_patch_copyops | 517 | call niagara_patch_copyops |
418 | nop | 518 | nop |
419 | call niagara_patch_bzero | 519 | call niagara_patch_bzero |
@@ -421,6 +521,7 @@ niagara_tlb_fixup: | |||
421 | call niagara_patch_pageops | 521 | call niagara_patch_pageops |
422 | nop | 522 | nop |
423 | 523 | ||
524 | 80: | ||
424 | /* Patch TLB/cache ops. */ | 525 | /* Patch TLB/cache ops. */ |
425 | call hypervisor_patch_cachetlbops | 526 | call hypervisor_patch_cachetlbops |
426 | nop | 527 | nop |