Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c68e5d39 authored by David S. Miller's avatar David S. Miller
Browse files

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: default avatarDavid S. Miller <davem@davemloft.net>
Tested-by: default avatarSam Ravnborg <sam@ravnborg.org>
parent 5d83d666
Loading
Loading
Loading
Loading
+1 −42
Original line number Diff line number Diff line
@@ -59,12 +59,9 @@ void smp_bogo(struct seq_file *);
void smp_info(struct seq_file *);

BTFIXUPDEF_CALL(void, smp_cross_call, smpfunc_t, cpumask_t, unsigned long, unsigned long, unsigned long, unsigned long)
BTFIXUPDEF_CALL(int, __hard_smp_processor_id, void)
BTFIXUPDEF_CALL(void, smp_ipi_resched, int);
BTFIXUPDEF_CALL(void, smp_ipi_single, int);
BTFIXUPDEF_CALL(void, smp_ipi_mask_one, int);
BTFIXUPDEF_BLACKBOX(hard_smp_processor_id)
BTFIXUPDEF_BLACKBOX(load_current)

#define smp_cross_call(func,mask,arg1,arg2,arg3,arg4) BTFIXUP_CALL(smp_cross_call)(func,mask,arg1,arg2,arg3,arg4)

@@ -117,45 +114,7 @@ extern inline int hard_smpleon_processor_id(void)
	return cpuid;
}

#ifndef MODULE
static inline int hard_smp_processor_id(void)
{
	int cpuid;

	/* Black box - sun4m
		__asm__ __volatile__("rd %%tbr, %0\n\t"
				     "srl %0, 12, %0\n\t"
				     "and %0, 3, %0\n\t" :
				     "=&r" (cpuid));
	             - sun4d
		__asm__ __volatile__("lda [%g0] ASI_M_VIKING_TMP1, %0\n\t"
				     "nop; nop" :
				     "=&r" (cpuid));
		     - leon
		__asm__ __volatile__(	"rd %asr17, %0\n\t"
					"srl %0, 0x1c, %0\n\t"
					"nop\n\t" :
					"=&r" (cpuid));
	   See btfixup.h and btfixupprep.c to understand how a blackbox works.
	 */
	__asm__ __volatile__("sethi %%hi(___b_hard_smp_processor_id), %0\n\t"
			     "sethi %%hi(boot_cpu_id), %0\n\t"
			     "ldub [%0 + %%lo(boot_cpu_id)], %0\n\t" :
			     "=&r" (cpuid));
	return cpuid;
}
#else
static inline int hard_smp_processor_id(void)
{
	int cpuid;

	__asm__ __volatile__("mov %%o7, %%g1\n\t"
			     "call ___f___hard_smp_processor_id\n\t"
			     " nop\n\t"
			     "mov %%g2, %0\n\t" : "=r"(cpuid) : : "g1", "g2");
	return cpuid;
}
#endif
extern int hard_smp_processor_id(void);

#define raw_smp_processor_id()		(current_thread_info()->cpu)

+18 −31
Original line number Diff line number Diff line
@@ -103,37 +103,24 @@
        st       %scratch, [%cur_reg + TI_W_SAVED];

#ifdef CONFIG_SMP
/* Results of LOAD_CURRENT() after BTFIXUP for SUN4M, SUN4D & LEON (comments) */
#define LOAD_CURRENT4M(dest_reg, idreg) \
        rd       %tbr, %idreg; \
	sethi    %hi(current_set), %dest_reg; \
#define LOAD_CURRENT(dest_reg, idreg) 			\
661:	rd	%tbr, %idreg;				\
	srl	%idreg, 10, %idreg;			\
	or       %dest_reg, %lo(current_set), %dest_reg; \
	and	%idreg, 0xc, %idreg;			\
	ld       [%idreg + %dest_reg], %dest_reg;

#define LOAD_CURRENT4D(dest_reg, idreg) \
	.section	.cpuid_patch, "ax";		\
	/* Instruction location. */			\
	.word		661b;				\
	/* SUN4D implementation. */			\
	lda	 [%g0] ASI_M_VIKING_TMP1, %idreg;	\
	sethi	%hi(C_LABEL(current_set)), %dest_reg; \
	sll	 %idreg, 2, %idreg;			\
	or	%dest_reg, %lo(C_LABEL(current_set)), %dest_reg; \
	ld	[%idreg + %dest_reg], %dest_reg;

#define LOAD_CURRENT_LEON(dest_reg, idreg)			\
	nop;						\
	/* LEON implementation. */			\
	rd 	%asr17, %idreg;				\
	sethi	%hi(current_set), %dest_reg;			\
	srl	%idreg, 0x1c, %idreg;			\
	or	%dest_reg, %lo(current_set), %dest_reg;		\
	sll	%idreg, 0x2, %idreg;				\
	ld	[%idreg + %dest_reg], %dest_reg;

/* Blackbox - take care with this... - check smp4m and smp4d before changing this. */
#define LOAD_CURRENT(dest_reg, idreg) 					\
	sethi	 %hi(___b_load_current), %idreg;			\
	sll	%idreg, 0x02, %idreg;			\
	.previous;					\
	sethi    %hi(current_set), %dest_reg; 		\
	sethi    %hi(boot_cpu_id4), %idreg; 			\
	or       %dest_reg, %lo(current_set), %dest_reg;\
	ldub	 [%idreg + %lo(boot_cpu_id4)], %idreg;		\
	ld       [%idreg + %dest_reg], %dest_reg;
#else
#define LOAD_CURRENT(dest_reg, idreg) \
+23 −0
Original line number Diff line number Diff line
@@ -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 */
+0 −2
Original line number Diff line number Diff line
@@ -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;

+1 −28
Original line number Diff line number Diff line
@@ -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);
Loading