本节来详细描述下ARMv8-A下的异常处理。
当设备正在愉快的执行时候,此时发生了一个异常,处理器就必须暂停当前的任务,转而去处理发生的异常。当异常处理完毕后,处理就会发回到被打断的程序继续执行。
此图就是描述异常的处理流程。
异常分为同步异常和异步异常,而这两种异常的区别是:
同步异常:如果异常的产生是通过执行指令,而且返回结果提供了产生异常的详细信息,则此类异常称为同步异常(Synchronous Exceprions)
异步异常:如果异常不是通过指令执行产生,而且返回结果不提供产线异常的详细信息,则此类异常为异步异常(asynchronous exceptions)
同步异常包含的类型很多,比如第一次申请内存,当去写或者读的时候就会触发一次page fault,此类异常就属于同步异常
我们先来看下异常处理的整个过程
当异常发生时,硬件会自动做如下几个步骤:
PSTATE,SPSR已经在上一篇文章Process Status中做过描述了,此处不做说明了。
当异常发生时,我们可以从ESR_ELn寄存器中获取对应的异常状态。
比如:
这四组在EL1的实现为,也就是linux内核的实现为:
424/*
425 * Exception vectors.
426 */
427 .pushsection ".entry.text", "ax"
428
429 .align 11
430ENTRY(vectors)
431 kernel_ventry 1, sync_invalid // Synchronous EL1t
432 kernel_ventry 1, irq_invalid // IRQ EL1t
433 kernel_ventry 1, fiq_invalid // FIQ EL1t
434 kernel_ventry 1, error_invalid // Error EL1t
435
436 kernel_ventry 1, sync // Synchronous EL1h
437 kernel_ventry 1, irq // IRQ EL1h
438 kernel_ventry 1, fiq_invalid // FIQ EL1h
439 kernel_ventry 1, error // Error EL1h
440
441 kernel_ventry 0, sync // Synchronous 64-bit EL0
442 kernel_ventry 0, irq // IRQ 64-bit EL0
443 kernel_ventry 0, fiq_invalid // FIQ 64-bit EL0
444 kernel_ventry 0, error // Error 64-bit EL0
445
446#ifdef CONFIG_COMPAT
447 kernel_ventry 0, sync_compat, 32 // Synchronous 32-bit EL0
448 kernel_ventry 0, irq_compat, 32 // IRQ 32-bit EL0
449 kernel_ventry 0, fiq_invalid_compat, 32 // FIQ 32-bit EL0
450 kernel_ventry 0, error_compat, 32 // Error 32-bit EL0
451#else
452 kernel_ventry 0, sync_invalid, 32 // Synchronous 32-bit EL0
453 kernel_ventry 0, irq_invalid, 32 // IRQ 32-bit EL0
454 kernel_ventry 0, fiq_invalid, 32 // FIQ 32-bit EL0
455 kernel_ventry 0, error_invalid, 32 // Error 32-bit EL0
456#endif
457END(vectors)
分为四组,其中第一组是invaild的。