Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[platform/adaptation/renesas_rcar/renesas_kernel.git] / arch / hexagon / kernel / vm_switch.S
1 /*
2  * Context switch support for Hexagon
3  *
4  * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 and
8  * only version 2 as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  * 02110-1301, USA.
19  */
20
21 #include <asm/asm-offsets.h>
22
23 .text
24
25 /*
26  * The register used as a fast-path thread information pointer
27  * is determined as a kernel configuration option.  If it happens
28  * to be a callee-save register, we're going to be saving and
29  * restoring it twice here.
30  *
31  * This code anticipates a revised ABI where R20-23 are added
32  * to the set of callee-save registers, but this should be
33  * backward compatible to legacy tools.
34  */
35
36
37 /*
38  *      void switch_to(struct task_struct *prev,
39  *              struct task_struct *next, struct task_struct *last);
40  */
41         .p2align 2
42         .globl __switch_to
43         .type   __switch_to, @function
44
45 /*
46  * When we exit the wormhole, we need to store the previous task
47  * in the new R0's pointer.  Technically it should be R2, but they should
48  * be the same; seems like a legacy thing.  In short, don't butcher
49  * R0, let it go back out unmolested.
50  */
51
52 __switch_to:
53         /*
54          * Push callee-saves onto "prev" stack.
55          * Here, we're sneaky because the LR and FP
56          * storage of the thread_stack structure
57          * is automagically allocated by allocframe,
58          * so we pass struct size less 8.
59          */
60         allocframe(#(_SWITCH_STACK_SIZE - 8));
61         memd(R29+#(_SWITCH_R2726))=R27:26;
62         memd(R29+#(_SWITCH_R2524))=R25:24;
63         memd(R29+#(_SWITCH_R2322))=R23:22;
64         memd(R29+#(_SWITCH_R2120))=R21:20;
65         memd(R29+#(_SWITCH_R1918))=R19:18;
66         memd(R29+#(_SWITCH_R1716))=R17:16;
67         /* Stash thread_info pointer in task_struct */
68         memw(R0+#_TASK_THREAD_INFO) = THREADINFO_REG;
69         memw(R0 +#(_TASK_STRUCT_THREAD + _THREAD_STRUCT_SWITCH_SP)) = R29;
70         /* Switch to "next" stack and restore callee saves from there */
71         R29 = memw(R1 + #(_TASK_STRUCT_THREAD + _THREAD_STRUCT_SWITCH_SP));
72         {
73             R27:26 = memd(R29+#(_SWITCH_R2726));
74             R25:24 = memd(R29+#(_SWITCH_R2524));
75         }
76         {
77             R23:22 = memd(R29+#(_SWITCH_R2322));
78             R21:20 = memd(R29+#(_SWITCH_R2120));
79         }
80         {
81             R19:18 = memd(R29+#(_SWITCH_R1918));
82             R17:16 = memd(R29+#(_SWITCH_R1716));
83         }
84         {
85             /* THREADINFO_REG is currently one of the callee-saved regs
86              * above, and so be sure to re-load it last.
87              */
88             THREADINFO_REG = memw(R1 + #_TASK_THREAD_INFO);
89             R31:30 = memd(R29+#_SWITCH_FP);
90         }
91         {
92             R29 = add(R29,#_SWITCH_STACK_SIZE);
93             jumpr R31;
94         }
95         .size   __switch_to, .-__switch_to