aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2005-10-12 00:43:32 -0400
committerPaul Mackerras <paulus@samba.org>2005-10-12 00:43:32 -0400
commitb6ec995a21a9428aef620b5adf46d047a18d88b8 (patch)
tree6719121e6605cbca524b687f47336b9bbf3b8d41 /arch/sparc64
parent3a5f8c5f788d68e325d9fe3c26f4df5a5aee838a (diff)
parentda64c6ee6bb71bfb3f09d9bb89ce1aa4b1ee7e89 (diff)
Merge from Linus' tree
Diffstat (limited to 'arch/sparc64')
-rw-r--r--arch/sparc64/kernel/cpu.c4
-rw-r--r--arch/sparc64/kernel/entry.S82
-rw-r--r--arch/sparc64/kernel/etrap.S51
-rw-r--r--arch/sparc64/kernel/head.S167
-rw-r--r--arch/sparc64/kernel/irq.c1
-rw-r--r--arch/sparc64/kernel/power.c64
-rw-r--r--arch/sparc64/kernel/ptrace.c14
-rw-r--r--arch/sparc64/kernel/rtrap.S30
-rw-r--r--arch/sparc64/kernel/setup.c29
-rw-r--r--arch/sparc64/kernel/sys32.S170
-rw-r--r--arch/sparc64/kernel/trampoline.S15
-rw-r--r--arch/sparc64/kernel/traps.c60
-rw-r--r--arch/sparc64/kernel/una_asm.S65
-rw-r--r--arch/sparc64/kernel/unaligned.c53
-rw-r--r--arch/sparc64/kernel/us3_cpufreq.c5
-rw-r--r--arch/sparc64/kernel/winfixup.S33
-rw-r--r--arch/sparc64/lib/VISsave.S8
-rw-r--r--arch/sparc64/lib/strncpy_from_user.S16
-rw-r--r--arch/sparc64/lib/user_fixup.c63
-rw-r--r--arch/sparc64/mm/Makefile2
-rw-r--r--arch/sparc64/mm/extable.c80
-rw-r--r--arch/sparc64/mm/fault.c69
-rw-r--r--arch/sparc64/mm/init.c441
-rw-r--r--arch/sparc64/prom/Makefile2
-rw-r--r--arch/sparc64/prom/init.c3
-rw-r--r--arch/sparc64/prom/memory.c152
26 files changed, 649 insertions, 1030 deletions
diff --git a/arch/sparc64/kernel/cpu.c b/arch/sparc64/kernel/cpu.c
index 48756958116b..77ef5df4e5a7 100644
--- a/arch/sparc64/kernel/cpu.c
+++ b/arch/sparc64/kernel/cpu.c
@@ -39,6 +39,8 @@ struct cpu_fp_info linux_sparc_fpu[] = {
39 { 0x3e, 0x15, 0, "UltraSparc III+ integrated FPU"}, 39 { 0x3e, 0x15, 0, "UltraSparc III+ integrated FPU"},
40 { 0x3e, 0x16, 0, "UltraSparc IIIi integrated FPU"}, 40 { 0x3e, 0x16, 0, "UltraSparc IIIi integrated FPU"},
41 { 0x3e, 0x18, 0, "UltraSparc IV integrated FPU"}, 41 { 0x3e, 0x18, 0, "UltraSparc IV integrated FPU"},
42 { 0x3e, 0x19, 0, "UltraSparc IV+ integrated FPU"},
43 { 0x3e, 0x22, 0, "UltraSparc IIIi+ integrated FPU"},
42}; 44};
43 45
44#define NSPARCFPU (sizeof(linux_sparc_fpu)/sizeof(struct cpu_fp_info)) 46#define NSPARCFPU (sizeof(linux_sparc_fpu)/sizeof(struct cpu_fp_info))
@@ -53,6 +55,8 @@ struct cpu_iu_info linux_sparc_chips[] = {
53 { 0x3e, 0x15, "TI UltraSparc III+ (Cheetah+)"}, 55 { 0x3e, 0x15, "TI UltraSparc III+ (Cheetah+)"},
54 { 0x3e, 0x16, "TI UltraSparc IIIi (Jalapeno)"}, 56 { 0x3e, 0x16, "TI UltraSparc IIIi (Jalapeno)"},
55 { 0x3e, 0x18, "TI UltraSparc IV (Jaguar)"}, 57 { 0x3e, 0x18, "TI UltraSparc IV (Jaguar)"},
58 { 0x3e, 0x19, "TI UltraSparc IV+ (Panther)"},
59 { 0x3e, 0x22, "TI UltraSparc IIIi+ (Serrano)"},
56}; 60};
57 61
58#define NSPARCCHIPS (sizeof(linux_sparc_chips)/sizeof(struct cpu_iu_info)) 62#define NSPARCCHIPS (sizeof(linux_sparc_chips)/sizeof(struct cpu_iu_info))
diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S
index 2879b1072921..11a848402fb1 100644
--- a/arch/sparc64/kernel/entry.S
+++ b/arch/sparc64/kernel/entry.S
@@ -33,7 +33,7 @@
33 /* This is trivial with the new code... */ 33 /* This is trivial with the new code... */
34 .globl do_fpdis 34 .globl do_fpdis
35do_fpdis: 35do_fpdis:
36 sethi %hi(TSTATE_PEF), %g4 ! IEU0 36 sethi %hi(TSTATE_PEF), %g4
37 rdpr %tstate, %g5 37 rdpr %tstate, %g5
38 andcc %g5, %g4, %g0 38 andcc %g5, %g4, %g0
39 be,pt %xcc, 1f 39 be,pt %xcc, 1f
@@ -50,18 +50,18 @@ do_fpdis:
50 add %g0, %g0, %g0 50 add %g0, %g0, %g0
51 ba,a,pt %xcc, rtrap_clr_l6 51 ba,a,pt %xcc, rtrap_clr_l6
52 52
531: ldub [%g6 + TI_FPSAVED], %g5 ! Load Group 531: ldub [%g6 + TI_FPSAVED], %g5
54 wr %g0, FPRS_FEF, %fprs ! LSU Group+4bubbles 54 wr %g0, FPRS_FEF, %fprs
55 andcc %g5, FPRS_FEF, %g0 ! IEU1 Group 55 andcc %g5, FPRS_FEF, %g0
56 be,a,pt %icc, 1f ! CTI 56 be,a,pt %icc, 1f
57 clr %g7 ! IEU0 57 clr %g7
58 ldx [%g6 + TI_GSR], %g7 ! Load Group 58 ldx [%g6 + TI_GSR], %g7
591: andcc %g5, FPRS_DL, %g0 ! IEU1 591: andcc %g5, FPRS_DL, %g0
60 bne,pn %icc, 2f ! CTI 60 bne,pn %icc, 2f
61 fzero %f0 ! FPA 61 fzero %f0
62 andcc %g5, FPRS_DU, %g0 ! IEU1 Group 62 andcc %g5, FPRS_DU, %g0
63 bne,pn %icc, 1f ! CTI 63 bne,pn %icc, 1f
64 fzero %f2 ! FPA 64 fzero %f2
65 faddd %f0, %f2, %f4 65 faddd %f0, %f2, %f4
66 fmuld %f0, %f2, %f6 66 fmuld %f0, %f2, %f6
67 faddd %f0, %f2, %f8 67 faddd %f0, %f2, %f8
@@ -97,15 +97,17 @@ do_fpdis:
97 faddd %f0, %f2, %f4 97 faddd %f0, %f2, %f4
98 fmuld %f0, %f2, %f6 98 fmuld %f0, %f2, %f6
99 ldxa [%g3] ASI_DMMU, %g5 99 ldxa [%g3] ASI_DMMU, %g5
100cplus_fptrap_insn_1: 100 sethi %hi(sparc64_kern_sec_context), %g2
101 sethi %hi(0), %g2 101 ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2
102 stxa %g2, [%g3] ASI_DMMU 102 stxa %g2, [%g3] ASI_DMMU
103 membar #Sync 103 membar #Sync
104 add %g6, TI_FPREGS + 0xc0, %g2 104 add %g6, TI_FPREGS + 0xc0, %g2
105 faddd %f0, %f2, %f8 105 faddd %f0, %f2, %f8
106 fmuld %f0, %f2, %f10 106 fmuld %f0, %f2, %f10
107 ldda [%g1] ASI_BLK_S, %f32 ! grrr, where is ASI_BLK_NUCLEUS 8-( 107 membar #Sync
108 ldda [%g1] ASI_BLK_S, %f32
108 ldda [%g2] ASI_BLK_S, %f48 109 ldda [%g2] ASI_BLK_S, %f48
110 membar #Sync
109 faddd %f0, %f2, %f12 111 faddd %f0, %f2, %f12
110 fmuld %f0, %f2, %f14 112 fmuld %f0, %f2, %f14
111 faddd %f0, %f2, %f16 113 faddd %f0, %f2, %f16
@@ -116,7 +118,6 @@ cplus_fptrap_insn_1:
116 fmuld %f0, %f2, %f26 118 fmuld %f0, %f2, %f26
117 faddd %f0, %f2, %f28 119 faddd %f0, %f2, %f28
118 fmuld %f0, %f2, %f30 120 fmuld %f0, %f2, %f30
119 membar #Sync
120 b,pt %xcc, fpdis_exit 121 b,pt %xcc, fpdis_exit
121 nop 122 nop
1222: andcc %g5, FPRS_DU, %g0 1232: andcc %g5, FPRS_DU, %g0
@@ -126,15 +127,17 @@ cplus_fptrap_insn_1:
126 fzero %f34 127 fzero %f34
127 ldxa [%g3] ASI_DMMU, %g5 128 ldxa [%g3] ASI_DMMU, %g5
128 add %g6, TI_FPREGS, %g1 129 add %g6, TI_FPREGS, %g1
129cplus_fptrap_insn_2: 130 sethi %hi(sparc64_kern_sec_context), %g2
130 sethi %hi(0), %g2 131 ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2
131 stxa %g2, [%g3] ASI_DMMU 132 stxa %g2, [%g3] ASI_DMMU
132 membar #Sync 133 membar #Sync
133 add %g6, TI_FPREGS + 0x40, %g2 134 add %g6, TI_FPREGS + 0x40, %g2
134 faddd %f32, %f34, %f36 135 faddd %f32, %f34, %f36
135 fmuld %f32, %f34, %f38 136 fmuld %f32, %f34, %f38
136 ldda [%g1] ASI_BLK_S, %f0 ! grrr, where is ASI_BLK_NUCLEUS 8-( 137 membar #Sync
138 ldda [%g1] ASI_BLK_S, %f0
137 ldda [%g2] ASI_BLK_S, %f16 139 ldda [%g2] ASI_BLK_S, %f16
140 membar #Sync
138 faddd %f32, %f34, %f40 141 faddd %f32, %f34, %f40
139 fmuld %f32, %f34, %f42 142 fmuld %f32, %f34, %f42
140 faddd %f32, %f34, %f44 143 faddd %f32, %f34, %f44
@@ -147,18 +150,18 @@ cplus_fptrap_insn_2:
147 fmuld %f32, %f34, %f58 150 fmuld %f32, %f34, %f58
148 faddd %f32, %f34, %f60 151 faddd %f32, %f34, %f60
149 fmuld %f32, %f34, %f62 152 fmuld %f32, %f34, %f62
150 membar #Sync
151 ba,pt %xcc, fpdis_exit 153 ba,pt %xcc, fpdis_exit
152 nop 154 nop
1533: mov SECONDARY_CONTEXT, %g3 1553: mov SECONDARY_CONTEXT, %g3
154 add %g6, TI_FPREGS, %g1 156 add %g6, TI_FPREGS, %g1
155 ldxa [%g3] ASI_DMMU, %g5 157 ldxa [%g3] ASI_DMMU, %g5
156cplus_fptrap_insn_3: 158 sethi %hi(sparc64_kern_sec_context), %g2
157 sethi %hi(0), %g2 159 ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2
158 stxa %g2, [%g3] ASI_DMMU 160 stxa %g2, [%g3] ASI_DMMU
159 membar #Sync 161 membar #Sync
160 mov 0x40, %g2 162 mov 0x40, %g2
161 ldda [%g1] ASI_BLK_S, %f0 ! grrr, where is ASI_BLK_NUCLEUS 8-( 163 membar #Sync
164 ldda [%g1] ASI_BLK_S, %f0
162 ldda [%g1 + %g2] ASI_BLK_S, %f16 165 ldda [%g1 + %g2] ASI_BLK_S, %f16
163 add %g1, 0x80, %g1 166 add %g1, 0x80, %g1
164 ldda [%g1] ASI_BLK_S, %f32 167 ldda [%g1] ASI_BLK_S, %f32
@@ -319,8 +322,8 @@ do_fptrap_after_fsr:
319 stx %g3, [%g6 + TI_GSR] 322 stx %g3, [%g6 + TI_GSR]
320 mov SECONDARY_CONTEXT, %g3 323 mov SECONDARY_CONTEXT, %g3
321 ldxa [%g3] ASI_DMMU, %g5 324 ldxa [%g3] ASI_DMMU, %g5
322cplus_fptrap_insn_4: 325 sethi %hi(sparc64_kern_sec_context), %g2
323 sethi %hi(0), %g2 326 ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2
324 stxa %g2, [%g3] ASI_DMMU 327 stxa %g2, [%g3] ASI_DMMU
325 membar #Sync 328 membar #Sync
326 add %g6, TI_FPREGS, %g2 329 add %g6, TI_FPREGS, %g2
@@ -341,33 +344,6 @@ cplus_fptrap_insn_4:
341 ba,pt %xcc, etrap 344 ba,pt %xcc, etrap
342 wr %g0, 0, %fprs 345 wr %g0, 0, %fprs
343 346
344cplus_fptrap_1:
345 sethi %hi(CTX_CHEETAH_PLUS_CTX0), %g2
346
347 .globl cheetah_plus_patch_fpdis
348cheetah_plus_patch_fpdis:
349 /* We configure the dTLB512_0 for 4MB pages and the
350 * dTLB512_1 for 8K pages when in context zero.
351 */
352 sethi %hi(cplus_fptrap_1), %o0
353 lduw [%o0 + %lo(cplus_fptrap_1)], %o1
354
355 set cplus_fptrap_insn_1, %o2
356 stw %o1, [%o2]
357 flush %o2
358 set cplus_fptrap_insn_2, %o2
359 stw %o1, [%o2]
360 flush %o2
361 set cplus_fptrap_insn_3, %o2
362 stw %o1, [%o2]
363 flush %o2
364 set cplus_fptrap_insn_4, %o2
365 stw %o1, [%o2]
366 flush %o2
367
368 retl
369 nop
370
371 /* The registers for cross calls will be: 347 /* The registers for cross calls will be:
372 * 348 *
373 * DATA 0: [low 32-bits] Address of function to call, jmp to this 349 * DATA 0: [low 32-bits] Address of function to call, jmp to this
diff --git a/arch/sparc64/kernel/etrap.S b/arch/sparc64/kernel/etrap.S
index 50d2af1d98ae..0d8eba21111b 100644
--- a/arch/sparc64/kernel/etrap.S
+++ b/arch/sparc64/kernel/etrap.S
@@ -68,12 +68,8 @@ etrap_irq:
68 68
69 wrpr %g3, 0, %otherwin 69 wrpr %g3, 0, %otherwin
70 wrpr %g2, 0, %wstate 70 wrpr %g2, 0, %wstate
71cplus_etrap_insn_1: 71 sethi %hi(sparc64_kern_pri_context), %g2
72 sethi %hi(0), %g3 72 ldx [%g2 + %lo(sparc64_kern_pri_context)], %g3
73 sllx %g3, 32, %g3
74cplus_etrap_insn_2:
75 sethi %hi(0), %g2
76 or %g3, %g2, %g3
77 stxa %g3, [%l4] ASI_DMMU 73 stxa %g3, [%l4] ASI_DMMU
78 flush %l6 74 flush %l6
79 wr %g0, ASI_AIUS, %asi 75 wr %g0, ASI_AIUS, %asi
@@ -215,12 +211,8 @@ scetrap: rdpr %pil, %g2
215 mov PRIMARY_CONTEXT, %l4 211 mov PRIMARY_CONTEXT, %l4
216 wrpr %g3, 0, %otherwin 212 wrpr %g3, 0, %otherwin
217 wrpr %g2, 0, %wstate 213 wrpr %g2, 0, %wstate
218cplus_etrap_insn_3: 214 sethi %hi(sparc64_kern_pri_context), %g2
219 sethi %hi(0), %g3 215 ldx [%g2 + %lo(sparc64_kern_pri_context)], %g3
220 sllx %g3, 32, %g3
221cplus_etrap_insn_4:
222 sethi %hi(0), %g2
223 or %g3, %g2, %g3
224 stxa %g3, [%l4] ASI_DMMU 216 stxa %g3, [%l4] ASI_DMMU
225 flush %l6 217 flush %l6
226 218
@@ -264,38 +256,3 @@ cplus_etrap_insn_4:
264 256
265#undef TASK_REGOFF 257#undef TASK_REGOFF
266#undef ETRAP_PSTATE1 258#undef ETRAP_PSTATE1
267
268cplus_einsn_1:
269 sethi %uhi(CTX_CHEETAH_PLUS_NUC), %g3
270cplus_einsn_2:
271 sethi %hi(CTX_CHEETAH_PLUS_CTX0), %g2
272
273 .globl cheetah_plus_patch_etrap
274cheetah_plus_patch_etrap:
275 /* We configure the dTLB512_0 for 4MB pages and the
276 * dTLB512_1 for 8K pages when in context zero.
277 */
278 sethi %hi(cplus_einsn_1), %o0
279 sethi %hi(cplus_etrap_insn_1), %o2
280 lduw [%o0 + %lo(cplus_einsn_1)], %o1
281 or %o2, %lo(cplus_etrap_insn_1), %o2
282 stw %o1, [%o2]
283 flush %o2
284 sethi %hi(cplus_etrap_insn_3), %o2
285 or %o2, %lo(cplus_etrap_insn_3), %o2
286 stw %o1, [%o2]
287 flush %o2
288
289 sethi %hi(cplus_einsn_2), %o0
290 sethi %hi(cplus_etrap_insn_2), %o2
291 lduw [%o0 + %lo(cplus_einsn_2)], %o1
292 or %o2, %lo(cplus_etrap_insn_2), %o2
293 stw %o1, [%o2]
294 flush %o2
295 sethi %hi(cplus_etrap_insn_4), %o2
296 or %o2, %lo(cplus_etrap_insn_4), %o2
297 stw %o1, [%o2]
298 flush %o2
299
300 retl
301 nop
diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S
index ecc748fb9ad7..4c942f71184d 100644
--- a/arch/sparc64/kernel/head.S
+++ b/arch/sparc64/kernel/head.S
@@ -191,8 +191,9 @@ prom_boot_mapping_phys_low:
191 stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 5 191 stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 5
192 stx %l2, [%sp + 2047 + 128 + 0x18] ! arg1: "translate" 192 stx %l2, [%sp + 2047 + 128 + 0x18] ! arg1: "translate"
193 stx %l5, [%sp + 2047 + 128 + 0x20] ! arg2: prom_mmu_ihandle_cache 193 stx %l5, [%sp + 2047 + 128 + 0x20] ! arg2: prom_mmu_ihandle_cache
194 srlx %l0, 22, %l3 194 /* PAGE align */
195 sllx %l3, 22, %l3 195 srlx %l0, 13, %l3
196 sllx %l3, 13, %l3
196 stx %l3, [%sp + 2047 + 128 + 0x28] ! arg3: vaddr, our PC 197 stx %l3, [%sp + 2047 + 128 + 0x28] ! arg3: vaddr, our PC
197 stx %g0, [%sp + 2047 + 128 + 0x30] ! res1 198 stx %g0, [%sp + 2047 + 128 + 0x30] ! res1
198 stx %g0, [%sp + 2047 + 128 + 0x38] ! res2 199 stx %g0, [%sp + 2047 + 128 + 0x38] ! res2
@@ -211,6 +212,9 @@ prom_boot_mapping_phys_low:
211 ldx [%sp + 2047 + 128 + 0x48], %l2 ! physaddr high 212 ldx [%sp + 2047 + 128 + 0x48], %l2 ! physaddr high
212 stx %l2, [%l4 + 0x0] 213 stx %l2, [%l4 + 0x0]
213 ldx [%sp + 2047 + 128 + 0x50], %l3 ! physaddr low 214 ldx [%sp + 2047 + 128 + 0x50], %l3 ! physaddr low
215 /* 4MB align */
216 srlx %l3, 22, %l3
217 sllx %l3, 22, %l3
214 stx %l3, [%l4 + 0x8] 218 stx %l3, [%l4 + 0x8]
215 219
216 /* Leave service as-is, "call-method" */ 220 /* Leave service as-is, "call-method" */
@@ -325,23 +329,7 @@ cheetah_tlb_fixup:
3251: sethi %hi(tlb_type), %g1 3291: sethi %hi(tlb_type), %g1
326 stw %g2, [%g1 + %lo(tlb_type)] 330 stw %g2, [%g1 + %lo(tlb_type)]
327 331
328 BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,1f) 332 /* Patch copy/page operations to cheetah optimized versions. */
329 ba,pt %xcc, 2f
330 nop
331
3321: /* Patch context register writes to support nucleus page
333 * size correctly.
334 */
335 call cheetah_plus_patch_etrap
336 nop
337 call cheetah_plus_patch_rtrap
338 nop
339 call cheetah_plus_patch_fpdis
340 nop
341 call cheetah_plus_patch_winfixup
342 nop
343
3442: /* Patch copy/page operations to cheetah optimized versions. */
345 call cheetah_patch_copyops 333 call cheetah_patch_copyops
346 nop 334 nop
347 call cheetah_patch_copy_page 335 call cheetah_patch_copy_page
@@ -398,32 +386,79 @@ tlb_fixup_done:
398 nop 386 nop
399 /* Not reached... */ 387 /* Not reached... */
400 388
401/* IMPORTANT NOTE: Whenever making changes here, check 389 /* This is meant to allow the sharing of this code between
402 * trampoline.S as well. -jj */ 390 * boot processor invocation (via setup_tba() below) and
403 .globl setup_tba 391 * secondary processor startup (via trampoline.S). The
404setup_tba: /* i0 = is_starfire */ 392 * former does use this code, the latter does not yet due
405 save %sp, -160, %sp 393 * to some complexities. That should be fixed up at some
394 * point.
395 */
396 .globl setup_trap_table
397setup_trap_table:
398 save %sp, -192, %sp
399
400 /* Force interrupts to be disabled. Transferring over to
401 * the Linux trap table is a very delicate operation.
402 * Until we are actually on the Linux trap table, we cannot
403 * get the PAGE_OFFSET linear mappings translated. We need
404 * that mapping to be setup in order to initialize the firmware
405 * page tables.
406 *
407 * So there is this window of time, from the return from
408 * prom_set_trap_table() until inherit_prom_mappings_post()
409 * (in arch/sparc64/mm/init.c) completes, during which no
410 * firmware address space accesses can be made.
411 */
412 rdpr %pstate, %o1
413 andn %o1, PSTATE_IE, %o1
414 wrpr %o1, 0x0, %pstate
415 wrpr %g0, 15, %pil
406 416
407 rdpr %tba, %g7 417 /* Ok, now make the final valid firmware call to jump over
408 sethi %hi(prom_tba), %o1 418 * to the Linux trap table.
409 or %o1, %lo(prom_tba), %o1 419 */
410 stx %g7, [%o1] 420 call prom_set_trap_table
421 sethi %hi(sparc64_ttable_tl0), %o0
422
423 /* Start using proper page size encodings in ctx register. */
424 sethi %hi(sparc64_kern_pri_context), %g3
425 ldx [%g3 + %lo(sparc64_kern_pri_context)], %g2
426 mov PRIMARY_CONTEXT, %g1
427 stxa %g2, [%g1] ASI_DMMU
428 membar #Sync
429
430 /* The Linux trap handlers expect various trap global registers
431 * to be setup with some fixed values. So here we set these
432 * up very carefully. These globals are:
433 *
434 * Alternate Globals (PSTATE_AG):
435 *
436 * %g6 --> current_thread_info()
437 *
438 * MMU Globals (PSTATE_MG):
439 *
440 * %g1 --> TLB_SFSR
441 * %g2 --> ((_PAGE_VALID | _PAGE_SZ4MB |
442 * _PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W)
443 * ^ 0xfffff80000000000)
444 * (this %g2 value is used for computing the PAGE_OFFSET kernel
445 * TLB entries quickly, the virtual address of the fault XOR'd
446 * with this %g2 value is the PTE to load into the TLB)
447 * %g3 --> VPTE_BASE_CHEETAH or VPTE_BASE_SPITFIRE
448 *
449 * Interrupt Globals (PSTATE_IG, setup by init_irqwork_curcpu()):
450 *
451 * %g6 --> __irq_work[smp_processor_id()]
452 */
411 453
412 /* Setup "Linux" globals 8-) */
413 rdpr %pstate, %o1 454 rdpr %pstate, %o1
414 mov %g6, %o2 455 mov %g6, %o2
415 wrpr %o1, (PSTATE_AG|PSTATE_IE), %pstate 456 wrpr %o1, PSTATE_AG, %pstate
416 sethi %hi(sparc64_ttable_tl0), %g1
417 wrpr %g1, %tba
418 mov %o2, %g6 457 mov %o2, %g6
419 458
420 /* Set up MMU globals */
421 wrpr %o1, (PSTATE_MG|PSTATE_IE), %pstate
422
423 /* Set fixed globals used by dTLB miss handler. */
424#define KERN_HIGHBITS ((_PAGE_VALID|_PAGE_SZ4MB)^0xfffff80000000000) 459#define KERN_HIGHBITS ((_PAGE_VALID|_PAGE_SZ4MB)^0xfffff80000000000)
425#define KERN_LOWBITS (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W) 460#define KERN_LOWBITS (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W)
426 461 wrpr %o1, PSTATE_MG, %pstate
427 mov TSB_REG, %g1 462 mov TSB_REG, %g1
428 stxa %g0, [%g1] ASI_DMMU 463 stxa %g0, [%g1] ASI_DMMU
429 membar #Sync 464 membar #Sync
@@ -435,17 +470,17 @@ setup_tba: /* i0 = is_starfire */
435 sllx %g2, 32, %g2 470 sllx %g2, 32, %g2
436 or %g2, KERN_LOWBITS, %g2 471 or %g2, KERN_LOWBITS, %g2
437 472
438 BRANCH_IF_ANY_CHEETAH(g3,g7,cheetah_vpte_base) 473 BRANCH_IF_ANY_CHEETAH(g3,g7,8f)
439 ba,pt %xcc, spitfire_vpte_base 474 ba,pt %xcc, 9f
440 nop 475 nop
441 476
442cheetah_vpte_base: 4778:
443 sethi %uhi(VPTE_BASE_CHEETAH), %g3 478 sethi %uhi(VPTE_BASE_CHEETAH), %g3
444 or %g3, %ulo(VPTE_BASE_CHEETAH), %g3 479 or %g3, %ulo(VPTE_BASE_CHEETAH), %g3
445 ba,pt %xcc, 2f 480 ba,pt %xcc, 2f
446 sllx %g3, 32, %g3 481 sllx %g3, 32, %g3
447 482
448spitfire_vpte_base: 4839:
449 sethi %uhi(VPTE_BASE_SPITFIRE), %g3 484 sethi %uhi(VPTE_BASE_SPITFIRE), %g3
450 or %g3, %ulo(VPTE_BASE_SPITFIRE), %g3 485 or %g3, %ulo(VPTE_BASE_SPITFIRE), %g3
451 sllx %g3, 32, %g3 486 sllx %g3, 32, %g3
@@ -471,36 +506,37 @@ spitfire_vpte_base:
471 sllx %o2, 32, %o2 506 sllx %o2, 32, %o2
472 wr %o2, %asr25 507 wr %o2, %asr25
473 508
474 /* Ok, we're done setting up all the state our trap mechanims needs,
475 * now get back into normal globals and let the PROM know what is up.
476 */
4772: 5092:
478 wrpr %g0, %g0, %wstate 510 wrpr %g0, %g0, %wstate
479 wrpr %o1, PSTATE_IE, %pstate 511 wrpr %o1, 0x0, %pstate
480 512
481 call init_irqwork_curcpu 513 call init_irqwork_curcpu
482 nop 514 nop
483 515
484 call prom_set_trap_table 516 /* Now we can turn interrupts back on. */
485 sethi %hi(sparc64_ttable_tl0), %o0
486
487 BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g2,g3,1f)
488 ba,pt %xcc, 2f
489 nop
490
4911: /* Start using proper page size encodings in ctx register. */
492 sethi %uhi(CTX_CHEETAH_PLUS_NUC), %g3
493 mov PRIMARY_CONTEXT, %g1
494 sllx %g3, 32, %g3
495 sethi %hi(CTX_CHEETAH_PLUS_CTX0), %g2
496 or %g3, %g2, %g3
497 stxa %g3, [%g1] ASI_DMMU
498 membar #Sync
499
5002:
501 rdpr %pstate, %o1 517 rdpr %pstate, %o1
502 or %o1, PSTATE_IE, %o1 518 or %o1, PSTATE_IE, %o1
503 wrpr %o1, 0, %pstate 519 wrpr %o1, 0, %pstate
520 wrpr %g0, 0x0, %pil
521
522 ret
523 restore
524
525 .globl setup_tba
526setup_tba: /* i0 = is_starfire */
527 save %sp, -192, %sp
528
529 /* The boot processor is the only cpu which invokes this
530 * routine, the other cpus set things up via trampoline.S.
531 * So save the OBP trap table address here.
532 */
533 rdpr %tba, %g7
534 sethi %hi(prom_tba), %o1
535 or %o1, %lo(prom_tba), %o1
536 stx %g7, [%o1]
537
538 call setup_trap_table
539 nop
504 540
505 ret 541 ret
506 restore 542 restore
@@ -540,8 +576,11 @@ bootup_user_stack_end:
540prom_tba: .xword 0 576prom_tba: .xword 0
541tlb_type: .word 0 /* Must NOT end up in BSS */ 577tlb_type: .word 0 /* Must NOT end up in BSS */
542 .section ".fixup",#alloc,#execinstr 578 .section ".fixup",#alloc,#execinstr
543 .globl __ret_efault 579
580 .globl __ret_efault, __retl_efault
544__ret_efault: 581__ret_efault:
545 ret 582 ret
546 restore %g0, -EFAULT, %o0 583 restore %g0, -EFAULT, %o0
547 584__retl_efault:
585 retl
586 mov -EFAULT, %o0
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index c9b69167632a..233526ba3abe 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -27,6 +27,7 @@
27#include <asm/atomic.h> 27#include <asm/atomic.h>
28#include <asm/system.h> 28#include <asm/system.h>
29#include <asm/irq.h> 29#include <asm/irq.h>
30#include <asm/io.h>
30#include <asm/sbus.h> 31#include <asm/sbus.h>
31#include <asm/iommu.h> 32#include <asm/iommu.h>
32#include <asm/upa.h> 33#include <asm/upa.h>
diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c
index 946cee0257ea..9e8362ea3104 100644
--- a/arch/sparc64/kernel/power.c
+++ b/arch/sparc64/kernel/power.c
@@ -17,6 +17,7 @@
17 17
18#include <asm/system.h> 18#include <asm/system.h>
19#include <asm/ebus.h> 19#include <asm/ebus.h>
20#include <asm/isa.h>
20#include <asm/auxio.h> 21#include <asm/auxio.h>
21 22
22#include <linux/unistd.h> 23#include <linux/unistd.h>
@@ -100,46 +101,83 @@ again:
100 return 0; 101 return 0;
101} 102}
102 103
103static int __init has_button_interrupt(struct linux_ebus_device *edev) 104static int __init has_button_interrupt(unsigned int irq, int prom_node)
104{ 105{
105 if (edev->irqs[0] == PCI_IRQ_NONE) 106 if (irq == PCI_IRQ_NONE)
106 return 0; 107 return 0;
107 if (!prom_node_has_property(edev->prom_node, "button")) 108 if (!prom_node_has_property(prom_node, "button"))
108 return 0; 109 return 0;
109 110
110 return 1; 111 return 1;
111} 112}
112 113
113void __init power_init(void) 114static int __init power_probe_ebus(struct resource **resp, unsigned int *irq_p, int *prom_node_p)
114{ 115{
115 struct linux_ebus *ebus; 116 struct linux_ebus *ebus;
116 struct linux_ebus_device *edev; 117 struct linux_ebus_device *edev;
118
119 for_each_ebus(ebus) {
120 for_each_ebusdev(edev, ebus) {
121 if (!strcmp(edev->prom_name, "power")) {
122 *resp = &edev->resource[0];
123 *irq_p = edev->irqs[0];
124 *prom_node_p = edev->prom_node;
125 return 0;
126 }
127 }
128 }
129 return -ENODEV;
130}
131
132static int __init power_probe_isa(struct resource **resp, unsigned int *irq_p, int *prom_node_p)
133{
134 struct sparc_isa_bridge *isa_bus;
135 struct sparc_isa_device *isa_dev;
136
137 for_each_isa(isa_bus) {
138 for_each_isadev(isa_dev, isa_bus) {
139 if (!strcmp(isa_dev->prom_name, "power")) {
140 *resp = &isa_dev->resource;
141 *irq_p = isa_dev->irq;
142 *prom_node_p = isa_dev->prom_node;
143 return 0;
144 }
145 }
146 }
147 return -ENODEV;
148}
149
150void __init power_init(void)
151{
152 struct resource *res = NULL;
153 unsigned int irq;
154 int prom_node;
117 static int invoked; 155 static int invoked;
118 156
119 if (invoked) 157 if (invoked)
120 return; 158 return;
121 invoked = 1; 159 invoked = 1;
122 160
123 for_each_ebus(ebus) { 161 if (!power_probe_ebus(&res, &irq, &prom_node))
124 for_each_ebusdev(edev, ebus) { 162 goto found;
125 if (!strcmp(edev->prom_name, "power")) 163
126 goto found; 164 if (!power_probe_isa(&res, &irq, &prom_node))
127 } 165 goto found;
128 } 166
129 return; 167 return;
130 168
131found: 169found:
132 power_reg = ioremap(edev->resource[0].start, 0x4); 170 power_reg = ioremap(res->start, 0x4);
133 printk("power: Control reg at %p ... ", power_reg); 171 printk("power: Control reg at %p ... ", power_reg);
134 poweroff_method = machine_halt; /* able to use the standard halt */ 172 poweroff_method = machine_halt; /* able to use the standard halt */
135 if (has_button_interrupt(edev)) { 173 if (has_button_interrupt(irq, prom_node)) {
136 if (kernel_thread(powerd, NULL, CLONE_FS) < 0) { 174 if (kernel_thread(powerd, NULL, CLONE_FS) < 0) {
137 printk("Failed to start power daemon.\n"); 175 printk("Failed to start power daemon.\n");
138 return; 176 return;
139 } 177 }
140 printk("powerd running.\n"); 178 printk("powerd running.\n");
141 179
142 if (request_irq(edev->irqs[0], 180 if (request_irq(irq,
143 power_handler, SA_SHIRQ, "power", NULL) < 0) 181 power_handler, SA_SHIRQ, "power", NULL) < 0)
144 printk("power: Error, cannot register IRQ handler.\n"); 182 printk("power: Error, cannot register IRQ handler.\n");
145 } else { 183 } else {
diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c
index 5efbff90d668..774ecbb8a031 100644
--- a/arch/sparc64/kernel/ptrace.c
+++ b/arch/sparc64/kernel/ptrace.c
@@ -31,6 +31,7 @@
31#include <asm/visasm.h> 31#include <asm/visasm.h>
32#include <asm/spitfire.h> 32#include <asm/spitfire.h>
33#include <asm/page.h> 33#include <asm/page.h>
34#include <asm/cpudata.h>
34 35
35/* Returning from ptrace is a bit tricky because the syscall return 36/* Returning from ptrace is a bit tricky because the syscall return
36 * low level code assumes any value returned which is negative and 37 * low level code assumes any value returned which is negative and
@@ -132,12 +133,16 @@ void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
132 if ((uaddr ^ (unsigned long) kaddr) & (1UL << 13)) { 133 if ((uaddr ^ (unsigned long) kaddr) & (1UL << 13)) {
133 unsigned long start = __pa(kaddr); 134 unsigned long start = __pa(kaddr);
134 unsigned long end = start + len; 135 unsigned long end = start + len;
136 unsigned long dcache_line_size;
137
138 dcache_line_size = local_cpu_data().dcache_line_size;
135 139
136 if (tlb_type == spitfire) { 140 if (tlb_type == spitfire) {
137 for (; start < end; start += 32) 141 for (; start < end; start += dcache_line_size)
138 spitfire_put_dcache_tag(start & 0x3fe0, 0x0); 142 spitfire_put_dcache_tag(start & 0x3fe0, 0x0);
139 } else { 143 } else {
140 for (; start < end; start += 32) 144 start &= ~(dcache_line_size - 1);
145 for (; start < end; start += dcache_line_size)
141 __asm__ __volatile__( 146 __asm__ __volatile__(
142 "stxa %%g0, [%0] %1\n\t" 147 "stxa %%g0, [%0] %1\n\t"
143 "membar #Sync" 148 "membar #Sync"
@@ -150,8 +155,11 @@ void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
150 if (write && tlb_type == spitfire) { 155 if (write && tlb_type == spitfire) {
151 unsigned long start = (unsigned long) kaddr; 156 unsigned long start = (unsigned long) kaddr;
152 unsigned long end = start + len; 157 unsigned long end = start + len;
158 unsigned long icache_line_size;
159
160 icache_line_size = local_cpu_data().icache_line_size;
153 161
154 for (; start < end; start += 32) 162 for (; start < end; start += icache_line_size)
155 flushi(start); 163 flushi(start);
156 } 164 }
157} 165}
diff --git a/arch/sparc64/kernel/rtrap.S b/arch/sparc64/kernel/rtrap.S
index fafd227735fa..090dcca00d2a 100644
--- a/arch/sparc64/kernel/rtrap.S
+++ b/arch/sparc64/kernel/rtrap.S
@@ -256,9 +256,8 @@ rt_continue: ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1
256 brnz,pn %l3, kern_rtt 256 brnz,pn %l3, kern_rtt
257 mov PRIMARY_CONTEXT, %l7 257 mov PRIMARY_CONTEXT, %l7
258 ldxa [%l7 + %l7] ASI_DMMU, %l0 258 ldxa [%l7 + %l7] ASI_DMMU, %l0
259cplus_rtrap_insn_1: 259 sethi %hi(sparc64_kern_pri_nuc_bits), %l1
260 sethi %hi(0), %l1 260 ldx [%l1 + %lo(sparc64_kern_pri_nuc_bits)], %l1
261 sllx %l1, 32, %l1
262 or %l0, %l1, %l0 261 or %l0, %l1, %l0
263 stxa %l0, [%l7] ASI_DMMU 262 stxa %l0, [%l7] ASI_DMMU
264 flush %g6 263 flush %g6
@@ -313,53 +312,36 @@ kern_fpucheck: ldub [%g6 + TI_FPDEPTH], %l5
313 wr %g1, FPRS_FEF, %fprs 312 wr %g1, FPRS_FEF, %fprs
314 ldx [%o1 + %o5], %g1 313 ldx [%o1 + %o5], %g1
315 add %g6, TI_XFSR, %o1 314 add %g6, TI_XFSR, %o1
316 membar #StoreLoad | #LoadLoad
317 sll %o0, 8, %o2 315 sll %o0, 8, %o2
318 add %g6, TI_FPREGS, %o3 316 add %g6, TI_FPREGS, %o3
319 brz,pn %l6, 1f 317 brz,pn %l6, 1f
320 add %g6, TI_FPREGS+0x40, %o4 318 add %g6, TI_FPREGS+0x40, %o4
321 319
320 membar #Sync
322 ldda [%o3 + %o2] ASI_BLK_P, %f0 321 ldda [%o3 + %o2] ASI_BLK_P, %f0
323 ldda [%o4 + %o2] ASI_BLK_P, %f16 322 ldda [%o4 + %o2] ASI_BLK_P, %f16
323 membar #Sync
3241: andcc %l2, FPRS_DU, %g0 3241: andcc %l2, FPRS_DU, %g0
325 be,pn %icc, 1f 325 be,pn %icc, 1f
326 wr %g1, 0, %gsr 326 wr %g1, 0, %gsr
327 add %o2, 0x80, %o2 327 add %o2, 0x80, %o2
328 membar #Sync
328 ldda [%o3 + %o2] ASI_BLK_P, %f32 329 ldda [%o3 + %o2] ASI_BLK_P, %f32
329 ldda [%o4 + %o2] ASI_BLK_P, %f48 330 ldda [%o4 + %o2] ASI_BLK_P, %f48
330
3311: membar #Sync 3311: membar #Sync
332 ldx [%o1 + %o5], %fsr 332 ldx [%o1 + %o5], %fsr
3332: stb %l5, [%g6 + TI_FPDEPTH] 3332: stb %l5, [%g6 + TI_FPDEPTH]
334 ba,pt %xcc, rt_continue 334 ba,pt %xcc, rt_continue
335 nop 335 nop
3365: wr %g0, FPRS_FEF, %fprs 3365: wr %g0, FPRS_FEF, %fprs
337 membar #StoreLoad | #LoadLoad
338 sll %o0, 8, %o2 337 sll %o0, 8, %o2
339 338
340 add %g6, TI_FPREGS+0x80, %o3 339 add %g6, TI_FPREGS+0x80, %o3
341 add %g6, TI_FPREGS+0xc0, %o4 340 add %g6, TI_FPREGS+0xc0, %o4
341 membar #Sync
342 ldda [%o3 + %o2] ASI_BLK_P, %f32 342 ldda [%o3 + %o2] ASI_BLK_P, %f32
343 ldda [%o4 + %o2] ASI_BLK_P, %f48 343 ldda [%o4 + %o2] ASI_BLK_P, %f48
344 membar #Sync 344 membar #Sync
345 wr %g0, FPRS_DU, %fprs 345 wr %g0, FPRS_DU, %fprs
346 ba,pt %xcc, rt_continue 346 ba,pt %xcc, rt_continue
347 stb %l5, [%g6 + TI_FPDEPTH] 347 stb %l5, [%g6 + TI_FPDEPTH]
348
349cplus_rinsn_1:
350 sethi %uhi(CTX_CHEETAH_PLUS_NUC), %l1
351
352 .globl cheetah_plus_patch_rtrap
353cheetah_plus_patch_rtrap:
354 /* We configure the dTLB512_0 for 4MB pages and the
355 * dTLB512_1 for 8K pages when in context zero.
356 */
357 sethi %hi(cplus_rinsn_1), %o0
358 sethi %hi(cplus_rtrap_insn_1), %o2
359 lduw [%o0 + %lo(cplus_rinsn_1)], %o1
360 or %o2, %lo(cplus_rtrap_insn_1), %o2
361 stw %o1, [%o2]
362 flush %o2
363
364 retl
365 nop
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
index 8e8baf2354df..c1f34237cdf2 100644
--- a/arch/sparc64/kernel/setup.c
+++ b/arch/sparc64/kernel/setup.c
@@ -187,17 +187,13 @@ int prom_callback(long *args)
187 } 187 }
188 188
189 if ((va >= KERNBASE) && (va < (KERNBASE + (4 * 1024 * 1024)))) { 189 if ((va >= KERNBASE) && (va < (KERNBASE + (4 * 1024 * 1024)))) {
190 unsigned long kernel_pctx = 0; 190 extern unsigned long sparc64_kern_pri_context;
191
192 if (tlb_type == cheetah_plus)
193 kernel_pctx |= (CTX_CHEETAH_PLUS_NUC |
194 CTX_CHEETAH_PLUS_CTX0);
195 191
196 /* Spitfire Errata #32 workaround */ 192 /* Spitfire Errata #32 workaround */
197 __asm__ __volatile__("stxa %0, [%1] %2\n\t" 193 __asm__ __volatile__("stxa %0, [%1] %2\n\t"
198 "flush %%g6" 194 "flush %%g6"
199 : /* No outputs */ 195 : /* No outputs */
200 : "r" (kernel_pctx), 196 : "r" (sparc64_kern_pri_context),
201 "r" (PRIMARY_CONTEXT), 197 "r" (PRIMARY_CONTEXT),
202 "i" (ASI_DMMU)); 198 "i" (ASI_DMMU));
203 199
@@ -464,8 +460,6 @@ static void __init boot_flags_init(char *commands)
464 } 460 }
465} 461}
466 462
467extern int prom_probe_memory(void);
468extern unsigned long start, end;
469extern void panic_setup(char *, int *); 463extern void panic_setup(char *, int *);
470 464
471extern unsigned short root_flags; 465extern unsigned short root_flags;
@@ -492,12 +486,8 @@ void register_prom_callbacks(void)
492 "' linux-.soft2 to .soft2"); 486 "' linux-.soft2 to .soft2");
493} 487}
494 488
495extern void paging_init(void);
496
497void __init setup_arch(char **cmdline_p) 489void __init setup_arch(char **cmdline_p)
498{ 490{
499 int i;
500
501 /* Initialize PROM console and command line. */ 491 /* Initialize PROM console and command line. */
502 *cmdline_p = prom_getbootargs(); 492 *cmdline_p = prom_getbootargs();
503 strcpy(saved_command_line, *cmdline_p); 493 strcpy(saved_command_line, *cmdline_p);
@@ -516,21 +506,6 @@ void __init setup_arch(char **cmdline_p)
516 boot_flags_init(*cmdline_p); 506 boot_flags_init(*cmdline_p);
517 507
518 idprom_init(); 508 idprom_init();
519 (void) prom_probe_memory();
520
521 phys_base = 0xffffffffffffffffUL;
522 for (i = 0; sp_banks[i].num_bytes != 0; i++) {
523 unsigned long top;
524
525 if (sp_banks[i].base_addr < phys_base)
526 phys_base = sp_banks[i].base_addr;
527 top = sp_banks[i].base_addr +
528 sp_banks[i].num_bytes;
529 }
530 pfn_base = phys_base >> PAGE_SHIFT;
531
532 kern_base = (prom_boot_mapping_phys_low >> 22UL) << 22UL;
533 kern_size = (unsigned long)&_end - (unsigned long)KERNBASE;
534 509
535 if (!root_flags) 510 if (!root_flags)
536 root_mountflags &= ~MS_RDONLY; 511 root_mountflags &= ~MS_RDONLY;
diff --git a/arch/sparc64/kernel/sys32.S b/arch/sparc64/kernel/sys32.S
index 5f9e4fae612e..9cd272ac3ac1 100644
--- a/arch/sparc64/kernel/sys32.S
+++ b/arch/sparc64/kernel/sys32.S
@@ -157,173 +157,199 @@ sys32_socketcall: /* %o0=call, %o1=args */
157 or %g2, %lo(__socketcall_table_begin), %g2 157 or %g2, %lo(__socketcall_table_begin), %g2
158 jmpl %g2 + %o0, %g0 158 jmpl %g2 + %o0, %g0
159 nop 159 nop
160do_einval:
161 retl
162 mov -EINVAL, %o0
160 163
161 /* Each entry is exactly 32 bytes. */
162 .align 32 164 .align 32
163__socketcall_table_begin: 165__socketcall_table_begin:
166
167 /* Each entry is exactly 32 bytes. */
164do_sys_socket: /* sys_socket(int, int, int) */ 168do_sys_socket: /* sys_socket(int, int, int) */
165 ldswa [%o1 + 0x0] %asi, %o0 1691: ldswa [%o1 + 0x0] %asi, %o0
166 sethi %hi(sys_socket), %g1 170 sethi %hi(sys_socket), %g1
167 ldswa [%o1 + 0x8] %asi, %o2 1712: ldswa [%o1 + 0x8] %asi, %o2
168 jmpl %g1 + %lo(sys_socket), %g0 172 jmpl %g1 + %lo(sys_socket), %g0
169 ldswa [%o1 + 0x4] %asi, %o1 1733: ldswa [%o1 + 0x4] %asi, %o1
170 nop 174 nop
171 nop 175 nop
172 nop 176 nop
173do_sys_bind: /* sys_bind(int fd, struct sockaddr *, int) */ 177do_sys_bind: /* sys_bind(int fd, struct sockaddr *, int) */
174 ldswa [%o1 + 0x0] %asi, %o0 1784: ldswa [%o1 + 0x0] %asi, %o0
175 sethi %hi(sys_bind), %g1 179 sethi %hi(sys_bind), %g1
176 ldswa [%o1 + 0x8] %asi, %o2 1805: ldswa [%o1 + 0x8] %asi, %o2
177 jmpl %g1 + %lo(sys_bind), %g0 181 jmpl %g1 + %lo(sys_bind), %g0
178 lduwa [%o1 + 0x4] %asi, %o1 1826: lduwa [%o1 + 0x4] %asi, %o1
179 nop 183 nop
180 nop 184 nop
181 nop 185 nop
182do_sys_connect: /* sys_connect(int, struct sockaddr *, int) */ 186do_sys_connect: /* sys_connect(int, struct sockaddr *, int) */
183 ldswa [%o1 + 0x0] %asi, %o0 1877: ldswa [%o1 + 0x0] %asi, %o0
184 sethi %hi(sys_connect), %g1 188 sethi %hi(sys_connect), %g1
185 ldswa [%o1 + 0x8] %asi, %o2 1898: ldswa [%o1 + 0x8] %asi, %o2
186 jmpl %g1 + %lo(sys_connect), %g0 190 jmpl %g1 + %lo(sys_connect), %g0
187 lduwa [%o1 + 0x4] %asi, %o1 1919: lduwa [%o1 + 0x4] %asi, %o1
188 nop 192 nop
189 nop 193 nop
190 nop 194 nop
191do_sys_listen: /* sys_listen(int, int) */ 195do_sys_listen: /* sys_listen(int, int) */
192 ldswa [%o1 + 0x0] %asi, %o0 19610: ldswa [%o1 + 0x0] %asi, %o0
193 sethi %hi(sys_listen), %g1 197 sethi %hi(sys_listen), %g1
194 jmpl %g1 + %lo(sys_listen), %g0 198 jmpl %g1 + %lo(sys_listen), %g0
195 ldswa [%o1 + 0x4] %asi, %o1 19911: ldswa [%o1 + 0x4] %asi, %o1
196 nop 200 nop
197 nop 201 nop
198 nop 202 nop
199 nop 203 nop
200do_sys_accept: /* sys_accept(int, struct sockaddr *, int *) */ 204do_sys_accept: /* sys_accept(int, struct sockaddr *, int *) */
201 ldswa [%o1 + 0x0] %asi, %o0 20512: ldswa [%o1 + 0x0] %asi, %o0
202 sethi %hi(sys_accept), %g1 206 sethi %hi(sys_accept), %g1
203 lduwa [%o1 + 0x8] %asi, %o2 20713: lduwa [%o1 + 0x8] %asi, %o2
204 jmpl %g1 + %lo(sys_accept), %g0 208 jmpl %g1 + %lo(sys_accept), %g0
205 lduwa [%o1 + 0x4] %asi, %o1 20914: lduwa [%o1 + 0x4] %asi, %o1
206 nop 210 nop
207 nop 211 nop
208 nop 212 nop
209do_sys_getsockname: /* sys_getsockname(int, struct sockaddr *, int *) */ 213do_sys_getsockname: /* sys_getsockname(int, struct sockaddr *, int *) */
210 ldswa [%o1 + 0x0] %asi, %o0 21415: ldswa [%o1 + 0x0] %asi, %o0
211 sethi %hi(sys_getsockname), %g1 215 sethi %hi(sys_getsockname), %g1
212 lduwa [%o1 + 0x8] %asi, %o2 21616: lduwa [%o1 + 0x8] %asi, %o2
213 jmpl %g1 + %lo(sys_getsockname), %g0 217 jmpl %g1 + %lo(sys_getsockname), %g0
214 lduwa [%o1 + 0x4] %asi, %o1 21817: lduwa [%o1 + 0x4] %asi, %o1
215 nop 219 nop
216 nop 220 nop
217 nop 221 nop
218do_sys_getpeername: /* sys_getpeername(int, struct sockaddr *, int *) */ 222do_sys_getpeername: /* sys_getpeername(int, struct sockaddr *, int *) */
219 ldswa [%o1 + 0x0] %asi, %o0 22318: ldswa [%o1 + 0x0] %asi, %o0
220 sethi %hi(sys_getpeername), %g1 224 sethi %hi(sys_getpeername), %g1
221 lduwa [%o1 + 0x8] %asi, %o2 22519: lduwa [%o1 + 0x8] %asi, %o2
222 jmpl %g1 + %lo(sys_getpeername), %g0 226 jmpl %g1 + %lo(sys_getpeername), %g0
223 lduwa [%o1 + 0x4] %asi, %o1 22720: lduwa [%o1 + 0x4] %asi, %o1
224 nop 228 nop
225 nop 229 nop
226 nop 230 nop
227do_sys_socketpair: /* sys_socketpair(int, int, int, int *) */ 231do_sys_socketpair: /* sys_socketpair(int, int, int, int *) */
228 ldswa [%o1 + 0x0] %asi, %o0 23221: ldswa [%o1 + 0x0] %asi, %o0
229 sethi %hi(sys_socketpair), %g1 233 sethi %hi(sys_socketpair), %g1
230 ldswa [%o1 + 0x8] %asi, %o2 23422: ldswa [%o1 + 0x8] %asi, %o2
231 lduwa [%o1 + 0xc] %asi, %o3 23523: lduwa [%o1 + 0xc] %asi, %o3
232 jmpl %g1 + %lo(sys_socketpair), %g0 236 jmpl %g1 + %lo(sys_socketpair), %g0
233 ldswa [%o1 + 0x4] %asi, %o1 23724: ldswa [%o1 + 0x4] %asi, %o1
234 nop 238 nop
235 nop 239 nop
236do_sys_send: /* sys_send(int, void *, size_t, unsigned int) */ 240do_sys_send: /* sys_send(int, void *, size_t, unsigned int) */
237 ldswa [%o1 + 0x0] %asi, %o0 24125: ldswa [%o1 + 0x0] %asi, %o0
238 sethi %hi(sys_send), %g1 242 sethi %hi(sys_send), %g1
239 lduwa [%o1 + 0x8] %asi, %o2 24326: lduwa [%o1 + 0x8] %asi, %o2
240 lduwa [%o1 + 0xc] %asi, %o3 24427: lduwa [%o1 + 0xc] %asi, %o3
241 jmpl %g1 + %lo(sys_send), %g0 245 jmpl %g1 + %lo(sys_send), %g0
242 lduwa [%o1 + 0x4] %asi, %o1 24628: lduwa [%o1 + 0x4] %asi, %o1
243 nop 247 nop
244 nop 248 nop
245do_sys_recv: /* sys_recv(int, void *, size_t, unsigned int) */ 249do_sys_recv: /* sys_recv(int, void *, size_t, unsigned int) */
246 ldswa [%o1 + 0x0] %asi, %o0 25029: ldswa [%o1 + 0x0] %asi, %o0
247 sethi %hi(sys_recv), %g1 251 sethi %hi(sys_recv), %g1
248 lduwa [%o1 + 0x8] %asi, %o2 25230: lduwa [%o1 + 0x8] %asi, %o2
249 lduwa [%o1 + 0xc] %asi, %o3 25331: lduwa [%o1 + 0xc] %asi, %o3
250 jmpl %g1 + %lo(sys_recv), %g0 254 jmpl %g1 + %lo(sys_recv), %g0
251 lduwa [%o1 + 0x4] %asi, %o1 25532: lduwa [%o1 + 0x4] %asi, %o1
252 nop 256 nop
253 nop 257 nop
254do_sys_sendto: /* sys_sendto(int, u32, compat_size_t, unsigned int, u32, int) */ 258do_sys_sendto: /* sys_sendto(int, u32, compat_size_t, unsigned int, u32, int) */
255 ldswa [%o1 + 0x0] %asi, %o0 25933: ldswa [%o1 + 0x0] %asi, %o0
256 sethi %hi(sys_sendto), %g1 260 sethi %hi(sys_sendto), %g1
257 lduwa [%o1 + 0x8] %asi, %o2 26134: lduwa [%o1 + 0x8] %asi, %o2
258 lduwa [%o1 + 0xc] %asi, %o3 26235: lduwa [%o1 + 0xc] %asi, %o3
259 lduwa [%o1 + 0x10] %asi, %o4 26336: lduwa [%o1 + 0x10] %asi, %o4
260 ldswa [%o1 + 0x14] %asi, %o5 26437: ldswa [%o1 + 0x14] %asi, %o5
261 jmpl %g1 + %lo(sys_sendto), %g0 265 jmpl %g1 + %lo(sys_sendto), %g0
262 lduwa [%o1 + 0x4] %asi, %o1 26638: lduwa [%o1 + 0x4] %asi, %o1
263do_sys_recvfrom: /* sys_recvfrom(int, u32, compat_size_t, unsigned int, u32, u32) */ 267do_sys_recvfrom: /* sys_recvfrom(int, u32, compat_size_t, unsigned int, u32, u32) */
264 ldswa [%o1 + 0x0] %asi, %o0 26839: ldswa [%o1 + 0x0] %asi, %o0
265 sethi %hi(sys_recvfrom), %g1 269 sethi %hi(sys_recvfrom), %g1
266 lduwa [%o1 + 0x8] %asi, %o2 27040: lduwa [%o1 + 0x8] %asi, %o2
267 lduwa [%o1 + 0xc] %asi, %o3 27141: lduwa [%o1 + 0xc] %asi, %o3
268 lduwa [%o1 + 0x10] %asi, %o4 27242: lduwa [%o1 + 0x10] %asi, %o4
269 lduwa [%o1 + 0x14] %asi, %o5 27343: lduwa [%o1 + 0x14] %asi, %o5
270 jmpl %g1 + %lo(sys_recvfrom), %g0 274 jmpl %g1 + %lo(sys_recvfrom), %g0
271 lduwa [%o1 + 0x4] %asi, %o1 27544: lduwa [%o1 + 0x4] %asi, %o1
272do_sys_shutdown: /* sys_shutdown(int, int) */ 276do_sys_shutdown: /* sys_shutdown(int, int) */
273 ldswa [%o1 + 0x0] %asi, %o0 27745: ldswa [%o1 + 0x0] %asi, %o0
274 sethi %hi(sys_shutdown), %g1 278 sethi %hi(sys_shutdown), %g1
275 jmpl %g1 + %lo(sys_shutdown), %g0 279 jmpl %g1 + %lo(sys_shutdown), %g0
276 ldswa [%o1 + 0x4] %asi, %o1 28046: ldswa [%o1 + 0x4] %asi, %o1
277 nop 281 nop
278 nop 282 nop
279 nop 283 nop
280 nop 284 nop
281do_sys_setsockopt: /* compat_sys_setsockopt(int, int, int, char *, int) */ 285do_sys_setsockopt: /* compat_sys_setsockopt(int, int, int, char *, int) */
282 ldswa [%o1 + 0x0] %asi, %o0 28647: ldswa [%o1 + 0x0] %asi, %o0
283 sethi %hi(compat_sys_setsockopt), %g1 287 sethi %hi(compat_sys_setsockopt), %g1
284 ldswa [%o1 + 0x8] %asi, %o2 28848: ldswa [%o1 + 0x8] %asi, %o2
285 lduwa [%o1 + 0xc] %asi, %o3 28949: lduwa [%o1 + 0xc] %asi, %o3
286 ldswa [%o1 + 0x10] %asi, %o4 29050: ldswa [%o1 + 0x10] %asi, %o4
287 jmpl %g1 + %lo(compat_sys_setsockopt), %g0 291 jmpl %g1 + %lo(compat_sys_setsockopt), %g0
288 ldswa [%o1 + 0x4] %asi, %o1 29251: ldswa [%o1 + 0x4] %asi, %o1
289 nop 293 nop
290do_sys_getsockopt: /* compat_sys_getsockopt(int, int, int, u32, u32) */ 294do_sys_getsockopt: /* compat_sys_getsockopt(int, int, int, u32, u32) */
291 ldswa [%o1 + 0x0] %asi, %o0 29552: ldswa [%o1 + 0x0] %asi, %o0
292 sethi %hi(compat_sys_getsockopt), %g1 296 sethi %hi(compat_sys_getsockopt), %g1
293 ldswa [%o1 + 0x8] %asi, %o2 29753: ldswa [%o1 + 0x8] %asi, %o2
294 lduwa [%o1 + 0xc] %asi, %o3 29854: lduwa [%o1 + 0xc] %asi, %o3
295 lduwa [%o1 + 0x10] %asi, %o4 29955: lduwa [%o1 + 0x10] %asi, %o4
296 jmpl %g1 + %lo(compat_sys_getsockopt), %g0 300 jmpl %g1 + %lo(compat_sys_getsockopt), %g0
297 ldswa [%o1 + 0x4] %asi, %o1 30156: ldswa [%o1 + 0x4] %asi, %o1
298 nop 302 nop
299do_sys_sendmsg: /* compat_sys_sendmsg(int, struct compat_msghdr *, unsigned int) */ 303do_sys_sendmsg: /* compat_sys_sendmsg(int, struct compat_msghdr *, unsigned int) */
300 ldswa [%o1 + 0x0] %asi, %o0 30457: ldswa [%o1 + 0x0] %asi, %o0
301 sethi %hi(compat_sys_sendmsg), %g1 305 sethi %hi(compat_sys_sendmsg), %g1
302 lduwa [%o1 + 0x8] %asi, %o2 30658: lduwa [%o1 + 0x8] %asi, %o2
303 jmpl %g1 + %lo(compat_sys_sendmsg), %g0 307 jmpl %g1 + %lo(compat_sys_sendmsg), %g0
304 lduwa [%o1 + 0x4] %asi, %o1 30859: lduwa [%o1 + 0x4] %asi, %o1
305 nop 309 nop
306 nop 310 nop
307 nop 311 nop
308do_sys_recvmsg: /* compat_sys_recvmsg(int, struct compat_msghdr *, unsigned int) */ 312do_sys_recvmsg: /* compat_sys_recvmsg(int, struct compat_msghdr *, unsigned int) */
309 ldswa [%o1 + 0x0] %asi, %o0 31360: ldswa [%o1 + 0x0] %asi, %o0
310 sethi %hi(compat_sys_recvmsg), %g1 314 sethi %hi(compat_sys_recvmsg), %g1
311 lduwa [%o1 + 0x8] %asi, %o2 31561: lduwa [%o1 + 0x8] %asi, %o2
312 jmpl %g1 + %lo(compat_sys_recvmsg), %g0 316 jmpl %g1 + %lo(compat_sys_recvmsg), %g0
313 lduwa [%o1 + 0x4] %asi, %o1 31762: lduwa [%o1 + 0x4] %asi, %o1
314 nop 318 nop
315 nop 319 nop
316 nop 320 nop
317__socketcall_table_end:
318
319do_einval:
320 retl
321 mov -EINVAL, %o0
322do_efault:
323 retl
324 mov -EFAULT, %o0
325 321
326 .section __ex_table 322 .section __ex_table
327 .align 4 323 .align 4
328 .word __socketcall_table_begin, 0, __socketcall_table_end, do_efault 324 .word 1b, __retl_efault, 2b, __retl_efault
325 .word 3b, __retl_efault, 4b, __retl_efault
326 .word 5b, __retl_efault, 6b, __retl_efault
327 .word 7b, __retl_efault, 8b, __retl_efault
328 .word 9b, __retl_efault, 10b, __retl_efault
329 .word 11b, __retl_efault, 12b, __retl_efault
330 .word 13b, __retl_efault, 14b, __retl_efault
331 .word 15b, __retl_efault, 16b, __retl_efault
332 .word 17b, __retl_efault, 18b, __retl_efault
333 .word 19b, __retl_efault, 20b, __retl_efault
334 .word 21b, __retl_efault, 22b, __retl_efault
335 .word 23b, __retl_efault, 24b, __retl_efault
336 .word 25b, __retl_efault, 26b, __retl_efault
337 .word 27b, __retl_efault, 28b, __retl_efault
338 .word 29b, __retl_efault, 30b, __retl_efault
339 .word 31b, __retl_efault, 32b, __retl_efault
340 .word 33b, __retl_efault, 34b, __retl_efault
341 .word 35b, __retl_efault, 36b, __retl_efault
342 .word 37b, __retl_efault, 38b, __retl_efault
343 .word 39b, __retl_efault, 40b, __retl_efault
344 .word 41b, __retl_efault, 42b, __retl_efault
345 .word 43b, __retl_efault, 44b, __retl_efault
346 .word 45b, __retl_efault, 46b, __retl_efault
347 .word 47b, __retl_efault, 48b, __retl_efault
348 .word 49b, __retl_efault, 50b, __retl_efault
349 .word 51b, __retl_efault, 52b, __retl_efault
350 .word 53b, __retl_efault, 54b, __retl_efault
351 .word 55b, __retl_efault, 56b, __retl_efault
352 .word 57b, __retl_efault, 58b, __retl_efault
353 .word 59b, __retl_efault, 60b, __retl_efault
354 .word 61b, __retl_efault, 62b, __retl_efault
329 .previous 355 .previous
diff --git a/arch/sparc64/kernel/trampoline.S b/arch/sparc64/kernel/trampoline.S
index 89f2fcfcd662..9478551cb020 100644
--- a/arch/sparc64/kernel/trampoline.S
+++ b/arch/sparc64/kernel/trampoline.S
@@ -336,20 +336,13 @@ do_unlock:
336 call init_irqwork_curcpu 336 call init_irqwork_curcpu
337 nop 337 nop
338 338
339 BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g2,g3,1f) 339 /* Start using proper page size encodings in ctx register. */
340 ba,pt %xcc, 2f 340 sethi %hi(sparc64_kern_pri_context), %g3
341 nop 341 ldx [%g3 + %lo(sparc64_kern_pri_context)], %g2
342
3431: /* Start using proper page size encodings in ctx register. */
344 sethi %uhi(CTX_CHEETAH_PLUS_NUC), %g3
345 mov PRIMARY_CONTEXT, %g1 342 mov PRIMARY_CONTEXT, %g1
346 sllx %g3, 32, %g3 343 stxa %g2, [%g1] ASI_DMMU
347 sethi %hi(CTX_CHEETAH_PLUS_CTX0), %g2
348 or %g3, %g2, %g3
349 stxa %g3, [%g1] ASI_DMMU
350 membar #Sync 344 membar #Sync
351 345
3522:
353 rdpr %pstate, %o1 346 rdpr %pstate, %o1
354 or %o1, PSTATE_IE, %o1 347 or %o1, PSTATE_IE, %o1
355 wrpr %o1, 0, %pstate 348 wrpr %o1, 0, %pstate
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index f8e7005fede9..5570e7bb22bb 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -189,19 +189,18 @@ void spitfire_data_access_exception(struct pt_regs *regs, unsigned long sfsr, un
189 189
190 if (regs->tstate & TSTATE_PRIV) { 190 if (regs->tstate & TSTATE_PRIV) {
191 /* Test if this comes from uaccess places. */ 191 /* Test if this comes from uaccess places. */
192 unsigned long fixup; 192 const struct exception_table_entry *entry;
193 unsigned long g2 = regs->u_regs[UREG_G2];
194 193
195 if ((fixup = search_extables_range(regs->tpc, &g2))) { 194 entry = search_exception_tables(regs->tpc);
196 /* Ouch, somebody is trying ugly VM hole tricks on us... */ 195 if (entry) {
196 /* Ouch, somebody is trying VM hole tricks on us... */
197#ifdef DEBUG_EXCEPTIONS 197#ifdef DEBUG_EXCEPTIONS
198 printk("Exception: PC<%016lx> faddr<UNKNOWN>\n", regs->tpc); 198 printk("Exception: PC<%016lx> faddr<UNKNOWN>\n", regs->tpc);
199 printk("EX_TABLE: insn<%016lx> fixup<%016lx> " 199 printk("EX_TABLE: insn<%016lx> fixup<%016lx>\n",
200 "g2<%016lx>\n", regs->tpc, fixup, g2); 200 regs->tpc, entry->fixup);
201#endif 201#endif
202 regs->tpc = fixup; 202 regs->tpc = entry->fixup;
203 regs->tnpc = regs->tpc + 4; 203 regs->tnpc = regs->tpc + 4;
204 regs->u_regs[UREG_G2] = g2;
205 return; 204 return;
206 } 205 }
207 /* Shit... */ 206 /* Shit... */
@@ -758,26 +757,12 @@ void __init cheetah_ecache_flush_init(void)
758 ecache_flush_size = (2 * largest_size); 757 ecache_flush_size = (2 * largest_size);
759 ecache_flush_linesize = smallest_linesize; 758 ecache_flush_linesize = smallest_linesize;
760 759
761 /* Discover a physically contiguous chunk of physical 760 ecache_flush_physbase = find_ecache_flush_span(ecache_flush_size);
762 * memory in 'sp_banks' of size ecache_flush_size calculated
763 * above. Store the physical base of this area at
764 * ecache_flush_physbase.
765 */
766 for (node = 0; ; node++) {
767 if (sp_banks[node].num_bytes == 0)
768 break;
769 if (sp_banks[node].num_bytes >= ecache_flush_size) {
770 ecache_flush_physbase = sp_banks[node].base_addr;
771 break;
772 }
773 }
774 761
775 /* Note: Zero would be a valid value of ecache_flush_physbase so 762 if (ecache_flush_physbase == ~0UL) {
776 * don't use that as the success test. :-)
777 */
778 if (sp_banks[node].num_bytes == 0) {
779 prom_printf("cheetah_ecache_flush_init: Cannot find %d byte " 763 prom_printf("cheetah_ecache_flush_init: Cannot find %d byte "
780 "contiguous physical memory.\n", ecache_flush_size); 764 "contiguous physical memory.\n",
765 ecache_flush_size);
781 prom_halt(); 766 prom_halt();
782 } 767 }
783 768
@@ -1346,16 +1331,12 @@ static int cheetah_fix_ce(unsigned long physaddr)
1346/* Return non-zero if PADDR is a valid physical memory address. */ 1331/* Return non-zero if PADDR is a valid physical memory address. */
1347static int cheetah_check_main_memory(unsigned long paddr) 1332static int cheetah_check_main_memory(unsigned long paddr)
1348{ 1333{
1349 int i; 1334 unsigned long vaddr = PAGE_OFFSET + paddr;
1350 1335
1351 for (i = 0; ; i++) { 1336 if (vaddr > (unsigned long) high_memory)
1352 if (sp_banks[i].num_bytes == 0) 1337 return 0;
1353 break; 1338
1354 if (paddr >= sp_banks[i].base_addr && 1339 return kern_addr_valid(vaddr);
1355 paddr < (sp_banks[i].base_addr + sp_banks[i].num_bytes))
1356 return 1;
1357 }
1358 return 0;
1359} 1340}
1360 1341
1361void cheetah_cee_handler(struct pt_regs *regs, unsigned long afsr, unsigned long afar) 1342void cheetah_cee_handler(struct pt_regs *regs, unsigned long afsr, unsigned long afar)
@@ -1610,10 +1591,10 @@ void cheetah_deferred_handler(struct pt_regs *regs, unsigned long afsr, unsigned
1610 /* OK, usermode access. */ 1591 /* OK, usermode access. */
1611 recoverable = 1; 1592 recoverable = 1;
1612 } else { 1593 } else {
1613 unsigned long g2 = regs->u_regs[UREG_G2]; 1594 const struct exception_table_entry *entry;
1614 unsigned long fixup = search_extables_range(regs->tpc, &g2);
1615 1595
1616 if (fixup != 0UL) { 1596 entry = search_exception_tables(regs->tpc);
1597 if (entry) {
1617 /* OK, kernel access to userspace. */ 1598 /* OK, kernel access to userspace. */
1618 recoverable = 1; 1599 recoverable = 1;
1619 1600
@@ -1632,9 +1613,8 @@ void cheetah_deferred_handler(struct pt_regs *regs, unsigned long afsr, unsigned
1632 * recoverable condition. 1613 * recoverable condition.
1633 */ 1614 */
1634 if (recoverable) { 1615 if (recoverable) {
1635 regs->tpc = fixup; 1616 regs->tpc = entry->fixup;
1636 regs->tnpc = regs->tpc + 4; 1617 regs->tnpc = regs->tpc + 4;
1637 regs->u_regs[UREG_G2] = g2;
1638 } 1618 }
1639 } 1619 }
1640 } 1620 }
diff --git a/arch/sparc64/kernel/una_asm.S b/arch/sparc64/kernel/una_asm.S
index da48400bcc95..1f5b5b708ce7 100644
--- a/arch/sparc64/kernel/una_asm.S
+++ b/arch/sparc64/kernel/una_asm.S
@@ -6,13 +6,6 @@
6 6
7 .text 7 .text
8 8
9kernel_unaligned_trap_fault:
10 call kernel_mna_trap_fault
11 nop
12 retl
13 nop
14 .size kern_unaligned_trap_fault, .-kern_unaligned_trap_fault
15
16 .globl __do_int_store 9 .globl __do_int_store
17__do_int_store: 10__do_int_store:
18 rd %asi, %o4 11 rd %asi, %o4
@@ -51,24 +44,24 @@ __do_int_store:
510: 440:
52 wr %o4, 0x0, %asi 45 wr %o4, 0x0, %asi
53 retl 46 retl
54 nop 47 mov 0, %o0
55 .size __do_int_store, .-__do_int_store 48 .size __do_int_store, .-__do_int_store
56 49
57 .section __ex_table 50 .section __ex_table
58 .word 4b, kernel_unaligned_trap_fault 51 .word 4b, __retl_efault
59 .word 5b, kernel_unaligned_trap_fault 52 .word 5b, __retl_efault
60 .word 6b, kernel_unaligned_trap_fault 53 .word 6b, __retl_efault
61 .word 7b, kernel_unaligned_trap_fault 54 .word 7b, __retl_efault
62 .word 8b, kernel_unaligned_trap_fault 55 .word 8b, __retl_efault
63 .word 9b, kernel_unaligned_trap_fault 56 .word 9b, __retl_efault
64 .word 10b, kernel_unaligned_trap_fault 57 .word 10b, __retl_efault
65 .word 11b, kernel_unaligned_trap_fault 58 .word 11b, __retl_efault
66 .word 12b, kernel_unaligned_trap_fault 59 .word 12b, __retl_efault
67 .word 13b, kernel_unaligned_trap_fault 60 .word 13b, __retl_efault
68 .word 14b, kernel_unaligned_trap_fault 61 .word 14b, __retl_efault
69 .word 15b, kernel_unaligned_trap_fault 62 .word 15b, __retl_efault
70 .word 16b, kernel_unaligned_trap_fault 63 .word 16b, __retl_efault
71 .word 17b, kernel_unaligned_trap_fault 64 .word 17b, __retl_efault
72 .previous 65 .previous
73 66
74 .globl do_int_load 67 .globl do_int_load
@@ -133,21 +126,21 @@ do_int_load:
1330: 1260:
134 wr %o5, 0x0, %asi 127 wr %o5, 0x0, %asi
135 retl 128 retl
136 nop 129 mov 0, %o0
137 .size __do_int_load, .-__do_int_load 130 .size __do_int_load, .-__do_int_load
138 131
139 .section __ex_table 132 .section __ex_table
140 .word 4b, kernel_unaligned_trap_fault 133 .word 4b, __retl_efault
141 .word 5b, kernel_unaligned_trap_fault 134 .word 5b, __retl_efault
142 .word 6b, kernel_unaligned_trap_fault 135 .word 6b, __retl_efault
143 .word 7b, kernel_unaligned_trap_fault 136 .word 7b, __retl_efault
144 .word 8b, kernel_unaligned_trap_fault 137 .word 8b, __retl_efault
145 .word 9b, kernel_unaligned_trap_fault 138 .word 9b, __retl_efault
146 .word 10b, kernel_unaligned_trap_fault 139 .word 10b, __retl_efault
147 .word 11b, kernel_unaligned_trap_fault 140 .word 11b, __retl_efault
148 .word 12b, kernel_unaligned_trap_fault 141 .word 12b, __retl_efault
149 .word 13b, kernel_unaligned_trap_fault 142 .word 13b, __retl_efault
150 .word 14b, kernel_unaligned_trap_fault 143 .word 14b, __retl_efault
151 .word 15b, kernel_unaligned_trap_fault 144 .word 15b, __retl_efault
152 .word 16b, kernel_unaligned_trap_fault 145 .word 16b, __retl_efault
153 .previous 146 .previous
diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c
index 42718f6a7d36..70faf630603b 100644
--- a/arch/sparc64/kernel/unaligned.c
+++ b/arch/sparc64/kernel/unaligned.c
@@ -180,14 +180,14 @@ static void __attribute_used__ unaligned_panic(char *str, struct pt_regs *regs)
180 die_if_kernel(str, regs); 180 die_if_kernel(str, regs);
181} 181}
182 182
183extern void do_int_load(unsigned long *dest_reg, int size, 183extern int do_int_load(unsigned long *dest_reg, int size,
184 unsigned long *saddr, int is_signed, int asi); 184 unsigned long *saddr, int is_signed, int asi);
185 185
186extern void __do_int_store(unsigned long *dst_addr, int size, 186extern int __do_int_store(unsigned long *dst_addr, int size,
187 unsigned long src_val, int asi); 187 unsigned long src_val, int asi);
188 188
189static inline void do_int_store(int reg_num, int size, unsigned long *dst_addr, 189static inline int do_int_store(int reg_num, int size, unsigned long *dst_addr,
190 struct pt_regs *regs, int asi, int orig_asi) 190 struct pt_regs *regs, int asi, int orig_asi)
191{ 191{
192 unsigned long zero = 0; 192 unsigned long zero = 0;
193 unsigned long *src_val_p = &zero; 193 unsigned long *src_val_p = &zero;
@@ -219,7 +219,7 @@ static inline void do_int_store(int reg_num, int size, unsigned long *dst_addr,
219 break; 219 break;
220 }; 220 };
221 } 221 }
222 __do_int_store(dst_addr, size, src_val, asi); 222 return __do_int_store(dst_addr, size, src_val, asi);
223} 223}
224 224
225static inline void advance(struct pt_regs *regs) 225static inline void advance(struct pt_regs *regs)
@@ -242,14 +242,14 @@ static inline int ok_for_kernel(unsigned int insn)
242 return !floating_point_load_or_store_p(insn); 242 return !floating_point_load_or_store_p(insn);
243} 243}
244 244
245void kernel_mna_trap_fault(void) 245static void kernel_mna_trap_fault(void)
246{ 246{
247 struct pt_regs *regs = current_thread_info()->kern_una_regs; 247 struct pt_regs *regs = current_thread_info()->kern_una_regs;
248 unsigned int insn = current_thread_info()->kern_una_insn; 248 unsigned int insn = current_thread_info()->kern_una_insn;
249 unsigned long g2 = regs->u_regs[UREG_G2]; 249 const struct exception_table_entry *entry;
250 unsigned long fixup = search_extables_range(regs->tpc, &g2);
251 250
252 if (!fixup) { 251 entry = search_exception_tables(regs->tpc);
252 if (!entry) {
253 unsigned long address; 253 unsigned long address;
254 254
255 address = compute_effective_address(regs, insn, 255 address = compute_effective_address(regs, insn,
@@ -270,9 +270,8 @@ void kernel_mna_trap_fault(void)
270 die_if_kernel("Oops", regs); 270 die_if_kernel("Oops", regs);
271 /* Not reached */ 271 /* Not reached */
272 } 272 }
273 regs->tpc = fixup; 273 regs->tpc = entry->fixup;
274 regs->tnpc = regs->tpc + 4; 274 regs->tnpc = regs->tpc + 4;
275 regs->u_regs [UREG_G2] = g2;
276 275
277 regs->tstate &= ~TSTATE_ASI; 276 regs->tstate &= ~TSTATE_ASI;
278 regs->tstate |= (ASI_AIUS << 24UL); 277 regs->tstate |= (ASI_AIUS << 24UL);
@@ -294,8 +293,8 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u
294 293
295 kernel_mna_trap_fault(); 294 kernel_mna_trap_fault();
296 } else { 295 } else {
297 unsigned long addr; 296 unsigned long addr, *reg_addr;
298 int orig_asi, asi; 297 int orig_asi, asi, err;
299 298
300 addr = compute_effective_address(regs, insn, 299 addr = compute_effective_address(regs, insn,
301 ((insn >> 25) & 0x1f)); 300 ((insn >> 25) & 0x1f));
@@ -319,11 +318,12 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u
319 }; 318 };
320 switch (dir) { 319 switch (dir) {
321 case load: 320 case load:
322 do_int_load(fetch_reg_addr(((insn>>25)&0x1f), regs), 321 reg_addr = fetch_reg_addr(((insn>>25)&0x1f), regs);
323 size, (unsigned long *) addr, 322 err = do_int_load(reg_addr, size,
324 decode_signedness(insn), asi); 323 (unsigned long *) addr,
325 if (unlikely(asi != orig_asi)) { 324 decode_signedness(insn), asi);
326 unsigned long val_in = *(unsigned long *) addr; 325 if (likely(!err) && unlikely(asi != orig_asi)) {
326 unsigned long val_in = *reg_addr;
327 switch (size) { 327 switch (size) {
328 case 2: 328 case 2:
329 val_in = swab16(val_in); 329 val_in = swab16(val_in);
@@ -339,21 +339,24 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u
339 BUG(); 339 BUG();
340 break; 340 break;
341 }; 341 };
342 *(unsigned long *) addr = val_in; 342 *reg_addr = val_in;
343 } 343 }
344 break; 344 break;
345 345
346 case store: 346 case store:
347 do_int_store(((insn>>25)&0x1f), size, 347 err = do_int_store(((insn>>25)&0x1f), size,
348 (unsigned long *) addr, regs, 348 (unsigned long *) addr, regs,
349 asi, orig_asi); 349 asi, orig_asi);
350 break; 350 break;
351 351
352 default: 352 default:
353 panic("Impossible kernel unaligned trap."); 353 panic("Impossible kernel unaligned trap.");
354 /* Not reached... */ 354 /* Not reached... */
355 } 355 }
356 advance(regs); 356 if (unlikely(err))
357 kernel_mna_trap_fault();
358 else
359 advance(regs);
357 } 360 }
358} 361}
359 362
diff --git a/arch/sparc64/kernel/us3_cpufreq.c b/arch/sparc64/kernel/us3_cpufreq.c
index 9080e7cd4bb0..0340041f6143 100644
--- a/arch/sparc64/kernel/us3_cpufreq.c
+++ b/arch/sparc64/kernel/us3_cpufreq.c
@@ -208,7 +208,10 @@ static int __init us3_freq_init(void)
208 impl = ((ver >> 32) & 0xffff); 208 impl = ((ver >> 32) & 0xffff);
209 209
210 if (manuf == CHEETAH_MANUF && 210 if (manuf == CHEETAH_MANUF &&
211 (impl == CHEETAH_IMPL || impl == CHEETAH_PLUS_IMPL)) { 211 (impl == CHEETAH_IMPL ||
212 impl == CHEETAH_PLUS_IMPL ||
213 impl == JAGUAR_IMPL ||
214 impl == PANTHER_IMPL)) {
212 struct cpufreq_driver *driver; 215 struct cpufreq_driver *driver;
213 216
214 ret = -ENOMEM; 217 ret = -ENOMEM;
diff --git a/arch/sparc64/kernel/winfixup.S b/arch/sparc64/kernel/winfixup.S
index 99c809a1e5ac..39160926267b 100644
--- a/arch/sparc64/kernel/winfixup.S
+++ b/arch/sparc64/kernel/winfixup.S
@@ -16,23 +16,14 @@
16 .text 16 .text
17 17
18set_pcontext: 18set_pcontext:
19cplus_winfixup_insn_1: 19 sethi %hi(sparc64_kern_pri_context), %l1
20 sethi %hi(0), %l1 20 ldx [%l1 + %lo(sparc64_kern_pri_context)], %l1
21 mov PRIMARY_CONTEXT, %g1 21 mov PRIMARY_CONTEXT, %g1
22 sllx %l1, 32, %l1
23cplus_winfixup_insn_2:
24 sethi %hi(0), %g2
25 or %l1, %g2, %l1
26 stxa %l1, [%g1] ASI_DMMU 22 stxa %l1, [%g1] ASI_DMMU
27 flush %g6 23 flush %g6
28 retl 24 retl
29 nop 25 nop
30 26
31cplus_wfinsn_1:
32 sethi %uhi(CTX_CHEETAH_PLUS_NUC), %l1
33cplus_wfinsn_2:
34 sethi %hi(CTX_CHEETAH_PLUS_CTX0), %g2
35
36 .align 32 27 .align 32
37 28
38 /* Here are the rules, pay attention. 29 /* Here are the rules, pay attention.
@@ -395,23 +386,3 @@ window_dax_from_user_common:
395 add %sp, PTREGS_OFF, %o0 386 add %sp, PTREGS_OFF, %o0
396 ba,pt %xcc, rtrap 387 ba,pt %xcc, rtrap
397 clr %l6 388 clr %l6
398
399
400 .globl cheetah_plus_patch_winfixup
401cheetah_plus_patch_winfixup:
402 sethi %hi(cplus_wfinsn_1), %o0
403 sethi %hi(cplus_winfixup_insn_1), %o2
404 lduw [%o0 + %lo(cplus_wfinsn_1)], %o1
405 or %o2, %lo(cplus_winfixup_insn_1), %o2
406 stw %o1, [%o2]
407 flush %o2
408
409 sethi %hi(cplus_wfinsn_2), %o0
410 sethi %hi(cplus_winfixup_insn_2), %o2
411 lduw [%o0 + %lo(cplus_wfinsn_2)], %o1
412 or %o2, %lo(cplus_winfixup_insn_2), %o2
413 stw %o1, [%o2]
414 flush %o2
415
416 retl
417 nop
diff --git a/arch/sparc64/lib/VISsave.S b/arch/sparc64/lib/VISsave.S
index 4e18989bd602..a0ded5c5aa5c 100644
--- a/arch/sparc64/lib/VISsave.S
+++ b/arch/sparc64/lib/VISsave.S
@@ -59,15 +59,17 @@ vis1: ldub [%g6 + TI_FPSAVED], %g3
59 be,pn %icc, 9b 59 be,pn %icc, 9b
60 add %g6, TI_FPREGS, %g2 60 add %g6, TI_FPREGS, %g2
61 andcc %o5, FPRS_DL, %g0 61 andcc %o5, FPRS_DL, %g0
62 membar #StoreStore | #LoadStore
63 62
64 be,pn %icc, 4f 63 be,pn %icc, 4f
65 add %g6, TI_FPREGS+0x40, %g3 64 add %g6, TI_FPREGS+0x40, %g3
65 membar #Sync
66 stda %f0, [%g2 + %g1] ASI_BLK_P 66 stda %f0, [%g2 + %g1] ASI_BLK_P
67 stda %f16, [%g3 + %g1] ASI_BLK_P 67 stda %f16, [%g3 + %g1] ASI_BLK_P
68 membar #Sync
68 andcc %o5, FPRS_DU, %g0 69 andcc %o5, FPRS_DU, %g0
69 be,pn %icc, 5f 70 be,pn %icc, 5f
704: add %g1, 128, %g1 714: add %g1, 128, %g1
72 membar #Sync
71 stda %f32, [%g2 + %g1] ASI_BLK_P 73 stda %f32, [%g2 + %g1] ASI_BLK_P
72 74
73 stda %f48, [%g3 + %g1] ASI_BLK_P 75 stda %f48, [%g3 + %g1] ASI_BLK_P
@@ -87,7 +89,7 @@ vis1: ldub [%g6 + TI_FPSAVED], %g3
87 sll %g1, 5, %g1 89 sll %g1, 5, %g1
88 add %g6, TI_FPREGS+0xc0, %g3 90 add %g6, TI_FPREGS+0xc0, %g3
89 wr %g0, FPRS_FEF, %fprs 91 wr %g0, FPRS_FEF, %fprs
90 membar #StoreStore | #LoadStore 92 membar #Sync
91 stda %f32, [%g2 + %g1] ASI_BLK_P 93 stda %f32, [%g2 + %g1] ASI_BLK_P
92 stda %f48, [%g3 + %g1] ASI_BLK_P 94 stda %f48, [%g3 + %g1] ASI_BLK_P
93 membar #Sync 95 membar #Sync
@@ -128,8 +130,8 @@ VISenterhalf:
128 be,pn %icc, 4f 130 be,pn %icc, 4f
129 add %g6, TI_FPREGS, %g2 131 add %g6, TI_FPREGS, %g2
130 132
131 membar #StoreStore | #LoadStore
132 add %g6, TI_FPREGS+0x40, %g3 133 add %g6, TI_FPREGS+0x40, %g3
134 membar #Sync
133 stda %f0, [%g2 + %g1] ASI_BLK_P 135 stda %f0, [%g2 + %g1] ASI_BLK_P
134 stda %f16, [%g3 + %g1] ASI_BLK_P 136 stda %f16, [%g3 + %g1] ASI_BLK_P
135 membar #Sync 137 membar #Sync
diff --git a/arch/sparc64/lib/strncpy_from_user.S b/arch/sparc64/lib/strncpy_from_user.S
index 09cbbaa0ebf4..e1264650ca7a 100644
--- a/arch/sparc64/lib/strncpy_from_user.S
+++ b/arch/sparc64/lib/strncpy_from_user.S
@@ -125,15 +125,11 @@ __strncpy_from_user:
125 add %o2, %o3, %o0 125 add %o2, %o3, %o0
126 .size __strncpy_from_user, .-__strncpy_from_user 126 .size __strncpy_from_user, .-__strncpy_from_user
127 127
128 .section .fixup,#alloc,#execinstr
129 .align 4
1304: retl
131 mov -EFAULT, %o0
132
133 .section __ex_table,#alloc 128 .section __ex_table,#alloc
134 .align 4 129 .align 4
135 .word 60b, 4b 130 .word 60b, __retl_efault
136 .word 61b, 4b 131 .word 61b, __retl_efault
137 .word 62b, 4b 132 .word 62b, __retl_efault
138 .word 63b, 4b 133 .word 63b, __retl_efault
139 .word 64b, 4b 134 .word 64b, __retl_efault
135 .previous
diff --git a/arch/sparc64/lib/user_fixup.c b/arch/sparc64/lib/user_fixup.c
index 0278e34125db..19d1fdb17d0e 100644
--- a/arch/sparc64/lib/user_fixup.c
+++ b/arch/sparc64/lib/user_fixup.c
@@ -11,61 +11,56 @@
11 11
12/* Calculating the exact fault address when using 12/* Calculating the exact fault address when using
13 * block loads and stores can be very complicated. 13 * block loads and stores can be very complicated.
14 *
14 * Instead of trying to be clever and handling all 15 * Instead of trying to be clever and handling all
15 * of the cases, just fix things up simply here. 16 * of the cases, just fix things up simply here.
16 */ 17 */
17 18
18unsigned long copy_from_user_fixup(void *to, const void __user *from, unsigned long size) 19static unsigned long compute_size(unsigned long start, unsigned long size, unsigned long *offset)
19{ 20{
20 char *dst = to; 21 unsigned long fault_addr = current_thread_info()->fault_address;
21 const char __user *src = from; 22 unsigned long end = start + size;
22 23
23 while (size) { 24 if (fault_addr < start || fault_addr >= end) {
24 if (__get_user(*dst, src)) 25 *offset = 0;
25 break; 26 } else {
26 dst++; 27 *offset = start - fault_addr;
27 src++; 28 size = end - fault_addr;
28 size--;
29 } 29 }
30 return size;
31}
30 32
31 if (size) 33unsigned long copy_from_user_fixup(void *to, const void __user *from, unsigned long size)
32 memset(dst, 0, size); 34{
35 unsigned long offset;
36
37 size = compute_size((unsigned long) from, size, &offset);
38 if (likely(size))
39 memset(to + offset, 0, size);
33 40
34 return size; 41 return size;
35} 42}
36 43
37unsigned long copy_to_user_fixup(void __user *to, const void *from, unsigned long size) 44unsigned long copy_to_user_fixup(void __user *to, const void *from, unsigned long size)
38{ 45{
39 char __user *dst = to; 46 unsigned long offset;
40 const char *src = from;
41
42 while (size) {
43 if (__put_user(*src, dst))
44 break;
45 dst++;
46 src++;
47 size--;
48 }
49 47
50 return size; 48 return compute_size((unsigned long) to, size, &offset);
51} 49}
52 50
53unsigned long copy_in_user_fixup(void __user *to, void __user *from, unsigned long size) 51unsigned long copy_in_user_fixup(void __user *to, void __user *from, unsigned long size)
54{ 52{
55 char __user *dst = to; 53 unsigned long fault_addr = current_thread_info()->fault_address;
56 char __user *src = from; 54 unsigned long start = (unsigned long) to;
55 unsigned long end = start + size;
57 56
58 while (size) { 57 if (fault_addr >= start && fault_addr < end)
59 char tmp; 58 return end - fault_addr;
60 59
61 if (__get_user(tmp, src)) 60 start = (unsigned long) from;
62 break; 61 end = start + size;
63 if (__put_user(tmp, dst)) 62 if (fault_addr >= start && fault_addr < end)
64 break; 63 return end - fault_addr;
65 dst++;
66 src++;
67 size--;
68 }
69 64
70 return size; 65 return size;
71} 66}
diff --git a/arch/sparc64/mm/Makefile b/arch/sparc64/mm/Makefile
index cda87333a77b..9d0960e69f48 100644
--- a/arch/sparc64/mm/Makefile
+++ b/arch/sparc64/mm/Makefile
@@ -5,6 +5,6 @@
5EXTRA_AFLAGS := -ansi 5EXTRA_AFLAGS := -ansi
6EXTRA_CFLAGS := -Werror 6EXTRA_CFLAGS := -Werror
7 7
8obj-y := ultra.o tlb.o fault.o init.o generic.o extable.o 8obj-y := ultra.o tlb.o fault.o init.o generic.o
9 9
10obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o 10obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
diff --git a/arch/sparc64/mm/extable.c b/arch/sparc64/mm/extable.c
deleted file mode 100644
index ec334297ff4f..000000000000
--- a/arch/sparc64/mm/extable.c
+++ /dev/null
@@ -1,80 +0,0 @@
1/*
2 * linux/arch/sparc64/mm/extable.c
3 */
4
5#include <linux/config.h>
6#include <linux/module.h>
7#include <asm/uaccess.h>
8
9extern const struct exception_table_entry __start___ex_table[];
10extern const struct exception_table_entry __stop___ex_table[];
11
12void sort_extable(struct exception_table_entry *start,
13 struct exception_table_entry *finish)
14{
15}
16
17/* Caller knows they are in a range if ret->fixup == 0 */
18const struct exception_table_entry *
19search_extable(const struct exception_table_entry *start,
20 const struct exception_table_entry *last,
21 unsigned long value)
22{
23 const struct exception_table_entry *walk;
24
25 /* Single insn entries are encoded as:
26 * word 1: insn address
27 * word 2: fixup code address
28 *
29 * Range entries are encoded as:
30 * word 1: first insn address
31 * word 2: 0
32 * word 3: last insn address + 4 bytes
33 * word 4: fixup code address
34 *
35 * See asm/uaccess.h for more details.
36 */
37
38 /* 1. Try to find an exact match. */
39 for (walk = start; walk <= last; walk++) {
40 if (walk->fixup == 0) {
41 /* A range entry, skip both parts. */
42 walk++;
43 continue;
44 }
45
46 if (walk->insn == value)
47 return walk;
48 }
49
50 /* 2. Try to find a range match. */
51 for (walk = start; walk <= (last - 1); walk++) {
52 if (walk->fixup)
53 continue;
54
55 if (walk[0].insn <= value && walk[1].insn > value)
56 return walk;
57
58 walk++;
59 }
60
61 return NULL;
62}
63
64/* Special extable search, which handles ranges. Returns fixup */
65unsigned long search_extables_range(unsigned long addr, unsigned long *g2)
66{
67 const struct exception_table_entry *entry;
68
69 entry = search_exception_tables(addr);
70 if (!entry)
71 return 0;
72
73 /* Inside range? Fix g2 and return correct fixup */
74 if (!entry->fixup) {
75 *g2 = (addr - entry->insn) / 4;
76 return (entry + 1)->fixup;
77 }
78
79 return entry->fixup;
80}
diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c
index db1e3310e907..31fbc67719a1 100644
--- a/arch/sparc64/mm/fault.c
+++ b/arch/sparc64/mm/fault.c
@@ -32,8 +32,6 @@
32 32
33#define ELEMENTS(arr) (sizeof (arr)/sizeof (arr[0])) 33#define ELEMENTS(arr) (sizeof (arr)/sizeof (arr[0]))
34 34
35extern struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS];
36
37/* 35/*
38 * To debug kernel to catch accesses to certain virtual/physical addresses. 36 * To debug kernel to catch accesses to certain virtual/physical addresses.
39 * Mode = 0 selects physical watchpoints, mode = 1 selects virtual watchpoints. 37 * Mode = 0 selects physical watchpoints, mode = 1 selects virtual watchpoints.
@@ -71,53 +69,6 @@ void set_brkpt(unsigned long addr, unsigned char mask, int flags, int mode)
71 : "memory"); 69 : "memory");
72} 70}
73 71
74/* Nice, simple, prom library does all the sweating for us. ;) */
75unsigned long __init prom_probe_memory (void)
76{
77 register struct linux_mlist_p1275 *mlist;
78 register unsigned long bytes, base_paddr, tally;
79 register int i;
80
81 i = 0;
82 mlist = *prom_meminfo()->p1275_available;
83 bytes = tally = mlist->num_bytes;
84 base_paddr = mlist->start_adr;
85
86 sp_banks[0].base_addr = base_paddr;
87 sp_banks[0].num_bytes = bytes;
88
89 while (mlist->theres_more != (void *) 0) {
90 i++;
91 mlist = mlist->theres_more;
92 bytes = mlist->num_bytes;
93 tally += bytes;
94 if (i >= SPARC_PHYS_BANKS-1) {
95 printk ("The machine has more banks than "
96 "this kernel can support\n"
97 "Increase the SPARC_PHYS_BANKS "
98 "setting (currently %d)\n",
99 SPARC_PHYS_BANKS);
100 i = SPARC_PHYS_BANKS-1;
101 break;
102 }
103
104 sp_banks[i].base_addr = mlist->start_adr;
105 sp_banks[i].num_bytes = mlist->num_bytes;
106 }
107
108 i++;
109 sp_banks[i].base_addr = 0xdeadbeefbeefdeadUL;
110 sp_banks[i].num_bytes = 0;
111
112 /* Now mask all bank sizes on a page boundary, it is all we can
113 * use anyways.
114 */
115 for (i = 0; sp_banks[i].num_bytes != 0; i++)
116 sp_banks[i].num_bytes &= PAGE_MASK;
117
118 return tally;
119}
120
121static void __kprobes unhandled_fault(unsigned long address, 72static void __kprobes unhandled_fault(unsigned long address,
122 struct task_struct *tsk, 73 struct task_struct *tsk,
123 struct pt_regs *regs) 74 struct pt_regs *regs)
@@ -242,7 +193,6 @@ static unsigned int get_fault_insn(struct pt_regs *regs, unsigned int insn)
242static void do_kernel_fault(struct pt_regs *regs, int si_code, int fault_code, 193static void do_kernel_fault(struct pt_regs *regs, int si_code, int fault_code,
243 unsigned int insn, unsigned long address) 194 unsigned int insn, unsigned long address)
244{ 195{
245 unsigned long g2;
246 unsigned char asi = ASI_P; 196 unsigned char asi = ASI_P;
247 197
248 if ((!insn) && (regs->tstate & TSTATE_PRIV)) 198 if ((!insn) && (regs->tstate & TSTATE_PRIV))
@@ -273,11 +223,9 @@ static void do_kernel_fault(struct pt_regs *regs, int si_code, int fault_code,
273 } 223 }
274 } 224 }
275 225
276 g2 = regs->u_regs[UREG_G2];
277
278 /* Is this in ex_table? */ 226 /* Is this in ex_table? */
279 if (regs->tstate & TSTATE_PRIV) { 227 if (regs->tstate & TSTATE_PRIV) {
280 unsigned long fixup; 228 const struct exception_table_entry *entry;
281 229
282 if (asi == ASI_P && (insn & 0xc0800000) == 0xc0800000) { 230 if (asi == ASI_P && (insn & 0xc0800000) == 0xc0800000) {
283 if (insn & 0x2000) 231 if (insn & 0x2000)
@@ -288,10 +236,9 @@ static void do_kernel_fault(struct pt_regs *regs, int si_code, int fault_code,
288 236
289 /* Look in asi.h: All _S asis have LS bit set */ 237 /* Look in asi.h: All _S asis have LS bit set */
290 if ((asi & 0x1) && 238 if ((asi & 0x1) &&
291 (fixup = search_extables_range(regs->tpc, &g2))) { 239 (entry = search_exception_tables(regs->tpc))) {
292 regs->tpc = fixup; 240 regs->tpc = entry->fixup;
293 regs->tnpc = regs->tpc + 4; 241 regs->tnpc = regs->tpc + 4;
294 regs->u_regs[UREG_G2] = g2;
295 return; 242 return;
296 } 243 }
297 } else { 244 } else {
@@ -461,7 +408,7 @@ good_area:
461 } 408 }
462 409
463 up_read(&mm->mmap_sem); 410 up_read(&mm->mmap_sem);
464 goto fault_done; 411 return;
465 412
466 /* 413 /*
467 * Something tried to access memory that isn't in our memory map.. 414 * Something tried to access memory that isn't in our memory map..
@@ -473,8 +420,7 @@ bad_area:
473 420
474handle_kernel_fault: 421handle_kernel_fault:
475 do_kernel_fault(regs, si_code, fault_code, insn, address); 422 do_kernel_fault(regs, si_code, fault_code, insn, address);
476 423 return;
477 goto fault_done;
478 424
479/* 425/*
480 * We ran out of memory, or some other thing happened to us that made 426 * We ran out of memory, or some other thing happened to us that made
@@ -505,9 +451,4 @@ do_sigbus:
505 /* Kernel mode? Handle exceptions or die */ 451 /* Kernel mode? Handle exceptions or die */
506 if (regs->tstate & TSTATE_PRIV) 452 if (regs->tstate & TSTATE_PRIV)
507 goto handle_kernel_fault; 453 goto handle_kernel_fault;
508
509fault_done:
510 /* These values are no longer needed, clear them. */
511 set_thread_fault_code(0);
512 current_thread_info()->fault_address = 0;
513} 454}
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index 9f6ca624892d..0d2e967c7200 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -21,6 +21,7 @@
21#include <linux/seq_file.h> 21#include <linux/seq_file.h>
22#include <linux/kprobes.h> 22#include <linux/kprobes.h>
23#include <linux/cache.h> 23#include <linux/cache.h>
24#include <linux/sort.h>
24 25
25#include <asm/head.h> 26#include <asm/head.h>
26#include <asm/system.h> 27#include <asm/system.h>
@@ -41,7 +42,72 @@
41 42
42extern void device_scan(void); 43extern void device_scan(void);
43 44
44struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS]; 45#define MAX_BANKS 32
46
47static struct linux_prom64_registers pavail[MAX_BANKS] __initdata;
48static struct linux_prom64_registers pavail_rescan[MAX_BANKS] __initdata;
49static int pavail_ents __initdata;
50static int pavail_rescan_ents __initdata;
51
52static int cmp_p64(const void *a, const void *b)
53{
54 const struct linux_prom64_registers *x = a, *y = b;
55
56 if (x->phys_addr > y->phys_addr)
57 return 1;
58 if (x->phys_addr < y->phys_addr)
59 return -1;
60 return 0;
61}
62
63static void __init read_obp_memory(const char *property,
64 struct linux_prom64_registers *regs,
65 int *num_ents)
66{
67 int node = prom_finddevice("/memory");
68 int prop_size = prom_getproplen(node, property);
69 int ents, ret, i;
70
71 ents = prop_size / sizeof(struct linux_prom64_registers);
72 if (ents > MAX_BANKS) {
73 prom_printf("The machine has more %s property entries than "
74 "this kernel can support (%d).\n",
75 property, MAX_BANKS);
76 prom_halt();
77 }
78
79 ret = prom_getproperty(node, property, (char *) regs, prop_size);
80 if (ret == -1) {
81 prom_printf("Couldn't get %s property from /memory.\n");
82 prom_halt();
83 }
84
85 *num_ents = ents;
86
87 /* Sanitize what we got from the firmware, by page aligning
88 * everything.
89 */
90 for (i = 0; i < ents; i++) {
91 unsigned long base, size;
92
93 base = regs[i].phys_addr;
94 size = regs[i].reg_size;
95
96 size &= PAGE_MASK;
97 if (base & ~PAGE_MASK) {
98 unsigned long new_base = PAGE_ALIGN(base);
99
100 size -= new_base - base;
101 if ((long) size < 0L)
102 size = 0UL;
103 base = new_base;
104 }
105 regs[i].phys_addr = base;
106 regs[i].reg_size = size;
107 }
108 sort(regs, ents, sizeof(struct linux_prom64_registers),
109 cmp_p64, NULL);
110}
45 111
46unsigned long *sparc64_valid_addr_bitmap __read_mostly; 112unsigned long *sparc64_valid_addr_bitmap __read_mostly;
47 113
@@ -67,6 +133,12 @@ extern unsigned int sparc_ramdisk_size;
67 133
68struct page *mem_map_zero __read_mostly; 134struct page *mem_map_zero __read_mostly;
69 135
136unsigned int sparc64_highest_unlocked_tlb_ent __read_mostly;
137
138unsigned long sparc64_kern_pri_context __read_mostly;
139unsigned long sparc64_kern_pri_nuc_bits __read_mostly;
140unsigned long sparc64_kern_sec_context __read_mostly;
141
70int bigkernel = 0; 142int bigkernel = 0;
71 143
72/* XXX Tune this... */ 144/* XXX Tune this... */
@@ -296,6 +368,7 @@ struct linux_prom_translation {
296 unsigned long data; 368 unsigned long data;
297}; 369};
298static struct linux_prom_translation prom_trans[512] __initdata; 370static struct linux_prom_translation prom_trans[512] __initdata;
371static unsigned int prom_trans_ents __initdata;
299 372
300extern unsigned long prom_boot_page; 373extern unsigned long prom_boot_page;
301extern void prom_remap(unsigned long physpage, unsigned long virtpage, int mmu_ihandle); 374extern void prom_remap(unsigned long physpage, unsigned long virtpage, int mmu_ihandle);
@@ -309,57 +382,7 @@ unsigned long kern_locked_tte_data;
309unsigned long prom_pmd_phys __read_mostly; 382unsigned long prom_pmd_phys __read_mostly;
310unsigned int swapper_pgd_zero __read_mostly; 383unsigned int swapper_pgd_zero __read_mostly;
311 384
312/* Allocate power-of-2 aligned chunks from the end of the 385static pmd_t *prompmd __read_mostly;
313 * kernel image. Return physical address.
314 */
315static inline unsigned long early_alloc_phys(unsigned long size)
316{
317 unsigned long base;
318
319 BUILD_BUG_ON(size & (size - 1));
320
321 kern_size = (kern_size + (size - 1)) & ~(size - 1);
322 base = kern_base + kern_size;
323 kern_size += size;
324
325 return base;
326}
327
328static inline unsigned long load_phys32(unsigned long pa)
329{
330 unsigned long val;
331
332 __asm__ __volatile__("lduwa [%1] %2, %0"
333 : "=&r" (val)
334 : "r" (pa), "i" (ASI_PHYS_USE_EC));
335
336 return val;
337}
338
339static inline unsigned long load_phys64(unsigned long pa)
340{
341 unsigned long val;
342
343 __asm__ __volatile__("ldxa [%1] %2, %0"
344 : "=&r" (val)
345 : "r" (pa), "i" (ASI_PHYS_USE_EC));
346
347 return val;
348}
349
350static inline void store_phys32(unsigned long pa, unsigned long val)
351{
352 __asm__ __volatile__("stwa %0, [%1] %2"
353 : /* no outputs */
354 : "r" (val), "r" (pa), "i" (ASI_PHYS_USE_EC));
355}
356
357static inline void store_phys64(unsigned long pa, unsigned long val)
358{
359 __asm__ __volatile__("stxa %0, [%1] %2"
360 : /* no outputs */
361 : "r" (val), "r" (pa), "i" (ASI_PHYS_USE_EC));
362}
363 386
364#define BASE_PAGE_SIZE 8192 387#define BASE_PAGE_SIZE 8192
365 388
@@ -369,34 +392,28 @@ static inline void store_phys64(unsigned long pa, unsigned long val)
369 */ 392 */
370unsigned long prom_virt_to_phys(unsigned long promva, int *error) 393unsigned long prom_virt_to_phys(unsigned long promva, int *error)
371{ 394{
372 unsigned long pmd_phys = (prom_pmd_phys + 395 pmd_t *pmdp = prompmd + ((promva >> 23) & 0x7ff);
373 ((promva >> 23) & 0x7ff) * sizeof(pmd_t)); 396 pte_t *ptep;
374 unsigned long pte_phys;
375 pmd_t pmd_ent;
376 pte_t pte_ent;
377 unsigned long base; 397 unsigned long base;
378 398
379 pmd_val(pmd_ent) = load_phys32(pmd_phys); 399 if (pmd_none(*pmdp)) {
380 if (pmd_none(pmd_ent)) {
381 if (error) 400 if (error)
382 *error = 1; 401 *error = 1;
383 return 0; 402 return 0;
384 } 403 }
385 404 ptep = (pte_t *)__pmd_page(*pmdp) + ((promva >> 13) & 0x3ff);
386 pte_phys = (unsigned long)pmd_val(pmd_ent) << 11UL; 405 if (!pte_present(*ptep)) {
387 pte_phys += ((promva >> 13) & 0x3ff) * sizeof(pte_t);
388 pte_val(pte_ent) = load_phys64(pte_phys);
389 if (!pte_present(pte_ent)) {
390 if (error) 406 if (error)
391 *error = 1; 407 *error = 1;
392 return 0; 408 return 0;
393 } 409 }
394 if (error) { 410 if (error) {
395 *error = 0; 411 *error = 0;
396 return pte_val(pte_ent); 412 return pte_val(*ptep);
397 } 413 }
398 base = pte_val(pte_ent) & _PAGE_PADDR; 414 base = pte_val(*ptep) & _PAGE_PADDR;
399 return (base + (promva & (BASE_PAGE_SIZE - 1))); 415
416 return base + (promva & (BASE_PAGE_SIZE - 1));
400} 417}
401 418
402/* The obp translations are saved based on 8k pagesize, since obp can 419/* The obp translations are saved based on 8k pagesize, since obp can
@@ -409,25 +426,20 @@ static void __init build_obp_range(unsigned long start, unsigned long end, unsig
409 unsigned long vaddr; 426 unsigned long vaddr;
410 427
411 for (vaddr = start; vaddr < end; vaddr += BASE_PAGE_SIZE) { 428 for (vaddr = start; vaddr < end; vaddr += BASE_PAGE_SIZE) {
412 unsigned long val, pte_phys, pmd_phys; 429 unsigned long val;
413 pmd_t pmd_ent; 430 pmd_t *pmd;
414 int i; 431 pte_t *pte;
415
416 pmd_phys = (prom_pmd_phys +
417 (((vaddr >> 23) & 0x7ff) * sizeof(pmd_t)));
418 pmd_val(pmd_ent) = load_phys32(pmd_phys);
419 if (pmd_none(pmd_ent)) {
420 pte_phys = early_alloc_phys(BASE_PAGE_SIZE);
421
422 for (i = 0; i < BASE_PAGE_SIZE / sizeof(pte_t); i++)
423 store_phys64(pte_phys+i*sizeof(pte_t),0);
424 432
425 pmd_val(pmd_ent) = pte_phys >> 11UL; 433 pmd = prompmd + ((vaddr >> 23) & 0x7ff);
426 store_phys32(pmd_phys, pmd_val(pmd_ent)); 434 if (pmd_none(*pmd)) {
435 pte = __alloc_bootmem(BASE_PAGE_SIZE, BASE_PAGE_SIZE,
436 PAGE_SIZE);
437 if (!pte)
438 prom_halt();
439 memset(pte, 0, BASE_PAGE_SIZE);
440 pmd_set(pmd, pte);
427 } 441 }
428 442 pte = (pte_t *) __pmd_page(*pmd) + ((vaddr >> 13) & 0x3ff);
429 pte_phys = (unsigned long)pmd_val(pmd_ent) << 11UL;
430 pte_phys += (((vaddr >> 13) & 0x3ff) * sizeof(pte_t));
431 443
432 val = data; 444 val = data;
433 445
@@ -435,7 +447,8 @@ static void __init build_obp_range(unsigned long start, unsigned long end, unsig
435 if (tlb_type == spitfire) 447 if (tlb_type == spitfire)
436 val &= ~0x0003fe0000000000UL; 448 val &= ~0x0003fe0000000000UL;
437 449
438 store_phys64(pte_phys, val | _PAGE_MODIFIED); 450 set_pte_at(&init_mm, vaddr, pte,
451 __pte(val | _PAGE_MODIFIED));
439 452
440 data += BASE_PAGE_SIZE; 453 data += BASE_PAGE_SIZE;
441 } 454 }
@@ -448,13 +461,17 @@ static inline int in_obp_range(unsigned long vaddr)
448} 461}
449 462
450#define OBP_PMD_SIZE 2048 463#define OBP_PMD_SIZE 2048
451static void __init build_obp_pgtable(int prom_trans_ents) 464static void __init build_obp_pgtable(void)
452{ 465{
453 unsigned long i; 466 unsigned long i;
454 467
455 prom_pmd_phys = early_alloc_phys(OBP_PMD_SIZE); 468 prompmd = __alloc_bootmem(OBP_PMD_SIZE, OBP_PMD_SIZE, PAGE_SIZE);
456 for (i = 0; i < OBP_PMD_SIZE; i += 4) 469 if (!prompmd)
457 store_phys32(prom_pmd_phys + i, 0); 470 prom_halt();
471
472 memset(prompmd, 0, OBP_PMD_SIZE);
473
474 prom_pmd_phys = __pa(prompmd);
458 475
459 for (i = 0; i < prom_trans_ents; i++) { 476 for (i = 0; i < prom_trans_ents; i++) {
460 unsigned long start, end; 477 unsigned long start, end;
@@ -474,7 +491,7 @@ static void __init build_obp_pgtable(int prom_trans_ents)
474/* Read OBP translations property into 'prom_trans[]'. 491/* Read OBP translations property into 'prom_trans[]'.
475 * Return the number of entries. 492 * Return the number of entries.
476 */ 493 */
477static int __init read_obp_translations(void) 494static void __init read_obp_translations(void)
478{ 495{
479 int n, node; 496 int n, node;
480 497
@@ -495,8 +512,10 @@ static int __init read_obp_translations(void)
495 prom_printf("prom_mappings: Couldn't get property.\n"); 512 prom_printf("prom_mappings: Couldn't get property.\n");
496 prom_halt(); 513 prom_halt();
497 } 514 }
515
498 n = n / sizeof(struct linux_prom_translation); 516 n = n / sizeof(struct linux_prom_translation);
499 return n; 517
518 prom_trans_ents = n;
500} 519}
501 520
502static void __init remap_kernel(void) 521static void __init remap_kernel(void)
@@ -516,28 +535,38 @@ static void __init remap_kernel(void)
516 prom_dtlb_load(tlb_ent, tte_data, tte_vaddr); 535 prom_dtlb_load(tlb_ent, tte_data, tte_vaddr);
517 prom_itlb_load(tlb_ent, tte_data, tte_vaddr); 536 prom_itlb_load(tlb_ent, tte_data, tte_vaddr);
518 if (bigkernel) { 537 if (bigkernel) {
519 prom_dtlb_load(tlb_ent - 1, 538 tlb_ent -= 1;
539 prom_dtlb_load(tlb_ent,
520 tte_data + 0x400000, 540 tte_data + 0x400000,
521 tte_vaddr + 0x400000); 541 tte_vaddr + 0x400000);
522 prom_itlb_load(tlb_ent - 1, 542 prom_itlb_load(tlb_ent,
523 tte_data + 0x400000, 543 tte_data + 0x400000,
524 tte_vaddr + 0x400000); 544 tte_vaddr + 0x400000);
525 } 545 }
546 sparc64_highest_unlocked_tlb_ent = tlb_ent - 1;
547 if (tlb_type == cheetah_plus) {
548 sparc64_kern_pri_context = (CTX_CHEETAH_PLUS_CTX0 |
549 CTX_CHEETAH_PLUS_NUC);
550 sparc64_kern_pri_nuc_bits = CTX_CHEETAH_PLUS_NUC;
551 sparc64_kern_sec_context = CTX_CHEETAH_PLUS_CTX0;
552 }
526} 553}
527 554
528static void __init inherit_prom_mappings(void)
529{
530 int n;
531 555
532 n = read_obp_translations(); 556static void __init inherit_prom_mappings_pre(void)
533 build_obp_pgtable(n); 557{
558 read_obp_translations();
534 559
535 /* Now fixup OBP's idea about where we really are mapped. */ 560 /* Now fixup OBP's idea about where we really are mapped. */
536 prom_printf("Remapping the kernel... "); 561 prom_printf("Remapping the kernel... ");
537 remap_kernel(); 562 remap_kernel();
538 563
539 prom_printf("done.\n"); 564 prom_printf("done.\n");
565}
540 566
567static void __init inherit_prom_mappings_post(void)
568{
569 build_obp_pgtable();
541 register_prom_callbacks(); 570 register_prom_callbacks();
542} 571}
543 572
@@ -722,8 +751,8 @@ void inherit_locked_prom_mappings(int save_p)
722 } 751 }
723 } 752 }
724 if (tlb_type == spitfire) { 753 if (tlb_type == spitfire) {
725 int high = SPITFIRE_HIGHEST_LOCKED_TLBENT - bigkernel; 754 int high = sparc64_highest_unlocked_tlb_ent;
726 for (i = 0; i < high; i++) { 755 for (i = 0; i <= high; i++) {
727 unsigned long data; 756 unsigned long data;
728 757
729 /* Spitfire Errata #32 workaround */ 758 /* Spitfire Errata #32 workaround */
@@ -811,9 +840,9 @@ void inherit_locked_prom_mappings(int save_p)
811 } 840 }
812 } 841 }
813 } else if (tlb_type == cheetah || tlb_type == cheetah_plus) { 842 } else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
814 int high = CHEETAH_HIGHEST_LOCKED_TLBENT - bigkernel; 843 int high = sparc64_highest_unlocked_tlb_ent;
815 844
816 for (i = 0; i < high; i++) { 845 for (i = 0; i <= high; i++) {
817 unsigned long data; 846 unsigned long data;
818 847
819 data = cheetah_get_ldtlb_data(i); 848 data = cheetah_get_ldtlb_data(i);
@@ -1206,14 +1235,14 @@ unsigned long __init bootmem_init(unsigned long *pages_avail)
1206 int i; 1235 int i;
1207 1236
1208#ifdef CONFIG_DEBUG_BOOTMEM 1237#ifdef CONFIG_DEBUG_BOOTMEM
1209 prom_printf("bootmem_init: Scan sp_banks, "); 1238 prom_printf("bootmem_init: Scan pavail, ");
1210#endif 1239#endif
1211 1240
1212 bytes_avail = 0UL; 1241 bytes_avail = 0UL;
1213 for (i = 0; sp_banks[i].num_bytes != 0; i++) { 1242 for (i = 0; i < pavail_ents; i++) {
1214 end_of_phys_memory = sp_banks[i].base_addr + 1243 end_of_phys_memory = pavail[i].phys_addr +
1215 sp_banks[i].num_bytes; 1244 pavail[i].reg_size;
1216 bytes_avail += sp_banks[i].num_bytes; 1245 bytes_avail += pavail[i].reg_size;
1217 if (cmdline_memory_size) { 1246 if (cmdline_memory_size) {
1218 if (bytes_avail > cmdline_memory_size) { 1247 if (bytes_avail > cmdline_memory_size) {
1219 unsigned long slack = bytes_avail - cmdline_memory_size; 1248 unsigned long slack = bytes_avail - cmdline_memory_size;
@@ -1221,12 +1250,15 @@ unsigned long __init bootmem_init(unsigned long *pages_avail)
1221 bytes_avail -= slack; 1250 bytes_avail -= slack;
1222 end_of_phys_memory -= slack; 1251 end_of_phys_memory -= slack;
1223 1252
1224 sp_banks[i].num_bytes -= slack; 1253 pavail[i].reg_size -= slack;
1225 if (sp_banks[i].num_bytes == 0) { 1254 if ((long)pavail[i].reg_size <= 0L) {
1226 sp_banks[i].base_addr = 0xdeadbeef; 1255 pavail[i].phys_addr = 0xdeadbeefUL;
1256 pavail[i].reg_size = 0UL;
1257 pavail_ents = i;
1227 } else { 1258 } else {
1228 sp_banks[i+1].num_bytes = 0; 1259 pavail[i+1].reg_size = 0Ul;
1229 sp_banks[i+1].base_addr = 0xdeadbeef; 1260 pavail[i+1].phys_addr = 0xdeadbeefUL;
1261 pavail_ents = i + 1;
1230 } 1262 }
1231 break; 1263 break;
1232 } 1264 }
@@ -1280,12 +1312,12 @@ unsigned long __init bootmem_init(unsigned long *pages_avail)
1280 /* Now register the available physical memory with the 1312 /* Now register the available physical memory with the
1281 * allocator. 1313 * allocator.
1282 */ 1314 */
1283 for (i = 0; sp_banks[i].num_bytes != 0; i++) { 1315 for (i = 0; i < pavail_ents; i++) {
1284#ifdef CONFIG_DEBUG_BOOTMEM 1316#ifdef CONFIG_DEBUG_BOOTMEM
1285 prom_printf("free_bootmem(sp_banks:%d): base[%lx] size[%lx]\n", 1317 prom_printf("free_bootmem(pavail:%d): base[%lx] size[%lx]\n",
1286 i, sp_banks[i].base_addr, sp_banks[i].num_bytes); 1318 i, pavail[i].phys_addr, pavail[i].reg_size);
1287#endif 1319#endif
1288 free_bootmem(sp_banks[i].base_addr, sp_banks[i].num_bytes); 1320 free_bootmem(pavail[i].phys_addr, pavail[i].reg_size);
1289 } 1321 }
1290 1322
1291#ifdef CONFIG_BLK_DEV_INITRD 1323#ifdef CONFIG_BLK_DEV_INITRD
@@ -1334,7 +1366,7 @@ static unsigned long kernel_map_range(unsigned long pstart, unsigned long pend,
1334 unsigned long alloc_bytes = 0UL; 1366 unsigned long alloc_bytes = 0UL;
1335 1367
1336 if ((vstart & ~PAGE_MASK) || (vend & ~PAGE_MASK)) { 1368 if ((vstart & ~PAGE_MASK) || (vend & ~PAGE_MASK)) {
1337 prom_printf("kernel_map: Unaligned sp_banks[%lx:%lx]\n", 1369 prom_printf("kernel_map: Unaligned physmem[%lx:%lx]\n",
1338 vstart, vend); 1370 vstart, vend);
1339 prom_halt(); 1371 prom_halt();
1340 } 1372 }
@@ -1381,23 +1413,24 @@ static unsigned long kernel_map_range(unsigned long pstart, unsigned long pend,
1381 return alloc_bytes; 1413 return alloc_bytes;
1382} 1414}
1383 1415
1384extern struct linux_mlist_p1275 *prom_ptot_ptr; 1416static struct linux_prom64_registers pall[MAX_BANKS] __initdata;
1417static int pall_ents __initdata;
1418
1385extern unsigned int kvmap_linear_patch[1]; 1419extern unsigned int kvmap_linear_patch[1];
1386 1420
1387static void __init kernel_physical_mapping_init(void) 1421static void __init kernel_physical_mapping_init(void)
1388{ 1422{
1389 struct linux_mlist_p1275 *p = prom_ptot_ptr; 1423 unsigned long i, mem_alloced = 0UL;
1390 unsigned long mem_alloced = 0UL; 1424
1425 read_obp_memory("reg", &pall[0], &pall_ents);
1391 1426
1392 while (p) { 1427 for (i = 0; i < pall_ents; i++) {
1393 unsigned long phys_start, phys_end; 1428 unsigned long phys_start, phys_end;
1394 1429
1395 phys_start = p->start_adr; 1430 phys_start = pall[i].phys_addr;
1396 phys_end = phys_start + p->num_bytes; 1431 phys_end = phys_start + pall[i].reg_size;
1397 mem_alloced += kernel_map_range(phys_start, phys_end, 1432 mem_alloced += kernel_map_range(phys_start, phys_end,
1398 PAGE_KERNEL); 1433 PAGE_KERNEL);
1399
1400 p = p->theres_more;
1401 } 1434 }
1402 1435
1403 printk("Allocated %ld bytes for kernel page tables.\n", 1436 printk("Allocated %ld bytes for kernel page tables.\n",
@@ -1425,6 +1458,18 @@ void kernel_map_pages(struct page *page, int numpages, int enable)
1425} 1458}
1426#endif 1459#endif
1427 1460
1461unsigned long __init find_ecache_flush_span(unsigned long size)
1462{
1463 int i;
1464
1465 for (i = 0; i < pavail_ents; i++) {
1466 if (pavail[i].reg_size >= size)
1467 return pavail[i].phys_addr;
1468 }
1469
1470 return ~0UL;
1471}
1472
1428/* paging_init() sets up the page tables */ 1473/* paging_init() sets up the page tables */
1429 1474
1430extern void cheetah_ecache_flush_init(void); 1475extern void cheetah_ecache_flush_init(void);
@@ -1435,7 +1480,19 @@ pgd_t swapper_pg_dir[2048];
1435void __init paging_init(void) 1480void __init paging_init(void)
1436{ 1481{
1437 unsigned long end_pfn, pages_avail, shift; 1482 unsigned long end_pfn, pages_avail, shift;
1438 unsigned long real_end; 1483 unsigned long real_end, i;
1484
1485 /* Find available physical memory... */
1486 read_obp_memory("available", &pavail[0], &pavail_ents);
1487
1488 phys_base = 0xffffffffffffffffUL;
1489 for (i = 0; i < pavail_ents; i++)
1490 phys_base = min(phys_base, pavail[i].phys_addr);
1491
1492 pfn_base = phys_base >> PAGE_SHIFT;
1493
1494 kern_base = (prom_boot_mapping_phys_low >> 22UL) << 22UL;
1495 kern_size = (unsigned long)&_end - (unsigned long)KERNBASE;
1439 1496
1440 set_bit(0, mmu_context_bmap); 1497 set_bit(0, mmu_context_bmap);
1441 1498
@@ -1462,8 +1519,7 @@ void __init paging_init(void)
1462 1519
1463 swapper_pgd_zero = pgd_val(swapper_pg_dir[0]); 1520 swapper_pgd_zero = pgd_val(swapper_pg_dir[0]);
1464 1521
1465 /* Inherit non-locked OBP mappings. */ 1522 inherit_prom_mappings_pre();
1466 inherit_prom_mappings();
1467 1523
1468 /* Ok, we can use our TLB miss and window trap handlers safely. 1524 /* Ok, we can use our TLB miss and window trap handlers safely.
1469 * We need to do a quick peek here to see if we are on StarFire 1525 * We need to do a quick peek here to see if we are on StarFire
@@ -1474,15 +1530,23 @@ void __init paging_init(void)
1474 extern void setup_tba(int); 1530 extern void setup_tba(int);
1475 setup_tba(this_is_starfire); 1531 setup_tba(this_is_starfire);
1476 } 1532 }
1477
1478 inherit_locked_prom_mappings(1);
1479
1480 __flush_tlb_all(); 1533 __flush_tlb_all();
1481 1534
1535 /* Everything from this point forward, until we are done with
1536 * inherit_prom_mappings_post(), must complete successfully
1537 * without calling into the firmware. The firwmare page tables
1538 * have not been built, but we are running on the Linux kernel's
1539 * trap table.
1540 */
1541
1482 /* Setup bootmem... */ 1542 /* Setup bootmem... */
1483 pages_avail = 0; 1543 pages_avail = 0;
1484 last_valid_pfn = end_pfn = bootmem_init(&pages_avail); 1544 last_valid_pfn = end_pfn = bootmem_init(&pages_avail);
1485 1545
1546 inherit_prom_mappings_post();
1547
1548 inherit_locked_prom_mappings(1);
1549
1486#ifdef CONFIG_DEBUG_PAGEALLOC 1550#ifdef CONFIG_DEBUG_PAGEALLOC
1487 kernel_physical_mapping_init(); 1551 kernel_physical_mapping_init();
1488#endif 1552#endif
@@ -1507,128 +1571,35 @@ void __init paging_init(void)
1507 device_scan(); 1571 device_scan();
1508} 1572}
1509 1573
1510/* Ok, it seems that the prom can allocate some more memory chunks
1511 * as a side effect of some prom calls we perform during the
1512 * boot sequence. My most likely theory is that it is from the
1513 * prom_set_traptable() call, and OBP is allocating a scratchpad
1514 * for saving client program register state etc.
1515 */
1516static void __init sort_memlist(struct linux_mlist_p1275 *thislist)
1517{
1518 int swapi = 0;
1519 int i, mitr;
1520 unsigned long tmpaddr, tmpsize;
1521 unsigned long lowest;
1522
1523 for (i = 0; thislist[i].theres_more != 0; i++) {
1524 lowest = thislist[i].start_adr;
1525 for (mitr = i+1; thislist[mitr-1].theres_more != 0; mitr++)
1526 if (thislist[mitr].start_adr < lowest) {
1527 lowest = thislist[mitr].start_adr;
1528 swapi = mitr;
1529 }
1530 if (lowest == thislist[i].start_adr)
1531 continue;
1532 tmpaddr = thislist[swapi].start_adr;
1533 tmpsize = thislist[swapi].num_bytes;
1534 for (mitr = swapi; mitr > i; mitr--) {
1535 thislist[mitr].start_adr = thislist[mitr-1].start_adr;
1536 thislist[mitr].num_bytes = thislist[mitr-1].num_bytes;
1537 }
1538 thislist[i].start_adr = tmpaddr;
1539 thislist[i].num_bytes = tmpsize;
1540 }
1541}
1542
1543void __init rescan_sp_banks(void)
1544{
1545 struct linux_prom64_registers memlist[64];
1546 struct linux_mlist_p1275 avail[64], *mlist;
1547 unsigned long bytes, base_paddr;
1548 int num_regs, node = prom_finddevice("/memory");
1549 int i;
1550
1551 num_regs = prom_getproperty(node, "available",
1552 (char *) memlist, sizeof(memlist));
1553 num_regs = (num_regs / sizeof(struct linux_prom64_registers));
1554 for (i = 0; i < num_regs; i++) {
1555 avail[i].start_adr = memlist[i].phys_addr;
1556 avail[i].num_bytes = memlist[i].reg_size;
1557 avail[i].theres_more = &avail[i + 1];
1558 }
1559 avail[i - 1].theres_more = NULL;
1560 sort_memlist(avail);
1561
1562 mlist = &avail[0];
1563 i = 0;
1564 bytes = mlist->num_bytes;
1565 base_paddr = mlist->start_adr;
1566
1567 sp_banks[0].base_addr = base_paddr;
1568 sp_banks[0].num_bytes = bytes;
1569
1570 while (mlist->theres_more != NULL){
1571 i++;
1572 mlist = mlist->theres_more;
1573 bytes = mlist->num_bytes;
1574 if (i >= SPARC_PHYS_BANKS-1) {
1575 printk ("The machine has more banks than "
1576 "this kernel can support\n"
1577 "Increase the SPARC_PHYS_BANKS "
1578 "setting (currently %d)\n",
1579 SPARC_PHYS_BANKS);
1580 i = SPARC_PHYS_BANKS-1;
1581 break;
1582 }
1583
1584 sp_banks[i].base_addr = mlist->start_adr;
1585 sp_banks[i].num_bytes = mlist->num_bytes;
1586 }
1587
1588 i++;
1589 sp_banks[i].base_addr = 0xdeadbeefbeefdeadUL;
1590 sp_banks[i].num_bytes = 0;
1591
1592 for (i = 0; sp_banks[i].num_bytes != 0; i++)
1593 sp_banks[i].num_bytes &= PAGE_MASK;
1594}
1595
1596static void __init taint_real_pages(void) 1574static void __init taint_real_pages(void)
1597{ 1575{
1598 struct sparc_phys_banks saved_sp_banks[SPARC_PHYS_BANKS];
1599 int i; 1576 int i;
1600 1577
1601 for (i = 0; i < SPARC_PHYS_BANKS; i++) { 1578 read_obp_memory("available", &pavail_rescan[0], &pavail_rescan_ents);
1602 saved_sp_banks[i].base_addr =
1603 sp_banks[i].base_addr;
1604 saved_sp_banks[i].num_bytes =
1605 sp_banks[i].num_bytes;
1606 }
1607
1608 rescan_sp_banks();
1609 1579
1610 /* Find changes discovered in the sp_bank rescan and 1580 /* Find changes discovered in the physmem available rescan and
1611 * reserve the lost portions in the bootmem maps. 1581 * reserve the lost portions in the bootmem maps.
1612 */ 1582 */
1613 for (i = 0; saved_sp_banks[i].num_bytes; i++) { 1583 for (i = 0; i < pavail_ents; i++) {
1614 unsigned long old_start, old_end; 1584 unsigned long old_start, old_end;
1615 1585
1616 old_start = saved_sp_banks[i].base_addr; 1586 old_start = pavail[i].phys_addr;
1617 old_end = old_start + 1587 old_end = old_start +
1618 saved_sp_banks[i].num_bytes; 1588 pavail[i].reg_size;
1619 while (old_start < old_end) { 1589 while (old_start < old_end) {
1620 int n; 1590 int n;
1621 1591
1622 for (n = 0; sp_banks[n].num_bytes; n++) { 1592 for (n = 0; pavail_rescan_ents; n++) {
1623 unsigned long new_start, new_end; 1593 unsigned long new_start, new_end;
1624 1594
1625 new_start = sp_banks[n].base_addr; 1595 new_start = pavail_rescan[n].phys_addr;
1626 new_end = new_start + sp_banks[n].num_bytes; 1596 new_end = new_start +
1597 pavail_rescan[n].reg_size;
1627 1598
1628 if (new_start <= old_start && 1599 if (new_start <= old_start &&
1629 new_end >= (old_start + PAGE_SIZE)) { 1600 new_end >= (old_start + PAGE_SIZE)) {
1630 set_bit (old_start >> 22, 1601 set_bit(old_start >> 22,
1631 sparc64_valid_addr_bitmap); 1602 sparc64_valid_addr_bitmap);
1632 goto do_next_page; 1603 goto do_next_page;
1633 } 1604 }
1634 } 1605 }
diff --git a/arch/sparc64/prom/Makefile b/arch/sparc64/prom/Makefile
index c7898a5ee456..3d33ed27bc27 100644
--- a/arch/sparc64/prom/Makefile
+++ b/arch/sparc64/prom/Makefile
@@ -6,5 +6,5 @@
6EXTRA_AFLAGS := -ansi 6EXTRA_AFLAGS := -ansi
7EXTRA_CFLAGS := -Werror 7EXTRA_CFLAGS := -Werror
8 8
9lib-y := bootstr.o devops.o init.o memory.o misc.o \ 9lib-y := bootstr.o devops.o init.o misc.o \
10 tree.o console.o printf.o p1275.o cif.o 10 tree.o console.o printf.o p1275.o cif.o
diff --git a/arch/sparc64/prom/init.c b/arch/sparc64/prom/init.c
index 8b4b622d0909..f3cc2d8578b2 100644
--- a/arch/sparc64/prom/init.c
+++ b/arch/sparc64/prom/init.c
@@ -27,7 +27,6 @@ int prom_chosen_node;
27 * failure. It gets passed the pointer to the PROM vector. 27 * failure. It gets passed the pointer to the PROM vector.
28 */ 28 */
29 29
30extern void prom_meminit(void);
31extern void prom_cif_init(void *, void *); 30extern void prom_cif_init(void *, void *);
32 31
33void __init prom_init(void *cif_handler, void *cif_stack) 32void __init prom_init(void *cif_handler, void *cif_stack)
@@ -90,8 +89,6 @@ void __init prom_init(void *cif_handler, void *cif_stack)
90 89
91 printk ("PROMLIB: Sun IEEE Boot Prom %s\n", buffer + bufadjust); 90 printk ("PROMLIB: Sun IEEE Boot Prom %s\n", buffer + bufadjust);
92 91
93 prom_meminit();
94
95 /* Initialization successful. */ 92 /* Initialization successful. */
96 return; 93 return;
97 94
diff --git a/arch/sparc64/prom/memory.c b/arch/sparc64/prom/memory.c
deleted file mode 100644
index f4a8143e052c..000000000000
--- a/arch/sparc64/prom/memory.c
+++ /dev/null
@@ -1,152 +0,0 @@
1/* $Id: memory.c,v 1.5 1999/08/31 06:55:04 davem Exp $
2 * memory.c: Prom routine for acquiring various bits of information
3 * about RAM on the machine, both virtual and physical.
4 *
5 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
6 * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
7 */
8
9#include <linux/kernel.h>
10#include <linux/init.h>
11
12#include <asm/openprom.h>
13#include <asm/oplib.h>
14
15/* This routine, for consistency, returns the ram parameters in the
16 * V0 prom memory descriptor format. I choose this format because I
17 * think it was the easiest to work with. I feel the religious
18 * arguments now... ;) Also, I return the linked lists sorted to
19 * prevent paging_init() upset stomach as I have not yet written
20 * the pepto-bismol kernel module yet.
21 */
22
23struct linux_prom64_registers prom_reg_memlist[64];
24struct linux_prom64_registers prom_reg_tmp[64];
25
26struct linux_mlist_p1275 prom_phys_total[64];
27struct linux_mlist_p1275 prom_prom_taken[64];
28struct linux_mlist_p1275 prom_phys_avail[64];
29
30struct linux_mlist_p1275 *prom_ptot_ptr = prom_phys_total;
31struct linux_mlist_p1275 *prom_ptak_ptr = prom_prom_taken;
32struct linux_mlist_p1275 *prom_pavl_ptr = prom_phys_avail;
33
34struct linux_mem_p1275 prom_memlist;
35
36
37/* Internal Prom library routine to sort a linux_mlist_p1275 memory
38 * list. Used below in initialization.
39 */
40static void __init
41prom_sortmemlist(struct linux_mlist_p1275 *thislist)
42{
43 int swapi = 0;
44 int i, mitr;
45 unsigned long tmpaddr, tmpsize;
46 unsigned long lowest;
47
48 for(i=0; thislist[i].theres_more; i++) {
49 lowest = thislist[i].start_adr;
50 for(mitr = i+1; thislist[mitr-1].theres_more; mitr++)
51 if(thislist[mitr].start_adr < lowest) {
52 lowest = thislist[mitr].start_adr;
53 swapi = mitr;
54 }
55 if(lowest == thislist[i].start_adr) continue;
56 tmpaddr = thislist[swapi].start_adr;
57 tmpsize = thislist[swapi].num_bytes;
58 for(mitr = swapi; mitr > i; mitr--) {
59 thislist[mitr].start_adr = thislist[mitr-1].start_adr;
60 thislist[mitr].num_bytes = thislist[mitr-1].num_bytes;
61 }
62 thislist[i].start_adr = tmpaddr;
63 thislist[i].num_bytes = tmpsize;
64 }
65}
66
67/* Initialize the memory lists based upon the prom version. */
68void __init prom_meminit(void)
69{
70 int node = 0;
71 unsigned int iter, num_regs;
72
73 node = prom_finddevice("/memory");
74 num_regs = prom_getproperty(node, "available",
75 (char *) prom_reg_memlist,
76 sizeof(prom_reg_memlist));
77 num_regs = (num_regs/sizeof(struct linux_prom64_registers));
78 for(iter=0; iter<num_regs; iter++) {
79 prom_phys_avail[iter].start_adr =
80 prom_reg_memlist[iter].phys_addr;
81 prom_phys_avail[iter].num_bytes =
82 prom_reg_memlist[iter].reg_size;
83 prom_phys_avail[iter].theres_more =
84 &prom_phys_avail[iter+1];
85 }
86 prom_phys_avail[iter-1].theres_more = NULL;
87
88 num_regs = prom_getproperty(node, "reg",
89 (char *) prom_reg_memlist,
90 sizeof(prom_reg_memlist));
91 num_regs = (num_regs/sizeof(struct linux_prom64_registers));
92 for(iter=0; iter<num_regs; iter++) {
93 prom_phys_total[iter].start_adr =
94 prom_reg_memlist[iter].phys_addr;
95 prom_phys_total[iter].num_bytes =
96 prom_reg_memlist[iter].reg_size;
97 prom_phys_total[iter].theres_more =
98 &prom_phys_total[iter+1];
99 }
100 prom_phys_total[iter-1].theres_more = NULL;
101
102 node = prom_finddevice("/virtual-memory");
103 num_regs = prom_getproperty(node, "available",
104 (char *) prom_reg_memlist,
105 sizeof(prom_reg_memlist));
106 num_regs = (num_regs/sizeof(struct linux_prom64_registers));
107
108 /* Convert available virtual areas to taken virtual
109 * areas. First sort, then convert.
110 */
111 for(iter=0; iter<num_regs; iter++) {
112 prom_prom_taken[iter].start_adr =
113 prom_reg_memlist[iter].phys_addr;
114 prom_prom_taken[iter].num_bytes =
115 prom_reg_memlist[iter].reg_size;
116 prom_prom_taken[iter].theres_more =
117 &prom_prom_taken[iter+1];
118 }
119 prom_prom_taken[iter-1].theres_more = NULL;
120
121 prom_sortmemlist(prom_prom_taken);
122
123 /* Finally, convert. */
124 for(iter=0; iter<num_regs; iter++) {
125 prom_prom_taken[iter].start_adr =
126 prom_prom_taken[iter].start_adr +
127 prom_prom_taken[iter].num_bytes;
128 prom_prom_taken[iter].num_bytes =
129 prom_prom_taken[iter+1].start_adr -
130 prom_prom_taken[iter].start_adr;
131 }
132 prom_prom_taken[iter-1].num_bytes =
133 -1UL - prom_prom_taken[iter-1].start_adr;
134
135 /* Sort the other two lists. */
136 prom_sortmemlist(prom_phys_total);
137 prom_sortmemlist(prom_phys_avail);
138
139 /* Link all the lists into the top-level descriptor. */
140 prom_memlist.p1275_totphys=&prom_ptot_ptr;
141 prom_memlist.p1275_prommap=&prom_ptak_ptr;
142 prom_memlist.p1275_available=&prom_pavl_ptr;
143}
144
145/* This returns a pointer to our libraries internal p1275 format
146 * memory descriptor.
147 */
148struct linux_mem_p1275 *
149prom_meminfo(void)
150{
151 return &prom_memlist;
152}