summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/s390/Kconfig18
-rw-r--r--arch/s390/include/asm/compat.h19
-rw-r--r--arch/s390/include/asm/cpu.h32
-rw-r--r--arch/s390/include/asm/cputime.h19
-rw-r--r--arch/s390/include/asm/lowcore.h1
-rw-r--r--arch/s390/include/asm/pgtable.h7
-rw-r--r--arch/s390/include/asm/seccomp.h16
-rw-r--r--arch/s390/include/asm/spinlock.h19
-rw-r--r--arch/s390/include/asm/thread_info.h10
-rw-r--r--arch/s390/include/asm/uaccess.h16
-rw-r--r--arch/s390/kernel/Makefile2
-rw-r--r--arch/s390/kernel/entry.S5
-rw-r--r--arch/s390/kernel/entry64.S5
-rw-r--r--arch/s390/kernel/head.S65
-rw-r--r--arch/s390/kernel/nmi.c2
-rw-r--r--arch/s390/kernel/process.c3
-rw-r--r--arch/s390/kernel/ptrace.c16
-rw-r--r--arch/s390/kernel/s390_ext.c2
-rw-r--r--arch/s390/kernel/sclp.S327
-rw-r--r--arch/s390/kernel/signal.c3
-rw-r--r--arch/s390/kernel/smp.c2
-rw-r--r--arch/s390/kernel/vdso.c19
-rw-r--r--arch/s390/kernel/vtime.c2
-rw-r--r--arch/s390/kvm/kvm-s390.c2
-rw-r--r--arch/s390/lib/spinlock.c40
-rw-r--r--arch/s390/mm/fault.c3
-rw-r--r--arch/s390/mm/mmap.c11
-rw-r--r--arch/s390/mm/pgtable.c16
-rw-r--r--drivers/s390/char/con3270.c38
-rw-r--r--drivers/s390/char/tty3270.c57
-rw-r--r--drivers/s390/cio/cio.c2
-rw-r--r--drivers/s390/cio/device_ops.c24
-rw-r--r--drivers/s390/cio/qdio_main.c46
-rw-r--r--drivers/s390/cio/qdio_perf.c12
-rw-r--r--drivers/s390/cio/qdio_perf.h10
35 files changed, 641 insertions, 230 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 2eca5fe0e75b..1094787e97e5 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -567,6 +567,24 @@ bool "s390 guest support for KVM (EXPERIMENTAL)"
the KVM hypervisor. This will add detection for KVM as well as a
virtio transport. If KVM is detected, the virtio console will be
the default console.
+
+config SECCOMP
+ bool "Enable seccomp to safely compute untrusted bytecode"
+ depends on PROC_FS
+ default y
+ help
+ This kernel feature is useful for number crunching applications
+ that may need to compute untrusted bytecode during their
+ execution. By using pipes or other transports made available to
+ the process as file descriptors supporting the read/write
+ syscalls, it's possible to isolate those applications in
+ their own address space using seccomp. Once seccomp is
+ enabled via /proc/<pid>/seccomp, it cannot be disabled
+ and the task is only allowed to execute a few safe syscalls
+ defined by each seccomp mode.
+
+ If unsure, say Y.
+
endmenu
source "net/Kconfig"
diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h
index de065b32381a..01a08020bc0e 100644
--- a/arch/s390/include/asm/compat.h
+++ b/arch/s390/include/asm/compat.h
@@ -5,6 +5,7 @@
*/
#include <linux/types.h>
#include <linux/sched.h>
+#include <linux/thread_info.h>
#define PSW32_MASK_PER 0x40000000UL
#define PSW32_MASK_DAT 0x04000000UL
@@ -163,12 +164,28 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr)
return (u32)(unsigned long)uptr;
}
+#ifdef CONFIG_COMPAT
+
+static inline int is_compat_task(void)
+{
+ return test_thread_flag(TIF_31BIT);
+}
+
+#else
+
+static inline int is_compat_task(void)
+{
+ return 0;
+}
+
+#endif
+
static inline void __user *compat_alloc_user_space(long len)
{
unsigned long stack;
stack = KSTK_ESP(current);
- if (test_thread_flag(TIF_31BIT))
+ if (is_compat_task())
stack &= 0x7fffffffUL;
return (void __user *) (stack - len);
}
diff --git a/arch/s390/include/asm/cpu.h b/arch/s390/include/asm/cpu.h
deleted file mode 100644
index d60a2eefb17b..000000000000
--- a/arch/s390/include/asm/cpu.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * include/asm-s390/cpu.h
- *
- * Copyright IBM Corp. 2007
- * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
- */
-
-#ifndef _ASM_S390_CPU_H_
-#define _ASM_S390_CPU_H_
-
-#include <linux/types.h>
-#include <linux/percpu.h>
-#include <linux/spinlock.h>
-
-struct s390_idle_data {
- spinlock_t lock;
- unsigned long long idle_count;
- unsigned long long idle_enter;
- unsigned long long idle_time;
-};
-
-DECLARE_PER_CPU(struct s390_idle_data, s390_idle);
-
-void vtime_start_cpu(void);
-
-static inline void s390_idle_check(void)
-{
- if ((&__get_cpu_var(s390_idle))->idle_enter != 0ULL)
- vtime_start_cpu();
-}
-
-#endif /* _ASM_S390_CPU_H_ */
diff --git a/arch/s390/include/asm/cputime.h b/arch/s390/include/asm/cputime.h
index 941384fbd39c..ec917d42ee6d 100644
--- a/arch/s390/include/asm/cputime.h
+++ b/arch/s390/include/asm/cputime.h
@@ -9,6 +9,9 @@
#ifndef _S390_CPUTIME_H
#define _S390_CPUTIME_H
+#include <linux/types.h>
+#include <linux/percpu.h>
+#include <linux/spinlock.h>
#include <asm/div64.h>
/* We want to use full resolution of the CPU timer: 2**-12 micro-seconds. */
@@ -174,8 +177,24 @@ cputime64_to_clock_t(cputime64_t cputime)
return __div(cputime, 4096000000ULL / USER_HZ);
}
+struct s390_idle_data {
+ spinlock_t lock;
+ unsigned long long idle_count;
+ unsigned long long idle_enter;
+ unsigned long long idle_time;
+};
+
+DECLARE_PER_CPU(struct s390_idle_data, s390_idle);
+
+void vtime_start_cpu(void);
cputime64_t s390_get_idle_time(int cpu);
#define arch_idle_time(cpu) s390_get_idle_time(cpu)
+static inline void s390_idle_check(void)
+{
+ if ((&__get_cpu_var(s390_idle))->idle_enter != 0ULL)
+ vtime_start_cpu();
+}
+
#endif /* _S390_CPUTIME_H */
diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h
index 3aeca492b147..713fe9fb1fcc 100644
--- a/arch/s390/include/asm/lowcore.h
+++ b/arch/s390/include/asm/lowcore.h
@@ -30,6 +30,7 @@
#define __LC_SUBCHANNEL_NR 0x00ba
#define __LC_IO_INT_PARM 0x00bc
#define __LC_IO_INT_WORD 0x00c0
+#define __LC_STFL_FAC_LIST 0x00c8
#define __LC_MCCK_CODE 0x00e8
#define __LC_DUMP_REIPL 0x0e00
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
index 5caddd4f7bed..60a7b1a1702f 100644
--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -112,12 +112,15 @@ extern char empty_zero_page[PAGE_SIZE];
* effect, this also makes sure that 64 bit module code cannot be used
* as system call address.
*/
+
+extern unsigned long VMALLOC_START;
+
#ifndef __s390x__
-#define VMALLOC_START 0x78000000UL
+#define VMALLOC_SIZE (96UL << 20)
#define VMALLOC_END 0x7e000000UL
#define VMEM_MAP_END 0x80000000UL
#else /* __s390x__ */
-#define VMALLOC_START 0x3e000000000UL
+#define VMALLOC_SIZE (1UL << 30)
#define VMALLOC_END 0x3e040000000UL
#define VMEM_MAP_END 0x40000000000UL
#endif /* __s390x__ */
diff --git a/arch/s390/include/asm/seccomp.h b/arch/s390/include/asm/seccomp.h
new file mode 100644
index 000000000000..781a9cf9b002
--- /dev/null
+++ b/arch/s390/include/asm/seccomp.h
@@ -0,0 +1,16 @@
+#ifndef _ASM_S390_SECCOMP_H
+#define _ASM_S390_SECCOMP_H
+
+#include <linux/unistd.h>
+
+#define __NR_seccomp_read __NR_read
+#define __NR_seccomp_write __NR_write
+#define __NR_seccomp_exit __NR_exit
+#define __NR_seccomp_sigreturn __NR_sigreturn
+
+#define __NR_seccomp_read_32 __NR_read
+#define __NR_seccomp_write_32 __NR_write
+#define __NR_seccomp_exit_32 __NR_exit
+#define __NR_seccomp_sigreturn_32 __NR_sigreturn
+
+#endif /* _ASM_S390_SECCOMP_H */
diff --git a/arch/s390/include/asm/spinlock.h b/arch/s390/include/asm/spinlock.h
index f3861b09ebb0..c9af0d19c7ab 100644
--- a/arch/s390/include/asm/spinlock.h
+++ b/arch/s390/include/asm/spinlock.h
@@ -122,8 +122,10 @@ static inline void __raw_spin_unlock(raw_spinlock_t *lp)
#define __raw_write_can_lock(x) ((x)->lock == 0)
extern void _raw_read_lock_wait(raw_rwlock_t *lp);
+extern void _raw_read_lock_wait_flags(raw_rwlock_t *lp, unsigned long flags);
extern int _raw_read_trylock_retry(raw_rwlock_t *lp);
extern void _raw_write_lock_wait(raw_rwlock_t *lp);
+extern void _raw_write_lock_wait_flags(raw_rwlock_t *lp, unsigned long flags);
extern int _raw_write_trylock_retry(raw_rwlock_t *lp);
static inline void __raw_read_lock(raw_rwlock_t *rw)
@@ -134,6 +136,14 @@ static inline void __raw_read_lock(raw_rwlock_t *rw)
_raw_read_lock_wait(rw);
}
+static inline void __raw_read_lock_flags(raw_rwlock_t *rw, unsigned long flags)
+{
+ unsigned int old;
+ old = rw->lock & 0x7fffffffU;
+ if (_raw_compare_and_swap(&rw->lock, old, old + 1) != old)
+ _raw_read_lock_wait_flags(rw, flags);
+}
+
static inline void __raw_read_unlock(raw_rwlock_t *rw)
{
unsigned int old, cmp;
@@ -151,6 +161,12 @@ static inline void __raw_write_lock(raw_rwlock_t *rw)
_raw_write_lock_wait(rw);
}
+static inline void __raw_write_lock_flags(raw_rwlock_t *rw, unsigned long flags)
+{
+ if (unlikely(_raw_compare_and_swap(&rw->lock, 0, 0x80000000) != 0))
+ _raw_write_lock_wait_flags(rw, flags);
+}
+
static inline void __raw_write_unlock(raw_rwlock_t *rw)
{
_raw_compare_and_swap(&rw->lock, 0x80000000, 0);
@@ -172,9 +188,6 @@ static inline int __raw_write_trylock(raw_rwlock_t *rw)
return _raw_write_trylock_retry(rw);
}
-#define __raw_read_lock_flags(lock, flags) __raw_read_lock(lock)
-#define __raw_write_lock_flags(lock, flags) __raw_write_lock(lock)
-
#define _raw_read_relax(lock) cpu_relax()
#define _raw_write_relax(lock) cpu_relax()
diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h
index 461f2abd2e6f..2f86653dda69 100644
--- a/arch/s390/include/asm/thread_info.h
+++ b/arch/s390/include/asm/thread_info.h
@@ -83,14 +83,15 @@ static inline struct thread_info *current_thread_info(void)
/*
* thread information flags bit numbers
*/
-#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
#define TIF_NOTIFY_RESUME 1 /* callback before returning to user */
#define TIF_SIGPENDING 2 /* signal pending */
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
#define TIF_RESTART_SVC 4 /* restart svc with new svc number */
-#define TIF_SYSCALL_AUDIT 5 /* syscall auditing active */
#define TIF_SINGLE_STEP 6 /* deliver sigtrap on return to user */
#define TIF_MCCK_PENDING 7 /* machine check handling is pending */
+#define TIF_SYSCALL_TRACE 8 /* syscall trace active */
+#define TIF_SYSCALL_AUDIT 9 /* syscall auditing active */
+#define TIF_SECCOMP 10 /* secure computing */
#define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */
#define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling
TIF_NEED_RESCHED */
@@ -99,15 +100,16 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_RESTORE_SIGMASK 20 /* restore signal mask in do_signal() */
#define TIF_FREEZE 21 /* thread is freezing for suspend */
-#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
#define _TIF_RESTART_SVC (1<<TIF_RESTART_SVC)
-#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
#define _TIF_SINGLE_STEP (1<<TIF_SINGLE_STEP)
#define _TIF_MCCK_PENDING (1<<TIF_MCCK_PENDING)
+#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
+#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
+#define _TIF_SECCOMP (1<<TIF_SECCOMP)
#define _TIF_USEDFPU (1<<TIF_USEDFPU)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
#define _TIF_31BIT (1<<TIF_31BIT)
diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h
index 0235970278f0..8377e91533d2 100644
--- a/arch/s390/include/asm/uaccess.h
+++ b/arch/s390/include/asm/uaccess.h
@@ -131,7 +131,7 @@ static inline int __get_user_fn(size_t size, const void __user *ptr, void *x)
#define put_user(x, ptr) \
({ \
- might_sleep(); \
+ might_fault(); \
__put_user(x, ptr); \
})
@@ -180,7 +180,7 @@ extern int __put_user_bad(void) __attribute__((noreturn));
#define get_user(x, ptr) \
({ \
- might_sleep(); \
+ might_fault(); \
__get_user(x, ptr); \
})
@@ -231,7 +231,7 @@ __copy_to_user(void __user *to, const void *from, unsigned long n)
static inline unsigned long __must_check
copy_to_user(void __user *to, const void *from, unsigned long n)
{
- might_sleep();
+ might_fault();
if (access_ok(VERIFY_WRITE, to, n))
n = __copy_to_user(to, from, n);
return n;
@@ -282,7 +282,7 @@ __copy_from_user(void *to, const void __user *from, unsigned long n)
static inline unsigned long __must_check
copy_from_user(void *to, const void __user *from, unsigned long n)
{
- might_sleep();
+ might_fault();
if (access_ok(VERIFY_READ, from, n))
n = __copy_from_user(to, from, n);
else
@@ -299,7 +299,7 @@ __copy_in_user(void __user *to, const void __user *from, unsigned long n)
static inline unsigned long __must_check
copy_in_user(void __user *to, const void __user *from, unsigned long n)
{
- might_sleep();
+ might_fault();
if (__access_ok(from,n) && __access_ok(to,n))
n = __copy_in_user(to, from, n);
return n;
@@ -312,7 +312,7 @@ static inline long __must_check
strncpy_from_user(char *dst, const char __user *src, long count)
{
long res = -EFAULT;
- might_sleep();
+ might_fault();
if (access_ok(VERIFY_READ, src, 1))
res = uaccess.strncpy_from_user(count, src, dst);
return res;
@@ -321,7 +321,7 @@ strncpy_from_user(char *dst, const char __user *src, long count)
static inline unsigned long
strnlen_user(const char __user * src, unsigned long n)
{
- might_sleep();
+ might_fault();
return uaccess.strnlen_user(n, src);
}
@@ -354,7 +354,7 @@ __clear_user(void __user *to, unsigned long n)
static inline unsigned long __must_check
clear_user(void __user *to, unsigned long n)
{
- might_sleep();
+ might_fault();
if (access_ok(VERIFY_WRITE, to, n))
n = uaccess.clear_user(n, to);
return n;
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 228e3105ded7..0657de7944fe 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -22,7 +22,7 @@ CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w
obj-y := bitmap.o traps.o time.o process.o base.o early.o setup.o \
processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
s390_ext.o debug.o irq.o ipl.o dis.o diag.o mem_detect.o \
- vdso.o vtime.o sysinfo.o nmi.o
+ vdso.o vtime.o sysinfo.o nmi.o sclp.o
obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o)
obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index f3e275934213..db25cdc21e12 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -53,6 +53,7 @@ _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
_TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
_TIF_MCCK_PENDING)
+_TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | _TIF_SECCOMP>>8)
STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
STACK_SIZE = 1 << STACK_SHIFT
@@ -265,7 +266,7 @@ sysc_do_restart:
sth %r7,SP_SVCNR(%r15)
sll %r7,2 # svc number *4
l %r8,BASED(.Lsysc_table)
- tm __TI_flags+3(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
+ tm __TI_flags+2(%r9),_TIF_SYSCALL
l %r8,0(%r7,%r8) # get system call addr.
bnz BASED(sysc_tracesys)
basr %r14,%r8 # call sys_xxxx
@@ -405,7 +406,7 @@ sysc_tracego:
basr %r14,%r8 # call sys_xxx
st %r2,SP_R2(%r15) # store return value
sysc_tracenogo:
- tm __TI_flags+3(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
+ tm __TI_flags+2(%r9),_TIF_SYSCALL
bz BASED(sysc_return)
l %r1,BASED(.Ltrace_exit)
la %r2,SP_PTREGS(%r15) # load pt_regs
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 84a105838e03..3cec9b504f5f 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -56,6 +56,7 @@ _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
_TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
_TIF_MCCK_PENDING)
+_TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | _TIF_SECCOMP>>8)
#define BASED(name) name-system_call(%r13)
@@ -260,7 +261,7 @@ sysc_do_restart:
larl %r10,sys_call_table_emu # use 31 bit emulation system calls
sysc_noemu:
#endif
- tm __TI_flags+7(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
+ tm __TI_flags+6(%r9),_TIF_SYSCALL
lgf %r8,0(%r7,%r10) # load address of system call routine
jnz sysc_tracesys
basr %r14,%r8 # call sys_xxxx
@@ -391,7 +392,7 @@ sysc_tracego:
basr %r14,%r8 # call sys_xxx
stg %r2,SP_R2(%r15) # store return value
sysc_tracenogo:
- tm __TI_flags+7(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
+ tm __TI_flags+6(%r9),_TIF_SYSCALL
jz sysc_return
la %r2,SP_PTREGS(%r15) # load pt_regs
larl %r14,sysc_return # return point is sysc_return
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S
index 22596d70fc2e..6d227413cbe7 100644
--- a/arch/s390/kernel/head.S
+++ b/arch/s390/kernel/head.S
@@ -1,7 +1,5 @@
/*
- * arch/s390/kernel/head.S
- *
- * Copyright (C) IBM Corp. 1999,2006
+ * Copyright IBM Corp. 1999,2009
*
* Author(s): Hartmut Penner <hp@de.ibm.com>
* Martin Schwidefsky <schwidefsky@de.ibm.com>
@@ -479,27 +477,58 @@ startup:basr %r13,0 # get base
mvc __LC_LAST_UPDATE_TIMER(8),6f-.LPG0(%r13)
mvc __LC_EXIT_TIMER(8),5f-.LPG0(%r13)
#ifndef CONFIG_MARCH_G5
- # check processor version against MARCH_{G5,Z900,Z990,Z9_109,Z10}
- stidp __LC_CPUID # store cpuid
- lhi %r0,(3f-2f) / 2
- la %r1,2f-.LPG0(%r13)
-0: clc __LC_CPUID+4(2),0(%r1)
- jne 3f
- lpsw 1f-.LPG0(13) # machine type not good enough, crash
+ # check capabilities against MARCH_{G5,Z900,Z990,Z9_109,Z10}
+ xc __LC_STFL_FAC_LIST(8),__LC_STFL_FAC_LIST
+ stfl __LC_STFL_FAC_LIST # store facility list
+ tm __LC_STFL_FAC_LIST,0x01 # stfle available ?
+ jz 0f
+ la %r0,0
+ .insn s,0xb2b00000,__LC_STFL_FAC_LIST # store facility list extended
+0: l %r0,__LC_STFL_FAC_LIST
+ n %r0,2f+8-.LPG0(%r13)
+ cl %r0,2f+8-.LPG0(%r13)
+ jne 1f
+ l %r0,__LC_STFL_FAC_LIST+4
+ n %r0,2f+12-.LPG0(%r13)
+ cl %r0,2f+12-.LPG0(%r13)
+ je 3f
+1: l %r15,.Lstack-.LPG0(%r13)
+ ahi %r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union+THREAD_SIZE
+ ahi %r15,-96
+ la %r2,.Lals_string-.LPG0(%r13)
+ l %r3,.Lsclp_print-.LPG0(%r13)
+ basr %r14,%r3
+ lpsw 2f-.LPG0(%r13) # machine type not good enough, crash
+.Lals_string:
+ .asciz "The Linux kernel requires more recent processor hardware"
+.Lsclp_print:
+ .long _sclp_print_early
+.Lstack:
+ .long init_thread_union
.align 16
-1: .long 0x000a0000,0x00000000
-2:
+2: .long 0x000a0000,0x8badcccc
+#if defined(CONFIG_64BIT)
#if defined(CONFIG_MARCH_Z10)
- .short 0x9672, 0x2064, 0x2066, 0x2084, 0x2086, 0x2094, 0x2096
+ .long 0xc100efe3, 0xf0680000
#elif defined(CONFIG_MARCH_Z9_109)
- .short 0x9672, 0x2064, 0x2066, 0x2084, 0x2086
+ .long 0xc100efc3, 0x00000000
#elif defined(CONFIG_MARCH_Z990)
- .short 0x9672, 0x2064, 0x2066
+ .long 0xc0002000, 0x00000000
#elif defined(CONFIG_MARCH_Z900)
- .short 0x9672
+ .long 0xc0000000, 0x00000000
+#endif
+#else
+#if defined(CONFIG_MARCH_Z10)
+ .long 0x8100c880, 0x00000000
+#elif defined(CONFIG_MARCH_Z9_109)
+ .long 0x8100c880, 0x00000000
+#elif defined(CONFIG_MARCH_Z990)
+ .long 0x80002000, 0x00000000
+#elif defined(CONFIG_MARCH_Z900)
+ .long 0x80000000, 0x00000000
+#endif
#endif
-3: la %r1,2(%r1)
- brct %r0,0b
+3:
#endif
l %r13,4f-.LPG0(%r13)
diff --git a/arch/s390/kernel/nmi.c b/arch/s390/kernel/nmi.c
index 28cf196ba775..015e27da40eb 100644
--- a/arch/s390/kernel/nmi.c
+++ b/arch/s390/kernel/nmi.c
@@ -16,7 +16,7 @@
#include <asm/lowcore.h>
#include <asm/smp.h>
#include <asm/etr.h>
-#include <asm/cpu.h>
+#include <asm/cputime.h>
#include <asm/nmi.h>
#include <asm/crw.h>
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index a3acd8e60aff..355f7a30c3f1 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -32,6 +32,7 @@
#include <linux/elfcore.h>
#include <linux/kernel_stat.h>
#include <linux/syscalls.h>
+#include <asm/compat.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/system.h>
@@ -204,7 +205,7 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
save_fp_regs(&p->thread.fp_regs);
/* Set a new TLS ? */
if (clone_flags & CLONE_SETTLS) {
- if (test_thread_flag(TIF_31BIT)) {
+ if (is_compat_task()) {
p->thread.acrs[0] = (unsigned int) regs->gprs[6];
} else {
p->thread.acrs[0] = (unsigned int)(regs->gprs[6] >> 32);
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index 75c496f4f16d..b6fc1ae2ffcb 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -36,7 +36,8 @@
#include <linux/elf.h>
#include <linux/regset.h>
#include <linux/tracehook.h>
-
+#include <linux/seccomp.h>
+#include <asm/compat.h>
#include <asm/segment.h>
#include <asm/page.h>
#include <asm/pgtable.h>
@@ -69,7 +70,7 @@ FixPerRegisters(struct task_struct *task)
if (per_info->single_step) {
per_info->control_regs.bits.starting_addr = 0;
#ifdef CONFIG_COMPAT
- if (test_thread_flag(TIF_31BIT))
+ if (is_compat_task())
per_info->control_regs.bits.ending_addr = 0x7fffffffUL;
else
#endif
@@ -482,8 +483,7 @@ static int peek_user_compat(struct task_struct *child,
{
__u32 tmp;
- if (!test_thread_flag(TIF_31BIT) ||
- (addr & 3) || addr > sizeof(struct user) - 3)
+ if (!is_compat_task() || (addr & 3) || addr > sizeof(struct user) - 3)
return -EIO;
tmp = __peek_user_compat(child, addr);
@@ -584,8 +584,7 @@ static int __poke_user_compat(struct task_struct *child,
static int poke_user_compat(struct task_struct *child,
addr_t addr, addr_t data)
{
- if (!test_thread_flag(TIF_31BIT) ||
- (addr & 3) || addr > sizeof(struct user32) - 3)
+ if (!is_compat_task() || (addr & 3) || addr > sizeof(struct user32) - 3)
return -EIO;
return __poke_user_compat(child, addr, data);
@@ -642,6 +641,9 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
{
long ret;
+ /* Do the secure computing check first. */
+ secure_computing(regs->gprs[2]);
+
/*
* The sysc_tracesys code in entry.S stored the system
* call number to gprs[2].
@@ -660,7 +662,7 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
}
if (unlikely(current->audit_context))
- audit_syscall_entry(test_thread_flag(TIF_31BIT) ?
+ audit_syscall_entry(is_compat_task() ?
AUDIT_ARCH_S390 : AUDIT_ARCH_S390X,
regs->gprs[2], regs->orig_gpr2,
regs->gprs[3], regs->gprs[4],
diff --git a/arch/s390/kernel/s390_ext.c b/arch/s390/kernel/s390_ext.c
index a0d2d55d7fb3..6b0686d78fc7 100644
--- a/arch/s390/kernel/s390_ext.c
+++ b/arch/s390/kernel/s390_ext.c
@@ -13,7 +13,7 @@
#include <linux/errno.h>
#include <linux/kernel_stat.h>
#include <linux/interrupt.h>
-#include <asm/cpu.h>
+#include <asm/cputime.h>
#include <asm/lowcore.h>
#include <asm/s390_ext.h>
#include <asm/irq_regs.h>
diff --git a/arch/s390/kernel/sclp.S b/arch/s390/kernel/sclp.S
new file mode 100644
index 000000000000..20639dfe0c42
--- /dev/null
+++ b/arch/s390/kernel/sclp.S
@@ -0,0 +1,327 @@
+/*
+ * Mini SCLP driver.
+ *
+ * Copyright IBM Corp. 2004,2009
+ *
+ * Author(s): Peter Oberparleiter <Peter.Oberparleiter@de.ibm.com>,
+ * Heiko Carstens <heiko.carstens@de.ibm.com>,
+ *
+ */
+
+LC_EXT_NEW_PSW = 0x58 # addr of ext int handler
+LC_EXT_INT_PARAM = 0x80 # addr of ext int parameter
+LC_EXT_INT_CODE = 0x86 # addr of ext int code
+
+#
+# Subroutine which waits synchronously until either an external interruption
+# or a timeout occurs.
+#
+# Parameters:
+# R2 = 0 for no timeout, non-zero for timeout in (approximated) seconds
+#
+# Returns:
+# R2 = 0 on interrupt, 2 on timeout
+# R3 = external interruption parameter if R2=0
+#
+
+.section ".init.text","ax"
+
+_sclp_wait_int:
+ stm %r6,%r15,24(%r15) # save registers
+ basr %r13,0 # get base register
+.LbaseS1:
+ ahi %r15,-96 # create stack frame
+ la %r8,LC_EXT_NEW_PSW # register int handler
+ mvc .LoldpswS1-.LbaseS1(8,%r13),0(%r8)
+ mvc 0(8,%r8),.LextpswS1-.LbaseS1(%r13)
+ lhi %r6,0x0200 # cr mask for ext int (cr0.54)
+ ltr %r2,%r2
+ jz .LsetctS1
+ ahi %r6,0x0800 # cr mask for clock int (cr0.52)
+ stck .LtimeS1-.LbaseS1(%r13) # initiate timeout
+ al %r2,.LtimeS1-.LbaseS1(%r13)
+ st %r2,.LtimeS1-.LbaseS1(%r13)
+ sckc .LtimeS1-.LbaseS1(%r13)
+
+.LsetctS1:
+ stctl %c0,%c0,.LctlS1-.LbaseS1(%r13) # enable required interrupts
+ l %r0,.LctlS1-.LbaseS1(%r13)
+ lhi %r1,~(0x200 | 0x800) # clear old values
+ nr %r1,%r0
+ or %r1,%r6 # set new value
+ st %r1,.LctlS1-.LbaseS1(%r13)
+ lctl %c0,%c0,.LctlS1-.LbaseS1(%r13)
+ st %r0,.LctlS1-.LbaseS1(%r13)
+ lhi %r2,2 # return code for timeout
+.LloopS1:
+ lpsw .LwaitpswS1-.LbaseS1(%r13) # wait until interrupt
+.LwaitS1:
+ lh %r7,LC_EXT_INT_CODE
+ chi %r7,0x1004 # timeout?
+ je .LtimeoutS1
+ chi %r7,0x2401 # service int?
+ jne .LloopS1
+ sr %r2,%r2
+ l %r3,LC_EXT_INT_PARAM
+.LtimeoutS1:
+ lctl %c0,%c0,.LctlS1-.LbaseS1(%r13) # restore interrupt setting
+ # restore old handler
+ mvc 0(8,%r8),.LoldpswS1-.LbaseS1(%r13)
+ lm %r6,%r15,120(%r15) # restore registers
+ br %r14 # return to caller
+
+ .align 8
+.LoldpswS1:
+ .long 0, 0 # old ext int PSW
+.LextpswS1:
+ .long 0x00080000, 0x80000000+.LwaitS1 # PSW to handle ext int
+.LwaitpswS1:
+ .long 0x010a0000, 0x00000000+.LloopS1 # PSW to wait for ext int
+.LtimeS1:
+ .quad 0 # current time
+.LctlS1:
+ .long 0 # CT0 contents
+
+#
+# Subroutine to synchronously issue a service call.
+#
+# Parameters:
+# R2 = command word
+# R3 = sccb address
+#
+# Returns:
+# R2 = 0 on success, 1 on failure
+# R3 = sccb response code if R2 = 0
+#
+
+_sclp_servc:
+ stm %r6,%r15,24(%r15) # save registers
+ ahi %r15,-96 # create stack frame
+ lr %r6,%r2 # save command word
+ lr %r7,%r3 # save sccb address
+.LretryS2:
+ lhi %r2,1 # error return code
+ .insn rre,0xb2200000,%r6,%r7 # servc
+ brc 1,.LendS2 # exit if not operational
+ brc 8,.LnotbusyS2 # go on if not busy
+ sr %r2,%r2 # wait until no longer busy
+ bras %r14,_sclp_wait_int
+ j .LretryS2 # retry
+.LnotbusyS2:
+ sr %r2,%r2 # wait until result
+ bras %r14,_sclp_wait_int
+ sr %r2,%r2
+ lh %r3,6(%r7)
+.LendS2:
+ lm %r6,%r15,120(%r15) # restore registers
+ br %r14
+
+#
+# Subroutine to set up the SCLP interface.
+#
+# Parameters:
+# R2 = 0 to activate, non-zero to deactivate
+#
+# Returns:
+# R2 = 0 on success, non-zero on failure
+#
+
+_sclp_setup:
+ stm %r6,%r15,24(%r15) # save registers
+ ahi %r15,-96 # create stack frame
+ basr %r13,0 # get base register
+.LbaseS3:
+ l %r6,.LsccbS0-.LbaseS3(%r13) # prepare init mask sccb
+ mvc 0(.LinitendS3-.LinitsccbS3,%r6),.LinitsccbS3-.LbaseS3(%r13)
+ ltr %r2,%r2 # initialization?
+ jz .LdoinitS3 # go ahead
+ # clear masks
+ xc .LinitmaskS3-.LinitsccbS3(8,%r6),.LinitmaskS3-.LinitsccbS3(%r6)
+.LdoinitS3:
+ l %r2,.LwritemaskS3-.LbaseS3(%r13)# get command word
+ lr %r3,%r6 # get sccb address
+ bras %r14,_sclp_servc # issue service call
+ ltr %r2,%r2 # servc successful?
+ jnz .LerrorS3
+ chi %r3,0x20 # write mask successful?
+ jne .LerrorS3
+ # check masks
+ la %r2,.LinitmaskS3-.LinitsccbS3(%r6)
+ l %r1,0(%r2) # receive mask ok?
+ n %r1,12(%r2)
+ cl %r1,0(%r2)
+ jne .LerrorS3
+ l %r1,4(%r2) # send mask ok?
+ n %r1,8(%r2)
+ cl %r1,4(%r2)
+ sr %r2,%r2
+ je .LendS3
+.LerrorS3:
+ lhi %r2,1 # error return code
+.LendS3:
+ lm %r6,%r15,120(%r15) # restore registers
+ br %r14
+.LwritemaskS3:
+ .long 0x00780005 # SCLP command for write mask
+.LinitsccbS3:
+ .word .LinitendS3-.LinitsccbS3
+ .byte 0,0,0,0
+ .word 0
+ .word 0
+ .word 4
+.LinitmaskS3:
+ .long 0x80000000
+ .long 0x40000000
+ .long 0
+ .long 0
+.LinitendS3:
+
+#
+# Subroutine which prints a given text to the SCLP console.
+#
+# Parameters:
+# R2 = address of nil-terminated ASCII text
+#
+# Returns:
+# R2 = 0 on success, 1 on failure
+#
+
+_sclp_print:
+ stm %r6,%r15,24(%r15) # save registers
+ ahi %r15,-96 # create stack frame
+ basr %r13,0 # get base register
+.LbaseS4:
+ l %r8,.LsccbS0-.LbaseS4(%r13) # prepare write data sccb
+ mvc 0(.LmtoS4-.LwritesccbS4,%r8),.LwritesccbS4-.LbaseS4(%r13)
+ la %r7,.LmtoS4-.LwritesccbS4(%r8) # current mto addr
+ sr %r0,%r0
+ l %r10,.Lascebc-.LbaseS4(%r13) # address of translation table
+.LinitmtoS4:
+ # initialize mto
+ mvc 0(.LmtoendS4-.LmtoS4,%r7),.LmtoS4-.LbaseS4(%r13)
+ lhi %r6,.LmtoendS4-.LmtoS4 # current mto length
+.LloopS4:
+ ic %r0,0(%r2) # get character
+ ahi %r2,1
+ ltr %r0,%r0 # end of string?
+ jz .LfinalizemtoS4
+ chi %r0,0x15 # end of line (NL)?
+ jz .LfinalizemtoS4
+ stc %r0,0(%r6,%r7) # copy to mto
+ la %r11,0(%r6,%r7)
+ tr 0(1,%r11),0(%r10) # translate to EBCDIC
+ ahi %r6,1
+ j .LloopS4
+.LfinalizemtoS4:
+ sth %r6,0(%r7) # update mto length
+ lh %r9,.LmdbS4-.LwritesccbS4(%r8) # update mdb length
+ ar %r9,%r6
+ sth %r9,.LmdbS4-.LwritesccbS4(%r8)
+ lh %r9,.LevbufS4-.LwritesccbS4(%r8)# update evbuf length
+ ar %r9,%r6
+ sth %r9,.LevbufS4-.LwritesccbS4(%r8)
+ lh %r9,0(%r8) # update sccb length
+ ar %r9,%r6
+ sth %r9,0(%r8)
+ ar %r7,%r6 # update current mto adress
+ ltr %r0,%r0 # more characters?
+ jnz .LinitmtoS4
+ l %r2,.LwritedataS4-.LbaseS4(%r13)# write data
+ lr %r3,%r8
+ bras %r14,_sclp_servc
+ ltr %r2,%r2 # servc successful?
+ jnz .LendS4
+ chi %r3,0x20 # write data successful?
+ je .LendS4
+ lhi %r2,1 # error return code
+.LendS4:
+ lm %r6,%r15,120(%r15) # restore registers
+ br %r14
+
+#
+# Function which prints a given text to the SCLP console.
+#
+# Parameters:
+# R2 = address of nil-terminated ASCII text
+#
+# Returns:
+# R2 = 0 on success, 1 on failure
+#
+
+ .globl _sclp_print_early
+_sclp_print_early:
+ stm %r6,%r15,24(%r15) # save registers
+ ahi %r15,-96 # create stack frame
+ lr %r10,%r2 # save string pointer
+ lhi %r2,0
+ bras %r14,_sclp_setup # enable console
+ ltr %r2,%r2
+ jnz .LendS5
+ lr %r2,%r10
+ bras %r14,_sclp_print # print string
+ ltr %r2,%r2
+ jnz .LendS5
+ lhi %r2,1
+ bras %r14,_sclp_setup # disable console
+.LendS5:
+ lm %r6,%r15,120(%r15) # restore registers
+ br %r14
+
+.LwritedataS4:
+ .long 0x00760005 # SCLP command for write data
+.LwritesccbS4:
+ # sccb
+ .word .LmtoS4-.LwritesccbS4
+ .byte 0
+ .byte 0,0,0
+ .word 0
+
+ # evbuf
+.LevbufS4:
+ .word .LmtoS4-.LevbufS4
+ .byte 0x02
+ .byte 0
+ .word 0
+
+.LmdbS4:
+ # mdb
+ .word .LmtoS4-.LmdbS4
+ .word 1
+ .long 0xd4c4c240
+ .long 1
+
+ # go
+.LgoS4:
+ .word .LmtoS4-.LgoS4
+ .word 1
+ .long 0
+ .byte 0,0,0,0,0,0,0,0
+ .byte 0,0,0
+ .byte 0
+ .byte 0,0,0,0,0,0,0
+ .byte 0
+ .word 0
+ .byte 0,0,0,0,0,0,0,0,0,0
+ .byte 0,0,0,0,0,0,0,0
+ .byte 0,0,0,0,0,0,0,0
+
+.LmtoS4:
+ .word .LmtoendS4-.LmtoS4
+ .word 4
+ .word 0x1000
+ .byte 0
+ .byte 0,0,0
+.LmtoendS4:
+
+ # Global constants
+.LsccbS0:
+ .long _sclp_work_area
+.Lascebc:
+ .long _ascebc
+.previous
+
+.section ".init.data","a"
+ .balign 4096
+_sclp_work_area:
+ .fill 4096
+.previous
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index 3cf74c3ccb69..062bd64e65fa 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -26,6 +26,7 @@
#include <linux/binfmts.h>
#include <linux/tracehook.h>
#include <linux/syscalls.h>
+#include <linux/compat.h>
#include <asm/ucontext.h>
#include <asm/uaccess.h>
#include <asm/lowcore.h>
@@ -482,7 +483,7 @@ void do_signal(struct pt_regs *regs)
/* Whee! Actually deliver the signal. */
int ret;
#ifdef CONFIG_COMPAT
- if (test_thread_flag(TIF_31BIT)) {
+ if (is_compat_task()) {
ret = handle_signal32(signr, &ka, &info, oldset, regs);
}
else
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index a985a3ba4401..0af302ceac2d 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -47,7 +47,7 @@
#include <asm/timer.h>
#include <asm/lowcore.h>
#include <asm/sclp.h>
-#include <asm/cpu.h>
+#include <asm/cputime.h>
#include <asm/vdso.h>
#include "entry.h"
diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c
index 89b2e7f1b7a9..45e1708b70fd 100644
--- a/arch/s390/kernel/vdso.c
+++ b/arch/s390/kernel/vdso.c
@@ -22,7 +22,7 @@
#include <linux/elf.h>
#include <linux/security.h>
#include <linux/bootmem.h>
-
+#include <linux/compat.h>
#include <asm/pgtable.h>
#include <asm/system.h>
#include <asm/processor.h>
@@ -53,8 +53,19 @@ unsigned int __read_mostly vdso_enabled = 1;
static int __init vdso_setup(char *s)
{
- vdso_enabled = simple_strtoul(s, NULL, 0);
- return 1;
+ unsigned long val;
+ int rc;
+
+ rc = 0;
+ if (strncmp(s, "on", 3) == 0)
+ vdso_enabled = 1;
+ else if (strncmp(s, "off", 4) == 0)
+ vdso_enabled = 0;
+ else {
+ rc = strict_strtoul(s, 0, &val);
+ vdso_enabled = rc ? 0 : !!val;
+ }
+ return !rc;
}
__setup("vdso=", vdso_setup);
@@ -203,7 +214,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
vdso_pagelist = vdso64_pagelist;
vdso_pages = vdso64_pages;
#ifdef CONFIG_COMPAT
- if (test_thread_flag(TIF_31BIT)) {
+ if (is_compat_task()) {
vdso_pagelist = vdso32_pagelist;
vdso_pages = vdso32_pages;
}
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
index c87f59bd8246..c8eb7255332b 100644
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -23,7 +23,7 @@
#include <asm/s390_ext.h>
#include <asm/timer.h>
#include <asm/irq_regs.h>
-#include <asm/cpu.h>
+#include <asm/cputime.h>
static ext_int_info_t ext_int_info_timer;
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index f4d56e9939c9..cb6f5b994691 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -497,7 +497,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
BUG();
}
- might_sleep();
+ might_fault();
do {
__vcpu_run(vcpu);
diff --git a/arch/s390/lib/spinlock.c b/arch/s390/lib/spinlock.c
index e41f4008afc5..f7e0d30250b7 100644
--- a/arch/s390/lib/spinlock.c
+++ b/arch/s390/lib/spinlock.c
@@ -124,6 +124,27 @@ void _raw_read_lock_wait(raw_rwlock_t *rw)
}
EXPORT_SYMBOL(_raw_read_lock_wait);
+void _raw_read_lock_wait_flags(raw_rwlock_t *rw, unsigned long flags)
+{
+ unsigned int old;
+ int count = spin_retry;
+
+ local_irq_restore(flags);
+ while (1) {
+ if (count-- <= 0) {
+ _raw_yield();
+ count = spin_retry;
+ }
+ if (!__raw_read_can_lock(rw))
+ continue;
+ old = rw->lock & 0x7fffffffU;
+ local_irq_disable();
+ if (_raw_compare_and_swap(&rw->lock, old, old + 1) == old)
+ return;
+ }
+}
+EXPORT_SYMBOL(_raw_read_lock_wait_flags);
+
int _raw_read_trylock_retry(raw_rwlock_t *rw)
{
unsigned int old;
@@ -157,6 +178,25 @@ void _raw_write_lock_wait(raw_rwlock_t *rw)
}
EXPORT_SYMBOL(_raw_write_lock_wait);
+void _raw_write_lock_wait_flags(raw_rwlock_t *rw, unsigned long flags)
+{
+ int count = spin_retry;
+
+ local_irq_restore(flags);
+ while (1) {
+ if (count-- <= 0) {
+ _raw_yield();
+ count = spin_retry;
+ }
+ if (!__raw_write_can_lock(rw))
+ continue;
+ local_irq_disable();
+ if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0)
+ return;
+ }
+}
+EXPORT_SYMBOL(_raw_write_lock_wait_flags);
+
int _raw_write_trylock_retry(raw_rwlock_t *rw)
{
int count = spin_retry;
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 833e8366c351..220a152c836c 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -19,6 +19,7 @@
#include <linux/ptrace.h>
#include <linux/mman.h>
#include <linux/mm.h>
+#include <linux/compat.h>
#include <linux/smp.h>
#include <linux/kdebug.h>
#include <linux/smp_lock.h>
@@ -239,7 +240,7 @@ static int signal_return(struct mm_struct *mm, struct pt_regs *regs,
up_read(&mm->mmap_sem);
clear_tsk_thread_flag(current, TIF_SINGLE_STEP);
#ifdef CONFIG_COMPAT
- compat = test_tsk_thread_flag(current, TIF_31BIT);
+ compat = is_compat_task();
if (compat && instruction == 0x0a77)
sys32_sigreturn();
else if (compat && instruction == 0x0aad)
diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c
index e008d236cc15..f4558ccf02b9 100644
--- a/arch/s390/mm/mmap.c
+++ b/arch/s390/mm/mmap.c
@@ -28,6 +28,7 @@
#include <linux/mm.h>
#include <linux/module.h>
#include <asm/pgalloc.h>
+#include <asm/compat.h>
/*
* Top of mmap area (just below the process stack).
@@ -55,7 +56,7 @@ static inline int mmap_is_legacy(void)
/*
* Force standard allocation for 64 bit programs.
*/
- if (!test_thread_flag(TIF_31BIT))
+ if (!is_compat_task())
return 1;
#endif
return sysctl_legacy_va_layout ||
@@ -91,7 +92,7 @@ EXPORT_SYMBOL_GPL(arch_pick_mmap_layout);
int s390_mmap_check(unsigned long addr, unsigned long len)
{
- if (!test_thread_flag(TIF_31BIT) &&
+ if (!is_compat_task() &&
len >= TASK_SIZE && TASK_SIZE < (1UL << 53))
return crst_table_upgrade(current->mm, 1UL << 53);
return 0;
@@ -108,8 +109,7 @@ s390_get_unmapped_area(struct file *filp, unsigned long addr,
area = arch_get_unmapped_area(filp, addr, len, pgoff, flags);
if (!(area & ~PAGE_MASK))
return area;
- if (area == -ENOMEM &&
- !test_thread_flag(TIF_31BIT) && TASK_SIZE < (1UL << 53)) {
+ if (area == -ENOMEM && !is_compat_task() && TASK_SIZE < (1UL << 53)) {
/* Upgrade the page table to 4 levels and retry. */
rc = crst_table_upgrade(mm, 1UL << 53);
if (rc)
@@ -131,8 +131,7 @@ s390_get_unmapped_area_topdown(struct file *filp, const unsigned long addr,
area = arch_get_unmapped_area_topdown(filp, addr, len, pgoff, flags);
if (!(area & ~PAGE_MASK))
return area;
- if (area == -ENOMEM &&
- !test_thread_flag(TIF_31BIT) && TASK_SIZE < (1UL << 53)) {
+ if (area == -ENOMEM && !is_compat_task() && TASK_SIZE < (1UL << 53)) {
/* Upgrade the page table to 4 levels and retry. */
rc = crst_table_upgrade(mm, 1UL << 53);
if (rc)
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index be6c1cf4ad5a..4ca8e826bf30 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -1,7 +1,5 @@
/*
- * arch/s390/mm/pgtable.c
- *
- * Copyright IBM Corp. 2007
+ * Copyright IBM Corp. 2007,2009
* Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
*/
@@ -53,6 +51,18 @@ void clear_table_pgstes(unsigned long *table)
#endif
+unsigned long VMALLOC_START = VMALLOC_END - VMALLOC_SIZE;
+EXPORT_SYMBOL(VMALLOC_START);
+
+static int __init parse_vmalloc(char *arg)
+{
+ if (!arg)
+ return -EINVAL;
+ VMALLOC_START = (VMALLOC_END - memparse(arg, &arg)) & PAGE_MASK;
+ return 0;
+}
+early_param("vmalloc", parse_vmalloc);
+
unsigned long *crst_table_alloc(struct mm_struct *mm, int noexec)
{
struct page *page = alloc_pages(GFP_KERNEL, ALLOC_ORDER);
diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c
index d028d2ee83dd..ed5396dae58e 100644
--- a/drivers/s390/char/con3270.c
+++ b/drivers/s390/char/con3270.c
@@ -64,7 +64,7 @@ static struct con3270 *condev;
#define CON_UPDATE_ERASE 1 /* Use EWRITEA instead of WRITE. */
#define CON_UPDATE_LIST 2 /* Update lines in tty3270->update. */
#define CON_UPDATE_STATUS 4 /* Update status line. */
-#define CON_UPDATE_ALL 7
+#define CON_UPDATE_ALL 8 /* Recreate screen. */
static void con3270_update(struct con3270 *);
@@ -73,18 +73,10 @@ static void con3270_update(struct con3270 *);
*/
static void con3270_set_timer(struct con3270 *cp, int expires)
{
- if (expires == 0) {
- if (timer_pending(&cp->timer))
- del_timer(&cp->timer);
- return;
- }
- if (timer_pending(&cp->timer) &&
- mod_timer(&cp->timer, jiffies + expires))
- return;
- cp->timer.function = (void (*)(unsigned long)) con3270_update;
- cp->timer.data = (unsigned long) cp;
- cp->timer.expires = jiffies + expires;
- add_timer(&cp->timer);
+ if (expires == 0)
+ del_timer(&cp->timer);
+ else
+ mod_timer(&cp->timer, jiffies + expires);
}
/*
@@ -225,6 +217,12 @@ con3270_update(struct con3270 *cp)
spin_lock_irqsave(&cp->view.lock, flags);
updated = 0;
+ if (cp->update_flags & CON_UPDATE_ALL) {
+ con3270_rebuild_update(cp);
+ con3270_update_status(cp);
+ cp->update_flags = CON_UPDATE_ERASE | CON_UPDATE_LIST |
+ CON_UPDATE_STATUS;
+ }
if (cp->update_flags & CON_UPDATE_ERASE) {
/* Use erase write alternate to initialize display. */
raw3270_request_set_cmd(wrq, TC_EWRITEA);
@@ -302,7 +300,6 @@ con3270_read_tasklet(struct raw3270_request *rrq)
deactivate = 1;
break;
case 0x6d: /* clear: start from scratch. */
- con3270_rebuild_update(cp);
cp->update_flags = CON_UPDATE_ALL;
con3270_set_timer(cp, 1);
break;
@@ -382,30 +379,21 @@ con3270_issue_read(struct con3270 *cp)
static int
con3270_activate(struct raw3270_view *view)
{
- unsigned long flags;
struct con3270 *cp;
cp = (struct con3270 *) view;
- spin_lock_irqsave(&cp->view.lock, flags);
- cp->nr_up = 0;
- con3270_rebuild_update(cp);
- con3270_update_status(cp);
cp->update_flags = CON_UPDATE_ALL;
con3270_set_timer(cp, 1);
- spin_unlock_irqrestore(&cp->view.lock, flags);
return 0;
}
static void
con3270_deactivate(struct raw3270_view *view)
{
- unsigned long flags;
struct con3270 *cp;
cp = (struct con3270 *) view;
- spin_lock_irqsave(&cp->view.lock, flags);
del_timer(&cp->timer);
- spin_unlock_irqrestore(&cp->view.lock, flags);
}
static int
@@ -504,6 +492,7 @@ con3270_write(struct console *co, const char *str, unsigned int count)
con3270_cline_end(cp);
}
/* Setup timer to output current console buffer after 1/10 second */
+ cp->nr_up = 0;
if (cp->view.dev && !timer_pending(&cp->timer))
con3270_set_timer(cp, HZ/10);
spin_unlock_irqrestore(&cp->view.lock,flags);
@@ -624,7 +613,8 @@ con3270_init(void)
INIT_LIST_HEAD(&condev->lines);
INIT_LIST_HEAD(&condev->update);
- init_timer(&condev->timer);
+ setup_timer(&condev->timer, (void (*)(unsigned long)) con3270_update,
+ (unsigned long) condev);
tasklet_init(&condev->readlet,
(void (*)(unsigned long)) con3270_read_tasklet,
(unsigned long) condev->read);
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
index a7fe6302c982..38385677c653 100644
--- a/drivers/s390/char/tty3270.c
+++ b/drivers/s390/char/tty3270.c
@@ -112,7 +112,7 @@ struct tty3270 {
#define TTY_UPDATE_LIST 2 /* Update lines in tty3270->update. */
#define TTY_UPDATE_INPUT 4 /* Update input line. */
#define TTY_UPDATE_STATUS 8 /* Update status line. */
-#define TTY_UPDATE_ALL 15
+#define TTY_UPDATE_ALL 16 /* Recreate screen. */
static void tty3270_update(struct tty3270 *);
@@ -121,19 +121,10 @@ static void tty3270_update(struct tty3270 *);
*/
static void tty3270_set_timer(struct tty3270 *tp, int expires)
{
- if (expires == 0) {
- if (timer_pending(&tp->timer) && del_timer(&tp->timer))
- raw3270_put_view(&tp->view);
- return;
- }
- if (timer_pending(&tp->timer) &&
- mod_timer(&tp->timer, jiffies + expires))
- return;
- raw3270_get_view(&tp->view);
- tp->timer.function = (void (*)(unsigned long)) tty3270_update;
- tp->timer.data = (unsigned long) tp;
- tp->timer.expires = jiffies + expires;
- add_timer(&tp->timer);
+ if (expires == 0)
+ del_timer(&tp->timer);
+ else
+ mod_timer(&tp->timer, jiffies + expires);
}
/*
@@ -337,7 +328,6 @@ tty3270_write_callback(struct raw3270_request *rq, void *data)
tp = (struct tty3270 *) rq->view;
if (rq->rc != 0) {
/* Write wasn't successfull. Refresh all. */
- tty3270_rebuild_update(tp);
tp->update_flags = TTY_UPDATE_ALL;
tty3270_set_timer(tp, 1);
}
@@ -366,6 +356,12 @@ tty3270_update(struct tty3270 *tp)
spin_lock(&tp->view.lock);
updated = 0;
+ if (tp->update_flags & TTY_UPDATE_ALL) {
+ tty3270_rebuild_update(tp);
+ tty3270_update_status(tp);
+ tp->update_flags = TTY_UPDATE_ERASE | TTY_UPDATE_LIST |
+ TTY_UPDATE_INPUT | TTY_UPDATE_STATUS;
+ }
if (tp->update_flags & TTY_UPDATE_ERASE) {
/* Use erase write alternate to erase display. */
raw3270_request_set_cmd(wrq, TC_EWRITEA);
@@ -425,7 +421,6 @@ tty3270_update(struct tty3270 *tp)
xchg(&tp->write, wrq);
}
spin_unlock(&tp->view.lock);
- raw3270_put_view(&tp->view);
}
/*
@@ -570,7 +565,6 @@ tty3270_read_tasklet(struct raw3270_request *rrq)
tty3270_set_timer(tp, 1);
} else if (tp->input->string[0] == 0x6d) {
/* Display has been cleared. Redraw. */
- tty3270_rebuild_update(tp);
tp->update_flags = TTY_UPDATE_ALL;
tty3270_set_timer(tp, 1);
}
@@ -641,22 +635,20 @@ static int
tty3270_activate(struct raw3270_view *view)
{
struct tty3270 *tp;
- unsigned long flags;
tp = (struct tty3270 *) view;
- spin_lock_irqsave(&tp->view.lock, flags);
- tp->nr_up = 0;
- tty3270_rebuild_update(tp);
- tty3270_update_status(tp);
tp->update_flags = TTY_UPDATE_ALL;
tty3270_set_timer(tp, 1);
- spin_unlock_irqrestore(&tp->view.lock, flags);
return 0;
}
static void
tty3270_deactivate(struct raw3270_view *view)
{
+ struct tty3270 *tp;
+
+ tp = (struct tty3270 *) view;
+ del_timer(&tp->timer);
}
static int
@@ -743,6 +735,7 @@ tty3270_free_view(struct tty3270 *tp)
{
int pages;
+ del_timer_sync(&tp->timer);
kbd_free(tp->kbd);
raw3270_request_free(tp->kreset);
raw3270_request_free(tp->read);
@@ -889,7 +882,8 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
INIT_LIST_HEAD(&tp->update);
INIT_LIST_HEAD(&tp->rcl_lines);
tp->rcl_max = 20;
- init_timer(&tp->timer);
+ setup_timer(&tp->timer, (void (*)(unsigned long)) tty3270_update,
+ (unsigned long) tp);
tasklet_init(&tp->readlet,
(void (*)(unsigned long)) tty3270_read_tasklet,
(unsigned long) tp->read);
@@ -1754,14 +1748,6 @@ static const struct tty_operations tty3270_ops = {
.set_termios = tty3270_set_termios
};
-static void tty3270_notifier(int index, int active)
-{
- if (active)
- tty_register_device(tty3270_driver, index, NULL);
- else
- tty_unregister_device(tty3270_driver, index);
-}
-
/*
* 3270 tty registration code called from tty_init().
* Most kernel services (incl. kmalloc) are available at this poimt.
@@ -1796,12 +1782,6 @@ static int __init tty3270_init(void)
return ret;
}
tty3270_driver = driver;
- ret = raw3270_register_notifier(tty3270_notifier);
- if (ret) {
- put_tty_driver(driver);
- return ret;
-
- }
return 0;
}
@@ -1810,7 +1790,6 @@ tty3270_exit(void)
{
struct tty_driver *driver;
- raw3270_unregister_notifier(tty3270_notifier);
driver = tty3270_driver;
tty3270_driver = NULL;
tty_unregister_driver(driver);
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 2aebb9823044..9889f188c7c5 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -28,7 +28,7 @@
#include <asm/chpid.h>
#include <asm/airq.h>
#include <asm/isc.h>
-#include <asm/cpu.h>
+#include <asm/cputime.h>
#include <asm/fcx.h>
#include <asm/nmi.h>
#include <asm/crw.h>
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index 151754d54745..bf0a24af39a0 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -114,7 +114,7 @@ int ccw_device_clear(struct ccw_device *cdev, unsigned long intparm)
struct subchannel *sch;
int ret;
- if (!cdev)
+ if (!cdev || !cdev->dev.parent)
return -ENODEV;
if (cdev->private->state == DEV_STATE_NOT_OPER)
return -ENODEV;
@@ -122,8 +122,6 @@ int ccw_device_clear(struct ccw_device *cdev, unsigned long intparm)
cdev->private->state != DEV_STATE_W4SENSE)
return -EINVAL;
sch = to_subchannel(cdev->dev.parent);
- if (!sch)
- return -ENODEV;
ret = cio_clear(sch);
if (ret == 0)
cdev->private->intparm = intparm;
@@ -161,11 +159,9 @@ int ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa,
struct subchannel *sch;
int ret;
- if (!cdev)
+ if (!cdev || !cdev->dev.parent)
return -ENODEV;
sch = to_subchannel(cdev->dev.parent);
- if (!sch)
- return -ENODEV;
if (cdev->private->state == DEV_STATE_NOT_OPER)
return -ENODEV;
if (cdev->private->state == DEV_STATE_VERIFY ||
@@ -339,7 +335,7 @@ int ccw_device_halt(struct ccw_device *cdev, unsigned long intparm)
struct subchannel *sch;
int ret;
- if (!cdev)
+ if (!cdev || !cdev->dev.parent)
return -ENODEV;
if (cdev->private->state == DEV_STATE_NOT_OPER)
return -ENODEV;
@@ -347,8 +343,6 @@ int ccw_device_halt(struct ccw_device *cdev, unsigned long intparm)
cdev->private->state != DEV_STATE_W4SENSE)
return -EINVAL;
sch = to_subchannel(cdev->dev.parent);
- if (!sch)
- return -ENODEV;
ret = cio_halt(sch);
if (ret == 0)
cdev->private->intparm = intparm;
@@ -372,11 +366,9 @@ int ccw_device_resume(struct ccw_device *cdev)
{
struct subchannel *sch;
- if (!cdev)
+ if (!cdev || !cdev->dev.parent)
return -ENODEV;
sch = to_subchannel(cdev->dev.parent);
- if (!sch)
- return -ENODEV;
if (cdev->private->state == DEV_STATE_NOT_OPER)
return -ENODEV;
if (cdev->private->state != DEV_STATE_ONLINE ||
@@ -471,11 +463,11 @@ __u8 ccw_device_get_path_mask(struct ccw_device *cdev)
{
struct subchannel *sch;
- sch = to_subchannel(cdev->dev.parent);
- if (!sch)
+ if (!cdev->dev.parent)
return 0;
- else
- return sch->lpm;
+
+ sch = to_subchannel(cdev->dev.parent);
+ return sch->lpm;
}
/*
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
index accd957454e7..d79cf5bf0e62 100644
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -881,42 +881,26 @@ no_handler:
qdio_set_state(irq_ptr, QDIO_IRQ_STATE_STOPPED);
}
-static int qdio_establish_check_errors(struct ccw_device *cdev, int cstat,
- int dstat)
+static void qdio_establish_handle_irq(struct ccw_device *cdev, int cstat,
+ int dstat)
{
struct qdio_irq *irq_ptr = cdev->private->qdio_data;
- if (cstat || (dstat & ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END))) {
- DBF_ERROR("EQ:ck con");
- goto error;
- }
+ DBF_DEV_EVENT(DBF_INFO, irq_ptr, "qest irq");
- if (!(dstat & DEV_STAT_DEV_END)) {
- DBF_ERROR("EQ:no dev");
+ if (cstat)
goto error;
- }
-
- if (dstat & ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) {
- DBF_ERROR("EQ: bad io");
+ if (dstat & ~(DEV_STAT_DEV_END | DEV_STAT_CHN_END))
goto error;
- }
- return 0;
+ if (!(dstat & DEV_STAT_DEV_END))
+ goto error;
+ qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ESTABLISHED);
+ return;
+
error:
DBF_ERROR("%4x EQ:error", irq_ptr->schid.sch_no);
DBF_ERROR("ds: %2x cs:%2x", dstat, cstat);
-
qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR);
- return 1;
-}
-
-static void qdio_establish_handle_irq(struct ccw_device *cdev, int cstat,
- int dstat)
-{
- struct qdio_irq *irq_ptr = cdev->private->qdio_data;
-
- DBF_DEV_EVENT(DBF_INFO, irq_ptr, "qest irq");
- if (!qdio_establish_check_errors(cdev, cstat, dstat))
- qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ESTABLISHED);
}
/* qdio interrupt handler */
@@ -946,7 +930,6 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,
}
}
qdio_irq_check_sense(irq_ptr, irb);
-
cstat = irb->scsw.cmd.cstat;
dstat = irb->scsw.cmd.dstat;
@@ -954,22 +937,19 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,
case QDIO_IRQ_STATE_INACTIVE:
qdio_establish_handle_irq(cdev, cstat, dstat);
break;
-
case QDIO_IRQ_STATE_CLEANUP:
qdio_set_state(irq_ptr, QDIO_IRQ_STATE_INACTIVE);
break;
-
case QDIO_IRQ_STATE_ESTABLISHED:
case QDIO_IRQ_STATE_ACTIVE:
if (cstat & SCHN_STAT_PCI) {
qdio_int_handler_pci(irq_ptr);
return;
}
- if ((cstat & ~SCHN_STAT_PCI) || dstat) {
+ if (cstat || dstat)
qdio_handle_activate_check(cdev, intparm, cstat,
dstat);
- break;
- }
+ break;
default:
WARN_ON(1);
}
@@ -1514,7 +1494,7 @@ int do_QDIO(struct ccw_device *cdev, unsigned int callflags,
if ((bufnr > QDIO_MAX_BUFFERS_PER_Q) ||
(count > QDIO_MAX_BUFFERS_PER_Q) ||
- (q_nr > QDIO_MAX_QUEUES_PER_IRQ))
+ (q_nr >= QDIO_MAX_QUEUES_PER_IRQ))
return -EINVAL;
if (!count)
diff --git a/drivers/s390/cio/qdio_perf.c b/drivers/s390/cio/qdio_perf.c
index 136d0f0b1e93..eff943923c6f 100644
--- a/drivers/s390/cio/qdio_perf.c
+++ b/drivers/s390/cio/qdio_perf.c
@@ -25,18 +25,6 @@ struct qdio_perf_stats perf_stats;
static struct proc_dir_entry *qdio_perf_pde;
#endif
-inline void qdio_perf_stat_inc(atomic_long_t *count)
-{
- if (qdio_performance_stats)
- atomic_long_inc(count);
-}
-
-inline void qdio_perf_stat_dec(atomic_long_t *count)
-{
- if (qdio_performance_stats)
- atomic_long_dec(count);
-}
-
/*
* procfs functions
*/
diff --git a/drivers/s390/cio/qdio_perf.h b/drivers/s390/cio/qdio_perf.h
index 7821ac4fa517..ff4504ce1e3c 100644
--- a/drivers/s390/cio/qdio_perf.h
+++ b/drivers/s390/cio/qdio_perf.h
@@ -9,7 +9,6 @@
#define QDIO_PERF_H
#include <linux/types.h>
-#include <linux/device.h>
#include <asm/atomic.h>
struct qdio_perf_stats {
@@ -50,10 +49,13 @@ struct qdio_perf_stats {
extern struct qdio_perf_stats perf_stats;
extern int qdio_performance_stats;
+static inline void qdio_perf_stat_inc(atomic_long_t *count)
+{
+ if (qdio_performance_stats)
+ atomic_long_inc(count);
+}
+
int qdio_setup_perf_stats(void);
void qdio_remove_perf_stats(void);
-extern void qdio_perf_stat_inc(atomic_long_t *count);
-extern void qdio_perf_stat_dec(atomic_long_t *count);
-
#endif