1. 程式人生 > >Linux核心panic到ramdump基本流程

Linux核心panic到ramdump基本流程

Linux核心空指標訪問異常大致流程

插一下arm系統模式切換說明
/*
arm處理有很多模式,暫存器也有各個模式下專用和通用的暫存器
當從使用者態等切入異常模式的時候,cpsr會發生切換,pc指標強制指向對應異常向量地址。
彙編程式碼vector_\name處理時會從異常模式切到svc模式,不然一些暫存器不是通用的,回不去。
vector_\name:
    .if \correction
    sub    lr, lr, #\correction
    .endif

    @
    @ Save r0, lr_<exception> (parent PC) and spsr_<exception>
    @ (parent CPSR)
    @
    stmia    sp, {r0, lr}        @ save r0, lr
    mrs    lr, spsr
    str    lr, [sp, #8]        @ save spsr

    @
    @ Prepare for SVC32 mode.  IRQs remain disabled.
    @
    mrs    r0, cpsr
    eor    r0, r0, #(\mode ^ SVC_MODE | PSR_ISETSTATE)
    msr    spsr_cxsf, r0

之後進入對應異常處理,同時保持異常之前模式下的暫存器,sp等資訊,r0和lr在上面的程式碼已經儲存到堆疊了。
     .macro    usr_entry
 UNWIND(.fnstart    )
 UNWIND(.cantunwind    )    @ don't unwind the user space
    sub    sp, sp, #S_FRAME_SIZE
 ARM(    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	5

vector_\name:
	.if \correction
	sub	lr, lr, #\correction
	.endif

	@
	@ Save r0, lr_<exception> (parent PC) and spsr_<exception>
	@ (parent CPSR)
	@
	stmia	sp, {r0, lr}		@ save r0, lr
	mrs	lr, spsr
	str	lr, [sp, #8]		@ save spsr

	@
	@ Prepare for SVC32 mode.  IRQs remain disabled.
	@
	mrs	r0, cpsr
	eor	r0, r0, #(\mode ^ SVC_MODE | PSR_ISETSTATE)
	msr	spsr_cxsf, r0

	@
	@ the branch table must immediately follow this code
	@
	and	lr, lr, #0x0f
 THUMB(	adr	r0, 1f			)
 THUMB(	ldr	lr, [r0, lr, lsl #2]	)
	mov	r0, sp
 ARM(	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_offset
	W(ldr)	pc, .LCvswi + stubs_offset
	W(b)	vector_pabt + stubs_offset
	W(b)	vector_dabt + stubs_offset
	W(b)	vector_addrexcptn + stubs_offset
	W(b)	vector_irq + stubs_offset
	W(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 FSR
	mrc	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 fault
	and	r3, r1, r3
	cmp	r3, #0x0d
	bne	do_DataAbort

	mcr	p15, 0, r0, c7, c8, 0   	@ Retranslate FAR
	isb
	mrc	p15, 0, ip, c7, c4, 0   	@ Read the PAR
	and	r3, ip, #0x7b   		@ On translation fault
	cmp	r3, #0x0b
	bne	do_DataAbort
	bic	r1, r1, #0xf			@ Fix up FSR FS[5:0]
	and	ip, ip, #0x7e
	orr	r1, r1, ip, LSR #1
#endif

	b	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_fault
    do_page_fault
    __do_page_fault
    __do_kernel_fault
    die("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