--- zzzz-none-000/linux-2.6.13.1/arch/mips/kernel/traps.c 2005-09-10 02:42:58.000000000 +0000 +++ ohio-7170-487/linux-2.6.13.1/arch/mips/kernel/traps.c 2007-06-13 08:22:30.000000000 +0000 @@ -13,6 +13,7 @@ */ #include #include +#include #include #include #include @@ -57,6 +58,45 @@ extern asmlinkage void handle_mcheck(void); extern asmlinkage void handle_reserved(void); +#if defined(CONFIG_MIPS_OHIO) && 0 +extern asmlinkage void ohio_handle_tlbm(void); +extern asmlinkage void ohio_handle_tlbl(void); +extern asmlinkage void ohio_handle_tlbs(void); +extern asmlinkage void ohio_handle_adel(void); +extern asmlinkage void ohio_handle_ades(void); +extern asmlinkage void ohio_handle_ibe(void); +extern asmlinkage void ohio_handle_dbe(void); +extern asmlinkage void ohio_handle_sys(void); +extern asmlinkage void ohio_handle_bp(void); +extern asmlinkage void ohio_handle_ri(void); +extern asmlinkage void ohio_handle_cpu(void); +extern asmlinkage void ohio_handle_ov(void); +extern asmlinkage void ohio_handle_tr(void); +extern asmlinkage void ohio_handle_fpe(void); +extern asmlinkage void ohio_handle_mdmx(void); +extern asmlinkage void ohio_handle_watch(void); +extern asmlinkage void ohio_handle_mcheck(void); +extern asmlinkage void ohio_handle_reserved(void); +/*--- #define handle_mcheck ohio_handle_mcheck ---*/ +/*--- #define handle_watch ohio_handle_watch ---*/ +/*--- #define handle_mdmx ohio_handle_mdmx ---*/ +/*--- #define handle_fpe ohio_handle_fpe ---*/ +/*--- #define handle_tr ohio_handle_tr ---*/ +/*--- #define handle_ov ohio_handle_ov ---*/ +/*--- #define handle_cpu ohio_handle_cpu ---*/ +/*--- #define handle_ri ohio_handle_ri ---*/ +/*--- #define handle_bp ohio_handle_bp ---*/ +/*--- #define handle_sys ohio_handle_sys ---*/ +/*--- #define handle_dbe ohio_handle_dbe ---*/ +/*--- #define handle_ibe ohio_handle_ibe ---*/ +/*--- #define handle_ades ohio_handle_ades ---*/ +/*--- #define handle_adel ohio_handle_adel ---*/ +/*--- #define handle_tlbs ohio_handle_tlbs ---*/ +/*--- #define handle_tlbl ohio_handle_tlbl ---*/ +/*--- #define handle_tlbm ohio_handle_tlbm ---*/ +/*--- #define handle_reserved ohio_handle_reserved ---*/ +#endif /*--- #if defined(CONFIG_MIPS_OHIO) ---*/ + extern int fpu_emulator_cop1Handler(int xcptno, struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx); @@ -257,6 +297,7 @@ { static int die_counter; + console_verbose(); spin_lock_irq(&die_lock); printk("%s", str); @@ -304,6 +345,7 @@ int data = regs->cp0_cause & 4; int action = MIPS_BE_FATAL; + /* XXX For now. Fixme, this searches the wrong table ... */ if (data && !user_mode(regs)) fixup = search_dbe_tables(exception_epc(regs)); @@ -330,6 +372,9 @@ /* * Assume it would be too dangerous to continue ... */ + if (!user_mode(regs)) { + restore_printk(); /*--- standard-printk ---*/ + } printk(KERN_ALERT "%s bus error, epc == %0*lx, ra == %0*lx\n", data ? "Data" : "Instruction", field, regs->cp0_epc, field, regs->regs[31]); @@ -554,6 +599,9 @@ unsigned int opcode, bcode; siginfo_t info; + if (!user_mode(regs)) { + restore_printk(); /*--- standard-printk ---*/ + } die_if_kernel("Break instruction in kernel code", regs); if (get_insn_opcode(regs, &opcode)) @@ -597,6 +645,9 @@ unsigned int opcode, tcode = 0; siginfo_t info; + if (!user_mode(regs)) { + restore_printk(); /*--- standard-printk ---*/ + } die_if_kernel("Trap instruction in kernel code", regs); if (get_insn_opcode(regs, &opcode)) @@ -631,6 +682,9 @@ asmlinkage void do_ri(struct pt_regs *regs) { + if (!user_mode(regs)) { + restore_printk(); /*--- standard-printk ---*/ + } die_if_kernel("Reserved instruction in kernel code", regs); if (!cpu_has_llsc) @@ -644,6 +698,9 @@ { unsigned int cpid; + if (!user_mode(regs)) { + restore_printk(); /*--- standard-printk ---*/ + } die_if_kernel("do_cpu invoked from kernel context!", regs); cpid = (regs->cp0_cause >> CAUSEB_CE) & 3; @@ -835,11 +892,22 @@ */ void nmi_exception_handler(struct pt_regs *regs) { + restore_printk(); /*--- standard-printk ---*/ printk("NMI taken!!!!\n"); die("NMI", regs); while(1) ; } +void create_long_jump_with_KO(void *addr, void *handler, char *text) { + printk("[create_long_jump_with_KO] gen jump code to 0x%p (%s) at 0x%p\n", handler, text, addr); + /*--- 3c1a____ lui,k0,____ ---*/ + /*--- 275a____ addiu k0,k0,____ ---*/ + /*--- 03400008 jr k0 ---*/ + ((unsigned int *)addr)[0] = 0x3c1a0000 | ((unsigned int)handler >> 16); + ((unsigned int *)addr)[1] = 0x275a0000 | ((unsigned int)handler & 0xFFFF); + ((unsigned int *)addr)[2] = 0x03400008; +} + unsigned long exception_handlers[32]; /* @@ -854,9 +922,46 @@ exception_handlers[n] = handler; if (n == 0 && cpu_has_divec) { - *(volatile u32 *)(CAC_BASE + 0x200) = 0x08000000 | - (0x03ffffff & (handler >> 2)); - flush_icache_range(CAC_BASE + 0x200, CAC_BASE + 0x204); +#if defined(CONFIG_MIPS_OHIO) && 0 + /*----------------------------------------------------------------------------------*\ + * addiu sp,sp,-8 = 0x27bdfff8 + * sw v0,4(sp) = 0x8fa20004 + * lui v0,_handler = 0x3c02xxxx + * ori v0,v0,_handler = 0x3442xxxx + * jr v0 = 0x00400008 + * nop = 0x00000000 + \*----------------------------------------------------------------------------------*/ + unsigned int first_handler[] = { 0x27bdfff8, 0x8fa20004, 0x3c020000, 0x34420000, 0x00400008, 0x00000000 }; + volatile unsigned int *p_first_handler = *(volatile unsigned int *)(CAC_BASE + 0x200); + if(handler == handle_mcheck) handler = ohio_handle_mcheck; + else if(handler == (unsigned int)handle_watch) handler = ohio_handle_watch; + else if(handler == (unsigned int)handle_mdmx) handler = ohio_handle_mdmx; + else if(handler == (unsigned int)handle_fpe) handler = ohio_handle_fpe; + else if(handler == (unsigned int)handle_tr) handler = ohio_handle_tr; + else if(handler == (unsigned int)handle_ov) handler = ohio_handle_ov; + else if(handler == (unsigned int)handle_cpu) handler = ohio_handle_cpu; + else if(handler == (unsigned int)handle_ri) handler = ohio_handle_ri; + else if(handler == (unsigned int)handle_bp) handler = ohio_handle_bp; + else if(handler == (unsigned int)handle_sys) handler = ohio_handle_sys; + else if(handler == (unsigned int)handle_dbe) handler = ohio_handle_dbe; + else if(handler == (unsigned int)handle_ibe) handler = ohio_handle_ibe; + else if(handler == (unsigned int)handle_ades) handler = ohio_handle_ades; + else if(handler == (unsigned int)handle_adel) handler = ohio_handle_adel; + else if(handler == (unsigned int)handle_tlbs) handler = ohio_handle_tlbs; + else if(handler == (unsigned int)handle_tlbl) handler = ohio_handle_tlbl; + else if(handler == (unsigned int)handle_tlbm) handler = ohio_handle_tlbm; + else if(handler == (unsigned int)handle_reserved) handler = ohio_handle_reserved; + + p_first_handler[0] = first_handler[0]; + p_first_handler[1] = first_handler[1]; + p_first_handler[2] = first_handler[2] | (handler >> 16); + p_first_handler[3] = first_handler[3] | (handler && 0xFFFF); + p_first_handler[4] = first_handler[4]; + p_first_handler[5] = first_handler[5]; +#else /*--- #if defined(CONFIG_MIPS_OHIO) ---*/ + /*--- *(volatile u32 *)(CAC_BASE + 0x200) = 0x08000000 | (0x03ffffff & (handler >> 2)); ---*/ +#endif /*--- #else ---*/ /*--- #if defined(CONFIG_MIPS_OHIO) ---*/ + /*--- flush_icache_range(CAC_BASE + 0x200, CAC_BASE + 0x204); ---*/ } return (void *)old_handler; } @@ -956,7 +1061,11 @@ extern char except_vec3_generic, except_vec3_r4000; extern char except_vec_ejtag_debug; extern char except_vec4; + extern char except_vec3_generic_end, except_vec3_r4000_end; + extern char except_vec_ejtag_debug_end; + extern char except_vec4_end; unsigned long i; + unsigned int len; per_cpu_trap_init(); @@ -965,7 +1074,9 @@ * This will be overriden later as suitable for a particular * configuration. */ - memcpy((void *)(CAC_BASE + 0x180), &except_vec3_generic, 0x80); + len = (unsigned int)&except_vec3_generic_end - (unsigned int)&except_vec3_generic; + /*--- printk("[trap_init] memcpy((void *)(CAC_BASE + 0x180), &except_vec3_generic, 0x%x);\n", len); ---*/ + memcpy((void *)(CAC_BASE + 0x180), &except_vec3_generic, len); /* * Setup default vectors @@ -977,8 +1088,11 @@ * Copy the EJTAG debug exception vector handler code to it's final * destination. */ - if (cpu_has_ejtag) - memcpy((void *)(CAC_BASE + 0x300), &except_vec_ejtag_debug, 0x80); + if (cpu_has_ejtag) { + len = (unsigned int)&except_vec_ejtag_debug_end - (unsigned int)&except_vec_ejtag_debug; + /*--- printk("[trap_init] memcpy((void *)(CAC_BASE + 0x300), &except_vec_ejtag_debug, 0x%x);\n", len); ---*/ + memcpy((void *)(CAC_BASE + 0x300), &except_vec_ejtag_debug, len); + } /* * Only some CPUs have the watch exceptions. @@ -990,8 +1104,11 @@ * Some MIPS CPUs have a dedicated interrupt vector which reduces the * interrupt processing overhead. Use it where available. */ - if (cpu_has_divec) - memcpy((void *)(CAC_BASE + 0x200), &except_vec4, 0x8); + if (cpu_has_divec) { + len = (unsigned int)&except_vec4_end - (unsigned int)&except_vec4; + /*--- printk("[trap_init] memcpy((void *)(CAC_BASE + 0x200), &except_vec4, 0x%x);\n", len); ---*/ + memcpy((void *)(CAC_BASE + 0x200), &except_vec4, len); + } /* * Some CPUs can enable/disable for cache parity detection, but does @@ -1031,13 +1148,20 @@ if (cpu_has_mcheck) set_except_vector(24, handle_mcheck); - if (cpu_has_vce) + if (cpu_has_vce) { /* Special exception: R4[04]00 uses also the divec space. */ - memcpy((void *)(CAC_BASE + 0x180), &except_vec3_r4000, 0x100); - else if (cpu_has_4kex) - memcpy((void *)(CAC_BASE + 0x180), &except_vec3_generic, 0x80); - else - memcpy((void *)(CAC_BASE + 0x080), &except_vec3_generic, 0x80); + len = (unsigned int)&except_vec3_r4000_end - (unsigned int)&except_vec3_r4000; + /*--- printk("[trap_init] memcpy((void *)(CAC_BASE + 0x180), &except_vec3_r4000, 0x%x);\n", len); ---*/ + memcpy((void *)(CAC_BASE + 0x180), &except_vec3_r4000, len); + } else if (cpu_has_4kex) { + len = (unsigned int)&except_vec3_generic_end - (unsigned int)&except_vec3_generic; + /*--- printk("[trap_init] memcpy((void *)(CAC_BASE + 0x180), &except_vec3_generic, 0x%x);\n", len); ---*/ + memcpy((void *)(CAC_BASE + 0x180), &except_vec3_generic, len); + } else { + len = (unsigned int)&except_vec3_generic_end - (unsigned int)&except_vec3_generic; + /*--- printk("[trap_init] memcpy((void *)(CAC_BASE + 0x080), &except_vec3_generic, 0x%x);\n", len); ---*/ + memcpy((void *)(CAC_BASE + 0x080), &except_vec3_generic, len); + } if (current_cpu_data.cputype == CPU_R6000 || current_cpu_data.cputype == CPU_R6000A) { @@ -1058,5 +1182,6 @@ signal32_init(); #endif + /*--- printk("[trap_init] flush_icache_range(CAC_BASE, CAC_BASE + 0x400);\n"); ---*/ flush_icache_range(CAC_BASE, CAC_BASE + 0x400); }