aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2011-11-28 12:46:22 -0500
committerTejun Heo <tj@kernel.org>2011-11-28 12:46:22 -0500
commitd4bbf7e7759afc172e2bfbc5c416324590049cdd (patch)
tree7eab5ee5481cd3dcf1162329fec827177640018a /arch/sparc
parenta150439c4a97db379f0ed6faa46fbbb6e7bf3cb2 (diff)
parent401d0069cb344f401bc9d264c31db55876ff78c0 (diff)
Merge branch 'master' into x86/memblock
Conflicts & resolutions: * arch/x86/xen/setup.c dc91c728fd "xen: allow extra memory to be in multiple regions" 24aa07882b "memblock, x86: Replace memblock_x86_reserve/free..." conflicted on xen_add_extra_mem() updates. The resolution is trivial as the latter just want to replace memblock_x86_reserve_range() with memblock_reserve(). * drivers/pci/intel-iommu.c 166e9278a3f "x86/ia64: intel-iommu: move to drivers/iommu/" 5dfe8660a3d "bootmem: Replace work_with_active_regions() with..." conflicted as the former moved the file under drivers/iommu/. Resolved by applying the chnages from the latter on the moved file. * mm/Kconfig 6661672053a "memblock: add NO_BOOTMEM config symbol" c378ddd53f9 "memblock, x86: Make ARCH_DISCARD_MEMBLOCK a config option" conflicted trivially. Both added config options. Just letting both add their own options resolves the conflict. * mm/memblock.c d1f0ece6cdc "mm/memblock.c: small function definition fixes" ed7b56a799c "memblock: Remove memblock_memory_can_coalesce()" confliected. The former updates function removed by the latter. Resolution is trivial. Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'arch/sparc')
-rw-r--r--arch/sparc/Kconfig14
-rw-r--r--arch/sparc/include/asm/Kbuild5
-rw-r--r--arch/sparc/include/asm/atomic_32.h4
-rw-r--r--arch/sparc/include/asm/atomic_64.h6
-rw-r--r--arch/sparc/include/asm/bitops_64.h54
-rw-r--r--arch/sparc/include/asm/compat.h3
-rw-r--r--arch/sparc/include/asm/div64.h1
-rw-r--r--arch/sparc/include/asm/elf_64.h63
-rw-r--r--arch/sparc/include/asm/hypervisor.h14
-rw-r--r--arch/sparc/include/asm/irq_regs.h1
-rw-r--r--arch/sparc/include/asm/irqflags_32.h8
-rw-r--r--arch/sparc/include/asm/irqflags_64.h14
-rw-r--r--arch/sparc/include/asm/leon_pci.h2
-rw-r--r--arch/sparc/include/asm/local.h6
-rw-r--r--arch/sparc/include/asm/local64.h1
-rw-r--r--arch/sparc/include/asm/pci_32.h3
-rw-r--r--arch/sparc/include/asm/pci_64.h3
-rw-r--r--arch/sparc/include/asm/pgalloc_64.h76
-rw-r--r--arch/sparc/include/asm/pgtable_32.h20
-rw-r--r--arch/sparc/include/asm/pgtable_64.h35
-rw-r--r--arch/sparc/include/asm/pgtsrmmu.h2
-rw-r--r--arch/sparc/include/asm/prom.h2
-rw-r--r--arch/sparc/include/asm/ptrace.h3
-rw-r--r--arch/sparc/include/asm/sigcontext.h14
-rw-r--r--arch/sparc/include/asm/smp_32.h2
-rw-r--r--arch/sparc/include/asm/smp_64.h2
-rw-r--r--arch/sparc/include/asm/spinlock_32.h11
-rw-r--r--arch/sparc/include/asm/spinlock_64.h6
-rw-r--r--arch/sparc/include/asm/spitfire.h3
-rw-r--r--arch/sparc/include/asm/termios.h1
-rw-r--r--arch/sparc/include/asm/tsb.h51
-rw-r--r--arch/sparc/include/asm/unistd.h4
-rw-r--r--arch/sparc/include/asm/xor_64.h5
-rw-r--r--arch/sparc/kernel/Makefile1
-rw-r--r--arch/sparc/kernel/apc.c1
-rw-r--r--arch/sparc/kernel/auxio_32.c1
-rw-r--r--arch/sparc/kernel/btext.c1
-rw-r--r--arch/sparc/kernel/central.c1
-rw-r--r--arch/sparc/kernel/cpu.c22
-rw-r--r--arch/sparc/kernel/cpumap.c5
-rw-r--r--arch/sparc/kernel/dma.c1
-rw-r--r--arch/sparc/kernel/ds.c31
-rw-r--r--arch/sparc/kernel/ebus.c2
-rw-r--r--arch/sparc/kernel/entry.S2
-rw-r--r--arch/sparc/kernel/entry.h21
-rw-r--r--arch/sparc/kernel/head_64.S52
-rw-r--r--arch/sparc/kernel/hvapi.c9
-rw-r--r--arch/sparc/kernel/hvcalls.S7
-rw-r--r--arch/sparc/kernel/idprom.c2
-rw-r--r--arch/sparc/kernel/iommu.c2
-rw-r--r--arch/sparc/kernel/ioport.c44
-rw-r--r--arch/sparc/kernel/irq.h2
-rw-r--r--arch/sparc/kernel/irq_32.c1
-rw-r--r--arch/sparc/kernel/irq_64.c3
-rw-r--r--arch/sparc/kernel/jump_label.c8
-rw-r--r--arch/sparc/kernel/kernel.h15
-rw-r--r--arch/sparc/kernel/ktlb.S24
-rw-r--r--arch/sparc/kernel/ldc.c2
-rw-r--r--arch/sparc/kernel/leon_kernel.c1
-rw-r--r--arch/sparc/kernel/leon_pci.c1
-rw-r--r--arch/sparc/kernel/leon_pci_grpci2.c4
-rw-r--r--arch/sparc/kernel/leon_smp.c2
-rw-r--r--arch/sparc/kernel/mdesc.c32
-rw-r--r--arch/sparc/kernel/module.c55
-rw-r--r--arch/sparc/kernel/nmi.c2
-rw-r--r--arch/sparc/kernel/of_device_32.c1
-rw-r--r--arch/sparc/kernel/of_device_64.c3
-rw-r--r--arch/sparc/kernel/of_device_common.c2
-rw-r--r--arch/sparc/kernel/pci.c19
-rw-r--r--arch/sparc/kernel/pci_fire.c1
-rw-r--r--arch/sparc/kernel/pci_psycho.c1
-rw-r--r--arch/sparc/kernel/pci_sabre.c1
-rw-r--r--arch/sparc/kernel/pci_schizo.c1
-rw-r--r--arch/sparc/kernel/pci_sun4v.c1
-rw-r--r--arch/sparc/kernel/pcic.c13
-rw-r--r--arch/sparc/kernel/pcr.c14
-rw-r--r--arch/sparc/kernel/perf_event.c49
-rw-r--r--arch/sparc/kernel/pmc.c1
-rw-r--r--arch/sparc/kernel/power.c2
-rw-r--r--arch/sparc/kernel/process_32.c3
-rw-r--r--arch/sparc/kernel/process_64.c5
-rw-r--r--arch/sparc/kernel/prom_32.c1
-rw-r--r--arch/sparc/kernel/prom_64.c1
-rw-r--r--arch/sparc/kernel/prom_common.c2
-rw-r--r--arch/sparc/kernel/reboot.c2
-rw-r--r--arch/sparc/kernel/sbus.c1
-rw-r--r--arch/sparc/kernel/setup_32.c3
-rw-r--r--arch/sparc/kernel/setup_64.c250
-rw-r--r--arch/sparc/kernel/signal32.c223
-rw-r--r--arch/sparc/kernel/signal_32.c234
-rw-r--r--arch/sparc/kernel/signal_64.c182
-rw-r--r--arch/sparc/kernel/sigutil.h9
-rw-r--r--arch/sparc/kernel/sigutil_32.c120
-rw-r--r--arch/sparc/kernel/sigutil_64.c94
-rw-r--r--arch/sparc/kernel/smp_32.c2
-rw-r--r--arch/sparc/kernel/smp_64.c4
-rw-r--r--arch/sparc/kernel/sparc_ksyms_64.c13
-rw-r--r--arch/sparc/kernel/sstate.c9
-rw-r--r--arch/sparc/kernel/stacktrace.c2
-rw-r--r--arch/sparc/kernel/sys32.S1
-rw-r--r--arch/sparc/kernel/sys_sparc32.c1
-rw-r--r--arch/sparc/kernel/sys_sparc_64.c2
-rw-r--r--arch/sparc/kernel/systbls_32.S4
-rw-r--r--arch/sparc/kernel/systbls_64.S8
-rw-r--r--arch/sparc/kernel/time_64.c2
-rw-r--r--arch/sparc/kernel/traps_32.c1
-rw-r--r--arch/sparc/kernel/unaligned_32.c5
-rw-r--r--arch/sparc/kernel/unaligned_64.c27
-rw-r--r--arch/sparc/kernel/vio.c1
-rw-r--r--arch/sparc/kernel/viohs.c2
-rw-r--r--arch/sparc/kernel/visemul.c34
-rw-r--r--arch/sparc/kernel/vmlinux.lds.S21
-rw-r--r--arch/sparc/lib/Makefile4
-rw-r--r--arch/sparc/lib/NG2page.S61
-rw-r--r--arch/sparc/lib/NGpage.S114
-rw-r--r--arch/sparc/lib/atomic32.c8
-rw-r--r--arch/sparc/lib/ffs.S84
-rw-r--r--arch/sparc/lib/hweight.S51
-rw-r--r--arch/sparc/lib/memcpy.S804
-rw-r--r--arch/sparc/math-emu/math_32.c2
-rw-r--r--arch/sparc/math-emu/math_64.c2
-rw-r--r--arch/sparc/mm/Makefile3
-rw-r--r--arch/sparc/mm/fault_32.c9
-rw-r--r--arch/sparc/mm/fault_64.c8
-rw-r--r--arch/sparc/mm/generic_32.c98
-rw-r--r--arch/sparc/mm/generic_64.c164
-rw-r--r--arch/sparc/mm/gup.c183
-rw-r--r--arch/sparc/mm/highmem.c1
-rw-r--r--arch/sparc/mm/hugetlbpage.c1
-rw-r--r--arch/sparc/mm/init_64.c47
-rw-r--r--arch/sparc/mm/leon_mm.c4
-rw-r--r--arch/sparc/mm/tsb.c11
132 files changed, 2000 insertions, 1833 deletions
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 253986bd6bb6..f92602e86607 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -41,6 +41,7 @@ config SPARC64
41 select HAVE_FUNCTION_TRACE_MCOUNT_TEST 41 select HAVE_FUNCTION_TRACE_MCOUNT_TEST
42 select HAVE_KRETPROBES 42 select HAVE_KRETPROBES
43 select HAVE_KPROBES 43 select HAVE_KPROBES
44 select HAVE_RCU_TABLE_FREE if SMP
44 select HAVE_MEMBLOCK 45 select HAVE_MEMBLOCK
45 select HAVE_SYSCALL_WRAPPERS 46 select HAVE_SYSCALL_WRAPPERS
46 select HAVE_DYNAMIC_FTRACE 47 select HAVE_DYNAMIC_FTRACE
@@ -53,6 +54,8 @@ config SPARC64
53 select HAVE_PERF_EVENTS 54 select HAVE_PERF_EVENTS
54 select PERF_USE_VMALLOC 55 select PERF_USE_VMALLOC
55 select IRQ_PREFLOW_FASTEOI 56 select IRQ_PREFLOW_FASTEOI
57 select ARCH_HAVE_NMI_SAFE_CMPXCHG
58 select HAVE_C_RECORDMCOUNT
56 59
57config ARCH_DEFCONFIG 60config ARCH_DEFCONFIG
58 string 61 string
@@ -81,10 +84,6 @@ config IOMMU_HELPER
81 bool 84 bool
82 default y if SPARC64 85 default y if SPARC64
83 86
84config QUICKLIST
85 bool
86 default y if SPARC64
87
88config STACKTRACE_SUPPORT 87config STACKTRACE_SUPPORT
89 bool 88 bool
90 default y if SPARC64 89 default y if SPARC64
@@ -561,12 +560,7 @@ config SUN_OPENPROMFS
561 Only choose N if you know in advance that you will not need to modify 560 Only choose N if you know in advance that you will not need to modify
562 OpenPROM settings on the running system. 561 OpenPROM settings on the running system.
563 562
564# Makefile helpers 563# Makefile helper
565config SPARC32_PCI
566 bool
567 default y
568 depends on SPARC32 && PCI
569
570config SPARC64_PCI 564config SPARC64_PCI
571 bool 565 bool
572 default y 566 default y
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 3c93f08ce187..2c2e38821f60 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -16,3 +16,8 @@ header-y += traps.h
16header-y += uctx.h 16header-y += uctx.h
17header-y += utrap.h 17header-y += utrap.h
18header-y += watchdog.h 18header-y += watchdog.h
19
20generic-y += div64.h
21generic-y += local64.h
22generic-y += irq_regs.h
23generic-y += local.h
diff --git a/arch/sparc/include/asm/atomic_32.h b/arch/sparc/include/asm/atomic_32.h
index 7ae128b19d3f..5c3c8b69884d 100644
--- a/arch/sparc/include/asm/atomic_32.h
+++ b/arch/sparc/include/asm/atomic_32.h
@@ -22,7 +22,7 @@
22extern int __atomic_add_return(int, atomic_t *); 22extern int __atomic_add_return(int, atomic_t *);
23extern int atomic_cmpxchg(atomic_t *, int, int); 23extern int atomic_cmpxchg(atomic_t *, int, int);
24#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) 24#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
25extern int atomic_add_unless(atomic_t *, int, int); 25extern int __atomic_add_unless(atomic_t *, int, int);
26extern void atomic_set(atomic_t *, int); 26extern void atomic_set(atomic_t *, int);
27 27
28#define atomic_read(v) (*(volatile int *)&(v)->counter) 28#define atomic_read(v) (*(volatile int *)&(v)->counter)
@@ -52,7 +52,6 @@ extern void atomic_set(atomic_t *, int);
52#define atomic_dec_and_test(v) (atomic_dec_return(v) == 0) 52#define atomic_dec_and_test(v) (atomic_dec_return(v) == 0)
53#define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0) 53#define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0)
54 54
55#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
56 55
57/* This is the old 24-bit implementation. It's still used internally 56/* This is the old 24-bit implementation. It's still used internally
58 * by some sparc-specific code, notably the semaphore implementation. 57 * by some sparc-specific code, notably the semaphore implementation.
@@ -161,5 +160,4 @@ static inline int __atomic24_sub(int i, atomic24_t *v)
161 160
162#endif /* !(__KERNEL__) */ 161#endif /* !(__KERNEL__) */
163 162
164#include <asm-generic/atomic-long.h>
165#endif /* !(__ARCH_SPARC_ATOMIC__) */ 163#endif /* !(__ARCH_SPARC_ATOMIC__) */
diff --git a/arch/sparc/include/asm/atomic_64.h b/arch/sparc/include/asm/atomic_64.h
index bdb2ff880bdd..9f421df46aec 100644
--- a/arch/sparc/include/asm/atomic_64.h
+++ b/arch/sparc/include/asm/atomic_64.h
@@ -70,7 +70,7 @@ extern long atomic64_sub_ret(long, atomic64_t *);
70#define atomic_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n))) 70#define atomic_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n)))
71#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) 71#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
72 72
73static inline int atomic_add_unless(atomic_t *v, int a, int u) 73static inline int __atomic_add_unless(atomic_t *v, int a, int u)
74{ 74{
75 int c, old; 75 int c, old;
76 c = atomic_read(v); 76 c = atomic_read(v);
@@ -82,10 +82,9 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
82 break; 82 break;
83 c = old; 83 c = old;
84 } 84 }
85 return c != (u); 85 return c;
86} 86}
87 87
88#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
89 88
90#define atomic64_cmpxchg(v, o, n) \ 89#define atomic64_cmpxchg(v, o, n) \
91 ((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n))) 90 ((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n)))
@@ -114,5 +113,4 @@ static inline long atomic64_add_unless(atomic64_t *v, long a, long u)
114#define smp_mb__before_atomic_inc() barrier() 113#define smp_mb__before_atomic_inc() barrier()
115#define smp_mb__after_atomic_inc() barrier() 114#define smp_mb__after_atomic_inc() barrier()
116 115
117#include <asm-generic/atomic-long.h>
118#endif /* !(__ARCH_SPARC64_ATOMIC__) */ 116#endif /* !(__ARCH_SPARC64_ATOMIC__) */
diff --git a/arch/sparc/include/asm/bitops_64.h b/arch/sparc/include/asm/bitops_64.h
index 38e9aa1b2cea..29011cc0e4be 100644
--- a/arch/sparc/include/asm/bitops_64.h
+++ b/arch/sparc/include/asm/bitops_64.h
@@ -26,61 +26,28 @@ extern void change_bit(unsigned long nr, volatile unsigned long *addr);
26#define smp_mb__before_clear_bit() barrier() 26#define smp_mb__before_clear_bit() barrier()
27#define smp_mb__after_clear_bit() barrier() 27#define smp_mb__after_clear_bit() barrier()
28 28
29#include <asm-generic/bitops/ffz.h>
30#include <asm-generic/bitops/__ffs.h>
31#include <asm-generic/bitops/fls.h> 29#include <asm-generic/bitops/fls.h>
32#include <asm-generic/bitops/__fls.h> 30#include <asm-generic/bitops/__fls.h>
33#include <asm-generic/bitops/fls64.h> 31#include <asm-generic/bitops/fls64.h>
34 32
35#ifdef __KERNEL__ 33#ifdef __KERNEL__
36 34
35extern int ffs(int x);
36extern unsigned long __ffs(unsigned long);
37
38#include <asm-generic/bitops/ffz.h>
37#include <asm-generic/bitops/sched.h> 39#include <asm-generic/bitops/sched.h>
38#include <asm-generic/bitops/ffs.h>
39 40
40/* 41/*
41 * hweightN: returns the hamming weight (i.e. the number 42 * hweightN: returns the hamming weight (i.e. the number
42 * of bits set) of a N-bit word 43 * of bits set) of a N-bit word
43 */ 44 */
44 45
45#ifdef ULTRA_HAS_POPULATION_COUNT 46extern unsigned long __arch_hweight64(__u64 w);
46 47extern unsigned int __arch_hweight32(unsigned int w);
47static inline unsigned int __arch_hweight64(unsigned long w) 48extern unsigned int __arch_hweight16(unsigned int w);
48{ 49extern unsigned int __arch_hweight8(unsigned int w);
49 unsigned int res;
50
51 __asm__ ("popc %1,%0" : "=r" (res) : "r" (w));
52 return res;
53}
54
55static inline unsigned int __arch_hweight32(unsigned int w)
56{
57 unsigned int res;
58
59 __asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xffffffff));
60 return res;
61}
62 50
63static inline unsigned int __arch_hweight16(unsigned int w)
64{
65 unsigned int res;
66
67 __asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xffff));
68 return res;
69}
70
71static inline unsigned int __arch_hweight8(unsigned int w)
72{
73 unsigned int res;
74
75 __asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xff));
76 return res;
77}
78
79#else
80
81#include <asm-generic/bitops/arch_hweight.h>
82
83#endif
84#include <asm-generic/bitops/const_hweight.h> 51#include <asm-generic/bitops/const_hweight.h>
85#include <asm-generic/bitops/lock.h> 52#include <asm-generic/bitops/lock.h>
86#endif /* __KERNEL__ */ 53#endif /* __KERNEL__ */
@@ -91,10 +58,7 @@ static inline unsigned int __arch_hweight8(unsigned int w)
91 58
92#include <asm-generic/bitops/le.h> 59#include <asm-generic/bitops/le.h>
93 60
94#define ext2_set_bit_atomic(lock,nr,addr) \ 61#include <asm-generic/bitops/ext2-atomic-setbit.h>
95 test_and_set_bit((nr) ^ 0x38,(unsigned long *)(addr))
96#define ext2_clear_bit_atomic(lock,nr,addr) \
97 test_and_clear_bit((nr) ^ 0x38,(unsigned long *)(addr))
98 62
99#endif /* __KERNEL__ */ 63#endif /* __KERNEL__ */
100 64
diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h
index 6f57325bb883..b8be20d42a0a 100644
--- a/arch/sparc/include/asm/compat.h
+++ b/arch/sparc/include/asm/compat.h
@@ -134,7 +134,8 @@ struct compat_statfs {
134 compat_fsid_t f_fsid; 134 compat_fsid_t f_fsid;
135 int f_namelen; /* SunOS ignores this field. */ 135 int f_namelen; /* SunOS ignores this field. */
136 int f_frsize; 136 int f_frsize;
137 int f_spare[5]; 137 int f_flags;
138 int f_spare[4];
138}; 139};
139 140
140#define COMPAT_RLIM_INFINITY 0x7fffffff 141#define COMPAT_RLIM_INFINITY 0x7fffffff
diff --git a/arch/sparc/include/asm/div64.h b/arch/sparc/include/asm/div64.h
deleted file mode 100644
index 6cd978cefb28..000000000000
--- a/arch/sparc/include/asm/div64.h
+++ /dev/null
@@ -1 +0,0 @@
1#include <asm-generic/div64.h>
diff --git a/arch/sparc/include/asm/elf_64.h b/arch/sparc/include/asm/elf_64.h
index e67880381b84..7df8b7f544d4 100644
--- a/arch/sparc/include/asm/elf_64.h
+++ b/arch/sparc/include/asm/elf_64.h
@@ -59,15 +59,33 @@
59#define R_SPARC_6 45 59#define R_SPARC_6 45
60 60
61/* Bits present in AT_HWCAP, primarily for Sparc32. */ 61/* Bits present in AT_HWCAP, primarily for Sparc32. */
62 62#define HWCAP_SPARC_FLUSH 0x00000001
63#define HWCAP_SPARC_FLUSH 1 /* CPU supports flush instruction. */ 63#define HWCAP_SPARC_STBAR 0x00000002
64#define HWCAP_SPARC_STBAR 2 64#define HWCAP_SPARC_SWAP 0x00000004
65#define HWCAP_SPARC_SWAP 4 65#define HWCAP_SPARC_MULDIV 0x00000008
66#define HWCAP_SPARC_MULDIV 8 66#define HWCAP_SPARC_V9 0x00000010
67#define HWCAP_SPARC_V9 16 67#define HWCAP_SPARC_ULTRA3 0x00000020
68#define HWCAP_SPARC_ULTRA3 32 68#define HWCAP_SPARC_BLKINIT 0x00000040
69#define HWCAP_SPARC_BLKINIT 64 69#define HWCAP_SPARC_N2 0x00000080
70#define HWCAP_SPARC_N2 128 70
71/* Solaris compatible AT_HWCAP bits. */
72#define AV_SPARC_MUL32 0x00000100 /* 32x32 multiply is efficient */
73#define AV_SPARC_DIV32 0x00000200 /* 32x32 divide is efficient */
74#define AV_SPARC_FSMULD 0x00000400 /* 'fsmuld' is efficient */
75#define AV_SPARC_V8PLUS 0x00000800 /* v9 insn available to 32bit */
76#define AV_SPARC_POPC 0x00001000 /* 'popc' is efficient */
77#define AV_SPARC_VIS 0x00002000 /* VIS insns available */
78#define AV_SPARC_VIS2 0x00004000 /* VIS2 insns available */
79#define AV_SPARC_ASI_BLK_INIT 0x00008000 /* block init ASIs available */
80#define AV_SPARC_FMAF 0x00010000 /* fused multiply-add */
81#define AV_SPARC_VIS3 0x00020000 /* VIS3 insns available */
82#define AV_SPARC_HPC 0x00040000 /* HPC insns available */
83#define AV_SPARC_RANDOM 0x00080000 /* 'random' insn available */
84#define AV_SPARC_TRANS 0x00100000 /* transaction insns available */
85#define AV_SPARC_FJFMAU 0x00200000 /* unfused multiply-add */
86#define AV_SPARC_IMA 0x00400000 /* integer multiply-add */
87#define AV_SPARC_ASI_CACHE_SPARING \
88 0x00800000 /* cache sparing ASIs available */
71 89
72#define CORE_DUMP_USE_REGSET 90#define CORE_DUMP_USE_REGSET
73 91
@@ -162,31 +180,8 @@ typedef struct {
162#define ELF_ET_DYN_BASE 0x0000010000000000UL 180#define ELF_ET_DYN_BASE 0x0000010000000000UL
163#define COMPAT_ELF_ET_DYN_BASE 0x0000000070000000UL 181#define COMPAT_ELF_ET_DYN_BASE 0x0000000070000000UL
164 182
165 183extern unsigned long sparc64_elf_hwcap;
166/* This yields a mask that user programs can use to figure out what 184#define ELF_HWCAP sparc64_elf_hwcap
167 instruction set this cpu supports. */
168
169/* On Ultra, we support all of the v8 capabilities. */
170static inline unsigned int sparc64_elf_hwcap(void)
171{
172 unsigned int cap = (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR |
173 HWCAP_SPARC_SWAP | HWCAP_SPARC_MULDIV |
174 HWCAP_SPARC_V9);
175
176 if (tlb_type == cheetah || tlb_type == cheetah_plus)
177 cap |= HWCAP_SPARC_ULTRA3;
178 else if (tlb_type == hypervisor) {
179 if (sun4v_chip_type == SUN4V_CHIP_NIAGARA1 ||
180 sun4v_chip_type == SUN4V_CHIP_NIAGARA2)
181 cap |= HWCAP_SPARC_BLKINIT;
182 if (sun4v_chip_type == SUN4V_CHIP_NIAGARA2)
183 cap |= HWCAP_SPARC_N2;
184 }
185
186 return cap;
187}
188
189#define ELF_HWCAP sparc64_elf_hwcap();
190 185
191/* This yields a string that ld.so will use to load implementation 186/* This yields a string that ld.so will use to load implementation
192 specific libraries for optimization. This is more specific in 187 specific libraries for optimization. This is more specific in
diff --git a/arch/sparc/include/asm/hypervisor.h b/arch/sparc/include/asm/hypervisor.h
index 75686409be24..015a761eaa32 100644
--- a/arch/sparc/include/asm/hypervisor.h
+++ b/arch/sparc/include/asm/hypervisor.h
@@ -2927,6 +2927,13 @@ extern unsigned long sun4v_ncs_request(unsigned long request,
2927#define HV_FAST_FIRE_GET_PERFREG 0x120 2927#define HV_FAST_FIRE_GET_PERFREG 0x120
2928#define HV_FAST_FIRE_SET_PERFREG 0x121 2928#define HV_FAST_FIRE_SET_PERFREG 0x121
2929 2929
2930#define HV_FAST_REBOOT_DATA_SET 0x172
2931
2932#ifndef __ASSEMBLY__
2933extern unsigned long sun4v_reboot_data_set(unsigned long ra,
2934 unsigned long len);
2935#endif
2936
2930/* Function numbers for HV_CORE_TRAP. */ 2937/* Function numbers for HV_CORE_TRAP. */
2931#define HV_CORE_SET_VER 0x00 2938#define HV_CORE_SET_VER 0x00
2932#define HV_CORE_PUTCHAR 0x01 2939#define HV_CORE_PUTCHAR 0x01
@@ -2940,16 +2947,23 @@ extern unsigned long sun4v_ncs_request(unsigned long request,
2940#define HV_GRP_CORE 0x0001 2947#define HV_GRP_CORE 0x0001
2941#define HV_GRP_INTR 0x0002 2948#define HV_GRP_INTR 0x0002
2942#define HV_GRP_SOFT_STATE 0x0003 2949#define HV_GRP_SOFT_STATE 0x0003
2950#define HV_GRP_TM 0x0080
2943#define HV_GRP_PCI 0x0100 2951#define HV_GRP_PCI 0x0100
2944#define HV_GRP_LDOM 0x0101 2952#define HV_GRP_LDOM 0x0101
2945#define HV_GRP_SVC_CHAN 0x0102 2953#define HV_GRP_SVC_CHAN 0x0102
2946#define HV_GRP_NCS 0x0103 2954#define HV_GRP_NCS 0x0103
2947#define HV_GRP_RNG 0x0104 2955#define HV_GRP_RNG 0x0104
2956#define HV_GRP_PBOOT 0x0105
2957#define HV_GRP_TPM 0x0107
2958#define HV_GRP_SDIO 0x0108
2959#define HV_GRP_SDIO_ERR 0x0109
2960#define HV_GRP_REBOOT_DATA 0x0110
2948#define HV_GRP_NIAG_PERF 0x0200 2961#define HV_GRP_NIAG_PERF 0x0200
2949#define HV_GRP_FIRE_PERF 0x0201 2962#define HV_GRP_FIRE_PERF 0x0201
2950#define HV_GRP_N2_CPU 0x0202 2963#define HV_GRP_N2_CPU 0x0202
2951#define HV_GRP_NIU 0x0204 2964#define HV_GRP_NIU 0x0204
2952#define HV_GRP_VF_CPU 0x0205 2965#define HV_GRP_VF_CPU 0x0205
2966#define HV_GRP_KT_CPU 0x0209
2953#define HV_GRP_DIAG 0x0300 2967#define HV_GRP_DIAG 0x0300
2954 2968
2955#ifndef __ASSEMBLY__ 2969#ifndef __ASSEMBLY__
diff --git a/arch/sparc/include/asm/irq_regs.h b/arch/sparc/include/asm/irq_regs.h
deleted file mode 100644
index 3dd9c0b70270..000000000000
--- a/arch/sparc/include/asm/irq_regs.h
+++ /dev/null
@@ -1 +0,0 @@
1#include <asm-generic/irq_regs.h>
diff --git a/arch/sparc/include/asm/irqflags_32.h b/arch/sparc/include/asm/irqflags_32.h
index d4d0711de0f9..14848909e0de 100644
--- a/arch/sparc/include/asm/irqflags_32.h
+++ b/arch/sparc/include/asm/irqflags_32.h
@@ -18,7 +18,7 @@ extern void arch_local_irq_restore(unsigned long);
18extern unsigned long arch_local_irq_save(void); 18extern unsigned long arch_local_irq_save(void);
19extern void arch_local_irq_enable(void); 19extern void arch_local_irq_enable(void);
20 20
21static inline unsigned long arch_local_save_flags(void) 21static inline notrace unsigned long arch_local_save_flags(void)
22{ 22{
23 unsigned long flags; 23 unsigned long flags;
24 24
@@ -26,17 +26,17 @@ static inline unsigned long arch_local_save_flags(void)
26 return flags; 26 return flags;
27} 27}
28 28
29static inline void arch_local_irq_disable(void) 29static inline notrace void arch_local_irq_disable(void)
30{ 30{
31 arch_local_irq_save(); 31 arch_local_irq_save();
32} 32}
33 33
34static inline bool arch_irqs_disabled_flags(unsigned long flags) 34static inline notrace bool arch_irqs_disabled_flags(unsigned long flags)
35{ 35{
36 return (flags & PSR_PIL) != 0; 36 return (flags & PSR_PIL) != 0;
37} 37}
38 38
39static inline bool arch_irqs_disabled(void) 39static inline notrace bool arch_irqs_disabled(void)
40{ 40{
41 return arch_irqs_disabled_flags(arch_local_save_flags()); 41 return arch_irqs_disabled_flags(arch_local_save_flags());
42} 42}
diff --git a/arch/sparc/include/asm/irqflags_64.h b/arch/sparc/include/asm/irqflags_64.h
index aab969c82c2b..23cd27f6beb4 100644
--- a/arch/sparc/include/asm/irqflags_64.h
+++ b/arch/sparc/include/asm/irqflags_64.h
@@ -14,7 +14,7 @@
14 14
15#ifndef __ASSEMBLY__ 15#ifndef __ASSEMBLY__
16 16
17static inline unsigned long arch_local_save_flags(void) 17static inline notrace unsigned long arch_local_save_flags(void)
18{ 18{
19 unsigned long flags; 19 unsigned long flags;
20 20
@@ -26,7 +26,7 @@ static inline unsigned long arch_local_save_flags(void)
26 return flags; 26 return flags;
27} 27}
28 28
29static inline void arch_local_irq_restore(unsigned long flags) 29static inline notrace void arch_local_irq_restore(unsigned long flags)
30{ 30{
31 __asm__ __volatile__( 31 __asm__ __volatile__(
32 "wrpr %0, %%pil" 32 "wrpr %0, %%pil"
@@ -36,7 +36,7 @@ static inline void arch_local_irq_restore(unsigned long flags)
36 ); 36 );
37} 37}
38 38
39static inline void arch_local_irq_disable(void) 39static inline notrace void arch_local_irq_disable(void)
40{ 40{
41 __asm__ __volatile__( 41 __asm__ __volatile__(
42 "wrpr %0, %%pil" 42 "wrpr %0, %%pil"
@@ -46,7 +46,7 @@ static inline void arch_local_irq_disable(void)
46 ); 46 );
47} 47}
48 48
49static inline void arch_local_irq_enable(void) 49static inline notrace void arch_local_irq_enable(void)
50{ 50{
51 __asm__ __volatile__( 51 __asm__ __volatile__(
52 "wrpr 0, %%pil" 52 "wrpr 0, %%pil"
@@ -56,17 +56,17 @@ static inline void arch_local_irq_enable(void)
56 ); 56 );
57} 57}
58 58
59static inline int arch_irqs_disabled_flags(unsigned long flags) 59static inline notrace int arch_irqs_disabled_flags(unsigned long flags)
60{ 60{
61 return (flags > 0); 61 return (flags > 0);
62} 62}
63 63
64static inline int arch_irqs_disabled(void) 64static inline notrace int arch_irqs_disabled(void)
65{ 65{
66 return arch_irqs_disabled_flags(arch_local_save_flags()); 66 return arch_irqs_disabled_flags(arch_local_save_flags());
67} 67}
68 68
69static inline unsigned long arch_local_irq_save(void) 69static inline notrace unsigned long arch_local_irq_save(void)
70{ 70{
71 unsigned long flags, tmp; 71 unsigned long flags, tmp;
72 72
diff --git a/arch/sparc/include/asm/leon_pci.h b/arch/sparc/include/asm/leon_pci.h
index 42b4b31a82fe..f48527ebdd8f 100644
--- a/arch/sparc/include/asm/leon_pci.h
+++ b/arch/sparc/include/asm/leon_pci.h
@@ -12,7 +12,7 @@ struct leon_pci_info {
12 struct pci_ops *ops; 12 struct pci_ops *ops;
13 struct resource io_space; 13 struct resource io_space;
14 struct resource mem_space; 14 struct resource mem_space;
15 int (*map_irq)(struct pci_dev *dev, u8 slot, u8 pin); 15 int (*map_irq)(const struct pci_dev *dev, u8 slot, u8 pin);
16}; 16};
17 17
18extern void leon_pci_init(struct platform_device *ofdev, 18extern void leon_pci_init(struct platform_device *ofdev,
diff --git a/arch/sparc/include/asm/local.h b/arch/sparc/include/asm/local.h
deleted file mode 100644
index bc80815a435c..000000000000
--- a/arch/sparc/include/asm/local.h
+++ /dev/null
@@ -1,6 +0,0 @@
1#ifndef _SPARC_LOCAL_H
2#define _SPARC_LOCAL_H
3
4#include <asm-generic/local.h>
5
6#endif
diff --git a/arch/sparc/include/asm/local64.h b/arch/sparc/include/asm/local64.h
deleted file mode 100644
index 36c93b5cc239..000000000000
--- a/arch/sparc/include/asm/local64.h
+++ /dev/null
@@ -1 +0,0 @@
1#include <asm-generic/local64.h>
diff --git a/arch/sparc/include/asm/pci_32.h b/arch/sparc/include/asm/pci_32.h
index 862e3ce92b15..02939abd356c 100644
--- a/arch/sparc/include/asm/pci_32.h
+++ b/arch/sparc/include/asm/pci_32.h
@@ -42,9 +42,6 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
42} 42}
43#endif 43#endif
44 44
45struct device_node;
46extern struct device_node *pci_device_to_OF_node(struct pci_dev *pdev);
47
48#endif /* __KERNEL__ */ 45#endif /* __KERNEL__ */
49 46
50#ifndef CONFIG_LEON_PCI 47#ifndef CONFIG_LEON_PCI
diff --git a/arch/sparc/include/asm/pci_64.h b/arch/sparc/include/asm/pci_64.h
index 948b686ec089..2614d96141c9 100644
--- a/arch/sparc/include/asm/pci_64.h
+++ b/arch/sparc/include/asm/pci_64.h
@@ -91,9 +91,6 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
91 return PCI_IRQ_NONE; 91 return PCI_IRQ_NONE;
92} 92}
93 93
94struct device_node;
95extern struct device_node *pci_device_to_OF_node(struct pci_dev *pdev);
96
97#define HAVE_ARCH_PCI_RESOURCE_TO_USER 94#define HAVE_ARCH_PCI_RESOURCE_TO_USER
98extern void pci_resource_to_user(const struct pci_dev *dev, int bar, 95extern void pci_resource_to_user(const struct pci_dev *dev, int bar,
99 const struct resource *rsrc, 96 const struct resource *rsrc,
diff --git a/arch/sparc/include/asm/pgalloc_64.h b/arch/sparc/include/asm/pgalloc_64.h
index 4e5e0878144f..40b2d7a7023d 100644
--- a/arch/sparc/include/asm/pgalloc_64.h
+++ b/arch/sparc/include/asm/pgalloc_64.h
@@ -5,7 +5,6 @@
5#include <linux/sched.h> 5#include <linux/sched.h>
6#include <linux/mm.h> 6#include <linux/mm.h>
7#include <linux/slab.h> 7#include <linux/slab.h>
8#include <linux/quicklist.h>
9 8
10#include <asm/spitfire.h> 9#include <asm/spitfire.h>
11#include <asm/cpudata.h> 10#include <asm/cpudata.h>
@@ -14,71 +13,114 @@
14 13
15/* Page table allocation/freeing. */ 14/* Page table allocation/freeing. */
16 15
16extern struct kmem_cache *pgtable_cache;
17
17static inline pgd_t *pgd_alloc(struct mm_struct *mm) 18static inline pgd_t *pgd_alloc(struct mm_struct *mm)
18{ 19{
19 return quicklist_alloc(0, GFP_KERNEL, NULL); 20 return kmem_cache_alloc(pgtable_cache, GFP_KERNEL);
20} 21}
21 22
22static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) 23static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
23{ 24{
24 quicklist_free(0, NULL, pgd); 25 kmem_cache_free(pgtable_cache, pgd);
25} 26}
26 27
27#define pud_populate(MM, PUD, PMD) pud_set(PUD, PMD) 28#define pud_populate(MM, PUD, PMD) pud_set(PUD, PMD)
28 29
29static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) 30static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
30{ 31{
31 return quicklist_alloc(0, GFP_KERNEL, NULL); 32 return kmem_cache_alloc(pgtable_cache,
33 GFP_KERNEL|__GFP_REPEAT);
32} 34}
33 35
34static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd) 36static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
35{ 37{
36 quicklist_free(0, NULL, pmd); 38 kmem_cache_free(pgtable_cache, pmd);
37} 39}
38 40
39static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, 41static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
40 unsigned long address) 42 unsigned long address)
41{ 43{
42 return quicklist_alloc(0, GFP_KERNEL, NULL); 44 return (pte_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO);
43} 45}
44 46
45static inline pgtable_t pte_alloc_one(struct mm_struct *mm, 47static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
46 unsigned long address) 48 unsigned long address)
47{ 49{
48 struct page *page; 50 struct page *page;
49 void *pg; 51 pte_t *pte;
50 52
51 pg = quicklist_alloc(0, GFP_KERNEL, NULL); 53 pte = pte_alloc_one_kernel(mm, address);
52 if (!pg) 54 if (!pte)
53 return NULL; 55 return NULL;
54 page = virt_to_page(pg); 56 page = virt_to_page(pte);
55 pgtable_page_ctor(page); 57 pgtable_page_ctor(page);
56 return page; 58 return page;
57} 59}
58 60
59static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) 61static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
60{ 62{
61 quicklist_free(0, NULL, pte); 63 free_page((unsigned long)pte);
62} 64}
63 65
64static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage) 66static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage)
65{ 67{
66 pgtable_page_dtor(ptepage); 68 pgtable_page_dtor(ptepage);
67 quicklist_free_page(0, NULL, ptepage); 69 __free_page(ptepage);
68} 70}
69 71
70
71#define pmd_populate_kernel(MM, PMD, PTE) pmd_set(PMD, PTE) 72#define pmd_populate_kernel(MM, PMD, PTE) pmd_set(PMD, PTE)
72#define pmd_populate(MM,PMD,PTE_PAGE) \ 73#define pmd_populate(MM,PMD,PTE_PAGE) \
73 pmd_populate_kernel(MM,PMD,page_address(PTE_PAGE)) 74 pmd_populate_kernel(MM,PMD,page_address(PTE_PAGE))
74#define pmd_pgtable(pmd) pmd_page(pmd) 75#define pmd_pgtable(pmd) pmd_page(pmd)
75 76
76static inline void check_pgt_cache(void) 77#define check_pgt_cache() do { } while (0)
78
79static inline void pgtable_free(void *table, bool is_page)
80{
81 if (is_page)
82 free_page((unsigned long)table);
83 else
84 kmem_cache_free(pgtable_cache, table);
85}
86
87#ifdef CONFIG_SMP
88
89struct mmu_gather;
90extern void tlb_remove_table(struct mmu_gather *, void *);
91
92static inline void pgtable_free_tlb(struct mmu_gather *tlb, void *table, bool is_page)
93{
94 unsigned long pgf = (unsigned long)table;
95 if (is_page)
96 pgf |= 0x1UL;
97 tlb_remove_table(tlb, (void *)pgf);
98}
99
100static inline void __tlb_remove_table(void *_table)
101{
102 void *table = (void *)((unsigned long)_table & ~0x1UL);
103 bool is_page = false;
104
105 if ((unsigned long)_table & 0x1UL)
106 is_page = true;
107 pgtable_free(table, is_page);
108}
109#else /* CONFIG_SMP */
110static inline void pgtable_free_tlb(struct mmu_gather *tlb, void *table, bool is_page)
77{ 111{
78 quicklist_trim(0, NULL, 25, 16); 112 pgtable_free(table, is_page);
113}
114#endif /* !CONFIG_SMP */
115
116static inline void __pte_free_tlb(struct mmu_gather *tlb, struct page *ptepage,
117 unsigned long address)
118{
119 pgtable_page_dtor(ptepage);
120 pgtable_free_tlb(tlb, page_address(ptepage), true);
79} 121}
80 122
81#define __pte_free_tlb(tlb, pte, addr) pte_free((tlb)->mm, pte) 123#define __pmd_free_tlb(tlb, pmd, addr) \
82#define __pmd_free_tlb(tlb, pmd, addr) pmd_free((tlb)->mm, pmd) 124 pgtable_free_tlb(tlb, pmd, false)
83 125
84#endif /* _SPARC64_PGALLOC_H */ 126#endif /* _SPARC64_PGALLOC_H */
diff --git a/arch/sparc/include/asm/pgtable_32.h b/arch/sparc/include/asm/pgtable_32.h
index 5b31a8e89823..a790cc657476 100644
--- 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_bitmap;
431#define kern_addr_valid(addr) \ 431#define kern_addr_valid(addr) \
432 (test_bit(__pa((unsigned long)(addr))>>20, sparc_valid_addr_bitmap)) 432 (test_bit(__pa((unsigned long)(addr))>>20, sparc_valid_addr_bitmap))
433 433
434extern int io_remap_pfn_range(struct vm_area_struct *vma,
435 unsigned long from, unsigned long pfn,
436 unsigned long size, pgprot_t prot);
437
438/* 434/*
439 * For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in 435 * For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in
440 * its high 4 bits. These macros/functions put it there or get it from there. 436 * 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_area_struct *vma,
443#define GET_IOSPACE(pfn) (pfn >> (BITS_PER_LONG - 4)) 439#define GET_IOSPACE(pfn) (pfn >> (BITS_PER_LONG - 4))
444#define GET_PFN(pfn) (pfn & 0x0fffffffUL) 440#define GET_PFN(pfn) (pfn & 0x0fffffffUL)
445 441
442extern int remap_pfn_range(struct vm_area_struct *, unsigned long, unsigned long,
443 unsigned long, pgprot_t);
444
445static inline int io_remap_pfn_range(struct vm_area_struct *vma,
446 unsigned long from, unsigned long pfn,
447 unsigned long size, pgprot_t prot)
448{
449 unsigned long long offset, space, phys_base;
450
451 offset = ((unsigned long long) GET_PFN(pfn)) << PAGE_SHIFT;
452 space = GET_IOSPACE(pfn);
453 phys_base = offset | (space << 32ULL);
454
455 return remap_pfn_range(vma, from, phys_base >> PAGE_SHIFT, size, prot);
456}
457
446#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS 458#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
447#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \ 459#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
448({ \ 460({ \
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h
index 1e03c5a6b4f7..38ebb2c60137 100644
--- a/arch/sparc/include/asm/pgtable_64.h
+++ b/arch/sparc/include/asm/pgtable_64.h
@@ -95,6 +95,10 @@
95/* PTE bits which are the same in SUN4U and SUN4V format. */ 95/* PTE bits which are the same in SUN4U and SUN4V format. */
96#define _PAGE_VALID _AC(0x8000000000000000,UL) /* Valid TTE */ 96#define _PAGE_VALID _AC(0x8000000000000000,UL) /* Valid TTE */
97#define _PAGE_R _AC(0x8000000000000000,UL) /* Keep ref bit uptodate*/ 97#define _PAGE_R _AC(0x8000000000000000,UL) /* Keep ref bit uptodate*/
98#define _PAGE_SPECIAL _AC(0x0200000000000000,UL) /* Special page */
99
100/* Advertise support for _PAGE_SPECIAL */
101#define __HAVE_ARCH_PTE_SPECIAL
98 102
99/* SUN4U pte bits... */ 103/* SUN4U pte bits... */
100#define _PAGE_SZ4MB_4U _AC(0x6000000000000000,UL) /* 4MB Page */ 104#define _PAGE_SZ4MB_4U _AC(0x6000000000000000,UL) /* 4MB Page */
@@ -104,6 +108,7 @@
104#define _PAGE_NFO_4U _AC(0x1000000000000000,UL) /* No Fault Only */ 108#define _PAGE_NFO_4U _AC(0x1000000000000000,UL) /* No Fault Only */
105#define _PAGE_IE_4U _AC(0x0800000000000000,UL) /* Invert Endianness */ 109#define _PAGE_IE_4U _AC(0x0800000000000000,UL) /* Invert Endianness */
106#define _PAGE_SOFT2_4U _AC(0x07FC000000000000,UL) /* Software bits, set 2 */ 110#define _PAGE_SOFT2_4U _AC(0x07FC000000000000,UL) /* Software bits, set 2 */
111#define _PAGE_SPECIAL_4U _AC(0x0200000000000000,UL) /* Special page */
107#define _PAGE_RES1_4U _AC(0x0002000000000000,UL) /* Reserved */ 112#define _PAGE_RES1_4U _AC(0x0002000000000000,UL) /* Reserved */
108#define _PAGE_SZ32MB_4U _AC(0x0001000000000000,UL) /* (Panther) 32MB page */ 113#define _PAGE_SZ32MB_4U _AC(0x0001000000000000,UL) /* (Panther) 32MB page */
109#define _PAGE_SZ256MB_4U _AC(0x2001000000000000,UL) /* (Panther) 256MB page */ 114#define _PAGE_SZ256MB_4U _AC(0x2001000000000000,UL) /* (Panther) 256MB page */
@@ -133,6 +138,7 @@
133#define _PAGE_ACCESSED_4V _AC(0x1000000000000000,UL) /* Accessed (ref'd) */ 138#define _PAGE_ACCESSED_4V _AC(0x1000000000000000,UL) /* Accessed (ref'd) */
134#define _PAGE_READ_4V _AC(0x0800000000000000,UL) /* Readable SW Bit */ 139#define _PAGE_READ_4V _AC(0x0800000000000000,UL) /* Readable SW Bit */
135#define _PAGE_WRITE_4V _AC(0x0400000000000000,UL) /* Writable SW Bit */ 140#define _PAGE_WRITE_4V _AC(0x0400000000000000,UL) /* Writable SW Bit */
141#define _PAGE_SPECIAL_4V _AC(0x0200000000000000,UL) /* Special page */
136#define _PAGE_PADDR_4V _AC(0x00FFFFFFFFFFE000,UL) /* paddr[55:13] */ 142#define _PAGE_PADDR_4V _AC(0x00FFFFFFFFFFE000,UL) /* paddr[55:13] */
137#define _PAGE_IE_4V _AC(0x0000000000001000,UL) /* Invert Endianness */ 143#define _PAGE_IE_4V _AC(0x0000000000001000,UL) /* Invert Endianness */
138#define _PAGE_E_4V _AC(0x0000000000000800,UL) /* side-Effect */ 144#define _PAGE_E_4V _AC(0x0000000000000800,UL) /* side-Effect */
@@ -302,10 +308,10 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t prot)
302 : "=r" (mask), "=r" (tmp) 308 : "=r" (mask), "=r" (tmp)
303 : "i" (_PAGE_PADDR_4U | _PAGE_MODIFIED_4U | _PAGE_ACCESSED_4U | 309 : "i" (_PAGE_PADDR_4U | _PAGE_MODIFIED_4U | _PAGE_ACCESSED_4U |
304 _PAGE_CP_4U | _PAGE_CV_4U | _PAGE_E_4U | _PAGE_PRESENT_4U | 310 _PAGE_CP_4U | _PAGE_CV_4U | _PAGE_E_4U | _PAGE_PRESENT_4U |
305 _PAGE_SZBITS_4U), 311 _PAGE_SZBITS_4U | _PAGE_SPECIAL),
306 "i" (_PAGE_PADDR_4V | _PAGE_MODIFIED_4V | _PAGE_ACCESSED_4V | 312 "i" (_PAGE_PADDR_4V | _PAGE_MODIFIED_4V | _PAGE_ACCESSED_4V |
307 _PAGE_CP_4V | _PAGE_CV_4V | _PAGE_E_4V | _PAGE_PRESENT_4V | 313 _PAGE_CP_4V | _PAGE_CV_4V | _PAGE_E_4V | _PAGE_PRESENT_4V |
308 _PAGE_SZBITS_4V)); 314 _PAGE_SZBITS_4V | _PAGE_SPECIAL));
309 315
310 return __pte((pte_val(pte) & mask) | (pgprot_val(prot) & ~mask)); 316 return __pte((pte_val(pte) & mask) | (pgprot_val(prot) & ~mask));
311} 317}
@@ -502,6 +508,7 @@ static inline pte_t pte_mkyoung(pte_t pte)
502 508
503static inline pte_t pte_mkspecial(pte_t pte) 509static inline pte_t pte_mkspecial(pte_t pte)
504{ 510{
511 pte_val(pte) |= _PAGE_SPECIAL;
505 return pte; 512 return pte;
506} 513}
507 514
@@ -607,9 +614,9 @@ static inline unsigned long pte_present(pte_t pte)
607 return val; 614 return val;
608} 615}
609 616
610static inline int pte_special(pte_t pte) 617static inline unsigned long pte_special(pte_t pte)
611{ 618{
612 return 0; 619 return pte_val(pte) & _PAGE_SPECIAL;
613} 620}
614 621
615#define pmd_set(pmdp, ptep) \ 622#define pmd_set(pmdp, ptep) \
@@ -750,10 +757,6 @@ static inline bool kern_addr_valid(unsigned long addr)
750 757
751extern int page_in_phys_avail(unsigned long paddr); 758extern int page_in_phys_avail(unsigned long paddr);
752 759
753extern int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
754 unsigned long pfn,
755 unsigned long size, pgprot_t prot);
756
757/* 760/*
758 * For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in 761 * For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in
759 * its high 4 bits. These macros/functions put it there or get it from there. 762 * its high 4 bits. These macros/functions put it there or get it from there.
@@ -762,6 +765,22 @@ extern int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
762#define GET_IOSPACE(pfn) (pfn >> (BITS_PER_LONG - 4)) 765#define GET_IOSPACE(pfn) (pfn >> (BITS_PER_LONG - 4))
763#define GET_PFN(pfn) (pfn & 0x0fffffffffffffffUL) 766#define GET_PFN(pfn) (pfn & 0x0fffffffffffffffUL)
764 767
768extern int remap_pfn_range(struct vm_area_struct *, unsigned long, unsigned long,
769 unsigned long, pgprot_t);
770
771static inline int io_remap_pfn_range(struct vm_area_struct *vma,
772 unsigned long from, unsigned long pfn,
773 unsigned long size, pgprot_t prot)
774{
775 unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT;
776 int space = GET_IOSPACE(pfn);
777 unsigned long phys_base;
778
779 phys_base = offset | (((unsigned long) space) << 32UL);
780
781 return remap_pfn_range(vma, from, phys_base >> PAGE_SHIFT, size, prot);
782}
783
765#include <asm-generic/pgtable.h> 784#include <asm-generic/pgtable.h>
766 785
767/* We provide our own get_unmapped_area to cope with VA holes and 786/* We provide our own get_unmapped_area to cope with VA holes and
diff --git a/arch/sparc/include/asm/pgtsrmmu.h b/arch/sparc/include/asm/pgtsrmmu.h
index 1407c07bdade..f6ae2b2b6870 100644
--- a/arch/sparc/include/asm/pgtsrmmu.h
+++ b/arch/sparc/include/asm/pgtsrmmu.h
@@ -280,7 +280,7 @@ static inline unsigned long srmmu_hwprobe(unsigned long vaddr)
280 return retval; 280 return retval;
281} 281}
282#else 282#else
283#define srmmu_hwprobe(addr) (srmmu_swprobe(addr, 0) & SRMMU_PTE_PMASK) 283#define srmmu_hwprobe(addr) srmmu_swprobe(addr, 0)
284#endif 284#endif
285 285
286static inline int 286static inline int
diff --git a/arch/sparc/include/asm/prom.h b/arch/sparc/include/asm/prom.h
index 56bbaadef646..edd3d3cde460 100644
--- a/arch/sparc/include/asm/prom.h
+++ b/arch/sparc/include/asm/prom.h
@@ -21,7 +21,7 @@
21#include <linux/of_pdt.h> 21#include <linux/of_pdt.h>
22#include <linux/proc_fs.h> 22#include <linux/proc_fs.h>
23#include <linux/mutex.h> 23#include <linux/mutex.h>
24#include <asm/atomic.h> 24#include <linux/atomic.h>
25 25
26#define OF_ROOT_NODE_ADDR_CELLS_DEFAULT 2 26#define OF_ROOT_NODE_ADDR_CELLS_DEFAULT 2
27#define OF_ROOT_NODE_SIZE_CELLS_DEFAULT 1 27#define OF_ROOT_NODE_SIZE_CELLS_DEFAULT 1
diff --git a/arch/sparc/include/asm/ptrace.h b/arch/sparc/include/asm/ptrace.h
index c7ad3fe2b252..a0e1bcf843a1 100644
--- a/arch/sparc/include/asm/ptrace.h
+++ b/arch/sparc/include/asm/ptrace.h
@@ -205,6 +205,7 @@ do { current_thread_info()->syscall_noerror = 1; \
205} while (0) 205} while (0)
206#define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV)) 206#define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV))
207#define instruction_pointer(regs) ((regs)->tpc) 207#define instruction_pointer(regs) ((regs)->tpc)
208#define instruction_pointer_set(regs, val) ((regs)->tpc = (val))
208#define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP]) 209#define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
209#define regs_return_value(regs) ((regs)->u_regs[UREG_I0]) 210#define regs_return_value(regs) ((regs)->u_regs[UREG_I0])
210#ifdef CONFIG_SMP 211#ifdef CONFIG_SMP
@@ -212,7 +213,6 @@ extern unsigned long profile_pc(struct pt_regs *);
212#else 213#else
213#define profile_pc(regs) instruction_pointer(regs) 214#define profile_pc(regs) instruction_pointer(regs)
214#endif 215#endif
215extern void show_regs(struct pt_regs *);
216#endif /* (__KERNEL__) */ 216#endif /* (__KERNEL__) */
217 217
218#else /* __ASSEMBLY__ */ 218#else /* __ASSEMBLY__ */
@@ -256,7 +256,6 @@ static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
256#define instruction_pointer(regs) ((regs)->pc) 256#define instruction_pointer(regs) ((regs)->pc)
257#define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP]) 257#define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
258unsigned long profile_pc(struct pt_regs *); 258unsigned long profile_pc(struct pt_regs *);
259extern void show_regs(struct pt_regs *);
260#endif /* (__KERNEL__) */ 259#endif /* (__KERNEL__) */
261 260
262#else /* (!__ASSEMBLY__) */ 261#else /* (!__ASSEMBLY__) */
diff --git a/arch/sparc/include/asm/sigcontext.h b/arch/sparc/include/asm/sigcontext.h
index a1607d180354..69914d748130 100644
--- a/arch/sparc/include/asm/sigcontext.h
+++ b/arch/sparc/include/asm/sigcontext.h
@@ -45,6 +45,19 @@ typedef struct {
45 int si_mask; 45 int si_mask;
46} __siginfo32_t; 46} __siginfo32_t;
47 47
48#define __SIGC_MAXWIN 7
49
50typedef struct {
51 unsigned long locals[8];
52 unsigned long ins[8];
53} __siginfo_reg_window;
54
55typedef struct {
56 int wsaved;
57 __siginfo_reg_window reg_window[__SIGC_MAXWIN];
58 unsigned long rwbuf_stkptrs[__SIGC_MAXWIN];
59} __siginfo_rwin_t;
60
48#ifdef CONFIG_SPARC64 61#ifdef CONFIG_SPARC64
49typedef struct { 62typedef struct {
50 unsigned int si_float_regs [64]; 63 unsigned int si_float_regs [64];
@@ -73,6 +86,7 @@ struct sigcontext {
73 unsigned long ss_size; 86 unsigned long ss_size;
74 } sigc_stack; 87 } sigc_stack;
75 unsigned long sigc_mask; 88 unsigned long sigc_mask;
89 __siginfo_rwin_t * sigc_rwin_save;
76}; 90};
77 91
78#else 92#else
diff --git a/arch/sparc/include/asm/smp_32.h b/arch/sparc/include/asm/smp_32.h
index 093f10843ff2..01c51c704341 100644
--- a/arch/sparc/include/asm/smp_32.h
+++ b/arch/sparc/include/asm/smp_32.h
@@ -22,7 +22,7 @@
22 22
23#include <asm/ptrace.h> 23#include <asm/ptrace.h>
24#include <asm/asi.h> 24#include <asm/asi.h>
25#include <asm/atomic.h> 25#include <linux/atomic.h>
26 26
27/* 27/*
28 * Private routines/data 28 * Private routines/data
diff --git a/arch/sparc/include/asm/smp_64.h b/arch/sparc/include/asm/smp_64.h
index 20bca8950710..29862a9e9065 100644
--- a/arch/sparc/include/asm/smp_64.h
+++ b/arch/sparc/include/asm/smp_64.h
@@ -27,7 +27,7 @@
27 */ 27 */
28 28
29#include <linux/bitops.h> 29#include <linux/bitops.h>
30#include <asm/atomic.h> 30#include <linux/atomic.h>
31#include <asm/percpu.h> 31#include <asm/percpu.h>
32 32
33DECLARE_PER_CPU(cpumask_t, cpu_sibling_map); 33DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
diff --git a/arch/sparc/include/asm/spinlock_32.h b/arch/sparc/include/asm/spinlock_32.h
index 5f5b8bf3f50d..bcc98fc35281 100644
--- a/arch/sparc/include/asm/spinlock_32.h
+++ b/arch/sparc/include/asm/spinlock_32.h
@@ -131,6 +131,15 @@ static inline void arch_write_lock(arch_rwlock_t *rw)
131 *(volatile __u32 *)&lp->lock = ~0U; 131 *(volatile __u32 *)&lp->lock = ~0U;
132} 132}
133 133
134static void inline arch_write_unlock(arch_rwlock_t *lock)
135{
136 __asm__ __volatile__(
137" st %%g0, [%0]"
138 : /* no outputs */
139 : "r" (lock)
140 : "memory");
141}
142
134static inline int arch_write_trylock(arch_rwlock_t *rw) 143static inline int arch_write_trylock(arch_rwlock_t *rw)
135{ 144{
136 unsigned int val; 145 unsigned int val;
@@ -175,8 +184,6 @@ static inline int __arch_read_trylock(arch_rwlock_t *rw)
175 res; \ 184 res; \
176}) 185})
177 186
178#define arch_write_unlock(rw) do { (rw)->lock = 0; } while(0)
179
180#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock) 187#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock)
181#define arch_read_lock_flags(rw, flags) arch_read_lock(rw) 188#define arch_read_lock_flags(rw, flags) arch_read_lock(rw)
182#define arch_write_lock_flags(rw, flags) arch_write_lock(rw) 189#define arch_write_lock_flags(rw, flags) arch_write_lock(rw)
diff --git a/arch/sparc/include/asm/spinlock_64.h b/arch/sparc/include/asm/spinlock_64.h
index 073936a8b275..968917694978 100644
--- a/arch/sparc/include/asm/spinlock_64.h
+++ b/arch/sparc/include/asm/spinlock_64.h
@@ -210,14 +210,8 @@ static int inline arch_write_trylock(arch_rwlock_t *lock)
210 return result; 210 return result;
211} 211}
212 212
213#define arch_read_lock(p) arch_read_lock(p)
214#define arch_read_lock_flags(p, f) arch_read_lock(p) 213#define arch_read_lock_flags(p, f) arch_read_lock(p)
215#define arch_read_trylock(p) arch_read_trylock(p)
216#define arch_read_unlock(p) arch_read_unlock(p)
217#define arch_write_lock(p) arch_write_lock(p)
218#define arch_write_lock_flags(p, f) arch_write_lock(p) 214#define arch_write_lock_flags(p, f) arch_write_lock(p)
219#define arch_write_unlock(p) arch_write_unlock(p)
220#define arch_write_trylock(p) arch_write_trylock(p)
221 215
222#define arch_read_can_lock(rw) (!((rw)->lock & 0x80000000UL)) 216#define arch_read_can_lock(rw) (!((rw)->lock & 0x80000000UL))
223#define arch_write_can_lock(rw) (!(rw)->lock) 217#define arch_write_can_lock(rw) (!(rw)->lock)
diff --git a/arch/sparc/include/asm/spitfire.h b/arch/sparc/include/asm/spitfire.h
index f0d0c40c44da..d06a26601753 100644
--- a/arch/sparc/include/asm/spitfire.h
+++ b/arch/sparc/include/asm/spitfire.h
@@ -42,6 +42,9 @@
42#define SUN4V_CHIP_INVALID 0x00 42#define SUN4V_CHIP_INVALID 0x00
43#define SUN4V_CHIP_NIAGARA1 0x01 43#define SUN4V_CHIP_NIAGARA1 0x01
44#define SUN4V_CHIP_NIAGARA2 0x02 44#define SUN4V_CHIP_NIAGARA2 0x02
45#define SUN4V_CHIP_NIAGARA3 0x03
46#define SUN4V_CHIP_NIAGARA4 0x04
47#define SUN4V_CHIP_NIAGARA5 0x05
45#define SUN4V_CHIP_UNKNOWN 0xff 48#define SUN4V_CHIP_UNKNOWN 0xff
46 49
47#ifndef __ASSEMBLY__ 50#ifndef __ASSEMBLY__
diff --git a/arch/sparc/include/asm/termios.h b/arch/sparc/include/asm/termios.h
index e8ba95399643..e2f46705a210 100644
--- a/arch/sparc/include/asm/termios.h
+++ b/arch/sparc/include/asm/termios.h
@@ -40,7 +40,6 @@ struct winsize {
40}; 40};
41 41
42#ifdef __KERNEL__ 42#ifdef __KERNEL__
43#include <linux/module.h>
44 43
45/* 44/*
46 * c_cc characters in the termio structure. Oh, how I love being 45 * c_cc characters in the termio structure. Oh, how I love being
diff --git a/arch/sparc/include/asm/tsb.h b/arch/sparc/include/asm/tsb.h
index 83c571d8c8a7..1a8afd1ad04f 100644
--- a/arch/sparc/include/asm/tsb.h
+++ b/arch/sparc/include/asm/tsb.h
@@ -133,29 +133,6 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
133 sub TSB, 0x8, TSB; \ 133 sub TSB, 0x8, TSB; \
134 TSB_STORE(TSB, TAG); 134 TSB_STORE(TSB, TAG);
135 135
136#define KTSB_LOAD_QUAD(TSB, REG) \
137 ldda [TSB] ASI_NUCLEUS_QUAD_LDD, REG;
138
139#define KTSB_STORE(ADDR, VAL) \
140 stxa VAL, [ADDR] ASI_N;
141
142#define KTSB_LOCK_TAG(TSB, REG1, REG2) \
14399: lduwa [TSB] ASI_N, REG1; \
144 sethi %hi(TSB_TAG_LOCK_HIGH), REG2;\
145 andcc REG1, REG2, %g0; \
146 bne,pn %icc, 99b; \
147 nop; \
148 casa [TSB] ASI_N, REG1, REG2;\
149 cmp REG1, REG2; \
150 bne,pn %icc, 99b; \
151 nop; \
152
153#define KTSB_WRITE(TSB, TTE, TAG) \
154 add TSB, 0x8, TSB; \
155 stxa TTE, [TSB] ASI_N; \
156 sub TSB, 0x8, TSB; \
157 stxa TAG, [TSB] ASI_N;
158
159 /* Do a kernel page table walk. Leaves physical PTE pointer in 136 /* Do a kernel page table walk. Leaves physical PTE pointer in
160 * REG1. Jumps to FAIL_LABEL on early page table walk termination. 137 * REG1. Jumps to FAIL_LABEL on early page table walk termination.
161 * VADDR will not be clobbered, but REG2 will. 138 * VADDR will not be clobbered, but REG2 will.
@@ -239,6 +216,8 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
239 (KERNEL_TSB_SIZE_BYTES / 16) 216 (KERNEL_TSB_SIZE_BYTES / 16)
240#define KERNEL_TSB4M_NENTRIES 4096 217#define KERNEL_TSB4M_NENTRIES 4096
241 218
219#define KTSB_PHYS_SHIFT 15
220
242 /* Do a kernel TSB lookup at tl>0 on VADDR+TAG, branch to OK_LABEL 221 /* Do a kernel TSB lookup at tl>0 on VADDR+TAG, branch to OK_LABEL
243 * on TSB hit. REG1, REG2, REG3, and REG4 are used as temporaries 222 * on TSB hit. REG1, REG2, REG3, and REG4 are used as temporaries
244 * and the found TTE will be left in REG1. REG3 and REG4 must 223 * and the found TTE will be left in REG1. REG3 and REG4 must
@@ -247,13 +226,22 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
247 * VADDR and TAG will be preserved and not clobbered by this macro. 226 * VADDR and TAG will be preserved and not clobbered by this macro.
248 */ 227 */
249#define KERN_TSB_LOOKUP_TL1(VADDR, TAG, REG1, REG2, REG3, REG4, OK_LABEL) \ 228#define KERN_TSB_LOOKUP_TL1(VADDR, TAG, REG1, REG2, REG3, REG4, OK_LABEL) \
250 sethi %hi(swapper_tsb), REG1; \ 229661: sethi %hi(swapper_tsb), REG1; \
251 or REG1, %lo(swapper_tsb), REG1; \ 230 or REG1, %lo(swapper_tsb), REG1; \
231 .section .swapper_tsb_phys_patch, "ax"; \
232 .word 661b; \
233 .previous; \
234661: nop; \
235 .section .tsb_ldquad_phys_patch, "ax"; \
236 .word 661b; \
237 sllx REG1, KTSB_PHYS_SHIFT, REG1; \
238 sllx REG1, KTSB_PHYS_SHIFT, REG1; \
239 .previous; \
252 srlx VADDR, PAGE_SHIFT, REG2; \ 240 srlx VADDR, PAGE_SHIFT, REG2; \
253 and REG2, (KERNEL_TSB_NENTRIES - 1), REG2; \ 241 and REG2, (KERNEL_TSB_NENTRIES - 1), REG2; \
254 sllx REG2, 4, REG2; \ 242 sllx REG2, 4, REG2; \
255 add REG1, REG2, REG2; \ 243 add REG1, REG2, REG2; \
256 KTSB_LOAD_QUAD(REG2, REG3); \ 244 TSB_LOAD_QUAD(REG2, REG3); \
257 cmp REG3, TAG; \ 245 cmp REG3, TAG; \
258 be,a,pt %xcc, OK_LABEL; \ 246 be,a,pt %xcc, OK_LABEL; \
259 mov REG4, REG1; 247 mov REG4, REG1;
@@ -263,12 +251,21 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
263 * we can make use of that for the index computation. 251 * we can make use of that for the index computation.
264 */ 252 */
265#define KERN_TSB4M_LOOKUP_TL1(TAG, REG1, REG2, REG3, REG4, OK_LABEL) \ 253#define KERN_TSB4M_LOOKUP_TL1(TAG, REG1, REG2, REG3, REG4, OK_LABEL) \
266 sethi %hi(swapper_4m_tsb), REG1; \ 254661: sethi %hi(swapper_4m_tsb), REG1; \
267 or REG1, %lo(swapper_4m_tsb), REG1; \ 255 or REG1, %lo(swapper_4m_tsb), REG1; \
256 .section .swapper_4m_tsb_phys_patch, "ax"; \
257 .word 661b; \
258 .previous; \
259661: nop; \
260 .section .tsb_ldquad_phys_patch, "ax"; \
261 .word 661b; \
262 sllx REG1, KTSB_PHYS_SHIFT, REG1; \
263 sllx REG1, KTSB_PHYS_SHIFT, REG1; \
264 .previous; \
268 and TAG, (KERNEL_TSB4M_NENTRIES - 1), REG2; \ 265 and TAG, (KERNEL_TSB4M_NENTRIES - 1), REG2; \
269 sllx REG2, 4, REG2; \ 266 sllx REG2, 4, REG2; \
270 add REG1, REG2, REG2; \ 267 add REG1, REG2, REG2; \
271 KTSB_LOAD_QUAD(REG2, REG3); \ 268 TSB_LOAD_QUAD(REG2, REG3); \
272 cmp REG3, TAG; \ 269 cmp REG3, TAG; \
273 be,a,pt %xcc, OK_LABEL; \ 270 be,a,pt %xcc, OK_LABEL; \
274 mov REG4, REG1; 271 mov REG4, REG1;
diff --git a/arch/sparc/include/asm/unistd.h b/arch/sparc/include/asm/unistd.h
index 6260d5deeabc..c7cb0af0eb59 100644
--- a/arch/sparc/include/asm/unistd.h
+++ b/arch/sparc/include/asm/unistd.h
@@ -406,8 +406,10 @@
406#define __NR_syncfs 335 406#define __NR_syncfs 335
407#define __NR_sendmmsg 336 407#define __NR_sendmmsg 336
408#define __NR_setns 337 408#define __NR_setns 337
409#define __NR_process_vm_readv 338
410#define __NR_process_vm_writev 339
409 411
410#define NR_syscalls 338 412#define NR_syscalls 340
411 413
412#ifdef __32bit_syscall_numbers__ 414#ifdef __32bit_syscall_numbers__
413/* Sparc 32-bit only has the "setresuid32", "getresuid32" variants, 415/* Sparc 32-bit only has the "setresuid32", "getresuid32" variants,
diff --git a/arch/sparc/include/asm/xor_64.h b/arch/sparc/include/asm/xor_64.h
index bee4bf4be3af..ee8edc68423e 100644
--- a/arch/sparc/include/asm/xor_64.h
+++ b/arch/sparc/include/asm/xor_64.h
@@ -65,6 +65,9 @@ static struct xor_block_template xor_block_niagara = {
65#define XOR_SELECT_TEMPLATE(FASTEST) \ 65#define XOR_SELECT_TEMPLATE(FASTEST) \
66 ((tlb_type == hypervisor && \ 66 ((tlb_type == hypervisor && \
67 (sun4v_chip_type == SUN4V_CHIP_NIAGARA1 || \ 67 (sun4v_chip_type == SUN4V_CHIP_NIAGARA1 || \
68 sun4v_chip_type == SUN4V_CHIP_NIAGARA2)) ? \ 68 sun4v_chip_type == SUN4V_CHIP_NIAGARA2 || \
69 sun4v_chip_type == SUN4V_CHIP_NIAGARA3 || \
70 sun4v_chip_type == SUN4V_CHIP_NIAGARA4 || \
71 sun4v_chip_type == SUN4V_CHIP_NIAGARA5)) ? \
69 &xor_block_niagara : \ 72 &xor_block_niagara : \
70 &xor_block_VIS) 73 &xor_block_VIS)
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
index b90b4a1d070a..cb85458f89d2 100644
--- a/arch/sparc/kernel/Makefile
+++ b/arch/sparc/kernel/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_SPARC32) += sun4m_irq.o sun4c_irq.o sun4d_irq.o
32 32
33obj-y += process_$(BITS).o 33obj-y += process_$(BITS).o
34obj-y += signal_$(BITS).o 34obj-y += signal_$(BITS).o
35obj-y += sigutil_$(BITS).o
35obj-$(CONFIG_SPARC32) += ioport.o 36obj-$(CONFIG_SPARC32) += ioport.o
36obj-y += setup_$(BITS).o 37obj-y += setup_$(BITS).o
37obj-y += idprom.o 38obj-y += idprom.o
diff --git a/arch/sparc/kernel/apc.c b/arch/sparc/kernel/apc.c
index caef9deb5866..812e10bbb0b3 100644
--- a/arch/sparc/kernel/apc.c
+++ b/arch/sparc/kernel/apc.c
@@ -13,6 +13,7 @@
13#include <linux/pm.h> 13#include <linux/pm.h>
14#include <linux/of.h> 14#include <linux/of.h>
15#include <linux/of_device.h> 15#include <linux/of_device.h>
16#include <linux/module.h>
16 17
17#include <asm/io.h> 18#include <asm/io.h>
18#include <asm/oplib.h> 19#include <asm/oplib.h>
diff --git a/arch/sparc/kernel/auxio_32.c b/arch/sparc/kernel/auxio_32.c
index acf5151f3c1d..f7ea8f032719 100644
--- a/arch/sparc/kernel/auxio_32.c
+++ b/arch/sparc/kernel/auxio_32.c
@@ -8,6 +8,7 @@
8#include <linux/spinlock.h> 8#include <linux/spinlock.h>
9#include <linux/of.h> 9#include <linux/of.h>
10#include <linux/of_device.h> 10#include <linux/of_device.h>
11#include <linux/export.h>
11#include <asm/oplib.h> 12#include <asm/oplib.h>
12#include <asm/io.h> 13#include <asm/io.h>
13#include <asm/auxio.h> 14#include <asm/auxio.h>
diff --git a/arch/sparc/kernel/btext.c b/arch/sparc/kernel/btext.c
index 89aa4eb20cf5..57073e56ba9e 100644
--- a/arch/sparc/kernel/btext.c
+++ b/arch/sparc/kernel/btext.c
@@ -6,7 +6,6 @@
6#include <linux/kernel.h> 6#include <linux/kernel.h>
7#include <linux/string.h> 7#include <linux/string.h>
8#include <linux/init.h> 8#include <linux/init.h>
9#include <linux/module.h>
10#include <linux/console.h> 9#include <linux/console.h>
11 10
12#include <asm/btext.h> 11#include <asm/btext.h>
diff --git a/arch/sparc/kernel/central.c b/arch/sparc/kernel/central.c
index 7eef3f741963..38d48a59879c 100644
--- a/arch/sparc/kernel/central.c
+++ b/arch/sparc/kernel/central.c
@@ -6,6 +6,7 @@
6#include <linux/kernel.h> 6#include <linux/kernel.h>
7#include <linux/types.h> 7#include <linux/types.h>
8#include <linux/slab.h> 8#include <linux/slab.h>
9#include <linux/export.h>
9#include <linux/string.h> 10#include <linux/string.h>
10#include <linux/init.h> 11#include <linux/init.h>
11#include <linux/of_device.h> 12#include <linux/of_device.h>
diff --git a/arch/sparc/kernel/cpu.c b/arch/sparc/kernel/cpu.c
index 138dbbc8dc84..2d1819641769 100644
--- a/arch/sparc/kernel/cpu.c
+++ b/arch/sparc/kernel/cpu.c
@@ -6,7 +6,7 @@
6 6
7#include <linux/seq_file.h> 7#include <linux/seq_file.h>
8#include <linux/kernel.h> 8#include <linux/kernel.h>
9#include <linux/module.h> 9#include <linux/export.h>
10#include <linux/init.h> 10#include <linux/init.h>
11#include <linux/smp.h> 11#include <linux/smp.h>
12#include <linux/threads.h> 12#include <linux/threads.h>
@@ -396,6 +396,7 @@ static int show_cpuinfo(struct seq_file *m, void *__unused)
396 , cpu_data(0).clock_tick 396 , cpu_data(0).clock_tick
397#endif 397#endif
398 ); 398 );
399 cpucap_info(m);
399#ifdef CONFIG_SMP 400#ifdef CONFIG_SMP
400 smp_bogo(m); 401 smp_bogo(m);
401#endif 402#endif
@@ -474,11 +475,30 @@ static void __init sun4v_cpu_probe(void)
474 sparc_pmu_type = "niagara2"; 475 sparc_pmu_type = "niagara2";
475 break; 476 break;
476 477
478 case SUN4V_CHIP_NIAGARA3:
479 sparc_cpu_type = "UltraSparc T3 (Niagara3)";
480 sparc_fpu_type = "UltraSparc T3 integrated FPU";
481 sparc_pmu_type = "niagara3";
482 break;
483
484 case SUN4V_CHIP_NIAGARA4:
485 sparc_cpu_type = "UltraSparc T4 (Niagara4)";
486 sparc_fpu_type = "UltraSparc T4 integrated FPU";
487 sparc_pmu_type = "niagara4";
488 break;
489
490 case SUN4V_CHIP_NIAGARA5:
491 sparc_cpu_type = "UltraSparc T5 (Niagara5)";
492 sparc_fpu_type = "UltraSparc T5 integrated FPU";
493 sparc_pmu_type = "niagara5";
494 break;
495
477 default: 496 default:
478 printk(KERN_WARNING "CPU: Unknown sun4v cpu type [%s]\n", 497 printk(KERN_WARNING "CPU: Unknown sun4v cpu type [%s]\n",
479 prom_cpu_compatible); 498 prom_cpu_compatible);
480 sparc_cpu_type = "Unknown SUN4V CPU"; 499 sparc_cpu_type = "Unknown SUN4V CPU";
481 sparc_fpu_type = "Unknown SUN4V FPU"; 500 sparc_fpu_type = "Unknown SUN4V FPU";
501 sparc_pmu_type = "Unknown SUN4V PMU";
482 break; 502 break;
483 } 503 }
484} 504}
diff --git a/arch/sparc/kernel/cpumap.c b/arch/sparc/kernel/cpumap.c
index d91fd782743a..e4de74c2c9b0 100644
--- a/arch/sparc/kernel/cpumap.c
+++ b/arch/sparc/kernel/cpumap.c
@@ -3,7 +3,7 @@
3 * Copyright (C) 2009 Hong H. Pham <hong.pham@windriver.com> 3 * Copyright (C) 2009 Hong H. Pham <hong.pham@windriver.com>
4 */ 4 */
5 5
6#include <linux/module.h> 6#include <linux/export.h>
7#include <linux/slab.h> 7#include <linux/slab.h>
8#include <linux/kernel.h> 8#include <linux/kernel.h>
9#include <linux/init.h> 9#include <linux/init.h>
@@ -324,6 +324,9 @@ static int iterate_cpu(struct cpuinfo_tree *t, unsigned int root_index)
324 switch (sun4v_chip_type) { 324 switch (sun4v_chip_type) {
325 case SUN4V_CHIP_NIAGARA1: 325 case SUN4V_CHIP_NIAGARA1:
326 case SUN4V_CHIP_NIAGARA2: 326 case SUN4V_CHIP_NIAGARA2:
327 case SUN4V_CHIP_NIAGARA3:
328 case SUN4V_CHIP_NIAGARA4:
329 case SUN4V_CHIP_NIAGARA5:
327 rover_inc_table = niagara_iterate_method; 330 rover_inc_table = niagara_iterate_method;
328 break; 331 break;
329 default: 332 default:
diff --git a/arch/sparc/kernel/dma.c b/arch/sparc/kernel/dma.c
index e1ba8ee21b9a..b667aa6f28f6 100644
--- a/arch/sparc/kernel/dma.c
+++ b/arch/sparc/kernel/dma.c
@@ -1,5 +1,4 @@
1#include <linux/kernel.h> 1#include <linux/kernel.h>
2#include <linux/module.h>
3#include <linux/dma-mapping.h> 2#include <linux/dma-mapping.h>
4#include <linux/dma-debug.h> 3#include <linux/dma-debug.h>
5 4
diff --git a/arch/sparc/kernel/ds.c b/arch/sparc/kernel/ds.c
index dd1342c0a3be..7429b47c3aca 100644
--- a/arch/sparc/kernel/ds.c
+++ b/arch/sparc/kernel/ds.c
@@ -15,12 +15,15 @@
15#include <linux/reboot.h> 15#include <linux/reboot.h>
16#include <linux/cpu.h> 16#include <linux/cpu.h>
17 17
18#include <asm/hypervisor.h>
18#include <asm/ldc.h> 19#include <asm/ldc.h>
19#include <asm/vio.h> 20#include <asm/vio.h>
20#include <asm/mdesc.h> 21#include <asm/mdesc.h>
21#include <asm/head.h> 22#include <asm/head.h>
22#include <asm/irq.h> 23#include <asm/irq.h>
23 24
25#include "kernel.h"
26
24#define DRV_MODULE_NAME "ds" 27#define DRV_MODULE_NAME "ds"
25#define PFX DRV_MODULE_NAME ": " 28#define PFX DRV_MODULE_NAME ": "
26#define DRV_MODULE_VERSION "1.0" 29#define DRV_MODULE_VERSION "1.0"
@@ -828,18 +831,32 @@ void ldom_set_var(const char *var, const char *value)
828 } 831 }
829} 832}
830 833
834static char full_boot_str[256] __attribute__((aligned(32)));
835static int reboot_data_supported;
836
831void ldom_reboot(const char *boot_command) 837void ldom_reboot(const char *boot_command)
832{ 838{
833 /* Don't bother with any of this if the boot_command 839 /* Don't bother with any of this if the boot_command
834 * is empty. 840 * is empty.
835 */ 841 */
836 if (boot_command && strlen(boot_command)) { 842 if (boot_command && strlen(boot_command)) {
837 char full_boot_str[256]; 843 unsigned long len;
838 844
839 strcpy(full_boot_str, "boot "); 845 strcpy(full_boot_str, "boot ");
840 strcpy(full_boot_str + strlen("boot "), boot_command); 846 strcpy(full_boot_str + strlen("boot "), boot_command);
847 len = strlen(full_boot_str);
841 848
842 ldom_set_var("reboot-command", full_boot_str); 849 if (reboot_data_supported) {
850 unsigned long ra = kimage_addr_to_ra(full_boot_str);
851 unsigned long hv_ret;
852
853 hv_ret = sun4v_reboot_data_set(ra, len);
854 if (hv_ret != HV_EOK)
855 pr_err("SUN4V: Unable to set reboot data "
856 "hv_ret=%lu\n", hv_ret);
857 } else {
858 ldom_set_var("reboot-command", full_boot_str);
859 }
843 } 860 }
844 sun4v_mach_sir(); 861 sun4v_mach_sir();
845} 862}
@@ -1237,6 +1254,16 @@ static struct vio_driver ds_driver = {
1237 1254
1238static int __init ds_init(void) 1255static int __init ds_init(void)
1239{ 1256{
1257 unsigned long hv_ret, major, minor;
1258
1259 if (tlb_type == hypervisor) {
1260 hv_ret = sun4v_get_version(HV_GRP_REBOOT_DATA, &major, &minor);
1261 if (hv_ret == HV_EOK) {
1262 pr_info("SUN4V: Reboot data supported (maj=%lu,min=%lu).\n",
1263 major, minor);
1264 reboot_data_supported = 1;
1265 }
1266 }
1240 kthread_run(ds_thread, NULL, "kldomd"); 1267 kthread_run(ds_thread, NULL, "kldomd");
1241 1268
1242 return vio_register_driver(&ds_driver); 1269 return vio_register_driver(&ds_driver);
diff --git a/arch/sparc/kernel/ebus.c b/arch/sparc/kernel/ebus.c
index 77dbf6d45faf..e306fb08ee5e 100644
--- a/arch/sparc/kernel/ebus.c
+++ b/arch/sparc/kernel/ebus.c
@@ -4,7 +4,7 @@
4 * Copyright (C) 1999 David S. Miller (davem@redhat.com) 4 * Copyright (C) 1999 David S. Miller (davem@redhat.com)
5 */ 5 */
6 6
7#include <linux/module.h> 7#include <linux/export.h>
8#include <linux/kernel.h> 8#include <linux/kernel.h>
9#include <linux/types.h> 9#include <linux/types.h>
10#include <linux/init.h> 10#include <linux/init.h>
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
index 9fe08a1ea6c6..f445e98463e6 100644
--- a/arch/sparc/kernel/entry.S
+++ b/arch/sparc/kernel/entry.S
@@ -293,7 +293,7 @@ maybe_smp4m_msg:
293 WRITE_PAUSE 293 WRITE_PAUSE
294 wr %l4, PSR_ET, %psr 294 wr %l4, PSR_ET, %psr
295 WRITE_PAUSE 295 WRITE_PAUSE
296 sll %o3, 28, %o2 ! shift for simpler checks below 296 srl %o3, 28, %o2 ! shift for simpler checks below
297maybe_smp4m_msg_check_single: 297maybe_smp4m_msg_check_single:
298 andcc %o2, 0x1, %g0 298 andcc %o2, 0x1, %g0
299 beq,a maybe_smp4m_msg_check_mask 299 beq,a maybe_smp4m_msg_check_mask
diff --git a/arch/sparc/kernel/entry.h b/arch/sparc/kernel/entry.h
index d1f1361c4167..0c218e4c0881 100644
--- a/arch/sparc/kernel/entry.h
+++ b/arch/sparc/kernel/entry.h
@@ -42,7 +42,28 @@ extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
42extern void fpload(unsigned long *fpregs, unsigned long *fsr); 42extern void fpload(unsigned long *fpregs, unsigned long *fsr);
43 43
44#else /* CONFIG_SPARC32 */ 44#else /* CONFIG_SPARC32 */
45
46#include <asm/trap_block.h>
47
48struct popc_3insn_patch_entry {
49 unsigned int addr;
50 unsigned int insns[3];
51};
52extern struct popc_3insn_patch_entry __popc_3insn_patch,
53 __popc_3insn_patch_end;
54
55struct popc_6insn_patch_entry {
56 unsigned int addr;
57 unsigned int insns[6];
58};
59extern struct popc_6insn_patch_entry __popc_6insn_patch,
60 __popc_6insn_patch_end;
61
45extern void __init per_cpu_patch(void); 62extern void __init per_cpu_patch(void);
63extern void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *,
64 struct sun4v_1insn_patch_entry *);
65extern void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *,
66 struct sun4v_2insn_patch_entry *);
46extern void __init sun4v_patch(void); 67extern void __init sun4v_patch(void);
47extern void __init boot_cpu_id_too_large(int cpu); 68extern void __init boot_cpu_id_too_large(int cpu);
48extern unsigned int dcache_parity_tl1_occurred; 69extern unsigned int dcache_parity_tl1_occurred;
diff --git a/arch/sparc/kernel/head_64.S b/arch/sparc/kernel/head_64.S
index aa594c792d19..0d810c2f1d00 100644
--- a/arch/sparc/kernel/head_64.S
+++ b/arch/sparc/kernel/head_64.S
@@ -132,6 +132,8 @@ prom_sun4v_name:
132 .asciz "sun4v" 132 .asciz "sun4v"
133prom_niagara_prefix: 133prom_niagara_prefix:
134 .asciz "SUNW,UltraSPARC-T" 134 .asciz "SUNW,UltraSPARC-T"
135prom_sparc_prefix:
136 .asciz "SPARC-"
135 .align 4 137 .align 4
136prom_root_compatible: 138prom_root_compatible:
137 .skip 64 139 .skip 64
@@ -382,6 +384,22 @@ sun4v_chip_type:
38290: ldub [%g7], %g2 38490: ldub [%g7], %g2
383 ldub [%g1], %g4 385 ldub [%g1], %g4
384 cmp %g2, %g4 386 cmp %g2, %g4
387 bne,pn %icc, 89f
388 add %g7, 1, %g7
389 subcc %g3, 1, %g3
390 bne,pt %xcc, 90b
391 add %g1, 1, %g1
392 ba,pt %xcc, 91f
393 nop
394
39589: sethi %hi(prom_cpu_compatible), %g1
396 or %g1, %lo(prom_cpu_compatible), %g1
397 sethi %hi(prom_sparc_prefix), %g7
398 or %g7, %lo(prom_sparc_prefix), %g7
399 mov 6, %g3
40090: ldub [%g7], %g2
401 ldub [%g1], %g4
402 cmp %g2, %g4
385 bne,pn %icc, 4f 403 bne,pn %icc, 4f
386 add %g7, 1, %g7 404 add %g7, 1, %g7
387 subcc %g3, 1, %g3 405 subcc %g3, 1, %g3
@@ -390,6 +408,28 @@ sun4v_chip_type:
390 408
391 sethi %hi(prom_cpu_compatible), %g1 409 sethi %hi(prom_cpu_compatible), %g1
392 or %g1, %lo(prom_cpu_compatible), %g1 410 or %g1, %lo(prom_cpu_compatible), %g1
411 ldub [%g1 + 6], %g2
412 cmp %g2, 'T'
413 be,pt %xcc, 70f
414 cmp %g2, 'M'
415 bne,pn %xcc, 4f
416 nop
417
41870: ldub [%g1 + 7], %g2
419 cmp %g2, '3'
420 be,pt %xcc, 5f
421 mov SUN4V_CHIP_NIAGARA3, %g4
422 cmp %g2, '4'
423 be,pt %xcc, 5f
424 mov SUN4V_CHIP_NIAGARA4, %g4
425 cmp %g2, '5'
426 be,pt %xcc, 5f
427 mov SUN4V_CHIP_NIAGARA5, %g4
428 ba,pt %xcc, 4f
429 nop
430
43191: sethi %hi(prom_cpu_compatible), %g1
432 or %g1, %lo(prom_cpu_compatible), %g1
393 ldub [%g1 + 17], %g2 433 ldub [%g1 + 17], %g2
394 cmp %g2, '1' 434 cmp %g2, '1'
395 be,pt %xcc, 5f 435 be,pt %xcc, 5f
@@ -397,6 +437,7 @@ sun4v_chip_type:
397 cmp %g2, '2' 437 cmp %g2, '2'
398 be,pt %xcc, 5f 438 be,pt %xcc, 5f
399 mov SUN4V_CHIP_NIAGARA2, %g4 439 mov SUN4V_CHIP_NIAGARA2, %g4
440
4004: 4414:
401 mov SUN4V_CHIP_UNKNOWN, %g4 442 mov SUN4V_CHIP_UNKNOWN, %g4
4025: sethi %hi(sun4v_chip_type), %g2 4435: sethi %hi(sun4v_chip_type), %g2
@@ -514,6 +555,15 @@ niagara_tlb_fixup:
514 cmp %g1, SUN4V_CHIP_NIAGARA2 555 cmp %g1, SUN4V_CHIP_NIAGARA2
515 be,pt %xcc, niagara2_patch 556 be,pt %xcc, niagara2_patch
516 nop 557 nop
558 cmp %g1, SUN4V_CHIP_NIAGARA3
559 be,pt %xcc, niagara2_patch
560 nop
561 cmp %g1, SUN4V_CHIP_NIAGARA4
562 be,pt %xcc, niagara2_patch
563 nop
564 cmp %g1, SUN4V_CHIP_NIAGARA5
565 be,pt %xcc, niagara2_patch
566 nop
517 567
518 call generic_patch_copyops 568 call generic_patch_copyops
519 nop 569 nop
@@ -528,7 +578,7 @@ niagara2_patch:
528 nop 578 nop
529 call niagara_patch_bzero 579 call niagara_patch_bzero
530 nop 580 nop
531 call niagara2_patch_pageops 581 call niagara_patch_pageops
532 nop 582 nop
533 583
534 ba,a,pt %xcc, 80f 584 ba,a,pt %xcc, 80f
diff --git a/arch/sparc/kernel/hvapi.c b/arch/sparc/kernel/hvapi.c
index 7c60afb835b0..8593672838fd 100644
--- a/arch/sparc/kernel/hvapi.c
+++ b/arch/sparc/kernel/hvapi.c
@@ -3,7 +3,7 @@
3 * Copyright (C) 2007 David S. Miller <davem@davemloft.net> 3 * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
4 */ 4 */
5#include <linux/kernel.h> 5#include <linux/kernel.h>
6#include <linux/module.h> 6#include <linux/export.h>
7#include <linux/init.h> 7#include <linux/init.h>
8 8
9#include <asm/hypervisor.h> 9#include <asm/hypervisor.h>
@@ -28,16 +28,23 @@ static struct api_info api_table[] = {
28 { .group = HV_GRP_CORE, .flags = FLAG_PRE_API }, 28 { .group = HV_GRP_CORE, .flags = FLAG_PRE_API },
29 { .group = HV_GRP_INTR, }, 29 { .group = HV_GRP_INTR, },
30 { .group = HV_GRP_SOFT_STATE, }, 30 { .group = HV_GRP_SOFT_STATE, },
31 { .group = HV_GRP_TM, },
31 { .group = HV_GRP_PCI, .flags = FLAG_PRE_API }, 32 { .group = HV_GRP_PCI, .flags = FLAG_PRE_API },
32 { .group = HV_GRP_LDOM, }, 33 { .group = HV_GRP_LDOM, },
33 { .group = HV_GRP_SVC_CHAN, .flags = FLAG_PRE_API }, 34 { .group = HV_GRP_SVC_CHAN, .flags = FLAG_PRE_API },
34 { .group = HV_GRP_NCS, .flags = FLAG_PRE_API }, 35 { .group = HV_GRP_NCS, .flags = FLAG_PRE_API },
35 { .group = HV_GRP_RNG, }, 36 { .group = HV_GRP_RNG, },
37 { .group = HV_GRP_PBOOT, },
38 { .group = HV_GRP_TPM, },
39 { .group = HV_GRP_SDIO, },
40 { .group = HV_GRP_SDIO_ERR, },
41 { .group = HV_GRP_REBOOT_DATA, },
36 { .group = HV_GRP_NIAG_PERF, .flags = FLAG_PRE_API }, 42 { .group = HV_GRP_NIAG_PERF, .flags = FLAG_PRE_API },
37 { .group = HV_GRP_FIRE_PERF, }, 43 { .group = HV_GRP_FIRE_PERF, },
38 { .group = HV_GRP_N2_CPU, }, 44 { .group = HV_GRP_N2_CPU, },
39 { .group = HV_GRP_NIU, }, 45 { .group = HV_GRP_NIU, },
40 { .group = HV_GRP_VF_CPU, }, 46 { .group = HV_GRP_VF_CPU, },
47 { .group = HV_GRP_KT_CPU, },
41 { .group = HV_GRP_DIAG, .flags = FLAG_PRE_API }, 48 { .group = HV_GRP_DIAG, .flags = FLAG_PRE_API },
42}; 49};
43 50
diff --git a/arch/sparc/kernel/hvcalls.S b/arch/sparc/kernel/hvcalls.S
index 8a5f35ffb15e..58d60de4d65b 100644
--- a/arch/sparc/kernel/hvcalls.S
+++ b/arch/sparc/kernel/hvcalls.S
@@ -798,3 +798,10 @@ ENTRY(sun4v_niagara2_setperf)
798 retl 798 retl
799 nop 799 nop
800ENDPROC(sun4v_niagara2_setperf) 800ENDPROC(sun4v_niagara2_setperf)
801
802ENTRY(sun4v_reboot_data_set)
803 mov HV_FAST_REBOOT_DATA_SET, %o5
804 ta HV_FAST_TRAP
805 retl
806 nop
807ENDPROC(sun4v_reboot_data_set)
diff --git a/arch/sparc/kernel/idprom.c b/arch/sparc/kernel/idprom.c
index 52a15fe2db19..9167db40720e 100644
--- a/arch/sparc/kernel/idprom.c
+++ b/arch/sparc/kernel/idprom.c
@@ -8,7 +8,7 @@
8#include <linux/kernel.h> 8#include <linux/kernel.h>
9#include <linux/types.h> 9#include <linux/types.h>
10#include <linux/init.h> 10#include <linux/init.h>
11#include <linux/module.h> 11#include <linux/export.h>
12 12
13#include <asm/oplib.h> 13#include <asm/oplib.h>
14#include <asm/idprom.h> 14#include <asm/idprom.h>
diff --git a/arch/sparc/kernel/iommu.c b/arch/sparc/kernel/iommu.c
index 6f01e8c83197..4643d68713fa 100644
--- a/arch/sparc/kernel/iommu.c
+++ b/arch/sparc/kernel/iommu.c
@@ -5,7 +5,7 @@
5 */ 5 */
6 6
7#include <linux/kernel.h> 7#include <linux/kernel.h>
8#include <linux/module.h> 8#include <linux/export.h>
9#include <linux/slab.h> 9#include <linux/slab.h>
10#include <linux/delay.h> 10#include <linux/delay.h>
11#include <linux/device.h> 11#include <linux/device.h>
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index 1c9c80a1a86a..d0479e2163fa 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -65,9 +65,6 @@ static inline void dma_make_coherent(unsigned long pa, unsigned long len)
65} 65}
66#endif 66#endif
67 67
68static struct resource *_sparc_find_resource(struct resource *r,
69 unsigned long);
70
71static void __iomem *_sparc_ioremap(struct resource *res, u32 bus, u32 pa, int sz); 68static void __iomem *_sparc_ioremap(struct resource *res, u32 bus, u32 pa, int sz);
72static void __iomem *_sparc_alloc_io(unsigned int busno, unsigned long phys, 69static void __iomem *_sparc_alloc_io(unsigned int busno, unsigned long phys,
73 unsigned long size, char *name); 70 unsigned long size, char *name);
@@ -143,7 +140,11 @@ void iounmap(volatile void __iomem *virtual)
143 unsigned long vaddr = (unsigned long) virtual & PAGE_MASK; 140 unsigned long vaddr = (unsigned long) virtual & PAGE_MASK;
144 struct resource *res; 141 struct resource *res;
145 142
146 if ((res = _sparc_find_resource(&sparc_iomap, vaddr)) == NULL) { 143 /*
144 * XXX Too slow. Can have 8192 DVMA pages on sun4m in the worst case.
145 * This probably warrants some sort of hashing.
146 */
147 if ((res = lookup_resource(&sparc_iomap, vaddr)) == NULL) {
147 printk("free_io/iounmap: cannot free %lx\n", vaddr); 148 printk("free_io/iounmap: cannot free %lx\n", vaddr);
148 return; 149 return;
149 } 150 }
@@ -228,7 +229,7 @@ _sparc_ioremap(struct resource *res, u32 bus, u32 pa, int sz)
228 } 229 }
229 230
230 pa &= PAGE_MASK; 231 pa &= PAGE_MASK;
231 sparc_mapiorange(bus, pa, res->start, res->end - res->start + 1); 232 sparc_mapiorange(bus, pa, res->start, resource_size(res));
232 233
233 return (void __iomem *)(unsigned long)(res->start + offset); 234 return (void __iomem *)(unsigned long)(res->start + offset);
234} 235}
@@ -240,7 +241,7 @@ static void _sparc_free_io(struct resource *res)
240{ 241{
241 unsigned long plen; 242 unsigned long plen;
242 243
243 plen = res->end - res->start + 1; 244 plen = resource_size(res);
244 BUG_ON((plen & (PAGE_SIZE-1)) != 0); 245 BUG_ON((plen & (PAGE_SIZE-1)) != 0);
245 sparc_unmapiorange(res->start, plen); 246 sparc_unmapiorange(res->start, plen);
246 release_resource(res); 247 release_resource(res);
@@ -319,7 +320,7 @@ static void sbus_free_coherent(struct device *dev, size_t n, void *p,
319 struct resource *res; 320 struct resource *res;
320 struct page *pgv; 321 struct page *pgv;
321 322
322 if ((res = _sparc_find_resource(&_sparc_dvma, 323 if ((res = lookup_resource(&_sparc_dvma,
323 (unsigned long)p)) == NULL) { 324 (unsigned long)p)) == NULL) {
324 printk("sbus_free_consistent: cannot free %p\n", p); 325 printk("sbus_free_consistent: cannot free %p\n", p);
325 return; 326 return;
@@ -331,9 +332,9 @@ static void sbus_free_coherent(struct device *dev, size_t n, void *p,
331 } 332 }
332 333
333 n = PAGE_ALIGN(n); 334 n = PAGE_ALIGN(n);
334 if ((res->end-res->start)+1 != n) { 335 if (resource_size(res) != n) {
335 printk("sbus_free_consistent: region 0x%lx asked 0x%zx\n", 336 printk("sbus_free_consistent: region 0x%lx asked 0x%zx\n",
336 (long)((res->end-res->start)+1), n); 337 (long)resource_size(res), n);
337 return; 338 return;
338 } 339 }
339 340
@@ -492,7 +493,7 @@ static void pci32_free_coherent(struct device *dev, size_t n, void *p,
492{ 493{
493 struct resource *res; 494 struct resource *res;
494 495
495 if ((res = _sparc_find_resource(&_sparc_dvma, 496 if ((res = lookup_resource(&_sparc_dvma,
496 (unsigned long)p)) == NULL) { 497 (unsigned long)p)) == NULL) {
497 printk("pci_free_consistent: cannot free %p\n", p); 498 printk("pci_free_consistent: cannot free %p\n", p);
498 return; 499 return;
@@ -504,9 +505,9 @@ static void pci32_free_coherent(struct device *dev, size_t n, void *p,
504 } 505 }
505 506
506 n = PAGE_ALIGN(n); 507 n = PAGE_ALIGN(n);
507 if ((res->end-res->start)+1 != n) { 508 if (resource_size(res) != n) {
508 printk("pci_free_consistent: region 0x%lx asked 0x%lx\n", 509 printk("pci_free_consistent: region 0x%lx asked 0x%lx\n",
509 (long)((res->end-res->start)+1), (long)n); 510 (long)resource_size(res), (long)n);
510 return; 511 return;
511 } 512 }
512 513
@@ -715,25 +716,6 @@ static const struct file_operations sparc_io_proc_fops = {
715}; 716};
716#endif /* CONFIG_PROC_FS */ 717#endif /* CONFIG_PROC_FS */
717 718
718/*
719 * This is a version of find_resource and it belongs to kernel/resource.c.
720 * Until we have agreement with Linus and Martin, it lingers here.
721 *
722 * XXX Too slow. Can have 8192 DVMA pages on sun4m in the worst case.
723 * This probably warrants some sort of hashing.
724 */
725static struct resource *_sparc_find_resource(struct resource *root,
726 unsigned long hit)
727{
728 struct resource *tmp;
729
730 for (tmp = root->child; tmp != 0; tmp = tmp->sibling) {
731 if (tmp->start <= hit && tmp->end >= hit)
732 return tmp;
733 }
734 return NULL;
735}
736
737static void register_proc_sparc_ioport(void) 719static void register_proc_sparc_ioport(void)
738{ 720{
739#ifdef CONFIG_PROC_FS 721#ifdef CONFIG_PROC_FS
diff --git a/arch/sparc/kernel/irq.h b/arch/sparc/kernel/irq.h
index 100b9c204e78..42851122bbd9 100644
--- a/arch/sparc/kernel/irq.h
+++ b/arch/sparc/kernel/irq.h
@@ -88,7 +88,7 @@ BTFIXUPDEF_CALL(void, set_irq_udt, int)
88#define set_irq_udt(cpu) BTFIXUP_CALL(set_irq_udt)(cpu) 88#define set_irq_udt(cpu) BTFIXUP_CALL(set_irq_udt)(cpu)
89 89
90/* All SUN4D IPIs are sent on this IRQ, may be shared with hard IRQs */ 90/* All SUN4D IPIs are sent on this IRQ, may be shared with hard IRQs */
91#define SUN4D_IPI_IRQ 14 91#define SUN4D_IPI_IRQ 13
92 92
93extern void sun4d_ipi_interrupt(void); 93extern void sun4d_ipi_interrupt(void);
94 94
diff --git a/arch/sparc/kernel/irq_32.c b/arch/sparc/kernel/irq_32.c
index 9b89d842913c..b2668afd1c34 100644
--- a/arch/sparc/kernel/irq_32.c
+++ b/arch/sparc/kernel/irq_32.c
@@ -13,6 +13,7 @@
13 13
14#include <linux/kernel_stat.h> 14#include <linux/kernel_stat.h>
15#include <linux/seq_file.h> 15#include <linux/seq_file.h>
16#include <linux/export.h>
16 17
17#include <asm/cacheflush.h> 18#include <asm/cacheflush.h>
18#include <asm/cpudata.h> 19#include <asm/cpudata.h>
diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c
index 4e78862d12fd..d45b710ea7e4 100644
--- a/arch/sparc/kernel/irq_64.c
+++ b/arch/sparc/kernel/irq_64.c
@@ -5,7 +5,6 @@
5 * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) 5 * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz)
6 */ 6 */
7 7
8#include <linux/module.h>
9#include <linux/sched.h> 8#include <linux/sched.h>
10#include <linux/linkage.h> 9#include <linux/linkage.h>
11#include <linux/ptrace.h> 10#include <linux/ptrace.h>
@@ -26,7 +25,7 @@
26 25
27#include <asm/ptrace.h> 26#include <asm/ptrace.h>
28#include <asm/processor.h> 27#include <asm/processor.h>
29#include <asm/atomic.h> 28#include <linux/atomic.h>
30#include <asm/system.h> 29#include <asm/system.h>
31#include <asm/irq.h> 30#include <asm/irq.h>
32#include <asm/io.h> 31#include <asm/io.h>
diff --git a/arch/sparc/kernel/jump_label.c b/arch/sparc/kernel/jump_label.c
index ea2dafc93d78..971fd435a281 100644
--- a/arch/sparc/kernel/jump_label.c
+++ b/arch/sparc/kernel/jump_label.c
@@ -36,12 +36,4 @@ void arch_jump_label_transform(struct jump_entry *entry,
36 put_online_cpus(); 36 put_online_cpus();
37} 37}
38 38
39void arch_jump_label_text_poke_early(jump_label_t addr)
40{
41 u32 *insn_p = (u32 *) (unsigned long) addr;
42
43 *insn_p = 0x01000000;
44 flushi(insn_p);
45}
46
47#endif 39#endif
diff --git a/arch/sparc/kernel/kernel.h b/arch/sparc/kernel/kernel.h
index 6f6544cfa0ef..fd6c36b1df74 100644
--- a/arch/sparc/kernel/kernel.h
+++ b/arch/sparc/kernel/kernel.h
@@ -4,12 +4,27 @@
4#include <linux/interrupt.h> 4#include <linux/interrupt.h>
5 5
6#include <asm/traps.h> 6#include <asm/traps.h>
7#include <asm/head.h>
8#include <asm/io.h>
7 9
8/* cpu.c */ 10/* cpu.c */
9extern const char *sparc_pmu_type; 11extern const char *sparc_pmu_type;
10extern unsigned int fsr_storage; 12extern unsigned int fsr_storage;
11extern int ncpus_probed; 13extern int ncpus_probed;
12 14
15#ifdef CONFIG_SPARC64
16/* setup_64.c */
17struct seq_file;
18extern void cpucap_info(struct seq_file *);
19
20static inline unsigned long kimage_addr_to_ra(const char *p)
21{
22 unsigned long val = (unsigned long) p;
23
24 return kern_base + (val - KERNBASE);
25}
26#endif
27
13#ifdef CONFIG_SPARC32 28#ifdef CONFIG_SPARC32
14/* cpu.c */ 29/* cpu.c */
15extern void cpu_probe(void); 30extern void cpu_probe(void);
diff --git a/arch/sparc/kernel/ktlb.S b/arch/sparc/kernel/ktlb.S
index 1d361477d7d6..79f310364849 100644
--- a/arch/sparc/kernel/ktlb.S
+++ b/arch/sparc/kernel/ktlb.S
@@ -47,16 +47,16 @@ kvmap_itlb_tsb_miss:
47kvmap_itlb_vmalloc_addr: 47kvmap_itlb_vmalloc_addr:
48 KERN_PGTABLE_WALK(%g4, %g5, %g2, kvmap_itlb_longpath) 48 KERN_PGTABLE_WALK(%g4, %g5, %g2, kvmap_itlb_longpath)
49 49
50 KTSB_LOCK_TAG(%g1, %g2, %g7) 50 TSB_LOCK_TAG(%g1, %g2, %g7)
51 51
52 /* Load and check PTE. */ 52 /* Load and check PTE. */
53 ldxa [%g5] ASI_PHYS_USE_EC, %g5 53 ldxa [%g5] ASI_PHYS_USE_EC, %g5
54 mov 1, %g7 54 mov 1, %g7
55 sllx %g7, TSB_TAG_INVALID_BIT, %g7 55 sllx %g7, TSB_TAG_INVALID_BIT, %g7
56 brgez,a,pn %g5, kvmap_itlb_longpath 56 brgez,a,pn %g5, kvmap_itlb_longpath
57 KTSB_STORE(%g1, %g7) 57 TSB_STORE(%g1, %g7)
58 58
59 KTSB_WRITE(%g1, %g5, %g6) 59 TSB_WRITE(%g1, %g5, %g6)
60 60
61 /* fallthrough to TLB load */ 61 /* fallthrough to TLB load */
62 62
@@ -102,9 +102,9 @@ kvmap_itlb_longpath:
102kvmap_itlb_obp: 102kvmap_itlb_obp:
103 OBP_TRANS_LOOKUP(%g4, %g5, %g2, %g3, kvmap_itlb_longpath) 103 OBP_TRANS_LOOKUP(%g4, %g5, %g2, %g3, kvmap_itlb_longpath)
104 104
105 KTSB_LOCK_TAG(%g1, %g2, %g7) 105 TSB_LOCK_TAG(%g1, %g2, %g7)
106 106
107 KTSB_WRITE(%g1, %g5, %g6) 107 TSB_WRITE(%g1, %g5, %g6)
108 108
109 ba,pt %xcc, kvmap_itlb_load 109 ba,pt %xcc, kvmap_itlb_load
110 nop 110 nop
@@ -112,17 +112,17 @@ kvmap_itlb_obp:
112kvmap_dtlb_obp: 112kvmap_dtlb_obp:
113 OBP_TRANS_LOOKUP(%g4, %g5, %g2, %g3, kvmap_dtlb_longpath) 113 OBP_TRANS_LOOKUP(%g4, %g5, %g2, %g3, kvmap_dtlb_longpath)
114 114
115 KTSB_LOCK_TAG(%g1, %g2, %g7) 115 TSB_LOCK_TAG(%g1, %g2, %g7)
116 116
117 KTSB_WRITE(%g1, %g5, %g6) 117 TSB_WRITE(%g1, %g5, %g6)
118 118
119 ba,pt %xcc, kvmap_dtlb_load 119 ba,pt %xcc, kvmap_dtlb_load
120 nop 120 nop
121 121
122 .align 32 122 .align 32
123kvmap_dtlb_tsb4m_load: 123kvmap_dtlb_tsb4m_load:
124 KTSB_LOCK_TAG(%g1, %g2, %g7) 124 TSB_LOCK_TAG(%g1, %g2, %g7)
125 KTSB_WRITE(%g1, %g5, %g6) 125 TSB_WRITE(%g1, %g5, %g6)
126 ba,pt %xcc, kvmap_dtlb_load 126 ba,pt %xcc, kvmap_dtlb_load
127 nop 127 nop
128 128
@@ -222,16 +222,16 @@ kvmap_linear_patch:
222kvmap_dtlb_vmalloc_addr: 222kvmap_dtlb_vmalloc_addr:
223 KERN_PGTABLE_WALK(%g4, %g5, %g2, kvmap_dtlb_longpath) 223 KERN_PGTABLE_WALK(%g4, %g5, %g2, kvmap_dtlb_longpath)
224 224
225 KTSB_LOCK_TAG(%g1, %g2, %g7) 225 TSB_LOCK_TAG(%g1, %g2, %g7)
226 226
227 /* Load and check PTE. */ 227 /* Load and check PTE. */
228 ldxa [%g5] ASI_PHYS_USE_EC, %g5 228 ldxa [%g5] ASI_PHYS_USE_EC, %g5
229 mov 1, %g7 229 mov 1, %g7
230 sllx %g7, TSB_TAG_INVALID_BIT, %g7 230 sllx %g7, TSB_TAG_INVALID_BIT, %g7
231 brgez,a,pn %g5, kvmap_dtlb_longpath 231 brgez,a,pn %g5, kvmap_dtlb_longpath
232 KTSB_STORE(%g1, %g7) 232 TSB_STORE(%g1, %g7)
233 233
234 KTSB_WRITE(%g1, %g5, %g6) 234 TSB_WRITE(%g1, %g5, %g6)
235 235
236 /* fallthrough to TLB load */ 236 /* fallthrough to TLB load */
237 237
diff --git a/arch/sparc/kernel/ldc.c b/arch/sparc/kernel/ldc.c
index 732b0bce6001..435e406fdec3 100644
--- a/arch/sparc/kernel/ldc.c
+++ b/arch/sparc/kernel/ldc.c
@@ -4,7 +4,7 @@
4 */ 4 */
5 5
6#include <linux/kernel.h> 6#include <linux/kernel.h>
7#include <linux/module.h> 7#include <linux/export.h>
8#include <linux/slab.h> 8#include <linux/slab.h>
9#include <linux/spinlock.h> 9#include <linux/spinlock.h>
10#include <linux/delay.h> 10#include <linux/delay.h>
diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c
index d17255a2bbac..a19c8a063683 100644
--- a/arch/sparc/kernel/leon_kernel.c
+++ b/arch/sparc/kernel/leon_kernel.c
@@ -4,7 +4,6 @@
4 */ 4 */
5 5
6#include <linux/kernel.h> 6#include <linux/kernel.h>
7#include <linux/module.h>
8#include <linux/errno.h> 7#include <linux/errno.h>
9#include <linux/mutex.h> 8#include <linux/mutex.h>
10#include <linux/of.h> 9#include <linux/of.h>
diff --git a/arch/sparc/kernel/leon_pci.c b/arch/sparc/kernel/leon_pci.c
index a8a9a275037d..f1cf6ef011a7 100644
--- a/arch/sparc/kernel/leon_pci.c
+++ b/arch/sparc/kernel/leon_pci.c
@@ -9,6 +9,7 @@
9#include <linux/of_device.h> 9#include <linux/of_device.h>
10#include <linux/kernel.h> 10#include <linux/kernel.h>
11#include <linux/pci.h> 11#include <linux/pci.h>
12#include <linux/export.h>
12#include <asm/leon.h> 13#include <asm/leon.h>
13#include <asm/leon_pci.h> 14#include <asm/leon_pci.h>
14 15
diff --git a/arch/sparc/kernel/leon_pci_grpci2.c b/arch/sparc/kernel/leon_pci_grpci2.c
index 44dc093ee33a..b1bc38853a3d 100644
--- a/arch/sparc/kernel/leon_pci_grpci2.c
+++ b/arch/sparc/kernel/leon_pci_grpci2.c
@@ -9,7 +9,7 @@
9#include <linux/kernel.h> 9#include <linux/kernel.h>
10#include <linux/pci.h> 10#include <linux/pci.h>
11#include <linux/delay.h> 11#include <linux/delay.h>
12#include <linux/module.h> 12#include <linux/export.h>
13#include <asm/io.h> 13#include <asm/io.h>
14#include <asm/leon.h> 14#include <asm/leon.h>
15#include <asm/vaddrs.h> 15#include <asm/vaddrs.h>
@@ -215,7 +215,7 @@ struct grpci2_priv {
215DEFINE_SPINLOCK(grpci2_dev_lock); 215DEFINE_SPINLOCK(grpci2_dev_lock);
216struct grpci2_priv *grpci2priv; 216struct grpci2_priv *grpci2priv;
217 217
218int grpci2_map_irq(struct pci_dev *dev, u8 slot, u8 pin) 218int grpci2_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
219{ 219{
220 struct grpci2_priv *priv = dev->bus->sysdata; 220 struct grpci2_priv *priv = dev->bus->sysdata;
221 int irq_group; 221 int irq_group;
diff --git a/arch/sparc/kernel/leon_smp.c b/arch/sparc/kernel/leon_smp.c
index fe8fb44c609c..1210fde18740 100644
--- a/arch/sparc/kernel/leon_smp.c
+++ b/arch/sparc/kernel/leon_smp.c
@@ -28,7 +28,7 @@
28#include <asm/tlbflush.h> 28#include <asm/tlbflush.h>
29 29
30#include <asm/ptrace.h> 30#include <asm/ptrace.h>
31#include <asm/atomic.h> 31#include <linux/atomic.h>
32#include <asm/irq_regs.h> 32#include <asm/irq_regs.h>
33#include <asm/traps.h> 33#include <asm/traps.h>
34 34
diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c
index 42f28c7420e1..6dc796280589 100644
--- a/arch/sparc/kernel/mdesc.c
+++ b/arch/sparc/kernel/mdesc.c
@@ -11,11 +11,13 @@
11#include <linux/mm.h> 11#include <linux/mm.h>
12#include <linux/miscdevice.h> 12#include <linux/miscdevice.h>
13#include <linux/bootmem.h> 13#include <linux/bootmem.h>
14#include <linux/export.h>
14 15
15#include <asm/cpudata.h> 16#include <asm/cpudata.h>
16#include <asm/hypervisor.h> 17#include <asm/hypervisor.h>
17#include <asm/mdesc.h> 18#include <asm/mdesc.h>
18#include <asm/prom.h> 19#include <asm/prom.h>
20#include <asm/uaccess.h>
19#include <asm/oplib.h> 21#include <asm/oplib.h>
20#include <asm/smp.h> 22#include <asm/smp.h>
21 23
@@ -508,6 +510,8 @@ const char *mdesc_node_name(struct mdesc_handle *hp, u64 node)
508} 510}
509EXPORT_SYMBOL(mdesc_node_name); 511EXPORT_SYMBOL(mdesc_node_name);
510 512
513static u64 max_cpus = 64;
514
511static void __init report_platform_properties(void) 515static void __init report_platform_properties(void)
512{ 516{
513 struct mdesc_handle *hp = mdesc_grab(); 517 struct mdesc_handle *hp = mdesc_grab();
@@ -543,8 +547,10 @@ static void __init report_platform_properties(void)
543 if (v) 547 if (v)
544 printk("PLATFORM: watchdog-max-timeout [%llu ms]\n", *v); 548 printk("PLATFORM: watchdog-max-timeout [%llu ms]\n", *v);
545 v = mdesc_get_property(hp, pn, "max-cpus", NULL); 549 v = mdesc_get_property(hp, pn, "max-cpus", NULL);
546 if (v) 550 if (v) {
547 printk("PLATFORM: max-cpus [%llu]\n", *v); 551 max_cpus = *v;
552 printk("PLATFORM: max-cpus [%llu]\n", max_cpus);
553 }
548 554
549#ifdef CONFIG_SMP 555#ifdef CONFIG_SMP
550 { 556 {
@@ -715,7 +721,7 @@ static void __cpuinit set_proc_ids(struct mdesc_handle *hp)
715} 721}
716 722
717static void __cpuinit get_one_mondo_bits(const u64 *p, unsigned int *mask, 723static void __cpuinit get_one_mondo_bits(const u64 *p, unsigned int *mask,
718 unsigned char def) 724 unsigned long def, unsigned long max)
719{ 725{
720 u64 val; 726 u64 val;
721 727
@@ -726,6 +732,9 @@ static void __cpuinit get_one_mondo_bits(const u64 *p, unsigned int *mask,
726 if (!val || val >= 64) 732 if (!val || val >= 64)
727 goto use_default; 733 goto use_default;
728 734
735 if (val > max)
736 val = max;
737
729 *mask = ((1U << val) * 64U) - 1U; 738 *mask = ((1U << val) * 64U) - 1U;
730 return; 739 return;
731 740
@@ -736,19 +745,28 @@ use_default:
736static void __cpuinit get_mondo_data(struct mdesc_handle *hp, u64 mp, 745static void __cpuinit get_mondo_data(struct mdesc_handle *hp, u64 mp,
737 struct trap_per_cpu *tb) 746 struct trap_per_cpu *tb)
738{ 747{
748 static int printed;
739 const u64 *val; 749 const u64 *val;
740 750
741 val = mdesc_get_property(hp, mp, "q-cpu-mondo-#bits", NULL); 751 val = mdesc_get_property(hp, mp, "q-cpu-mondo-#bits", NULL);
742 get_one_mondo_bits(val, &tb->cpu_mondo_qmask, 7); 752 get_one_mondo_bits(val, &tb->cpu_mondo_qmask, 7, ilog2(max_cpus * 2));
743 753
744 val = mdesc_get_property(hp, mp, "q-dev-mondo-#bits", NULL); 754 val = mdesc_get_property(hp, mp, "q-dev-mondo-#bits", NULL);
745 get_one_mondo_bits(val, &tb->dev_mondo_qmask, 7); 755 get_one_mondo_bits(val, &tb->dev_mondo_qmask, 7, 8);
746 756
747 val = mdesc_get_property(hp, mp, "q-resumable-#bits", NULL); 757 val = mdesc_get_property(hp, mp, "q-resumable-#bits", NULL);
748 get_one_mondo_bits(val, &tb->resum_qmask, 6); 758 get_one_mondo_bits(val, &tb->resum_qmask, 6, 7);
749 759
750 val = mdesc_get_property(hp, mp, "q-nonresumable-#bits", NULL); 760 val = mdesc_get_property(hp, mp, "q-nonresumable-#bits", NULL);
751 get_one_mondo_bits(val, &tb->nonresum_qmask, 2); 761 get_one_mondo_bits(val, &tb->nonresum_qmask, 2, 2);
762 if (!printed++) {
763 pr_info("SUN4V: Mondo queue sizes "
764 "[cpu(%u) dev(%u) r(%u) nr(%u)]\n",
765 tb->cpu_mondo_qmask + 1,
766 tb->dev_mondo_qmask + 1,
767 tb->resum_qmask + 1,
768 tb->nonresum_qmask + 1);
769 }
752} 770}
753 771
754static void * __cpuinit mdesc_iterate_over_cpus(void *(*func)(struct mdesc_handle *, u64, int, void *), void *arg, cpumask_t *mask) 772static void * __cpuinit mdesc_iterate_over_cpus(void *(*func)(struct mdesc_handle *, u64, int, void *), void *arg, cpumask_t *mask)
diff --git a/arch/sparc/kernel/module.c b/arch/sparc/kernel/module.c
index 99ba5baa9497..e5519870c3d9 100644
--- a/arch/sparc/kernel/module.c
+++ b/arch/sparc/kernel/module.c
@@ -17,6 +17,8 @@
17#include <asm/processor.h> 17#include <asm/processor.h>
18#include <asm/spitfire.h> 18#include <asm/spitfire.h>
19 19
20#include "entry.h"
21
20#ifdef CONFIG_SPARC64 22#ifdef CONFIG_SPARC64
21 23
22#include <linux/jump_label.h> 24#include <linux/jump_label.h>
@@ -68,12 +70,6 @@ void *module_alloc(unsigned long size)
68 return ret; 70 return ret;
69} 71}
70 72
71/* Free memory returned from module_core_alloc/module_init_alloc */
72void module_free(struct module *mod, void *module_region)
73{
74 vfree(module_region);
75}
76
77/* Make generic code ignore STT_REGISTER dummy undefined symbols. */ 73/* Make generic code ignore STT_REGISTER dummy undefined symbols. */
78int module_frob_arch_sections(Elf_Ehdr *hdr, 74int module_frob_arch_sections(Elf_Ehdr *hdr,
79 Elf_Shdr *sechdrs, 75 Elf_Shdr *sechdrs,
@@ -107,17 +103,6 @@ int module_frob_arch_sections(Elf_Ehdr *hdr,
107 return 0; 103 return 0;
108} 104}
109 105
110int apply_relocate(Elf_Shdr *sechdrs,
111 const char *strtab,
112 unsigned int symindex,
113 unsigned int relsec,
114 struct module *me)
115{
116 printk(KERN_ERR "module %s: non-ADD RELOCATION unsupported\n",
117 me->name);
118 return -ENOEXEC;
119}
120
121int apply_relocate_add(Elf_Shdr *sechdrs, 106int apply_relocate_add(Elf_Shdr *sechdrs,
122 const char *strtab, 107 const char *strtab,
123 unsigned int symindex, 108 unsigned int symindex,
@@ -220,6 +205,29 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
220} 205}
221 206
222#ifdef CONFIG_SPARC64 207#ifdef CONFIG_SPARC64
208static void do_patch_sections(const Elf_Ehdr *hdr,
209 const Elf_Shdr *sechdrs)
210{
211 const Elf_Shdr *s, *sun4v_1insn = NULL, *sun4v_2insn = NULL;
212 char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
213
214 for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
215 if (!strcmp(".sun4v_1insn_patch", secstrings + s->sh_name))
216 sun4v_1insn = s;
217 if (!strcmp(".sun4v_2insn_patch", secstrings + s->sh_name))
218 sun4v_2insn = s;
219 }
220
221 if (sun4v_1insn && tlb_type == hypervisor) {
222 void *p = (void *) sun4v_1insn->sh_addr;
223 sun4v_patch_1insn_range(p, p + sun4v_1insn->sh_size);
224 }
225 if (sun4v_2insn && tlb_type == hypervisor) {
226 void *p = (void *) sun4v_2insn->sh_addr;
227 sun4v_patch_2insn_range(p, p + sun4v_2insn->sh_size);
228 }
229}
230
223int module_finalize(const Elf_Ehdr *hdr, 231int module_finalize(const Elf_Ehdr *hdr,
224 const Elf_Shdr *sechdrs, 232 const Elf_Shdr *sechdrs,
225 struct module *me) 233 struct module *me)
@@ -227,6 +235,8 @@ int module_finalize(const Elf_Ehdr *hdr,
227 /* make jump label nops */ 235 /* make jump label nops */
228 jump_label_apply_nops(me); 236 jump_label_apply_nops(me);
229 237
238 do_patch_sections(hdr, sechdrs);
239
230 /* Cheetah's I-cache is fully coherent. */ 240 /* Cheetah's I-cache is fully coherent. */
231 if (tlb_type == spitfire) { 241 if (tlb_type == spitfire) {
232 unsigned long va; 242 unsigned long va;
@@ -239,15 +249,4 @@ int module_finalize(const Elf_Ehdr *hdr,
239 249
240 return 0; 250 return 0;
241} 251}
242#else
243int module_finalize(const Elf_Ehdr *hdr,
244 const Elf_Shdr *sechdrs,
245 struct module *me)
246{
247 return 0;
248}
249#endif /* CONFIG_SPARC64 */ 252#endif /* CONFIG_SPARC64 */
250
251void module_arch_cleanup(struct module *mod)
252{
253}
diff --git a/arch/sparc/kernel/nmi.c b/arch/sparc/kernel/nmi.c
index 300f810142f5..c76fe0b5bd94 100644
--- a/arch/sparc/kernel/nmi.c
+++ b/arch/sparc/kernel/nmi.c
@@ -10,7 +10,7 @@
10#include <linux/init.h> 10#include <linux/init.h>
11#include <linux/percpu.h> 11#include <linux/percpu.h>
12#include <linux/nmi.h> 12#include <linux/nmi.h>
13#include <linux/module.h> 13#include <linux/export.h>
14#include <linux/kprobes.h> 14#include <linux/kprobes.h>
15#include <linux/kernel_stat.h> 15#include <linux/kernel_stat.h>
16#include <linux/reboot.h> 16#include <linux/reboot.h>
diff --git a/arch/sparc/kernel/of_device_32.c b/arch/sparc/kernel/of_device_32.c
index a312af40ea84..4ee8ce0d5d8d 100644
--- a/arch/sparc/kernel/of_device_32.c
+++ b/arch/sparc/kernel/of_device_32.c
@@ -2,7 +2,6 @@
2#include <linux/kernel.h> 2#include <linux/kernel.h>
3#include <linux/of.h> 3#include <linux/of.h>
4#include <linux/init.h> 4#include <linux/init.h>
5#include <linux/module.h>
6#include <linux/mod_devicetable.h> 5#include <linux/mod_devicetable.h>
7#include <linux/slab.h> 6#include <linux/slab.h>
8#include <linux/errno.h> 7#include <linux/errno.h>
diff --git a/arch/sparc/kernel/of_device_64.c b/arch/sparc/kernel/of_device_64.c
index 3bb2eace58cf..7a3be6f6737a 100644
--- a/arch/sparc/kernel/of_device_64.c
+++ b/arch/sparc/kernel/of_device_64.c
@@ -2,13 +2,14 @@
2#include <linux/kernel.h> 2#include <linux/kernel.h>
3#include <linux/of.h> 3#include <linux/of.h>
4#include <linux/init.h> 4#include <linux/init.h>
5#include <linux/module.h> 5#include <linux/export.h>
6#include <linux/mod_devicetable.h> 6#include <linux/mod_devicetable.h>
7#include <linux/slab.h> 7#include <linux/slab.h>
8#include <linux/errno.h> 8#include <linux/errno.h>
9#include <linux/irq.h> 9#include <linux/irq.h>
10#include <linux/of_device.h> 10#include <linux/of_device.h>
11#include <linux/of_platform.h> 11#include <linux/of_platform.h>
12#include <asm/spitfire.h>
12 13
13#include "of_device_common.h" 14#include "of_device_common.h"
14 15
diff --git a/arch/sparc/kernel/of_device_common.c b/arch/sparc/kernel/of_device_common.c
index cb15bbf8a201..de199bf0cb05 100644
--- a/arch/sparc/kernel/of_device_common.c
+++ b/arch/sparc/kernel/of_device_common.c
@@ -2,7 +2,7 @@
2#include <linux/kernel.h> 2#include <linux/kernel.h>
3#include <linux/of.h> 3#include <linux/of.h>
4#include <linux/init.h> 4#include <linux/init.h>
5#include <linux/module.h> 5#include <linux/export.h>
6#include <linux/mod_devicetable.h> 6#include <linux/mod_devicetable.h>
7#include <linux/errno.h> 7#include <linux/errno.h>
8#include <linux/irq.h> 8#include <linux/irq.h>
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index 713dc91020a6..31111e35281e 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -8,7 +8,7 @@
8 * with minor modifications, see there for credits. 8 * with minor modifications, see there for credits.
9 */ 9 */
10 10
11#include <linux/module.h> 11#include <linux/export.h>
12#include <linux/kernel.h> 12#include <linux/kernel.h>
13#include <linux/string.h> 13#include <linux/string.h>
14#include <linux/sched.h> 14#include <linux/sched.h>
@@ -230,7 +230,8 @@ static void pci_parse_of_addrs(struct platform_device *op,
230 res = &dev->resource[(i - PCI_BASE_ADDRESS_0) >> 2]; 230 res = &dev->resource[(i - PCI_BASE_ADDRESS_0) >> 2];
231 } else if (i == dev->rom_base_reg) { 231 } else if (i == dev->rom_base_reg) {
232 res = &dev->resource[PCI_ROM_RESOURCE]; 232 res = &dev->resource[PCI_ROM_RESOURCE];
233 flags |= IORESOURCE_READONLY | IORESOURCE_CACHEABLE; 233 flags |= IORESOURCE_READONLY | IORESOURCE_CACHEABLE
234 | IORESOURCE_SIZEALIGN;
234 } else { 235 } else {
235 printk(KERN_ERR "PCI: bad cfg reg num 0x%x\n", i); 236 printk(KERN_ERR "PCI: bad cfg reg num 0x%x\n", i);
236 continue; 237 continue;
@@ -284,7 +285,7 @@ static struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
284 dev->sysdata = node; 285 dev->sysdata = node;
285 dev->dev.parent = bus->bridge; 286 dev->dev.parent = bus->bridge;
286 dev->dev.bus = &pci_bus_type; 287 dev->dev.bus = &pci_bus_type;
287 dev->dev.of_node = node; 288 dev->dev.of_node = of_node_get(node);
288 dev->devfn = devfn; 289 dev->devfn = devfn;
289 dev->multifunction = 0; /* maybe a lie? */ 290 dev->multifunction = 0; /* maybe a lie? */
290 set_pcie_port_type(dev); 291 set_pcie_port_type(dev);
@@ -820,11 +821,9 @@ static int __pci_mmap_make_offset_bus(struct pci_dev *pdev, struct vm_area_struc
820 unsigned long space_size, user_offset, user_size; 821 unsigned long space_size, user_offset, user_size;
821 822
822 if (mmap_state == pci_mmap_io) { 823 if (mmap_state == pci_mmap_io) {
823 space_size = (pbm->io_space.end - 824 space_size = resource_size(&pbm->io_space);
824 pbm->io_space.start) + 1;
825 } else { 825 } else {
826 space_size = (pbm->mem_space.end - 826 space_size = resource_size(&pbm->mem_space);
827 pbm->mem_space.start) + 1;
828 } 827 }
829 828
830 /* Make sure the request is in range. */ 829 /* Make sure the request is in range. */
@@ -1021,12 +1020,6 @@ void arch_teardown_msi_irq(unsigned int irq)
1021} 1020}
1022#endif /* !(CONFIG_PCI_MSI) */ 1021#endif /* !(CONFIG_PCI_MSI) */
1023 1022
1024struct device_node *pci_device_to_OF_node(struct pci_dev *pdev)
1025{
1026 return pdev->dev.of_node;
1027}
1028EXPORT_SYMBOL(pci_device_to_OF_node);
1029
1030static void ali_sound_dma_hack(struct pci_dev *pdev, int set_bit) 1023static void ali_sound_dma_hack(struct pci_dev *pdev, int set_bit)
1031{ 1024{
1032 struct pci_dev *ali_isa_bridge; 1025 struct pci_dev *ali_isa_bridge;
diff --git a/arch/sparc/kernel/pci_fire.c b/arch/sparc/kernel/pci_fire.c
index d29a32fcc5e4..188f935276fd 100644
--- a/arch/sparc/kernel/pci_fire.c
+++ b/arch/sparc/kernel/pci_fire.c
@@ -7,6 +7,7 @@
7#include <linux/slab.h> 7#include <linux/slab.h>
8#include <linux/init.h> 8#include <linux/init.h>
9#include <linux/msi.h> 9#include <linux/msi.h>
10#include <linux/export.h>
10#include <linux/irq.h> 11#include <linux/irq.h>
11#include <linux/of_device.h> 12#include <linux/of_device.h>
12 13
diff --git a/arch/sparc/kernel/pci_psycho.c b/arch/sparc/kernel/pci_psycho.c
index 86ae08d9b6ee..f4d29e15ce71 100644
--- a/arch/sparc/kernel/pci_psycho.c
+++ b/arch/sparc/kernel/pci_psycho.c
@@ -9,6 +9,7 @@
9#include <linux/types.h> 9#include <linux/types.h>
10#include <linux/pci.h> 10#include <linux/pci.h>
11#include <linux/init.h> 11#include <linux/init.h>
12#include <linux/export.h>
12#include <linux/slab.h> 13#include <linux/slab.h>
13#include <linux/interrupt.h> 14#include <linux/interrupt.h>
14#include <linux/of_device.h> 15#include <linux/of_device.h>
diff --git a/arch/sparc/kernel/pci_sabre.c b/arch/sparc/kernel/pci_sabre.c
index d1840dbdaa2f..3efaa4644d60 100644
--- a/arch/sparc/kernel/pci_sabre.c
+++ b/arch/sparc/kernel/pci_sabre.c
@@ -9,6 +9,7 @@
9#include <linux/types.h> 9#include <linux/types.h>
10#include <linux/pci.h> 10#include <linux/pci.h>
11#include <linux/init.h> 11#include <linux/init.h>
12#include <linux/export.h>
12#include <linux/slab.h> 13#include <linux/slab.h>
13#include <linux/interrupt.h> 14#include <linux/interrupt.h>
14#include <linux/of_device.h> 15#include <linux/of_device.h>
diff --git a/arch/sparc/kernel/pci_schizo.c b/arch/sparc/kernel/pci_schizo.c
index f030b02edddd..13d4aa20b5a5 100644
--- a/arch/sparc/kernel/pci_schizo.c
+++ b/arch/sparc/kernel/pci_schizo.c
@@ -8,6 +8,7 @@
8#include <linux/pci.h> 8#include <linux/pci.h>
9#include <linux/init.h> 9#include <linux/init.h>
10#include <linux/slab.h> 10#include <linux/slab.h>
11#include <linux/export.h>
11#include <linux/interrupt.h> 12#include <linux/interrupt.h>
12#include <linux/of_device.h> 13#include <linux/of_device.h>
13 14
diff --git a/arch/sparc/kernel/pci_sun4v.c b/arch/sparc/kernel/pci_sun4v.c
index b01a06e9ae4e..b272cda35a01 100644
--- a/arch/sparc/kernel/pci_sun4v.c
+++ b/arch/sparc/kernel/pci_sun4v.c
@@ -12,6 +12,7 @@
12#include <linux/percpu.h> 12#include <linux/percpu.h>
13#include <linux/irq.h> 13#include <linux/irq.h>
14#include <linux/msi.h> 14#include <linux/msi.h>
15#include <linux/export.h>
15#include <linux/log2.h> 16#include <linux/log2.h>
16#include <linux/of_device.h> 17#include <linux/of_device.h>
17 18
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index 948601a066ff..fcc148effaac 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -25,6 +25,7 @@
25#include <linux/time.h> 25#include <linux/time.h>
26#include <linux/timex.h> 26#include <linux/timex.h>
27#include <linux/interrupt.h> 27#include <linux/interrupt.h>
28#include <linux/export.h>
28 29
29#include <asm/irq.h> 30#include <asm/irq.h>
30#include <asm/oplib.h> 31#include <asm/oplib.h>
@@ -352,8 +353,8 @@ int __init pcic_probe(void)
352 strcpy(pbm->prom_name, namebuf); 353 strcpy(pbm->prom_name, namebuf);
353 354
354 { 355 {
355 extern volatile int t_nmi[1]; 356 extern volatile int t_nmi[4];
356 extern int pcic_nmi_trap_patch[1]; 357 extern int pcic_nmi_trap_patch[4];
357 358
358 t_nmi[0] = pcic_nmi_trap_patch[0]; 359 t_nmi[0] = pcic_nmi_trap_patch[0];
359 t_nmi[1] = pcic_nmi_trap_patch[1]; 360 t_nmi[1] = pcic_nmi_trap_patch[1];
@@ -885,14 +886,6 @@ int pcibios_assign_resource(struct pci_dev *pdev, int resource)
885 return -ENXIO; 886 return -ENXIO;
886} 887}
887 888
888struct device_node *pci_device_to_OF_node(struct pci_dev *pdev)
889{
890 struct pcidev_cookie *pc = pdev->sysdata;
891
892 return pc->prom_node;
893}
894EXPORT_SYMBOL(pci_device_to_OF_node);
895
896/* 889/*
897 * This probably belongs here rather than ioport.c because 890 * This probably belongs here rather than ioport.c because
898 * we do not want this crud linked into SBus kernels. 891 * we do not want this crud linked into SBus kernels.
diff --git a/arch/sparc/kernel/pcr.c b/arch/sparc/kernel/pcr.c
index 8ac23e660080..a24072a49270 100644
--- a/arch/sparc/kernel/pcr.c
+++ b/arch/sparc/kernel/pcr.c
@@ -3,7 +3,7 @@
3 * Copyright (C) 2009 David S. Miller (davem@davemloft.net) 3 * Copyright (C) 2009 David S. Miller (davem@davemloft.net)
4 */ 4 */
5#include <linux/kernel.h> 5#include <linux/kernel.h>
6#include <linux/module.h> 6#include <linux/export.h>
7#include <linux/init.h> 7#include <linux/init.h>
8#include <linux/irq.h> 8#include <linux/irq.h>
9 9
@@ -13,6 +13,7 @@
13#include <asm/pil.h> 13#include <asm/pil.h>
14#include <asm/pcr.h> 14#include <asm/pcr.h>
15#include <asm/nmi.h> 15#include <asm/nmi.h>
16#include <asm/spitfire.h>
16 17
17/* This code is shared between various users of the performance 18/* This code is shared between various users of the performance
18 * counters. Users will be oprofile, pseudo-NMI watchdog, and the 19 * counters. Users will be oprofile, pseudo-NMI watchdog, and the
@@ -80,8 +81,11 @@ static void n2_pcr_write(u64 val)
80{ 81{
81 unsigned long ret; 82 unsigned long ret;
82 83
83 ret = sun4v_niagara2_setperf(HV_N2_PERF_SPARC_CTL, val); 84 if (val & PCR_N2_HTRACE) {
84 if (ret != HV_EOK) 85 ret = sun4v_niagara2_setperf(HV_N2_PERF_SPARC_CTL, val);
86 if (ret != HV_EOK)
87 write_pcr(val);
88 } else
85 write_pcr(val); 89 write_pcr(val);
86} 90}
87 91
@@ -106,6 +110,10 @@ static int __init register_perf_hsvc(void)
106 perf_hsvc_group = HV_GRP_N2_CPU; 110 perf_hsvc_group = HV_GRP_N2_CPU;
107 break; 111 break;
108 112
113 case SUN4V_CHIP_NIAGARA3:
114 perf_hsvc_group = HV_GRP_KT_CPU;
115 break;
116
109 default: 117 default:
110 return -ENODEV; 118 return -ENODEV;
111 } 119 }
diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c
index 2cb0e1c001e2..614da624330c 100644
--- a/arch/sparc/kernel/perf_event.c
+++ b/arch/sparc/kernel/perf_event.c
@@ -22,7 +22,7 @@
22#include <asm/stacktrace.h> 22#include <asm/stacktrace.h>
23#include <asm/cpudata.h> 23#include <asm/cpudata.h>
24#include <asm/uaccess.h> 24#include <asm/uaccess.h>
25#include <asm/atomic.h> 25#include <linux/atomic.h>
26#include <asm/nmi.h> 26#include <asm/nmi.h>
27#include <asm/pcr.h> 27#include <asm/pcr.h>
28 28
@@ -246,6 +246,20 @@ static const cache_map_t ultra3_cache_map = {
246 [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED }, 246 [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED },
247 }, 247 },
248}, 248},
249[C(NODE)] = {
250 [C(OP_READ)] = {
251 [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
252 [C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED },
253 },
254 [ C(OP_WRITE) ] = {
255 [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
256 [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED },
257 },
258 [ C(OP_PREFETCH) ] = {
259 [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
260 [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED },
261 },
262},
249}; 263};
250 264
251static const struct sparc_pmu ultra3_pmu = { 265static const struct sparc_pmu ultra3_pmu = {
@@ -361,6 +375,20 @@ static const cache_map_t niagara1_cache_map = {
361 [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED }, 375 [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED },
362 }, 376 },
363}, 377},
378[C(NODE)] = {
379 [C(OP_READ)] = {
380 [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
381 [C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED },
382 },
383 [ C(OP_WRITE) ] = {
384 [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
385 [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED },
386 },
387 [ C(OP_PREFETCH) ] = {
388 [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
389 [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED },
390 },
391},
364}; 392};
365 393
366static const struct sparc_pmu niagara1_pmu = { 394static const struct sparc_pmu niagara1_pmu = {
@@ -473,6 +501,20 @@ static const cache_map_t niagara2_cache_map = {
473 [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED }, 501 [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED },
474 }, 502 },
475}, 503},
504[C(NODE)] = {
505 [C(OP_READ)] = {
506 [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
507 [C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED },
508 },
509 [ C(OP_WRITE) ] = {
510 [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
511 [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED },
512 },
513 [ C(OP_PREFETCH) ] = {
514 [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
515 [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED },
516 },
517},
476}; 518};
477 519
478static const struct sparc_pmu niagara2_pmu = { 520static const struct sparc_pmu niagara2_pmu = {
@@ -1277,7 +1319,7 @@ static int __kprobes perf_event_nmi_handler(struct notifier_block *self,
1277 if (!sparc_perf_event_set_period(event, hwc, idx)) 1319 if (!sparc_perf_event_set_period(event, hwc, idx))
1278 continue; 1320 continue;
1279 1321
1280 if (perf_event_overflow(event, 1, &data, regs)) 1322 if (perf_event_overflow(event, &data, regs))
1281 sparc_pmu_stop(event, 0); 1323 sparc_pmu_stop(event, 0);
1282 } 1324 }
1283 1325
@@ -1301,7 +1343,8 @@ static bool __init supported_pmu(void)
1301 sparc_pmu = &niagara1_pmu; 1343 sparc_pmu = &niagara1_pmu;
1302 return true; 1344 return true;
1303 } 1345 }
1304 if (!strcmp(sparc_pmu_type, "niagara2")) { 1346 if (!strcmp(sparc_pmu_type, "niagara2") ||
1347 !strcmp(sparc_pmu_type, "niagara3")) {
1305 sparc_pmu = &niagara2_pmu; 1348 sparc_pmu = &niagara2_pmu;
1306 return true; 1349 return true;
1307 } 1350 }
diff --git a/arch/sparc/kernel/pmc.c b/arch/sparc/kernel/pmc.c
index 6a585d393580..0e3202239ff5 100644
--- a/arch/sparc/kernel/pmc.c
+++ b/arch/sparc/kernel/pmc.c
@@ -11,6 +11,7 @@
11#include <linux/pm.h> 11#include <linux/pm.h>
12#include <linux/of.h> 12#include <linux/of.h>
13#include <linux/of_device.h> 13#include <linux/of_device.h>
14#include <linux/module.h>
14 15
15#include <asm/io.h> 16#include <asm/io.h>
16#include <asm/oplib.h> 17#include <asm/oplib.h>
diff --git a/arch/sparc/kernel/power.c b/arch/sparc/kernel/power.c
index cb4c0f57c024..0d39075063b2 100644
--- a/arch/sparc/kernel/power.c
+++ b/arch/sparc/kernel/power.c
@@ -4,7 +4,7 @@
4 */ 4 */
5 5
6#include <linux/kernel.h> 6#include <linux/kernel.h>
7#include <linux/module.h> 7#include <linux/export.h>
8#include <linux/init.h> 8#include <linux/init.h>
9#include <linux/interrupt.h> 9#include <linux/interrupt.h>
10#include <linux/reboot.h> 10#include <linux/reboot.h>
diff --git a/arch/sparc/kernel/process_32.c b/arch/sparc/kernel/process_32.c
index c8cc461ff75f..f793742eec2b 100644
--- a/arch/sparc/kernel/process_32.c
+++ b/arch/sparc/kernel/process_32.c
@@ -380,8 +380,7 @@ void flush_thread(void)
380#endif 380#endif
381 } 381 }
382 382
383 /* Now, this task is no longer a kernel thread. */ 383 /* This task is no longer a kernel thread. */
384 current->thread.current_ds = USER_DS;
385 if (current->thread.flags & SPARC_FLAG_KTHREAD) { 384 if (current->thread.flags & SPARC_FLAG_KTHREAD) {
386 current->thread.flags &= ~SPARC_FLAG_KTHREAD; 385 current->thread.flags &= ~SPARC_FLAG_KTHREAD;
387 386
diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c
index c158a95ec664..3739a06a76cb 100644
--- a/arch/sparc/kernel/process_64.c
+++ b/arch/sparc/kernel/process_64.c
@@ -12,7 +12,7 @@
12#include <stdarg.h> 12#include <stdarg.h>
13 13
14#include <linux/errno.h> 14#include <linux/errno.h>
15#include <linux/module.h> 15#include <linux/export.h>
16#include <linux/sched.h> 16#include <linux/sched.h>
17#include <linux/kernel.h> 17#include <linux/kernel.h>
18#include <linux/mm.h> 18#include <linux/mm.h>
@@ -368,9 +368,6 @@ void flush_thread(void)
368 368
369 /* Clear FPU register state. */ 369 /* Clear FPU register state. */
370 t->fpsaved[0] = 0; 370 t->fpsaved[0] = 0;
371
372 if (get_thread_current_ds() != ASI_AIUS)
373 set_fs(USER_DS);
374} 371}
375 372
376/* It's a bit more tricky when 64-bit tasks are involved... */ 373/* It's a bit more tricky when 64-bit tasks are involved... */
diff --git a/arch/sparc/kernel/prom_32.c b/arch/sparc/kernel/prom_32.c
index 5ce3d15a99b0..b51cbb9e87dc 100644
--- a/arch/sparc/kernel/prom_32.c
+++ b/arch/sparc/kernel/prom_32.c
@@ -20,7 +20,6 @@
20#include <linux/string.h> 20#include <linux/string.h>
21#include <linux/mm.h> 21#include <linux/mm.h>
22#include <linux/bootmem.h> 22#include <linux/bootmem.h>
23#include <linux/module.h>
24 23
25#include <asm/prom.h> 24#include <asm/prom.h>
26#include <asm/oplib.h> 25#include <asm/oplib.h>
diff --git a/arch/sparc/kernel/prom_64.c b/arch/sparc/kernel/prom_64.c
index 86597d9867fd..340c5b976d28 100644
--- a/arch/sparc/kernel/prom_64.c
+++ b/arch/sparc/kernel/prom_64.c
@@ -19,7 +19,6 @@
19#include <linux/types.h> 19#include <linux/types.h>
20#include <linux/string.h> 20#include <linux/string.h>
21#include <linux/mm.h> 21#include <linux/mm.h>
22#include <linux/module.h>
23#include <linux/memblock.h> 22#include <linux/memblock.h>
24#include <linux/of.h> 23#include <linux/of.h>
25 24
diff --git a/arch/sparc/kernel/prom_common.c b/arch/sparc/kernel/prom_common.c
index ed25834328f4..46614807a57f 100644
--- a/arch/sparc/kernel/prom_common.c
+++ b/arch/sparc/kernel/prom_common.c
@@ -15,7 +15,7 @@
15 */ 15 */
16 16
17#include <linux/kernel.h> 17#include <linux/kernel.h>
18#include <linux/module.h> 18#include <linux/export.h>
19#include <linux/errno.h> 19#include <linux/errno.h>
20#include <linux/mutex.h> 20#include <linux/mutex.h>
21#include <linux/slab.h> 21#include <linux/slab.h>
diff --git a/arch/sparc/kernel/reboot.c b/arch/sparc/kernel/reboot.c
index ef89d3d69748..006a42dd2007 100644
--- a/arch/sparc/kernel/reboot.c
+++ b/arch/sparc/kernel/reboot.c
@@ -4,7 +4,7 @@
4 */ 4 */
5#include <linux/kernel.h> 5#include <linux/kernel.h>
6#include <linux/reboot.h> 6#include <linux/reboot.h>
7#include <linux/module.h> 7#include <linux/export.h>
8#include <linux/pm.h> 8#include <linux/pm.h>
9 9
10#include <asm/system.h> 10#include <asm/system.h>
diff --git a/arch/sparc/kernel/sbus.c b/arch/sparc/kernel/sbus.c
index a161b9c77f05..1271b3a27d4e 100644
--- a/arch/sparc/kernel/sbus.c
+++ b/arch/sparc/kernel/sbus.c
@@ -9,6 +9,7 @@
9#include <linux/mm.h> 9#include <linux/mm.h>
10#include <linux/spinlock.h> 10#include <linux/spinlock.h>
11#include <linux/slab.h> 11#include <linux/slab.h>
12#include <linux/export.h>
12#include <linux/init.h> 13#include <linux/init.h>
13#include <linux/interrupt.h> 14#include <linux/interrupt.h>
14#include <linux/of.h> 15#include <linux/of.h>
diff --git a/arch/sparc/kernel/setup_32.c b/arch/sparc/kernel/setup_32.c
index d26e1f6c717a..fe1e3fc31bc5 100644
--- a/arch/sparc/kernel/setup_32.c
+++ b/arch/sparc/kernel/setup_32.c
@@ -31,6 +31,7 @@
31#include <linux/root_dev.h> 31#include <linux/root_dev.h>
32#include <linux/cpu.h> 32#include <linux/cpu.h>
33#include <linux/kdebug.h> 33#include <linux/kdebug.h>
34#include <linux/export.h>
34 35
35#include <asm/system.h> 36#include <asm/system.h>
36#include <asm/io.h> 37#include <asm/io.h>
@@ -137,7 +138,7 @@ static void __init process_switch(char c)
137 prom_halt(); 138 prom_halt();
138 break; 139 break;
139 case 'p': 140 case 'p':
140 /* Just ignore, this behavior is now the default. */ 141 prom_early_console.flags &= ~CON_BOOT;
141 break; 142 break;
142 default: 143 default:
143 printk("Unknown boot switch (-%c)\n", c); 144 printk("Unknown boot switch (-%c)\n", c);
diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c
index c4dd0999da86..a854a1c240ff 100644
--- a/arch/sparc/kernel/setup_64.c
+++ b/arch/sparc/kernel/setup_64.c
@@ -29,6 +29,7 @@
29#include <linux/interrupt.h> 29#include <linux/interrupt.h>
30#include <linux/cpu.h> 30#include <linux/cpu.h>
31#include <linux/initrd.h> 31#include <linux/initrd.h>
32#include <linux/module.h>
32 33
33#include <asm/system.h> 34#include <asm/system.h>
34#include <asm/io.h> 35#include <asm/io.h>
@@ -46,6 +47,8 @@
46#include <asm/mmu.h> 47#include <asm/mmu.h>
47#include <asm/ns87303.h> 48#include <asm/ns87303.h>
48#include <asm/btext.h> 49#include <asm/btext.h>
50#include <asm/elf.h>
51#include <asm/mdesc.h>
49 52
50#ifdef CONFIG_IP_PNP 53#ifdef CONFIG_IP_PNP
51#include <net/ipconfig.h> 54#include <net/ipconfig.h>
@@ -103,7 +106,7 @@ static void __init process_switch(char c)
103 prom_halt(); 106 prom_halt();
104 break; 107 break;
105 case 'p': 108 case 'p':
106 /* Just ignore, this behavior is now the default. */ 109 prom_early_console.flags &= ~CON_BOOT;
107 break; 110 break;
108 case 'P': 111 case 'P':
109 /* Force UltraSPARC-III P-Cache on. */ 112 /* Force UltraSPARC-III P-Cache on. */
@@ -231,44 +234,88 @@ void __init per_cpu_patch(void)
231 } 234 }
232} 235}
233 236
234void __init sun4v_patch(void) 237void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *start,
238 struct sun4v_1insn_patch_entry *end)
235{ 239{
236 extern void sun4v_hvapi_init(void); 240 while (start < end) {
237 struct sun4v_1insn_patch_entry *p1; 241 unsigned long addr = start->addr;
238 struct sun4v_2insn_patch_entry *p2;
239
240 if (tlb_type != hypervisor)
241 return;
242 242
243 p1 = &__sun4v_1insn_patch; 243 *(unsigned int *) (addr + 0) = start->insn;
244 while (p1 < &__sun4v_1insn_patch_end) {
245 unsigned long addr = p1->addr;
246
247 *(unsigned int *) (addr + 0) = p1->insn;
248 wmb(); 244 wmb();
249 __asm__ __volatile__("flush %0" : : "r" (addr + 0)); 245 __asm__ __volatile__("flush %0" : : "r" (addr + 0));
250 246
251 p1++; 247 start++;
252 } 248 }
249}
253 250
254 p2 = &__sun4v_2insn_patch; 251void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *start,
255 while (p2 < &__sun4v_2insn_patch_end) { 252 struct sun4v_2insn_patch_entry *end)
256 unsigned long addr = p2->addr; 253{
254 while (start < end) {
255 unsigned long addr = start->addr;
257 256
258 *(unsigned int *) (addr + 0) = p2->insns[0]; 257 *(unsigned int *) (addr + 0) = start->insns[0];
259 wmb(); 258 wmb();
260 __asm__ __volatile__("flush %0" : : "r" (addr + 0)); 259 __asm__ __volatile__("flush %0" : : "r" (addr + 0));
261 260
262 *(unsigned int *) (addr + 4) = p2->insns[1]; 261 *(unsigned int *) (addr + 4) = start->insns[1];
263 wmb(); 262 wmb();
264 __asm__ __volatile__("flush %0" : : "r" (addr + 4)); 263 __asm__ __volatile__("flush %0" : : "r" (addr + 4));
265 264
266 p2++; 265 start++;
267 } 266 }
267}
268
269void __init sun4v_patch(void)
270{
271 extern void sun4v_hvapi_init(void);
272
273 if (tlb_type != hypervisor)
274 return;
275
276 sun4v_patch_1insn_range(&__sun4v_1insn_patch,
277 &__sun4v_1insn_patch_end);
278
279 sun4v_patch_2insn_range(&__sun4v_2insn_patch,
280 &__sun4v_2insn_patch_end);
268 281
269 sun4v_hvapi_init(); 282 sun4v_hvapi_init();
270} 283}
271 284
285static void __init popc_patch(void)
286{
287 struct popc_3insn_patch_entry *p3;
288 struct popc_6insn_patch_entry *p6;
289
290 p3 = &__popc_3insn_patch;
291 while (p3 < &__popc_3insn_patch_end) {
292 unsigned long i, addr = p3->addr;
293
294 for (i = 0; i < 3; i++) {
295 *(unsigned int *) (addr + (i * 4)) = p3->insns[i];
296 wmb();
297 __asm__ __volatile__("flush %0"
298 : : "r" (addr + (i * 4)));
299 }
300
301 p3++;
302 }
303
304 p6 = &__popc_6insn_patch;
305 while (p6 < &__popc_6insn_patch_end) {
306 unsigned long i, addr = p6->addr;
307
308 for (i = 0; i < 6; i++) {
309 *(unsigned int *) (addr + (i * 4)) = p6->insns[i];
310 wmb();
311 __asm__ __volatile__("flush %0"
312 : : "r" (addr + (i * 4)));
313 }
314
315 p6++;
316 }
317}
318
272#ifdef CONFIG_SMP 319#ifdef CONFIG_SMP
273void __init boot_cpu_id_too_large(int cpu) 320void __init boot_cpu_id_too_large(int cpu)
274{ 321{
@@ -278,6 +325,168 @@ void __init boot_cpu_id_too_large(int cpu)
278} 325}
279#endif 326#endif
280 327
328/* On Ultra, we support all of the v8 capabilities. */
329unsigned long sparc64_elf_hwcap = (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR |
330 HWCAP_SPARC_SWAP | HWCAP_SPARC_MULDIV |
331 HWCAP_SPARC_V9);
332EXPORT_SYMBOL(sparc64_elf_hwcap);
333
334static const char *hwcaps[] = {
335 "flush", "stbar", "swap", "muldiv", "v9",
336 "ultra3", "blkinit", "n2",
337
338 /* These strings are as they appear in the machine description
339 * 'hwcap-list' property for cpu nodes.
340 */
341 "mul32", "div32", "fsmuld", "v8plus", "popc", "vis", "vis2",
342 "ASIBlkInit", "fmaf", "vis3", "hpc", "random", "trans", "fjfmau",
343 "ima", "cspare",
344};
345
346void cpucap_info(struct seq_file *m)
347{
348 unsigned long caps = sparc64_elf_hwcap;
349 int i, printed = 0;
350
351 seq_puts(m, "cpucaps\t\t: ");
352 for (i = 0; i < ARRAY_SIZE(hwcaps); i++) {
353 unsigned long bit = 1UL << i;
354 if (caps & bit) {
355 seq_printf(m, "%s%s",
356 printed ? "," : "", hwcaps[i]);
357 printed++;
358 }
359 }
360 seq_putc(m, '\n');
361}
362
363static void __init report_hwcaps(unsigned long caps)
364{
365 int i, printed = 0;
366
367 printk(KERN_INFO "CPU CAPS: [");
368 for (i = 0; i < ARRAY_SIZE(hwcaps); i++) {
369 unsigned long bit = 1UL << i;
370 if (caps & bit) {
371 printk(KERN_CONT "%s%s",
372 printed ? "," : "", hwcaps[i]);
373 if (++printed == 8) {
374 printk(KERN_CONT "]\n");
375 printk(KERN_INFO "CPU CAPS: [");
376 printed = 0;
377 }
378 }
379 }
380 printk(KERN_CONT "]\n");
381}
382
383static unsigned long __init mdesc_cpu_hwcap_list(void)
384{
385 struct mdesc_handle *hp;
386 unsigned long caps = 0;
387 const char *prop;
388 int len;
389 u64 pn;
390
391 hp = mdesc_grab();
392 if (!hp)
393 return 0;
394
395 pn = mdesc_node_by_name(hp, MDESC_NODE_NULL, "cpu");
396 if (pn == MDESC_NODE_NULL)
397 goto out;
398
399 prop = mdesc_get_property(hp, pn, "hwcap-list", &len);
400 if (!prop)
401 goto out;
402
403 while (len) {
404 int i, plen;
405
406 for (i = 0; i < ARRAY_SIZE(hwcaps); i++) {
407 unsigned long bit = 1UL << i;
408
409 if (!strcmp(prop, hwcaps[i])) {
410 caps |= bit;
411 break;
412 }
413 }
414
415 plen = strlen(prop) + 1;
416 prop += plen;
417 len -= plen;
418 }
419
420out:
421 mdesc_release(hp);
422 return caps;
423}
424
425/* This yields a mask that user programs can use to figure out what
426 * instruction set this cpu supports.
427 */
428static void __init init_sparc64_elf_hwcap(void)
429{
430 unsigned long cap = sparc64_elf_hwcap;
431 unsigned long mdesc_caps;
432
433 if (tlb_type == cheetah || tlb_type == cheetah_plus)
434 cap |= HWCAP_SPARC_ULTRA3;
435 else if (tlb_type == hypervisor) {
436 if (sun4v_chip_type == SUN4V_CHIP_NIAGARA1 ||
437 sun4v_chip_type == SUN4V_CHIP_NIAGARA2 ||
438 sun4v_chip_type == SUN4V_CHIP_NIAGARA3 ||
439 sun4v_chip_type == SUN4V_CHIP_NIAGARA4 ||
440 sun4v_chip_type == SUN4V_CHIP_NIAGARA5)
441 cap |= HWCAP_SPARC_BLKINIT;
442 if (sun4v_chip_type == SUN4V_CHIP_NIAGARA2 ||
443 sun4v_chip_type == SUN4V_CHIP_NIAGARA3 ||
444 sun4v_chip_type == SUN4V_CHIP_NIAGARA4 ||
445 sun4v_chip_type == SUN4V_CHIP_NIAGARA5)
446 cap |= HWCAP_SPARC_N2;
447 }
448
449 cap |= (AV_SPARC_MUL32 | AV_SPARC_DIV32 | AV_SPARC_V8PLUS);
450
451 mdesc_caps = mdesc_cpu_hwcap_list();
452 if (!mdesc_caps) {
453 if (tlb_type == spitfire)
454 cap |= AV_SPARC_VIS;
455 if (tlb_type == cheetah || tlb_type == cheetah_plus)
456 cap |= AV_SPARC_VIS | AV_SPARC_VIS2;
457 if (tlb_type == cheetah_plus) {
458 unsigned long impl, ver;
459
460 __asm__ __volatile__("rdpr %%ver, %0" : "=r" (ver));
461 impl = ((ver >> 32) & 0xffff);
462 if (impl == PANTHER_IMPL)
463 cap |= AV_SPARC_POPC;
464 }
465 if (tlb_type == hypervisor) {
466 if (sun4v_chip_type == SUN4V_CHIP_NIAGARA1)
467 cap |= AV_SPARC_ASI_BLK_INIT;
468 if (sun4v_chip_type == SUN4V_CHIP_NIAGARA2 ||
469 sun4v_chip_type == SUN4V_CHIP_NIAGARA3 ||
470 sun4v_chip_type == SUN4V_CHIP_NIAGARA4 ||
471 sun4v_chip_type == SUN4V_CHIP_NIAGARA5)
472 cap |= (AV_SPARC_VIS | AV_SPARC_VIS2 |
473 AV_SPARC_ASI_BLK_INIT |
474 AV_SPARC_POPC);
475 if (sun4v_chip_type == SUN4V_CHIP_NIAGARA3 ||
476 sun4v_chip_type == SUN4V_CHIP_NIAGARA4 ||
477 sun4v_chip_type == SUN4V_CHIP_NIAGARA5)
478 cap |= (AV_SPARC_VIS3 | AV_SPARC_HPC |
479 AV_SPARC_FMAF);
480 }
481 }
482 sparc64_elf_hwcap = cap | mdesc_caps;
483
484 report_hwcaps(sparc64_elf_hwcap);
485
486 if (sparc64_elf_hwcap & AV_SPARC_POPC)
487 popc_patch();
488}
489
281void __init setup_arch(char **cmdline_p) 490void __init setup_arch(char **cmdline_p)
282{ 491{
283 /* Initialize PROM console and command line. */ 492 /* Initialize PROM console and command line. */
@@ -337,6 +546,7 @@ void __init setup_arch(char **cmdline_p)
337 init_cur_cpu_trap(current_thread_info()); 546 init_cur_cpu_trap(current_thread_info());
338 547
339 paging_init(); 548 paging_init();
549 init_sparc64_elf_hwcap();
340} 550}
341 551
342extern int stop_a_enabled; 552extern int stop_a_enabled;
diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c
index 75fad425e249..023b8860dc97 100644
--- a/arch/sparc/kernel/signal32.c
+++ b/arch/sparc/kernel/signal32.c
@@ -29,6 +29,8 @@
29#include <asm/visasm.h> 29#include <asm/visasm.h>
30#include <asm/compat_signal.h> 30#include <asm/compat_signal.h>
31 31
32#include "sigutil.h"
33
32#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 34#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
33 35
34/* This magic should be in g_upper[0] for all upper parts 36/* This magic should be in g_upper[0] for all upper parts
@@ -44,14 +46,14 @@ typedef struct {
44struct signal_frame32 { 46struct signal_frame32 {
45 struct sparc_stackf32 ss; 47 struct sparc_stackf32 ss;
46 __siginfo32_t info; 48 __siginfo32_t info;
47 /* __siginfo_fpu32_t * */ u32 fpu_save; 49 /* __siginfo_fpu_t * */ u32 fpu_save;
48 unsigned int insns[2]; 50 unsigned int insns[2];
49 unsigned int extramask[_COMPAT_NSIG_WORDS - 1]; 51 unsigned int extramask[_COMPAT_NSIG_WORDS - 1];
50 unsigned int extra_size; /* Should be sizeof(siginfo_extra_v8plus_t) */ 52 unsigned int extra_size; /* Should be sizeof(siginfo_extra_v8plus_t) */
51 /* Only valid if (info.si_regs.psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS */ 53 /* Only valid if (info.si_regs.psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS */
52 siginfo_extra_v8plus_t v8plus; 54 siginfo_extra_v8plus_t v8plus;
53 __siginfo_fpu_t fpu_state; 55 /* __siginfo_rwin_t * */u32 rwin_save;
54}; 56} __attribute__((aligned(8)));
55 57
56typedef struct compat_siginfo{ 58typedef struct compat_siginfo{
57 int si_signo; 59 int si_signo;
@@ -110,18 +112,14 @@ struct rt_signal_frame32 {
110 compat_siginfo_t info; 112 compat_siginfo_t info;
111 struct pt_regs32 regs; 113 struct pt_regs32 regs;
112 compat_sigset_t mask; 114 compat_sigset_t mask;
113 /* __siginfo_fpu32_t * */ u32 fpu_save; 115 /* __siginfo_fpu_t * */ u32 fpu_save;
114 unsigned int insns[2]; 116 unsigned int insns[2];
115 stack_t32 stack; 117 stack_t32 stack;
116 unsigned int extra_size; /* Should be sizeof(siginfo_extra_v8plus_t) */ 118 unsigned int extra_size; /* Should be sizeof(siginfo_extra_v8plus_t) */
117 /* Only valid if (regs.psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS */ 119 /* Only valid if (regs.psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS */
118 siginfo_extra_v8plus_t v8plus; 120 siginfo_extra_v8plus_t v8plus;
119 __siginfo_fpu_t fpu_state; 121 /* __siginfo_rwin_t * */u32 rwin_save;
120}; 122} __attribute__((aligned(8)));
121
122/* Align macros */
123#define SF_ALIGNEDSZ (((sizeof(struct signal_frame32) + 15) & (~15)))
124#define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame32) + 15) & (~15)))
125 123
126int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) 124int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
127{ 125{
@@ -192,30 +190,13 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
192 return 0; 190 return 0;
193} 191}
194 192
195static int restore_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
196{
197 unsigned long *fpregs = current_thread_info()->fpregs;
198 unsigned long fprs;
199 int err;
200
201 err = __get_user(fprs, &fpu->si_fprs);
202 fprs_write(0);
203 regs->tstate &= ~TSTATE_PEF;
204 if (fprs & FPRS_DL)
205 err |= copy_from_user(fpregs, &fpu->si_float_regs[0], (sizeof(unsigned int) * 32));
206 if (fprs & FPRS_DU)
207 err |= copy_from_user(fpregs+16, &fpu->si_float_regs[32], (sizeof(unsigned int) * 32));
208 err |= __get_user(current_thread_info()->xfsr[0], &fpu->si_fsr);
209 err |= __get_user(current_thread_info()->gsr[0], &fpu->si_gsr);
210 current_thread_info()->fpsaved[0] |= fprs;
211 return err;
212}
213
214void do_sigreturn32(struct pt_regs *regs) 193void do_sigreturn32(struct pt_regs *regs)
215{ 194{
216 struct signal_frame32 __user *sf; 195 struct signal_frame32 __user *sf;
196 compat_uptr_t fpu_save;
197 compat_uptr_t rwin_save;
217 unsigned int psr; 198 unsigned int psr;
218 unsigned pc, npc, fpu_save; 199 unsigned pc, npc;
219 sigset_t set; 200 sigset_t set;
220 unsigned seta[_COMPAT_NSIG_WORDS]; 201 unsigned seta[_COMPAT_NSIG_WORDS];
221 int err, i; 202 int err, i;
@@ -273,8 +254,13 @@ void do_sigreturn32(struct pt_regs *regs)
273 pt_regs_clear_syscall(regs); 254 pt_regs_clear_syscall(regs);
274 255
275 err |= __get_user(fpu_save, &sf->fpu_save); 256 err |= __get_user(fpu_save, &sf->fpu_save);
276 if (fpu_save) 257 if (!err && fpu_save)
277 err |= restore_fpu_state32(regs, &sf->fpu_state); 258 err |= restore_fpu_state(regs, compat_ptr(fpu_save));
259 err |= __get_user(rwin_save, &sf->rwin_save);
260 if (!err && rwin_save) {
261 if (restore_rwin_state(compat_ptr(rwin_save)))
262 goto segv;
263 }
278 err |= __get_user(seta[0], &sf->info.si_mask); 264 err |= __get_user(seta[0], &sf->info.si_mask);
279 err |= copy_from_user(seta+1, &sf->extramask, 265 err |= copy_from_user(seta+1, &sf->extramask,
280 (_COMPAT_NSIG_WORDS - 1) * sizeof(unsigned int)); 266 (_COMPAT_NSIG_WORDS - 1) * sizeof(unsigned int));
@@ -287,10 +273,7 @@ void do_sigreturn32(struct pt_regs *regs)
287 case 1: set.sig[0] = seta[0] + (((long)seta[1]) << 32); 273 case 1: set.sig[0] = seta[0] + (((long)seta[1]) << 32);
288 } 274 }
289 sigdelsetmask(&set, ~_BLOCKABLE); 275 sigdelsetmask(&set, ~_BLOCKABLE);
290 spin_lock_irq(&current->sighand->siglock); 276 set_current_blocked(&set);
291 current->blocked = set;
292 recalc_sigpending();
293 spin_unlock_irq(&current->sighand->siglock);
294 return; 277 return;
295 278
296segv: 279segv:
@@ -300,7 +283,9 @@ segv:
300asmlinkage void do_rt_sigreturn32(struct pt_regs *regs) 283asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
301{ 284{
302 struct rt_signal_frame32 __user *sf; 285 struct rt_signal_frame32 __user *sf;
303 unsigned int psr, pc, npc, fpu_save, u_ss_sp; 286 unsigned int psr, pc, npc, u_ss_sp;
287 compat_uptr_t fpu_save;
288 compat_uptr_t rwin_save;
304 mm_segment_t old_fs; 289 mm_segment_t old_fs;
305 sigset_t set; 290 sigset_t set;
306 compat_sigset_t seta; 291 compat_sigset_t seta;
@@ -359,8 +344,8 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
359 pt_regs_clear_syscall(regs); 344 pt_regs_clear_syscall(regs);
360 345
361 err |= __get_user(fpu_save, &sf->fpu_save); 346 err |= __get_user(fpu_save, &sf->fpu_save);
362 if (fpu_save) 347 if (!err && fpu_save)
363 err |= restore_fpu_state32(regs, &sf->fpu_state); 348 err |= restore_fpu_state(regs, compat_ptr(fpu_save));
364 err |= copy_from_user(&seta, &sf->mask, sizeof(compat_sigset_t)); 349 err |= copy_from_user(&seta, &sf->mask, sizeof(compat_sigset_t));
365 err |= __get_user(u_ss_sp, &sf->stack.ss_sp); 350 err |= __get_user(u_ss_sp, &sf->stack.ss_sp);
366 st.ss_sp = compat_ptr(u_ss_sp); 351 st.ss_sp = compat_ptr(u_ss_sp);
@@ -376,6 +361,12 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
376 do_sigaltstack((stack_t __user *) &st, NULL, (unsigned long)sf); 361 do_sigaltstack((stack_t __user *) &st, NULL, (unsigned long)sf);
377 set_fs(old_fs); 362 set_fs(old_fs);
378 363
364 err |= __get_user(rwin_save, &sf->rwin_save);
365 if (!err && rwin_save) {
366 if (restore_rwin_state(compat_ptr(rwin_save)))
367 goto segv;
368 }
369
379 switch (_NSIG_WORDS) { 370 switch (_NSIG_WORDS) {
380 case 4: set.sig[3] = seta.sig[6] + (((long)seta.sig[7]) << 32); 371 case 4: set.sig[3] = seta.sig[6] + (((long)seta.sig[7]) << 32);
381 case 3: set.sig[2] = seta.sig[4] + (((long)seta.sig[5]) << 32); 372 case 3: set.sig[2] = seta.sig[4] + (((long)seta.sig[5]) << 32);
@@ -383,10 +374,7 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
383 case 1: set.sig[0] = seta.sig[0] + (((long)seta.sig[1]) << 32); 374 case 1: set.sig[0] = seta.sig[0] + (((long)seta.sig[1]) << 32);
384 } 375 }
385 sigdelsetmask(&set, ~_BLOCKABLE); 376 sigdelsetmask(&set, ~_BLOCKABLE);
386 spin_lock_irq(&current->sighand->siglock); 377 set_current_blocked(&set);
387 current->blocked = set;
388 recalc_sigpending();
389 spin_unlock_irq(&current->sighand->siglock);
390 return; 378 return;
391segv: 379segv:
392 force_sig(SIGSEGV, current); 380 force_sig(SIGSEGV, current);
@@ -433,26 +421,6 @@ static void __user *get_sigframe(struct sigaction *sa, struct pt_regs *regs, uns
433 return (void __user *) sp; 421 return (void __user *) sp;
434} 422}
435 423
436static int save_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
437{
438 unsigned long *fpregs = current_thread_info()->fpregs;
439 unsigned long fprs;
440 int err = 0;
441
442 fprs = current_thread_info()->fpsaved[0];
443 if (fprs & FPRS_DL)
444 err |= copy_to_user(&fpu->si_float_regs[0], fpregs,
445 (sizeof(unsigned int) * 32));
446 if (fprs & FPRS_DU)
447 err |= copy_to_user(&fpu->si_float_regs[32], fpregs+16,
448 (sizeof(unsigned int) * 32));
449 err |= __put_user(current_thread_info()->xfsr[0], &fpu->si_fsr);
450 err |= __put_user(current_thread_info()->gsr[0], &fpu->si_gsr);
451 err |= __put_user(fprs, &fpu->si_fprs);
452
453 return err;
454}
455
456/* The I-cache flush instruction only works in the primary ASI, which 424/* The I-cache flush instruction only works in the primary ASI, which
457 * right now is the nucleus, aka. kernel space. 425 * right now is the nucleus, aka. kernel space.
458 * 426 *
@@ -515,18 +483,23 @@ static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
515 int signo, sigset_t *oldset) 483 int signo, sigset_t *oldset)
516{ 484{
517 struct signal_frame32 __user *sf; 485 struct signal_frame32 __user *sf;
486 int i, err, wsaved;
487 void __user *tail;
518 int sigframe_size; 488 int sigframe_size;
519 u32 psr; 489 u32 psr;
520 int i, err;
521 unsigned int seta[_COMPAT_NSIG_WORDS]; 490 unsigned int seta[_COMPAT_NSIG_WORDS];
522 491
523 /* 1. Make sure everything is clean */ 492 /* 1. Make sure everything is clean */
524 synchronize_user_stack(); 493 synchronize_user_stack();
525 save_and_clear_fpu(); 494 save_and_clear_fpu();
526 495
527 sigframe_size = SF_ALIGNEDSZ; 496 wsaved = get_thread_wsaved();
528 if (!(current_thread_info()->fpsaved[0] & FPRS_FEF)) 497
529 sigframe_size -= sizeof(__siginfo_fpu_t); 498 sigframe_size = sizeof(*sf);
499 if (current_thread_info()->fpsaved[0] & FPRS_FEF)
500 sigframe_size += sizeof(__siginfo_fpu_t);
501 if (wsaved)
502 sigframe_size += sizeof(__siginfo_rwin_t);
530 503
531 sf = (struct signal_frame32 __user *) 504 sf = (struct signal_frame32 __user *)
532 get_sigframe(&ka->sa, regs, sigframe_size); 505 get_sigframe(&ka->sa, regs, sigframe_size);
@@ -534,8 +507,7 @@ static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
534 if (invalid_frame_pointer(sf, sigframe_size)) 507 if (invalid_frame_pointer(sf, sigframe_size))
535 goto sigill; 508 goto sigill;
536 509
537 if (get_thread_wsaved() != 0) 510 tail = (sf + 1);
538 goto sigill;
539 511
540 /* 2. Save the current process state */ 512 /* 2. Save the current process state */
541 if (test_thread_flag(TIF_32BIT)) { 513 if (test_thread_flag(TIF_32BIT)) {
@@ -560,11 +532,22 @@ static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
560 &sf->v8plus.asi); 532 &sf->v8plus.asi);
561 533
562 if (psr & PSR_EF) { 534 if (psr & PSR_EF) {
563 err |= save_fpu_state32(regs, &sf->fpu_state); 535 __siginfo_fpu_t __user *fp = tail;
564 err |= __put_user((u64)&sf->fpu_state, &sf->fpu_save); 536 tail += sizeof(*fp);
537 err |= save_fpu_state(regs, fp);
538 err |= __put_user((u64)fp, &sf->fpu_save);
565 } else { 539 } else {
566 err |= __put_user(0, &sf->fpu_save); 540 err |= __put_user(0, &sf->fpu_save);
567 } 541 }
542 if (wsaved) {
543 __siginfo_rwin_t __user *rwp = tail;
544 tail += sizeof(*rwp);
545 err |= save_rwin_state(wsaved, rwp);
546 err |= __put_user((u64)rwp, &sf->rwin_save);
547 set_thread_wsaved(0);
548 } else {
549 err |= __put_user(0, &sf->rwin_save);
550 }
568 551
569 switch (_NSIG_WORDS) { 552 switch (_NSIG_WORDS) {
570 case 4: seta[7] = (oldset->sig[3] >> 32); 553 case 4: seta[7] = (oldset->sig[3] >> 32);
@@ -580,10 +563,21 @@ static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
580 err |= __copy_to_user(sf->extramask, seta + 1, 563 err |= __copy_to_user(sf->extramask, seta + 1,
581 (_COMPAT_NSIG_WORDS - 1) * sizeof(unsigned int)); 564 (_COMPAT_NSIG_WORDS - 1) * sizeof(unsigned int));
582 565
583 err |= copy_in_user((u32 __user *)sf, 566 if (!wsaved) {
584 (u32 __user *)(regs->u_regs[UREG_FP]), 567 err |= copy_in_user((u32 __user *)sf,
585 sizeof(struct reg_window32)); 568 (u32 __user *)(regs->u_regs[UREG_FP]),
586 569 sizeof(struct reg_window32));
570 } else {
571 struct reg_window *rp;
572
573 rp = &current_thread_info()->reg_window[wsaved - 1];
574 for (i = 0; i < 8; i++)
575 err |= __put_user(rp->locals[i], &sf->ss.locals[i]);
576 for (i = 0; i < 6; i++)
577 err |= __put_user(rp->ins[i], &sf->ss.ins[i]);
578 err |= __put_user(rp->ins[6], &sf->ss.fp);
579 err |= __put_user(rp->ins[7], &sf->ss.callers_pc);
580 }
587 if (err) 581 if (err)
588 goto sigsegv; 582 goto sigsegv;
589 583
@@ -613,7 +607,6 @@ static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
613 err |= __put_user(0x91d02010, &sf->insns[1]); /*t 0x10*/ 607 err |= __put_user(0x91d02010, &sf->insns[1]); /*t 0x10*/
614 if (err) 608 if (err)
615 goto sigsegv; 609 goto sigsegv;
616
617 flush_signal_insns(address); 610 flush_signal_insns(address);
618 } 611 }
619 return 0; 612 return 0;
@@ -632,18 +625,23 @@ static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
632 siginfo_t *info) 625 siginfo_t *info)
633{ 626{
634 struct rt_signal_frame32 __user *sf; 627 struct rt_signal_frame32 __user *sf;
628 int i, err, wsaved;
629 void __user *tail;
635 int sigframe_size; 630 int sigframe_size;
636 u32 psr; 631 u32 psr;
637 int i, err;
638 compat_sigset_t seta; 632 compat_sigset_t seta;
639 633
640 /* 1. Make sure everything is clean */ 634 /* 1. Make sure everything is clean */
641 synchronize_user_stack(); 635 synchronize_user_stack();
642 save_and_clear_fpu(); 636 save_and_clear_fpu();
643 637
644 sigframe_size = RT_ALIGNEDSZ; 638 wsaved = get_thread_wsaved();
645 if (!(current_thread_info()->fpsaved[0] & FPRS_FEF)) 639
646 sigframe_size -= sizeof(__siginfo_fpu_t); 640 sigframe_size = sizeof(*sf);
641 if (current_thread_info()->fpsaved[0] & FPRS_FEF)
642 sigframe_size += sizeof(__siginfo_fpu_t);
643 if (wsaved)
644 sigframe_size += sizeof(__siginfo_rwin_t);
647 645
648 sf = (struct rt_signal_frame32 __user *) 646 sf = (struct rt_signal_frame32 __user *)
649 get_sigframe(&ka->sa, regs, sigframe_size); 647 get_sigframe(&ka->sa, regs, sigframe_size);
@@ -651,8 +649,7 @@ static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
651 if (invalid_frame_pointer(sf, sigframe_size)) 649 if (invalid_frame_pointer(sf, sigframe_size))
652 goto sigill; 650 goto sigill;
653 651
654 if (get_thread_wsaved() != 0) 652 tail = (sf + 1);
655 goto sigill;
656 653
657 /* 2. Save the current process state */ 654 /* 2. Save the current process state */
658 if (test_thread_flag(TIF_32BIT)) { 655 if (test_thread_flag(TIF_32BIT)) {
@@ -677,11 +674,22 @@ static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
677 &sf->v8plus.asi); 674 &sf->v8plus.asi);
678 675
679 if (psr & PSR_EF) { 676 if (psr & PSR_EF) {
680 err |= save_fpu_state32(regs, &sf->fpu_state); 677 __siginfo_fpu_t __user *fp = tail;
681 err |= __put_user((u64)&sf->fpu_state, &sf->fpu_save); 678 tail += sizeof(*fp);
679 err |= save_fpu_state(regs, fp);
680 err |= __put_user((u64)fp, &sf->fpu_save);
682 } else { 681 } else {
683 err |= __put_user(0, &sf->fpu_save); 682 err |= __put_user(0, &sf->fpu_save);
684 } 683 }
684 if (wsaved) {
685 __siginfo_rwin_t __user *rwp = tail;
686 tail += sizeof(*rwp);
687 err |= save_rwin_state(wsaved, rwp);
688 err |= __put_user((u64)rwp, &sf->rwin_save);
689 set_thread_wsaved(0);
690 } else {
691 err |= __put_user(0, &sf->rwin_save);
692 }
685 693
686 /* Update the siginfo structure. */ 694 /* Update the siginfo structure. */
687 err |= copy_siginfo_to_user32(&sf->info, info); 695 err |= copy_siginfo_to_user32(&sf->info, info);
@@ -703,9 +711,21 @@ static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
703 } 711 }
704 err |= __copy_to_user(&sf->mask, &seta, sizeof(compat_sigset_t)); 712 err |= __copy_to_user(&sf->mask, &seta, sizeof(compat_sigset_t));
705 713
706 err |= copy_in_user((u32 __user *)sf, 714 if (!wsaved) {
707 (u32 __user *)(regs->u_regs[UREG_FP]), 715 err |= copy_in_user((u32 __user *)sf,
708 sizeof(struct reg_window32)); 716 (u32 __user *)(regs->u_regs[UREG_FP]),
717 sizeof(struct reg_window32));
718 } else {
719 struct reg_window *rp;
720
721 rp = &current_thread_info()->reg_window[wsaved - 1];
722 for (i = 0; i < 8; i++)
723 err |= __put_user(rp->locals[i], &sf->ss.locals[i]);
724 for (i = 0; i < 6; i++)
725 err |= __put_user(rp->ins[i], &sf->ss.ins[i]);
726 err |= __put_user(rp->ins[6], &sf->ss.fp);
727 err |= __put_user(rp->ins[7], &sf->ss.callers_pc);
728 }
709 if (err) 729 if (err)
710 goto sigsegv; 730 goto sigsegv;
711 731
@@ -756,6 +776,7 @@ static inline int handle_signal32(unsigned long signr, struct k_sigaction *ka,
756 siginfo_t *info, 776 siginfo_t *info,
757 sigset_t *oldset, struct pt_regs *regs) 777 sigset_t *oldset, struct pt_regs *regs)
758{ 778{
779 sigset_t blocked;
759 int err; 780 int err;
760 781
761 if (ka->sa.sa_flags & SA_SIGINFO) 782 if (ka->sa.sa_flags & SA_SIGINFO)
@@ -766,12 +787,10 @@ static inline int handle_signal32(unsigned long signr, struct k_sigaction *ka,
766 if (err) 787 if (err)
767 return err; 788 return err;
768 789
769 spin_lock_irq(&current->sighand->siglock); 790 sigorsets(&blocked, &current->blocked, &ka->sa.sa_mask);
770 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
771 if (!(ka->sa.sa_flags & SA_NOMASK)) 791 if (!(ka->sa.sa_flags & SA_NOMASK))
772 sigaddset(&current->blocked,signr); 792 sigaddset(&blocked, signr);
773 recalc_sigpending(); 793 set_current_blocked(&blocked);
774 spin_unlock_irq(&current->sighand->siglock);
775 794
776 tracehook_signal_handler(signr, info, ka, regs, 0); 795 tracehook_signal_handler(signr, info, ka, regs, 0);
777 796
@@ -803,21 +822,23 @@ static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs
803 * want to handle. Thus you cannot kill init even with a SIGKILL even by 822 * want to handle. Thus you cannot kill init even with a SIGKILL even by
804 * mistake. 823 * mistake.
805 */ 824 */
806void do_signal32(sigset_t *oldset, struct pt_regs * regs, 825void do_signal32(sigset_t *oldset, struct pt_regs * regs)
807 int restart_syscall, unsigned long orig_i0)
808{ 826{
809 struct k_sigaction ka; 827 struct k_sigaction ka;
828 unsigned long orig_i0;
829 int restart_syscall;
810 siginfo_t info; 830 siginfo_t info;
811 int signr; 831 int signr;
812 832
813 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 833 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
814 834
815 /* If the debugger messes with the program counter, it clears 835 restart_syscall = 0;
816 * the "in syscall" bit, directing us to not perform a syscall 836 orig_i0 = 0;
817 * restart. 837 if (pt_regs_is_syscall(regs) &&
818 */ 838 (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
819 if (restart_syscall && !pt_regs_is_syscall(regs)) 839 restart_syscall = 1;
820 restart_syscall = 0; 840 orig_i0 = regs->u_regs[UREG_G6];
841 }
821 842
822 if (signr > 0) { 843 if (signr > 0) {
823 if (restart_syscall) 844 if (restart_syscall)
@@ -855,7 +876,7 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs,
855 */ 876 */
856 if (current_thread_info()->status & TS_RESTORE_SIGMASK) { 877 if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
857 current_thread_info()->status &= ~TS_RESTORE_SIGMASK; 878 current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
858 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL); 879 set_current_blocked(&current->saved_sigmask);
859 } 880 }
860} 881}
861 882
diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c
index 5e5c5fd03783..d54c6e53aba0 100644
--- a/arch/sparc/kernel/signal_32.c
+++ b/arch/sparc/kernel/signal_32.c
@@ -26,6 +26,8 @@
26#include <asm/pgtable.h> 26#include <asm/pgtable.h>
27#include <asm/cacheflush.h> /* flush_sig_insns */ 27#include <asm/cacheflush.h> /* flush_sig_insns */
28 28
29#include "sigutil.h"
30
29#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 31#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
30 32
31extern void fpsave(unsigned long *fpregs, unsigned long *fsr, 33extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
@@ -39,8 +41,8 @@ struct signal_frame {
39 unsigned long insns[2] __attribute__ ((aligned (8))); 41 unsigned long insns[2] __attribute__ ((aligned (8)));
40 unsigned int extramask[_NSIG_WORDS - 1]; 42 unsigned int extramask[_NSIG_WORDS - 1];
41 unsigned int extra_size; /* Should be 0 */ 43 unsigned int extra_size; /* Should be 0 */
42 __siginfo_fpu_t fpu_state; 44 __siginfo_rwin_t __user *rwin_save;
43}; 45} __attribute__((aligned(8)));
44 46
45struct rt_signal_frame { 47struct rt_signal_frame {
46 struct sparc_stackf ss; 48 struct sparc_stackf ss;
@@ -51,8 +53,8 @@ struct rt_signal_frame {
51 unsigned int insns[2]; 53 unsigned int insns[2];
52 stack_t stack; 54 stack_t stack;
53 unsigned int extra_size; /* Should be 0 */ 55 unsigned int extra_size; /* Should be 0 */
54 __siginfo_fpu_t fpu_state; 56 __siginfo_rwin_t __user *rwin_save;
55}; 57} __attribute__((aligned(8)));
56 58
57/* Align macros */ 59/* Align macros */
58#define SF_ALIGNEDSZ (((sizeof(struct signal_frame) + 7) & (~7))) 60#define SF_ALIGNEDSZ (((sizeof(struct signal_frame) + 7) & (~7)))
@@ -60,12 +62,13 @@ struct rt_signal_frame {
60 62
61static int _sigpause_common(old_sigset_t set) 63static int _sigpause_common(old_sigset_t set)
62{ 64{
63 set &= _BLOCKABLE; 65 sigset_t blocked;
64 spin_lock_irq(&current->sighand->siglock); 66
65 current->saved_sigmask = current->blocked; 67 current->saved_sigmask = current->blocked;
66 siginitset(&current->blocked, set); 68
67 recalc_sigpending(); 69 set &= _BLOCKABLE;
68 spin_unlock_irq(&current->sighand->siglock); 70 siginitset(&blocked, set);
71 set_current_blocked(&blocked);
69 72
70 current->state = TASK_INTERRUPTIBLE; 73 current->state = TASK_INTERRUPTIBLE;
71 schedule(); 74 schedule();
@@ -79,43 +82,13 @@ asmlinkage int sys_sigsuspend(old_sigset_t set)
79 return _sigpause_common(set); 82 return _sigpause_common(set);
80} 83}
81 84
82static inline int
83restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
84{
85 int err;
86#ifdef CONFIG_SMP
87 if (test_tsk_thread_flag(current, TIF_USEDFPU))
88 regs->psr &= ~PSR_EF;
89#else
90 if (current == last_task_used_math) {
91 last_task_used_math = NULL;
92 regs->psr &= ~PSR_EF;
93 }
94#endif
95 set_used_math();
96 clear_tsk_thread_flag(current, TIF_USEDFPU);
97
98 if (!access_ok(VERIFY_READ, fpu, sizeof(*fpu)))
99 return -EFAULT;
100
101 err = __copy_from_user(&current->thread.float_regs[0], &fpu->si_float_regs[0],
102 (sizeof(unsigned long) * 32));
103 err |= __get_user(current->thread.fsr, &fpu->si_fsr);
104 err |= __get_user(current->thread.fpqdepth, &fpu->si_fpqdepth);
105 if (current->thread.fpqdepth != 0)
106 err |= __copy_from_user(&current->thread.fpqueue[0],
107 &fpu->si_fpqueue[0],
108 ((sizeof(unsigned long) +
109 (sizeof(unsigned long *)))*16));
110 return err;
111}
112
113asmlinkage void do_sigreturn(struct pt_regs *regs) 85asmlinkage void do_sigreturn(struct pt_regs *regs)
114{ 86{
115 struct signal_frame __user *sf; 87 struct signal_frame __user *sf;
116 unsigned long up_psr, pc, npc; 88 unsigned long up_psr, pc, npc;
117 sigset_t set; 89 sigset_t set;
118 __siginfo_fpu_t __user *fpu_save; 90 __siginfo_fpu_t __user *fpu_save;
91 __siginfo_rwin_t __user *rwin_save;
119 int err; 92 int err;
120 93
121 /* Always make any pending restarted system calls return -EINTR */ 94 /* Always make any pending restarted system calls return -EINTR */
@@ -150,9 +123,11 @@ asmlinkage void do_sigreturn(struct pt_regs *regs)
150 pt_regs_clear_syscall(regs); 123 pt_regs_clear_syscall(regs);
151 124
152 err |= __get_user(fpu_save, &sf->fpu_save); 125 err |= __get_user(fpu_save, &sf->fpu_save);
153
154 if (fpu_save) 126 if (fpu_save)
155 err |= restore_fpu_state(regs, fpu_save); 127 err |= restore_fpu_state(regs, fpu_save);
128 err |= __get_user(rwin_save, &sf->rwin_save);
129 if (rwin_save)
130 err |= restore_rwin_state(rwin_save);
156 131
157 /* This is pretty much atomic, no amount locking would prevent 132 /* This is pretty much atomic, no amount locking would prevent
158 * the races which exist anyways. 133 * the races which exist anyways.
@@ -165,10 +140,7 @@ asmlinkage void do_sigreturn(struct pt_regs *regs)
165 goto segv_and_exit; 140 goto segv_and_exit;
166 141
167 sigdelsetmask(&set, ~_BLOCKABLE); 142 sigdelsetmask(&set, ~_BLOCKABLE);
168 spin_lock_irq(&current->sighand->siglock); 143 set_current_blocked(&set);
169 current->blocked = set;
170 recalc_sigpending();
171 spin_unlock_irq(&current->sighand->siglock);
172 return; 144 return;
173 145
174segv_and_exit: 146segv_and_exit:
@@ -180,6 +152,7 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
180 struct rt_signal_frame __user *sf; 152 struct rt_signal_frame __user *sf;
181 unsigned int psr, pc, npc; 153 unsigned int psr, pc, npc;
182 __siginfo_fpu_t __user *fpu_save; 154 __siginfo_fpu_t __user *fpu_save;
155 __siginfo_rwin_t __user *rwin_save;
183 mm_segment_t old_fs; 156 mm_segment_t old_fs;
184 sigset_t set; 157 sigset_t set;
185 stack_t st; 158 stack_t st;
@@ -207,8 +180,7 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
207 pt_regs_clear_syscall(regs); 180 pt_regs_clear_syscall(regs);
208 181
209 err |= __get_user(fpu_save, &sf->fpu_save); 182 err |= __get_user(fpu_save, &sf->fpu_save);
210 183 if (!err && fpu_save)
211 if (fpu_save)
212 err |= restore_fpu_state(regs, fpu_save); 184 err |= restore_fpu_state(regs, fpu_save);
213 err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t)); 185 err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t));
214 186
@@ -228,11 +200,14 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
228 do_sigaltstack((const stack_t __user *) &st, NULL, (unsigned long)sf); 200 do_sigaltstack((const stack_t __user *) &st, NULL, (unsigned long)sf);
229 set_fs(old_fs); 201 set_fs(old_fs);
230 202
203 err |= __get_user(rwin_save, &sf->rwin_save);
204 if (!err && rwin_save) {
205 if (restore_rwin_state(rwin_save))
206 goto segv;
207 }
208
231 sigdelsetmask(&set, ~_BLOCKABLE); 209 sigdelsetmask(&set, ~_BLOCKABLE);
232 spin_lock_irq(&current->sighand->siglock); 210 set_current_blocked(&set);
233 current->blocked = set;
234 recalc_sigpending();
235 spin_unlock_irq(&current->sighand->siglock);
236 return; 211 return;
237segv: 212segv:
238 force_sig(SIGSEGV, current); 213 force_sig(SIGSEGV, current);
@@ -280,53 +255,23 @@ static inline void __user *get_sigframe(struct sigaction *sa, struct pt_regs *re
280 return (void __user *) sp; 255 return (void __user *) sp;
281} 256}
282 257
283static inline int
284save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
285{
286 int err = 0;
287#ifdef CONFIG_SMP
288 if (test_tsk_thread_flag(current, TIF_USEDFPU)) {
289 put_psr(get_psr() | PSR_EF);
290 fpsave(&current->thread.float_regs[0], &current->thread.fsr,
291 &current->thread.fpqueue[0], &current->thread.fpqdepth);
292 regs->psr &= ~(PSR_EF);
293 clear_tsk_thread_flag(current, TIF_USEDFPU);
294 }
295#else
296 if (current == last_task_used_math) {
297 put_psr(get_psr() | PSR_EF);
298 fpsave(&current->thread.float_regs[0], &current->thread.fsr,
299 &current->thread.fpqueue[0], &current->thread.fpqdepth);
300 last_task_used_math = NULL;
301 regs->psr &= ~(PSR_EF);
302 }
303#endif
304 err |= __copy_to_user(&fpu->si_float_regs[0],
305 &current->thread.float_regs[0],
306 (sizeof(unsigned long) * 32));
307 err |= __put_user(current->thread.fsr, &fpu->si_fsr);
308 err |= __put_user(current->thread.fpqdepth, &fpu->si_fpqdepth);
309 if (current->thread.fpqdepth != 0)
310 err |= __copy_to_user(&fpu->si_fpqueue[0],
311 &current->thread.fpqueue[0],
312 ((sizeof(unsigned long) +
313 (sizeof(unsigned long *)))*16));
314 clear_used_math();
315 return err;
316}
317
318static int setup_frame(struct k_sigaction *ka, struct pt_regs *regs, 258static int setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
319 int signo, sigset_t *oldset) 259 int signo, sigset_t *oldset)
320{ 260{
321 struct signal_frame __user *sf; 261 struct signal_frame __user *sf;
322 int sigframe_size, err; 262 int sigframe_size, err, wsaved;
263 void __user *tail;
323 264
324 /* 1. Make sure everything is clean */ 265 /* 1. Make sure everything is clean */
325 synchronize_user_stack(); 266 synchronize_user_stack();
326 267
327 sigframe_size = SF_ALIGNEDSZ; 268 wsaved = current_thread_info()->w_saved;
328 if (!used_math()) 269
329 sigframe_size -= sizeof(__siginfo_fpu_t); 270 sigframe_size = sizeof(*sf);
271 if (used_math())
272 sigframe_size += sizeof(__siginfo_fpu_t);
273 if (wsaved)
274 sigframe_size += sizeof(__siginfo_rwin_t);
330 275
331 sf = (struct signal_frame __user *) 276 sf = (struct signal_frame __user *)
332 get_sigframe(&ka->sa, regs, sigframe_size); 277 get_sigframe(&ka->sa, regs, sigframe_size);
@@ -334,8 +279,7 @@ static int setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
334 if (invalid_frame_pointer(sf, sigframe_size)) 279 if (invalid_frame_pointer(sf, sigframe_size))
335 goto sigill_and_return; 280 goto sigill_and_return;
336 281
337 if (current_thread_info()->w_saved != 0) 282 tail = sf + 1;
338 goto sigill_and_return;
339 283
340 /* 2. Save the current process state */ 284 /* 2. Save the current process state */
341 err = __copy_to_user(&sf->info.si_regs, regs, sizeof(struct pt_regs)); 285 err = __copy_to_user(&sf->info.si_regs, regs, sizeof(struct pt_regs));
@@ -343,17 +287,34 @@ static int setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
343 err |= __put_user(0, &sf->extra_size); 287 err |= __put_user(0, &sf->extra_size);
344 288
345 if (used_math()) { 289 if (used_math()) {
346 err |= save_fpu_state(regs, &sf->fpu_state); 290 __siginfo_fpu_t __user *fp = tail;
347 err |= __put_user(&sf->fpu_state, &sf->fpu_save); 291 tail += sizeof(*fp);
292 err |= save_fpu_state(regs, fp);
293 err |= __put_user(fp, &sf->fpu_save);
348 } else { 294 } else {
349 err |= __put_user(0, &sf->fpu_save); 295 err |= __put_user(0, &sf->fpu_save);
350 } 296 }
297 if (wsaved) {
298 __siginfo_rwin_t __user *rwp = tail;
299 tail += sizeof(*rwp);
300 err |= save_rwin_state(wsaved, rwp);
301 err |= __put_user(rwp, &sf->rwin_save);
302 } else {
303 err |= __put_user(0, &sf->rwin_save);
304 }
351 305
352 err |= __put_user(oldset->sig[0], &sf->info.si_mask); 306 err |= __put_user(oldset->sig[0], &sf->info.si_mask);
353 err |= __copy_to_user(sf->extramask, &oldset->sig[1], 307 err |= __copy_to_user(sf->extramask, &oldset->sig[1],
354 (_NSIG_WORDS - 1) * sizeof(unsigned int)); 308 (_NSIG_WORDS - 1) * sizeof(unsigned int));
355 err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP], 309 if (!wsaved) {
356 sizeof(struct reg_window32)); 310 err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP],
311 sizeof(struct reg_window32));
312 } else {
313 struct reg_window32 *rp;
314
315 rp = &current_thread_info()->reg_window[wsaved - 1];
316 err |= __copy_to_user(sf, rp, sizeof(struct reg_window32));
317 }
357 if (err) 318 if (err)
358 goto sigsegv; 319 goto sigsegv;
359 320
@@ -399,21 +360,24 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
399 int signo, sigset_t *oldset, siginfo_t *info) 360 int signo, sigset_t *oldset, siginfo_t *info)
400{ 361{
401 struct rt_signal_frame __user *sf; 362 struct rt_signal_frame __user *sf;
402 int sigframe_size; 363 int sigframe_size, wsaved;
364 void __user *tail;
403 unsigned int psr; 365 unsigned int psr;
404 int err; 366 int err;
405 367
406 synchronize_user_stack(); 368 synchronize_user_stack();
407 sigframe_size = RT_ALIGNEDSZ; 369 wsaved = current_thread_info()->w_saved;
408 if (!used_math()) 370 sigframe_size = sizeof(*sf);
409 sigframe_size -= sizeof(__siginfo_fpu_t); 371 if (used_math())
372 sigframe_size += sizeof(__siginfo_fpu_t);
373 if (wsaved)
374 sigframe_size += sizeof(__siginfo_rwin_t);
410 sf = (struct rt_signal_frame __user *) 375 sf = (struct rt_signal_frame __user *)
411 get_sigframe(&ka->sa, regs, sigframe_size); 376 get_sigframe(&ka->sa, regs, sigframe_size);
412 if (invalid_frame_pointer(sf, sigframe_size)) 377 if (invalid_frame_pointer(sf, sigframe_size))
413 goto sigill; 378 goto sigill;
414 if (current_thread_info()->w_saved != 0)
415 goto sigill;
416 379
380 tail = sf + 1;
417 err = __put_user(regs->pc, &sf->regs.pc); 381 err = __put_user(regs->pc, &sf->regs.pc);
418 err |= __put_user(regs->npc, &sf->regs.npc); 382 err |= __put_user(regs->npc, &sf->regs.npc);
419 err |= __put_user(regs->y, &sf->regs.y); 383 err |= __put_user(regs->y, &sf->regs.y);
@@ -425,11 +389,21 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
425 err |= __put_user(0, &sf->extra_size); 389 err |= __put_user(0, &sf->extra_size);
426 390
427 if (psr & PSR_EF) { 391 if (psr & PSR_EF) {
428 err |= save_fpu_state(regs, &sf->fpu_state); 392 __siginfo_fpu_t *fp = tail;
429 err |= __put_user(&sf->fpu_state, &sf->fpu_save); 393 tail += sizeof(*fp);
394 err |= save_fpu_state(regs, fp);
395 err |= __put_user(fp, &sf->fpu_save);
430 } else { 396 } else {
431 err |= __put_user(0, &sf->fpu_save); 397 err |= __put_user(0, &sf->fpu_save);
432 } 398 }
399 if (wsaved) {
400 __siginfo_rwin_t *rwp = tail;
401 tail += sizeof(*rwp);
402 err |= save_rwin_state(wsaved, rwp);
403 err |= __put_user(rwp, &sf->rwin_save);
404 } else {
405 err |= __put_user(0, &sf->rwin_save);
406 }
433 err |= __copy_to_user(&sf->mask, &oldset->sig[0], sizeof(sigset_t)); 407 err |= __copy_to_user(&sf->mask, &oldset->sig[0], sizeof(sigset_t));
434 408
435 /* Setup sigaltstack */ 409 /* Setup sigaltstack */
@@ -437,8 +411,15 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
437 err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags); 411 err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags);
438 err |= __put_user(current->sas_ss_size, &sf->stack.ss_size); 412 err |= __put_user(current->sas_ss_size, &sf->stack.ss_size);
439 413
440 err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP], 414 if (!wsaved) {
441 sizeof(struct reg_window32)); 415 err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP],
416 sizeof(struct reg_window32));
417 } else {
418 struct reg_window32 *rp;
419
420 rp = &current_thread_info()->reg_window[wsaved - 1];
421 err |= __copy_to_user(sf, rp, sizeof(struct reg_window32));
422 }
442 423
443 err |= copy_siginfo_to_user(&sf->info, info); 424 err |= copy_siginfo_to_user(&sf->info, info);
444 425
@@ -484,6 +465,7 @@ static inline int
484handle_signal(unsigned long signr, struct k_sigaction *ka, 465handle_signal(unsigned long signr, struct k_sigaction *ka,
485 siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) 466 siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
486{ 467{
468 sigset_t blocked;
487 int err; 469 int err;
488 470
489 if (ka->sa.sa_flags & SA_SIGINFO) 471 if (ka->sa.sa_flags & SA_SIGINFO)
@@ -494,12 +476,10 @@ handle_signal(unsigned long signr, struct k_sigaction *ka,
494 if (err) 476 if (err)
495 return err; 477 return err;
496 478
497 spin_lock_irq(&current->sighand->siglock); 479 sigorsets(&blocked, &current->blocked, &ka->sa.sa_mask);
498 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
499 if (!(ka->sa.sa_flags & SA_NOMASK)) 480 if (!(ka->sa.sa_flags & SA_NOMASK))
500 sigaddset(&current->blocked, signr); 481 sigaddset(&blocked, signr);
501 recalc_sigpending(); 482 set_current_blocked(&blocked);
502 spin_unlock_irq(&current->sighand->siglock);
503 483
504 tracehook_signal_handler(signr, info, ka, regs, 0); 484 tracehook_signal_handler(signr, info, ka, regs, 0);
505 485
@@ -539,10 +519,26 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
539 siginfo_t info; 519 siginfo_t info;
540 int signr; 520 int signr;
541 521
522 /* It's a lot of work and synchronization to add a new ptrace
523 * register for GDB to save and restore in order to get
524 * orig_i0 correct for syscall restarts when debugging.
525 *
526 * Although it should be the case that most of the global
527 * registers are volatile across a system call, glibc already
528 * depends upon that fact that we preserve them. So we can't
529 * just use any global register to save away the orig_i0 value.
530 *
531 * In particular %g2, %g3, %g4, and %g5 are all assumed to be
532 * preserved across a system call trap by various pieces of
533 * code in glibc.
534 *
535 * %g7 is used as the "thread register". %g6 is not used in
536 * any fixed manner. %g6 is used as a scratch register and
537 * a compiler temporary, but it's value is never used across
538 * a system call. Therefore %g6 is usable for orig_i0 storage.
539 */
542 if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C)) 540 if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C))
543 restart_syscall = 1; 541 regs->u_regs[UREG_G6] = orig_i0;
544 else
545 restart_syscall = 0;
546 542
547 if (test_thread_flag(TIF_RESTORE_SIGMASK)) 543 if (test_thread_flag(TIF_RESTORE_SIGMASK))
548 oldset = &current->saved_sigmask; 544 oldset = &current->saved_sigmask;
@@ -555,8 +551,12 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
555 * the software "in syscall" bit, directing us to not perform 551 * the software "in syscall" bit, directing us to not perform
556 * a syscall restart. 552 * a syscall restart.
557 */ 553 */
558 if (restart_syscall && !pt_regs_is_syscall(regs)) 554 restart_syscall = 0;
559 restart_syscall = 0; 555 if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C)) {
556 restart_syscall = 1;
557 orig_i0 = regs->u_regs[UREG_G6];
558 }
559
560 560
561 if (signr > 0) { 561 if (signr > 0) {
562 if (restart_syscall) 562 if (restart_syscall)
@@ -595,7 +595,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
595 */ 595 */
596 if (test_thread_flag(TIF_RESTORE_SIGMASK)) { 596 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
597 clear_thread_flag(TIF_RESTORE_SIGMASK); 597 clear_thread_flag(TIF_RESTORE_SIGMASK);
598 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL); 598 set_current_blocked(&current->saved_sigmask);
599 } 599 }
600} 600}
601 601
diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c
index 006fe4515886..f0836cd0e2f2 100644
--- a/arch/sparc/kernel/signal_64.c
+++ b/arch/sparc/kernel/signal_64.c
@@ -34,6 +34,7 @@
34 34
35#include "entry.h" 35#include "entry.h"
36#include "systbls.h" 36#include "systbls.h"
37#include "sigutil.h"
37 38
38#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 39#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
39 40
@@ -69,10 +70,7 @@ asmlinkage void sparc64_set_context(struct pt_regs *regs)
69 goto do_sigsegv; 70 goto do_sigsegv;
70 } 71 }
71 sigdelsetmask(&set, ~_BLOCKABLE); 72 sigdelsetmask(&set, ~_BLOCKABLE);
72 spin_lock_irq(&current->sighand->siglock); 73 set_current_blocked(&set);
73 current->blocked = set;
74 recalc_sigpending();
75 spin_unlock_irq(&current->sighand->siglock);
76 } 74 }
77 if (test_thread_flag(TIF_32BIT)) { 75 if (test_thread_flag(TIF_32BIT)) {
78 pc &= 0xffffffff; 76 pc &= 0xffffffff;
@@ -236,17 +234,18 @@ struct rt_signal_frame {
236 __siginfo_fpu_t __user *fpu_save; 234 __siginfo_fpu_t __user *fpu_save;
237 stack_t stack; 235 stack_t stack;
238 sigset_t mask; 236 sigset_t mask;
239 __siginfo_fpu_t fpu_state; 237 __siginfo_rwin_t *rwin_save;
240}; 238};
241 239
242static long _sigpause_common(old_sigset_t set) 240static long _sigpause_common(old_sigset_t set)
243{ 241{
244 set &= _BLOCKABLE; 242 sigset_t blocked;
245 spin_lock_irq(&current->sighand->siglock); 243
246 current->saved_sigmask = current->blocked; 244 current->saved_sigmask = current->blocked;
247 siginitset(&current->blocked, set); 245
248 recalc_sigpending(); 246 set &= _BLOCKABLE;
249 spin_unlock_irq(&current->sighand->siglock); 247 siginitset(&blocked, set);
248 set_current_blocked(&blocked);
250 249
251 current->state = TASK_INTERRUPTIBLE; 250 current->state = TASK_INTERRUPTIBLE;
252 schedule(); 251 schedule();
@@ -266,33 +265,12 @@ asmlinkage long sys_sigsuspend(old_sigset_t set)
266 return _sigpause_common(set); 265 return _sigpause_common(set);
267} 266}
268 267
269static inline int
270restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
271{
272 unsigned long *fpregs = current_thread_info()->fpregs;
273 unsigned long fprs;
274 int err;
275
276 err = __get_user(fprs, &fpu->si_fprs);
277 fprs_write(0);
278 regs->tstate &= ~TSTATE_PEF;
279 if (fprs & FPRS_DL)
280 err |= copy_from_user(fpregs, &fpu->si_float_regs[0],
281 (sizeof(unsigned int) * 32));
282 if (fprs & FPRS_DU)
283 err |= copy_from_user(fpregs+16, &fpu->si_float_regs[32],
284 (sizeof(unsigned int) * 32));
285 err |= __get_user(current_thread_info()->xfsr[0], &fpu->si_fsr);
286 err |= __get_user(current_thread_info()->gsr[0], &fpu->si_gsr);
287 current_thread_info()->fpsaved[0] |= fprs;
288 return err;
289}
290
291void do_rt_sigreturn(struct pt_regs *regs) 268void do_rt_sigreturn(struct pt_regs *regs)
292{ 269{
293 struct rt_signal_frame __user *sf; 270 struct rt_signal_frame __user *sf;
294 unsigned long tpc, tnpc, tstate; 271 unsigned long tpc, tnpc, tstate;
295 __siginfo_fpu_t __user *fpu_save; 272 __siginfo_fpu_t __user *fpu_save;
273 __siginfo_rwin_t __user *rwin_save;
296 sigset_t set; 274 sigset_t set;
297 int err; 275 int err;
298 276
@@ -325,8 +303,8 @@ void do_rt_sigreturn(struct pt_regs *regs)
325 regs->tstate |= (tstate & (TSTATE_ASI | TSTATE_ICC | TSTATE_XCC)); 303 regs->tstate |= (tstate & (TSTATE_ASI | TSTATE_ICC | TSTATE_XCC));
326 304
327 err |= __get_user(fpu_save, &sf->fpu_save); 305 err |= __get_user(fpu_save, &sf->fpu_save);
328 if (fpu_save) 306 if (!err && fpu_save)
329 err |= restore_fpu_state(regs, &sf->fpu_state); 307 err |= restore_fpu_state(regs, fpu_save);
330 308
331 err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t)); 309 err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t));
332 err |= do_sigaltstack(&sf->stack, NULL, (unsigned long)sf); 310 err |= do_sigaltstack(&sf->stack, NULL, (unsigned long)sf);
@@ -334,6 +312,12 @@ void do_rt_sigreturn(struct pt_regs *regs)
334 if (err) 312 if (err)
335 goto segv; 313 goto segv;
336 314
315 err |= __get_user(rwin_save, &sf->rwin_save);
316 if (!err && rwin_save) {
317 if (restore_rwin_state(rwin_save))
318 goto segv;
319 }
320
337 regs->tpc = tpc; 321 regs->tpc = tpc;
338 regs->tnpc = tnpc; 322 regs->tnpc = tnpc;
339 323
@@ -341,44 +325,20 @@ void do_rt_sigreturn(struct pt_regs *regs)
341 pt_regs_clear_syscall(regs); 325 pt_regs_clear_syscall(regs);
342 326
343 sigdelsetmask(&set, ~_BLOCKABLE); 327 sigdelsetmask(&set, ~_BLOCKABLE);
344 spin_lock_irq(&current->sighand->siglock); 328 set_current_blocked(&set);
345 current->blocked = set;
346 recalc_sigpending();
347 spin_unlock_irq(&current->sighand->siglock);
348 return; 329 return;
349segv: 330segv:
350 force_sig(SIGSEGV, current); 331 force_sig(SIGSEGV, current);
351} 332}
352 333
353/* Checks if the fp is valid */ 334/* Checks if the fp is valid */
354static int invalid_frame_pointer(void __user *fp, int fplen) 335static int invalid_frame_pointer(void __user *fp)
355{ 336{
356 if (((unsigned long) fp) & 15) 337 if (((unsigned long) fp) & 15)
357 return 1; 338 return 1;
358 return 0; 339 return 0;
359} 340}
360 341
361static inline int
362save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
363{
364 unsigned long *fpregs = current_thread_info()->fpregs;
365 unsigned long fprs;
366 int err = 0;
367
368 fprs = current_thread_info()->fpsaved[0];
369 if (fprs & FPRS_DL)
370 err |= copy_to_user(&fpu->si_float_regs[0], fpregs,
371 (sizeof(unsigned int) * 32));
372 if (fprs & FPRS_DU)
373 err |= copy_to_user(&fpu->si_float_regs[32], fpregs+16,
374 (sizeof(unsigned int) * 32));
375 err |= __put_user(current_thread_info()->xfsr[0], &fpu->si_fsr);
376 err |= __put_user(current_thread_info()->gsr[0], &fpu->si_gsr);
377 err |= __put_user(fprs, &fpu->si_fprs);
378
379 return err;
380}
381
382static inline void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, unsigned long framesize) 342static inline void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, unsigned long framesize)
383{ 343{
384 unsigned long sp = regs->u_regs[UREG_FP] + STACK_BIAS; 344 unsigned long sp = regs->u_regs[UREG_FP] + STACK_BIAS;
@@ -414,34 +374,48 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
414 int signo, sigset_t *oldset, siginfo_t *info) 374 int signo, sigset_t *oldset, siginfo_t *info)
415{ 375{
416 struct rt_signal_frame __user *sf; 376 struct rt_signal_frame __user *sf;
417 int sigframe_size, err; 377 int wsaved, err, sf_size;
378 void __user *tail;
418 379
419 /* 1. Make sure everything is clean */ 380 /* 1. Make sure everything is clean */
420 synchronize_user_stack(); 381 synchronize_user_stack();
421 save_and_clear_fpu(); 382 save_and_clear_fpu();
422 383
423 sigframe_size = sizeof(struct rt_signal_frame); 384 wsaved = get_thread_wsaved();
424 if (!(current_thread_info()->fpsaved[0] & FPRS_FEF))
425 sigframe_size -= sizeof(__siginfo_fpu_t);
426 385
386 sf_size = sizeof(struct rt_signal_frame);
387 if (current_thread_info()->fpsaved[0] & FPRS_FEF)
388 sf_size += sizeof(__siginfo_fpu_t);
389 if (wsaved)
390 sf_size += sizeof(__siginfo_rwin_t);
427 sf = (struct rt_signal_frame __user *) 391 sf = (struct rt_signal_frame __user *)
428 get_sigframe(ka, regs, sigframe_size); 392 get_sigframe(ka, regs, sf_size);
429
430 if (invalid_frame_pointer (sf, sigframe_size))
431 goto sigill;
432 393
433 if (get_thread_wsaved() != 0) 394 if (invalid_frame_pointer (sf))
434 goto sigill; 395 goto sigill;
435 396
397 tail = (sf + 1);
398
436 /* 2. Save the current process state */ 399 /* 2. Save the current process state */
437 err = copy_to_user(&sf->regs, regs, sizeof (*regs)); 400 err = copy_to_user(&sf->regs, regs, sizeof (*regs));
438 401
439 if (current_thread_info()->fpsaved[0] & FPRS_FEF) { 402 if (current_thread_info()->fpsaved[0] & FPRS_FEF) {
440 err |= save_fpu_state(regs, &sf->fpu_state); 403 __siginfo_fpu_t __user *fpu_save = tail;
441 err |= __put_user((u64)&sf->fpu_state, &sf->fpu_save); 404 tail += sizeof(__siginfo_fpu_t);
405 err |= save_fpu_state(regs, fpu_save);
406 err |= __put_user((u64)fpu_save, &sf->fpu_save);
442 } else { 407 } else {
443 err |= __put_user(0, &sf->fpu_save); 408 err |= __put_user(0, &sf->fpu_save);
444 } 409 }
410 if (wsaved) {
411 __siginfo_rwin_t __user *rwin_save = tail;
412 tail += sizeof(__siginfo_rwin_t);
413 err |= save_rwin_state(wsaved, rwin_save);
414 err |= __put_user((u64)rwin_save, &sf->rwin_save);
415 set_thread_wsaved(0);
416 } else {
417 err |= __put_user(0, &sf->rwin_save);
418 }
445 419
446 /* Setup sigaltstack */ 420 /* Setup sigaltstack */
447 err |= __put_user(current->sas_ss_sp, &sf->stack.ss_sp); 421 err |= __put_user(current->sas_ss_sp, &sf->stack.ss_sp);
@@ -450,10 +424,17 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
450 424
451 err |= copy_to_user(&sf->mask, oldset, sizeof(sigset_t)); 425 err |= copy_to_user(&sf->mask, oldset, sizeof(sigset_t));
452 426
453 err |= copy_in_user((u64 __user *)sf, 427 if (!wsaved) {
454 (u64 __user *)(regs->u_regs[UREG_FP]+STACK_BIAS), 428 err |= copy_in_user((u64 __user *)sf,
455 sizeof(struct reg_window)); 429 (u64 __user *)(regs->u_regs[UREG_FP] +
430 STACK_BIAS),
431 sizeof(struct reg_window));
432 } else {
433 struct reg_window *rp;
456 434
435 rp = &current_thread_info()->reg_window[wsaved - 1];
436 err |= copy_to_user(sf, rp, sizeof(struct reg_window));
437 }
457 if (info) 438 if (info)
458 err |= copy_siginfo_to_user(&sf->info, info); 439 err |= copy_siginfo_to_user(&sf->info, info);
459 else { 440 else {
@@ -498,18 +479,17 @@ static inline int handle_signal(unsigned long signr, struct k_sigaction *ka,
498 siginfo_t *info, 479 siginfo_t *info,
499 sigset_t *oldset, struct pt_regs *regs) 480 sigset_t *oldset, struct pt_regs *regs)
500{ 481{
482 sigset_t blocked;
501 int err; 483 int err;
502 484
503 err = setup_rt_frame(ka, regs, signr, oldset, 485 err = setup_rt_frame(ka, regs, signr, oldset,
504 (ka->sa.sa_flags & SA_SIGINFO) ? info : NULL); 486 (ka->sa.sa_flags & SA_SIGINFO) ? info : NULL);
505 if (err) 487 if (err)
506 return err; 488 return err;
507 spin_lock_irq(&current->sighand->siglock); 489 sigorsets(&blocked, &current->blocked, &ka->sa.sa_mask);
508 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
509 if (!(ka->sa.sa_flags & SA_NOMASK)) 490 if (!(ka->sa.sa_flags & SA_NOMASK))
510 sigaddset(&current->blocked,signr); 491 sigaddset(&blocked, signr);
511 recalc_sigpending(); 492 set_current_blocked(&blocked);
512 spin_unlock_irq(&current->sighand->siglock);
513 493
514 tracehook_signal_handler(signr, info, ka, regs, 0); 494 tracehook_signal_handler(signr, info, ka, regs, 0);
515 495
@@ -549,11 +529,27 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
549 siginfo_t info; 529 siginfo_t info;
550 int signr; 530 int signr;
551 531
532 /* It's a lot of work and synchronization to add a new ptrace
533 * register for GDB to save and restore in order to get
534 * orig_i0 correct for syscall restarts when debugging.
535 *
536 * Although it should be the case that most of the global
537 * registers are volatile across a system call, glibc already
538 * depends upon that fact that we preserve them. So we can't
539 * just use any global register to save away the orig_i0 value.
540 *
541 * In particular %g2, %g3, %g4, and %g5 are all assumed to be
542 * preserved across a system call trap by various pieces of
543 * code in glibc.
544 *
545 * %g7 is used as the "thread register". %g6 is not used in
546 * any fixed manner. %g6 is used as a scratch register and
547 * a compiler temporary, but it's value is never used across
548 * a system call. Therefore %g6 is usable for orig_i0 storage.
549 */
552 if (pt_regs_is_syscall(regs) && 550 if (pt_regs_is_syscall(regs) &&
553 (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) { 551 (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY)))
554 restart_syscall = 1; 552 regs->u_regs[UREG_G6] = orig_i0;
555 } else
556 restart_syscall = 0;
557 553
558 if (current_thread_info()->status & TS_RESTORE_SIGMASK) 554 if (current_thread_info()->status & TS_RESTORE_SIGMASK)
559 oldset = &current->saved_sigmask; 555 oldset = &current->saved_sigmask;
@@ -562,22 +558,20 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
562 558
563#ifdef CONFIG_COMPAT 559#ifdef CONFIG_COMPAT
564 if (test_thread_flag(TIF_32BIT)) { 560 if (test_thread_flag(TIF_32BIT)) {
565 extern void do_signal32(sigset_t *, struct pt_regs *, 561 extern void do_signal32(sigset_t *, struct pt_regs *);
566 int restart_syscall, 562 do_signal32(oldset, regs);
567 unsigned long orig_i0);
568 do_signal32(oldset, regs, restart_syscall, orig_i0);
569 return; 563 return;
570 } 564 }
571#endif 565#endif
572 566
573 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 567 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
574 568
575 /* If the debugger messes with the program counter, it clears 569 restart_syscall = 0;
576 * the software "in syscall" bit, directing us to not perform 570 if (pt_regs_is_syscall(regs) &&
577 * a syscall restart. 571 (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
578 */ 572 restart_syscall = 1;
579 if (restart_syscall && !pt_regs_is_syscall(regs)) 573 orig_i0 = regs->u_regs[UREG_G6];
580 restart_syscall = 0; 574 }
581 575
582 if (signr > 0) { 576 if (signr > 0) {
583 if (restart_syscall) 577 if (restart_syscall)
@@ -615,7 +609,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
615 */ 609 */
616 if (current_thread_info()->status & TS_RESTORE_SIGMASK) { 610 if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
617 current_thread_info()->status &= ~TS_RESTORE_SIGMASK; 611 current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
618 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL); 612 set_current_blocked(&current->saved_sigmask);
619 } 613 }
620} 614}
621 615
diff --git a/arch/sparc/kernel/sigutil.h b/arch/sparc/kernel/sigutil.h
new file mode 100644
index 000000000000..d223aa432bb6
--- /dev/null
+++ b/arch/sparc/kernel/sigutil.h
@@ -0,0 +1,9 @@
1#ifndef _SIGUTIL_H
2#define _SIGUTIL_H
3
4int save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu);
5int restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu);
6int save_rwin_state(int wsaved, __siginfo_rwin_t __user *rwin);
7int restore_rwin_state(__siginfo_rwin_t __user *rp);
8
9#endif /* _SIGUTIL_H */
diff --git a/arch/sparc/kernel/sigutil_32.c b/arch/sparc/kernel/sigutil_32.c
new file mode 100644
index 000000000000..35c7897b009a
--- /dev/null
+++ b/arch/sparc/kernel/sigutil_32.c
@@ -0,0 +1,120 @@
1#include <linux/kernel.h>
2#include <linux/types.h>
3#include <linux/thread_info.h>
4#include <linux/uaccess.h>
5#include <linux/sched.h>
6
7#include <asm/sigcontext.h>
8#include <asm/fpumacro.h>
9#include <asm/ptrace.h>
10
11#include "sigutil.h"
12
13int save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
14{
15 int err = 0;
16#ifdef CONFIG_SMP
17 if (test_tsk_thread_flag(current, TIF_USEDFPU)) {
18 put_psr(get_psr() | PSR_EF);
19 fpsave(&current->thread.float_regs[0], &current->thread.fsr,
20 &current->thread.fpqueue[0], &current->thread.fpqdepth);
21 regs->psr &= ~(PSR_EF);
22 clear_tsk_thread_flag(current, TIF_USEDFPU);
23 }
24#else
25 if (current == last_task_used_math) {
26 put_psr(get_psr() | PSR_EF);
27 fpsave(&current->thread.float_regs[0], &current->thread.fsr,
28 &current->thread.fpqueue[0], &current->thread.fpqdepth);
29 last_task_used_math = NULL;
30 regs->psr &= ~(PSR_EF);
31 }
32#endif
33 err |= __copy_to_user(&fpu->si_float_regs[0],
34 &current->thread.float_regs[0],
35 (sizeof(unsigned long) * 32));
36 err |= __put_user(current->thread.fsr, &fpu->si_fsr);
37 err |= __put_user(current->thread.fpqdepth, &fpu->si_fpqdepth);
38 if (current->thread.fpqdepth != 0)
39 err |= __copy_to_user(&fpu->si_fpqueue[0],
40 &current->thread.fpqueue[0],
41 ((sizeof(unsigned long) +
42 (sizeof(unsigned long *)))*16));
43 clear_used_math();
44 return err;
45}
46
47int restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
48{
49 int err;
50#ifdef CONFIG_SMP
51 if (test_tsk_thread_flag(current, TIF_USEDFPU))
52 regs->psr &= ~PSR_EF;
53#else
54 if (current == last_task_used_math) {
55 last_task_used_math = NULL;
56 regs->psr &= ~PSR_EF;
57 }
58#endif
59 set_used_math();
60 clear_tsk_thread_flag(current, TIF_USEDFPU);
61
62 if (!access_ok(VERIFY_READ, fpu, sizeof(*fpu)))
63 return -EFAULT;
64
65 err = __copy_from_user(&current->thread.float_regs[0], &fpu->si_float_regs[0],
66 (sizeof(unsigned long) * 32));
67 err |= __get_user(current->thread.fsr, &fpu->si_fsr);
68 err |= __get_user(current->thread.fpqdepth, &fpu->si_fpqdepth);
69 if (current->thread.fpqdepth != 0)
70 err |= __copy_from_user(&current->thread.fpqueue[0],
71 &fpu->si_fpqueue[0],
72 ((sizeof(unsigned long) +
73 (sizeof(unsigned long *)))*16));
74 return err;
75}
76
77int save_rwin_state(int wsaved, __siginfo_rwin_t __user *rwin)
78{
79 int i, err = __put_user(wsaved, &rwin->wsaved);
80
81 for (i = 0; i < wsaved; i++) {
82 struct reg_window32 *rp;
83 unsigned long fp;
84
85 rp = &current_thread_info()->reg_window[i];
86 fp = current_thread_info()->rwbuf_stkptrs[i];
87 err |= copy_to_user(&rwin->reg_window[i], rp,
88 sizeof(struct reg_window32));
89 err |= __put_user(fp, &rwin->rwbuf_stkptrs[i]);
90 }
91 return err;
92}
93
94int restore_rwin_state(__siginfo_rwin_t __user *rp)
95{
96 struct thread_info *t = current_thread_info();
97 int i, wsaved, err;
98
99 __get_user(wsaved, &rp->wsaved);
100 if (wsaved > NSWINS)
101 return -EFAULT;
102
103 err = 0;
104 for (i = 0; i < wsaved; i++) {
105 err |= copy_from_user(&t->reg_window[i],
106 &rp->reg_window[i],
107 sizeof(struct reg_window32));
108 err |= __get_user(t->rwbuf_stkptrs[i],
109 &rp->rwbuf_stkptrs[i]);
110 }
111 if (err)
112 return err;
113
114 t->w_saved = wsaved;
115 synchronize_user_stack();
116 if (t->w_saved)
117 return -EFAULT;
118 return 0;
119
120}
diff --git a/arch/sparc/kernel/sigutil_64.c b/arch/sparc/kernel/sigutil_64.c
new file mode 100644
index 000000000000..b19570d41a39
--- /dev/null
+++ b/arch/sparc/kernel/sigutil_64.c
@@ -0,0 +1,94 @@
1#include <linux/kernel.h>
2#include <linux/types.h>
3#include <linux/thread_info.h>
4#include <linux/uaccess.h>
5#include <linux/errno.h>
6
7#include <asm/sigcontext.h>
8#include <asm/fpumacro.h>
9#include <asm/ptrace.h>
10
11#include "sigutil.h"
12
13int save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
14{
15 unsigned long *fpregs = current_thread_info()->fpregs;
16 unsigned long fprs;
17 int err = 0;
18
19 fprs = current_thread_info()->fpsaved[0];
20 if (fprs & FPRS_DL)
21 err |= copy_to_user(&fpu->si_float_regs[0], fpregs,
22 (sizeof(unsigned int) * 32));
23 if (fprs & FPRS_DU)
24 err |= copy_to_user(&fpu->si_float_regs[32], fpregs+16,
25 (sizeof(unsigned int) * 32));
26 err |= __put_user(current_thread_info()->xfsr[0], &fpu->si_fsr);
27 err |= __put_user(current_thread_info()->gsr[0], &fpu->si_gsr);
28 err |= __put_user(fprs, &fpu->si_fprs);
29
30 return err;
31}
32
33int restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
34{
35 unsigned long *fpregs = current_thread_info()->fpregs;
36 unsigned long fprs;
37 int err;
38
39 err = __get_user(fprs, &fpu->si_fprs);
40 fprs_write(0);
41 regs->tstate &= ~TSTATE_PEF;
42 if (fprs & FPRS_DL)
43 err |= copy_from_user(fpregs, &fpu->si_float_regs[0],
44 (sizeof(unsigned int) * 32));
45 if (fprs & FPRS_DU)
46 err |= copy_from_user(fpregs+16, &fpu->si_float_regs[32],
47 (sizeof(unsigned int) * 32));
48 err |= __get_user(current_thread_info()->xfsr[0], &fpu->si_fsr);
49 err |= __get_user(current_thread_info()->gsr[0], &fpu->si_gsr);
50 current_thread_info()->fpsaved[0] |= fprs;
51 return err;
52}
53
54int save_rwin_state(int wsaved, __siginfo_rwin_t __user *rwin)
55{
56 int i, err = __put_user(wsaved, &rwin->wsaved);
57
58 for (i = 0; i < wsaved; i++) {
59 struct reg_window *rp = &current_thread_info()->reg_window[i];
60 unsigned long fp = current_thread_info()->rwbuf_stkptrs[i];
61
62 err |= copy_to_user(&rwin->reg_window[i], rp,
63 sizeof(struct reg_window));
64 err |= __put_user(fp, &rwin->rwbuf_stkptrs[i]);
65 }
66 return err;
67}
68
69int restore_rwin_state(__siginfo_rwin_t __user *rp)
70{
71 struct thread_info *t = current_thread_info();
72 int i, wsaved, err;
73
74 __get_user(wsaved, &rp->wsaved);
75 if (wsaved > NSWINS)
76 return -EFAULT;
77
78 err = 0;
79 for (i = 0; i < wsaved; i++) {
80 err |= copy_from_user(&t->reg_window[i],
81 &rp->reg_window[i],
82 sizeof(struct reg_window));
83 err |= __get_user(t->rwbuf_stkptrs[i],
84 &rp->rwbuf_stkptrs[i]);
85 }
86 if (err)
87 return err;
88
89 set_thread_wsaved(wsaved);
90 synchronize_user_stack();
91 if (get_thread_wsaved())
92 return -EFAULT;
93 return 0;
94}
diff --git a/arch/sparc/kernel/smp_32.c b/arch/sparc/kernel/smp_32.c
index 21b125341bf7..f671e7fd6ddc 100644
--- a/arch/sparc/kernel/smp_32.c
+++ b/arch/sparc/kernel/smp_32.c
@@ -22,7 +22,7 @@
22#include <linux/delay.h> 22#include <linux/delay.h>
23 23
24#include <asm/ptrace.h> 24#include <asm/ptrace.h>
25#include <asm/atomic.h> 25#include <linux/atomic.h>
26 26
27#include <asm/irq.h> 27#include <asm/irq.h>
28#include <asm/page.h> 28#include <asm/page.h>
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c
index 99cb17251bb5..75607724d290 100644
--- a/arch/sparc/kernel/smp_64.c
+++ b/arch/sparc/kernel/smp_64.c
@@ -3,7 +3,7 @@
3 * Copyright (C) 1997, 2007, 2008 David S. Miller (davem@davemloft.net) 3 * Copyright (C) 1997, 2007, 2008 David S. Miller (davem@davemloft.net)
4 */ 4 */
5 5
6#include <linux/module.h> 6#include <linux/export.h>
7#include <linux/kernel.h> 7#include <linux/kernel.h>
8#include <linux/sched.h> 8#include <linux/sched.h>
9#include <linux/mm.h> 9#include <linux/mm.h>
@@ -28,7 +28,7 @@
28 28
29#include <asm/head.h> 29#include <asm/head.h>
30#include <asm/ptrace.h> 30#include <asm/ptrace.h>
31#include <asm/atomic.h> 31#include <linux/atomic.h>
32#include <asm/tlbflush.h> 32#include <asm/tlbflush.h>
33#include <asm/mmu_context.h> 33#include <asm/mmu_context.h>
34#include <asm/cpudata.h> 34#include <asm/cpudata.h>
diff --git a/arch/sparc/kernel/sparc_ksyms_64.c b/arch/sparc/kernel/sparc_ksyms_64.c
index 372ad59c4cba..12ff09824cd9 100644
--- a/arch/sparc/kernel/sparc_ksyms_64.c
+++ b/arch/sparc/kernel/sparc_ksyms_64.c
@@ -5,9 +5,10 @@
5 * Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz) 5 * Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz)
6 */ 6 */
7 7
8#include <linux/module.h> 8#include <linux/export.h>
9#include <linux/pci.h> 9#include <linux/pci.h>
10#include <linux/init.h> 10#include <linux/init.h>
11#include <linux/bitops.h>
11 12
12#include <asm/system.h> 13#include <asm/system.h>
13#include <asm/cpudata.h> 14#include <asm/cpudata.h>
@@ -38,5 +39,15 @@ EXPORT_SYMBOL(sun4v_niagara_setperf);
38EXPORT_SYMBOL(sun4v_niagara2_getperf); 39EXPORT_SYMBOL(sun4v_niagara2_getperf);
39EXPORT_SYMBOL(sun4v_niagara2_setperf); 40EXPORT_SYMBOL(sun4v_niagara2_setperf);
40 41
42/* from hweight.S */
43EXPORT_SYMBOL(__arch_hweight8);
44EXPORT_SYMBOL(__arch_hweight16);
45EXPORT_SYMBOL(__arch_hweight32);
46EXPORT_SYMBOL(__arch_hweight64);
47
48/* from ffs_ffz.S */
49EXPORT_SYMBOL(ffs);
50EXPORT_SYMBOL(__ffs);
51
41/* Exporting a symbol from /init/main.c */ 52/* Exporting a symbol from /init/main.c */
42EXPORT_SYMBOL(saved_command_line); 53EXPORT_SYMBOL(saved_command_line);
diff --git a/arch/sparc/kernel/sstate.c b/arch/sparc/kernel/sstate.c
index 8cdbe5946b43..c59af546f522 100644
--- a/arch/sparc/kernel/sstate.c
+++ b/arch/sparc/kernel/sstate.c
@@ -14,14 +14,9 @@
14#include <asm/head.h> 14#include <asm/head.h>
15#include <asm/io.h> 15#include <asm/io.h>
16 16
17static int hv_supports_soft_state; 17#include "kernel.h"
18
19static unsigned long kimage_addr_to_ra(const char *p)
20{
21 unsigned long val = (unsigned long) p;
22 18
23 return kern_base + (val - KERNBASE); 19static int hv_supports_soft_state;
24}
25 20
26static void do_set_sstate(unsigned long state, const char *msg) 21static void do_set_sstate(unsigned long state, const char *msg)
27{ 22{
diff --git a/arch/sparc/kernel/stacktrace.c b/arch/sparc/kernel/stacktrace.c
index 3e0815349630..e78386a0029f 100644
--- a/arch/sparc/kernel/stacktrace.c
+++ b/arch/sparc/kernel/stacktrace.c
@@ -2,7 +2,7 @@
2#include <linux/stacktrace.h> 2#include <linux/stacktrace.h>
3#include <linux/thread_info.h> 3#include <linux/thread_info.h>
4#include <linux/ftrace.h> 4#include <linux/ftrace.h>
5#include <linux/module.h> 5#include <linux/export.h>
6#include <asm/ptrace.h> 6#include <asm/ptrace.h>
7#include <asm/stacktrace.h> 7#include <asm/stacktrace.h>
8 8
diff --git a/arch/sparc/kernel/sys32.S b/arch/sparc/kernel/sys32.S
index 44e5faf1ad5f..d97f3eb72e06 100644
--- a/arch/sparc/kernel/sys32.S
+++ b/arch/sparc/kernel/sys32.S
@@ -81,7 +81,6 @@ SIGN2(sys32_fadvise64, compat_sys_fadvise64, %o0, %o4)
81SIGN2(sys32_fadvise64_64, compat_sys_fadvise64_64, %o0, %o5) 81SIGN2(sys32_fadvise64_64, compat_sys_fadvise64_64, %o0, %o5)
82SIGN2(sys32_bdflush, sys_bdflush, %o0, %o1) 82SIGN2(sys32_bdflush, sys_bdflush, %o0, %o1)
83SIGN1(sys32_mlockall, sys_mlockall, %o0) 83SIGN1(sys32_mlockall, sys_mlockall, %o0)
84SIGN1(sys32_nfsservctl, compat_sys_nfsservctl, %o0)
85SIGN1(sys32_clock_nanosleep, compat_sys_clock_nanosleep, %o1) 84SIGN1(sys32_clock_nanosleep, compat_sys_clock_nanosleep, %o1)
86SIGN1(sys32_timer_settime, compat_sys_timer_settime, %o1) 85SIGN1(sys32_timer_settime, compat_sys_timer_settime, %o1)
87SIGN1(sys32_io_submit, compat_sys_io_submit, %o1) 86SIGN1(sys32_io_submit, compat_sys_io_submit, %o1)
diff --git a/arch/sparc/kernel/sys_sparc32.c b/arch/sparc/kernel/sys_sparc32.c
index 170cd8e8eb2a..29c478ffed91 100644
--- a/arch/sparc/kernel/sys_sparc32.c
+++ b/arch/sparc/kernel/sys_sparc32.c
@@ -23,7 +23,6 @@
23#include <linux/uio.h> 23#include <linux/uio.h>
24#include <linux/nfs_fs.h> 24#include <linux/nfs_fs.h>
25#include <linux/quota.h> 25#include <linux/quota.h>
26#include <linux/module.h>
27#include <linux/poll.h> 26#include <linux/poll.h>
28#include <linux/personality.h> 27#include <linux/personality.h>
29#include <linux/stat.h> 28#include <linux/stat.h>
diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c
index 908b47a5ee24..441521ad8a3f 100644
--- a/arch/sparc/kernel/sys_sparc_64.c
+++ b/arch/sparc/kernel/sys_sparc_64.c
@@ -23,7 +23,7 @@
23#include <linux/ipc.h> 23#include <linux/ipc.h>
24#include <linux/personality.h> 24#include <linux/personality.h>
25#include <linux/random.h> 25#include <linux/random.h>
26#include <linux/module.h> 26#include <linux/export.h>
27 27
28#include <asm/uaccess.h> 28#include <asm/uaccess.h>
29#include <asm/utrap.h> 29#include <asm/utrap.h>
diff --git a/arch/sparc/kernel/systbls_32.S b/arch/sparc/kernel/systbls_32.S
index 6e492d59f6b1..63402f9e9f51 100644
--- a/arch/sparc/kernel/systbls_32.S
+++ b/arch/sparc/kernel/systbls_32.S
@@ -67,7 +67,7 @@ sys_call_table:
67/*235*/ .long sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall 67/*235*/ .long sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
68/*240*/ .long sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler 68/*240*/ .long sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler
69/*245*/ .long sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep 69/*245*/ .long sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep
70/*250*/ .long sys_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl 70/*250*/ .long sys_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_ni_syscall
71/*255*/ .long sys_sync_file_range, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep 71/*255*/ .long sys_sync_file_range, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep
72/*260*/ .long sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun 72/*260*/ .long sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun
73/*265*/ .long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_io_setup, sys_io_destroy 73/*265*/ .long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_io_setup, sys_io_destroy
@@ -84,4 +84,4 @@ sys_call_table:
84/*320*/ .long sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv 84/*320*/ .long sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv
85/*325*/ .long sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init 85/*325*/ .long sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init
86/*330*/ .long sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime 86/*330*/ .long sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
87/*335*/ .long sys_syncfs, sys_sendmmsg, sys_setns 87/*335*/ .long sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev
diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S
index f566518483b5..db86b1a0e9a9 100644
--- a/arch/sparc/kernel/systbls_64.S
+++ b/arch/sparc/kernel/systbls_64.S
@@ -68,7 +68,7 @@ sys_call_table32:
68 .word compat_sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys32_mlockall 68 .word compat_sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys32_mlockall
69/*240*/ .word sys_munlockall, sys32_sched_setparam, sys32_sched_getparam, sys32_sched_setscheduler, sys32_sched_getscheduler 69/*240*/ .word sys_munlockall, sys32_sched_setparam, sys32_sched_getparam, sys32_sched_setscheduler, sys32_sched_getscheduler
70 .word sys_sched_yield, sys32_sched_get_priority_max, sys32_sched_get_priority_min, sys32_sched_rr_get_interval, compat_sys_nanosleep 70 .word sys_sched_yield, sys32_sched_get_priority_max, sys32_sched_get_priority_min, sys32_sched_rr_get_interval, compat_sys_nanosleep
71/*250*/ .word sys_mremap, compat_sys_sysctl, sys32_getsid, sys_fdatasync, sys32_nfsservctl 71/*250*/ .word sys_mremap, compat_sys_sysctl, sys32_getsid, sys_fdatasync, sys_nis_syscall
72 .word sys32_sync_file_range, compat_sys_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep 72 .word sys32_sync_file_range, compat_sys_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep
73/*260*/ .word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_sys_timer_gettime, sys_timer_getoverrun 73/*260*/ .word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_sys_timer_gettime, sys_timer_getoverrun
74 .word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy 74 .word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy
@@ -85,7 +85,7 @@ sys_call_table32:
85/*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, compat_sys_preadv 85/*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, compat_sys_preadv
86 .word compat_sys_pwritev, compat_sys_rt_tgsigqueueinfo, sys_perf_event_open, compat_sys_recvmmsg, sys_fanotify_init 86 .word compat_sys_pwritev, compat_sys_rt_tgsigqueueinfo, sys_perf_event_open, compat_sys_recvmmsg, sys_fanotify_init
87/*330*/ .word sys32_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime 87/*330*/ .word sys32_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime
88 .word sys_syncfs, compat_sys_sendmmsg, sys_setns 88 .word sys_syncfs, compat_sys_sendmmsg, sys_setns, compat_sys_process_vm_readv, compat_sys_process_vm_writev
89 89
90#endif /* CONFIG_COMPAT */ 90#endif /* CONFIG_COMPAT */
91 91
@@ -145,7 +145,7 @@ sys_call_table:
145 .word sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall 145 .word sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
146/*240*/ .word sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler 146/*240*/ .word sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler
147 .word sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep 147 .word sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep
148/*250*/ .word sys_64_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl 148/*250*/ .word sys_64_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nis_syscall
149 .word sys_sync_file_range, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep 149 .word sys_sync_file_range, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep
150/*260*/ .word sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun 150/*260*/ .word sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun
151 .word sys_timer_delete, sys_timer_create, sys_ni_syscall, sys_io_setup, sys_io_destroy 151 .word sys_timer_delete, sys_timer_create, sys_ni_syscall, sys_io_setup, sys_io_destroy
@@ -162,4 +162,4 @@ sys_call_table:
162/*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv 162/*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv
163 .word sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init 163 .word sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init
164/*330*/ .word sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime 164/*330*/ .word sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
165 .word sys_syncfs, sys_sendmmsg, sys_setns 165 .word sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev
diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c
index 1db6b18964d2..e861072b9c52 100644
--- a/arch/sparc/kernel/time_64.c
+++ b/arch/sparc/kernel/time_64.c
@@ -9,7 +9,7 @@
9 */ 9 */
10 10
11#include <linux/errno.h> 11#include <linux/errno.h>
12#include <linux/module.h> 12#include <linux/export.h>
13#include <linux/sched.h> 13#include <linux/sched.h>
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include <linux/param.h> 15#include <linux/param.h>
diff --git a/arch/sparc/kernel/traps_32.c b/arch/sparc/kernel/traps_32.c
index c0490c7bbde0..591f20ca9e48 100644
--- a/arch/sparc/kernel/traps_32.c
+++ b/arch/sparc/kernel/traps_32.c
@@ -14,6 +14,7 @@
14#include <linux/signal.h> 14#include <linux/signal.h>
15#include <linux/smp.h> 15#include <linux/smp.h>
16#include <linux/kdebug.h> 16#include <linux/kdebug.h>
17#include <linux/export.h>
17 18
18#include <asm/delay.h> 19#include <asm/delay.h>
19#include <asm/system.h> 20#include <asm/system.h>
diff --git a/arch/sparc/kernel/unaligned_32.c b/arch/sparc/kernel/unaligned_32.c
index 4491f4cb2695..4d043a1b2492 100644
--- a/arch/sparc/kernel/unaligned_32.c
+++ b/arch/sparc/kernel/unaligned_32.c
@@ -10,7 +10,6 @@
10#include <linux/kernel.h> 10#include <linux/kernel.h>
11#include <linux/sched.h> 11#include <linux/sched.h>
12#include <linux/mm.h> 12#include <linux/mm.h>
13#include <linux/module.h>
14#include <asm/ptrace.h> 13#include <asm/ptrace.h>
15#include <asm/processor.h> 14#include <asm/processor.h>
16#include <asm/system.h> 15#include <asm/system.h>
@@ -247,7 +246,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
247 unsigned long addr = compute_effective_address(regs, insn); 246 unsigned long addr = compute_effective_address(regs, insn);
248 int err; 247 int err;
249 248
250 perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, regs, addr); 249 perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, addr);
251 switch (dir) { 250 switch (dir) {
252 case load: 251 case load:
253 err = do_int_load(fetch_reg_addr(((insn>>25)&0x1f), 252 err = do_int_load(fetch_reg_addr(((insn>>25)&0x1f),
@@ -338,7 +337,7 @@ asmlinkage void user_unaligned_trap(struct pt_regs *regs, unsigned int insn)
338 } 337 }
339 338
340 addr = compute_effective_address(regs, insn); 339 addr = compute_effective_address(regs, insn);
341 perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, regs, addr); 340 perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, addr);
342 switch(dir) { 341 switch(dir) {
343 case load: 342 case load:
344 err = do_int_load(fetch_reg_addr(((insn>>25)&0x1f), 343 err = do_int_load(fetch_reg_addr(((insn>>25)&0x1f),
diff --git a/arch/sparc/kernel/unaligned_64.c b/arch/sparc/kernel/unaligned_64.c
index b2b019ea8caa..76e4ac1a13e1 100644
--- a/arch/sparc/kernel/unaligned_64.c
+++ b/arch/sparc/kernel/unaligned_64.c
@@ -22,6 +22,7 @@
22#include <linux/bitops.h> 22#include <linux/bitops.h>
23#include <linux/perf_event.h> 23#include <linux/perf_event.h>
24#include <linux/ratelimit.h> 24#include <linux/ratelimit.h>
25#include <linux/bitops.h>
25#include <asm/fpumacro.h> 26#include <asm/fpumacro.h>
26 27
27enum direction { 28enum direction {
@@ -317,7 +318,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
317 318
318 addr = compute_effective_address(regs, insn, 319 addr = compute_effective_address(regs, insn,
319 ((insn >> 25) & 0x1f)); 320 ((insn >> 25) & 0x1f));
320 perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, regs, addr); 321 perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, addr);
321 switch (asi) { 322 switch (asi) {
322 case ASI_NL: 323 case ASI_NL:
323 case ASI_AIUPL: 324 case ASI_AIUPL:
@@ -373,18 +374,13 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
373 } 374 }
374} 375}
375 376
376static char popc_helper[] = {
3770, 1, 1, 2, 1, 2, 2, 3,
3781, 2, 2, 3, 2, 3, 3, 4,
379};
380
381int handle_popc(u32 insn, struct pt_regs *regs) 377int handle_popc(u32 insn, struct pt_regs *regs)
382{ 378{
383 u64 value;
384 int ret, i, rd = ((insn >> 25) & 0x1f);
385 int from_kernel = (regs->tstate & TSTATE_PRIV) != 0; 379 int from_kernel = (regs->tstate & TSTATE_PRIV) != 0;
380 int ret, rd = ((insn >> 25) & 0x1f);
381 u64 value;
386 382
387 perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, 0); 383 perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
388 if (insn & 0x2000) { 384 if (insn & 0x2000) {
389 maybe_flush_windows(0, 0, rd, from_kernel); 385 maybe_flush_windows(0, 0, rd, from_kernel);
390 value = sign_extend_imm13(insn); 386 value = sign_extend_imm13(insn);
@@ -392,10 +388,7 @@ int handle_popc(u32 insn, struct pt_regs *regs)
392 maybe_flush_windows(0, insn & 0x1f, rd, from_kernel); 388 maybe_flush_windows(0, insn & 0x1f, rd, from_kernel);
393 value = fetch_reg(insn & 0x1f, regs); 389 value = fetch_reg(insn & 0x1f, regs);
394 } 390 }
395 for (ret = 0, i = 0; i < 16; i++) { 391 ret = hweight64(value);
396 ret += popc_helper[value & 0xf];
397 value >>= 4;
398 }
399 if (rd < 16) { 392 if (rd < 16) {
400 if (rd) 393 if (rd)
401 regs->u_regs[rd] = ret; 394 regs->u_regs[rd] = ret;
@@ -431,7 +424,7 @@ int handle_ldf_stq(u32 insn, struct pt_regs *regs)
431 int asi = decode_asi(insn, regs); 424 int asi = decode_asi(insn, regs);
432 int flag = (freg < 32) ? FPRS_DL : FPRS_DU; 425 int flag = (freg < 32) ? FPRS_DL : FPRS_DU;
433 426
434 perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, 0); 427 perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
435 428
436 save_and_clear_fpu(); 429 save_and_clear_fpu();
437 current_thread_info()->xfsr[0] &= ~0x1c000; 430 current_thread_info()->xfsr[0] &= ~0x1c000;
@@ -554,7 +547,7 @@ void handle_ld_nf(u32 insn, struct pt_regs *regs)
554 int from_kernel = (regs->tstate & TSTATE_PRIV) != 0; 547 int from_kernel = (regs->tstate & TSTATE_PRIV) != 0;
555 unsigned long *reg; 548 unsigned long *reg;
556 549
557 perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, 0); 550 perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
558 551
559 maybe_flush_windows(0, 0, rd, from_kernel); 552 maybe_flush_windows(0, 0, rd, from_kernel);
560 reg = fetch_reg_addr(rd, regs); 553 reg = fetch_reg_addr(rd, regs);
@@ -586,7 +579,7 @@ void handle_lddfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr
586 579
587 if (tstate & TSTATE_PRIV) 580 if (tstate & TSTATE_PRIV)
588 die_if_kernel("lddfmna from kernel", regs); 581 die_if_kernel("lddfmna from kernel", regs);
589 perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, regs, sfar); 582 perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, sfar);
590 if (test_thread_flag(TIF_32BIT)) 583 if (test_thread_flag(TIF_32BIT))
591 pc = (u32)pc; 584 pc = (u32)pc;
592 if (get_user(insn, (u32 __user *) pc) != -EFAULT) { 585 if (get_user(insn, (u32 __user *) pc) != -EFAULT) {
@@ -647,7 +640,7 @@ void handle_stdfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr
647 640
648 if (tstate & TSTATE_PRIV) 641 if (tstate & TSTATE_PRIV)
649 die_if_kernel("stdfmna from kernel", regs); 642 die_if_kernel("stdfmna from kernel", regs);
650 perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, regs, sfar); 643 perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, sfar);
651 if (test_thread_flag(TIF_32BIT)) 644 if (test_thread_flag(TIF_32BIT))
652 pc = (u32)pc; 645 pc = (u32)pc;
653 if (get_user(insn, (u32 __user *) pc) != -EFAULT) { 646 if (get_user(insn, (u32 __user *) pc) != -EFAULT) {
diff --git a/arch/sparc/kernel/vio.c b/arch/sparc/kernel/vio.c
index 3cb1def9806c..f67e28ef598c 100644
--- a/arch/sparc/kernel/vio.c
+++ b/arch/sparc/kernel/vio.c
@@ -12,6 +12,7 @@
12#include <linux/kernel.h> 12#include <linux/kernel.h>
13#include <linux/slab.h> 13#include <linux/slab.h>
14#include <linux/irq.h> 14#include <linux/irq.h>
15#include <linux/export.h>
15#include <linux/init.h> 16#include <linux/init.h>
16 17
17#include <asm/mdesc.h> 18#include <asm/mdesc.h>
diff --git a/arch/sparc/kernel/viohs.c b/arch/sparc/kernel/viohs.c
index 29348ea139c3..f8e7dd53e1c7 100644
--- a/arch/sparc/kernel/viohs.c
+++ b/arch/sparc/kernel/viohs.c
@@ -4,7 +4,7 @@
4 */ 4 */
5 5
6#include <linux/kernel.h> 6#include <linux/kernel.h>
7#include <linux/module.h> 7#include <linux/export.h>
8#include <linux/string.h> 8#include <linux/string.h>
9#include <linux/delay.h> 9#include <linux/delay.h>
10#include <linux/sched.h> 10#include <linux/sched.h>
diff --git a/arch/sparc/kernel/visemul.c b/arch/sparc/kernel/visemul.c
index 36357717d691..73370674ccff 100644
--- a/arch/sparc/kernel/visemul.c
+++ b/arch/sparc/kernel/visemul.c
@@ -713,17 +713,17 @@ static void pcmp(struct pt_regs *regs, unsigned int insn, unsigned int opf)
713 s16 b = (rs2 >> (i * 16)) & 0xffff; 713 s16 b = (rs2 >> (i * 16)) & 0xffff;
714 714
715 if (a > b) 715 if (a > b)
716 rd_val |= 1 << i; 716 rd_val |= 8 >> i;
717 } 717 }
718 break; 718 break;
719 719
720 case FCMPGT32_OPF: 720 case FCMPGT32_OPF:
721 for (i = 0; i < 2; i++) { 721 for (i = 0; i < 2; i++) {
722 s32 a = (rs1 >> (i * 32)) & 0xffff; 722 s32 a = (rs1 >> (i * 32)) & 0xffffffff;
723 s32 b = (rs2 >> (i * 32)) & 0xffff; 723 s32 b = (rs2 >> (i * 32)) & 0xffffffff;
724 724
725 if (a > b) 725 if (a > b)
726 rd_val |= 1 << i; 726 rd_val |= 2 >> i;
727 } 727 }
728 break; 728 break;
729 729
@@ -733,17 +733,17 @@ static void pcmp(struct pt_regs *regs, unsigned int insn, unsigned int opf)
733 s16 b = (rs2 >> (i * 16)) & 0xffff; 733 s16 b = (rs2 >> (i * 16)) & 0xffff;
734 734
735 if (a <= b) 735 if (a <= b)
736 rd_val |= 1 << i; 736 rd_val |= 8 >> i;
737 } 737 }
738 break; 738 break;
739 739
740 case FCMPLE32_OPF: 740 case FCMPLE32_OPF:
741 for (i = 0; i < 2; i++) { 741 for (i = 0; i < 2; i++) {
742 s32 a = (rs1 >> (i * 32)) & 0xffff; 742 s32 a = (rs1 >> (i * 32)) & 0xffffffff;
743 s32 b = (rs2 >> (i * 32)) & 0xffff; 743 s32 b = (rs2 >> (i * 32)) & 0xffffffff;
744 744
745 if (a <= b) 745 if (a <= b)
746 rd_val |= 1 << i; 746 rd_val |= 2 >> i;
747 } 747 }
748 break; 748 break;
749 749
@@ -753,17 +753,17 @@ static void pcmp(struct pt_regs *regs, unsigned int insn, unsigned int opf)
753 s16 b = (rs2 >> (i * 16)) & 0xffff; 753 s16 b = (rs2 >> (i * 16)) & 0xffff;
754 754
755 if (a != b) 755 if (a != b)
756 rd_val |= 1 << i; 756 rd_val |= 8 >> i;
757 } 757 }
758 break; 758 break;
759 759
760 case FCMPNE32_OPF: 760 case FCMPNE32_OPF:
761 for (i = 0; i < 2; i++) { 761 for (i = 0; i < 2; i++) {
762 s32 a = (rs1 >> (i * 32)) & 0xffff; 762 s32 a = (rs1 >> (i * 32)) & 0xffffffff;
763 s32 b = (rs2 >> (i * 32)) & 0xffff; 763 s32 b = (rs2 >> (i * 32)) & 0xffffffff;
764 764
765 if (a != b) 765 if (a != b)
766 rd_val |= 1 << i; 766 rd_val |= 2 >> i;
767 } 767 }
768 break; 768 break;
769 769
@@ -773,17 +773,17 @@ static void pcmp(struct pt_regs *regs, unsigned int insn, unsigned int opf)
773 s16 b = (rs2 >> (i * 16)) & 0xffff; 773 s16 b = (rs2 >> (i * 16)) & 0xffff;
774 774
775 if (a == b) 775 if (a == b)
776 rd_val |= 1 << i; 776 rd_val |= 8 >> i;
777 } 777 }
778 break; 778 break;
779 779
780 case FCMPEQ32_OPF: 780 case FCMPEQ32_OPF:
781 for (i = 0; i < 2; i++) { 781 for (i = 0; i < 2; i++) {
782 s32 a = (rs1 >> (i * 32)) & 0xffff; 782 s32 a = (rs1 >> (i * 32)) & 0xffffffff;
783 s32 b = (rs2 >> (i * 32)) & 0xffff; 783 s32 b = (rs2 >> (i * 32)) & 0xffffffff;
784 784
785 if (a == b) 785 if (a == b)
786 rd_val |= 1 << i; 786 rd_val |= 2 >> i;
787 } 787 }
788 break; 788 break;
789 } 789 }
@@ -802,7 +802,7 @@ int vis_emul(struct pt_regs *regs, unsigned int insn)
802 802
803 BUG_ON(regs->tstate & TSTATE_PRIV); 803 BUG_ON(regs->tstate & TSTATE_PRIV);
804 804
805 perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, 0); 805 perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
806 806
807 if (test_thread_flag(TIF_32BIT)) 807 if (test_thread_flag(TIF_32BIT))
808 pc = (u32)pc; 808 pc = (u32)pc;
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index c0220759003e..0e1605697b49 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -107,7 +107,26 @@ SECTIONS
107 *(.sun4v_2insn_patch) 107 *(.sun4v_2insn_patch)
108 __sun4v_2insn_patch_end = .; 108 __sun4v_2insn_patch_end = .;
109 } 109 }
110 110 .swapper_tsb_phys_patch : {
111 __swapper_tsb_phys_patch = .;
112 *(.swapper_tsb_phys_patch)
113 __swapper_tsb_phys_patch_end = .;
114 }
115 .swapper_4m_tsb_phys_patch : {
116 __swapper_4m_tsb_phys_patch = .;
117 *(.swapper_4m_tsb_phys_patch)
118 __swapper_4m_tsb_phys_patch_end = .;
119 }
120 .popc_3insn_patch : {
121 __popc_3insn_patch = .;
122 *(.popc_3insn_patch)
123 __popc_3insn_patch_end = .;
124 }
125 .popc_6insn_patch : {
126 __popc_6insn_patch = .;
127 *(.popc_6insn_patch)
128 __popc_6insn_patch_end = .;
129 }
111 PERCPU_SECTION(SMP_CACHE_BYTES) 130 PERCPU_SECTION(SMP_CACHE_BYTES)
112 131
113 . = ALIGN(PAGE_SIZE); 132 . = ALIGN(PAGE_SIZE);
diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile
index 7f01b8fce8bc..a3fc4375a150 100644
--- a/arch/sparc/lib/Makefile
+++ b/arch/sparc/lib/Makefile
@@ -31,13 +31,13 @@ lib-$(CONFIG_SPARC64) += NGmemcpy.o NGcopy_from_user.o NGcopy_to_user.o
31lib-$(CONFIG_SPARC64) += NGpatch.o NGpage.o NGbzero.o 31lib-$(CONFIG_SPARC64) += NGpatch.o NGpage.o NGbzero.o
32 32
33lib-$(CONFIG_SPARC64) += NG2memcpy.o NG2copy_from_user.o NG2copy_to_user.o 33lib-$(CONFIG_SPARC64) += NG2memcpy.o NG2copy_from_user.o NG2copy_to_user.o
34lib-$(CONFIG_SPARC64) += NG2patch.o NG2page.o 34lib-$(CONFIG_SPARC64) += NG2patch.o
35 35
36lib-$(CONFIG_SPARC64) += GENmemcpy.o GENcopy_from_user.o GENcopy_to_user.o 36lib-$(CONFIG_SPARC64) += GENmemcpy.o GENcopy_from_user.o GENcopy_to_user.o
37lib-$(CONFIG_SPARC64) += GENpatch.o GENpage.o GENbzero.o 37lib-$(CONFIG_SPARC64) += GENpatch.o GENpage.o GENbzero.o
38 38
39lib-$(CONFIG_SPARC64) += copy_in_user.o user_fixup.o memmove.o 39lib-$(CONFIG_SPARC64) += copy_in_user.o user_fixup.o memmove.o
40lib-$(CONFIG_SPARC64) += mcount.o ipcsum.o xor.o 40lib-$(CONFIG_SPARC64) += mcount.o ipcsum.o xor.o hweight.o ffs.o
41 41
42obj-y += iomap.o 42obj-y += iomap.o
43obj-$(CONFIG_SPARC32) += atomic32.o 43obj-$(CONFIG_SPARC32) += atomic32.o
diff --git a/arch/sparc/lib/NG2page.S b/arch/sparc/lib/NG2page.S
deleted file mode 100644
index 73b6b7c72cbf..000000000000
--- a/arch/sparc/lib/NG2page.S
+++ /dev/null
@@ -1,61 +0,0 @@
1/* NG2page.S: Niagara-2 optimized clear and copy page.
2 *
3 * Copyright (C) 2007 (davem@davemloft.net)
4 */
5
6#include <asm/asi.h>
7#include <asm/page.h>
8#include <asm/visasm.h>
9
10 .text
11 .align 32
12
13 /* This is heavily simplified from the sun4u variants
14 * because Niagara-2 does not have any D-cache aliasing issues.
15 */
16NG2copy_user_page: /* %o0=dest, %o1=src, %o2=vaddr */
17 prefetch [%o1 + 0x00], #one_read
18 prefetch [%o1 + 0x40], #one_read
19 VISEntryHalf
20 set PAGE_SIZE, %g7
21 sub %o0, %o1, %g3
221: stxa %g0, [%o1 + %g3] ASI_BLK_INIT_QUAD_LDD_P
23 subcc %g7, 64, %g7
24 ldda [%o1] ASI_BLK_P, %f0
25 stda %f0, [%o1 + %g3] ASI_BLK_P
26 add %o1, 64, %o1
27 bne,pt %xcc, 1b
28 prefetch [%o1 + 0x40], #one_read
29 membar #Sync
30 VISExitHalf
31 retl
32 nop
33
34#define BRANCH_ALWAYS 0x10680000
35#define NOP 0x01000000
36#define NG_DO_PATCH(OLD, NEW) \
37 sethi %hi(NEW), %g1; \
38 or %g1, %lo(NEW), %g1; \
39 sethi %hi(OLD), %g2; \
40 or %g2, %lo(OLD), %g2; \
41 sub %g1, %g2, %g1; \
42 sethi %hi(BRANCH_ALWAYS), %g3; \
43 sll %g1, 11, %g1; \
44 srl %g1, 11 + 2, %g1; \
45 or %g3, %lo(BRANCH_ALWAYS), %g3; \
46 or %g3, %g1, %g3; \
47 stw %g3, [%g2]; \
48 sethi %hi(NOP), %g3; \
49 or %g3, %lo(NOP), %g3; \
50 stw %g3, [%g2 + 0x4]; \
51 flush %g2;
52
53 .globl niagara2_patch_pageops
54 .type niagara2_patch_pageops,#function
55niagara2_patch_pageops:
56 NG_DO_PATCH(copy_user_page, NG2copy_user_page)
57 NG_DO_PATCH(_clear_page, NGclear_page)
58 NG_DO_PATCH(clear_user_page, NGclear_user_page)
59 retl
60 nop
61 .size niagara2_patch_pageops,.-niagara2_patch_pageops
diff --git a/arch/sparc/lib/NGpage.S b/arch/sparc/lib/NGpage.S
index 428920de05ba..b9e790b9c6b8 100644
--- a/arch/sparc/lib/NGpage.S
+++ b/arch/sparc/lib/NGpage.S
@@ -16,55 +16,91 @@
16 */ 16 */
17 17
18NGcopy_user_page: /* %o0=dest, %o1=src, %o2=vaddr */ 18NGcopy_user_page: /* %o0=dest, %o1=src, %o2=vaddr */
19 prefetch [%o1 + 0x00], #one_read 19 save %sp, -192, %sp
20 mov 8, %g1 20 rd %asi, %g3
21 mov 16, %g2 21 wr %g0, ASI_BLK_INIT_QUAD_LDD_P, %asi
22 mov 24, %g3
23 set PAGE_SIZE, %g7 22 set PAGE_SIZE, %g7
23 prefetch [%i1 + 0x00], #one_read
24 prefetch [%i1 + 0x40], #one_read
24 25
251: ldda [%o1 + %g0] ASI_BLK_INIT_QUAD_LDD_P, %o2 261: prefetch [%i1 + 0x80], #one_read
26 ldda [%o1 + %g2] ASI_BLK_INIT_QUAD_LDD_P, %o4 27 prefetch [%i1 + 0xc0], #one_read
27 prefetch [%o1 + 0x40], #one_read 28 ldda [%i1 + 0x00] %asi, %o2
28 add %o1, 32, %o1 29 ldda [%i1 + 0x10] %asi, %o4
29 stxa %o2, [%o0 + %g0] ASI_BLK_INIT_QUAD_LDD_P 30 ldda [%i1 + 0x20] %asi, %l2
30 stxa %o3, [%o0 + %g1] ASI_BLK_INIT_QUAD_LDD_P 31 ldda [%i1 + 0x30] %asi, %l4
31 ldda [%o1 + %g0] ASI_BLK_INIT_QUAD_LDD_P, %o2 32 stxa %o2, [%i0 + 0x00] %asi
32 stxa %o4, [%o0 + %g2] ASI_BLK_INIT_QUAD_LDD_P 33 stxa %o3, [%i0 + 0x08] %asi
33 stxa %o5, [%o0 + %g3] ASI_BLK_INIT_QUAD_LDD_P 34 stxa %o4, [%i0 + 0x10] %asi
34 ldda [%o1 + %g2] ASI_BLK_INIT_QUAD_LDD_P, %o4 35 stxa %o5, [%i0 + 0x18] %asi
35 add %o1, 32, %o1 36 stxa %l2, [%i0 + 0x20] %asi
36 add %o0, 32, %o0 37 stxa %l3, [%i0 + 0x28] %asi
37 stxa %o2, [%o0 + %g0] ASI_BLK_INIT_QUAD_LDD_P 38 stxa %l4, [%i0 + 0x30] %asi
38 stxa %o3, [%o0 + %g1] ASI_BLK_INIT_QUAD_LDD_P 39 stxa %l5, [%i0 + 0x38] %asi
39 stxa %o4, [%o0 + %g2] ASI_BLK_INIT_QUAD_LDD_P 40 ldda [%i1 + 0x40] %asi, %o2
40 stxa %o5, [%o0 + %g3] ASI_BLK_INIT_QUAD_LDD_P 41 ldda [%i1 + 0x50] %asi, %o4
41 subcc %g7, 64, %g7 42 ldda [%i1 + 0x60] %asi, %l2
43 ldda [%i1 + 0x70] %asi, %l4
44 stxa %o2, [%i0 + 0x40] %asi
45 stxa %o3, [%i0 + 0x48] %asi
46 stxa %o4, [%i0 + 0x50] %asi
47 stxa %o5, [%i0 + 0x58] %asi
48 stxa %l2, [%i0 + 0x60] %asi
49 stxa %l3, [%i0 + 0x68] %asi
50 stxa %l4, [%i0 + 0x70] %asi
51 stxa %l5, [%i0 + 0x78] %asi
52 add %i1, 128, %i1
53 subcc %g7, 128, %g7
42 bne,pt %xcc, 1b 54 bne,pt %xcc, 1b
43 add %o0, 32, %o0 55 add %i0, 128, %i0
56 wr %g3, 0x0, %asi
44 membar #Sync 57 membar #Sync
45 retl 58 ret
46 nop 59 restore
47 60
48 .globl NGclear_page, NGclear_user_page 61 .align 32
49NGclear_page: /* %o0=dest */ 62NGclear_page: /* %o0=dest */
50NGclear_user_page: /* %o0=dest, %o1=vaddr */ 63NGclear_user_page: /* %o0=dest, %o1=vaddr */
51 mov 8, %g1 64 rd %asi, %g3
52 mov 16, %g2 65 wr %g0, ASI_BLK_INIT_QUAD_LDD_P, %asi
53 mov 24, %g3
54 set PAGE_SIZE, %g7 66 set PAGE_SIZE, %g7
55 67
561: stxa %g0, [%o0 + %g0] ASI_BLK_INIT_QUAD_LDD_P 681: stxa %g0, [%o0 + 0x00] %asi
57 stxa %g0, [%o0 + %g1] ASI_BLK_INIT_QUAD_LDD_P 69 stxa %g0, [%o0 + 0x08] %asi
58 stxa %g0, [%o0 + %g2] ASI_BLK_INIT_QUAD_LDD_P 70 stxa %g0, [%o0 + 0x10] %asi
59 stxa %g0, [%o0 + %g3] ASI_BLK_INIT_QUAD_LDD_P 71 stxa %g0, [%o0 + 0x18] %asi
60 add %o0, 32, %o0 72 stxa %g0, [%o0 + 0x20] %asi
61 stxa %g0, [%o0 + %g0] ASI_BLK_INIT_QUAD_LDD_P 73 stxa %g0, [%o0 + 0x28] %asi
62 stxa %g0, [%o0 + %g1] ASI_BLK_INIT_QUAD_LDD_P 74 stxa %g0, [%o0 + 0x30] %asi
63 stxa %g0, [%o0 + %g2] ASI_BLK_INIT_QUAD_LDD_P 75 stxa %g0, [%o0 + 0x38] %asi
64 stxa %g0, [%o0 + %g3] ASI_BLK_INIT_QUAD_LDD_P 76 stxa %g0, [%o0 + 0x40] %asi
65 subcc %g7, 64, %g7 77 stxa %g0, [%o0 + 0x48] %asi
78 stxa %g0, [%o0 + 0x50] %asi
79 stxa %g0, [%o0 + 0x58] %asi
80 stxa %g0, [%o0 + 0x60] %asi
81 stxa %g0, [%o0 + 0x68] %asi
82 stxa %g0, [%o0 + 0x70] %asi
83 stxa %g0, [%o0 + 0x78] %asi
84 stxa %g0, [%o0 + 0x80] %asi
85 stxa %g0, [%o0 + 0x88] %asi
86 stxa %g0, [%o0 + 0x90] %asi
87 stxa %g0, [%o0 + 0x98] %asi
88 stxa %g0, [%o0 + 0xa0] %asi
89 stxa %g0, [%o0 + 0xa8] %asi
90 stxa %g0, [%o0 + 0xb0] %asi
91 stxa %g0, [%o0 + 0xb8] %asi
92 stxa %g0, [%o0 + 0xc0] %asi
93 stxa %g0, [%o0 + 0xc8] %asi
94 stxa %g0, [%o0 + 0xd0] %asi
95 stxa %g0, [%o0 + 0xd8] %asi
96 stxa %g0, [%o0 + 0xe0] %asi
97 stxa %g0, [%o0 + 0xe8] %asi
98 stxa %g0, [%o0 + 0xf0] %asi
99 stxa %g0, [%o0 + 0xf8] %asi
100 subcc %g7, 256, %g7
66 bne,pt %xcc, 1b 101 bne,pt %xcc, 1b
67 add %o0, 32, %o0 102 add %o0, 256, %o0
103 wr %g3, 0x0, %asi
68 membar #Sync 104 membar #Sync
69 retl 105 retl
70 nop 106 nop
diff --git a/arch/sparc/lib/atomic32.c b/arch/sparc/lib/atomic32.c
index d3c7a12ad879..1d32b54089aa 100644
--- a/arch/sparc/lib/atomic32.c
+++ b/arch/sparc/lib/atomic32.c
@@ -7,7 +7,7 @@
7 * Based on asm-parisc/atomic.h Copyright (C) 2000 Philipp Rumpf 7 * Based on asm-parisc/atomic.h Copyright (C) 2000 Philipp Rumpf
8 */ 8 */
9 9
10#include <asm/atomic.h> 10#include <linux/atomic.h>
11#include <linux/spinlock.h> 11#include <linux/spinlock.h>
12#include <linux/module.h> 12#include <linux/module.h>
13 13
@@ -55,7 +55,7 @@ int atomic_cmpxchg(atomic_t *v, int old, int new)
55} 55}
56EXPORT_SYMBOL(atomic_cmpxchg); 56EXPORT_SYMBOL(atomic_cmpxchg);
57 57
58int atomic_add_unless(atomic_t *v, int a, int u) 58int __atomic_add_unless(atomic_t *v, int a, int u)
59{ 59{
60 int ret; 60 int ret;
61 unsigned long flags; 61 unsigned long flags;
@@ -65,9 +65,9 @@ int atomic_add_unless(atomic_t *v, int a, int u)
65 if (ret != u) 65 if (ret != u)
66 v->counter += a; 66 v->counter += a;
67 spin_unlock_irqrestore(ATOMIC_HASH(v), flags); 67 spin_unlock_irqrestore(ATOMIC_HASH(v), flags);
68 return ret != u; 68 return ret;
69} 69}
70EXPORT_SYMBOL(atomic_add_unless); 70EXPORT_SYMBOL(__atomic_add_unless);
71 71
72/* Atomic operations are already serializing */ 72/* Atomic operations are already serializing */
73void atomic_set(atomic_t *v, int i) 73void atomic_set(atomic_t *v, int i)
diff --git a/arch/sparc/lib/ffs.S b/arch/sparc/lib/ffs.S
new file mode 100644
index 000000000000..b39389f69899
--- /dev/null
+++ b/arch/sparc/lib/ffs.S
@@ -0,0 +1,84 @@
1#include <linux/linkage.h>
2
3 .register %g2,#scratch
4
5 .text
6 .align 32
7
8ENTRY(ffs)
9 brnz,pt %o0, 1f
10 mov 1, %o1
11 retl
12 clr %o0
13 nop
14 nop
15ENTRY(__ffs)
16 sllx %o0, 32, %g1 /* 1 */
17 srlx %o0, 32, %g2
18
19 clr %o1 /* 2 */
20 movrz %g1, %g2, %o0
21
22 movrz %g1, 32, %o1 /* 3 */
231: clr %o2
24
25 sllx %o0, (64 - 16), %g1 /* 4 */
26 srlx %o0, 16, %g2
27
28 movrz %g1, %g2, %o0 /* 5 */
29 clr %o3
30
31 movrz %g1, 16, %o2 /* 6 */
32 clr %o4
33
34 and %o0, 0xff, %g1 /* 7 */
35 srlx %o0, 8, %g2
36
37 movrz %g1, %g2, %o0 /* 8 */
38 clr %o5
39
40 movrz %g1, 8, %o3 /* 9 */
41 add %o2, %o1, %o2
42
43 and %o0, 0xf, %g1 /* 10 */
44 srlx %o0, 4, %g2
45
46 movrz %g1, %g2, %o0 /* 11 */
47 add %o2, %o3, %o2
48
49 movrz %g1, 4, %o4 /* 12 */
50
51 and %o0, 0x3, %g1 /* 13 */
52 srlx %o0, 2, %g2
53
54 movrz %g1, %g2, %o0 /* 14 */
55 add %o2, %o4, %o2
56
57 movrz %g1, 2, %o5 /* 15 */
58
59 and %o0, 0x1, %g1 /* 16 */
60
61 add %o2, %o5, %o2 /* 17 */
62 xor %g1, 0x1, %g1
63
64 retl /* 18 */
65 add %o2, %g1, %o0
66ENDPROC(ffs)
67ENDPROC(__ffs)
68
69 .section .popc_6insn_patch, "ax"
70 .word ffs
71 brz,pn %o0, 98f
72 neg %o0, %g1
73 xnor %o0, %g1, %o1
74 popc %o1, %o0
7598: retl
76 nop
77 .word __ffs
78 neg %o0, %g1
79 xnor %o0, %g1, %o1
80 popc %o1, %o0
81 retl
82 sub %o0, 1, %o0
83 nop
84 .previous
diff --git a/arch/sparc/lib/hweight.S b/arch/sparc/lib/hweight.S
new file mode 100644
index 000000000000..95414e0a6808
--- /dev/null
+++ b/arch/sparc/lib/hweight.S
@@ -0,0 +1,51 @@
1#include <linux/linkage.h>
2
3 .text
4 .align 32
5ENTRY(__arch_hweight8)
6 ba,pt %xcc, __sw_hweight8
7 nop
8 nop
9ENDPROC(__arch_hweight8)
10 .section .popc_3insn_patch, "ax"
11 .word __arch_hweight8
12 sllx %o0, 64-8, %g1
13 retl
14 popc %g1, %o0
15 .previous
16
17ENTRY(__arch_hweight16)
18 ba,pt %xcc, __sw_hweight16
19 nop
20 nop
21ENDPROC(__arch_hweight16)
22 .section .popc_3insn_patch, "ax"
23 .word __arch_hweight16
24 sllx %o0, 64-16, %g1
25 retl
26 popc %g1, %o0
27 .previous
28
29ENTRY(__arch_hweight32)
30 ba,pt %xcc, __sw_hweight32
31 nop
32 nop
33ENDPROC(__arch_hweight32)
34 .section .popc_3insn_patch, "ax"
35 .word __arch_hweight32
36 sllx %o0, 64-32, %g1
37 retl
38 popc %g1, %o0
39 .previous
40
41ENTRY(__arch_hweight64)
42 ba,pt %xcc, __sw_hweight64
43 nop
44 nop
45ENDPROC(__arch_hweight64)
46 .section .popc_3insn_patch, "ax"
47 .word __arch_hweight64
48 retl
49 popc %o0, %o0
50 nop
51 .previous
diff --git a/arch/sparc/lib/memcpy.S b/arch/sparc/lib/memcpy.S
index 34fe65751737..4d8c497517bd 100644
--- a/arch/sparc/lib/memcpy.S
+++ b/arch/sparc/lib/memcpy.S
@@ -7,40 +7,12 @@
7 * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz) 7 * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
8 */ 8 */
9 9
10#ifdef __KERNEL__ 10#define FUNC(x) \
11
12#define FUNC(x) \
13 .globl x; \ 11 .globl x; \
14 .type x,@function; \ 12 .type x,@function; \
15 .align 4; \ 13 .align 4; \
16x: 14x:
17 15
18#undef FASTER_REVERSE
19#undef FASTER_NONALIGNED
20#define FASTER_ALIGNED
21
22/* In kernel these functions don't return a value.
23 * One should use macros in asm/string.h for that purpose.
24 * We return 0, so that bugs are more apparent.
25 */
26#define SETUP_RETL
27#define RETL_INSN clr %o0
28
29#else
30
31/* libc */
32
33#include "DEFS.h"
34
35#define FASTER_REVERSE
36#define FASTER_NONALIGNED
37#define FASTER_ALIGNED
38
39#define SETUP_RETL mov %o0, %g6
40#define RETL_INSN mov %g6, %o0
41
42#endif
43
44/* Both these macros have to start with exactly the same insn */ 16/* Both these macros have to start with exactly the same insn */
45#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ 17#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \
46 ldd [%src + (offset) + 0x00], %t0; \ 18 ldd [%src + (offset) + 0x00], %t0; \
@@ -164,30 +136,6 @@ x:
164 .text 136 .text
165 .align 4 137 .align 4
166 138
167#ifdef FASTER_REVERSE
168
16970: /* rdword_align */
170
171 andcc %o1, 1, %g0
172 be 4f
173 andcc %o1, 2, %g0
174
175 ldub [%o1 - 1], %g2
176 sub %o1, 1, %o1
177 stb %g2, [%o0 - 1]
178 sub %o2, 1, %o2
179 be 3f
180 sub %o0, 1, %o0
1814:
182 lduh [%o1 - 2], %g2
183 sub %o1, 2, %o1
184 sth %g2, [%o0 - 2]
185 sub %o2, 2, %o2
186 b 3f
187 sub %o0, 2, %o0
188
189#endif /* FASTER_REVERSE */
190
1910: 1390:
192 retl 140 retl
193 nop ! Only bcopy returns here and it retuns void... 141 nop ! Only bcopy returns here and it retuns void...
@@ -198,7 +146,7 @@ FUNC(__memmove)
198#endif 146#endif
199FUNC(memmove) 147FUNC(memmove)
200 cmp %o0, %o1 148 cmp %o0, %o1
201 SETUP_RETL 149 mov %o0, %g7
202 bleu 9f 150 bleu 9f
203 sub %o0, %o1, %o4 151 sub %o0, %o1, %o4
204 152
@@ -207,8 +155,6 @@ FUNC(memmove)
207 bleu 0f 155 bleu 0f
208 andcc %o4, 3, %o5 156 andcc %o4, 3, %o5
209 157
210#ifndef FASTER_REVERSE
211
212 add %o1, %o2, %o1 158 add %o1, %o2, %o1
213 add %o0, %o2, %o0 159 add %o0, %o2, %o0
214 sub %o1, 1, %o1 160 sub %o1, 1, %o1
@@ -224,295 +170,7 @@ FUNC(memmove)
224 sub %o0, 1, %o0 170 sub %o0, 1, %o0
225 171
226 retl 172 retl
227 RETL_INSN 173 mov %g7, %o0
228
229#else /* FASTER_REVERSE */
230
231 add %o1, %o2, %o1
232 add %o0, %o2, %o0
233 bne 77f
234 cmp %o2, 15
235 bleu 91f
236 andcc %o1, 3, %g0
237 bne 70b
2383:
239 andcc %o1, 4, %g0
240
241 be 2f
242 mov %o2, %g1
243
244 ld [%o1 - 4], %o4
245 sub %g1, 4, %g1
246 st %o4, [%o0 - 4]
247 sub %o1, 4, %o1
248 sub %o0, 4, %o0
2492:
250 andcc %g1, 0xffffff80, %g7
251 be 3f
252 andcc %o0, 4, %g0
253
254 be 74f + 4
2555:
256 RMOVE_BIGCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
257 RMOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
258 RMOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
259 RMOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
260 subcc %g7, 128, %g7
261 sub %o1, 128, %o1
262 bne 5b
263 sub %o0, 128, %o0
2643:
265 andcc %g1, 0x70, %g7
266 be 72f
267 andcc %g1, 8, %g0
268
269 sethi %hi(72f), %o5
270 srl %g7, 1, %o4
271 add %g7, %o4, %o4
272 sub %o1, %g7, %o1
273 sub %o5, %o4, %o5
274 jmpl %o5 + %lo(72f), %g0
275 sub %o0, %g7, %o0
276
27771: /* rmemcpy_table */
278 RMOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g4, g5)
279 RMOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g4, g5)
280 RMOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g4, g5)
281 RMOVE_LASTCHUNK(o1, o0, 0x30, g2, g3, g4, g5)
282 RMOVE_LASTCHUNK(o1, o0, 0x20, g2, g3, g4, g5)
283 RMOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g4, g5)
284 RMOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g4, g5)
285
28672: /* rmemcpy_table_end */
287
288 be 73f
289 andcc %g1, 4, %g0
290
291 ldd [%o1 - 0x08], %g2
292 sub %o0, 8, %o0
293 sub %o1, 8, %o1
294 st %g2, [%o0]
295 st %g3, [%o0 + 0x04]
296
29773: /* rmemcpy_last7 */
298
299 be 1f
300 andcc %g1, 2, %g0
301
302 ld [%o1 - 4], %g2
303 sub %o1, 4, %o1
304 st %g2, [%o0 - 4]
305 sub %o0, 4, %o0
3061:
307 be 1f
308 andcc %g1, 1, %g0
309
310 lduh [%o1 - 2], %g2
311 sub %o1, 2, %o1
312 sth %g2, [%o0 - 2]
313 sub %o0, 2, %o0
3141:
315 be 1f
316 nop
317
318 ldub [%o1 - 1], %g2
319 stb %g2, [%o0 - 1]
3201:
321 retl
322 RETL_INSN
323
32474: /* rldd_std */
325 RMOVE_BIGALIGNCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
326 RMOVE_BIGALIGNCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
327 RMOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
328 RMOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
329 subcc %g7, 128, %g7
330 sub %o1, 128, %o1
331 bne 74b
332 sub %o0, 128, %o0
333
334 andcc %g1, 0x70, %g7
335 be 72b
336 andcc %g1, 8, %g0
337
338 sethi %hi(72b), %o5
339 srl %g7, 1, %o4
340 add %g7, %o4, %o4
341 sub %o1, %g7, %o1
342 sub %o5, %o4, %o5
343 jmpl %o5 + %lo(72b), %g0
344 sub %o0, %g7, %o0
345
34675: /* rshort_end */
347
348 and %o2, 0xe, %o3
3492:
350 sethi %hi(76f), %o5
351 sll %o3, 3, %o4
352 sub %o0, %o3, %o0
353 sub %o5, %o4, %o5
354 sub %o1, %o3, %o1
355 jmpl %o5 + %lo(76f), %g0
356 andcc %o2, 1, %g0
357
358 RMOVE_SHORTCHUNK(o1, o0, 0x0c, g2, g3)
359 RMOVE_SHORTCHUNK(o1, o0, 0x0a, g2, g3)
360 RMOVE_SHORTCHUNK(o1, o0, 0x08, g2, g3)
361 RMOVE_SHORTCHUNK(o1, o0, 0x06, g2, g3)
362 RMOVE_SHORTCHUNK(o1, o0, 0x04, g2, g3)
363 RMOVE_SHORTCHUNK(o1, o0, 0x02, g2, g3)
364 RMOVE_SHORTCHUNK(o1, o0, 0x00, g2, g3)
365
36676: /* rshort_table_end */
367
368 be 1f
369 nop
370 ldub [%o1 - 1], %g2
371 stb %g2, [%o0 - 1]
3721:
373 retl
374 RETL_INSN
375
37691: /* rshort_aligned_end */
377
378 bne 75b
379 andcc %o2, 8, %g0
380
381 be 1f
382 andcc %o2, 4, %g0
383
384 ld [%o1 - 0x08], %g2
385 ld [%o1 - 0x04], %g3
386 sub %o1, 8, %o1
387 st %g2, [%o0 - 0x08]
388 st %g3, [%o0 - 0x04]
389 sub %o0, 8, %o0
3901:
391 b 73b
392 mov %o2, %g1
393
39477: /* rnon_aligned */
395 cmp %o2, 15
396 bleu 75b
397 andcc %o0, 3, %g0
398 be 64f
399 andcc %o0, 1, %g0
400 be 63f
401 andcc %o0, 2, %g0
402 ldub [%o1 - 1], %g5
403 sub %o1, 1, %o1
404 stb %g5, [%o0 - 1]
405 sub %o0, 1, %o0
406 be 64f
407 sub %o2, 1, %o2
40863:
409 ldub [%o1 - 1], %g5
410 sub %o1, 2, %o1
411 stb %g5, [%o0 - 1]
412 sub %o0, 2, %o0
413 ldub [%o1], %g5
414 sub %o2, 2, %o2
415 stb %g5, [%o0]
41664:
417 and %o1, 3, %g2
418 and %o1, -4, %o1
419 and %o2, 0xc, %g3
420 add %o1, 4, %o1
421 cmp %g3, 4
422 sll %g2, 3, %g4
423 mov 32, %g2
424 be 4f
425 sub %g2, %g4, %g7
426
427 blu 3f
428 cmp %g3, 8
429
430 be 2f
431 srl %o2, 2, %g3
432
433 ld [%o1 - 4], %o3
434 add %o0, -8, %o0
435 ld [%o1 - 8], %o4
436 add %o1, -16, %o1
437 b 7f
438 add %g3, 1, %g3
4392:
440 ld [%o1 - 4], %o4
441 add %o0, -4, %o0
442 ld [%o1 - 8], %g1
443 add %o1, -12, %o1
444 b 8f
445 add %g3, 2, %g3
4463:
447 ld [%o1 - 4], %o5
448 add %o0, -12, %o0
449 ld [%o1 - 8], %o3
450 add %o1, -20, %o1
451 b 6f
452 srl %o2, 2, %g3
4534:
454 ld [%o1 - 4], %g1
455 srl %o2, 2, %g3
456 ld [%o1 - 8], %o5
457 add %o1, -24, %o1
458 add %o0, -16, %o0
459 add %g3, -1, %g3
460
461 ld [%o1 + 12], %o3
4625:
463 sll %o5, %g4, %g2
464 srl %g1, %g7, %g5
465 or %g2, %g5, %g2
466 st %g2, [%o0 + 12]
4676:
468 ld [%o1 + 8], %o4
469 sll %o3, %g4, %g2
470 srl %o5, %g7, %g5
471 or %g2, %g5, %g2
472 st %g2, [%o0 + 8]
4737:
474 ld [%o1 + 4], %g1
475 sll %o4, %g4, %g2
476 srl %o3, %g7, %g5
477 or %g2, %g5, %g2
478 st %g2, [%o0 + 4]
4798:
480 ld [%o1], %o5
481 sll %g1, %g4, %g2
482 srl %o4, %g7, %g5
483 addcc %g3, -4, %g3
484 or %g2, %g5, %g2
485 add %o1, -16, %o1
486 st %g2, [%o0]
487 add %o0, -16, %o0
488 bne,a 5b
489 ld [%o1 + 12], %o3
490 sll %o5, %g4, %g2
491 srl %g1, %g7, %g5
492 srl %g4, 3, %g3
493 or %g2, %g5, %g2
494 add %o1, %g3, %o1
495 andcc %o2, 2, %g0
496 st %g2, [%o0 + 12]
497 be 1f
498 andcc %o2, 1, %g0
499
500 ldub [%o1 + 15], %g5
501 add %o1, -2, %o1
502 stb %g5, [%o0 + 11]
503 add %o0, -2, %o0
504 ldub [%o1 + 16], %g5
505 stb %g5, [%o0 + 12]
5061:
507 be 1f
508 nop
509 ldub [%o1 + 15], %g5
510 stb %g5, [%o0 + 11]
5111:
512 retl
513 RETL_INSN
514
515#endif /* FASTER_REVERSE */
516 174
517/* NOTE: This code is executed just for the cases, 175/* NOTE: This code is executed just for the cases,
518 where %src (=%o1) & 3 is != 0. 176 where %src (=%o1) & 3 is != 0.
@@ -546,7 +204,7 @@ FUNC(memmove)
546FUNC(memcpy) /* %o0=dst %o1=src %o2=len */ 204FUNC(memcpy) /* %o0=dst %o1=src %o2=len */
547 205
548 sub %o0, %o1, %o4 206 sub %o0, %o1, %o4
549 SETUP_RETL 207 mov %o0, %g7
5509: 2089:
551 andcc %o4, 3, %o5 209 andcc %o4, 3, %o5
5520: 2100:
@@ -569,7 +227,7 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len */
569 add %o1, 4, %o1 227 add %o1, 4, %o1
570 add %o0, 4, %o0 228 add %o0, 4, %o0
5712: 2292:
572 andcc %g1, 0xffffff80, %g7 230 andcc %g1, 0xffffff80, %g0
573 be 3f 231 be 3f
574 andcc %o0, 4, %g0 232 andcc %o0, 4, %g0
575 233
@@ -579,22 +237,23 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len */
579 MOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5) 237 MOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
580 MOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5) 238 MOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
581 MOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5) 239 MOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
582 subcc %g7, 128, %g7 240 sub %g1, 128, %g1
583 add %o1, 128, %o1 241 add %o1, 128, %o1
584 bne 5b 242 cmp %g1, 128
243 bge 5b
585 add %o0, 128, %o0 244 add %o0, 128, %o0
5863: 2453:
587 andcc %g1, 0x70, %g7 246 andcc %g1, 0x70, %g4
588 be 80f 247 be 80f
589 andcc %g1, 8, %g0 248 andcc %g1, 8, %g0
590 249
591 sethi %hi(80f), %o5 250 sethi %hi(80f), %o5
592 srl %g7, 1, %o4 251 srl %g4, 1, %o4
593 add %g7, %o4, %o4 252 add %g4, %o4, %o4
594 add %o1, %g7, %o1 253 add %o1, %g4, %o1
595 sub %o5, %o4, %o5 254 sub %o5, %o4, %o5
596 jmpl %o5 + %lo(80f), %g0 255 jmpl %o5 + %lo(80f), %g0
597 add %o0, %g7, %o0 256 add %o0, %g4, %o0
598 257
59979: /* memcpy_table */ 25879: /* memcpy_table */
600 259
@@ -641,43 +300,28 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len */
641 stb %g2, [%o0] 300 stb %g2, [%o0]
6421: 3011:
643 retl 302 retl
644 RETL_INSN 303 mov %g7, %o0
645 304
64682: /* ldd_std */ 30582: /* ldd_std */
647 MOVE_BIGALIGNCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5) 306 MOVE_BIGALIGNCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
648 MOVE_BIGALIGNCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5) 307 MOVE_BIGALIGNCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
649 MOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5) 308 MOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
650 MOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5) 309 MOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
651 subcc %g7, 128, %g7 310 subcc %g1, 128, %g1
652 add %o1, 128, %o1 311 add %o1, 128, %o1
653 bne 82b 312 cmp %g1, 128
313 bge 82b
654 add %o0, 128, %o0 314 add %o0, 128, %o0
655 315
656#ifndef FASTER_ALIGNED 316 andcc %g1, 0x70, %g4
657
658 andcc %g1, 0x70, %g7
659 be 80b
660 andcc %g1, 8, %g0
661
662 sethi %hi(80b), %o5
663 srl %g7, 1, %o4
664 add %g7, %o4, %o4
665 add %o1, %g7, %o1
666 sub %o5, %o4, %o5
667 jmpl %o5 + %lo(80b), %g0
668 add %o0, %g7, %o0
669
670#else /* FASTER_ALIGNED */
671
672 andcc %g1, 0x70, %g7
673 be 84f 317 be 84f
674 andcc %g1, 8, %g0 318 andcc %g1, 8, %g0
675 319
676 sethi %hi(84f), %o5 320 sethi %hi(84f), %o5
677 add %o1, %g7, %o1 321 add %o1, %g4, %o1
678 sub %o5, %g7, %o5 322 sub %o5, %g4, %o5
679 jmpl %o5 + %lo(84f), %g0 323 jmpl %o5 + %lo(84f), %g0
680 add %o0, %g7, %o0 324 add %o0, %g4, %o0
681 325
68283: /* amemcpy_table */ 32683: /* amemcpy_table */
683 327
@@ -721,382 +365,132 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len */
721 stb %g2, [%o0] 365 stb %g2, [%o0]
7221: 3661:
723 retl 367 retl
724 RETL_INSN 368 mov %g7, %o0
725
726#endif /* FASTER_ALIGNED */
727 369
72886: /* non_aligned */ 37086: /* non_aligned */
729 cmp %o2, 6 371 cmp %o2, 6
730 bleu 88f 372 bleu 88f
373 nop
731 374
732#ifdef FASTER_NONALIGNED 375 save %sp, -96, %sp
733 376 andcc %i0, 3, %g0
734 cmp %o2, 256
735 bcc 87f
736
737#endif /* FASTER_NONALIGNED */
738
739 andcc %o0, 3, %g0
740 be 61f 377 be 61f
741 andcc %o0, 1, %g0 378 andcc %i0, 1, %g0
742 be 60f 379 be 60f
743 andcc %o0, 2, %g0 380 andcc %i0, 2, %g0
744 381
745 ldub [%o1], %g5 382 ldub [%i1], %g5
746 add %o1, 1, %o1 383 add %i1, 1, %i1
747 stb %g5, [%o0] 384 stb %g5, [%i0]
748 sub %o2, 1, %o2 385 sub %i2, 1, %i2
749 bne 61f 386 bne 61f
750 add %o0, 1, %o0 387 add %i0, 1, %i0
75160: 38860:
752 ldub [%o1], %g3 389 ldub [%i1], %g3
753 add %o1, 2, %o1 390 add %i1, 2, %i1
754 stb %g3, [%o0] 391 stb %g3, [%i0]
755 sub %o2, 2, %o2 392 sub %i2, 2, %i2
756 ldub [%o1 - 1], %g3 393 ldub [%i1 - 1], %g3
757 add %o0, 2, %o0 394 add %i0, 2, %i0
758 stb %g3, [%o0 - 1] 395 stb %g3, [%i0 - 1]
75961: 39661:
760 and %o1, 3, %g2 397 and %i1, 3, %g2
761 and %o2, 0xc, %g3 398 and %i2, 0xc, %g3
762 and %o1, -4, %o1 399 and %i1, -4, %i1
763 cmp %g3, 4 400 cmp %g3, 4
764 sll %g2, 3, %g4 401 sll %g2, 3, %g4
765 mov 32, %g2 402 mov 32, %g2
766 be 4f 403 be 4f
767 sub %g2, %g4, %g7 404 sub %g2, %g4, %l0
768 405
769 blu 3f 406 blu 3f
770 cmp %g3, 0x8 407 cmp %g3, 0x8
771 408
772 be 2f 409 be 2f
773 srl %o2, 2, %g3 410 srl %i2, 2, %g3
774 411
775 ld [%o1], %o3 412 ld [%i1], %i3
776 add %o0, -8, %o0 413 add %i0, -8, %i0
777 ld [%o1 + 4], %o4 414 ld [%i1 + 4], %i4
778 b 8f 415 b 8f
779 add %g3, 1, %g3 416 add %g3, 1, %g3
7802: 4172:
781 ld [%o1], %o4 418 ld [%i1], %i4
782 add %o0, -12, %o0 419 add %i0, -12, %i0
783 ld [%o1 + 4], %o5 420 ld [%i1 + 4], %i5
784 add %g3, 2, %g3 421 add %g3, 2, %g3
785 b 9f 422 b 9f
786 add %o1, -4, %o1 423 add %i1, -4, %i1
7873: 4243:
788 ld [%o1], %g1 425 ld [%i1], %g1
789 add %o0, -4, %o0 426 add %i0, -4, %i0
790 ld [%o1 + 4], %o3 427 ld [%i1 + 4], %i3
791 srl %o2, 2, %g3 428 srl %i2, 2, %g3
792 b 7f 429 b 7f
793 add %o1, 4, %o1 430 add %i1, 4, %i1
7944: 4314:
795 ld [%o1], %o5 432 ld [%i1], %i5
796 cmp %o2, 7 433 cmp %i2, 7
797 ld [%o1 + 4], %g1 434 ld [%i1 + 4], %g1
798 srl %o2, 2, %g3 435 srl %i2, 2, %g3
799 bleu 10f 436 bleu 10f
800 add %o1, 8, %o1 437 add %i1, 8, %i1
801 438
802 ld [%o1], %o3 439 ld [%i1], %i3
803 add %g3, -1, %g3 440 add %g3, -1, %g3
8045: 4415:
805 sll %o5, %g4, %g2 442 sll %i5, %g4, %g2
806 srl %g1, %g7, %g5 443 srl %g1, %l0, %g5
807 or %g2, %g5, %g2 444 or %g2, %g5, %g2
808 st %g2, [%o0] 445 st %g2, [%i0]
8097: 4467:
810 ld [%o1 + 4], %o4 447 ld [%i1 + 4], %i4
811 sll %g1, %g4, %g2 448 sll %g1, %g4, %g2
812 srl %o3, %g7, %g5 449 srl %i3, %l0, %g5
813 or %g2, %g5, %g2 450 or %g2, %g5, %g2
814 st %g2, [%o0 + 4] 451 st %g2, [%i0 + 4]
8158: 4528:
816 ld [%o1 + 8], %o5 453 ld [%i1 + 8], %i5
817 sll %o3, %g4, %g2 454 sll %i3, %g4, %g2
818 srl %o4, %g7, %g5 455 srl %i4, %l0, %g5
819 or %g2, %g5, %g2 456 or %g2, %g5, %g2
820 st %g2, [%o0 + 8] 457 st %g2, [%i0 + 8]
8219: 4589:
822 ld [%o1 + 12], %g1 459 ld [%i1 + 12], %g1
823 sll %o4, %g4, %g2 460 sll %i4, %g4, %g2
824 srl %o5, %g7, %g5 461 srl %i5, %l0, %g5
825 addcc %g3, -4, %g3 462 addcc %g3, -4, %g3
826 or %g2, %g5, %g2 463 or %g2, %g5, %g2
827 add %o1, 16, %o1 464 add %i1, 16, %i1
828 st %g2, [%o0 + 12] 465 st %g2, [%i0 + 12]
829 add %o0, 16, %o0 466 add %i0, 16, %i0
830 bne,a 5b 467 bne,a 5b
831 ld [%o1], %o3 468 ld [%i1], %i3
83210: 46910:
833 sll %o5, %g4, %g2 470 sll %i5, %g4, %g2
834 srl %g1, %g7, %g5 471 srl %g1, %l0, %g5
835 srl %g7, 3, %g3 472 srl %l0, 3, %g3
836 or %g2, %g5, %g2 473 or %g2, %g5, %g2
837 sub %o1, %g3, %o1 474 sub %i1, %g3, %i1
838 andcc %o2, 2, %g0 475 andcc %i2, 2, %g0
839 st %g2, [%o0] 476 st %g2, [%i0]
840 be 1f 477 be 1f
841 andcc %o2, 1, %g0 478 andcc %i2, 1, %g0
842 479
843 ldub [%o1], %g2 480 ldub [%i1], %g2
844 add %o1, 2, %o1 481 add %i1, 2, %i1
845 stb %g2, [%o0 + 4] 482 stb %g2, [%i0 + 4]
846 add %o0, 2, %o0 483 add %i0, 2, %i0
847 ldub [%o1 - 1], %g2 484 ldub [%i1 - 1], %g2
848 stb %g2, [%o0 + 3] 485 stb %g2, [%i0 + 3]
8491: 4861:
850 be 1f 487 be 1f
851 nop 488 nop
852 ldub [%o1], %g2 489 ldub [%i1], %g2
853 stb %g2, [%o0 + 4] 490 stb %g2, [%i0 + 4]
8541:
855 retl
856 RETL_INSN
857
858#ifdef FASTER_NONALIGNED
859
86087: /* faster_nonaligned */
861
862 andcc %o1, 3, %g0
863 be 3f
864 andcc %o1, 1, %g0
865
866 be 4f
867 andcc %o1, 2, %g0
868
869 ldub [%o1], %g2
870 add %o1, 1, %o1
871 stb %g2, [%o0]
872 sub %o2, 1, %o2
873 bne 3f
874 add %o0, 1, %o0
8754:
876 lduh [%o1], %g2
877 add %o1, 2, %o1
878 srl %g2, 8, %g3
879 sub %o2, 2, %o2
880 stb %g3, [%o0]
881 add %o0, 2, %o0
882 stb %g2, [%o0 - 1]
8833:
884 andcc %o1, 4, %g0
885
886 bne 2f
887 cmp %o5, 1
888
889 ld [%o1], %o4
890 srl %o4, 24, %g2
891 stb %g2, [%o0]
892 srl %o4, 16, %g3
893 stb %g3, [%o0 + 1]
894 srl %o4, 8, %g2
895 stb %g2, [%o0 + 2]
896 sub %o2, 4, %o2
897 stb %o4, [%o0 + 3]
898 add %o1, 4, %o1
899 add %o0, 4, %o0
9002:
901 be 33f
902 cmp %o5, 2
903 be 32f
904 sub %o2, 4, %o2
90531:
906 ld [%o1], %g2
907 add %o1, 4, %o1
908 srl %g2, 24, %g3
909 and %o0, 7, %g5
910 stb %g3, [%o0]
911 cmp %g5, 7
912 sll %g2, 8, %g1
913 add %o0, 4, %o0
914 be 41f
915 and %o2, 0xffffffc0, %o3
916 ld [%o0 - 7], %o4
9174:
918 SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
919 SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
920 SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
921 SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
922 subcc %o3, 64, %o3
923 add %o1, 64, %o1
924 bne 4b
925 add %o0, 64, %o0
926
927 andcc %o2, 0x30, %o3
928 be,a 1f
929 srl %g1, 16, %g2
9304:
931 SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
932 subcc %o3, 16, %o3
933 add %o1, 16, %o1
934 bne 4b
935 add %o0, 16, %o0
936
937 srl %g1, 16, %g2
9381:
939 st %o4, [%o0 - 7]
940 sth %g2, [%o0 - 3]
941 srl %g1, 8, %g4
942 b 88f
943 stb %g4, [%o0 - 1]
94432:
945 ld [%o1], %g2
946 add %o1, 4, %o1
947 srl %g2, 16, %g3
948 and %o0, 7, %g5
949 sth %g3, [%o0]
950 cmp %g5, 6
951 sll %g2, 16, %g1
952 add %o0, 4, %o0
953 be 42f
954 and %o2, 0xffffffc0, %o3
955 ld [%o0 - 6], %o4
9564:
957 SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
958 SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
959 SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
960 SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
961 subcc %o3, 64, %o3
962 add %o1, 64, %o1
963 bne 4b
964 add %o0, 64, %o0
965
966 andcc %o2, 0x30, %o3
967 be,a 1f
968 srl %g1, 16, %g2
9694:
970 SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
971 subcc %o3, 16, %o3
972 add %o1, 16, %o1
973 bne 4b
974 add %o0, 16, %o0
975
976 srl %g1, 16, %g2
9771:
978 st %o4, [%o0 - 6]
979 b 88f
980 sth %g2, [%o0 - 2]
98133:
982 ld [%o1], %g2
983 sub %o2, 4, %o2
984 srl %g2, 24, %g3
985 and %o0, 7, %g5
986 stb %g3, [%o0]
987 cmp %g5, 5
988 srl %g2, 8, %g4
989 sll %g2, 24, %g1
990 sth %g4, [%o0 + 1]
991 add %o1, 4, %o1
992 be 43f
993 and %o2, 0xffffffc0, %o3
994
995 ld [%o0 - 1], %o4
996 add %o0, 4, %o0
9974:
998 SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
999 SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
1000 SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
1001 SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
1002 subcc %o3, 64, %o3
1003 add %o1, 64, %o1
1004 bne 4b
1005 add %o0, 64, %o0
1006
1007 andcc %o2, 0x30, %o3
1008 be,a 1f
1009 srl %g1, 24, %g2
10104:
1011 SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
1012 subcc %o3, 16, %o3
1013 add %o1, 16, %o1
1014 bne 4b
1015 add %o0, 16, %o0
1016
1017 srl %g1, 24, %g2
10181:
1019 st %o4, [%o0 - 5]
1020 b 88f
1021 stb %g2, [%o0 - 1]
102241:
1023 SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
1024 SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
1025 SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
1026 SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
1027 subcc %o3, 64, %o3
1028 add %o1, 64, %o1
1029 bne 41b
1030 add %o0, 64, %o0
1031
1032 andcc %o2, 0x30, %o3
1033 be,a 1f
1034 srl %g1, 16, %g2
10354:
1036 SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
1037 subcc %o3, 16, %o3
1038 add %o1, 16, %o1
1039 bne 4b
1040 add %o0, 16, %o0
1041
1042 srl %g1, 16, %g2
10431: 4911:
1044 sth %g2, [%o0 - 3] 492 ret
1045 srl %g1, 8, %g4 493 restore %g7, %g0, %o0
1046 b 88f
1047 stb %g4, [%o0 - 1]
104843:
1049 SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
1050 SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
1051 SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
1052 SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
1053 subcc %o3, 64, %o3
1054 add %o1, 64, %o1
1055 bne 43b
1056 add %o0, 64, %o0
1057
1058 andcc %o2, 0x30, %o3
1059 be,a 1f
1060 srl %g1, 24, %g2
10614:
1062 SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
1063 subcc %o3, 16, %o3
1064 add %o1, 16, %o1
1065 bne 4b
1066 add %o0, 16, %o0
1067
1068 srl %g1, 24, %g2
10691:
1070 stb %g2, [%o0 + 3]
1071 b 88f
1072 add %o0, 4, %o0
107342:
1074 SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
1075 SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
1076 SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
1077 SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
1078 subcc %o3, 64, %o3
1079 add %o1, 64, %o1
1080 bne 42b
1081 add %o0, 64, %o0
1082
1083 andcc %o2, 0x30, %o3
1084 be,a 1f
1085 srl %g1, 16, %g2
10864:
1087 SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
1088 subcc %o3, 16, %o3
1089 add %o1, 16, %o1
1090 bne 4b
1091 add %o0, 16, %o0
1092
1093 srl %g1, 16, %g2
10941:
1095 sth %g2, [%o0 - 2]
1096
1097 /* Fall through */
1098
1099#endif /* FASTER_NONALIGNED */
1100 494
110188: /* short_end */ 49588: /* short_end */
1102 496
@@ -1127,7 +521,7 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len */
1127 stb %g2, [%o0] 521 stb %g2, [%o0]
11281: 5221:
1129 retl 523 retl
1130 RETL_INSN 524 mov %g7, %o0
1131 525
113290: /* short_aligned_end */ 52690: /* short_aligned_end */
1133 bne 88b 527 bne 88b
diff --git a/arch/sparc/math-emu/math_32.c b/arch/sparc/math-emu/math_32.c
index a3fccde894ec..aa4d55b0bdf0 100644
--- a/arch/sparc/math-emu/math_32.c
+++ b/arch/sparc/math-emu/math_32.c
@@ -164,7 +164,7 @@ int do_mathemu(struct pt_regs *regs, struct task_struct *fpt)
164 int retcode = 0; /* assume all succeed */ 164 int retcode = 0; /* assume all succeed */
165 unsigned long insn; 165 unsigned long insn;
166 166
167 perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, 0); 167 perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
168 168
169#ifdef DEBUG_MATHEMU 169#ifdef DEBUG_MATHEMU
170 printk("In do_mathemu()... pc is %08lx\n", regs->pc); 170 printk("In do_mathemu()... pc is %08lx\n", regs->pc);
diff --git a/arch/sparc/math-emu/math_64.c b/arch/sparc/math-emu/math_64.c
index 56d2c44747b8..e575bd2fe381 100644
--- a/arch/sparc/math-emu/math_64.c
+++ b/arch/sparc/math-emu/math_64.c
@@ -184,7 +184,7 @@ int do_mathemu(struct pt_regs *regs, struct fpustate *f)
184 184
185 if (tstate & TSTATE_PRIV) 185 if (tstate & TSTATE_PRIV)
186 die_if_kernel("unfinished/unimplemented FPop from kernel", regs); 186 die_if_kernel("unfinished/unimplemented FPop from kernel", regs);
187 perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, 0); 187 perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
188 if (test_thread_flag(TIF_32BIT)) 188 if (test_thread_flag(TIF_32BIT))
189 pc = (u32)pc; 189 pc = (u32)pc;
190 if (get_user(insn, (u32 __user *) pc) != -EFAULT) { 190 if (get_user(insn, (u32 __user *) pc) != -EFAULT) {
diff --git a/arch/sparc/mm/Makefile b/arch/sparc/mm/Makefile
index 79836a7dd00c..301421c11291 100644
--- a/arch/sparc/mm/Makefile
+++ b/arch/sparc/mm/Makefile
@@ -4,11 +4,10 @@
4asflags-y := -ansi 4asflags-y := -ansi
5ccflags-y := -Werror 5ccflags-y := -Werror
6 6
7obj-$(CONFIG_SPARC64) += ultra.o tlb.o tsb.o 7obj-$(CONFIG_SPARC64) += ultra.o tlb.o tsb.o gup.o
8obj-y += fault_$(BITS).o 8obj-y += fault_$(BITS).o
9obj-y += init_$(BITS).o 9obj-y += init_$(BITS).o
10obj-$(CONFIG_SPARC32) += loadmmu.o 10obj-$(CONFIG_SPARC32) += loadmmu.o
11obj-y += generic_$(BITS).o
12obj-$(CONFIG_SPARC32) += extable.o btfixup.o srmmu.o iommu.o io-unit.o 11obj-$(CONFIG_SPARC32) += extable.o btfixup.o srmmu.o iommu.o io-unit.o
13obj-$(CONFIG_SPARC32) += hypersparc.o viking.o tsunami.o swift.o 12obj-$(CONFIG_SPARC32) += hypersparc.o viking.o tsunami.o swift.o
14obj-$(CONFIG_SPARC_LEON)+= leon_mm.o 13obj-$(CONFIG_SPARC_LEON)+= leon_mm.o
diff --git a/arch/sparc/mm/fault_32.c b/arch/sparc/mm/fault_32.c
index 7543ddbdadb2..8023fd7e77b5 100644
--- a/arch/sparc/mm/fault_32.c
+++ b/arch/sparc/mm/fault_32.c
@@ -20,7 +20,6 @@
20#include <linux/smp.h> 20#include <linux/smp.h>
21#include <linux/perf_event.h> 21#include <linux/perf_event.h>
22#include <linux/interrupt.h> 22#include <linux/interrupt.h>
23#include <linux/module.h>
24#include <linux/kdebug.h> 23#include <linux/kdebug.h>
25 24
26#include <asm/system.h> 25#include <asm/system.h>
@@ -251,7 +250,7 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
251 if (in_atomic() || !mm) 250 if (in_atomic() || !mm)
252 goto no_context; 251 goto no_context;
253 252
254 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address); 253 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
255 254
256 down_read(&mm->mmap_sem); 255 down_read(&mm->mmap_sem);
257 256
@@ -301,12 +300,10 @@ good_area:
301 } 300 }
302 if (fault & VM_FAULT_MAJOR) { 301 if (fault & VM_FAULT_MAJOR) {
303 current->maj_flt++; 302 current->maj_flt++;
304 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0, 303 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, regs, address);
305 regs, address);
306 } else { 304 } else {
307 current->min_flt++; 305 current->min_flt++;
308 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0, 306 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, regs, address);
309 regs, address);
310 } 307 }
311 up_read(&mm->mmap_sem); 308 up_read(&mm->mmap_sem);
312 return; 309 return;
diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c
index f92ce56a8b22..504c0622f729 100644
--- a/arch/sparc/mm/fault_64.c
+++ b/arch/sparc/mm/fault_64.c
@@ -325,7 +325,7 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
325 if (in_atomic() || !mm) 325 if (in_atomic() || !mm)
326 goto intr_or_no_mm; 326 goto intr_or_no_mm;
327 327
328 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address); 328 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
329 329
330 if (!down_read_trylock(&mm->mmap_sem)) { 330 if (!down_read_trylock(&mm->mmap_sem)) {
331 if ((regs->tstate & TSTATE_PRIV) && 331 if ((regs->tstate & TSTATE_PRIV) &&
@@ -433,12 +433,10 @@ good_area:
433 } 433 }
434 if (fault & VM_FAULT_MAJOR) { 434 if (fault & VM_FAULT_MAJOR) {
435 current->maj_flt++; 435 current->maj_flt++;
436 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0, 436 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, regs, address);
437 regs, address);
438 } else { 437 } else {
439 current->min_flt++; 438 current->min_flt++;
440 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0, 439 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, regs, address);
441 regs, address);
442 } 440 }
443 up_read(&mm->mmap_sem); 441 up_read(&mm->mmap_sem);
444 442
diff --git a/arch/sparc/mm/generic_32.c b/arch/sparc/mm/generic_32.c
deleted file mode 100644
index e6067b75f11c..000000000000
--- a/arch/sparc/mm/generic_32.c
+++ /dev/null
@@ -1,98 +0,0 @@
1/*
2 * generic.c: Generic Sparc mm routines that are not dependent upon
3 * MMU type but are Sparc specific.
4 *
5 * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
6 */
7
8#include <linux/kernel.h>
9#include <linux/mm.h>
10#include <linux/swap.h>
11#include <linux/pagemap.h>
12
13#include <asm/pgalloc.h>
14#include <asm/pgtable.h>
15#include <asm/page.h>
16#include <asm/cacheflush.h>
17#include <asm/tlbflush.h>
18
19/* Remap IO memory, the same way as remap_pfn_range(), but use
20 * the obio memory space.
21 *
22 * They use a pgprot that sets PAGE_IO and does not check the
23 * mem_map table as this is independent of normal memory.
24 */
25static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte, unsigned long address, unsigned long size,
26 unsigned long offset, pgprot_t prot, int space)
27{
28 unsigned long end;
29
30 address &= ~PMD_MASK;
31 end = address + size;
32 if (end > PMD_SIZE)
33 end = PMD_SIZE;
34 do {
35 set_pte_at(mm, address, pte, mk_pte_io(offset, prot, space));
36 address += PAGE_SIZE;
37 offset += PAGE_SIZE;
38 pte++;
39 } while (address < end);
40}
41
42static inline int io_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
43 unsigned long offset, pgprot_t prot, int space)
44{
45 unsigned long end;
46
47 address &= ~PGDIR_MASK;
48 end = address + size;
49 if (end > PGDIR_SIZE)
50 end = PGDIR_SIZE;
51 offset -= address;
52 do {
53 pte_t *pte = pte_alloc_map(mm, NULL, pmd, address);
54 if (!pte)
55 return -ENOMEM;
56 io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space);
57 address = (address + PMD_SIZE) & PMD_MASK;
58 pmd++;
59 } while (address < end);
60 return 0;
61}
62
63int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
64 unsigned long pfn, unsigned long size, pgprot_t prot)
65{
66 int error = 0;
67 pgd_t * dir;
68 unsigned long beg = from;
69 unsigned long end = from + size;
70 struct mm_struct *mm = vma->vm_mm;
71 int space = GET_IOSPACE(pfn);
72 unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT;
73
74 /* See comment in mm/memory.c remap_pfn_range */
75 vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP;
76 vma->vm_pgoff = (offset >> PAGE_SHIFT) |
77 ((unsigned long)space << 28UL);
78
79 offset -= from;
80 dir = pgd_offset(mm, from);
81 flush_cache_range(vma, beg, end);
82
83 while (from < end) {
84 pmd_t *pmd = pmd_alloc(mm, dir, from);
85 error = -ENOMEM;
86 if (!pmd)
87 break;
88 error = io_remap_pmd_range(mm, pmd, from, end - from, offset + from, prot, space);
89 if (error)
90 break;
91 from = (from + PGDIR_SIZE) & PGDIR_MASK;
92 dir++;
93 }
94
95 flush_tlb_range(vma, beg, end);
96 return error;
97}
98EXPORT_SYMBOL(io_remap_pfn_range);
diff --git a/arch/sparc/mm/generic_64.c b/arch/sparc/mm/generic_64.c
deleted file mode 100644
index 3cb00dfd4bd6..000000000000
--- a/arch/sparc/mm/generic_64.c
+++ /dev/null
@@ -1,164 +0,0 @@
1/*
2 * generic.c: Generic Sparc mm routines that are not dependent upon
3 * MMU type but are Sparc specific.
4 *
5 * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
6 */
7
8#include <linux/kernel.h>
9#include <linux/mm.h>
10#include <linux/swap.h>
11#include <linux/pagemap.h>
12
13#include <asm/pgalloc.h>
14#include <asm/pgtable.h>
15#include <asm/page.h>
16#include <asm/tlbflush.h>
17
18/* Remap IO memory, the same way as remap_pfn_range(), but use
19 * the obio memory space.
20 *
21 * They use a pgprot that sets PAGE_IO and does not check the
22 * mem_map table as this is independent of normal memory.
23 */
24static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte,
25 unsigned long address,
26 unsigned long size,
27 unsigned long offset, pgprot_t prot,
28 int space)
29{
30 unsigned long end;
31
32 /* clear hack bit that was used as a write_combine side-effect flag */
33 offset &= ~0x1UL;
34 address &= ~PMD_MASK;
35 end = address + size;
36 if (end > PMD_SIZE)
37 end = PMD_SIZE;
38 do {
39 pte_t entry;
40 unsigned long curend = address + PAGE_SIZE;
41
42 entry = mk_pte_io(offset, prot, space, PAGE_SIZE);
43 if (!(address & 0xffff)) {
44 if (PAGE_SIZE < (4 * 1024 * 1024) &&
45 !(address & 0x3fffff) &&
46 !(offset & 0x3ffffe) &&
47 end >= address + 0x400000) {
48 entry = mk_pte_io(offset, prot, space,
49 4 * 1024 * 1024);
50 curend = address + 0x400000;
51 offset += 0x400000;
52 } else if (PAGE_SIZE < (512 * 1024) &&
53 !(address & 0x7ffff) &&
54 !(offset & 0x7fffe) &&
55 end >= address + 0x80000) {
56 entry = mk_pte_io(offset, prot, space,
57 512 * 1024 * 1024);
58 curend = address + 0x80000;
59 offset += 0x80000;
60 } else if (PAGE_SIZE < (64 * 1024) &&
61 !(offset & 0xfffe) &&
62 end >= address + 0x10000) {
63 entry = mk_pte_io(offset, prot, space,
64 64 * 1024);
65 curend = address + 0x10000;
66 offset += 0x10000;
67 } else
68 offset += PAGE_SIZE;
69 } else
70 offset += PAGE_SIZE;
71
72 if (pte_write(entry))
73 entry = pte_mkdirty(entry);
74 do {
75 BUG_ON(!pte_none(*pte));
76 set_pte_at(mm, address, pte, entry);
77 address += PAGE_SIZE;
78 pte_val(entry) += PAGE_SIZE;
79 pte++;
80 } while (address < curend);
81 } while (address < end);
82}
83
84static inline int io_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
85 unsigned long offset, pgprot_t prot, int space)
86{
87 unsigned long end;
88
89 address &= ~PGDIR_MASK;
90 end = address + size;
91 if (end > PGDIR_SIZE)
92 end = PGDIR_SIZE;
93 offset -= address;
94 do {
95 pte_t *pte = pte_alloc_map(mm, NULL, pmd, address);
96 if (!pte)
97 return -ENOMEM;
98 io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space);
99 pte_unmap(pte);
100 address = (address + PMD_SIZE) & PMD_MASK;
101 pmd++;
102 } while (address < end);
103 return 0;
104}
105
106static inline int io_remap_pud_range(struct mm_struct *mm, pud_t * pud, unsigned long address, unsigned long size,
107 unsigned long offset, pgprot_t prot, int space)
108{
109 unsigned long end;
110
111 address &= ~PUD_MASK;
112 end = address + size;
113 if (end > PUD_SIZE)
114 end = PUD_SIZE;
115 offset -= address;
116 do {
117 pmd_t *pmd = pmd_alloc(mm, pud, address);
118 if (!pud)
119 return -ENOMEM;
120 io_remap_pmd_range(mm, pmd, address, end - address, address + offset, prot, space);
121 address = (address + PUD_SIZE) & PUD_MASK;
122 pud++;
123 } while (address < end);
124 return 0;
125}
126
127int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
128 unsigned long pfn, unsigned long size, pgprot_t prot)
129{
130 int error = 0;
131 pgd_t * dir;
132 unsigned long beg = from;
133 unsigned long end = from + size;
134 struct mm_struct *mm = vma->vm_mm;
135 int space = GET_IOSPACE(pfn);
136 unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT;
137 unsigned long phys_base;
138
139 phys_base = offset | (((unsigned long) space) << 32UL);
140
141 /* See comment in mm/memory.c remap_pfn_range */
142 vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP;
143 vma->vm_pgoff = phys_base >> PAGE_SHIFT;
144
145 offset -= from;
146 dir = pgd_offset(mm, from);
147 flush_cache_range(vma, beg, end);
148
149 while (from < end) {
150 pud_t *pud = pud_alloc(mm, dir, from);
151 error = -ENOMEM;
152 if (!pud)
153 break;
154 error = io_remap_pud_range(mm, pud, from, end - from, offset + from, prot, space);
155 if (error)
156 break;
157 from = (from + PGDIR_SIZE) & PGDIR_MASK;
158 dir++;
159 }
160
161 flush_tlb_range(vma, beg, end);
162 return error;
163}
164EXPORT_SYMBOL(io_remap_pfn_range);
diff --git a/arch/sparc/mm/gup.c b/arch/sparc/mm/gup.c
new file mode 100644
index 000000000000..42c55df3aec3
--- /dev/null
+++ b/arch/sparc/mm/gup.c
@@ -0,0 +1,183 @@
1/*
2 * Lockless get_user_pages_fast for sparc, cribbed from powerpc
3 *
4 * Copyright (C) 2008 Nick Piggin
5 * Copyright (C) 2008 Novell Inc.
6 */
7
8#include <linux/sched.h>
9#include <linux/mm.h>
10#include <linux/vmstat.h>
11#include <linux/pagemap.h>
12#include <linux/rwsem.h>
13#include <asm/pgtable.h>
14
15/*
16 * The performance critical leaf functions are made noinline otherwise gcc
17 * inlines everything into a single function which results in too much
18 * register pressure.
19 */
20static noinline int gup_pte_range(pmd_t pmd, unsigned long addr,
21 unsigned long end, int write, struct page **pages, int *nr)
22{
23 unsigned long mask, result;
24 pte_t *ptep;
25
26 if (tlb_type == hypervisor) {
27 result = _PAGE_PRESENT_4V|_PAGE_P_4V;
28 if (write)
29 result |= _PAGE_WRITE_4V;
30 } else {
31 result = _PAGE_PRESENT_4U|_PAGE_P_4U;
32 if (write)
33 result |= _PAGE_WRITE_4U;
34 }
35 mask = result | _PAGE_SPECIAL;
36
37 ptep = pte_offset_kernel(&pmd, addr);
38 do {
39 struct page *page, *head;
40 pte_t pte = *ptep;
41
42 if ((pte_val(pte) & mask) != result)
43 return 0;
44 VM_BUG_ON(!pfn_valid(pte_pfn(pte)));
45
46 /* The hugepage case is simplified on sparc64 because
47 * we encode the sub-page pfn offsets into the
48 * hugepage PTEs. We could optimize this in the future
49 * use page_cache_add_speculative() for the hugepage case.
50 */
51 page = pte_page(pte);
52 head = compound_head(page);
53 if (!page_cache_get_speculative(head))
54 return 0;
55 if (unlikely(pte_val(pte) != pte_val(*ptep))) {
56 put_page(head);
57 return 0;
58 }
59 if (head != page)
60 get_huge_page_tail(page);
61
62 pages[*nr] = page;
63 (*nr)++;
64 } while (ptep++, addr += PAGE_SIZE, addr != end);
65
66 return 1;
67}
68
69static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end,
70 int write, struct page **pages, int *nr)
71{
72 unsigned long next;
73 pmd_t *pmdp;
74
75 pmdp = pmd_offset(&pud, addr);
76 do {
77 pmd_t pmd = *pmdp;
78
79 next = pmd_addr_end(addr, end);
80 if (pmd_none(pmd))
81 return 0;
82 if (!gup_pte_range(pmd, addr, next, write, pages, nr))
83 return 0;
84 } while (pmdp++, addr = next, addr != end);
85
86 return 1;
87}
88
89static int gup_pud_range(pgd_t pgd, unsigned long addr, unsigned long end,
90 int write, struct page **pages, int *nr)
91{
92 unsigned long next;
93 pud_t *pudp;
94
95 pudp = pud_offset(&pgd, addr);
96 do {
97 pud_t pud = *pudp;
98
99 next = pud_addr_end(addr, end);
100 if (pud_none(pud))
101 return 0;
102 if (!gup_pmd_range(pud, addr, next, write, pages, nr))
103 return 0;
104 } while (pudp++, addr = next, addr != end);
105
106 return 1;
107}
108
109int get_user_pages_fast(unsigned long start, int nr_pages, int write,
110 struct page **pages)
111{
112 struct mm_struct *mm = current->mm;
113 unsigned long addr, len, end;
114 unsigned long next;
115 pgd_t *pgdp;
116 int nr = 0;
117
118 start &= PAGE_MASK;
119 addr = start;
120 len = (unsigned long) nr_pages << PAGE_SHIFT;
121 end = start + len;
122
123 /*
124 * XXX: batch / limit 'nr', to avoid large irq off latency
125 * needs some instrumenting to determine the common sizes used by
126 * important workloads (eg. DB2), and whether limiting the batch size
127 * will decrease performance.
128 *
129 * It seems like we're in the clear for the moment. Direct-IO is
130 * the main guy that batches up lots of get_user_pages, and even
131 * they are limited to 64-at-a-time which is not so many.
132 */
133 /*
134 * This doesn't prevent pagetable teardown, but does prevent
135 * the pagetables from being freed on sparc.
136 *
137 * So long as we atomically load page table pointers versus teardown,
138 * we can follow the address down to the the page and take a ref on it.
139 */
140 local_irq_disable();
141
142 pgdp = pgd_offset(mm, addr);
143 do {
144 pgd_t pgd = *pgdp;
145
146 next = pgd_addr_end(addr, end);
147 if (pgd_none(pgd))
148 goto slow;
149 if (!gup_pud_range(pgd, addr, next, write, pages, &nr))
150 goto slow;
151 } while (pgdp++, addr = next, addr != end);
152
153 local_irq_enable();
154
155 VM_BUG_ON(nr != (end - start) >> PAGE_SHIFT);
156 return nr;
157
158 {
159 int ret;
160
161slow:
162 local_irq_enable();
163
164 /* Try to get the remaining pages with get_user_pages */
165 start += nr << PAGE_SHIFT;
166 pages += nr;
167
168 down_read(&mm->mmap_sem);
169 ret = get_user_pages(current, mm, start,
170 (end - start) >> PAGE_SHIFT, write, 0, pages, NULL);
171 up_read(&mm->mmap_sem);
172
173 /* Have to be a bit careful with return values */
174 if (nr > 0) {
175 if (ret < 0)
176 ret = nr;
177 else
178 ret += nr;
179 }
180
181 return ret;
182 }
183}
diff --git a/arch/sparc/mm/highmem.c b/arch/sparc/mm/highmem.c
index 4730eac0747b..77140a02c86a 100644
--- a/arch/sparc/mm/highmem.c
+++ b/arch/sparc/mm/highmem.c
@@ -24,6 +24,7 @@
24 */ 24 */
25#include <linux/mm.h> 25#include <linux/mm.h>
26#include <linux/highmem.h> 26#include <linux/highmem.h>
27#include <linux/export.h>
27#include <asm/pgalloc.h> 28#include <asm/pgalloc.h>
28#include <asm/cacheflush.h> 29#include <asm/cacheflush.h>
29#include <asm/tlbflush.h> 30#include <asm/tlbflush.h>
diff --git a/arch/sparc/mm/hugetlbpage.c b/arch/sparc/mm/hugetlbpage.c
index f4e97646ce23..07e14535375c 100644
--- a/arch/sparc/mm/hugetlbpage.c
+++ b/arch/sparc/mm/hugetlbpage.c
@@ -5,7 +5,6 @@
5 */ 5 */
6 6
7#include <linux/init.h> 7#include <linux/init.h>
8#include <linux/module.h>
9#include <linux/fs.h> 8#include <linux/fs.h>
10#include <linux/mm.h> 9#include <linux/mm.h>
11#include <linux/hugetlb.h> 10#include <linux/hugetlb.h>
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 8415f614ce0c..8584a25a9f0d 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -511,6 +511,11 @@ static void __init read_obp_translations(void)
511 for (i = 0; i < prom_trans_ents; i++) 511 for (i = 0; i < prom_trans_ents; i++)
512 prom_trans[i].data &= ~0x0003fe0000000000UL; 512 prom_trans[i].data &= ~0x0003fe0000000000UL;
513 } 513 }
514
515 /* Force execute bit on. */
516 for (i = 0; i < prom_trans_ents; i++)
517 prom_trans[i].data |= (tlb_type == hypervisor ?
518 _PAGE_EXEC_4V : _PAGE_EXEC_4U);
514} 519}
515 520
516static void __init hypervisor_tlb_lock(unsigned long vaddr, 521static void __init hypervisor_tlb_lock(unsigned long vaddr,
@@ -1597,6 +1602,44 @@ static void __init tsb_phys_patch(void)
1597static struct hv_tsb_descr ktsb_descr[NUM_KTSB_DESCR]; 1602static struct hv_tsb_descr ktsb_descr[NUM_KTSB_DESCR];
1598extern struct tsb swapper_tsb[KERNEL_TSB_NENTRIES]; 1603extern struct tsb swapper_tsb[KERNEL_TSB_NENTRIES];
1599 1604
1605static void patch_one_ktsb_phys(unsigned int *start, unsigned int *end, unsigned long pa)
1606{
1607 pa >>= KTSB_PHYS_SHIFT;
1608
1609 while (start < end) {
1610 unsigned int *ia = (unsigned int *)(unsigned long)*start;
1611
1612 ia[0] = (ia[0] & ~0x3fffff) | (pa >> 10);
1613 __asm__ __volatile__("flush %0" : : "r" (ia));
1614
1615 ia[1] = (ia[1] & ~0x3ff) | (pa & 0x3ff);
1616 __asm__ __volatile__("flush %0" : : "r" (ia + 1));
1617
1618 start++;
1619 }
1620}
1621
1622static void ktsb_phys_patch(void)
1623{
1624 extern unsigned int __swapper_tsb_phys_patch;
1625 extern unsigned int __swapper_tsb_phys_patch_end;
1626 unsigned long ktsb_pa;
1627
1628 ktsb_pa = kern_base + ((unsigned long)&swapper_tsb[0] - KERNBASE);
1629 patch_one_ktsb_phys(&__swapper_tsb_phys_patch,
1630 &__swapper_tsb_phys_patch_end, ktsb_pa);
1631#ifndef CONFIG_DEBUG_PAGEALLOC
1632 {
1633 extern unsigned int __swapper_4m_tsb_phys_patch;
1634 extern unsigned int __swapper_4m_tsb_phys_patch_end;
1635 ktsb_pa = (kern_base +
1636 ((unsigned long)&swapper_4m_tsb[0] - KERNBASE));
1637 patch_one_ktsb_phys(&__swapper_4m_tsb_phys_patch,
1638 &__swapper_4m_tsb_phys_patch_end, ktsb_pa);
1639 }
1640#endif
1641}
1642
1600static void __init sun4v_ktsb_init(void) 1643static void __init sun4v_ktsb_init(void)
1601{ 1644{
1602 unsigned long ktsb_pa; 1645 unsigned long ktsb_pa;
@@ -1716,8 +1759,10 @@ void __init paging_init(void)
1716 sun4u_pgprot_init(); 1759 sun4u_pgprot_init();
1717 1760
1718 if (tlb_type == cheetah_plus || 1761 if (tlb_type == cheetah_plus ||
1719 tlb_type == hypervisor) 1762 tlb_type == hypervisor) {
1720 tsb_phys_patch(); 1763 tsb_phys_patch();
1764 ktsb_phys_patch();
1765 }
1721 1766
1722 if (tlb_type == hypervisor) { 1767 if (tlb_type == hypervisor) {
1723 sun4v_patch_tlb_handlers(); 1768 sun4v_patch_tlb_handlers();
diff --git a/arch/sparc/mm/leon_mm.c b/arch/sparc/mm/leon_mm.c
index c0e01297e64e..13c2169822a8 100644
--- a/arch/sparc/mm/leon_mm.c
+++ b/arch/sparc/mm/leon_mm.c
@@ -162,7 +162,7 @@ ready:
162 printk(KERN_INFO "swprobe: padde %x\n", paddr_calc); 162 printk(KERN_INFO "swprobe: padde %x\n", paddr_calc);
163 if (paddr) 163 if (paddr)
164 *paddr = paddr_calc; 164 *paddr = paddr_calc;
165 return paddrbase; 165 return pte;
166} 166}
167 167
168void leon_flush_icache_all(void) 168void leon_flush_icache_all(void)
@@ -226,7 +226,7 @@ void leon3_getCacheRegs(struct leon3_cacheregs *regs)
226 * Leon2 and Leon3 differ in their way of telling cache information 226 * Leon2 and Leon3 differ in their way of telling cache information
227 * 227 *
228 */ 228 */
229int leon_flush_needed(void) 229int __init leon_flush_needed(void)
230{ 230{
231 int flush_needed = -1; 231 int flush_needed = -1;
232 unsigned int ssize, sets; 232 unsigned int ssize, sets;
diff --git a/arch/sparc/mm/tsb.c b/arch/sparc/mm/tsb.c
index a5f51b22fcbe..536412d8f416 100644
--- a/arch/sparc/mm/tsb.c
+++ b/arch/sparc/mm/tsb.c
@@ -236,6 +236,8 @@ static void setup_tsb_params(struct mm_struct *mm, unsigned long tsb_idx, unsign
236 } 236 }
237} 237}
238 238
239struct kmem_cache *pgtable_cache __read_mostly;
240
239static struct kmem_cache *tsb_caches[8] __read_mostly; 241static struct kmem_cache *tsb_caches[8] __read_mostly;
240 242
241static const char *tsb_cache_names[8] = { 243static const char *tsb_cache_names[8] = {
@@ -253,6 +255,15 @@ void __init pgtable_cache_init(void)
253{ 255{
254 unsigned long i; 256 unsigned long i;
255 257
258 pgtable_cache = kmem_cache_create("pgtable_cache",
259 PAGE_SIZE, PAGE_SIZE,
260 0,
261 _clear_page);
262 if (!pgtable_cache) {
263 prom_printf("pgtable_cache_init(): Could not create!\n");
264 prom_halt();
265 }
266
256 for (i = 0; i < 8; i++) { 267 for (i = 0; i < 8; i++) {
257 unsigned long size = 8192 << i; 268 unsigned long size = 8192 << i;
258 const char *name = tsb_cache_names[i]; 269 const char *name = tsb_cache_names[i];