From: Greg Kroah-Hartman Date: Tue, 3 Jan 2012 20:13:33 +0000 (-0800) Subject: 3.0-stable patches X-Git-Tag: v3.1.8~8 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b73ab79a4c6a8cb838391cd1899cb21cca04d2aa;p=thirdparty%2Fkernel%2Fstable-queue.git 3.0-stable patches 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 --- diff --git a/queue-3.0/mpt2sas-crashes-on-shutdown.patch b/queue-3.0/mpt2sas-crashes-on-shutdown.patch new file mode 100644 index 00000000000..290c18a3fac --- /dev/null +++ b/queue-3.0/mpt2sas-crashes-on-shutdown.patch @@ -0,0 +1,75 @@ +From davem@davemloft.net Tue Jan 3 12:06:53 2012 +From: David Miller +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 + +[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 +Cc: Eric Moore +Cc: Nagalakshmi Nandigama +Signed-off-by: Greg Kroah-Hartman + +--- + 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; + diff --git a/queue-3.0/series b/queue-3.0/series index 493f73d5704..08a268a0ece 100644 --- a/queue-3.0/series +++ b/queue-3.0/series @@ -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 index 00000000000..3e0cd99433b --- /dev/null +++ b/queue-3.0/sparc-fix-handling-of-orig_i0-wrt.-debugging-when-restarting-syscalls.patch @@ -0,0 +1,179 @@ +From d16b87e22fe215f640a5a3e95dfd34d6ff182d7e Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +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" + +[ 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 +Signed-off-by: Greg Kroah-Hartman +--- + 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 = ¤t->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 = ¤t->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 index 00000000000..d4e7b31d3c3 --- /dev/null +++ b/queue-3.0/sparc-kill-custom-io_remap_pfn_range.patch @@ -0,0 +1,375 @@ +From 81f6423527575fc9b9ab9c79784078ba93ed8d31 Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +Date: Thu, 17 Nov 2011 18:17:59 -0800 +Subject: sparc: Kill custom io_remap_pfn_range(). + + +From: "David S. Miller" + +[ 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 +Signed-off-by: Greg Kroah-Hartman +--- + 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 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 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 + + /* 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 +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include +- +-/* 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 +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +- +-/* 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 index 00000000000..8af3f286de2 --- /dev/null +++ b/queue-3.0/sparc32-be-less-strict-in-matching-lo-part-of-relocation.patch @@ -0,0 +1,33 @@ +From 8c8f38c77fccfe61501d26016b9c66c231a588ac Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +Date: Wed, 14 Dec 2011 10:05:22 -0800 +Subject: sparc32: Be less strict in matching %lo part of relocation. + + +From: "David S. Miller" + +[ 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 +Tested-by: Sergei Trofimovich +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..afba5c33f95 --- /dev/null +++ b/queue-3.0/sparc32-correct-the-return-value-of-memcpy.patch @@ -0,0 +1,99 @@ +From 45b26bff9ac2a8df2239ed5ed90b092f1a7d033c Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +Date: Wed, 19 Oct 2011 15:31:55 -0700 +Subject: sparc32: Correct the return value of memcpy. + + +From: "David S. Miller" + +[ Upstream commit a52312b88c8103e965979a79a07f6b34af82ca4b ] + +Properly return the original destination buffer pointer. + +Signed-off-by: David S. Miller +Tested-by: Kjetil Oftedal +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..0e698363082 --- /dev/null +++ b/queue-3.0/sparc32-remove-non-kernel-code-from-memcpy-implementation.patch @@ -0,0 +1,689 @@ +From b1f1286b491efd1a217bea6a74461b08692d511d Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +Date: Wed, 19 Oct 2011 15:15:58 -0700 +Subject: sparc32: Remove non-kernel code from memcpy implementation. + + +From: "David S. Miller" + +[ Upstream commit 045b7de9ca0cf09f1adc3efa467f668b89238390 ] + +Signed-off-by: David S. Miller +Tested-by: Kjetil Oftedal +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..4b14a62ea42 --- /dev/null +++ b/queue-3.0/sparc32-remove-uses-of-g7-in-memcpy-implementation.patch @@ -0,0 +1,291 @@ +From 2e5dbd43a1c674f1d82c22b8c4070172882024b8 Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +Date: Wed, 19 Oct 2011 15:30:14 -0700 +Subject: sparc32: Remove uses of %g7 in memcpy implementation. + + +From: "David S. Miller" + +[ 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 +Tested-by: Kjetil Oftedal +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..ab374ea22ae --- /dev/null +++ b/queue-3.0/sparc64-fix-masking-and-shifting-in-vis-fpcmp-emulation.patch @@ -0,0 +1,106 @@ +From ff3f6f646f6eba78b05cc38af922782bd1b8712f Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +Date: Mon, 31 Oct 2011 01:05:49 -0700 +Subject: sparc64: Fix masking and shifting in VIS fpcmp emulation. + + +From: "David S. Miller" + +[ Upstream commit 2e8ecdc008a16b9a6c4b9628bb64d0d1c05f9f92 ] + +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..fb8719526ba --- /dev/null +++ b/queue-3.0/sparc64-fix-msiq-hv-call-ordering-in-pci_sun4v_msiq_build_irq.patch @@ -0,0 +1,44 @@ +From 485b01a81c3c41501c3b6c30e0899713a9bbb6a1 Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +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" + +[ 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 +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..b3466f20536 --- /dev/null +++ b/queue-3.0/sparc64-patch-sun4v-code-sequences-properly-on-module-load.patch @@ -0,0 +1,168 @@ +From 0c84d92038fa2b130475b11044772c0b8f0e6f89 Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +Date: Thu, 17 Nov 2011 22:44:58 -0800 +Subject: sparc64: Patch sun4v code sequences properly on module load. + + +From: "David S. Miller" + +[ 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 +Signed-off-by: Greg Kroah-Hartman +--- + 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 ++ + 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 + #include + ++#include "entry.h" ++ + #ifdef CONFIG_SPARC64 + + #include +@@ -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(); + }