-
Notifications
You must be signed in to change notification settings - Fork 6
/
context_switch.s
169 lines (149 loc) · 2.84 KB
/
context_switch.s
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/*
* Copyright (C) 2021-2022 Gary Sims
* Copyright (C) 2022 Keith Standiford
* All rights reserved.
*
* Portions copyright (C) 2017 Scott Nelson
* Portions copyright (C) 2015-2018 National Cheng Kung University, Taiwan
* Portions copyright (C) 2014-2017 Chris Stones
*
* SPDX-License-Identifier: BSD-3-Clause
*/
.thumb
.syntax unified
.type isr_svcall, %function
.global isr_svcall
.type isr_systick, %function
.global isr_systick
isr_svcall:
isr_systick:
mrs r0, psp
/* Save r4, r5, r6, r7, and lr first
even though that isn't the stack order, as we need
to use those registers in a moment */
subs r0, #4
mov r1, lr
str r1, [r0]
subs r0, #16
stmia r0!, {r4,r5, r6, r7}
mov r4, r8
mov r5, r9
mov r6, r10
mov r7, r11
subs r0, #32
stmia r0!, {r4,r5, r6, r7}
subs r0, #16 /* fix r0 to point to end of stack frame, 36 bytes from original r0 */
/* load kernel state from stack*/
/*
+------+
| LR |
| R7 |
| R6 |
| R5 |
| R4 |
| R12 | NB: R12 (i.e IP which holds the PSR) is included, unlike user state
| R11 |
| R10 |
| R9 |
| R8 | <- POP from here
+------+
*/
pop {r1, r2, r3, r4, r5}
mov r8, r1
mov r9, r2
mov r10, r3
mov r11, r4
mov r12, r5 /* r12 is ip */
pop {r4, r5, r6, r7}
msr psr_nzcvq, ip
pop {pc}
.global __piccolo_pre_switch
__piccolo_pre_switch:
/* save kernel state */
/*
+------+
| LR |
| R7 |
| R6 |
| R5 |
| R4 |
| R12 | NB: R12 (i.e IP) is included, unlike user state
| R11 |
| R10 |
| R9 |
| R8 |
+------+
*/
mrs ip, psr
push {r4, r5, r6, r7, lr}
mov r1, r8
mov r2, r9
mov r3, r10
mov r4, r11
mov r5, r12
push {r1, r2, r3, r4, r5}
/* load user state */
/*
+------+
| LR |
| R7 |
| R6 |
| R5 |
| R4 |
| R11 |
| R10 |
| R9 |
| R8 | <- r0
+------+
*/
ldmia r0!,{r4-r7}
mov r8, r4
mov r9, r5
mov r10, r6
mov r11, r7
ldmia r0!,{r4-r7}
ldmia r0!,{r1}
mov lr, r1
msr psp, r0 /* r0 is usertask_stack_start from activate(usertask_stack_start); */
/* jump to user task */
bx lr
.global __piccolo_task_init_stack
__piccolo_task_init_stack:
/* save kernel state */
/*
+------+
| LR |
| R7 |
| R6 |
| R5 |
| R4 |
| R12 | NB: R12 (i.e IP which holds the PSR) is included, unlike user state
| R11 |
| R10 |
| R9 |
| R8 |
+------+
*/
mrs ip, psr
push {r4, r5, r6, r7, lr}
mov r1, r8
mov r2, r9
mov r3, r10
mov r4, r11
mov r5, r12
push {r1, r2, r3, r4, r5}
/* switch to process stack */
msr psp, r0
movs r0, #2
msr control, r0
isb
/* intentionally continue down into piccolo_syscall */
/* same as bl piccolo_syscall, if the code wasn't below */
.global piccolo_yield
.global piccolo_syscall
piccolo_yield:
piccolo_syscall:
nop
svc 0
nop
bx lr