Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2295060
  • 博文数量: 218
  • 博客积分: 5767
  • 博客等级: 大校
  • 技术积分: 5883
  • 用 户 组: 普通用户
  • 注册时间: 2008-03-01 14:44
文章存档

2012年(53)

2011年(131)

2009年(1)

2008年(33)

分类: LINUX

2011-09-05 15:00:00

arch/arm/kernel/setup.c
struct stack {
    u32 irq[3];
    u32 abt[3];
    u32 und[3];
} ____cacheline_aligned;

/*
 * cpu_init - initialise one CPU.
 *
 * cpu_init sets up the per-CPU stacks.
 */
arm的R13是bank register,arm的七种处理器模式有各自的R13(user模式和system模式共用一个,总共六个不同的R13),也就是arm汇编默认的 SP(堆栈指针),就是说一旦产生了模式切换(IRQ,FIQ,异常等), 接着的代码就使用模式对应的SP.cpu_init就是对用到的IRQ, ABT, UND模式的SP都作了初始化
void cpu_init(void) //设置cpu堆栈
{
    unsigned int cpu = smp_processor_id(); //获取cpu的id
    struct stack *stk = &stacks[cpu];

    if (cpu >= NR_CPUS) {  //对于ARM NR_CPUS为1
        printk(KERN_CRIT "CPU%u: bad primary CPU number\n", cpu);
        BUG();
    }

    /*
     * Define the placement constraint for the inline asm directive below.
     * In Thumb-2, msr with an immediate value is not allowed.
     */
#ifdef CONFIG_THUMB2_KERNEL
#define PLC    "r"
#else
#define PLC    "I"
#endif

    /*
     * setup stacks for re-entrant exception handlers
     */
    __asm__ (
    "msr    cpsr_c, %1\n\t"   //切换到IRQ_MODE
    "add    r14, %0, %2\n\t"  
    "mov    sp, r14\n\t"     //设置r13_irq,此时sp是r13_irq
    "msr    cpsr_c, %3\n\t"  //切换到ABT_MODE
    "add    r14, %0, %4\n\t"
    "mov    sp, r14\n\t"     //设置r13_abt,此时sp是r13_abt
    "msr    cpsr_c, %5\n\t"  //切换到UND_MODE
    "add    r14, %0, %6\n\t"
    "mov    sp, r14\n\t"   //设置r13_und,此时sp是r13_und
    "msr    cpsr_c, %7"    //切换回SVC_MODE
        :
        : "r" (stk),
          PLC (PSR_F_BIT | PSR_I_BIT | IRQ_MODE),
          "I" (offsetof(struct stack, irq[0])),
          PLC (PSR_F_BIT | PSR_I_BIT | ABT_MODE),
          "I" (offsetof(struct stack, abt[0])),
          PLC (PSR_F_BIT | PSR_I_BIT | UND_MODE),
          "I" (offsetof(struct stack, und[0])),
          PLC (PSR_F_BIT | PSR_I_BIT | SVC_MODE)
        : "r14");
}
可以看到,IRQ, ABT, UND模式的堆栈大小都只有3个int,
你可能会问,进入这三个模式后, 怎么保存大量的寄存器?
呵呵,进入这三种模式后,linux会把模式切换到SVC_MODE,使用的是SVC_MODE的堆栈.我们看一下在arch/arm/kernel/entry-armv.S中的汇编代码
1040 /*
1041  * Vector stubs.
1042  *
1043  * This code is copied to 0xffff0200 so we can use branches in the
1044  * vectors, rather than ldr's.  Note that this code must not
1045  * exceed 0x300 bytes.
1046  *
1047  * Common stub entry macro:
1048  *   Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
1049  *
1050  * SP points to a minimal amount of processor-private memory, the address
1051  * of which is copied into r0 for the mode specific abort handler.
1052  */
1053         .macro  vector_stub, name, mode, correction=0
1054         .align  5
1055
1056 vector_\name:
1057         .if \correction
1058         sub     lr, lr, #\correction
1059         .endif
1060
1061         @
1062         @ Save r0, lr_ (parent PC) and spsr_
1063         @ (parent CPSR)
1064         @
1065         stmia   sp, {r0, lr}            @ save r0, lr //R13_保存两个int
1066         mrs     lr, spsr
1067         str     lr, [sp, #8]            @ save spsr   //R13_再保存一个int
1068
1069         @
1070         @ Prepare for SVC32 mode.  IRQs remain disabled.
1071         @
1072         mrs     r0, cpsr
1073         eor     r0, r0, #(\mode ^ SVC_MODE | PSR_ISETSTATE) //切换到SVC,之后的堆栈操作都用R13_svc,sp都是R13_svc的值
1074         msr     spsr_cxsf, r0
1075
1076         @
1077         @ the branch table must immediately follow this code
1078         @
1079         and     lr, lr, #0x0f
1080  THUMB( adr     r0, 1f                  )
1081  THUMB( ldr     lr, [r0, lr, lsl #2]    )
1082         mov     r0, sp
1083  ARM(   ldr     lr, [pc, lr, lsl #2]    )
1084         movs    pc, lr                  @ branch to handler in SVC mode
1085 ENDPROC(vector_\name)

/*
 * PSR bits
 */
#define USR26_MODE    0x00000000
#define FIQ26_MODE    0x00000001
#define IRQ26_MODE    0x00000002
#define SVC26_MODE    0x00000003
#define USR_MODE    0x00000010
#define FIQ_MODE    0x00000011
#define IRQ_MODE    0x00000012
#define SVC_MODE    0x00000013
#define ABT_MODE    0x00000017
#define UND_MODE    0x0000001b
#define SYSTEM_MODE    0x0000001f
#define MODE32_BIT    0x00000010
#define MODE_MASK    0x0000001f
#define PSR_T_BIT    0x00000020
#define PSR_F_BIT    0x00000040
#define PSR_I_BIT    0x00000080
#define PSR_A_BIT    0x00000100
#define PSR_E_BIT    0x00000200
#define PSR_J_BIT    0x01000000
#define PSR_Q_BIT    0x08000000
#define PSR_V_BIT    0x10000000
#define PSR_C_BIT    0x20000000
#define PSR_Z_BIT    0x40000000
#define PSR_N_BIT    0x80000000

阅读(1649) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~