diff options
author | Jeff Garzik <jgarzik@pobox.com> | 2005-10-13 21:22:27 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-10-13 21:22:27 -0400 |
commit | 59aee3c2a1e69fe5062bd1facb72d6fcea3f3f8f (patch) | |
tree | b337d73229a69e399d4e4f7128b33ce734660e35 /arch/sparc64 | |
parent | 0d69ae5fb7eb9ba3b54cf0ba4ef5ae591f31eef7 (diff) | |
parent | 046d20b73960b7a2474b6d5e920d54c3fd7c23fe (diff) |
Merge branch 'master'
Diffstat (limited to 'arch/sparc64')
-rw-r--r-- | arch/sparc64/kernel/dtlb_base.S | 14 | ||||
-rw-r--r-- | arch/sparc64/kernel/dtlb_prot.S | 12 | ||||
-rw-r--r-- | arch/sparc64/kernel/entry.S | 82 | ||||
-rw-r--r-- | arch/sparc64/kernel/etrap.S | 51 | ||||
-rw-r--r-- | arch/sparc64/kernel/head.S | 191 | ||||
-rw-r--r-- | arch/sparc64/kernel/irq.c | 1 | ||||
-rw-r--r-- | arch/sparc64/kernel/itlb_base.S | 26 | ||||
-rw-r--r-- | arch/sparc64/kernel/ktlb.S | 92 | ||||
-rw-r--r-- | arch/sparc64/kernel/power.c | 64 | ||||
-rw-r--r-- | arch/sparc64/kernel/rtrap.S | 30 | ||||
-rw-r--r-- | arch/sparc64/kernel/setup.c | 8 | ||||
-rw-r--r-- | arch/sparc64/kernel/trampoline.S | 15 | ||||
-rw-r--r-- | arch/sparc64/kernel/winfixup.S | 33 | ||||
-rw-r--r-- | arch/sparc64/lib/VISsave.S | 8 | ||||
-rw-r--r-- | arch/sparc64/mm/init.c | 255 |
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? |
71 | from_tl1_trap: | 70 | from_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 |
82 | 1: brgez,pn %g5, longpath ! Invalid, branch out | 81 | 1: brgez,pn %g5, longpath ! Invalid, branch out |
83 | nop ! Delay-slot | 82 | nop ! Delay-slot |
84 | 9: stxa %g5, [%g0] ASI_DTLB_DATA_IN ! Reload TLB | 83 | 9: 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 */ |
91 | longpath: | 88 | longpath: |
@@ -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 |
35 | do_fpdis: | 35 | do_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 | ||
53 | 1: ldub [%g6 + TI_FPSAVED], %g5 ! Load Group | 53 | 1: 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 |
59 | 1: andcc %g5, FPRS_DL, %g0 ! IEU1 | 59 | 1: 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 |
100 | cplus_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 |
122 | 2: andcc %g5, FPRS_DU, %g0 | 123 | 2: 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 |
129 | cplus_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 |
153 | 3: mov SECONDARY_CONTEXT, %g3 | 155 | 3: 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 |
156 | cplus_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 |
322 | cplus_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 | ||
344 | cplus_fptrap_1: | ||
345 | sethi %hi(CTX_CHEETAH_PLUS_CTX0), %g2 | ||
346 | |||
347 | .globl cheetah_plus_patch_fpdis | ||
348 | cheetah_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 |
71 | cplus_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 | ||
74 | cplus_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 |
218 | cplus_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 | ||
221 | cplus_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 | |||
268 | cplus_einsn_1: | ||
269 | sethi %uhi(CTX_CHEETAH_PLUS_NUC), %g3 | ||
270 | cplus_einsn_2: | ||
271 | sethi %hi(CTX_CHEETAH_PLUS_CTX0), %g2 | ||
272 | |||
273 | .globl cheetah_plus_patch_etrap | ||
274 | cheetah_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: |
40 | start: | 36 | start: |
41 | _stext: | 37 | _stext: |
42 | stext: | 38 | stext: |
43 | bootup_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: | |||
325 | 1: sethi %hi(tlb_type), %g1 | 324 | 1: 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 | |||
332 | 1: /* 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 | |||
344 | 2: /* 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 |
404 | setup_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 | ||
404 | setup_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 | ||
442 | cheetah_vpte_base: | 471 | 8: |
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 | ||
448 | spitfire_vpte_base: | 477 | 9: |
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 | */ | ||
477 | 2: | 503 | 2: |
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 | |||
491 | 1: /* 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 | |||
500 | 2: | ||
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 | ||
520 | setup_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 |
537 | sparc64_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 | */ |
512 | sparc64_boot_end: | 550 | 1: |
513 | .skip 0x2000 + _start - sparc64_boot_end | 551 | .skip 0x4000 + _start - 1b |
514 | bootup_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 @@ | |||
43 | 1: brgez,pn %g5, 3f ! Not valid, branch out | 42 | 1: 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 |
48 | 2: stxa %g5, [%g0] ASI_ITLB_DATA_IN ! Load PTE into TLB | 49 | 2: stxa %g5, [%g0] ASI_ITLB_DATA_IN ! Load PTE into TLB |
49 | retry ! Trap return | 50 | retry ! Trap return |
50 | 3: rdpr %pstate, %g4 ! Move into alternate globals | 51 | 3: 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 |
56 | sparc64_realfault_common: ! Called by TL0 dtlb_miss too | 55 | |
56 | /* ITLB ** ICACHE line 3: Finish faults */ | ||
57 | sparc64_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 |
60 | 1: rd %pc, %g7 ! ... | 61 | 1: 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 */ | ||
68 | winfix_trampoline: | 68 | winfix_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 | ||
60 | vpte_insn_obp: | 60 | vpte_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 | 74 | 1: 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 | ||
98 | kvmap_do_obp: | 92 | 2: 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. */ | 95 | kvmap_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 | |||
101 | 1: 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 | ||
119 | 2: 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 | ||
103 | static int __init has_button_interrupt(struct linux_ebus_device *edev) | 104 | static 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 | ||
113 | void __init power_init(void) | 114 | static 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 | |||
132 | static 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 | |||
150 | void __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 | ||
131 | found: | 169 | found: |
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 |
259 | cplus_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 | ||
324 | 1: andcc %l2, FPRS_DU, %g0 | 324 | 1: 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 | |||
331 | 1: membar #Sync | 331 | 1: membar #Sync |
332 | ldx [%o1 + %o5], %fsr | 332 | ldx [%o1 + %o5], %fsr |
333 | 2: stb %l5, [%g6 + TI_FPDEPTH] | 333 | 2: stb %l5, [%g6 + TI_FPDEPTH] |
334 | ba,pt %xcc, rt_continue | 334 | ba,pt %xcc, rt_continue |
335 | nop | 335 | nop |
336 | 5: wr %g0, FPRS_FEF, %fprs | 336 | 5: 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 | |||
349 | cplus_rinsn_1: | ||
350 | sethi %uhi(CTX_CHEETAH_PLUS_NUC), %l1 | ||
351 | |||
352 | .globl cheetah_plus_patch_rtrap | ||
353 | cheetah_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 | |||
343 | 1: /* 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 | ||
352 | 2: | ||
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 | ||
18 | set_pcontext: | 18 | set_pcontext: |
19 | cplus_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 | ||
23 | cplus_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 | ||
31 | cplus_wfinsn_1: | ||
32 | sethi %uhi(CTX_CHEETAH_PLUS_NUC), %l1 | ||
33 | cplus_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 | ||
401 | cheetah_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 |
70 | 4: add %g1, 128, %g1 | 71 | 4: 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 | ||
134 | struct page *mem_map_zero __read_mostly; | 134 | struct page *mem_map_zero __read_mostly; |
135 | 135 | ||
136 | unsigned int sparc64_highest_unlocked_tlb_ent __read_mostly; | ||
137 | |||
138 | unsigned long sparc64_kern_pri_context __read_mostly; | ||
139 | unsigned long sparc64_kern_pri_nuc_bits __read_mostly; | ||
140 | unsigned long sparc64_kern_sec_context __read_mostly; | ||
141 | |||
136 | int bigkernel = 0; | 142 | int 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 | }; |
364 | static struct linux_prom_translation prom_trans[512] __initdata; | 370 | |
371 | /* Exported for kernel TLB miss handling in ktlb.S */ | ||
372 | struct linux_prom_translation prom_trans[512] __read_mostly; | ||
373 | unsigned int prom_trans_ents __read_mostly; | ||
374 | unsigned int swapper_pgd_zero __read_mostly; | ||
365 | 375 | ||
366 | extern unsigned long prom_boot_page; | 376 | extern unsigned long prom_boot_page; |
367 | extern void prom_remap(unsigned long physpage, unsigned long virtpage, int mmu_ihandle); | 377 | extern 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. */ |
372 | unsigned long kern_locked_tte_data; | 382 | unsigned long kern_locked_tte_data; |
373 | 383 | ||
374 | /* Exported for kernel TLB miss handling in ktlb.S */ | ||
375 | unsigned long prom_pmd_phys __read_mostly; | ||
376 | unsigned 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 | */ | ||
381 | static 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 | |||
394 | static 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 | |||
405 | static 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 | |||
416 | static 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 | |||
423 | static 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 | */ |
436 | unsigned long prom_virt_to_phys(unsigned long promva, int *error) | 388 | unsigned 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 | */ |
473 | static 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 | |||
510 | static inline int in_obp_range(unsigned long vaddr) | 414 | static 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 | 420 | static int cmp_ptrans(const void *a, const void *b) |
517 | static 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. | 432 | static void __init read_obp_translations(void) |
542 | */ | ||
543 | static 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 | ||
568 | static void __init remap_kernel(void) | 493 | static 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 | |||
594 | static void __init inherit_prom_mappings(void) | 528 | static 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. |