aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r--arch/arm/kernel/leds.c28
-rw-r--r--arch/arm/kernel/perf_event.c5
-rw-r--r--arch/arm/kernel/ptrace.c348
-rw-r--r--arch/arm/kernel/setup.c13
-rw-r--r--arch/arm/kernel/signal.c90
-rw-r--r--arch/arm/kernel/smp.c12
-rw-r--r--arch/arm/kernel/time.c35
-rw-r--r--arch/arm/kernel/traps.c1
8 files changed, 337 insertions, 195 deletions
diff --git a/arch/arm/kernel/leds.c b/arch/arm/kernel/leds.c
index 31a316c1777b..0f107dcb0347 100644
--- a/arch/arm/kernel/leds.c
+++ b/arch/arm/kernel/leds.c
@@ -10,6 +10,7 @@
10#include <linux/module.h> 10#include <linux/module.h>
11#include <linux/init.h> 11#include <linux/init.h>
12#include <linux/sysdev.h> 12#include <linux/sysdev.h>
13#include <linux/syscore_ops.h>
13 14
14#include <asm/leds.h> 15#include <asm/leds.h>
15 16
@@ -69,36 +70,37 @@ static ssize_t leds_store(struct sys_device *dev,
69 70
70static SYSDEV_ATTR(event, 0200, NULL, leds_store); 71static SYSDEV_ATTR(event, 0200, NULL, leds_store);
71 72
72static int leds_suspend(struct sys_device *dev, pm_message_t state) 73static struct sysdev_class leds_sysclass = {
74 .name = "leds",
75};
76
77static struct sys_device leds_device = {
78 .id = 0,
79 .cls = &leds_sysclass,
80};
81
82static int leds_suspend(void)
73{ 83{
74 leds_event(led_stop); 84 leds_event(led_stop);
75 return 0; 85 return 0;
76} 86}
77 87
78static int leds_resume(struct sys_device *dev) 88static void leds_resume(void)
79{ 89{
80 leds_event(led_start); 90 leds_event(led_start);
81 return 0;
82} 91}
83 92
84static int leds_shutdown(struct sys_device *dev) 93static void leds_shutdown(void)
85{ 94{
86 leds_event(led_halted); 95 leds_event(led_halted);
87 return 0;
88} 96}
89 97
90static struct sysdev_class leds_sysclass = { 98static struct syscore_ops leds_syscore_ops = {
91 .name = "leds",
92 .shutdown = leds_shutdown, 99 .shutdown = leds_shutdown,
93 .suspend = leds_suspend, 100 .suspend = leds_suspend,
94 .resume = leds_resume, 101 .resume = leds_resume,
95}; 102};
96 103
97static struct sys_device leds_device = {
98 .id = 0,
99 .cls = &leds_sysclass,
100};
101
102static int __init leds_init(void) 104static int __init leds_init(void)
103{ 105{
104 int ret; 106 int ret;
@@ -107,6 +109,8 @@ static int __init leds_init(void)
107 ret = sysdev_register(&leds_device); 109 ret = sysdev_register(&leds_device);
108 if (ret == 0) 110 if (ret == 0)
109 ret = sysdev_create_file(&leds_device, &attr_event); 111 ret = sysdev_create_file(&leds_device, &attr_event);
112 if (ret == 0)
113 register_syscore_ops(&leds_syscore_ops);
110 return ret; 114 return ret;
111} 115}
112 116
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index 139e3c827369..d53c0abc4dd3 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -560,11 +560,6 @@ static int armpmu_event_init(struct perf_event *event)
560 event->destroy = hw_perf_event_destroy; 560 event->destroy = hw_perf_event_destroy;
561 561
562 if (!atomic_inc_not_zero(&active_events)) { 562 if (!atomic_inc_not_zero(&active_events)) {
563 if (atomic_read(&active_events) > armpmu->num_events) {
564 atomic_dec(&active_events);
565 return -ENOSPC;
566 }
567
568 mutex_lock(&pmu_reserve_mutex); 563 mutex_lock(&pmu_reserve_mutex);
569 if (atomic_read(&active_events) == 0) { 564 if (atomic_read(&active_events) == 0) {
570 err = armpmu_reserve_hardware(); 565 err = armpmu_reserve_hardware();
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 8182f45ca493..97260060bf26 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -21,6 +21,7 @@
21#include <linux/uaccess.h> 21#include <linux/uaccess.h>
22#include <linux/perf_event.h> 22#include <linux/perf_event.h>
23#include <linux/hw_breakpoint.h> 23#include <linux/hw_breakpoint.h>
24#include <linux/regset.h>
24 25
25#include <asm/pgtable.h> 26#include <asm/pgtable.h>
26#include <asm/system.h> 27#include <asm/system.h>
@@ -308,58 +309,6 @@ static int ptrace_write_user(struct task_struct *tsk, unsigned long off,
308 return put_user_reg(tsk, off >> 2, val); 309 return put_user_reg(tsk, off >> 2, val);
309} 310}
310 311
311/*
312 * Get all user integer registers.
313 */
314static int ptrace_getregs(struct task_struct *tsk, void __user *uregs)
315{
316 struct pt_regs *regs = task_pt_regs(tsk);
317
318 return copy_to_user(uregs, regs, sizeof(struct pt_regs)) ? -EFAULT : 0;
319}
320
321/*
322 * Set all user integer registers.
323 */
324static int ptrace_setregs(struct task_struct *tsk, void __user *uregs)
325{
326 struct pt_regs newregs;
327 int ret;
328
329 ret = -EFAULT;
330 if (copy_from_user(&newregs, uregs, sizeof(struct pt_regs)) == 0) {
331 struct pt_regs *regs = task_pt_regs(tsk);
332
333 ret = -EINVAL;
334 if (valid_user_regs(&newregs)) {
335 *regs = newregs;
336 ret = 0;
337 }
338 }
339
340 return ret;
341}
342
343/*
344 * Get the child FPU state.
345 */
346static int ptrace_getfpregs(struct task_struct *tsk, void __user *ufp)
347{
348 return copy_to_user(ufp, &task_thread_info(tsk)->fpstate,
349 sizeof(struct user_fp)) ? -EFAULT : 0;
350}
351
352/*
353 * Set the child FPU state.
354 */
355static int ptrace_setfpregs(struct task_struct *tsk, void __user *ufp)
356{
357 struct thread_info *thread = task_thread_info(tsk);
358 thread->used_cp[1] = thread->used_cp[2] = 1;
359 return copy_from_user(&thread->fpstate, ufp,
360 sizeof(struct user_fp)) ? -EFAULT : 0;
361}
362
363#ifdef CONFIG_IWMMXT 312#ifdef CONFIG_IWMMXT
364 313
365/* 314/*
@@ -418,56 +367,6 @@ static int ptrace_setcrunchregs(struct task_struct *tsk, void __user *ufp)
418} 367}
419#endif 368#endif
420 369
421#ifdef CONFIG_VFP
422/*
423 * Get the child VFP state.
424 */
425static int ptrace_getvfpregs(struct task_struct *tsk, void __user *data)
426{
427 struct thread_info *thread = task_thread_info(tsk);
428 union vfp_state *vfp = &thread->vfpstate;
429 struct user_vfp __user *ufp = data;
430
431 vfp_sync_hwstate(thread);
432
433 /* copy the floating point registers */
434 if (copy_to_user(&ufp->fpregs, &vfp->hard.fpregs,
435 sizeof(vfp->hard.fpregs)))
436 return -EFAULT;
437
438 /* copy the status and control register */
439 if (put_user(vfp->hard.fpscr, &ufp->fpscr))
440 return -EFAULT;
441
442 return 0;
443}
444
445/*
446 * Set the child VFP state.
447 */
448static int ptrace_setvfpregs(struct task_struct *tsk, void __user *data)
449{
450 struct thread_info *thread = task_thread_info(tsk);
451 union vfp_state *vfp = &thread->vfpstate;
452 struct user_vfp __user *ufp = data;
453
454 vfp_sync_hwstate(thread);
455
456 /* copy the floating point registers */
457 if (copy_from_user(&vfp->hard.fpregs, &ufp->fpregs,
458 sizeof(vfp->hard.fpregs)))
459 return -EFAULT;
460
461 /* copy the status and control register */
462 if (get_user(vfp->hard.fpscr, &ufp->fpscr))
463 return -EFAULT;
464
465 vfp_flush_hwstate(thread);
466
467 return 0;
468}
469#endif
470
471#ifdef CONFIG_HAVE_HW_BREAKPOINT 370#ifdef CONFIG_HAVE_HW_BREAKPOINT
472/* 371/*
473 * Convert a virtual register number into an index for a thread_info 372 * Convert a virtual register number into an index for a thread_info
@@ -694,6 +593,219 @@ out:
694} 593}
695#endif 594#endif
696 595
596/* regset get/set implementations */
597
598static int gpr_get(struct task_struct *target,
599 const struct user_regset *regset,
600 unsigned int pos, unsigned int count,
601 void *kbuf, void __user *ubuf)
602{
603 struct pt_regs *regs = task_pt_regs(target);
604
605 return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
606 regs,
607 0, sizeof(*regs));
608}
609
610static int gpr_set(struct task_struct *target,
611 const struct user_regset *regset,
612 unsigned int pos, unsigned int count,
613 const void *kbuf, const void __user *ubuf)
614{
615 int ret;
616 struct pt_regs newregs;
617
618 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
619 &newregs,
620 0, sizeof(newregs));
621 if (ret)
622 return ret;
623
624 if (!valid_user_regs(&newregs))
625 return -EINVAL;
626
627 *task_pt_regs(target) = newregs;
628 return 0;
629}
630
631static int fpa_get(struct task_struct *target,
632 const struct user_regset *regset,
633 unsigned int pos, unsigned int count,
634 void *kbuf, void __user *ubuf)
635{
636 return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
637 &task_thread_info(target)->fpstate,
638 0, sizeof(struct user_fp));
639}
640
641static int fpa_set(struct task_struct *target,
642 const struct user_regset *regset,
643 unsigned int pos, unsigned int count,
644 const void *kbuf, const void __user *ubuf)
645{
646 struct thread_info *thread = task_thread_info(target);
647
648 thread->used_cp[1] = thread->used_cp[2] = 1;
649
650 return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
651 &thread->fpstate,
652 0, sizeof(struct user_fp));
653}
654
655#ifdef CONFIG_VFP
656/*
657 * VFP register get/set implementations.
658 *
659 * With respect to the kernel, struct user_fp is divided into three chunks:
660 * 16 or 32 real VFP registers (d0-d15 or d0-31)
661 * These are transferred to/from the real registers in the task's
662 * vfp_hard_struct. The number of registers depends on the kernel
663 * configuration.
664 *
665 * 16 or 0 fake VFP registers (d16-d31 or empty)
666 * i.e., the user_vfp structure has space for 32 registers even if
667 * the kernel doesn't have them all.
668 *
669 * vfp_get() reads this chunk as zero where applicable
670 * vfp_set() ignores this chunk
671 *
672 * 1 word for the FPSCR
673 *
674 * The bounds-checking logic built into user_regset_copyout and friends
675 * means that we can make a simple sequence of calls to map the relevant data
676 * to/from the specified slice of the user regset structure.
677 */
678static int vfp_get(struct task_struct *target,
679 const struct user_regset *regset,
680 unsigned int pos, unsigned int count,
681 void *kbuf, void __user *ubuf)
682{
683 int ret;
684 struct thread_info *thread = task_thread_info(target);
685 struct vfp_hard_struct const *vfp = &thread->vfpstate.hard;
686 const size_t user_fpregs_offset = offsetof(struct user_vfp, fpregs);
687 const size_t user_fpscr_offset = offsetof(struct user_vfp, fpscr);
688
689 vfp_sync_hwstate(thread);
690
691 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
692 &vfp->fpregs,
693 user_fpregs_offset,
694 user_fpregs_offset + sizeof(vfp->fpregs));
695 if (ret)
696 return ret;
697
698 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
699 user_fpregs_offset + sizeof(vfp->fpregs),
700 user_fpscr_offset);
701 if (ret)
702 return ret;
703
704 return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
705 &vfp->fpscr,
706 user_fpscr_offset,
707 user_fpscr_offset + sizeof(vfp->fpscr));
708}
709
710/*
711 * For vfp_set() a read-modify-write is done on the VFP registers,
712 * in order to avoid writing back a half-modified set of registers on
713 * failure.
714 */
715static int vfp_set(struct task_struct *target,
716 const struct user_regset *regset,
717 unsigned int pos, unsigned int count,
718 const void *kbuf, const void __user *ubuf)
719{
720 int ret;
721 struct thread_info *thread = task_thread_info(target);
722 struct vfp_hard_struct new_vfp = thread->vfpstate.hard;
723 const size_t user_fpregs_offset = offsetof(struct user_vfp, fpregs);
724 const size_t user_fpscr_offset = offsetof(struct user_vfp, fpscr);
725
726 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
727 &new_vfp.fpregs,
728 user_fpregs_offset,
729 user_fpregs_offset + sizeof(new_vfp.fpregs));
730 if (ret)
731 return ret;
732
733 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
734 user_fpregs_offset + sizeof(new_vfp.fpregs),
735 user_fpscr_offset);
736 if (ret)
737 return ret;
738
739 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
740 &new_vfp.fpscr,
741 user_fpscr_offset,
742 user_fpscr_offset + sizeof(new_vfp.fpscr));
743 if (ret)
744 return ret;
745
746 vfp_sync_hwstate(thread);
747 thread->vfpstate.hard = new_vfp;
748 vfp_flush_hwstate(thread);
749
750 return 0;
751}
752#endif /* CONFIG_VFP */
753
754enum arm_regset {
755 REGSET_GPR,
756 REGSET_FPR,
757#ifdef CONFIG_VFP
758 REGSET_VFP,
759#endif
760};
761
762static const struct user_regset arm_regsets[] = {
763 [REGSET_GPR] = {
764 .core_note_type = NT_PRSTATUS,
765 .n = ELF_NGREG,
766 .size = sizeof(u32),
767 .align = sizeof(u32),
768 .get = gpr_get,
769 .set = gpr_set
770 },
771 [REGSET_FPR] = {
772 /*
773 * For the FPA regs in fpstate, the real fields are a mixture
774 * of sizes, so pretend that the registers are word-sized:
775 */
776 .core_note_type = NT_PRFPREG,
777 .n = sizeof(struct user_fp) / sizeof(u32),
778 .size = sizeof(u32),
779 .align = sizeof(u32),
780 .get = fpa_get,
781 .set = fpa_set
782 },
783#ifdef CONFIG_VFP
784 [REGSET_VFP] = {
785 /*
786 * Pretend that the VFP regs are word-sized, since the FPSCR is
787 * a single word dangling at the end of struct user_vfp:
788 */
789 .core_note_type = NT_ARM_VFP,
790 .n = ARM_VFPREGS_SIZE / sizeof(u32),
791 .size = sizeof(u32),
792 .align = sizeof(u32),
793 .get = vfp_get,
794 .set = vfp_set
795 },
796#endif /* CONFIG_VFP */
797};
798
799static const struct user_regset_view user_arm_view = {
800 .name = "arm", .e_machine = ELF_ARCH, .ei_osabi = ELF_OSABI,
801 .regsets = arm_regsets, .n = ARRAY_SIZE(arm_regsets)
802};
803
804const struct user_regset_view *task_user_regset_view(struct task_struct *task)
805{
806 return &user_arm_view;
807}
808
697long arch_ptrace(struct task_struct *child, long request, 809long arch_ptrace(struct task_struct *child, long request,
698 unsigned long addr, unsigned long data) 810 unsigned long addr, unsigned long data)
699{ 811{
@@ -710,19 +822,31 @@ long arch_ptrace(struct task_struct *child, long request,
710 break; 822 break;
711 823
712 case PTRACE_GETREGS: 824 case PTRACE_GETREGS:
713 ret = ptrace_getregs(child, datap); 825 ret = copy_regset_to_user(child,
826 &user_arm_view, REGSET_GPR,
827 0, sizeof(struct pt_regs),
828 datap);
714 break; 829 break;
715 830
716 case PTRACE_SETREGS: 831 case PTRACE_SETREGS:
717 ret = ptrace_setregs(child, datap); 832 ret = copy_regset_from_user(child,
833 &user_arm_view, REGSET_GPR,
834 0, sizeof(struct pt_regs),
835 datap);
718 break; 836 break;
719 837
720 case PTRACE_GETFPREGS: 838 case PTRACE_GETFPREGS:
721 ret = ptrace_getfpregs(child, datap); 839 ret = copy_regset_to_user(child,
840 &user_arm_view, REGSET_FPR,
841 0, sizeof(union fp_state),
842 datap);
722 break; 843 break;
723 844
724 case PTRACE_SETFPREGS: 845 case PTRACE_SETFPREGS:
725 ret = ptrace_setfpregs(child, datap); 846 ret = copy_regset_from_user(child,
847 &user_arm_view, REGSET_FPR,
848 0, sizeof(union fp_state),
849 datap);
726 break; 850 break;
727 851
728#ifdef CONFIG_IWMMXT 852#ifdef CONFIG_IWMMXT
@@ -757,11 +881,17 @@ long arch_ptrace(struct task_struct *child, long request,
757 881
758#ifdef CONFIG_VFP 882#ifdef CONFIG_VFP
759 case PTRACE_GETVFPREGS: 883 case PTRACE_GETVFPREGS:
760 ret = ptrace_getvfpregs(child, datap); 884 ret = copy_regset_to_user(child,
885 &user_arm_view, REGSET_VFP,
886 0, ARM_VFPREGS_SIZE,
887 datap);
761 break; 888 break;
762 889
763 case PTRACE_SETVFPREGS: 890 case PTRACE_SETVFPREGS:
764 ret = ptrace_setvfpregs(child, datap); 891 ret = copy_regset_from_user(child,
892 &user_arm_view, REGSET_VFP,
893 0, ARM_VFPREGS_SIZE,
894 datap);
765 break; 895 break;
766#endif 896#endif
767 897
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 05db25ef3dd5..ed11fb08b05a 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -661,11 +661,16 @@ __tagtable(ATAG_REVISION, parse_tag_revision);
661 661
662static int __init parse_tag_cmdline(const struct tag *tag) 662static int __init parse_tag_cmdline(const struct tag *tag)
663{ 663{
664#ifndef CONFIG_CMDLINE_FORCE 664#if defined(CONFIG_CMDLINE_EXTEND)
665 strlcpy(default_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE); 665 strlcat(default_command_line, " ", COMMAND_LINE_SIZE);
666#else 666 strlcat(default_command_line, tag->u.cmdline.cmdline,
667 COMMAND_LINE_SIZE);
668#elif defined(CONFIG_CMDLINE_FORCE)
667 pr_warning("Ignoring tag cmdline (using the default kernel command line)\n"); 669 pr_warning("Ignoring tag cmdline (using the default kernel command line)\n");
668#endif /* CONFIG_CMDLINE_FORCE */ 670#else
671 strlcpy(default_command_line, tag->u.cmdline.cmdline,
672 COMMAND_LINE_SIZE);
673#endif
669 return 0; 674 return 0;
670} 675}
671 676
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index cb8398317644..0340224cf73c 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -597,19 +597,13 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
597 return err; 597 return err;
598} 598}
599 599
600static inline void setup_syscall_restart(struct pt_regs *regs)
601{
602 regs->ARM_r0 = regs->ARM_ORIG_r0;
603 regs->ARM_pc -= thumb_mode(regs) ? 2 : 4;
604}
605
606/* 600/*
607 * OK, we're invoking a handler 601 * OK, we're invoking a handler
608 */ 602 */
609static int 603static int
610handle_signal(unsigned long sig, struct k_sigaction *ka, 604handle_signal(unsigned long sig, struct k_sigaction *ka,
611 siginfo_t *info, sigset_t *oldset, 605 siginfo_t *info, sigset_t *oldset,
612 struct pt_regs * regs, int syscall) 606 struct pt_regs * regs)
613{ 607{
614 struct thread_info *thread = current_thread_info(); 608 struct thread_info *thread = current_thread_info();
615 struct task_struct *tsk = current; 609 struct task_struct *tsk = current;
@@ -617,26 +611,6 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
617 int ret; 611 int ret;
618 612
619 /* 613 /*
620 * If we were from a system call, check for system call restarting...
621 */
622 if (syscall) {
623 switch (regs->ARM_r0) {
624 case -ERESTART_RESTARTBLOCK:
625 case -ERESTARTNOHAND:
626 regs->ARM_r0 = -EINTR;
627 break;
628 case -ERESTARTSYS:
629 if (!(ka->sa.sa_flags & SA_RESTART)) {
630 regs->ARM_r0 = -EINTR;
631 break;
632 }
633 /* fallthrough */
634 case -ERESTARTNOINTR:
635 setup_syscall_restart(regs);
636 }
637 }
638
639 /*
640 * translate the signal 614 * translate the signal
641 */ 615 */
642 if (usig < 32 && thread->exec_domain && thread->exec_domain->signal_invmap) 616 if (usig < 32 && thread->exec_domain && thread->exec_domain->signal_invmap)
@@ -685,6 +659,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
685 */ 659 */
686static void do_signal(struct pt_regs *regs, int syscall) 660static void do_signal(struct pt_regs *regs, int syscall)
687{ 661{
662 unsigned int retval = 0, continue_addr = 0, restart_addr = 0;
688 struct k_sigaction ka; 663 struct k_sigaction ka;
689 siginfo_t info; 664 siginfo_t info;
690 int signr; 665 int signr;
@@ -698,18 +673,61 @@ static void do_signal(struct pt_regs *regs, int syscall)
698 if (!user_mode(regs)) 673 if (!user_mode(regs))
699 return; 674 return;
700 675
676 /*
677 * If we were from a system call, check for system call restarting...
678 */
679 if (syscall) {
680 continue_addr = regs->ARM_pc;
681 restart_addr = continue_addr - (thumb_mode(regs) ? 2 : 4);
682 retval = regs->ARM_r0;
683
684 /*
685 * Prepare for system call restart. We do this here so that a
686 * debugger will see the already changed PSW.
687 */
688 switch (retval) {
689 case -ERESTARTNOHAND:
690 case -ERESTARTSYS:
691 case -ERESTARTNOINTR:
692 regs->ARM_r0 = regs->ARM_ORIG_r0;
693 regs->ARM_pc = restart_addr;
694 break;
695 case -ERESTART_RESTARTBLOCK:
696 regs->ARM_r0 = -EINTR;
697 break;
698 }
699 }
700
701 if (try_to_freeze()) 701 if (try_to_freeze())
702 goto no_signal; 702 goto no_signal;
703 703
704 /*
705 * Get the signal to deliver. When running under ptrace, at this
706 * point the debugger may change all our registers ...
707 */
704 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 708 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
705 if (signr > 0) { 709 if (signr > 0) {
706 sigset_t *oldset; 710 sigset_t *oldset;
707 711
712 /*
713 * Depending on the signal settings we may need to revert the
714 * decision to restart the system call. But skip this if a
715 * debugger has chosen to restart at a different PC.
716 */
717 if (regs->ARM_pc == restart_addr) {
718 if (retval == -ERESTARTNOHAND
719 || (retval == -ERESTARTSYS
720 && !(ka.sa.sa_flags & SA_RESTART))) {
721 regs->ARM_r0 = -EINTR;
722 regs->ARM_pc = continue_addr;
723 }
724 }
725
708 if (test_thread_flag(TIF_RESTORE_SIGMASK)) 726 if (test_thread_flag(TIF_RESTORE_SIGMASK))
709 oldset = &current->saved_sigmask; 727 oldset = &current->saved_sigmask;
710 else 728 else
711 oldset = &current->blocked; 729 oldset = &current->blocked;
712 if (handle_signal(signr, &ka, &info, oldset, regs, syscall) == 0) { 730 if (handle_signal(signr, &ka, &info, oldset, regs) == 0) {
713 /* 731 /*
714 * A signal was successfully delivered; the saved 732 * A signal was successfully delivered; the saved
715 * sigmask will have been stored in the signal frame, 733 * sigmask will have been stored in the signal frame,
@@ -723,11 +741,14 @@ static void do_signal(struct pt_regs *regs, int syscall)
723 } 741 }
724 742
725 no_signal: 743 no_signal:
726 /*
727 * No signal to deliver to the process - restart the syscall.
728 */
729 if (syscall) { 744 if (syscall) {
730 if (regs->ARM_r0 == -ERESTART_RESTARTBLOCK) { 745 /*
746 * Handle restarting a different system call. As above,
747 * if a debugger has chosen to restart at a different PC,
748 * ignore the restart.
749 */
750 if (retval == -ERESTART_RESTARTBLOCK
751 && regs->ARM_pc == continue_addr) {
731 if (thumb_mode(regs)) { 752 if (thumb_mode(regs)) {
732 regs->ARM_r7 = __NR_restart_syscall - __NR_SYSCALL_BASE; 753 regs->ARM_r7 = __NR_restart_syscall - __NR_SYSCALL_BASE;
733 regs->ARM_pc -= 2; 754 regs->ARM_pc -= 2;
@@ -750,11 +771,6 @@ static void do_signal(struct pt_regs *regs, int syscall)
750#endif 771#endif
751 } 772 }
752 } 773 }
753 if (regs->ARM_r0 == -ERESTARTNOHAND ||
754 regs->ARM_r0 == -ERESTARTSYS ||
755 regs->ARM_r0 == -ERESTARTNOINTR) {
756 setup_syscall_restart(regs);
757 }
758 774
759 /* If there's no signal to deliver, we just put the saved sigmask 775 /* If there's no signal to deliver, we just put the saved sigmask
760 * back. 776 * back.
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index f29b8a29b174..d439a8f4c078 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -376,6 +376,13 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
376 } 376 }
377} 377}
378 378
379static void (*smp_cross_call)(const struct cpumask *, unsigned int);
380
381void __init set_smp_cross_call(void (*fn)(const struct cpumask *, unsigned int))
382{
383 smp_cross_call = fn;
384}
385
379void arch_send_call_function_ipi_mask(const struct cpumask *mask) 386void arch_send_call_function_ipi_mask(const struct cpumask *mask)
380{ 387{
381 smp_cross_call(mask, IPI_CALL_FUNC); 388 smp_cross_call(mask, IPI_CALL_FUNC);
@@ -560,10 +567,7 @@ asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs)
560 break; 567 break;
561 568
562 case IPI_RESCHEDULE: 569 case IPI_RESCHEDULE:
563 /* 570 scheduler_ipi();
564 * nothing more to do - eveything is
565 * done on the interrupt return path
566 */
567 break; 571 break;
568 572
569 case IPI_CALL_FUNC: 573 case IPI_CALL_FUNC:
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index 1ff46cabc7ef..cb634c3e28e9 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -21,7 +21,7 @@
21#include <linux/timex.h> 21#include <linux/timex.h>
22#include <linux/errno.h> 22#include <linux/errno.h>
23#include <linux/profile.h> 23#include <linux/profile.h>
24#include <linux/sysdev.h> 24#include <linux/syscore_ops.h>
25#include <linux/timer.h> 25#include <linux/timer.h>
26#include <linux/irq.h> 26#include <linux/irq.h>
27 27
@@ -115,48 +115,37 @@ void timer_tick(void)
115#endif 115#endif
116 116
117#if defined(CONFIG_PM) && !defined(CONFIG_GENERIC_CLOCKEVENTS) 117#if defined(CONFIG_PM) && !defined(CONFIG_GENERIC_CLOCKEVENTS)
118static int timer_suspend(struct sys_device *dev, pm_message_t state) 118static int timer_suspend(void)
119{ 119{
120 struct sys_timer *timer = container_of(dev, struct sys_timer, dev); 120 if (system_timer->suspend)
121 121 system_timer->suspend();
122 if (timer->suspend != NULL)
123 timer->suspend();
124 122
125 return 0; 123 return 0;
126} 124}
127 125
128static int timer_resume(struct sys_device *dev) 126static void timer_resume(void)
129{ 127{
130 struct sys_timer *timer = container_of(dev, struct sys_timer, dev); 128 if (system_timer->resume)
131 129 system_timer->resume();
132 if (timer->resume != NULL)
133 timer->resume();
134
135 return 0;
136} 130}
137#else 131#else
138#define timer_suspend NULL 132#define timer_suspend NULL
139#define timer_resume NULL 133#define timer_resume NULL
140#endif 134#endif
141 135
142static struct sysdev_class timer_sysclass = { 136static struct syscore_ops timer_syscore_ops = {
143 .name = "timer",
144 .suspend = timer_suspend, 137 .suspend = timer_suspend,
145 .resume = timer_resume, 138 .resume = timer_resume,
146}; 139};
147 140
148static int __init timer_init_sysfs(void) 141static int __init timer_init_syscore_ops(void)
149{ 142{
150 int ret = sysdev_class_register(&timer_sysclass); 143 register_syscore_ops(&timer_syscore_ops);
151 if (ret == 0) {
152 system_timer->dev.cls = &timer_sysclass;
153 ret = sysdev_register(&system_timer->dev);
154 }
155 144
156 return ret; 145 return 0;
157} 146}
158 147
159device_initcall(timer_init_sysfs); 148device_initcall(timer_init_syscore_ops);
160 149
161void __init time_init(void) 150void __init time_init(void)
162{ 151{
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 3b54ad19d489..d52eec268b47 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -234,7 +234,6 @@ static int __die(const char *str, int err, struct thread_info *thread, struct pt
234 234
235 printk(KERN_EMERG "Internal error: %s: %x [#%d]" S_PREEMPT S_SMP "\n", 235 printk(KERN_EMERG "Internal error: %s: %x [#%d]" S_PREEMPT S_SMP "\n",
236 str, err, ++die_counter); 236 str, err, ++die_counter);
237 sysfs_printk_last_file();
238 237
239 /* trap and error numbers are mostly meaningless on ARM */ 238 /* trap and error numbers are mostly meaningless on ARM */
240 ret = notify_die(DIE_OOPS, str, regs, err, tsk->thread.trap_no, SIGSEGV); 239 ret = notify_die(DIE_OOPS, str, regs, err, tsk->thread.trap_no, SIGSEGV);