diff options
author | Jens Axboe <jens.axboe@oracle.com> | 2009-11-03 15:14:39 -0500 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2009-11-03 15:14:39 -0500 |
commit | 2058297d2d045cb57138c33b87cfabcc80e65186 (patch) | |
tree | 7ccffd0e162cbd7471f643561e79f23abb989a62 /arch/s390/kernel | |
parent | 150e6c67f4bf6ab51e62defc41bd19a2eefe5709 (diff) | |
parent | 4b27e1bb442e964903f8a3fa6bdf33a602dc0941 (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.c | 35 | ||||
-rw-r--r-- | arch/s390/kernel/compat_wrapper.S | 2 | ||||
-rw-r--r-- | arch/s390/kernel/ftrace.c | 3 | ||||
-rw-r--r-- | arch/s390/kernel/ipl.c | 7 | ||||
-rw-r--r-- | arch/s390/kernel/module.c | 3 | ||||
-rw-r--r-- | arch/s390/kernel/processor.c | 6 | ||||
-rw-r--r-- | arch/s390/kernel/ptrace.c | 70 | ||||
-rw-r--r-- | arch/s390/kernel/setup.c | 15 | ||||
-rw-r--r-- | arch/s390/kernel/smp.c | 7 | ||||
-rw-r--r-- | arch/s390/kernel/swsusp_asm64.S | 28 | ||||
-rw-r--r-- | arch/s390/kernel/vdso.c | 16 | ||||
-rw-r--r-- | arch/s390/kernel/vmlinux.lds.S | 1 |
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 | ||
53 | int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) | 55 | int 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 | ||
349 | static 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 | |||
360 | static 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 *)®s->gprs[i] = gprs_high[i]; | ||
370 | return 0; | ||
371 | } | ||
372 | |||
347 | asmlinkage long sys32_sigreturn(void) | 373 | asmlinkage 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 |
410 | sys32_truncate_wrapper: | 410 | sys32_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(¤t->tracing_graph_pause))) | 188 | if (unlikely(atomic_read(¤t->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 | ||
1604 | static struct shutdown_action stop_action = {SHUTDOWN_ACTION_STOP_STR, | 1603 | static 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 */ |
56 | void module_free(struct module *mod, void *module_region) | 56 | void 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 | ||
32 | static int show_cpuinfo(struct seq_file *m, void *v) | 32 | static 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 @@ | |||
57 | enum s390_regset { | 57 | enum s390_regset { |
58 | REGSET_GENERAL, | 58 | REGSET_GENERAL, |
59 | REGSET_FP, | 59 | REGSET_FP, |
60 | REGSET_GENERAL_EXTENDED, | ||
60 | }; | 61 | }; |
61 | 62 | ||
62 | static void | 63 | static 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 | ||
883 | static 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 | |||
911 | static 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 | |||
882 | static const struct user_regset s390_compat_regsets[] = { | 944 | static 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 | ||
901 | static const struct user_regset_view user_s390_compat_view = { | 971 | static 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) | |||
645 | void cpu_die(void) | 646 | void 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 */ |
188 | 5: | 200 | 5: |
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 */ | ||
190 | 6: j 6b | 203 | 6: j 6b |
191 | 204 | ||
192 | restart_suspend: | 205 | restart_suspend: |
@@ -194,14 +207,18 @@ restart_suspend: | |||
194 | llgh %r2,0(%r1) | 207 | llgh %r2,0(%r1) |
195 | 7: | 208 | 7: |
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 | ||
201 | restore_registers: | 215 | restore_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 | |||
278 | out_up: | 278 | out_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 | ||