diff options
author | David S. Miller <davem@davemloft.net> | 2012-05-14 02:09:04 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-05-14 16:31:38 -0400 |
commit | c68e5d39a502d01421cbc70d25c377e9215facef (patch) | |
tree | 9135a68681381d94a929b57a28a1878df0134ff7 /arch/sparc/kernel/setup_32.c | |
parent | 5d83d66635bb1642f3c6a3690c28ff4afdf1ae5f (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.c | 51 |
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 | ||
193 | char reboot_command[COMMAND_LINE_SIZE]; | 193 | char reboot_command[COMMAND_LINE_SIZE]; |
194 | 194 | ||
195 | struct cpuid_patch_entry { | ||
196 | unsigned int addr; | ||
197 | unsigned int sun4d[3]; | ||
198 | unsigned int leon[3]; | ||
199 | }; | ||
200 | extern struct cpuid_patch_entry __cpuid_patch, __cpuid_patch_end; | ||
201 | |||
202 | static 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 | |||
195 | enum sparc_cpu sparc_cpu_model; | 241 | enum sparc_cpu sparc_cpu_model; |
196 | EXPORT_SYMBOL(sparc_cpu_model); | 242 | EXPORT_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 | ||