Wei Dongshan uboot_kernel_root file system study notes 5.6-Lesson 005_Character Device Driver_Section 006_Key Driver of Interrupt Mode of Character Device Driver_Linux Exception Handling Structure

A Linux exception handling architecture/framework

General exception handling mechanism
Insert picture description here

Two linux kernel for abnormal settings (P397)

The summary of the following analysis:
(1) __vector_startCopy the code at the start address of the exception vector to the vectorsaddress
(2) Once an interrupt occurs, it will jump to the vector_irqbeginning code; the code is implemented in the form of a macro
(3) Macro: return from calculation Address -> save the scene -> call the c function of interrupt processing -> restore the scene

  1. The trap_init function analysis
    Insert picture description here
    Insert picture description here
    code is as follows:
    Insert picture description here
    Among them: where:,
    vectors=0xffff0000
    __vectors_start=异常代码存储地址this code is a jump instruction,
    for example
    LINE1064:出现未定义的指令
    LINE1069:中断跳转指令
    Insert picture description here
  2. Tracking vector_undvariables
    Continue to track the vector_undvariables in the figure above , but we can’t find the code even though we searched through the code...actually the variable is a macro definition. (For detailed description, please refer to: Vector_stub Macro Analysis of Linux Exception System )
    The code in the figure below is vector_stuba reference to the macro :
    Insert picture description here
    the figure below is vector_stubthe definition of the macro in the code :
    Insert picture description here
    Insert picture description here
  3. Tracking vector_irqvariables
    The following code is vector_stuba reference to the macro .
    Insert picture description here
    According to the macro definition, you can get the following actual code:
/*
 * Interrupt dispatcher
 */
	/*
		vector_stub	irq, IRQ_MODE, 4
	*/
		/*
		.	macro	vector_stub, name, mode, correction=0
			参数赋值:
			name=irq
			mode=IRQ_MODE
			correction=4
		*/
	.align	5

vector_irq:
	@计算返回地址,与单片机程序一致
	sub	lr, lr, #4

	@
	@ 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)
	msr	spsr_cxsf, r0

	@
	@ the branch table must immediately follow this code
	@向下面的列表跳转
	and	lr, lr, #0x0f
	mov	r0, sp
	ldr	lr, [pc, lr, lsl #2]
	movs	pc, lr			@ branch to handler in SVC mode

	.long	__irq_usr			@  0  (USR_26 / USR_32)-用户模式下发生中断的时候跳到这里来
	.long	__irq_invalid			@  1  (FIQ_26 / FIQ_32)
	.long	__irq_invalid			@  2  (IRQ_26 / IRQ_32)
	.long	__irq_svc			@  3  (SVC_26 / SVC_32)-管理模式下发生中断的时候跳到这里来
	.long	__irq_invalid			@  4
	.long	__irq_invalid			@  5
	.long	__irq_invalid			@  6
	.long	__irq_invalid			@  7
	.long	__irq_invalid			@  8
	.long	__irq_invalid			@  9
	.long	__irq_invalid			@  a
	.long	__irq_invalid			@  b
	.long	__irq_invalid			@  c
	.long	__irq_invalid			@  d
	.long	__irq_invalid			@  e
	.long	__irq_invalid			@  f
  1. Track the __irq_usrcorresponding code
__irq_usr:
	usr_entry

#ifdef CONFIG_TRACE_IRQFLAGS
	bl	trace_hardirqs_off
#endif
	get_thread_info tsk
#ifdef CONFIG_PREEMPT
	ldr	r8, [tsk, #TI_PREEMPT]		@ get preempt count
	add	r7, r8, #1			@ increment it
	str	r7, [tsk, #TI_PREEMPT]
#endif

	irq_handler
#ifdef CONFIG_PREEMPT
	ldr	r0, [tsk, #TI_PREEMPT]
	str	r8, [tsk, #TI_PREEMPT]
	teq	r0, r7
	strne	r0, [r0, -r0]
#endif
#ifdef CONFIG_TRACE_IRQFLAGS
	bl	trace_hardirqs_on
#endif

	mov	why, #0
	b	ret_to_user

	.ltorg

	.align	5

Which usr_entryis also a macro, defined as follows:

//功能:保存现场
	.macro	usr_entry
	sub	sp, sp, #S_FRAME_SIZE
	stmib	sp, {r1 - r12}

	ldmia	r0, {r1 - r3}
	add	r0, sp, #S_PC		@ here for interlock avoidance
	mov	r4, #-1			@  ""  ""     ""        ""

	str	r1, [sp]		@ save the "real" r0 copied
					@ from the exception stack

#if __LINUX_ARM_ARCH__ < 6 && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG)
#ifndef CONFIG_MMU
#warning "NPTL on non MMU needs fixing"
#else
	@ make sure our user space atomic helper is aborted
	cmp	r2, #TASK_SIZE
	bichs	r3, r3, #PSR_Z_BIT
#endif
#endif

	@
	@ We are now ready to fill in the remaining blanks on the stack:
	@
	@  r2 - lr_<exception>, already fixed up for correct return/restart
	@  r3 - spsr_<exception>
	@  r4 - orig_r0 (see pt_regs definition in ptrace.h)
	@
	@ Also, separately save sp_usr and lr_usr
	@
	stmia	r0, {r2 - r4}
	stmdb	r0, {sp, lr}^

	@
	@ Enable the alignment trap while in kernel mode
	@
	alignment_trap r0

	@
	@ Clear FP to mark the first stack frame
	@
	zero_fp
	.endm

Among them, it irq_handleris also a macro, defined as follows

/*
 * Interrupt handling.  Preserves r7, r8, r9
 */
	.macro	irq_handler
	get_irqnr_preamble r5, lr
1:	get_irqnr_and_base r0, r6, r5, lr
	movne	r1, sp
	@
	@ routine called with r0 = irq number, r1 = struct pt_regs *
	@最终调用了函数asm_do_IRQ
	adrne	lr, 1b
	bne	asm_do_IRQ
	...
	.endm

Then, the trace function asm_do_IRQis the interrupt handler function
Insert picture description here

Guess you like

Origin blog.csdn.net/xiaoaojianghu09/article/details/104254624