[笔记分享] [Exception] 内核空间异常之流程小结

本文详细介绍了在Android 2.3.4系统上,内核空间异常处理的流程,特别是针对数据异常(oops)的情况。从异常的接收、处理器(汇编和C语言部分)到最终的错误处理,包括do_page_fault函数的角色,以及如何通过dump信息来分析异常。
摘要由CSDN通过智能技术生成

平台: MSM8260
OS: Android 2.3.4

Overview

本文主要描述下kernel exception(这里以oops为主线)的flow以及如何对oops进行分析作一个讲解。

Exception flow

1.1 介绍

android系统上的exception的大致流程:

这里写图片描述

从arm_notify_die开始,左边是Kernel exception flow, 右边为user space exception flow,也就是说当exception处于user space时,kernel会发送信号给user space, 而不会像kernel exception一样会down机。

另外,我们发现,各种excetpion type和arm的exception基本上是对应的。如data abort, prefetch abort。

从图上看到,不管是哪种异常都会进入arm_notify_die,然后再die。其实经常碰到的exception不会经过arm_notify_die, 而是直接调用了do_page_fault就返回,不过没关系,do_page_fault最终也会调用die或者是force_sig_info。一会我们从代码中就可以看到了。

1.2Recieve

那么系统是如何知道一个exception发生的呢。拿kernel data abort为例(后面都是),当我们在kernel中对一个虚拟地址进行访问的时候,如0x12345678,但在系统初始化的时候,该地址所对应的权限是禁止访问,MMU捕捉到访问0x0的action之后,但是发现初始化时是设置禁止访问的,然后它就设置相关registers,产生一个exception。

这里写图片描述

1.3 Handler

1.3.1 汇编部分

Ok, exception 产生了, 到了区分是哪种exception的时候。 每种体系结构的exception都不尽相同,
我们是arm平台,所以对应的文件为entry-arm.S@y:\1090\android\kernel\arch\arm\kernel。

Exception时,首先进入异常向量表:

这里写图片描述

这里暂不讨论vector table放在高端时是如何跳转,毕竟exception为theme嘛,有兴趣的童鞋可参考http://blog.csdn.net/hongtao_liu/article/details/4263176 。所以这里不讨论直接进入vector_dabt + stubs_offset所对应地址:

这里写图片描述

虽然arm有好多种工作模式,但是在linux上只有两种,user和svc mode。这也使得linux在x86上的处理简单很多,题外话….

Vector_stub为一个宏:

这里写图片描述

Asm相对c看起来比较吃力(自己不熟悉也是原因咯–!),熬一熬就出头了。大概的意思就是保存当前当前信息(lr, cpsr, r0), 准备进入SVC mode前一些工作(不管是user还是kernel exception时都会进入svc mode), 然后判断产生exception的Mode, 最后跳转到相应handler。

那么我们这里就是进入了__dabt_svc了:

这里写图片描述

可以看到,不管是user还是kernel exception, 最终都会调用do_DataAbort, 只是kernel exception就reboot了。这里我们要关注的是r0保存了exception的address, r1保存了fault status。至于其他信息,如各种register, 是通过stack传参给do_DataAbort了。

顺便说下,arm中asm到c的传参是通过r0-r3, 当参数多个4个之后,就可以使用stack传递,当然你也可以都用stack传递,没人会说你违法的….

1.3.2 C语言部分

终于熬出头进入了c语言部分,稍稍有点激动,稳住,看fault.c@y:\1090\android\kernel\arch\arm\mm。你会发现里面有do_PrefetchAbort, do_ DataAbort。还有其他一些函数后面会提到。这里以do_ DataAbort举例:

这里写图片描述

先看其参数,addr就是r0, fsr是r1, 而且pregs就是通过stack传过来的。先执行inf->fn, inf是什么 ?看const struct fsr_info *inf = fsr_info + fsr_fs(fsr);, 你会发现它发现根据fualt status value(fsr变量)去相应的inf,每个fsr_info都有自己的fn,然后通过inf->fn调用。

这里写图片描述

很多fn都是do_bad,其实它只是个空函数,

这里写图片描述

这样它就可以执行inf->fn后面的语句也就是arm_notify_die了。

不过从测试当中发现,不管是data abort还是prefect abort,执行的基本上是fsr_info中的do_page_fault函数,因为一般的错误基本上是引用控制值,或者访问了没有访问权限的地址之类。

因此,我们转去看do_page_fault。

这里写图片描述

其实这个函数主要是处理缺页申请的。它是为虚拟内存管理所服务的。过程为这样子:当取的虚拟地址有效,但是其所对应的也不在当前物理内存,系统必须要从磁盘或者交换文件中装入内存。

对于缺页申请,这里就不描述了。当是use mode的exception时, __do_user_fault会call到force_sig_info发送信号给用户空间,让用户空间处理exception, 然后返回到之前说的汇编部分继续执行被exception打断前的事,当然并不一定是之前的process咯,因为return时会发生schedule嘛!

忘了一件重要事情:oops的log信息是怎么样的我们到现在还没看过呢!内容有点多,sorry,我也不想…

1>[   24.566404] Unable to handle kernel paging request at virtual address 1234
5678
<1>
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值