Transfer from http://www.xuebuyuan.com/2208550.html
In most processors after arm V4 and v4t, the position of the interrupt vector table can be two locations: one is 0x00000000 and the other is 0xffff0000. Can be controlled by the V-bit (bit[13]) in the CP15 coprocessor C1 register. The corresponding relationship between V and interrupt vector table is as follows:
v=0 ~ 0x00000000~0x0000001c
V=1 ~ 0xffff0000~0xffff001c
In arch/arm/mm/proc-arm920. S in:
. Type __arm920_setup, #function__arm920_setup: mov r0, #0MCR P15,0, R0, C7, C7 @ Invalidate i,d caches on V4 MCR P15,0, R0, C7, C10,4@ Drain Write buffer on v4#ifdef config_mmu MCR P15,0, R0, C8, C7 @ invalidate i,d tlbs on v4#endifADR R5, Arm920_crval Ldmia R5, {R5, R6} MRC P15,0, R0, C1, C0 @GetControl Register v4 BIC R0, R0, R5 Orr R0, R0, R6 mov pc, LR. Size __arm920_setup,.-__arm920_setup/*┊* r┊*. RVI Zfrs BLDP wcam┊*. 11 0001.. 11 0101┊*┊*/. Type Arm920_crval, #ObjectArm920_crval:crval Clear=0x00003f3f, mmuset=0x00003135, ucset=0x00001130
V (bit13) = 1, the interrupt vector table base address is 0xffff0000.
In Linux, the functions created by the vector table are:
INIT/MAIN.C-Start_kernel ()-Trap_init ().
void __init trap_init (void) { long vectors = config_vectors_base; ... memcpy (void *) vectors, __vectors_start, __vectors_end- __vectors_start); memcpy (void0x200, __stubs_start, __stubs_end- __stubs_start); ...}
In the 2.6.26 kernel, Config_vectors_base is initially set in the configuration files of each platform, such as Arch/arm/configs/s3c2410_defconfig:
config_vectors_base=0xffff0000
__vectors_end to __vectors_start is the exception vector table, located in ARCH/ARM/KERNEL/ENTRY-ARMV. S in:
. Globl __vectors_start__vectors_start:arm ( swi sys_error0 ) THUMB (svc #0 ) THUMB (NOP ) W (b) + stubs_offset w (LDR) + stubs_offset W (b) + stubs_offset W (b) + stubs_offset W (b) + Stubs_offset W (b) + Stubs_offset W (b) + stubs_offset . Globl __vectors_end__vectors_end:
__stubs_end to __stubs_start is the location of exception handling. Also located in file ARCH/ARM/KERNEL/ENTRY-ARMV. S in. Vector_und, Vector_pabt, VECTOR_IRQ, and Vector_fiq are among them.
Stubs_offset Value: . equ Stubs_offset, __vectors_start + 0x200-__stubs_start
When the assembler sees the B command, it converts the label to jump to the offset (±32m) write script relative to the current PC. From the code above you can see that the interrupt vector table and stubs have code removal, so if the interrupt vector table is still written as B Vector_irq, then the actual execution will not be able to jump to the VECTOR_IRQ after the move, because the script is written in the original offset, Therefore, the offset in the instruction code must be written as a moving. We irq_pc the IRQ entry address in the interrupt vector table before the move, the offset of the interrupt vector table is Irq_pc-vectors_start, and the Vector_irq offset in stubs is Vector_irq-stubs_start, These two offsets are constant before and after the move. After the removal of the Vectors_start at 0xffff0000, and Stubs_start in the 0xffff0200, so the removal of VECTOR_IRQ relative to the interrupt vector in the interrupt entry address offset is
200+ (Vector_irq-stubs_start)-(Irq_pc-vectors_star) = (VECTOR_IRQ-IRQ_PC) + Vectors_start+200-stubs_start
The value in parentheses is actually the VECTOR_IRQ that is written in the interrupt vector table, minus the irq_pc is done by the assembler , and the vectors_start+200-stubs_start behind it should be stubs_offset. Actually in ENTRY-ARMV. This is also defined in S.
Stubs_offset of the Linux anomaly system