diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2006-02-09 05:52:44 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-03-20 04:12:03 -0500 |
commit | d82ace7dc4073b090a55b9740700e32b9a9ae302 (patch) | |
tree | d5aa8e10664b05bbfe31eacf95e2066c03cab102 /arch/sparc64/kernel/head.S | |
parent | 1d2f1f90a1e004b0c1b8a73ed4394a93f09104b3 (diff) |
[SPARC64]: Detect sun4v early in boot process.
We look for "SUNW,sun4v" in the 'compatible' property
of the root OBP device tree node.
Protect every %ver register access, to make sure it is
not touched on sun4v, as %ver is hyperprivileged there.
Lock kernel TLB entries using hypervisor calls instead of
calls into OBP.
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 | 96 |
1 files changed, 88 insertions, 8 deletions
diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S index 01980014aead..d048f0dfd423 100644 --- a/arch/sparc64/kernel/head.S +++ b/arch/sparc64/kernel/head.S | |||
@@ -95,12 +95,17 @@ sparc64_boot: | |||
95 | wrpr %g1, 0x0, %pstate | 95 | wrpr %g1, 0x0, %pstate |
96 | ba,a,pt %xcc, 1f | 96 | ba,a,pt %xcc, 1f |
97 | 97 | ||
98 | .globl prom_finddev_name, prom_chosen_path | 98 | .globl prom_finddev_name, prom_chosen_path, prom_root_node |
99 | .globl prom_getprop_name, prom_mmu_name | 99 | .globl prom_getprop_name, prom_mmu_name, prom_peer_name |
100 | .globl prom_callmethod_name, prom_translate_name | 100 | .globl prom_callmethod_name, prom_translate_name, prom_root_compatible |
101 | .globl prom_map_name, prom_unmap_name, prom_mmu_ihandle_cache | 101 | .globl prom_map_name, prom_unmap_name, prom_mmu_ihandle_cache |
102 | .globl prom_boot_mapped_pc, prom_boot_mapping_mode | 102 | .globl prom_boot_mapped_pc, prom_boot_mapping_mode |
103 | .globl prom_boot_mapping_phys_high, prom_boot_mapping_phys_low | 103 | .globl prom_boot_mapping_phys_high, prom_boot_mapping_phys_low |
104 | .globl is_sun4v | ||
105 | prom_peer_name: | ||
106 | .asciz "peer" | ||
107 | prom_compatible_name: | ||
108 | .asciz "compatible" | ||
104 | prom_finddev_name: | 109 | prom_finddev_name: |
105 | .asciz "finddevice" | 110 | .asciz "finddevice" |
106 | prom_chosen_path: | 111 | prom_chosen_path: |
@@ -117,7 +122,13 @@ prom_map_name: | |||
117 | .asciz "map" | 122 | .asciz "map" |
118 | prom_unmap_name: | 123 | prom_unmap_name: |
119 | .asciz "unmap" | 124 | .asciz "unmap" |
125 | prom_sun4v_name: | ||
126 | .asciz "SUNW,sun4v" | ||
120 | .align 4 | 127 | .align 4 |
128 | prom_root_compatible: | ||
129 | .skip 64 | ||
130 | prom_root_node: | ||
131 | .word 0 | ||
121 | prom_mmu_ihandle_cache: | 132 | prom_mmu_ihandle_cache: |
122 | .word 0 | 133 | .word 0 |
123 | prom_boot_mapped_pc: | 134 | prom_boot_mapped_pc: |
@@ -129,8 +140,54 @@ prom_boot_mapping_phys_high: | |||
129 | .xword 0 | 140 | .xword 0 |
130 | prom_boot_mapping_phys_low: | 141 | prom_boot_mapping_phys_low: |
131 | .xword 0 | 142 | .xword 0 |
143 | is_sun4v: | ||
144 | .word 0 | ||
132 | 1: | 145 | 1: |
133 | rd %pc, %l0 | 146 | rd %pc, %l0 |
147 | |||
148 | mov (1b - prom_peer_name), %l1 | ||
149 | sub %l0, %l1, %l1 | ||
150 | mov 0, %l2 | ||
151 | |||
152 | /* prom_root_node = prom_peer(0) */ | ||
153 | stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "peer" | ||
154 | mov 1, %l3 | ||
155 | stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 1 | ||
156 | stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1 | ||
157 | stx %l2, [%sp + 2047 + 128 + 0x18] ! arg1, 0 | ||
158 | stx %g0, [%sp + 2047 + 128 + 0x20] ! ret1 | ||
159 | call %l7 | ||
160 | add %sp, (2047 + 128), %o0 ! argument array | ||
161 | |||
162 | ldx [%sp + 2047 + 128 + 0x20], %l4 ! prom root node | ||
163 | mov (1b - prom_root_node), %l1 | ||
164 | sub %l0, %l1, %l1 | ||
165 | stw %l4, [%l1] | ||
166 | |||
167 | mov (1b - prom_getprop_name), %l1 | ||
168 | mov (1b - prom_compatible_name), %l2 | ||
169 | mov (1b - prom_root_compatible), %l5 | ||
170 | sub %l0, %l1, %l1 | ||
171 | sub %l0, %l2, %l2 | ||
172 | sub %l0, %l5, %l5 | ||
173 | |||
174 | /* prom_getproperty(prom_root_node, "compatible", | ||
175 | * &prom_root_compatible, 64) | ||
176 | */ | ||
177 | stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "getprop" | ||
178 | mov 4, %l3 | ||
179 | stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 4 | ||
180 | mov 1, %l3 | ||
181 | stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1 | ||
182 | stx %l4, [%sp + 2047 + 128 + 0x18] ! arg1, prom_root_node | ||
183 | stx %l2, [%sp + 2047 + 128 + 0x20] ! arg2, "compatible" | ||
184 | stx %l5, [%sp + 2047 + 128 + 0x28] ! arg3, &prom_root_compatible | ||
185 | mov 64, %l3 | ||
186 | stx %l3, [%sp + 2047 + 128 + 0x30] ! arg4, size | ||
187 | stx %g0, [%sp + 2047 + 128 + 0x38] ! ret1 | ||
188 | call %l7 | ||
189 | add %sp, (2047 + 128), %o0 ! argument array | ||
190 | |||
134 | mov (1b - prom_finddev_name), %l1 | 191 | mov (1b - prom_finddev_name), %l1 |
135 | mov (1b - prom_chosen_path), %l2 | 192 | mov (1b - prom_chosen_path), %l2 |
136 | mov (1b - prom_boot_mapped_pc), %l3 | 193 | mov (1b - prom_boot_mapped_pc), %l3 |
@@ -239,6 +296,27 @@ prom_boot_mapping_phys_low: | |||
239 | add %sp, (192 + 128), %sp | 296 | add %sp, (192 + 128), %sp |
240 | 297 | ||
241 | sparc64_boot_after_remap: | 298 | sparc64_boot_after_remap: |
299 | sethi %hi(prom_root_compatible), %g1 | ||
300 | or %g1, %lo(prom_root_compatible), %g1 | ||
301 | sethi %hi(prom_sun4v_name), %g7 | ||
302 | or %g7, %lo(prom_sun4v_name), %g7 | ||
303 | mov 10, %g3 | ||
304 | 1: ldub [%g7], %g2 | ||
305 | ldub [%g1], %g4 | ||
306 | cmp %g2, %g4 | ||
307 | bne,pn %icc, 2f | ||
308 | add %g7, 1, %g7 | ||
309 | subcc %g3, 1, %g3 | ||
310 | bne,pt %xcc, 1b | ||
311 | add %g1, 1, %g1 | ||
312 | |||
313 | sethi %hi(is_sun4v), %g1 | ||
314 | or %g1, %lo(is_sun4v), %g1 | ||
315 | mov 1, %g7 | ||
316 | stw %g7, [%g1] | ||
317 | |||
318 | 2: | ||
319 | BRANCH_IF_SUN4V(g1, jump_to_sun4u_init) | ||
242 | BRANCH_IF_CHEETAH_BASE(g1,g7,cheetah_boot) | 320 | BRANCH_IF_CHEETAH_BASE(g1,g7,cheetah_boot) |
243 | BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,cheetah_plus_boot) | 321 | BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,cheetah_plus_boot) |
244 | ba,pt %xcc, spitfire_boot | 322 | ba,pt %xcc, spitfire_boot |
@@ -323,14 +401,12 @@ sun4u_init: | |||
323 | 401 | ||
324 | membar #Sync | 402 | membar #Sync |
325 | 403 | ||
326 | BRANCH_IF_ANY_CHEETAH(g1,g7,cheetah_tlb_fixup) | 404 | BRANCH_IF_SUN4V(g1, niagara_tlb_fixup) |
405 | BRANCH_IF_ANY_CHEETAH(g1, g7, cheetah_tlb_fixup) | ||
327 | 406 | ||
328 | ba,pt %xcc, spitfire_tlb_fixup | 407 | ba,pt %xcc, spitfire_tlb_fixup |
329 | nop | 408 | nop |
330 | 409 | ||
331 | /* XXX Nothing branches to here yet, when %ver register indicates | ||
332 | * XXX Niagara we should do this. | ||
333 | */ | ||
334 | niagara_tlb_fixup: | 410 | niagara_tlb_fixup: |
335 | mov 3, %g2 /* Set TLB type to hypervisor. */ | 411 | mov 3, %g2 /* Set TLB type to hypervisor. */ |
336 | sethi %hi(tlb_type), %g1 | 412 | sethi %hi(tlb_type), %g1 |
@@ -346,6 +422,9 @@ niagara_tlb_fixup: | |||
346 | call hypervisor_patch_cachetlbops | 422 | call hypervisor_patch_cachetlbops |
347 | nop | 423 | nop |
348 | 424 | ||
425 | ba,pt %xcc, tlb_fixup_done | ||
426 | nop | ||
427 | |||
349 | cheetah_tlb_fixup: | 428 | cheetah_tlb_fixup: |
350 | mov 2, %g2 /* Set TLB type to cheetah+. */ | 429 | mov 2, %g2 /* Set TLB type to cheetah+. */ |
351 | BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,1f) | 430 | BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,1f) |
@@ -464,7 +543,8 @@ setup_trap_table: | |||
464 | sllx %o2, 32, %o2 | 543 | sllx %o2, 32, %o2 |
465 | wr %o2, 0, %tick_cmpr | 544 | wr %o2, 0, %tick_cmpr |
466 | 545 | ||
467 | BRANCH_IF_ANY_CHEETAH(o2,o3,1f) | 546 | BRANCH_IF_SUN4V(o2, 1f) |
547 | BRANCH_IF_ANY_CHEETAH(o2, o3, 1f) | ||
468 | 548 | ||
469 | ba,pt %xcc, 2f | 549 | ba,pt %xcc, 2f |
470 | nop | 550 | nop |