diff options
author | David S. Miller <davem@davemloft.net> | 2012-05-13 23:09:04 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-05-14 13:31:38 -0700 |
commit | c68e5d39a502d01421cbc70d25c377e9215facef (patch) | |
tree | 9135a68681381d94a929b57a28a1878df0134ff7 /arch/sparc/kernel/setup_32.c | |
parent | 5d83d66635bb1642f3c6a3690c28ff4afdf1ae5f (diff) | |
download | linux-c68e5d39a502d01421cbc70d25c377e9215facef.tar.bz2 |
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; char reboot_command[COMMAND_LINE_SIZE]; +struct cpuid_patch_entry { + unsigned int addr; + unsigned int sun4d[3]; + unsigned int leon[3]; +}; +extern struct cpuid_patch_entry __cpuid_patch, __cpuid_patch_end; + +static void __init per_cpu_patch(void) +{ + struct cpuid_patch_entry *p; + + if (sparc_cpu_model == sun4m) { + /* Nothing to do, this is what the unpatched code + * targets. + */ + return; + } + + p = &__cpuid_patch; + while (p < &__cpuid_patch_end) { + unsigned long addr = p->addr; + unsigned int *insns; + + switch (sparc_cpu_model) { + case sun4d: + insns = &p->sun4d[0]; + break; + + case sparc_leon: + insns = &p->leon[0]; + break; + default: + prom_printf("Unknown cpu type, halting.\n"); + prom_halt(); + } + *(unsigned int *) (addr + 0) = insns[0]; + *(unsigned int *) (addr + 4) = insns[1]; + *(unsigned int *) (addr + 8) = insns[2]; + } +#ifdef CONFIG_SMP + local_ops->cache_all(); +#else + sparc32_cachetlb_ops->cache_all(); +#endif +} + enum sparc_cpu sparc_cpu_model; EXPORT_SYMBOL(sparc_cpu_model); @@ -295,6 +341,11 @@ void __init setup_arch(char **cmdline_p) paging_init(); + /* Now that we have the cache ops hooked up, we can patch + * instructions. + */ + per_cpu_patch(); + smp_setup_cpu_possible_map(); } |