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 <[email protected]> know about it.
>From foo@baz Thu Aug 7 22:33:35 PDT 2014
From: "David S. Miller" <[email protected]>
Date: Mon, 28 Apr 2014 23:52:11 -0700
Subject: sparc64: Fix top-level fault handling bugs.
From: "David S. Miller" <[email protected]>
[ 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 <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
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 [email protected] 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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html