First version
[3rdparty/ote_partner/tlk.git] / arch / arm / arm / asm.S
1 /*
2  * Copyright (c) 2008 Travis Geiselbrecht
3  * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files
7  * (the "Software"), to deal in the Software without restriction,
8  * including without limitation the rights to use, copy, modify, merge,
9  * publish, distribute, sublicense, and/or sell copies of the Software,
10  * and to permit persons to whom the Software is furnished to do so,
11  * subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 #include <asm.h>
25 #include <arch/arm.h>
26 #include <arch/arch_thread.h>
27 #include <kernel/task.h>
28
29 #if ARM_WITH_LPAE
30 #include <arch/arm/mmu_ldesc_macros.h>
31 #else
32 #include <arch/arm/mmu_sdesc_macros.h>
33 #endif
34
35 /* arm_make_thread_current(thread_t *thread) */
36 FUNCTION(arm_make_thread_current)
37         ldr     r14, [r0, #THREAD_ARCH_TASK]
38         cmp     r14, #0
39         beq     page_table_current
40
41         /* switch user page tables */
42         ldr     r1, [r14, #TASK_PAGETABLE]
43         ldr     r2, [r14, #TASK_CONTEXTID]
44         mmu_desc_switch_pt r1, r2, r3, r4
45         isb
46
47 #if ARM_WITH_NEON
48         /* reload thread's FPEXC state */
49         ldr     r1, [r0, #THREAD_ARCH_FPCTX]
50         ldr     r2, [r1, #FPCTX_FPEXC]
51         mcr     p10, 7, r2, c8, c0, 0
52 #endif
53
54 page_table_current:
55         /* thread state (frame) kept on kernel stack */
56         ldr     r14, [r0, #THREAD_ARCH_KERN_STACK]
57
58         /* restore psr (and thread init into user mode) */
59         ldr     r1, [r14, #CSF_OFFSET_PSR]
60         and     r2, r1, #MODE_MASK
61         cmp     r2, #MODE_USR
62         beq     return_to_user
63
64 continue_in_svc:
65         /* safe to set cpsr directly (same mode) */
66         msr     cpsr_fsxc, r1
67
68         ldmia   r14, { r0-r13 }
69         add     r14, #CSF_OFFSET_LR
70         ldmia   r14, { lr, pc }
71
72 return_to_user:
73         /* setup next mode in shadow spsr */
74         msr     spsr_fsxc, r1
75
76         /* restores sp_usr/lr_usr from lr_svc (still context frame ptr) */
77         ldmia   r14, { r0-r13, r14 }^
78
79         /* set sp_svc also (syscalls use this stack) and return */
80         add     r13, r14, #CSF_SIZE
81         ldr     r14, [r14, #CSF_OFFSET_PC]
82         movs    pc, r14
83
84
85 /* arm_context_switch(thread_t *old_thread, thread_t *new_thread) */
86 FUNCTION(arm_context_switch)
87         /* save context frame ptr */
88         sub     r3, sp, #CSF_SIZE
89         str     r3, [r0, #THREAD_ARCH_KERN_STACK]
90
91         /* fill in context frame */
92         stmia   r3, { r0-r13, r14 }
93         str     lr, [r3, #CSF_OFFSET_PC]
94         mrs     r4, cpsr
95         str     r4, [r3, #CSF_OFFSET_PSR]
96
97         clrex
98         mov     r0, r1
99         b       arm_make_thread_current
100 .ltorg
101
102
103 FUNCTION(arm_save_mode_regs)
104         mrs             r1, cpsr
105
106 #if ARM_ISA_ARMv6
107         cps             #0x11                   /* fiq */
108         str             r13, [r0], #4
109         str             r14, [r0], #4
110         cps             #0x12                   /* irq */
111         str             r13, [r0], #4
112         str             r14, [r0], #4
113         cps             #0x13                   /* svc */
114         str             r13, [r0], #4
115         str             r14, [r0], #4
116         cps             #0x17                   /* abt */
117         str             r13, [r0], #4
118         str             r14, [r0], #4
119         cps             #0x1b                   /* und */
120         str             r13, [r0], #4
121         str             r14, [r0], #4
122         cps             #0x1f                   /* sys */
123         str             r13, [r0], #4
124         str             r14, [r0], #4
125 #else
126         // XXX implement
127         b               .
128 #endif
129         msr             cpsr_c, r1
130         bx              lr
131