aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel
diff options
context:
space:
mode:
authorJens Axboe <jens.axboe@oracle.com>2009-11-03 15:14:39 -0500
committerJens Axboe <jens.axboe@oracle.com>2009-11-03 15:14:39 -0500
commit2058297d2d045cb57138c33b87cfabcc80e65186 (patch)
tree7ccffd0e162cbd7471f643561e79f23abb989a62 /arch/s390/kernel
parent150e6c67f4bf6ab51e62defc41bd19a2eefe5709 (diff)
parent4b27e1bb442e964903f8a3fa6bdf33a602dc0941 (diff)
Merge branch 'for-linus' into for-2.6.33
Conflicts: block/cfq-iosched.c Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'arch/s390/kernel')
-rw-r--r--arch/s390/kernel/compat_signal.c35
-rw-r--r--arch/s390/kernel/compat_wrapper.S2
-rw-r--r--arch/s390/kernel/ftrace.c3
-rw-r--r--arch/s390/kernel/ipl.c7
-rw-r--r--arch/s390/kernel/module.c3
-rw-r--r--arch/s390/kernel/processor.c6
-rw-r--r--arch/s390/kernel/ptrace.c70
-rw-r--r--arch/s390/kernel/setup.c15
-rw-r--r--arch/s390/kernel/smp.c7
-rw-r--r--arch/s390/kernel/swsusp_asm64.S28
-rw-r--r--arch/s390/kernel/vdso.c16
-rw-r--r--arch/s390/kernel/vmlinux.lds.S1
12 files changed, 160 insertions, 33 deletions
diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c
index b537cb0e9b55..eee999853a7c 100644
--- a/arch/s390/kernel/compat_signal.c
+++ b/arch/s390/kernel/compat_signal.c
@@ -39,6 +39,7 @@ typedef struct
39 struct sigcontext32 sc; 39 struct sigcontext32 sc;
40 _sigregs32 sregs; 40 _sigregs32 sregs;
41 int signo; 41 int signo;
42 __u32 gprs_high[NUM_GPRS];
42 __u8 retcode[S390_SYSCALL_SIZE]; 43 __u8 retcode[S390_SYSCALL_SIZE];
43} sigframe32; 44} sigframe32;
44 45
@@ -48,6 +49,7 @@ typedef struct
48 __u8 retcode[S390_SYSCALL_SIZE]; 49 __u8 retcode[S390_SYSCALL_SIZE];
49 compat_siginfo_t info; 50 compat_siginfo_t info;
50 struct ucontext32 uc; 51 struct ucontext32 uc;
52 __u32 gprs_high[NUM_GPRS];
51} rt_sigframe32; 53} rt_sigframe32;
52 54
53int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) 55int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
@@ -344,6 +346,30 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
344 return 0; 346 return 0;
345} 347}
346 348
349static int save_sigregs_gprs_high(struct pt_regs *regs, __u32 __user *uregs)
350{
351 __u32 gprs_high[NUM_GPRS];
352 int i;
353
354 for (i = 0; i < NUM_GPRS; i++)
355 gprs_high[i] = regs->gprs[i] >> 32;
356
357 return __copy_to_user(uregs, &gprs_high, sizeof(gprs_high));
358}
359
360static int restore_sigregs_gprs_high(struct pt_regs *regs, __u32 __user *uregs)
361{
362 __u32 gprs_high[NUM_GPRS];
363 int err, i;
364
365 err = __copy_from_user(&gprs_high, uregs, sizeof(gprs_high));
366 if (err)
367 return err;
368 for (i = 0; i < NUM_GPRS; i++)
369 *(__u32 *)&regs->gprs[i] = gprs_high[i];
370 return 0;
371}
372
347asmlinkage long sys32_sigreturn(void) 373asmlinkage long sys32_sigreturn(void)
348{ 374{
349 struct pt_regs *regs = task_pt_regs(current); 375 struct pt_regs *regs = task_pt_regs(current);
@@ -363,6 +389,8 @@ asmlinkage long sys32_sigreturn(void)
363 389
364 if (restore_sigregs32(regs, &frame->sregs)) 390 if (restore_sigregs32(regs, &frame->sregs))
365 goto badframe; 391 goto badframe;
392 if (restore_sigregs_gprs_high(regs, frame->gprs_high))
393 goto badframe;
366 394
367 return regs->gprs[2]; 395 return regs->gprs[2];
368 396
@@ -394,6 +422,8 @@ asmlinkage long sys32_rt_sigreturn(void)
394 422
395 if (restore_sigregs32(regs, &frame->uc.uc_mcontext)) 423 if (restore_sigregs32(regs, &frame->uc.uc_mcontext))
396 goto badframe; 424 goto badframe;
425 if (restore_sigregs_gprs_high(regs, frame->gprs_high))
426 goto badframe;
397 427
398 err = __get_user(ss_sp, &frame->uc.uc_stack.ss_sp); 428 err = __get_user(ss_sp, &frame->uc.uc_stack.ss_sp);
399 st.ss_sp = compat_ptr(ss_sp); 429 st.ss_sp = compat_ptr(ss_sp);
@@ -474,6 +504,8 @@ static int setup_frame32(int sig, struct k_sigaction *ka,
474 504
475 if (save_sigregs32(regs, &frame->sregs)) 505 if (save_sigregs32(regs, &frame->sregs))
476 goto give_sigsegv; 506 goto give_sigsegv;
507 if (save_sigregs_gprs_high(regs, frame->gprs_high))
508 goto give_sigsegv;
477 if (__put_user((unsigned long) &frame->sregs, &frame->sc.sregs)) 509 if (__put_user((unsigned long) &frame->sregs, &frame->sc.sregs))
478 goto give_sigsegv; 510 goto give_sigsegv;
479 511
@@ -529,13 +561,14 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
529 goto give_sigsegv; 561 goto give_sigsegv;
530 562
531 /* Create the ucontext. */ 563 /* Create the ucontext. */
532 err |= __put_user(0, &frame->uc.uc_flags); 564 err |= __put_user(UC_EXTENDED, &frame->uc.uc_flags);
533 err |= __put_user(0, &frame->uc.uc_link); 565 err |= __put_user(0, &frame->uc.uc_link);
534 err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); 566 err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
535 err |= __put_user(sas_ss_flags(regs->gprs[15]), 567 err |= __put_user(sas_ss_flags(regs->gprs[15]),
536 &frame->uc.uc_stack.ss_flags); 568 &frame->uc.uc_stack.ss_flags);
537 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); 569 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
538 err |= save_sigregs32(regs, &frame->uc.uc_mcontext); 570 err |= save_sigregs32(regs, &frame->uc.uc_mcontext);
571 err |= save_sigregs_gprs_high(regs, frame->gprs_high);
539 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); 572 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
540 if (err) 573 if (err)
541 goto give_sigsegv; 574 goto give_sigsegv;
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index 682fb69dba21..cbd9901dc0f8 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -409,7 +409,7 @@ sys32_munmap_wrapper:
409 .globl sys32_truncate_wrapper 409 .globl sys32_truncate_wrapper
410sys32_truncate_wrapper: 410sys32_truncate_wrapper:
411 llgtr %r2,%r2 # const char * 411 llgtr %r2,%r2 # const char *
412 llgfr %r3,%r3 # unsigned long 412 lgfr %r3,%r3 # long
413 jg sys_truncate # branch to system call 413 jg sys_truncate # branch to system call
414 414
415 .globl sys32_ftruncate_wrapper 415 .globl sys32_ftruncate_wrapper
diff --git a/arch/s390/kernel/ftrace.c b/arch/s390/kernel/ftrace.c
index 57bdcb1e3cdf..f5fe34dd821b 100644
--- a/arch/s390/kernel/ftrace.c
+++ b/arch/s390/kernel/ftrace.c
@@ -185,9 +185,6 @@ unsigned long prepare_ftrace_return(unsigned long ip, unsigned long parent)
185{ 185{
186 struct ftrace_graph_ent trace; 186 struct ftrace_graph_ent trace;
187 187
188 /* Nmi's are currently unsupported. */
189 if (unlikely(in_nmi()))
190 goto out;
191 if (unlikely(atomic_read(&current->tracing_graph_pause))) 188 if (unlikely(atomic_read(&current->tracing_graph_pause)))
192 goto out; 189 goto out;
193 if (ftrace_push_return_trace(parent, ip, &trace.depth, 0) == -EBUSY) 190 if (ftrace_push_return_trace(parent, ip, &trace.depth, 0) == -EBUSY)
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index ee57a42e6e93..4890ac6d7faa 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -1595,10 +1595,9 @@ static void stop_run(struct shutdown_trigger *trigger)
1595{ 1595{
1596 if (strcmp(trigger->name, ON_PANIC_STR) == 0) 1596 if (strcmp(trigger->name, ON_PANIC_STR) == 0)
1597 disabled_wait((unsigned long) __builtin_return_address(0)); 1597 disabled_wait((unsigned long) __builtin_return_address(0));
1598 else { 1598 while (signal_processor(smp_processor_id(), sigp_stop) == sigp_busy)
1599 signal_processor(smp_processor_id(), sigp_stop); 1599 cpu_relax();
1600 for (;;); 1600 for (;;);
1601 }
1602} 1601}
1603 1602
1604static struct shutdown_action stop_action = {SHUTDOWN_ACTION_STOP_STR, 1603static struct shutdown_action stop_action = {SHUTDOWN_ACTION_STOP_STR,
diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c
index ab2e3ed28abc..639380a0c45c 100644
--- a/arch/s390/kernel/module.c
+++ b/arch/s390/kernel/module.c
@@ -55,6 +55,8 @@ void *module_alloc(unsigned long size)
55/* Free memory returned from module_alloc */ 55/* Free memory returned from module_alloc */
56void module_free(struct module *mod, void *module_region) 56void module_free(struct module *mod, void *module_region)
57{ 57{
58 vfree(mod->arch.syminfo);
59 mod->arch.syminfo = NULL;
58 vfree(module_region); 60 vfree(module_region);
59} 61}
60 62
@@ -402,6 +404,7 @@ int module_finalize(const Elf_Ehdr *hdr,
402 struct module *me) 404 struct module *me)
403{ 405{
404 vfree(me->arch.syminfo); 406 vfree(me->arch.syminfo);
407 me->arch.syminfo = NULL;
405 return module_bug_finalize(hdr, sechdrs, me); 408 return module_bug_finalize(hdr, sechdrs, me);
406} 409}
407 410
diff --git a/arch/s390/kernel/processor.c b/arch/s390/kernel/processor.c
index 802c8ab247f3..0729f36c2fe3 100644
--- a/arch/s390/kernel/processor.c
+++ b/arch/s390/kernel/processor.c
@@ -31,9 +31,9 @@ void __cpuinit print_cpu_info(void)
31 31
32static int show_cpuinfo(struct seq_file *m, void *v) 32static int show_cpuinfo(struct seq_file *m, void *v)
33{ 33{
34 static const char *hwcap_str[9] = { 34 static const char *hwcap_str[10] = {
35 "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp", 35 "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp",
36 "edat", "etf3eh" 36 "edat", "etf3eh", "highgprs"
37 }; 37 };
38 struct _lowcore *lc; 38 struct _lowcore *lc;
39 unsigned long n = (unsigned long) v - 1; 39 unsigned long n = (unsigned long) v - 1;
@@ -48,7 +48,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
48 num_online_cpus(), loops_per_jiffy/(500000/HZ), 48 num_online_cpus(), loops_per_jiffy/(500000/HZ),
49 (loops_per_jiffy/(5000/HZ))%100); 49 (loops_per_jiffy/(5000/HZ))%100);
50 seq_puts(m, "features\t: "); 50 seq_puts(m, "features\t: ");
51 for (i = 0; i < 9; i++) 51 for (i = 0; i < 10; i++)
52 if (hwcap_str[i] && (elf_hwcap & (1UL << i))) 52 if (hwcap_str[i] && (elf_hwcap & (1UL << i)))
53 seq_printf(m, "%s ", hwcap_str[i]); 53 seq_printf(m, "%s ", hwcap_str[i]);
54 seq_puts(m, "\n"); 54 seq_puts(m, "\n");
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index a8738676b26c..653c6a178740 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -57,6 +57,7 @@
57enum s390_regset { 57enum s390_regset {
58 REGSET_GENERAL, 58 REGSET_GENERAL,
59 REGSET_FP, 59 REGSET_FP,
60 REGSET_GENERAL_EXTENDED,
60}; 61};
61 62
62static void 63static void
@@ -879,6 +880,67 @@ static int s390_compat_regs_set(struct task_struct *target,
879 return rc; 880 return rc;
880} 881}
881 882
883static int s390_compat_regs_high_get(struct task_struct *target,
884 const struct user_regset *regset,
885 unsigned int pos, unsigned int count,
886 void *kbuf, void __user *ubuf)
887{
888 compat_ulong_t *gprs_high;
889
890 gprs_high = (compat_ulong_t *)
891 &task_pt_regs(target)->gprs[pos / sizeof(compat_ulong_t)];
892 if (kbuf) {
893 compat_ulong_t *k = kbuf;
894 while (count > 0) {
895 *k++ = *gprs_high;
896 gprs_high += 2;
897 count -= sizeof(*k);
898 }
899 } else {
900 compat_ulong_t __user *u = ubuf;
901 while (count > 0) {
902 if (__put_user(*gprs_high, u++))
903 return -EFAULT;
904 gprs_high += 2;
905 count -= sizeof(*u);
906 }
907 }
908 return 0;
909}
910
911static int s390_compat_regs_high_set(struct task_struct *target,
912 const struct user_regset *regset,
913 unsigned int pos, unsigned int count,
914 const void *kbuf, const void __user *ubuf)
915{
916 compat_ulong_t *gprs_high;
917 int rc = 0;
918
919 gprs_high = (compat_ulong_t *)
920 &task_pt_regs(target)->gprs[pos / sizeof(compat_ulong_t)];
921 if (kbuf) {
922 const compat_ulong_t *k = kbuf;
923 while (count > 0) {
924 *gprs_high = *k++;
925 *gprs_high += 2;
926 count -= sizeof(*k);
927 }
928 } else {
929 const compat_ulong_t __user *u = ubuf;
930 while (count > 0 && !rc) {
931 unsigned long word;
932 rc = __get_user(word, u++);
933 if (rc)
934 break;
935 *gprs_high = word;
936 *gprs_high += 2;
937 count -= sizeof(*u);
938 }
939 }
940
941 return rc;
942}
943
882static const struct user_regset s390_compat_regsets[] = { 944static const struct user_regset s390_compat_regsets[] = {
883 [REGSET_GENERAL] = { 945 [REGSET_GENERAL] = {
884 .core_note_type = NT_PRSTATUS, 946 .core_note_type = NT_PRSTATUS,
@@ -896,6 +958,14 @@ static const struct user_regset s390_compat_regsets[] = {
896 .get = s390_fpregs_get, 958 .get = s390_fpregs_get,
897 .set = s390_fpregs_set, 959 .set = s390_fpregs_set,
898 }, 960 },
961 [REGSET_GENERAL_EXTENDED] = {
962 .core_note_type = NT_PRXSTATUS,
963 .n = sizeof(s390_compat_regs_high) / sizeof(compat_long_t),
964 .size = sizeof(compat_long_t),
965 .align = sizeof(compat_long_t),
966 .get = s390_compat_regs_high_get,
967 .set = s390_compat_regs_high_set,
968 },
899}; 969};
900 970
901static const struct user_regset_view user_s390_compat_view = { 971static const struct user_regset_view user_s390_compat_view = {
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 9ed13a1ed376..061479ff029f 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -729,7 +729,7 @@ static void __init setup_hwcaps(void)
729 729
730 if ((facility_list & (1UL << (31 - 22))) 730 if ((facility_list & (1UL << (31 - 22)))
731 && (facility_list & (1UL << (31 - 30)))) 731 && (facility_list & (1UL << (31 - 30))))
732 elf_hwcap |= 1UL << 8; 732 elf_hwcap |= HWCAP_S390_ETF3EH;
733 733
734 /* 734 /*
735 * Check for additional facilities with store-facility-list-extended. 735 * Check for additional facilities with store-facility-list-extended.
@@ -748,11 +748,20 @@ static void __init setup_hwcaps(void)
748 __stfle(&facility_list_extended, 1) > 0) { 748 __stfle(&facility_list_extended, 1) > 0) {
749 if ((facility_list_extended & (1ULL << (63 - 42))) 749 if ((facility_list_extended & (1ULL << (63 - 42)))
750 && (facility_list_extended & (1ULL << (63 - 44)))) 750 && (facility_list_extended & (1ULL << (63 - 44))))
751 elf_hwcap |= 1UL << 6; 751 elf_hwcap |= HWCAP_S390_DFP;
752 } 752 }
753 753
754 /*
755 * Huge page support HWCAP_S390_HPAGE is bit 7.
756 */
754 if (MACHINE_HAS_HPAGE) 757 if (MACHINE_HAS_HPAGE)
755 elf_hwcap |= 1UL << 7; 758 elf_hwcap |= HWCAP_S390_HPAGE;
759
760 /*
761 * 64-bit register support for 31-bit processes
762 * HWCAP_S390_HIGH_GPRS is bit 9.
763 */
764 elf_hwcap |= HWCAP_S390_HIGH_GPRS;
756 765
757 switch (S390_lowcore.cpu_id.machine) { 766 switch (S390_lowcore.cpu_id.machine) {
758 case 0x9672: 767 case 0x9672:
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index c932caa5e850..93e52039321b 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -76,7 +76,6 @@ static int cpu_stopped(int cpu)
76 __u32 status; 76 __u32 status;
77 77
78 switch (signal_processor_ps(&status, 0, cpu, sigp_sense)) { 78 switch (signal_processor_ps(&status, 0, cpu, sigp_sense)) {
79 case sigp_order_code_accepted:
80 case sigp_status_stored: 79 case sigp_status_stored:
81 /* Check for stopped and check stop state */ 80 /* Check for stopped and check stop state */
82 if (status & 0x50) 81 if (status & 0x50)
@@ -638,6 +637,8 @@ void __cpu_die(unsigned int cpu)
638 /* Wait until target cpu is down */ 637 /* Wait until target cpu is down */
639 while (!cpu_stopped(cpu)) 638 while (!cpu_stopped(cpu))
640 cpu_relax(); 639 cpu_relax();
640 while (signal_processor_p(0, cpu, sigp_set_prefix) == sigp_busy)
641 udelay(10);
641 smp_free_lowcore(cpu); 642 smp_free_lowcore(cpu);
642 pr_info("Processor %d stopped\n", cpu); 643 pr_info("Processor %d stopped\n", cpu);
643} 644}
@@ -645,8 +646,8 @@ void __cpu_die(unsigned int cpu)
645void cpu_die(void) 646void cpu_die(void)
646{ 647{
647 idle_task_exit(); 648 idle_task_exit();
648 signal_processor(smp_processor_id(), sigp_stop); 649 while (signal_processor(smp_processor_id(), sigp_stop) == sigp_busy)
649 BUG(); 650 cpu_relax();
650 for (;;); 651 for (;;);
651} 652}
652 653
diff --git a/arch/s390/kernel/swsusp_asm64.S b/arch/s390/kernel/swsusp_asm64.S
index fe927d0bc20b..0c26cc1898ec 100644
--- a/arch/s390/kernel/swsusp_asm64.S
+++ b/arch/s390/kernel/swsusp_asm64.S
@@ -43,7 +43,7 @@ swsusp_arch_suspend:
43 lghi %r1,0x1000 43 lghi %r1,0x1000
44 44
45 /* Save CPU address */ 45 /* Save CPU address */
46 stap __LC_CPU_ADDRESS(%r1) 46 stap __LC_CPU_ADDRESS(%r0)
47 47
48 /* Store registers */ 48 /* Store registers */
49 mvc 0x318(4,%r1),__SF_EMPTY(%r15) /* move prefix to lowcore */ 49 mvc 0x318(4,%r1),__SF_EMPTY(%r15) /* move prefix to lowcore */
@@ -69,8 +69,21 @@ swsusp_arch_suspend:
69 stmg %r0,%r15,0x280(%r1) /* store general registers */ 69 stmg %r0,%r15,0x280(%r1) /* store general registers */
70 70
71 stpt 0x328(%r1) /* store timer */ 71 stpt 0x328(%r1) /* store timer */
72 stck __SF_EMPTY(%r15) /* store clock */
72 stckc 0x330(%r1) /* store clock comparator */ 73 stckc 0x330(%r1) /* store clock comparator */
73 74
75 /* Update cputime accounting before going to sleep */
76 lg %r0,__LC_LAST_UPDATE_TIMER
77 slg %r0,0x328(%r1)
78 alg %r0,__LC_SYSTEM_TIMER
79 stg %r0,__LC_SYSTEM_TIMER
80 mvc __LC_LAST_UPDATE_TIMER(8),0x328(%r1)
81 lg %r0,__LC_LAST_UPDATE_CLOCK
82 slg %r0,__SF_EMPTY(%r15)
83 alg %r0,__LC_STEAL_TIMER
84 stg %r0,__LC_STEAL_TIMER
85 mvc __LC_LAST_UPDATE_CLOCK(8),__SF_EMPTY(%r15)
86
74 /* Activate DAT */ 87 /* Activate DAT */
75 stosm __SF_EMPTY(%r15),0x04 88 stosm __SF_EMPTY(%r15),0x04
76 89
@@ -159,8 +172,7 @@ pgm_check_entry:
159 larl %r1,.Lresume_cpu /* Resume CPU address: r2 */ 172 larl %r1,.Lresume_cpu /* Resume CPU address: r2 */
160 stap 0(%r1) 173 stap 0(%r1)
161 llgh %r2,0(%r1) 174 llgh %r2,0(%r1)
162 lghi %r3,0x1000 175 llgh %r1,__LC_CPU_ADDRESS(%r0) /* Suspend CPU address: r1 */
163 llgh %r1,__LC_CPU_ADDRESS(%r3) /* Suspend CPU address: r1 */
164 cgr %r1,%r2 176 cgr %r1,%r2
165 je restore_registers /* r1 = r2 -> nothing to do */ 177 je restore_registers /* r1 = r2 -> nothing to do */
166 larl %r4,.Lrestart_suspend_psw /* Set new restart PSW */ 178 larl %r4,.Lrestart_suspend_psw /* Set new restart PSW */
@@ -187,6 +199,7 @@ pgm_check_entry:
187 brc 2,4b /* busy, try again */ 199 brc 2,4b /* busy, try again */
1885: 2005:
189 sigp %r9,%r2,__SIGP_STOP /* stop resume (current) CPU */ 201 sigp %r9,%r2,__SIGP_STOP /* stop resume (current) CPU */
202 brc 2,5b /* busy, try again */
1906: j 6b 2036: j 6b
191 204
192restart_suspend: 205restart_suspend:
@@ -194,14 +207,18 @@ restart_suspend:
194 llgh %r2,0(%r1) 207 llgh %r2,0(%r1)
1957: 2087:
196 sigp %r9,%r2,__SIGP_SENSE /* Wait for resume CPU */ 209 sigp %r9,%r2,__SIGP_SENSE /* Wait for resume CPU */
210 brc 8,7b /* accepted, status 0, still running */
197 brc 2,7b /* busy, try again */ 211 brc 2,7b /* busy, try again */
198 tmll %r9,0x40 /* Test if resume CPU is stopped */ 212 tmll %r9,0x40 /* Test if resume CPU is stopped */
199 jz 7b 213 jz 7b
200 214
201restore_registers: 215restore_registers:
202 /* Restore registers */ 216 /* Restore registers */
203 lghi %r13,0x1000 /* %r1 = pointer to save arae */ 217 lghi %r13,0x1000 /* %r1 = pointer to save area */
204 218
219 /* Ignore time spent in suspended state. */
220 llgf %r1,0x318(%r13)
221 stck __LC_LAST_UPDATE_CLOCK(%r1)
205 spt 0x328(%r13) /* reprogram timer */ 222 spt 0x328(%r13) /* reprogram timer */
206 //sckc 0x330(%r13) /* set clock comparator */ 223 //sckc 0x330(%r13) /* set clock comparator */
207 224
@@ -229,9 +246,6 @@ restore_registers:
229 /* Load old stack */ 246 /* Load old stack */
230 lg %r15,0x2f8(%r13) 247 lg %r15,0x2f8(%r13)
231 248
232 /* Pointer to save area */
233 lghi %r13,0x1000
234
235 /* Restore prefix register */ 249 /* Restore prefix register */
236 spx 0x318(%r13) 250 spx 0x318(%r13)
237 251
diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c
index 45a3e9a7ae21..adfb32aa6d59 100644
--- a/arch/s390/kernel/vdso.c
+++ b/arch/s390/kernel/vdso.c
@@ -247,6 +247,13 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
247 } 247 }
248 248
249 /* 249 /*
250 * Put vDSO base into mm struct. We need to do this before calling
251 * install_special_mapping or the perf counter mmap tracking code
252 * will fail to recognise it as a vDSO (since arch_vma_name fails).
253 */
254 current->mm->context.vdso_base = vdso_base;
255
256 /*
250 * our vma flags don't have VM_WRITE so by default, the process 257 * our vma flags don't have VM_WRITE so by default, the process
251 * isn't allowed to write those pages. 258 * isn't allowed to write those pages.
252 * gdb can break that with ptrace interface, and thus trigger COW 259 * gdb can break that with ptrace interface, and thus trigger COW
@@ -267,14 +274,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
267 VM_ALWAYSDUMP, 274 VM_ALWAYSDUMP,
268 vdso_pagelist); 275 vdso_pagelist);
269 if (rc) 276 if (rc)
270 goto out_up; 277 current->mm->context.vdso_base = 0;
271
272 /* Put vDSO base into mm struct */
273 current->mm->context.vdso_base = vdso_base;
274
275 up_write(&mm->mmap_sem);
276 return 0;
277
278out_up: 278out_up:
279 up_write(&mm->mmap_sem); 279 up_write(&mm->mmap_sem);
280 return rc; 280 return rc;
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index bc15ef93e656..a68ac10213b2 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -51,6 +51,7 @@ SECTIONS
51 51
52 . = ALIGN(PAGE_SIZE); 52 . = ALIGN(PAGE_SIZE);
53 _eshared = .; /* End of shareable data */ 53 _eshared = .; /* End of shareable data */
54 _sdata = .; /* Start of data section */
54 55
55 EXCEPTION_TABLE(16) :data 56 EXCEPTION_TABLE(16) :data
56 57