diff options
| -rw-r--r-- | arch/sparc/mm/fault_64.c | 49 |
1 files changed, 35 insertions, 14 deletions
diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c index 1a786abdada3..4ab8993b0863 100644 --- a/arch/sparc/mm/fault_64.c +++ b/arch/sparc/mm/fault_64.c | |||
| @@ -225,6 +225,30 @@ cannot_handle: | |||
| 225 | unhandled_fault (address, current, regs); | 225 | unhandled_fault (address, current, regs); |
| 226 | } | 226 | } |
| 227 | 227 | ||
| 228 | static void noinline bogus_32bit_fault_tpc(struct pt_regs *regs) | ||
| 229 | { | ||
| 230 | static int times; | ||
| 231 | |||
| 232 | if (times++ < 10) | ||
| 233 | printk(KERN_ERR "FAULT[%s:%d]: 32-bit process reports " | ||
| 234 | "64-bit TPC [%lx]\n", | ||
| 235 | current->comm, current->pid, | ||
| 236 | regs->tpc); | ||
| 237 | show_regs(regs); | ||
| 238 | } | ||
| 239 | |||
| 240 | static void noinline bogus_32bit_fault_address(struct pt_regs *regs, | ||
| 241 | unsigned long addr) | ||
| 242 | { | ||
| 243 | static int times; | ||
| 244 | |||
| 245 | if (times++ < 10) | ||
| 246 | printk(KERN_ERR "FAULT[%s:%d]: 32-bit process " | ||
| 247 | "reports 64-bit fault address [%lx]\n", | ||
| 248 | current->comm, current->pid, addr); | ||
| 249 | show_regs(regs); | ||
| 250 | } | ||
| 251 | |||
| 228 | asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) | 252 | asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) |
| 229 | { | 253 | { |
| 230 | struct mm_struct *mm = current->mm; | 254 | struct mm_struct *mm = current->mm; |
| @@ -246,13 +270,20 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) | |||
| 246 | BUG(); | 270 | BUG(); |
| 247 | 271 | ||
| 248 | if (test_thread_flag(TIF_32BIT)) { | 272 | if (test_thread_flag(TIF_32BIT)) { |
| 249 | if (!(regs->tstate & TSTATE_PRIV)) | 273 | if (!(regs->tstate & TSTATE_PRIV)) { |
| 250 | regs->tpc &= 0xffffffff; | 274 | if (unlikely((regs->tpc >> 32) != 0)) { |
| 251 | address &= 0xffffffff; | 275 | bogus_32bit_fault_tpc(regs); |
| 276 | goto intr_or_no_mm; | ||
| 277 | } | ||
| 278 | } | ||
| 279 | if (unlikely((address >> 32) != 0)) { | ||
| 280 | bogus_32bit_fault_address(regs, address); | ||
| 281 | goto intr_or_no_mm; | ||
| 282 | } | ||
| 252 | } | 283 | } |
| 253 | 284 | ||
| 254 | if (regs->tstate & TSTATE_PRIV) { | 285 | if (regs->tstate & TSTATE_PRIV) { |
| 255 | unsigned long eaddr, tpc = regs->tpc; | 286 | unsigned long tpc = regs->tpc; |
| 256 | 287 | ||
| 257 | /* Sanity check the PC. */ | 288 | /* Sanity check the PC. */ |
| 258 | if ((tpc >= KERNBASE && tpc < (unsigned long) __init_end) || | 289 | if ((tpc >= KERNBASE && tpc < (unsigned long) __init_end) || |
| @@ -262,16 +293,6 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) | |||
| 262 | bad_kernel_pc(regs, address); | 293 | bad_kernel_pc(regs, address); |
| 263 | return; | 294 | return; |
| 264 | } | 295 | } |
| 265 | |||
| 266 | insn = get_fault_insn(regs, insn); | ||
| 267 | eaddr = compute_effective_address(regs, insn, 0); | ||
| 268 | if (WARN_ON_ONCE((eaddr & PAGE_MASK) != (address & PAGE_MASK))){ | ||
| 269 | printk(KERN_ERR "FAULT: Mismatch kernel fault " | ||
| 270 | "address: addr[%lx] eaddr[%lx] TPC[%lx]\n", | ||
| 271 | address, eaddr, tpc); | ||
| 272 | show_regs(regs); | ||
| 273 | goto handle_kernel_fault; | ||
| 274 | } | ||
| 275 | } | 296 | } |
| 276 | 297 | ||
| 277 | /* | 298 | /* |
