diff options
Diffstat (limited to 'arch/sparc/kernel/smp_32.c')
-rw-r--r-- | arch/sparc/kernel/smp_32.c | 103 |
1 files changed, 73 insertions, 30 deletions
diff --git a/arch/sparc/kernel/smp_32.c b/arch/sparc/kernel/smp_32.c index 442286d83435..d5b3958be0b4 100644 --- a/arch/sparc/kernel/smp_32.c +++ b/arch/sparc/kernel/smp_32.c | |||
@@ -37,8 +37,6 @@ | |||
37 | #include "irq.h" | 37 | #include "irq.h" |
38 | 38 | ||
39 | volatile unsigned long cpu_callin_map[NR_CPUS] __cpuinitdata = {0,}; | 39 | volatile unsigned long cpu_callin_map[NR_CPUS] __cpuinitdata = {0,}; |
40 | unsigned char boot_cpu_id = 0; | ||
41 | unsigned char boot_cpu_id4 = 0; /* boot_cpu_id << 2 */ | ||
42 | 40 | ||
43 | cpumask_t smp_commenced_mask = CPU_MASK_NONE; | 41 | cpumask_t smp_commenced_mask = CPU_MASK_NONE; |
44 | 42 | ||
@@ -130,14 +128,57 @@ struct linux_prom_registers smp_penguin_ctable __cpuinitdata = { 0 }; | |||
130 | void smp_send_reschedule(int cpu) | 128 | void smp_send_reschedule(int cpu) |
131 | { | 129 | { |
132 | /* | 130 | /* |
133 | * XXX missing reschedule IPI, see scheduler_ipi() | 131 | * CPU model dependent way of implementing IPI generation targeting |
132 | * a single CPU. The trap handler needs only to do trap entry/return | ||
133 | * to call schedule. | ||
134 | */ | 134 | */ |
135 | BTFIXUP_CALL(smp_ipi_resched)(cpu); | ||
135 | } | 136 | } |
136 | 137 | ||
137 | void smp_send_stop(void) | 138 | void smp_send_stop(void) |
138 | { | 139 | { |
139 | } | 140 | } |
140 | 141 | ||
142 | void arch_send_call_function_single_ipi(int cpu) | ||
143 | { | ||
144 | /* trigger one IPI single call on one CPU */ | ||
145 | BTFIXUP_CALL(smp_ipi_single)(cpu); | ||
146 | } | ||
147 | |||
148 | void arch_send_call_function_ipi_mask(const struct cpumask *mask) | ||
149 | { | ||
150 | int cpu; | ||
151 | |||
152 | /* trigger IPI mask call on each CPU */ | ||
153 | for_each_cpu(cpu, mask) | ||
154 | BTFIXUP_CALL(smp_ipi_mask_one)(cpu); | ||
155 | } | ||
156 | |||
157 | void smp_resched_interrupt(void) | ||
158 | { | ||
159 | irq_enter(); | ||
160 | scheduler_ipi(); | ||
161 | local_cpu_data().irq_resched_count++; | ||
162 | irq_exit(); | ||
163 | /* re-schedule routine called by interrupt return code. */ | ||
164 | } | ||
165 | |||
166 | void smp_call_function_single_interrupt(void) | ||
167 | { | ||
168 | irq_enter(); | ||
169 | generic_smp_call_function_single_interrupt(); | ||
170 | local_cpu_data().irq_call_count++; | ||
171 | irq_exit(); | ||
172 | } | ||
173 | |||
174 | void smp_call_function_interrupt(void) | ||
175 | { | ||
176 | irq_enter(); | ||
177 | generic_smp_call_function_interrupt(); | ||
178 | local_cpu_data().irq_call_count++; | ||
179 | irq_exit(); | ||
180 | } | ||
181 | |||
141 | void smp_flush_cache_all(void) | 182 | void smp_flush_cache_all(void) |
142 | { | 183 | { |
143 | xc0((smpfunc_t) BTFIXUP_CALL(local_flush_cache_all)); | 184 | xc0((smpfunc_t) BTFIXUP_CALL(local_flush_cache_all)); |
@@ -153,9 +194,10 @@ void smp_flush_tlb_all(void) | |||
153 | void smp_flush_cache_mm(struct mm_struct *mm) | 194 | void smp_flush_cache_mm(struct mm_struct *mm) |
154 | { | 195 | { |
155 | if(mm->context != NO_CONTEXT) { | 196 | if(mm->context != NO_CONTEXT) { |
156 | cpumask_t cpu_mask = *mm_cpumask(mm); | 197 | cpumask_t cpu_mask; |
157 | cpu_clear(smp_processor_id(), cpu_mask); | 198 | cpumask_copy(&cpu_mask, mm_cpumask(mm)); |
158 | if (!cpus_empty(cpu_mask)) | 199 | cpumask_clear_cpu(smp_processor_id(), &cpu_mask); |
200 | if (!cpumask_empty(&cpu_mask)) | ||
159 | xc1((smpfunc_t) BTFIXUP_CALL(local_flush_cache_mm), (unsigned long) mm); | 201 | xc1((smpfunc_t) BTFIXUP_CALL(local_flush_cache_mm), (unsigned long) mm); |
160 | local_flush_cache_mm(mm); | 202 | local_flush_cache_mm(mm); |
161 | } | 203 | } |
@@ -164,9 +206,10 @@ void smp_flush_cache_mm(struct mm_struct *mm) | |||
164 | void smp_flush_tlb_mm(struct mm_struct *mm) | 206 | void smp_flush_tlb_mm(struct mm_struct *mm) |
165 | { | 207 | { |
166 | if(mm->context != NO_CONTEXT) { | 208 | if(mm->context != NO_CONTEXT) { |
167 | cpumask_t cpu_mask = *mm_cpumask(mm); | 209 | cpumask_t cpu_mask; |
168 | cpu_clear(smp_processor_id(), cpu_mask); | 210 | cpumask_copy(&cpu_mask, mm_cpumask(mm)); |
169 | if (!cpus_empty(cpu_mask)) { | 211 | cpumask_clear_cpu(smp_processor_id(), &cpu_mask); |
212 | if (!cpumask_empty(&cpu_mask)) { | ||
170 | xc1((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_mm), (unsigned long) mm); | 213 | xc1((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_mm), (unsigned long) mm); |
171 | if(atomic_read(&mm->mm_users) == 1 && current->active_mm == mm) | 214 | if(atomic_read(&mm->mm_users) == 1 && current->active_mm == mm) |
172 | cpumask_copy(mm_cpumask(mm), | 215 | cpumask_copy(mm_cpumask(mm), |
@@ -182,9 +225,10 @@ void smp_flush_cache_range(struct vm_area_struct *vma, unsigned long start, | |||
182 | struct mm_struct *mm = vma->vm_mm; | 225 | struct mm_struct *mm = vma->vm_mm; |
183 | 226 | ||
184 | if (mm->context != NO_CONTEXT) { | 227 | if (mm->context != NO_CONTEXT) { |
185 | cpumask_t cpu_mask = *mm_cpumask(mm); | 228 | cpumask_t cpu_mask; |
186 | cpu_clear(smp_processor_id(), cpu_mask); | 229 | cpumask_copy(&cpu_mask, mm_cpumask(mm)); |
187 | if (!cpus_empty(cpu_mask)) | 230 | cpumask_clear_cpu(smp_processor_id(), &cpu_mask); |
231 | if (!cpumask_empty(&cpu_mask)) | ||
188 | xc3((smpfunc_t) BTFIXUP_CALL(local_flush_cache_range), (unsigned long) vma, start, end); | 232 | xc3((smpfunc_t) BTFIXUP_CALL(local_flush_cache_range), (unsigned long) vma, start, end); |
189 | local_flush_cache_range(vma, start, end); | 233 | local_flush_cache_range(vma, start, end); |
190 | } | 234 | } |
@@ -196,9 +240,10 @@ void smp_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, | |||
196 | struct mm_struct *mm = vma->vm_mm; | 240 | struct mm_struct *mm = vma->vm_mm; |
197 | 241 | ||
198 | if (mm->context != NO_CONTEXT) { | 242 | if (mm->context != NO_CONTEXT) { |
199 | cpumask_t cpu_mask = *mm_cpumask(mm); | 243 | cpumask_t cpu_mask; |
200 | cpu_clear(smp_processor_id(), cpu_mask); | 244 | cpumask_copy(&cpu_mask, mm_cpumask(mm)); |
201 | if (!cpus_empty(cpu_mask)) | 245 | cpumask_clear_cpu(smp_processor_id(), &cpu_mask); |
246 | if (!cpumask_empty(&cpu_mask)) | ||
202 | xc3((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_range), (unsigned long) vma, start, end); | 247 | xc3((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_range), (unsigned long) vma, start, end); |
203 | local_flush_tlb_range(vma, start, end); | 248 | local_flush_tlb_range(vma, start, end); |
204 | } | 249 | } |
@@ -209,9 +254,10 @@ void smp_flush_cache_page(struct vm_area_struct *vma, unsigned long page) | |||
209 | struct mm_struct *mm = vma->vm_mm; | 254 | struct mm_struct *mm = vma->vm_mm; |
210 | 255 | ||
211 | if(mm->context != NO_CONTEXT) { | 256 | if(mm->context != NO_CONTEXT) { |
212 | cpumask_t cpu_mask = *mm_cpumask(mm); | 257 | cpumask_t cpu_mask; |
213 | cpu_clear(smp_processor_id(), cpu_mask); | 258 | cpumask_copy(&cpu_mask, mm_cpumask(mm)); |
214 | if (!cpus_empty(cpu_mask)) | 259 | cpumask_clear_cpu(smp_processor_id(), &cpu_mask); |
260 | if (!cpumask_empty(&cpu_mask)) | ||
215 | xc2((smpfunc_t) BTFIXUP_CALL(local_flush_cache_page), (unsigned long) vma, page); | 261 | xc2((smpfunc_t) BTFIXUP_CALL(local_flush_cache_page), (unsigned long) vma, page); |
216 | local_flush_cache_page(vma, page); | 262 | local_flush_cache_page(vma, page); |
217 | } | 263 | } |
@@ -222,19 +268,15 @@ void smp_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) | |||
222 | struct mm_struct *mm = vma->vm_mm; | 268 | struct mm_struct *mm = vma->vm_mm; |
223 | 269 | ||
224 | if(mm->context != NO_CONTEXT) { | 270 | if(mm->context != NO_CONTEXT) { |
225 | cpumask_t cpu_mask = *mm_cpumask(mm); | 271 | cpumask_t cpu_mask; |
226 | cpu_clear(smp_processor_id(), cpu_mask); | 272 | cpumask_copy(&cpu_mask, mm_cpumask(mm)); |
227 | if (!cpus_empty(cpu_mask)) | 273 | cpumask_clear_cpu(smp_processor_id(), &cpu_mask); |
274 | if (!cpumask_empty(&cpu_mask)) | ||
228 | xc2((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_page), (unsigned long) vma, page); | 275 | xc2((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_page), (unsigned long) vma, page); |
229 | local_flush_tlb_page(vma, page); | 276 | local_flush_tlb_page(vma, page); |
230 | } | 277 | } |
231 | } | 278 | } |
232 | 279 | ||
233 | void smp_reschedule_irq(void) | ||
234 | { | ||
235 | set_need_resched(); | ||
236 | } | ||
237 | |||
238 | void smp_flush_page_to_ram(unsigned long page) | 280 | void smp_flush_page_to_ram(unsigned long page) |
239 | { | 281 | { |
240 | /* Current theory is that those who call this are the one's | 282 | /* Current theory is that those who call this are the one's |
@@ -251,9 +293,10 @@ void smp_flush_page_to_ram(unsigned long page) | |||
251 | 293 | ||
252 | void smp_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr) | 294 | void smp_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr) |
253 | { | 295 | { |
254 | cpumask_t cpu_mask = *mm_cpumask(mm); | 296 | cpumask_t cpu_mask; |
255 | cpu_clear(smp_processor_id(), cpu_mask); | 297 | cpumask_copy(&cpu_mask, mm_cpumask(mm)); |
256 | if (!cpus_empty(cpu_mask)) | 298 | cpumask_clear_cpu(smp_processor_id(), &cpu_mask); |
299 | if (!cpumask_empty(&cpu_mask)) | ||
257 | xc2((smpfunc_t) BTFIXUP_CALL(local_flush_sig_insns), (unsigned long) mm, insn_addr); | 300 | xc2((smpfunc_t) BTFIXUP_CALL(local_flush_sig_insns), (unsigned long) mm, insn_addr); |
258 | local_flush_sig_insns(mm, insn_addr); | 301 | local_flush_sig_insns(mm, insn_addr); |
259 | } | 302 | } |
@@ -407,7 +450,7 @@ int __cpuinit __cpu_up(unsigned int cpu) | |||
407 | }; | 450 | }; |
408 | 451 | ||
409 | if (!ret) { | 452 | if (!ret) { |
410 | cpu_set(cpu, smp_commenced_mask); | 453 | cpumask_set_cpu(cpu, &smp_commenced_mask); |
411 | while (!cpu_online(cpu)) | 454 | while (!cpu_online(cpu)) |
412 | mb(); | 455 | mb(); |
413 | } | 456 | } |