• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * Vineetg: Aug 2009
9  *  -"C" version of lowest level context switch asm macro called by schedular
10  *   gcc doesn't generate the dward CFI info for hand written asm, hence can't
11  *   backtrace out of it (e.g. tasks sleeping in kernel).
12  *   So we cheat a bit by writing almost similar code in inline-asm.
13  *  -This is a hacky way of doing things, but there is no other simple way.
14  *   I don't want/intend to extend unwinding code to understand raw asm
15  */
16 
17 #include <asm/asm-offsets.h>
18 #include <linux/sched.h>
19 #ifdef CONFIG_ARC_PLAT_EZNPS
20 #include <plat/ctop.h>
21 #endif
22 
23 #define KSP_WORD_OFF 	((TASK_THREAD + THREAD_KSP) / 4)
24 
25 struct task_struct *__sched
__switch_to(struct task_struct * prev_task,struct task_struct * next_task)26 __switch_to(struct task_struct *prev_task, struct task_struct *next_task)
27 {
28 	unsigned int tmp;
29 	unsigned int prev = (unsigned int)prev_task;
30 	unsigned int next = (unsigned int)next_task;
31 
32 	__asm__ __volatile__(
33 		/* FP/BLINK save generated by gcc (standard function prologue */
34 		"st.a    r13, [sp, -4]   \n\t"
35 		"st.a    r14, [sp, -4]   \n\t"
36 		"st.a    r15, [sp, -4]   \n\t"
37 		"st.a    r16, [sp, -4]   \n\t"
38 		"st.a    r17, [sp, -4]   \n\t"
39 		"st.a    r18, [sp, -4]   \n\t"
40 		"st.a    r19, [sp, -4]   \n\t"
41 		"st.a    r20, [sp, -4]   \n\t"
42 		"st.a    r21, [sp, -4]   \n\t"
43 		"st.a    r22, [sp, -4]   \n\t"
44 		"st.a    r23, [sp, -4]   \n\t"
45 		"st.a    r24, [sp, -4]   \n\t"
46 #ifndef CONFIG_ARC_CURR_IN_REG
47 		"st.a    r25, [sp, -4]   \n\t"
48 #else
49 		"sub     sp, sp, 4      \n\t"	/* usual r25 placeholder */
50 #endif
51 
52 		/* set ksp of outgoing task in tsk->thread.ksp */
53 #if KSP_WORD_OFF <= 255
54 		"st.as   sp, [%3, %1]    \n\t"
55 #else
56 		/*
57 		 * Workaround for NR_CPUS=4k
58 		 * %1 is bigger than 255 (S9 offset for st.as)
59 		 */
60 		"add2    r24, %3, %1     \n\t"
61 		"st      sp, [r24]       \n\t"
62 #endif
63 
64 		/*
65 		 * setup _current_task with incoming tsk.
66 		 * optionally, set r25 to that as well
67 		 * For SMP extra work to get to &_current_task[cpu]
68 		 * (open coded SET_CURR_TASK_ON_CPU)
69 		 */
70 #ifndef CONFIG_SMP
71 		"st  %2, [@_current_task]	\n\t"
72 #else
73 #ifdef CONFIG_ARC_PLAT_EZNPS
74 		"lr   r24, [%4]		\n\t"
75 #ifndef CONFIG_EZNPS_MTM_EXT
76 		"lsr  r24, r24, 4		\n\t"
77 #endif
78 #else
79 		"lr   r24, [identity]		\n\t"
80 		"lsr  r24, r24, 8		\n\t"
81 		"bmsk r24, r24, 7		\n\t"
82 #endif
83 		"add2 r24, @_current_task, r24	\n\t"
84 		"st   %2,  [r24]		\n\t"
85 #endif
86 #ifdef CONFIG_ARC_CURR_IN_REG
87 		"mov r25, %2   \n\t"
88 #endif
89 
90 		/* get ksp of incoming task from tsk->thread.ksp */
91 		"ld.as  sp, [%2, %1]   \n\t"
92 
93 		/* start loading it's CALLEE reg file */
94 
95 #ifndef CONFIG_ARC_CURR_IN_REG
96 		"ld.ab   r25, [sp, 4]   \n\t"
97 #else
98 		"add    sp, sp, 4       \n\t"
99 #endif
100 		"ld.ab   r24, [sp, 4]   \n\t"
101 		"ld.ab   r23, [sp, 4]   \n\t"
102 		"ld.ab   r22, [sp, 4]   \n\t"
103 		"ld.ab   r21, [sp, 4]   \n\t"
104 		"ld.ab   r20, [sp, 4]   \n\t"
105 		"ld.ab   r19, [sp, 4]   \n\t"
106 		"ld.ab   r18, [sp, 4]   \n\t"
107 		"ld.ab   r17, [sp, 4]   \n\t"
108 		"ld.ab   r16, [sp, 4]   \n\t"
109 		"ld.ab   r15, [sp, 4]   \n\t"
110 		"ld.ab   r14, [sp, 4]   \n\t"
111 		"ld.ab   r13, [sp, 4]   \n\t"
112 
113 		/* last (ret value) = prev : although for ARC it mov r0, r0 */
114 		"mov     %0, %3        \n\t"
115 
116 		/* FP/BLINK restore generated by gcc (standard func epilogue */
117 
118 		: "=r"(tmp)
119 		: "n"(KSP_WORD_OFF), "r"(next), "r"(prev)
120 #ifdef CONFIG_ARC_PLAT_EZNPS
121 		, "i"(CTOP_AUX_LOGIC_GLOBAL_ID)
122 #endif
123 		: "blink"
124 	);
125 
126 	return (struct task_struct *)tmp;
127 }
128