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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
|
// To keep this in the first portion of the binary.
.section ".text.boot"
// Make _start global.
.globl _start
_start:
reset:
cpsid if
// disable core0,1,2.
mrc p15, #0, r1, c0, c0, #5
and r1, r1, #3
cmp r1, #1
beq core1run
cmp r1, #2
beq core2run
cmp r1, #3
bge core3run
// set vector address.
ldr r0, =vector
mcr p15, 0, r0, c12, c0, 0
// Setup sp in IRQ mode.
cps #0x12
mov sp,#0x4000
// Setup sp in FIQ mode.
cps #0x11
mov sp,#0x2000
// Setup sp in UNDEF mode.
cps #0x1B
mov sp,#0x1000
// Setup sp in ABORT mode.
cps #0x17
mov sp,#0x0800
// Setup sp in USR/SYS mode.
cps #0x1f
mov sp,#0x6000
// Setup sp in SVC mode.
cps #0x13
mov sp, #0x8000
// Clear out bss.
ldr r4, =__bss_start
ldr r9, =__bss_end
mov r5, #0
mov r6, #0
mov r7, #0
mov r8, #0
b 2f
1:
// store multiple at r4.
stmia r4!, {r5-r8}
// If we are still below bss_end, loop.
2:
cmp r4, r9
blo 1b
// Call kernel_main
ldr r3, =kernel_main
blx r3
irq:
push {r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
bl c_irq_handler
pop {r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
subs pc, lr, #4
// TODO: Each core needs to set up their stacks
core1run:
core2run:
core3run:
.globl io_halt
io_halt:
wfi
b io_halt
undefined:
stmfd sp!, {r0-r12,lr}
ldr r4, [lr, #-4]
mov r0, #0
mov r1, #17
ldr r2, =undefined_msg
bl draw_string
mov r0, #18
mov r1, #17
mov r2, r4
bl draw_hex32
mov r0, #27
mov r1, #17
ldr r2, =undefined_at
bl draw_string
// Output lr
mov r1, #0x1000
ldr r0, [r1, #-4]
sub r2, r0, #4
mov r0, #31
mov r1, #17
bl draw_hex32
// Skip instruction for now
// In future,
// ldmfd sp!, {r0-r12,lr} // Note the lack of ^ since subs will handle it
// subs pc, lr, #4
ldmfd sp!, {r0-r12,pc}^
svc:
stmfd sp!, {r0-r12,lr}
ldr r0, [lr, #-4]
bic r0, #0xFF000000
// SVC #0 returns to supervisor mode
// TODO: Make supervisor mode return to a specific location
// (rather than to a user location) such as the kernel loop
cmp r0, #3
bgt svc_exit
beq svc_000003
cmp r0, #2
beq svc_000002
cmp r0, #1
beq svc_000001
cmp r0, #1
beq svc_000000
svc_000000:
cps #0x13
b svc_exit
svc_000001:
b svc_exit
svc_000002:
ldmfd sp!, {r0-r12,lr}
b schedule
svc_000003:
ldr r3, =scheduler
ldr r2, [r3, #0]
ldr r1, [r2, #8] // sp_base
cmp r1, #-1
beq svc_exit
ldr r3, =stacks_table
mov r0, #0
strb r0, [r3, r1]
// Free the thread after freeing the stack
mov r0, r2
bl free
b svc_exit
svc_exit:
ldmfd sp!, {r0-r12,pc}^
prefetch:
stmfd sp!, {r0-r12,lr}
mov r4, lr
mov r0, #0
mov r1, #16
ldr r2, =prefetch_msg
bl draw_string
// Output return address
mov r0, #17
mov r1, #16
mov r2, r4
bl draw_hex32
ldmfd sp!, {r0-r12,lr}
subs pc, lr, #4
data:
stmfd sp!, {r0-r12,lr}
mov r4, lr
mov r0, #0
mov r1, #15
ldr r2, =data_msg
bl draw_string
// Output return address
mov r0, #13
mov r1, #15
mov r2, r4
sub r2, #8
bl draw_hex32
mov r0, #22
mov r1, #15
ldr r2, [r4, #-8]
bl draw_hex32
ldmfd sp!, {r0-r12,lr}
subs pc, lr, #4 // Should be 8 once I can actually handle the abort
fiq:
stmfd sp!, {r0-r12,lr}
bl c_fiq_handler
cmp r0, #1
bne 1f
ldmfd sp!, {r0-r12,lr}
sub lr, #4
push {r3}
ldr r3, =irqlr
str lr, [r3, #0]
pop {r3}
cps #0x13
b schedule
1:
ldmfd sp!, {r0-r12,lr}
subs pc, lr, #4
.align 5
vector:
ldr pc, reset_handler
ldr pc, undefined_handler
ldr pc, svc_handler
ldr pc, prefetch_handler
ldr pc, data_handler
ldr pc, unused_handler
ldr pc, irq_handler
ldr pc, fiq_handler
reset_handler: .word reset
undefined_handler: .word undefined
svc_handler: .word svc
prefetch_handler: .word prefetch
data_handler: .word data
unused_handler: .word io_halt
irq_handler: .word irq
fiq_handler: .word fiq
.section .data
undefined_msg: .asciz "Undefined Handler"
undefined_at: .asciz "@ 0x"
svc_msg: .asciz "SVC Handler #"
prefetch_msg: .asciz "Prefetch Handler"
data_msg: .asciz "Data Handler"
fiq_msg: .asciz "FIQ\n"
|