📄 entry-armv.s
字号:
/* * linux/arch/arm/lib/traps-arm6.S * * Copyright (C) 1996 Russell King. * ARM700 fix by Matthew Godbolt (linux-user@willothewisp.demon.co.uk) * * Low-level vector interface routines * * Note: there is a StrongARM bug in the STMIA rn, {regs}^ instruction that causes * it to save wrong values... Be aware! */#include <linux/autoconf.h>#include <asm/assembler.h>#include <asm/errno.h>#include <asm/hardware.h>#define current current_set#ifdef IOC_BASE/* IOC / IOMD based hardware */ .equ ioc_base_high, IOC_BASE & 0xff000000 .equ ioc_base_low, IOC_BASE & 0x00ff0000 .macro disable_fiq mov r12, #ioc_base_high .if ioc_base_low orr r12, r12, #ioc_base_low .endif strb r12, [r12, #0x38] @ Disable FIQ register .endm .macro get_irqnr_and_base, irqnr, base mov r4, #ioc_base_high @ point at IOC .if ioc_base_low orr r4, r4, #ioc_base_low .endif ldrb \irqnr, [r4, #0x24] @ get high priority first adr \base, irq_prio_h teq \irqnr, #0#ifdef IOMD_BASE ldreqb \irqnr, [r4, #0x1f4] @ get dma adreq \base, irq_prio_d teqeq \irqnr, #0#endif ldreqb \irqnr, [r4, #0x14] @ get low priority adreq \base, irq_prio_l .endm/* * Interrupt table (incorporates priority) */ .macro irq_prio_tableirq_prio_l: .byte 0, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 .byte 4, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 .byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 .byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 .byte 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3 .byte 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3 .byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 .byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7#ifdef IOMD_BASEirq_prio_d: .byte 0,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 .byte 20,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 .byte 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 .byte 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 .byte 23,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 .byte 23,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 .byte 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 .byte 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16#endifirq_prio_h: .byte 0, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10 .byte 12, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10 .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 .byte 14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10 .byte 14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10 .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 .byte 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10 .byte 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10 .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 .byte 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10 .byte 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10 .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 .endm#elif defined(CONFIG_ARCH_EBSA110) .macro disable_fiq .endm .macro get_irqnr_and_base, irqnr, base mov r4, #0xf3000000 ldrb \irqnr, [r4] @ get interrupts adr \base, irq_prio_ebsa110 .endm .macro irq_prio_tableirq_prio_ebsa110: .byte 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 1, 1, 2, 2, 2, 2 .byte 4, 4, 1, 1, 2, 2, 2, 2, 3, 3, 1, 1, 2, 2, 2, 2 .byte 5, 5, 1, 1, 2, 2, 2, 2, 3, 3, 1, 1, 2, 2, 2, 2 .byte 5, 5, 1, 1, 2, 2, 2, 2, 3, 3, 1, 1, 2, 2, 2, 2 .byte 6, 6, 6, 6, 2, 2, 2, 2, 3, 3, 6, 6, 2, 2, 2, 2 .byte 6, 6, 6, 6, 2, 2, 2, 2, 3, 3, 6, 6, 2, 2, 2, 2 .byte 6, 6, 6, 6, 2, 2, 2, 2, 3, 3, 6, 6, 2, 2, 2, 2 .byte 6, 6, 6, 6, 2, 2, 2, 2, 3, 3, 6, 6, 2, 2, 2, 2 .byte 7, 0, 1, 1, 2, 2, 2, 2, 3, 3, 1, 1, 2, 2, 2, 2 .byte 4, 4, 1, 1, 2, 2, 2, 2, 3, 3, 1, 1, 2, 2, 2, 2 .byte 5, 5, 1, 1, 2, 2, 2, 2, 3, 3, 1, 1, 2, 2, 2, 2 .byte 5, 5, 1, 1, 2, 2, 2, 2, 3, 3, 1, 1, 2, 2, 2, 2 .byte 6, 6, 6, 6, 2, 2, 2, 2, 3, 3, 6, 6, 2, 2, 2, 2 .byte 6, 6, 6, 6, 2, 2, 2, 2, 3, 3, 6, 6, 2, 2, 2, 2 .byte 6, 6, 6, 6, 2, 2, 2, 2, 3, 3, 6, 6, 2, 2, 2, 2 .byte 6, 6, 6, 6, 2, 2, 2, 2, 3, 3, 6, 6, 2, 2, 2, 2 .endm#elif defined(CONFIG_ARCH_TRIO) .macro disable_fiq .endm .macro get_irqnr_and_base, irqnr, base ldr r4, =AIC_IVR ldr \irqnr, [r4] @ get interrupts bic \irqnr, \irqnr, #0xffffffe0 adr \base, irq_prio_trio .endm .macro irq_prio_tableirq_prio_trio: .byte 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 .endm#else#error Unknown architecture#endif .text@ Offsets into task structure@ ---------------------------@#define STATE 0#define COUNTER 4#define PRIORITY 8#define SIGNAL 12#define BLOCKED 16#define FLAGS 20#define ERRNO 24#define PF_TRACESYS 0x20@ Bad Abort numbers@ -----------------@#define BAD_PREFETCH 0#define BAD_DATA 1#define BAD_ADDREXCPTN 2#define BAD_IRQ 3#define BAD_UNDEFINSTR 4@ Number of syscalls accepted@#define NSYS_CALL 142@ OS version number used in SWIs@ RISC OS is 0@ RISC iX is 8@#define OS_NUMBER 9@@ Stack format (ensured by USER_* and SVC_*)@#define S_FRAME_SIZE 72#define S_OLD_R0 68#define S_PSR 64#define S_PC 60#define S_LR 56#define S_SP 52#define S_IP 48#define S_FP 44#define S_R10 40#define S_R9 36#define S_R8 32#define S_R7 28#define S_R6 24#define S_R5 20#define S_R4 16#define S_R3 12#define S_R2 8#define S_R1 4#define S_R0 0#include "../lib/constants.h" .global _ret_from_sys_call,ret_from_sys_call/* *================================================================================================ * Low-level interface code *------------------------------------------------------------------------------------------------ * Trap initialisation *------------------------------------------------------------------------------------------------ * * Note - FIQ code has changed. The default is a couple of words in 0x1c, 0x20 * that call _unexp_fiq. Nowever, we now copy the FIQ routine to 0x1c (removes * some excess cycles). * * What we need to put into 0-0x1c are ldrs to branch to 0xC0000000 * (the kernel). * 0x1c onwards is reserved for FIQ, so I think that I will allocate 0xe0 onwards for * the actuall address to jump to. *//* * these go into 0x00 */Lbranches: swi SYS_ERROR0 ldr pc, Lbranches + 0xe4 ldr pc, Lbranches + 0xe8 ldr pc, Lbranches + 0xec ldr pc, Lbranches + 0xf0 ldr pc, Lbranches + 0xf4 ldr pc, Lbranches + 0xf8 ldr pc, . + 4 .word _unexp_fiq/* * this is put into 0xe0 and above */jump_addresses: .word 0 .word vector_undefinstr .word vector_swi .word vector_prefetch .word vector_data .word vector_addrexcptn .word vector_IRQ/* * initialise the trap system */ .global _trap_init,trap_inittrap_init:_trap_init: stmfd sp !,{r4 - r9, lr} @ Save link register mrs r0, cpsr bic r0, r0, #31 orr r0, r0, #0xd3 msr cpsr, r0 mov r0, #0xe0 adr r1, jump_addresses ldmia r1, {r1 - r7} stmia r0, {r1 - r7} mov r0, #0 @ Lowest location adr r1, Lbranches ldmia r1, {r1 - r9} stmia r0, {r1 - r9} @ Save all into page 0 ram ldmfd sp!, {r4 - r9, pc}/* *------------------------------------------------------------------------------------------------ * Undefined FIQs *------------------------------------------------------------------------------------------------ * Enter in FIQ mode, spsr = ANY CPSR, lr = ANY PC * MUST PRESERVE SVC SPSR, but need to switch to SVC mode to show our msg. * Basically to switch modes, we *HAVE* to clobber one register... brain damage alert! * I don't think that we can execute any code in here in any other mode than FIQ... Ok * you can switch to another mode, but you can't get out of that mode without clobbering one * register. */_unexp_fiq: disable_fiq subs pc, lr, #4/* *------------------------------------------------------------------------------------------------ * Interrupt entry dispatcher - dispatches it to the correct handler for the processor mode *------------------------------------------------------------------------------------------------ * Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC */ .global vector_IRQ,vector_undefinstr,vector_data,vector_prefetch,vector_swiLCirq: .word __temp_irqvector_IRQ: @ @ save mode specific registers @ ldr r13, LCirq sub lr, lr, #4 str lr, [r13] @ save lr_IRQ mrs lr, spsr str lr, [r13, #4] @ save spsr_IRQ @ @ now branch to the relevent MODE handling routine @ mrs sp, cpsr @ switch to SVC mode bic sp, sp, #31 orr sp, sp, #0x13 msr spsr, sp and lr, lr, #15 cmp lr, #4 addlts pc, pc, lr, lsl #2 @ Changes mode and branches b __irq_invalid @ 4 - 15 b __irq_usr @ 0 (USR_26 / USR_32) b __irq_invalid @ 1 (FIQ_26 / FIQ_32) b __irq_invalid @ 2 (IRQ_26 / IRQ_32) b __irq_svc @ 3 (SVC_26 / SVC_32)/* *------------------------------------------------------------------------------------------------ * Undef instr entry dispatcher - dispatches it to the correct handler for the processor mode *------------------------------------------------------------------------------------------------ * Enter in UND mode, spsr = SVC/USR CPSR, lr = SVC/USR PC */LCund: .word __temp_undvector_undefinstr: @ @ save mode specific registers @ ldr r13, [pc, #LCund - . - 8] str lr, [r13] mrs lr, spsr str lr, [r13, #4] @ @ now branch to the relevent MODE handling routine @ mrs sp, cpsr bic sp, sp, #31 orr sp, sp, #0x13 msr spsr, sp and lr, lr, #15 cmp lr, #4 addlts pc, pc, lr, lsl #2 @ Changes mode and branches b __und_invalid @ 4 - 15 b __und_usr @ 0 (USR_26 / USR_32) b __und_invalid @ 1 (FIQ_26 / FIQ_32) b __und_invalid @ 2 (IRQ_26 / IRQ_32) b __und_svc @ 3 (SVC_26 / SVC_32)/* *------------------------------------------------------------------------------------------------ * Prefetch abort dispatcher - dispatches it to the correct handler for the processor mode *------------------------------------------------------------------------------------------------ * Enter in ABT mode, spsr = USR CPSR, lr = USR PC */LCabt: .word __temp_abtvector_prefetch: @ @ save mode specific registers @ sub lr, lr, #4 ldr r13, LCabt str lr, [r13] mrs lr, spsr str lr, [r13, #4] @ @ now branch to the relevent MODE handling routine @ mrs sp, cpsr bic sp, sp, #31 orr sp, sp, #0x13 msr spsr, sp and lr, lr, #15 cmp lr, #4 addlts pc, pc, lr, lsl #2 @ Changes mode and branches b __pabt_invalid @ 4 - 15 b __pabt_usr @ 0 (USR_26 / USR_32) b __pabt_invalid @ 1 (FIQ_26 / FIQ_32) b __pabt_invalid @ 2 (IRQ_26 / IRQ_32) b __pabt_invalid @ 3 (SVC_26 / SVC_32)/* *------------------------------------------------------------------------------------------------ * Data abort dispatcher - dispatches it to the correct handler for the processor mode *------------------------------------------------------------------------------------------------ * Enter in ABT mode, spsr = USR CPSR, lr = USR PC */vector_data: @ @ save mode specific registers @ sub lr, lr, #8 ldr r13, LCabt str lr, [r13] mrs lr, spsr str lr, [r13, #4] @ @ now branch to the relevent MODE handling routine @ mrs sp, cpsr bic sp, sp, #31 orr sp, sp, #0x13 msr spsr, sp and lr, lr, #15 cmp lr, #4 addlts pc, pc, lr, lsl #2 @ Changes mode & branches b __dabt_invalid @ 4 - 15 b __dabt_usr @ 0 (USR_26 / USR_32) b __dabt_invalid @ 1 (FIQ_26 / FIQ_32) b __dabt_invalid @ 2 (IRQ_26 / IRQ_32) b __dabt_svc @ 3 (SVC_26 / SVC_32)/* *=============================================================================== * SWI handler *------------------------------------------------------------------------------- * * We now handle sys-call tracing, and the errno in the task structure. * Still have a problem with >4 arguments for functions. Theres only * a couple of functions in the code that have 5 arguments, so Im not * too worried. */#include "calls.S"LC1: .word current/* * Enter in SVC mode, spsr_all = OLD_USER_cpsr_all, R14 = OLD_USER_PC */vector_swi: sub sp, sp, #S_FRAME_SIZE stmia sp, {r0 - r12} @ Calling r0 - r12 add r8, sp, #S_PC stmdb r8, {sp, lr}^ @ Calling sp, lr mov r7, r0 mrs r6, spsr mov r5, lr stmia r8, {r5, r6, r7} @ Save calling PC, CPSR, OLD_R0 mov fp, #0 ldr r6, [lr, #-4]! @ get swi instruction and r5, r6, #0x0f000000 teq r5, #0x0f000000 bne Larm700bug mrs r5, cpsr @ enable irqs bic r5, r5, #I_BIT msr cpsr, r5 bic r6, r6, #0xff000000 @ mask off swi op code eor r6, r6, #OS_NUMBER << 20 @ check OS numberLretry: cmp r6, #NR_SYSCALLS @ check upper syscall limit bcs Lswi_bad_call ldr r5, [pc, #LC1 - . - 8] ldr r5, [r5] mov ip, #0 @ zero errno str ip, [r5, #ERRNO] ldr ip, [r5, #FLAGS] @ check for syscall tracing tst ip, #PF_TRACESYS bne Ltrace_this_syscall adr ip, _sys_call_table mov r9, sp @ hack for routines needing > 4 values str r4, [sp, #-4]! @ new-style: (r0 = arg1, r4 = arg5) mov lr, pc ldr pc, [ip, r6, lsl #2] @ call sys routine add sp, sp, #4 ldr ip, [r5, #ERRNO] @ check errno rsbs ip, ip, #0 movne r0, ip str r0, [sp, #S_R0] @ returned r0 b _ret_from_sys_callLtrace_this_syscall: ldr r7, [sp, #S_IP] mov r0, #0 str r0, [sp, #S_IP] bl syscall_trace @ trace entry [IP must = 0] str r7, [sp, #S_IP] ldmia sp, {r0 - r3} @ have to reload r0 - r3 adr ip, _sys_call_table mov r9, sp @ hack for routines needing > 4 values str r4, [sp, #-4]! @ new-style: (r0 = arg1, r4 = arg5) mov lr, pc ldr pc, [ip, r6, lsl #2] @ call sys routine add sp, sp, #4 ldr ip, [r5, #ERRNO] rsbs ip, ip, #0 movne r0, ip str r0, [sp, #S_R0] @ returned r0 mov r0, #1 str r0, [sp, #S_IP] bl syscall_trace @ trace exit [IP must != 0] str r7, [sp, #S_IP] b _ret_from_sys_callLswi_bad_call: tst r6, #0x00f00000 bne Lbad cmp r6, #(KSWI_SYS_BASE - KSWI_BASE) @ check for arm private syscalls bcs Larm_sys_call bl sys_ni_syscall str r0, [sp, #0] @ returned r0 b _ret_from_sys_callLbad: eor r0, r6, #OS_NUMBER << 20 @ Put OS number back
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -