aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/Kconfig8
-rw-r--r--arch/s390/hypfs/inode.c2
-rw-r--r--arch/s390/include/asm/dasd.h13
-rw-r--r--arch/s390/include/asm/delay.h1
-rw-r--r--arch/s390/include/asm/elf.h8
-rw-r--r--arch/s390/include/asm/pgtable.h45
-rw-r--r--arch/s390/include/asm/ptrace.h1
-rw-r--r--arch/s390/include/asm/qdio.h8
-rw-r--r--arch/s390/include/asm/statfs.h11
-rw-r--r--arch/s390/include/asm/syscall.h80
-rw-r--r--arch/s390/include/asm/thread_info.h2
-rw-r--r--arch/s390/kernel/compat_linux.c110
-rw-r--r--arch/s390/kernel/compat_linux.h5
-rw-r--r--arch/s390/kernel/compat_wrapper.S14
-rw-r--r--arch/s390/kernel/entry.S50
-rw-r--r--arch/s390/kernel/entry64.S42
-rw-r--r--arch/s390/kernel/ptrace.c61
-rw-r--r--arch/s390/kernel/signal.c13
-rw-r--r--arch/s390/kernel/smp.c2
-rw-r--r--arch/s390/kernel/syscalls.S6
-rw-r--r--arch/s390/kernel/time.c2
-rw-r--r--arch/s390/kvm/priv.c4
-rw-r--r--arch/s390/lib/delay.c13
-rw-r--r--arch/s390/mm/extmem.c251
24 files changed, 518 insertions, 234 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 8d41908e2513..bc581d8a7cd9 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -74,6 +74,7 @@ config S390
74 select HAVE_KPROBES 74 select HAVE_KPROBES
75 select HAVE_KRETPROBES 75 select HAVE_KRETPROBES
76 select HAVE_KVM if 64BIT 76 select HAVE_KVM if 64BIT
77 select HAVE_ARCH_TRACEHOOK
77 78
78source "init/Kconfig" 79source "init/Kconfig"
79 80
@@ -564,13 +565,16 @@ config ZFCPDUMP
564 Refer to <file:Documentation/s390/zfcpdump.txt> for more details on this. 565 Refer to <file:Documentation/s390/zfcpdump.txt> for more details on this.
565 566
566config S390_GUEST 567config S390_GUEST
567bool "s390 guest support (EXPERIMENTAL)" 568bool "s390 guest support for KVM (EXPERIMENTAL)"
568 depends on 64BIT && EXPERIMENTAL 569 depends on 64BIT && EXPERIMENTAL
569 select VIRTIO 570 select VIRTIO
570 select VIRTIO_RING 571 select VIRTIO_RING
571 select VIRTIO_CONSOLE 572 select VIRTIO_CONSOLE
572 help 573 help
573 Select this option if you want to run the kernel under s390 linux 574 Select this option if you want to run the kernel as a guest under
575 the KVM hypervisor. This will add detection for KVM as well as a
576 virtio transport. If KVM is detected, the virtio console will be
577 the default console.
574endmenu 578endmenu
575 579
576source "net/Kconfig" 580source "net/Kconfig"
diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c
index 7383781f3e6a..36313801cd5c 100644
--- a/arch/s390/hypfs/inode.c
+++ b/arch/s390/hypfs/inode.c
@@ -219,7 +219,7 @@ static int hypfs_release(struct inode *inode, struct file *filp)
219 219
220enum { opt_uid, opt_gid, opt_err }; 220enum { opt_uid, opt_gid, opt_err };
221 221
222static match_table_t hypfs_tokens = { 222static const match_table_t hypfs_tokens = {
223 {opt_uid, "uid=%u"}, 223 {opt_uid, "uid=%u"},
224 {opt_gid, "gid=%u"}, 224 {opt_gid, "gid=%u"},
225 {opt_err, NULL} 225 {opt_err, NULL}
diff --git a/arch/s390/include/asm/dasd.h b/arch/s390/include/asm/dasd.h
index 3f002e13d024..55b2b80cdf6e 100644
--- a/arch/s390/include/asm/dasd.h
+++ b/arch/s390/include/asm/dasd.h
@@ -3,6 +3,8 @@
3 * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> 3 * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
4 * Bugreports.to..: <Linux390@de.ibm.com> 4 * Bugreports.to..: <Linux390@de.ibm.com>
5 * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 5 * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
6 * EMC Symmetrix ioctl Copyright EMC Corporation, 2008
7 * Author.........: Nigel Hislop <hislop_nigel@emc.com>
6 * 8 *
7 * This file is the interface of the DASD device driver, which is exported to user space 9 * This file is the interface of the DASD device driver, which is exported to user space
8 * any future changes wrt the API will result in a change of the APIVERSION reported 10 * any future changes wrt the API will result in a change of the APIVERSION reported
@@ -202,6 +204,16 @@ typedef struct attrib_data_t {
202#define DASD_SEQ_PRESTAGE 0x4 204#define DASD_SEQ_PRESTAGE 0x4
203#define DASD_REC_ACCESS 0x5 205#define DASD_REC_ACCESS 0x5
204 206
207/*
208 * Perform EMC Symmetrix I/O
209 */
210typedef struct dasd_symmio_parms {
211 unsigned char reserved[8]; /* compat with older releases */
212 unsigned long long psf_data; /* char * cast to u64 */
213 unsigned long long rssd_result; /* char * cast to u64 */
214 int psf_data_len;
215 int rssd_result_len;
216} __attribute__ ((packed)) dasd_symmio_parms_t;
205 217
206/******************************************************************************** 218/********************************************************************************
207 * SECTION: Definition of IOCTLs 219 * SECTION: Definition of IOCTLs
@@ -247,6 +259,7 @@ typedef struct attrib_data_t {
247/* Set Attributes (cache operations) */ 259/* Set Attributes (cache operations) */
248#define BIODASDSATTR _IOW(DASD_IOCTL_LETTER,2,attrib_data_t) 260#define BIODASDSATTR _IOW(DASD_IOCTL_LETTER,2,attrib_data_t)
249 261
262#define BIODASDSYMMIO _IOWR(DASD_IOCTL_LETTER, 240, dasd_symmio_parms_t)
250 263
251#endif /* DASD_H */ 264#endif /* DASD_H */
252 265
diff --git a/arch/s390/include/asm/delay.h b/arch/s390/include/asm/delay.h
index 78357314c450..a356c958e260 100644
--- a/arch/s390/include/asm/delay.h
+++ b/arch/s390/include/asm/delay.h
@@ -15,6 +15,7 @@
15#define _S390_DELAY_H 15#define _S390_DELAY_H
16 16
17extern void __udelay(unsigned long usecs); 17extern void __udelay(unsigned long usecs);
18extern void udelay_simple(unsigned long usecs);
18extern void __delay(unsigned long loops); 19extern void __delay(unsigned long loops);
19 20
20#define udelay(n) __udelay(n) 21#define udelay(n) __udelay(n)
diff --git a/arch/s390/include/asm/elf.h b/arch/s390/include/asm/elf.h
index 3cad56923815..261785ab5b22 100644
--- a/arch/s390/include/asm/elf.h
+++ b/arch/s390/include/asm/elf.h
@@ -166,13 +166,11 @@ extern char elf_platform[];
166#define ELF_PLATFORM (elf_platform) 166#define ELF_PLATFORM (elf_platform)
167 167
168#ifndef __s390x__ 168#ifndef __s390x__
169#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX) 169#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
170#else /* __s390x__ */ 170#else /* __s390x__ */
171#define SET_PERSONALITY(ex, ibcs2) \ 171#define SET_PERSONALITY(ex) \
172do { \ 172do { \
173 if (ibcs2) \ 173 if (current->personality != PER_LINUX32) \
174 set_personality(PER_SVR4); \
175 else if (current->personality != PER_LINUX32) \
176 set_personality(PER_LINUX); \ 174 set_personality(PER_LINUX); \
177 if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \ 175 if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \
178 set_thread_flag(TIF_31BIT); \ 176 set_thread_flag(TIF_31BIT); \
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
index 0bdb704ae051..1a928f84afd6 100644
--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -281,6 +281,9 @@ extern char empty_zero_page[PAGE_SIZE];
281#define RCP_GR_BIT 50 281#define RCP_GR_BIT 50
282#define RCP_GC_BIT 49 282#define RCP_GC_BIT 49
283 283
284/* User dirty bit for KVM's migration feature */
285#define KVM_UD_BIT 47
286
284#ifndef __s390x__ 287#ifndef __s390x__
285 288
286/* Bits in the segment table address-space-control-element */ 289/* Bits in the segment table address-space-control-element */
@@ -575,12 +578,16 @@ static inline void ptep_rcp_copy(pte_t *ptep)
575 unsigned long *pgste = (unsigned long *) (ptep + PTRS_PER_PTE); 578 unsigned long *pgste = (unsigned long *) (ptep + PTRS_PER_PTE);
576 579
577 skey = page_get_storage_key(page_to_phys(page)); 580 skey = page_get_storage_key(page_to_phys(page));
578 if (skey & _PAGE_CHANGED) 581 if (skey & _PAGE_CHANGED) {
579 set_bit_simple(RCP_GC_BIT, pgste); 582 set_bit_simple(RCP_GC_BIT, pgste);
583 set_bit_simple(KVM_UD_BIT, pgste);
584 }
580 if (skey & _PAGE_REFERENCED) 585 if (skey & _PAGE_REFERENCED)
581 set_bit_simple(RCP_GR_BIT, pgste); 586 set_bit_simple(RCP_GR_BIT, pgste);
582 if (test_and_clear_bit_simple(RCP_HC_BIT, pgste)) 587 if (test_and_clear_bit_simple(RCP_HC_BIT, pgste)) {
583 SetPageDirty(page); 588 SetPageDirty(page);
589 set_bit_simple(KVM_UD_BIT, pgste);
590 }
584 if (test_and_clear_bit_simple(RCP_HR_BIT, pgste)) 591 if (test_and_clear_bit_simple(RCP_HR_BIT, pgste))
585 SetPageReferenced(page); 592 SetPageReferenced(page);
586#endif 593#endif
@@ -744,6 +751,40 @@ static inline pte_t pte_mkspecial(pte_t pte)
744 return pte; 751 return pte;
745} 752}
746 753
754#ifdef CONFIG_PGSTE
755/*
756 * Get (and clear) the user dirty bit for a PTE.
757 */
758static inline int kvm_s390_test_and_clear_page_dirty(struct mm_struct *mm,
759 pte_t *ptep)
760{
761 int dirty;
762 unsigned long *pgste;
763 struct page *page;
764 unsigned int skey;
765
766 if (!mm->context.pgstes)
767 return -EINVAL;
768 rcp_lock(ptep);
769 pgste = (unsigned long *) (ptep + PTRS_PER_PTE);
770 page = virt_to_page(pte_val(*ptep));
771 skey = page_get_storage_key(page_to_phys(page));
772 if (skey & _PAGE_CHANGED) {
773 set_bit_simple(RCP_GC_BIT, pgste);
774 set_bit_simple(KVM_UD_BIT, pgste);
775 }
776 if (test_and_clear_bit_simple(RCP_HC_BIT, pgste)) {
777 SetPageDirty(page);
778 set_bit_simple(KVM_UD_BIT, pgste);
779 }
780 dirty = test_and_clear_bit_simple(KVM_UD_BIT, pgste);
781 if (skey & _PAGE_CHANGED)
782 page_clear_dirty(page);
783 rcp_unlock(ptep);
784 return dirty;
785}
786#endif
787
747#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG 788#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
748static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, 789static inline int ptep_test_and_clear_young(struct vm_area_struct *vma,
749 unsigned long addr, pte_t *ptep) 790 unsigned long addr, pte_t *ptep)
diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h
index af2c9ac28a07..a7226f8143fb 100644
--- a/arch/s390/include/asm/ptrace.h
+++ b/arch/s390/include/asm/ptrace.h
@@ -490,6 +490,7 @@ extern void user_disable_single_step(struct task_struct *);
490 490
491#define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0) 491#define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0)
492#define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN) 492#define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN)
493#define user_stack_pointer(regs)((regs)->gprs[15])
493#define regs_return_value(regs)((regs)->gprs[2]) 494#define regs_return_value(regs)((regs)->gprs[2])
494#define profile_pc(regs) instruction_pointer(regs) 495#define profile_pc(regs) instruction_pointer(regs)
495extern void show_regs(struct pt_regs * regs); 496extern void show_regs(struct pt_regs * regs);
diff --git a/arch/s390/include/asm/qdio.h b/arch/s390/include/asm/qdio.h
index 6813772171f2..4734c3f05354 100644
--- a/arch/s390/include/asm/qdio.h
+++ b/arch/s390/include/asm/qdio.h
@@ -299,7 +299,13 @@ struct qdio_ssqd_desc {
299 u8 mbccnt; 299 u8 mbccnt;
300 u16 qdioac2; 300 u16 qdioac2;
301 u64 sch_token; 301 u64 sch_token;
302 u64:64; 302 u8 mro;
303 u8 mri;
304 u8:8;
305 u8 sbalic;
306 u16:16;
307 u8:8;
308 u8 mmwc;
303} __attribute__ ((packed)); 309} __attribute__ ((packed));
304 310
305/* params are: ccw_device, qdio_error, queue_number, 311/* params are: ccw_device, qdio_error, queue_number,
diff --git a/arch/s390/include/asm/statfs.h b/arch/s390/include/asm/statfs.h
index 099a45579190..06cc70307ece 100644
--- a/arch/s390/include/asm/statfs.h
+++ b/arch/s390/include/asm/statfs.h
@@ -12,19 +12,16 @@
12#ifndef __s390x__ 12#ifndef __s390x__
13#include <asm-generic/statfs.h> 13#include <asm-generic/statfs.h>
14#else 14#else
15/*
16 * We can't use <asm-generic/statfs.h> because in 64-bit mode
17 * we mix ints of different sizes in our struct statfs.
18 */
15 19
16#ifndef __KERNEL_STRICT_NAMES 20#ifndef __KERNEL_STRICT_NAMES
17
18#include <linux/types.h> 21#include <linux/types.h>
19
20typedef __kernel_fsid_t fsid_t; 22typedef __kernel_fsid_t fsid_t;
21
22#endif 23#endif
23 24
24/*
25 * This is ugly -- we're already 64-bit clean, so just duplicate the
26 * definitions.
27 */
28struct statfs { 25struct statfs {
29 int f_type; 26 int f_type;
30 int f_bsize; 27 int f_bsize;
diff --git a/arch/s390/include/asm/syscall.h b/arch/s390/include/asm/syscall.h
new file mode 100644
index 000000000000..6e623971fbb9
--- /dev/null
+++ b/arch/s390/include/asm/syscall.h
@@ -0,0 +1,80 @@
1/*
2 * Access to user system call parameters and results
3 *
4 * Copyright IBM Corp. 2008
5 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License (version 2 only)
9 * as published by the Free Software Foundation.
10 */
11
12#ifndef _ASM_SYSCALL_H
13#define _ASM_SYSCALL_H 1
14
15#include <asm/ptrace.h>
16
17static inline long syscall_get_nr(struct task_struct *task,
18 struct pt_regs *regs)
19{
20 if (regs->trap != __LC_SVC_OLD_PSW)
21 return -1;
22 return regs->gprs[2];
23}
24
25static inline void syscall_rollback(struct task_struct *task,
26 struct pt_regs *regs)
27{
28 regs->gprs[2] = regs->orig_gpr2;
29}
30
31static inline long syscall_get_error(struct task_struct *task,
32 struct pt_regs *regs)
33{
34 return (regs->gprs[2] >= -4096UL) ? -regs->gprs[2] : 0;
35}
36
37static inline long syscall_get_return_value(struct task_struct *task,
38 struct pt_regs *regs)
39{
40 return regs->gprs[2];
41}
42
43static inline void syscall_set_return_value(struct task_struct *task,
44 struct pt_regs *regs,
45 int error, long val)
46{
47 regs->gprs[2] = error ? -error : val;
48}
49
50static inline void syscall_get_arguments(struct task_struct *task,
51 struct pt_regs *regs,
52 unsigned int i, unsigned int n,
53 unsigned long *args)
54{
55 BUG_ON(i + n > 6);
56#ifdef CONFIG_COMPAT
57 if (test_tsk_thread_flag(task, TIF_31BIT)) {
58 if (i + n == 6)
59 args[--n] = (u32) regs->args[0];
60 while (n-- > 0)
61 args[n] = (u32) regs->gprs[2 + i + n];
62 }
63#endif
64 if (i + n == 6)
65 args[--n] = regs->args[0];
66 memcpy(args, &regs->gprs[2 + i], n * sizeof(args[0]));
67}
68
69static inline void syscall_set_arguments(struct task_struct *task,
70 struct pt_regs *regs,
71 unsigned int i, unsigned int n,
72 const unsigned long *args)
73{
74 BUG_ON(i + n > 6);
75 if (i + n == 6)
76 regs->args[0] = args[--n];
77 memcpy(&regs->gprs[2 + i], args, n * sizeof(args[0]));
78}
79
80#endif /* _ASM_SYSCALL_H */
diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h
index 91a8f93ad355..ea40a9d690fc 100644
--- a/arch/s390/include/asm/thread_info.h
+++ b/arch/s390/include/asm/thread_info.h
@@ -86,6 +86,7 @@ static inline struct thread_info *current_thread_info(void)
86 * thread information flags bit numbers 86 * thread information flags bit numbers
87 */ 87 */
88#define TIF_SYSCALL_TRACE 0 /* syscall trace active */ 88#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
89#define TIF_NOTIFY_RESUME 1 /* callback before returning to user */
89#define TIF_SIGPENDING 2 /* signal pending */ 90#define TIF_SIGPENDING 2 /* signal pending */
90#define TIF_NEED_RESCHED 3 /* rescheduling necessary */ 91#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
91#define TIF_RESTART_SVC 4 /* restart svc with new svc number */ 92#define TIF_RESTART_SVC 4 /* restart svc with new svc number */
@@ -100,6 +101,7 @@ static inline struct thread_info *current_thread_info(void)
100#define TIF_RESTORE_SIGMASK 20 /* restore signal mask in do_signal() */ 101#define TIF_RESTORE_SIGMASK 20 /* restore signal mask in do_signal() */
101 102
102#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) 103#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
104#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
103#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK) 105#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
104#define _TIF_SIGPENDING (1<<TIF_SIGPENDING) 106#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
105#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED) 107#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index d7f22226fc4e..4646382af34f 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -279,22 +279,6 @@ asmlinkage long sys32_getegid16(void)
279 return high2lowgid(current->egid); 279 return high2lowgid(current->egid);
280} 280}
281 281
282/* 32-bit timeval and related flotsam. */
283
284static inline long get_tv32(struct timeval *o, struct compat_timeval __user *i)
285{
286 return (!access_ok(VERIFY_READ, o, sizeof(*o)) ||
287 (__get_user(o->tv_sec, &i->tv_sec) ||
288 __get_user(o->tv_usec, &i->tv_usec)));
289}
290
291static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i)
292{
293 return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
294 (__put_user(i->tv_sec, &o->tv_sec) ||
295 __put_user(i->tv_usec, &o->tv_usec)));
296}
297
298/* 282/*
299 * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation. 283 * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation.
300 * 284 *
@@ -362,41 +346,6 @@ asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned
362 return sys_ftruncate(fd, (high << 32) | low); 346 return sys_ftruncate(fd, (high << 32) | low);
363} 347}
364 348
365int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
366{
367 compat_ino_t ino;
368 int err;
369
370 if (!old_valid_dev(stat->dev) || !old_valid_dev(stat->rdev))
371 return -EOVERFLOW;
372
373 ino = stat->ino;
374 if (sizeof(ino) < sizeof(stat->ino) && ino != stat->ino)
375 return -EOVERFLOW;
376
377 err = put_user(old_encode_dev(stat->dev), &statbuf->st_dev);
378 err |= put_user(stat->ino, &statbuf->st_ino);
379 err |= put_user(stat->mode, &statbuf->st_mode);
380 err |= put_user(stat->nlink, &statbuf->st_nlink);
381 err |= put_user(high2lowuid(stat->uid), &statbuf->st_uid);
382 err |= put_user(high2lowgid(stat->gid), &statbuf->st_gid);
383 err |= put_user(old_encode_dev(stat->rdev), &statbuf->st_rdev);
384 err |= put_user(stat->size, &statbuf->st_size);
385 err |= put_user(stat->atime.tv_sec, &statbuf->st_atime);
386 err |= put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec);
387 err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime);
388 err |= put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec);
389 err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime);
390 err |= put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec);
391 err |= put_user(stat->blksize, &statbuf->st_blksize);
392 err |= put_user(stat->blocks, &statbuf->st_blocks);
393/* fixme
394 err |= put_user(0, &statbuf->__unused4[0]);
395 err |= put_user(0, &statbuf->__unused4[1]);
396*/
397 return err;
398}
399
400asmlinkage long sys32_sched_rr_get_interval(compat_pid_t pid, 349asmlinkage long sys32_sched_rr_get_interval(compat_pid_t pid,
401 struct compat_timespec __user *interval) 350 struct compat_timespec __user *interval)
402{ 351{
@@ -557,65 +506,6 @@ sys32_delete_module(const char __user *name_user, unsigned int flags)
557 506
558#endif /* CONFIG_MODULES */ 507#endif /* CONFIG_MODULES */
559 508
560/* Translations due to time_t size differences. Which affects all
561 sorts of things, like timeval and itimerval. */
562
563extern struct timezone sys_tz;
564
565asmlinkage long sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
566{
567 if (tv) {
568 struct timeval ktv;
569 do_gettimeofday(&ktv);
570 if (put_tv32(tv, &ktv))
571 return -EFAULT;
572 }
573 if (tz) {
574 if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
575 return -EFAULT;
576 }
577 return 0;
578}
579
580static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
581{
582 long usec;
583
584 if (!access_ok(VERIFY_READ, i, sizeof(*i)))
585 return -EFAULT;
586 if (__get_user(o->tv_sec, &i->tv_sec))
587 return -EFAULT;
588 if (__get_user(usec, &i->tv_usec))
589 return -EFAULT;
590 o->tv_nsec = usec * 1000;
591 return 0;
592}
593
594asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
595{
596 struct timespec kts;
597 struct timezone ktz;
598
599 if (tv) {
600 if (get_ts32(&kts, tv))
601 return -EFAULT;
602 }
603 if (tz) {
604 if (copy_from_user(&ktz, tz, sizeof(ktz)))
605 return -EFAULT;
606 }
607
608 return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
609}
610
611/* These are here just in case some old sparc32 binary calls it. */
612asmlinkage long sys32_pause(void)
613{
614 current->state = TASK_INTERRUPTIBLE;
615 schedule();
616 return -ERESTARTNOHAND;
617}
618
619asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf, 509asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf,
620 size_t count, u32 poshi, u32 poslo) 510 size_t count, u32 poshi, u32 poslo)
621{ 511{
diff --git a/arch/s390/kernel/compat_linux.h b/arch/s390/kernel/compat_linux.h
index 20723a062017..836a28842900 100644
--- a/arch/s390/kernel/compat_linux.h
+++ b/arch/s390/kernel/compat_linux.h
@@ -202,11 +202,6 @@ long sys32_execve(void);
202long sys32_init_module(void __user *umod, unsigned long len, 202long sys32_init_module(void __user *umod, unsigned long len,
203 const char __user *uargs); 203 const char __user *uargs);
204long sys32_delete_module(const char __user *name_user, unsigned int flags); 204long sys32_delete_module(const char __user *name_user, unsigned int flags);
205long sys32_gettimeofday(struct compat_timeval __user *tv,
206 struct timezone __user *tz);
207long sys32_settimeofday(struct compat_timeval __user *tv,
208 struct timezone __user *tz);
209long sys32_pause(void);
210long sys32_pread64(unsigned int fd, char __user *ubuf, size_t count, 205long sys32_pread64(unsigned int fd, char __user *ubuf, size_t count,
211 u32 poshi, u32 poslo); 206 u32 poshi, u32 poslo);
212long sys32_pwrite64(unsigned int fd, const char __user *ubuf, 207long sys32_pwrite64(unsigned int fd, const char __user *ubuf,
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index 328a20e880b5..fc2c97197a53 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -128,8 +128,6 @@ sys32_alarm_wrapper:
128 llgfr %r2,%r2 # unsigned int 128 llgfr %r2,%r2 # unsigned int
129 jg sys_alarm # branch to system call 129 jg sys_alarm # branch to system call
130 130
131#sys32_pause_wrapper # void
132
133 .globl compat_sys_utime_wrapper 131 .globl compat_sys_utime_wrapper
134compat_sys_utime_wrapper: 132compat_sys_utime_wrapper:
135 llgtr %r2,%r2 # char * 133 llgtr %r2,%r2 # char *
@@ -334,17 +332,17 @@ compat_sys_getrusage_wrapper:
334 llgtr %r3,%r3 # struct rusage_emu31 * 332 llgtr %r3,%r3 # struct rusage_emu31 *
335 jg compat_sys_getrusage # branch to system call 333 jg compat_sys_getrusage # branch to system call
336 334
337 .globl sys32_gettimeofday_wrapper 335 .globl compat_sys_gettimeofday_wrapper
338sys32_gettimeofday_wrapper: 336compat_sys_gettimeofday_wrapper:
339 llgtr %r2,%r2 # struct timeval_emu31 * 337 llgtr %r2,%r2 # struct timeval_emu31 *
340 llgtr %r3,%r3 # struct timezone * 338 llgtr %r3,%r3 # struct timezone *
341 jg sys32_gettimeofday # branch to system call 339 jg compat_sys_gettimeofday # branch to system call
342 340
343 .globl sys32_settimeofday_wrapper 341 .globl compat_sys_settimeofday_wrapper
344sys32_settimeofday_wrapper: 342compat_sys_settimeofday_wrapper:
345 llgtr %r2,%r2 # struct timeval_emu31 * 343 llgtr %r2,%r2 # struct timeval_emu31 *
346 llgtr %r3,%r3 # struct timezone * 344 llgtr %r3,%r3 # struct timezone *
347 jg sys32_settimeofday # branch to system call 345 jg compat_sys_settimeofday # branch to system call
348 346
349 .globl sys32_getgroups16_wrapper 347 .globl sys32_getgroups16_wrapper
350sys32_getgroups16_wrapper: 348sys32_getgroups16_wrapper:
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 708cf9cf9a35..ed500ef799b7 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -49,9 +49,9 @@ SP_ILC = STACK_FRAME_OVERHEAD + __PT_ILC
49SP_TRAP = STACK_FRAME_OVERHEAD + __PT_TRAP 49SP_TRAP = STACK_FRAME_OVERHEAD + __PT_TRAP
50SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE 50SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE
51 51
52_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \ 52_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
53 _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP ) 53 _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
54_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \ 54_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
55 _TIF_MCCK_PENDING) 55 _TIF_MCCK_PENDING)
56 56
57STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER 57STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
@@ -318,6 +318,8 @@ sysc_work:
318 bo BASED(sysc_reschedule) 318 bo BASED(sysc_reschedule)
319 tm __TI_flags+3(%r9),_TIF_SIGPENDING 319 tm __TI_flags+3(%r9),_TIF_SIGPENDING
320 bnz BASED(sysc_sigpending) 320 bnz BASED(sysc_sigpending)
321 tm __TI_flags+3(%r9),_TIF_NOTIFY_RESUME
322 bnz BASED(sysc_notify_resume)
321 tm __TI_flags+3(%r9),_TIF_RESTART_SVC 323 tm __TI_flags+3(%r9),_TIF_RESTART_SVC
322 bo BASED(sysc_restart) 324 bo BASED(sysc_restart)
323 tm __TI_flags+3(%r9),_TIF_SINGLE_STEP 325 tm __TI_flags+3(%r9),_TIF_SINGLE_STEP
@@ -356,6 +358,16 @@ sysc_sigpending:
356 b BASED(sysc_work_loop) 358 b BASED(sysc_work_loop)
357 359
358# 360#
361# _TIF_NOTIFY_RESUME is set, call do_notify_resume
362#
363sysc_notify_resume:
364 la %r2,SP_PTREGS(%r15) # load pt_regs
365 l %r1,BASED(.Ldo_notify_resume)
366 la %r14,BASED(sysc_work_loop)
367 br %r1 # call do_notify_resume
368
369
370#
359# _TIF_RESTART_SVC is set, set up registers and restart svc 371# _TIF_RESTART_SVC is set, set up registers and restart svc
360# 372#
361sysc_restart: 373sysc_restart:
@@ -378,20 +390,21 @@ sysc_singlestep:
378 br %r1 # branch to do_single_step 390 br %r1 # branch to do_single_step
379 391
380# 392#
381# call trace before and after sys_call 393# call tracehook_report_syscall_entry/tracehook_report_syscall_exit before
394# and after the system call
382# 395#
383sysc_tracesys: 396sysc_tracesys:
384 l %r1,BASED(.Ltrace) 397 l %r1,BASED(.Ltrace_entry)
385 la %r2,SP_PTREGS(%r15) # load pt_regs 398 la %r2,SP_PTREGS(%r15) # load pt_regs
386 la %r3,0 399 la %r3,0
387 srl %r7,2 400 srl %r7,2
388 st %r7,SP_R2(%r15) 401 st %r7,SP_R2(%r15)
389 basr %r14,%r1 402 basr %r14,%r1
390 clc SP_R2(4,%r15),BASED(.Lnr_syscalls) 403 cl %r2,BASED(.Lnr_syscalls)
391 bnl BASED(sysc_tracenogo) 404 bnl BASED(sysc_tracenogo)
392 l %r8,BASED(.Lsysc_table) 405 l %r8,BASED(.Lsysc_table)
393 l %r7,SP_R2(%r15) # strace might have changed the 406 lr %r7,%r2
394 sll %r7,2 # system call 407 sll %r7,2 # *4
395 l %r8,0(%r7,%r8) 408 l %r8,0(%r7,%r8)
396sysc_tracego: 409sysc_tracego:
397 lm %r3,%r6,SP_R3(%r15) 410 lm %r3,%r6,SP_R3(%r15)
@@ -401,9 +414,8 @@ sysc_tracego:
401sysc_tracenogo: 414sysc_tracenogo:
402 tm __TI_flags+3(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT) 415 tm __TI_flags+3(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
403 bz BASED(sysc_return) 416 bz BASED(sysc_return)
404 l %r1,BASED(.Ltrace) 417 l %r1,BASED(.Ltrace_exit)
405 la %r2,SP_PTREGS(%r15) # load pt_regs 418 la %r2,SP_PTREGS(%r15) # load pt_regs
406 la %r3,1
407 la %r14,BASED(sysc_return) 419 la %r14,BASED(sysc_return)
408 br %r1 420 br %r1
409 421
@@ -666,6 +678,8 @@ io_work_loop:
666 bo BASED(io_reschedule) 678 bo BASED(io_reschedule)
667 tm __TI_flags+3(%r9),_TIF_SIGPENDING 679 tm __TI_flags+3(%r9),_TIF_SIGPENDING
668 bnz BASED(io_sigpending) 680 bnz BASED(io_sigpending)
681 tm __TI_flags+3(%r9),_TIF_NOTIFY_RESUME
682 bnz BASED(io_notify_resume)
669 b BASED(io_restore) 683 b BASED(io_restore)
670io_work_done: 684io_work_done:
671 685
@@ -704,6 +718,19 @@ io_sigpending:
704 TRACE_IRQS_OFF 718 TRACE_IRQS_OFF
705 b BASED(io_work_loop) 719 b BASED(io_work_loop)
706 720
721#
722# _TIF_SIGPENDING is set, call do_signal
723#
724io_notify_resume:
725 TRACE_IRQS_ON
726 stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
727 la %r2,SP_PTREGS(%r15) # load pt_regs
728 l %r1,BASED(.Ldo_notify_resume)
729 basr %r14,%r1 # call do_signal
730 stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
731 TRACE_IRQS_OFF
732 b BASED(io_work_loop)
733
707/* 734/*
708 * External interrupt handler routine 735 * External interrupt handler routine
709 */ 736 */
@@ -1070,6 +1097,8 @@ cleanup_io_leave_insn:
1070.Ldo_IRQ: .long do_IRQ 1097.Ldo_IRQ: .long do_IRQ
1071.Ldo_extint: .long do_extint 1098.Ldo_extint: .long do_extint
1072.Ldo_signal: .long do_signal 1099.Ldo_signal: .long do_signal
1100.Ldo_notify_resume:
1101 .long do_notify_resume
1073.Lhandle_per: .long do_single_step 1102.Lhandle_per: .long do_single_step
1074.Ldo_execve: .long do_execve 1103.Ldo_execve: .long do_execve
1075.Lexecve_tail: .long execve_tail 1104.Lexecve_tail: .long execve_tail
@@ -1079,7 +1108,8 @@ cleanup_io_leave_insn:
1079.Lpreempt_schedule_irq: 1108.Lpreempt_schedule_irq:
1080 .long preempt_schedule_irq 1109 .long preempt_schedule_irq
1081#endif 1110#endif
1082.Ltrace: .long syscall_trace 1111.Ltrace_entry: .long do_syscall_trace_enter
1112.Ltrace_exit: .long do_syscall_trace_exit
1083.Lschedtail: .long schedule_tail 1113.Lschedtail: .long schedule_tail
1084.Lsysc_table: .long sys_call_table 1114.Lsysc_table: .long sys_call_table
1085#ifdef CONFIG_TRACE_IRQFLAGS 1115#ifdef CONFIG_TRACE_IRQFLAGS
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index fee10177dbfc..d7ce150453f2 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -52,9 +52,9 @@ SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE
52STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER 52STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
53STACK_SIZE = 1 << STACK_SHIFT 53STACK_SIZE = 1 << STACK_SHIFT
54 54
55_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \ 55_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
56 _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP ) 56 _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
57_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \ 57_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
58 _TIF_MCCK_PENDING) 58 _TIF_MCCK_PENDING)
59 59
60#define BASED(name) name-system_call(%r13) 60#define BASED(name) name-system_call(%r13)
@@ -310,6 +310,8 @@ sysc_work:
310 jo sysc_reschedule 310 jo sysc_reschedule
311 tm __TI_flags+7(%r9),_TIF_SIGPENDING 311 tm __TI_flags+7(%r9),_TIF_SIGPENDING
312 jnz sysc_sigpending 312 jnz sysc_sigpending
313 tm __TI_flags+7(%r9),_TIF_NOTIFY_RESUME
314 jnz sysc_notify_resume
313 tm __TI_flags+7(%r9),_TIF_RESTART_SVC 315 tm __TI_flags+7(%r9),_TIF_RESTART_SVC
314 jo sysc_restart 316 jo sysc_restart
315 tm __TI_flags+7(%r9),_TIF_SINGLE_STEP 317 tm __TI_flags+7(%r9),_TIF_SINGLE_STEP
@@ -345,6 +347,14 @@ sysc_sigpending:
345 j sysc_work_loop 347 j sysc_work_loop
346 348
347# 349#
350# _TIF_NOTIFY_RESUME is set, call do_notify_resume
351#
352sysc_notify_resume:
353 la %r2,SP_PTREGS(%r15) # load pt_regs
354 larl %r14,sysc_work_loop
355 jg do_notify_resume # call do_notify_resume
356
357#
348# _TIF_RESTART_SVC is set, set up registers and restart svc 358# _TIF_RESTART_SVC is set, set up registers and restart svc
349# 359#
350sysc_restart: 360sysc_restart:
@@ -367,20 +377,19 @@ sysc_singlestep:
367 jg do_single_step # branch to do_sigtrap 377 jg do_single_step # branch to do_sigtrap
368 378
369# 379#
370# call syscall_trace before and after system call 380# call tracehook_report_syscall_entry/tracehook_report_syscall_exit before
371# special linkage: %r12 contains the return address for trace_svc 381# and after the system call
372# 382#
373sysc_tracesys: 383sysc_tracesys:
374 la %r2,SP_PTREGS(%r15) # load pt_regs 384 la %r2,SP_PTREGS(%r15) # load pt_regs
375 la %r3,0 385 la %r3,0
376 srl %r7,2 386 srl %r7,2
377 stg %r7,SP_R2(%r15) 387 stg %r7,SP_R2(%r15)
378 brasl %r14,syscall_trace 388 brasl %r14,do_syscall_trace_enter
379 lghi %r0,NR_syscalls 389 lghi %r0,NR_syscalls
380 clg %r0,SP_R2(%r15) 390 clgr %r0,%r2
381 jnh sysc_tracenogo 391 jnh sysc_tracenogo
382 lg %r7,SP_R2(%r15) # strace might have changed the 392 slag %r7,%r2,2 # *4
383 sll %r7,2 # system call
384 lgf %r8,0(%r7,%r10) 393 lgf %r8,0(%r7,%r10)
385sysc_tracego: 394sysc_tracego:
386 lmg %r3,%r6,SP_R3(%r15) 395 lmg %r3,%r6,SP_R3(%r15)
@@ -391,9 +400,8 @@ sysc_tracenogo:
391 tm __TI_flags+7(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT) 400 tm __TI_flags+7(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
392 jz sysc_return 401 jz sysc_return
393 la %r2,SP_PTREGS(%r15) # load pt_regs 402 la %r2,SP_PTREGS(%r15) # load pt_regs
394 la %r3,1
395 larl %r14,sysc_return # return point is sysc_return 403 larl %r14,sysc_return # return point is sysc_return
396 jg syscall_trace 404 jg do_syscall_trace_exit
397 405
398# 406#
399# a new process exits the kernel with ret_from_fork 407# a new process exits the kernel with ret_from_fork
@@ -672,6 +680,8 @@ io_work_loop:
672 jo io_reschedule 680 jo io_reschedule
673 tm __TI_flags+7(%r9),_TIF_SIGPENDING 681 tm __TI_flags+7(%r9),_TIF_SIGPENDING
674 jnz io_sigpending 682 jnz io_sigpending
683 tm __TI_flags+7(%r9),_TIF_NOTIFY_RESUME
684 jnz io_notify_resume
675 j io_restore 685 j io_restore
676io_work_done: 686io_work_done:
677 687
@@ -712,6 +722,18 @@ io_sigpending:
712 TRACE_IRQS_OFF 722 TRACE_IRQS_OFF
713 j io_work_loop 723 j io_work_loop
714 724
725#
726# _TIF_NOTIFY_RESUME or is set, call do_notify_resume
727#
728io_notify_resume:
729 TRACE_IRQS_ON
730 stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
731 la %r2,SP_PTREGS(%r15) # load pt_regs
732 brasl %r14,do_notify_resume # call do_notify_resume
733 stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
734 TRACE_IRQS_OFF
735 j io_work_loop
736
715/* 737/*
716 * External interrupt handler routine 738 * External interrupt handler routine
717 */ 739 */
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index c8b08289eb87..1f31be1ecc4b 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -35,6 +35,7 @@
35#include <linux/signal.h> 35#include <linux/signal.h>
36#include <linux/elf.h> 36#include <linux/elf.h>
37#include <linux/regset.h> 37#include <linux/regset.h>
38#include <linux/tracehook.h>
38 39
39#include <asm/segment.h> 40#include <asm/segment.h>
40#include <asm/page.h> 41#include <asm/page.h>
@@ -639,40 +640,44 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
639} 640}
640#endif 641#endif
641 642
642asmlinkage void 643asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
643syscall_trace(struct pt_regs *regs, int entryexit)
644{ 644{
645 if (unlikely(current->audit_context) && entryexit) 645 long ret;
646 audit_syscall_exit(AUDITSC_RESULT(regs->gprs[2]), regs->gprs[2]);
647
648 if (!test_thread_flag(TIF_SYSCALL_TRACE))
649 goto out;
650 if (!(current->ptrace & PT_PTRACED))
651 goto out;
652 ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
653 ? 0x80 : 0));
654 646
655 /* 647 /*
656 * If the debuffer has set an invalid system call number, 648 * The sysc_tracesys code in entry.S stored the system
657 * we prepare to skip the system call restart handling. 649 * call number to gprs[2].
658 */ 650 */
659 if (!entryexit && regs->gprs[2] >= NR_syscalls) 651 ret = regs->gprs[2];
652 if (test_thread_flag(TIF_SYSCALL_TRACE) &&
653 (tracehook_report_syscall_entry(regs) ||
654 regs->gprs[2] >= NR_syscalls)) {
655 /*
656 * Tracing decided this syscall should not happen or the
657 * debugger stored an invalid system call number. Skip
658 * the system call and the system call restart handling.
659 */
660 regs->trap = -1; 660 regs->trap = -1;
661 661 ret = -1;
662 /*
663 * this isn't the same as continuing with a signal, but it will do
664 * for normal use. strace only continues with a signal if the
665 * stopping signal is not SIGTRAP. -brl
666 */
667 if (current->exit_code) {
668 send_sig(current->exit_code, current, 1);
669 current->exit_code = 0;
670 } 662 }
671 out: 663
672 if (unlikely(current->audit_context) && !entryexit) 664 if (unlikely(current->audit_context))
673 audit_syscall_entry(test_thread_flag(TIF_31BIT)?AUDIT_ARCH_S390:AUDIT_ARCH_S390X, 665 audit_syscall_entry(test_thread_flag(TIF_31BIT) ?
674 regs->gprs[2], regs->orig_gpr2, regs->gprs[3], 666 AUDIT_ARCH_S390 : AUDIT_ARCH_S390X,
675 regs->gprs[4], regs->gprs[5]); 667 regs->gprs[2], regs->orig_gpr2,
668 regs->gprs[3], regs->gprs[4],
669 regs->gprs[5]);
670 return ret;
671}
672
673asmlinkage void do_syscall_trace_exit(struct pt_regs *regs)
674{
675 if (unlikely(current->audit_context))
676 audit_syscall_exit(AUDITSC_RESULT(regs->gprs[2]),
677 regs->gprs[2]);
678
679 if (test_thread_flag(TIF_SYSCALL_TRACE))
680 tracehook_report_syscall_exit(regs, 0);
676} 681}
677 682
678/* 683/*
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index b97682040215..4f7fc3059a8e 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -24,6 +24,7 @@
24#include <linux/tty.h> 24#include <linux/tty.h>
25#include <linux/personality.h> 25#include <linux/personality.h>
26#include <linux/binfmts.h> 26#include <linux/binfmts.h>
27#include <linux/tracehook.h>
27#include <asm/ucontext.h> 28#include <asm/ucontext.h>
28#include <asm/uaccess.h> 29#include <asm/uaccess.h>
29#include <asm/lowcore.h> 30#include <asm/lowcore.h>
@@ -507,6 +508,12 @@ void do_signal(struct pt_regs *regs)
507 */ 508 */
508 if (current->thread.per_info.single_step) 509 if (current->thread.per_info.single_step)
509 set_thread_flag(TIF_SINGLE_STEP); 510 set_thread_flag(TIF_SINGLE_STEP);
511
512 /*
513 * Let tracing know that we've done the handler setup.
514 */
515 tracehook_signal_handler(signr, &info, &ka, regs,
516 test_thread_flag(TIF_SINGLE_STEP));
510 } 517 }
511 return; 518 return;
512 } 519 }
@@ -526,3 +533,9 @@ void do_signal(struct pt_regs *regs)
526 set_thread_flag(TIF_RESTART_SVC); 533 set_thread_flag(TIF_RESTART_SVC);
527 } 534 }
528} 535}
536
537void do_notify_resume(struct pt_regs *regs)
538{
539 clear_thread_flag(TIF_NOTIFY_RESUME);
540 tracehook_notify_resume(regs);
541}
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 00b9b4dec5eb..9e8b1f9b8f4d 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -585,6 +585,8 @@ int __cpuinit start_secondary(void *cpuvoid)
585 /* Enable pfault pseudo page faults on this cpu. */ 585 /* Enable pfault pseudo page faults on this cpu. */
586 pfault_init(); 586 pfault_init();
587 587
588 /* call cpu notifiers */
589 notify_cpu_starting(smp_processor_id());
588 /* Mark this cpu as online */ 590 /* Mark this cpu as online */
589 spin_lock(&call_lock); 591 spin_lock(&call_lock);
590 cpu_set(smp_processor_id(), cpu_online_map); 592 cpu_set(smp_processor_id(), cpu_online_map);
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index c66d35e55142..2d61787949d5 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -37,7 +37,7 @@ SYSCALL(sys_stime,sys_ni_syscall,sys32_stime_wrapper) /* 25 old stime syscall *
37SYSCALL(sys_ptrace,sys_ptrace,sys32_ptrace_wrapper) 37SYSCALL(sys_ptrace,sys_ptrace,sys32_ptrace_wrapper)
38SYSCALL(sys_alarm,sys_alarm,sys32_alarm_wrapper) 38SYSCALL(sys_alarm,sys_alarm,sys32_alarm_wrapper)
39NI_SYSCALL /* old fstat syscall */ 39NI_SYSCALL /* old fstat syscall */
40SYSCALL(sys_pause,sys_pause,sys32_pause) 40SYSCALL(sys_pause,sys_pause,sys_pause)
41SYSCALL(sys_utime,sys_utime,compat_sys_utime_wrapper) /* 30 */ 41SYSCALL(sys_utime,sys_utime,compat_sys_utime_wrapper) /* 30 */
42NI_SYSCALL /* old stty syscall */ 42NI_SYSCALL /* old stty syscall */
43NI_SYSCALL /* old gtty syscall */ 43NI_SYSCALL /* old gtty syscall */
@@ -86,8 +86,8 @@ SYSCALL(sys_sethostname,sys_sethostname,sys32_sethostname_wrapper)
86SYSCALL(sys_setrlimit,sys_setrlimit,compat_sys_setrlimit_wrapper) /* 75 */ 86SYSCALL(sys_setrlimit,sys_setrlimit,compat_sys_setrlimit_wrapper) /* 75 */
87SYSCALL(sys_old_getrlimit,sys_getrlimit,compat_sys_old_getrlimit_wrapper) 87SYSCALL(sys_old_getrlimit,sys_getrlimit,compat_sys_old_getrlimit_wrapper)
88SYSCALL(sys_getrusage,sys_getrusage,compat_sys_getrusage_wrapper) 88SYSCALL(sys_getrusage,sys_getrusage,compat_sys_getrusage_wrapper)
89SYSCALL(sys_gettimeofday,sys_gettimeofday,sys32_gettimeofday_wrapper) 89SYSCALL(sys_gettimeofday,sys_gettimeofday,compat_sys_gettimeofday_wrapper)
90SYSCALL(sys_settimeofday,sys_settimeofday,sys32_settimeofday_wrapper) 90SYSCALL(sys_settimeofday,sys_settimeofday,compat_sys_settimeofday_wrapper)
91SYSCALL(sys_getgroups16,sys_ni_syscall,sys32_getgroups16_wrapper) /* 80 old getgroups16 syscall */ 91SYSCALL(sys_getgroups16,sys_ni_syscall,sys32_getgroups16_wrapper) /* 80 old getgroups16 syscall */
92SYSCALL(sys_setgroups16,sys_ni_syscall,sys32_setgroups16_wrapper) /* old setgroups16 syscall */ 92SYSCALL(sys_setgroups16,sys_ni_syscall,sys32_setgroups16_wrapper) /* old setgroups16 syscall */
93NI_SYSCALL /* old select syscall */ 93NI_SYSCALL /* old select syscall */
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 06acb1a18bbc..b94e9e3b694a 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -1356,7 +1356,7 @@ static void __init stp_reset(void)
1356 1356
1357 stp_page = alloc_bootmem_pages(PAGE_SIZE); 1357 stp_page = alloc_bootmem_pages(PAGE_SIZE);
1358 rc = chsc_sstpc(stp_page, STP_OP_CTRL, 0x0000); 1358 rc = chsc_sstpc(stp_page, STP_OP_CTRL, 0x0000);
1359 if (rc == 1) 1359 if (rc == 0)
1360 set_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags); 1360 set_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags);
1361 else if (stp_online) { 1361 else if (stp_online) {
1362 printk(KERN_WARNING "Running on non STP capable machine.\n"); 1362 printk(KERN_WARNING "Running on non STP capable machine.\n");
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
index d1faf5c54405..cce40ff2913b 100644
--- a/arch/s390/kvm/priv.c
+++ b/arch/s390/kvm/priv.c
@@ -157,8 +157,8 @@ static int handle_stfl(struct kvm_vcpu *vcpu)
157 int rc; 157 int rc;
158 158
159 vcpu->stat.instruction_stfl++; 159 vcpu->stat.instruction_stfl++;
160 facility_list &= ~(1UL<<24); /* no stfle */ 160 /* only pass the facility bits, which we can handle */
161 facility_list &= ~(1UL<<23); /* no large pages */ 161 facility_list &= 0xfe00fff3;
162 162
163 rc = copy_to_guest(vcpu, offsetof(struct _lowcore, stfl_fac_list), 163 rc = copy_to_guest(vcpu, offsetof(struct _lowcore, stfl_fac_list),
164 &facility_list, sizeof(facility_list)); 164 &facility_list, sizeof(facility_list));
diff --git a/arch/s390/lib/delay.c b/arch/s390/lib/delay.c
index 0953cee05efc..6ccb9fab055a 100644
--- a/arch/s390/lib/delay.c
+++ b/arch/s390/lib/delay.c
@@ -92,3 +92,16 @@ out:
92 local_irq_restore(flags); 92 local_irq_restore(flags);
93 preempt_enable(); 93 preempt_enable();
94} 94}
95
96/*
97 * Simple udelay variant. To be used on startup and reboot
98 * when the interrupt handler isn't working.
99 */
100void udelay_simple(unsigned long usecs)
101{
102 u64 end;
103
104 end = get_clock() + ((u64) usecs << 12);
105 while (get_clock() < end)
106 cpu_relax();
107}
diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c
index f231f5ec74b6..580fc64cc735 100644
--- a/arch/s390/mm/extmem.c
+++ b/arch/s390/mm/extmem.c
@@ -43,20 +43,40 @@
43#define DCSS_FINDSEG 0x0c 43#define DCSS_FINDSEG 0x0c
44#define DCSS_LOADNOLY 0x10 44#define DCSS_LOADNOLY 0x10
45#define DCSS_SEGEXT 0x18 45#define DCSS_SEGEXT 0x18
46#define DCSS_LOADSHRX 0x20
47#define DCSS_LOADNSRX 0x24
48#define DCSS_FINDSEGX 0x2c
49#define DCSS_SEGEXTX 0x38
46#define DCSS_FINDSEGA 0x0c 50#define DCSS_FINDSEGA 0x0c
47 51
48struct qrange { 52struct qrange {
49 unsigned int start; // 3byte start address, 1 byte type 53 unsigned long start; /* last byte type */
50 unsigned int end; // 3byte end address, 1 byte reserved 54 unsigned long end; /* last byte reserved */
51}; 55};
52 56
53struct qout64 { 57struct qout64 {
58 unsigned long segstart;
59 unsigned long segend;
60 int segcnt;
61 int segrcnt;
62 struct qrange range[6];
63};
64
65#ifdef CONFIG_64BIT
66struct qrange_old {
67 unsigned int start; /* last byte type */
68 unsigned int end; /* last byte reserved */
69};
70
71/* output area format for the Diag x'64' old subcode x'18' */
72struct qout64_old {
54 int segstart; 73 int segstart;
55 int segend; 74 int segend;
56 int segcnt; 75 int segcnt;
57 int segrcnt; 76 int segrcnt;
58 struct qrange range[6]; 77 struct qrange_old range[6];
59}; 78};
79#endif
60 80
61struct qin64 { 81struct qin64 {
62 char qopcode; 82 char qopcode;
@@ -86,6 +106,55 @@ static DEFINE_MUTEX(dcss_lock);
86static LIST_HEAD(dcss_list); 106static LIST_HEAD(dcss_list);
87static char *segtype_string[] = { "SW", "EW", "SR", "ER", "SN", "EN", "SC", 107static char *segtype_string[] = { "SW", "EW", "SR", "ER", "SN", "EN", "SC",
88 "EW/EN-MIXED" }; 108 "EW/EN-MIXED" };
109static int loadshr_scode, loadnsr_scode, findseg_scode;
110static int segext_scode, purgeseg_scode;
111static int scode_set;
112
113/* set correct Diag x'64' subcodes. */
114static int
115dcss_set_subcodes(void)
116{
117#ifdef CONFIG_64BIT
118 char *name = kmalloc(8 * sizeof(char), GFP_DMA);
119 unsigned long rx, ry;
120 int rc;
121
122 if (name == NULL)
123 return -ENOMEM;
124
125 rx = (unsigned long) name;
126 ry = DCSS_FINDSEGX;
127
128 strcpy(name, "dummy");
129 asm volatile(
130 " diag %0,%1,0x64\n"
131 "0: ipm %2\n"
132 " srl %2,28\n"
133 " j 2f\n"
134 "1: la %2,3\n"
135 "2:\n"
136 EX_TABLE(0b, 1b)
137 : "+d" (rx), "+d" (ry), "=d" (rc) : : "cc");
138
139 kfree(name);
140 /* Diag x'64' new subcodes are supported, set to new subcodes */
141 if (rc != 3) {
142 loadshr_scode = DCSS_LOADSHRX;
143 loadnsr_scode = DCSS_LOADNSRX;
144 purgeseg_scode = DCSS_PURGESEG;
145 findseg_scode = DCSS_FINDSEGX;
146 segext_scode = DCSS_SEGEXTX;
147 return 0;
148 }
149#endif
150 /* Diag x'64' new subcodes are not supported, set to old subcodes */
151 loadshr_scode = DCSS_LOADNOLY;
152 loadnsr_scode = DCSS_LOADNSR;
153 purgeseg_scode = DCSS_PURGESEG;
154 findseg_scode = DCSS_FINDSEG;
155 segext_scode = DCSS_SEGEXT;
156 return 0;
157}
89 158
90/* 159/*
91 * Create the 8 bytes, ebcdic VM segment name from 160 * Create the 8 bytes, ebcdic VM segment name from
@@ -135,25 +204,45 @@ segment_by_name (char *name)
135 * Perform a function on a dcss segment. 204 * Perform a function on a dcss segment.
136 */ 205 */
137static inline int 206static inline int
138dcss_diag (__u8 func, void *parameter, 207dcss_diag(int *func, void *parameter,
139 unsigned long *ret1, unsigned long *ret2) 208 unsigned long *ret1, unsigned long *ret2)
140{ 209{
141 unsigned long rx, ry; 210 unsigned long rx, ry;
142 int rc; 211 int rc;
143 212
213 if (scode_set == 0) {
214 rc = dcss_set_subcodes();
215 if (rc < 0)
216 return rc;
217 scode_set = 1;
218 }
144 rx = (unsigned long) parameter; 219 rx = (unsigned long) parameter;
145 ry = (unsigned long) func; 220 ry = (unsigned long) *func;
146 asm volatile( 221
147#ifdef CONFIG_64BIT 222#ifdef CONFIG_64BIT
148 " sam31\n" 223 /* 64-bit Diag x'64' new subcode, keep in 64-bit addressing mode */
149 " diag %0,%1,0x64\n" 224 if (*func > DCSS_SEGEXT)
150 " sam64\n" 225 asm volatile(
226 " diag %0,%1,0x64\n"
227 " ipm %2\n"
228 " srl %2,28\n"
229 : "+d" (rx), "+d" (ry), "=d" (rc) : : "cc");
230 /* 31-bit Diag x'64' old subcode, switch to 31-bit addressing mode */
231 else
232 asm volatile(
233 " sam31\n"
234 " diag %0,%1,0x64\n"
235 " sam64\n"
236 " ipm %2\n"
237 " srl %2,28\n"
238 : "+d" (rx), "+d" (ry), "=d" (rc) : : "cc");
151#else 239#else
240 asm volatile(
152 " diag %0,%1,0x64\n" 241 " diag %0,%1,0x64\n"
153#endif
154 " ipm %2\n" 242 " ipm %2\n"
155 " srl %2,28\n" 243 " srl %2,28\n"
156 : "+d" (rx), "+d" (ry), "=d" (rc) : : "cc"); 244 : "+d" (rx), "+d" (ry), "=d" (rc) : : "cc");
245#endif
157 *ret1 = rx; 246 *ret1 = rx;
158 *ret2 = ry; 247 *ret2 = ry;
159 return rc; 248 return rc;
@@ -190,14 +279,45 @@ query_segment_type (struct dcss_segment *seg)
190 qin->qoutlen = sizeof(struct qout64); 279 qin->qoutlen = sizeof(struct qout64);
191 memcpy (qin->qname, seg->dcss_name, 8); 280 memcpy (qin->qname, seg->dcss_name, 8);
192 281
193 diag_cc = dcss_diag (DCSS_SEGEXT, qin, &dummy, &vmrc); 282 diag_cc = dcss_diag(&segext_scode, qin, &dummy, &vmrc);
194 283
284 if (diag_cc < 0) {
285 rc = diag_cc;
286 goto out_free;
287 }
195 if (diag_cc > 1) { 288 if (diag_cc > 1) {
196 PRINT_WARN ("segment_type: diag returned error %ld\n", vmrc); 289 PRINT_WARN ("segment_type: diag returned error %ld\n", vmrc);
197 rc = dcss_diag_translate_rc (vmrc); 290 rc = dcss_diag_translate_rc (vmrc);
198 goto out_free; 291 goto out_free;
199 } 292 }
200 293
294#ifdef CONFIG_64BIT
295 /* Only old format of output area of Diagnose x'64' is supported,
296 copy data for the new format. */
297 if (segext_scode == DCSS_SEGEXT) {
298 struct qout64_old *qout_old;
299 qout_old = kzalloc(sizeof(struct qout64_old), GFP_DMA);
300 if (qout_old == NULL) {
301 rc = -ENOMEM;
302 goto out_free;
303 }
304 memcpy(qout_old, qout, sizeof(struct qout64_old));
305 qout->segstart = (unsigned long) qout_old->segstart;
306 qout->segend = (unsigned long) qout_old->segend;
307 qout->segcnt = qout_old->segcnt;
308 qout->segrcnt = qout_old->segrcnt;
309
310 if (qout->segcnt > 6)
311 qout->segrcnt = 6;
312 for (i = 0; i < qout->segrcnt; i++) {
313 qout->range[i].start =
314 (unsigned long) qout_old->range[i].start;
315 qout->range[i].end =
316 (unsigned long) qout_old->range[i].end;
317 }
318 kfree(qout_old);
319 }
320#endif
201 if (qout->segcnt > 6) { 321 if (qout->segcnt > 6) {
202 rc = -ENOTSUPP; 322 rc = -ENOTSUPP;
203 goto out_free; 323 goto out_free;
@@ -269,6 +389,30 @@ segment_type (char* name)
269} 389}
270 390
271/* 391/*
392 * check if segment collides with other segments that are currently loaded
393 * returns 1 if this is the case, 0 if no collision was found
394 */
395static int
396segment_overlaps_others (struct dcss_segment *seg)
397{
398 struct list_head *l;
399 struct dcss_segment *tmp;
400
401 BUG_ON(!mutex_is_locked(&dcss_lock));
402 list_for_each(l, &dcss_list) {
403 tmp = list_entry(l, struct dcss_segment, list);
404 if ((tmp->start_addr >> 20) > (seg->end >> 20))
405 continue;
406 if ((tmp->end >> 20) < (seg->start_addr >> 20))
407 continue;
408 if (seg == tmp)
409 continue;
410 return 1;
411 }
412 return 0;
413}
414
415/*
272 * real segment loading function, called from segment_load 416 * real segment loading function, called from segment_load
273 */ 417 */
274static int 418static int
@@ -276,7 +420,8 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
276{ 420{
277 struct dcss_segment *seg = kmalloc(sizeof(struct dcss_segment), 421 struct dcss_segment *seg = kmalloc(sizeof(struct dcss_segment),
278 GFP_DMA); 422 GFP_DMA);
279 int dcss_command, rc, diag_cc; 423 int rc, diag_cc;
424 unsigned long start_addr, end_addr, dummy;
280 425
281 if (seg == NULL) { 426 if (seg == NULL) {
282 rc = -ENOMEM; 427 rc = -ENOMEM;
@@ -287,6 +432,13 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
287 if (rc < 0) 432 if (rc < 0)
288 goto out_free; 433 goto out_free;
289 434
435 if (loadshr_scode == DCSS_LOADSHRX) {
436 if (segment_overlaps_others(seg)) {
437 rc = -EBUSY;
438 goto out_free;
439 }
440 }
441
290 rc = vmem_add_mapping(seg->start_addr, seg->end - seg->start_addr + 1); 442 rc = vmem_add_mapping(seg->start_addr, seg->end - seg->start_addr + 1);
291 443
292 if (rc) 444 if (rc)
@@ -316,20 +468,28 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
316 } 468 }
317 469
318 if (do_nonshared) 470 if (do_nonshared)
319 dcss_command = DCSS_LOADNSR; 471 diag_cc = dcss_diag(&loadnsr_scode, seg->dcss_name,
472 &start_addr, &end_addr);
320 else 473 else
321 dcss_command = DCSS_LOADNOLY; 474 diag_cc = dcss_diag(&loadshr_scode, seg->dcss_name,
322 475 &start_addr, &end_addr);
323 diag_cc = dcss_diag(dcss_command, seg->dcss_name, 476 if (diag_cc < 0) {
324 &seg->start_addr, &seg->end); 477 dcss_diag(&purgeseg_scode, seg->dcss_name,
478 &dummy, &dummy);
479 rc = diag_cc;
480 goto out_resource;
481 }
325 if (diag_cc > 1) { 482 if (diag_cc > 1) {
326 PRINT_WARN ("segment_load: could not load segment %s - " 483 PRINT_WARN ("segment_load: could not load segment %s - "
327 "diag returned error (%ld)\n",name,seg->end); 484 "diag returned error (%ld)\n",
328 rc = dcss_diag_translate_rc (seg->end); 485 name, end_addr);
329 dcss_diag(DCSS_PURGESEG, seg->dcss_name, 486 rc = dcss_diag_translate_rc(end_addr);
330 &seg->start_addr, &seg->end); 487 dcss_diag(&purgeseg_scode, seg->dcss_name,
488 &dummy, &dummy);
331 goto out_resource; 489 goto out_resource;
332 } 490 }
491 seg->start_addr = start_addr;
492 seg->end = end_addr;
333 seg->do_nonshared = do_nonshared; 493 seg->do_nonshared = do_nonshared;
334 atomic_set(&seg->ref_count, 1); 494 atomic_set(&seg->ref_count, 1);
335 list_add(&seg->list, &dcss_list); 495 list_add(&seg->list, &dcss_list);
@@ -423,8 +583,8 @@ int
423segment_modify_shared (char *name, int do_nonshared) 583segment_modify_shared (char *name, int do_nonshared)
424{ 584{
425 struct dcss_segment *seg; 585 struct dcss_segment *seg;
426 unsigned long dummy; 586 unsigned long start_addr, end_addr, dummy;
427 int dcss_command, rc, diag_cc; 587 int rc, diag_cc;
428 588
429 mutex_lock(&dcss_lock); 589 mutex_lock(&dcss_lock);
430 seg = segment_by_name (name); 590 seg = segment_by_name (name);
@@ -445,38 +605,51 @@ segment_modify_shared (char *name, int do_nonshared)
445 goto out_unlock; 605 goto out_unlock;
446 } 606 }
447 release_resource(seg->res); 607 release_resource(seg->res);
448 if (do_nonshared) { 608 if (do_nonshared)
449 dcss_command = DCSS_LOADNSR;
450 seg->res->flags &= ~IORESOURCE_READONLY; 609 seg->res->flags &= ~IORESOURCE_READONLY;
451 } else { 610 else
452 dcss_command = DCSS_LOADNOLY;
453 if (seg->vm_segtype == SEG_TYPE_SR || 611 if (seg->vm_segtype == SEG_TYPE_SR ||
454 seg->vm_segtype == SEG_TYPE_ER) 612 seg->vm_segtype == SEG_TYPE_ER)
455 seg->res->flags |= IORESOURCE_READONLY; 613 seg->res->flags |= IORESOURCE_READONLY;
456 } 614
457 if (request_resource(&iomem_resource, seg->res)) { 615 if (request_resource(&iomem_resource, seg->res)) {
458 PRINT_WARN("segment_modify_shared: could not reload segment %s" 616 PRINT_WARN("segment_modify_shared: could not reload segment %s"
459 " - overlapping resources\n", name); 617 " - overlapping resources\n", name);
460 rc = -EBUSY; 618 rc = -EBUSY;
461 kfree(seg->res); 619 kfree(seg->res);
462 goto out_del; 620 goto out_del_mem;
621 }
622
623 dcss_diag(&purgeseg_scode, seg->dcss_name, &dummy, &dummy);
624 if (do_nonshared)
625 diag_cc = dcss_diag(&loadnsr_scode, seg->dcss_name,
626 &start_addr, &end_addr);
627 else
628 diag_cc = dcss_diag(&loadshr_scode, seg->dcss_name,
629 &start_addr, &end_addr);
630 if (diag_cc < 0) {
631 rc = diag_cc;
632 goto out_del_res;
463 } 633 }
464 dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy);
465 diag_cc = dcss_diag(dcss_command, seg->dcss_name,
466 &seg->start_addr, &seg->end);
467 if (diag_cc > 1) { 634 if (diag_cc > 1) {
468 PRINT_WARN ("segment_modify_shared: could not reload segment %s" 635 PRINT_WARN ("segment_modify_shared: could not reload segment %s"
469 " - diag returned error (%ld)\n",name,seg->end); 636 " - diag returned error (%ld)\n",
470 rc = dcss_diag_translate_rc (seg->end); 637 name, end_addr);
471 goto out_del; 638 rc = dcss_diag_translate_rc(end_addr);
639 goto out_del_res;
472 } 640 }
641 seg->start_addr = start_addr;
642 seg->end = end_addr;
473 seg->do_nonshared = do_nonshared; 643 seg->do_nonshared = do_nonshared;
474 rc = 0; 644 rc = 0;
475 goto out_unlock; 645 goto out_unlock;
476 out_del: 646 out_del_res:
647 release_resource(seg->res);
648 kfree(seg->res);
649 out_del_mem:
477 vmem_remove_mapping(seg->start_addr, seg->end - seg->start_addr + 1); 650 vmem_remove_mapping(seg->start_addr, seg->end - seg->start_addr + 1);
478 list_del(&seg->list); 651 list_del(&seg->list);
479 dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy); 652 dcss_diag(&purgeseg_scode, seg->dcss_name, &dummy, &dummy);
480 kfree(seg); 653 kfree(seg);
481 out_unlock: 654 out_unlock:
482 mutex_unlock(&dcss_lock); 655 mutex_unlock(&dcss_lock);
@@ -510,7 +683,7 @@ segment_unload(char *name)
510 kfree(seg->res); 683 kfree(seg->res);
511 vmem_remove_mapping(seg->start_addr, seg->end - seg->start_addr + 1); 684 vmem_remove_mapping(seg->start_addr, seg->end - seg->start_addr + 1);
512 list_del(&seg->list); 685 list_del(&seg->list);
513 dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy); 686 dcss_diag(&purgeseg_scode, seg->dcss_name, &dummy, &dummy);
514 kfree(seg); 687 kfree(seg);
515out_unlock: 688out_unlock:
516 mutex_unlock(&dcss_lock); 689 mutex_unlock(&dcss_lock);
@@ -545,7 +718,7 @@ segment_save(char *name)
545 endpfn = (seg->end) >> PAGE_SHIFT; 718 endpfn = (seg->end) >> PAGE_SHIFT;
546 sprintf(cmd1, "DEFSEG %s", name); 719 sprintf(cmd1, "DEFSEG %s", name);
547 for (i=0; i<seg->segcnt; i++) { 720 for (i=0; i<seg->segcnt; i++) {
548 sprintf(cmd1+strlen(cmd1), " %X-%X %s", 721 sprintf(cmd1+strlen(cmd1), " %lX-%lX %s",
549 seg->range[i].start >> PAGE_SHIFT, 722 seg->range[i].start >> PAGE_SHIFT,
550 seg->range[i].end >> PAGE_SHIFT, 723 seg->range[i].end >> PAGE_SHIFT,
551 segtype_string[seg->range[i].start & 0xff]); 724 segtype_string[seg->range[i].start & 0xff]);