lk启动汇编部分

arm 汇编简单介绍

汇编
1
2
3
4
5
6
b:  用于不返回的跳转,比如跳到某个标号处,b  .  
其中的‘.’代表当前地址,那么 b . 就是死循环。
bl: 用于子程序跳转,要返回地址,返回地址存于LR中。
当发生bl跳转前,会在寄存器 R14 (即LR)中保存当前PC-4,即bl跳转指令的下一条指令的地址。
所以在返回时只要 MOV pc,lr 。
pc: 正在执行的代码地址
MRC/MCR指令:
1
2
mrc p15, 0, r0, c1, c0{, 0}     ;将 CP15 的寄存器 C1 的值读到 r0 中
mcr p15, 0, r0, c1, c0{, 0} ;将 r0 的值写到 CP15 的寄存器 C1 中
MRS/MSR:
1
2
MRS: 程序状态寄存器到通用寄存器的数据传送指令
MSR: 通用寄存器到程序状态寄存器的数据传送指令
CP15 中的寄存器 C1 的编码格式及含义说明如下:

C1中的控制位含义:

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
M(bit[0])
0 :禁止 MMU 或者 PU
1 :使能 MMU 或者 PU

A(bit[1])
0 :禁止地址对齐检查
1 :使能地址对齐检查

C(bit[2])
当数据cache和指令cache分开时,本控制位禁止/使能数据cache。当数据cache和指令cache统一时,该控制位禁止/使能整个cache。
0 :禁止数据 / 整个 cache
1 :使能数据 / 整个 cache

W(bit[3])
0 :禁止写缓冲
1 :使能写缓冲

P(bit[4])
0 :异常中断处理程序进入 32 位地址模式
1 :异常中断处理程序进入26 位地址模式

D(bit[5])
0 :禁止 26 位地址异常检查
1 :使能 26 位地址异常检查

L(bit[6])
0 :选择早期中止模型
1 :选择后期中止模型

B(bit[7])
0 : little endian
1 : big endian

S(bit[8])
在基于 MMU 的存储系统中,本位用作系统保护

R(bit[9])
在基于 MMU 的存储系统中,本位用作 ROM 保护

F(bit[10])
由生产商定义

Z(bit[11])
0 :禁止跳转预测功能
1 :使能跳转预测功能

I(bit[12])
当数据cache和指令cache是分开的,本控制位禁止/使能指令cache
0 :禁止指令 cache
1 :使能指令 cache

V(bit[13])
0 :选择低端异常中断向量 0x0~0x1c
1 :选择高端异常中断向量0xffff0000~ 0xffff001c

PR(bit[14])
0 :常规的 cache 淘汰算法,如随机淘汰
1 :预测性淘汰算法,如round-robin 淘汰算法

L4(bit[15])
0 :保持 ARMv5 以上版本的正常功能
1 :将 ARMv5 以上版本与以前版本处理器兼容,不根据跳转地址的 bit[0] 进行 ARM 指令和 Thumb 状态切换: bit[0] 等于 0 表示 ARM 指令,等于 1 表示 Thumb 指令

Bits[31:16])
保留将来使用
CPSR 当前程序状态寄存器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
bit32
bit[31:24]为条件标志位域,用f 表示;
bit[23:16]为状态位域,用s 表示;
bit[15:8]为扩展位域,用x 表示;
bit[7:0]为控制位域,用c 表示;

运行模式位[4-0]
0b10000 用户模式user
0b10001 FIQ模式
0b10010 IRQ模式
0b10011 管理模式
0b10111 终止模式Abort
0b11011 未定义模式
0b11111 系统模式
IFT[7-5],I=1禁止IRQ,F=1禁止FIQ,T=1执行thumb指令

[27-8]保留

NZCV[31-28]
N-(负)标志,N=1表示运算结果为负数,N=0表示运算结果为正数或零
Z-(零)标志,Z=1表示运算结果为零,Z=0表示运算结果为非零
C-(进位)标志
V-(溢出)标志

lk/arch/arm/arm/start.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
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
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
#include <asm.h>
#include <arch/arm/cores.h>
#include <arch/arm/mmu.h>
#include <kernel/vm.h>

.section ".text.boot"
.globl _start // 声明全局符号_start
_start:
b platform_reset
b arm_undefined
b arm_syscall
b arm_prefetch_abort
b arm_data_abort
b arm_reserved
b arm_irq
b arm_fiq
#if WITH_SMP
b arm_reset
#endif

.weak platform_reset
platform_reset:
/* Fall through for the weak symbol */

.globl arm_reset
arm_reset:
/* do some early cpu setup */
mrc p15, 0, r12, c1, c0, 0
/* i/d cache disable, mmu disabled */
bic r12, #(1<<12)
bic r12, #(1<<2 | 1<<0)
#if WITH_KERNEL_VM
/* enable caches so atomics and spinlocks work */
orr r12, r12, #(1<<12)
orr r12, r12, #(1<<2)
#endif // WITH_KERNEL_VM
mcr p15, 0, r12, c1, c0, 0

/* calculate the physical offset from our eventual virtual location */
.Lphys_offset:
ldr r4, =.Lphys_offset
adr r11, .Lphys_offset
sub r11, r11, r4

#if WITH_SMP
/* figure out our cpu number */
mrc p15, 0, r12, c0, c0, 5 /* read MPIDR */

/* mask off the bottom bits to test cluster number:cpu number */
ubfx r12, r12, #0, #SMP_CPU_ID_BITS

/* if we're not cpu 0:0, fall into a trap and wait */
teq r12, #0
movne r0, r12
bne arm_secondary_setup
#endif // WITH_SMP

#if WITH_CPU_EARLY_INIT
/* call platform/arch/etc specific init code */
bl __cpu_early_init
#endif // WITH_CPU_EARLY_INIT

#if WITH_NO_PHYS_RELOCATION
/* assume that image is properly loaded in physical memory */
#else
/* see if we need to relocate to our proper location in physical memory */
adr r4, _start /* this emits sub r4, pc, #constant */
ldr r5, =(MEMBASE + KERNEL_LOAD_OFFSET) /* calculate the binary's physical load address */
subs r12, r4, r5 /* calculate the delta between where we're loaded and the proper spot */
beq .Lrelocate_done

/* we need to relocate ourselves to the proper spot */
ldr r6, =__data_end
ldr r7, =(KERNEL_BASE - MEMBASE)
sub r6, r7
add r6, r12

.Lrelocate_loop: // 进行循环拷贝,将代码段拷贝到代码地址处
ldr r7, [r4], #4
str r7, [r5], #4
cmp r4, r6 // 判断拷贝是否完成
bne .Lrelocate_loop

/* we're relocated, jump to the right address */
sub pc, r12
nop /* skipped in the add to pc */

/* recalculate the physical offset */
sub r11, r11, r12

.Lrelocate_done:
#endif // !WITH_NO_PHYS_RELOCATION

#if ARM_WITH_MMU
.Lsetup_mmu:

/* set up the mmu according to mmu_initial_mappings */

/* load the base of the translation table and clear the table */
ldr r4, =arm_kernel_translation_table
add r4, r4, r11
/* r4 = physical address of translation table */

mov r5, #0
mov r6, #0

/* walk through all the entries in the translation table, setting them up */
0:
str r5, [r4, r6, lsl #2]
add r6, #1
cmp r6, #4096
bne 0b

/* load the address of the mmu_initial_mappings table and start processing */
ldr r5, =mmu_initial_mappings
add r5, r5, r11
/* r5 = physical address of mmu initial mapping table */

.Linitial_mapping_loop:
ldmia r5!, { r6-r10 }
/* r6 = phys, r7 = virt, r8 = size, r9 = flags, r10 = name */

/* round size up to 1MB alignment */
ubfx r10, r6, #0, #20
add r8, r8, r10
add r8, r8, #(1 << 20)
sub r8, r8, #1

/* mask all the addresses and sizes to 1MB boundaries */
lsr r6, #20 /* r6 = physical address / 1MB */
lsr r7, #20 /* r7 = virtual address / 1MB */
lsr r8, #20 /* r8 = size in 1MB chunks */

/* if size == 0, end of list */
cmp r8, #0
beq .Linitial_mapping_done

/* set up the flags */
ldr r10, =MMU_KERNEL_L1_PTE_FLAGS
teq r9, #MMU_INITIAL_MAPPING_FLAG_UNCACHED
ldreq r10, =MMU_INITIAL_MAP_STRONGLY_ORDERED
beq 0f
teq r9, #MMU_INITIAL_MAPPING_FLAG_DEVICE
ldreq r10, =MMU_INITIAL_MAP_DEVICE
/* r10 = mmu entry flags */

0:
orr r12, r10, r6, lsl #20
/* r12 = phys addr | flags */

/* store into appropriate translation table entry */
str r12, [r4, r7, lsl #2]

/* loop until we're done */
add r6, #1
add r7, #1
subs r8, #1
bne 0b

b .Linitial_mapping_loop

.Linitial_mapping_done:

#if MMU_WITH_TRAMPOLINE
/* move arm_kernel_translation_table address to r8 and
* set cacheable attributes on translation walk
*/
orr r8, r4, #MMU_TTBRx_FLAGS

/* Prepare tt_trampoline page table */
/* Calculate pagetable physical addresses */
ldr r4, =tt_trampoline /* r4 = tt_trampoline vaddr */
add r4, r4, r11 /* r4 = tt_trampoline paddr */

/* Zero tt_trampoline translation tables */
mov r6, #0
mov r7, #0
1:
str r7, [r4, r6, lsl#2]
add r6, #1
cmp r6, #0x1000
blt 1b

/* Setup 1M section mapping at
* phys -> phys and
* virt -> phys
*/
lsr r6, pc, #20 /* r6 = paddr index */
ldr r7, =MMU_KERNEL_L1_PTE_FLAGS
add r7, r7, r6, lsl #20 /* r7 = pt entry */

str r7, [r4, r6, lsl #2] /* tt_trampoline[paddr index] = pt entry */

rsb r6, r11, r6, lsl #20 /* r6 = vaddr */
str r7, [r4, r6, lsr #(20 - 2)] /* tt_trampoline[vaddr index] = pt entry */
#endif // MMU_WITH_TRAMPOLINE

/* set up the mmu */
bl .Lmmu_setup
#endif // WITH_KERNEL_VM

/* at this point we're running at our final location in virtual memory (if enabled) */
.Lstack_setup:
/* set up the stack for irq, fiq, abort, undefined, system/user, and lastly supervisor mode */
mov r12, #0

cpsid i,#0x12 /* irq */
mov sp, r12

cpsid i,#0x11 /* fiq */
mov sp, r12

cpsid i,#0x17 /* abort */
mov sp, r12

cpsid i,#0x1b /* undefined */
mov sp, r12

cpsid i,#0x1f /* system */
mov sp, r12

cpsid i,#0x13 /* supervisor */
ldr r12, =abort_stack
add r12, #ARCH_DEFAULT_STACK_SIZE
mov sp, r12

/* stay in supervisor mode from now on out */

/* copy the initialized data segment out of rom if necessary */
ldr r4, =__data_start_rom
ldr r5, =__data_start
ldr r6, =__data_end

cmp r4, r5
beq .L__do_bss

.L__copy_loop:
cmp r5, r6
ldrlt r7, [r4], #4
strlt r7, [r5], #4
blt .L__copy_loop

.L__do_bss:
#if FOR_VERIFICATION_DONT_CLEAR_BSS == 0
/* clear out the bss */
ldr r4, =__bss_start
ldr r5, =_end
mov r6, #0
.L__bss_loop:
cmp r4, r5
strlt r6, [r4], #4
blt .L__bss_loop
#endif
#if FOR_VERIFICATION == 1
mov r0, #0
mov r1, #0
mov r2, #0
mov r3, #0
#endif
bl lk_main
b .