]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.0-stable patches
authorGreg Kroah-Hartman <gregkh@suse.de>
Tue, 3 Jan 2012 20:13:33 +0000 (12:13 -0800)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 3 Jan 2012 20:13:33 +0000 (12:13 -0800)
added patches:
mpt2sas-crashes-on-shutdown.patch
sparc32-be-less-strict-in-matching-lo-part-of-relocation.patch
sparc32-correct-the-return-value-of-memcpy.patch
sparc32-remove-non-kernel-code-from-memcpy-implementation.patch
sparc32-remove-uses-of-g7-in-memcpy-implementation.patch
sparc64-fix-masking-and-shifting-in-vis-fpcmp-emulation.patch
sparc64-fix-msiq-hv-call-ordering-in-pci_sun4v_msiq_build_irq.patch
sparc64-patch-sun4v-code-sequences-properly-on-module-load.patch
sparc-fix-handling-of-orig_i0-wrt.-debugging-when-restarting-syscalls.patch
sparc-kill-custom-io_remap_pfn_range.patch

queue-3.0/mpt2sas-crashes-on-shutdown.patch [new file with mode: 0644]
queue-3.0/series
queue-3.0/sparc-fix-handling-of-orig_i0-wrt.-debugging-when-restarting-syscalls.patch [new file with mode: 0644]
queue-3.0/sparc-kill-custom-io_remap_pfn_range.patch [new file with mode: 0644]
queue-3.0/sparc32-be-less-strict-in-matching-lo-part-of-relocation.patch [new file with mode: 0644]
queue-3.0/sparc32-correct-the-return-value-of-memcpy.patch [new file with mode: 0644]
queue-3.0/sparc32-remove-non-kernel-code-from-memcpy-implementation.patch [new file with mode: 0644]
queue-3.0/sparc32-remove-uses-of-g7-in-memcpy-implementation.patch [new file with mode: 0644]
queue-3.0/sparc64-fix-masking-and-shifting-in-vis-fpcmp-emulation.patch [new file with mode: 0644]
queue-3.0/sparc64-fix-msiq-hv-call-ordering-in-pci_sun4v_msiq_build_irq.patch [new file with mode: 0644]
queue-3.0/sparc64-patch-sun4v-code-sequences-properly-on-module-load.patch [new file with mode: 0644]

diff --git a/queue-3.0/mpt2sas-crashes-on-shutdown.patch b/queue-3.0/mpt2sas-crashes-on-shutdown.patch
new file mode 100644 (file)
index 0000000..290c18a
--- /dev/null
@@ -0,0 +1,75 @@
+From davem@davemloft.net  Tue Jan  3 12:06:53 2012
+From: David Miller <davem@davemloft.net>
+Date: Mon, 26 Dec 2011 14:59:20 -0500 (EST)
+Subject: mpt2sas crashes on shutdown
+To: stable@vger.kernel.org
+Cc: linux-scsi@vger.kernel.org, nagalakshmi.nandigama@lsi.com
+Message-ID: <20111226.145920.1088076837634135764.davem@davemloft.net>
+
+From: David Miller <davem@davemloft.net>
+
+[Fixed differently in 3.2]
+
+The mpt2sas driver accesses I/O space as virtual addresses when
+saving and restoring the MSIX table, this only works by luck on x86.
+
+One needs to use the appropriate {read,write}{b,w,l}() APIs.
+
+This is fixed in v3.2.x because all of this code got rewritten for
+NUMA I/O support.
+
+But both 3.0.x and 3.1.x still have this bug, and my Niagara sparc
+machines crash on shutdown every single time due to this bug making my
+-stable work more difficult than it needs to be.
+
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Cc: Eric Moore <Eric.Moore@lsi.com>
+Cc: Nagalakshmi Nandigama <nagalakshmi.nandigama@lsi.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/scsi/mpt2sas/mpt2sas_base.c |    6 +++---
+ drivers/scsi/mpt2sas/mpt2sas_base.h |    2 +-
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
++++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
+@@ -1096,7 +1096,7 @@ _base_save_msix_table(struct MPT2SAS_ADA
+               return;
+       for (i = 0; i < ioc->msix_vector_count; i++)
+-              ioc->msix_table_backup[i] = ioc->msix_table[i];
++              ioc->msix_table_backup[i] = readl(&ioc->msix_table[i]);
+ }
+ /**
+@@ -1113,7 +1113,7 @@ _base_restore_msix_table(struct MPT2SAS_
+               return;
+       for (i = 0; i < ioc->msix_vector_count; i++)
+-              ioc->msix_table[i] = ioc->msix_table_backup[i];
++              writel(ioc->msix_table_backup[i], &ioc->msix_table[i]);
+ }
+ /**
+@@ -1144,7 +1144,7 @@ _base_check_enable_msix(struct MPT2SAS_A
+       /* get msix table  */
+       pci_read_config_dword(ioc->pdev, base + 4, &msix_table_offset);
+       msix_table_offset &= 0xFFFFFFF8;
+-      ioc->msix_table = (u32 *)((void *)ioc->chip + msix_table_offset);
++      ioc->msix_table = ((void __iomem *)ioc->chip + msix_table_offset);
+       dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "msix is supported, "
+           "vector_count(%d), table_offset(0x%08x), table(%p)\n", ioc->name,
+--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
++++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
+@@ -768,7 +768,7 @@ struct MPT2SAS_ADAPTER {
+       u8              msix_enable;
+       u16             msix_vector_count;
+-      u32             *msix_table;
++      u32 __iomem     *msix_table;
+       u32             *msix_table_backup;
+       u32             ioc_reset_count;
index 493f73d570490a34d8c2613c7a1cbbb736d7f2e2..08a268a0ecedc78c01423b239761a1f7f7bc7951 100644 (file)
@@ -38,3 +38,13 @@ futex-fix-uninterruptible-loop-due-to-gate_area.patch
 watchdog-hpwdt-changes-to-handle-nx-secure-bit-in-32bit-path.patch
 drm-radeon-kms-bail-on-btc-parts-if-mc-ucode-is-missing.patch
 mm-hugetlb-fix-non-atomic-enqueue-of-huge-page.patch
+mpt2sas-crashes-on-shutdown.patch
+sparc64-fix-msiq-hv-call-ordering-in-pci_sun4v_msiq_build_irq.patch
+sparc32-be-less-strict-in-matching-lo-part-of-relocation.patch
+sparc64-patch-sun4v-code-sequences-properly-on-module-load.patch
+sparc-kill-custom-io_remap_pfn_range.patch
+sparc32-remove-non-kernel-code-from-memcpy-implementation.patch
+sparc32-remove-uses-of-g7-in-memcpy-implementation.patch
+sparc32-correct-the-return-value-of-memcpy.patch
+sparc64-fix-masking-and-shifting-in-vis-fpcmp-emulation.patch
+sparc-fix-handling-of-orig_i0-wrt.-debugging-when-restarting-syscalls.patch
diff --git a/queue-3.0/sparc-fix-handling-of-orig_i0-wrt.-debugging-when-restarting-syscalls.patch b/queue-3.0/sparc-fix-handling-of-orig_i0-wrt.-debugging-when-restarting-syscalls.patch
new file mode 100644 (file)
index 0000000..3e0cd99
--- /dev/null
@@ -0,0 +1,179 @@
+From d16b87e22fe215f640a5a3e95dfd34d6ff182d7e Mon Sep 17 00:00:00 2001
+From: "David S. Miller" <davem@davemloft.net>
+Date: Mon, 26 Dec 2011 12:30:13 -0500
+Subject: sparc: Fix handling of orig_i0 wrt. debugging when restarting syscalls.
+
+
+From: "David S. Miller" <davem@davemloft.net>
+
+[ A combination of upstream commits 1d299bc7732c34d85bd43ac1a8745f5a2fed2078 and
+  e88d2468718b0789b4c33da2f7e1cef2a1eee279 ]
+
+Although we provide a proper way for a debugger to control whether
+syscall restart occurs, we run into problems because orig_i0 is not
+saved and restored properly.
+
+Luckily we can solve this problem without having to make debuggers
+aware of the issue.  Across system calls, several registers are
+considered volatile and can be safely clobbered.
+
+Therefore we use the pt_regs save area of one of those registers, %g6,
+as a place to save and restore orig_i0.
+
+Debuggers transparently will do the right thing because they save and
+restore this register already.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/sparc/kernel/signal32.c  |   18 ++++++++++--------
+ arch/sparc/kernel/signal_32.c |   30 +++++++++++++++++++++++++-----
+ arch/sparc/kernel/signal_64.c |   42 ++++++++++++++++++++++++++++--------------
+ 3 files changed, 63 insertions(+), 27 deletions(-)
+
+--- a/arch/sparc/kernel/signal32.c
++++ b/arch/sparc/kernel/signal32.c
+@@ -829,21 +829,23 @@ static inline void syscall_restart32(uns
+  * want to handle. Thus you cannot kill init even with a SIGKILL even by
+  * mistake.
+  */
+-void do_signal32(sigset_t *oldset, struct pt_regs * regs,
+-               int restart_syscall, unsigned long orig_i0)
++void do_signal32(sigset_t *oldset, struct pt_regs * regs)
+ {
+       struct k_sigaction ka;
++      unsigned long orig_i0;
++      int restart_syscall;
+       siginfo_t info;
+       int signr;
+       
+       signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+-      /* If the debugger messes with the program counter, it clears
+-       * the "in syscall" bit, directing us to not perform a syscall
+-       * restart.
+-       */
+-      if (restart_syscall && !pt_regs_is_syscall(regs))
+-              restart_syscall = 0;
++      restart_syscall = 0;
++      orig_i0 = 0;
++      if (pt_regs_is_syscall(regs) &&
++          (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
++              restart_syscall = 1;
++              orig_i0 = regs->u_regs[UREG_G6];
++      }
+       if (signr > 0) {
+               if (restart_syscall)
+--- a/arch/sparc/kernel/signal_32.c
++++ b/arch/sparc/kernel/signal_32.c
+@@ -525,10 +525,26 @@ static void do_signal(struct pt_regs *re
+       siginfo_t info;
+       int signr;
++      /* It's a lot of work and synchronization to add a new ptrace
++       * register for GDB to save and restore in order to get
++       * orig_i0 correct for syscall restarts when debugging.
++       *
++       * Although it should be the case that most of the global
++       * registers are volatile across a system call, glibc already
++       * depends upon that fact that we preserve them.  So we can't
++       * just use any global register to save away the orig_i0 value.
++       *
++       * In particular %g2, %g3, %g4, and %g5 are all assumed to be
++       * preserved across a system call trap by various pieces of
++       * code in glibc.
++       *
++       * %g7 is used as the "thread register".   %g6 is not used in
++       * any fixed manner.  %g6 is used as a scratch register and
++       * a compiler temporary, but it's value is never used across
++       * a system call.  Therefore %g6 is usable for orig_i0 storage.
++       */
+       if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C))
+-              restart_syscall = 1;
+-      else
+-              restart_syscall = 0;
++              regs->u_regs[UREG_G6] = orig_i0;
+       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+               oldset = &current->saved_sigmask;
+@@ -541,8 +557,12 @@ static void do_signal(struct pt_regs *re
+        * the software "in syscall" bit, directing us to not perform
+        * a syscall restart.
+        */
+-      if (restart_syscall && !pt_regs_is_syscall(regs))
+-              restart_syscall = 0;
++      restart_syscall = 0;
++      if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C)) {
++              restart_syscall = 1;
++              orig_i0 = regs->u_regs[UREG_G6];
++      }
++
+       if (signr > 0) {
+               if (restart_syscall)
+--- a/arch/sparc/kernel/signal_64.c
++++ b/arch/sparc/kernel/signal_64.c
+@@ -535,11 +535,27 @@ static void do_signal(struct pt_regs *re
+       siginfo_t info;
+       int signr;
+       
++      /* It's a lot of work and synchronization to add a new ptrace
++       * register for GDB to save and restore in order to get
++       * orig_i0 correct for syscall restarts when debugging.
++       *
++       * Although it should be the case that most of the global
++       * registers are volatile across a system call, glibc already
++       * depends upon that fact that we preserve them.  So we can't
++       * just use any global register to save away the orig_i0 value.
++       *
++       * In particular %g2, %g3, %g4, and %g5 are all assumed to be
++       * preserved across a system call trap by various pieces of
++       * code in glibc.
++       *
++       * %g7 is used as the "thread register".   %g6 is not used in
++       * any fixed manner.  %g6 is used as a scratch register and
++       * a compiler temporary, but it's value is never used across
++       * a system call.  Therefore %g6 is usable for orig_i0 storage.
++       */
+       if (pt_regs_is_syscall(regs) &&
+-          (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
+-              restart_syscall = 1;
+-      } else
+-              restart_syscall = 0;
++          (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY)))
++              regs->u_regs[UREG_G6] = orig_i0;
+       if (current_thread_info()->status & TS_RESTORE_SIGMASK)
+               oldset = &current->saved_sigmask;
+@@ -548,22 +564,20 @@ static void do_signal(struct pt_regs *re
+ #ifdef CONFIG_COMPAT
+       if (test_thread_flag(TIF_32BIT)) {
+-              extern void do_signal32(sigset_t *, struct pt_regs *,
+-                                      int restart_syscall,
+-                                      unsigned long orig_i0);
+-              do_signal32(oldset, regs, restart_syscall, orig_i0);
++              extern void do_signal32(sigset_t *, struct pt_regs *);
++              do_signal32(oldset, regs);
+               return;
+       }
+ #endif        
+       signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+-      /* If the debugger messes with the program counter, it clears
+-       * the software "in syscall" bit, directing us to not perform
+-       * a syscall restart.
+-       */
+-      if (restart_syscall && !pt_regs_is_syscall(regs))
+-              restart_syscall = 0;
++      restart_syscall = 0;
++      if (pt_regs_is_syscall(regs) &&
++          (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
++              restart_syscall = 1;
++              orig_i0 = regs->u_regs[UREG_G6];
++      }
+       if (signr > 0) {
+               if (restart_syscall)
diff --git a/queue-3.0/sparc-kill-custom-io_remap_pfn_range.patch b/queue-3.0/sparc-kill-custom-io_remap_pfn_range.patch
new file mode 100644 (file)
index 0000000..d4e7b31
--- /dev/null
@@ -0,0 +1,375 @@
+From 81f6423527575fc9b9ab9c79784078ba93ed8d31 Mon Sep 17 00:00:00 2001
+From: "David S. Miller" <davem@davemloft.net>
+Date: Thu, 17 Nov 2011 18:17:59 -0800
+Subject: sparc: Kill custom io_remap_pfn_range().
+
+
+From: "David S. Miller" <davem@davemloft.net>
+
+[ Upstream commit 3e37fd3153ac95088a74f5e7c569f7567e9f993a ]
+
+To handle the large physical addresses, just make a simple wrapper
+around remap_pfn_range() like MIPS does.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/sparc/include/asm/pgtable_32.h |   20 +++-
+ arch/sparc/include/asm/pgtable_64.h |   20 +++-
+ arch/sparc/mm/Makefile              |    1 
+ arch/sparc/mm/generic_32.c          |   98 ---------------------
+ arch/sparc/mm/generic_64.c          |  164 ------------------------------------
+ 5 files changed, 32 insertions(+), 271 deletions(-)
+ delete mode 100644 arch/sparc/mm/generic_32.c
+ delete mode 100644 arch/sparc/mm/generic_64.c
+
+--- a/arch/sparc/include/asm/pgtable_32.h
++++ b/arch/sparc/include/asm/pgtable_32.h
+@@ -431,10 +431,6 @@ extern unsigned long *sparc_valid_addr_b
+ #define kern_addr_valid(addr) \
+       (test_bit(__pa((unsigned long)(addr))>>20, sparc_valid_addr_bitmap))
+-extern int io_remap_pfn_range(struct vm_area_struct *vma,
+-                            unsigned long from, unsigned long pfn,
+-                            unsigned long size, pgprot_t prot);
+-
+ /*
+  * For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in
+  * its high 4 bits.  These macros/functions put it there or get it from there.
+@@ -443,6 +439,22 @@ extern int io_remap_pfn_range(struct vm_
+ #define GET_IOSPACE(pfn)              (pfn >> (BITS_PER_LONG - 4))
+ #define GET_PFN(pfn)                  (pfn & 0x0fffffffUL)
++extern int remap_pfn_range(struct vm_area_struct *, unsigned long, unsigned long,
++                         unsigned long, pgprot_t);
++
++static inline int io_remap_pfn_range(struct vm_area_struct *vma,
++                                   unsigned long from, unsigned long pfn,
++                                   unsigned long size, pgprot_t prot)
++{
++      unsigned long long offset, space, phys_base;
++
++      offset = ((unsigned long long) GET_PFN(pfn)) << PAGE_SHIFT;
++      space = GET_IOSPACE(pfn);
++      phys_base = offset | (space << 32ULL);
++
++      return remap_pfn_range(vma, from, phys_base >> PAGE_SHIFT, size, prot);
++}
++
+ #define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
+ #define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
+ ({                                                                      \
+--- a/arch/sparc/include/asm/pgtable_64.h
++++ b/arch/sparc/include/asm/pgtable_64.h
+@@ -750,10 +750,6 @@ static inline bool kern_addr_valid(unsig
+ extern int page_in_phys_avail(unsigned long paddr);
+-extern int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
+-                             unsigned long pfn,
+-                             unsigned long size, pgprot_t prot);
+-
+ /*
+  * For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in
+  * its high 4 bits.  These macros/functions put it there or get it from there.
+@@ -762,6 +758,22 @@ extern int io_remap_pfn_range(struct vm_
+ #define GET_IOSPACE(pfn)              (pfn >> (BITS_PER_LONG - 4))
+ #define GET_PFN(pfn)                  (pfn & 0x0fffffffffffffffUL)
++extern int remap_pfn_range(struct vm_area_struct *, unsigned long, unsigned long,
++                         unsigned long, pgprot_t);
++
++static inline int io_remap_pfn_range(struct vm_area_struct *vma,
++                                   unsigned long from, unsigned long pfn,
++                                   unsigned long size, pgprot_t prot)
++{
++      unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT;
++      int space = GET_IOSPACE(pfn);
++      unsigned long phys_base;
++
++      phys_base = offset | (((unsigned long) space) << 32UL);
++
++      return remap_pfn_range(vma, from, phys_base >> PAGE_SHIFT, size, prot);
++}
++
+ #include <asm-generic/pgtable.h>
+ /* We provide our own get_unmapped_area to cope with VA holes and
+--- a/arch/sparc/mm/Makefile
++++ b/arch/sparc/mm/Makefile
+@@ -8,7 +8,6 @@ obj-$(CONFIG_SPARC64)   += ultra.o tlb.o
+ obj-y                   += fault_$(BITS).o
+ obj-y                   += init_$(BITS).o
+ obj-$(CONFIG_SPARC32)   += loadmmu.o
+-obj-y                   += generic_$(BITS).o
+ obj-$(CONFIG_SPARC32)   += extable.o btfixup.o srmmu.o iommu.o io-unit.o
+ obj-$(CONFIG_SPARC32)   += hypersparc.o viking.o tsunami.o swift.o
+ obj-$(CONFIG_SPARC_LEON)+= leon_mm.o
+--- a/arch/sparc/mm/generic_32.c
++++ /dev/null
+@@ -1,98 +0,0 @@
+-/*
+- * generic.c: Generic Sparc mm routines that are not dependent upon
+- *            MMU type but are Sparc specific.
+- *
+- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/mm.h>
+-#include <linux/swap.h>
+-#include <linux/pagemap.h>
+-
+-#include <asm/pgalloc.h>
+-#include <asm/pgtable.h>
+-#include <asm/page.h>
+-#include <asm/cacheflush.h>
+-#include <asm/tlbflush.h>
+-
+-/* Remap IO memory, the same way as remap_pfn_range(), but use
+- * the obio memory space.
+- *
+- * They use a pgprot that sets PAGE_IO and does not check the
+- * mem_map table as this is independent of normal memory.
+- */
+-static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte, unsigned long address, unsigned long size,
+-      unsigned long offset, pgprot_t prot, int space)
+-{
+-      unsigned long end;
+-
+-      address &= ~PMD_MASK;
+-      end = address + size;
+-      if (end > PMD_SIZE)
+-              end = PMD_SIZE;
+-      do {
+-              set_pte_at(mm, address, pte, mk_pte_io(offset, prot, space));
+-              address += PAGE_SIZE;
+-              offset += PAGE_SIZE;
+-              pte++;
+-      } while (address < end);
+-}
+-
+-static inline int io_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
+-      unsigned long offset, pgprot_t prot, int space)
+-{
+-      unsigned long end;
+-
+-      address &= ~PGDIR_MASK;
+-      end = address + size;
+-      if (end > PGDIR_SIZE)
+-              end = PGDIR_SIZE;
+-      offset -= address;
+-      do {
+-              pte_t *pte = pte_alloc_map(mm, NULL, pmd, address);
+-              if (!pte)
+-                      return -ENOMEM;
+-              io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space);
+-              address = (address + PMD_SIZE) & PMD_MASK;
+-              pmd++;
+-      } while (address < end);
+-      return 0;
+-}
+-
+-int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
+-                     unsigned long pfn, unsigned long size, pgprot_t prot)
+-{
+-      int error = 0;
+-      pgd_t * dir;
+-      unsigned long beg = from;
+-      unsigned long end = from + size;
+-      struct mm_struct *mm = vma->vm_mm;
+-      int space = GET_IOSPACE(pfn);
+-      unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT;
+-
+-      /* See comment in mm/memory.c remap_pfn_range */
+-      vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP;
+-      vma->vm_pgoff = (offset >> PAGE_SHIFT) |
+-              ((unsigned long)space << 28UL);
+-
+-      offset -= from;
+-      dir = pgd_offset(mm, from);
+-      flush_cache_range(vma, beg, end);
+-
+-      while (from < end) {
+-              pmd_t *pmd = pmd_alloc(mm, dir, from);
+-              error = -ENOMEM;
+-              if (!pmd)
+-                      break;
+-              error = io_remap_pmd_range(mm, pmd, from, end - from, offset + from, prot, space);
+-              if (error)
+-                      break;
+-              from = (from + PGDIR_SIZE) & PGDIR_MASK;
+-              dir++;
+-      }
+-
+-      flush_tlb_range(vma, beg, end);
+-      return error;
+-}
+-EXPORT_SYMBOL(io_remap_pfn_range);
+--- a/arch/sparc/mm/generic_64.c
++++ /dev/null
+@@ -1,164 +0,0 @@
+-/*
+- * generic.c: Generic Sparc mm routines that are not dependent upon
+- *            MMU type but are Sparc specific.
+- *
+- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/mm.h>
+-#include <linux/swap.h>
+-#include <linux/pagemap.h>
+-
+-#include <asm/pgalloc.h>
+-#include <asm/pgtable.h>
+-#include <asm/page.h>
+-#include <asm/tlbflush.h>
+-
+-/* Remap IO memory, the same way as remap_pfn_range(), but use
+- * the obio memory space.
+- *
+- * They use a pgprot that sets PAGE_IO and does not check the
+- * mem_map table as this is independent of normal memory.
+- */
+-static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte,
+-                                    unsigned long address,
+-                                    unsigned long size,
+-                                    unsigned long offset, pgprot_t prot,
+-                                    int space)
+-{
+-      unsigned long end;
+-
+-      /* clear hack bit that was used as a write_combine side-effect flag */
+-      offset &= ~0x1UL;
+-      address &= ~PMD_MASK;
+-      end = address + size;
+-      if (end > PMD_SIZE)
+-              end = PMD_SIZE;
+-      do {
+-              pte_t entry;
+-              unsigned long curend = address + PAGE_SIZE;
+-              
+-              entry = mk_pte_io(offset, prot, space, PAGE_SIZE);
+-              if (!(address & 0xffff)) {
+-                      if (PAGE_SIZE < (4 * 1024 * 1024) &&
+-                          !(address & 0x3fffff) &&
+-                          !(offset & 0x3ffffe) &&
+-                          end >= address + 0x400000) {
+-                              entry = mk_pte_io(offset, prot, space,
+-                                                4 * 1024 * 1024);
+-                              curend = address + 0x400000;
+-                              offset += 0x400000;
+-                      } else if (PAGE_SIZE < (512 * 1024) &&
+-                                 !(address & 0x7ffff) &&
+-                                 !(offset & 0x7fffe) &&
+-                                 end >= address + 0x80000) {
+-                              entry = mk_pte_io(offset, prot, space,
+-                                                512 * 1024 * 1024);
+-                              curend = address + 0x80000;
+-                              offset += 0x80000;
+-                      } else if (PAGE_SIZE < (64 * 1024) &&
+-                                 !(offset & 0xfffe) &&
+-                                 end >= address + 0x10000) {
+-                              entry = mk_pte_io(offset, prot, space,
+-                                                64 * 1024);
+-                              curend = address + 0x10000;
+-                              offset += 0x10000;
+-                      } else
+-                              offset += PAGE_SIZE;
+-              } else
+-                      offset += PAGE_SIZE;
+-
+-              if (pte_write(entry))
+-                      entry = pte_mkdirty(entry);
+-              do {
+-                      BUG_ON(!pte_none(*pte));
+-                      set_pte_at(mm, address, pte, entry);
+-                      address += PAGE_SIZE;
+-                      pte_val(entry) += PAGE_SIZE;
+-                      pte++;
+-              } while (address < curend);
+-      } while (address < end);
+-}
+-
+-static inline int io_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
+-      unsigned long offset, pgprot_t prot, int space)
+-{
+-      unsigned long end;
+-
+-      address &= ~PGDIR_MASK;
+-      end = address + size;
+-      if (end > PGDIR_SIZE)
+-              end = PGDIR_SIZE;
+-      offset -= address;
+-      do {
+-              pte_t *pte = pte_alloc_map(mm, NULL, pmd, address);
+-              if (!pte)
+-                      return -ENOMEM;
+-              io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space);
+-              pte_unmap(pte);
+-              address = (address + PMD_SIZE) & PMD_MASK;
+-              pmd++;
+-      } while (address < end);
+-      return 0;
+-}
+-
+-static inline int io_remap_pud_range(struct mm_struct *mm, pud_t * pud, unsigned long address, unsigned long size,
+-      unsigned long offset, pgprot_t prot, int space)
+-{
+-      unsigned long end;
+-
+-      address &= ~PUD_MASK;
+-      end = address + size;
+-      if (end > PUD_SIZE)
+-              end = PUD_SIZE;
+-      offset -= address;
+-      do {
+-              pmd_t *pmd = pmd_alloc(mm, pud, address);
+-              if (!pud)
+-                      return -ENOMEM;
+-              io_remap_pmd_range(mm, pmd, address, end - address, address + offset, prot, space);
+-              address = (address + PUD_SIZE) & PUD_MASK;
+-              pud++;
+-      } while (address < end);
+-      return 0;
+-}
+-
+-int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
+-              unsigned long pfn, unsigned long size, pgprot_t prot)
+-{
+-      int error = 0;
+-      pgd_t * dir;
+-      unsigned long beg = from;
+-      unsigned long end = from + size;
+-      struct mm_struct *mm = vma->vm_mm;
+-      int space = GET_IOSPACE(pfn);
+-      unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT;
+-      unsigned long phys_base;
+-
+-      phys_base = offset | (((unsigned long) space) << 32UL);
+-
+-      /* See comment in mm/memory.c remap_pfn_range */
+-      vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP;
+-      vma->vm_pgoff = phys_base >> PAGE_SHIFT;
+-
+-      offset -= from;
+-      dir = pgd_offset(mm, from);
+-      flush_cache_range(vma, beg, end);
+-
+-      while (from < end) {
+-              pud_t *pud = pud_alloc(mm, dir, from);
+-              error = -ENOMEM;
+-              if (!pud)
+-                      break;
+-              error = io_remap_pud_range(mm, pud, from, end - from, offset + from, prot, space);
+-              if (error)
+-                      break;
+-              from = (from + PGDIR_SIZE) & PGDIR_MASK;
+-              dir++;
+-      }
+-
+-      flush_tlb_range(vma, beg, end);
+-      return error;
+-}
+-EXPORT_SYMBOL(io_remap_pfn_range);
diff --git a/queue-3.0/sparc32-be-less-strict-in-matching-lo-part-of-relocation.patch b/queue-3.0/sparc32-be-less-strict-in-matching-lo-part-of-relocation.patch
new file mode 100644 (file)
index 0000000..8af3f28
--- /dev/null
@@ -0,0 +1,33 @@
+From 8c8f38c77fccfe61501d26016b9c66c231a588ac Mon Sep 17 00:00:00 2001
+From: "David S. Miller" <davem@davemloft.net>
+Date: Wed, 14 Dec 2011 10:05:22 -0800
+Subject: sparc32: Be less strict in matching %lo part of relocation.
+
+
+From: "David S. Miller" <davem@davemloft.net>
+
+[ Upstream commit b1f44e13a525d2ffb7d5afe2273b7169d6f2222e ]
+
+The "(insn & 0x01800000) != 0x01800000" test matches 'restore'
+but that is a legitimate place to see the %lo() part of a 32-bit
+symbol relocation, particularly in tail calls.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Tested-by: Sergei Trofimovich <slyfox@gentoo.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/sparc/mm/btfixup.c |    3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/arch/sparc/mm/btfixup.c
++++ b/arch/sparc/mm/btfixup.c
+@@ -302,8 +302,7 @@ void __init btfixup(void)
+                               case 'i':       /* INT */
+                                       if ((insn & 0xc1c00000) == 0x01000000) /* %HI */
+                                               set_addr(addr, q[1], fmangled, (insn & 0xffc00000) | (p[1] >> 10));
+-                                      else if ((insn & 0x80002000) == 0x80002000 &&
+-                                               (insn & 0x01800000) != 0x01800000) /* %LO */
++                                      else if ((insn & 0x80002000) == 0x80002000) /* %LO */
+                                               set_addr(addr, q[1], fmangled, (insn & 0xffffe000) | (p[1] & 0x3ff));
+                                       else {
+                                               prom_printf(insn_i, p, addr, insn);
diff --git a/queue-3.0/sparc32-correct-the-return-value-of-memcpy.patch b/queue-3.0/sparc32-correct-the-return-value-of-memcpy.patch
new file mode 100644 (file)
index 0000000..afba5c3
--- /dev/null
@@ -0,0 +1,99 @@
+From 45b26bff9ac2a8df2239ed5ed90b092f1a7d033c Mon Sep 17 00:00:00 2001
+From: "David S. Miller" <davem@davemloft.net>
+Date: Wed, 19 Oct 2011 15:31:55 -0700
+Subject: sparc32: Correct the return value of memcpy.
+
+
+From: "David S. Miller" <davem@davemloft.net>
+
+[ Upstream commit a52312b88c8103e965979a79a07f6b34af82ca4b ]
+
+Properly return the original destination buffer pointer.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Tested-by: Kjetil Oftedal <oftedal@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/sparc/lib/memcpy.S |   22 +++++++---------------
+ 1 file changed, 7 insertions(+), 15 deletions(-)
+
+--- a/arch/sparc/lib/memcpy.S
++++ b/arch/sparc/lib/memcpy.S
+@@ -13,14 +13,6 @@
+       .align  4;              \
+ x:
+-
+-/* In kernel these functions don't return a value.
+- * One should use macros in asm/string.h for that purpose.
+- * We return 0, so that bugs are more apparent.
+- */
+-#define SETUP_RETL
+-#define RETL_INSN     clr     %o0
+-
+ /* Both these macros have to start with exactly the same insn */
+ #define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \
+       ldd     [%src + (offset) + 0x00], %t0; \
+@@ -154,7 +146,7 @@ FUNC(__memmove)
+ #endif
+ FUNC(memmove)
+       cmp             %o0, %o1
+-      SETUP_RETL
++      mov             %o0, %g7
+       bleu            9f
+        sub            %o0, %o1, %o4
+@@ -178,7 +170,7 @@ FUNC(memmove)
+        sub            %o0, 1, %o0
+       retl
+-       RETL_INSN
++       mov            %g7, %o0
+ /* NOTE: This code is executed just for the cases,
+          where %src (=%o1) & 3 is != 0.
+@@ -212,7 +204,7 @@ FUNC(memmove)
+ FUNC(memcpy)  /* %o0=dst %o1=src %o2=len */
+       sub             %o0, %o1, %o4
+-      SETUP_RETL
++      mov             %o0, %g7
+ 9:
+       andcc           %o4, 3, %o5
+ 0:
+@@ -308,7 +300,7 @@ FUNC(memcpy)       /* %o0=dst %o1=src %o2=len
+       stb             %g2, [%o0]
+ 1:
+       retl
+-       RETL_INSN
++       mov            %g7, %o0
+ 82:   /* ldd_std */
+       MOVE_BIGALIGNCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
+@@ -373,7 +365,7 @@ FUNC(memcpy)       /* %o0=dst %o1=src %o2=len
+       stb             %g2, [%o0]
+ 1:
+       retl
+-       RETL_INSN
++       mov            %g7, %o0
+ 86:   /* non_aligned */
+       cmp             %o2, 6
+@@ -498,7 +490,7 @@ FUNC(memcpy)       /* %o0=dst %o1=src %o2=len
+       stb             %g2, [%i0 + 4]
+ 1:
+       ret
+-       restore        %g0, %g0, %o0
++       restore        %g7, %g0, %o0
+ 88:   /* short_end */
+@@ -529,7 +521,7 @@ FUNC(memcpy)       /* %o0=dst %o1=src %o2=len
+       stb             %g2, [%o0]
+ 1:
+       retl
+-       RETL_INSN
++       mov            %g7, %o0
+ 90:   /* short_aligned_end */
+       bne             88b
diff --git a/queue-3.0/sparc32-remove-non-kernel-code-from-memcpy-implementation.patch b/queue-3.0/sparc32-remove-non-kernel-code-from-memcpy-implementation.patch
new file mode 100644 (file)
index 0000000..0e69836
--- /dev/null
@@ -0,0 +1,689 @@
+From b1f1286b491efd1a217bea6a74461b08692d511d Mon Sep 17 00:00:00 2001
+From: "David S. Miller" <davem@davemloft.net>
+Date: Wed, 19 Oct 2011 15:15:58 -0700
+Subject: sparc32: Remove non-kernel code from memcpy implementation.
+
+
+From: "David S. Miller" <davem@davemloft.net>
+
+[ Upstream commit 045b7de9ca0cf09f1adc3efa467f668b89238390 ]
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Tested-by: Kjetil Oftedal <oftedal@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/sparc/lib/memcpy.S |  607 ------------------------------------------------
+ 1 file changed, 2 insertions(+), 605 deletions(-)
+
+--- a/arch/sparc/lib/memcpy.S
++++ b/arch/sparc/lib/memcpy.S
+@@ -7,17 +7,12 @@
+  * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+  */
+-#ifdef __KERNEL__
+-
+-#define FUNC(x)                                                                                       \
++#define FUNC(x)               \
+       .globl  x;              \
+       .type   x,@function;    \
+-      .align  4;                                                                                      \
++      .align  4;              \
+ x:
+-#undef FASTER_REVERSE
+-#undef FASTER_NONALIGNED
+-#define FASTER_ALIGNED
+ /* In kernel these functions don't return a value.
+  * One should use macros in asm/string.h for that purpose.
+@@ -26,21 +21,6 @@ x:
+ #define SETUP_RETL
+ #define RETL_INSN     clr     %o0
+-#else
+-
+-/* libc */
+-
+-#include "DEFS.h"
+-
+-#define FASTER_REVERSE
+-#define FASTER_NONALIGNED
+-#define FASTER_ALIGNED
+-
+-#define SETUP_RETL    mov     %o0, %g6
+-#define RETL_INSN     mov     %g6, %o0
+-
+-#endif
+-
+ /* Both these macros have to start with exactly the same insn */
+ #define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \
+       ldd     [%src + (offset) + 0x00], %t0; \
+@@ -164,30 +144,6 @@ x:
+       .text
+       .align  4
+-#ifdef FASTER_REVERSE
+-
+-70:   /* rdword_align */
+-
+-      andcc           %o1, 1, %g0
+-      be              4f
+-       andcc          %o1, 2, %g0
+-
+-      ldub            [%o1 - 1], %g2
+-      sub             %o1, 1, %o1
+-      stb             %g2, [%o0 - 1]
+-      sub             %o2, 1, %o2
+-      be              3f
+-       sub            %o0, 1, %o0
+-4:
+-      lduh            [%o1 - 2], %g2
+-      sub             %o1, 2, %o1
+-      sth             %g2, [%o0 - 2]
+-      sub             %o2, 2, %o2
+-      b               3f
+-       sub            %o0, 2, %o0
+-
+-#endif /* FASTER_REVERSE */
+-
+ 0:
+       retl
+        nop            ! Only bcopy returns here and it retuns void...
+@@ -207,8 +163,6 @@ FUNC(memmove)
+       bleu            0f
+        andcc          %o4, 3, %o5
+-#ifndef FASTER_REVERSE
+-
+       add             %o1, %o2, %o1
+       add             %o0, %o2, %o0
+       sub             %o1, 1, %o1
+@@ -226,294 +180,6 @@ FUNC(memmove)
+       retl
+        RETL_INSN
+-#else /* FASTER_REVERSE */
+-
+-      add             %o1, %o2, %o1
+-      add             %o0, %o2, %o0
+-      bne             77f
+-       cmp            %o2, 15
+-      bleu            91f
+-       andcc          %o1, 3, %g0
+-      bne             70b
+-3:
+-       andcc          %o1, 4, %g0
+-
+-      be              2f
+-       mov            %o2, %g1
+-
+-      ld              [%o1 - 4], %o4
+-      sub             %g1, 4, %g1
+-      st              %o4, [%o0 - 4]
+-      sub             %o1, 4, %o1
+-      sub             %o0, 4, %o0
+-2:
+-      andcc           %g1, 0xffffff80, %g7
+-      be              3f
+-       andcc          %o0, 4, %g0
+-
+-      be              74f + 4
+-5:
+-      RMOVE_BIGCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
+-      RMOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
+-      RMOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
+-      RMOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
+-      subcc           %g7, 128, %g7
+-      sub             %o1, 128, %o1
+-      bne             5b
+-       sub            %o0, 128, %o0
+-3:
+-      andcc           %g1, 0x70, %g7
+-      be              72f
+-       andcc          %g1, 8, %g0
+-
+-      sethi           %hi(72f), %o5
+-      srl             %g7, 1, %o4
+-      add             %g7, %o4, %o4
+-      sub             %o1, %g7, %o1
+-      sub             %o5, %o4, %o5
+-      jmpl            %o5 + %lo(72f), %g0
+-       sub            %o0, %g7, %o0
+-
+-71:   /* rmemcpy_table */
+-      RMOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g4, g5)
+-      RMOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g4, g5)
+-      RMOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g4, g5)
+-      RMOVE_LASTCHUNK(o1, o0, 0x30, g2, g3, g4, g5)
+-      RMOVE_LASTCHUNK(o1, o0, 0x20, g2, g3, g4, g5)
+-      RMOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g4, g5)
+-      RMOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g4, g5)
+-
+-72:   /* rmemcpy_table_end */
+-
+-      be              73f
+-       andcc          %g1, 4, %g0
+-
+-      ldd             [%o1 - 0x08], %g2
+-      sub             %o0, 8, %o0
+-      sub             %o1, 8, %o1
+-      st              %g2, [%o0]
+-      st              %g3, [%o0 + 0x04]
+-
+-73:   /* rmemcpy_last7 */
+-
+-      be              1f
+-       andcc          %g1, 2, %g0
+-
+-      ld              [%o1 - 4], %g2
+-      sub             %o1, 4, %o1
+-      st              %g2, [%o0 - 4]
+-      sub             %o0, 4, %o0
+-1:
+-      be              1f
+-       andcc          %g1, 1, %g0
+-
+-      lduh            [%o1 - 2], %g2
+-      sub             %o1, 2, %o1
+-      sth             %g2, [%o0 - 2]
+-      sub             %o0, 2, %o0
+-1:
+-      be              1f
+-       nop
+-
+-      ldub            [%o1 - 1], %g2
+-      stb             %g2, [%o0 - 1]
+-1:
+-      retl
+-       RETL_INSN
+-
+-74:   /* rldd_std */
+-      RMOVE_BIGALIGNCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
+-      RMOVE_BIGALIGNCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
+-      RMOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
+-      RMOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
+-      subcc           %g7, 128, %g7
+-      sub             %o1, 128, %o1
+-      bne             74b
+-       sub            %o0, 128, %o0
+-
+-      andcc           %g1, 0x70, %g7
+-      be              72b
+-       andcc          %g1, 8, %g0
+-
+-      sethi           %hi(72b), %o5
+-      srl             %g7, 1, %o4
+-      add             %g7, %o4, %o4
+-      sub             %o1, %g7, %o1
+-      sub             %o5, %o4, %o5
+-      jmpl            %o5 + %lo(72b), %g0
+-       sub            %o0, %g7, %o0
+-
+-75:   /* rshort_end */
+-
+-      and             %o2, 0xe, %o3
+-2:
+-      sethi           %hi(76f), %o5
+-      sll             %o3, 3, %o4
+-      sub             %o0, %o3, %o0
+-      sub             %o5, %o4, %o5
+-      sub             %o1, %o3, %o1
+-      jmpl            %o5 + %lo(76f), %g0
+-       andcc          %o2, 1, %g0
+-
+-      RMOVE_SHORTCHUNK(o1, o0, 0x0c, g2, g3)
+-      RMOVE_SHORTCHUNK(o1, o0, 0x0a, g2, g3)
+-      RMOVE_SHORTCHUNK(o1, o0, 0x08, g2, g3)
+-      RMOVE_SHORTCHUNK(o1, o0, 0x06, g2, g3)
+-      RMOVE_SHORTCHUNK(o1, o0, 0x04, g2, g3)
+-      RMOVE_SHORTCHUNK(o1, o0, 0x02, g2, g3)
+-      RMOVE_SHORTCHUNK(o1, o0, 0x00, g2, g3)
+-
+-76:   /* rshort_table_end */
+-
+-      be              1f
+-       nop
+-      ldub            [%o1 - 1], %g2
+-      stb             %g2, [%o0 - 1]
+-1:
+-      retl
+-       RETL_INSN
+-
+-91:   /* rshort_aligned_end */
+-
+-      bne             75b
+-       andcc          %o2, 8, %g0
+-
+-      be              1f
+-       andcc          %o2, 4, %g0
+-
+-      ld              [%o1 - 0x08], %g2
+-      ld              [%o1 - 0x04], %g3
+-      sub             %o1, 8, %o1
+-      st              %g2, [%o0 - 0x08]
+-      st              %g3, [%o0 - 0x04]
+-      sub             %o0, 8, %o0
+-1:
+-      b               73b
+-       mov            %o2, %g1
+-
+-77:   /* rnon_aligned */
+-      cmp             %o2, 15
+-      bleu            75b
+-       andcc          %o0, 3, %g0
+-      be              64f
+-       andcc          %o0, 1, %g0
+-      be              63f
+-       andcc          %o0, 2, %g0
+-      ldub            [%o1 - 1], %g5
+-      sub             %o1, 1, %o1
+-      stb             %g5, [%o0 - 1]
+-      sub             %o0, 1, %o0
+-      be              64f
+-       sub            %o2, 1, %o2
+-63:
+-      ldub            [%o1 - 1], %g5
+-      sub             %o1, 2, %o1
+-      stb             %g5, [%o0 - 1]
+-      sub             %o0, 2, %o0
+-      ldub            [%o1], %g5
+-      sub             %o2, 2, %o2
+-      stb             %g5, [%o0]
+-64:   
+-      and             %o1, 3, %g2
+-      and             %o1, -4, %o1
+-      and             %o2, 0xc, %g3
+-      add             %o1, 4, %o1
+-      cmp             %g3, 4
+-      sll             %g2, 3, %g4
+-      mov             32, %g2
+-      be              4f
+-       sub            %g2, %g4, %g7
+-
+-      blu             3f
+-       cmp            %g3, 8
+-
+-      be              2f
+-       srl            %o2, 2, %g3
+-
+-      ld              [%o1 - 4], %o3
+-      add             %o0, -8, %o0
+-      ld              [%o1 - 8], %o4
+-      add             %o1, -16, %o1
+-      b               7f
+-       add            %g3, 1, %g3
+-2:
+-      ld              [%o1 - 4], %o4
+-      add             %o0, -4, %o0
+-      ld              [%o1 - 8], %g1
+-      add             %o1, -12, %o1
+-      b               8f
+-       add            %g3, 2, %g3
+-3:
+-      ld              [%o1 - 4], %o5
+-      add             %o0, -12, %o0
+-      ld              [%o1 - 8], %o3
+-      add             %o1, -20, %o1
+-      b               6f
+-       srl            %o2, 2, %g3
+-4:
+-      ld              [%o1 - 4], %g1
+-      srl             %o2, 2, %g3
+-      ld              [%o1 - 8], %o5
+-      add             %o1, -24, %o1
+-      add             %o0, -16, %o0
+-      add             %g3, -1, %g3
+-
+-      ld              [%o1 + 12], %o3
+-5:
+-      sll             %o5, %g4, %g2
+-      srl             %g1, %g7, %g5
+-      or              %g2, %g5, %g2
+-      st              %g2, [%o0 + 12]
+-6:
+-      ld              [%o1 + 8], %o4
+-      sll             %o3, %g4, %g2
+-      srl             %o5, %g7, %g5
+-      or              %g2, %g5, %g2
+-      st              %g2, [%o0 + 8]
+-7:
+-      ld              [%o1 + 4], %g1
+-      sll             %o4, %g4, %g2
+-      srl             %o3, %g7, %g5
+-      or              %g2, %g5, %g2
+-      st              %g2, [%o0 + 4]
+-8:
+-      ld              [%o1], %o5
+-      sll             %g1, %g4, %g2
+-      srl             %o4, %g7, %g5
+-      addcc           %g3, -4, %g3
+-      or              %g2, %g5, %g2
+-      add             %o1, -16, %o1
+-      st              %g2, [%o0]
+-      add             %o0, -16, %o0
+-      bne,a           5b      
+-       ld             [%o1 + 12], %o3
+-      sll             %o5, %g4, %g2
+-      srl             %g1, %g7, %g5
+-      srl             %g4, 3, %g3
+-      or              %g2, %g5, %g2
+-      add             %o1, %g3, %o1
+-      andcc           %o2, 2, %g0
+-      st              %g2, [%o0 + 12]
+-      be              1f
+-       andcc          %o2, 1, %g0
+-      
+-      ldub            [%o1 + 15], %g5
+-      add             %o1, -2, %o1
+-      stb             %g5, [%o0 + 11]
+-      add             %o0, -2, %o0
+-      ldub            [%o1 + 16], %g5
+-      stb             %g5, [%o0 + 12]
+-1:
+-      be              1f
+-       nop
+-      ldub            [%o1 + 15], %g5
+-      stb             %g5, [%o0 + 11]
+-1:
+-      retl
+-       RETL_INSN
+-
+-#endif /* FASTER_REVERSE */
+-
+ /* NOTE: This code is executed just for the cases,
+          where %src (=%o1) & 3 is != 0.
+        We need to align it to 4. So, for (%src & 3)
+@@ -653,22 +319,6 @@ FUNC(memcpy)      /* %o0=dst %o1=src %o2=len
+       bne             82b
+        add            %o0, 128, %o0
+-#ifndef FASTER_ALIGNED
+-
+-      andcc           %g1, 0x70, %g7
+-      be              80b
+-       andcc          %g1, 8, %g0
+-
+-      sethi           %hi(80b), %o5
+-      srl             %g7, 1, %o4
+-      add             %g7, %o4, %o4
+-      add             %o1, %g7, %o1
+-      sub             %o5, %o4, %o5
+-      jmpl            %o5 + %lo(80b), %g0
+-       add            %o0, %g7, %o0
+-
+-#else /* FASTER_ALIGNED */
+-
+       andcc           %g1, 0x70, %g7
+       be              84f
+        andcc          %g1, 8, %g0
+@@ -723,19 +373,9 @@ FUNC(memcpy)      /* %o0=dst %o1=src %o2=len
+       retl
+        RETL_INSN
+-#endif /* FASTER_ALIGNED */
+-
+ 86:   /* non_aligned */
+       cmp             %o2, 6
+       bleu            88f
+-
+-#ifdef FASTER_NONALIGNED
+-
+-       cmp            %o2, 256
+-      bcc             87f
+-
+-#endif /* FASTER_NONALIGNED */
+-
+        andcc          %o0, 3, %g0
+       be              61f
+        andcc          %o0, 1, %g0
+@@ -855,249 +495,6 @@ FUNC(memcpy)     /* %o0=dst %o1=src %o2=len
+       retl
+        RETL_INSN
+-#ifdef FASTER_NONALIGNED
+-
+-87:   /* faster_nonaligned */
+-
+-      andcc           %o1, 3, %g0
+-      be              3f
+-       andcc          %o1, 1, %g0
+-
+-      be              4f
+-       andcc          %o1, 2, %g0
+-
+-      ldub            [%o1], %g2
+-      add             %o1, 1, %o1
+-      stb             %g2, [%o0]
+-      sub             %o2, 1, %o2
+-      bne             3f
+-       add            %o0, 1, %o0
+-4:
+-      lduh            [%o1], %g2
+-      add             %o1, 2, %o1
+-      srl             %g2, 8, %g3
+-      sub             %o2, 2, %o2
+-      stb             %g3, [%o0]
+-      add             %o0, 2, %o0
+-      stb             %g2, [%o0 - 1]
+-3:
+-       andcc          %o1, 4, %g0
+-
+-      bne             2f
+-       cmp            %o5, 1
+-
+-      ld              [%o1], %o4
+-      srl             %o4, 24, %g2
+-      stb             %g2, [%o0]
+-      srl             %o4, 16, %g3
+-      stb             %g3, [%o0 + 1]
+-      srl             %o4, 8, %g2
+-      stb             %g2, [%o0 + 2]
+-      sub             %o2, 4, %o2
+-      stb             %o4, [%o0 + 3]
+-      add             %o1, 4, %o1
+-      add             %o0, 4, %o0
+-2:
+-      be              33f
+-       cmp            %o5, 2
+-      be              32f
+-       sub            %o2, 4, %o2
+-31:
+-      ld              [%o1], %g2
+-      add             %o1, 4, %o1
+-      srl             %g2, 24, %g3
+-      and             %o0, 7, %g5
+-      stb             %g3, [%o0]
+-      cmp             %g5, 7
+-      sll             %g2, 8, %g1
+-      add             %o0, 4, %o0
+-      be              41f
+-       and            %o2, 0xffffffc0, %o3
+-      ld              [%o0 - 7], %o4
+-4:
+-      SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
+-      SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
+-      SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
+-      SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
+-      subcc           %o3, 64, %o3
+-      add             %o1, 64, %o1
+-      bne             4b
+-       add            %o0, 64, %o0
+-
+-      andcc           %o2, 0x30, %o3
+-      be,a            1f
+-       srl            %g1, 16, %g2
+-4:
+-      SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
+-      subcc           %o3, 16, %o3
+-      add             %o1, 16, %o1
+-      bne             4b
+-       add            %o0, 16, %o0
+-
+-      srl             %g1, 16, %g2
+-1:
+-      st              %o4, [%o0 - 7]
+-      sth             %g2, [%o0 - 3]
+-      srl             %g1, 8, %g4
+-      b               88f
+-       stb            %g4, [%o0 - 1]
+-32:
+-      ld              [%o1], %g2
+-      add             %o1, 4, %o1
+-      srl             %g2, 16, %g3
+-      and             %o0, 7, %g5
+-      sth             %g3, [%o0]
+-      cmp             %g5, 6
+-      sll             %g2, 16, %g1
+-      add             %o0, 4, %o0
+-      be              42f
+-       and            %o2, 0xffffffc0, %o3
+-      ld              [%o0 - 6], %o4
+-4:
+-      SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
+-      SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
+-      SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
+-      SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
+-      subcc           %o3, 64, %o3
+-      add             %o1, 64, %o1
+-      bne             4b
+-       add            %o0, 64, %o0
+-
+-      andcc           %o2, 0x30, %o3
+-      be,a            1f
+-       srl            %g1, 16, %g2
+-4:
+-      SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
+-      subcc           %o3, 16, %o3
+-      add             %o1, 16, %o1
+-      bne             4b
+-       add            %o0, 16, %o0
+-
+-      srl             %g1, 16, %g2
+-1:
+-      st              %o4, [%o0 - 6]
+-      b               88f
+-       sth            %g2, [%o0 - 2]
+-33:
+-      ld              [%o1], %g2
+-      sub             %o2, 4, %o2
+-      srl             %g2, 24, %g3
+-      and             %o0, 7, %g5
+-      stb             %g3, [%o0]
+-      cmp             %g5, 5
+-      srl             %g2, 8, %g4
+-      sll             %g2, 24, %g1
+-      sth             %g4, [%o0 + 1]
+-      add             %o1, 4, %o1
+-      be              43f
+-       and            %o2, 0xffffffc0, %o3
+-
+-      ld              [%o0 - 1], %o4
+-      add             %o0, 4, %o0
+-4:
+-      SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
+-      SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
+-      SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
+-      SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
+-      subcc           %o3, 64, %o3
+-      add             %o1, 64, %o1
+-      bne             4b
+-       add            %o0, 64, %o0
+-
+-      andcc           %o2, 0x30, %o3
+-      be,a            1f
+-       srl            %g1, 24, %g2
+-4:
+-      SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
+-      subcc           %o3, 16, %o3
+-      add             %o1, 16, %o1
+-      bne             4b
+-       add            %o0, 16, %o0
+-
+-      srl             %g1, 24, %g2
+-1:
+-      st              %o4, [%o0 - 5]
+-      b               88f
+-       stb            %g2, [%o0 - 1]
+-41:
+-      SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
+-      SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
+-      SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
+-      SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
+-      subcc           %o3, 64, %o3
+-      add             %o1, 64, %o1
+-      bne             41b
+-       add            %o0, 64, %o0
+-       
+-      andcc           %o2, 0x30, %o3
+-      be,a            1f
+-       srl            %g1, 16, %g2
+-4:
+-      SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
+-      subcc           %o3, 16, %o3
+-      add             %o1, 16, %o1
+-      bne             4b
+-       add            %o0, 16, %o0
+-
+-      srl             %g1, 16, %g2
+-1:
+-      sth             %g2, [%o0 - 3]
+-      srl             %g1, 8, %g4
+-      b               88f
+-       stb            %g4, [%o0 - 1]
+-43:
+-      SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
+-      SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
+-      SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
+-      SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
+-      subcc           %o3, 64, %o3
+-      add             %o1, 64, %o1
+-      bne             43b
+-       add            %o0, 64, %o0
+-
+-      andcc           %o2, 0x30, %o3
+-      be,a            1f
+-       srl            %g1, 24, %g2
+-4:
+-      SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
+-      subcc           %o3, 16, %o3
+-      add             %o1, 16, %o1
+-      bne             4b
+-       add            %o0, 16, %o0
+-
+-      srl             %g1, 24, %g2
+-1:
+-      stb             %g2, [%o0 + 3]
+-      b               88f
+-       add            %o0, 4, %o0
+-42:
+-      SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
+-      SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
+-      SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
+-      SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
+-      subcc           %o3, 64, %o3
+-      add             %o1, 64, %o1
+-      bne             42b
+-       add            %o0, 64, %o0
+-       
+-      andcc           %o2, 0x30, %o3
+-      be,a            1f
+-       srl            %g1, 16, %g2
+-4:
+-      SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
+-      subcc           %o3, 16, %o3
+-      add             %o1, 16, %o1
+-      bne             4b
+-       add            %o0, 16, %o0
+-
+-      srl             %g1, 16, %g2
+-1:
+-      sth             %g2, [%o0 - 2]
+-
+-      /* Fall through */
+-       
+-#endif /* FASTER_NONALIGNED */
+-
+ 88:   /* short_end */
+       and             %o2, 0xe, %o3
diff --git a/queue-3.0/sparc32-remove-uses-of-g7-in-memcpy-implementation.patch b/queue-3.0/sparc32-remove-uses-of-g7-in-memcpy-implementation.patch
new file mode 100644 (file)
index 0000000..4b14a62
--- /dev/null
@@ -0,0 +1,291 @@
+From 2e5dbd43a1c674f1d82c22b8c4070172882024b8 Mon Sep 17 00:00:00 2001
+From: "David S. Miller" <davem@davemloft.net>
+Date: Wed, 19 Oct 2011 15:30:14 -0700
+Subject: sparc32: Remove uses of %g7 in memcpy implementation.
+
+
+From: "David S. Miller" <davem@davemloft.net>
+
+[ Upstream commit 21f74d361dfd6a7d0e47574e315f780d8172084a ]
+
+This is setting things up so that we can correct the return
+value, so that it properly returns the original destination
+buffer pointer.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Tested-by: Kjetil Oftedal <oftedal@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/sparc/lib/memcpy.S |  177 ++++++++++++++++++++++++------------------------
+ 1 file changed, 91 insertions(+), 86 deletions(-)
+
+--- a/arch/sparc/lib/memcpy.S
++++ b/arch/sparc/lib/memcpy.S
+@@ -235,7 +235,7 @@ FUNC(memcpy)       /* %o0=dst %o1=src %o2=len
+       add             %o1, 4, %o1
+       add             %o0, 4, %o0
+ 2:
+-      andcc           %g1, 0xffffff80, %g7
++      andcc           %g1, 0xffffff80, %g0
+       be              3f
+        andcc          %o0, 4, %g0
+@@ -245,22 +245,23 @@ FUNC(memcpy)     /* %o0=dst %o1=src %o2=len
+       MOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
+       MOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
+       MOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
+-      subcc           %g7, 128, %g7
++      sub             %g1, 128, %g1
+       add             %o1, 128, %o1
+-      bne             5b
++      cmp             %g1, 128
++      bge             5b
+        add            %o0, 128, %o0
+ 3:
+-      andcc           %g1, 0x70, %g7
++      andcc           %g1, 0x70, %g4
+       be              80f
+        andcc          %g1, 8, %g0
+       sethi           %hi(80f), %o5
+-      srl             %g7, 1, %o4
+-      add             %g7, %o4, %o4
+-      add             %o1, %g7, %o1
++      srl             %g4, 1, %o4
++      add             %g4, %o4, %o4
++      add             %o1, %g4, %o1
+       sub             %o5, %o4, %o5
+       jmpl            %o5 + %lo(80f), %g0
+-       add            %o0, %g7, %o0
++       add            %o0, %g4, %o0
+ 79:   /* memcpy_table */
+@@ -314,20 +315,21 @@ FUNC(memcpy)     /* %o0=dst %o1=src %o2=len
+       MOVE_BIGALIGNCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
+       MOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
+       MOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
+-      subcc           %g7, 128, %g7
++      subcc           %g1, 128, %g1
+       add             %o1, 128, %o1
+-      bne             82b
++      cmp             %g1, 128
++      bge             82b
+        add            %o0, 128, %o0
+-      andcc           %g1, 0x70, %g7
++      andcc           %g1, 0x70, %g4
+       be              84f
+        andcc          %g1, 8, %g0
+       sethi           %hi(84f), %o5
+-      add             %o1, %g7, %o1
+-      sub             %o5, %g7, %o5
++      add             %o1, %g4, %o1
++      sub             %o5, %g4, %o5
+       jmpl            %o5 + %lo(84f), %g0
+-       add            %o0, %g7, %o0
++       add            %o0, %g4, %o0
+ 83:   /* amemcpy_table */
+@@ -376,124 +378,127 @@ FUNC(memcpy)   /* %o0=dst %o1=src %o2=len
+ 86:   /* non_aligned */
+       cmp             %o2, 6
+       bleu            88f
+-       andcc          %o0, 3, %g0
++       nop
++
++      save            %sp, -96, %sp
++      andcc           %i0, 3, %g0
+       be              61f
+-       andcc          %o0, 1, %g0
++       andcc          %i0, 1, %g0
+       be              60f
+-       andcc          %o0, 2, %g0
++       andcc          %i0, 2, %g0
+-      ldub            [%o1], %g5
+-      add             %o1, 1, %o1
+-      stb             %g5, [%o0]
+-      sub             %o2, 1, %o2
++      ldub            [%i1], %g5
++      add             %i1, 1, %i1
++      stb             %g5, [%i0]
++      sub             %i2, 1, %i2
+       bne             61f
+-       add            %o0, 1, %o0
++       add            %i0, 1, %i0
+ 60:
+-      ldub            [%o1], %g3
+-      add             %o1, 2, %o1
+-      stb             %g3, [%o0]
+-      sub             %o2, 2, %o2
+-      ldub            [%o1 - 1], %g3
+-      add             %o0, 2, %o0
+-      stb             %g3, [%o0 - 1]
++      ldub            [%i1], %g3
++      add             %i1, 2, %i1
++      stb             %g3, [%i0]
++      sub             %i2, 2, %i2
++      ldub            [%i1 - 1], %g3
++      add             %i0, 2, %i0
++      stb             %g3, [%i0 - 1]
+ 61:
+-      and             %o1, 3, %g2
+-      and             %o2, 0xc, %g3
+-      and             %o1, -4, %o1
++      and             %i1, 3, %g2
++      and             %i2, 0xc, %g3
++      and             %i1, -4, %i1
+       cmp             %g3, 4
+       sll             %g2, 3, %g4
+       mov             32, %g2
+       be              4f
+-       sub            %g2, %g4, %g7
++       sub            %g2, %g4, %l0
+       
+       blu             3f
+        cmp            %g3, 0x8
+       be              2f
+-       srl            %o2, 2, %g3
++       srl            %i2, 2, %g3
+-      ld              [%o1], %o3
+-      add             %o0, -8, %o0
+-      ld              [%o1 + 4], %o4
++      ld              [%i1], %i3
++      add             %i0, -8, %i0
++      ld              [%i1 + 4], %i4
+       b               8f
+        add            %g3, 1, %g3
+ 2:
+-      ld              [%o1], %o4
+-      add             %o0, -12, %o0
+-      ld              [%o1 + 4], %o5
++      ld              [%i1], %i4
++      add             %i0, -12, %i0
++      ld              [%i1 + 4], %i5
+       add             %g3, 2, %g3
+       b               9f
+-       add            %o1, -4, %o1
++       add            %i1, -4, %i1
+ 3:
+-      ld              [%o1], %g1
+-      add             %o0, -4, %o0
+-      ld              [%o1 + 4], %o3
+-      srl             %o2, 2, %g3
++      ld              [%i1], %g1
++      add             %i0, -4, %i0
++      ld              [%i1 + 4], %i3
++      srl             %i2, 2, %g3
+       b               7f
+-       add            %o1, 4, %o1
++       add            %i1, 4, %i1
+ 4:
+-      ld              [%o1], %o5
+-      cmp             %o2, 7
+-      ld              [%o1 + 4], %g1
+-      srl             %o2, 2, %g3
++      ld              [%i1], %i5
++      cmp             %i2, 7
++      ld              [%i1 + 4], %g1
++      srl             %i2, 2, %g3
+       bleu            10f
+-       add            %o1, 8, %o1
++       add            %i1, 8, %i1
+-      ld              [%o1], %o3
++      ld              [%i1], %i3
+       add             %g3, -1, %g3
+ 5:
+-      sll             %o5, %g4, %g2
+-      srl             %g1, %g7, %g5
++      sll             %i5, %g4, %g2
++      srl             %g1, %l0, %g5
+       or              %g2, %g5, %g2
+-      st              %g2, [%o0]
++      st              %g2, [%i0]
+ 7:
+-      ld              [%o1 + 4], %o4
++      ld              [%i1 + 4], %i4
+       sll             %g1, %g4, %g2
+-      srl             %o3, %g7, %g5
++      srl             %i3, %l0, %g5
+       or              %g2, %g5, %g2
+-      st              %g2, [%o0 + 4]
++      st              %g2, [%i0 + 4]
+ 8:
+-      ld              [%o1 + 8], %o5
+-      sll             %o3, %g4, %g2
+-      srl             %o4, %g7, %g5
++      ld              [%i1 + 8], %i5
++      sll             %i3, %g4, %g2
++      srl             %i4, %l0, %g5
+       or              %g2, %g5, %g2
+-      st              %g2, [%o0 + 8]
++      st              %g2, [%i0 + 8]
+ 9:
+-      ld              [%o1 + 12], %g1
+-      sll             %o4, %g4, %g2
+-      srl             %o5, %g7, %g5
++      ld              [%i1 + 12], %g1
++      sll             %i4, %g4, %g2
++      srl             %i5, %l0, %g5
+       addcc           %g3, -4, %g3
+       or              %g2, %g5, %g2
+-      add             %o1, 16, %o1
+-      st              %g2, [%o0 + 12]
+-      add             %o0, 16, %o0
++      add             %i1, 16, %i1
++      st              %g2, [%i0 + 12]
++      add             %i0, 16, %i0
+       bne,a           5b
+-       ld             [%o1], %o3
++       ld             [%i1], %i3
+ 10:
+-      sll             %o5, %g4, %g2
+-      srl             %g1, %g7, %g5
+-      srl             %g7, 3, %g3
++      sll             %i5, %g4, %g2
++      srl             %g1, %l0, %g5
++      srl             %l0, 3, %g3
+       or              %g2, %g5, %g2
+-      sub             %o1, %g3, %o1
+-      andcc           %o2, 2, %g0
+-      st              %g2, [%o0]
++      sub             %i1, %g3, %i1
++      andcc           %i2, 2, %g0
++      st              %g2, [%i0]
+       be              1f
+-       andcc          %o2, 1, %g0
++       andcc          %i2, 1, %g0
+-      ldub            [%o1], %g2
+-      add             %o1, 2, %o1
+-      stb             %g2, [%o0 + 4]
+-      add             %o0, 2, %o0
+-      ldub            [%o1 - 1], %g2
+-      stb             %g2, [%o0 + 3]
++      ldub            [%i1], %g2
++      add             %i1, 2, %i1
++      stb             %g2, [%i0 + 4]
++      add             %i0, 2, %i0
++      ldub            [%i1 - 1], %g2
++      stb             %g2, [%i0 + 3]
+ 1:
+       be              1f
+        nop
+-      ldub            [%o1], %g2
+-      stb             %g2, [%o0 + 4]
++      ldub            [%i1], %g2
++      stb             %g2, [%i0 + 4]
+ 1:
+-      retl
+-       RETL_INSN
++      ret
++       restore        %g0, %g0, %o0
+ 88:   /* short_end */
diff --git a/queue-3.0/sparc64-fix-masking-and-shifting-in-vis-fpcmp-emulation.patch b/queue-3.0/sparc64-fix-masking-and-shifting-in-vis-fpcmp-emulation.patch
new file mode 100644 (file)
index 0000000..ab374ea
--- /dev/null
@@ -0,0 +1,106 @@
+From ff3f6f646f6eba78b05cc38af922782bd1b8712f Mon Sep 17 00:00:00 2001
+From: "David S. Miller" <davem@davemloft.net>
+Date: Mon, 31 Oct 2011 01:05:49 -0700
+Subject: sparc64: Fix masking and shifting in VIS fpcmp emulation.
+
+
+From: "David S. Miller" <davem@davemloft.net>
+
+[ Upstream commit 2e8ecdc008a16b9a6c4b9628bb64d0d1c05f9f92 ]
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/sparc/kernel/visemul.c |   32 ++++++++++++++++----------------
+ 1 file changed, 16 insertions(+), 16 deletions(-)
+
+--- a/arch/sparc/kernel/visemul.c
++++ b/arch/sparc/kernel/visemul.c
+@@ -713,17 +713,17 @@ static void pcmp(struct pt_regs *regs, u
+                       s16 b = (rs2 >> (i * 16)) & 0xffff;
+                       if (a > b)
+-                              rd_val |= 1 << i;
++                              rd_val |= 8 >> i;
+               }
+               break;
+       case FCMPGT32_OPF:
+               for (i = 0; i < 2; i++) {
+-                      s32 a = (rs1 >> (i * 32)) & 0xffff;
+-                      s32 b = (rs2 >> (i * 32)) & 0xffff;
++                      s32 a = (rs1 >> (i * 32)) & 0xffffffff;
++                      s32 b = (rs2 >> (i * 32)) & 0xffffffff;
+                       if (a > b)
+-                              rd_val |= 1 << i;
++                              rd_val |= 2 >> i;
+               }
+               break;
+@@ -733,17 +733,17 @@ static void pcmp(struct pt_regs *regs, u
+                       s16 b = (rs2 >> (i * 16)) & 0xffff;
+                       if (a <= b)
+-                              rd_val |= 1 << i;
++                              rd_val |= 8 >> i;
+               }
+               break;
+       case FCMPLE32_OPF:
+               for (i = 0; i < 2; i++) {
+-                      s32 a = (rs1 >> (i * 32)) & 0xffff;
+-                      s32 b = (rs2 >> (i * 32)) & 0xffff;
++                      s32 a = (rs1 >> (i * 32)) & 0xffffffff;
++                      s32 b = (rs2 >> (i * 32)) & 0xffffffff;
+                       if (a <= b)
+-                              rd_val |= 1 << i;
++                              rd_val |= 2 >> i;
+               }
+               break;
+@@ -753,17 +753,17 @@ static void pcmp(struct pt_regs *regs, u
+                       s16 b = (rs2 >> (i * 16)) & 0xffff;
+                       if (a != b)
+-                              rd_val |= 1 << i;
++                              rd_val |= 8 >> i;
+               }
+               break;
+       case FCMPNE32_OPF:
+               for (i = 0; i < 2; i++) {
+-                      s32 a = (rs1 >> (i * 32)) & 0xffff;
+-                      s32 b = (rs2 >> (i * 32)) & 0xffff;
++                      s32 a = (rs1 >> (i * 32)) & 0xffffffff;
++                      s32 b = (rs2 >> (i * 32)) & 0xffffffff;
+                       if (a != b)
+-                              rd_val |= 1 << i;
++                              rd_val |= 2 >> i;
+               }
+               break;
+@@ -773,17 +773,17 @@ static void pcmp(struct pt_regs *regs, u
+                       s16 b = (rs2 >> (i * 16)) & 0xffff;
+                       if (a == b)
+-                              rd_val |= 1 << i;
++                              rd_val |= 8 >> i;
+               }
+               break;
+       case FCMPEQ32_OPF:
+               for (i = 0; i < 2; i++) {
+-                      s32 a = (rs1 >> (i * 32)) & 0xffff;
+-                      s32 b = (rs2 >> (i * 32)) & 0xffff;
++                      s32 a = (rs1 >> (i * 32)) & 0xffffffff;
++                      s32 b = (rs2 >> (i * 32)) & 0xffffffff;
+                       if (a == b)
+-                              rd_val |= 1 << i;
++                              rd_val |= 2 >> i;
+               }
+               break;
+       }
diff --git a/queue-3.0/sparc64-fix-msiq-hv-call-ordering-in-pci_sun4v_msiq_build_irq.patch b/queue-3.0/sparc64-fix-msiq-hv-call-ordering-in-pci_sun4v_msiq_build_irq.patch
new file mode 100644 (file)
index 0000000..fb87195
--- /dev/null
@@ -0,0 +1,44 @@
+From 485b01a81c3c41501c3b6c30e0899713a9bbb6a1 Mon Sep 17 00:00:00 2001
+From: "David S. Miller" <davem@davemloft.net>
+Date: Thu, 22 Dec 2011 13:23:59 -0800
+Subject: sparc64: Fix MSIQ HV call ordering in pci_sun4v_msiq_build_irq().
+
+
+From: "David S. Miller" <davem@davemloft.net>
+
+[ Upstream commit 7cc8583372a21d98a23b703ad96cab03180b5030 ]
+
+This silently was working for many years and stopped working on
+Niagara-T3 machines.
+
+We need to set the MSIQ to VALID before we can set it's state to IDLE.
+
+On Niagara-T3, setting the state to IDLE first was causing HV_EINVAL
+errors.  The hypervisor documentation says, rather ambiguously, that
+the MSIQ must be "initialized" before one can set the state.
+
+I previously understood this to mean merely that a successful setconf()
+operation has been performed on the MSIQ, which we have done at this
+point.  But it seems to also mean that it has been set VALID too.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/sparc/kernel/pci_sun4v.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/sparc/kernel/pci_sun4v.c
++++ b/arch/sparc/kernel/pci_sun4v.c
+@@ -848,10 +848,10 @@ static int pci_sun4v_msiq_build_irq(stru
+       if (!irq)
+               return -ENOMEM;
+-      if (pci_sun4v_msiq_setstate(pbm->devhandle, msiqid, HV_MSIQSTATE_IDLE))
+-              return -EINVAL;
+       if (pci_sun4v_msiq_setvalid(pbm->devhandle, msiqid, HV_MSIQ_VALID))
+               return -EINVAL;
++      if (pci_sun4v_msiq_setstate(pbm->devhandle, msiqid, HV_MSIQSTATE_IDLE))
++              return -EINVAL;
+       return irq;
+ }
diff --git a/queue-3.0/sparc64-patch-sun4v-code-sequences-properly-on-module-load.patch b/queue-3.0/sparc64-patch-sun4v-code-sequences-properly-on-module-load.patch
new file mode 100644 (file)
index 0000000..b3466f2
--- /dev/null
@@ -0,0 +1,168 @@
+From 0c84d92038fa2b130475b11044772c0b8f0e6f89 Mon Sep 17 00:00:00 2001
+From: "David S. Miller" <davem@davemloft.net>
+Date: Thu, 17 Nov 2011 22:44:58 -0800
+Subject: sparc64: Patch sun4v code sequences properly on module load.
+
+
+From: "David S. Miller" <davem@davemloft.net>
+
+[ Upstream commit 0b64120cceb86e93cb1bda0dc055f13016646907 ]
+
+Some of the sun4v code patching occurs in inline functions visible
+to, and usable by, modules.
+
+Therefore we have to patch them up during module load.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/sparc/kernel/entry.h    |    7 ++++++
+ arch/sparc/kernel/module.c   |   27 ++++++++++++++++++++++++
+ arch/sparc/kernel/setup_64.c |   48 +++++++++++++++++++++++++------------------
+ 3 files changed, 63 insertions(+), 19 deletions(-)
+
+--- a/arch/sparc/kernel/entry.h
++++ b/arch/sparc/kernel/entry.h
+@@ -42,6 +42,9 @@ extern void fpsave(unsigned long *fpregs
+ extern void fpload(unsigned long *fpregs, unsigned long *fsr);
+ #else /* CONFIG_SPARC32 */
++
++#include <asm/trap_block.h>
++
+ struct popc_3insn_patch_entry {
+       unsigned int    addr;
+       unsigned int    insns[3];
+@@ -57,6 +60,10 @@ extern struct popc_6insn_patch_entry __p
+       __popc_6insn_patch_end;
+ extern void __init per_cpu_patch(void);
++extern void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *,
++                                  struct sun4v_1insn_patch_entry *);
++extern void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *,
++                                  struct sun4v_2insn_patch_entry *);
+ extern void __init sun4v_patch(void);
+ extern void __init boot_cpu_id_too_large(int cpu);
+ extern unsigned int dcache_parity_tl1_occurred;
+--- a/arch/sparc/kernel/module.c
++++ b/arch/sparc/kernel/module.c
+@@ -17,6 +17,8 @@
+ #include <asm/processor.h>
+ #include <asm/spitfire.h>
++#include "entry.h"
++
+ #ifdef CONFIG_SPARC64
+ #include <linux/jump_label.h>
+@@ -220,6 +222,29 @@ int apply_relocate_add(Elf_Shdr *sechdrs
+ }
+ #ifdef CONFIG_SPARC64
++static void do_patch_sections(const Elf_Ehdr *hdr,
++                            const Elf_Shdr *sechdrs)
++{
++      const Elf_Shdr *s, *sun4v_1insn = NULL, *sun4v_2insn = NULL;
++      char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
++
++      for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
++              if (!strcmp(".sun4v_1insn_patch", secstrings + s->sh_name))
++                      sun4v_1insn = s;
++              if (!strcmp(".sun4v_2insn_patch", secstrings + s->sh_name))
++                      sun4v_2insn = s;
++      }
++
++      if (sun4v_1insn && tlb_type == hypervisor) {
++              void *p = (void *) sun4v_1insn->sh_addr;
++              sun4v_patch_1insn_range(p, p + sun4v_1insn->sh_size);
++      }
++      if (sun4v_2insn && tlb_type == hypervisor) {
++              void *p = (void *) sun4v_2insn->sh_addr;
++              sun4v_patch_2insn_range(p, p + sun4v_2insn->sh_size);
++      }
++}
++
+ int module_finalize(const Elf_Ehdr *hdr,
+                   const Elf_Shdr *sechdrs,
+                   struct module *me)
+@@ -227,6 +252,8 @@ int module_finalize(const Elf_Ehdr *hdr,
+       /* make jump label nops */
+       jump_label_apply_nops(me);
++      do_patch_sections(hdr, sechdrs);
++
+       /* Cheetah's I-cache is fully coherent.  */
+       if (tlb_type == spitfire) {
+               unsigned long va;
+--- a/arch/sparc/kernel/setup_64.c
++++ b/arch/sparc/kernel/setup_64.c
+@@ -234,40 +234,50 @@ void __init per_cpu_patch(void)
+       }
+ }
+-void __init sun4v_patch(void)
++void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *start,
++                           struct sun4v_1insn_patch_entry *end)
+ {
+-      extern void sun4v_hvapi_init(void);
+-      struct sun4v_1insn_patch_entry *p1;
+-      struct sun4v_2insn_patch_entry *p2;
+-
+-      if (tlb_type != hypervisor)
+-              return;
++      while (start < end) {
++              unsigned long addr = start->addr;
+-      p1 = &__sun4v_1insn_patch;
+-      while (p1 < &__sun4v_1insn_patch_end) {
+-              unsigned long addr = p1->addr;
+-
+-              *(unsigned int *) (addr +  0) = p1->insn;
++              *(unsigned int *) (addr +  0) = start->insn;
+               wmb();
+               __asm__ __volatile__("flush     %0" : : "r" (addr +  0));
+-              p1++;
++              start++;
+       }
++}
+-      p2 = &__sun4v_2insn_patch;
+-      while (p2 < &__sun4v_2insn_patch_end) {
+-              unsigned long addr = p2->addr;
++void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *start,
++                           struct sun4v_2insn_patch_entry *end)
++{
++      while (start < end) {
++              unsigned long addr = start->addr;
+-              *(unsigned int *) (addr +  0) = p2->insns[0];
++              *(unsigned int *) (addr +  0) = start->insns[0];
+               wmb();
+               __asm__ __volatile__("flush     %0" : : "r" (addr +  0));
+-              *(unsigned int *) (addr +  4) = p2->insns[1];
++              *(unsigned int *) (addr +  4) = start->insns[1];
+               wmb();
+               __asm__ __volatile__("flush     %0" : : "r" (addr +  4));
+-              p2++;
++              start++;
+       }
++}
++
++void __init sun4v_patch(void)
++{
++      extern void sun4v_hvapi_init(void);
++
++      if (tlb_type != hypervisor)
++              return;
++
++      sun4v_patch_1insn_range(&__sun4v_1insn_patch,
++                              &__sun4v_1insn_patch_end);
++
++      sun4v_patch_2insn_range(&__sun4v_2insn_patch,
++                              &__sun4v_2insn_patch_end);
+       sun4v_hvapi_init();
+ }