diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-15 12:00:19 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-15 12:00:19 -0500 |
commit | 17c330f98383629cfd359ee62b3adde1d2a3ff7c (patch) | |
tree | 876bed8fc7de7d404fae579035a948c46a7f05d4 /arch/sparc | |
parent | 48e902f0a3aea4b6b3a73e9d277b92024a493e6d (diff) | |
parent | 7466bd3caab6bd1d0095de957affbacd02ca58a7 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6:
sparc64: Fix clock event multiplier printf format.
sparc64: Use clock{source,events}_calc_mult_shift().
sparc64: Use free_bootmem_late() in mdesc_lmb_free().
sparc: Add alignment and emulation fault perf events.
sparc64: Add syscall tracepoint support.
sparc: Stop trying to be so fancy and use __builtin_{memcpy,memset}()
sparc: Use __builtin_object_size() to validate the buffer size for copy_from_user()
sparc64: Add some missing __kprobes annotations to kernel fault paths.
sparc64: Use kprobes_built_in() to avoid ifdefs in fault_64.c
sparc: Validate that kprobe address is 4-byte aligned.
sparc64: Don't specify IRQF_SHARED for LDC interrupts.
sparc64: Fix stack debugging IRQ stack regression.
sparc64: Fix overly strict range type matching for PCI devices.
Diffstat (limited to 'arch/sparc')
31 files changed, 154 insertions, 210 deletions
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 33ac1a9ac881..108197ac0d56 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig | |||
@@ -43,6 +43,7 @@ config SPARC64 | |||
43 | select HAVE_SYSCALL_WRAPPERS | 43 | select HAVE_SYSCALL_WRAPPERS |
44 | select HAVE_DYNAMIC_FTRACE | 44 | select HAVE_DYNAMIC_FTRACE |
45 | select HAVE_FTRACE_MCOUNT_RECORD | 45 | select HAVE_FTRACE_MCOUNT_RECORD |
46 | select HAVE_SYSCALL_TRACEPOINTS | ||
46 | select USE_GENERIC_SMP_HELPERS if SMP | 47 | select USE_GENERIC_SMP_HELPERS if SMP |
47 | select RTC_DRV_CMOS | 48 | select RTC_DRV_CMOS |
48 | select RTC_DRV_BQ4802 | 49 | select RTC_DRV_BQ4802 |
diff --git a/arch/sparc/Kconfig.debug b/arch/sparc/Kconfig.debug index 90d5fe223a74..9d3c889718ac 100644 --- a/arch/sparc/Kconfig.debug +++ b/arch/sparc/Kconfig.debug | |||
@@ -33,4 +33,18 @@ config FRAME_POINTER | |||
33 | depends on MCOUNT | 33 | depends on MCOUNT |
34 | default y | 34 | default y |
35 | 35 | ||
36 | config DEBUG_STRICT_USER_COPY_CHECKS | ||
37 | bool "Strict copy size checks" | ||
38 | depends on DEBUG_KERNEL && !TRACE_BRANCH_PROFILING | ||
39 | ---help--- | ||
40 | Enabling this option turns a certain set of sanity checks for user | ||
41 | copy operations into compile time failures. | ||
42 | |||
43 | The copy_from_user() etc checks are there to help test if there | ||
44 | are sufficient security checks on the length argument of | ||
45 | the copy operation, by having gcc prove that the argument is | ||
46 | within bounds. | ||
47 | |||
48 | If unsure, or if you run an older (pre 4.4) gcc, say N. | ||
49 | |||
36 | endmenu | 50 | endmenu |
diff --git a/arch/sparc/include/asm/string_32.h b/arch/sparc/include/asm/string_32.h index 6c5fddb7e6b5..edf196ee4ef8 100644 --- a/arch/sparc/include/asm/string_32.h +++ b/arch/sparc/include/asm/string_32.h | |||
@@ -16,8 +16,6 @@ | |||
16 | #ifdef __KERNEL__ | 16 | #ifdef __KERNEL__ |
17 | 17 | ||
18 | extern void __memmove(void *,const void *,__kernel_size_t); | 18 | extern void __memmove(void *,const void *,__kernel_size_t); |
19 | extern __kernel_size_t __memcpy(void *,const void *,__kernel_size_t); | ||
20 | extern __kernel_size_t __memset(void *,int,__kernel_size_t); | ||
21 | 19 | ||
22 | #ifndef EXPORT_SYMTAB_STROPS | 20 | #ifndef EXPORT_SYMTAB_STROPS |
23 | 21 | ||
@@ -32,82 +30,10 @@ extern __kernel_size_t __memset(void *,int,__kernel_size_t); | |||
32 | }) | 30 | }) |
33 | 31 | ||
34 | #define __HAVE_ARCH_MEMCPY | 32 | #define __HAVE_ARCH_MEMCPY |
35 | 33 | #define memcpy(t, f, n) __builtin_memcpy(t, f, n) | |
36 | static inline void *__constant_memcpy(void *to, const void *from, __kernel_size_t n) | ||
37 | { | ||
38 | extern void __copy_1page(void *, const void *); | ||
39 | |||
40 | if(n <= 32) { | ||
41 | __builtin_memcpy(to, from, n); | ||
42 | } else if (((unsigned int) to & 7) != 0) { | ||
43 | /* Destination is not aligned on the double-word boundary */ | ||
44 | __memcpy(to, from, n); | ||
45 | } else { | ||
46 | switch(n) { | ||
47 | case PAGE_SIZE: | ||
48 | __copy_1page(to, from); | ||
49 | break; | ||
50 | default: | ||
51 | __memcpy(to, from, n); | ||
52 | break; | ||
53 | } | ||
54 | } | ||
55 | return to; | ||
56 | } | ||
57 | |||
58 | static inline void *__nonconstant_memcpy(void *to, const void *from, __kernel_size_t n) | ||
59 | { | ||
60 | __memcpy(to, from, n); | ||
61 | return to; | ||
62 | } | ||
63 | |||
64 | #undef memcpy | ||
65 | #define memcpy(t, f, n) \ | ||
66 | (__builtin_constant_p(n) ? \ | ||
67 | __constant_memcpy((t),(f),(n)) : \ | ||
68 | __nonconstant_memcpy((t),(f),(n))) | ||
69 | 34 | ||
70 | #define __HAVE_ARCH_MEMSET | 35 | #define __HAVE_ARCH_MEMSET |
71 | 36 | #define memset(s, c, count) __builtin_memset(s, c, count) | |
72 | static inline void *__constant_c_and_count_memset(void *s, char c, __kernel_size_t count) | ||
73 | { | ||
74 | extern void bzero_1page(void *); | ||
75 | extern __kernel_size_t __bzero(void *, __kernel_size_t); | ||
76 | |||
77 | if(!c) { | ||
78 | if(count == PAGE_SIZE) | ||
79 | bzero_1page(s); | ||
80 | else | ||
81 | __bzero(s, count); | ||
82 | } else { | ||
83 | __memset(s, c, count); | ||
84 | } | ||
85 | return s; | ||
86 | } | ||
87 | |||
88 | static inline void *__constant_c_memset(void *s, char c, __kernel_size_t count) | ||
89 | { | ||
90 | extern __kernel_size_t __bzero(void *, __kernel_size_t); | ||
91 | |||
92 | if(!c) | ||
93 | __bzero(s, count); | ||
94 | else | ||
95 | __memset(s, c, count); | ||
96 | return s; | ||
97 | } | ||
98 | |||
99 | static inline void *__nonconstant_memset(void *s, char c, __kernel_size_t count) | ||
100 | { | ||
101 | __memset(s, c, count); | ||
102 | return s; | ||
103 | } | ||
104 | |||
105 | #undef memset | ||
106 | #define memset(s, c, count) \ | ||
107 | (__builtin_constant_p(c) ? (__builtin_constant_p(count) ? \ | ||
108 | __constant_c_and_count_memset((s), (c), (count)) : \ | ||
109 | __constant_c_memset((s), (c), (count))) \ | ||
110 | : __nonconstant_memset((s), (c), (count))) | ||
111 | 37 | ||
112 | #define __HAVE_ARCH_MEMSCAN | 38 | #define __HAVE_ARCH_MEMSCAN |
113 | 39 | ||
diff --git a/arch/sparc/include/asm/string_64.h b/arch/sparc/include/asm/string_64.h index 43161f2d17eb..9623bc213158 100644 --- a/arch/sparc/include/asm/string_64.h +++ b/arch/sparc/include/asm/string_64.h | |||
@@ -15,8 +15,6 @@ | |||
15 | 15 | ||
16 | #include <asm/asi.h> | 16 | #include <asm/asi.h> |
17 | 17 | ||
18 | extern void *__memset(void *,int,__kernel_size_t); | ||
19 | |||
20 | #ifndef EXPORT_SYMTAB_STROPS | 18 | #ifndef EXPORT_SYMTAB_STROPS |
21 | 19 | ||
22 | /* First the mem*() things. */ | 20 | /* First the mem*() things. */ |
@@ -24,29 +22,10 @@ extern void *__memset(void *,int,__kernel_size_t); | |||
24 | extern void *memmove(void *, const void *, __kernel_size_t); | 22 | extern void *memmove(void *, const void *, __kernel_size_t); |
25 | 23 | ||
26 | #define __HAVE_ARCH_MEMCPY | 24 | #define __HAVE_ARCH_MEMCPY |
27 | extern void *memcpy(void *, const void *, __kernel_size_t); | 25 | #define memcpy(t, f, n) __builtin_memcpy(t, f, n) |
28 | 26 | ||
29 | #define __HAVE_ARCH_MEMSET | 27 | #define __HAVE_ARCH_MEMSET |
30 | extern void *__builtin_memset(void *,int,__kernel_size_t); | 28 | #define memset(s, c, count) __builtin_memset(s, c, count) |
31 | |||
32 | static inline void *__constant_memset(void *s, int c, __kernel_size_t count) | ||
33 | { | ||
34 | extern __kernel_size_t __bzero(void *, __kernel_size_t); | ||
35 | |||
36 | if (!c) { | ||
37 | __bzero(s, count); | ||
38 | return s; | ||
39 | } else | ||
40 | return __memset(s, c, count); | ||
41 | } | ||
42 | |||
43 | #undef memset | ||
44 | #define memset(s, c, count) \ | ||
45 | ((__builtin_constant_p(count) && (count) <= 32) ? \ | ||
46 | __builtin_memset((s), (c), (count)) : \ | ||
47 | (__builtin_constant_p(c) ? \ | ||
48 | __constant_memset((s), (c), (count)) : \ | ||
49 | __memset((s), (c), (count)))) | ||
50 | 29 | ||
51 | #define __HAVE_ARCH_MEMSCAN | 30 | #define __HAVE_ARCH_MEMSCAN |
52 | 31 | ||
diff --git a/arch/sparc/include/asm/thread_info_64.h b/arch/sparc/include/asm/thread_info_64.h index 1b45a7bbe407..7257ebb8f394 100644 --- a/arch/sparc/include/asm/thread_info_64.h +++ b/arch/sparc/include/asm/thread_info_64.h | |||
@@ -227,6 +227,7 @@ register struct thread_info *current_thread_info_reg asm("g6"); | |||
227 | /* flag bit 8 is available */ | 227 | /* flag bit 8 is available */ |
228 | #define TIF_SECCOMP 9 /* secure computing */ | 228 | #define TIF_SECCOMP 9 /* secure computing */ |
229 | #define TIF_SYSCALL_AUDIT 10 /* syscall auditing active */ | 229 | #define TIF_SYSCALL_AUDIT 10 /* syscall auditing active */ |
230 | #define TIF_SYSCALL_TRACEPOINT 11 /* syscall tracepoint instrumentation */ | ||
230 | /* flag bit 11 is available */ | 231 | /* flag bit 11 is available */ |
231 | /* NOTE: Thread flags >= 12 should be ones we have no interest | 232 | /* NOTE: Thread flags >= 12 should be ones we have no interest |
232 | * in using in assembly, else we can't use the mask as | 233 | * in using in assembly, else we can't use the mask as |
@@ -246,6 +247,7 @@ register struct thread_info *current_thread_info_reg asm("g6"); | |||
246 | #define _TIF_32BIT (1<<TIF_32BIT) | 247 | #define _TIF_32BIT (1<<TIF_32BIT) |
247 | #define _TIF_SECCOMP (1<<TIF_SECCOMP) | 248 | #define _TIF_SECCOMP (1<<TIF_SECCOMP) |
248 | #define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT) | 249 | #define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT) |
250 | #define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT) | ||
249 | #define _TIF_ABI_PENDING (1<<TIF_ABI_PENDING) | 251 | #define _TIF_ABI_PENDING (1<<TIF_ABI_PENDING) |
250 | #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) | 252 | #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) |
251 | #define _TIF_FREEZE (1<<TIF_FREEZE) | 253 | #define _TIF_FREEZE (1<<TIF_FREEZE) |
diff --git a/arch/sparc/include/asm/uaccess_32.h b/arch/sparc/include/asm/uaccess_32.h index 8303ac481034..489d2ba92bcb 100644 --- a/arch/sparc/include/asm/uaccess_32.h +++ b/arch/sparc/include/asm/uaccess_32.h | |||
@@ -260,8 +260,23 @@ static inline unsigned long __copy_to_user(void __user *to, const void *from, un | |||
260 | return __copy_user(to, (__force void __user *) from, n); | 260 | return __copy_user(to, (__force void __user *) from, n); |
261 | } | 261 | } |
262 | 262 | ||
263 | extern void copy_from_user_overflow(void) | ||
264 | #ifdef CONFIG_DEBUG_STRICT_USER_COPY_CHECKS | ||
265 | __compiletime_error("copy_from_user() buffer size is not provably correct") | ||
266 | #else | ||
267 | __compiletime_warning("copy_from_user() buffer size is not provably correct") | ||
268 | #endif | ||
269 | ; | ||
270 | |||
263 | static inline unsigned long copy_from_user(void *to, const void __user *from, unsigned long n) | 271 | static inline unsigned long copy_from_user(void *to, const void __user *from, unsigned long n) |
264 | { | 272 | { |
273 | int sz = __compiletime_object_size(to); | ||
274 | |||
275 | if (unlikely(sz != -1 && sz < n)) { | ||
276 | copy_from_user_overflow(); | ||
277 | return -EFAULT; | ||
278 | } | ||
279 | |||
265 | if (n && __access_ok((unsigned long) from, n)) | 280 | if (n && __access_ok((unsigned long) from, n)) |
266 | return __copy_user((__force void __user *) to, from, n); | 281 | return __copy_user((__force void __user *) to, from, n); |
267 | else | 282 | else |
diff --git a/arch/sparc/include/asm/uaccess_64.h b/arch/sparc/include/asm/uaccess_64.h index 9ea271e19c70..dbc141660994 100644 --- a/arch/sparc/include/asm/uaccess_64.h +++ b/arch/sparc/include/asm/uaccess_64.h | |||
@@ -6,6 +6,7 @@ | |||
6 | */ | 6 | */ |
7 | 7 | ||
8 | #ifdef __KERNEL__ | 8 | #ifdef __KERNEL__ |
9 | #include <linux/errno.h> | ||
9 | #include <linux/compiler.h> | 10 | #include <linux/compiler.h> |
10 | #include <linux/string.h> | 11 | #include <linux/string.h> |
11 | #include <linux/thread_info.h> | 12 | #include <linux/thread_info.h> |
@@ -204,6 +205,14 @@ __asm__ __volatile__( \ | |||
204 | 205 | ||
205 | extern int __get_user_bad(void); | 206 | extern int __get_user_bad(void); |
206 | 207 | ||
208 | extern void copy_from_user_overflow(void) | ||
209 | #ifdef CONFIG_DEBUG_STRICT_USER_COPY_CHECKS | ||
210 | __compiletime_error("copy_from_user() buffer size is not provably correct") | ||
211 | #else | ||
212 | __compiletime_warning("copy_from_user() buffer size is not provably correct") | ||
213 | #endif | ||
214 | ; | ||
215 | |||
207 | extern unsigned long __must_check ___copy_from_user(void *to, | 216 | extern unsigned long __must_check ___copy_from_user(void *to, |
208 | const void __user *from, | 217 | const void __user *from, |
209 | unsigned long size); | 218 | unsigned long size); |
@@ -212,10 +221,16 @@ extern unsigned long copy_from_user_fixup(void *to, const void __user *from, | |||
212 | static inline unsigned long __must_check | 221 | static inline unsigned long __must_check |
213 | copy_from_user(void *to, const void __user *from, unsigned long size) | 222 | copy_from_user(void *to, const void __user *from, unsigned long size) |
214 | { | 223 | { |
215 | unsigned long ret = ___copy_from_user(to, from, size); | 224 | unsigned long ret = (unsigned long) -EFAULT; |
216 | 225 | int sz = __compiletime_object_size(to); | |
217 | if (unlikely(ret)) | 226 | |
218 | ret = copy_from_user_fixup(to, from, size); | 227 | if (likely(sz == -1 || sz >= size)) { |
228 | ret = ___copy_from_user(to, from, size); | ||
229 | if (unlikely(ret)) | ||
230 | ret = copy_from_user_fixup(to, from, size); | ||
231 | } else { | ||
232 | copy_from_user_overflow(); | ||
233 | } | ||
219 | return ret; | 234 | return ret; |
220 | } | 235 | } |
221 | #define __copy_from_user copy_from_user | 236 | #define __copy_from_user copy_from_user |
diff --git a/arch/sparc/include/asm/unistd.h b/arch/sparc/include/asm/unistd.h index d8d25bd97121..cb4b9bfd0d87 100644 --- a/arch/sparc/include/asm/unistd.h +++ b/arch/sparc/include/asm/unistd.h | |||
@@ -398,7 +398,7 @@ | |||
398 | #define __NR_perf_event_open 327 | 398 | #define __NR_perf_event_open 327 |
399 | #define __NR_recvmmsg 328 | 399 | #define __NR_recvmmsg 328 |
400 | 400 | ||
401 | #define NR_SYSCALLS 329 | 401 | #define NR_syscalls 329 |
402 | 402 | ||
403 | #ifdef __32bit_syscall_numbers__ | 403 | #ifdef __32bit_syscall_numbers__ |
404 | /* Sparc 32-bit only has the "setresuid32", "getresuid32" variants, | 404 | /* Sparc 32-bit only has the "setresuid32", "getresuid32" variants, |
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index ec9c7bc67d21..1504df8ddf70 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S | |||
@@ -1294,7 +1294,7 @@ linux_sparc_syscall: | |||
1294 | sethi %hi(PSR_SYSCALL), %l4 | 1294 | sethi %hi(PSR_SYSCALL), %l4 |
1295 | or %l0, %l4, %l0 | 1295 | or %l0, %l4, %l0 |
1296 | /* Direct access to user regs, must faster. */ | 1296 | /* Direct access to user regs, must faster. */ |
1297 | cmp %g1, NR_SYSCALLS | 1297 | cmp %g1, NR_syscalls |
1298 | bgeu linux_sparc_ni_syscall | 1298 | bgeu linux_sparc_ni_syscall |
1299 | sll %g1, 2, %l4 | 1299 | sll %g1, 2, %l4 |
1300 | ld [%l7 + %l4], %l7 | 1300 | ld [%l7 + %l4], %l7 |
diff --git a/arch/sparc/kernel/ftrace.c b/arch/sparc/kernel/ftrace.c index d3b1a3076569..29973daa9930 100644 --- a/arch/sparc/kernel/ftrace.c +++ b/arch/sparc/kernel/ftrace.c | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <linux/percpu.h> | 4 | #include <linux/percpu.h> |
5 | #include <linux/init.h> | 5 | #include <linux/init.h> |
6 | #include <linux/list.h> | 6 | #include <linux/list.h> |
7 | #include <trace/syscall.h> | ||
7 | 8 | ||
8 | #include <asm/ftrace.h> | 9 | #include <asm/ftrace.h> |
9 | 10 | ||
@@ -91,3 +92,13 @@ int __init ftrace_dyn_arch_init(void *data) | |||
91 | } | 92 | } |
92 | #endif | 93 | #endif |
93 | 94 | ||
95 | #ifdef CONFIG_FTRACE_SYSCALLS | ||
96 | |||
97 | extern unsigned int sys_call_table[]; | ||
98 | |||
99 | unsigned long __init arch_syscall_addr(int nr) | ||
100 | { | ||
101 | return (unsigned long)sys_call_table[nr]; | ||
102 | } | ||
103 | |||
104 | #endif | ||
diff --git a/arch/sparc/kernel/kprobes.c b/arch/sparc/kernel/kprobes.c index 3bc6527c95af..6716584e48ab 100644 --- a/arch/sparc/kernel/kprobes.c +++ b/arch/sparc/kernel/kprobes.c | |||
@@ -46,6 +46,9 @@ struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}}; | |||
46 | 46 | ||
47 | int __kprobes arch_prepare_kprobe(struct kprobe *p) | 47 | int __kprobes arch_prepare_kprobe(struct kprobe *p) |
48 | { | 48 | { |
49 | if ((unsigned long) p->addr & 0x3UL) | ||
50 | return -EILSEQ; | ||
51 | |||
49 | p->ainsn.insn[0] = *p->addr; | 52 | p->ainsn.insn[0] = *p->addr; |
50 | flushi(&p->ainsn.insn[0]); | 53 | flushi(&p->ainsn.insn[0]); |
51 | 54 | ||
diff --git a/arch/sparc/kernel/ldc.c b/arch/sparc/kernel/ldc.c index cb3c72c45aab..e0ba898e30cf 100644 --- a/arch/sparc/kernel/ldc.c +++ b/arch/sparc/kernel/ldc.c | |||
@@ -1242,13 +1242,13 @@ int ldc_bind(struct ldc_channel *lp, const char *name) | |||
1242 | snprintf(lp->tx_irq_name, LDC_IRQ_NAME_MAX, "%s TX", name); | 1242 | snprintf(lp->tx_irq_name, LDC_IRQ_NAME_MAX, "%s TX", name); |
1243 | 1243 | ||
1244 | err = request_irq(lp->cfg.rx_irq, ldc_rx, | 1244 | err = request_irq(lp->cfg.rx_irq, ldc_rx, |
1245 | IRQF_SAMPLE_RANDOM | IRQF_DISABLED | IRQF_SHARED, | 1245 | IRQF_SAMPLE_RANDOM | IRQF_DISABLED, |
1246 | lp->rx_irq_name, lp); | 1246 | lp->rx_irq_name, lp); |
1247 | if (err) | 1247 | if (err) |
1248 | return err; | 1248 | return err; |
1249 | 1249 | ||
1250 | err = request_irq(lp->cfg.tx_irq, ldc_tx, | 1250 | err = request_irq(lp->cfg.tx_irq, ldc_tx, |
1251 | IRQF_SAMPLE_RANDOM | IRQF_DISABLED | IRQF_SHARED, | 1251 | IRQF_SAMPLE_RANDOM | IRQF_DISABLED, |
1252 | lp->tx_irq_name, lp); | 1252 | lp->tx_irq_name, lp); |
1253 | if (err) { | 1253 | if (err) { |
1254 | free_irq(lp->cfg.rx_irq, lp); | 1254 | free_irq(lp->cfg.rx_irq, lp); |
diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c index 938da19dc065..cdc91d919e93 100644 --- a/arch/sparc/kernel/mdesc.c +++ b/arch/sparc/kernel/mdesc.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
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 | 14 | ||
14 | #include <asm/cpudata.h> | 15 | #include <asm/cpudata.h> |
15 | #include <asm/hypervisor.h> | 16 | #include <asm/hypervisor.h> |
@@ -108,25 +109,15 @@ static struct mdesc_handle * __init mdesc_lmb_alloc(unsigned int mdesc_size) | |||
108 | 109 | ||
109 | static void mdesc_lmb_free(struct mdesc_handle *hp) | 110 | static void mdesc_lmb_free(struct mdesc_handle *hp) |
110 | { | 111 | { |
111 | unsigned int alloc_size, handle_size = hp->handle_size; | 112 | unsigned int alloc_size; |
112 | unsigned long start, end; | 113 | unsigned long start; |
113 | 114 | ||
114 | BUG_ON(atomic_read(&hp->refcnt) != 0); | 115 | BUG_ON(atomic_read(&hp->refcnt) != 0); |
115 | BUG_ON(!list_empty(&hp->list)); | 116 | BUG_ON(!list_empty(&hp->list)); |
116 | 117 | ||
117 | alloc_size = PAGE_ALIGN(handle_size); | 118 | alloc_size = PAGE_ALIGN(hp->handle_size); |
118 | 119 | start = __pa(hp); | |
119 | start = (unsigned long) hp; | 120 | free_bootmem_late(start, alloc_size); |
120 | end = start + alloc_size; | ||
121 | |||
122 | while (start < end) { | ||
123 | struct page *p; | ||
124 | |||
125 | p = virt_to_page(start); | ||
126 | ClearPageReserved(p); | ||
127 | __free_page(p); | ||
128 | start += PAGE_SIZE; | ||
129 | } | ||
130 | } | 121 | } |
131 | 122 | ||
132 | static struct mdesc_mem_ops lmb_mdesc_ops = { | 123 | static struct mdesc_mem_ops lmb_mdesc_ops = { |
diff --git a/arch/sparc/kernel/of_device_64.c b/arch/sparc/kernel/of_device_64.c index 881947e59e95..0a6f2d1798d1 100644 --- a/arch/sparc/kernel/of_device_64.c +++ b/arch/sparc/kernel/of_device_64.c | |||
@@ -104,9 +104,19 @@ static int of_bus_pci_map(u32 *addr, const u32 *range, | |||
104 | int i; | 104 | int i; |
105 | 105 | ||
106 | /* Check address type match */ | 106 | /* Check address type match */ |
107 | if ((addr[0] ^ range[0]) & 0x03000000) | 107 | if (!((addr[0] ^ range[0]) & 0x03000000)) |
108 | return -EINVAL; | 108 | goto type_match; |
109 | |||
110 | /* Special exception, we can map a 64-bit address into | ||
111 | * a 32-bit range. | ||
112 | */ | ||
113 | if ((addr[0] & 0x03000000) == 0x03000000 && | ||
114 | (range[0] & 0x03000000) == 0x02000000) | ||
115 | goto type_match; | ||
116 | |||
117 | return -EINVAL; | ||
109 | 118 | ||
119 | type_match: | ||
110 | if (of_out_of_range(addr + 1, range + 1, range + na + pna, | 120 | if (of_out_of_range(addr + 1, range + 1, range + na + pna, |
111 | na - 1, ns)) | 121 | na - 1, ns)) |
112 | return -EINVAL; | 122 | return -EINVAL; |
diff --git a/arch/sparc/kernel/ptrace_64.c b/arch/sparc/kernel/ptrace_64.c index 4ae91dc2feb9..2f6524d1a817 100644 --- a/arch/sparc/kernel/ptrace_64.c +++ b/arch/sparc/kernel/ptrace_64.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/signal.h> | 23 | #include <linux/signal.h> |
24 | #include <linux/regset.h> | 24 | #include <linux/regset.h> |
25 | #include <linux/tracehook.h> | 25 | #include <linux/tracehook.h> |
26 | #include <trace/syscall.h> | ||
26 | #include <linux/compat.h> | 27 | #include <linux/compat.h> |
27 | #include <linux/elf.h> | 28 | #include <linux/elf.h> |
28 | 29 | ||
@@ -37,6 +38,9 @@ | |||
37 | #include <asm/cpudata.h> | 38 | #include <asm/cpudata.h> |
38 | #include <asm/cacheflush.h> | 39 | #include <asm/cacheflush.h> |
39 | 40 | ||
41 | #define CREATE_TRACE_POINTS | ||
42 | #include <trace/events/syscalls.h> | ||
43 | |||
40 | #include "entry.h" | 44 | #include "entry.h" |
41 | 45 | ||
42 | /* #define ALLOW_INIT_TRACING */ | 46 | /* #define ALLOW_INIT_TRACING */ |
@@ -1059,6 +1063,9 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs) | |||
1059 | if (test_thread_flag(TIF_SYSCALL_TRACE)) | 1063 | if (test_thread_flag(TIF_SYSCALL_TRACE)) |
1060 | ret = tracehook_report_syscall_entry(regs); | 1064 | ret = tracehook_report_syscall_entry(regs); |
1061 | 1065 | ||
1066 | if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) | ||
1067 | trace_sys_enter(regs, regs->u_regs[UREG_G1]); | ||
1068 | |||
1062 | if (unlikely(current->audit_context) && !ret) | 1069 | if (unlikely(current->audit_context) && !ret) |
1063 | audit_syscall_entry((test_thread_flag(TIF_32BIT) ? | 1070 | audit_syscall_entry((test_thread_flag(TIF_32BIT) ? |
1064 | AUDIT_ARCH_SPARC : | 1071 | AUDIT_ARCH_SPARC : |
@@ -1084,6 +1091,9 @@ asmlinkage void syscall_trace_leave(struct pt_regs *regs) | |||
1084 | audit_syscall_exit(result, regs->u_regs[UREG_I0]); | 1091 | audit_syscall_exit(result, regs->u_regs[UREG_I0]); |
1085 | } | 1092 | } |
1086 | 1093 | ||
1094 | if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) | ||
1095 | trace_sys_exit(regs, regs->u_regs[UREG_G1]); | ||
1096 | |||
1087 | if (test_thread_flag(TIF_SYSCALL_TRACE)) | 1097 | if (test_thread_flag(TIF_SYSCALL_TRACE)) |
1088 | tracehook_report_syscall_exit(regs, 0); | 1098 | tracehook_report_syscall_exit(regs, 0); |
1089 | } | 1099 | } |
diff --git a/arch/sparc/kernel/syscalls.S b/arch/sparc/kernel/syscalls.S index d150c2aa98d2..dc4a458f74dc 100644 --- a/arch/sparc/kernel/syscalls.S +++ b/arch/sparc/kernel/syscalls.S | |||
@@ -62,7 +62,7 @@ sys32_rt_sigreturn: | |||
62 | #endif | 62 | #endif |
63 | .align 32 | 63 | .align 32 |
64 | 1: ldx [%g6 + TI_FLAGS], %l5 | 64 | 1: ldx [%g6 + TI_FLAGS], %l5 |
65 | andcc %l5, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0 | 65 | andcc %l5, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %g0 |
66 | be,pt %icc, rtrap | 66 | be,pt %icc, rtrap |
67 | nop | 67 | nop |
68 | call syscall_trace_leave | 68 | call syscall_trace_leave |
@@ -187,7 +187,7 @@ linux_syscall_trace: | |||
187 | .globl linux_sparc_syscall32 | 187 | .globl linux_sparc_syscall32 |
188 | linux_sparc_syscall32: | 188 | linux_sparc_syscall32: |
189 | /* Direct access to user regs, much faster. */ | 189 | /* Direct access to user regs, much faster. */ |
190 | cmp %g1, NR_SYSCALLS ! IEU1 Group | 190 | cmp %g1, NR_syscalls ! IEU1 Group |
191 | bgeu,pn %xcc, linux_sparc_ni_syscall ! CTI | 191 | bgeu,pn %xcc, linux_sparc_ni_syscall ! CTI |
192 | srl %i0, 0, %o0 ! IEU0 | 192 | srl %i0, 0, %o0 ! IEU0 |
193 | sll %g1, 2, %l4 ! IEU0 Group | 193 | sll %g1, 2, %l4 ! IEU0 Group |
@@ -198,7 +198,7 @@ linux_sparc_syscall32: | |||
198 | 198 | ||
199 | srl %i5, 0, %o5 ! IEU1 | 199 | srl %i5, 0, %o5 ! IEU1 |
200 | srl %i2, 0, %o2 ! IEU0 Group | 200 | srl %i2, 0, %o2 ! IEU0 Group |
201 | andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0 | 201 | andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %g0 |
202 | bne,pn %icc, linux_syscall_trace32 ! CTI | 202 | bne,pn %icc, linux_syscall_trace32 ! CTI |
203 | mov %i0, %l5 ! IEU1 | 203 | mov %i0, %l5 ! IEU1 |
204 | call %l7 ! CTI Group brk forced | 204 | call %l7 ! CTI Group brk forced |
@@ -210,7 +210,7 @@ linux_sparc_syscall32: | |||
210 | .globl linux_sparc_syscall | 210 | .globl linux_sparc_syscall |
211 | linux_sparc_syscall: | 211 | linux_sparc_syscall: |
212 | /* Direct access to user regs, much faster. */ | 212 | /* Direct access to user regs, much faster. */ |
213 | cmp %g1, NR_SYSCALLS ! IEU1 Group | 213 | cmp %g1, NR_syscalls ! IEU1 Group |
214 | bgeu,pn %xcc, linux_sparc_ni_syscall ! CTI | 214 | bgeu,pn %xcc, linux_sparc_ni_syscall ! CTI |
215 | mov %i0, %o0 ! IEU0 | 215 | mov %i0, %o0 ! IEU0 |
216 | sll %g1, 2, %l4 ! IEU0 Group | 216 | sll %g1, 2, %l4 ! IEU0 Group |
@@ -221,7 +221,7 @@ linux_sparc_syscall: | |||
221 | 221 | ||
222 | mov %i3, %o3 ! IEU1 | 222 | mov %i3, %o3 ! IEU1 |
223 | mov %i4, %o4 ! IEU0 Group | 223 | mov %i4, %o4 ! IEU0 Group |
224 | andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0 | 224 | andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %g0 |
225 | bne,pn %icc, linux_syscall_trace ! CTI Group | 225 | bne,pn %icc, linux_syscall_trace ! CTI Group |
226 | mov %i0, %l5 ! IEU0 | 226 | mov %i0, %l5 ! IEU0 |
227 | 2: call %l7 ! CTI Group brk forced | 227 | 2: call %l7 ! CTI Group brk forced |
@@ -245,7 +245,7 @@ ret_sys_call: | |||
245 | 245 | ||
246 | cmp %o0, -ERESTART_RESTARTBLOCK | 246 | cmp %o0, -ERESTART_RESTARTBLOCK |
247 | bgeu,pn %xcc, 1f | 247 | bgeu,pn %xcc, 1f |
248 | andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %l6 | 248 | andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %l6 |
249 | 80: | 249 | 80: |
250 | /* System call success, clear Carry condition code. */ | 250 | /* System call success, clear Carry condition code. */ |
251 | andn %g3, %g2, %g3 | 251 | andn %g3, %g2, %g3 |
@@ -260,7 +260,7 @@ ret_sys_call: | |||
260 | /* System call failure, set Carry condition code. | 260 | /* System call failure, set Carry condition code. |
261 | * Also, get abs(errno) to return to the process. | 261 | * Also, get abs(errno) to return to the process. |
262 | */ | 262 | */ |
263 | andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %l6 | 263 | andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %l6 |
264 | sub %g0, %o0, %o0 | 264 | sub %g0, %o0, %o0 |
265 | or %g3, %g2, %g3 | 265 | or %g3, %g2, %g3 |
266 | stx %o0, [%sp + PTREGS_OFF + PT_V9_I0] | 266 | stx %o0, [%sp + PTREGS_OFF + PT_V9_I0] |
diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c index 63f73ae8a892..67e165102885 100644 --- a/arch/sparc/kernel/time_64.c +++ b/arch/sparc/kernel/time_64.c | |||
@@ -774,26 +774,9 @@ void __devinit setup_sparc64_timer(void) | |||
774 | static struct clocksource clocksource_tick = { | 774 | static struct clocksource clocksource_tick = { |
775 | .rating = 100, | 775 | .rating = 100, |
776 | .mask = CLOCKSOURCE_MASK(64), | 776 | .mask = CLOCKSOURCE_MASK(64), |
777 | .shift = 16, | ||
778 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 777 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
779 | }; | 778 | }; |
780 | 779 | ||
781 | static void __init setup_clockevent_multiplier(unsigned long hz) | ||
782 | { | ||
783 | unsigned long mult, shift = 32; | ||
784 | |||
785 | while (1) { | ||
786 | mult = div_sc(hz, NSEC_PER_SEC, shift); | ||
787 | if (mult && (mult >> 32UL) == 0UL) | ||
788 | break; | ||
789 | |||
790 | shift--; | ||
791 | } | ||
792 | |||
793 | sparc64_clockevent.shift = shift; | ||
794 | sparc64_clockevent.mult = mult; | ||
795 | } | ||
796 | |||
797 | static unsigned long tb_ticks_per_usec __read_mostly; | 780 | static unsigned long tb_ticks_per_usec __read_mostly; |
798 | 781 | ||
799 | void __delay(unsigned long loops) | 782 | void __delay(unsigned long loops) |
@@ -828,9 +811,7 @@ void __init time_init(void) | |||
828 | clocksource_hz2mult(freq, SPARC64_NSEC_PER_CYC_SHIFT); | 811 | clocksource_hz2mult(freq, SPARC64_NSEC_PER_CYC_SHIFT); |
829 | 812 | ||
830 | clocksource_tick.name = tick_ops->name; | 813 | clocksource_tick.name = tick_ops->name; |
831 | clocksource_tick.mult = | 814 | clocksource_calc_mult_shift(&clocksource_tick, freq, 4); |
832 | clocksource_hz2mult(freq, | ||
833 | clocksource_tick.shift); | ||
834 | clocksource_tick.read = clocksource_tick_read; | 815 | clocksource_tick.read = clocksource_tick_read; |
835 | 816 | ||
836 | printk("clocksource: mult[%x] shift[%d]\n", | 817 | printk("clocksource: mult[%x] shift[%d]\n", |
@@ -839,15 +820,14 @@ void __init time_init(void) | |||
839 | clocksource_register(&clocksource_tick); | 820 | clocksource_register(&clocksource_tick); |
840 | 821 | ||
841 | sparc64_clockevent.name = tick_ops->name; | 822 | sparc64_clockevent.name = tick_ops->name; |
842 | 823 | clockevents_calc_mult_shift(&sparc64_clockevent, freq, 4); | |
843 | setup_clockevent_multiplier(freq); | ||
844 | 824 | ||
845 | sparc64_clockevent.max_delta_ns = | 825 | sparc64_clockevent.max_delta_ns = |
846 | clockevent_delta2ns(0x7fffffffffffffffUL, &sparc64_clockevent); | 826 | clockevent_delta2ns(0x7fffffffffffffffUL, &sparc64_clockevent); |
847 | sparc64_clockevent.min_delta_ns = | 827 | sparc64_clockevent.min_delta_ns = |
848 | clockevent_delta2ns(0xF, &sparc64_clockevent); | 828 | clockevent_delta2ns(0xF, &sparc64_clockevent); |
849 | 829 | ||
850 | printk("clockevent: mult[%ux] shift[%d]\n", | 830 | printk("clockevent: mult[%x] shift[%d]\n", |
851 | sparc64_clockevent.mult, sparc64_clockevent.shift); | 831 | sparc64_clockevent.mult, sparc64_clockevent.shift); |
852 | 832 | ||
853 | setup_sparc64_timer(); | 833 | setup_sparc64_timer(); |
diff --git a/arch/sparc/kernel/unaligned_32.c b/arch/sparc/kernel/unaligned_32.c index 6b1e6cde6fff..f8514e291e15 100644 --- a/arch/sparc/kernel/unaligned_32.c +++ b/arch/sparc/kernel/unaligned_32.c | |||
@@ -17,8 +17,7 @@ | |||
17 | #include <asm/uaccess.h> | 17 | #include <asm/uaccess.h> |
18 | #include <linux/smp.h> | 18 | #include <linux/smp.h> |
19 | #include <linux/smp_lock.h> | 19 | #include <linux/smp_lock.h> |
20 | 20 | #include <linux/perf_event.h> | |
21 | /* #define DEBUG_MNA */ | ||
22 | 21 | ||
23 | enum direction { | 22 | enum direction { |
24 | load, /* ld, ldd, ldh, ldsh */ | 23 | load, /* ld, ldd, ldh, ldsh */ |
@@ -29,12 +28,6 @@ enum direction { | |||
29 | invalid, | 28 | invalid, |
30 | }; | 29 | }; |
31 | 30 | ||
32 | #ifdef DEBUG_MNA | ||
33 | static char *dirstrings[] = { | ||
34 | "load", "store", "both", "fpload", "fpstore", "invalid" | ||
35 | }; | ||
36 | #endif | ||
37 | |||
38 | static inline enum direction decode_direction(unsigned int insn) | 31 | static inline enum direction decode_direction(unsigned int insn) |
39 | { | 32 | { |
40 | unsigned long tmp = (insn >> 21) & 1; | 33 | unsigned long tmp = (insn >> 21) & 1; |
@@ -255,10 +248,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn) | |||
255 | unsigned long addr = compute_effective_address(regs, insn); | 248 | unsigned long addr = compute_effective_address(regs, insn); |
256 | int err; | 249 | int err; |
257 | 250 | ||
258 | #ifdef DEBUG_MNA | 251 | perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, regs, addr); |
259 | printk("KMNA: pc=%08lx [dir=%s addr=%08lx size=%d] retpc[%08lx]\n", | ||
260 | regs->pc, dirstrings[dir], addr, size, regs->u_regs[UREG_RETPC]); | ||
261 | #endif | ||
262 | switch (dir) { | 252 | switch (dir) { |
263 | case load: | 253 | case load: |
264 | err = do_int_load(fetch_reg_addr(((insn>>25)&0x1f), | 254 | err = do_int_load(fetch_reg_addr(((insn>>25)&0x1f), |
@@ -350,6 +340,7 @@ asmlinkage void user_unaligned_trap(struct pt_regs *regs, unsigned int insn) | |||
350 | } | 340 | } |
351 | 341 | ||
352 | addr = compute_effective_address(regs, insn); | 342 | addr = compute_effective_address(regs, insn); |
343 | perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, regs, addr); | ||
353 | switch(dir) { | 344 | switch(dir) { |
354 | case load: | 345 | case load: |
355 | err = do_int_load(fetch_reg_addr(((insn>>25)&0x1f), | 346 | 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 379209982a07..378ca82b9ccc 100644 --- a/arch/sparc/kernel/unaligned_64.c +++ b/arch/sparc/kernel/unaligned_64.c | |||
@@ -20,10 +20,9 @@ | |||
20 | #include <asm/uaccess.h> | 20 | #include <asm/uaccess.h> |
21 | #include <linux/smp.h> | 21 | #include <linux/smp.h> |
22 | #include <linux/bitops.h> | 22 | #include <linux/bitops.h> |
23 | #include <linux/perf_event.h> | ||
23 | #include <asm/fpumacro.h> | 24 | #include <asm/fpumacro.h> |
24 | 25 | ||
25 | /* #define DEBUG_MNA */ | ||
26 | |||
27 | enum direction { | 26 | enum direction { |
28 | load, /* ld, ldd, ldh, ldsh */ | 27 | load, /* ld, ldd, ldh, ldsh */ |
29 | store, /* st, std, sth, stsh */ | 28 | store, /* st, std, sth, stsh */ |
@@ -33,12 +32,6 @@ enum direction { | |||
33 | invalid, | 32 | invalid, |
34 | }; | 33 | }; |
35 | 34 | ||
36 | #ifdef DEBUG_MNA | ||
37 | static char *dirstrings[] = { | ||
38 | "load", "store", "both", "fpload", "fpstore", "invalid" | ||
39 | }; | ||
40 | #endif | ||
41 | |||
42 | static inline enum direction decode_direction(unsigned int insn) | 35 | static inline enum direction decode_direction(unsigned int insn) |
43 | { | 36 | { |
44 | unsigned long tmp = (insn >> 21) & 1; | 37 | unsigned long tmp = (insn >> 21) & 1; |
@@ -327,12 +320,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn) | |||
327 | 320 | ||
328 | addr = compute_effective_address(regs, insn, | 321 | addr = compute_effective_address(regs, insn, |
329 | ((insn >> 25) & 0x1f)); | 322 | ((insn >> 25) & 0x1f)); |
330 | #ifdef DEBUG_MNA | 323 | perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, regs, addr); |
331 | printk("KMNA: pc=%016lx [dir=%s addr=%016lx size=%d] " | ||
332 | "retpc[%016lx]\n", | ||
333 | regs->tpc, dirstrings[dir], addr, size, | ||
334 | regs->u_regs[UREG_RETPC]); | ||
335 | #endif | ||
336 | switch (asi) { | 324 | switch (asi) { |
337 | case ASI_NL: | 325 | case ASI_NL: |
338 | case ASI_AIUPL: | 326 | case ASI_AIUPL: |
@@ -399,6 +387,7 @@ int handle_popc(u32 insn, struct pt_regs *regs) | |||
399 | int ret, i, rd = ((insn >> 25) & 0x1f); | 387 | int ret, i, rd = ((insn >> 25) & 0x1f); |
400 | int from_kernel = (regs->tstate & TSTATE_PRIV) != 0; | 388 | int from_kernel = (regs->tstate & TSTATE_PRIV) != 0; |
401 | 389 | ||
390 | perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, 0); | ||
402 | if (insn & 0x2000) { | 391 | if (insn & 0x2000) { |
403 | maybe_flush_windows(0, 0, rd, from_kernel); | 392 | maybe_flush_windows(0, 0, rd, from_kernel); |
404 | value = sign_extend_imm13(insn); | 393 | value = sign_extend_imm13(insn); |
@@ -445,6 +434,8 @@ int handle_ldf_stq(u32 insn, struct pt_regs *regs) | |||
445 | int asi = decode_asi(insn, regs); | 434 | int asi = decode_asi(insn, regs); |
446 | int flag = (freg < 32) ? FPRS_DL : FPRS_DU; | 435 | int flag = (freg < 32) ? FPRS_DL : FPRS_DU; |
447 | 436 | ||
437 | perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, 0); | ||
438 | |||
448 | save_and_clear_fpu(); | 439 | save_and_clear_fpu(); |
449 | current_thread_info()->xfsr[0] &= ~0x1c000; | 440 | current_thread_info()->xfsr[0] &= ~0x1c000; |
450 | if (freg & 3) { | 441 | if (freg & 3) { |
@@ -566,6 +557,8 @@ void handle_ld_nf(u32 insn, struct pt_regs *regs) | |||
566 | int from_kernel = (regs->tstate & TSTATE_PRIV) != 0; | 557 | int from_kernel = (regs->tstate & TSTATE_PRIV) != 0; |
567 | unsigned long *reg; | 558 | unsigned long *reg; |
568 | 559 | ||
560 | perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, 0); | ||
561 | |||
569 | maybe_flush_windows(0, 0, rd, from_kernel); | 562 | maybe_flush_windows(0, 0, rd, from_kernel); |
570 | reg = fetch_reg_addr(rd, regs); | 563 | reg = fetch_reg_addr(rd, regs); |
571 | if (from_kernel || rd < 16) { | 564 | if (from_kernel || rd < 16) { |
@@ -596,6 +589,7 @@ void handle_lddfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr | |||
596 | 589 | ||
597 | if (tstate & TSTATE_PRIV) | 590 | if (tstate & TSTATE_PRIV) |
598 | die_if_kernel("lddfmna from kernel", regs); | 591 | die_if_kernel("lddfmna from kernel", regs); |
592 | perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, regs, sfar); | ||
599 | if (test_thread_flag(TIF_32BIT)) | 593 | if (test_thread_flag(TIF_32BIT)) |
600 | pc = (u32)pc; | 594 | pc = (u32)pc; |
601 | if (get_user(insn, (u32 __user *) pc) != -EFAULT) { | 595 | if (get_user(insn, (u32 __user *) pc) != -EFAULT) { |
@@ -657,6 +651,7 @@ void handle_stdfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr | |||
657 | 651 | ||
658 | if (tstate & TSTATE_PRIV) | 652 | if (tstate & TSTATE_PRIV) |
659 | die_if_kernel("stdfmna from kernel", regs); | 653 | die_if_kernel("stdfmna from kernel", regs); |
654 | perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, regs, sfar); | ||
660 | if (test_thread_flag(TIF_32BIT)) | 655 | if (test_thread_flag(TIF_32BIT)) |
661 | pc = (u32)pc; | 656 | pc = (u32)pc; |
662 | if (get_user(insn, (u32 __user *) pc) != -EFAULT) { | 657 | if (get_user(insn, (u32 __user *) pc) != -EFAULT) { |
diff --git a/arch/sparc/kernel/visemul.c b/arch/sparc/kernel/visemul.c index d231cbd5c526..9dfd2ebcb157 100644 --- a/arch/sparc/kernel/visemul.c +++ b/arch/sparc/kernel/visemul.c | |||
@@ -5,6 +5,7 @@ | |||
5 | #include <linux/kernel.h> | 5 | #include <linux/kernel.h> |
6 | #include <linux/errno.h> | 6 | #include <linux/errno.h> |
7 | #include <linux/thread_info.h> | 7 | #include <linux/thread_info.h> |
8 | #include <linux/perf_event.h> | ||
8 | 9 | ||
9 | #include <asm/ptrace.h> | 10 | #include <asm/ptrace.h> |
10 | #include <asm/pstate.h> | 11 | #include <asm/pstate.h> |
@@ -801,6 +802,8 @@ int vis_emul(struct pt_regs *regs, unsigned int insn) | |||
801 | 802 | ||
802 | BUG_ON(regs->tstate & TSTATE_PRIV); | 803 | BUG_ON(regs->tstate & TSTATE_PRIV); |
803 | 804 | ||
805 | perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, 0); | ||
806 | |||
804 | if (test_thread_flag(TIF_32BIT)) | 807 | if (test_thread_flag(TIF_32BIT)) |
805 | pc = (u32)pc; | 808 | pc = (u32)pc; |
806 | 809 | ||
diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile index e75faf0e59ae..c4b5e03af115 100644 --- a/arch/sparc/lib/Makefile +++ b/arch/sparc/lib/Makefile | |||
@@ -44,3 +44,4 @@ obj-y += iomap.o | |||
44 | obj-$(CONFIG_SPARC32) += atomic32.o | 44 | obj-$(CONFIG_SPARC32) += atomic32.o |
45 | obj-y += ksyms.o | 45 | obj-y += ksyms.o |
46 | obj-$(CONFIG_SPARC64) += PeeCeeI.o | 46 | obj-$(CONFIG_SPARC64) += PeeCeeI.o |
47 | obj-y += usercopy.o | ||
diff --git a/arch/sparc/lib/bzero.S b/arch/sparc/lib/bzero.S index b6557297440f..615f401edf69 100644 --- a/arch/sparc/lib/bzero.S +++ b/arch/sparc/lib/bzero.S | |||
@@ -6,10 +6,6 @@ | |||
6 | 6 | ||
7 | .text | 7 | .text |
8 | 8 | ||
9 | .globl __memset | ||
10 | .type __memset, #function | ||
11 | __memset: /* %o0=buf, %o1=pat, %o2=len */ | ||
12 | |||
13 | .globl memset | 9 | .globl memset |
14 | .type memset, #function | 10 | .type memset, #function |
15 | memset: /* %o0=buf, %o1=pat, %o2=len */ | 11 | memset: /* %o0=buf, %o1=pat, %o2=len */ |
@@ -83,7 +79,6 @@ __bzero_done: | |||
83 | retl | 79 | retl |
84 | mov %o3, %o0 | 80 | mov %o3, %o0 |
85 | .size __bzero, .-__bzero | 81 | .size __bzero, .-__bzero |
86 | .size __memset, .-__memset | ||
87 | .size memset, .-memset | 82 | .size memset, .-memset |
88 | 83 | ||
89 | #define EX_ST(x,y) \ | 84 | #define EX_ST(x,y) \ |
diff --git a/arch/sparc/lib/checksum_32.S b/arch/sparc/lib/checksum_32.S index 77f228533d47..3632cb34e914 100644 --- a/arch/sparc/lib/checksum_32.S +++ b/arch/sparc/lib/checksum_32.S | |||
@@ -560,7 +560,7 @@ __csum_partial_copy_end: | |||
560 | mov %i0, %o1 | 560 | mov %i0, %o1 |
561 | mov %i1, %o0 | 561 | mov %i1, %o0 |
562 | 5: | 562 | 5: |
563 | call __memcpy | 563 | call memcpy |
564 | mov %i2, %o2 | 564 | mov %i2, %o2 |
565 | tst %o0 | 565 | tst %o0 |
566 | bne,a 2f | 566 | bne,a 2f |
diff --git a/arch/sparc/lib/ksyms.c b/arch/sparc/lib/ksyms.c index 704b12668388..1b30bb3bfdb1 100644 --- a/arch/sparc/lib/ksyms.c +++ b/arch/sparc/lib/ksyms.c | |||
@@ -30,7 +30,6 @@ EXPORT_SYMBOL(__memscan_generic); | |||
30 | EXPORT_SYMBOL(memcmp); | 30 | EXPORT_SYMBOL(memcmp); |
31 | EXPORT_SYMBOL(memcpy); | 31 | EXPORT_SYMBOL(memcpy); |
32 | EXPORT_SYMBOL(memset); | 32 | EXPORT_SYMBOL(memset); |
33 | EXPORT_SYMBOL(__memset); | ||
34 | EXPORT_SYMBOL(memmove); | 33 | EXPORT_SYMBOL(memmove); |
35 | EXPORT_SYMBOL(__bzero); | 34 | EXPORT_SYMBOL(__bzero); |
36 | 35 | ||
@@ -81,7 +80,6 @@ EXPORT_SYMBOL(__csum_partial_copy_sparc_generic); | |||
81 | 80 | ||
82 | /* Special internal versions of library functions. */ | 81 | /* Special internal versions of library functions. */ |
83 | EXPORT_SYMBOL(__copy_1page); | 82 | EXPORT_SYMBOL(__copy_1page); |
84 | EXPORT_SYMBOL(__memcpy); | ||
85 | EXPORT_SYMBOL(__memmove); | 83 | EXPORT_SYMBOL(__memmove); |
86 | EXPORT_SYMBOL(bzero_1page); | 84 | EXPORT_SYMBOL(bzero_1page); |
87 | 85 | ||
diff --git a/arch/sparc/lib/mcount.S b/arch/sparc/lib/mcount.S index 7ce9c65f3592..24b8b12deed2 100644 --- a/arch/sparc/lib/mcount.S +++ b/arch/sparc/lib/mcount.S | |||
@@ -64,8 +64,9 @@ mcount: | |||
64 | 2: sethi %hi(softirq_stack), %g3 | 64 | 2: sethi %hi(softirq_stack), %g3 |
65 | or %g3, %lo(softirq_stack), %g3 | 65 | or %g3, %lo(softirq_stack), %g3 |
66 | ldx [%g3 + %g1], %g7 | 66 | ldx [%g3 + %g1], %g7 |
67 | sub %g7, STACK_BIAS, %g7 | ||
67 | cmp %sp, %g7 | 68 | cmp %sp, %g7 |
68 | bleu,pt %xcc, 2f | 69 | bleu,pt %xcc, 3f |
69 | sethi %hi(THREAD_SIZE), %g3 | 70 | sethi %hi(THREAD_SIZE), %g3 |
70 | add %g7, %g3, %g7 | 71 | add %g7, %g3, %g7 |
71 | cmp %sp, %g7 | 72 | cmp %sp, %g7 |
@@ -75,7 +76,7 @@ mcount: | |||
75 | * again, we are already trying to output the stack overflow | 76 | * again, we are already trying to output the stack overflow |
76 | * message. | 77 | * message. |
77 | */ | 78 | */ |
78 | sethi %hi(ovstack), %g7 ! cant move to panic stack fast enough | 79 | 3: sethi %hi(ovstack), %g7 ! cant move to panic stack fast enough |
79 | or %g7, %lo(ovstack), %g7 | 80 | or %g7, %lo(ovstack), %g7 |
80 | add %g7, OVSTACKSIZE, %g3 | 81 | add %g7, OVSTACKSIZE, %g3 |
81 | sub %g3, STACK_BIAS + 192, %g3 | 82 | sub %g3, STACK_BIAS + 192, %g3 |
diff --git a/arch/sparc/lib/memcpy.S b/arch/sparc/lib/memcpy.S index ce10bc869af9..34fe65751737 100644 --- a/arch/sparc/lib/memcpy.S +++ b/arch/sparc/lib/memcpy.S | |||
@@ -543,9 +543,6 @@ FUNC(memmove) | |||
543 | b 3f | 543 | b 3f |
544 | add %o0, 2, %o0 | 544 | add %o0, 2, %o0 |
545 | 545 | ||
546 | #ifdef __KERNEL__ | ||
547 | FUNC(__memcpy) | ||
548 | #endif | ||
549 | FUNC(memcpy) /* %o0=dst %o1=src %o2=len */ | 546 | FUNC(memcpy) /* %o0=dst %o1=src %o2=len */ |
550 | 547 | ||
551 | sub %o0, %o1, %o4 | 548 | sub %o0, %o1, %o4 |
diff --git a/arch/sparc/lib/memset.S b/arch/sparc/lib/memset.S index 1c37ea892deb..99c017be8719 100644 --- a/arch/sparc/lib/memset.S +++ b/arch/sparc/lib/memset.S | |||
@@ -60,11 +60,10 @@ | |||
60 | .globl __bzero_begin | 60 | .globl __bzero_begin |
61 | __bzero_begin: | 61 | __bzero_begin: |
62 | 62 | ||
63 | .globl __bzero, __memset, | 63 | .globl __bzero |
64 | .globl memset | 64 | .globl memset |
65 | .globl __memset_start, __memset_end | 65 | .globl __memset_start, __memset_end |
66 | __memset_start: | 66 | __memset_start: |
67 | __memset: | ||
68 | memset: | 67 | memset: |
69 | and %o1, 0xff, %g3 | 68 | and %o1, 0xff, %g3 |
70 | sll %g3, 8, %g2 | 69 | sll %g3, 8, %g2 |
diff --git a/arch/sparc/lib/usercopy.c b/arch/sparc/lib/usercopy.c new file mode 100644 index 000000000000..14b363fec8a2 --- /dev/null +++ b/arch/sparc/lib/usercopy.c | |||
@@ -0,0 +1,8 @@ | |||
1 | #include <linux/module.h> | ||
2 | #include <linux/bug.h> | ||
3 | |||
4 | void copy_from_user_overflow(void) | ||
5 | { | ||
6 | WARN(1, "Buffer overflow detected!\n"); | ||
7 | } | ||
8 | EXPORT_SYMBOL(copy_from_user_overflow); | ||
diff --git a/arch/sparc/math-emu/math_32.c b/arch/sparc/math-emu/math_32.c index e13f65da17df..a3fccde894ec 100644 --- a/arch/sparc/math-emu/math_32.c +++ b/arch/sparc/math-emu/math_32.c | |||
@@ -67,6 +67,7 @@ | |||
67 | #include <linux/types.h> | 67 | #include <linux/types.h> |
68 | #include <linux/sched.h> | 68 | #include <linux/sched.h> |
69 | #include <linux/mm.h> | 69 | #include <linux/mm.h> |
70 | #include <linux/perf_event.h> | ||
70 | #include <asm/uaccess.h> | 71 | #include <asm/uaccess.h> |
71 | 72 | ||
72 | #include "sfp-util_32.h" | 73 | #include "sfp-util_32.h" |
@@ -163,6 +164,8 @@ int do_mathemu(struct pt_regs *regs, struct task_struct *fpt) | |||
163 | int retcode = 0; /* assume all succeed */ | 164 | int retcode = 0; /* assume all succeed */ |
164 | unsigned long insn; | 165 | unsigned long insn; |
165 | 166 | ||
167 | perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, 0); | ||
168 | |||
166 | #ifdef DEBUG_MATHEMU | 169 | #ifdef DEBUG_MATHEMU |
167 | printk("In do_mathemu()... pc is %08lx\n", regs->pc); | 170 | printk("In do_mathemu()... pc is %08lx\n", regs->pc); |
168 | printk("fpqdepth is %ld\n", fpt->thread.fpqdepth); | 171 | printk("fpqdepth is %ld\n", fpt->thread.fpqdepth); |
diff --git a/arch/sparc/math-emu/math_64.c b/arch/sparc/math-emu/math_64.c index 6863c9bde25c..56d2c44747b8 100644 --- a/arch/sparc/math-emu/math_64.c +++ b/arch/sparc/math-emu/math_64.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/types.h> | 11 | #include <linux/types.h> |
12 | #include <linux/sched.h> | 12 | #include <linux/sched.h> |
13 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
14 | #include <linux/perf_event.h> | ||
14 | 15 | ||
15 | #include <asm/fpumacro.h> | 16 | #include <asm/fpumacro.h> |
16 | #include <asm/ptrace.h> | 17 | #include <asm/ptrace.h> |
@@ -183,6 +184,7 @@ int do_mathemu(struct pt_regs *regs, struct fpustate *f) | |||
183 | 184 | ||
184 | if (tstate & TSTATE_PRIV) | 185 | if (tstate & TSTATE_PRIV) |
185 | 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); | ||
186 | if (test_thread_flag(TIF_32BIT)) | 188 | if (test_thread_flag(TIF_32BIT)) |
187 | pc = (u32)pc; | 189 | pc = (u32)pc; |
188 | if (get_user(insn, (u32 __user *) pc) != -EFAULT) { | 190 | if (get_user(insn, (u32 __user *) pc) != -EFAULT) { |
diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c index 43b0da96a4fb..6081936bf03b 100644 --- a/arch/sparc/mm/fault_64.c +++ b/arch/sparc/mm/fault_64.c | |||
@@ -31,13 +31,12 @@ | |||
31 | #include <asm/sections.h> | 31 | #include <asm/sections.h> |
32 | #include <asm/mmu_context.h> | 32 | #include <asm/mmu_context.h> |
33 | 33 | ||
34 | #ifdef CONFIG_KPROBES | 34 | static inline __kprobes int notify_page_fault(struct pt_regs *regs) |
35 | static inline int notify_page_fault(struct pt_regs *regs) | ||
36 | { | 35 | { |
37 | int ret = 0; | 36 | int ret = 0; |
38 | 37 | ||
39 | /* kprobe_running() needs smp_processor_id() */ | 38 | /* kprobe_running() needs smp_processor_id() */ |
40 | if (!user_mode(regs)) { | 39 | if (kprobes_built_in() && !user_mode(regs)) { |
41 | preempt_disable(); | 40 | preempt_disable(); |
42 | if (kprobe_running() && kprobe_fault_handler(regs, 0)) | 41 | if (kprobe_running() && kprobe_fault_handler(regs, 0)) |
43 | ret = 1; | 42 | ret = 1; |
@@ -45,12 +44,6 @@ static inline int notify_page_fault(struct pt_regs *regs) | |||
45 | } | 44 | } |
46 | return ret; | 45 | return ret; |
47 | } | 46 | } |
48 | #else | ||
49 | static inline int notify_page_fault(struct pt_regs *regs) | ||
50 | { | ||
51 | return 0; | ||
52 | } | ||
53 | #endif | ||
54 | 47 | ||
55 | static void __kprobes unhandled_fault(unsigned long address, | 48 | static void __kprobes unhandled_fault(unsigned long address, |
56 | struct task_struct *tsk, | 49 | struct task_struct *tsk, |
@@ -73,7 +66,7 @@ static void __kprobes unhandled_fault(unsigned long address, | |||
73 | die_if_kernel("Oops", regs); | 66 | die_if_kernel("Oops", regs); |
74 | } | 67 | } |
75 | 68 | ||
76 | static void bad_kernel_pc(struct pt_regs *regs, unsigned long vaddr) | 69 | static void __kprobes bad_kernel_pc(struct pt_regs *regs, unsigned long vaddr) |
77 | { | 70 | { |
78 | printk(KERN_CRIT "OOPS: Bogus kernel PC [%016lx] in fault handler\n", | 71 | printk(KERN_CRIT "OOPS: Bogus kernel PC [%016lx] in fault handler\n", |
79 | regs->tpc); | 72 | regs->tpc); |
@@ -170,8 +163,9 @@ static unsigned int get_fault_insn(struct pt_regs *regs, unsigned int insn) | |||
170 | return insn; | 163 | return insn; |
171 | } | 164 | } |
172 | 165 | ||
173 | static void do_kernel_fault(struct pt_regs *regs, int si_code, int fault_code, | 166 | static void __kprobes do_kernel_fault(struct pt_regs *regs, int si_code, |
174 | unsigned int insn, unsigned long address) | 167 | int fault_code, unsigned int insn, |
168 | unsigned long address) | ||
175 | { | 169 | { |
176 | unsigned char asi = ASI_P; | 170 | unsigned char asi = ASI_P; |
177 | 171 | ||
@@ -225,7 +219,7 @@ cannot_handle: | |||
225 | unhandled_fault (address, current, regs); | 219 | unhandled_fault (address, current, regs); |
226 | } | 220 | } |
227 | 221 | ||
228 | static void noinline bogus_32bit_fault_tpc(struct pt_regs *regs) | 222 | static void noinline __kprobes bogus_32bit_fault_tpc(struct pt_regs *regs) |
229 | { | 223 | { |
230 | static int times; | 224 | static int times; |
231 | 225 | ||
@@ -237,8 +231,8 @@ static void noinline bogus_32bit_fault_tpc(struct pt_regs *regs) | |||
237 | show_regs(regs); | 231 | show_regs(regs); |
238 | } | 232 | } |
239 | 233 | ||
240 | static void noinline bogus_32bit_fault_address(struct pt_regs *regs, | 234 | static void noinline __kprobes bogus_32bit_fault_address(struct pt_regs *regs, |
241 | unsigned long addr) | 235 | unsigned long addr) |
242 | { | 236 | { |
243 | static int times; | 237 | static int times; |
244 | 238 | ||