aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/head.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64/kernel/head.S')
-rw-r--r--arch/sparc64/kernel/head.S748
1 files changed, 271 insertions, 477 deletions
diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S
index 1fa06c4e3bd..b49dcd4504b 100644
--- a/arch/sparc64/kernel/head.S
+++ b/arch/sparc64/kernel/head.S
@@ -28,19 +28,14 @@
28#include <asm/mmu.h> 28#include <asm/mmu.h>
29 29
30/* This section from from _start to sparc64_boot_end should fit into 30/* This section from from _start to sparc64_boot_end should fit into
31 * 0x0000.0000.0040.4000 to 0x0000.0000.0040.8000 and will be sharing space 31 * 0x0000000000404000 to 0x0000000000408000.
32 * with bootup_user_stack, which is from 0x0000.0000.0040.4000 to
33 * 0x0000.0000.0040.6000 and empty_bad_page, which is from
34 * 0x0000.0000.0040.6000 to 0x0000.0000.0040.8000.
35 */ 32 */
36
37 .text 33 .text
38 .globl start, _start, stext, _stext 34 .globl start, _start, stext, _stext
39_start: 35_start:
40start: 36start:
41_stext: 37_stext:
42stext: 38stext:
43bootup_user_stack:
44! 0x0000000000404000 39! 0x0000000000404000
45 b sparc64_boot 40 b sparc64_boot
46 flushw /* Flush register file. */ 41 flushw /* Flush register file. */
@@ -80,15 +75,169 @@ sparc_ramdisk_image64:
80 .xword 0 75 .xword 0
81 .word _end 76 .word _end
82 77
83 /* We must be careful, 32-bit OpenBOOT will get confused if it 78 /* PROM cif handler code address is in %o4. */
84 * tries to save away a register window to a 64-bit kernel 79sparc64_boot:
85 * stack address. Flush all windows, disable interrupts, 801: rd %pc, %g7
86 * remap if necessary, jump onto kernel trap table, then kernel 81 set 1b, %g1
87 * stack, or else we die. 82 cmp %g1, %g7
83 be,pn %xcc, sparc64_boot_after_remap
84 mov %o4, %l7
85
86 /* We need to remap the kernel. Use position independant
87 * code to remap us to KERNBASE.
88 * 88 *
89 * PROM entry point is on %o4 89 * SILO can invoke us with 32-bit address masking enabled,
90 * so make sure that's clear.
90 */ 91 */
91sparc64_boot: 92 rdpr %pstate, %g1
93 andn %g1, PSTATE_AM, %g1
94 wrpr %g1, 0x0, %pstate
95 ba,a,pt %xcc, 1f
96
97 .globl prom_finddev_name, prom_chosen_path
98 .globl prom_getprop_name, prom_mmu_name
99 .globl prom_callmethod_name, prom_translate_name
100 .globl prom_map_name, prom_unmap_name, prom_mmu_ihandle_cache
101 .globl prom_boot_mapped_pc, prom_boot_mapping_mode
102 .globl prom_boot_mapping_phys_high, prom_boot_mapping_phys_low
103prom_finddev_name:
104 .asciz "finddevice"
105prom_chosen_path:
106 .asciz "/chosen"
107prom_getprop_name:
108 .asciz "getprop"
109prom_mmu_name:
110 .asciz "mmu"
111prom_callmethod_name:
112 .asciz "call-method"
113prom_translate_name:
114 .asciz "translate"
115prom_map_name:
116 .asciz "map"
117prom_unmap_name:
118 .asciz "unmap"
119 .align 4
120prom_mmu_ihandle_cache:
121 .word 0
122prom_boot_mapped_pc:
123 .word 0
124prom_boot_mapping_mode:
125 .word 0
126 .align 8
127prom_boot_mapping_phys_high:
128 .xword 0
129prom_boot_mapping_phys_low:
130 .xword 0
1311:
132 rd %pc, %l0
133 mov (1b - prom_finddev_name), %l1
134 mov (1b - prom_chosen_path), %l2
135 mov (1b - prom_boot_mapped_pc), %l3
136 sub %l0, %l1, %l1
137 sub %l0, %l2, %l2
138 sub %l0, %l3, %l3
139 stw %l0, [%l3]
140 sub %sp, (192 + 128), %sp
141
142 /* chosen_node = prom_finddevice("/chosen") */
143 stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "finddevice"
144 mov 1, %l3
145 stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 1
146 stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1
147 stx %l2, [%sp + 2047 + 128 + 0x18] ! arg1, "/chosen"
148 stx %g0, [%sp + 2047 + 128 + 0x20] ! ret1
149 call %l7
150 add %sp, (2047 + 128), %o0 ! argument array
151
152 ldx [%sp + 2047 + 128 + 0x20], %l4 ! chosen device node
153
154 mov (1b - prom_getprop_name), %l1
155 mov (1b - prom_mmu_name), %l2
156 mov (1b - prom_mmu_ihandle_cache), %l5
157 sub %l0, %l1, %l1
158 sub %l0, %l2, %l2
159 sub %l0, %l5, %l5
160
161 /* prom_mmu_ihandle_cache = prom_getint(chosen_node, "mmu") */
162 stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "getprop"
163 mov 4, %l3
164 stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 4
165 mov 1, %l3
166 stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1
167 stx %l4, [%sp + 2047 + 128 + 0x18] ! arg1, chosen_node
168 stx %l2, [%sp + 2047 + 128 + 0x20] ! arg2, "mmu"
169 stx %l5, [%sp + 2047 + 128 + 0x28] ! arg3, &prom_mmu_ihandle_cache
170 mov 4, %l3
171 stx %l3, [%sp + 2047 + 128 + 0x30] ! arg4, sizeof(arg3)
172 stx %g0, [%sp + 2047 + 128 + 0x38] ! ret1
173 call %l7
174 add %sp, (2047 + 128), %o0 ! argument array
175
176 mov (1b - prom_callmethod_name), %l1
177 mov (1b - prom_translate_name), %l2
178 sub %l0, %l1, %l1
179 sub %l0, %l2, %l2
180 lduw [%l5], %l5 ! prom_mmu_ihandle_cache
181
182 stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "call-method"
183 mov 3, %l3
184 stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 3
185 mov 5, %l3
186 stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 5
187 stx %l2, [%sp + 2047 + 128 + 0x18] ! arg1: "translate"
188 stx %l5, [%sp + 2047 + 128 + 0x20] ! arg2: prom_mmu_ihandle_cache
189 /* PAGE align */
190 srlx %l0, 13, %l3
191 sllx %l3, 13, %l3
192 stx %l3, [%sp + 2047 + 128 + 0x28] ! arg3: vaddr, our PC
193 stx %g0, [%sp + 2047 + 128 + 0x30] ! res1
194 stx %g0, [%sp + 2047 + 128 + 0x38] ! res2
195 stx %g0, [%sp + 2047 + 128 + 0x40] ! res3
196 stx %g0, [%sp + 2047 + 128 + 0x48] ! res4
197 stx %g0, [%sp + 2047 + 128 + 0x50] ! res5
198 call %l7
199 add %sp, (2047 + 128), %o0 ! argument array
200
201 ldx [%sp + 2047 + 128 + 0x40], %l1 ! translation mode
202 mov (1b - prom_boot_mapping_mode), %l4
203 sub %l0, %l4, %l4
204 stw %l1, [%l4]
205 mov (1b - prom_boot_mapping_phys_high), %l4
206 sub %l0, %l4, %l4
207 ldx [%sp + 2047 + 128 + 0x48], %l2 ! physaddr high
208 stx %l2, [%l4 + 0x0]
209 ldx [%sp + 2047 + 128 + 0x50], %l3 ! physaddr low
210 /* 4MB align */
211 srlx %l3, 22, %l3
212 sllx %l3, 22, %l3
213 stx %l3, [%l4 + 0x8]
214
215 /* Leave service as-is, "call-method" */
216 mov 7, %l3
217 stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 7
218 mov 1, %l3
219 stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1
220 mov (1b - prom_map_name), %l3
221 sub %l0, %l3, %l3
222 stx %l3, [%sp + 2047 + 128 + 0x18] ! arg1: "map"
223 /* Leave arg2 as-is, prom_mmu_ihandle_cache */
224 mov -1, %l3
225 stx %l3, [%sp + 2047 + 128 + 0x28] ! arg3: mode (-1 default)
226 sethi %hi(8 * 1024 * 1024), %l3
227 stx %l3, [%sp + 2047 + 128 + 0x30] ! arg4: size (8MB)
228 sethi %hi(KERNBASE), %l3
229 stx %l3, [%sp + 2047 + 128 + 0x38] ! arg5: vaddr (KERNBASE)
230 stx %g0, [%sp + 2047 + 128 + 0x40] ! arg6: empty
231 mov (1b - prom_boot_mapping_phys_low), %l3
232 sub %l0, %l3, %l3
233 ldx [%l3], %l3
234 stx %l3, [%sp + 2047 + 128 + 0x48] ! arg7: phys addr
235 call %l7
236 add %sp, (2047 + 128), %o0 ! argument array
237
238 add %sp, (192 + 128), %sp
239
240sparc64_boot_after_remap:
92 BRANCH_IF_CHEETAH_BASE(g1,g7,cheetah_boot) 241 BRANCH_IF_CHEETAH_BASE(g1,g7,cheetah_boot)
93 BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,cheetah_plus_boot) 242 BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,cheetah_plus_boot)
94 ba,pt %xcc, spitfire_boot 243 ba,pt %xcc, spitfire_boot
@@ -125,185 +274,7 @@ cheetah_generic_boot:
125 stxa %g0, [%g3] ASI_IMMU 274 stxa %g0, [%g3] ASI_IMMU
126 membar #Sync 275 membar #Sync
127 276
128 wrpr %g0, (PSTATE_PRIV|PSTATE_PEF|PSTATE_IE), %pstate 277 ba,a,pt %xcc, jump_to_sun4u_init
129 wr %g0, 0, %fprs
130
131 /* Just like for Spitfire, we probe itlb-2 for a mapping which
132 * matches our current %pc. We take the physical address in
133 * that mapping and use it to make our own.
134 */
135
136 /* %g5 holds the tlb data */
137 sethi %uhi(_PAGE_VALID | _PAGE_SZ4MB), %g5
138 sllx %g5, 32, %g5
139 or %g5, (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W | _PAGE_G), %g5
140
141 /* Put PADDR tlb data mask into %g3. */
142 sethi %uhi(_PAGE_PADDR), %g3
143 or %g3, %ulo(_PAGE_PADDR), %g3
144 sllx %g3, 32, %g3
145 sethi %hi(_PAGE_PADDR), %g7
146 or %g7, %lo(_PAGE_PADDR), %g7
147 or %g3, %g7, %g3
148
149 set 2 << 16, %l0 /* TLB entry walker. */
150 set 0x1fff, %l2 /* Page mask. */
151 rd %pc, %l3
152 andn %l3, %l2, %g2 /* vaddr comparator */
153
1541: ldxa [%l0] ASI_ITLB_TAG_READ, %g1
155 membar #Sync
156 andn %g1, %l2, %g1
157 cmp %g1, %g2
158 be,pn %xcc, cheetah_got_tlbentry
159 nop
160 and %l0, (127 << 3), %g1
161 cmp %g1, (127 << 3)
162 blu,pt %xcc, 1b
163 add %l0, (1 << 3), %l0
164
165 /* Search the small TLB. OBP never maps us like that but
166 * newer SILO can.
167 */
168 clr %l0
169
1701: ldxa [%l0] ASI_ITLB_TAG_READ, %g1
171 membar #Sync
172 andn %g1, %l2, %g1
173 cmp %g1, %g2
174 be,pn %xcc, cheetah_got_tlbentry
175 nop
176 cmp %l0, (15 << 3)
177 blu,pt %xcc, 1b
178 add %l0, (1 << 3), %l0
179
180 /* BUG() if we get here... */
181 ta 0x5
182
183cheetah_got_tlbentry:
184 ldxa [%l0] ASI_ITLB_DATA_ACCESS, %g0
185 ldxa [%l0] ASI_ITLB_DATA_ACCESS, %g1
186 membar #Sync
187 and %g1, %g3, %g1
188 set 0x5fff, %l0
189 andn %g1, %l0, %g1
190 or %g5, %g1, %g5
191
192 /* Clear out any KERNBASE area entries. */
193 set 2 << 16, %l0
194 sethi %hi(KERNBASE), %g3
195 sethi %hi(KERNBASE<<1), %g7
196 mov TLB_TAG_ACCESS, %l7
197
198 /* First, check ITLB */
1991: ldxa [%l0] ASI_ITLB_TAG_READ, %g1
200 membar #Sync
201 andn %g1, %l2, %g1
202 cmp %g1, %g3
203 blu,pn %xcc, 2f
204 cmp %g1, %g7
205 bgeu,pn %xcc, 2f
206 nop
207 stxa %g0, [%l7] ASI_IMMU
208 membar #Sync
209 stxa %g0, [%l0] ASI_ITLB_DATA_ACCESS
210 membar #Sync
211
2122: and %l0, (127 << 3), %g1
213 cmp %g1, (127 << 3)
214 blu,pt %xcc, 1b
215 add %l0, (1 << 3), %l0
216
217 /* Next, check DTLB */
218 set 2 << 16, %l0
2191: ldxa [%l0] ASI_DTLB_TAG_READ, %g1
220 membar #Sync
221 andn %g1, %l2, %g1
222 cmp %g1, %g3
223 blu,pn %xcc, 2f
224 cmp %g1, %g7
225 bgeu,pn %xcc, 2f
226 nop
227 stxa %g0, [%l7] ASI_DMMU
228 membar #Sync
229 stxa %g0, [%l0] ASI_DTLB_DATA_ACCESS
230 membar #Sync
231
2322: and %l0, (511 << 3), %g1
233 cmp %g1, (511 << 3)
234 blu,pt %xcc, 1b
235 add %l0, (1 << 3), %l0
236
237 /* On Cheetah+, have to check second DTLB. */
238 BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,l0,2f)
239 ba,pt %xcc, 9f
240 nop
241
2422: set 3 << 16, %l0
2431: ldxa [%l0] ASI_DTLB_TAG_READ, %g1
244 membar #Sync
245 andn %g1, %l2, %g1
246 cmp %g1, %g3
247 blu,pn %xcc, 2f
248 cmp %g1, %g7
249 bgeu,pn %xcc, 2f
250 nop
251 stxa %g0, [%l7] ASI_DMMU
252 membar #Sync
253 stxa %g0, [%l0] ASI_DTLB_DATA_ACCESS
254 membar #Sync
255
2562: and %l0, (511 << 3), %g1
257 cmp %g1, (511 << 3)
258 blu,pt %xcc, 1b
259 add %l0, (1 << 3), %l0
260
2619:
262
263 /* Now lock the TTE we created into ITLB-0 and DTLB-0,
264 * entry 15 (and maybe 14 too).
265 */
266 sethi %hi(KERNBASE), %g3
267 set (0 << 16) | (15 << 3), %g7
268 stxa %g3, [%l7] ASI_DMMU
269 membar #Sync
270 stxa %g5, [%g7] ASI_DTLB_DATA_ACCESS
271 membar #Sync
272 stxa %g3, [%l7] ASI_IMMU
273 membar #Sync
274 stxa %g5, [%g7] ASI_ITLB_DATA_ACCESS
275 membar #Sync
276 flush %g3
277 membar #Sync
278 sethi %hi(_end), %g3 /* Check for bigkernel case */
279 or %g3, %lo(_end), %g3
280 srl %g3, 23, %g3 /* Check if _end > 8M */
281 brz,pt %g3, 1f
282 sethi %hi(KERNBASE), %g3 /* Restore for fixup code below */
283 sethi %hi(0x400000), %g3
284 or %g3, %lo(0x400000), %g3
285 add %g5, %g3, %g5 /* New tte data */
286 andn %g5, (_PAGE_G), %g5
287 sethi %hi(KERNBASE+0x400000), %g3
288 or %g3, %lo(KERNBASE+0x400000), %g3
289 set (0 << 16) | (14 << 3), %g7
290 stxa %g3, [%l7] ASI_DMMU
291 membar #Sync
292 stxa %g5, [%g7] ASI_DTLB_DATA_ACCESS
293 membar #Sync
294 stxa %g3, [%l7] ASI_IMMU
295 membar #Sync
296 stxa %g5, [%g7] ASI_ITLB_DATA_ACCESS
297 membar #Sync
298 flush %g3
299 membar #Sync
300 sethi %hi(KERNBASE), %g3 /* Restore for fixup code below */
301 ba,pt %xcc, 1f
302 nop
303
3041: set sun4u_init, %g2
305 jmpl %g2 + %g0, %g0
306 nop
307 278
308spitfire_boot: 279spitfire_boot:
309 /* Typically PROM has already enabled both MMU's and both on-chip 280 /* Typically PROM has already enabled both MMU's and both on-chip
@@ -313,6 +284,7 @@ spitfire_boot:
313 stxa %g1, [%g0] ASI_LSU_CONTROL 284 stxa %g1, [%g0] ASI_LSU_CONTROL
314 membar #Sync 285 membar #Sync
315 286
287jump_to_sun4u_init:
316 /* 288 /*
317 * Make sure we are in privileged mode, have address masking, 289 * Make sure we are in privileged mode, have address masking,
318 * using the ordinary globals and have enabled floating 290 * using the ordinary globals and have enabled floating
@@ -324,151 +296,6 @@ spitfire_boot:
324 wrpr %g0, (PSTATE_PRIV|PSTATE_PEF|PSTATE_IE), %pstate 296 wrpr %g0, (PSTATE_PRIV|PSTATE_PEF|PSTATE_IE), %pstate
325 wr %g0, 0, %fprs 297 wr %g0, 0, %fprs
326 298
327spitfire_create_mappings:
328 /* %g5 holds the tlb data */
329 sethi %uhi(_PAGE_VALID | _PAGE_SZ4MB), %g5
330 sllx %g5, 32, %g5
331 or %g5, (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W | _PAGE_G), %g5
332
333 /* Base of physical memory cannot reliably be assumed to be
334 * at 0x0! Figure out where it happens to be. -DaveM
335 */
336
337 /* Put PADDR tlb data mask into %g3. */
338 sethi %uhi(_PAGE_PADDR_SF), %g3
339 or %g3, %ulo(_PAGE_PADDR_SF), %g3
340 sllx %g3, 32, %g3
341 sethi %hi(_PAGE_PADDR_SF), %g7
342 or %g7, %lo(_PAGE_PADDR_SF), %g7
343 or %g3, %g7, %g3
344
345 /* Walk through entire ITLB, looking for entry which maps
346 * our %pc currently, stick PADDR from there into %g5 tlb data.
347 */
348 clr %l0 /* TLB entry walker. */
349 set 0x1fff, %l2 /* Page mask. */
350 rd %pc, %l3
351 andn %l3, %l2, %g2 /* vaddr comparator */
3521:
353 /* Yes, the nops seem to be necessary for now, don't ask me why. -DaveM */
354 ldxa [%l0] ASI_ITLB_TAG_READ, %g1
355 nop
356 nop
357 nop
358 andn %g1, %l2, %g1 /* Get vaddr */
359 cmp %g1, %g2
360 be,a,pn %xcc, spitfire_got_tlbentry
361 ldxa [%l0] ASI_ITLB_DATA_ACCESS, %g1
362 cmp %l0, (63 << 3)
363 blu,pt %xcc, 1b
364 add %l0, (1 << 3), %l0
365
366 /* BUG() if we get here... */
367 ta 0x5
368
369spitfire_got_tlbentry:
370 /* Nops here again, perhaps Cheetah/Blackbird are better behaved... */
371 nop
372 nop
373 nop
374 and %g1, %g3, %g1 /* Mask to just get paddr bits. */
375 set 0x5fff, %l3 /* Mask offset to get phys base. */
376 andn %g1, %l3, %g1
377
378 /* NOTE: We hold on to %g1 paddr base as we need it below to lock
379 * NOTE: the PROM cif code into the TLB.
380 */
381
382 or %g5, %g1, %g5 /* Or it into TAG being built. */
383
384 clr %l0 /* TLB entry walker. */
385 sethi %hi(KERNBASE), %g3 /* 4M lower limit */
386 sethi %hi(KERNBASE<<1), %g7 /* 8M upper limit */
387 mov TLB_TAG_ACCESS, %l7
3881:
389 /* Yes, the nops seem to be necessary for now, don't ask me why. -DaveM */
390 ldxa [%l0] ASI_ITLB_TAG_READ, %g1
391 nop
392 nop
393 nop
394 andn %g1, %l2, %g1 /* Get vaddr */
395 cmp %g1, %g3
396 blu,pn %xcc, 2f
397 cmp %g1, %g7
398 bgeu,pn %xcc, 2f
399 nop
400 stxa %g0, [%l7] ASI_IMMU
401 stxa %g0, [%l0] ASI_ITLB_DATA_ACCESS
402 membar #Sync
4032:
404 cmp %l0, (63 << 3)
405 blu,pt %xcc, 1b
406 add %l0, (1 << 3), %l0
407
408 nop; nop; nop
409
410 clr %l0 /* TLB entry walker. */
4111:
412 /* Yes, the nops seem to be necessary for now, don't ask me why. -DaveM */
413 ldxa [%l0] ASI_DTLB_TAG_READ, %g1
414 nop
415 nop
416 nop
417 andn %g1, %l2, %g1 /* Get vaddr */
418 cmp %g1, %g3
419 blu,pn %xcc, 2f
420 cmp %g1, %g7
421 bgeu,pn %xcc, 2f
422 nop
423 stxa %g0, [%l7] ASI_DMMU
424 stxa %g0, [%l0] ASI_DTLB_DATA_ACCESS
425 membar #Sync
4262:
427 cmp %l0, (63 << 3)
428 blu,pt %xcc, 1b
429 add %l0, (1 << 3), %l0
430
431 nop; nop; nop
432
433
434 /* PROM never puts any TLB entries into the MMU with the lock bit
435 * set. So we gladly use tlb entry 63 for KERNBASE. And maybe 62 too.
436 */
437
438 sethi %hi(KERNBASE), %g3
439 mov (63 << 3), %g7
440 stxa %g3, [%l7] ASI_DMMU /* KERNBASE into TLB TAG */
441 stxa %g5, [%g7] ASI_DTLB_DATA_ACCESS /* TTE into TLB DATA */
442 membar #Sync
443 stxa %g3, [%l7] ASI_IMMU /* KERNBASE into TLB TAG */
444 stxa %g5, [%g7] ASI_ITLB_DATA_ACCESS /* TTE into TLB DATA */
445 membar #Sync
446 flush %g3
447 membar #Sync
448 sethi %hi(_end), %g3 /* Check for bigkernel case */
449 or %g3, %lo(_end), %g3
450 srl %g3, 23, %g3 /* Check if _end > 8M */
451 brz,pt %g3, 2f
452 sethi %hi(KERNBASE), %g3 /* Restore for fixup code below */
453 sethi %hi(0x400000), %g3
454 or %g3, %lo(0x400000), %g3
455 add %g5, %g3, %g5 /* New tte data */
456 andn %g5, (_PAGE_G), %g5
457 sethi %hi(KERNBASE+0x400000), %g3
458 or %g3, %lo(KERNBASE+0x400000), %g3
459 mov (62 << 3), %g7
460 stxa %g3, [%l7] ASI_DMMU
461 stxa %g5, [%g7] ASI_DTLB_DATA_ACCESS
462 membar #Sync
463 stxa %g3, [%l7] ASI_IMMU
464 stxa %g5, [%g7] ASI_ITLB_DATA_ACCESS
465 membar #Sync
466 flush %g3
467 membar #Sync
468 sethi %hi(KERNBASE), %g3 /* Restore for fixup code below */
4692: ba,pt %xcc, 1f
470 nop
4711:
472 set sun4u_init, %g2 299 set sun4u_init, %g2
473 jmpl %g2 + %g0, %g0 300 jmpl %g2 + %g0, %g0
474 nop 301 nop
@@ -483,38 +310,12 @@ sun4u_init:
483 stxa %g0, [%g7] ASI_DMMU 310 stxa %g0, [%g7] ASI_DMMU
484 membar #Sync 311 membar #Sync
485 312
486 /* We are now safely (we hope) in Nucleus context (0), rewrite
487 * the KERNBASE TTE's so they no longer have the global bit set.
488 * Don't forget to setup TAG_ACCESS first 8-)
489 */
490 mov TLB_TAG_ACCESS, %g2
491 stxa %g3, [%g2] ASI_IMMU
492 stxa %g3, [%g2] ASI_DMMU
493 membar #Sync
494
495 BRANCH_IF_ANY_CHEETAH(g1,g7,cheetah_tlb_fixup) 313 BRANCH_IF_ANY_CHEETAH(g1,g7,cheetah_tlb_fixup)
496 314
497 ba,pt %xcc, spitfire_tlb_fixup 315 ba,pt %xcc, spitfire_tlb_fixup
498 nop 316 nop
499 317
500cheetah_tlb_fixup: 318cheetah_tlb_fixup:
501 set (0 << 16) | (15 << 3), %g7
502 ldxa [%g7] ASI_ITLB_DATA_ACCESS, %g0
503 ldxa [%g7] ASI_ITLB_DATA_ACCESS, %g1
504 andn %g1, (_PAGE_G), %g1
505 stxa %g1, [%g7] ASI_ITLB_DATA_ACCESS
506 membar #Sync
507
508 ldxa [%g7] ASI_DTLB_DATA_ACCESS, %g0
509 ldxa [%g7] ASI_DTLB_DATA_ACCESS, %g1
510 andn %g1, (_PAGE_G), %g1
511 stxa %g1, [%g7] ASI_DTLB_DATA_ACCESS
512 membar #Sync
513
514 /* Kill instruction prefetch queues. */
515 flush %g3
516 membar #Sync
517
518 mov 2, %g2 /* Set TLB type to cheetah+. */ 319 mov 2, %g2 /* Set TLB type to cheetah+. */
519 BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,1f) 320 BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,1f)
520 321
@@ -523,23 +324,7 @@ cheetah_tlb_fixup:
5231: sethi %hi(tlb_type), %g1 3241: sethi %hi(tlb_type), %g1
524 stw %g2, [%g1 + %lo(tlb_type)] 325 stw %g2, [%g1 + %lo(tlb_type)]
525 326
526 BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,1f) 327 /* Patch copy/page operations to cheetah optimized versions. */
527 ba,pt %xcc, 2f
528 nop
529
5301: /* Patch context register writes to support nucleus page
531 * size correctly.
532 */
533 call cheetah_plus_patch_etrap
534 nop
535 call cheetah_plus_patch_rtrap
536 nop
537 call cheetah_plus_patch_fpdis
538 nop
539 call cheetah_plus_patch_winfixup
540 nop
541
5422: /* Patch copy/page operations to cheetah optimized versions. */
543 call cheetah_patch_copyops 328 call cheetah_patch_copyops
544 nop 329 nop
545 call cheetah_patch_copy_page 330 call cheetah_patch_copy_page
@@ -551,21 +336,6 @@ cheetah_tlb_fixup:
551 nop 336 nop
552 337
553spitfire_tlb_fixup: 338spitfire_tlb_fixup:
554 mov (63 << 3), %g7
555 ldxa [%g7] ASI_ITLB_DATA_ACCESS, %g1
556 andn %g1, (_PAGE_G), %g1
557 stxa %g1, [%g7] ASI_ITLB_DATA_ACCESS
558 membar #Sync
559
560 ldxa [%g7] ASI_DTLB_DATA_ACCESS, %g1
561 andn %g1, (_PAGE_G), %g1
562 stxa %g1, [%g7] ASI_DTLB_DATA_ACCESS
563 membar #Sync
564
565 /* Kill instruction prefetch queues. */
566 flush %g3
567 membar #Sync
568
569 /* Set TLB type to spitfire. */ 339 /* Set TLB type to spitfire. */
570 mov 0, %g2 340 mov 0, %g2
571 sethi %hi(tlb_type), %g1 341 sethi %hi(tlb_type), %g1
@@ -578,24 +348,6 @@ tlb_fixup_done:
578 mov %sp, %l6 348 mov %sp, %l6
579 mov %o4, %l7 349 mov %o4, %l7
580 350
581#if 0 /* We don't do it like this anymore, but for historical hack value
582 * I leave this snippet here to show how crazy we can be sometimes. 8-)
583 */
584
585 /* Setup "Linux Current Register", thanks Sun 8-) */
586 wr %g0, 0x1, %pcr
587
588 /* Blackbird errata workaround. See commentary in
589 * smp.c:smp_percpu_timer_interrupt() for more
590 * information.
591 */
592 ba,pt %xcc, 99f
593 nop
594 .align 64
59599: wr %g6, %g0, %pic
596 rd %pic, %g0
597#endif
598
599 wr %g0, ASI_P, %asi 351 wr %g0, ASI_P, %asi
600 mov 1, %g1 352 mov 1, %g1
601 sllx %g1, THREAD_SHIFT, %g1 353 sllx %g1, THREAD_SHIFT, %g1
@@ -629,32 +381,78 @@ tlb_fixup_done:
629 nop 381 nop
630 /* Not reached... */ 382 /* Not reached... */
631 383
632/* IMPORTANT NOTE: Whenever making changes here, check 384 /* This is meant to allow the sharing of this code between
633 * trampoline.S as well. -jj */ 385 * boot processor invocation (via setup_tba() below) and
634 .globl setup_tba 386 * secondary processor startup (via trampoline.S). The
635setup_tba: /* i0 = is_starfire */ 387 * former does use this code, the latter does not yet due
636 save %sp, -160, %sp 388 * to some complexities. That should be fixed up at some
389 * point.
390 *
391 * There used to be enormous complexity wrt. transferring
392 * over from the firwmare's trap table to the Linux kernel's.
393 * For example, there was a chicken & egg problem wrt. building
394 * the OBP page tables, yet needing to be on the Linux kernel
395 * trap table (to translate PAGE_OFFSET addresses) in order to
396 * do that.
397 *
398 * We now handle OBP tlb misses differently, via linear lookups
399 * into the prom_trans[] array. So that specific problem no
400 * longer exists. Yet, unfortunately there are still some issues
401 * preventing trampoline.S from using this code... ho hum.
402 */
403 .globl setup_trap_table
404setup_trap_table:
405 save %sp, -192, %sp
637 406
638 rdpr %tba, %g7 407 /* Force interrupts to be disabled. */
639 sethi %hi(prom_tba), %o1 408 rdpr %pstate, %o1
640 or %o1, %lo(prom_tba), %o1 409 andn %o1, PSTATE_IE, %o1
641 stx %g7, [%o1] 410 wrpr %o1, 0x0, %pstate
411 wrpr %g0, 15, %pil
412
413 /* Make the firmware call to jump over to the Linux trap table. */
414 call prom_set_trap_table
415 sethi %hi(sparc64_ttable_tl0), %o0
416
417 /* Start using proper page size encodings in ctx register. */
418 sethi %hi(sparc64_kern_pri_context), %g3
419 ldx [%g3 + %lo(sparc64_kern_pri_context)], %g2
420 mov PRIMARY_CONTEXT, %g1
421 stxa %g2, [%g1] ASI_DMMU
422 membar #Sync
423
424 /* The Linux trap handlers expect various trap global registers
425 * to be setup with some fixed values. So here we set these
426 * up very carefully. These globals are:
427 *
428 * Alternate Globals (PSTATE_AG):
429 *
430 * %g6 --> current_thread_info()
431 *
432 * MMU Globals (PSTATE_MG):
433 *
434 * %g1 --> TLB_SFSR
435 * %g2 --> ((_PAGE_VALID | _PAGE_SZ4MB |
436 * _PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W)
437 * ^ 0xfffff80000000000)
438 * (this %g2 value is used for computing the PAGE_OFFSET kernel
439 * TLB entries quickly, the virtual address of the fault XOR'd
440 * with this %g2 value is the PTE to load into the TLB)
441 * %g3 --> VPTE_BASE_CHEETAH or VPTE_BASE_SPITFIRE
442 *
443 * Interrupt Globals (PSTATE_IG, setup by init_irqwork_curcpu()):
444 *
445 * %g6 --> __irq_work[smp_processor_id()]
446 */
642 447
643 /* Setup "Linux" globals 8-) */
644 rdpr %pstate, %o1 448 rdpr %pstate, %o1
645 mov %g6, %o2 449 mov %g6, %o2
646 wrpr %o1, (PSTATE_AG|PSTATE_IE), %pstate 450 wrpr %o1, PSTATE_AG, %pstate
647 sethi %hi(sparc64_ttable_tl0), %g1
648 wrpr %g1, %tba
649 mov %o2, %g6 451 mov %o2, %g6
650 452
651 /* Set up MMU globals */
652 wrpr %o1, (PSTATE_MG|PSTATE_IE), %pstate
653
654 /* Set fixed globals used by dTLB miss handler. */
655#define KERN_HIGHBITS ((_PAGE_VALID|_PAGE_SZ4MB)^0xfffff80000000000) 453#define KERN_HIGHBITS ((_PAGE_VALID|_PAGE_SZ4MB)^0xfffff80000000000)
656#define KERN_LOWBITS (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W) 454#define KERN_LOWBITS (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W)
657 455 wrpr %o1, PSTATE_MG, %pstate
658 mov TSB_REG, %g1 456 mov TSB_REG, %g1
659 stxa %g0, [%g1] ASI_DMMU 457 stxa %g0, [%g1] ASI_DMMU
660 membar #Sync 458 membar #Sync
@@ -666,17 +464,17 @@ setup_tba: /* i0 = is_starfire */
666 sllx %g2, 32, %g2 464 sllx %g2, 32, %g2
667 or %g2, KERN_LOWBITS, %g2 465 or %g2, KERN_LOWBITS, %g2
668 466
669 BRANCH_IF_ANY_CHEETAH(g3,g7,cheetah_vpte_base) 467 BRANCH_IF_ANY_CHEETAH(g3,g7,8f)
670 ba,pt %xcc, spitfire_vpte_base 468 ba,pt %xcc, 9f
671 nop 469 nop
672 470
673cheetah_vpte_base: 4718:
674 sethi %uhi(VPTE_BASE_CHEETAH), %g3 472 sethi %uhi(VPTE_BASE_CHEETAH), %g3
675 or %g3, %ulo(VPTE_BASE_CHEETAH), %g3 473 or %g3, %ulo(VPTE_BASE_CHEETAH), %g3
676 ba,pt %xcc, 2f 474 ba,pt %xcc, 2f
677 sllx %g3, 32, %g3 475 sllx %g3, 32, %g3
678 476
679spitfire_vpte_base: 4779:
680 sethi %uhi(VPTE_BASE_SPITFIRE), %g3 478 sethi %uhi(VPTE_BASE_SPITFIRE), %g3
681 or %g3, %ulo(VPTE_BASE_SPITFIRE), %g3 479 or %g3, %ulo(VPTE_BASE_SPITFIRE), %g3
682 sllx %g3, 32, %g3 480 sllx %g3, 32, %g3
@@ -702,48 +500,55 @@ spitfire_vpte_base:
702 sllx %o2, 32, %o2 500 sllx %o2, 32, %o2
703 wr %o2, %asr25 501 wr %o2, %asr25
704 502
705 /* Ok, we're done setting up all the state our trap mechanims needs,
706 * now get back into normal globals and let the PROM know what is up.
707 */
7082: 5032:
709 wrpr %g0, %g0, %wstate 504 wrpr %g0, %g0, %wstate
710 wrpr %o1, PSTATE_IE, %pstate 505 wrpr %o1, 0x0, %pstate
711 506
712 call init_irqwork_curcpu 507 call init_irqwork_curcpu
713 nop 508 nop
714 509
715 call prom_set_trap_table 510 /* Now we can turn interrupts back on. */
716 sethi %hi(sparc64_ttable_tl0), %o0
717
718 BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g2,g3,1f)
719 ba,pt %xcc, 2f
720 nop
721
7221: /* Start using proper page size encodings in ctx register. */
723 sethi %uhi(CTX_CHEETAH_PLUS_NUC), %g3
724 mov PRIMARY_CONTEXT, %g1
725 sllx %g3, 32, %g3
726 sethi %hi(CTX_CHEETAH_PLUS_CTX0), %g2
727 or %g3, %g2, %g3
728 stxa %g3, [%g1] ASI_DMMU
729 membar #Sync
730
7312:
732 rdpr %pstate, %o1 511 rdpr %pstate, %o1
733 or %o1, PSTATE_IE, %o1 512 or %o1, PSTATE_IE, %o1
734 wrpr %o1, 0, %pstate 513 wrpr %o1, 0, %pstate
514 wrpr %g0, 0x0, %pil
515
516 ret
517 restore
518
519 .globl setup_tba
520setup_tba: /* i0 = is_starfire */
521 save %sp, -192, %sp
522
523 /* The boot processor is the only cpu which invokes this
524 * routine, the other cpus set things up via trampoline.S.
525 * So save the OBP trap table address here.
526 */
527 rdpr %tba, %g7
528 sethi %hi(prom_tba), %o1
529 or %o1, %lo(prom_tba), %o1
530 stx %g7, [%o1]
531
532 call setup_trap_table
533 nop
735 534
736 ret 535 ret
737 restore 536 restore
537sparc64_boot_end:
538
539#include "systbls.S"
540#include "ktlb.S"
541#include "etrap.S"
542#include "rtrap.S"
543#include "winfixup.S"
544#include "entry.S"
738 545
739/* 546/*
740 * The following skips make sure the trap table in ttable.S is aligned 547 * The following skip makes sure the trap table in ttable.S is aligned
741 * on a 32K boundary as required by the v9 specs for TBA register. 548 * on a 32K boundary as required by the v9 specs for TBA register.
742 */ 549 */
743sparc64_boot_end: 5501:
744 .skip 0x2000 + _start - sparc64_boot_end 551 .skip 0x4000 + _start - 1b
745bootup_user_stack_end:
746 .skip 0x2000
747 552
748#ifdef CONFIG_SBUS 553#ifdef CONFIG_SBUS
749/* This is just a hack to fool make depend config.h discovering 554/* This is just a hack to fool make depend config.h discovering
@@ -755,20 +560,6 @@ bootup_user_stack_end:
755! 0x0000000000408000 560! 0x0000000000408000
756 561
757#include "ttable.S" 562#include "ttable.S"
758#include "systbls.S"
759
760 .align 1024
761 .globl swapper_pg_dir
762swapper_pg_dir:
763 .word 0
764
765#include "etrap.S"
766#include "rtrap.S"
767#include "winfixup.S"
768#include "entry.S"
769
770 /* This is just anal retentiveness on my part... */
771 .align 16384
772 563
773 .data 564 .data
774 .align 8 565 .align 8
@@ -776,8 +567,11 @@ swapper_pg_dir:
776prom_tba: .xword 0 567prom_tba: .xword 0
777tlb_type: .word 0 /* Must NOT end up in BSS */ 568tlb_type: .word 0 /* Must NOT end up in BSS */
778 .section ".fixup",#alloc,#execinstr 569 .section ".fixup",#alloc,#execinstr
779 .globl __ret_efault 570
571 .globl __ret_efault, __retl_efault
780__ret_efault: 572__ret_efault:
781 ret 573 ret
782 restore %g0, -EFAULT, %o0 574 restore %g0, -EFAULT, %o0
783 575__retl_efault:
576 retl
577 mov -EFAULT, %o0