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

Commit 41195d23 authored by Vineet Gupta's avatar Vineet Gupta
Browse files

ARC: SMP support



ARC common code to enable a SMP system + ISS provided SMP extensions.

ARC700 natively lacks SMP support, hence some of the core features are
are only enabled if SoCs have the necessary h/w pixie-dust. This
includes:
-Inter Processor Interrupts (IPI)
-Cache coherency
-load-locked/store-conditional
...

The low level exception handling would be completely broken in SMP
because we don't have hardware assisted stack switching. Thus a fair bit
of this code is repurposing the MMU_SCRATCH reg for event handler
prologues to keep them re-entrant.

Many thanks to Rajeshwar Ranga for his initial "major" contributions to
SMP Port (back in 2008), and to Noam Camus and Gilad Ben-Yossef for help
with resurrecting that in 3.2 kernel (2012).

Note that this platform code is again singleton design pattern - so
multiple SMP platforms won't build at the moment - this deficiency is
addressed in subsequent patches within this series.

Signed-off-by: default avatarVineet Gupta <vgupta@synopsys.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Rajeshwar Ranga <rajeshwar.ranga@gmail.com>
Cc: Noam Camus <noamc@ezchip.com>
Cc: Gilad Ben-Yossef <gilad@benyossef.com>
parent 0ef88a54
Loading
Loading
Loading
Loading
+38 −1
Original line number Original line Diff line number Diff line
@@ -116,9 +116,42 @@ config CPU_BIG_ENDIAN
	help
	help
	  Build kernel for Big Endian Mode of ARC CPU
	  Build kernel for Big Endian Mode of ARC CPU


config SMP
	bool "Symmetric Multi-Processing (Incomplete)"
	default n
	select USE_GENERIC_SMP_HELPERS
	help
	  This enables support for systems with more than one CPU. If you have
	  a system with only one CPU, like most personal computers, say N. If
	  you have a system with more than one CPU, say Y.

if SMP

config ARC_HAS_COH_CACHES
	def_bool n

config ARC_HAS_COH_LLSC
	def_bool n

config ARC_HAS_COH_RTSC
	def_bool n

config ARC_HAS_REENTRANT_IRQ_LV2
	def_bool n

endif

config NR_CPUS
	int "Maximum number of CPUs (2-32)"
	range 2 32
	depends on SMP
	default "2"

menuconfig ARC_CACHE
menuconfig ARC_CACHE
	bool "Enable Cache Support"
	bool "Enable Cache Support"
	default y
	default y
	# if SMP, cache enabled ONLY if ARC implementation has cache coherency
	depends on !SMP || ARC_HAS_COH_CACHES


if ARC_CACHE
if ARC_CACHE


@@ -213,6 +246,8 @@ config ARC_COMPACT_IRQ_LEVELS
	default n
	default n
	# Timer HAS to be high priority, for any other high priority config
	# Timer HAS to be high priority, for any other high priority config
	select ARC_IRQ3_LV2
	select ARC_IRQ3_LV2
	# if SMP, LV2 enabled ONLY if ARC implementation has LV2 re-entrancy
	depends on !SMP || ARC_HAS_REENTRANT_IRQ_LV2


if ARC_COMPACT_IRQ_LEVELS
if ARC_COMPACT_IRQ_LEVELS


@@ -261,6 +296,8 @@ config ARC_HAS_RTSC
	bool "Insn: RTSC (64-bit r/o cycle counter)"
	bool "Insn: RTSC (64-bit r/o cycle counter)"
	default y
	default y
	depends on ARC_CPU_REL_4_10
	depends on ARC_CPU_REL_4_10
	# if SMP, enable RTSC only if counter is coherent across cores
	depends on !SMP || ARC_HAS_COH_RTSC


endmenu   # "ARC CPU Configuration"
endmenu   # "ARC CPU Configuration"


@@ -309,7 +346,7 @@ menuconfig ARC_DBG


config ARC_DBG_TLB_PARANOIA
config ARC_DBG_TLB_PARANOIA
	bool "Paranoia Checks in Low Level TLB Handlers"
	bool "Paranoia Checks in Low Level TLB Handlers"
	depends on ARC_DBG
	depends on ARC_DBG && !SMP
	default n
	default n


config ARC_DBG_TLB_MISS_COUNT
config ARC_DBG_TLB_MISS_COUNT
+3 −0
Original line number Original line Diff line number Diff line
@@ -133,3 +133,6 @@ archclean:
# Thus forcing all exten calls in this file to be long calls
# Thus forcing all exten calls in this file to be long calls
export CFLAGS_decompress_inflate.o = -mmedium-calls
export CFLAGS_decompress_inflate.o = -mmedium-calls
export CFLAGS_initramfs.o = -mmedium-calls
export CFLAGS_initramfs.o = -mmedium-calls
ifdef CONFIG_SMP
export CFLAGS_core.o = -mmedium-calls
endif
+49 −0
Original line number Original line Diff line number Diff line
@@ -389,11 +389,19 @@
 * to be saved again on kernel mode stack, as part of ptregs.
 * to be saved again on kernel mode stack, as part of ptregs.
 *-------------------------------------------------------------*/
 *-------------------------------------------------------------*/
.macro EXCPN_PROLOG_FREEUP_REG	reg
.macro EXCPN_PROLOG_FREEUP_REG	reg
#ifdef CONFIG_SMP
	sr  \reg, [ARC_REG_SCRATCH_DATA0]
#else
	st  \reg, [@ex_saved_reg1]
	st  \reg, [@ex_saved_reg1]
#endif
.endm
.endm


.macro EXCPN_PROLOG_RESTORE_REG	reg
.macro EXCPN_PROLOG_RESTORE_REG	reg
#ifdef CONFIG_SMP
	lr  \reg, [ARC_REG_SCRATCH_DATA0]
#else
	ld  \reg, [@ex_saved_reg1]
	ld  \reg, [@ex_saved_reg1]
#endif
.endm
.endm


/*--------------------------------------------------------------
/*--------------------------------------------------------------
@@ -508,7 +516,11 @@
	/* restore original r9 , saved in int1_saved_reg
	/* restore original r9 , saved in int1_saved_reg
	* It will be saved on stack in macro: SAVE_CALLER_SAVED
	* It will be saved on stack in macro: SAVE_CALLER_SAVED
	*/
	*/
#ifdef CONFIG_SMP
	lr  r9, [ARC_REG_SCRATCH_DATA0]
#else
	ld  r9, [@int1_saved_reg]
	ld  r9, [@int1_saved_reg]
#endif


	/* now we are ready to save the remaining context :) */
	/* now we are ready to save the remaining context :) */
	st      orig_r8_IS_IRQ1, [sp, 8]    /* Event Type */
	st      orig_r8_IS_IRQ1, [sp, 8]    /* Event Type */
@@ -639,6 +651,41 @@
	bmsk \reg, \reg, 7
	bmsk \reg, \reg, 7
.endm
.endm


#ifdef CONFIG_SMP

/*-------------------------------------------------
 * Retrieve the current running task on this CPU
 * 1. Determine curr CPU id.
 * 2. Use it to index into _current_task[ ]
 */
.macro  GET_CURR_TASK_ON_CPU   reg
	GET_CPU_ID  \reg
	ld.as  \reg, [@_current_task, \reg]
.endm

/*-------------------------------------------------
 * Save a new task as the "current" task on this CPU
 * 1. Determine curr CPU id.
 * 2. Use it to index into _current_task[ ]
 *
 * Coded differently than GET_CURR_TASK_ON_CPU (which uses LD.AS)
 * because ST r0, [r1, offset] can ONLY have s9 @offset
 * while   LD can take s9 (4 byte insn) or LIMM (8 byte insn)
 */

.macro  SET_CURR_TASK_ON_CPU    tsk, tmp
	GET_CPU_ID  \tmp
	add2 \tmp, @_current_task, \tmp
	st   \tsk, [\tmp]
#ifdef CONFIG_ARC_CURR_IN_REG
	mov r25, \tsk
#endif

.endm


#else   /* Uniprocessor implementation of macros */

.macro  GET_CURR_TASK_ON_CPU    reg
.macro  GET_CURR_TASK_ON_CPU    reg
	ld  \reg, [@_current_task]
	ld  \reg, [@_current_task]
.endm
.endm
@@ -650,6 +697,8 @@
#endif
#endif
.endm
.endm


#endif /* SMP / UNI */

/* ------------------------------------------------------------------
/* ------------------------------------------------------------------
 * Get the ptr to some field of Current Task at @off in task struct
 * Get the ptr to some field of Current Task at @off in task struct
 *  -Uses r25 for Current task ptr if that is enabled
 *  -Uses r25 for Current task ptr if that is enabled
+4 −0
Original line number Original line Diff line number Diff line
@@ -147,8 +147,10 @@ init_new_context(struct task_struct *tsk, struct mm_struct *mm)
static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
			     struct task_struct *tsk)
			     struct task_struct *tsk)
{
{
#ifndef CONFIG_SMP
	/* PGD cached in MMU reg to avoid 3 mem lookups: task->mm->pgd */
	/* PGD cached in MMU reg to avoid 3 mem lookups: task->mm->pgd */
	write_aux_reg(ARC_REG_SCRATCH_DATA0, next->pgd);
	write_aux_reg(ARC_REG_SCRATCH_DATA0, next->pgd);
#endif


	/*
	/*
	 * Get a new ASID if task doesn't have a valid one. Possible when
	 * Get a new ASID if task doesn't have a valid one. Possible when
@@ -197,7 +199,9 @@ static inline void destroy_context(struct mm_struct *mm)


static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
{
{
#ifndef CONFIG_SMP
	write_aux_reg(ARC_REG_SCRATCH_DATA0, next->pgd);
	write_aux_reg(ARC_REG_SCRATCH_DATA0, next->pgd);
#endif


	/* Unconditionally get a new ASID */
	/* Unconditionally get a new ASID */
	get_new_mmu_context(next);
	get_new_mmu_context(next);
+9 −0
Original line number Original line Diff line number Diff line
@@ -6,4 +6,13 @@
 * published by the Free Software Foundation.
 * published by the Free Software Foundation.
 */
 */


/*
 * xchg() based mutex fast path maintains a state of 0 or 1, as opposed to
 * atomic dec based which can "count" any number of lock contenders.
 * This ideally needs to be fixed in core, but for now switching to dec ver.
 */
#if defined(CONFIG_SMP) && (CONFIG_NR_CPUS > 2)
#include <asm-generic/mutex-dec.h>
#else
#include <asm-generic/mutex-xchg.h>
#include <asm-generic/mutex-xchg.h>
#endif
Loading