aboutsummaryrefslogtreecommitdiffstats
path: root/arch/avr32/kernel
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /arch/avr32/kernel
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'arch/avr32/kernel')
-rw-r--r--arch/avr32/kernel/Makefile4
-rw-r--r--arch/avr32/kernel/cpu.c74
-rw-r--r--arch/avr32/kernel/entry-avr32b.S18
-rw-r--r--arch/avr32/kernel/irq.c2
-rw-r--r--arch/avr32/kernel/process.c125
-rw-r--r--arch/avr32/kernel/signal.c60
-rw-r--r--arch/avr32/kernel/syscall-stubs.S24
-rw-r--r--arch/avr32/kernel/syscall_table.S8
-rw-r--r--arch/avr32/kernel/traps.c2
9 files changed, 219 insertions, 98 deletions
diff --git a/arch/avr32/kernel/Makefile b/arch/avr32/kernel/Makefile
index 119a2e41def..18229d0d186 100644
--- a/arch/avr32/kernel/Makefile
+++ b/arch/avr32/kernel/Makefile
@@ -7,8 +7,8 @@ extra-y := head.o vmlinux.lds
7obj-$(CONFIG_SUBARCH_AVR32B) += entry-avr32b.o 7obj-$(CONFIG_SUBARCH_AVR32B) += entry-avr32b.o
8obj-y += syscall_table.o syscall-stubs.o irq.o 8obj-y += syscall_table.o syscall-stubs.o irq.o
9obj-y += setup.o traps.o ocd.o ptrace.o 9obj-y += setup.o traps.o ocd.o ptrace.o
10obj-y += signal.o process.o time.o 10obj-y += signal.o sys_avr32.o process.o time.o
11obj-y += switch_to.o cpu.o 11obj-y += init_task.o switch_to.o cpu.o
12obj-$(CONFIG_MODULES) += module.o avr32_ksyms.o 12obj-$(CONFIG_MODULES) += module.o avr32_ksyms.o
13obj-$(CONFIG_KPROBES) += kprobes.o 13obj-$(CONFIG_KPROBES) += kprobes.o
14obj-$(CONFIG_STACKTRACE) += stacktrace.o 14obj-$(CONFIG_STACKTRACE) += stacktrace.o
diff --git a/arch/avr32/kernel/cpu.c b/arch/avr32/kernel/cpu.c
index 2233be71e2e..e84faffbbec 100644
--- a/arch/avr32/kernel/cpu.c
+++ b/arch/avr32/kernel/cpu.c
@@ -6,7 +6,7 @@
6 * published by the Free Software Foundation. 6 * published by the Free Software Foundation.
7 */ 7 */
8#include <linux/init.h> 8#include <linux/init.h>
9#include <linux/device.h> 9#include <linux/sysdev.h>
10#include <linux/seq_file.h> 10#include <linux/seq_file.h>
11#include <linux/cpu.h> 11#include <linux/cpu.h>
12#include <linux/module.h> 12#include <linux/module.h>
@@ -26,16 +26,16 @@ static DEFINE_PER_CPU(struct cpu, cpu_devices);
26 * XXX: If/when a SMP-capable implementation of AVR32 will ever be 26 * XXX: If/when a SMP-capable implementation of AVR32 will ever be
27 * made, we must make sure that the code executes on the correct CPU. 27 * made, we must make sure that the code executes on the correct CPU.
28 */ 28 */
29static ssize_t show_pc0event(struct device *dev, 29static ssize_t show_pc0event(struct sys_device *dev,
30 struct device_attribute *attr, char *buf) 30 struct sysdev_attribute *attr, char *buf)
31{ 31{
32 unsigned long pccr; 32 unsigned long pccr;
33 33
34 pccr = sysreg_read(PCCR); 34 pccr = sysreg_read(PCCR);
35 return sprintf(buf, "0x%lx\n", (pccr >> 12) & 0x3f); 35 return sprintf(buf, "0x%lx\n", (pccr >> 12) & 0x3f);
36} 36}
37static ssize_t store_pc0event(struct device *dev, 37static ssize_t store_pc0event(struct sys_device *dev,
38 struct device_attribute *attr, const char *buf, 38 struct sysdev_attribute *attr, const char *buf,
39 size_t count) 39 size_t count)
40{ 40{
41 unsigned long val; 41 unsigned long val;
@@ -48,16 +48,16 @@ static ssize_t store_pc0event(struct device *dev,
48 sysreg_write(PCCR, val); 48 sysreg_write(PCCR, val);
49 return count; 49 return count;
50} 50}
51static ssize_t show_pc0count(struct device *dev, 51static ssize_t show_pc0count(struct sys_device *dev,
52 struct device_attribute *attr, char *buf) 52 struct sysdev_attribute *attr, char *buf)
53{ 53{
54 unsigned long pcnt0; 54 unsigned long pcnt0;
55 55
56 pcnt0 = sysreg_read(PCNT0); 56 pcnt0 = sysreg_read(PCNT0);
57 return sprintf(buf, "%lu\n", pcnt0); 57 return sprintf(buf, "%lu\n", pcnt0);
58} 58}
59static ssize_t store_pc0count(struct device *dev, 59static ssize_t store_pc0count(struct sys_device *dev,
60 struct device_attribute *attr, 60 struct sysdev_attribute *attr,
61 const char *buf, size_t count) 61 const char *buf, size_t count)
62{ 62{
63 unsigned long val; 63 unsigned long val;
@@ -71,16 +71,16 @@ static ssize_t store_pc0count(struct device *dev,
71 return count; 71 return count;
72} 72}
73 73
74static ssize_t show_pc1event(struct device *dev, 74static ssize_t show_pc1event(struct sys_device *dev,
75 struct device_attribute *attr, char *buf) 75 struct sysdev_attribute *attr, char *buf)
76{ 76{
77 unsigned long pccr; 77 unsigned long pccr;
78 78
79 pccr = sysreg_read(PCCR); 79 pccr = sysreg_read(PCCR);
80 return sprintf(buf, "0x%lx\n", (pccr >> 18) & 0x3f); 80 return sprintf(buf, "0x%lx\n", (pccr >> 18) & 0x3f);
81} 81}
82static ssize_t store_pc1event(struct device *dev, 82static ssize_t store_pc1event(struct sys_device *dev,
83 struct device_attribute *attr, const char *buf, 83 struct sysdev_attribute *attr, const char *buf,
84 size_t count) 84 size_t count)
85{ 85{
86 unsigned long val; 86 unsigned long val;
@@ -93,16 +93,16 @@ static ssize_t store_pc1event(struct device *dev,
93 sysreg_write(PCCR, val); 93 sysreg_write(PCCR, val);
94 return count; 94 return count;
95} 95}
96static ssize_t show_pc1count(struct device *dev, 96static ssize_t show_pc1count(struct sys_device *dev,
97 struct device_attribute *attr, char *buf) 97 struct sysdev_attribute *attr, char *buf)
98{ 98{
99 unsigned long pcnt1; 99 unsigned long pcnt1;
100 100
101 pcnt1 = sysreg_read(PCNT1); 101 pcnt1 = sysreg_read(PCNT1);
102 return sprintf(buf, "%lu\n", pcnt1); 102 return sprintf(buf, "%lu\n", pcnt1);
103} 103}
104static ssize_t store_pc1count(struct device *dev, 104static ssize_t store_pc1count(struct sys_device *dev,
105 struct device_attribute *attr, const char *buf, 105 struct sysdev_attribute *attr, const char *buf,
106 size_t count) 106 size_t count)
107{ 107{
108 unsigned long val; 108 unsigned long val;
@@ -116,16 +116,16 @@ static ssize_t store_pc1count(struct device *dev,
116 return count; 116 return count;
117} 117}
118 118
119static ssize_t show_pccycles(struct device *dev, 119static ssize_t show_pccycles(struct sys_device *dev,
120 struct device_attribute *attr, char *buf) 120 struct sysdev_attribute *attr, char *buf)
121{ 121{
122 unsigned long pccnt; 122 unsigned long pccnt;
123 123
124 pccnt = sysreg_read(PCCNT); 124 pccnt = sysreg_read(PCCNT);
125 return sprintf(buf, "%lu\n", pccnt); 125 return sprintf(buf, "%lu\n", pccnt);
126} 126}
127static ssize_t store_pccycles(struct device *dev, 127static ssize_t store_pccycles(struct sys_device *dev,
128 struct device_attribute *attr, const char *buf, 128 struct sysdev_attribute *attr, const char *buf,
129 size_t count) 129 size_t count)
130{ 130{
131 unsigned long val; 131 unsigned long val;
@@ -139,16 +139,16 @@ static ssize_t store_pccycles(struct device *dev,
139 return count; 139 return count;
140} 140}
141 141
142static ssize_t show_pcenable(struct device *dev, 142static ssize_t show_pcenable(struct sys_device *dev,
143 struct device_attribute *attr, char *buf) 143 struct sysdev_attribute *attr, char *buf)
144{ 144{
145 unsigned long pccr; 145 unsigned long pccr;
146 146
147 pccr = sysreg_read(PCCR); 147 pccr = sysreg_read(PCCR);
148 return sprintf(buf, "%c\n", (pccr & 1)?'1':'0'); 148 return sprintf(buf, "%c\n", (pccr & 1)?'1':'0');
149} 149}
150static ssize_t store_pcenable(struct device *dev, 150static ssize_t store_pcenable(struct sys_device *dev,
151 struct device_attribute *attr, const char *buf, 151 struct sysdev_attribute *attr, const char *buf,
152 size_t count) 152 size_t count)
153{ 153{
154 unsigned long pccr, val; 154 unsigned long pccr, val;
@@ -167,12 +167,12 @@ static ssize_t store_pcenable(struct device *dev,
167 return count; 167 return count;
168} 168}
169 169
170static DEVICE_ATTR(pc0event, 0600, show_pc0event, store_pc0event); 170static SYSDEV_ATTR(pc0event, 0600, show_pc0event, store_pc0event);
171static DEVICE_ATTR(pc0count, 0600, show_pc0count, store_pc0count); 171static SYSDEV_ATTR(pc0count, 0600, show_pc0count, store_pc0count);
172static DEVICE_ATTR(pc1event, 0600, show_pc1event, store_pc1event); 172static SYSDEV_ATTR(pc1event, 0600, show_pc1event, store_pc1event);
173static DEVICE_ATTR(pc1count, 0600, show_pc1count, store_pc1count); 173static SYSDEV_ATTR(pc1count, 0600, show_pc1count, store_pc1count);
174static DEVICE_ATTR(pccycles, 0600, show_pccycles, store_pccycles); 174static SYSDEV_ATTR(pccycles, 0600, show_pccycles, store_pccycles);
175static DEVICE_ATTR(pcenable, 0600, show_pcenable, store_pcenable); 175static SYSDEV_ATTR(pcenable, 0600, show_pcenable, store_pcenable);
176 176
177#endif /* CONFIG_PERFORMANCE_COUNTERS */ 177#endif /* CONFIG_PERFORMANCE_COUNTERS */
178 178
@@ -186,12 +186,12 @@ static int __init topology_init(void)
186 register_cpu(c, cpu); 186 register_cpu(c, cpu);
187 187
188#ifdef CONFIG_PERFORMANCE_COUNTERS 188#ifdef CONFIG_PERFORMANCE_COUNTERS
189 device_create_file(&c->dev, &dev_attr_pc0event); 189 sysdev_create_file(&c->sysdev, &attr_pc0event);
190 device_create_file(&c->dev, &dev_attr_pc0count); 190 sysdev_create_file(&c->sysdev, &attr_pc0count);
191 device_create_file(&c->dev, &dev_attr_pc1event); 191 sysdev_create_file(&c->sysdev, &attr_pc1event);
192 device_create_file(&c->dev, &dev_attr_pc1count); 192 sysdev_create_file(&c->sysdev, &attr_pc1count);
193 device_create_file(&c->dev, &dev_attr_pccycles); 193 sysdev_create_file(&c->sysdev, &attr_pccycles);
194 device_create_file(&c->dev, &dev_attr_pcenable); 194 sysdev_create_file(&c->sysdev, &attr_pcenable);
195#endif 195#endif
196 } 196 }
197 197
diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S
index 9899d3cc6f0..169268c40ae 100644
--- a/arch/avr32/kernel/entry-avr32b.S
+++ b/arch/avr32/kernel/entry-avr32b.S
@@ -251,15 +251,13 @@ syscall_badsys:
251 .global ret_from_fork 251 .global ret_from_fork
252ret_from_fork: 252ret_from_fork:
253 call schedule_tail 253 call schedule_tail
254 mov r12, 0
255 rjmp syscall_return
256 254
257 .global ret_from_kernel_thread 255 /* check for syscall tracing */
258ret_from_kernel_thread: 256 get_thread_info r0
259 call schedule_tail 257 ld.w r1, r0[TI_flags]
260 mov r12, r0 258 andl r1, _TIF_ALLWORK_MASK, COH
261 mov lr, r2 /* syscall_return */ 259 brne syscall_exit_work
262 mov pc, r1 260 rjmp syscall_exit_cont
263 261
264syscall_trace_enter: 262syscall_trace_enter:
265 pushm r8-r12 263 pushm r8-r12
@@ -283,7 +281,7 @@ syscall_exit_work:
283 ld.w r1, r0[TI_flags] 281 ld.w r1, r0[TI_flags]
284 rjmp 1b 282 rjmp 1b
285 283
2862: mov r2, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME 2842: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NOTIFY_RESUME
287 tst r1, r2 285 tst r1, r2
288 breq 3f 286 breq 3f
289 unmask_interrupts 287 unmask_interrupts
@@ -589,7 +587,7 @@ fault_exit_work:
589 ld.w r1, r0[TI_flags] 587 ld.w r1, r0[TI_flags]
590 rjmp fault_exit_work 588 rjmp fault_exit_work
591 589
5921: mov r2, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME 5901: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK
593 tst r1, r2 591 tst r1, r2
594 breq 2f 592 breq 2f
595 unmask_interrupts 593 unmask_interrupts
diff --git a/arch/avr32/kernel/irq.c b/arch/avr32/kernel/irq.c
index 900e49b2258..bc3aa18293d 100644
--- a/arch/avr32/kernel/irq.c
+++ b/arch/avr32/kernel/irq.c
@@ -14,7 +14,7 @@
14#include <linux/kernel_stat.h> 14#include <linux/kernel_stat.h>
15#include <linux/proc_fs.h> 15#include <linux/proc_fs.h>
16#include <linux/seq_file.h> 16#include <linux/seq_file.h>
17#include <linux/device.h> 17#include <linux/sysdev.h>
18 18
19/* May be overridden by platform code */ 19/* May be overridden by platform code */
20int __weak nmi_enable(void) 20int __weak nmi_enable(void)
diff --git a/arch/avr32/kernel/process.c b/arch/avr32/kernel/process.c
index fd78f58ea79..ef5a2a08fcc 100644
--- a/arch/avr32/kernel/process.c
+++ b/arch/avr32/kernel/process.c
@@ -34,13 +34,13 @@ void cpu_idle(void)
34{ 34{
35 /* endless idle loop with no priority at all */ 35 /* endless idle loop with no priority at all */
36 while (1) { 36 while (1) {
37 tick_nohz_idle_enter(); 37 tick_nohz_stop_sched_tick(1);
38 rcu_idle_enter();
39 while (!need_resched()) 38 while (!need_resched())
40 cpu_idle_sleep(); 39 cpu_idle_sleep();
41 rcu_idle_exit(); 40 tick_nohz_restart_sched_tick();
42 tick_nohz_idle_exit(); 41 preempt_enable_no_resched();
43 schedule_preempt_disabled(); 42 schedule();
43 preempt_disable();
44 } 44 }
45} 45}
46 46
@@ -69,6 +69,44 @@ void machine_restart(char *cmd)
69} 69}
70 70
71/* 71/*
72 * PC is actually discarded when returning from a system call -- the
73 * return address must be stored in LR. This function will make sure
74 * LR points to do_exit before starting the thread.
75 *
76 * Also, when returning from fork(), r12 is 0, so we must copy the
77 * argument as well.
78 *
79 * r0 : The argument to the main thread function
80 * r1 : The address of do_exit
81 * r2 : The address of the main thread function
82 */
83asmlinkage extern void kernel_thread_helper(void);
84__asm__(" .type kernel_thread_helper, @function\n"
85 "kernel_thread_helper:\n"
86 " mov r12, r0\n"
87 " mov lr, r2\n"
88 " mov pc, r1\n"
89 " .size kernel_thread_helper, . - kernel_thread_helper");
90
91int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
92{
93 struct pt_regs regs;
94
95 memset(&regs, 0, sizeof(regs));
96
97 regs.r0 = (unsigned long)arg;
98 regs.r1 = (unsigned long)fn;
99 regs.r2 = (unsigned long)do_exit;
100 regs.lr = (unsigned long)kernel_thread_helper;
101 regs.pc = (unsigned long)kernel_thread_helper;
102 regs.sr = MODE_SUPERVISOR;
103
104 return do_fork(flags | CLONE_VM | CLONE_UNTRACED,
105 0, &regs, 0, NULL, NULL);
106}
107EXPORT_SYMBOL(kernel_thread);
108
109/*
72 * Free current thread data structures etc 110 * Free current thread data structures etc
73 */ 111 */
74void exit_thread(void) 112void exit_thread(void)
@@ -294,32 +332,26 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
294} 332}
295 333
296asmlinkage void ret_from_fork(void); 334asmlinkage void ret_from_fork(void);
297asmlinkage void ret_from_kernel_thread(void);
298asmlinkage void syscall_return(void);
299 335
300int copy_thread(unsigned long clone_flags, unsigned long usp, 336int copy_thread(unsigned long clone_flags, unsigned long usp,
301 unsigned long arg, 337 unsigned long unused,
302 struct task_struct *p) 338 struct task_struct *p, struct pt_regs *regs)
303{ 339{
304 struct pt_regs *childregs = task_pt_regs(p); 340 struct pt_regs *childregs;
305 341
306 if (unlikely(p->flags & PF_KTHREAD)) { 342 childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long)task_stack_page(p))) - 1;
307 memset(childregs, 0, sizeof(struct pt_regs)); 343 *childregs = *regs;
308 p->thread.cpu_context.r0 = arg; 344
309 p->thread.cpu_context.r1 = usp; /* fn */ 345 if (user_mode(regs))
310 p->thread.cpu_context.r2 = syscall_return; 346 childregs->sp = usp;
311 p->thread.cpu_context.pc = (unsigned long)ret_from_kernel_thread; 347 else
312 childregs->sr = MODE_SUPERVISOR; 348 childregs->sp = (unsigned long)task_stack_page(p) + THREAD_SIZE;
313 } else { 349
314 *childregs = *current_pt_regs(); 350 childregs->r12 = 0; /* Set return value for child */
315 if (usp)
316 childregs->sp = usp;
317 childregs->r12 = 0; /* Set return value for child */
318 p->thread.cpu_context.pc = (unsigned long)ret_from_fork;
319 }
320 351
321 p->thread.cpu_context.sr = MODE_SUPERVISOR | SR_GM; 352 p->thread.cpu_context.sr = MODE_SUPERVISOR | SR_GM;
322 p->thread.cpu_context.ksp = (unsigned long)childregs; 353 p->thread.cpu_context.ksp = (unsigned long)childregs;
354 p->thread.cpu_context.pc = (unsigned long)ret_from_fork;
323 355
324 clear_tsk_thread_flag(p, TIF_DEBUG); 356 clear_tsk_thread_flag(p, TIF_DEBUG);
325 if ((clone_flags & CLONE_PTRACE) && test_thread_flag(TIF_DEBUG)) 357 if ((clone_flags & CLONE_PTRACE) && test_thread_flag(TIF_DEBUG))
@@ -328,6 +360,49 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
328 return 0; 360 return 0;
329} 361}
330 362
363/* r12-r8 are dummy parameters to force the compiler to use the stack */
364asmlinkage int sys_fork(struct pt_regs *regs)
365{
366 return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL);
367}
368
369asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
370 void __user *parent_tidptr, void __user *child_tidptr,
371 struct pt_regs *regs)
372{
373 if (!newsp)
374 newsp = regs->sp;
375 return do_fork(clone_flags, newsp, regs, 0, parent_tidptr,
376 child_tidptr);
377}
378
379asmlinkage int sys_vfork(struct pt_regs *regs)
380{
381 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp, regs,
382 0, NULL, NULL);
383}
384
385asmlinkage int sys_execve(const char __user *ufilename,
386 const char __user *const __user *uargv,
387 const char __user *const __user *uenvp,
388 struct pt_regs *regs)
389{
390 int error;
391 char *filename;
392
393 filename = getname(ufilename);
394 error = PTR_ERR(filename);
395 if (IS_ERR(filename))
396 goto out;
397
398 error = do_execve(filename, uargv, uenvp, regs);
399 putname(filename);
400
401out:
402 return error;
403}
404
405
331/* 406/*
332 * This function is supposed to answer the question "who called 407 * This function is supposed to answer the question "who called
333 * schedule()?" 408 * schedule()?"
diff --git a/arch/avr32/kernel/signal.c b/arch/avr32/kernel/signal.c
index 5e01c3a40ce..64f886fac2e 100644
--- a/arch/avr32/kernel/signal.c
+++ b/arch/avr32/kernel/signal.c
@@ -15,12 +15,15 @@
15#include <linux/errno.h> 15#include <linux/errno.h>
16#include <linux/ptrace.h> 16#include <linux/ptrace.h>
17#include <linux/unistd.h> 17#include <linux/unistd.h>
18#include <linux/freezer.h>
18#include <linux/tracehook.h> 19#include <linux/tracehook.h>
19 20
20#include <asm/uaccess.h> 21#include <asm/uaccess.h>
21#include <asm/ucontext.h> 22#include <asm/ucontext.h>
22#include <asm/syscalls.h> 23#include <asm/syscalls.h>
23 24
25#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
26
24asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, 27asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
25 struct pt_regs *regs) 28 struct pt_regs *regs)
26{ 29{
@@ -74,9 +77,6 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
74 struct rt_sigframe __user *frame; 77 struct rt_sigframe __user *frame;
75 sigset_t set; 78 sigset_t set;
76 79
77 /* Always make any pending restarted system calls return -EINTR */
78 current_thread_info()->restart_block.fn = do_no_restart_syscall;
79
80 frame = (struct rt_sigframe __user *)regs->sp; 80 frame = (struct rt_sigframe __user *)regs->sp;
81 pr_debug("SIG return: frame = %p\n", frame); 81 pr_debug("SIG return: frame = %p\n", frame);
82 82
@@ -86,7 +86,11 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
86 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) 86 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
87 goto badframe; 87 goto badframe;
88 88
89 set_current_blocked(&set); 89 sigdelsetmask(&set, ~_BLOCKABLE);
90 spin_lock_irq(&current->sighand->siglock);
91 current->blocked = set;
92 recalc_sigpending();
93 spin_unlock_irq(&current->sighand->siglock);
90 94
91 if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) 95 if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
92 goto badframe; 96 goto badframe;
@@ -220,14 +224,14 @@ static inline void setup_syscall_restart(struct pt_regs *regs)
220 224
221static inline void 225static inline void
222handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, 226handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
223 struct pt_regs *regs, int syscall) 227 sigset_t *oldset, struct pt_regs *regs, int syscall)
224{ 228{
225 int ret; 229 int ret;
226 230
227 /* 231 /*
228 * Set up the stack frame 232 * Set up the stack frame
229 */ 233 */
230 ret = setup_rt_frame(sig, ka, info, sigmask_to_save(), regs); 234 ret = setup_rt_frame(sig, ka, info, oldset, regs);
231 235
232 /* 236 /*
233 * Check that the resulting registers are sane 237 * Check that the resulting registers are sane
@@ -235,12 +239,21 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
235 ret |= !valid_user_regs(regs); 239 ret |= !valid_user_regs(regs);
236 240
237 /* 241 /*
238 * Block the signal if we were successful. 242 * Block the signal if we were unsuccessful.
239 */ 243 */
240 if (ret != 0) 244 if (ret != 0 || !(ka->sa.sa_flags & SA_NODEFER)) {
241 force_sigsegv(sig, current); 245 spin_lock_irq(&current->sighand->siglock);
242 else 246 sigorsets(&current->blocked, &current->blocked,
243 signal_delivered(sig, info, ka, regs, 0); 247 &ka->sa.sa_mask);
248 sigaddset(&current->blocked, sig);
249 recalc_sigpending();
250 spin_unlock_irq(&current->sighand->siglock);
251 }
252
253 if (ret == 0)
254 return;
255
256 force_sigsegv(sig, current);
244} 257}
245 258
246/* 259/*
@@ -248,7 +261,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
248 * doesn't want to handle. Thus you cannot kill init even with a 261 * doesn't want to handle. Thus you cannot kill init even with a
249 * SIGKILL even by mistake. 262 * SIGKILL even by mistake.
250 */ 263 */
251static void do_signal(struct pt_regs *regs, int syscall) 264int do_signal(struct pt_regs *regs, sigset_t *oldset, int syscall)
252{ 265{
253 siginfo_t info; 266 siginfo_t info;
254 int signr; 267 int signr;
@@ -260,7 +273,12 @@ static void do_signal(struct pt_regs *regs, int syscall)
260 * without doing anything if so. 273 * without doing anything if so.
261 */ 274 */
262 if (!user_mode(regs)) 275 if (!user_mode(regs))
263 return; 276 return 0;
277
278 if (test_thread_flag(TIF_RESTORE_SIGMASK))
279 oldset = &current->saved_sigmask;
280 else if (!oldset)
281 oldset = &current->blocked;
264 282
265 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 283 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
266 if (syscall) { 284 if (syscall) {
@@ -285,11 +303,15 @@ static void do_signal(struct pt_regs *regs, int syscall)
285 303
286 if (signr == 0) { 304 if (signr == 0) {
287 /* No signal to deliver -- put the saved sigmask back */ 305 /* No signal to deliver -- put the saved sigmask back */
288 restore_saved_sigmask(); 306 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
289 return; 307 clear_thread_flag(TIF_RESTORE_SIGMASK);
308 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
309 }
310 return 0;
290 } 311 }
291 312
292 handle_signal(signr, &ka, &info, regs, syscall); 313 handle_signal(signr, &ka, &info, oldset, regs, syscall);
314 return 1;
293} 315}
294 316
295asmlinkage void do_notify_resume(struct pt_regs *regs, struct thread_info *ti) 317asmlinkage void do_notify_resume(struct pt_regs *regs, struct thread_info *ti)
@@ -299,11 +321,13 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, struct thread_info *ti)
299 if ((sysreg_read(SR) & MODE_MASK) == MODE_SUPERVISOR) 321 if ((sysreg_read(SR) & MODE_MASK) == MODE_SUPERVISOR)
300 syscall = 1; 322 syscall = 1;
301 323
302 if (ti->flags & _TIF_SIGPENDING) 324 if (ti->flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
303 do_signal(regs, syscall); 325 do_signal(regs, &current->blocked, syscall);
304 326
305 if (ti->flags & _TIF_NOTIFY_RESUME) { 327 if (ti->flags & _TIF_NOTIFY_RESUME) {
306 clear_thread_flag(TIF_NOTIFY_RESUME); 328 clear_thread_flag(TIF_NOTIFY_RESUME);
307 tracehook_notify_resume(regs); 329 tracehook_notify_resume(regs);
330 if (current->replacement_session_keyring)
331 key_replace_session_keyring();
308 } 332 }
309} 333}
diff --git a/arch/avr32/kernel/syscall-stubs.S b/arch/avr32/kernel/syscall-stubs.S
index 275aab9731f..0447a3e2ba6 100644
--- a/arch/avr32/kernel/syscall-stubs.S
+++ b/arch/avr32/kernel/syscall-stubs.S
@@ -32,6 +32,30 @@ __sys_rt_sigreturn:
32 mov r12, sp 32 mov r12, sp
33 rjmp sys_rt_sigreturn 33 rjmp sys_rt_sigreturn
34 34
35 .global __sys_fork
36 .type __sys_fork,@function
37__sys_fork:
38 mov r12, sp
39 rjmp sys_fork
40
41 .global __sys_clone
42 .type __sys_clone,@function
43__sys_clone:
44 mov r8, sp
45 rjmp sys_clone
46
47 .global __sys_vfork
48 .type __sys_vfork,@function
49__sys_vfork:
50 mov r12, sp
51 rjmp sys_vfork
52
53 .global __sys_execve
54 .type __sys_execve,@function
55__sys_execve:
56 mov r9, sp
57 rjmp sys_execve
58
35 .global __sys_mmap2 59 .global __sys_mmap2
36 .type __sys_mmap2,@function 60 .type __sys_mmap2,@function
37__sys_mmap2: 61__sys_mmap2:
diff --git a/arch/avr32/kernel/syscall_table.S b/arch/avr32/kernel/syscall_table.S
index f27bb878da6..6eba53530d1 100644
--- a/arch/avr32/kernel/syscall_table.S
+++ b/arch/avr32/kernel/syscall_table.S
@@ -15,7 +15,7 @@
15sys_call_table: 15sys_call_table:
16 .long sys_restart_syscall 16 .long sys_restart_syscall
17 .long sys_exit 17 .long sys_exit
18 .long sys_fork 18 .long __sys_fork
19 .long sys_read 19 .long sys_read
20 .long sys_write 20 .long sys_write
21 .long sys_open /* 5 */ 21 .long sys_open /* 5 */
@@ -24,7 +24,7 @@ sys_call_table:
24 .long sys_creat 24 .long sys_creat
25 .long sys_link 25 .long sys_link
26 .long sys_unlink /* 10 */ 26 .long sys_unlink /* 10 */
27 .long sys_execve 27 .long __sys_execve
28 .long sys_chdir 28 .long sys_chdir
29 .long sys_time 29 .long sys_time
30 .long sys_mknod 30 .long sys_mknod
@@ -57,7 +57,7 @@ sys_call_table:
57 .long sys_dup 57 .long sys_dup
58 .long sys_pipe 58 .long sys_pipe
59 .long sys_times 59 .long sys_times
60 .long sys_clone 60 .long __sys_clone
61 .long sys_brk /* 45 */ 61 .long sys_brk /* 45 */
62 .long sys_setgid 62 .long sys_setgid
63 .long sys_getgid 63 .long sys_getgid
@@ -127,7 +127,7 @@ sys_call_table:
127 .long sys_newuname 127 .long sys_newuname
128 .long sys_adjtimex 128 .long sys_adjtimex
129 .long sys_mprotect 129 .long sys_mprotect
130 .long sys_vfork 130 .long __sys_vfork
131 .long sys_init_module /* 115 */ 131 .long sys_init_module /* 115 */
132 .long sys_delete_module 132 .long sys_delete_module
133 .long sys_quotactl 133 .long sys_quotactl
diff --git a/arch/avr32/kernel/traps.c b/arch/avr32/kernel/traps.c
index 3d760c06f02..7aa25756412 100644
--- a/arch/avr32/kernel/traps.c
+++ b/arch/avr32/kernel/traps.c
@@ -24,7 +24,7 @@
24 24
25static DEFINE_SPINLOCK(die_lock); 25static DEFINE_SPINLOCK(die_lock);
26 26
27void die(const char *str, struct pt_regs *regs, long err) 27void NORET_TYPE die(const char *str, struct pt_regs *regs, long err)
28{ 28{
29 static int die_counter; 29 static int die_counter;
30 30