aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@pobox.com>2005-10-13 21:22:27 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-10-13 21:22:27 -0400
commit59aee3c2a1e69fe5062bd1facb72d6fcea3f3f8f (patch)
treeb337d73229a69e399d4e4f7128b33ce734660e35 /arch/sparc64
parent0d69ae5fb7eb9ba3b54cf0ba4ef5ae591f31eef7 (diff)
parent046d20b73960b7a2474b6d5e920d54c3fd7c23fe (diff)
Merge branch 'master'
Diffstat (limited to 'arch/sparc64')
-rw-r--r--arch/sparc64/kernel/dtlb_base.S14
-rw-r--r--arch/sparc64/kernel/dtlb_prot.S12
-rw-r--r--arch/sparc64/kernel/entry.S82
-rw-r--r--arch/sparc64/kernel/etrap.S51
-rw-r--r--arch/sparc64/kernel/head.S191
-rw-r--r--arch/sparc64/kernel/irq.c1
-rw-r--r--arch/sparc64/kernel/itlb_base.S26
-rw-r--r--arch/sparc64/kernel/ktlb.S92
-rw-r--r--arch/sparc64/kernel/power.c64
-rw-r--r--arch/sparc64/kernel/rtrap.S30
-rw-r--r--arch/sparc64/kernel/setup.c8
-rw-r--r--arch/sparc64/kernel/trampoline.S15
-rw-r--r--arch/sparc64/kernel/winfixup.S33
-rw-r--r--arch/sparc64/lib/VISsave.S8
-rw-r--r--arch/sparc64/mm/init.c255
15 files changed, 372 insertions, 510 deletions
diff --git a/arch/sparc64/kernel/dtlb_base.S b/arch/sparc64/kernel/dtlb_base.S
index 702d349c1e88..6528786840c0 100644
--- a/arch/sparc64/kernel/dtlb_base.S
+++ b/arch/sparc64/kernel/dtlb_base.S
@@ -53,19 +53,18 @@
53 * be guaranteed to be 0 ... mmu_context.h does guarantee this 53 * be guaranteed to be 0 ... mmu_context.h does guarantee this
54 * by only using 10 bits in the hwcontext value. 54 * by only using 10 bits in the hwcontext value.
55 */ 55 */
56#define CREATE_VPTE_OFFSET1(r1, r2) 56#define CREATE_VPTE_OFFSET1(r1, r2) nop
57#define CREATE_VPTE_OFFSET2(r1, r2) \ 57#define CREATE_VPTE_OFFSET2(r1, r2) \
58 srax r1, 10, r2 58 srax r1, 10, r2
59#define CREATE_VPTE_NOP nop
60#else 59#else
61#define CREATE_VPTE_OFFSET1(r1, r2) \ 60#define CREATE_VPTE_OFFSET1(r1, r2) \
62 srax r1, PAGE_SHIFT, r2 61 srax r1, PAGE_SHIFT, r2
63#define CREATE_VPTE_OFFSET2(r1, r2) \ 62#define CREATE_VPTE_OFFSET2(r1, r2) \
64 sllx r2, 3, r2 63 sllx r2, 3, r2
65#define CREATE_VPTE_NOP
66#endif 64#endif
67 65
68/* DTLB ** ICACHE line 1: Quick user TLB misses */ 66/* DTLB ** ICACHE line 1: Quick user TLB misses */
67 mov TLB_SFSR, %g1
69 ldxa [%g1 + %g1] ASI_DMMU, %g4 ! Get TAG_ACCESS 68 ldxa [%g1 + %g1] ASI_DMMU, %g4 ! Get TAG_ACCESS
70 andcc %g4, TAG_CONTEXT_BITS, %g0 ! From Nucleus? 69 andcc %g4, TAG_CONTEXT_BITS, %g0 ! From Nucleus?
71from_tl1_trap: 70from_tl1_trap:
@@ -74,18 +73,16 @@ from_tl1_trap:
74 be,pn %xcc, kvmap ! Yep, special processing 73 be,pn %xcc, kvmap ! Yep, special processing
75 CREATE_VPTE_OFFSET2(%g4, %g6) ! Create VPTE offset 74 CREATE_VPTE_OFFSET2(%g4, %g6) ! Create VPTE offset
76 cmp %g5, 4 ! Last trap level? 75 cmp %g5, 4 ! Last trap level?
77 be,pn %xcc, longpath ! Yep, cannot risk VPTE miss
78 nop ! delay slot
79 76
80/* DTLB ** ICACHE line 2: User finish + quick kernel TLB misses */ 77/* DTLB ** ICACHE line 2: User finish + quick kernel TLB misses */
78 be,pn %xcc, longpath ! Yep, cannot risk VPTE miss
79 nop ! delay slot
81 ldxa [%g3 + %g6] ASI_S, %g5 ! Load VPTE 80 ldxa [%g3 + %g6] ASI_S, %g5 ! Load VPTE
821: brgez,pn %g5, longpath ! Invalid, branch out 811: brgez,pn %g5, longpath ! Invalid, branch out
83 nop ! Delay-slot 82 nop ! Delay-slot
849: stxa %g5, [%g0] ASI_DTLB_DATA_IN ! Reload TLB 839: stxa %g5, [%g0] ASI_DTLB_DATA_IN ! Reload TLB
85 retry ! Trap return 84 retry ! Trap return
86 nop 85 nop
87 nop
88 nop
89 86
90/* DTLB ** ICACHE line 3: winfixups+real_faults */ 87/* DTLB ** ICACHE line 3: winfixups+real_faults */
91longpath: 88longpath:
@@ -106,8 +103,7 @@ longpath:
106 nop 103 nop
107 nop 104 nop
108 nop 105 nop
109 CREATE_VPTE_NOP 106 nop
110 107
111#undef CREATE_VPTE_OFFSET1 108#undef CREATE_VPTE_OFFSET1
112#undef CREATE_VPTE_OFFSET2 109#undef CREATE_VPTE_OFFSET2
113#undef CREATE_VPTE_NOP
diff --git a/arch/sparc64/kernel/dtlb_prot.S b/arch/sparc64/kernel/dtlb_prot.S
index d848bb7374bb..e0a920162604 100644
--- a/arch/sparc64/kernel/dtlb_prot.S
+++ b/arch/sparc64/kernel/dtlb_prot.S
@@ -14,14 +14,14 @@
14 */ 14 */
15 15
16/* PROT ** ICACHE line 1: User DTLB protection trap */ 16/* PROT ** ICACHE line 1: User DTLB protection trap */
17 stxa %g0, [%g1] ASI_DMMU ! Clear SFSR FaultValid bit 17 mov TLB_SFSR, %g1
18 membar #Sync ! Synchronize ASI stores 18 stxa %g0, [%g1] ASI_DMMU ! Clear FaultValid bit
19 rdpr %pstate, %g5 ! Move into alternate globals 19 membar #Sync ! Synchronize stores
20 rdpr %pstate, %g5 ! Move into alt-globals
20 wrpr %g5, PSTATE_AG|PSTATE_MG, %pstate 21 wrpr %g5, PSTATE_AG|PSTATE_MG, %pstate
21 rdpr %tl, %g1 ! Need to do a winfixup? 22 rdpr %tl, %g1 ! Need a winfixup?
22 cmp %g1, 1 ! Trap level >1? 23 cmp %g1, 1 ! Trap level >1?
23 mov TLB_TAG_ACCESS, %g4 ! Prepare reload of vaddr 24 mov TLB_TAG_ACCESS, %g4 ! For reload of vaddr
24 nop
25 25
26/* PROT ** ICACHE line 2: More real fault processing */ 26/* PROT ** ICACHE line 2: More real fault processing */
27 bgu,pn %xcc, winfix_trampoline ! Yes, perform winfixup 27 bgu,pn %xcc, winfix_trampoline ! Yes, perform winfixup
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 89406f9649a9..b49dcd4504b0 100644
--- a/arch/sparc64/kernel/head.S
+++ b/arch/sparc64/kernel/head.S
@@ -28,19 +28,14 @@
28#include <asm/mmu.h> 28#include <asm/mmu.h>
29 29
30/* This section from from _start to sparc64_boot_end should fit into 30/* This section from from _start to sparc64_boot_end should fit into
31 * 0x0000.0000.0040.4000 to 0x0000.0000.0040.8000 and will be sharing space 31 * 0x0000000000404000 to 0x0000000000408000.
32 * with bootup_user_stack, which is from 0x0000.0000.0040.4000 to
33 * 0x0000.0000.0040.6000 and empty_bad_page, which is from
34 * 0x0000.0000.0040.6000 to 0x0000.0000.0040.8000.
35 */ 32 */
36
37 .text 33 .text
38 .globl start, _start, stext, _stext 34 .globl start, _start, stext, _stext
39_start: 35_start:
40start: 36start:
41_stext: 37_stext:
42stext: 38stext:
43bootup_user_stack:
44! 0x0000000000404000 39! 0x0000000000404000
45 b sparc64_boot 40 b sparc64_boot
46 flushw /* Flush register file. */ 41 flushw /* Flush register file. */
@@ -191,8 +186,9 @@ prom_boot_mapping_phys_low:
191 stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 5 186 stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 5
192 stx %l2, [%sp + 2047 + 128 + 0x18] ! arg1: "translate" 187 stx %l2, [%sp + 2047 + 128 + 0x18] ! arg1: "translate"
193 stx %l5, [%sp + 2047 + 128 + 0x20] ! arg2: prom_mmu_ihandle_cache 188 stx %l5, [%sp + 2047 + 128 + 0x20] ! arg2: prom_mmu_ihandle_cache
194 srlx %l0, 22, %l3 189 /* PAGE align */
195 sllx %l3, 22, %l3 190 srlx %l0, 13, %l3
191 sllx %l3, 13, %l3
196 stx %l3, [%sp + 2047 + 128 + 0x28] ! arg3: vaddr, our PC 192 stx %l3, [%sp + 2047 + 128 + 0x28] ! arg3: vaddr, our PC
197 stx %g0, [%sp + 2047 + 128 + 0x30] ! res1 193 stx %g0, [%sp + 2047 + 128 + 0x30] ! res1
198 stx %g0, [%sp + 2047 + 128 + 0x38] ! res2 194 stx %g0, [%sp + 2047 + 128 + 0x38] ! res2
@@ -211,6 +207,9 @@ prom_boot_mapping_phys_low:
211 ldx [%sp + 2047 + 128 + 0x48], %l2 ! physaddr high 207 ldx [%sp + 2047 + 128 + 0x48], %l2 ! physaddr high
212 stx %l2, [%l4 + 0x0] 208 stx %l2, [%l4 + 0x0]
213 ldx [%sp + 2047 + 128 + 0x50], %l3 ! physaddr low 209 ldx [%sp + 2047 + 128 + 0x50], %l3 ! physaddr low
210 /* 4MB align */
211 srlx %l3, 22, %l3
212 sllx %l3, 22, %l3
214 stx %l3, [%l4 + 0x8] 213 stx %l3, [%l4 + 0x8]
215 214
216 /* Leave service as-is, "call-method" */ 215 /* Leave service as-is, "call-method" */
@@ -325,23 +324,7 @@ cheetah_tlb_fixup:
3251: sethi %hi(tlb_type), %g1 3241: sethi %hi(tlb_type), %g1
326 stw %g2, [%g1 + %lo(tlb_type)] 325 stw %g2, [%g1 + %lo(tlb_type)]
327 326
328 BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,1f) 327 /* 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 328 call cheetah_patch_copyops
346 nop 329 nop
347 call cheetah_patch_copy_page 330 call cheetah_patch_copy_page
@@ -398,32 +381,78 @@ tlb_fixup_done:
398 nop 381 nop
399 /* Not reached... */ 382 /* Not reached... */
400 383
401/* IMPORTANT NOTE: Whenever making changes here, check 384 /* This is meant to allow the sharing of this code between
402 * trampoline.S as well. -jj */ 385 * boot processor invocation (via setup_tba() below) and
403 .globl setup_tba 386 * secondary processor startup (via trampoline.S). The
404setup_tba: /* i0 = is_starfire */ 387 * former does use this code, the latter does not yet due
405 save %sp, -160, %sp 388 * to some complexities. That should be fixed up at some
389 * point.
390 *
391 * There used to be enormous complexity wrt. transferring
392 * over from the firwmare's trap table to the Linux kernel's.
393 * For example, there was a chicken & egg problem wrt. building
394 * the OBP page tables, yet needing to be on the Linux kernel
395 * trap table (to translate PAGE_OFFSET addresses) in order to
396 * do that.
397 *
398 * We now handle OBP tlb misses differently, via linear lookups
399 * into the prom_trans[] array. So that specific problem no
400 * longer exists. Yet, unfortunately there are still some issues
401 * preventing trampoline.S from using this code... ho hum.
402 */
403 .globl setup_trap_table
404setup_trap_table:
405 save %sp, -192, %sp
406 406
407 rdpr %tba, %g7 407 /* Force interrupts to be disabled. */
408 sethi %hi(prom_tba), %o1 408 rdpr %pstate, %o1
409 or %o1, %lo(prom_tba), %o1 409 andn %o1, PSTATE_IE, %o1
410 stx %g7, [%o1] 410 wrpr %o1, 0x0, %pstate
411 wrpr %g0, 15, %pil
412
413 /* Make the firmware call to jump over to the Linux trap table. */
414 call prom_set_trap_table
415 sethi %hi(sparc64_ttable_tl0), %o0
416
417 /* Start using proper page size encodings in ctx register. */
418 sethi %hi(sparc64_kern_pri_context), %g3
419 ldx [%g3 + %lo(sparc64_kern_pri_context)], %g2
420 mov PRIMARY_CONTEXT, %g1
421 stxa %g2, [%g1] ASI_DMMU
422 membar #Sync
423
424 /* The Linux trap handlers expect various trap global registers
425 * to be setup with some fixed values. So here we set these
426 * up very carefully. These globals are:
427 *
428 * Alternate Globals (PSTATE_AG):
429 *
430 * %g6 --> current_thread_info()
431 *
432 * MMU Globals (PSTATE_MG):
433 *
434 * %g1 --> TLB_SFSR
435 * %g2 --> ((_PAGE_VALID | _PAGE_SZ4MB |
436 * _PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W)
437 * ^ 0xfffff80000000000)
438 * (this %g2 value is used for computing the PAGE_OFFSET kernel
439 * TLB entries quickly, the virtual address of the fault XOR'd
440 * with this %g2 value is the PTE to load into the TLB)
441 * %g3 --> VPTE_BASE_CHEETAH or VPTE_BASE_SPITFIRE
442 *
443 * Interrupt Globals (PSTATE_IG, setup by init_irqwork_curcpu()):
444 *
445 * %g6 --> __irq_work[smp_processor_id()]
446 */
411 447
412 /* Setup "Linux" globals 8-) */
413 rdpr %pstate, %o1 448 rdpr %pstate, %o1
414 mov %g6, %o2 449 mov %g6, %o2
415 wrpr %o1, (PSTATE_AG|PSTATE_IE), %pstate 450 wrpr %o1, PSTATE_AG, %pstate
416 sethi %hi(sparc64_ttable_tl0), %g1
417 wrpr %g1, %tba
418 mov %o2, %g6 451 mov %o2, %g6
419 452
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) 453#define KERN_HIGHBITS ((_PAGE_VALID|_PAGE_SZ4MB)^0xfffff80000000000)
425#define KERN_LOWBITS (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W) 454#define KERN_LOWBITS (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W)
426 455 wrpr %o1, PSTATE_MG, %pstate
427 mov TSB_REG, %g1 456 mov TSB_REG, %g1
428 stxa %g0, [%g1] ASI_DMMU 457 stxa %g0, [%g1] ASI_DMMU
429 membar #Sync 458 membar #Sync
@@ -435,17 +464,17 @@ setup_tba: /* i0 = is_starfire */
435 sllx %g2, 32, %g2 464 sllx %g2, 32, %g2
436 or %g2, KERN_LOWBITS, %g2 465 or %g2, KERN_LOWBITS, %g2
437 466
438 BRANCH_IF_ANY_CHEETAH(g3,g7,cheetah_vpte_base) 467 BRANCH_IF_ANY_CHEETAH(g3,g7,8f)
439 ba,pt %xcc, spitfire_vpte_base 468 ba,pt %xcc, 9f
440 nop 469 nop
441 470
442cheetah_vpte_base: 4718:
443 sethi %uhi(VPTE_BASE_CHEETAH), %g3 472 sethi %uhi(VPTE_BASE_CHEETAH), %g3
444 or %g3, %ulo(VPTE_BASE_CHEETAH), %g3 473 or %g3, %ulo(VPTE_BASE_CHEETAH), %g3
445 ba,pt %xcc, 2f 474 ba,pt %xcc, 2f
446 sllx %g3, 32, %g3 475 sllx %g3, 32, %g3
447 476
448spitfire_vpte_base: 4779:
449 sethi %uhi(VPTE_BASE_SPITFIRE), %g3 478 sethi %uhi(VPTE_BASE_SPITFIRE), %g3
450 or %g3, %ulo(VPTE_BASE_SPITFIRE), %g3 479 or %g3, %ulo(VPTE_BASE_SPITFIRE), %g3
451 sllx %g3, 32, %g3 480 sllx %g3, 32, %g3
@@ -471,48 +500,55 @@ spitfire_vpte_base:
471 sllx %o2, 32, %o2 500 sllx %o2, 32, %o2
472 wr %o2, %asr25 501 wr %o2, %asr25
473 502
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: 5032:
478 wrpr %g0, %g0, %wstate 504 wrpr %g0, %g0, %wstate
479 wrpr %o1, PSTATE_IE, %pstate 505 wrpr %o1, 0x0, %pstate
480 506
481 call init_irqwork_curcpu 507 call init_irqwork_curcpu
482 nop 508 nop
483 509
484 call prom_set_trap_table 510 /* 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 511 rdpr %pstate, %o1
502 or %o1, PSTATE_IE, %o1 512 or %o1, PSTATE_IE, %o1
503 wrpr %o1, 0, %pstate 513 wrpr %o1, 0, %pstate
514 wrpr %g0, 0x0, %pil
515
516 ret
517 restore
518
519 .globl setup_tba
520setup_tba: /* i0 = is_starfire */
521 save %sp, -192, %sp
522
523 /* The boot processor is the only cpu which invokes this
524 * routine, the other cpus set things up via trampoline.S.
525 * So save the OBP trap table address here.
526 */
527 rdpr %tba, %g7
528 sethi %hi(prom_tba), %o1
529 or %o1, %lo(prom_tba), %o1
530 stx %g7, [%o1]
531
532 call setup_trap_table
533 nop
504 534
505 ret 535 ret
506 restore 536 restore
537sparc64_boot_end:
538
539#include "systbls.S"
540#include "ktlb.S"
541#include "etrap.S"
542#include "rtrap.S"
543#include "winfixup.S"
544#include "entry.S"
507 545
508/* 546/*
509 * The following skips make sure the trap table in ttable.S is aligned 547 * The following skip makes sure the trap table in ttable.S is aligned
510 * on a 32K boundary as required by the v9 specs for TBA register. 548 * on a 32K boundary as required by the v9 specs for TBA register.
511 */ 549 */
512sparc64_boot_end: 5501:
513 .skip 0x2000 + _start - sparc64_boot_end 551 .skip 0x4000 + _start - 1b
514bootup_user_stack_end:
515 .skip 0x2000
516 552
517#ifdef CONFIG_SBUS 553#ifdef CONFIG_SBUS
518/* This is just a hack to fool make depend config.h discovering 554/* This is just a hack to fool make depend config.h discovering
@@ -524,15 +560,6 @@ bootup_user_stack_end:
524! 0x0000000000408000 560! 0x0000000000408000
525 561
526#include "ttable.S" 562#include "ttable.S"
527#include "systbls.S"
528#include "ktlb.S"
529#include "etrap.S"
530#include "rtrap.S"
531#include "winfixup.S"
532#include "entry.S"
533
534 /* This is just anal retentiveness on my part... */
535 .align 16384
536 563
537 .data 564 .data
538 .align 8 565 .align 8
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/itlb_base.S b/arch/sparc64/kernel/itlb_base.S
index b5e32dfa4fbc..4951ff8f6877 100644
--- a/arch/sparc64/kernel/itlb_base.S
+++ b/arch/sparc64/kernel/itlb_base.S
@@ -15,14 +15,12 @@
15 */ 15 */
16#define CREATE_VPTE_OFFSET1(r1, r2) \ 16#define CREATE_VPTE_OFFSET1(r1, r2) \
17 srax r1, 10, r2 17 srax r1, 10, r2
18#define CREATE_VPTE_OFFSET2(r1, r2) 18#define CREATE_VPTE_OFFSET2(r1, r2) nop
19#define CREATE_VPTE_NOP nop
20#else /* PAGE_SHIFT */ 19#else /* PAGE_SHIFT */
21#define CREATE_VPTE_OFFSET1(r1, r2) \ 20#define CREATE_VPTE_OFFSET1(r1, r2) \
22 srax r1, PAGE_SHIFT, r2 21 srax r1, PAGE_SHIFT, r2
23#define CREATE_VPTE_OFFSET2(r1, r2) \ 22#define CREATE_VPTE_OFFSET2(r1, r2) \
24 sllx r2, 3, r2 23 sllx r2, 3, r2
25#define CREATE_VPTE_NOP
26#endif /* PAGE_SHIFT */ 24#endif /* PAGE_SHIFT */
27 25
28 26
@@ -36,6 +34,7 @@
36 */ 34 */
37 35
38/* ITLB ** ICACHE line 1: Quick user TLB misses */ 36/* ITLB ** ICACHE line 1: Quick user TLB misses */
37 mov TLB_SFSR, %g1
39 ldxa [%g1 + %g1] ASI_IMMU, %g4 ! Get TAG_ACCESS 38 ldxa [%g1 + %g1] ASI_IMMU, %g4 ! Get TAG_ACCESS
40 CREATE_VPTE_OFFSET1(%g4, %g6) ! Create VPTE offset 39 CREATE_VPTE_OFFSET1(%g4, %g6) ! Create VPTE offset
41 CREATE_VPTE_OFFSET2(%g4, %g6) ! Create VPTE offset 40 CREATE_VPTE_OFFSET2(%g4, %g6) ! Create VPTE offset
@@ -43,41 +42,38 @@
431: brgez,pn %g5, 3f ! Not valid, branch out 421: brgez,pn %g5, 3f ! Not valid, branch out
44 sethi %hi(_PAGE_EXEC), %g4 ! Delay-slot 43 sethi %hi(_PAGE_EXEC), %g4 ! Delay-slot
45 andcc %g5, %g4, %g0 ! Executable? 44 andcc %g5, %g4, %g0 ! Executable?
45
46/* ITLB ** ICACHE line 2: Real faults */
46 be,pn %xcc, 3f ! Nope, branch. 47 be,pn %xcc, 3f ! Nope, branch.
47 nop ! Delay-slot 48 nop ! Delay-slot
482: stxa %g5, [%g0] ASI_ITLB_DATA_IN ! Load PTE into TLB 492: stxa %g5, [%g0] ASI_ITLB_DATA_IN ! Load PTE into TLB
49 retry ! Trap return 50 retry ! Trap return
503: rdpr %pstate, %g4 ! Move into alternate globals 513: rdpr %pstate, %g4 ! Move into alt-globals
51
52/* ITLB ** ICACHE line 2: Real faults */
53 wrpr %g4, PSTATE_AG|PSTATE_MG, %pstate 52 wrpr %g4, PSTATE_AG|PSTATE_MG, %pstate
54 rdpr %tpc, %g5 ! And load faulting VA 53 rdpr %tpc, %g5 ! And load faulting VA
55 mov FAULT_CODE_ITLB, %g4 ! It was read from ITLB 54 mov FAULT_CODE_ITLB, %g4 ! It was read from ITLB
56sparc64_realfault_common: ! Called by TL0 dtlb_miss too 55
56/* ITLB ** ICACHE line 3: Finish faults */
57sparc64_realfault_common: ! Called by dtlb_miss
57 stb %g4, [%g6 + TI_FAULT_CODE] 58 stb %g4, [%g6 + TI_FAULT_CODE]
58 stx %g5, [%g6 + TI_FAULT_ADDR] 59 stx %g5, [%g6 + TI_FAULT_ADDR]
59 ba,pt %xcc, etrap ! Save state 60 ba,pt %xcc, etrap ! Save state
601: rd %pc, %g7 ! ... 611: rd %pc, %g7 ! ...
61 nop
62
63/* ITLB ** ICACHE line 3: Finish faults + window fixups */
64 call do_sparc64_fault ! Call fault handler 62 call do_sparc64_fault ! Call fault handler
65 add %sp, PTREGS_OFF, %o0! Compute pt_regs arg 63 add %sp, PTREGS_OFF, %o0! Compute pt_regs arg
66 ba,pt %xcc, rtrap_clr_l6 ! Restore cpu state 64 ba,pt %xcc, rtrap_clr_l6 ! Restore cpu state
67 nop 65 nop
66
67/* ITLB ** ICACHE line 4: Window fixups */
68winfix_trampoline: 68winfix_trampoline:
69 rdpr %tpc, %g3 ! Prepare winfixup TNPC 69 rdpr %tpc, %g3 ! Prepare winfixup TNPC
70 or %g3, 0x7c, %g3 ! Compute offset to branch 70 or %g3, 0x7c, %g3 ! Compute branch offset
71 wrpr %g3, %tnpc ! Write it into TNPC 71 wrpr %g3, %tnpc ! Write it into TNPC
72 done ! Do it to it 72 done ! Do it to it
73
74/* ITLB ** ICACHE line 4: Unused... */
75 nop 73 nop
76 nop 74 nop
77 nop 75 nop
78 nop 76 nop
79 CREATE_VPTE_NOP
80 77
81#undef CREATE_VPTE_OFFSET1 78#undef CREATE_VPTE_OFFSET1
82#undef CREATE_VPTE_OFFSET2 79#undef CREATE_VPTE_OFFSET2
83#undef CREATE_VPTE_NOP
diff --git a/arch/sparc64/kernel/ktlb.S b/arch/sparc64/kernel/ktlb.S
index 7796b37f478c..d9244d3c9f73 100644
--- a/arch/sparc64/kernel/ktlb.S
+++ b/arch/sparc64/kernel/ktlb.S
@@ -58,9 +58,6 @@ vpte_noent:
58 done 58 done
59 59
60vpte_insn_obp: 60vpte_insn_obp:
61 sethi %hi(prom_pmd_phys), %g5
62 ldx [%g5 + %lo(prom_pmd_phys)], %g5
63
64 /* Behave as if we are at TL0. */ 61 /* Behave as if we are at TL0. */
65 wrpr %g0, 1, %tl 62 wrpr %g0, 1, %tl
66 rdpr %tpc, %g4 /* Find original faulting iaddr */ 63 rdpr %tpc, %g4 /* Find original faulting iaddr */
@@ -71,58 +68,57 @@ vpte_insn_obp:
71 mov TLB_SFSR, %g1 68 mov TLB_SFSR, %g1
72 stxa %g4, [%g1 + %g1] ASI_IMMU 69 stxa %g4, [%g1 + %g1] ASI_IMMU
73 70
74 /* Get PMD offset. */ 71 sethi %hi(prom_trans), %g5
75 srlx %g4, 23, %g6 72 or %g5, %lo(prom_trans), %g5
76 and %g6, 0x7ff, %g6 73
77 sllx %g6, 2, %g6 741: ldx [%g5 + 0x00], %g6 ! base
78 75 brz,a,pn %g6, longpath ! no more entries, fail
79 /* Load PMD, is it valid? */ 76 mov TLB_SFSR, %g1 ! and restore %g1
80 lduwa [%g5 + %g6] ASI_PHYS_USE_EC, %g5 77 ldx [%g5 + 0x08], %g1 ! len
81 brz,pn %g5, longpath 78 add %g6, %g1, %g1 ! end
82 sllx %g5, 11, %g5 79 cmp %g6, %g4
83 80 bgu,pt %xcc, 2f
84 /* Get PTE offset. */ 81 cmp %g4, %g1
85 srlx %g4, 13, %g6 82 bgeu,pt %xcc, 2f
86 and %g6, 0x3ff, %g6 83 ldx [%g5 + 0x10], %g1 ! PTE
87 sllx %g6, 3, %g6 84
88 85 /* TLB load, restore %g1, and return from trap. */
89 /* Load PTE. */ 86 sub %g4, %g6, %g6
90 ldxa [%g5 + %g6] ASI_PHYS_USE_EC, %g5 87 add %g1, %g6, %g5
91 brgez,pn %g5, longpath 88 mov TLB_SFSR, %g1
92 nop
93
94 /* TLB load and return from trap. */
95 stxa %g5, [%g0] ASI_ITLB_DATA_IN 89 stxa %g5, [%g0] ASI_ITLB_DATA_IN
96 retry 90 retry
97 91
98kvmap_do_obp: 922: ba,pt %xcc, 1b
99 sethi %hi(prom_pmd_phys), %g5 93 add %g5, (3 * 8), %g5 ! next entry
100 ldx [%g5 + %lo(prom_pmd_phys)], %g5
101
102 /* Get PMD offset. */
103 srlx %g4, 23, %g6
104 and %g6, 0x7ff, %g6
105 sllx %g6, 2, %g6
106
107 /* Load PMD, is it valid? */
108 lduwa [%g5 + %g6] ASI_PHYS_USE_EC, %g5
109 brz,pn %g5, longpath
110 sllx %g5, 11, %g5
111
112 /* Get PTE offset. */
113 srlx %g4, 13, %g6
114 and %g6, 0x3ff, %g6
115 sllx %g6, 3, %g6
116
117 /* Load PTE. */
118 ldxa [%g5 + %g6] ASI_PHYS_USE_EC, %g5
119 brgez,pn %g5, longpath
120 nop
121 94
122 /* TLB load and return from trap. */ 95kvmap_do_obp:
96 sethi %hi(prom_trans), %g5
97 or %g5, %lo(prom_trans), %g5
98 srlx %g4, 13, %g4
99 sllx %g4, 13, %g4
100
1011: ldx [%g5 + 0x00], %g6 ! base
102 brz,a,pn %g6, longpath ! no more entries, fail
103 mov TLB_SFSR, %g1 ! and restore %g1
104 ldx [%g5 + 0x08], %g1 ! len
105 add %g6, %g1, %g1 ! end
106 cmp %g6, %g4
107 bgu,pt %xcc, 2f
108 cmp %g4, %g1
109 bgeu,pt %xcc, 2f
110 ldx [%g5 + 0x10], %g1 ! PTE
111
112 /* TLB load, restore %g1, and return from trap. */
113 sub %g4, %g6, %g6
114 add %g1, %g6, %g5
115 mov TLB_SFSR, %g1
123 stxa %g5, [%g0] ASI_DTLB_DATA_IN 116 stxa %g5, [%g0] ASI_DTLB_DATA_IN
124 retry 117 retry
125 118
1192: ba,pt %xcc, 1b
120 add %g5, (3 * 8), %g5 ! next entry
121
126/* 122/*
127 * On a first level data miss, check whether this is to the OBP range (note 123 * On a first level data miss, check whether this is to the OBP range (note
128 * that such accesses can be made by prom, as well as by kernel using 124 * that such accesses can be made by prom, as well as by kernel using
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/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 4c9c8f241748..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
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/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/mm/init.c b/arch/sparc64/mm/init.c
index 5db50524f20d..1e44ee26cee8 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -105,7 +105,7 @@ static void __init read_obp_memory(const char *property,
105 regs[i].phys_addr = base; 105 regs[i].phys_addr = base;
106 regs[i].reg_size = size; 106 regs[i].reg_size = size;
107 } 107 }
108 sort(regs, ents, sizeof(struct linux_prom64_registers), 108 sort(regs, ents, sizeof(struct linux_prom64_registers),
109 cmp_p64, NULL); 109 cmp_p64, NULL);
110} 110}
111 111
@@ -133,6 +133,12 @@ extern unsigned int sparc_ramdisk_size;
133 133
134struct page *mem_map_zero __read_mostly; 134struct page *mem_map_zero __read_mostly;
135 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
136int bigkernel = 0; 142int bigkernel = 0;
137 143
138/* XXX Tune this... */ 144/* XXX Tune this... */
@@ -361,7 +367,11 @@ struct linux_prom_translation {
361 unsigned long size; 367 unsigned long size;
362 unsigned long data; 368 unsigned long data;
363}; 369};
364static struct linux_prom_translation prom_trans[512] __initdata; 370
371/* Exported for kernel TLB miss handling in ktlb.S */
372struct linux_prom_translation prom_trans[512] __read_mostly;
373unsigned int prom_trans_ents __read_mostly;
374unsigned int swapper_pgd_zero __read_mostly;
365 375
366extern unsigned long prom_boot_page; 376extern unsigned long prom_boot_page;
367extern void prom_remap(unsigned long physpage, unsigned long virtpage, int mmu_ihandle); 377extern void prom_remap(unsigned long physpage, unsigned long virtpage, int mmu_ihandle);
@@ -371,178 +381,57 @@ extern void register_prom_callbacks(void);
371/* Exported for SMP bootup purposes. */ 381/* Exported for SMP bootup purposes. */
372unsigned long kern_locked_tte_data; 382unsigned long kern_locked_tte_data;
373 383
374/* Exported for kernel TLB miss handling in ktlb.S */
375unsigned long prom_pmd_phys __read_mostly;
376unsigned int swapper_pgd_zero __read_mostly;
377
378/* Allocate power-of-2 aligned chunks from the end of the
379 * kernel image. Return physical address.
380 */
381static inline unsigned long early_alloc_phys(unsigned long size)
382{
383 unsigned long base;
384
385 BUILD_BUG_ON(size & (size - 1));
386
387 kern_size = (kern_size + (size - 1)) & ~(size - 1);
388 base = kern_base + kern_size;
389 kern_size += size;
390
391 return base;
392}
393
394static inline unsigned long load_phys32(unsigned long pa)
395{
396 unsigned long val;
397
398 __asm__ __volatile__("lduwa [%1] %2, %0"
399 : "=&r" (val)
400 : "r" (pa), "i" (ASI_PHYS_USE_EC));
401
402 return val;
403}
404
405static inline unsigned long load_phys64(unsigned long pa)
406{
407 unsigned long val;
408
409 __asm__ __volatile__("ldxa [%1] %2, %0"
410 : "=&r" (val)
411 : "r" (pa), "i" (ASI_PHYS_USE_EC));
412
413 return val;
414}
415
416static inline void store_phys32(unsigned long pa, unsigned long val)
417{
418 __asm__ __volatile__("stwa %0, [%1] %2"
419 : /* no outputs */
420 : "r" (val), "r" (pa), "i" (ASI_PHYS_USE_EC));
421}
422
423static inline void store_phys64(unsigned long pa, unsigned long val)
424{
425 __asm__ __volatile__("stxa %0, [%1] %2"
426 : /* no outputs */
427 : "r" (val), "r" (pa), "i" (ASI_PHYS_USE_EC));
428}
429
430#define BASE_PAGE_SIZE 8192
431
432/* 384/*
433 * Translate PROM's mapping we capture at boot time into physical address. 385 * Translate PROM's mapping we capture at boot time into physical address.
434 * The second parameter is only set from prom_callback() invocations. 386 * The second parameter is only set from prom_callback() invocations.
435 */ 387 */
436unsigned long prom_virt_to_phys(unsigned long promva, int *error) 388unsigned long prom_virt_to_phys(unsigned long promva, int *error)
437{ 389{
438 unsigned long pmd_phys = (prom_pmd_phys + 390 int i;
439 ((promva >> 23) & 0x7ff) * sizeof(pmd_t));
440 unsigned long pte_phys;
441 pmd_t pmd_ent;
442 pte_t pte_ent;
443 unsigned long base;
444
445 pmd_val(pmd_ent) = load_phys32(pmd_phys);
446 if (pmd_none(pmd_ent)) {
447 if (error)
448 *error = 1;
449 return 0;
450 }
451 391
452 pte_phys = (unsigned long)pmd_val(pmd_ent) << 11UL; 392 for (i = 0; i < prom_trans_ents; i++) {
453 pte_phys += ((promva >> 13) & 0x3ff) * sizeof(pte_t); 393 struct linux_prom_translation *p = &prom_trans[i];
454 pte_val(pte_ent) = load_phys64(pte_phys); 394
455 if (!pte_present(pte_ent)) { 395 if (promva >= p->virt &&
456 if (error) 396 promva < (p->virt + p->size)) {
457 *error = 1; 397 unsigned long base = p->data & _PAGE_PADDR;
458 return 0; 398
459 } 399 if (error)
460 if (error) { 400 *error = 0;
461 *error = 0; 401 return base + (promva & (8192 - 1));
462 return pte_val(pte_ent); 402 }
463 } 403 }
464 base = pte_val(pte_ent) & _PAGE_PADDR; 404 if (error)
465 return (base + (promva & (BASE_PAGE_SIZE - 1))); 405 *error = 1;
406 return 0UL;
466} 407}
467 408
468/* The obp translations are saved based on 8k pagesize, since obp can 409/* The obp translations are saved based on 8k pagesize, since obp can
469 * use a mixture of pagesizes. Misses to the LOW_OBP_ADDRESS -> 410 * use a mixture of pagesizes. Misses to the LOW_OBP_ADDRESS ->
470 * HI_OBP_ADDRESS range are handled in entry.S and do not use the vpte 411 * HI_OBP_ADDRESS range are handled in ktlb.S and do not use the vpte
471 * scheme (also, see rant in inherit_locked_prom_mappings()). 412 * scheme (also, see rant in inherit_locked_prom_mappings()).
472 */ 413 */
473static void __init build_obp_range(unsigned long start, unsigned long end, unsigned long data)
474{
475 unsigned long vaddr;
476
477 for (vaddr = start; vaddr < end; vaddr += BASE_PAGE_SIZE) {
478 unsigned long val, pte_phys, pmd_phys;
479 pmd_t pmd_ent;
480 int i;
481
482 pmd_phys = (prom_pmd_phys +
483 (((vaddr >> 23) & 0x7ff) * sizeof(pmd_t)));
484 pmd_val(pmd_ent) = load_phys32(pmd_phys);
485 if (pmd_none(pmd_ent)) {
486 pte_phys = early_alloc_phys(BASE_PAGE_SIZE);
487
488 for (i = 0; i < BASE_PAGE_SIZE / sizeof(pte_t); i++)
489 store_phys64(pte_phys+i*sizeof(pte_t),0);
490
491 pmd_val(pmd_ent) = pte_phys >> 11UL;
492 store_phys32(pmd_phys, pmd_val(pmd_ent));
493 }
494
495 pte_phys = (unsigned long)pmd_val(pmd_ent) << 11UL;
496 pte_phys += (((vaddr >> 13) & 0x3ff) * sizeof(pte_t));
497
498 val = data;
499
500 /* Clear diag TTE bits. */
501 if (tlb_type == spitfire)
502 val &= ~0x0003fe0000000000UL;
503
504 store_phys64(pte_phys, val | _PAGE_MODIFIED);
505
506 data += BASE_PAGE_SIZE;
507 }
508}
509
510static inline int in_obp_range(unsigned long vaddr) 414static inline int in_obp_range(unsigned long vaddr)
511{ 415{
512 return (vaddr >= LOW_OBP_ADDRESS && 416 return (vaddr >= LOW_OBP_ADDRESS &&
513 vaddr < HI_OBP_ADDRESS); 417 vaddr < HI_OBP_ADDRESS);
514} 418}
515 419
516#define OBP_PMD_SIZE 2048 420static int cmp_ptrans(const void *a, const void *b)
517static void __init build_obp_pgtable(int prom_trans_ents)
518{ 421{
519 unsigned long i; 422 const struct linux_prom_translation *x = a, *y = b;
520
521 prom_pmd_phys = early_alloc_phys(OBP_PMD_SIZE);
522 for (i = 0; i < OBP_PMD_SIZE; i += 4)
523 store_phys32(prom_pmd_phys + i, 0);
524 423
525 for (i = 0; i < prom_trans_ents; i++) { 424 if (x->virt > y->virt)
526 unsigned long start, end; 425 return 1;
527 426 if (x->virt < y->virt)
528 if (!in_obp_range(prom_trans[i].virt)) 427 return -1;
529 continue; 428 return 0;
530
531 start = prom_trans[i].virt;
532 end = start + prom_trans[i].size;
533 if (end > HI_OBP_ADDRESS)
534 end = HI_OBP_ADDRESS;
535
536 build_obp_range(start, end, prom_trans[i].data);
537 }
538} 429}
539 430
540/* Read OBP translations property into 'prom_trans[]'. 431/* Read OBP translations property into 'prom_trans[]'. */
541 * Return the number of entries. 432static void __init read_obp_translations(void)
542 */
543static int __init read_obp_translations(void)
544{ 433{
545 int n, node; 434 int n, node, ents, first, last, i;
546 435
547 node = prom_finddevice("/virtual-memory"); 436 node = prom_finddevice("/virtual-memory");
548 n = prom_getproplen(node, "translations"); 437 n = prom_getproplen(node, "translations");
@@ -561,8 +450,44 @@ static int __init read_obp_translations(void)
561 prom_printf("prom_mappings: Couldn't get property.\n"); 450 prom_printf("prom_mappings: Couldn't get property.\n");
562 prom_halt(); 451 prom_halt();
563 } 452 }
453
564 n = n / sizeof(struct linux_prom_translation); 454 n = n / sizeof(struct linux_prom_translation);
565 return n; 455
456 ents = n;
457
458 sort(prom_trans, ents, sizeof(struct linux_prom_translation),
459 cmp_ptrans, NULL);
460
461 /* Now kick out all the non-OBP entries. */
462 for (i = 0; i < ents; i++) {
463 if (in_obp_range(prom_trans[i].virt))
464 break;
465 }
466 first = i;
467 for (; i < ents; i++) {
468 if (!in_obp_range(prom_trans[i].virt))
469 break;
470 }
471 last = i;
472
473 for (i = 0; i < (last - first); i++) {
474 struct linux_prom_translation *src = &prom_trans[i + first];
475 struct linux_prom_translation *dest = &prom_trans[i];
476
477 *dest = *src;
478 }
479 for (; i < ents; i++) {
480 struct linux_prom_translation *dest = &prom_trans[i];
481 dest->virt = dest->size = dest->data = 0x0UL;
482 }
483
484 prom_trans_ents = last - first;
485
486 if (tlb_type == spitfire) {
487 /* Clear diag TTE bits. */
488 for (i = 0; i < prom_trans_ents; i++)
489 prom_trans[i].data &= ~0x0003fe0000000000UL;
490 }
566} 491}
567 492
568static void __init remap_kernel(void) 493static void __init remap_kernel(void)
@@ -582,29 +507,36 @@ static void __init remap_kernel(void)
582 prom_dtlb_load(tlb_ent, tte_data, tte_vaddr); 507 prom_dtlb_load(tlb_ent, tte_data, tte_vaddr);
583 prom_itlb_load(tlb_ent, tte_data, tte_vaddr); 508 prom_itlb_load(tlb_ent, tte_data, tte_vaddr);
584 if (bigkernel) { 509 if (bigkernel) {
585 prom_dtlb_load(tlb_ent - 1, 510 tlb_ent -= 1;
511 prom_dtlb_load(tlb_ent,
586 tte_data + 0x400000, 512 tte_data + 0x400000,
587 tte_vaddr + 0x400000); 513 tte_vaddr + 0x400000);
588 prom_itlb_load(tlb_ent - 1, 514 prom_itlb_load(tlb_ent,
589 tte_data + 0x400000, 515 tte_data + 0x400000,
590 tte_vaddr + 0x400000); 516 tte_vaddr + 0x400000);
591 } 517 }
518 sparc64_highest_unlocked_tlb_ent = tlb_ent - 1;
519 if (tlb_type == cheetah_plus) {
520 sparc64_kern_pri_context = (CTX_CHEETAH_PLUS_CTX0 |
521 CTX_CHEETAH_PLUS_NUC);
522 sparc64_kern_pri_nuc_bits = CTX_CHEETAH_PLUS_NUC;
523 sparc64_kern_sec_context = CTX_CHEETAH_PLUS_CTX0;
524 }
592} 525}
593 526
527
594static void __init inherit_prom_mappings(void) 528static void __init inherit_prom_mappings(void)
595{ 529{
596 int n; 530 read_obp_translations();
597
598 n = read_obp_translations();
599 build_obp_pgtable(n);
600 531
601 /* Now fixup OBP's idea about where we really are mapped. */ 532 /* Now fixup OBP's idea about where we really are mapped. */
602 prom_printf("Remapping the kernel... "); 533 prom_printf("Remapping the kernel... ");
603 remap_kernel(); 534 remap_kernel();
604
605 prom_printf("done.\n"); 535 prom_printf("done.\n");
606 536
537 prom_printf("Registering callbacks... ");
607 register_prom_callbacks(); 538 register_prom_callbacks();
539 prom_printf("done.\n");
608} 540}
609 541
610/* The OBP specifications for sun4u mark 0xfffffffc00000000 and 542/* The OBP specifications for sun4u mark 0xfffffffc00000000 and
@@ -788,8 +720,8 @@ void inherit_locked_prom_mappings(int save_p)
788 } 720 }
789 } 721 }
790 if (tlb_type == spitfire) { 722 if (tlb_type == spitfire) {
791 int high = SPITFIRE_HIGHEST_LOCKED_TLBENT - bigkernel; 723 int high = sparc64_highest_unlocked_tlb_ent;
792 for (i = 0; i < high; i++) { 724 for (i = 0; i <= high; i++) {
793 unsigned long data; 725 unsigned long data;
794 726
795 /* Spitfire Errata #32 workaround */ 727 /* Spitfire Errata #32 workaround */
@@ -877,9 +809,9 @@ void inherit_locked_prom_mappings(int save_p)
877 } 809 }
878 } 810 }
879 } else if (tlb_type == cheetah || tlb_type == cheetah_plus) { 811 } else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
880 int high = CHEETAH_HIGHEST_LOCKED_TLBENT - bigkernel; 812 int high = sparc64_highest_unlocked_tlb_ent;
881 813
882 for (i = 0; i < high; i++) { 814 for (i = 0; i <= high; i++) {
883 unsigned long data; 815 unsigned long data;
884 816
885 data = cheetah_get_ldtlb_data(i); 817 data = cheetah_get_ldtlb_data(i);
@@ -1556,7 +1488,6 @@ void __init paging_init(void)
1556 1488
1557 swapper_pgd_zero = pgd_val(swapper_pg_dir[0]); 1489 swapper_pgd_zero = pgd_val(swapper_pg_dir[0]);
1558 1490
1559 /* Inherit non-locked OBP mappings. */
1560 inherit_prom_mappings(); 1491 inherit_prom_mappings();
1561 1492
1562 /* Ok, we can use our TLB miss and window trap handlers safely. 1493 /* Ok, we can use our TLB miss and window trap handlers safely.