aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel/setup_32.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2012-05-14 02:09:04 -0400
committerDavid S. Miller <davem@davemloft.net>2012-05-14 16:31:38 -0400
commitc68e5d39a502d01421cbc70d25c377e9215facef (patch)
tree9135a68681381d94a929b57a28a1878df0134ff7 /arch/sparc/kernel/setup_32.c
parent5d83d66635bb1642f3c6a3690c28ff4afdf1ae5f (diff)
sparc32: Implement hard_smp_processor_id() via instruction patching.
This is the last non-trivial user of btfixup. Like sparc64, use a special patch section to resolve the various implementations of how to read the current CPU's ID when we don't have current_thread_info()->cpu necessarily available. Signed-off-by: David S. Miller <davem@davemloft.net> Tested-by: Sam Ravnborg <sam@ravnborg.org>
Diffstat (limited to 'arch/sparc/kernel/setup_32.c')
-rw-r--r--arch/sparc/kernel/setup_32.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/arch/sparc/kernel/setup_32.c b/arch/sparc/kernel/setup_32.c
index 6f294f371d68..2f7cfb5f7569 100644
--- a/arch/sparc/kernel/setup_32.c
+++ b/arch/sparc/kernel/setup_32.c
@@ -192,6 +192,52 @@ extern int root_mountflags;
192 192
193char reboot_command[COMMAND_LINE_SIZE]; 193char reboot_command[COMMAND_LINE_SIZE];
194 194
195struct cpuid_patch_entry {
196 unsigned int addr;
197 unsigned int sun4d[3];
198 unsigned int leon[3];
199};
200extern struct cpuid_patch_entry __cpuid_patch, __cpuid_patch_end;
201
202static void __init per_cpu_patch(void)
203{
204 struct cpuid_patch_entry *p;
205
206 if (sparc_cpu_model == sun4m) {
207 /* Nothing to do, this is what the unpatched code
208 * targets.
209 */
210 return;
211 }
212
213 p = &__cpuid_patch;
214 while (p < &__cpuid_patch_end) {
215 unsigned long addr = p->addr;
216 unsigned int *insns;
217
218 switch (sparc_cpu_model) {
219 case sun4d:
220 insns = &p->sun4d[0];
221 break;
222
223 case sparc_leon:
224 insns = &p->leon[0];
225 break;
226 default:
227 prom_printf("Unknown cpu type, halting.\n");
228 prom_halt();
229 }
230 *(unsigned int *) (addr + 0) = insns[0];
231 *(unsigned int *) (addr + 4) = insns[1];
232 *(unsigned int *) (addr + 8) = insns[2];
233 }
234#ifdef CONFIG_SMP
235 local_ops->cache_all();
236#else
237 sparc32_cachetlb_ops->cache_all();
238#endif
239}
240
195enum sparc_cpu sparc_cpu_model; 241enum sparc_cpu sparc_cpu_model;
196EXPORT_SYMBOL(sparc_cpu_model); 242EXPORT_SYMBOL(sparc_cpu_model);
197 243
@@ -295,6 +341,11 @@ void __init setup_arch(char **cmdline_p)
295 341
296 paging_init(); 342 paging_init();
297 343
344 /* Now that we have the cache ops hooked up, we can patch
345 * instructions.
346 */
347 per_cpu_patch();
348
298 smp_setup_cpu_possible_map(); 349 smp_setup_cpu_possible_map();
299} 350}
300 351