diff options
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 6f294f371d6..2f7cfb5f756 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(); } |