aboutsummaryrefslogtreecommitdiff
path: root/arch/sparc/kernel
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2012-05-13 23:09:04 -0700
committerDavid S. Miller <davem@davemloft.net>2012-05-14 13:31:38 -0700
commitc68e5d39a502d01421cbc70d25c377e9215facef (patch)
tree9135a68681381d94a929b57a28a1878df0134ff7 /arch/sparc/kernel
parent5d83d66635bb1642f3c6a3690c28ff4afdf1ae5f (diff)
downloadlinux-c68e5d39a502d01421cbc70d25c377e9215facef.tar.gz
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')
-rw-r--r--arch/sparc/kernel/entry.S23
-rw-r--r--arch/sparc/kernel/kernel.h2
-rw-r--r--arch/sparc/kernel/leon_smp.c29
-rw-r--r--arch/sparc/kernel/setup_32.c51
-rw-r--r--arch/sparc/kernel/sparc_ksyms_32.c5
-rw-r--r--arch/sparc/kernel/sun4d_smp.c27
-rw-r--r--arch/sparc/kernel/sun4m_smp.c23
-rw-r--r--arch/sparc/kernel/trampoline_32.S22
8 files changed, 80 insertions, 102 deletions
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
index d7143ba6a8f..773f3f05bf2 100644
--- a/arch/sparc/kernel/entry.S
+++ b/arch/sparc/kernel/entry.S
@@ -7,6 +7,7 @@
* Copyright (C) 1997 Anton Blanchard (anton@progsoc.uts.edu.au)
*/
+#include <linux/linkage.h>
#include <linux/errno.h>
#include <asm/head.h>
@@ -1347,4 +1348,26 @@ flushw_all:
ret
restore
+#ifdef CONFIG_SMP
+ENTRY(hard_smp_processor_id)
+661: rd %tbr, %g1
+ srl %g1, 12, %o0
+ and %o0, 3, %o0
+ .section .cpuid_patch, "ax"
+ /* Instruction location. */
+ .word 661b
+ /* SUN4D implementation. */
+ lda [%g0] ASI_M_VIKING_TMP1, %o0
+ nop
+ nop
+ /* LEON implementation. */
+ rd %asr17, %o0
+ srl %o0, 0x1c, %o0
+ nop
+ .previous
+ retl
+ nop
+ENDPROC(hard_smp_processor_id)
+#endif
+
/* End of entry.S */
diff --git a/arch/sparc/kernel/kernel.h b/arch/sparc/kernel/kernel.h
index 8278df5d4ce..1c1a7d39c7e 100644
--- a/arch/sparc/kernel/kernel.h
+++ b/arch/sparc/kernel/kernel.h
@@ -80,8 +80,6 @@ extern unsigned int patchme_maybe_smp_msg[];
extern void floppy_hardint(void);
/* trampoline_32.S */
-extern int __smp4m_processor_id(void);
-extern int __smp4d_processor_id(void);
extern unsigned long sun4m_cpu_startup;
extern unsigned long sun4d_cpu_startup;
diff --git a/arch/sparc/kernel/leon_smp.c b/arch/sparc/kernel/leon_smp.c
index f3e3630e31a..faff792d53c 100644
--- a/arch/sparc/kernel/leon_smp.c
+++ b/arch/sparc/kernel/leon_smp.c
@@ -73,7 +73,7 @@ static inline unsigned long do_swap(volatile unsigned long *ptr,
void __cpuinit leon_callin(void)
{
- int cpuid = hard_smpleon_processor_id();
+ int cpuid = hard_smp_processor_id();
local_ops->cache_all();
local_ops->tlb_all();
@@ -491,39 +491,12 @@ void leon_cross_call_irq(void)
ccall_info.processors_out[i] = 1;
}
-void __init leon_blackbox_id(unsigned *addr)
-{
- int rd = *addr & 0x3e000000;
- int rs1 = rd >> 11;
-
- /* patch places where ___b_hard_smp_processor_id appears */
- addr[0] = 0x81444000 | rd; /* rd %asr17, reg */
- addr[1] = 0x8130201c | rd | rs1; /* srl reg, 0x1c, reg */
- addr[2] = 0x01000000; /* nop */
-}
-
-void __init leon_blackbox_current(unsigned *addr)
-{
- int rd = *addr & 0x3e000000;
- int rs1 = rd >> 11;
-
- /* patch LOAD_CURRENT macro where ___b_load_current appears */
- addr[0] = 0x81444000 | rd; /* rd %asr17, reg */
- addr[2] = 0x8130201c | rd | rs1; /* srl reg, 0x1c, reg */
- addr[4] = 0x81282002 | rd | rs1; /* sll reg, 0x2, reg */
-
-}
-
void __init leon_init_smp(void)
{
/* Patch ipi15 trap table */
t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_leon - linux_trap_ipi15_sun4m);
- BTFIXUPSET_BLACKBOX(hard_smp_processor_id, leon_blackbox_id);
- BTFIXUPSET_BLACKBOX(load_current, leon_blackbox_current);
BTFIXUPSET_CALL(smp_cross_call, leon_cross_call, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(__hard_smp_processor_id, __leon_processor_id,
- BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(smp_ipi_resched, leon_ipi_resched, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(smp_ipi_single, leon_ipi_single, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(smp_ipi_mask_one, leon_ipi_mask_one, BTFIXUPCALL_NORM);
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();
}
diff --git a/arch/sparc/kernel/sparc_ksyms_32.c b/arch/sparc/kernel/sparc_ksyms_32.c
index 4ad7377e2d0..e521c54560f 100644
--- a/arch/sparc/kernel/sparc_ksyms_32.c
+++ b/arch/sparc/kernel/sparc_ksyms_32.c
@@ -28,10 +28,5 @@ EXPORT_SYMBOL(__ndelay);
EXPORT_SYMBOL(__ret_efault);
EXPORT_SYMBOL(empty_zero_page);
-/* Defined using magic */
-#ifdef CONFIG_SMP
-EXPORT_SYMBOL(BTFIXUP_CALL(__hard_smp_processor_id));
-#endif
-
/* Exporting a symbol from /init/main.c */
EXPORT_SYMBOL(saved_command_line);
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
index f17fd287bf7..38ca0aac2ef 100644
--- a/arch/sparc/kernel/sun4d_smp.c
+++ b/arch/sparc/kernel/sun4d_smp.c
@@ -52,7 +52,7 @@ static inline void show_leds(int cpuid)
void __cpuinit smp4d_callin(void)
{
- int cpuid = hard_smp4d_processor_id();
+ int cpuid = hard_smp_processor_id();
unsigned long flags;
/* Show we are alive */
@@ -354,7 +354,7 @@ static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
/* Running cross calls. */
void smp4d_cross_call_irq(void)
{
- int i = hard_smp4d_processor_id();
+ int i = hard_smp_processor_id();
ccall_info.processors_in[i] = 1;
ccall_info.func(ccall_info.arg1, ccall_info.arg2, ccall_info.arg3,
@@ -365,7 +365,7 @@ void smp4d_cross_call_irq(void)
void smp4d_percpu_timer_interrupt(struct pt_regs *regs)
{
struct pt_regs *old_regs;
- int cpu = hard_smp4d_processor_id();
+ int cpu = hard_smp_processor_id();
struct clock_event_device *ce;
static int cpu_tick[NR_CPUS];
static char led_mask[] = { 0xe, 0xd, 0xb, 0x7, 0xb, 0xd };
@@ -391,24 +391,6 @@ void smp4d_percpu_timer_interrupt(struct pt_regs *regs)
set_irq_regs(old_regs);
}
-void __init smp4d_blackbox_id(unsigned *addr)
-{
- int rd = *addr & 0x3e000000;
-
- addr[0] = 0xc0800800 | rd; /* lda [%g0] ASI_M_VIKING_TMP1, reg */
- addr[1] = 0x01000000; /* nop */
- addr[2] = 0x01000000; /* nop */
-}
-
-void __init smp4d_blackbox_current(unsigned *addr)
-{
- int rd = *addr & 0x3e000000;
-
- addr[0] = 0xc0800800 | rd; /* lda [%g0] ASI_M_VIKING_TMP1, reg */
- addr[2] = 0x81282002 | rd | (rd >> 11); /* sll reg, 2, reg */
- addr[4] = 0x01000000; /* nop */
-}
-
void __init sun4d_init_smp(void)
{
int i;
@@ -417,10 +399,7 @@ void __init sun4d_init_smp(void)
t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_sun4d - linux_trap_ipi15_sun4m);
/* And set btfixup... */
- BTFIXUPSET_BLACKBOX(hard_smp_processor_id, smp4d_blackbox_id);
- BTFIXUPSET_BLACKBOX(load_current, smp4d_blackbox_current);
BTFIXUPSET_CALL(smp_cross_call, smp4d_cross_call, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4d_processor_id, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(smp_ipi_resched, smp4d_ipi_resched, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(smp_ipi_single, smp4d_ipi_single, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(smp_ipi_mask_one, smp4d_ipi_mask_one, BTFIXUPCALL_NORM);
diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c
index afcf6743f0e..ff74d33e270 100644
--- a/arch/sparc/kernel/sun4m_smp.c
+++ b/arch/sparc/kernel/sun4m_smp.c
@@ -281,32 +281,9 @@ void smp4m_percpu_timer_interrupt(struct pt_regs *regs)
set_irq_regs(old_regs);
}
-static void __init smp4m_blackbox_id(unsigned *addr)
-{
- int rd = *addr & 0x3e000000;
- int rs1 = rd >> 11;
-
- addr[0] = 0x81580000 | rd; /* rd %tbr, reg */
- addr[1] = 0x8130200c | rd | rs1; /* srl reg, 0xc, reg */
- addr[2] = 0x80082003 | rd | rs1; /* and reg, 3, reg */
-}
-
-static void __init smp4m_blackbox_current(unsigned *addr)
-{
- int rd = *addr & 0x3e000000;
- int rs1 = rd >> 11;
-
- addr[0] = 0x81580000 | rd; /* rd %tbr, reg */
- addr[2] = 0x8130200a | rd | rs1; /* srl reg, 0xa, reg */
- addr[4] = 0x8008200c | rd | rs1; /* and reg, 0xc, reg */
-}
-
void __init sun4m_init_smp(void)
{
- BTFIXUPSET_BLACKBOX(hard_smp_processor_id, smp4m_blackbox_id);
- BTFIXUPSET_BLACKBOX(load_current, smp4m_blackbox_current);
BTFIXUPSET_CALL(smp_cross_call, smp4m_cross_call, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4m_processor_id, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(smp_ipi_resched, smp4m_ipi_resched, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(smp_ipi_single, smp4m_ipi_single, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(smp_ipi_mask_one, smp4m_ipi_mask_one, BTFIXUPCALL_NORM);
diff --git a/arch/sparc/kernel/trampoline_32.S b/arch/sparc/kernel/trampoline_32.S
index 691f484e03b..7364ddc9e5a 100644
--- a/arch/sparc/kernel/trampoline_32.S
+++ b/arch/sparc/kernel/trampoline_32.S
@@ -15,8 +15,8 @@
#include <asm/contregs.h>
#include <asm/thread_info.h>
- .globl sun4m_cpu_startup, __smp4m_processor_id, __leon_processor_id
- .globl sun4d_cpu_startup, __smp4d_processor_id
+ .globl sun4m_cpu_startup
+ .globl sun4d_cpu_startup
__CPUINIT
.align 4
@@ -94,24 +94,6 @@ smp_do_cpu_idle:
call cpu_panic
nop
-__smp4m_processor_id:
- rd %tbr, %g2
- srl %g2, 12, %g2
- and %g2, 3, %g2
- retl
- mov %g1, %o7
-
-__smp4d_processor_id:
- lda [%g0] ASI_M_VIKING_TMP1, %g2
- retl
- mov %g1, %o7
-
-__leon_processor_id:
- rd %asr17,%g2
- srl %g2,28,%g2
- retl
- mov %g1, %o7
-
/* CPUID in bootbus can be found at PA 0xff0140000 */
#define SUN4D_BOOTBUS_CPUID 0xf0140000