📄 mmu.s
字号:
;/***************************************************************************
; Copyright ARM Limited 1998 - 2000. All rights reserved.
;****************************************************************************
;
; Memory Management and Cache Initialisation Routines for the ARM. All
; access to the Co-processor must be in supervisor mode and these routines
; handle all these issues internally.
;
; $Id: mmu.s,v 1.1.1.1 2006/04/18 07:34:53 ivan Exp $
;
;****************************************************************************/
;INCLUDE bits.s
INCLUDE sizes.s
;INCLUDE platform.s
INCLUDE mmumacro.s
GET retmacro.s ; Thumb/ARM interworking
INCLUDE t_mmu.s
IMPORT Level1tab
IMPORT Level2tab_ROM
IMPORT MPUMaptab
EXPORT uHALr_InitMMU ; Setup page tables, MMU etc.
EXPORT uHALr_ResetMMU ; Reset Memory to initial state, no MMU
EXPORT uHALir_MMUSupported
EXPORT uHALir_MPUSupported
EXPORT uHALir_CacheSupported
EXPORT uHALir_CheckUnifiedCache
EXPORT uHALir_BranchPredSupported
EXPORT uHALir_WriteBranchPredictionMode
EXPORT uHALir_WriteCacheMode
EXPORT uHALir_ReadCacheMode
EXPORT uHALir_DisableICache
EXPORT uHALir_DisableDCache
EXPORT uHALir_DisableWriteBuffer
EXPORT uHALir_CleanCache
EXPORT uHALir_CleanDCache
EXPORT uHALir_CleanDCacheEntry
; Enter Supervisor mode & disable IRQ.
;IMPORT uHALir_EnterLockedSvcMode
;IMPORT uHALir_ExitSvcMode ; Exit Supervisor mode.
IMPORT uHAL_AddressTable
IMPORT uHAL_MappingTable
KEEP
AREA uHAL_MMU, CODE, READONLY
;-------------------------------------------------------------------
; Routine to initialise the page tables & MMU to memmap layout.
;
; See SETUPMMU macro for description
; WARNING: The MMU must be disabled when this routine is called,
; but routine checks MMU, will do nothing if enabled.
;
; void uHALir_InitMMU(void) - Init MMU to flat-memory map
uHALr_InitMMU
STMFD sp!,{r0-r2, r4-r9, lr} ; Save registers
MOV r9, r0 ; Save the mode
; Switch into SVC returns CPSR in r0
;BL uHALir_EnterLockedSvcMode
; If the MMU is already on, do nothing..
TEST_MMU r1
BEQ %F27
MOV r5, #0
SETUPMMU r4, r5, r6, r7, r8, r1, r2
; Enable MMU, and any caching required.
;
; This code must maintain the state of all other bits in the
; control register that apart from cache, write buffer & MMU
; enable bits
MOV r1, #(EnableMMU :OR: EnableDcache :OR: EnableWB)
ORR r1, r1, #EnableIcache ; Create mask of the bits we can touch
AND r9, r9, r1 ; Clear all other bits from the mask supplied
RDMMU_STATE r2 ; Read current state of control register
BIC r2, r2, r1 ; Clear the bits that we may change
ORR r9, r9, r2 ; Merge in the supplied mask
WRMMU_STATE r9 ; Write this to the control register
; Make sure the pipeline is clear of any cached entries
NOP
NOP
NOP
27
; Switch back to the mode we started in (restores interrupts, if any)
;BL uHALir_ExitSvcMode ; Switch out of SVC mode, r0 -> cpsr
POP_RETURN_EXTEND r0-r2, r4-r9
;-------------------------------------------------------------------
; void uHALr_ResetMMU(void) - Function to reset the MMU.
;
; Flushes the Icache, cleans & flushes the Dcache, disables IC, DC, WB and
; MMU returning the memory system to its powerup state (flat map allows this)
;
; Never call ResetMMU without having called InitMMU first.
;
; When running semihosted, care should be exercised to leave the debugger
; in a state similar to that when starting our application.
uHALr_ResetMMU
STMFD sp!, {r0, r4-r6, lr} ; Save registers
IF :DEF: DUMMY
; Has this CPU an MPU?
CHECK_FOR_MPU r0
BNE %F40
; Make sure this CPU has an MMU
CHECK_FOR_MMU r0
BEQ %F41
; If the current memory map is not 1-1 at 0, do NOT reset MMU
MOV r0, #0
TEST_121MAP r0, r4, r5
BNE %F41
ENDIF
40
; Switch into SVC returns SPSR in r0
;BL uHALir_EnterLockedSvcMode
; Do we need to clean the Dcache?
;TEST_MMU r4
;BLEQ uHALir_CleanDCache
WRMMU_FlushTB r4 ; Flush ITB's and DTB's
WRCACHE_FlushIDC r4 ; Flush the ICache and DCache
; Reset MMU control register
RDMMU_STATE r4
CLEAR_IDC r4
CLEAR_MMU r4
WRMMU_STATE r4
; Make sure the pipeline is clear of any cached entries
NOP
NOP
NOP
; Switch back to the mode we started in (restores interrupts, if any)
;BL uHALir_ExitSvcMode ; Switch out of SVC mode, r0 -> spsr
41
POP_RETURN_EXTEND r0, r4-r6
;-------------------------------------------------------------------
; Shell routines around MMU/cache query macros
uHALir_MMUSupported
CHECK_FOR_MMU r0
RETURN lr
uHALir_MPUSupported
CHECK_FOR_MPU r0
RETURN lr
uHALir_CacheSupported
CHECK_CACHE r0
RETURN lr
uHALir_CheckUnifiedCache
CHECK_UNIFIED r0
RETURN lr
uHALir_BranchPredSupported
CHECK_FOR_BRANCH_PRED r0
RETURN lr
;-------------------------------------------------------------------
; unsigned int uHALir_ReadCacheMode(void)
;
; Routine to read the mmu state from the Co-processor
uHALir_ReadCacheMode
STMFD sp!, {r1, lr}
;BL uHALir_EnterLockedSvcMode
RDMMU_STATE r1
;BL uHALir_ExitSvcMode ; Switch out of SVC mode, r0 -> spsr
;
; We need to clear all bits apart from cache, write buffer & MMU
; enable bits
;
MOV r0, #(EnableMMU :OR: EnableDcache :OR: EnableWB)
ORR r0, r0, #EnableIcache
AND r0, r0, r1
POP_RETURN r1
;-------------------------------------------------------------------
; void uHALir_WriteBranchPredictionMode(unsigned int)
;
; Sets the branch prediction mode to the value passed in r0
uHALir_WriteBranchPredictionMode
STMFD sp!, {r0, r4-r6, lr} ; Save registers
MOV r5, r0 ; save the new mode
CHECK_FOR_BRANCH_PRED r0
BEQ %F42
; Switch into SVC returns SPSR in r0
;BL uHALir_EnterLockedSvcMode
AND r5, r5, #BranchPrediction ; Clear all other bits from mask
RDMMU_STATE r4 ; Read current state of control register
BIC r4, r4, #BranchPrediction ; Clear bits that we may change
ORR r5, r5, r4 ; Merge in the supplied mask
WRMMU_STATE r5 ; Write this to the control register
; Switch back to the mode we started in (restores interrupts, if any)
;BL uHALir_ExitSvcMode ; Switch out of SVC mode, r0 -> spsr
42
POP_RETURN_EXTEND r0, r4-r6
;-------------------------------------------------------------------
; void uHALir_WriteCacheMode(unsigned int)
;
; Routine to write the mmu state to the Co-processor
uHALir_WriteCacheMode
STMFD sp!, {r0, r4-r6, lr} ; Save registers
MOV r6, r0 ; save the new mode
CHECK_CACHE r0
BEQ %F43
; Switch into SVC returns SPSR in r0
;BL uHALir_EnterLockedSvcMode
; This code must maintain the state of all other bits in the
; control register that apart from cache, write buffer & MMU
; enable bits
MOV r5, #(EnableMMU :OR: EnableDcache :OR: EnableWB)
ORR r5, r5, #EnableIcache ; Create mask of the bits we can touch
AND r6, r6, r5 ; Clear all other bits from the mask
RDMMU_STATE r4 ; Read current state of control register
BIC r4, r4, r5 ; Clear the bits that we may change
ORR r6, r6, r4 ; Merge in the supplied mask
ORR r6, r6, #0xC0000000 ; Async mode issue
WRMMU_STATE r6 ; Write this to the control register
; Make sure the pipeline is clear of any cached entries
NOP
NOP
NOP
; Switch back to the mode we started in (restores interrupts, if any)
;BL uHALir_ExitSvcMode ; Switch out of SVC mode, r0 -> spsr
43
POP_RETURN_EXTEND r0, r4-r6
;-------------------------------------------------------------------
; void uHALir_DisableICache(void)
;
; Routine to flush and disable the I Cache
uHALir_DisableICache
STMFD sp!,{r0, r4-r5, lr} ; Save registers
CHECK_CACHE r0
BEQ %F44
; Switch into SVC returns SPSR in r0
;BL uHALir_EnterLockedSvcMode
MOV r4, #0
WRCACHE_FlushIC r4 ; Flush ICache
RDMMU_STATE r4
CLEAR_ICACHE r4
WRMMU_STATE r4 ; Update current state
; Make sure the pipeline is clear of any cached entries
NOP
NOP
NOP
; Switch back to the mode we started in (restores interrupts, if any)
; uHALir_ExitSvcMode(spsr);
;BL uHALir_ExitSvcMode ; Switch out of SVC mode, r0 -> spsr
44
POP_RETURN_EXTEND r0, r4-r5
;-------------------------------------------------------------------
; void uHALir_DisableDCache(void)
;
; Routine to flush and disable the D Cache
uHALir_DisableDCache
STMFD sp!,{r0, r4-r5, lr} ; Save registers
CHECK_CACHE r0
BEQ %F45
; Switch into SVC returns SPSR in r0
;BL uHALir_EnterLockedSvcMode
; Clean the Dcache before flush
BL uHALir_CleanDCache
MOV r4, #0
WRCACHE_FlushDC r4 ; Flush DCache
RDMMU_STATE r4
CLEAR_DCACHE r4
WRMMU_STATE r4 ; Update current state
; Make sure the pipeline is clear of any cached entries
NOP
NOP
NOP
; Switch back to the mode we started in (restores interrupts, if any)
; uHALir_ExitSvcMode(spsr);
;BL uHALir_ExitSvcMode ; Switch out of SVC mode, r0 -> spsr
45
POP_RETURN_EXTEND r0, r4-r5
;-------------------------------------------------------------------
; void uHALir_DisableWriteBuffer(void)
;
; Routine to disable the Write Buffer
uHALir_DisableWriteBuffer
STMFD sp!,{r0, r4-r5, lr} ; Save registers
CHECK_CACHE r0
BEQ %F46
; Switch into SVC returns SPSR in r0
;BL uHALir_EnterLockedSvcMode
; Clean the Dcache before flush
BL uHALir_CleanDCache
MOV r4, #0
WRCACHE_FlushDC r4 ; Flush DCache
RDMMU_STATE r4
CLEAR_DCACHE r4
CLEAR_WBUFFER r4
WRMMU_STATE r4 ; Update current state
; Make sure the pipeline is clear of any cached entries
NOP
NOP
NOP
; Switch back to the mode we started in (restores interrupts, if any)
; uHALir_ExitSvcMode(spsr);
;BL uHALir_ExitSvcMode ; Switch out of SVC mode, r0 -> spsr
46
POP_RETURN_EXTEND r0, r4-r5
;-------------------------------------------------------------------
;void uHALir_CleanDCacheEntry (void *)
;
; Routine to clean (at least) one Data Cache entry
uHALir_CleanDCacheEntry
STMFD sp!,{r0-r1, lr} ; Save registers
WRCACHE_CleanDCentry r0
POP_RETURN r0-r1
;-------------------------------------------------------------------
; void uHALir_CleanDCache(void)
;
; Routine to clean D cache
uHALir_CleanDCache
STMFD sp!,{r0-r5, lr} ; Save registers
WRCACHE_CleanDCache r0, r1, r2, r3, r4, r5
POP_RETURN r0-r5
;-------------------------------------------------------------------
; void uHALir_CleanCache(void)
;
; Routine to clean Instruction and Data caches
uHALir_CleanCache
STMFD sp!,{r0-r5, lr} ; Save registers
WRCACHE_CleanDCache r0, r1, r2, r3, r4, r5
MOV r4, #0
WRCACHE_FlushDC r4 ; Flush DCache
WRCACHE_FlushIC r4 ; Flush ICache
POP_RETURN r0-r5
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -