]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 13 Jun 2009 01:18:05 +0000 (18:18 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 13 Jun 2009 01:18:05 +0000 (18:18 -0700)
* 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6: (30 commits)
  [S390] wire up sys_perf_counter_open
  [S390] wire up sys_rt_tgsigqueueinfo
  [S390] ftrace: add system call tracer support
  [S390] ftrace: add function graph tracer support
  [S390] ftrace: add function trace mcount test support
  [S390] ftrace: add dynamic ftrace support
  [S390] kprobes: use probe_kernel_write
  [S390] maccess: arch specific probe_kernel_write() implementation
  [S390] maccess: add weak attribute to probe_kernel_write
  [S390] profile_tick called twice
  [S390] dasd: forward internal errors to dasd_sleep_on caller
  [S390] dasd: sync after async probe
  [S390] dasd: check_characteristics cleanup
  [S390] dasd: no High Performance FICON in 31-bit mode
  [S390] dcssblk: revert devt conversion
  [S390] qdio: fix access beyond ARRAY_SIZE of irq_ptr->{in,out}put_qs
  [S390] vmalloc: add vmalloc kernel parameter support
  [S390] uaccess: use might_fault() instead of might_sleep()
  [S390] 3270: lock dependency fixes
  [S390] 3270: do not register with tty_register_device
  ...

57 files changed:
arch/s390/Kconfig
arch/s390/include/asm/compat.h
arch/s390/include/asm/cpu.h [deleted file]
arch/s390/include/asm/cputime.h
arch/s390/include/asm/ftrace.h
arch/s390/include/asm/lowcore.h
arch/s390/include/asm/pgtable.h
arch/s390/include/asm/seccomp.h [new file with mode: 0644]
arch/s390/include/asm/spinlock.h
arch/s390/include/asm/syscall.h
arch/s390/include/asm/thread_info.h
arch/s390/include/asm/uaccess.h
arch/s390/include/asm/unistd.h
arch/s390/kernel/Makefile
arch/s390/kernel/compat_wrapper.S
arch/s390/kernel/early.c
arch/s390/kernel/entry.S
arch/s390/kernel/entry64.S
arch/s390/kernel/ftrace.c [new file with mode: 0644]
arch/s390/kernel/head.S
arch/s390/kernel/kprobes.c
arch/s390/kernel/mcount.S
arch/s390/kernel/nmi.c
arch/s390/kernel/process.c
arch/s390/kernel/ptrace.c
arch/s390/kernel/s390_ext.c
arch/s390/kernel/sclp.S [new file with mode: 0644]
arch/s390/kernel/setup.c
arch/s390/kernel/signal.c
arch/s390/kernel/smp.c
arch/s390/kernel/syscalls.S
arch/s390/kernel/time.c
arch/s390/kernel/vdso.c
arch/s390/kernel/vmlinux.lds.S
arch/s390/kernel/vtime.c
arch/s390/kvm/kvm-s390.c
arch/s390/lib/spinlock.c
arch/s390/mm/Makefile
arch/s390/mm/fault.c
arch/s390/mm/maccess.c [new file with mode: 0644]
arch/s390/mm/mmap.c
arch/s390/mm/pgtable.c
drivers/s390/block/dasd.c
drivers/s390/block/dasd_diag.c
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_fba.c
drivers/s390/block/dasd_int.h
drivers/s390/block/dcssblk.c
drivers/s390/char/con3270.c
drivers/s390/char/tty3270.c
drivers/s390/cio/cio.c
drivers/s390/cio/device_ops.c
drivers/s390/cio/qdio_main.c
drivers/s390/cio/qdio_perf.c
drivers/s390/cio/qdio_perf.h
mm/maccess.c
scripts/recordmcount.pl

index 2eca5fe0e75b243a71b3f0450ac756d9dea2a1f9..99dc3ded6b4975dc190d0243b856d539c9a932ce 100644 (file)
@@ -82,6 +82,11 @@ config S390
        select USE_GENERIC_SMP_HELPERS if SMP
        select HAVE_SYSCALL_WRAPPERS
        select HAVE_FUNCTION_TRACER
+       select HAVE_FUNCTION_TRACE_MCOUNT_TEST
+       select HAVE_FTRACE_MCOUNT_RECORD
+       select HAVE_FTRACE_SYSCALLS
+       select HAVE_DYNAMIC_FTRACE
+       select HAVE_FUNCTION_GRAPH_TRACER
        select HAVE_DEFAULT_NO_SPIN_MUTEXES
        select HAVE_OPROFILE
        select HAVE_KPROBES
@@ -567,6 +572,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"
index de065b32381a36867eb7bf6bc58f2b0ba8ddeec2..01a08020bc0e2bb3757e783ca51ee35478bbbc52 100644 (file)
@@ -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 (file)
index d60a2ee..0000000
+++ /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_ */
index 941384fbd39c503b79bd9ebdebe3ef35772a6e7e..ec917d42ee6d2b18264e26fe6407d2ced5da17ed 100644 (file)
@@ -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 */
index 5a5bc75e19d4a3f94866a4da9ef31cf13b942356..96c14a9102b8beadc324ae8b50cf8c81806af420 100644 (file)
@@ -2,7 +2,28 @@
 #define _ASM_S390_FTRACE_H
 
 #ifndef __ASSEMBLY__
+
 extern void _mcount(void);
+extern unsigned long ftrace_dyn_func;
+
+struct dyn_arch_ftrace { };
+
+#define MCOUNT_ADDR ((long)_mcount)
+
+#ifdef CONFIG_64BIT
+#define MCOUNT_OFFSET_RET 18
+#define MCOUNT_INSN_SIZE  24
+#define MCOUNT_OFFSET    14
+#else
+#define MCOUNT_OFFSET_RET 26
+#define MCOUNT_INSN_SIZE  30
+#define MCOUNT_OFFSET     8
 #endif
 
+static inline unsigned long ftrace_call_adjust(unsigned long addr)
+{
+       return addr - MCOUNT_OFFSET;
+}
+
+#endif /* __ASSEMBLY__ */
 #endif /* _ASM_S390_FTRACE_H */
index 3aeca492b14763fa6431192a14830eb041e69609..5046ad6b7a63453e8b660acd6d70986f361a1265 100644 (file)
@@ -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
@@ -67,6 +68,7 @@
 #define __LC_CPUID                     0x02b0
 #define __LC_INT_CLOCK                 0x02c8
 #define __LC_MACHINE_FLAGS             0x02d8
+#define __LC_FTRACE_FUNC               0x02dc
 #define __LC_IRB                       0x0300
 #define __LC_PFAULT_INTPARM            0x0080
 #define __LC_CPU_TIMER_SAVE_AREA       0x00d8
 #define __LC_INT_CLOCK                 0x0340
 #define __LC_VDSO_PER_CPU              0x0350
 #define __LC_MACHINE_FLAGS             0x0358
+#define __LC_FTRACE_FUNC               0x0360
 #define __LC_IRB                       0x0380
 #define __LC_PASTE                     0x03c0
 #define __LC_PFAULT_INTPARM            0x11b8
@@ -280,7 +283,8 @@ struct _lowcore
        __u64   int_clock;                      /* 0x02c8 */
        __u64   clock_comparator;               /* 0x02d0 */
        __u32   machine_flags;                  /* 0x02d8 */
-       __u8    pad_0x02dc[0x0300-0x02dc];      /* 0x02dc */
+       __u32   ftrace_func;                    /* 0x02dc */
+       __u8    pad_0x02f0[0x0300-0x02f0];      /* 0x02f0 */
 
        /* Interrupt response block */
        __u8    irb[64];                        /* 0x0300 */
@@ -385,7 +389,8 @@ struct _lowcore
        __u64   clock_comparator;               /* 0x0348 */
        __u64   vdso_per_cpu_data;              /* 0x0350 */
        __u64   machine_flags;                  /* 0x0358 */
-       __u8    pad_0x0360[0x0380-0x0360];      /* 0x0360 */
+       __u64   ftrace_func;                    /* 0x0360 */
+       __u8    pad_0x0368[0x0380-0x0368];      /* 0x0368 */
 
        /* Interrupt response block. */
        __u8    irb[64];                        /* 0x0380 */
index 5caddd4f7bedd74ed7fa9078c8cf4d97bdfc2227..60a7b1a1702ff478b60177b2ac161341a2882873 100644 (file)
@@ -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 (file)
index 0000000..781a9cf
--- /dev/null
@@ -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 */
index f3861b09ebb08a2ef2a1081f623f59429b1c6049..c9af0d19c7ab7b4fc726528797be910ef7d7c0f3 100644 (file)
@@ -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()
 
index 2429b87eb28d92c6fc6adf5a5887f2b29e062d70..e0a73d3eb8371be3bb599413aa09cd65a7f7da56 100644 (file)
@@ -12,6 +12,7 @@
 #ifndef _ASM_SYSCALL_H
 #define _ASM_SYSCALL_H 1
 
+#include <linux/sched.h>
 #include <asm/ptrace.h>
 
 static inline long syscall_get_nr(struct task_struct *task,
index 461f2abd2e6fd2d9dcc94cf604f4a77e50f3ee18..925bcc6490354c3f2fa2c5dbbca8b37b553b1bd6 100644 (file)
@@ -83,14 +83,16 @@ 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_SYSCALL_FTRACE     11      /* ftrace syscall instrumentation */
 #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 +101,17 @@ 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_SYSCALL_FTRACE    (1<<TIF_SYSCALL_FTRACE)
 #define _TIF_USEDFPU           (1<<TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
 #define _TIF_31BIT             (1<<TIF_31BIT)
index 0235970278f0574516ca7638e08737ce58c3ef3c..8377e91533d26434878708fc6e3ecc7245bbb579 100644 (file)
@@ -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;
index f0f19e6ace6cf550253483a6eddee80b163326ca..c80602d7c88000a9d7e91f5edc10ba7135e2ef3f 100644 (file)
 #define __NR_epoll_create1     327
 #define        __NR_preadv             328
 #define        __NR_pwritev            329
-#define NR_syscalls 330
+#define __NR_rt_tgsigqueueinfo 330
+#define __NR_perf_counter_open 331
+#define NR_syscalls 332
 
 /* 
  * There are some system calls that are not present on 64 bit, some
index 228e3105ded772da7d975faf6afaddb73a4e1e9e..c75ed43b1a181e250695312fae9844e64185f590 100644 (file)
@@ -3,8 +3,9 @@
 #
 
 ifdef CONFIG_FUNCTION_TRACER
-# Do not trace early boot code
+# Don't trace early setup code and tracing code
 CFLAGS_REMOVE_early.o = -pg
+CFLAGS_REMOVE_ftrace.o = -pg
 endif
 
 #
@@ -22,7 +23,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)
@@ -41,6 +42,8 @@ obj-$(CONFIG_COMPAT)          += compat_linux.o compat_signal.o \
 obj-$(CONFIG_STACKTRACE)       += stacktrace.o
 obj-$(CONFIG_KPROBES)          += kprobes.o
 obj-$(CONFIG_FUNCTION_TRACER)  += mcount.o
+obj-$(CONFIG_DYNAMIC_FTRACE)   += ftrace.o
+obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
 
 # Kexec part
 S390_KEXEC_OBJS := machine_kexec.o crash.o
index fb38af6316bb84f26c5a7f169cc142ef687540e8..88a83366819f6f7bba0dfbc05ff6ac78f221becb 100644 (file)
@@ -1823,3 +1823,20 @@ compat_sys_pwritev_wrapper:
        llgfr   %r5,%r5                 # u32
        llgfr   %r6,%r6                 # u32
        jg      compat_sys_pwritev      # branch to system call
+
+       .globl  compat_sys_rt_tgsigqueueinfo_wrapper
+compat_sys_rt_tgsigqueueinfo_wrapper:
+       lgfr    %r2,%r2                 # compat_pid_t
+       lgfr    %r3,%r3                 # compat_pid_t
+       lgfr    %r4,%r4                 # int
+       llgtr   %r5,%r5                 # struct compat_siginfo *
+       jg      compat_sys_rt_tgsigqueueinfo_wrapper # branch to system call
+
+       .globl  sys_perf_counter_open_wrapper
+sys_perf_counter_open_wrapper:
+       llgtr   %r2,%r2                 # const struct perf_counter_attr *
+       lgfr    %r3,%r3                 # pid_t
+       lgfr    %r4,%r4                 # int
+       lgfr    %r5,%r5                 # int
+       llgfr   %r6,%r6                 # unsigned long
+       jg      sys_perf_counter_open   # branch to system call
index cf09948faad6330aba32a207a88921aac833a307..fb263736826c8d73d0e2f0031afbbd24c88c69a9 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/ctype.h>
+#include <linux/ftrace.h>
 #include <linux/lockdep.h>
 #include <linux/module.h>
 #include <linux/pfn.h>
@@ -410,5 +411,8 @@ void __init startup_init(void)
        sclp_facilities_detect();
        detect_memory_layout(memory_chunk);
        S390_lowcore.machine_flags = machine_flags;
+#ifdef CONFIG_DYNAMIC_FTRACE
+       S390_lowcore.ftrace_func = (unsigned long)ftrace_caller;
+#endif
        lockdep_on();
 }
index f3e2759342135c170b5b70e9f75375f9a62efdea..c4c80a22bc1f315215111d240a8756b479e2fe37 100644 (file)
@@ -53,6 +53,8 @@ _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 | _TIF_SYSCALL_FTRACE>>8)
 
 STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
 STACK_SIZE  = 1 << STACK_SHIFT
@@ -265,7 +267,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 +407,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
@@ -1107,6 +1109,7 @@ cleanup_io_leave_insn:
 
                .section .rodata, "a"
 #define SYSCALL(esa,esame,emu) .long esa
+       .globl  sys_call_table
 sys_call_table:
 #include "syscalls.S"
 #undef SYSCALL
index 84a105838e03d2765723a3b995d00133e434ea11..f6618e9e15efd85b47ca37e4923685edaca85cb8 100644 (file)
@@ -56,6 +56,8 @@ _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 | _TIF_SYSCALL_FTRACE>>8)
 
 #define BASED(name) name-system_call(%r13)
 
@@ -260,7 +262,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 +393,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
@@ -1058,6 +1060,7 @@ cleanup_io_leave_insn:
 
                .section .rodata, "a"
 #define SYSCALL(esa,esame,emu) .long esame
+       .globl  sys_call_table
 sys_call_table:
 #include "syscalls.S"
 #undef SYSCALL
diff --git a/arch/s390/kernel/ftrace.c b/arch/s390/kernel/ftrace.c
new file mode 100644 (file)
index 0000000..82ddfd3
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * Dynamic function tracer architecture backend.
+ *
+ * Copyright IBM Corp. 2009
+ *
+ *   Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>,
+ *
+ */
+
+#include <linux/hardirq.h>
+#include <linux/uaccess.h>
+#include <linux/ftrace.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <trace/syscall.h>
+#include <asm/lowcore.h>
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+
+void ftrace_disable_code(void);
+void ftrace_disable_return(void);
+void ftrace_call_code(void);
+void ftrace_nop_code(void);
+
+#define FTRACE_INSN_SIZE 4
+
+#ifdef CONFIG_64BIT
+
+asm(
+       "       .align  4\n"
+       "ftrace_disable_code:\n"
+       "       j       0f\n"
+       "       .word   0x0024\n"
+       "       lg      %r1,"__stringify(__LC_FTRACE_FUNC)"\n"
+       "       basr    %r14,%r1\n"
+       "ftrace_disable_return:\n"
+       "       lg      %r14,8(15)\n"
+       "       lgr     %r0,%r0\n"
+       "0:\n");
+
+asm(
+       "       .align  4\n"
+       "ftrace_nop_code:\n"
+       "       j       .+"__stringify(MCOUNT_INSN_SIZE)"\n");
+
+asm(
+       "       .align  4\n"
+       "ftrace_call_code:\n"
+       "       stg     %r14,8(%r15)\n");
+
+#else /* CONFIG_64BIT */
+
+asm(
+       "       .align  4\n"
+       "ftrace_disable_code:\n"
+       "       j       0f\n"
+       "       l       %r1,"__stringify(__LC_FTRACE_FUNC)"\n"
+       "       basr    %r14,%r1\n"
+       "ftrace_disable_return:\n"
+       "       l       %r14,4(%r15)\n"
+       "       j       0f\n"
+       "       bcr     0,%r7\n"
+       "       bcr     0,%r7\n"
+       "       bcr     0,%r7\n"
+       "       bcr     0,%r7\n"
+       "       bcr     0,%r7\n"
+       "       bcr     0,%r7\n"
+       "0:\n");
+
+asm(
+       "       .align  4\n"
+       "ftrace_nop_code:\n"
+       "       j       .+"__stringify(MCOUNT_INSN_SIZE)"\n");
+
+asm(
+       "       .align  4\n"
+       "ftrace_call_code:\n"
+       "       st      %r14,4(%r15)\n");
+
+#endif /* CONFIG_64BIT */
+
+static int ftrace_modify_code(unsigned long ip,
+                             void *old_code, int old_size,
+                             void *new_code, int new_size)
+{
+       unsigned char replaced[MCOUNT_INSN_SIZE];
+
+       /*
+        * Note: Due to modules code can disappear and change.
+        *  We need to protect against faulting as well as code
+        *  changing. We do this by using the probe_kernel_*
+        *  functions.
+        *  This however is just a simple sanity check.
+        */
+       if (probe_kernel_read(replaced, (void *)ip, old_size))
+               return -EFAULT;
+       if (memcmp(replaced, old_code, old_size) != 0)
+               return -EINVAL;
+       if (probe_kernel_write((void *)ip, new_code, new_size))
+               return -EPERM;
+       return 0;
+}
+
+static int ftrace_make_initial_nop(struct module *mod, struct dyn_ftrace *rec,
+                                  unsigned long addr)
+{
+       return ftrace_modify_code(rec->ip,
+                                 ftrace_call_code, FTRACE_INSN_SIZE,
+                                 ftrace_disable_code, MCOUNT_INSN_SIZE);
+}
+
+int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
+                   unsigned long addr)
+{
+       if (addr == MCOUNT_ADDR)
+               return ftrace_make_initial_nop(mod, rec, addr);
+       return ftrace_modify_code(rec->ip,
+                                 ftrace_call_code, FTRACE_INSN_SIZE,
+                                 ftrace_nop_code, FTRACE_INSN_SIZE);
+}
+
+int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
+{
+       return ftrace_modify_code(rec->ip,
+                                 ftrace_nop_code, FTRACE_INSN_SIZE,
+                                 ftrace_call_code, FTRACE_INSN_SIZE);
+}
+
+int ftrace_update_ftrace_func(ftrace_func_t func)
+{
+       ftrace_dyn_func = (unsigned long)func;
+       return 0;
+}
+
+int __init ftrace_dyn_arch_init(void *data)
+{
+       *(unsigned long *)data = 0;
+       return 0;
+}
+
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+#ifdef CONFIG_DYNAMIC_FTRACE
+/*
+ * Patch the kernel code at ftrace_graph_caller location:
+ * The instruction there is branch relative on condition. The condition mask
+ * is either all ones (always branch aka disable ftrace_graph_caller) or all
+ * zeroes (nop aka enable ftrace_graph_caller).
+ * Instruction format for brc is a7m4xxxx where m is the condition mask.
+ */
+int ftrace_enable_ftrace_graph_caller(void)
+{
+       unsigned short opcode = 0xa704;
+
+       return probe_kernel_write(ftrace_graph_caller, &opcode, sizeof(opcode));
+}
+
+int ftrace_disable_ftrace_graph_caller(void)
+{
+       unsigned short opcode = 0xa7f4;
+
+       return probe_kernel_write(ftrace_graph_caller, &opcode, sizeof(opcode));
+}
+
+static inline unsigned long ftrace_mcount_call_adjust(unsigned long addr)
+{
+       return addr - (ftrace_disable_return - ftrace_disable_code);
+}
+
+#else /* CONFIG_DYNAMIC_FTRACE */
+
+static inline unsigned long ftrace_mcount_call_adjust(unsigned long addr)
+{
+       return addr - MCOUNT_OFFSET_RET;
+}
+
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
+/*
+ * Hook the return address and push it in the stack of return addresses
+ * in current thread info.
+ */
+unsigned long prepare_ftrace_return(unsigned long ip, unsigned long parent)
+{
+       struct ftrace_graph_ent trace;
+
+       /* Nmi's are currently unsupported. */
+       if (unlikely(in_nmi()))
+               goto out;
+       if (unlikely(atomic_read(&current->tracing_graph_pause)))
+               goto out;
+       if (ftrace_push_return_trace(parent, ip, &trace.depth) == -EBUSY)
+               goto out;
+       trace.func = ftrace_mcount_call_adjust(ip) & PSW_ADDR_INSN;
+       /* Only trace if the calling function expects to. */
+       if (!ftrace_graph_entry(&trace)) {
+               current->curr_ret_stack--;
+               goto out;
+       }
+       parent = (unsigned long)return_to_handler;
+out:
+       return parent;
+}
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+
+#ifdef CONFIG_FTRACE_SYSCALLS
+
+extern unsigned long __start_syscalls_metadata[];
+extern unsigned long __stop_syscalls_metadata[];
+extern unsigned int sys_call_table[];
+
+static struct syscall_metadata **syscalls_metadata;
+
+struct syscall_metadata *syscall_nr_to_meta(int nr)
+{
+       if (!syscalls_metadata || nr >= NR_syscalls || nr < 0)
+               return NULL;
+
+       return syscalls_metadata[nr];
+}
+
+static struct syscall_metadata *find_syscall_meta(unsigned long syscall)
+{
+       struct syscall_metadata *start;
+       struct syscall_metadata *stop;
+       char str[KSYM_SYMBOL_LEN];
+
+       start = (struct syscall_metadata *)__start_syscalls_metadata;
+       stop = (struct syscall_metadata *)__stop_syscalls_metadata;
+       kallsyms_lookup(syscall, NULL, NULL, NULL, str);
+
+       for ( ; start < stop; start++) {
+               if (start->name && !strcmp(start->name + 3, str + 3))
+                       return start;
+       }
+       return NULL;
+}
+
+void arch_init_ftrace_syscalls(void)
+{
+       struct syscall_metadata *meta;
+       int i;
+       static atomic_t refs;
+
+       if (atomic_inc_return(&refs) != 1)
+               goto out;
+       syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) * NR_syscalls,
+                                   GFP_KERNEL);
+       if (!syscalls_metadata)
+               goto out;
+       for (i = 0; i < NR_syscalls; i++) {
+               meta = find_syscall_meta((unsigned long)sys_call_table[i]);
+               syscalls_metadata[i] = meta;
+       }
+       return;
+out:
+       atomic_dec(&refs);
+}
+#endif
index 22596d70fc2e8961f1e29dc80305248b20028c79..6d227413cbe77cf111dd088357f71cb6762fb56c 100644 (file)
@@ -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)
index a01cf0284db2dc20b2ab7b9e6e0d299074410a49..9bb2f6241d9faeaf77c71567569baba703716912 100644 (file)
@@ -25,9 +25,9 @@
 #include <linux/preempt.h>
 #include <linux/stop_machine.h>
 #include <linux/kdebug.h>
+#include <linux/uaccess.h>
 #include <asm/cacheflush.h>
 #include <asm/sections.h>
-#include <asm/uaccess.h>
 #include <linux/module.h>
 
 DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
@@ -155,35 +155,8 @@ void __kprobes get_instruction_type(struct arch_specific_insn *ainsn)
 static int __kprobes swap_instruction(void *aref)
 {
        struct ins_replace_args *args = aref;
-       u32 *addr;
-       u32 instr;
-       int err = -EFAULT;
 
-       /*
-        * Text segment is read-only, hence we use stura to bypass dynamic
-        * address translation to exchange the instruction. Since stura
-        * always operates on four bytes, but we only want to exchange two
-        * bytes do some calculations to get things right. In addition we
-        * shall not cross any page boundaries (vmalloc area!) when writing
-        * the new instruction.
-        */
-       addr = (u32 *)((unsigned long)args->ptr & -4UL);
-       if ((unsigned long)args->ptr & 2)
-               instr = ((*addr) & 0xffff0000) | args->new;
-       else
-               instr = ((*addr) & 0x0000ffff) | args->new << 16;
-
-       asm volatile(
-               "       lra     %1,0(%1)\n"
-               "0:     stura   %2,%1\n"
-               "1:     la      %0,0\n"
-               "2:\n"
-               EX_TABLE(0b,2b)
-               : "+d" (err)
-               : "a" (addr), "d" (instr)
-               : "memory", "cc");
-
-       return err;
+       return probe_kernel_write(args->ptr, &args->new, sizeof(args->new));
 }
 
 void __kprobes arch_arm_kprobe(struct kprobe *p)
index 80641224a0959299dff6ba72c8119378ecd87059..2a0a5e97ba8c2a6f954c2209a1836fe70d92ac0f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright IBM Corp. 2008
+ * Copyright IBM Corp. 2008,2009
  *
  *   Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>,
  *
@@ -7,36 +7,64 @@
 
 #include <asm/asm-offsets.h>
 
-#ifndef CONFIG_64BIT
-.globl _mcount
+       .globl ftrace_stub
+ftrace_stub:
+       br      %r14
+
+#ifdef CONFIG_64BIT
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+
+       .globl _mcount
 _mcount:
-       stm     %r0,%r5,8(%r15)
-       st      %r14,56(%r15)
-       lr      %r1,%r15
-       ahi     %r15,-96
-       l       %r3,100(%r15)
-       la      %r2,0(%r14)
-       st      %r1,__SF_BACKCHAIN(%r15)
-       la      %r3,0(%r3)
-       bras    %r14,0f
-       .long   ftrace_trace_function
-0:     l       %r14,0(%r14)
-       l       %r14,0(%r14)
-       basr    %r14,%r14
-       ahi     %r15,96
-       lm      %r0,%r5,8(%r15)
-       l       %r14,56(%r15)
        br      %r14
 
-.globl ftrace_stub
-ftrace_stub:
+       .globl ftrace_caller
+ftrace_caller:
+       larl    %r1,function_trace_stop
+       icm     %r1,0xf,0(%r1)
+       bnzr    %r14
+       stmg    %r2,%r5,32(%r15)
+       stg     %r14,112(%r15)
+       lgr     %r1,%r15
+       aghi    %r15,-160
+       stg     %r1,__SF_BACKCHAIN(%r15)
+       lgr     %r2,%r14
+       lg      %r3,168(%r15)
+       larl    %r14,ftrace_dyn_func
+       lg      %r14,0(%r14)
+       basr    %r14,%r14
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+       .globl  ftrace_graph_caller
+ftrace_graph_caller:
+       # This unconditional branch gets runtime patched. Change only if
+       # you know what you are doing. See ftrace_enable_graph_caller().
+       j       0f
+       lg      %r2,272(%r15)
+       lg      %r3,168(%r15)
+       brasl   %r14,prepare_ftrace_return
+       stg     %r2,168(%r15)
+0:
+#endif
+       aghi    %r15,160
+       lmg     %r2,%r5,32(%r15)
+       lg      %r14,112(%r15)
        br      %r14
 
-#else /* CONFIG_64BIT */
+       .data
+       .globl  ftrace_dyn_func
+ftrace_dyn_func:
+       .quad   ftrace_stub
+       .previous
+
+#else /* CONFIG_DYNAMIC_FTRACE */
 
-.globl _mcount
+       .globl _mcount
 _mcount:
-       stmg    %r0,%r5,16(%r15)
+       larl    %r1,function_trace_stop
+       icm     %r1,0xf,0(%r1)
+       bnzr    %r14
+       stmg    %r2,%r5,32(%r15)
        stg     %r14,112(%r15)
        lgr     %r1,%r15
        aghi    %r15,-160
@@ -46,13 +74,143 @@ _mcount:
        larl    %r14,ftrace_trace_function
        lg      %r14,0(%r14)
        basr    %r14,%r14
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+       lg      %r2,272(%r15)
+       lg      %r3,168(%r15)
+       brasl   %r14,prepare_ftrace_return
+       stg     %r2,168(%r15)
+#endif
        aghi    %r15,160
-       lmg     %r0,%r5,16(%r15)
+       lmg     %r2,%r5,32(%r15)
        lg      %r14,112(%r15)
        br      %r14
 
-.globl ftrace_stub
-ftrace_stub:
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+
+       .globl  return_to_handler
+return_to_handler:
+       stmg    %r2,%r5,32(%r15)
+       lgr     %r1,%r15
+       aghi    %r15,-160
+       stg     %r1,__SF_BACKCHAIN(%r15)
+       brasl   %r14,ftrace_return_to_handler
+       aghi    %r15,160
+       lgr     %r14,%r2
+       lmg     %r2,%r5,32(%r15)
+       br      %r14
+
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+
+#else /* CONFIG_64BIT */
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+
+       .globl _mcount
+_mcount:
+       br      %r14
+
+       .globl ftrace_caller
+ftrace_caller:
+       stm     %r2,%r5,16(%r15)
+       bras    %r1,2f
+0:     .long   ftrace_trace_function
+1:     .long   function_trace_stop
+2:     l       %r2,1b-0b(%r1)
+       icm     %r2,0xf,0(%r2)
+       jnz     3f
+       st      %r14,56(%r15)
+       lr      %r0,%r15
+       ahi     %r15,-96
+       l       %r3,100(%r15)
+       la      %r2,0(%r14)
+       st      %r0,__SF_BACKCHAIN(%r15)
+       la      %r3,0(%r3)
+       l       %r14,0b-0b(%r1)
+       l       %r14,0(%r14)
+       basr    %r14,%r14
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+       .globl  ftrace_graph_caller
+ftrace_graph_caller:
+       # This unconditional branch gets runtime patched. Change only if
+       # you know what you are doing. See ftrace_enable_graph_caller().
+       j       1f
+       bras    %r1,0f
+       .long   prepare_ftrace_return
+0:     l       %r2,152(%r15)
+       l       %r4,0(%r1)
+       l       %r3,100(%r15)
+       basr    %r14,%r4
+       st      %r2,100(%r15)
+1:
+#endif
+       ahi     %r15,96
+       l       %r14,56(%r15)
+3:     lm      %r2,%r5,16(%r15)
        br      %r14
 
+       .data
+       .globl  ftrace_dyn_func
+ftrace_dyn_func:
+       .long   ftrace_stub
+       .previous
+
+#else /* CONFIG_DYNAMIC_FTRACE */
+
+       .globl _mcount
+_mcount:
+       stm     %r2,%r5,16(%r15)
+       bras    %r1,2f
+0:     .long   ftrace_trace_function
+1:     .long   function_trace_stop
+2:     l       %r2,1b-0b(%r1)
+       icm     %r2,0xf,0(%r2)
+       jnz     3f
+       st      %r14,56(%r15)
+       lr      %r0,%r15
+       ahi     %r15,-96
+       l       %r3,100(%r15)
+       la      %r2,0(%r14)
+       st      %r0,__SF_BACKCHAIN(%r15)
+       la      %r3,0(%r3)
+       l       %r14,0b-0b(%r1)
+       l       %r14,0(%r14)
+       basr    %r14,%r14
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+       bras    %r1,0f
+       .long   prepare_ftrace_return
+0:     l       %r2,152(%r15)
+       l       %r4,0(%r1)
+       l       %r3,100(%r15)
+       basr    %r14,%r4
+       st      %r2,100(%r15)
+#endif
+       ahi     %r15,96
+       l       %r14,56(%r15)
+3:     lm      %r2,%r5,16(%r15)
+       br      %r14
+
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+
+       .globl  return_to_handler
+return_to_handler:
+       stm     %r2,%r5,16(%r15)
+       st      %r14,56(%r15)
+       lr      %r0,%r15
+       ahi     %r15,-96
+       st      %r0,__SF_BACKCHAIN(%r15)
+       bras    %r1,0f
+       .long   ftrace_return_to_handler
+0:     l       %r2,0b-0b(%r1)
+       basr    %r14,%r2
+       lr      %r14,%r2
+       ahi     %r15,96
+       lm      %r2,%r5,16(%r15)
+       br      %r14
+
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+
 #endif /* CONFIG_64BIT */
index 28cf196ba775e0e956024a123576fa15b5da1021..015e27da40eb100e5375d356c1160d4c3a98c552 100644 (file)
@@ -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>
 
index a3acd8e60aff70886b058afdc8bce0a441b60e62..355f7a30c3f11c7cdc8a1eaddc77c41a42e9808b 100644 (file)
@@ -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);
index 75c496f4f16d2c41900fb4db365f49149e52d022..490b39934d65aa8a98cc76f5772b10f3ef9735ea 100644 (file)
@@ -36,7 +36,9 @@
 #include <linux/elf.h>
 #include <linux/regset.h>
 #include <linux/tracehook.h>
-
+#include <linux/seccomp.h>
+#include <trace/syscall.h>
+#include <asm/compat.h>
 #include <asm/segment.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
@@ -69,7 +71,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 +484,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 +585,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 +642,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].
@@ -659,8 +662,11 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
                ret = -1;
        }
 
+       if (unlikely(test_thread_flag(TIF_SYSCALL_FTRACE)))
+               ftrace_syscall_enter(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],
@@ -674,6 +680,9 @@ asmlinkage void do_syscall_trace_exit(struct pt_regs *regs)
                audit_syscall_exit(AUDITSC_RESULT(regs->gprs[2]),
                                   regs->gprs[2]);
 
+       if (unlikely(test_thread_flag(TIF_SYSCALL_FTRACE)))
+               ftrace_syscall_exit(regs);
+
        if (test_thread_flag(TIF_SYSCALL_TRACE))
                tracehook_report_syscall_exit(regs, 0);
 }
index a0d2d55d7fb3996faae1fcaf686b44d1ef353863..0de305b598cee30a1352f67d4ded1eda4f0d3be0 100644 (file)
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
+#include <linux/ftrace.h>
 #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>
@@ -112,7 +113,7 @@ int unregister_early_external_interrupt(__u16 code, ext_int_handler_t handler,
        return 0;
 }
 
-void do_extint(struct pt_regs *regs, unsigned short code)
+void __irq_entry do_extint(struct pt_regs *regs, unsigned short code)
 {
         ext_int_info_t *p;
         int index;
diff --git a/arch/s390/kernel/sclp.S b/arch/s390/kernel/sclp.S
new file mode 100644 (file)
index 0000000..20639df
--- /dev/null
@@ -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
index 7402b6a39ead686232723361a5de31d6ad2e5b95..9717717c6fea5595b364e8b321ee6fa284580396 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/ctype.h>
 #include <linux/reboot.h>
 #include <linux/topology.h>
+#include <linux/ftrace.h>
 
 #include <asm/ipl.h>
 #include <asm/uaccess.h>
@@ -442,6 +443,7 @@ setup_lowcore(void)
        lc->steal_timer = S390_lowcore.steal_timer;
        lc->last_update_timer = S390_lowcore.last_update_timer;
        lc->last_update_clock = S390_lowcore.last_update_clock;
+       lc->ftrace_func = S390_lowcore.ftrace_func;
        set_prefix((u32)(unsigned long) lc);
        lowcore_ptr[0] = lc;
 }
index 3cf74c3ccb699184e7b55e9237103d6cd269b47a..062bd64e65fabe1f09641a4c3e0290ae4ff013ee 100644 (file)
@@ -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
index a985a3ba44011c948ef6948ac6631a2d9685a8a2..cc8c484984e33160375b11fd9f147c764b805cde 100644 (file)
@@ -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"
 
@@ -572,6 +572,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
        cpu_lowcore->cpu_nr = cpu;
        cpu_lowcore->kernel_asce = S390_lowcore.kernel_asce;
        cpu_lowcore->machine_flags = S390_lowcore.machine_flags;
+       cpu_lowcore->ftrace_func = S390_lowcore.ftrace_func;
        eieio();
 
        while (signal_processor(cpu, sigp_restart) == sigp_busy)
index 2c7739fe70b10a632146cb73ec674def95175478..ad1acd20038554ec19a518e8fda56cce7b4d5f17 100644 (file)
@@ -338,3 +338,5 @@ SYSCALL(sys_dup3,sys_dup3,sys_dup3_wrapper)
 SYSCALL(sys_epoll_create1,sys_epoll_create1,sys_epoll_create1_wrapper)
 SYSCALL(sys_preadv,sys_preadv,compat_sys_preadv_wrapper)
 SYSCALL(sys_pwritev,sys_pwritev,compat_sys_pwritev_wrapper)
+SYSCALL(sys_rt_tgsigqueueinfo,sys_rt_tgsigqueueinfo,compat_sys_rt_tgsigqueueinfo_wrapper) /* 330 */
+SYSCALL(sys_perf_counter_open,sys_perf_counter_open,sys_perf_counter_open_wrapper)
index ef596d020573ec0bfef8bc98ef1d4be225e7881f..215330a2c128dfce1bb341fed1bd138ef089c918 100644 (file)
@@ -70,7 +70,7 @@ static DEFINE_PER_CPU(struct clock_event_device, comparators);
 /*
  * Scheduler clock - returns current time in nanosec units.
  */
-unsigned long long sched_clock(void)
+unsigned long long notrace sched_clock(void)
 {
        return ((get_clock_xt() - sched_clock_base_cc) * 125) >> 9;
 }
@@ -95,12 +95,6 @@ void tod_to_timeval(__u64 todval, struct timespec *xtime)
        xtime->tv_nsec = ((todval * 1000) >> 12);
 }
 
-#ifdef CONFIG_PROFILING
-#define s390_do_profile()      profile_tick(CPU_PROFILING)
-#else
-#define s390_do_profile()      do { ; } while(0)
-#endif /* CONFIG_PROFILING */
-
 void clock_comparator_work(void)
 {
        struct clock_event_device *cd;
@@ -109,7 +103,6 @@ void clock_comparator_work(void)
        set_clock_comparator(S390_lowcore.clock_comparator);
        cd = &__get_cpu_var(comparators);
        cd->event_handler(cd);
-       s390_do_profile();
 }
 
 /*
index 89b2e7f1b7a9ca85c207880b54f7c220ac428728..45e1708b70fd028fdd9b6b432f156f886855d0ae 100644 (file)
@@ -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;
        }
index 89399b8756c2bae265601ba314bfb51dd9493f0f..a53db23ee092fcbd37f2fa2e16ca5fbc8a583cd7 100644 (file)
@@ -34,6 +34,7 @@ SECTIONS
                SCHED_TEXT
                LOCK_TEXT
                KPROBES_TEXT
+               IRQENTRY_TEXT
                *(.fixup)
                *(.gnu.warning)
        } :text = 0x0700
index c87f59bd8246a9ecdbe9d9417a58b19975df72f9..c8eb7255332b8bda03f187525087dd47baa535e2 100644 (file)
@@ -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;
 
index 10bccd1f8aee58a33220bfbc07aa3b3452b1b3e7..c18b21d6991cebacdb8dfb4358017db75782eb44 100644 (file)
@@ -512,7 +512,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);
index e41f4008afc501927a5c3b08fda18891c1afc887..f7e0d30250b707b1ed46f7878f0f6790e7295e30 100644 (file)
@@ -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;
index 2a745813454410cb35ff525e837efc9f29c0dd95..db05661ac8954269a36d796b548e7bb0a40f126c 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for the linux s390-specific parts of the memory manager.
 #
 
-obj-y   := init.o fault.o extmem.o mmap.o vmem.o pgtable.o
+obj-y   := init.o fault.o extmem.o mmap.o vmem.o pgtable.o maccess.o
 obj-$(CONFIG_CMM) += cmm.o
 obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
 obj-$(CONFIG_PAGE_STATES) += page-states.o
index 833e8366c351d08238466e21f660c66dc47e0845..220a152c836ccf990c109bed1089d297e4ba76d6 100644 (file)
@@ -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/maccess.c b/arch/s390/mm/maccess.c
new file mode 100644 (file)
index 0000000..8175627
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Access kernel memory without faulting -- s390 specific implementation.
+ *
+ * Copyright IBM Corp. 2009
+ *
+ *   Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>,
+ *
+ */
+
+#include <linux/uaccess.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/system.h>
+
+/*
+ * This function writes to kernel memory bypassing DAT and possible
+ * write protection. It copies one to four bytes from src to dst
+ * using the stura instruction.
+ * Returns the number of bytes copied or -EFAULT.
+ */
+static long probe_kernel_write_odd(void *dst, void *src, size_t size)
+{
+       unsigned long count, aligned;
+       int offset, mask;
+       int rc = -EFAULT;
+
+       aligned = (unsigned long) dst & ~3UL;
+       offset = (unsigned long) dst & 3;
+       count = min_t(unsigned long, 4 - offset, size);
+       mask = (0xf << (4 - count)) & 0xf;
+       mask >>= offset;
+       asm volatile(
+               "       bras    1,0f\n"
+               "       icm     0,0,0(%3)\n"
+               "0:     l       0,0(%1)\n"
+               "       lra     %1,0(%1)\n"
+               "1:     ex      %2,0(1)\n"
+               "2:     stura   0,%1\n"
+               "       la      %0,0\n"
+               "3:\n"
+               EX_TABLE(0b,3b) EX_TABLE(1b,3b) EX_TABLE(2b,3b)
+               : "+d" (rc), "+a" (aligned)
+               : "a" (mask), "a" (src) : "cc", "memory", "0", "1");
+       return rc ? rc : count;
+}
+
+long probe_kernel_write(void *dst, void *src, size_t size)
+{
+       long copied = 0;
+
+       while (size) {
+               copied = probe_kernel_write_odd(dst, src, size);
+               if (copied < 0)
+                       break;
+               dst += copied;
+               src += copied;
+               size -= copied;
+       }
+       return copied < 0 ? -EFAULT : 0;
+}
index e008d236cc150666187fc7921df901523fe476ce..f4558ccf02b9cd266ad005cb2925a2dfa5d7ea89 100644 (file)
@@ -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)
index be6c1cf4ad5ae8922f039ab2100b2e50183553f2..4ca8e826bf303b4d8694f0757fe8b471ba52d099 100644 (file)
@@ -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);
index 27a1be0cd4d467a1b3c4ba1d6ab501d3b4ea2fdf..442bb98a2821c5a34519b08e452bfb9ffa1bf629 100644 (file)
@@ -851,8 +851,10 @@ int dasd_start_IO(struct dasd_ccw_req *cqr)
 
        /* Check the cqr */
        rc = dasd_check_cqr(cqr);
-       if (rc)
+       if (rc) {
+               cqr->intrc = rc;
                return rc;
+       }
        device = (struct dasd_device *) cqr->startdev;
        if (cqr->retries < 0) {
                /* internal error 14 - start_IO run out of retries */
@@ -915,6 +917,7 @@ int dasd_start_IO(struct dasd_ccw_req *cqr)
                BUG();
                break;
        }
+       cqr->intrc = rc;
        return rc;
 }
 
@@ -1454,8 +1457,12 @@ int dasd_sleep_on(struct dasd_ccw_req *cqr)
        dasd_add_request_tail(cqr);
        wait_event(generic_waitq, _wait_for_wakeup(cqr));
 
-       /* Request status is either done or failed. */
-       rc = (cqr->status == DASD_CQR_DONE) ? 0 : -EIO;
+       if (cqr->status == DASD_CQR_DONE)
+               rc = 0;
+       else if (cqr->intrc)
+               rc = cqr->intrc;
+       else
+               rc = -EIO;
        return rc;
 }
 
@@ -1477,8 +1484,15 @@ int dasd_sleep_on_interruptible(struct dasd_ccw_req *cqr)
                dasd_cancel_req(cqr);
                /* wait (non-interruptible) for final status */
                wait_event(generic_waitq, _wait_for_wakeup(cqr));
+               cqr->intrc = rc;
        }
-       rc = (cqr->status == DASD_CQR_DONE) ? 0 : -EIO;
+
+       if (cqr->status == DASD_CQR_DONE)
+               rc = 0;
+       else if (cqr->intrc)
+               rc = cqr->intrc;
+       else
+               rc = -EIO;
        return rc;
 }
 
@@ -1523,8 +1537,12 @@ int dasd_sleep_on_immediatly(struct dasd_ccw_req *cqr)
 
        wait_event(generic_waitq, _wait_for_wakeup(cqr));
 
-       /* Request status is either done or failed. */
-       rc = (cqr->status == DASD_CQR_DONE) ? 0 : -EIO;
+       if (cqr->status == DASD_CQR_DONE)
+               rc = 0;
+       else if (cqr->intrc)
+               rc = cqr->intrc;
+       else
+               rc = -EIO;
        return rc;
 }
 
@@ -2427,12 +2445,12 @@ static struct dasd_ccw_req *dasd_generic_build_rdc(struct dasd_device *device,
 
 
 int dasd_generic_read_dev_chars(struct dasd_device *device, char *magic,
-                               void **rdc_buffer, int rdc_buffer_size)
+                               void *rdc_buffer, int rdc_buffer_size)
 {
        int ret;
        struct dasd_ccw_req *cqr;
 
-       cqr = dasd_generic_build_rdc(device, *rdc_buffer, rdc_buffer_size,
+       cqr = dasd_generic_build_rdc(device, rdc_buffer, rdc_buffer_size,
                                     magic);
        if (IS_ERR(cqr))
                return PTR_ERR(cqr);
index 2efaddfae56088be5d25bf27e4f53991105ec070..644086ba2ede9365e0733964855e41c992e6f2a5 100644 (file)
@@ -202,6 +202,7 @@ dasd_start_diag(struct dasd_ccw_req * cqr)
                rc = -EIO;
                break;
        }
+       cqr->intrc = rc;
        return rc;
 }
 
index a41c94053e64be88f1179153be06156c313d9093..cf0cfdba1244bb95891955820f6e873b24bdb6c7 100644 (file)
@@ -1097,20 +1097,20 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
 {
        struct dasd_eckd_private *private;
        struct dasd_block *block;
-       void *rdc_data;
        int is_known, rc;
 
        private = (struct dasd_eckd_private *) device->private;
-       if (private == NULL) {
-               private = kzalloc(sizeof(struct dasd_eckd_private),
-                                 GFP_KERNEL | GFP_DMA);
-               if (private == NULL) {
+       if (!private) {
+               private = kzalloc(sizeof(*private), GFP_KERNEL | GFP_DMA);
+               if (!private) {
                        dev_warn(&device->cdev->dev,
                                 "Allocating memory for private DASD data "
                                 "failed\n");
                        return -ENOMEM;
                }
                device->private = (void *) private;
+       } else {
+               memset(private, 0, sizeof(*private));
        }
        /* Invalidate status of initial analysis. */
        private->init_cqr_status = -1;
@@ -1161,9 +1161,8 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
                goto out_err3;
 
        /* Read Device Characteristics */
-       rdc_data = (void *) &(private->rdc_data);
-       memset(rdc_data, 0, sizeof(rdc_data));
-       rc = dasd_generic_read_dev_chars(device, "ECKD", &rdc_data, 64);
+       rc = dasd_generic_read_dev_chars(device, "ECKD", &private->rdc_data,
+                                        64);
        if (rc) {
                DBF_EVENT(DBF_WARNING,
                          "Read device characteristics failed, rc=%d for "
@@ -1183,7 +1182,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
                 private->rdc_data.dev_model,
                 private->rdc_data.cu_type,
                 private->rdc_data.cu_model.model,
-                   private->real_cyl,
+                private->real_cyl,
                 private->rdc_data.trk_per_cyl,
                 private->rdc_data.sec_per_trk);
        return 0;
@@ -2336,9 +2335,10 @@ static struct dasd_ccw_req *dasd_eckd_build_cp(struct dasd_device *startdev,
 {
        int tpm, cmdrtd, cmdwtd;
        int use_prefix;
-
-       struct dasd_eckd_private *private;
+#if defined(CONFIG_64BIT)
        int fcx_in_css, fcx_in_gneq, fcx_in_features;
+#endif
+       struct dasd_eckd_private *private;
        struct dasd_device *basedev;
        sector_t first_rec, last_rec;
        sector_t first_trk, last_trk;
@@ -2361,11 +2361,15 @@ static struct dasd_ccw_req *dasd_eckd_build_cp(struct dasd_device *startdev,
        last_offs = sector_div(last_trk, blk_per_trk);
        cdlspecial = (private->uses_cdl && first_rec < 2*blk_per_trk);
 
-       /* is transport mode supported ? */
+       /* is transport mode supported? */
+#if defined(CONFIG_64BIT)
        fcx_in_css = css_general_characteristics.fcx;
        fcx_in_gneq = private->gneq->reserved2[7] & 0x04;
        fcx_in_features = private->features.feature[40] & 0x80;
        tpm = fcx_in_css && fcx_in_gneq && fcx_in_features;
+#else
+       tpm = 0;
+#endif
 
        /* is read track data and write track data in command mode supported? */
        cmdrtd = private->features.feature[9] & 0x20;
@@ -3013,8 +3017,9 @@ static void dasd_eckd_dump_sense_ccw(struct dasd_device *device,
                      " I/O status report for device %s:\n",
                      dev_name(&device->cdev->dev));
        len += sprintf(page + len, KERN_ERR PRINTK_HEADER
-                      " in req: %p CS: 0x%02X DS: 0x%02X\n", req,
-                      scsw_cstat(&irb->scsw), scsw_dstat(&irb->scsw));
+                      " in req: %p CS: 0x%02X DS: 0x%02X CC: 0x%02X RC: %d\n",
+                      req, scsw_cstat(&irb->scsw), scsw_dstat(&irb->scsw),
+                      scsw_cc(&irb->scsw), req->intrc);
        len += sprintf(page + len, KERN_ERR PRINTK_HEADER
                       " device %s: Failing CCW: %p\n",
                       dev_name(&device->cdev->dev),
@@ -3115,9 +3120,10 @@ static void dasd_eckd_dump_sense_tcw(struct dasd_device *device,
                      " I/O status report for device %s:\n",
                      dev_name(&device->cdev->dev));
        len += sprintf(page + len, KERN_ERR PRINTK_HEADER
-                      " in req: %p CS: 0x%02X DS: 0x%02X "
+                      " in req: %p CS: 0x%02X DS: 0x%02X CC: 0x%02X RC: %d "
                       "fcxs: 0x%02X schxs: 0x%02X\n", req,
                       scsw_cstat(&irb->scsw), scsw_dstat(&irb->scsw),
+                      scsw_cc(&irb->scsw), req->intrc,
                       irb->scsw.tm.fcxs, irb->scsw.tm.schxs);
        len += sprintf(page + len, KERN_ERR PRINTK_HEADER
                       " device %s: Failing TCW: %p\n",
@@ -3273,8 +3279,14 @@ static struct dasd_discipline dasd_eckd_discipline = {
 static int __init
 dasd_eckd_init(void)
 {
+       int ret;
+
        ASCEBC(dasd_eckd_discipline.ebcname, 4);
-       return ccw_driver_register(&dasd_eckd_driver);
+       ret = ccw_driver_register(&dasd_eckd_driver);
+       if (!ret)
+               wait_for_device_probe();
+
+       return ret;
 }
 
 static void __exit
index 8912358daa2fd0c3c6561b7469c5d2d23b5e1d5d..597c6ffdb9f2308258a292a0b584f440f9c0ec6a 100644 (file)
@@ -122,20 +122,20 @@ dasd_fba_check_characteristics(struct dasd_device *device)
        struct dasd_block *block;
        struct dasd_fba_private *private;
        struct ccw_device *cdev = device->cdev;
-       void *rdc_data;
        int rc;
 
        private = (struct dasd_fba_private *) device->private;
-       if (private == NULL) {
-               private = kzalloc(sizeof(struct dasd_fba_private),
-                                 GFP_KERNEL | GFP_DMA);
-               if (private == NULL) {
+       if (!private) {
+               private = kzalloc(sizeof(*private), GFP_KERNEL | GFP_DMA);
+               if (!private) {
                        dev_warn(&device->cdev->dev,
                                 "Allocating memory for private DASD "
                                 "data failed\n");
                        return -ENOMEM;
                }
                device->private = (void *) private;
+       } else {
+               memset(private, 0, sizeof(*private));
        }
        block = dasd_alloc_block();
        if (IS_ERR(block)) {
@@ -150,8 +150,8 @@ dasd_fba_check_characteristics(struct dasd_device *device)
        block->base = device;
 
        /* Read Device Characteristics */
-       rdc_data = (void *) &(private->rdc_data);
-       rc = dasd_generic_read_dev_chars(device, "FBA ", &rdc_data, 32);
+       rc = dasd_generic_read_dev_chars(device, "FBA ", &private->rdc_data,
+                                        32);
        if (rc) {
                DBF_EVENT(DBF_WARNING, "Read device characteristics returned "
                          "error %d for device: %s",
@@ -604,8 +604,14 @@ static struct dasd_discipline dasd_fba_discipline = {
 static int __init
 dasd_fba_init(void)
 {
+       int ret;
+
        ASCEBC(dasd_fba_discipline.ebcname, 4);
-       return ccw_driver_register(&dasd_fba_driver);
+       ret = ccw_driver_register(&dasd_fba_driver);
+       if (!ret)
+               wait_for_device_probe();
+
+       return ret;
 }
 
 static void __exit
index c1e487f774c67fb5638be3cdbdadf73f1ea87474..f97ceb795078ee9c1cb0df2bba09c0755575dc9f 100644 (file)
@@ -173,6 +173,7 @@ struct dasd_ccw_req {
        void *data;                     /* pointer to data area */
 
        /* these are important for recovering erroneous requests          */
+       int intrc;                      /* internal error, e.g. from start_IO */
        struct irb irb;                 /* device status in case of an error */
        struct dasd_ccw_req *refers;    /* ERP-chain queueing. */
        void *function;                 /* originating ERP action */
@@ -578,7 +579,7 @@ int dasd_generic_set_offline (struct ccw_device *cdev);
 int dasd_generic_notify(struct ccw_device *, int);
 void dasd_generic_handle_state_change(struct dasd_device *);
 
-int dasd_generic_read_dev_chars(struct dasd_device *, char *, void **, int);
+int dasd_generic_read_dev_chars(struct dasd_device *, char *, void *, int);
 char *dasd_get_sense(struct irb *);
 
 /* externals in dasd_devmap.c */
index a4c7ffcd9987adb6dcec33687181597c84662ec9..b21caf177e370ef929f637c0f289b96a0db713db 100644 (file)
@@ -127,7 +127,7 @@ dcssblk_assign_free_minor(struct dcssblk_dev_info *dev_info)
                found = 0;
                // test if minor available
                list_for_each_entry(entry, &dcssblk_devices, lh)
-                       if (minor == MINOR(disk_devt(entry->gd)))
+                       if (minor == entry->gd->first_minor)
                                found++;
                if (!found) break; // got unused minor
        }
@@ -625,7 +625,7 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char
        if (rc)
                goto release_gd;
        sprintf(dev_info->gd->disk_name, "dcssblk%d",
-               MINOR(disk_devt(dev_info->gd)));
+               dev_info->gd->first_minor);
        list_add_tail(&dev_info->lh, &dcssblk_devices);
 
        if (!try_module_get(THIS_MODULE)) {
index d028d2ee83dd36a3dff91061fbfc8d830eca3470..ed5396dae58eef0edc2eb6f451419737c0b5dfd7 100644 (file)
@@ -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);
index a7fe6302c9820c3790f3c14bffb4f0aee4b35679..38385677c65380e45730b42b8af38d78c9f8ac50 100644 (file)
@@ -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);
index 2aebb9823044765427ceb806118b921276b94dbb..5ec7789bd9d84a0ab171d75d66315f4bce8e4b9c 100644 (file)
@@ -12,6 +12,7 @@
 #define KMSG_COMPONENT "cio"
 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
+#include <linux/ftrace.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -28,7 +29,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>
@@ -626,8 +627,7 @@ out:
  *         handlers).
  *
  */
-void
-do_IRQ (struct pt_regs *regs)
+void __irq_entry do_IRQ(struct pt_regs *regs)
 {
        struct tpi_info *tpi_info;
        struct subchannel *sch;
index 151754d54745a3565fde4dca29a00f3de6b6a208..bf0a24af39a0542be842f5705cc49ec58da63b2f 100644 (file)
@@ -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;
 }
 
 /*
index accd957454e7210aab8c5de0d054a5a7b099eae8..d79cf5bf0e62312d98506ccb105618a640e64d09 100644 (file)
@@ -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)
index 136d0f0b1e93e7e155172caf55c2fabc31bccb8a..eff943923c6fac1d3e0862c0134b3a2a9920efa0 100644 (file)
@@ -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
  */
index 7821ac4fa51759196f6dbdc0bf56045aef9140aa..ff4504ce1e3c0ad5577e86d0642895d08b8c7924 100644 (file)
@@ -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
index ac40796cfb15b8d41d1b0e5f45cd093c31bf7da2..9073695ff25f3db8da8df878e6ade3952542229a 100644 (file)
@@ -39,7 +39,7 @@ EXPORT_SYMBOL_GPL(probe_kernel_read);
  * Safely write to address @dst from the buffer at @src.  If a kernel fault
  * happens, handle that and return -EFAULT.
  */
-long probe_kernel_write(void *dst, void *src, size_t size)
+long notrace __weak probe_kernel_write(void *dst, void *src, size_t size)
 {
        long ret;
        mm_segment_t old_fs = get_fs();
index 0fae7da0529cac497a5337be4b6dd0e89cbf13d6..91033e67321e84e6479816cdff61c372f3be58d1 100755 (executable)
@@ -185,6 +185,19 @@ if ($arch eq "x86_64") {
     $objcopy .= " -O elf32-i386";
     $cc .= " -m32";
 
+} elsif ($arch eq "s390" && $bits == 32) {
+    $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_390_32\\s+_mcount\$";
+    $alignment = 4;
+    $ld .= " -m elf_s390";
+    $cc .= " -m31";
+
+} elsif ($arch eq "s390" && $bits == 64) {
+    $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_390_(PC|PLT)32DBL\\s+_mcount\\+0x2\$";
+    $alignment = 8;
+    $type = ".quad";
+    $ld .= " -m elf64_s390";
+    $cc .= " -m64";
+
 } elsif ($arch eq "sh") {
     $alignment = 2;