快乐虾
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 核,将返回 0 , B 核则返回 1 。
#define raw_smp_processor_id() blackfin_core_id()
#define blackfin_core_id() (bfin_read_DSPID() & 0xff)
#define bfin_read_DSPID() bfin_read32(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];