head.s分析(18):init_pda

来源:互联网 发布:一键开放服务器端口 编辑:程序博客网 时间:2024/06/09 19:18

 

快乐虾

http://blog.csdn.net/lights_joy/

lights@hb165.com

 

本文适用于

ADI bf561 DSP

uclinux-2008r1.5-rc3 (移植到vdsp5)

Visual DSP++ 5.0(update 5)

 

欢迎转载,但请保留作者信息

 

     sp += -12;

     call _init_pda;

     sp += 12;

init_pda的定义在linux-2.6.x/arch/blackfin/mm/init.c文件中。这是SMP相关的代码所调用的第一个函数。

PDA,即Per-processor Data Areas,一看就知道是每个核的私有财产,呵呵。

asmlinkage void init_pda(void)

{

     unsigned int cpu = raw_smp_processor_id();

 

     /* Initialize the PDA fields holding references to other parts

        of the memory. The content of such memory is still

        undefined at the time of the call, we are only setting up

        valid pointers to it. */

     memset(cpu_pda, 0, sizeof(*cpu_pda));

#ifdef CONFIG_MPU

#else

     write_pda(ipdt, ipdt_tables[cpu]);

#ifdef CONFIG_CPLB_INFO

     write_pda(ipdt_swapcount, ipdt_swapcount_tables[cpu]);

     write_pda(dpdt_swapcount, dpdt_swapcount_tables[cpu]);

#endif

     write_pda(dpdt, dpdt_tables[cpu]);

#endif

     write_pda(ex_stack, exception_stacks[cpu + 1]);

#ifdef CONFIG_SMP

     write_pda(imask, 0x1f);

#endif

}

1.1.1   获取DSPID

首先,它调用了raw_smp_processor_id来获取当前核的序号,对于561,如果运行这段代码的是A核,将返回0B核则返回1

#define raw_smp_processor_id()  blackfin_core_id()

#define blackfin_core_id()  (bfin_read_DSPID() & 0xff)

#define bfin_read_DSPID()                    bfin_read32(DSPID)

DSPID

1.1.2   cpu_pda

cpu_pda定义为:

#define cpu_pda        ((struct blackfin_pda *)get_l1_scratch_start())

#define get_l1_scratch_start()   get_l1_scratch_start_cpu(blackfin_core_id())

#define get_l1_scratch_start_cpu(cpu)          /

     ({ unsigned long __addr;                  /

        __addr = (cpu) ? L1_SCRATCH_COREB : L1_SCRATCH_COREA;     /

        __addr; })

即它将使用每个核各自的l1 scratchpad(4k)来存放私有数据。cpu_pda即指向这段存储空间的最低位置,并将之转换为(struct blackfin_pda *)。看看这个结构体的定义:

/* Per-processor Data Areas are located at the start of the L1 scratch

   memory, so that each can be accessed at a fixed address from the

   current CPU.  Used for SMP support and process stack checking.  */

 

struct pda_task_info {

     /* Points to the start of the stack.  */

     void *stack_start;

     /* Not updated by the kernel; a user process can modify this to

        keep track of the lowest address of the stack pointer during its

        runtime.  */

     void *lowest_sp;

};

 

struct blackfin_pda {   /* Per-processor Data Area */

 

     struct pda_task_info task_info;

 

#ifdef CONFIG_SMP

     unsigned long imask;        /* Current IMASK value */

#endif

 

     unsigned long *ipdt;        /* Start of switchable I-CPLB table */

     unsigned long *ipdt_swapcount;   /* Number of swaps in ipdt */

     unsigned long *dpdt;        /* Start of switchable D-CPLB table */

     unsigned long *dpdt_swapcount;   /* Number of swaps in dpdt */

 

     /*

      * Single instructions can have multiple faults, which

      * need to be handled by traps.c, in irq5. We store

      * the exception cause to ensure we don't miss a

      * double fault condition

      */

     unsigned long ex_iptr;

     unsigned long ex_optr;

     unsigned long ex_buf[4];

     unsigned long ex_imask;     /* Saved imask from exception */

     unsigned long *ex_stack;    /* Exception stack space */

 

#ifdef ANOMALY_05000261

     unsigned long last_cplb_fault_retx;

#endif

};

4K的大小还远着呢,还有扩展的潜力,呵呵。

1.1.3   write_pda

这个宏定义为:

#define write_pda(field, val)             /

     do {                   /

         cpu_pda->field = val;       /

     } while (0)

就是对cpu_pda的各个字段赋值。

这里涉及的几个数组,其定义如下:

u_long ipdt_tables[NR_CPUS][MAX_SWITCH_I_CPLBS+1];

u_long dpdt_tables[NR_CPUS][MAX_SWITCH_D_CPLBS+1];

#ifdef CONFIG_CPLB_INFO

u_long ipdt_swapcount_tables[NR_CPUS][MAX_SWITCH_I_CPLBS];

u_long dpdt_swapcount_tables[NR_CPUS][MAX_SWITCH_D_CPLBS];

#endif

extern unsigned long exception_stacks[NR_CPUS][1024];