diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-02-04 15:54:00 (GMT) |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-02-04 15:54:00 (GMT) |
commit | 024bb9617e01716c5ac7d235f54483cc6018978f (patch) | |
tree | 995fa77058bb980b891ca7cbe383399e1e81a8cb /arch/sparc/mm/fault_64.c | |
parent | 25431e900dc47abb312c9ae8599e8c8ae038eb5a (diff) | |
parent | 9b02605826903203d5301049c1f52e722584785c (diff) | |
download | linux-fsl-qoriq-024bb9617e01716c5ac7d235f54483cc6018978f.tar.xz |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6:
sparc64: Kill bogus TPC/address truncation during 32-bit faults.
sparc: fixup for sparseirq changes
sparc64: Validate kernel generated fault addresses on sparc64.
sparc64: On non-Niagara, need to touch NMI watchdog in NOHZ mode.
sparc64: Implement NMI watchdog on capable cpus.
sparc: Probe PMU type and record in sparc_pmu_type.
sparc64: Move generic PCR support code to seperate file.
Diffstat (limited to 'arch/sparc/mm/fault_64.c')
-rw-r--r-- | arch/sparc/mm/fault_64.c | 44 |
1 files changed, 38 insertions, 6 deletions
diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c index a9e474b..4ab8993 100644 --- a/arch/sparc/mm/fault_64.c +++ b/arch/sparc/mm/fault_64.c @@ -19,6 +19,7 @@ #include <linux/interrupt.h> #include <linux/kprobes.h> #include <linux/kdebug.h> +#include <linux/percpu.h> #include <asm/page.h> #include <asm/pgtable.h> @@ -224,6 +225,30 @@ cannot_handle: unhandled_fault (address, current, regs); } +static void noinline bogus_32bit_fault_tpc(struct pt_regs *regs) +{ + static int times; + + if (times++ < 10) + printk(KERN_ERR "FAULT[%s:%d]: 32-bit process reports " + "64-bit TPC [%lx]\n", + current->comm, current->pid, + regs->tpc); + show_regs(regs); +} + +static void noinline bogus_32bit_fault_address(struct pt_regs *regs, + unsigned long addr) +{ + static int times; + + if (times++ < 10) + printk(KERN_ERR "FAULT[%s:%d]: 32-bit process " + "reports 64-bit fault address [%lx]\n", + current->comm, current->pid, addr); + show_regs(regs); +} + asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) { struct mm_struct *mm = current->mm; @@ -244,6 +269,19 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) (fault_code & FAULT_CODE_DTLB)) BUG(); + if (test_thread_flag(TIF_32BIT)) { + if (!(regs->tstate & TSTATE_PRIV)) { + if (unlikely((regs->tpc >> 32) != 0)) { + bogus_32bit_fault_tpc(regs); + goto intr_or_no_mm; + } + } + if (unlikely((address >> 32) != 0)) { + bogus_32bit_fault_address(regs, address); + goto intr_or_no_mm; + } + } + if (regs->tstate & TSTATE_PRIV) { unsigned long tpc = regs->tpc; @@ -264,12 +302,6 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) if (in_atomic() || !mm) goto intr_or_no_mm; - if (test_thread_flag(TIF_32BIT)) { - if (!(regs->tstate & TSTATE_PRIV)) - regs->tpc &= 0xffffffff; - address &= 0xffffffff; - } - if (!down_read_trylock(&mm->mmap_sem)) { if ((regs->tstate & TSTATE_PRIV) && !search_exception_tables(regs->tpc)) { |