X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=arch%2Fsparc64%2Fkernel%2Funaligned.c;h=bc18d480dd1cb958fe4010acef75aa8e8a43a766;hb=7e20ef030dde0e52dd5a57220ee82fa9facbea4e;hp=001e8518331fb91bf56a28d2770e9cfef68769f0;hpb=ba93c6297b9cfad5a70b5e5ed13c9dbead6601d3;p=powerpc.git diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c index 001e851833..bc18d480dd 100644 --- a/arch/sparc64/kernel/unaligned.c +++ b/arch/sparc64/kernel/unaligned.c @@ -20,6 +20,7 @@ #include #include #include +#include #include /* #define DEBUG_MNA */ @@ -242,7 +243,7 @@ static inline int ok_for_kernel(unsigned int insn) return !floating_point_load_or_store_p(insn); } -static void kernel_mna_trap_fault(void) +static void kernel_mna_trap_fault(int fixup_tstate_asi) { struct pt_regs *regs = current_thread_info()->kern_una_regs; unsigned int insn = current_thread_info()->kern_una_insn; @@ -273,28 +274,57 @@ static void kernel_mna_trap_fault(void) regs->tpc = entry->fixup; regs->tnpc = regs->tpc + 4; - regs->tstate &= ~TSTATE_ASI; - regs->tstate |= (ASI_AIUS << 24UL); + if (fixup_tstate_asi) { + regs->tstate &= ~TSTATE_ASI; + regs->tstate |= (ASI_AIUS << 24UL); + } +} + +static void log_unaligned(struct pt_regs *regs) +{ + static unsigned long count, last_time; + + if (jiffies - last_time > 5 * HZ) + count = 0; + if (count < 5) { + last_time = jiffies; + count++; + printk("Kernel unaligned access at TPC[%lx] ", regs->tpc); + print_symbol("%s\n", regs->tpc); + } } asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn) { enum direction dir = decode_direction(insn); int size = decode_access_size(insn); + int orig_asi, asi; current_thread_info()->kern_una_regs = regs; current_thread_info()->kern_una_insn = insn; + orig_asi = asi = decode_asi(insn, regs); + + /* If this is a {get,put}_user() on an unaligned userspace pointer, + * just signal a fault and do not log the event. + */ + if (asi == ASI_AIUS) { + kernel_mna_trap_fault(0); + return; + } + + log_unaligned(regs); + if (!ok_for_kernel(insn) || dir == both) { printk("Unsupported unaligned load/store trap for kernel " "at <%016lx>.\n", regs->tpc); unaligned_panic("Kernel does fpu/atomic " "unaligned load/store.", regs); - kernel_mna_trap_fault(); + kernel_mna_trap_fault(0); } else { unsigned long addr, *reg_addr; - int orig_asi, asi, err; + int err; addr = compute_effective_address(regs, insn, ((insn >> 25) & 0x1f)); @@ -304,7 +334,6 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn) regs->tpc, dirstrings[dir], addr, size, regs->u_regs[UREG_RETPC]); #endif - orig_asi = asi = decode_asi(insn, regs); switch (asi) { case ASI_NL: case ASI_AIUPL: @@ -354,7 +383,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn) /* Not reached... */ } if (unlikely(err)) - kernel_mna_trap_fault(); + kernel_mna_trap_fault(1); else advance(regs); }