arm64 异常处理
2016-10-21 18:37
225 查看
<span style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: rgb(255, 255, 255);">armv8中有四个Exception Level,分别是下面四个:</span>
EL0 : 普通用户应用
EL1 : 操作系统OS层
EL2 : Hypervisor
EL3 : Low-level firmware, including the Secure Monitor
我们主要讨论EL0、EL1,不讨论EL2和EL3,有兴趣的可以研究下ARMv8设置这两个。
二、异常处理分类
Interrupts : 中断包括FIQ和IRQ;Aborts : Aborts包括 Instruction aborts 和 Data aborts,当访问数据和指令的时候MMU会检测指令或数据是否正确,如果错误MMU会返回一个错误。
Reset : Reset是一个特殊的vector,在最高的Exception level,这个vector使用一个IMPLEMENTATION DEFINED的地址。
Exception generating instructions :我的理解是当你执行一条指令时,如果这条指令属于EL0层时,你去访问EL1层的内容,就会触发这个异常。Supervisor Call ( SVC )在 EL1 、 Hypervisor Call ( HVC )在EL2、Secure monitor Call (
SMC )在EL3,后面我们会简单介绍下ELn的含义。
三、异常处理寄存器
如果发生异常,系统自动将PSTATE的信息保存到Saved Program Status Register(SPSR_ELn)中,注意不存在SR_EL0,因为异常不会执行在EL0.当发生异常时,SPSR_ELn寄存器被更新,存放PSTATE信息,然后将执行:
四、同步异常和异步异常
同步异常主要包含一下几点:Aborts from the MMU. For example, permission failures or memory areas marked as Access flag fault.
SP and PC alignment checking.
Unallocated instructions.
Service Calls (SVCs, SMCs and HVCs).
异常向量表
五、分析下arm64中entry.S中的异常处理代码
</pre><pre name="code" class="objc">/* * Exception vectors. */ .align 11 ENTRY(vectors) ventry el1_sync_invalid // Synchronous EL1t ventry el1_irq_invalid // IRQ EL1t ventry el1_fiq_invalid // FIQ EL1t ventry el1_error_invalid // Error EL1t ventry el1_sync // Synchronous EL1h ventry el1_irq // IRQ EL1h ventry el1_fiq_invalid // FIQ EL1h ventry el1_error_invalid // Error EL1h ventry el0_sync // Synchronous 64-bit EL0 ventry el0_irq // IRQ 64-bit EL0 ventry el0_fiq_invalid // FIQ 64-bit EL0 ventry el0_error_invalid // Error 64-bit EL0 #ifdef CONFIG_COMPAT ventry el0_sync_compat // Synchronous 32-bit EL0 ventry el0_irq_compat // IRQ 32-bit EL0 ventry el0_fiq_invalid_compat // FIQ 32-bit EL0 ventry el0_error_invalid_compat // Error 32-bit EL0 #else ventry el0_sync_invalid // Synchronous 32-bit EL0 ventry el0_irq_invalid // IRQ 32-bit EL0 ventry el0_fiq_invalid // FIQ 32-bit EL0 ventry el0_error_invalid // Error 32-bit EL0 #endif END(vectors) /* * Invalid mode handlers */ .macro inv_entry, el, reason, regsize = 64 kernel_entry el, \regsize mov x0, sp mov x1, #\reason mrs x2, esr_el1 b bad_mode .endm el0_sync_invalid: inv_entry 0, BAD_SYNC ENDPROC(el0_sync_invalid) el0_irq_invalid: inv_entry 0, BAD_IRQ ENDPROC(el0_irq_invalid) //inv_entry是一个宏定义,主要工作就是将寄存器压栈后跳到bad_mode函数运 //后面紧跟的1代表异常级是el1,即内核态 //BAD_IRQ定义在前面,值为1,代表发生异常的原因 el0_fiq_invalid: inv_entry 0, BAD_FIQ ENDPROC(el0_fiq_invalid) el0_error_invalid: inv_entry 0, BAD_ERROR ENDPROC(el0_error_invalid) #ifdef CONFIG_COMPAT el0_fiq_invalid_compat: inv_entry 0, BAD_FIQ, 32 ENDPROC(el0_fiq_invalid_compat) el0_error_invalid_compat: inv_entry 0, BAD_ERROR, 32 ENDPROC(el0_error_invalid_compat) #endif el1_sync_invalid: inv_entry 1, BAD_SYNC ENDPROC(el1_sync_invalid) el1_irq_invalid: inv_entry 1, BAD_IRQ ENDPROC(el1_irq_invalid) el1_fiq_invalid: inv_entry 1, BAD_FIQ ENDPROC(el1_fiq_invalid) el1_error_invalid: inv_entry 1, BAD_ERROR ENDPROC(el1_error_invalid) /* * EL1 mode handlers. */ .align 6 el1_sync: kernel_entry 1 mov x0, sp and x20, x0, #0xffffffffffffc000 ldr w4, [x20, #TI_CPU_EXCP] add w4, w4, #0x1 str w4, [x20, #TI_CPU_EXCP] cmp w4, #0x1 b.ne el1_sync_nest str x0, [x20, #TI_REGS_ON_EXCP] el1_sync_nest: cmp w4, #0x2 b.lt el1_sync_nest_skip bl aee_stop_nested_panic el1_sync_nest_skip: mrs x1, esr_el1 // read the syndrome register lsr x24, x1, #ESR_EL1_EC_SHIFT // exception class cmp x24, #ESR_EL1_EC_DABT_EL1 // data abort in EL1 b.eq el1_da cmp x24, #ESR_EL1_EC_SYS64 // configurable trap b.eq el1_undef cmp x24, #ESR_EL1_EC_SP_ALIGN // stack alignment exception b.eq el1_sp_pc cmp x24, #ESR_EL1_EC_PC_ALIGN // pc alignment exception b.eq el1_sp_pc cmp x24, #ESR_EL1_EC_UNKNOWN // unknown exception in EL1 b.eq el1_undef cmp x24, #ESR_EL1_EC_BREAKPT_EL1 // debug exception in EL1 b.ge el1_dbg b el1_inv el1_da: /* * Data abort handling */ mrs x0, far_el1 enable_dbg // re-enable interrupts if they were enabled in the aborted context tbnz x23, #7, 1f // PSR_I_BIT enable_irq 1: mov x2, sp // struct pt_regs bl do_mem_abort mov x5, sp and x20, x5, #0xffffffffffffc000 ldr w4, [x20, #TI_CPU_EXCP] sub w4, w4, #0x1 str w4, [x20, #TI_CPU_EXCP] // disable interrupts before pulling preserved data off the stack disable_irq kernel_exit 1 el1_sp_pc: /* * Stack or PC alignment exception handling */ mrs x0, far_el1 enable_dbg mov x2, sp b do_sp_pc_abort el1_undef: /* * Undefined instruction */ enable_dbg mov x0, sp bl do_undefinstr kernel_exit 1 el1_dbg: /* * Debug exception handling */ cmp x24, #ESR_EL1_EC_BRK64 // if BRK64 cinc x24, x24, eq // set bit '0' tbz x24, #0, el1_inv // EL1 only mrs x0, far_el1 mov x2, sp // struct pt_regs bl do_debug_exception mov x5, sp and x20, x5, #0xffffffffffffc000 ldr w4, [x20, #TI_CPU_EXCP] sub w4, w4, #0x1 str w4, [x20, #TI_CPU_EXCP] kernel_exit 1 el1_inv: // TODO: add support for undefined instructions in kernel mode enable_dbg mov x0, sp mov x1, #BAD_SYNC mrs x2, esr_el1 b bad_mode ENDPROC(el1_sync) .align 6 el1_irq: kernel_entry 1 enable_dbg #ifdef CONFIG_TRACE_IRQFLAGS bl trace_hardirqs_off #endif #ifdef CONFIG_MTPROF bl MT_trace_hardirqs_off #endif irq_handler #ifdef CONFIG_PREEMPT get_thread_info tsk ldr w24, [tsk, #TI_PREEMPT] // get preempt count cbnz w24, 1f // preempt count != 0 ldr x0, [tsk, #TI_FLAGS] // get flags tbz x0, #TIF_NEED_RESCHED, 1f // needs rescheduling? bl el1_preempt 1: #endif #ifdef CONFIG_MTPROF bl MT_trace_hardirqs_on #endif #ifdef CONFIG_TRACE_IRQFLAGS bl trace_hardirqs_on #endif kernel_exit 1 ENDPROC(el1_irq) #ifdef CONFIG_PREEMPT el1_preempt: mov x24, lr 1: bl preempt_schedule_irq // irq en/disable is done inside ldr x0, [tsk, #TI_FLAGS] // get new tasks TI_FLAGS tbnz x0, #TIF_NEED_RESCHED, 1b // needs rescheduling? ret x24 #endif
相关文章推荐
- 如何构建一个arm64 AArch64的Ubuntu rootfs
- Linux /Android ARM 64 bit/32 bit 编程移植
- armeabi-v7a armeabi arm64-v8a 参数的含义解释
- ARM64的启动过程之(五):UEFI
- 友盟统计编译不过arm64
- ARM64 Linux的启动分析
- Linux Kernel之spin_lock之ARM64实现
- 【技术】【操作】制作同时支持armv7,armv7s,arm64,i386,x86_64的静态库.a
- Apple移动设备处理器指令集 armv6、armv7、armv7s及arm64
- 支持Xcode6 IOS使用ZBar二维码扫描开发(解决arm64,arm7s兼容并解决中文乱码问题)
- iOS 中的 armv7,armv7s,arm64,i386,x86_64 都是什么
- iOS 中的 armv7,armv7s,arm64,i386,x86_64
- ART世界探险-arm64-v8a 64位CPU的架构快餐教程
- xcode armv6 armv7 armv7s arm64
- Linux Kernel之spin_lock之ARM64实现
- zbar适配arm64
- ios objc 方法调用记录插件(支持arm64+devlog):itracer v1.2
- Windows7中搭建Android x86_64及armv8-a操作步骤
- ARM64 qemu native build
- iOS——制作同时支持armv7,armv7s,arm64,i386,x86的静态库