1.3 其它例外入口初始化
其它例外的入口初始化位于:
[arch/mips/kernel/traps.c]
void __init trap_init()
{
......
/*
* Copy the generic exception handlers to their final destination.
* This will be overriden later as suitable for a particular
* configuration.
*/
set_handler(0x180, &except_vec3_generic, 0x80);
.......
}
set_handler 同样定义该文件中:/* Install CPU exception handler */
void __init set_handler(unsigned long offset, void *addr, unsigned long size)
{
memcpy((void *)(ebase + offset), addr, size);
local_flush_icache_range(ebase + offset, ebase + offset + size);
}
其主要的操作就是把其它例外处理函数 except_vec3_generic,复制到对应的入口处,这个入口一般为 ebase + 0x180。主要的不同在于 ebase 的值,这个在 cavium 上为 CKSEG0 + read_c0_ebase(),loongson2 上为 CKSEG0 = 0xFFFF FFFF8000 0180:
void __init trap_init()
{
......
if (cpu_has_veic || cpu_has_vint) {
unsigned long size = 0x200 + VECTORSPACING*64;
ebase = (unsigned long)
__alloc_bootmem(size, 1 << fls(size), 0);
} else {
ebase = CKSEG0;
if (cpu_has_mips_r2)
ebase += (read_c0_ebase() & 0x3ffff000);
}
......
}
其它例外处理函数 except_vec3_generic 定义于:
[arch/mips/kernel/genex.S]
/*代码很短,其功能为:取 cp0_cause 之 ExcCode 值,然后跳转到 exception_handlers[ExcCode] 处。这个 exception_handler 实际是一张表,每一项放的是具体异常处理函数的指针。ExcCode 为 cp0_cause[6:2],cp0_cause & 0x7c 就是 ExcCode * 4;64位下,指针长度为 8 字节,因此其还要左移一位,得 ExcCode * 8
这个 exception_handlers 定义于:
[arch/mips/kernel/traps]
unsigned long exception_handlers[32];
在 trap_init() 中填冲:
/*
......
set_except_vector(0, rollback ? rollback_handle_int : handle_int);......
这个 set_except_vector() 定义于同一文件中:
void __init *set_except_vector(int n, void *addr)
其完成的主要操作就是将传来的具体例外处理函数地址赋值给 exception_handlers 的元素 n
可以看到用来索引的 ExcCode 是这样与具体例外处理函数相关的,MIPS 规定 ExcCode 值表示的含义如下:
0 Int 中断
1 Mod TLB 修改异常
2 TLBL TLB 读异常
3 TLBS TLB 写异常
4 AdEL 读地址错误异常
5 AdEs 写地址错误异常
6 IBE 总线错误异常(取指令)
7 DBE 总线错误异常(读写数据)
8 Sys 系统调用异常
......
上述的 handle_int, handle_sys, handle_adel, handle_ades, handle_ibe, handle_dbe ... 由下面的宏生成:
[arch/mips/kernel/genex.S]
BUILD_HANDLER adel ade ade silent /* #4 */
BUILD_HANDLER ades ade ade silent /* #5 */
BUILD_HANDLER ibe be cli silent /* #6 */
BUILD_HANDLER dbe be cli silent /* #7 */
BUILD_HANDLER bp bp sti silent /* #9 */
BUILD_HANDLER ri ri sti silent /* #10 */
BUILD_HANDLER cpu cpu sti silent /* #11 */
BUILD_HANDLER ov ov sti silent /* #12 */
BUILD_HANDLER tr tr sti silent /* #13 */
BUILD_HANDLER fpe fpe fpe silent /* #15 */
BUILD_HANDLER mdmx mdmx sti silent /* #22 */
#ifdef CONFIG_HARDWARE_WATCHPOINTS
/*
* For watch, interrupts will be enabled after the watch
* registers are read.
*/
BUILD_HANDLER watch watch cli silent /* #23 */
#else
BUILD_HANDLER watch watch sti verbose /* #23 */
#endif
BUILD_HANDLER mcheck mcheck cli verbose /* #24 */
BUILD_HANDLER mt mt sti silent /* #25 */
BUILD_HANDLER dsp dsp sti silent /* #26 */
BUILD_HANDLER reserved reserved sti verbose /* others */
BUILD_HANDLER 定义为:
.macro BUILD_HANDLER exception handler clear verbose.endm
.macro __BUILD_HANDLER exception handler clear verbose ext
.align 5
NESTED(handle_\exception, PT_SIZE, sp)
.set noat
SAVE_ALL
FEXPORT(handle_\exception\ext)
__BUILD_clear_\clear
.set at
__BUILD_\verbose \exception
move a0, sp
PTR_LA ra, ret_from_exception
j do_\handler
END(handle_\exception)
.endm