]> Pileus Git - ~andy/linux/blob - arch/arc/kernel/ctx_sw.c
Merge branch 'wl12xx-next' into for-linville
[~andy/linux] / arch / arc / kernel / ctx_sw.c
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
20 struct task_struct *__sched
21 __switch_to(struct task_struct *prev_task, struct task_struct *next_task)
22 {
23         unsigned int tmp;
24         unsigned int prev = (unsigned int)prev_task;
25         unsigned int next = (unsigned int)next_task;
26         int num_words_to_skip = 1;
27 #ifdef CONFIG_ARC_CURR_IN_REG
28         num_words_to_skip++;
29 #endif
30
31         __asm__ __volatile__(
32                 /* FP/BLINK save generated by gcc (standard function prologue */
33                 "st.a    r13, [sp, -4]   \n\t"
34                 "st.a    r14, [sp, -4]   \n\t"
35                 "st.a    r15, [sp, -4]   \n\t"
36                 "st.a    r16, [sp, -4]   \n\t"
37                 "st.a    r17, [sp, -4]   \n\t"
38                 "st.a    r18, [sp, -4]   \n\t"
39                 "st.a    r19, [sp, -4]   \n\t"
40                 "st.a    r20, [sp, -4]   \n\t"
41                 "st.a    r21, [sp, -4]   \n\t"
42                 "st.a    r22, [sp, -4]   \n\t"
43                 "st.a    r23, [sp, -4]   \n\t"
44                 "st.a    r24, [sp, -4]   \n\t"
45 #ifndef CONFIG_ARC_CURR_IN_REG
46                 "st.a    r25, [sp, -4]   \n\t"
47 #endif
48                 "sub     sp, sp, %4      \n\t"  /* create gutter at top */
49
50                 /* set ksp of outgoing task in tsk->thread.ksp */
51                 "st.as   sp, [%3, %1]    \n\t"
52
53                 "sync   \n\t"
54
55                 /*
56                  * setup _current_task with incoming tsk.
57                  * optionally, set r25 to that as well
58                  * For SMP extra work to get to &_current_task[cpu]
59                  * (open coded SET_CURR_TASK_ON_CPU)
60                  */
61 #ifndef CONFIG_SMP
62                 "st  %2, [@_current_task]       \n\t"
63 #else
64                 "lr   r24, [identity]           \n\t"
65                 "lsr  r24, r24, 8               \n\t"
66                 "bmsk r24, r24, 7               \n\t"
67                 "add2 r24, @_current_task, r24  \n\t"
68                 "st   %2,  [r24]                \n\t"
69 #endif
70 #ifdef CONFIG_ARC_CURR_IN_REG
71                 "mov r25, %2   \n\t"
72 #endif
73
74                 /* get ksp of incoming task from tsk->thread.ksp */
75                 "ld.as  sp, [%2, %1]   \n\t"
76
77                 /* start loading it's CALLEE reg file */
78
79                 "add    sp, sp, %4     \n\t"    /* skip gutter at top */
80
81 #ifndef CONFIG_ARC_CURR_IN_REG
82                 "ld.ab   r25, [sp, 4]   \n\t"
83 #endif
84                 "ld.ab   r24, [sp, 4]   \n\t"
85                 "ld.ab   r23, [sp, 4]   \n\t"
86                 "ld.ab   r22, [sp, 4]   \n\t"
87                 "ld.ab   r21, [sp, 4]   \n\t"
88                 "ld.ab   r20, [sp, 4]   \n\t"
89                 "ld.ab   r19, [sp, 4]   \n\t"
90                 "ld.ab   r18, [sp, 4]   \n\t"
91                 "ld.ab   r17, [sp, 4]   \n\t"
92                 "ld.ab   r16, [sp, 4]   \n\t"
93                 "ld.ab   r15, [sp, 4]   \n\t"
94                 "ld.ab   r14, [sp, 4]   \n\t"
95                 "ld.ab   r13, [sp, 4]   \n\t"
96
97                 /* last (ret value) = prev : although for ARC it mov r0, r0 */
98                 "mov     %0, %3        \n\t"
99
100                 /* FP/BLINK restore generated by gcc (standard func epilogue */
101
102                 : "=r"(tmp)
103                 : "n"((TASK_THREAD + THREAD_KSP) / 4), "r"(next), "r"(prev),
104                   "n"(num_words_to_skip * 4)
105                 : "blink"
106         );
107
108         return (struct task_struct *)tmp;
109 }