[Kernel_exception2] data abort Unable to handle kernel paging request

一、概序:

    data abort 类型的KE比较常见,触发此KE的原因是,用户空间使用的地址都是虚拟地址,此地址经过MMU的负复杂

的页表映射到物理地址,当其中发生一些异常导致此虚拟地址无法访问到对应的物理地址时,就会通过报对应的BUG

使系统重启,此地址有可能已经被其他进程访问,也有可能因为部分硬件问题导致对应的地址出现翻转导致无法访问。

二、案例:

(1)硬件bitflip的KE:

    堆栈信息如下:

[20512.223175] -(3)[30488:kworker/u8:2]Unable to handle kernel paging request at virtual address 4156106c
[20512.223201] -(3)[30488:kworker/u8:2]pgd = c0003000
[20512.223207] [4156106c] *pgd=80000040005003, *pmd=00000000
[20512.223223] -(3)[30488:kworker/u8:2]Internal error: Oops: 205 [#1] PREEMPT SMP ARM
[20512.223230] -(3)[30488:kworker/u8:2]Kernel Offset: disabled
[20513.223253] -(3)[30488:kworker/u8:2]PC is at set_task_cpu+0xd8/0x23c
[20513.223262] -(3)[30488:kworker/u8:2]LR is at walt_fixup_busy_time+0x1f0/0x4ac
[20513.223268] -(3)[30488:kworker/u8:2]pc : [<c02596f0>]    lr : [<c028f46c>]    psr: 60070093

    使用GDB通过解析对应的符号表vmlinux可以看到堆栈如下:

(gdb) bt
#0  0xc02596f0 in set_task_rq (cpu=<optimized out>, p=<optimized out>)
    at /home/buildsrv-108/jenkins/workspace/PY_UNIFIED_VERSION_BUILD/code/kernel-4.9/kernel/sched/sched.h:1061
#1  __set_task_cpu (cpu=<optimized out>, p=<optimized out>)
    at /home/buildsrv-108/jenkins/workspace/PY_UNIFIED_VERSION_BUILD/code/kernel-4.9/kernel/sched/sched.h:1084
#2  set_task_cpu (p=0xdbcd4000, new_cpu=0) at /home/buildsrv-108/jenkins/workspace/PY_UNIFIED_VERSION_BUILD/code/kernel-4.9/kernel/sched/core.c:1314
#3  0xc025a648 in try_to_wake_up (p=0xdbcd4000, state=<optimized out>, wake_flags=<optimized out>)
    at /home/buildsrv-108/jenkins/workspace/PY_UNIFIED_VERSION_BUILD/code/kernel-4.9/kernel/sched/core.c:2214
#4  0xc025a914 in wake_up_process (p=<optimized out>)
    at /home/buildsrv-108/jenkins/workspace/PY_UNIFIED_VERSION_BUILD/code/kernel-4.9/kernel/sched/core.c:2294
#5  0xc0240bdc in wake_up_worker (pool=<optimized out>)
    at /home/buildsrv-108/jenkins/workspace/PY_UNIFIED_VERSION_BUILD/code/kernel-4.9/kernel/workqueue.c:837
#6  process_one_work (worker=0xdbea5080, work=0xd5c5b434)
    at /home/buildsrv-108/jenkins/workspace/PY_UNIFIED_VERSION_BUILD/code/kernel-4.9/kernel/workqueue.c:2076
#7  0xc0241998 in worker_thread (__worker=0xdbea5080)
    at /home/buildsrv-108/jenkins/workspace/PY_UNIFIED_VERSION_BUILD/code/kernel-4.9/kernel/workqueue.c:2225

    对应的set_task_cpu代码如下:

void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
{
    ......
	if (task_cpu(p) != new_cpu) {
		if (p->sched_class->migrate_task_rq)
			p->sched_class->migrate_task_rq(p);
		p->se.nr_migrations++;
		perf_event_task_migrate(p);

		walt_fixup_busy_time(p, new_cpu);
	}

	__set_task_cpu(p, new_cpu);
}

    对应帧的反汇编代码如下:

(gdb) f 3
#3  0xc025a648 in try_to_wake_up (p=0xdbcd4000, state=<optimized out>, wake_flags=<optimized out>)
    at /home/buildsrv-108/jenkins/workspace/PY_UNIFIED_VERSION_BUILD/code/kernel-4.9/kernel/sched/core.c:2214
2214	in /home/buildsrv-108/jenkins/workspace/PY_UNIFIED_VERSION_BUILD/code/kernel-4.9/kernel/sched/core.c

(gdb) i reg
r0             0xdbcd4080	3687661696
r1             0xdf79c900	3749300480
r2             0x4094d	264525
r3             0x4094d	264525
r4             0xdbcd4000	3687661568
r5             0xdbcd4644	3687663172
r6             0xc1404548	3242214728

gdb) disas
Dump of assembler code for function try_to_wake_up:

   0xc025a62c <+552>:    beq    0xc025a648 <try_to_wake_up+580>
   0xc025a630 <+556>:    ldr    r3, [r11, #-56]    ; 0x38
   0xc025a634 <+560>:    mov    r1, r10
   0xc025a638 <+564>:    mov    r0, r4      //将r4的值传给r0
   0xc025a63c <+568>:    orr    r3, r3, #4
   0xc025a640 <+572>:    str    r3, [r11, #-56]    ; 0x38
   0xc025a644 <+576>:    bl    0xc0259618 <set_task_cpu> //跳转到set_task_cpu函数中
=> 0xc025a648 <+580>:    movw    r3, #17828    ; 0x45a4

    从上面汇编代码可以看出r4的值应该和r0相等(也就是代码中p的值),但时间r0 的倒数第四位翻转为1,使访问的

地址发生变化:dbcd4000 ->dbcd4080,从此点可以看出是硬件Bitflip导致的KE,如果问题概率比较高的话,可

以通过交叉CPU/memory来验证此问题。

 

(2)踩内存触发的KE:

    所谓踩内存,意思就是将要使用的这块内存已经其他地方非法占有,非法占有的方式有数组越界/use after free等,下面

看一个具体的实例,其中kernel log打印出来的堆栈信息如下:

[  192.960966]  (0)[1410:Signal Catcher]Unable to handle kernel paging request at virtual address 880646e1
[  192.960998]  (0)[1410:Signal Catcher]pgd = d06f4000
[  192.961013] [880646e1] *pgd=00000000
[  193.961221] -(0)[1410:Signal Catcher]PC is at find_vma+0x54/0x80
[  193.961233] -(0)[1410:Signal Catcher]LR is at 0xd18ac3d8

    通过GDB加载vmlinux解析出如下堆栈:

(gdb) bt
#0  find_vma (mm=0xdab73180, addr=3040309248) at /home/buildsrv-96/jenkins/workspace/UNIFIED_VERSION_BUILD-2/code/kernel-3.18/mm/mmap.c:2099
#1  0xc01171f8 in __do_page_fault (tsk=<optimized out>, flags=<optimized out>, fsr=<optimized out>, addr=<optimized out>, mm=<optimized out>)
    at /home/buildsrv-96/jenkins/workspace/UNIFIED_VERSION_BUILD-2/code/kernel-3.18/arch/arm/mm/fault.c:232
#2  do_page_fault (addr=0, fsr=3040309248, regs=0xd0001fb0)
    at /home/buildsrv-96/jenkins/workspace/UNIFIED_VERSION_BUILD-2/code/kernel-3.18/arch/arm/mm/fault.c:314
#3  0xc01003dc in do_DataAbort (addr=0, fsr=23, regs=0xd0001fb0)

    看到第0帧的addr = 3040309248就可以明显发现很奇怪,一般不会出现这种异常的addr,下面接着分析,

(gdb) f 2
#2  do_page_fault (addr=0, fsr=3040309248, regs=0xd0001fb0)
    at /home/buildsrv-96/jenkins/workspace/UNIFIED_VERSION_BUILD-2/code/kernel-3.18/arch/arm/mm/fault.c:314
314	in /home/buildsrv-96/jenkins/workspace/UNIFIED_VERSION_BUILD-2/code/kernel-3.18/arch/arm/mm/fault.c

    切到第二帧的时候,可以看到addr = 0,并且在函数的传递过程中,addr的值并没有发生变化,这里可以看出addr

有被踩的可能,下面看汇编代码也可以很明显的看出addr被踩:

(gdb) disas
Dump of assembler code for function do_page_fault:
   0xc0117130 <+0>:	mov	r12, sp
   0xc0117134 <+4>:	push	{r4, r5, r6, r7, r8, r9, r10, r11, r12, lr, pc}
   0xc0117138 <+8>:	sub	r11, r12, #4
   0xc01171f0 <+192>:	mov	r0, r5
   0xc01171f4 <+196>:	bl	0xc0222e1c <find_vma>
=> 0xc01171f8 <+200>:	subs	r9, r0, #0   //r9 = r0 - 0=0
   0xc01171fc <+204>:	beq	0xc01173b8 <do_page_fault+648>
   0xc0117200 <+208>:	ldr	r3, [r9]
   0xc0117204 <+212>:	cmp	r8, r3
   0xc0117208 <+216>:	bcc	0xc0117390 <do_page_fault+608>

(gdb) i reg
r0             0x0	0
r1             0xb5377000	3040309248
r2             0xff000b2c	4278192940
r3             0x880646ed	2282112749
r4             0xd0001fb0	3489669040
r5             0xdab73180	3669438848
r6             0xd18ac100	3515531520
r7             0x17	23
r8             0xb5377000	3040309248
r9             0xb5377000	3040309248
r10            0xdab731b8	3669438904

    上面汇编代码中r9中的值应该为0,但栈打印出来的是0xb5377000 = 3040309248,怀疑这个地址被踩了导致出现

的问题。对于踩内存的问题,需要打开slub或者kasan的debug机制来调试此类问题,当出现踩内存时可以将对应踩的

位置表示出来,具体方法可以参考博客:内存管理三 内核内存检测KASAN

 

作者:frank_zyp 
您的支持是对博主最大的鼓励,感谢您的认真阅读。 
本文无所谓版权,欢迎转载。   

### 回答1: xil_dataaborthandler是一个函数,用于处理数据传输中断的情况。当数据传输过程中出现异常情况,如数据传输超时、数据传输错误等,xil_dataaborthandler函数会被调用,用于处理这些异常情况,保证数据传输的正确性和稳定性。 ### 回答2: xil_dataaborthandler是一个Xilinx Vivado Design Suite中的函数,用于处理FPGA设计中的数据终止问题。在设计中,FPGA板上的IP Core会处理数据流并产生输出数据,但是有时候由于各种原因,数据流可能会被提前终止。这种终止可能是由于输入数据的失真、突变或者在处理过程中发生的错误等。 在这种情况下,xil_dataaborthandler函数会被调用,来处理这个数据终止问题。这个函数会停止当前的IP Core运行,并通过FIFO通道发送一个终止信号,告诉其他的IP Core和设备,该数据流已经被终止了,需要清除相关状态。这种终止信号可以帮助其他设计组件及时清理数据并停止运行,从而避免数据错误传导、资源浪费和系统崩溃等问题。 xil_dataaborthandler函数还可以在IP Core运行过程中,检查数据是否符合特定的输入格式,如数据长度、数据类型等。如果数据不符合要求,这个函数也会调用终止信号来停止数据流的处理。这种检查可以在设计早期进行,以确保输入数据的正确性,避免IP Core和设备的异常终止。 因此,在FPGA设计中,xil_dataaborthandler函数非常重要,可以帮助保证数据流的正确性和设计的稳定性,提高系统的可靠性和效率。 ### 回答3: xil_dataaborthandler是一个在Xilinx芯片中用于处理数据异常中止的函数或者说是中断处理函数。在进行FPGA设计或者嵌入式开发时,如果出现数据异常中止的情况,这个函数会被调用来处理并恢复中止状态。 当数据传输过程中发生异常中止,比如DMA传输时读写地址超出范围,从外部接口读取的数据出错等情况,就会触发该函数。这个函数会检测中止类型,并进行相应的处理操作。处理完成后,系统会继续运行下一条指令,而不会导致整个系统中断。 需要注意的是,虽然xil_dataaborthandler可以帮助我们处理数据异常中止状态,但我们还需要尽可能地减少异常中止的发生。为此,可以合理设计硬件电路,严格控制软件流程等,降低异常中止的概率,提高系统的性能和可靠性。 总之,xil_dataaborthandler是一个在FPGA设计和嵌入式开发中非常重要的函数,它能够有效地处理数据异常中止状态,保证系统的可靠性和稳定性。同时,我们需要采取措施减少异常中止的发生,避免不必要的麻烦和损失。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值