diff -Nru ./arch/mips/math-emu/cp1emu.c.orig ./arch/mips/math-emu/cp1emu.c --- ./arch/mips/math-emu/cp1emu.c.orig Tue Oct 22 18:36:50 2002 +++ ./arch/mips/math-emu/cp1emu.c Wed Dec 4 13:44:55 2002 @@ -772,6 +772,47 @@ /* Instruction inserted following the AdELOAD to further tag the sequence */ #define BD_COOKIE 0x0000bd36 /* tne $0,$0 with baggage */ +int jsun_flag=0; +unsigned long jsun_addr; +struct { + unsigned dsemul_insns, epc, cpc, ir; + unsigned v0, s1; + unsigned ret_epc, ret_ir, ret_sp, ret_sp_80val; + unsigned ret_v0, ret_s1; + unsigned long bad_addr; + unsigned cache_tag[4], ret_cache_tag[4]; + unsigned long kaddr; + unsigned kaddr_data[4]; +} jsun_array[200]; +int jsun_index; + +extern unsigned long user_to_kernel(unsigned long addr); +extern int dcache_way_offset, icache_way_offset; + +#include +static inline unsigned load_icache_line_indexed(unsigned long addr) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "cache %1, (%0)\n\t" + ".set mips0\n\t" + ".set reorder" + : + : "r" (addr), + "i" (Index_Load_Tag_I)); + + return read_32bit_cp0_register(CP0_TAGLO); +} + +void read_cache_tag(unsigned long addr, unsigned *tag) +{ + tag[0] = load_icache_line_indexed(addr); + tag[1] = load_icache_line_indexed(addr+icache_way_offset); + tag[2] = load_icache_line_indexed(addr+icache_way_offset*2); + tag[3] = load_icache_line_indexed(addr+icache_way_offset*3); +} + int do_dsemulret(struct pt_regs *xcp) { unsigned long *pinst; @@ -786,7 +827,7 @@ * If we can't even access the area, something is very wrong, but we'll * leave that to the default handling */ - if (verify_area(VERIFY_READ, pinst, sizeof(unsigned long) * 3)) + if (verify_area(VERIFY_READ, pinst-1, sizeof(unsigned long) * 4)) return 0; /* Is the instruction pointed to by the EPC an AdELOAD? */ @@ -826,16 +867,77 @@ /* Set EPC to return to post-branch instruction */ xcp->cp0_epc = stackitem; + jsun_array[jsun_index].ret_epc = (unsigned long)pinst; + jsun_array[jsun_index].ret_ir = mips_get_word(xcp, pinst-1, &err); + jsun_array[jsun_index].ret_sp = xcp->regs[29]; + jsun_array[jsun_index].ret_v0 = xcp->regs[2]; + jsun_array[jsun_index].ret_s1 = xcp->regs[17]; + jsun_array[jsun_index].ret_sp_80val = mips_get_word(xcp, xcp->regs[29]+80, &err); + if (jsun_array[jsun_index].ret_ir == 0x8fa20050) { + xcp->regs[17] = jsun_array[jsun_index].s1; + } + + jsun_index ++; + return 1; } #define AdELOAD 0x8c000001 /* lw $0,1($0) */ +void jsun_dump_struct(void) +{ + int i; + printk("dump jsun_struct:\n"); + for (i=0; i< jsun_index; i++) { + printk("------\n"); + printk("dsemul_insns = %08x, epc=%08x, cpc=%08x, ir=%08x\n", + jsun_array[i].dsemul_insns, + jsun_array[i].epc, + jsun_array[i].cpc, + jsun_array[i].ir); + printk("v0 = %08x, s1=%08x\n", + jsun_array[i].v0, + jsun_array[i].s1); + printk("ret_epc = %08x, ret_ir=%08x, ret_sp=%08x, ret_sp_80val=%08x\n", + jsun_array[i].ret_epc, + jsun_array[i].ret_ir, + jsun_array[i].ret_sp, + jsun_array[i].ret_sp_80val); + printk("ret_v0 = %08x, ret_s1=%08x, bad_addr=%08lx\n", + jsun_array[i].ret_v0, + jsun_array[i].ret_s1, + jsun_array[i].bad_addr + ); + printk("cache tags before: %08x, %08x, %08x, %08x\n", + jsun_array[i].cache_tag[0], + jsun_array[i].cache_tag[1], + jsun_array[i].cache_tag[2], + jsun_array[i].cache_tag[3] + ); + printk("cache tags after : %08x, %08x, %08x, %08x\n", + jsun_array[i].ret_cache_tag[0], + jsun_array[i].ret_cache_tag[1], + jsun_array[i].ret_cache_tag[2], + jsun_array[i].ret_cache_tag[3] + ); + printk("mem @ %08x : %08x, %08x, %08x, %08x\n", + jsun_array[i].kaddr + 0x20000000, + jsun_array[i].kaddr_data[0], + jsun_array[i].kaddr_data[1], + jsun_array[i].kaddr_data[2], + jsun_array[i].kaddr_data[3]); + + } + jsun_index = 0; +} + static int mips_dsemul(struct pt_regs *regs, mips_instruction ir, vaddr_t cpc) { mips_instruction *dsemul_insns; extern asmlinkage void handle_dsemulret(void); + mips_instruction new_ir; + unsigned long temp; if (ir == 0) { /* a nop is easy */ regs->cp0_epc = VA_TO_REG(cpc); @@ -864,11 +966,17 @@ dsemul_insns = (mips_instruction *) (regs->regs[29] & ~0xf); dsemul_insns -= 4; /* Retain 16-byte alignment */ + temp=user_to_kernel((unsigned long)dsemul_insns); + /* Verify that the stack pointer is not competely insane */ if (verify_area (VERIFY_WRITE, dsemul_insns, sizeof(mips_instruction) * 4)) return SIGBUS; + if (ir == 0x8fa20050) { + // ir = 0x24020004; // li v0, 9 + // regs->regs[2]=0; + } if (mips_put_word(regs, &dsemul_insns[0], ir)) { fpuemuprivate.stats.errors++; return (SIGBUS); @@ -890,9 +998,50 @@ return (SIGBUS); } + + jsun_array[jsun_index].dsemul_insns = (unsigned long)dsemul_insns; + jsun_array[jsun_index].epc = (unsigned long)regs->cp0_epc; + jsun_array[jsun_index].cpc = cpc; + jsun_array[jsun_index].v0 = regs->regs[2]; + jsun_array[jsun_index].s1 = regs->regs[17]; + jsun_array[jsun_index].ir = *(unsigned long *)&ir; + jsun_array[jsun_index].kaddr = temp; + + // jsun_index ++; + + if (ir == 0x8fa20050) { + regs->regs[17] = 0x55; + } + regs->cp0_epc = VA_TO_REG & dsemul_insns[0]; + read_cache_tag(temp, jsun_array[jsun_index].cache_tag); + jsun_addr=0; flush_cache_sigtramp((unsigned long)dsemul_insns); + jsun_array[jsun_index].bad_addr = jsun_addr; + read_cache_tag(temp, jsun_array[jsun_index].ret_cache_tag); + + jsun_array[jsun_index].kaddr_data[0] = *(unsigned*)(temp + 0x20000000); + jsun_array[jsun_index].kaddr_data[1] = *(unsigned*)(temp + 0x20000004); + jsun_array[jsun_index].kaddr_data[2] = *(unsigned*)(temp + 0x20000008); + jsun_array[jsun_index].kaddr_data[3] = *(unsigned*)(temp + 0x2000000c); + + // my_flush_cache_sigtramp((unsigned long)dsemul_insns); + // flush_cache_all(); + +#if 0 + jsun_addr=user_to_kernel((unsigned long)dsemul_insns); + if (jsun_addr) + printk("mem @ %08x : %08x, %08x, %08x, %08x\n", + jsun_addr, + *(unsigned long*)jsun_addr, + *(unsigned long*)(jsun_addr+4), + *(unsigned long*)(jsun_addr+8), + *(unsigned long*)(jsun_addr+12)); + else + printk("convertion failed\n"); +#endif + return SIGILL; /* force out of emulation loop */ } diff -Nru ./arch/mips/mm/c-mips32.c.orig ./arch/mips/mm/c-mips32.c --- ./arch/mips/mm/c-mips32.c.orig Tue Dec 3 18:54:52 2002 +++ ./arch/mips/mm/c-mips32.c Wed Dec 4 13:04:29 2002 @@ -39,6 +39,7 @@ /* Primary cache parameters. */ int icache_size, dcache_size; /* Size in bytes */ int ic_lsize, dc_lsize; /* LineSize in bytes */ +int icache_way_offset, dcache_way_offset; /* offset between ways w. same set */ /* Secondary cache (if present) parameters. */ unsigned int scache_size, sc_lsize; /* Again, in bytes */ @@ -407,6 +408,55 @@ * very much about what happens in that case. Usually a segmentation * fault will dump the process later on anyway ... */ +static void indexed_writeback_dcache_line(unsigned long addr) +{ + int i; + int set_size = dcache_size / mips_cpu.dcache.ways; + for (i=0; imm || + !current->mm->context || + !current->active_mm || + !current->active_mm->context || + current->mm != current->active_mm) { + printk("user_to_kernel condition failed\n"); + return 0; + } + + mm= current->mm; + pgd = pgd_offset(mm, addr); + pmd = pmd_offset(pgd, addr); + pte = pte_offset(pmd, addr); + if(!(pte_val(*pte) & _PAGE_VALID)) { + printk("user_to_kernel : pte not valid\n"); + return 0; + } + + pg= pte_page(*pte); + return (unsigned long)pg->virtual + offset; +} + static void mips32_flush_cache_sigtramp(unsigned long addr) { protected_writeback_dcache_line(addr & ~(dc_lsize - 1)); @@ -451,6 +501,7 @@ } printk("Primary instruction cache %dkb, linesize %d bytes (%d ways)\n", icache_size >> 10, ic_lsize, mips_cpu.icache.ways); + icache_way_offset = icache_size / mips_cpu.icache.ways; } static void __init probe_dcache(unsigned long config) @@ -490,6 +541,7 @@ } printk("Primary data cache %dkb, linesize %d bytes (%d ways)\n", dcache_size >> 10, dc_lsize, mips_cpu.dcache.ways); + dcache_way_offset = dcache_size / mips_cpu.dcache.ways; } diff -Nru ./arch/mips/mm/fault.c.orig ./arch/mips/mm/fault.c --- ./arch/mips/mm/fault.c.orig Tue Oct 22 18:36:51 2002 +++ ./arch/mips/mm/fault.c Wed Dec 4 10:35:26 2002 @@ -74,6 +74,7 @@ * and the problem, and then passes it off to one of the appropriate * routines. */ +extern unsigned long jsun_addr; asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write, unsigned long address) { @@ -193,6 +194,7 @@ long new_epc; tsk->thread.cp0_baduaddr = address; + jsun_addr = address; new_epc = fixup_exception(dpf_reg, fixup, regs->cp0_epc); if (development_version) printk(KERN_DEBUG "%s: Exception at [<%lx>] (%lx)\n", diff -Nru ./include/asm-mips/mips32_cache.h.orig ./include/asm-mips/mips32_cache.h --- ./include/asm-mips/mips32_cache.h.orig Tue Oct 22 18:37:03 2002 +++ ./include/asm-mips/mips32_cache.h Tue Dec 3 18:24:25 2002 @@ -171,7 +171,7 @@ ".previous" : : "r" (addr), - "i" (Hit_Writeback_D)); + "i" (Hit_Writeback_Inv_D)); } #define cache_unroll(base,op) \ diff -Nru ./net/ipv4/icmp.c.orig ./net/ipv4/icmp.c --- ./net/ipv4/icmp.c.orig Mon Feb 25 11:38:14 2002 +++ ./net/ipv4/icmp.c Tue Dec 3 12:08:01 2002 @@ -733,6 +733,7 @@ static void icmp_echo(struct sk_buff *skb) { + jsun_dump_struct(); if (!sysctl_icmp_echo_ignore_all) { struct icmp_bxm icmp_param;