// 本文部分内容来自网络

// 基于内核版本3.4

发生Data Abort异常后,ARM处理器首先根据向量表找到对应异常入口,向量表位于arch/arm/kernel/entry-armv.S:

    .globl  __vectors_start
__vectors_start:ARM(    swi SYS_ERROR0  )THUMB( svc #0      )THUMB( nop         )W(b)   vector_und + stubs_offsetW(ldr)    pc, .LCvswi + stubs_offsetW(b) vector_pabt + stubs_offsetW(b) vector_dabt + stubs_offsetW(b) vector_addrexcptn + stubs_offsetW(b)   vector_irq + stubs_offsetW(b)  vector_fiq + stubs_offset.globl    __vectors_end

对于data abort,对应的跳转地址是vector_dabt + stubs_offset。这个地址的指令定义也在entry-armv.S

/** Data abort dispatcher* Enter in ABT mode, spsr = USR CPSR, lr = USR PC*/vector_stub    dabt, ABT_MODE, 8.long  __dabt_usr          @  0  (USR_26 / USR_32).long   __dabt_invalid          @  1  (FIQ_26 / FIQ_32).long   __dabt_invalid          @  2  (IRQ_26 / IRQ_32).long   __dabt_svc          @  3  (SVC_26 / SVC_32).long   __dabt_invalid          @  4.long  __dabt_invalid          @  5.long  __dabt_invalid          @  6.long  __dabt_invalid          @  7.long  __dabt_invalid          @  8.long  __dabt_invalid          @  9.long  __dabt_invalid          @  a.long  __dabt_invalid          @  b.long  __dabt_invalid          @  c.long  __dabt_invalid          @  d.long  __dabt_invalid          @  e.long  __dabt_invalid          @  f

怎么将vector_dabt + stubs_offset和上述代码对应起来呢?将vector_stub的宏定义展开就能看出:

/** Vector stubs.** This code is copied to 0xffff0200 so we can use branches in the* vectors, rather than ldr's.  Note that this code must not* exceed 0x300 bytes.** Common stub entry macro:*   Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC** SP points to a minimal amount of processor-private memory, the address* of which is copied into r0 for the mode specific abort handler.*/.macro    vector_stub, name, mode, correction=0.align    5vector_\name:.if \correctionsub    lr, lr, #\correction.endif@@ Save r0, lr_<exception> (parent PC) and spsr_<exception>@ (parent CPSR)@stmia    sp, {r0, lr}        @ save r0, lrmrs    lr, spsr          @保存跳转之前的CPSR到lr寄存器str    lr, [sp, #8]        @ save spsr@@ Prepare for SVC32 mode.  IRQs remain disabled.@mrs    r0, cpsreor    r0, r0, #(\mode ^ SVC_MODE | PSR_ISETSTATE)msr    spsr_cxsf, r0           @准备进入svc模式@@ the branch table must immediately follow this code@and    lr, lr, #0x0f          @得到跳转前所处的模式(usr、svr等)THUMB(    adr    r0, 1f            )THUMB(    ldr    lr, [r0, lr, lsl #2]    )mov    r0, sp                   ARM(    ldr    lr, [pc, lr, lsl #2]    ) @根据模式跳转到相应的data abort指令,并进入svc模式movs    pc, lr            @ branch to handler in SVC mode
ENDPROC(vector_\name).align    2@ handler addresses follow this label
1:.endm

对于同一个异常,根据进入异常之前所处的模式,会跳转到不同的指令分支,这些指令分支紧跟在vector_stub宏定义的后面。如果进入data abort之前处于usr模式,那么跳转到__dabt_usr;如果处于svc模式,那么跳转到__dabt_svc;否则跳转到__dabt_invalid。 实际上,进入异常向量前Linux只能处于usr或者svc两种模式之一。这时因为irq等异常在跳转表中都要经过vector_stub宏,而不管之前是哪种状态,这个宏都会将CPU状态改为svc模式。 usr模式即Linux中的用户态模式,svc即内核模式。

__dabt_svc流程,调用dabt_helper继续:

__dabt_svc:svc_entrymov    r2, spdabt_helper@@ IRQs off again before pulling preserved data off the stack@disable_irq_notrace#ifdef CONFIG_TRACE_IRQFLAGStst    r5, #PSR_I_BITbleq    trace_hardirqs_ontst    r5, #PSR_I_BITblne    trace_hardirqs_off
#endifsvc_exit r5                @ return from exceptionUNWIND(.fnend        )
ENDPROC(__dabt_svc)

dabt_helper流程,调用CPU_DABORT_HANDLER继续:

.macro    dabt_helper@@ Call the processor-specific abort handler:@@  r2 - pt_regs@  r4 - aborted context pc@  r5 - aborted context psr@@ The abort handler must return the aborted address in r0, and@ the fault status register in r1.  r9 must be preserved.@
#ifdef MULTI_DABORTldr    ip, .LCprocfnsmov    lr, pcldr    pc, [ip, #PROCESSOR_DABT_FUNC]
#elsebl    CPU_DABORT_HANDLER
#endif.endm#ifdef CONFIG_KPROBES.section    .kprobes.text,"ax",%progbits
#else.text
#endif

CPU_DABORT_HANDLER是一个宏定义,以armv6架构为例,最终函数为v6_early_abort

#  define CPU_DABORT_HANDLER v6_early_abort

v6_early_abort

首先读取DFSR和DFAR两个协处理寄存器,保存在R1和R0中,然后调用do_DataAbort进入C语言环境:

ENTRY(v6_early_abort)mrc    p15, 0, r1, c5, c0, 0       @ get FSRmrc   p15, 0, r0, c6, c0, 0       @ get FARb do_DataAbort

DFSR:失效状态寄存器,Data Fault Status Register -> R1: fsr

DFAR:失效地址寄存器,Data Fault Address Register ->R0:addr

 do_DataAbort:

asmlinkage void __exception
do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
{const struct fsr_info *inf = fsr_info + fsr_fs(fsr);struct siginfo info;if (!inf->fn(addr, fsr & ~FSR_LNX_PF, regs))return;printk(KERN_ALERT "Unhandled fault: %s (0x%03x) at 0x%08lx\n",inf->name, fsr, addr);info.si_signo = inf->sig;info.si_errno = 0;info.si_code  = inf->code;info.si_addr  = (void __user *)addr;arm_notify_die("", regs, &info, fsr, 0);
}

const struct fsr_info *inf = fsr_info + fsr_fs(fsr):

根据FSR的状态值,查询fsr_info表,得到相应处理函数与信号值。

struct fsr_info {int (*fn)(unsigned long addr, unsigned int fsr, struct pt_regs *regs);int   sig;int code;const char *name;
};

static struct fsr_info fsr_info[] = {{ do_bad,      SIGBUS,  0,     "unknown 0"           },{ do_bad,     SIGBUS,  0,     "unknown 1"           },{ do_bad,     SIGBUS,  0,     "unknown 2"           },{ do_bad,     SIGBUS,  0,     "unknown 3"           },{ do_bad,     SIGBUS,  0,     "reserved translation fault"  },{ do_translation_fault,   SIGSEGV, SEGV_MAPERR,   "level 1 translation fault"   },{ do_translation_fault,   SIGSEGV, SEGV_MAPERR,   "level 2 translation fault"   },{ do_page_fault,  SIGSEGV, SEGV_MAPERR,   "level 3 translation fault"   },{ do_bad,     SIGBUS,  0,     "reserved access flag fault"  },{ do_bad,     SIGSEGV, SEGV_ACCERR,   "level 1 access flag fault"   },{ do_bad,     SIGSEGV, SEGV_ACCERR,   "level 2 access flag fault"   },{ do_page_fault,  SIGSEGV, SEGV_ACCERR,   "level 3 access flag fault"   },......

fsr_info数组列出了常见的地址失效处理方案,例如do_page_fault处理缺页中断,do_translation_fault处理转换错误,其他不能处理的默认为do_bad:

static int
do_bad(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
{return 1;
}

do_bad不做任何处理,返回1后再调用arm_notify_die后处理:

void arm_notify_die(const char *str, struct pt_regs *regs,struct siginfo *info, unsigned long err, unsigned long trap)
{if (user_mode(regs)) {current->thread.error_code = err;current->thread.trap_no = trap;force_sig_info(info->si_signo, info, current);} else {die(str, regs, err);}
}

arm_notify_die函数判断当前处于Kernel模式还是User模式,如果是Kernel模式直接die,如果是User模式,调用force_sig_info向进程强制发送fsr_info表中对应信号,强制发送信号可以忽略信号处理的SIG_IGN标记,和stask_struct的blocked域。进程收到信号后,接着进行coredump等流程。

转载于:https://www.cnblogs.com/DF11G/p/9687443.html

ARM Linux Data Abort 异常处理流程相关推荐

  1. linux忽略abort信号,ARM Linux Data Abort 异常处理流程

    // 本文部分内容来自网络 //基于内核版本3.4 发生Data Abort异常后,ARM处理器首先根据向量表找到对应异常入口,向量表位于arch/arm/kernel/entry-armv.S: . ...

  2. arm linux之data abort异常处理

    data abort是ARM体系定义的异常之一.异常发生时,ARM会自动跳转到异常向量表中,通过向量表中的跳转命令跳转到相应的异常处理中去 svc模式进入data abort svc模式进入data ...

  3. 异常 | ARM _data_abort 异常处理流程

    ================================================ 博主github:https://github.com/MichaelBeechan 博主CSDN:h ...

  4. ARM Linux异常处理之data abort(一)

    本文简要分析了ARM Linux的data abort异常处理过程,内核版本2.6.28,s3c6410平台. 异常向量与程序跳转 data abort是ARM体系定义的异常之一.异常发生时,ARM会 ...

  5. abort linux,ARM Linux异常处理之data abort

    1 异常向量与程序跳转data abort是ARM体系定义的异常之一.异常发生时,ARM会自动跳转到异常向量表中,通过向量表中的跳转命令跳转到相应的异常处理中去. ARM的异常处理向量表在entry- ...

  6. 【嵌入式开发】ARM 异常向量表 ( 异常概念 | 异常处理流程 | 异常向量 | 汇编代码 )

    一. 异常向量表 1. 异常相关概念 (1) 异常 (2) 异常类型简介 2. 异常处理 (1) 异常处理 二. 异常向量表代码编写 1. 初始化异常向量表模块代码 2. 链接器脚本 3. Makef ...

  7. Linux 进内核,arm linux 启动流程之 进入内核

    原标题:arm linux 启动流程之 进入内核 还是从编译链接生成vm 的过程来看吧,由一大堆.o文件链接而成,第一个就是 kernel/arch//kernel/head-armv.o ,而且我们 ...

  8. arm linux系统启动流程

    ===================================================== arm linux系统启动相关文章列表: arm linux系统启动流程 http://bl ...

  9. 嵌入式linux内核启动过程,嵌入式Linux:ARM Linux启动流程

    ARM Linux启动流程大致为:bootloader---->kernel---->root filesystem.bootloader 是一上电就拿到cpu 的控制权的,而bootlo ...

最新文章

  1. php7-fpm webtatic,如何在 CentOS 7 中使用 Nginx 和 PHP7-FPM 安装 Nextcloud
  2. 字符编码看不懂你来打我!(ASCII,Unicode,Utf-8,GB2312…)
  3. FMDB(FMDatabase)--SQLite的封装
  4. mysql 8.0 安装_安装MySQL-8.0.19
  5. 我们需要什么样的计算
  6. C#的6种常用集合类大比拼(转)
  7. ElasticSearch学习笔记(二)
  8. 微信小程序云开发教程-WXML入门-基本语法
  9. ubuntu 安装和删除字体
  10. 关于nuxt sass-loader 报错 in ./pages/index.vue?vuetype=styleindex=0id=2a183b29lang=scssscoped=true
  11. get与post的解释与区别
  12. 【错误记录】Android 应用 POST 网络请求报错 ( java.io.IOException: Cleartext HTTP traffic to xxx not permitted )
  13. 如何使用NVivo进行定性研究?
  14. iOS开发人员必看的精品资料(100个)——下载目录
  15. 过来人的经验:自学编程的6个建议
  16. Android GridView如何固定间隔,item能自适应大小(笔记)
  17. Arduino按键控制MP3模块随机播放音乐(YX5300 MP3音乐模块)
  18. vue 防抖节流,开箱即用
  19. 解析几何--面积的计算
  20. IE10+删除input后面的叉

热门文章

  1. 华宇法律人工智能平台:用新一代的科技推动新时代的法律服务达到完全互联、无所不在 |百万人学AI评选
  2. 解决代理服务器出现问题,无法连接校园网
  3. PTA 2021C语言程序设计专题实验02-循环
  4. 从“去担保”向“强担保”的转变
  5. BGP机房的基本概念
  6. Java程序设计梁勇第十版第八章编程练习题
  7. Unity——通过Shader 制作精灵动画,瀑布
  8. c语言变量 集体备课,集体备课——分享智慧 共同成长
  9. matlab院校,MATLAB要来了?!
  10. 什么是黑帽SEO,哪些属于黑帽技术?