|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
分析内核顶层Makefile,以及arch/ARM/Makefile可知,从u-boot跳到内核后,第一个启动的文件是arch/arm/kernel/head.S。接下来就围绕这个文件来分析Linux架构/开发板相关的引导过程。
8 o5 i T4 ^% N L, Q- K& Y/ |( [/ P2 {; e% t" G1 m
/******************************以下仅分析重要部分********************************/
2 L; @) S; ~3 t9 h" g0 M) V9 m, M( ]8 ^/ p$ w. `2 W
#include "head-common.S" //下面会调用到这个文件里面的函数6 q( {$ k; C* @( W$ e
) }! D, h7 M$ j `% Q......
) r8 q" L2 Y) P* m7 ?; D8 _8 I8 d8 V8 B4 J1 j0 K
/*8 Q. u, b: N3 `& |' q; k) G$ I
* Kernel startup entry point.
7 {3 T3 z: |9 N( E Y( F. j. f* ---------------------------% V% H/ D6 `" V' v2 h9 x
*
) {" b( M" G* m5 m* This is normally called from the decompressor code. The requirements
, p& [# ~$ a) W! D8 u* are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0,
' \5 H# H. y( ]& q7 E, Q* r1 = machine nr, r2 = atags pointer.7 w; M7 e9 d2 j& b6 V7 d2 S. Y
** I* r: E" p- J( j% \9 N8 G5 l
* This code is mostly position independent, so if you link the kernel at* I! O$ V( E8 k3 n7 F
* 0xc0008000, you call this at __pa(0xc0008000).
8 @) D- b) K. v: e, P1 a*9 R! S% z4 ]. \2 o/ A/ }
* See linux/arch/arm/tools/mach-types for the complete list of machine
w3 ^ v6 @ A% y; l$ \* numbers for r1.
3 Y% h- o8 k; h* ........
* @! r5 {1 C# ]( r*/) `, p4 M9 i4 h$ y
.section ".text.head", "ax" //".text.head"段,在vmlinux.lds链接文件中定义0 E/ s2 [6 t+ T& ~/ {6 J& i8 }3 W; B
ENTRY(stext) K; |) P, j- W5 X7 t0 U
msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE //确保进入管理模式并禁止中断
* }" x& i9 D% v L" @1 h mrc p15, 0, r9, c0, c0 // r9 = CPU ID$ d) ^ I3 Y7 f( g2 p
bl __lookup_processor_type // r5=procinfo r9=cpuid* m- [. H* @: Z
movs r10, r5 //如果不支持该CPU则r5=0
3 h( j2 k8 J# G* ]" x4 P& W beq __error_p //如果r5=0,则打印错误信息
' G8 x6 v; W E bl __lookup_machine_type // r5=machinfo
7 k! R1 z7 C! _ movs r8, r5 // 如果不支持该开发板r5=0
Y4 p$ Y- ^2 y9 N beq __error_a //如果r5=0,则打印错误信息4 v, D2 f& B) U
bl __vet_atags' [/ {- A6 E2 s O1 a
bl __create_page_tables" Z& h7 }, U5 T `/ F; q2 Q
9 A1 r, V, n9 H/ ^
.......
* o$ {0 i" q' c$ d ldr r13, __switch_data @ address to jump to after mmu has been enabled7 S9 {' n: k' P0 R
adr lr, __enable_mmu @ return (PIC) address
( n2 _* |% e( c) o8 o& |3 g add pc, r10, #PROCINFO_INITFUNC4 w/ g* F8 _& E" b
ENDPROC(stext)4 D1 r* O* G# o h- [
+ t9 y$ e- ^5 s; b.......! _3 J1 l# H+ m8 c
1 {3 X, X0 _9 N1 o架构/开发板相关的引导过程就是由以上蓝色部分的函数来完成的,都是汇编子程序,下面逐个分析。
* R' F' U8 Q0 c1 N# p9 d: _" }) T6 X8 H4 O2 n( m( j
__lookup_processor_type子程序在arch/arm/kernel/head-common.S文件中定义
1 [$ L- Y% t' W- P- O* t. _8 M8 k7 ]1 N9 U3 y2 ~7 C" D7 [% E3 v
/*
! F; U; h! C3 |. M: G x * r9 = cpuid
# X4 q& p- o. W- o * Returns:& d# |" p1 J0 R1 G. y. h0 R) p0 h
* r3, r4, r6 corrupted
5 K6 U2 h, Y5 V% s9 ~ * r5 = proc_info pointer in physical address space6 u+ @8 A3 z7 h4 O) a# G1 p, u
* r9 = cpuid (preserved)- \# ^9 R: u+ }
*/. Q+ e1 q% p# d3 ]
3 u" X; Z q0 D0 D8 s" S__lookup_processor_type:
# V+ E* s/ @0 U. x, }0 H$ y$ e! ^ adr r3, 3f //将下面3标号的物理地址存到r3寄存器, f/ X+ W* T' S4 |3 B5 O
1 n: U- d$ R# ]( Y2 E; P- r/* r5 = __proc_info_begin,r6 = __proc_info_end 的虚拟地址,r7 = 3标号的虚拟地址 */3 V x. [4 D& U6 \$ o4 ^( P
ldmda r3, {r5 - r7}! F V2 m+ B2 e
sub r3, r3, r7 // r3 = r3 - r7,物理地址与虚拟地址之差7 m+ t6 M9 C1 X
add r5, r5, r3 // r5 = __ proc_info_begin 对应的物理地址
0 g8 f8 y- G$ H+ r3 j add r6, r6, r3 // r6 = __proc_info_end 对应的物理地址/ d6 {" ^4 `: z, L. [; W9 u
1: ldmia r5, {r3, r4} // r3 = cpu_val,r4 = cpu_mask 这两个成员在proc_info_list中定义
' j2 R9 X8 ^+ m3 ?7 n and r4, r4, r9 // r4 = r4&r9 = cpu_mask & 最开始从CP15传入的cpu id" ^! Z4 q7 i) G2 P+ K! Q6 D, ]
teq r3, r4
9 Q* r6 T) k# q7 d$ G/ t; m beq 2f //相等则返回
( N- T$ F1 o; A( G5 z add r5, r5, #PROC_INFO_SZ //下一个pro_info_list ,sizeof(proc_info_list)
) l& p$ d9 ]! _0 Z( ] cmp r5, r6 //判断是否已经比较完所有的proc_info_list3 P" n( Y- ~& t3 E, M
blo 1b //否则继续比较% Z, e8 A6 Q6 g8 B) M8 i3 `
mov r5, #0 //比较完后还是没有匹配的proc_info_list结构,r5 = 0 w! P3 J) O1 |
2: mov pc, lr // 返回2 d5 {$ m- F- _0 \3 T5 z& L+ z Q
ENDPROC(__lookup_processor_type)3 m4 g: W9 ~" w& i" T/ K
& J* D1 [4 d5 m5 W.......
8 d: w2 o/ ]( \* O: Z/ `' R6 [4 m0 h
5 ~: d" g& U* t4 d0 N) K. E: t p/*
% B; W1 y# P8 V# V * Look in <asm/procinfo.h> and arch/arm/kernel/arch.[ch] for, r1 G) P) R# Y* ~/ N7 c: z
* more information about the __proc_info and __arch_info structures.
: y' ^5 @8 x, W9 [* B */0 i& m; D1 U3 q/ x2 g
.long __proc_info_begin //proc_info_list结构体的开始地址(虚拟地址)
! Q5 e7 _! _. `* D4 m6 C6 [ .long __proc_info_end //proc_info_list结构体的结束地址(虚拟地址)+ s8 m8 q; `! }# m1 i0 h, x* k
3: .long . // 3标号在内存中的的物理地址
9 a3 p) |% J/ B+ P; k .long __arch_info_begin $ W0 o" B9 V' v
.long __arch_info_end
c- m. G+ P" f4 \/ j% M# i2 B# C, K' D4 `& \3 S; L u7 P. L+ F
; }, T/ h. O1 r
: ]. [0 G0 p. ~6 s; p. Z6 O
proc_info_list结构体在arch/arm/include/asm中定义
- a% J* l$ x! A H0 E
" }' ^1 |9 W1 j- W8 Estruct proc_info_list {
/ y) W+ ]7 @6 w7 v: ? unsigned int cpu_val;- l! H0 ~7 d' b# @# o
unsigned int cpu_mask;
. m' g. F9 s) S+ s5 H2 ?* g' h unsigned long __cpu_mm_mmu_flags; /* used by head.S */3 ?4 v( R! F a( R4 g; j* b4 Y
unsigned long __cpu_io_mmu_flags; /* used by head.S */
" n3 j, V1 T2 I" p unsigned long __cpu_flush; /* used by head.S */
( _7 h) V% ~- W const char *arch_name;2 i) J6 w8 D* L2 x% R2 [
const char *elf_name;
: K) F, R' R& ]5 q unsigned int elf_hwcap;1 T1 q# {7 b1 @; u
const char *cpu_name;
' ~" J: f1 J8 j- K struct processor *proc;
5 h4 F2 p- Z- H9 | struct cpu_tlb_fns *tlb;
/ N! o9 m& N% _ struct cpu_user_fns *user;3 }4 y4 U s6 J5 x4 s9 T' u
struct cpu_cache_fns *cache;1 O1 M R4 G O2 x( [7 C# P
};: x7 s( [2 {, v
8 K- l, C& j* o
对于S3C2440开发板的匹配,它的CPU ID是0x41129200,可查询协处理器的CP15获知。
7 w% ?; _' _ @# x6 c) v5 i% e1 F* e, U' ^8 s% g! x. ~7 \
而在arch/arm/mm/proc_arm920.S中定义的__arm920_proc_info结构如下
9 ]) n0 ^. q& e5 z" |
" C: z( D& {: i# P& D" Z s* r3 C__arm920_proc_info:
, N% s1 y y$ f# w* b .long 0x41009200
* \" c( o1 L+ |. x .long 0xff00fff00 I' F P) m4 ]) A# t0 ^
( Y7 b; r! M6 L. m5 w: h+ q
........
, [7 N: T4 t, l
* C# i3 S+ o8 V R即r3 = cpu_val = 0x41009200,r4 = cpu_mask = 0xff00ff00,刚好匹配。5 i& G+ B) ?$ d# V g! W
1 Y- D7 ~3 E; d# j1 H" m
/ `- d& R9 R5 Y" a' ?4 w- x5 [2 ^. v" M; t, ~3 L! ]& o. _
__lookup_machine_type子程序也在arch/arm/kernel/head-common.S文件中定义
% Y7 \# ]+ m/ i; w0 }' \6 q0 B5 R& A" t" G* N+ C& z8 L+ j
/*% N$ N$ |& c, r# i. X- ?
& T0 t6 E6 A# s# e
* ....# D( X l8 C- u& L E
; `2 r+ y' Z" n( H0 U& o- V# t4 r, p
* r1 = machine architecture number
/ r) e0 u4 Q9 l * Returns:; F6 ]$ D( Q( [: r+ Z1 ^" P
* r3, r4, r6 corrupted
F) M7 l" ]* h ?2 U * r5 = mach_info pointer in physical address space0 _( ~/ O# ~% d `% V
*/
q: N7 A' ]! r G w* M# s w9 @* m__lookup_machine_type:
. B' q. ]3 R+ A7 r adr r3, 3b //获得3标号的物理地址
) C4 S; q) C( f/ {8 Z$ q, a, ?8 O: b
/* r4 = __arch_info_begin,r6 = __arch_info_end 的虚拟地址,r7 = 3标号的虚拟地址 */
! b3 V+ }. T9 b, S( [
- g, D7 H: @2 W& L$ } ldmia r3, {r4, r5, r6}
: T" r5 q' a1 G. |1 ~ O sub r3, r3, r4 // r3 = r3 - r4 物理地址与虚拟地址之差6 ]. W" R/ { J$ _4 @! Q$ h
add r5, r5, r3 // r5 = __arch_info_begin 的物理地址
$ D7 e% V* T5 J9 R7 t% A2 m! h$ m add r6, r6, r3 // r6 = __arch_info_end 的物理地址
) P: ]- S2 y3 m9 _8 ?1 l$ E1: ldr r3, [r5, #MACHINFO_TYPE] // r5 是machine_desc结构体的地址" Q% r2 e9 ~0 `3 f1 a/ ~9 G. {
teq r3, r1 //判断从r1传入的机器ID是否匹配/ _4 x, o, O0 I; p& g
beq 2f //匹配则返回
" J4 ^( b e9 ]9 _3 X add r5, r5, #SIZEOF_MACHINE_DESC //否则,指向下一个 machine_desc
2 Q/ E. p# J1 ?5 J: q0 x cmp r5, r6 //是否已经比较完所有的machine_desc结构9 D) X; a3 \3 {
blo 1b //没有则继续比较* z5 O3 s- t2 K3 F0 W9 A" T4 ^" ~
mov r5, #0 //比较完毕之后都没有找到匹配的,r5 = 02 I- h0 e5 P" ~& z/ Y
2: mov pc, lr //返回* T) B4 `& F6 i z; Y1 }) P
ENDPROC(__lookup_machine_type)* i5 A$ \- c8 [
y1 l' j9 w; B p1 j
% S7 X) E! g' b& `- ?+ {
% L' q# h5 J9 ? d& |
machine_desc结构在 arch/arm/include/asm/mach/arch.h中定义. h* N' T" ~& G, o8 W5 c' D
+ b6 O+ t- w. v* u: A8 q1 [5 P& t
struct machine_desc {+ b$ J' p: ?; _) E4 N' I+ H0 B
/*; ]6 x1 o3 _# P1 q1 ^$ b. Z
* Note! The first four elements are used
# {9 C. ?6 V0 j! [1 v5 Y) q * by assembler code in head.S, head-common.S
, Z; W( x7 ~9 v6 `3 k */
) J5 g/ Q _) }6 v( z# _ unsigned int nr; /* architecture number */
. X0 K7 Y5 S6 _ unsigned int phys_io; /* start of physical io */8 h4 v( b% h" K. \5 [% `/ f) n
unsigned int io_pg_offst; /* byte offset for io + }' m2 U& x! v. p( C
* page tabe entry */) C) P! ?" ~0 G/ d. M# z- J
1 [" ~& ^5 k: q6 F" `# v2 o( j const char *name; /* architecture name */
" X/ _ o. i( ?0 A unsigned long boot_params; /* tagged list */
: m! v7 f3 e5 H Q X6 M* K/ z, v3 `/ n! k
unsigned int video_start; /* start of video RAM */
& T& i5 D2 d8 q$ m- T9 J5 r unsigned int video_end; /* end of video RAM */9 O* o' T o0 T# M3 R2 H
& S& r: C8 @4 N1 w- F+ h unsigned int reserve_lp0 :1; /* never has lp0 */ n; E) j1 \" L2 z6 x9 E
unsigned int reserve_lp1 :1; /* never has lp1 */; V! m$ i* \* C9 n7 N/ c
unsigned int reserve_lp2 :1; /* never has lp2 */
9 E ` _/ ~+ _4 Q$ r unsigned int soft_reboot :1; /* soft reboot */
, }3 P3 m# J6 j6 A% u void (*fixup)(struct machine_desc *,
' [5 \, Q* K4 O# d- A* ~& q9 T) O struct tag *, char **,
$ v1 h! `9 E1 w* W% J5 p struct meminfo *);
/ Y& I% f0 T& U1 A void (*map_io)(void);/* IO mapping function */
# b' w! E+ I9 H, K5 c/ |0 \ void (*init_irq)(void);3 ?6 W3 v' C2 z
struct sys_timer *timer; /* system tick timer */+ H$ W6 l% B0 Z- S1 h* s
void (*init_machine)(void);
$ x* A* h; G9 l) O+ X# i& x* L}; A, E; k0 M' c4 ]
. H7 a/ L8 a7 Z$ f#define MACHINE_START(_type,_name) \8 @% O( Z- R2 f
static const struct machine_desc __mach_desc_##_type \
5 @0 _$ C0 k8 Q2 G# o; C0 q' a Y% ` __used \
, g+ _6 W- y$ q s* Q5 y __attribute__((__section__(".arch.info.init"))) = { \. V" N5 t; Q, D) e" r
.nr = MACH_TYPE_##_type, \6 \2 ]+ g+ E* r1 [3 ?0 d/ V0 A
.name = _name,
. m! C ~+ d4 ^3 c. V5 b# @" ~# E9 F! l9 e/ `1 P% W
#define MACHINE_END \
) O% A- Y; n5 M. r# ~; _$ X* g};0 _- `3 N( I2 W$ u
2 Z& I; A& I- ?# s- [
M0 g% Y7 g5 a5 |- P; u! H8 X# E' Z6 X/ S- ?% \1 j
MACHINE_START(S3C2440, "SMDK2440")
9 d5 D+ | S" a+ l2 g" z6 R. |0 _ .phys_io = S3C2410_PA_UART,
) y! O2 a/ _) F Z$ P .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
" w- |. p+ A% H# ^; q .boot_params = S3C2410_SDRAM_PA + 0x100,$ G+ ?- }) M; ^5 v+ f
6 `3 v) p& V" m B% l5 u .init_irq = s3c24xx_init_irq,
" b- c+ p- Y/ n; K: k7 V ]2 I .map_io = smdk2440_map_io,
, X* k3 [* S5 t4 ]6 e/ q; q .init_machine = smdk2440_machine_init,
4 ~" u2 I3 o9 m# M7 A .timer = &s3c24xx_timer,
A' u( O- b0 w sMACHINE_END
3 d0 B' G& X& h* U# O
% \8 e9 t5 S/ \. a$ K* v2 F4 S% q* t ~$ \4 ^* {0 F/ k
+ z; t$ n& |5 n+ ^
由上面二个定义得到S3C2440 的machine_desc结构体
( P! H: n, c6 E3 l9 r) ~# X2 j, @% ~7 q
static const struct machine_desc __mach_desc_S3C2440
% \5 T: S$ {& |' E0 }4 J __used 5 S% ~. C5 P4 o& T2 t2 r9 N- G! F
__attribute__((__section__(".arch.info.init"))) =
4 S N6 O$ ?" _; h4 g6 r0 b, t2 [! L c! h# Z* N% D' g, L) J: O* O% \
{
4 y& o# b2 r0 j4 C* T; [ .nr = MACH_TYPE_S3C2440,
" f, L) o P+ j2 T$ ^& X9 L7 l .name = "SMDK2440",
- k/ Y4 B4 W, I- s% B$ [2 b- b .phys_io = S3C2410_PA_UART,$ C! T2 c( e) l
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
$ p. H2 Q0 Q G0 d! p& F! p1 L .boot_params = S3C2410_SDRAM_PA + 0x100,
- P( i8 ?0 w/ h
" Q$ e. q i; E6 x9 [" }# ] .init_irq = s3c24xx_init_irq,
" }5 ?1 ]3 x$ J) V .map_io = smdk2440_map_io,
/ D L3 r3 b2 ]+ U$ q; r .init_machine = smdk2440_machine_init,
! o, u6 Q4 X: D5 r K+ o; |# ] .timer = &s3c24xx_timer,
6 d& d1 |0 D( k! ?3 o
2 K, W7 g! {, E- y" L F9 |};& R) ^( f% A/ |" W! C4 F. U
- g+ O& G& j6 e8 X* i: V9 o
到此,__lookup_processor_type、__lookup_machine_type函数如果都匹配成功,则将继续执行- Q1 p* T) w* d, g% C
4 F- g. L9 q4 m0 h) M
__vet_atags、(处理u-boot传入的ATAGS)
* y' q. Y; B6 \, ~: @6 f# s9 O/ E' S4 D$ R- [
__create_page_tables创建一级页表,在arch/arm/kernel/head.S原文定义
: g1 L) B% Y5 t% j3 A! _ N$ k L* Y/ ~! Q5 ^9 f q3 b% a
__switch_data在arch/arm/kernel/head_common.S 定义
0 B/ Y a# K& Z5 t5 n! [' N
! f* P: }1 F" Q__switch_data:% D! ^2 b5 p- _3 N. ~$ Y
.long __mmap_switched
' Q' O* p5 z( I .long __data_loc @ r45 J! O# D& b |4 Z3 H: p6 X6 _
.long _data @ r5; D- Z7 ?7 G6 h" t( {0 `
.long __bss_start @ r6& u! K7 F% Y- F6 H. u! p
.long _end @ r7
- K6 h7 m5 q5 G4 m .long processor_id @ r4
. c6 ]- D) N* \5 A .long __machine_arch_type @ r57 X% c3 X& |$ w5 _
.long __atags_pointer @ r6
$ {- O$ |- `9 G- U" T .long cr_alignment @ r7, A/ Z6 w$ s5 T/ {- G
.long init_thread_union + THREAD_START_SP @ sp
. }/ u0 f* L! P9 R3 z
' j3 b/ @5 F2 N0 v$ ~- g2 \......8 B0 `% D# `$ n' a& i' {3 l
: P4 y) W' }' V& y8 Q& |__mmap_switched:
* u9 s# ^! L0 J2 b5 \ adr r3, __switch_data + 4
5 V4 A$ T( B& [% C: i) v$ T% U
( c2 I5 Z& M/ Z3 C: Z/ j' ~ ldmia r3!, {r4, r5, r6, r7} I& E/ W4 m7 L8 e6 `: A Y
cmp r4, r5 //复制数据段
% j# X7 ]! s5 e0 j' m2 [' n1: cmpne r5, r6$ o/ m1 n5 [) v/ Q' k
ldrne fp, [r4], #4
9 B! p* v) r- l strne fp, [r5], #4, j( |) z8 w+ {* Q. Z: h5 w
bne 1b5 u7 Y1 k( j7 |# V
4 l5 U& W! H) @. m4 d0 I W( O/ n
mov fp, #0 //清除BSS段3 N6 s- h# H" x6 \* T
1: cmp r6, r7
! d9 Q, y! [: l" N3 B4 H strcc fp, [r6],#4
9 g' N7 o5 f8 _8 q1 L; G N bcc 1b, U5 T+ a) O7 q; o- _1 v
7 B9 P7 v7 f" R' ^
ldmia r3, {r4, r5, r6, r7, sp}( d q" z1 J, ]0 p2 W
str r9, [r4] //保存CPU ID到 r9 寄存器0 | _3 S1 c; A$ i
str r1, [r5] //保存机器ID到 r1 寄存器& {' a7 X# v* \7 K' q% j) E
str r2, [r6] // 保存ATAGS指针到 r2 寄存器
# @- s$ E9 t0 t: o bic r4, r0, #CR_A @ Clear 'A' bit" t0 m( b" \# K t- B/ D, r( n
stmia r7, {r0, r4} @ Save control register values3 j* R& ? W' O! g# ]
b start_kernel //跳到第二阶段的C函数去执行,在init/main.c中定义4 ], T" K& {# u }* ^2 F; y1 @
ENDPROC(__mmap_switched), B" `7 h6 d9 h/ l+ g
! J ]1 a8 \$ k' R- l' h
0 y. }1 o+ [! g" k! X
. U0 Q1 ^, s, T1 a5 k1 e__enable_mmu 使能MMU3 ?: Q! v% ~$ O1 M. A
0 k; i/ I1 {" r
__enable_mmu:8 L3 c _; f5 r7 L! I2 ?" y& X
#ifdef CONFIG_ALIGNMENT_TRAP
0 y p7 |, u, A4 e& t orr r0, r0, #CR_A
/ t) y2 K5 \' F5 Q" I# M; {#else
# J. J7 G1 c/ Y* O bic r0, r0, #CR_A
( D. H- c& L) R+ P- v! a! s#endif( F9 ?3 x$ w4 ~5 z- D
#ifdef CONFIG_CPU_DCACHE_DISABLE$ ]8 p( k* a# B6 k
bic r0, r0, #CR_C
2 C3 B1 Y0 M7 |2 |( J+ Y- ~) {#endif
; r8 {: ~9 e) M$ x9 S. T/ b( T9 K: b: g6 \#ifdef CONFIG_CPU_BPREDICT_DISABLE
' J& g9 |6 P5 N- r' G bic r0, r0, #CR_Z
! W, B5 O/ X5 _$ E& P" [#endif9 k- [; r5 W3 y) K1 V" u$ Z
#ifdef CONFIG_CPU_ICACHE_DISABLE
( f9 I8 E9 s7 A bic r0, r0, #CR_I: N, H8 ]1 U1 Z3 u( S- X1 V: i- b* ]
#endif' I$ X9 L g0 P9 ^. }
mov r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \- X' K' m- \1 Q; Q$ J. Q9 I
domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \6 E; X% W: u7 L4 I" M5 g2 W
domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \3 g8 e3 H; C6 n! a k* Q* b5 s
domain_val(DOMAIN_IO, DOMAIN_CLIENT)) Q' M. |# A1 e4 W
mcr p15, 0, r5, c3, c0, 0 @ load domain access register- n7 N) j! O- h/ z
mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
, z8 @, ^% H" |: U/ O* N b __turn_mmu_on \, x) M) F5 q$ K% ^4 P
ENDPROC(__enable_mmu)3 O* ?$ H/ Z5 c4 C% r4 _5 J
) w* y+ y% L" \8 h8 [, B8 M
5 K& ?5 s, x8 E4 X) N4 e" {& I# e, ]4 ^
.align 58 f) W, u8 u6 R+ e) C+ G2 m
__turn_mmu_on:
4 w$ L; a _) h" m- K( w. ]; f mov r0, r0
1 D+ ~ S, p9 V7 I; j' z1 X mcr p15, 0, r0, c1, c0, 0 @ write control reg
! f7 ]2 H! v. Y( p. M mrc p15, 0, r3, c0, c0, 0 @ read id reg; i& r, S2 q3 I. z
mov r3, r3; H( R3 v! N8 e2 ]' C
mov r3, r3. c7 w) S) T4 r. e% }
mov pc, r13
" Z, l5 T+ L [$ q) C( AENDPROC(__turn_mmu_on)
$ ]+ Q- n# u1 ]2 X; `/ M9 B6 y( g2 L) V! q6 A2 k
$ e; g7 d, U# I
" b2 M3 @. Q ]+ }2 ^5 T: }
|
|