diff options
Diffstat (limited to 'arch/sparc/kernel/trampoline_64.S')
-rw-r--r-- | arch/sparc/kernel/trampoline_64.S | 417 |
1 files changed, 417 insertions, 0 deletions
diff --git a/arch/sparc/kernel/trampoline_64.S b/arch/sparc/kernel/trampoline_64.S new file mode 100644 index 000000000000..da1b781b5e65 --- /dev/null +++ b/arch/sparc/kernel/trampoline_64.S | |||
@@ -0,0 +1,417 @@ | |||
1 | /* | ||
2 | * trampoline.S: Jump start slave processors on sparc64. | ||
3 | * | ||
4 | * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) | ||
5 | */ | ||
6 | |||
7 | #include <linux/init.h> | ||
8 | |||
9 | #include <asm/head.h> | ||
10 | #include <asm/asi.h> | ||
11 | #include <asm/lsu.h> | ||
12 | #include <asm/dcr.h> | ||
13 | #include <asm/dcu.h> | ||
14 | #include <asm/pstate.h> | ||
15 | #include <asm/page.h> | ||
16 | #include <asm/pgtable.h> | ||
17 | #include <asm/spitfire.h> | ||
18 | #include <asm/processor.h> | ||
19 | #include <asm/thread_info.h> | ||
20 | #include <asm/mmu.h> | ||
21 | #include <asm/hypervisor.h> | ||
22 | #include <asm/cpudata.h> | ||
23 | |||
24 | .data | ||
25 | .align 8 | ||
26 | call_method: | ||
27 | .asciz "call-method" | ||
28 | .align 8 | ||
29 | itlb_load: | ||
30 | .asciz "SUNW,itlb-load" | ||
31 | .align 8 | ||
32 | dtlb_load: | ||
33 | .asciz "SUNW,dtlb-load" | ||
34 | |||
35 | /* XXX __cpuinit this thing XXX */ | ||
36 | #define TRAMP_STACK_SIZE 1024 | ||
37 | .align 16 | ||
38 | tramp_stack: | ||
39 | .skip TRAMP_STACK_SIZE | ||
40 | |||
41 | __CPUINIT | ||
42 | .align 8 | ||
43 | .globl sparc64_cpu_startup, sparc64_cpu_startup_end | ||
44 | sparc64_cpu_startup: | ||
45 | BRANCH_IF_SUN4V(g1, niagara_startup) | ||
46 | BRANCH_IF_CHEETAH_BASE(g1, g5, cheetah_startup) | ||
47 | BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1, g5, cheetah_plus_startup) | ||
48 | |||
49 | ba,pt %xcc, spitfire_startup | ||
50 | nop | ||
51 | |||
52 | cheetah_plus_startup: | ||
53 | /* Preserve OBP chosen DCU and DCR register settings. */ | ||
54 | ba,pt %xcc, cheetah_generic_startup | ||
55 | nop | ||
56 | |||
57 | cheetah_startup: | ||
58 | mov DCR_BPE | DCR_RPE | DCR_SI | DCR_IFPOE | DCR_MS, %g1 | ||
59 | wr %g1, %asr18 | ||
60 | |||
61 | sethi %uhi(DCU_ME|DCU_RE|DCU_HPE|DCU_SPE|DCU_SL|DCU_WE), %g5 | ||
62 | or %g5, %ulo(DCU_ME|DCU_RE|DCU_HPE|DCU_SPE|DCU_SL|DCU_WE), %g5 | ||
63 | sllx %g5, 32, %g5 | ||
64 | or %g5, DCU_DM | DCU_IM | DCU_DC | DCU_IC, %g5 | ||
65 | stxa %g5, [%g0] ASI_DCU_CONTROL_REG | ||
66 | membar #Sync | ||
67 | /* fallthru */ | ||
68 | |||
69 | cheetah_generic_startup: | ||
70 | mov TSB_EXTENSION_P, %g3 | ||
71 | stxa %g0, [%g3] ASI_DMMU | ||
72 | stxa %g0, [%g3] ASI_IMMU | ||
73 | membar #Sync | ||
74 | |||
75 | mov TSB_EXTENSION_S, %g3 | ||
76 | stxa %g0, [%g3] ASI_DMMU | ||
77 | membar #Sync | ||
78 | |||
79 | mov TSB_EXTENSION_N, %g3 | ||
80 | stxa %g0, [%g3] ASI_DMMU | ||
81 | stxa %g0, [%g3] ASI_IMMU | ||
82 | membar #Sync | ||
83 | /* fallthru */ | ||
84 | |||
85 | niagara_startup: | ||
86 | /* Disable STICK_INT interrupts. */ | ||
87 | sethi %hi(0x80000000), %g5 | ||
88 | sllx %g5, 32, %g5 | ||
89 | wr %g5, %asr25 | ||
90 | |||
91 | ba,pt %xcc, startup_continue | ||
92 | nop | ||
93 | |||
94 | spitfire_startup: | ||
95 | mov (LSU_CONTROL_IC | LSU_CONTROL_DC | LSU_CONTROL_IM | LSU_CONTROL_DM), %g1 | ||
96 | stxa %g1, [%g0] ASI_LSU_CONTROL | ||
97 | membar #Sync | ||
98 | |||
99 | startup_continue: | ||
100 | mov %o0, %l0 | ||
101 | BRANCH_IF_SUN4V(g1, niagara_lock_tlb) | ||
102 | |||
103 | sethi %hi(0x80000000), %g2 | ||
104 | sllx %g2, 32, %g2 | ||
105 | wr %g2, 0, %tick_cmpr | ||
106 | |||
107 | /* Call OBP by hand to lock KERNBASE into i/d tlbs. | ||
108 | * We lock 'num_kernel_image_mappings' consequetive entries. | ||
109 | */ | ||
110 | sethi %hi(prom_entry_lock), %g2 | ||
111 | 1: ldstub [%g2 + %lo(prom_entry_lock)], %g1 | ||
112 | brnz,pn %g1, 1b | ||
113 | nop | ||
114 | |||
115 | sethi %hi(p1275buf), %g2 | ||
116 | or %g2, %lo(p1275buf), %g2 | ||
117 | ldx [%g2 + 0x10], %l2 | ||
118 | add %l2, -(192 + 128), %sp | ||
119 | flushw | ||
120 | |||
121 | /* Setup the loop variables: | ||
122 | * %l3: VADDR base | ||
123 | * %l4: TTE base | ||
124 | * %l5: Loop iterator, iterates from 0 to 'num_kernel_image_mappings' | ||
125 | * %l6: Number of TTE entries to map | ||
126 | * %l7: Highest TTE entry number, we count down | ||
127 | */ | ||
128 | sethi %hi(KERNBASE), %l3 | ||
129 | sethi %hi(kern_locked_tte_data), %l4 | ||
130 | ldx [%l4 + %lo(kern_locked_tte_data)], %l4 | ||
131 | clr %l5 | ||
132 | sethi %hi(num_kernel_image_mappings), %l6 | ||
133 | lduw [%l6 + %lo(num_kernel_image_mappings)], %l6 | ||
134 | add %l6, 1, %l6 | ||
135 | |||
136 | mov 15, %l7 | ||
137 | BRANCH_IF_ANY_CHEETAH(g1,g5,2f) | ||
138 | |||
139 | mov 63, %l7 | ||
140 | 2: | ||
141 | |||
142 | 3: | ||
143 | /* Lock into I-MMU */ | ||
144 | sethi %hi(call_method), %g2 | ||
145 | or %g2, %lo(call_method), %g2 | ||
146 | stx %g2, [%sp + 2047 + 128 + 0x00] | ||
147 | mov 5, %g2 | ||
148 | stx %g2, [%sp + 2047 + 128 + 0x08] | ||
149 | mov 1, %g2 | ||
150 | stx %g2, [%sp + 2047 + 128 + 0x10] | ||
151 | sethi %hi(itlb_load), %g2 | ||
152 | or %g2, %lo(itlb_load), %g2 | ||
153 | stx %g2, [%sp + 2047 + 128 + 0x18] | ||
154 | sethi %hi(prom_mmu_ihandle_cache), %g2 | ||
155 | lduw [%g2 + %lo(prom_mmu_ihandle_cache)], %g2 | ||
156 | stx %g2, [%sp + 2047 + 128 + 0x20] | ||
157 | |||
158 | /* Each TTE maps 4MB, convert index to offset. */ | ||
159 | sllx %l5, 22, %g1 | ||
160 | |||
161 | add %l3, %g1, %g2 | ||
162 | stx %g2, [%sp + 2047 + 128 + 0x28] ! VADDR | ||
163 | add %l4, %g1, %g2 | ||
164 | stx %g2, [%sp + 2047 + 128 + 0x30] ! TTE | ||
165 | |||
166 | /* TTE index is highest minus loop index. */ | ||
167 | sub %l7, %l5, %g2 | ||
168 | stx %g2, [%sp + 2047 + 128 + 0x38] | ||
169 | |||
170 | sethi %hi(p1275buf), %g2 | ||
171 | or %g2, %lo(p1275buf), %g2 | ||
172 | ldx [%g2 + 0x08], %o1 | ||
173 | call %o1 | ||
174 | add %sp, (2047 + 128), %o0 | ||
175 | |||
176 | /* Lock into D-MMU */ | ||
177 | sethi %hi(call_method), %g2 | ||
178 | or %g2, %lo(call_method), %g2 | ||
179 | stx %g2, [%sp + 2047 + 128 + 0x00] | ||
180 | mov 5, %g2 | ||
181 | stx %g2, [%sp + 2047 + 128 + 0x08] | ||
182 | mov 1, %g2 | ||
183 | stx %g2, [%sp + 2047 + 128 + 0x10] | ||
184 | sethi %hi(dtlb_load), %g2 | ||
185 | or %g2, %lo(dtlb_load), %g2 | ||
186 | stx %g2, [%sp + 2047 + 128 + 0x18] | ||
187 | sethi %hi(prom_mmu_ihandle_cache), %g2 | ||
188 | lduw [%g2 + %lo(prom_mmu_ihandle_cache)], %g2 | ||
189 | stx %g2, [%sp + 2047 + 128 + 0x20] | ||
190 | |||
191 | /* Each TTE maps 4MB, convert index to offset. */ | ||
192 | sllx %l5, 22, %g1 | ||
193 | |||
194 | add %l3, %g1, %g2 | ||
195 | stx %g2, [%sp + 2047 + 128 + 0x28] ! VADDR | ||
196 | add %l4, %g1, %g2 | ||
197 | stx %g2, [%sp + 2047 + 128 + 0x30] ! TTE | ||
198 | |||
199 | /* TTE index is highest minus loop index. */ | ||
200 | sub %l7, %l5, %g2 | ||
201 | stx %g2, [%sp + 2047 + 128 + 0x38] | ||
202 | |||
203 | sethi %hi(p1275buf), %g2 | ||
204 | or %g2, %lo(p1275buf), %g2 | ||
205 | ldx [%g2 + 0x08], %o1 | ||
206 | call %o1 | ||
207 | add %sp, (2047 + 128), %o0 | ||
208 | |||
209 | add %l5, 1, %l5 | ||
210 | cmp %l5, %l6 | ||
211 | bne,pt %xcc, 3b | ||
212 | nop | ||
213 | |||
214 | sethi %hi(prom_entry_lock), %g2 | ||
215 | stb %g0, [%g2 + %lo(prom_entry_lock)] | ||
216 | |||
217 | ba,pt %xcc, after_lock_tlb | ||
218 | nop | ||
219 | |||
220 | niagara_lock_tlb: | ||
221 | sethi %hi(KERNBASE), %l3 | ||
222 | sethi %hi(kern_locked_tte_data), %l4 | ||
223 | ldx [%l4 + %lo(kern_locked_tte_data)], %l4 | ||
224 | clr %l5 | ||
225 | sethi %hi(num_kernel_image_mappings), %l6 | ||
226 | lduw [%l6 + %lo(num_kernel_image_mappings)], %l6 | ||
227 | add %l6, 1, %l6 | ||
228 | |||
229 | 1: | ||
230 | mov HV_FAST_MMU_MAP_PERM_ADDR, %o5 | ||
231 | sllx %l5, 22, %g2 | ||
232 | add %l3, %g2, %o0 | ||
233 | clr %o1 | ||
234 | add %l4, %g2, %o2 | ||
235 | mov HV_MMU_IMMU, %o3 | ||
236 | ta HV_FAST_TRAP | ||
237 | |||
238 | mov HV_FAST_MMU_MAP_PERM_ADDR, %o5 | ||
239 | sllx %l5, 22, %g2 | ||
240 | add %l3, %g2, %o0 | ||
241 | clr %o1 | ||
242 | add %l4, %g2, %o2 | ||
243 | mov HV_MMU_DMMU, %o3 | ||
244 | ta HV_FAST_TRAP | ||
245 | |||
246 | add %l5, 1, %l5 | ||
247 | cmp %l5, %l6 | ||
248 | bne,pt %xcc, 1b | ||
249 | nop | ||
250 | |||
251 | after_lock_tlb: | ||
252 | wrpr %g0, (PSTATE_PRIV | PSTATE_PEF), %pstate | ||
253 | wr %g0, 0, %fprs | ||
254 | |||
255 | wr %g0, ASI_P, %asi | ||
256 | |||
257 | mov PRIMARY_CONTEXT, %g7 | ||
258 | |||
259 | 661: stxa %g0, [%g7] ASI_DMMU | ||
260 | .section .sun4v_1insn_patch, "ax" | ||
261 | .word 661b | ||
262 | stxa %g0, [%g7] ASI_MMU | ||
263 | .previous | ||
264 | |||
265 | membar #Sync | ||
266 | mov SECONDARY_CONTEXT, %g7 | ||
267 | |||
268 | 661: stxa %g0, [%g7] ASI_DMMU | ||
269 | .section .sun4v_1insn_patch, "ax" | ||
270 | .word 661b | ||
271 | stxa %g0, [%g7] ASI_MMU | ||
272 | .previous | ||
273 | |||
274 | membar #Sync | ||
275 | |||
276 | /* Everything we do here, until we properly take over the | ||
277 | * trap table, must be done with extreme care. We cannot | ||
278 | * make any references to %g6 (current thread pointer), | ||
279 | * %g4 (current task pointer), or %g5 (base of current cpu's | ||
280 | * per-cpu area) until we properly take over the trap table | ||
281 | * from the firmware and hypervisor. | ||
282 | * | ||
283 | * Get onto temporary stack which is in the locked kernel image. | ||
284 | */ | ||
285 | sethi %hi(tramp_stack), %g1 | ||
286 | or %g1, %lo(tramp_stack), %g1 | ||
287 | add %g1, TRAMP_STACK_SIZE, %g1 | ||
288 | sub %g1, STACKFRAME_SZ + STACK_BIAS + 256, %sp | ||
289 | mov 0, %fp | ||
290 | |||
291 | /* Put garbage in these registers to trap any access to them. */ | ||
292 | set 0xdeadbeef, %g4 | ||
293 | set 0xdeadbeef, %g5 | ||
294 | set 0xdeadbeef, %g6 | ||
295 | |||
296 | call init_irqwork_curcpu | ||
297 | nop | ||
298 | |||
299 | sethi %hi(tlb_type), %g3 | ||
300 | lduw [%g3 + %lo(tlb_type)], %g2 | ||
301 | cmp %g2, 3 | ||
302 | bne,pt %icc, 1f | ||
303 | nop | ||
304 | |||
305 | call hard_smp_processor_id | ||
306 | nop | ||
307 | |||
308 | call sun4v_register_mondo_queues | ||
309 | nop | ||
310 | |||
311 | 1: call init_cur_cpu_trap | ||
312 | ldx [%l0], %o0 | ||
313 | |||
314 | /* Start using proper page size encodings in ctx register. */ | ||
315 | sethi %hi(sparc64_kern_pri_context), %g3 | ||
316 | ldx [%g3 + %lo(sparc64_kern_pri_context)], %g2 | ||
317 | mov PRIMARY_CONTEXT, %g1 | ||
318 | |||
319 | 661: stxa %g2, [%g1] ASI_DMMU | ||
320 | .section .sun4v_1insn_patch, "ax" | ||
321 | .word 661b | ||
322 | stxa %g2, [%g1] ASI_MMU | ||
323 | .previous | ||
324 | |||
325 | membar #Sync | ||
326 | |||
327 | wrpr %g0, 0, %wstate | ||
328 | |||
329 | sethi %hi(prom_entry_lock), %g2 | ||
330 | 1: ldstub [%g2 + %lo(prom_entry_lock)], %g1 | ||
331 | brnz,pn %g1, 1b | ||
332 | nop | ||
333 | |||
334 | /* As a hack, put &init_thread_union into %g6. | ||
335 | * prom_world() loads from here to restore the %asi | ||
336 | * register. | ||
337 | */ | ||
338 | sethi %hi(init_thread_union), %g6 | ||
339 | or %g6, %lo(init_thread_union), %g6 | ||
340 | |||
341 | sethi %hi(is_sun4v), %o0 | ||
342 | lduw [%o0 + %lo(is_sun4v)], %o0 | ||
343 | brz,pt %o0, 2f | ||
344 | nop | ||
345 | |||
346 | TRAP_LOAD_TRAP_BLOCK(%g2, %g3) | ||
347 | add %g2, TRAP_PER_CPU_FAULT_INFO, %g2 | ||
348 | stxa %g2, [%g0] ASI_SCRATCHPAD | ||
349 | |||
350 | /* Compute physical address: | ||
351 | * | ||
352 | * paddr = kern_base + (mmfsa_vaddr - KERNBASE) | ||
353 | */ | ||
354 | sethi %hi(KERNBASE), %g3 | ||
355 | sub %g2, %g3, %g2 | ||
356 | sethi %hi(kern_base), %g3 | ||
357 | ldx [%g3 + %lo(kern_base)], %g3 | ||
358 | add %g2, %g3, %o1 | ||
359 | sethi %hi(sparc64_ttable_tl0), %o0 | ||
360 | |||
361 | set prom_set_trap_table_name, %g2 | ||
362 | stx %g2, [%sp + 2047 + 128 + 0x00] | ||
363 | mov 2, %g2 | ||
364 | stx %g2, [%sp + 2047 + 128 + 0x08] | ||
365 | mov 0, %g2 | ||
366 | stx %g2, [%sp + 2047 + 128 + 0x10] | ||
367 | stx %o0, [%sp + 2047 + 128 + 0x18] | ||
368 | stx %o1, [%sp + 2047 + 128 + 0x20] | ||
369 | sethi %hi(p1275buf), %g2 | ||
370 | or %g2, %lo(p1275buf), %g2 | ||
371 | ldx [%g2 + 0x08], %o1 | ||
372 | call %o1 | ||
373 | add %sp, (2047 + 128), %o0 | ||
374 | |||
375 | ba,pt %xcc, 3f | ||
376 | nop | ||
377 | |||
378 | 2: sethi %hi(sparc64_ttable_tl0), %o0 | ||
379 | set prom_set_trap_table_name, %g2 | ||
380 | stx %g2, [%sp + 2047 + 128 + 0x00] | ||
381 | mov 1, %g2 | ||
382 | stx %g2, [%sp + 2047 + 128 + 0x08] | ||
383 | mov 0, %g2 | ||
384 | stx %g2, [%sp + 2047 + 128 + 0x10] | ||
385 | stx %o0, [%sp + 2047 + 128 + 0x18] | ||
386 | sethi %hi(p1275buf), %g2 | ||
387 | or %g2, %lo(p1275buf), %g2 | ||
388 | ldx [%g2 + 0x08], %o1 | ||
389 | call %o1 | ||
390 | add %sp, (2047 + 128), %o0 | ||
391 | |||
392 | 3: sethi %hi(prom_entry_lock), %g2 | ||
393 | stb %g0, [%g2 + %lo(prom_entry_lock)] | ||
394 | |||
395 | ldx [%l0], %g6 | ||
396 | ldx [%g6 + TI_TASK], %g4 | ||
397 | |||
398 | mov 1, %g5 | ||
399 | sllx %g5, THREAD_SHIFT, %g5 | ||
400 | sub %g5, (STACKFRAME_SZ + STACK_BIAS), %g5 | ||
401 | add %g6, %g5, %sp | ||
402 | mov 0, %fp | ||
403 | |||
404 | rdpr %pstate, %o1 | ||
405 | or %o1, PSTATE_IE, %o1 | ||
406 | wrpr %o1, 0, %pstate | ||
407 | |||
408 | call smp_callin | ||
409 | nop | ||
410 | call cpu_idle | ||
411 | mov 0, %o0 | ||
412 | call cpu_panic | ||
413 | nop | ||
414 | 1: b,a,pt %xcc, 1b | ||
415 | |||
416 | .align 8 | ||
417 | sparc64_cpu_startup_end: | ||