 41195d236e
			
		
	
	
	41195d236e
	
	
	
		
			
			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: Vineet 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>
		
			
				
	
	
		
			109 lines
		
	
	
	
		
			3.2 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			109 lines
		
	
	
	
		
			3.2 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
 | |
|  *
 | |
|  * This program is free software; you can redistribute it and/or modify
 | |
|  * it under the terms of the GNU General Public License version 2 as
 | |
|  * published by the Free Software Foundation.
 | |
|  *
 | |
|  * Vineetg: Aug 2009
 | |
|  *  -"C" version of lowest level context switch asm macro called by schedular
 | |
|  *   gcc doesn't generate the dward CFI info for hand written asm, hence can't
 | |
|  *   backtrace out of it (e.g. tasks sleeping in kernel).
 | |
|  *   So we cheat a bit by writing almost similar code in inline-asm.
 | |
|  *  -This is a hacky way of doing things, but there is no other simple way.
 | |
|  *   I don't want/intend to extend unwinding code to understand raw asm
 | |
|  */
 | |
| 
 | |
| #include <asm/asm-offsets.h>
 | |
| #include <linux/sched.h>
 | |
| 
 | |
| struct task_struct *__sched
 | |
| __switch_to(struct task_struct *prev_task, struct task_struct *next_task)
 | |
| {
 | |
| 	unsigned int tmp;
 | |
| 	unsigned int prev = (unsigned int)prev_task;
 | |
| 	unsigned int next = (unsigned int)next_task;
 | |
| 	int num_words_to_skip = 1;
 | |
| #ifdef CONFIG_ARC_CURR_IN_REG
 | |
| 	num_words_to_skip++;
 | |
| #endif
 | |
| 
 | |
| 	__asm__ __volatile__(
 | |
| 		/* FP/BLINK save generated by gcc (standard function prologue */
 | |
| 		"st.a    r13, [sp, -4]   \n\t"
 | |
| 		"st.a    r14, [sp, -4]   \n\t"
 | |
| 		"st.a    r15, [sp, -4]   \n\t"
 | |
| 		"st.a    r16, [sp, -4]   \n\t"
 | |
| 		"st.a    r17, [sp, -4]   \n\t"
 | |
| 		"st.a    r18, [sp, -4]   \n\t"
 | |
| 		"st.a    r19, [sp, -4]   \n\t"
 | |
| 		"st.a    r20, [sp, -4]   \n\t"
 | |
| 		"st.a    r21, [sp, -4]   \n\t"
 | |
| 		"st.a    r22, [sp, -4]   \n\t"
 | |
| 		"st.a    r23, [sp, -4]   \n\t"
 | |
| 		"st.a    r24, [sp, -4]   \n\t"
 | |
| #ifndef CONFIG_ARC_CURR_IN_REG
 | |
| 		"st.a    r25, [sp, -4]   \n\t"
 | |
| #endif
 | |
| 		"sub     sp, sp, %4      \n\t"	/* create gutter at top */
 | |
| 
 | |
| 		/* set ksp of outgoing task in tsk->thread.ksp */
 | |
| 		"st.as   sp, [%3, %1]    \n\t"
 | |
| 
 | |
| 		"sync   \n\t"
 | |
| 
 | |
| 		/*
 | |
| 		 * setup _current_task with incoming tsk.
 | |
| 		 * optionally, set r25 to that as well
 | |
| 		 * For SMP extra work to get to &_current_task[cpu]
 | |
| 		 * (open coded SET_CURR_TASK_ON_CPU)
 | |
| 		 */
 | |
| #ifndef CONFIG_SMP
 | |
| 		"st  %2, [@_current_task]	\n\t"
 | |
| #else
 | |
| 		"lr   r24, [identity]		\n\t"
 | |
| 		"lsr  r24, r24, 8		\n\t"
 | |
| 		"bmsk r24, r24, 7		\n\t"
 | |
| 		"add2 r24, @_current_task, r24	\n\t"
 | |
| 		"st   %2,  [r24]		\n\t"
 | |
| #endif
 | |
| #ifdef CONFIG_ARC_CURR_IN_REG
 | |
| 		"mov r25, %2   \n\t"
 | |
| #endif
 | |
| 
 | |
| 		/* get ksp of incoming task from tsk->thread.ksp */
 | |
| 		"ld.as  sp, [%2, %1]   \n\t"
 | |
| 
 | |
| 		/* start loading it's CALLEE reg file */
 | |
| 
 | |
| 		"add    sp, sp, %4     \n\t"	/* skip gutter at top */
 | |
| 
 | |
| #ifndef CONFIG_ARC_CURR_IN_REG
 | |
| 		"ld.ab   r25, [sp, 4]   \n\t"
 | |
| #endif
 | |
| 		"ld.ab   r24, [sp, 4]   \n\t"
 | |
| 		"ld.ab   r23, [sp, 4]   \n\t"
 | |
| 		"ld.ab   r22, [sp, 4]   \n\t"
 | |
| 		"ld.ab   r21, [sp, 4]   \n\t"
 | |
| 		"ld.ab   r20, [sp, 4]   \n\t"
 | |
| 		"ld.ab   r19, [sp, 4]   \n\t"
 | |
| 		"ld.ab   r18, [sp, 4]   \n\t"
 | |
| 		"ld.ab   r17, [sp, 4]   \n\t"
 | |
| 		"ld.ab   r16, [sp, 4]   \n\t"
 | |
| 		"ld.ab   r15, [sp, 4]   \n\t"
 | |
| 		"ld.ab   r14, [sp, 4]   \n\t"
 | |
| 		"ld.ab   r13, [sp, 4]   \n\t"
 | |
| 
 | |
| 		/* last (ret value) = prev : although for ARC it mov r0, r0 */
 | |
| 		"mov     %0, %3        \n\t"
 | |
| 
 | |
| 		/* FP/BLINK restore generated by gcc (standard func epilogue */
 | |
| 
 | |
| 		: "=r"(tmp)
 | |
| 		: "n"((TASK_THREAD + THREAD_KSP) / 4), "r"(next), "r"(prev),
 | |
| 		  "n"(num_words_to_skip * 4)
 | |
| 		: "blink"
 | |
| 	);
 | |
| 
 | |
| 	return (struct task_struct *)tmp;
 | |
| }
 |