This is a note to let you know that I've just added the patch titled sparc64: Fix top-level fault handling bugs. to the 3.4-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: sparc64-fix-top-level-fault-handling-bugs.patch and it can be found in the queue-3.4 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. >From foo@baz Thu Aug 7 22:33:35 PDT 2014 From: "David S. Miller" <davem@xxxxxxxxxxxxx> Date: Mon, 28 Apr 2014 23:52:11 -0700 Subject: sparc64: Fix top-level fault handling bugs. From: "David S. Miller" <davem@xxxxxxxxxxxxx> [ Upstream commit 70ffc6ebaead783ac8dafb1e87df0039bb043596 ] Make get_user_insn() able to cope with huge PMDs. Next, make do_fault_siginfo() more robust when get_user_insn() can't actually fetch the instruction. In particular, use the MMU announced fault address when that happens, instead of calling compute_effective_address() and computing garbage. Signed-off-by: David S. Miller <davem@xxxxxxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- arch/sparc/mm/fault_64.c | 84 +++++++++++++++++++++++++++++------------------ 1 file changed, 53 insertions(+), 31 deletions(-) --- a/arch/sparc/mm/fault_64.c +++ b/arch/sparc/mm/fault_64.c @@ -95,38 +95,51 @@ static unsigned int get_user_insn(unsign pte_t *ptep, pte; unsigned long pa; u32 insn = 0; - unsigned long pstate; - if (pgd_none(*pgdp)) - goto outret; + if (pgd_none(*pgdp) || unlikely(pgd_bad(*pgdp))) + goto out; pudp = pud_offset(pgdp, tpc); - if (pud_none(*pudp)) - goto outret; - pmdp = pmd_offset(pudp, tpc); - if (pmd_none(*pmdp)) - goto outret; - - /* This disables preemption for us as well. */ - __asm__ __volatile__("rdpr %%pstate, %0" : "=r" (pstate)); - __asm__ __volatile__("wrpr %0, %1, %%pstate" - : : "r" (pstate), "i" (PSTATE_IE)); - ptep = pte_offset_map(pmdp, tpc); - pte = *ptep; - if (!pte_present(pte)) + if (pud_none(*pudp) || unlikely(pud_bad(*pudp))) goto out; - pa = (pte_pfn(pte) << PAGE_SHIFT); - pa += (tpc & ~PAGE_MASK); + /* This disables preemption for us as well. */ + local_irq_disable(); - /* Use phys bypass so we don't pollute dtlb/dcache. */ - __asm__ __volatile__("lduwa [%1] %2, %0" - : "=r" (insn) - : "r" (pa), "i" (ASI_PHYS_USE_EC)); + pmdp = pmd_offset(pudp, tpc); + if (pmd_none(*pmdp) || unlikely(pmd_bad(*pmdp))) + goto out_irq_enable; +#ifdef CONFIG_TRANSPARENT_HUGEPAGE + if (pmd_trans_huge(*pmdp)) { + if (pmd_trans_splitting(*pmdp)) + goto out_irq_enable; + + pa = pmd_pfn(*pmdp) << PAGE_SHIFT; + pa += tpc & ~HPAGE_MASK; + + /* Use phys bypass so we don't pollute dtlb/dcache. */ + __asm__ __volatile__("lduwa [%1] %2, %0" + : "=r" (insn) + : "r" (pa), "i" (ASI_PHYS_USE_EC)); + } else +#endif + { + ptep = pte_offset_map(pmdp, tpc); + pte = *ptep; + if (pte_present(pte)) { + pa = (pte_pfn(pte) << PAGE_SHIFT); + pa += (tpc & ~PAGE_MASK); + + /* Use phys bypass so we don't pollute dtlb/dcache. */ + __asm__ __volatile__("lduwa [%1] %2, %0" + : "=r" (insn) + : "r" (pa), "i" (ASI_PHYS_USE_EC)); + } + pte_unmap(ptep); + } +out_irq_enable: + local_irq_enable(); out: - pte_unmap(ptep); - __asm__ __volatile__("wrpr %0, 0x0, %%pstate" : : "r" (pstate)); -outret: return insn; } @@ -154,7 +167,8 @@ show_signal_msg(struct pt_regs *regs, in extern unsigned long compute_effective_address(struct pt_regs *, unsigned int, unsigned int); static void do_fault_siginfo(int code, int sig, struct pt_regs *regs, - unsigned int insn, int fault_code) + unsigned long fault_addr, unsigned int insn, + int fault_code) { unsigned long addr; siginfo_t info; @@ -162,10 +176,18 @@ static void do_fault_siginfo(int code, i info.si_code = code; info.si_signo = sig; info.si_errno = 0; - if (fault_code & FAULT_CODE_ITLB) + if (fault_code & FAULT_CODE_ITLB) { addr = regs->tpc; - else - addr = compute_effective_address(regs, insn, 0); + } else { + /* If we were able to probe the faulting instruction, use it + * to compute a precise fault address. Otherwise use the fault + * time provided address which may only have page granularity. + */ + if (insn) + addr = compute_effective_address(regs, insn, 0); + else + addr = fault_addr; + } info.si_addr = (void __user *) addr; info.si_trapno = 0; @@ -240,7 +262,7 @@ static void __kprobes do_kernel_fault(st /* The si_code was set to make clear whether * this was a SEGV_MAPERR or SEGV_ACCERR fault. */ - do_fault_siginfo(si_code, SIGSEGV, regs, insn, fault_code); + do_fault_siginfo(si_code, SIGSEGV, regs, address, insn, fault_code); return; } @@ -515,7 +537,7 @@ do_sigbus: * Send a sigbus, regardless of whether we were in kernel * or user mode. */ - do_fault_siginfo(BUS_ADRERR, SIGBUS, regs, insn, fault_code); + do_fault_siginfo(BUS_ADRERR, SIGBUS, regs, address, insn, fault_code); /* Kernel mode? Handle exceptions or die */ if (regs->tstate & TSTATE_PRIV) Patches currently in stable-queue which might be from davem@xxxxxxxxxxxxx are queue-3.4/sparc64-add-membar-to-niagara2-memcpy-code.patch queue-3.4/ip-make-ip-identifiers-less-predictable.patch queue-3.4/sunsab-fix-detection-of-break-on-sunsab-serial-console.patch queue-3.4/tcp-fix-integer-overflow-in-tcp-vegas.patch queue-3.4/tcp-fix-integer-overflows-in-tcp-veno.patch queue-3.4/sparc64-fix-huge-tsb-mapping-on-pre-ultrasparc-iii-cpus.patch queue-3.4/sparc64-handle-32-bit-tasks-properly-in-compute_effective_address.patch queue-3.4/macvlan-initialize-vlan_features-to-turn-on-offload-support.patch queue-3.4/inetpeer-get-rid-of-ip_id_count.patch queue-3.4/arch-sparc-math-emu-math_32.c-drop-stray-break-operator.patch queue-3.4/sparc64-do-not-insert-non-valid-ptes-into-the-tsb-hash-table.patch queue-3.4/sparc64-fix-argument-sign-extension-for-compat_sys_futex.patch queue-3.4/bbc-i2c-fix-bbc-i2c-envctrl-on-sunblade-2000.patch queue-3.4/sparc64-guard-against-flushing-openfirmware-mappings.patch queue-3.4/sparc64-ldc_connect-should-not-return-einval-when-handshake-is-in-progress.patch queue-3.4/sparc64-fix-top-level-fault-handling-bugs.patch queue-3.4/sparc64-don-t-bark-so-loudly-about-32-bit-tasks-generating-64-bit-fault-addresses.patch queue-3.4/net-sendmsg-fix-null-pointer-dereference.patch queue-3.4/net-sctp-inherit-auth_capable-on-init-collisions.patch queue-3.4/sparc64-make-itc_sync_lock-raw.patch queue-3.4/sctp-fix-possible-seqlock-seadlock-in-sctp_packet_transmit.patch queue-3.4/iovec-make-sure-the-caller-actually-wants-anything-in-memcpy_fromiovecend.patch queue-3.4/net-correctly-set-segment-mac_len-in-skb_segment.patch -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html