mirror of
https://github.com/CTCaer/hekate
synced 2024-09-07 08:39:00 +00:00
![CTCaer](/assets/img/avatar_default.png)
This adds support for exception handling. It should provide simple and fast reporting of crucial info and full restoration without powering off.
234 lines
6.9 KiB
ArmAsm
234 lines
6.9 KiB
ArmAsm
/*
|
||
* Copyright (c) 2019 CTCaer
|
||
*
|
||
* This program is free software; you can redistribute it and/or modify it
|
||
* under the terms and conditions of the GNU General Public License,
|
||
* version 2, as published by the Free Software Foundation.
|
||
*
|
||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||
* more details.
|
||
*
|
||
* You should have received a copy of the GNU General Public License
|
||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
*/
|
||
|
||
/*
|
||
* Armv7tdmi Status register.
|
||
*
|
||
* bit0: Mode 0.
|
||
* bit1: Mode 1.
|
||
* bit2: Mode 2.
|
||
* bit3: Mode 3.
|
||
* bit4: Mode 4.
|
||
* bit5: Thumb state.
|
||
* bit6: FIQ disable.
|
||
* bit7: IRQ disable.
|
||
* bit8-27: Reserved.
|
||
* bit28: Overflow condition.
|
||
* bit29: Carry/Borrow/Extend condition.
|
||
* bit30: Zero condition.
|
||
* bit31: Negative/Less than condition.
|
||
*
|
||
* M[4:0] | Mode | Visible Thumb-state registers | Visible ARM-state registers
|
||
* 10000 | USER | r0–r7, SP, LR, PC, CPSR | r0–r14, PC, CPSR
|
||
* 10001 | FIQ | r0–r7, SP_fiq, LR_fiq, PC, CPSR, SPSR_fiq | r0–r7, r8_fiq–r14_fiq, PC, CPSR, SPSR_fiq
|
||
* 10010 | IRQ | r0–r7, SP_irq, LR_irq, PC, CPSR, SPSR_irq | r0–r12, r13_irq, r14_irq, PC, CPSR, SPSR_irq
|
||
* 10011 | SVC | r0–r7, SP_svc, LR_svc, PC, CPSR, SPSR_svc | r0–r12, r13_svc, r14_svc, PC, CPSR, SPSR_svc
|
||
* 10111 | ABRT | r0–r7, SP_abt, LR_abt, PC, CPSR, SPSR_abt | r0–r12, r13_abt, r14_abt, PC, CPSR, SPSR_abt
|
||
* 11011 | UNDF | r0–r7, SP_und, LR_und, PC, CPSR, SPSR_und | r0–r12, r13_und, r14_und, PC, CPSR, SPSR_und
|
||
* 11111 | SYS | r0–r7, SP, LR, PC, CPSR | r0–r14, PC, CPSR
|
||
*/
|
||
|
||
#define EXCP_EN_ADDR 0x4003FFFC
|
||
#define EXCP_TYPE_ADDR 0x4003FFF8
|
||
#define EXCP_LR_ADDR 0x4003FFF4
|
||
|
||
#define EXCP_VEC_BASE 0x6000F000
|
||
#define EVP_COP_RESET_VECTOR 0x200
|
||
#define EVP_COP_UNDEF_VECTOR 0x204
|
||
#define EVP_COP_SWI_VECTOR 0x208
|
||
#define EVP_COP_PREFETCH_ABORT_VECTOR 0x20C
|
||
#define EVP_COP_DATA_ABORT_VECTOR 0x210
|
||
#define EVP_COP_RSVD_VECTOR 0x214
|
||
#define EVP_COP_IRQ_VECTOR 0x218
|
||
#define EVP_COP_FIQ_VECTOR 0x21C
|
||
|
||
#define MODE_USR 0x10
|
||
#define MODE_FIQ 0x11
|
||
#define MODE_IRQ 0x12
|
||
#define MODE_SVC 0x13
|
||
#define MODE_ABT 0x17
|
||
#define MODE_UDF 0x1B
|
||
#define MODE_SYS 0x1F
|
||
#define MODE_MASK 0x1F
|
||
|
||
#define FIQ 0x40
|
||
#define IRQ 0x80
|
||
|
||
.section .text._irq_setup
|
||
.arm
|
||
|
||
.extern ipl_main
|
||
.type ipl_main, %function
|
||
|
||
.extern svc_handler
|
||
.type svc_handler, %function
|
||
|
||
.extern irq_handler
|
||
.type irq_handler, %function
|
||
|
||
.extern fiq_setup
|
||
.type fiq_setup, %function
|
||
|
||
.extern fiq_handler
|
||
.type fiq_handler, %function
|
||
|
||
.globl _irq_setup
|
||
.type _irq_setup, %function
|
||
_irq_setup:
|
||
MRS R0, CPSR
|
||
BIC R0, R0, #MODE_MASK /* Clear mode bits */
|
||
ORR R0, R0, #(MODE_SVC | IRQ | FIQ) /* SUPERVISOR mode, IRQ/FIQ disabled */
|
||
MSR CPSR, R0
|
||
|
||
/* Setup IRQ stack pointer */
|
||
MSR CPSR, #(MODE_IRQ | IRQ | FIQ) /* IRQ mode, IRQ/FIQ disabled */
|
||
LDR SP, =0x40040000
|
||
|
||
/* Setup SYS stack pointer */
|
||
MSR CPSR, #(MODE_SYS | IRQ | FIQ) /* SYSTEM mode, IRQ/FIQ disabled */
|
||
LDR SP, =0x4003FF00 /* Will be changed later to DRAM */
|
||
|
||
MOV LR, PC
|
||
BL setup_vectors
|
||
/*BL fiq_setup*/
|
||
|
||
/* Enable interrupts */
|
||
BL irq_enable_cpu_irq_exceptions
|
||
|
||
B ipl_main
|
||
B .
|
||
|
||
_reset:
|
||
LDR R0, =EXCP_EN_ADDR
|
||
LDR R1, =0x30505645 /* EVP0 */
|
||
STR R1, [R0] /* EVP0 in EXCP_EN_ADDR */
|
||
LDR R0, =EXCP_LR_ADDR
|
||
MOV R1, LR
|
||
STR R1, [R0] /* Save LR in EXCP_LR_ADDR */
|
||
LDR R0, =__bss_start
|
||
EOR R1, R1, R1
|
||
LDR R2, =__bss_end
|
||
SUB R2, R2, R0
|
||
BL memset
|
||
B _irq_setup
|
||
|
||
_reset_handler:
|
||
LDR R0, =EXCP_TYPE_ADDR
|
||
LDR R1, =0x545352 /* RST */
|
||
STR R1, [R0] /* RST in EXCP_TYPE_ADDR */
|
||
B _reset
|
||
|
||
_undefined_handler:
|
||
LDR R0, =EXCP_TYPE_ADDR
|
||
LDR R1, =0x464455 /* UDF */
|
||
STR R1, [R0] /* UDF in EXCP_TYPE_ADDR */
|
||
B _reset
|
||
|
||
_prefetch_abort_handler:
|
||
LDR R0, =EXCP_TYPE_ADDR
|
||
LDR R1, =0x54424150 /* PABT */
|
||
STR R1, [R0] /* PABT in EXCP_TYPE_ADDR */
|
||
B _reset
|
||
|
||
_data_abort_handler:
|
||
LDR R0, =EXCP_TYPE_ADDR
|
||
LDR R1, =0x54424144 /* DABT */
|
||
STR R1, [R0] /* DABT in EXCP_TYPE_ADDR */
|
||
B _reset
|
||
|
||
.globl irq_enable_cpu_irq_exceptions
|
||
.type irq_enable_cpu_irq_exceptions, %function
|
||
irq_enable_cpu_irq_exceptions:
|
||
MRS R12, CPSR
|
||
BIC R12, R12, #(IRQ | FIQ) /* IRQ/FIQ enabled */
|
||
MSR CPSR, R12
|
||
BX LR
|
||
|
||
.globl irq_disable_cpu_irq_exceptions
|
||
.type irq_disable_cpu_irq_exceptions, %function
|
||
irq_disable_cpu_irq_exceptions:
|
||
MRS R12, CPSR
|
||
ORR R12, R12, #(IRQ | FIQ) /* IRQ/FIQ disabled */
|
||
MSR CPSR, R12
|
||
BX LR
|
||
|
||
_irq_handler:
|
||
MOV R13, R0 /* Save R0 in R13_IRQ */
|
||
SUB R0, LR, #4 /* Put return address in R0_SYS */
|
||
MOV LR, R1 /* Save R1 in R14_IRQ (LR) */
|
||
MRS R1, SPSR /* Put the SPSR in R1_SYS */
|
||
|
||
MSR CPSR_c, #(MODE_SYS | IRQ) /* SYSTEM mode, IRQ disabled */
|
||
STMFD SP!, {R0, R1} /* SPSR and PC */
|
||
STMFD SP!, {R2-R3, R12, LR} /* AAPCS-clobbered registers */
|
||
MOV R0, SP /* Make SP_SYS visible to IRQ mode */
|
||
SUB SP, SP, #8 /* Make room for stacking R0 and R1 */
|
||
|
||
MSR CPSR_c, #(MODE_IRQ | IRQ) /* IRQ mode, IRQ disabled */
|
||
STMFD R0!, {R13, R14} /* Finish saving the context (R0, R1) */
|
||
|
||
MSR CPSR_c, #(MODE_SYS | IRQ) /* SYSTEM mode, IRQ disabled */
|
||
LDR R12, =irq_handler
|
||
MOV LR, PC /* Copy the return address to link register */
|
||
BX R12 /* Call the C IRQ handler (ARM/THUMB) */
|
||
|
||
MSR CPSR_c, #(MODE_SYS | IRQ | FIQ) /* SYSTEM mode, IRQ/FIQ disabled */
|
||
MOV R0, SP /* Make SP_SYS visible to IRQ mode */
|
||
ADD SP, SP, #32 /* Fake unstacking 8 registers from SP_SYS */
|
||
|
||
MSR CPSR_c, #(MODE_IRQ | IRQ | FIQ) /* IRQ mode, IRQ/FIQ disabled */
|
||
MOV SP, R0 /* Copy SP_SYS to SP_IRQ */
|
||
LDR R0, [SP, #28] /* Load the saved SPSR from the stack */
|
||
MSR SPSR_cxsf, R0 /* Copy it into SPSR_IRQ */
|
||
|
||
LDMFD SP, {R0-R3, R12, LR}^ /* Unstack all saved USER/SYSTEM registers */
|
||
NOP /* Cant access barked registers immediately */
|
||
LDR LR, [SP, #24] /* Load return address from the SYS stack */
|
||
MOVS PC, LR /* Return restoring CPSR from SPSR */
|
||
|
||
_fiq_handler:
|
||
BL fiq_handler
|
||
|
||
setup_vectors:
|
||
/* Setup vectors */
|
||
LDR R0, =EXCP_VEC_BASE
|
||
|
||
LDR R1, =_reset_handler
|
||
STR R1, [R0, #EVP_COP_RESET_VECTOR]
|
||
|
||
LDR R1, =_undefined_handler
|
||
STR R1, [R0, #EVP_COP_UNDEF_VECTOR]
|
||
|
||
LDR R1, =_reset_handler
|
||
STR R1, [R0, #EVP_COP_SWI_VECTOR]
|
||
|
||
LDR R1, =_prefetch_abort_handler
|
||
STR R1, [R0, #EVP_COP_PREFETCH_ABORT_VECTOR]
|
||
|
||
LDR R1, =_data_abort_handler
|
||
STR R1, [R0, #EVP_COP_DATA_ABORT_VECTOR]
|
||
|
||
LDR R1, =_reset_handler
|
||
STR R1, [R0, #EVP_COP_RSVD_VECTOR]
|
||
|
||
LDR R1, =_irq_handler
|
||
STR R1, [R0, #EVP_COP_IRQ_VECTOR]
|
||
|
||
LDR R1, =_fiq_handler
|
||
STR R1, [R0, #EVP_COP_FIQ_VECTOR]
|
||
|
||
BX LR
|