查看64位多核 MIPS 异常和中断内核代码分析 (1)的源代码
←
64位多核 MIPS 异常和中断内核代码分析 (1)
跳转到:
导航
,
搜索
因为以下原因,你没有权限编辑本页:
您刚才请求的操作只有这个用户组中的用户才能使用:
用户
您可以查看并复制此页面的源代码:
=== 其它例外入口初始化 === 其它例外的入口初始化位于: <source lang=c> [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); ....... } </source> set_handler 同样定义该文件中: <source lang=c> /* 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); } </source> 其主要的操作就是把其它例外处理函数 except_vec3_generic,复制到对应的入口处,这个入口一般为 ebase + 0x180。主要的不同在于 ebase 的值,这个在 cavium 上为 CKSEG0 + read_c0_ebase(),loongson2 上为 CKSEG0 = 0xFFFF FFFF8000 0180: <source lang=c> 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); } ...... } </source> 其它例外处理函数 except_vec3_generic 定义于: <source lang=c> [arch/mips/kernel/genex.S] /* * General exception vector for all other CPUs. * * Be careful when changing this, it has to be at most 128 bytes * to fit into space reserved for the exception handler. */ NESTED(except_vec3_generic, 0, sp) .set push .set noat #if R5432_CP0_INTERRUPT_WAR mfc0 k0, CP0_INDEX #endif mfc0 k1, CP0_CAUSE andi k1, k1, 0x7c # K1 = ExcCode * 4,32bit #ifdef CONFIG_64BIT dsll k1, k1, 1 # k1 = ExcCode * 8,64bit 指针为 8 字节 #endif PTR_L k0, exception_handlers(k1) jr k0 .set pop END(except_vec3_generic) </source> 代码很短,其功能为:取 cp0_cause 之 ExcCode 值,然后跳转到 exception_handlers[ExcCode] 处。这个 exception_handler 实际是一张表,每一项放的是具体异常处理函数的指针。ExcCode 为 cp0_cause[6:2],cp0_cause & 0x7c 就是 ExcCode * 4;64位下,指针长度为 8 字节,因此其还要左移一位,得 ExcCode * 8 这个 exception_handlers 定义于: <pre> [arch/mips/kernel/traps] unsigned long exception_handlers[32]; </pre> 在 trap_init() 中填冲: <source lang=c> /* * Setup default vectors */ for (i = 0; i <= 31; i++) set_except_vector(i, handle_reserved); ...... set_except_vector(0, rollback ? rollback_handle_int : handle_int); set_except_vector(1, handle_tlbm); set_except_vector(2, handle_tlbl); set_except_vector(3, handle_tlbs); set_except_vector(4, handle_adel); set_except_vector(5, handle_ades); set_except_vector(6, handle_ibe); set_except_vector(7, handle_dbe); set_except_vector(8, handle_sys); set_except_vector(9, handle_bp); set_except_vector(10, rdhwr_noopt ? handle_ri : (cpu_has_vtag_icache ? handle_ri_rdhwr_vivt : handle_ri_rdhwr)); set_except_vector(11, handle_cpu); set_except_vector(12, handle_ov); set_except_vector(13, handle_tr); ...... </source> 这个 set_except_vector() 定义于同一文件中: <source lang=c> void __init *set_except_vector(int n, void *addr) { unsigned long handler = (unsigned long) addr; unsigned long old_handler = exception_handlers[n]; exception_handlers[n] = handler; if (n == 0 && cpu_has_divec) { // 处理扩展中断向量的情形, MIPS32/64 R2 都带的一个可选 feature,loongson2 和 cavium 都没有实现,因此我们不关心 unsigned long jump_mask = ~((1 << 28) - 1); u32 *buf = (u32 *)(ebase + 0x200); unsigned int k0 = 26; if ((handler & jump_mask) == ((ebase + 0x200) & jump_mask)) { uasm_i_j(&buf, handler & ~jump_mask); uasm_i_nop(&buf); } else { UASM_i_LA(&buf, k0, handler); uasm_i_jr(&buf, k0); uasm_i_nop(&buf); } local_flush_icache_range(ebase + 0x200, (unsigned long)buf); } return (void *)old_handler; } </source> 其完成的主要操作就是将传来的具体例外处理函数地址赋值给 exception_handlers 的元素 n 可以看到用来索引的 ExcCode 是这样与具体例外处理函数相关的,MIPS 规定 ExcCode 值表示的含义如下: <pre> 0 Int 中断 1 Mod TLB 修改异常 2 TLBL TLB 读异常 3 TLBS TLB 写异常 4 AdEL 读地址错误异常 5 AdEs 写地址错误异常 6 IBE 总线错误异常(取指令) 7 DBE 总线错误异常(读写数据) 8 Sys 系统调用异常 ...... </pre> 上述的 handle_int, handle_sys, handle_adel, handle_ades, handle_ibe, handle_dbe ... 由下面的宏生成: <source lang=c> [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 __BUILD_HANDLER \exception \handler \clear \verbose _int .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 </source> <br><br> <br><br>
返回到
64位多核 MIPS 异常和中断内核代码分析 (1)
。
个人工具
登录
名字空间
页面
讨论
变换
查看
阅读
查看源代码
查看历史
操作
搜索
导航
首页
社区专页
新闻动态
最近更改
随机页面
帮助
工具箱
链入页面
相关更改
特殊页面