http://blog.chinaunix.net/uid-28247266-id-3415930.html转载自
内核部分:内核版本linux 2.6.22.6
点击(此处)折叠或打开
- start_kernel()
- ...
-
trap_init()
- ...
点击(此处)折叠或打开
- void __init trap_init(void)
- {
-
unsigned long vectors = CONFIG_VECTORS_BASE; //CONFIG_VECTORS_BASE = 0XFFFF0000 -
extern char __stubs_start[], __stubs_end[];
-
extern char __vectors_start[], __vectors_end[];
-
extern char __kuser_helper_start[], __kuser_helper_end[];
-
int kuser_sz = __kuser_helper_end - __kuser_helper_start;
-
-
/*
-
* Copy the vectors, stubs and kuser helpers (in entry-armv.S)
-
* into the vector page, mapped at 0xffff0000, and ensure these -
* are visible to the instruction stream. -
*/
-
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); -
... - }
点击(此处)折叠或打开
- .LCvswi:
- .word vector_swi
-
- .globl __stubs_end
- __stubs_end:
-
- .equ stubs_offset, __vectors_start + 0x200 - __stubs_start
-
- .globl __vectors_start
- __vectors_start:
-
swi SYS_ERROR0 -
b vector_und + stubs_offset -
ldr pc, .LCvswi + stubs_offset -
b vector_pabt + stubs_offset -
b vector_dabt + stubs_offset -
b vector_addrexcptn + stubs_offset -
b vector_irq + stubs_offset -
b vector_fiq + stubs_offset -
- .globl __vectors_end
- __vectors_end:
点击(此处)折叠或打开
- .macro vector_stub, name, mode, correction=0
- .align 5
-
- vector_\name:
- .if \correction
- sub lr, lr, #\correction
- .endif
-
- @
- @ Save r0, lr_ (parent PC) and spsr_
- @ (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
- .endm
点击(此处)折叠或打开
- vector_stub irq, IRQ_MODE, 4
-
- .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
点击(此处)折叠或打开
- __irq_svc:
- svc_entry
-
- #ifdef CONFIG_TRACE_IRQFLAGS
- bl trace_hardirqs_off
- #endif
- #ifdef CONFIG_PREEMPT
- get_thread_info tsk
- 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_FLAGS] @ get flags
- tst r0, #_TIF_NEED_RESCHED
- blne svc_preempt
- preempt_return:
- ldr r0, [tsk, #TI_PREEMPT] @ read preempt value
- str r8, [tsk, #TI_PREEMPT] @ restore preempt count
- teq r0, r7
- strne r0, [r0, -r0] @ bug()
- #endif
- ldr r0, [sp, #S_PSR] @ irqs are already disabled
- msr spsr_cxsf, r0
- #ifdef CONFIG_TRACE_IRQFLAGS
- tst r0, #PSR_I_BIT
- bleq trace_hardirqs_on
- #endif
- ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
点击(此处)折叠或打开
- .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 * - @
- adrne lr, 1b
- bne asm_do_IRQ