Linux内核panic到ramdump基本流程
Linux内核空指针访问异常大致流程
插一下arm系统模式切换说明
/*
arm处理有很多模式,寄存器也有各个模式下专用和通用的寄存器
当从用户态等切入异常模式的时候,cpsr会发生切换,pc指针强制指向对应异常向量地址。
汇编代码vector_\name处理时会从异常模式切到svc模式,不然一些寄存器不是通用的,回不去。
vector_\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, spsrstr 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之后进入对应异常处理,同时保持异常之前模式下的寄存器,sp等信息,r0和lr在上面的代码已经保存到堆栈了。.macro usr_entryUNWIND(.fnstart )UNWIND(.cantunwind ) @ don't unwind the user spacesub sp, sp, #S_FRAME_SIZEARM( stmib sp, {r1 - r12} )之后处理完成时,恢复这些寄存器信息,跳转pc,回到异常之前。*/
先看下异常向量表的定义,感觉很绕
early_trap_init
#define CONFIG_VECTORS_BASE 0xffff0000
early_trap_init((void *)CONFIG_VECTORS_BASE);memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start);memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start);memcpy((void *)vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz);
先看一个宏定义vector_stub 参数是name mode第三个应该是为b指令手动设置返回地址的
这块的解释借用别人的用下https://www.cnblogs.com/yangjiguang/p/7629928.html
参考https://blog.csdn.net/forever_2015/article/details/53235716?locationNum=6&fps=1
.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, spsrstr 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@@ the branch table must immediately follow this code@and lr, lr, #0x0fTHUMB( adr r0, 1f )THUMB( ldr lr, [r0, lr, lsl #2] )mov r0, spARM( ldr lr, [pc, lr, lsl #2] )movs pc, lr @ branch to handler in SVC mode
ENDPROC(vector_\name)
.equ stubs_offset, __vectors_start + 0x200 - __stubs_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
__vectors_end:
__stubs_start:
....../** 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.......globl __stubs_end
__stubs_end:
最后会跳转到__dabt_svc-->dabt_helper
bl CPU_DABORT_HANDLER
ENTRY(v7_early_abort)mrc p15, 0, r1, c5, c0, 0 @ get FSRmrc p15, 0, r0, c6, c0, 0 @ get FAR/** V6 code adjusts the returned DFSR.* New designs should not need to patch up faults.*/#if defined(CONFIG_VERIFY_PERMISSION_FAULT)/** Detect erroneous permission failures and fix*/ldr r3, =0x40d @ On permission faultand r3, r1, r3cmp r3, #0x0dbne do_DataAbortmcr p15, 0, r0, c7, c8, 0 @ Retranslate FARisbmrc p15, 0, ip, c7, c4, 0 @ Read the PARand r3, ip, #0x7b @ On translation faultcmp r3, #0x0bbne do_DataAbortbic r1, r1, #0xf @ Fix up FSR FS[5:0]and ip, ip, #0x7eorr r1, r1, ip, LSR #1
#endifb do_DataAbort
ENDPROC(v7_early_abort)
do_DataAbort static struct fsr_info fsr_info[] = {/** The following are the standard ARMv3 and ARMv4 aborts. ARMv5* defines these to be "precise" aborts.*/{ do_bad, SIGSEGV, 0, "vector exception" },{ do_bad, SIGBUS, BUS_ADRALN, "alignment exception" },{ do_bad, SIGKILL, 0, "terminal exception" },{ do_bad, SIGBUS, BUS_ADRALN, "alignment exception" },{ do_bad, SIGBUS, 0, "external abort on linefetch" },{ do_translation_fault, SIGSEGV, SEGV_MAPERR, "section translation fault" },{ do_bad, SIGBUS, 0, "external abort on linefetch" },{ do_page_fault, SIGSEGV, SEGV_MAPERR, "page translation fault" },{ do_bad, SIGBUS, 0, "external abort on non-linefetch" },{ do_bad, SIGSEGV, SEGV_ACCERR, "section domain fault" },{ do_bad, SIGBUS, 0, "external abort on non-linefetch" },{ do_bad, SIGSEGV, SEGV_ACCERR, "page domain fault" },{ do_bad, SIGBUS, 0, "external abort on translation" },{ do_sect_fault, SIGSEGV, SEGV_ACCERR, "section permission fault" },{ do_bad, SIGBUS, 0, "external abort on translation" },{ do_page_fault, SIGSEGV, SEGV_ACCERR, "page permission fault" },/** The following are "imprecise" aborts, which are signalled by bit* 10 of the FSR, and may not be recoverable. These are only* supported if the CPU abort handler supports bit 10.*/{ do_bad, SIGBUS, 0, "unknown 16" },{ do_bad, SIGBUS, 0, "unknown 17" },{ do_bad, SIGBUS, 0, "unknown 18" },{ do_bad, SIGBUS, 0, "unknown 19" },{ do_bad, SIGBUS, 0, "lock abort" }, /* xscale */{ do_bad, SIGBUS, 0, "unknown 21" },{ do_bad, SIGBUS, BUS_OBJERR, "imprecise external abort" }, /* xscale */{ do_bad, SIGBUS, 0, "unknown 23" },{ do_bad, SIGBUS, 0, "dcache parity error" }, /* xscale */{ do_bad, SIGBUS, 0, "unknown 25" },{ do_bad, SIGBUS, 0, "unknown 26" },{ do_bad, SIGBUS, 0, "unknown 27" },{ do_bad, SIGBUS, 0, "unknown 28" },{ do_bad, SIGBUS, 0, "unknown 29" },{ do_bad, SIGBUS, 0, "unknown 30" },{ do_bad, SIGBUS, 0, "unknown 31" },
};//硬件断点异常捕获hook_fault_code(FAULT_CODE_DEBUG, hw_breakpoint_pending, SIGTRAP,TRAP_HWBKPT, "watchpoint debug exception");if (!inf->fn(addr, fsr & ~FSR_LNX_PF, regs)) 这里根据异常的标志,找到对应的hook函数执行。do_translation_faultdo_page_fault__do_page_fault__do_kernel_faultdie("Oops", regs, fsr);if (in_interrupt())panic("Fatal exception in interrupt");if (panic_on_oops)panic("Fatal exception");if (ret != NOTIFY_STOP)do_exit(SIGSEGV); void panic(const char *fmt, ...)
__die dump线程stack和寄存器
local_irq_disable(); 锁中断
dump_stack(); 打印堆栈,防止二次panic
if (panic_timeout != 0) { 选择是否重启设备/** This will not be a clean reboot, with everything* shutting down. But if there is a chance of* rebooting the system it will be rebooted.*/emergency_restart();}
不重启进入ramdump流程
ramdump_entry()dump出ap的ddr空间,需要的设备寄存器信息,通过usb的内部dma控制器写出去
应用coredump参考https://blog.csdn.net/omnispace/article/details/77600721
处理器提供专门断点寄存器保存一个地址,处理器在执行程序过程,会不断去匹配,可以设置成不同的模式来触发程序中断,如执行到这个地址,读这个地址或写这个地址, 并且可以设置长度,按8位,16位,或32位来触发。和软件断点比,好处是可以支持读写断点,程序断点不需要改写内存,可以设在ROM中,在虚拟地址映射前也可设置等等。
软硬件断点参考https://blog.csdn.net/sxw1002/article/details/77169610
http://www.360doc.com/content/17/0823/11/17136639_681458868.shtml
Linux内核panic到ramdump基本流程相关推荐
- linux arm panic,ARM Linux 内核 panic 之cache 一致性 ——Cortex-A9多核cache和TLB一致性广播...
ARM Linux 内核 panic 之cache 一致性 --Cortex-A9多核cache和TLB一致性广播 Cortex-A9的多喝CPU可以接收和执行一致性广播操作,当其使能并处于SMP模式 ...
- Linux内核网络数据包处理流程
Linux内核网络数据包处理流程 from kernel-4.9: 0. Linux内核网络数据包处理流程 - 网络硬件 网卡工作在物理层和数据链路层,主要由PHY/MAC芯片.Tx/Rx FIFO. ...
- ARM Linux 内核 panic 之cache 一致性 ——cci-400 cache一致互联
ARM Linux 内核 panic 之cache 一致性 --cci-400 cache一致互联 CCI-400 集合了互联和一致性功能,有 2 个 ACE slave 接口和 3 个 ACE-Li ...
- linux内核panic
1. Linux Kernel Panic的产生的原因 panic是英文中是惊慌的意思,Linux Kernel panic正如其名,linux kernel不知道如何走了,它会尽可能把它此时能获取的 ...
- linux内核那些事之mmap_region流程梳理
承接<linux内核那些事之mmap>,mmap_region()是申请一个用户进程虚拟空间 并根据匿名映射或者文件映射做出相应动作,是实现mmap关键函数,趁这几天有空闲时间 整理下mm ...
- linux内核 panic,linux 内核 panic
Linux内核栈溢出(stack overflow)问题 最近一段时间在设计和开发一个Linux内核模块,进入到最后的正确性测试与稳定性测试阶段.在这个阶段发现了一个非常有意思的问题,堆栈溢出(sta ...
- 空指针引用,导致linux内核panic(重启)
这个bug搞了我整整两天,看了好多贴,调试了好多遍,终于解决了:复盘记录下. 先贴上重启打印日志. 1.重启打印日志 PC is at 0x0 LR is at devinet_ioctl+0x31c ...
- 一文讲解Linux内核中根文件系统挂载流程
根文件系统的概念 根文件系统是控制权从linux内核转移到用户空间的一个桥梁.linux内核就类似于一个黑匣子,只向用户提供各种功能的接口,但是功能的具体实现不可见,用户程序通过对这些功能接口的不同整 ...
- i386 Linux内核进入保护模式引导流程
在系统引导过程中,Bootloader将内核镜像加载到内存后,并将控制权转交给内核 ,通过长转移指令跳转到入口startup_32. 实际上进入startup_32入口前,CPU已经处于了 ...
- linux程序获取透传参数,Linux内核中TCP SACK处理流程分析
frankzfz2014-07-27 17:32 demo121:frankzfz您好: 我想请教一个问题,就是将写好的GenericApp项目(没有配置工具),我加入zigbee协议栈的配置工具后还 ...
最新文章
- python 爬取svg数据_python处理svg数据
- Best Time to Buy and Sell Stock II
- 刚学会深拷贝一个对象,学妹却问我怎么深拷贝一个图
- android将矩阵转换成字节数组,android-使用OpenGL矩阵转换将纹理从“ 1D”映...
- Linux常用命令——cat,tac
- Winform获取应用程序的当前路径的方法集合,具体如下,值得收藏
- Caffe上训练使用自己的数据
- Codeforces Round #215 (Div. 2) D. Sereja ans Anagrams
- 基于 KIF 的 iOS UI 自动化测试和持续集成
- java 字符串的编码与C#的区别
- Vivado设计流程(一)新建工程
- stm32是以c语言来编程吗,stm32用什么语言编程
- 计算机毕业设计之java+javaweb的房屋出租系统
- mousewheel事件
- 怀旧版大脚插件未能从服务器,魔兽世界怀旧服大脚插件怎么用 大脚插件安装使用攻略...
- c++文件的读取和写入
- 基于Rust-vmm实现Kubernetes运行时
- 关于 石墨文档客户端 的案例分析
- 电容笔和Apple pencil的区别?适合ipad画画的电容笔推荐
- 使用ffmpeg对mp3格式的音频文件类型转换、截取及合并