分类: 嵌入式
2010-01-27 11:39:30
在\arch\mips\lib\memcpy.S中有以下宏定义:
#define EXC(inst_reg,addr,handler) \
9: inst_reg, addr; \
.section __ex_table,"a"; \
PTR 9b, handler; \
.previous
其中.section/.previous的使用的目的是?
section __ex_table,"a"自定义一个名叫__ex_table的段,"a"表示需要为该段分配内存。
.previous使汇编器返回到该自定义段之前的段进行汇编。
__ex_table是异常故障地址转移表,用于将页故障点直接转移到指定地址。.seciton/.previous之间用”PTR 9b, handler”定义了两个地址,一个指向"9: inst_reg, addr; \",另一个指向"handler",表示当”inst_reg, addr”指令出现故障时,将在异常处理内通过在异常故障地址转移表内匹配地址后转交给"handler"处理。
异常故障地址转移表的数据结构:
struct exception_table_entry
{
unsigned long insn;
unsigned long nextinsn;
};
异常处理最终会调用到fixup_exception,该函数将通过在异常故障地址转移表内匹配地址后将epc赋值为nextinsn,将该异常转移给nextinsn处理。
int fixup_exception(struct pt_regs *regs)
{
const struct exception_table_entry *fixup;
fixup = search_exception_tables(exception_epc(regs));
if (fixup) {
regs->cp0_epc = fixup->nextinsn;
return 1;
}
return 0;
}
__ex_table在链接文件vmlinux.lds内的定义:
SECTIONS
{
. = 0xffffffff80100000;
/* read-only */
_text = .; /* Text and read-only data */
.text : {
. = ALIGN(8); *(.text.hot) *(.text) *(.ref.text) *(.text.init.refok) *(.exit.text.refok) *(.devinit.text) *(.devexit.text) *(.text.unlikely)
. = ALIGN(8); __sched_text_start = .; *(.sched.text) __sched_text_end = .;
. = ALIGN(8); __lock_text_start = .; *(.spinlock.text) __lock_text_end = .;
. = ALIGN(8); __kprobes_text_start = .; *(.kprobes.text) __kprobes_text_end = .;
*(.text.*)
*(.fixup)
*(.gnu.warning)
} :text = 0
_etext = .; /* End of text section */
/* Exception table */
. = ALIGN(16);
__ex_table : {
__start___ex_table = .;
*(__ex_table)
__stop___ex_table = .;
}