目录
硬件:armv8-aarch64\arch以及armv7的向量表和基地址寄存器介绍
1、ARMV8 aarch64的异常向量表介绍
2、ARMV8 aarch32的异常向量表介绍
3、ARMV7 4的异常向量表介绍
4、ARMV8 aarch64的向量表基地址
5、ARMV8 aarch的向量表基地址
6、ARMV7的向量表基地址
软件:各个系统的异常向量表(Linux, optee, ATF …32位/64位)
1、Linux Kernel 中arm64定义的向量表
(linux/arch/arm64/kernel/entry.S)
/*
* Exception vectors.
*/
.pushsection ".entry.text", "ax"
.align 11
SYM_CODE_START(vectors)
kernel_ventry 1, sync_invalid // Synchronous EL1t
kernel_ventry 1, irq_invalid // IRQ EL1t
kernel_ventry 1, fiq_invalid // FIQ EL1t
kernel_ventry 1, error_invalid // Error EL1t
kernel_ventry 1, sync // Synchronous EL1h
kernel_ventry 1, irq // IRQ EL1h
kernel_ventry 1, fiq // FIQ EL1h
kernel_ventry 1, error // Error EL1h
kernel_ventry 0, sync // Synchronous 64-bit EL0
kernel_ventry 0, irq // IRQ 64-bit EL0
kernel_ventry 0, fiq // FIQ 64-bit EL0
kernel_ventry 0, error // Error 64-bit EL0
#ifdef CONFIG_COMPAT
kernel_ventry 0, sync_compat, 32 // Synchronous 32-bit EL0
kernel_ventry 0, irq_compat, 32 // IRQ 32-bit EL0
kernel_ventry 0, fiq_compat, 32 // FIQ 32-bit EL0
kernel_ventry 0, error_compat, 32 // Error 32-bit EL0
#else
kernel_ventry 0, sync_invalid, 32 // Synchronous 32-bit EL0
kernel_ventry 0, irq_invalid, 32 // IRQ 32-bit EL0
kernel_ventry 0, fiq_invalid, 32 // FIQ 32-bit EL0
kcernel_ventry 0, error_invalid, 32 // Error 32-bit EL0
#endif
SYM_CODE_END(vectors)
el1_sync_invalid
el1_irq_invalid
el1_fiq_invalid
el1_error_invalid
el1_sync
el1_irq
el1_fiq
el1_error
el0_sync
el0_irq
el0_fiq
el0_error
2、Linux Kernel 中arm定义的向量表
.section .stubs, "ax", %progbits
__stubs_start:
@ This must be the first word
.word vector_swi
.section .vectors, "ax", %progbits
__vectors_start:
W(b) vector_rst
W(b) vector_und
W(ldr) pc, __vectors_start + 0x1000
W(b) vector_pabt
W(b) vector_dabt
W(b) vector_addrexcptn
W(b) vector_irq
W(b) vector_fiq
3、optee中arm64定义的异常向量表
(core/arch/arm/kernel/thread_a64.S)
.section .text.thread_excp_vect
.align 11, INV_INSN
FUNC thread_excp_vect , :
/* -----------------------------------------------------
* EL1 with SP0 : 0x0 - 0x180
* -----------------------------------------------------
*/
.align 7, INV_INSN
el1_sync_sp0:
store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3
b el1_sync_abort
check_vector_size el1_sync_sp0
.align 7, INV_INSN
el1_irq_sp0:
store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3
b elx_irq
check_vector_size el1_irq_sp0
.align 7, INV_INSN
el1_fiq_sp0:
store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3
b elx_fiq
check_vector_size el1_fiq_sp0
.align 7, INV_INSN
el1_serror_sp0:
b el1_serror_sp0
check_vector_size el1_serror_sp0
/* -----------------------------------------------------
* Current EL with SP1: 0x200 - 0x380
* -----------------------------------------------------
*/
.align 7, INV_INSN
el1_sync_sp1:
b el1_sync_sp1
check_vector_size el1_sync_sp1
.align 7, INV_INSN
el1_irq_sp1:
b el1_irq_sp1
check_vector_size el1_irq_sp1
.align 7, INV_INSN
el1_fiq_sp1:
b el1_fiq_sp1
check_vector_size el1_fiq_sp1
.align 7, INV_INSN
el1_serror_sp1:
b el1_serror_sp1
check_vector_size el1_serror_sp1
/* -----------------------------------------------------
* Lower EL using AArch64 : 0x400 - 0x580
* -----------------------------------------------------
*/
.align 7, INV_INSN
el0_sync_a64:
restore_mapping
mrs x2, esr_el1
mrs x3, sp_el0
lsr x2, x2, #ESR_EC_SHIFT
cmp x2, #ESR_EC_AARCH64_SVC
b.eq el0_svc
b el0_sync_abort
check_vector_size el0_sync_a64
.align 7, INV_INSN
el0_irq_a64:
restore_mapping
b elx_irq
check_vector_size el0_irq_a64
.align 7, INV_INSN
el0_fiq_a64:
restore_mapping
b elx_fiq
check_vector_size el0_fiq_a64
.align 7, INV_INSN
el0_serror_a64:
b el0_serror_a64
check_vector_size el0_serror_a64
/* -----------------------------------------------------
* Lower EL using AArch32 : 0x0 - 0x180
* -----------------------------------------------------
*/
.align 7, INV_INSN
el0_sync_a32:
restore_mapping
mrs x2, esr_el1
mrs x3, sp_el0
lsr x2, x2, #ESR_EC_SHIFT
cmp x2, #ESR_EC_AARCH32_SVC
b.eq el0_svc
b el0_sync_abort
check_vector_size el0_sync_a32
.align 7, INV_INSN
el0_irq_a32:
restore_mapping
b elx_irq
check_vector_size el0_irq_a32
.align 7, INV_INSN
el0_fiq_a32:
restore_mapping
b elx_fiq
check_vector_size el0_fiq_a32
.align 7, INV_INSN
el0_serror_a32:
b el0_serror_a32
check_vector_size el0_serror_a32
4、optee中arm定义的异常向量表
(core/arch/arm/kernel/thread_a32.S)
.section .text.thread_excp_vect
.align 5
FUNC thread_excp_vect , :
UNWIND( .fnstart)
UNWIND( .cantunwind)
b . /* Reset */
b thread_und_handler /* Undefined instruction */
b thread_svc_handler /* System call */
b thread_pabort_handler /* Prefetch abort */
b thread_dabort_handler /* Data abort */
b . /* Reserved */
b thread_irq_handler /* IRQ */
b thread_fiq_handler /* FIQ */
5、在ATF中arm64异常向量表的实现定义
func bl1_entrypoint
......
el3_entrypoint_common \
_set_endian=1 \
_warm_boot_mailbox=!PROGRAMMABLE_RESET_ADDRESS \
_secondary_cold_boot=!COLD_BOOT_SINGLE_CPU \
_init_memory=1 \
_init_c_runtime=1 \
_exception_vectors=bl1_exceptions
func bl2_entrypoint
el3_entrypoint_common \
_set_endian=0 \
_warm_boot_mailbox=0 \
_secondary_cold_boot=0 \
_secondary_cpu = 0 \
_init_memory=0 \
_init_c_runtime=1 \
_exception_vectors=bl2_vector
func bl31_entrypoint
......
el3_entrypoint_common \
_set_endian=0 \
_warm_boot_mailbox=0 \
_secondary_cold_boot=0 \
_init_memory=0 \
_init_c_runtime=1 \
_exception_vectors=runtime_exceptions
vector_entry sync_exception_sp_el0
b report_unhandled_exception
check_vector_size sync_exception_sp_el0
vector_entry irq_sp_el0
b report_unhandled_interrupt
check_vector_size irq_sp_el0
vector_entry fiq_sp_el0
b report_unhandled_interrupt
check_vector_size fiq_sp_el0
vector_entry serror_sp_el0
b report_unhandled_exception
check_vector_size serror_sp_el0
vector_entry sync_exception_sp_elx
b report_unhandled_exception
check_vector_size sync_exception_sp_elx
vector_entry irq_sp_elx
b report_unhandled_interrupt
check_vector_size irq_sp_elx
vector_entry fiq_sp_elx
b report_unhandled_interrupt
check_vector_size fiq_sp_elx
vector_entry serror_sp_elx
b report_unhandled_exception
check_vector_size serror_sp_elx
vector_entry sync_exception_aarch64
handle_sync_exception
check_vector_size sync_exception_aarch64
vector_entry irq_aarch64
handle_interrupt_exception irq_aarch64
check_vector_size irq_aarch64
vector_entry fiq_aarch64
handle_interrupt_exception fiq_aarch64
check_vector_size fiq_aarch64
vector_entry serror_aarch64
b report_unhandled_exception
check_vector_size serror_aarch64
vector_entry sync_exception_aarch32
handle_sync_exception
check_vector_size sync_exception_aarch32
vector_entry irq_aarch32
handle_interrupt_exception irq_aarch32
check_vector_size irq_aarch32
vector_entry fiq_aarch32
handle_interrupt_exception fiq_aarch32
check_vector_size fiq_aarch32
vector_entry serror_aarch32
b report_unhandled_exception
check_vector_size serror_aarch32
6、、在ATF中arm64异常向量表的实现定义
软件:各个系统的向量表基地址的设置(Linux, optee, ATF …32位/64位)
1、linux kernel的arm64下设置向量表基地址VBAR
__primary_switched:
adrp x4, init_thread_union
add sp, x4, #THREAD_SIZE
adr_l x5, init_task
msr sp_el0, x5 // Save thread_info
adr_l x8, vectors // load VBAR_EL1 with virtual
msr vbar_el1, x8 // vector table address
isb
stp xzr, x30, [sp, #-16]!
mov x29, sp
str_l x21, __fdt_pointer, x5 // Save FDT pointer
..
b start_kernel
ENDPROC(__primary_switched)
2、linux kernel的arm32下设置向量表基地址VBAR
(kernel-4.14/arch/arm/kernel/vmlinux.lds.S)
__vectors_start = .;
.vectors 0xffff0000 : AT(__vectors_start) {
*(.vectors)
}
. = __vectors_start + SIZEOF(.vectors);
__vectors_end = .;
__stubs_start = .;
.stubs ADDR(.vectors) + 0x1000 : AT(__stubs_start) {
*(.stubs)
}
. = __stubs_start + SIZEOF(.stubs);
__stubs_end = .;
(kernel-4.14/arch/arm/mm/nommu.c)
static unsigned long __init setup_vectors_base(void)
{
unsigned long reg = get_cr();
set_cr(reg | CR_V); //其实就是将CR_V写入到了cp15, 也就是写入到了VBAR寄存器.
return 0xffff0000;
}
static inline void set_cr(unsigned long val)
{
asm volatile("mcr p15, 0, %0, c1, c0, 0 @ set CR"
: : "r" (val) : "cc");
isb();
}
(kernel-4.14/arch/arm/include/asm/cp15.h)
#define CR_M (1 << 0) /* MMU enable */
#define CR_A (1 << 1) /* Alignment abort enable */
#define CR_C (1 << 2) /* Dcache enable */
#define CR_W (1 << 3) /* Write buffer enable */
#define CR_P (1 << 4) /* 32-bit exception handler */
#define CR_D (1 << 5) /* 32-bit data address range */
#define CR_L (1 << 6) /* Implementation defined */
#define CR_B (1 << 7) /* Big endian */
#define CR_S (1 << 8) /* System MMU protection */
#define CR_R (1 << 9) /* ROM MMU protection */
#define CR_F (1 << 10) /* Implementation defined */
#define CR_Z (1 << 11) /* Implementation defined */
#define CR_I (1 << 12) /* Icache enable */
#define CR_V (1 << 13) /* Vectors relocated to 0xffff0000 */
#define CR_RR (1 << 14) /* Round Robin cache replacement */
#define CR_L4 (1 << 15) /* LDR pc can set T bit */
#define CR_DT (1 << 16)
setup_arch ----> arm_memblock_init ----> arm_mm_memblock_reserve ---> setup_vectors_base
3、optee中arm64设置向量表基地址VBAR_EL1
(core/arch/arm/kernel/thread.c)
static vaddr_t get_excp_vect(void)
{
#ifdef CFG_CORE_WORKAROUND_SPECTRE_BP_SEC
uint32_t midr = read_midr();
if (get_midr_implementer(midr) != MIDR_IMPLEMENTER_ARM)
return (vaddr_t)thread_excp_vect;
switch (get_midr_primary_part(midr)) {
#ifdef ARM32
case CORTEX_A8_PART_NUM:
case CORTEX_A9_PART_NUM:
case CORTEX_A17_PART_NUM:
#endif
case CORTEX_A57_PART_NUM:
case CORTEX_A72_PART_NUM:
case CORTEX_A73_PART_NUM:
case CORTEX_A75_PART_NUM:
return select_vector((vaddr_t)thread_excp_vect_workaround);
#ifdef ARM32
case CORTEX_A15_PART_NUM:
return select_vector((vaddr_t)thread_excp_vect_workaround_a15);
#endif
default:
return (vaddr_t)thread_excp_vect;
}
#endif /*CFG_CORE_WORKAROUND_SPECTRE_BP_SEC*/
return (vaddr_t)thread_excp_vect;
}
void thread_init_per_cpu(void)
{
size_t pos = get_core_pos();
struct thread_core_local *l = thread_get_core_local();
init_sec_mon(pos);
set_tmp_stack(l, GET_STACK(stack_tmp[pos]) - STACK_TMP_OFFS);
set_abt_stack(l, GET_STACK(stack_abt[pos]));
thread_init_vbar(get_excp_vect());
}
(core/arch/arm/kernel/thread_a64.S)
FUNC thread_init_vbar , :
msr vbar_el1, x0
ret
END_FUNC thread_init_vbar
4、optee中arm设置向量表基地址VBAR_EL1
(core/arch/arm/kernel/thread_a32.S)
FUNC thread_init_vbar , :
UNWIND( .fnstart)
/* Set vector (VBAR) */
write_vbar r0
bx lr
UNWIND( .fnend)
END_FUNC thread_init_vbar
🌍咨询vx : sami01_2023