📄 xllp_suspendresumea.s
字号:
;******************************************************************************
;
; COPYRIGHT (C) 2002-2005 Intel Corporation.
;
; This software as well as the software described in it is furnished under
; license and may only be used or copied in accordance with the terms of the
; license. The information in this file is furnished for informational use
; only, is subject to change without notice, and should not be construed as
; a commitment by Intel Corporation. Intel Corporation assumes no
; responsibility or liability for any errors or inaccuracies that may appear
; in this document or any software that may be provided in association with
; this document.
;
; Except as permitted by such license, no part of this document may be
; reproduced, stored in a retrieval system, or transmitted in any form or by
; any means without the express written consent of Intel Corporation.
;
;******************************************************************************
; PURPOSE:
; Suspend/Resume functions linked into the OS kernel.
;
; NOTES:
;
; Conext:
; These functions assume that the MMU is enabled, the stack is valid, and CPU is in a priveledged mode.
; These functions are linked into the OS kernel. They are not linked into the boot loaders.
;
; Resume phases:
; These are a fabrication that have no direct basis in hardware, but help understanding of the resume process.
;
; Resume phase 1 puts the CPU and the platform in a known (default) working state.
; It is performed by the low level boot code.
;
; Phase 2 restores virtual addressing, the CPU core mode, and the stack for that mode.
; Phase 2 resume data therefore consists of data that is needed on resume to...
; 1. Restore the MMU.
; 2. Restore the CPU core to the mode it was in just before power off.
; 3. Restore the stack pointer for the restored CPU mode.
;
; Resume phase 3 (and beyond) restores other CPU and platform state.
;
; The routines in this file are used to save state prior to suspend and
; begin phase 3 of the resume (ie. restore current CPU mode registers).
; Phase 2 resume is performed in another module linked into the boot loader.
;
;**************************************************************************************************
INCLUDE xllp_ARM_macros.inc ; for RETURN macro
INCLUDE xllp_ResumePhase2_Data.inc ; definition of ResumePhase2 data area
INCLUDE xlli_Bulverde_defs.inc ; Bulverde specific include file
;
AREA |.text|, CODE, READONLY, ALIGN=5 ; Align =5 required for "ALIGN 32" to work
;
; Functions made public by this file:
;
EXPORT Xllp_SuspendAndResumeA
EXPORT Xllp_SaveMMU
EXPORT Xllp_SaveMSARMRegs
EXPORT Xllp_RestoreMSARMRegs
; External functions we need
IMPORT Xllp_SimpleChecksum
IMPORT OSD_CacheFlush
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Xllp_SaveMSARMRegs and Xllp_RestoreMSARMRegs
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Mode specific (MS) ARM registers are are saved and restored by the following functions.
; For all modes other than FIQ mode, 'mode specific' means SP, LR, and SPSR.
; R8-R12 are specific to FIQ mode but are common to all other modes.
; This is described in the ARM Architecture Reference Manual.
;
; Registers common to all modes are not saved and restored by these functions.
; It is left to the calling routine to save and restore the common registers.
;
; A 'pseudo-stack' is used to save the registers.
; The term 'pseudo-stack' is used because the customary stmdb and ldmia register saving instructions are used.
; However, since SP itself is mode specific, the current stack is not used.
; Previous counterparts of this code used the current stack for each mode as the save area.
; The approach used here means that we don't care what modes actually have their SP setup.
; All that matters is that the current mode stack is valid.
; This approach is likely to work with different operating systems regardless of what modes they use.
;
; R0 = pseudo-stack pointer (updated on return)
; R1 = mode
Xllp_SaveMSARMRegs FUNCTION
stmdb sp!, {r1-r7,lr} ; Save registers we may use (except r0)
mov r4, r0 ; setup pseudo stack pointer
and r1, r1, #(xlli_CPSR_Mode_MASK) ; get mode only
mrs r0, cpsr
mov r2, r0 ; save cpsr to restore before returning
bic r0, r0, #(xlli_CPSR_Mode_MASK)
orr r0, r0, #(xlli_CPSR_I_Bit:OR:xlli_CPSR_F_Bit) ; no interrupts
orr r0, r0, r1 ; Set requested mode
msr cpsr, r0
; SYS mode doesn't have an SPSR
cmp r1, #xlli_CPSR_Mode_SYS
mrsne r0, spsr
cmp r1, #xlli_CPSR_Mode_FIQ
stmeqdb r4!, {r0,r8-r12,sp,lr} ; Save SPSR, r8-r12, SP, LR, for FIQ mode
stmnedb r4!, {r0,sp,lr} ; Save SPSR, SP, LR, for other requested mode
msr cpsr, r2 ; restore cpsr - return to previous mode
mov r0, r4 ; return final address
ldmia sp!, {r1-r7,lr} ; restore registers we may have used
RETURN
ENDFUNC
; R0 = pseudo-stack pointer (updated on return)
; R1 = mode
Xllp_RestoreMSARMRegs FUNCTION
stmdb sp!, {r1-r7,lr} ; Save registers we may use (except r0)
mov r4, r0 ; setup pseudo stack pointer
and r1, r1, #(xlli_CPSR_Mode_MASK) ; mode bits only
mrs r0, cpsr
mov r2, r0 ; save cpsr to restore before returning
bic r0, r0, #(xlli_CPSR_Mode_MASK)
orr r0, r0, #(xlli_CPSR_I_Bit:OR:xlli_CPSR_F_Bit) ; no interrupts
orr r0, r0, r1 ; Set requested mode
msr cpsr, r0
cmp r1, #xlli_CPSR_Mode_FIQ
ldmeqia r4!, {r0,r8-r12,sp,lr} ; Restore SPSR, r8-r12, SP, LR, for FIQ mode
ldmneia r4!, {r0,sp,lr} ; Restore SPSR, SP, LR, for other requested mode
; SYS mode doesn't have an SPSR
cmp r1, #xlli_CPSR_Mode_SYS
msrne spsr, r0
msr cpsr, r2 ; return to previous mode
mov r0, r4 ; return final address
ldmia sp!, {r1-r7,lr} ; restore registers we may have used
RETURN
ENDFUNC
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; This function saves the various MMU registers.
; Restore of the MMU is done in Xllp_ResumePhase2A (which is linked into the boot loaders).
; r0 = address of MMU save area
Xllp_SaveMMU FUNCTION
stmdb sp!, {r1-r7,lr} ; Save regs we may use
; Save argument to free up r0
mov r5, r0
; Cp15_ACR_MMU
mrc p15, 0, r0, c1, c0, 0 ; load r0 with MMU Control
;ldr r1, =XLLP_CP15_ACR_MMU_VLD_MSK ; mask off the undefined bits
;and r0, r0, r1
str r0, [r5, #RESUMEPHASE2_CP15_ACR_MMU_OFFSET] ; store MMU Control data
; Cp15_AUXCR_MMU; // cp15 Reg1:1: assume restored elsewhere.
mrc p15, 0, r0, c1, c1, 0 ; load r0 with MMU Aux Control
;ldr r1, =XLLP_CP15_AUXCR_MMU_VLD_MSK ; mask off the undefined bits
;and r0, r0, r1
str r0, [r5, #RESUMEPHASE2_CP15_AUXCR_MMU_OFFSET] ; store MMU Aux Control data
; Cp15_TTBR_MMU; // cp15 Reg2:0
mrc p15, 0, r0, c2, c0, 0 ; load r0 with TTB address.
;ldr r1, =XLLP_CP15_TTBR_MMU_VLD_MSK ; mask off the undefined bits
;and r0, r0, r1
str r0, [r5, #RESUMEPHASE2_CP15_TTBR_MMU_OFFSET] ; store TTB address
; Cp15_DACR_MMU; // cp15 Reg3:0, all bits valid
mrc p15, 0, r0, c3, c0, 0 ; load r0 with domain access control.
str r0, [r5, #RESUMEPHASE2_CP15_DACR_MMU_OFFSET] ; store domain access control
; Cp15_PID_MMU; // cp15 Reg13; Assume set by OS if used.
mrc p15, 0, r0, c13, c0, 0 ; load r0 with PID.
;ldr r1, =XLLP_CP15_PID_MMU_VLD_MSK ; mask off the undefined bits
;and r0, r0, r1
str r0, [r5, #RESUMEPHASE2_CP15_PID_MMU_OFFSET] ; store PID
ldmia sp!, {r1-r7,lr} ; Restore regs we may have used
RETURN
ENDFUNC
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; This is the function that actually powers the system off.
; r0 = address of suspend save area
Xllp_SuspendAndResumeA FUNCTION
; Save current mode registers on the current mode stack.
stmdb sp!, {r0-r12,lr}
; Move parameter to free up r0
mov r5, r0
; Save the SP
; This is the value that should be restored on resume before jumping to XllpResume below
str sp, [r5, #RESUMEPHASE2_SP_OFFSET]
; Save CPSR
mrs r3, cpsr
str r3, [r5, #RESUMEPHASE2_CPSR_OFFSET]
; Save Coprocessor Access Register
mrc p15, 0, r0, c15, c1, 0
str r0, [r5, #RESUMEPHASE2_CPAR_OFFSET]
; Save the resume address
add r0, pc, #XllpResumePhase3 - (. + 8)
str r0, [r5, #RESUMEPHASE2_RESUMEPHASE3_PC_OFFSET]
; Save the MMU
mov r0, r5
bl Xllp_SaveMMU
; Store word and checksum (word count is included in checksum)
mov r1, #RESUMEPHASE2_DATA_WORDS
str r1, [r5, #RESUMEPHASE2_WORDCOUNT_OFFSET]
add r0, r5, #RESUMEPHASE2_WORDCOUNT_OFFSET
bl Xllp_SimpleChecksum
str r0, [r5, #RESUMEPHASE2_CHECKSUM_OFFSET]
; At this point all state has been saved.
; The cache and write buffers need to be flushed before power down.
; Cache flushing is OS dependent, so OSD_CacheFlush needs to be provided for each OS environment.
; It must simply ensure that all cached and buffered data has been written back to memory.
stmdb sp!, {lr}
bl OSD_CacheFlush
ldmia sp!, {lr}
nop
nop
nop
nop
;================================================================
XllpEnterSleepMode
;================================================================
ldr r3, =(xlli_PWRMODE_SLEEP)
b %F1 ; Purely precautionary, in case we needed to clear pipeline
ALIGN 32
1
mcr p14, 0, r3, c7, c0, 0 ; Enter sleep
nop
nop
nop
nop
nop
nop
nop
nop
;================================================================
XllpResumePhase3
;================================================================
; This is where we should end up here when we resume.
; The MMU, CPU mode, and stack should have been restored at this point so
; adrresses should be virtual and the stack should look as it did when we saved the SP above
; All that remains to be done here is to restore the current mode registers.
ldmia sp!, {r0-r12,lr}
RETURN
ENDFUNC
;**************************************************************************************************
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -