- SMP 시스템에서 캐시 coherent가 disable되어 있으면 enable시킨다.
- d-cache를 모두 flush(invalidate + clean)한다.
- 현재 프로세스와 관련 있는 ERRATA(프로세스 에러 패치)를 적용한다.
- i-cache를 모두 invalidate한다.
- TLB cache를 모두 invalidate한다.
- TTBCR을 0으로 설정한다. (페이지테이블을 나누어 사용하지 않는다)
- TTBR1에 TTB_RGN_WBWA | TTB_S를 설정한다.
- PRRR에 =PRRR 값을 설정한다.
- NMRR에 =NMRR 값을 설정한다.

__v7_ca7mp_setup:
/*
* __v7_setup
*
* Initialise TLB, Caches, and MMU state ready to switch the MMU
* on. Return in r0 the new CP15 C1 control register setting.
*
* This should be able to cover all ARMv7 cores.
*
* It is assumed that:
* - cache type register is implemented
*/
__v7_ca7mp_setup:
mov r10, #0
#ifdef CONFIG_SMP
ALT_SMP(mrc p15, 0, r0, c1, c0, 1)
ALT_UP(mov r0, #(1 << 6)) @ fake it for UP
tst r0, #(1 << 6) @ SMP/nAMP mode enabled?
orreq r0, r0, #(1 << 6) @ Enable SMP/nAMP mode
orreq r0, r0, r10 @ Enable CPU-specific SMP bits
mcreq p15, 0, r0, c1, c0, 1
#endif
b __v7_setup
- ACTLR.SMP를 읽어 0으로 되어 있으면 1로 다시 바꾼다.
- Enables coherent requests to the processor: 0=disable, 1=enable
__v7_setup:
__v7_setup:
adr r12, __v7_setup_stack @ the local stack
stmia r12, {r0-r5, r7, r9, r11, lr}
bl v7_flush_dcache_louis
ldmia r12, {r0-r5, r7, r9, r11, lr}
- adr r12, __v7_setup_stack
- r12=임시 스택용도로 사용할 공간 주소
- stmia r12, {r0-r5, r7, r9, r11, lr}
- 레지스터들을 잠시 백업한다.
- bl v7_flush_dcache_louis
- LoUIS 레벨까지의 d-cache를 flush한다.
- 백업해 두었던 레지스터들을 복원하다.
mrc p15, 0, r0, c0, c0, 0 @ read main ID register
and r10, r0, #0xff000000 @ ARM?
teq r10, #0x41000000
bne 3f
and r5, r0, #0x00f00000 @ variant
and r6, r0, #0x0000000f @ revision
orr r6, r6, r5, lsr #20-4 @ combine variant and revision
ubfx r0, r0, #4, #12 @ primary part number
- mrc p15, 0, r0, c0, c0, 0
- ERRATA 루틴들을 적용하기 위해 확인목적으로 read MIDR 한다.
- MIDR(Main ID Register)
- Implementer[31:24]: 0x41=ARM
- Variant[23:20]: Major Revision Number
- Architecture[19:16]: 0xf=ARMv7
- Primary_Part_Number[15:4]: 0xc07=Cortex A7 MPCore
- Revision[3:0]: Minor Revision Number
- bne 3f
- ARM이 아니면 3f로 jump
- and r5, r0, #0x00f00000
- r5=MIDR.variant 부분만 추출
- and r6, r0, #0x0000000f
- r6=MIDR.revision 부분만 추출
- orr r6, r6, r5, lsr #20-4
- r5를 우측으로 16비트 쉬프트하여 r6와 합친다.
- r6[7:4]=variant, r6[3:0]=revision
- ubfx r0, r0, #4, #12
- r0=r0를 우측으로 4비트 쉬프트한 후 lsb 12비트만을 가져온다.
- 결국 MIDR.Primary_Part_Number 부분만 추출한다.
- rpi2: r0=0xc07
/* Cortex-A8 Errata */
ldr r10, =0x00000c08 @ Cortex-A8 primary part number
teq r0, r10
bne 2f
- 다음은 Cortex-A8용 ERRATA이므로 Cortex-A8이 아니면 2f로 점프
#if defined(CONFIG_ARM_ERRATA_430973) && !defined(CONFIG_ARCH_MULTIPLATFORM)
teq r5, #0x00100000 @ only present in r1p*
mrceq p15, 0, r10, c1, c0, 1 @ read aux control register
orreq r10, r10, #(1 << 6) @ set IBE to 1
mcreq p15, 0, r10, c1, c0, 1 @ write aux control register
#endif
#ifdef CONFIG_ARM_ERRATA_458693
teq r6, #0x20 @ only present in r2p0
mrceq p15, 0, r10, c1, c0, 1 @ read aux control register
orreq r10, r10, #(1 << 5) @ set L1NEON to 1
orreq r10, r10, #(1 << 9) @ set PLDNOP to 1
mcreq p15, 0, r10, c1, c0, 1 @ write aux control register
#endif
#ifdef CONFIG_ARM_ERRATA_460075
teq r6, #0x20 @ only present in r2p0
mrceq p15, 1, r10, c9, c0, 2 @ read L2 cache aux ctrl register
tsteq r10, #1 << 22
orreq r10, r10, #(1 << 22) @ set the Write Allocate disable bit
mcreq p15, 1, r10, c9, c0, 2 @ write the L2 cache aux ctrl register
#endif
b 3f
/* Cortex-A9 Errata */
2: ldr r10, =0x00000c09 @ Cortex-A9 primary part number
teq r0, r10
bne 3f
- 다음은 Cortex-A9용 ERRATA이므로 Cortex-A9이 아니면 3f로 점프
#ifdef CONFIG_ARM_ERRATA_742230
cmp r6, #0x22 @ only present up to r2p2
mrcle p15, 0, r10, c15, c0, 1 @ read diagnostic register
orrle r10, r10, #1 << 4 @ set bit #4
mcrle p15, 0, r10, c15, c0, 1 @ write diagnostic register
#endif
#ifdef CONFIG_ARM_ERRATA_742231
teq r6, #0x20 @ present in r2p0
teqne r6, #0x21 @ present in r2p1
teqne r6, #0x22 @ present in r2p2
mrceq p15, 0, r10, c15, c0, 1 @ read diagnostic register
orreq r10, r10, #1 << 12 @ set bit #12
orreq r10, r10, #1 << 22 @ set bit #22
mcreq p15, 0, r10, c15, c0, 1 @ write diagnostic register
#endif
#ifdef CONFIG_ARM_ERRATA_743622
teq r5, #0x00200000 @ only present in r2p*
mrceq p15, 0, r10, c15, c0, 1 @ read diagnostic register
orreq r10, r10, #1 << 6 @ set bit #6
mcreq p15, 0, r10, c15, c0, 1 @ write diagnostic register
#endif
#if defined(CONFIG_ARM_ERRATA_751472) && defined(CONFIG_SMP)
ALT_SMP(cmp r6, #0x30) @ present prior to r3p0
ALT_UP_B(1f)
mrclt p15, 0, r10, c15, c0, 1 @ read diagnostic register
orrlt r10, r10, #1 << 11 @ set bit #11
mcrlt p15, 0, r10, c15, c0, 1 @ write diagnostic register
1:
#endif
/* Cortex-A15 Errata */
3: ldr r10, =0x00000c0f @ Cortex-A15 primary part number
teq r0, r10
bne 4f
- 다음은 Cortex-A15용 ERRATA이므로 Cortex-A15가 아니면 4f로 점프
#ifdef CONFIG_ARM_ERRATA_773022
cmp r6, #0x4 @ only present up to r0p4
mrcle p15, 0, r10, c1, c0, 1 @ read aux control register
orrle r10, r10, #1 << 1 @ disable loop buffer
mcrle p15, 0, r10, c1, c0, 1 @ write aux control register
#endif
4: mov r10, #0
mcr p15, 0, r10, c7, c5, 0 @ I+BTB cache invalidate
#ifdef CONFIG_MMU
mcr p15, 0, r10, c8, c7, 0 @ invalidate I + D TLBs
v7_ttb_setup r10, r4, r8, r5 @ TTBCR, TTBRx setup
ldr r5, =PRRR @ PRRR
ldr r6, =NMRR @ NMRR
mcr p15, 0, r5, c10, c2, 0 @ write PRRR
mcr p15, 0, r6, c10, c2, 1 @ write NMRR
#endif
dsb @ Complete invalidations
- mcr p15, 0, r10, c7, c5, 0
- invalidate all i-cache to PoU (ICIALLU)
- mcr p15, 0, r10, c8, c7, 0
- invalidate TLB cache all (TLBIALL)
- v7_ttb_setup r10, r4, r8, r5
- arch/arm/mm/proc-v7-2level.S
- .macro v7_ttb_setup, zero, ttbr0, ttbr1, tmp
- zero: TTBCR에서 사용할 0값이 담겨 있어야 한다.
- ttbr0 |= TTB_RGN_WBWA|TTB_S -> 기록하지 않음.
- ttbr1 |= TTB_RGN_WBWA|TTB_S -> 실제기록까지함.
- tmp: 사용하지 않는다.
- r10: 0
- r4, r8: 페이지테이블 물리주소 |= TTB_RGN_WBWA|TTB_S
- mcr p15, 0, r5, c10, c2, 0
- r5: 0xff0a_81a8 (PRRR)
- mcr p15, 0, r6, c10, c2, 1
- r6: 0x40e0_40e0(NMRR)
#ifndef CONFIG_ARM_THUMBEE
mrc p15, 0, r0, c0, c1, 0 @ read ID_PFR0 for ThumbEE
and r0, r0, #(0xf << 12) @ ThumbEE enabled field
teq r0, #(1 << 12) @ check if ThumbEE is present
bne 1f
mov r5, #0
mcr p14, 6, r5, c1, c0, 0 @ Initialize TEEHBR to 0
mrc p14, 6, r0, c0, c0, 0 @ load TEECR
orr r0, r0, #1 @ set the 1st bit in order to
mcr p14, 6, r0, c0, c0, 0 @ stop userspace TEEHBR access
1:
#endif
- mrc p15, 0, r0, c0, c1, 0
- read ID_PFR0.ThumbEE[15..12]: 12번비트가 1이면 ThumbEE가 지원됨.
- teq r0, #(1 << 12)
- ThumbEE 비트가 1인 경우 z flag가 1이 된다. (xor)
- bne 1f
- 0이 아니면(ThumbEE가 없으면) jump
adr r5, v7_crval
ldmia r5, {r5, r6}
ARM_BE8(orr r6, r6, #1 << 25) @ big-endian page tables
#ifdef CONFIG_SWP_EMULATE
orr r5, r5, #(1 << 10) @ set SW bit in "clear"
bic r6, r6, #(1 << 10) @ clear it in "mmuset"
#endif
mrc p15, 0, r0, c1, c0, 0 @ read control register
bic r0, r0, r5 @ clear bits them
orr r0, r0, r6 @ set them
THUMB( orr r0, r0, #1 << 30 ) @ Thumb exceptions
ret lr @ return to head.S:__ret
.space 256
ENDPROC(__v7_setup)
- adr r5, v7_crval
- v7_crval는 arch/arm/mm/proc-v7-2level.S에 있음
- ldmia r5, {r5, r6}
- r5=0x2120c302 (for bit clear)
- r6=0x10c03c7d (for orr)
- mrc p15, 0, r0, c1, c0, 0
- SCTLR을 r0에 읽어 들인다.
- bic r0, r0, r5
- r5로 bit clear
- orr r0, r0, r6
- r6를 더한다
- ret lr
- lr=__enable_mmu: 의 물리 주소가 담겨 있음.
__v7_setup_stack:
.align 2
__v7_setup_stack:
.space 4 * 11 @ 11 registers
v7_ttb_setup 매크로
/*
* Macro for setting up the TTBRx and TTBCR registers.
* - \ttb0 and \ttb1 updated with the corresponding flags.
*/
.macro v7_ttb_setup, zero, ttbr0, ttbr1, tmp
mcr p15, 0, \zero, c2, c0, 2 @ TTB control register
ALT_SMP(orr \ttbr0, \ttbr0, #TTB_FLAGS_SMP)
ALT_UP(orr \ttbr0, \ttbr0, #TTB_FLAGS_UP)
ALT_SMP(orr \ttbr1, \ttbr1, #TTB_FLAGS_SMP)
ALT_UP(orr \ttbr1, \ttbr1, #TTB_FLAGS_UP)
mcr p15, 0, \ttbr1, c2, c0, 1 @ load TTB1
.endm
- mcr p15, 0, \zero, c2, c0, 2
- TTBCR에 zero(0)를 기록한다.
- ALT_SMP:
- ttbr0 |= (TTB_RGN_WBWA|TTB_S)
- ttbr1 |= (TTB_RGN_WBWA|TTB_S)
- mcr p15, 0, \ttbr1, c2, c0, 1
- TTBR1에 ttbr1을 기록한다.
- global 커널 페이지 테이블용으로 백업해두고 커널에 진입할 때 마다 ttbr0에 복사하여 사용
v7_crval:
arch/arm/mm/proc-v7-2level.S
/* AT
* TFR EV X F I D LR S
* .EEE ..EE PUI. .T.T 4RVI ZWRS BLDP WCAM
* rxxx rrxx xxx0 0101 xxxx xxxx x111 xxxx < forced
* 01 0 110 0011 1100 .111 1101 < we want
*/
.align 2
.type v7_crval, #object
v7_crval:
crval clear=0x2120c302, mmuset=0x10c03c7d, ucset=0x00c01c7c
- clear
- AFE, VE, FI, Bit[15], RR, Bit[9], Bit[8], A
- mmuset
- TRE, Bit[23], U, V, I, Z, SW, Bit[6], CP15BEN, Bit[4], Bit[3], C, M
- ucset
- Bit[23], U, I, Z, SW, Bit[6], CP15BEN, Bit[4], Bit[3], C
- SCTLR
- Bit[31]: 0
- TE[30]: Thumb Exception enable. 0=ARM state, 1=Thumb state
- AFE[29]: Access Flag Enable. 0=full range, 1=simplified model
- TRE[28]: TEX remap enable.
- NMFI[27]: Non-maskable FIQ support. 0=SW can mask, 1=SW can not mask
- Bit[26]: 0
- EE[25]: Exception Endianness. 0=Little-endian, 1=Big-endian
- VE[24]: Interrupt Vectors Enable: 0=use FIQ and IRQ vectors. 1=impl.
- Bit[23]: 1
- U[22]: Alignment support on page (ARMv7에서 1)
- FI[21]: Fast Interrupts configuration enable. 0=All performance features enabled, 1=low interrupt latency. (some performance feature is disabled)
- UWXN[20]: Unprivileged Write permission implies PL1 XN (for VE)
- WXN[19]: Write permission implies XN (for VE)
- Bit[20:19]: 0
- Bit[18]: 1
- HA[17]: Hardware Access flag enable.
- Bit[16]: 1
- Bit[15]: 0
- RR[14]: Round Robin select. 0=normal(random), 1=Predictable strategy. (RR)
- V[13]: Vectors bit. 0=0x0000_0000, 1=0xFFFF_0000
- I[12]: Instruction Cache enable.
- Z[11]: Branch Prediction enable.
- SW[10]: SWP and SWPB enable
- Bit[9:8]: 0
- B[7]: Endian support on page (ARMv7에서 0)
- Bit[6]: 1
- CP15BEN[5]: CP15 barrier enable
- Bit[4:3]: 1
- C[2]: Cache enable
- A[1]: Alignment check enable
- M[0]: MMU enable
crval 매크로
.macro crval, clear, mmuset, ucset
#ifdef CONFIG_MMU
.word \clear
.word \mmuset
#else
.word \clear
.word \ucset
#endif
.endm
















