Merge branch 'akpm' (patches from Andrew Morton)
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 14 Oct 2014 01:54:50 +0000 (03:54 +0200)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 14 Oct 2014 01:54:50 +0000 (03:54 +0200)
Merge second patch-bomb from Andrew Morton:
 - a few hotfixes
 - drivers/dma updates
 - MAINTAINERS updates
 - Quite a lot of lib/ updates
 - checkpatch updates
 - binfmt updates
 - autofs4
 - drivers/rtc/
 - various small tweaks to less used filesystems
 - ipc/ updates
 - kernel/watchdog.c changes

* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (135 commits)
  mm: softdirty: enable write notifications on VMAs after VM_SOFTDIRTY cleared
  kernel/param: consolidate __{start,stop}___param[] in <linux/moduleparam.h>
  ia64: remove duplicate declarations of __per_cpu_start[] and __per_cpu_end[]
  frv: remove unused declarations of __start___ex_table and __stop___ex_table
  kvm: ensure hard lockup detection is disabled by default
  kernel/watchdog.c: control hard lockup detection default
  staging: rtl8192u: use %*pEn to escape buffer
  staging: rtl8192e: use %*pEn to escape buffer
  staging: wlan-ng: use %*pEhp to print SN
  lib80211: remove unused print_ssid()
  wireless: hostap: proc: print properly escaped SSID
  wireless: ipw2x00: print SSID via %*pE
  wireless: libertas: print esaped string via %*pE
  lib/vsprintf: add %*pE[achnops] format specifier
  lib / string_helpers: introduce string_escape_mem()
  lib / string_helpers: refactoring the test suite
  lib / string_helpers: move documentation to c-file
  include/linux: remove strict_strto* definitions
  arch/x86/mm/numa.c: fix boot failure when all nodes are hotpluggable
  fs: check bh blocknr earlier when searching lru
  ...

233 files changed:
Documentation/kprobes.txt
Documentation/x86/x86_64/mm.txt
arch/Kconfig
arch/arm/kernel/ptrace.c
arch/ia64/include/asm/unistd.h
arch/ia64/include/uapi/asm/unistd.h
arch/ia64/kernel/entry.S
arch/m68k/68000/Makefile [moved from arch/m68k/platform/68000/Makefile with 100% similarity]
arch/m68k/68000/bootlogo-vz.h [moved from arch/m68k/platform/68000/bootlogo-vz.h with 100% similarity]
arch/m68k/68000/bootlogo.h [moved from arch/m68k/platform/68000/bootlogo.h with 100% similarity]
arch/m68k/68000/entry.S [moved from arch/m68k/platform/68000/entry.S with 98% similarity]
arch/m68k/68000/head.S [moved from arch/m68k/platform/68000/head.S with 100% similarity]
arch/m68k/68000/ints.c [moved from arch/m68k/platform/68000/ints.c with 100% similarity]
arch/m68k/68000/m68328.c [moved from arch/m68k/platform/68000/m68328.c with 100% similarity]
arch/m68k/68000/m68EZ328.c [moved from arch/m68k/platform/68000/m68EZ328.c with 100% similarity]
arch/m68k/68000/m68VZ328.c [moved from arch/m68k/platform/68000/m68VZ328.c with 100% similarity]
arch/m68k/68000/romvec.S [moved from arch/m68k/platform/68000/romvec.S with 100% similarity]
arch/m68k/68000/timers.c [moved from arch/m68k/platform/68000/timers.c with 100% similarity]
arch/m68k/68360/Makefile [moved from arch/m68k/platform/68360/Makefile with 81% similarity]
arch/m68k/68360/commproc.c [moved from arch/m68k/platform/68360/commproc.c with 100% similarity]
arch/m68k/68360/config.c [moved from arch/m68k/platform/68360/config.c with 98% similarity]
arch/m68k/68360/entry.S [moved from arch/m68k/platform/68360/entry.S with 98% similarity]
arch/m68k/68360/head-ram.S [moved from arch/m68k/platform/68360/head-ram.S with 99% similarity]
arch/m68k/68360/head-rom.S [moved from arch/m68k/platform/68360/head-rom.S with 99% similarity]
arch/m68k/68360/ints.c [moved from arch/m68k/platform/68360/ints.c with 98% similarity]
arch/m68k/Makefile
arch/m68k/coldfire/Makefile [moved from arch/m68k/platform/coldfire/Makefile with 100% similarity]
arch/m68k/coldfire/cache.c [moved from arch/m68k/platform/coldfire/cache.c with 100% similarity]
arch/m68k/coldfire/clk.c [moved from arch/m68k/platform/coldfire/clk.c with 100% similarity]
arch/m68k/coldfire/device.c [moved from arch/m68k/platform/coldfire/device.c with 100% similarity]
arch/m68k/coldfire/dma.c [moved from arch/m68k/platform/coldfire/dma.c with 100% similarity]
arch/m68k/coldfire/dma_timer.c [moved from arch/m68k/platform/coldfire/dma_timer.c with 100% similarity]
arch/m68k/coldfire/entry.S [moved from arch/m68k/platform/coldfire/entry.S with 98% similarity]
arch/m68k/coldfire/firebee.c [moved from arch/m68k/platform/coldfire/firebee.c with 100% similarity]
arch/m68k/coldfire/gpio.c [moved from arch/m68k/platform/coldfire/gpio.c with 100% similarity]
arch/m68k/coldfire/head.S [moved from arch/m68k/platform/coldfire/head.S with 100% similarity]
arch/m68k/coldfire/intc-2.c [moved from arch/m68k/platform/coldfire/intc-2.c with 100% similarity]
arch/m68k/coldfire/intc-5249.c [moved from arch/m68k/platform/coldfire/intc-5249.c with 100% similarity]
arch/m68k/coldfire/intc-525x.c [moved from arch/m68k/platform/coldfire/intc-525x.c with 100% similarity]
arch/m68k/coldfire/intc-5272.c [moved from arch/m68k/platform/coldfire/intc-5272.c with 99% similarity]
arch/m68k/coldfire/intc-simr.c [moved from arch/m68k/platform/coldfire/intc-simr.c with 100% similarity]
arch/m68k/coldfire/intc.c [moved from arch/m68k/platform/coldfire/intc.c with 100% similarity]
arch/m68k/coldfire/m5206.c [moved from arch/m68k/platform/coldfire/m5206.c with 96% similarity]
arch/m68k/coldfire/m520x.c [moved from arch/m68k/platform/coldfire/m520x.c with 98% similarity]
arch/m68k/coldfire/m523x.c [moved from arch/m68k/platform/coldfire/m523x.c with 97% similarity]
arch/m68k/coldfire/m5249.c [moved from arch/m68k/platform/coldfire/m5249.c with 97% similarity]
arch/m68k/coldfire/m525x.c [moved from arch/m68k/platform/coldfire/m525x.c with 97% similarity]
arch/m68k/coldfire/m5272.c [moved from arch/m68k/platform/coldfire/m5272.c with 98% similarity]
arch/m68k/coldfire/m527x.c [moved from arch/m68k/platform/coldfire/m527x.c with 97% similarity]
arch/m68k/coldfire/m528x.c [moved from arch/m68k/platform/coldfire/m528x.c with 98% similarity]
arch/m68k/coldfire/m5307.c [moved from arch/m68k/platform/coldfire/m5307.c with 97% similarity]
arch/m68k/coldfire/m53xx.c [moved from arch/m68k/platform/coldfire/m53xx.c with 100% similarity]
arch/m68k/coldfire/m5407.c [moved from arch/m68k/platform/coldfire/m5407.c with 95% similarity]
arch/m68k/coldfire/m5441x.c [moved from arch/m68k/platform/coldfire/m5441x.c with 100% similarity]
arch/m68k/coldfire/m54xx.c [moved from arch/m68k/platform/coldfire/m54xx.c with 97% similarity]
arch/m68k/coldfire/mcf8390.c [moved from arch/m68k/platform/coldfire/mcf8390.c with 100% similarity]
arch/m68k/coldfire/nettel.c [moved from arch/m68k/platform/coldfire/nettel.c with 100% similarity]
arch/m68k/coldfire/pci.c [moved from arch/m68k/platform/coldfire/pci.c with 100% similarity]
arch/m68k/coldfire/pit.c [moved from arch/m68k/platform/coldfire/pit.c with 100% similarity]
arch/m68k/coldfire/reset.c [moved from arch/m68k/platform/coldfire/reset.c with 100% similarity]
arch/m68k/coldfire/sltimers.c [moved from arch/m68k/platform/coldfire/sltimers.c with 100% similarity]
arch/m68k/coldfire/timers.c [moved from arch/m68k/platform/coldfire/timers.c with 100% similarity]
arch/m68k/coldfire/vectors.c [moved from arch/m68k/platform/coldfire/vectors.c with 96% similarity]
arch/m68k/include/asm/io_no.h
arch/m68k/include/asm/m54xxpci.h
arch/m68k/platform/Makefile [deleted file]
arch/mips/kernel/ptrace.c
arch/s390/Kconfig
arch/s390/Makefile
arch/s390/include/asm/barrier.h
arch/s390/include/asm/cputime.h
arch/s390/include/asm/dis.h
arch/s390/include/asm/elf.h
arch/s390/include/asm/ftrace.h
arch/s390/include/asm/idle.h [new file with mode: 0644]
arch/s390/include/asm/ipl.h
arch/s390/include/asm/irq.h
arch/s390/include/asm/kprobes.h
arch/s390/include/asm/lowcore.h
arch/s390/include/asm/nmi.h
arch/s390/include/asm/pgtable.h
arch/s390/include/asm/processor.h
arch/s390/include/asm/ptrace.h
arch/s390/include/asm/setup.h
arch/s390/include/asm/sigp.h
arch/s390/include/asm/smp.h
arch/s390/include/asm/spinlock.h
arch/s390/include/asm/spinlock_types.h
arch/s390/include/asm/switch_to.h
arch/s390/include/asm/thread_info.h
arch/s390/include/asm/uprobes.h [new file with mode: 0644]
arch/s390/include/asm/vdso.h
arch/s390/include/asm/vtimer.h
arch/s390/include/uapi/asm/sigcontext.h
arch/s390/include/uapi/asm/types.h
arch/s390/include/uapi/asm/ucontext.h
arch/s390/kernel/Makefile
arch/s390/kernel/asm-offsets.c
arch/s390/kernel/compat_linux.h
arch/s390/kernel/compat_signal.c
arch/s390/kernel/crash_dump.c
arch/s390/kernel/dis.c
arch/s390/kernel/early.c
arch/s390/kernel/entry.h
arch/s390/kernel/entry64.S
arch/s390/kernel/ftrace.c
arch/s390/kernel/head.S
arch/s390/kernel/idle.c [new file with mode: 0644]
arch/s390/kernel/irq.c
arch/s390/kernel/kprobes.c
arch/s390/kernel/machine_kexec.c
arch/s390/kernel/mcount.S
arch/s390/kernel/mcount64.S [deleted file]
arch/s390/kernel/nmi.c
arch/s390/kernel/pgm_check.S
arch/s390/kernel/process.c
arch/s390/kernel/processor.c
arch/s390/kernel/ptrace.c
arch/s390/kernel/setup.c
arch/s390/kernel/signal.c
arch/s390/kernel/smp.c
arch/s390/kernel/time.c
arch/s390/kernel/topology.c
arch/s390/kernel/traps.c
arch/s390/kernel/uprobes.c [new file with mode: 0644]
arch/s390/kernel/vdso32/clock_getres.S
arch/s390/kernel/vdso32/clock_gettime.S
arch/s390/kernel/vdso32/gettimeofday.S
arch/s390/kernel/vdso64/clock_getres.S
arch/s390/kernel/vdso64/clock_gettime.S
arch/s390/kernel/vdso64/gettimeofday.S
arch/s390/kernel/vtime.c
arch/s390/lib/Makefile
arch/s390/lib/delay.c
arch/s390/lib/probes.c [new file with mode: 0644]
arch/s390/lib/spinlock.c
arch/s390/mm/dump_pagetables.c
arch/s390/mm/hugetlbpage.c
arch/s390/mm/pageattr.c
arch/s390/mm/vmem.c
arch/um/Kconfig.common
arch/um/drivers/net_kern.c
arch/um/drivers/ubd_kern.c
arch/um/include/asm/stacktrace.h [new file with mode: 0644]
arch/um/include/shared/mem_user.h
arch/um/kernel/Makefile
arch/um/kernel/physmem.c
arch/um/kernel/stacktrace.c [new file with mode: 0644]
arch/um/kernel/sysrq.c
arch/um/kernel/um_arch.c
arch/x86/.gitignore
arch/x86/Kconfig
arch/x86/boot/compressed/aslr.c
arch/x86/boot/mkcpustr.c
arch/x86/ia32/ia32entry.S
arch/x86/include/asm/calling.h
arch/x86/include/asm/cpufeature.h
arch/x86/include/asm/disabled-features.h [new file with mode: 0644]
arch/x86/include/asm/elf.h
arch/x86/include/asm/fpu-internal.h
arch/x86/include/asm/microcode_intel.h
arch/x86/include/asm/numa.h
arch/x86/include/asm/pgtable_32.h
arch/x86/include/asm/pgtable_64.h
arch/x86/include/asm/ptrace.h
arch/x86/kernel/apic/apic_numachip.c
arch/x86/kernel/apic/x2apic_uv_x.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpu/intel.c
arch/x86/kernel/cpu/mcheck/therm_throt.c
arch/x86/kernel/cpu/microcode/amd_early.c
arch/x86/kernel/cpu/microcode/intel.c
arch/x86/kernel/cpu/microcode/intel_early.c
arch/x86/kernel/cpu/mtrr/main.c
arch/x86/kernel/e820.c
arch/x86/kernel/entry_64.S
arch/x86/kernel/iosf_mbi.c
arch/x86/kernel/machine_kexec_32.c
arch/x86/kernel/pmc_atom.c
arch/x86/kernel/process.c
arch/x86/kernel/process_32.c
arch/x86/kernel/process_64.c
arch/x86/kernel/ptrace.c
arch/x86/kernel/quirks.c
arch/x86/kernel/setup.c
arch/x86/kernel/signal.c
arch/x86/kernel/vsyscall_64.c
arch/x86/kernel/xsave.c
arch/x86/mm/fault.c
arch/x86/mm/init_64.c
arch/x86/mm/numa.c
arch/x86/mm/pgtable_32.c
arch/x86/um/checksum_32.S
arch/x86/vdso/vdso2c.h
drivers/s390/block/dasd.c
drivers/s390/block/dasd_devmap.c
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_eckd.h
drivers/s390/block/dasd_int.h
drivers/s390/char/Kconfig
drivers/s390/char/Makefile
drivers/s390/char/diag_ftp.c [new file with mode: 0644]
drivers/s390/char/diag_ftp.h [new file with mode: 0644]
drivers/s390/char/hmcdrv_cache.c [new file with mode: 0644]
drivers/s390/char/hmcdrv_cache.h [new file with mode: 0644]
drivers/s390/char/hmcdrv_dev.c [new file with mode: 0644]
drivers/s390/char/hmcdrv_dev.h [new file with mode: 0644]
drivers/s390/char/hmcdrv_ftp.c [new file with mode: 0644]
drivers/s390/char/hmcdrv_ftp.h [new file with mode: 0644]
drivers/s390/char/hmcdrv_mod.c [new file with mode: 0644]
drivers/s390/char/sclp.h
drivers/s390/char/sclp_diag.h [new file with mode: 0644]
drivers/s390/char/sclp_early.c
drivers/s390/char/sclp_ftp.c [new file with mode: 0644]
drivers/s390/char/sclp_ftp.h [new file with mode: 0644]
drivers/s390/char/sclp_rw.c
drivers/s390/char/sclp_vt220.c
drivers/s390/char/tape_char.c
drivers/s390/char/zcore.c
drivers/s390/cio/airq.c
drivers/s390/cio/cio.c
drivers/s390/crypto/ap_bus.c
drivers/s390/crypto/ap_bus.h
drivers/s390/crypto/zcrypt_api.c
include/linux/pci_ids.h
include/linux/seccomp.h
include/linux/tick.h
include/uapi/linux/elf.h
kernel/seccomp.c
kernel/time/tick-sched.c
mm/page_alloc.c
scripts/recordmcount.c
scripts/recordmcount.pl

index 4bbeca8483ed339f7efd5b6314da77f9b4a99f0d..4227ec2e3ab21c13dd6e07342e264e257005a2a0 100644 (file)
@@ -300,6 +300,7 @@ architectures:
 - arm
 - ppc
 - mips
+- s390
 
 3. Configuring Kprobes
 
index afe68ddbe6a474667aac1684367274754a0189fd..052ee643a32ee2c9c44cc75af6abeb9bd97040d5 100644 (file)
@@ -5,7 +5,7 @@ Virtual memory map with 4 level page tables:
 
 0000000000000000 - 00007fffffffffff (=47 bits) user space, different per mm
 hole caused by [48:63] sign extension
-ffff800000000000 - ffff80ffffffffff (=40 bits) guard hole
+ffff800000000000 - ffff87ffffffffff (=43 bits) guard hole, reserved for hypervisor
 ffff880000000000 - ffffc7ffffffffff (=64 TB) direct mapping of all phys. memory
 ffffc80000000000 - ffffc8ffffffffff (=40 bits) hole
 ffffc90000000000 - ffffe8ffffffffff (=45 bits) vmalloc/ioremap space
index 0eae9df35b884190f7f988702c64158b9a66cda0..05d7a8a458d5850c181e527c2039904c66239de5 100644 (file)
@@ -323,6 +323,17 @@ config HAVE_ARCH_SECCOMP_FILTER
            results in the system call being skipped immediately.
          - seccomp syscall wired up
 
+         For best performance, an arch should use seccomp_phase1 and
+         seccomp_phase2 directly.  It should call seccomp_phase1 for all
+         syscalls if TIF_SECCOMP is set, but seccomp_phase1 does not
+         need to be called from a ptrace-safe context.  It must then
+         call seccomp_phase2 if seccomp_phase1 returns anything other
+         than SECCOMP_PHASE1_OK or SECCOMP_PHASE1_SKIP.
+
+         As an additional optimization, an arch may provide seccomp_data
+         directly to seccomp_phase1; this avoids multiple calls
+         to the syscall_xyz helpers for every syscall.
+
 config SECCOMP_FILTER
        def_bool y
        depends on HAVE_ARCH_SECCOMP_FILTER && SECCOMP && NET
index 0c27ed6f3f2346e9bd9c13a8cea1265536572ba5..5e772a21ab9707916b82cb4d2a42d24fcb1bf878 100644 (file)
@@ -933,8 +933,13 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs, int scno)
        current_thread_info()->syscall = scno;
 
        /* Do the secure computing check first; failures should be fast. */
-       if (secure_computing(scno) == -1)
+#ifdef CONFIG_HAVE_ARCH_SECCOMP_FILTER
+       if (secure_computing() == -1)
                return -1;
+#else
+       /* XXX: remove this once OABI gets fixed */
+       secure_computing_strict(scno);
+#endif
 
        if (test_thread_flag(TIF_SYSCALL_TRACE))
                tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER);
index 10a14ead70b9d9fd627b416c8567008d1aebc606..f3b51b57740af91e097a7b4b37b4067b5873cd44 100644 (file)
@@ -11,7 +11,7 @@
 
 
 
-#define NR_syscalls                    317 /* length of syscall table */
+#define NR_syscalls                    318 /* length of syscall table */
 
 /*
  * The following defines stop scripts/checksyscalls.sh from complaining about
index 18026b2eb5823c86ab0455088e9b3b1b0c409393..4c2240c1b0cb4b81e219631750c4e61f82ffb750 100644 (file)
 #define __NR_renameat2                 1338
 #define __NR_getrandom                 1339
 #define __NR_memfd_create              1340
+#define __NR_bpf                       1341
 
 #endif /* _UAPI_ASM_IA64_UNISTD_H */
index 01edf242eb296443293fc8b1ee178d72d0a89f55..f5e96dffc63c3d0ce54399759ceb9a5fefacde15 100644 (file)
@@ -1778,6 +1778,7 @@ sys_call_table:
        data8 sys_renameat2
        data8 sys_getrandom
        data8 sys_memfd_create                  // 1340
+       data8 sys_bpf
 
        .org sys_call_table + 8*NR_syscalls     // guard against failures to increase NR_syscalls
 #endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */
similarity index 98%
rename from arch/m68k/platform/68000/entry.S
rename to arch/m68k/68000/entry.S
index 23ac054c6e1ad929fa40e8aa033e51251c96538d..259b3661b614168ff8ab377587c66b1478222218 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  linux/arch/m68knommu/platform/68328/entry.S
+ *  entry.S -- non-mmu 68000 interrupt and exception entry points
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *
similarity index 81%
rename from arch/m68k/platform/68360/Makefile
rename to arch/m68k/68360/Makefile
index f6f43438304935908f59705dfa24ae7f174e29cb..591ce42df3def52cf03b27d3e3e5794fe6a6d16a 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Makefile for arch/m68knommu/platform/68360.
+# Makefile for 68360 machines.
 #
 model-y                          := ram
 model-$(CONFIG_ROMKERNEL) := rom
similarity index 98%
rename from arch/m68k/platform/68360/config.c
rename to arch/m68k/68360/config.c
index d493ac43fe3f900fe1b6ecd999e3452e96bdbfd3..17ec416fed9db5e8380d710f4d3b821599ca5da2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  linux/arch/m68knommu/platform/68360/config.c
+ *  config.c - non-mmu 68360 platform initialization code
  *
  *  Copyright (c) 2000 Michael Leslie <mleslie@lineo.com>
  *  Copyright (C) 1993 Hamish Macdonald
similarity index 98%
rename from arch/m68k/platform/68360/entry.S
rename to arch/m68k/68360/entry.S
index 447c33ef37fda3456b5fad22d705f123c91b4f84..22eb3022f9ee83f449e313a7715845df8b52bdad 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  linux/arch/m68knommu/platform/68360/entry.S
+ *  entry.S - non-mmu 68360 interrupt and exceptions entry points
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *  Copyright (C) 2001 SED Systems, a Division of Calian Ltd.
similarity index 99%
rename from arch/m68k/platform/68360/head-ram.S
rename to arch/m68k/68360/head-ram.S
index acd213170d80fe6ae1e74cddd2fcbd90c7b65115..62bc56f41d572311e4846aa28ed374f64631bba8 100644 (file)
@@ -1,6 +1,5 @@
-/* arch/m68knommu/platform/68360/head-ram.S
- *
- * Startup code for Motorola 68360
+/*
+ * head-ram.S - startup code for Motorola 68360
  *
  * Copyright 2001 (C) SED Systems, a Division of Calian Ltd.
  * Based on: arch/m68knommu/platform/68328/pilot/crt0_rom.S
similarity index 99%
rename from arch/m68k/platform/68360/head-rom.S
rename to arch/m68k/68360/head-rom.S
index dfc756d998861823e48ac2b87a291ea7d04cbbb2..b3a7e40f35e1eecfd17b641a29e042bb15f5a5e8 100644 (file)
@@ -1,6 +1,5 @@
-/* arch/m68knommu/platform/68360/head-rom.S
- *
- * Startup code for Motorola 68360
+/*
+ * head-rom.S - startup code for Motorola 68360
  *
  * Copyright (C) SED Systems, a Division of Calian Ltd.
  * Based on: arch/m68knommu/platform/68328/pilot/crt0_rom.S
similarity index 98%
rename from arch/m68k/platform/68360/ints.c
rename to arch/m68k/68360/ints.c
index 8cd42692331b8d3b6f1f2052dc3f563181917cd4..2360fc046681d72caf89114720ec92b53db351e1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/arch/$(ARCH)/platform/$(PLATFORM)/ints.c
+ * ints.c - first level interrupt handlers
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file COPYING in the main directory of this archive
index 7f7830f2c5bcb488745c0326e36a1889a733e04b..0b29dcfef69f339407880ac42d42d5d873d2e032 100644 (file)
@@ -92,9 +92,9 @@ endif
 #
 head-y                         := arch/m68k/kernel/head.o
 head-$(CONFIG_SUN3)            := arch/m68k/kernel/sun3-head.o
-head-$(CONFIG_M68360)          := arch/m68k/platform/68360/head.o
-head-$(CONFIG_M68000)          := arch/m68k/platform/68000/head.o
-head-$(CONFIG_COLDFIRE)                := arch/m68k/platform/coldfire/head.o
+head-$(CONFIG_M68360)          := arch/m68k/68360/head.o
+head-$(CONFIG_M68000)          := arch/m68k/68000/head.o
+head-$(CONFIG_COLDFIRE)                := arch/m68k/coldfire/head.o
 
 core-y                         += arch/m68k/kernel/    arch/m68k/mm/
 libs-y                         += arch/m68k/lib/
@@ -114,9 +114,9 @@ core-$(CONFIG_NATFEAT)              += arch/m68k/emu/
 core-$(CONFIG_M68040)          += arch/m68k/fpsp040/
 core-$(CONFIG_M68060)          += arch/m68k/ifpsp060/
 core-$(CONFIG_M68KFPU_EMU)     += arch/m68k/math-emu/
-core-$(CONFIG_M68360)          += arch/m68k/platform/68360/
-core-$(CONFIG_M68000)          += arch/m68k/platform/68000/
-core-$(CONFIG_COLDFIRE)                += arch/m68k/platform/coldfire/
+core-$(CONFIG_M68360)          += arch/m68k/68360/
+core-$(CONFIG_M68000)          += arch/m68k/68000/
+core-$(CONFIG_COLDFIRE)                += arch/m68k/coldfire/
 
 
 all:   zImage
similarity index 98%
rename from arch/m68k/platform/coldfire/entry.S
rename to arch/m68k/coldfire/entry.S
index 881ab8e379d4c68a42854b372fb906ef8f32d07c..52d312d5b4d4f68337aa8f9b711f50b1a1ad9eda 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  linux/arch/m68knommu/platform/5307/entry.S
+ *  entry.S  -- interrupt and exception processing for ColdFire
  *
  *  Copyright (C) 1999-2007, Greg Ungerer (gerg@snapgear.com)
  *  Copyright (C) 1998  D. Jeff Dionne <jeff@lineo.ca>,
similarity index 99%
rename from arch/m68k/platform/coldfire/intc-5272.c
rename to arch/m68k/coldfire/intc-5272.c
index d7b695629a7e3e2014a38189bf71d7bc403bcc1e..d1e2fbad327cecaa4c785e4b270177a6c030cbb5 100644 (file)
@@ -36,7 +36,7 @@
  * they also need acknowledging via acknowledge bits.
  */
 struct irqmap {
-       unsigned char   icr;
+       unsigned int    icr;
        unsigned char   index;
        unsigned char   ack;
 };
similarity index 96%
rename from arch/m68k/platform/coldfire/m5206.c
rename to arch/m68k/coldfire/m5206.c
index 0e55f449a88c445f47d51e289599ad76349e5648..8945f5e7b39c6dc05224beca10135440c684e1a4 100644 (file)
@@ -1,7 +1,7 @@
 /***************************************************************************/
 
 /*
- *     linux/arch/m68knommu/platform/5206/config.c
+ *     m5206.c  -- platform support for ColdFire 5206 based boards
  *
  *     Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
  *     Copyright (C) 2000-2001, Lineo Inc. (www.lineo.com) 
similarity index 98%
rename from arch/m68k/platform/coldfire/m520x.c
rename to arch/m68k/coldfire/m520x.c
index 4040a3c93733272465a015b1a1fff422983972f7..173834f251ebe96ea6ab9316bd31ce4054a476a6 100644 (file)
@@ -1,7 +1,7 @@
 /***************************************************************************/
 
 /*
- *  linux/arch/m68knommu/platform/520x/config.c
+ *  m520x.c  -- platform support for ColdFire 520x based boards
  *
  *  Copyright (C) 2005,      Freescale (www.freescale.com)
  *  Copyright (C) 2005,      Intec Automation (mike@steroidmicros.com)
similarity index 97%
rename from arch/m68k/platform/coldfire/m523x.c
rename to arch/m68k/coldfire/m523x.c
index 6b7135e6d5b42ffa08411becd33b7c451ce305aa..a191a467eff276a3f2a4a8027592f0c2e09fc9c3 100644 (file)
@@ -1,7 +1,7 @@
 /***************************************************************************/
 
 /*
- *     linux/arch/m68knommu/platform/523x/config.c
+ *     m523x.c  -- platform support for ColdFire 523x based boards
  *
  *     Sub-architcture dependent initialization code for the Freescale
  *     523x CPUs.
similarity index 97%
rename from arch/m68k/platform/coldfire/m5249.c
rename to arch/m68k/coldfire/m5249.c
index f6253a3313b3861681308c41f3a069c882ceb7f8..e48f55adc44777bcd6b7c6df456173064e7395b8 100644 (file)
@@ -1,7 +1,7 @@
 /***************************************************************************/
 
 /*
- *     linux/arch/m68knommu/platform/5249/config.c
+ *     m5249.c  -- platform support for ColdFire 5249 based boards
  *
  *     Copyright (C) 2002, Greg Ungerer (gerg@snapgear.com)
  */
similarity index 97%
rename from arch/m68k/platform/coldfire/m525x.c
rename to arch/m68k/coldfire/m525x.c
index 1adba3909035170b6f57be9a7d5b4589ae83f099..3d8583e2187c5bf135685cf5a325852e721823e1 100644 (file)
@@ -1,7 +1,7 @@
 /***************************************************************************/
 
 /*
- *     525x.c
+ *     525x.c  -- platform support for ColdFire 525x based boards
  *
  *     Copyright (C) 2012, Steven King <sfking@fdwdc.com>
  */
similarity index 98%
rename from arch/m68k/platform/coldfire/m5272.c
rename to arch/m68k/coldfire/m5272.c
index 8a4d3cc322c60126a5f92b9fa337e58ba38f45fe..b15219ed22bf5d61ab34392040826fc6823cab6e 100644 (file)
@@ -1,7 +1,7 @@
 /***************************************************************************/
 
 /*
- *     linux/arch/m68knommu/platform/5272/config.c
+ *     m5272.c  -- platform support for ColdFire 5272 based boards
  *
  *     Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
  *     Copyright (C) 2001-2002, SnapGear Inc. (www.snapgear.com)
similarity index 97%
rename from arch/m68k/platform/coldfire/m527x.c
rename to arch/m68k/coldfire/m527x.c
index 62d81ef016f1742081b35d2ce534a9b2eabcfa09..2ba470735bed0bc20486adaba2546853b0d9c344 100644 (file)
@@ -1,10 +1,10 @@
 /***************************************************************************/
 
 /*
- *     linux/arch/m68knommu/platform/527x/config.c
+ *     m527x.c  -- platform support for ColdFire 527x based boards
  *
  *     Sub-architcture dependent initialization code for the Freescale
- *     5270/5271 CPUs.
+ *     5270/5271 and 5274/5275 CPUs.
  *
  *     Copyright (C) 1999-2004, Greg Ungerer (gerg@snapgear.com)
  *     Copyright (C) 2001-2004, SnapGear Inc. (www.snapgear.com)
similarity index 98%
rename from arch/m68k/platform/coldfire/m528x.c
rename to arch/m68k/coldfire/m528x.c
index 21cd161d36f19d570a693bb6d315d56846416f6d..45e947aeade4a3f0e01807c9b4fb4d5ac64dfe75 100644 (file)
@@ -1,7 +1,7 @@
 /***************************************************************************/
 
 /*
- *     linux/arch/m68knommu/platform/528x/config.c
+ *     m528x.c  -- platform support for ColdFire 528x based boards
  *
  *     Sub-architcture dependent initialization code for the Freescale
  *     5280, 5281 and 5282 CPUs.
similarity index 97%
rename from arch/m68k/platform/coldfire/m5307.c
rename to arch/m68k/coldfire/m5307.c
index 887435361386fb7e4cd5d831de2816bcd0948e45..2da1d146e344aee94a712eb624efd40c5cc1952c 100644 (file)
@@ -1,7 +1,7 @@
 /***************************************************************************/
 
 /*
- *     linux/arch/m68knommu/platform/5307/config.c
+ *     m5307.c  -- platform support for ColdFire 5307 based boards
  *
  *     Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
  *     Copyright (C) 2000, Lineo (www.lineo.com)
similarity index 95%
rename from arch/m68k/platform/coldfire/m5407.c
rename to arch/m68k/coldfire/m5407.c
index 2fb3cdbfde30164e11bf7aa5341b48309681621f..738eba6be40ecadb0f0238b752c00d9415c8228a 100644 (file)
@@ -1,7 +1,7 @@
 /***************************************************************************/
 
 /*
- *     linux/arch/m68knommu/platform/5407/config.c
+ *     m5407.c  -- platform support for ColdFire 5407 based boards
  *
  *     Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
  *     Copyright (C) 2000, Lineo (www.lineo.com)
similarity index 97%
rename from arch/m68k/platform/coldfire/m54xx.c
rename to arch/m68k/coldfire/m54xx.c
index 952da53aa0bcd166f1c6fc7c972bb12b46c5f39b..075aaabd136026a408ee4560ee4870127c6b1b9d 100644 (file)
@@ -1,7 +1,7 @@
 /***************************************************************************/
 
 /*
- *     linux/arch/m68knommu/platform/54xx/config.c
+ *     m54xx.c  -- platform support for ColdFire 54xx based boards
  *
  *     Copyright (C) 2010, Philippe De Muyter <phdm@macqel.be>
  */
@@ -23,7 +23,6 @@
 #include <asm/mcfuart.h>
 #include <asm/mcfclk.h>
 #include <asm/m54xxgpt.h>
-#include <asm/mcfclk.h>
 #ifdef CONFIG_MMU
 #include <asm/mmu_context.h>
 #endif
similarity index 96%
rename from arch/m68k/platform/coldfire/vectors.c
rename to arch/m68k/coldfire/vectors.c
index a4dbdecbec7a0a6266e664839aeb3b118720a1e1..08923fe600e013d95610376959016e77064f3f91 100644 (file)
@@ -1,7 +1,7 @@
 /***************************************************************************/
 
 /*
- *     linux/arch/m68knommu/platform/coldfire/vectors.c
+ *     vectors.c  -- high level trap setup for ColdFire
  *
  *     Copyright (C) 1999-2007, Greg Ungerer <gerg@snapgear.com>
  */
index 52f7e8499172e101b5ba3d925c9d9d9694c325c1..be4b5a813ad401972624886802f5f69aa047e7dc 100644 (file)
@@ -179,6 +179,15 @@ static inline void *ioremap_fullcache(unsigned long physaddr, unsigned long size
  */
 #define xlate_dev_kmem_ptr(p)  p
 
+static inline void __iomem *ioport_map(unsigned long port, unsigned int nr)
+{
+       return (void __iomem *) port;
+}
+
+static inline void ioport_unmap(void __iomem *p)
+{
+}
+
 #endif /* __KERNEL__ */
 
 #endif /* _M68KNOMMU_IO_H */
index 6fbf54f72f2e0a5cc27b7b29207e68e2d702826c..4687f5aa374170c5780fb1f817e08770654f303d 100644 (file)
@@ -72,7 +72,7 @@
 #define        PCIRFWPR        (CONFIG_MBAR + 0x84d4)  /* RX FIFO write pointer */
 
 #define        PACR            (CONFIG_MBAR + 0xc00)   /* PCI arbiter control */
-#define        PASR            (COFNIG_MBAR + 0xc04)   /* PCI arbiter status */
+#define        PASR            (CONFIG_MBAR + 0xc04)   /* PCI arbiter status */
 
 /*
  *     Definitions for the Global status and control register.
diff --git a/arch/m68k/platform/Makefile b/arch/m68k/platform/Makefile
deleted file mode 100644 (file)
index fc932bf..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#
-# Makefile for the arch/m68knommu/platform.
-#
index 645b3c4fcfba9ae747f378a54fcbaf797103492b..f7aac5b57b4b8e29470d0d2dd5ee37db4523398e 100644 (file)
@@ -770,7 +770,7 @@ asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall)
        long ret = 0;
        user_exit();
 
-       if (secure_computing(syscall) == -1)
+       if (secure_computing() == -1)
                return -1;
 
        if (test_thread_flag(TIF_SYSCALL_TRACE) &&
index 296391395b955bb3e4ba25dc33458a55982d5546..f2cf1f90295b6b38e855b398a3e0a2180e82fe4e 100644 (file)
@@ -58,6 +58,9 @@ config NO_IOPORT_MAP
 config PCI_QUIRKS
        def_bool n
 
+config ARCH_SUPPORTS_UPROBES
+       def_bool 64BIT
+
 config S390
        def_bool y
        select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
@@ -97,6 +100,7 @@ config S390
        select ARCH_WANT_IPC_PARSE_VERSION
        select BUILDTIME_EXTABLE_SORT
        select CLONE_BACKWARDS2
+       select DYNAMIC_FTRACE if FUNCTION_TRACER
        select GENERIC_CLOCKEVENTS
        select GENERIC_CPU_DEVICES if !SMP
        select GENERIC_FIND_FIRST_BIT
@@ -113,10 +117,11 @@ config S390
        select HAVE_CMPXCHG_LOCAL
        select HAVE_C_RECORDMCOUNT
        select HAVE_DEBUG_KMEMLEAK
-       select HAVE_DYNAMIC_FTRACE
+       select HAVE_DYNAMIC_FTRACE if 64BIT
+       select HAVE_DYNAMIC_FTRACE_WITH_REGS if 64BIT
        select HAVE_FTRACE_MCOUNT_RECORD
-       select HAVE_FUNCTION_GRAPH_TRACER
-       select HAVE_FUNCTION_TRACER
+       select HAVE_FUNCTION_GRAPH_TRACER if 64BIT
+       select HAVE_FUNCTION_TRACER if 64BIT
        select HAVE_FUTEX_CMPXCHG if FUTEX
        select HAVE_KERNEL_BZIP2
        select HAVE_KERNEL_GZIP
index 874e6d6e9c5fe41e035f4fafb08f0cba44f92760..878e67973151b54c93c5eb078d53a4beef330f10 100644 (file)
@@ -35,13 +35,16 @@ endif
 
 export LD_BFD
 
-cflags-$(CONFIG_MARCH_G5)     += -march=g5
-cflags-$(CONFIG_MARCH_Z900)   += -march=z900
-cflags-$(CONFIG_MARCH_Z990)   += -march=z990
-cflags-$(CONFIG_MARCH_Z9_109) += -march=z9-109
-cflags-$(CONFIG_MARCH_Z10)    += -march=z10
-cflags-$(CONFIG_MARCH_Z196)   += -march=z196
-cflags-$(CONFIG_MARCH_ZEC12)  += -march=zEC12
+mflags-$(CONFIG_MARCH_G5)     := -march=g5
+mflags-$(CONFIG_MARCH_Z900)   := -march=z900
+mflags-$(CONFIG_MARCH_Z990)   := -march=z990
+mflags-$(CONFIG_MARCH_Z9_109) := -march=z9-109
+mflags-$(CONFIG_MARCH_Z10)    := -march=z10
+mflags-$(CONFIG_MARCH_Z196)   := -march=z196
+mflags-$(CONFIG_MARCH_ZEC12)  := -march=zEC12
+
+aflags-y += $(mflags-y)
+cflags-y += $(mflags-y)
 
 cflags-$(CONFIG_MARCH_G5_TUNE)         += -mtune=g5
 cflags-$(CONFIG_MARCH_Z900_TUNE)       += -mtune=z900
index 19ff956b752baf751380e1ecf553b8983cdad56d..b5dce6544d76e3357e4e8629333817008a0ee183 100644 (file)
 
 #ifdef CONFIG_HAVE_MARCH_Z196_FEATURES
 /* Fast-BCR without checkpoint synchronization */
-#define mb() do {  asm volatile("bcr 14,0" : : : "memory"); } while (0)
+#define __ASM_BARRIER "bcr 14,0\n"
 #else
-#define mb() do {  asm volatile("bcr 15,0" : : : "memory"); } while (0)
+#define __ASM_BARRIER "bcr 15,0\n"
 #endif
 
+#define mb() do {  asm volatile(__ASM_BARRIER : : : "memory"); } while (0)
+
 #define rmb()                          mb()
 #define wmb()                          mb()
 #define read_barrier_depends()         do { } while(0)
index 3001887f94b7a7c31ca01051db3f3cf9643e3ad0..f8c196984853e963c6e22dc6553b5f4cccdc2d23 100644 (file)
@@ -8,8 +8,6 @@
 #define _S390_CPUTIME_H
 
 #include <linux/types.h>
-#include <linux/percpu.h>
-#include <linux/spinlock.h>
 #include <asm/div64.h>
 
 
@@ -167,28 +165,8 @@ static inline clock_t cputime64_to_clock_t(cputime64_t cputime)
        return clock;
 }
 
-struct s390_idle_data {
-       int nohz_delay;
-       unsigned int sequence;
-       unsigned long long idle_count;
-       unsigned long long idle_time;
-       unsigned long long clock_idle_enter;
-       unsigned long long clock_idle_exit;
-       unsigned long long timer_idle_enter;
-       unsigned long long timer_idle_exit;
-};
+cputime64_t arch_cpu_idle_time(int cpu);
 
-DECLARE_PER_CPU(struct s390_idle_data, s390_idle);
-
-cputime64_t s390_get_idle_time(int cpu);
-
-#define arch_idle_time(cpu) s390_get_idle_time(cpu)
-
-static inline int s390_nohz_delay(int cpu)
-{
-       return __get_cpu_var(s390_idle).nohz_delay != 0;
-}
-
-#define arch_needs_cpu(cpu) s390_nohz_delay(cpu)
+#define arch_idle_time(cpu) arch_cpu_idle_time(cpu)
 
 #endif /* _S390_CPUTIME_H */
index 04a83f5773cd5638959c8d7187a4c0043ffca190..60323c21938bb5d97407e9f0cb35c6fcdd335597 100644 (file)
 #define OPERAND_FPR    0x2     /* Operand printed as %fx */
 #define OPERAND_AR     0x4     /* Operand printed as %ax */
 #define OPERAND_CR     0x8     /* Operand printed as %cx */
-#define OPERAND_DISP   0x10    /* Operand printed as displacement */
-#define OPERAND_BASE   0x20    /* Operand printed as base register */
-#define OPERAND_INDEX  0x40    /* Operand printed as index register */
-#define OPERAND_PCREL  0x80    /* Operand printed as pc-relative symbol */
-#define OPERAND_SIGNED 0x100   /* Operand printed as signed value */
-#define OPERAND_LENGTH 0x200   /* Operand printed as length (+1) */
+#define OPERAND_VR     0x10    /* Operand printed as %vx */
+#define OPERAND_DISP   0x20    /* Operand printed as displacement */
+#define OPERAND_BASE   0x40    /* Operand printed as base register */
+#define OPERAND_INDEX  0x80    /* Operand printed as index register */
+#define OPERAND_PCREL  0x100   /* Operand printed as pc-relative symbol */
+#define OPERAND_SIGNED 0x200   /* Operand printed as signed value */
+#define OPERAND_LENGTH 0x400   /* Operand printed as length (+1) */
 
 
 struct s390_operand {
index 78f4f8711d58a78f0a3e277b13719bd1514f38ea..f6e43d39e3d82e7c86e771078b752a88f998c481 100644 (file)
 #define HWCAP_S390_ETF3EH      256
 #define HWCAP_S390_HIGH_GPRS   512
 #define HWCAP_S390_TE          1024
+#define HWCAP_S390_VXRS                2048
 
 /*
  * These are used to set parameters in the core dumps.
@@ -225,6 +226,6 @@ int arch_setup_additional_pages(struct linux_binprm *, int);
 extern unsigned long arch_randomize_brk(struct mm_struct *mm);
 #define arch_randomize_brk arch_randomize_brk
 
-void *fill_cpu_elf_notes(void *ptr, struct save_area *sa);
+void *fill_cpu_elf_notes(void *ptr, struct save_area *sa, __vector128 *vxrs);
 
 #endif
index bf246dae1367333c109f7f28a60789c2f97deb84..3aef8afec336c822e2f3f44b76209e510ab510e0 100644 (file)
@@ -4,6 +4,7 @@
 #ifndef __ASSEMBLY__
 
 extern void _mcount(void);
+extern char ftrace_graph_caller_end;
 
 struct dyn_arch_ftrace { };
 
@@ -17,10 +18,8 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 
 #endif /* __ASSEMBLY__ */
 
-#ifdef CONFIG_64BIT
-#define MCOUNT_INSN_SIZE  12
-#else
-#define MCOUNT_INSN_SIZE  22
-#endif
+#define MCOUNT_INSN_SIZE  18
+
+#define ARCH_SUPPORTS_FTRACE_OPS 1
 
 #endif /* _ASM_S390_FTRACE_H */
diff --git a/arch/s390/include/asm/idle.h b/arch/s390/include/asm/idle.h
new file mode 100644 (file)
index 0000000..6af037f
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ *  Copyright IBM Corp. 2014
+ *
+ *  Author: Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+
+#ifndef _S390_IDLE_H
+#define _S390_IDLE_H
+
+#include <linux/types.h>
+#include <linux/device.h>
+
+struct s390_idle_data {
+       unsigned int sequence;
+       unsigned long long idle_count;
+       unsigned long long idle_time;
+       unsigned long long clock_idle_enter;
+       unsigned long long clock_idle_exit;
+       unsigned long long timer_idle_enter;
+       unsigned long long timer_idle_exit;
+};
+
+extern struct device_attribute dev_attr_idle_count;
+extern struct device_attribute dev_attr_idle_time_us;
+
+#endif /* _S390_IDLE_H */
index c81661e756a0396bb8e90dee214492b154081d91..ece606c2ee8674111b81bf9c5a6342e8ae5db421 100644 (file)
@@ -89,12 +89,12 @@ extern u32 ipl_flags;
 extern u32 dump_prefix_page;
 
 struct dump_save_areas {
-       struct save_area **areas;
+       struct save_area_ext **areas;
        int count;
 };
 
 extern struct dump_save_areas dump_save_areas;
-struct save_area *dump_save_area_create(int cpu);
+struct save_area_ext *dump_save_area_create(int cpu);
 
 extern void do_reipl(void);
 extern void do_halt(void);
index c4dd400a27917b7fa38a4e6daf66d91b5e88e688..e787cc1bff8fa30874358e069ecbeb1a8b136b10 100644 (file)
@@ -51,6 +51,7 @@ enum interruption_class {
        IRQEXT_CMS,
        IRQEXT_CMC,
        IRQEXT_CMR,
+       IRQEXT_FTP,
        IRQIO_CIO,
        IRQIO_QAI,
        IRQIO_DAS,
index 4176dfe0fba1c75ed253966ecab56eeea54c174b..98629173ce3b38bf07b07324df8515b1c5e285ad 100644 (file)
@@ -84,6 +84,10 @@ int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
 int kprobe_exceptions_notify(struct notifier_block *self,
        unsigned long val, void *data);
 
+int probe_is_prohibited_opcode(u16 *insn);
+int probe_get_fixup_type(u16 *insn);
+int probe_is_insn_relative_long(u16 *insn);
+
 #define flush_insn_slot(p)     do { } while (0)
 
 #endif /* _ASM_S390_KPROBES_H */
index 4349197ab9df9019ea5a23938f4b473e8d95442f..6cc51fe844108d712285ddfeb7b970a2f33d8329 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/types.h>
 #include <asm/ptrace.h>
 #include <asm/cpu.h>
+#include <asm/types.h>
 
 #ifdef CONFIG_32BIT
 
@@ -31,6 +32,11 @@ struct save_area {
        u32     ctrl_regs[16];
 } __packed;
 
+struct save_area_ext {
+       struct save_area        sa;
+       __vector128             vx_regs[32];
+};
+
 struct _lowcore {
        psw_t   restart_psw;                    /* 0x0000 */
        psw_t   restart_old_psw;                /* 0x0008 */
@@ -183,6 +189,11 @@ struct save_area {
        u64     ctrl_regs[16];
 } __packed;
 
+struct save_area_ext {
+       struct save_area        sa;
+       __vector128             vx_regs[32];
+};
+
 struct _lowcore {
        __u8    pad_0x0000[0x0014-0x0000];      /* 0x0000 */
        __u32   ipl_parmblock_ptr;              /* 0x0014 */
@@ -310,7 +321,10 @@ struct _lowcore {
 
        /* Extended facility list */
        __u64   stfle_fac_list[32];             /* 0x0f00 */
-       __u8    pad_0x1000[0x11b8-0x1000];      /* 0x1000 */
+       __u8    pad_0x1000[0x11b0-0x1000];      /* 0x1000 */
+
+       /* Pointer to vector register save area */
+       __u64   vector_save_area_addr;          /* 0x11b0 */
 
        /* 64 bit extparam used for pfault/diag 250: defined by architecture */
        __u64   ext_params2;                    /* 0x11B8 */
@@ -334,9 +348,10 @@ struct _lowcore {
 
        /* Transaction abort diagnostic block */
        __u8    pgm_tdb[256];                   /* 0x1800 */
+       __u8    pad_0x1900[0x1c00-0x1900];      /* 0x1900 */
 
-       /* align to the top of the prefix area */
-       __u8    pad_0x1900[0x2000-0x1900];      /* 0x1900 */
+       /* Software defined save area for vector registers */
+       __u8    vector_save_area[1024];         /* 0x1c00 */
 } __packed;
 
 #endif /* CONFIG_32BIT */
index 35f8ec185616f07a1485b1bd7085133d3f299d07..3027a5a72b748ab776d1693df011da55a2049ea1 100644 (file)
@@ -38,7 +38,7 @@ struct mci {
        __u32 pm :  1; /* 22 psw program mask and cc validity */
        __u32 ia :  1; /* 23 psw instruction address validity */
        __u32 fa :  1; /* 24 failing storage address validity */
-       __u32    :  1; /* 25 */
+       __u32 vr :  1; /* 25 vector register validity */
        __u32 ec :  1; /* 26 external damage code validity */
        __u32 fp :  1; /* 27 floating point register validity */
        __u32 gr :  1; /* 28 general register validity */
index b7054356cc9843ba4e80d17bc38614614f3361e3..57c882761deaa2e543342e5bb68cdb5524851eef 100644 (file)
@@ -217,7 +217,6 @@ extern unsigned long MODULES_END;
  */
 
 /* Hardware bits in the page table entry */
-#define _PAGE_CO       0x100           /* HW Change-bit override */
 #define _PAGE_PROTECT  0x200           /* HW read-only bit  */
 #define _PAGE_INVALID  0x400           /* HW invalid bit    */
 #define _PAGE_LARGE    0x800           /* Bit to mark a large pte */
@@ -234,8 +233,8 @@ extern unsigned long MODULES_END;
 #define __HAVE_ARCH_PTE_SPECIAL
 
 /* Set of bits not changed in pte_modify */
-#define _PAGE_CHG_MASK         (PAGE_MASK | _PAGE_SPECIAL | _PAGE_CO | \
-                                _PAGE_DIRTY | _PAGE_YOUNG)
+#define _PAGE_CHG_MASK         (PAGE_MASK | _PAGE_SPECIAL | _PAGE_DIRTY | \
+                                _PAGE_YOUNG)
 
 /*
  * handle_pte_fault uses pte_present, pte_none and pte_file to find out the
@@ -354,7 +353,6 @@ extern unsigned long MODULES_END;
 
 #define _REGION3_ENTRY_LARGE   0x400   /* RTTE-format control, large page  */
 #define _REGION3_ENTRY_RO      0x200   /* page protection bit              */
-#define _REGION3_ENTRY_CO      0x100   /* change-recording override        */
 
 /* Bits in the segment table entry */
 #define _SEGMENT_ENTRY_BITS    0xfffffffffffffe33UL
@@ -371,7 +369,6 @@ extern unsigned long MODULES_END;
 #define _SEGMENT_ENTRY_YOUNG   0x1000  /* SW segment young bit */
 #define _SEGMENT_ENTRY_SPLIT   0x0800  /* THP splitting bit */
 #define _SEGMENT_ENTRY_LARGE   0x0400  /* STE-format control, large page */
-#define _SEGMENT_ENTRY_CO      0x0100  /* change-recording override   */
 #define _SEGMENT_ENTRY_READ    0x0002  /* SW segment read bit */
 #define _SEGMENT_ENTRY_WRITE   0x0001  /* SW segment write bit */
 
@@ -873,8 +870,6 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
                pgste = pgste_set_pte(ptep, pgste, entry);
                pgste_set_unlock(ptep, pgste);
        } else {
-               if (!(pte_val(entry) & _PAGE_INVALID) && MACHINE_HAS_EDAT1)
-                       pte_val(entry) |= _PAGE_CO;
                *ptep = entry;
        }
 }
@@ -1044,6 +1039,22 @@ static inline void __ptep_ipte_local(unsigned long address, pte_t *ptep)
                : "=m" (*ptep) : "m" (*ptep), "a" (pto), "a" (address));
 }
 
+static inline void __ptep_ipte_range(unsigned long address, int nr, pte_t *ptep)
+{
+       unsigned long pto = (unsigned long) ptep;
+
+#ifndef CONFIG_64BIT
+       /* pto in ESA mode must point to the start of the segment table */
+       pto &= 0x7ffffc00;
+#endif
+       /* Invalidate a range of ptes + global TLB flush of the ptes */
+       do {
+               asm volatile(
+                       "       .insn rrf,0xb2210000,%2,%0,%1,0"
+                       : "+a" (address), "+a" (nr) : "a" (pto) : "memory");
+       } while (nr != 255);
+}
+
 static inline void ptep_flush_direct(struct mm_struct *mm,
                                     unsigned long address, pte_t *ptep)
 {
index e568fc8a725062f707b7875c7c4010a21bd0fcfa..d559bdb03d18325f5c5fda2e97eb0136aeb1baf3 100644 (file)
 
 #define CIF_MCCK_PENDING       0       /* machine check handling is pending */
 #define CIF_ASCE               1       /* user asce needs fixup / uaccess */
+#define CIF_NOHZ_DELAY         2       /* delay HZ disable for a tick */
 
 #define _CIF_MCCK_PENDING      (1<<CIF_MCCK_PENDING)
 #define _CIF_ASCE              (1<<CIF_ASCE)
+#define _CIF_NOHZ_DELAY                (1<<CIF_NOHZ_DELAY)
 
 
 #ifndef __ASSEMBLY__
@@ -43,6 +45,8 @@ static inline int test_cpu_flag(int flag)
        return !!(S390_lowcore.cpu_flags & (1U << flag));
 }
 
+#define arch_needs_cpu() test_cpu_flag(CIF_NOHZ_DELAY)
+
 /*
  * Default implementation of macro that returns current
  * instruction pointer ("program counter").
@@ -113,6 +117,7 @@ struct thread_struct {
        int ri_signum;
 #ifdef CONFIG_64BIT
        unsigned char trap_tdb[256];    /* Transaction abort diagnose block */
+       __vector128 *vxrs;              /* Vector register save area */
 #endif
 };
 
@@ -285,7 +290,12 @@ static inline unsigned long __rewind_psw(psw_t psw, unsigned long ilc)
        return (psw.addr - ilc) & mask;
 #endif
 }
+
+/*
+ * Function to stop a processor until the next interrupt occurs
+ */
+void enabled_wait(void);
+
 /*
  * Function to drop a processor into disabled wait state
  */
index 55d69dd7473c82db6f61855856fbd60e8c029272..be317feff7ac47fcdb0d6cd8903156c429c23255 100644 (file)
@@ -161,6 +161,12 @@ static inline long regs_return_value(struct pt_regs *regs)
        return regs->gprs[2];
 }
 
+static inline void instruction_pointer_set(struct pt_regs *regs,
+                                          unsigned long val)
+{
+       regs->psw.addr = val | PSW_ADDR_AMODE;
+}
+
 int regs_query_register_offset(const char *name);
 const char *regs_query_register_name(unsigned int offset);
 unsigned long regs_get_register(struct pt_regs *regs, unsigned int offset);
index 089a49814c505b506ed1689230a470ebfc575d03..7736fdd725953c862f3df931723ed355d8b23f8b 100644 (file)
@@ -55,8 +55,8 @@ extern void detect_memory_memblock(void);
 #define MACHINE_FLAG_LPP       (1UL << 13)
 #define MACHINE_FLAG_TOPOLOGY  (1UL << 14)
 #define MACHINE_FLAG_TE                (1UL << 15)
-#define MACHINE_FLAG_RRBM      (1UL << 16)
 #define MACHINE_FLAG_TLB_LC    (1UL << 17)
+#define MACHINE_FLAG_VX                (1UL << 18)
 
 #define MACHINE_IS_VM          (S390_lowcore.machine_flags & MACHINE_FLAG_VM)
 #define MACHINE_IS_KVM         (S390_lowcore.machine_flags & MACHINE_FLAG_KVM)
@@ -78,8 +78,8 @@ extern void detect_memory_memblock(void);
 #define MACHINE_HAS_LPP                (0)
 #define MACHINE_HAS_TOPOLOGY   (0)
 #define MACHINE_HAS_TE         (0)
-#define MACHINE_HAS_RRBM       (0)
 #define MACHINE_HAS_TLB_LC     (0)
+#define MACHINE_HAS_VX         (0)
 #else /* CONFIG_64BIT */
 #define MACHINE_HAS_IEEE       (1)
 #define MACHINE_HAS_CSP                (1)
@@ -91,8 +91,8 @@ extern void detect_memory_memblock(void);
 #define MACHINE_HAS_LPP                (S390_lowcore.machine_flags & MACHINE_FLAG_LPP)
 #define MACHINE_HAS_TOPOLOGY   (S390_lowcore.machine_flags & MACHINE_FLAG_TOPOLOGY)
 #define MACHINE_HAS_TE         (S390_lowcore.machine_flags & MACHINE_FLAG_TE)
-#define MACHINE_HAS_RRBM       (S390_lowcore.machine_flags & MACHINE_FLAG_RRBM)
 #define MACHINE_HAS_TLB_LC     (S390_lowcore.machine_flags & MACHINE_FLAG_TLB_LC)
+#define MACHINE_HAS_VX         (S390_lowcore.machine_flags & MACHINE_FLAG_VX)
 #endif /* CONFIG_64BIT */
 
 /*
index bf9c823d4020ec2549aecba28996a08d9d69fdc4..49576115dbb76da7659bdcceffca7f1452e37fdf 100644 (file)
@@ -15,6 +15,7 @@
 #define SIGP_SET_ARCHITECTURE       18
 #define SIGP_COND_EMERGENCY_SIGNAL   19
 #define SIGP_SENSE_RUNNING          21
+#define SIGP_STORE_ADDITIONAL_STATUS 23
 
 /* SIGP condition codes */
 #define SIGP_CC_ORDER_CODE_ACCEPTED 0
 
 #ifndef __ASSEMBLY__
 
-static inline int __pcpu_sigp(u16 addr, u8 order, u32 parm, u32 *status)
+static inline int __pcpu_sigp(u16 addr, u8 order, unsigned long parm,
+                             u32 *status)
 {
-       register unsigned int reg1 asm ("1") = parm;
+       register unsigned long reg1 asm ("1") = parm;
        int cc;
 
        asm volatile(
index 4f1307962a95a307d6dff37acf897abba8f7595d..762d4f88af5ae3453402e99fd216bd612e2d4377 100644 (file)
@@ -29,7 +29,6 @@ extern int smp_find_processor_id(u16 address);
 extern int smp_store_status(int cpu);
 extern int smp_vcpu_scheduled(int cpu);
 extern void smp_yield_cpu(int cpu);
-extern void smp_yield(void);
 extern void smp_cpu_set_polarization(int cpu, int val);
 extern int smp_cpu_get_polarization(int cpu);
 extern void smp_fill_possible_mask(void);
@@ -50,7 +49,6 @@ static inline int smp_find_processor_id(u16 address) { return 0; }
 static inline int smp_store_status(int cpu) { return 0; }
 static inline int smp_vcpu_scheduled(int cpu) { return 1; }
 static inline void smp_yield_cpu(int cpu) { }
-static inline void smp_yield(void) { }
 static inline void smp_fill_possible_mask(void) { }
 
 #endif /* CONFIG_SMP */
index 96879f7ad6daaebd896745a1edf08cd134e8546c..d6bdf906caa533231660113144c74861ef031e6c 100644 (file)
@@ -37,11 +37,17 @@ _raw_compare_and_swap(unsigned int *lock, unsigned int old, unsigned int new)
  * (the type definitions are in asm/spinlock_types.h)
  */
 
+void arch_lock_relax(unsigned int cpu);
+
 void arch_spin_lock_wait(arch_spinlock_t *);
 int arch_spin_trylock_retry(arch_spinlock_t *);
-void arch_spin_relax(arch_spinlock_t *);
 void arch_spin_lock_wait_flags(arch_spinlock_t *, unsigned long flags);
 
+static inline void arch_spin_relax(arch_spinlock_t *lock)
+{
+       arch_lock_relax(lock->lock);
+}
+
 static inline u32 arch_spin_lockval(int cpu)
 {
        return ~cpu;
@@ -64,11 +70,6 @@ static inline int arch_spin_trylock_once(arch_spinlock_t *lp)
                      _raw_compare_and_swap(&lp->lock, 0, SPINLOCK_LOCKVAL));
 }
 
-static inline int arch_spin_tryrelease_once(arch_spinlock_t *lp)
-{
-       return _raw_compare_and_swap(&lp->lock, SPINLOCK_LOCKVAL, 0);
-}
-
 static inline void arch_spin_lock(arch_spinlock_t *lp)
 {
        if (!arch_spin_trylock_once(lp))
@@ -91,7 +92,13 @@ static inline int arch_spin_trylock(arch_spinlock_t *lp)
 
 static inline void arch_spin_unlock(arch_spinlock_t *lp)
 {
-       arch_spin_tryrelease_once(lp);
+       typecheck(unsigned int, lp->lock);
+       asm volatile(
+               __ASM_BARRIER
+               "st     %1,%0\n"
+               : "+Q" (lp->lock)
+               : "d" (0)
+               : "cc", "memory");
 }
 
 static inline void arch_spin_unlock_wait(arch_spinlock_t *lock)
@@ -123,13 +130,12 @@ static inline void arch_spin_unlock_wait(arch_spinlock_t *lock)
  */
 #define arch_write_can_lock(x) ((x)->lock == 0)
 
-extern void _raw_read_lock_wait(arch_rwlock_t *lp);
-extern void _raw_read_lock_wait_flags(arch_rwlock_t *lp, unsigned long flags);
 extern int _raw_read_trylock_retry(arch_rwlock_t *lp);
-extern void _raw_write_lock_wait(arch_rwlock_t *lp);
-extern void _raw_write_lock_wait_flags(arch_rwlock_t *lp, unsigned long flags);
 extern int _raw_write_trylock_retry(arch_rwlock_t *lp);
 
+#define arch_read_lock_flags(lock, flags) arch_read_lock(lock)
+#define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
+
 static inline int arch_read_trylock_once(arch_rwlock_t *rw)
 {
        unsigned int old = ACCESS_ONCE(rw->lock);
@@ -144,16 +150,82 @@ static inline int arch_write_trylock_once(arch_rwlock_t *rw)
                      _raw_compare_and_swap(&rw->lock, 0, 0x80000000));
 }
 
+#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES
+
+#define __RAW_OP_OR    "lao"
+#define __RAW_OP_AND   "lan"
+#define __RAW_OP_ADD   "laa"
+
+#define __RAW_LOCK(ptr, op_val, op_string)             \
+({                                                     \
+       unsigned int old_val;                           \
+                                                       \
+       typecheck(unsigned int *, ptr);                 \
+       asm volatile(                                   \
+               op_string "     %0,%2,%1\n"             \
+               "bcr    14,0\n"                         \
+               : "=d" (old_val), "+Q" (*ptr)           \
+               : "d" (op_val)                          \
+               : "cc", "memory");                      \
+       old_val;                                        \
+})
+
+#define __RAW_UNLOCK(ptr, op_val, op_string)           \
+({                                                     \
+       unsigned int old_val;                           \
+                                                       \
+       typecheck(unsigned int *, ptr);                 \
+       asm volatile(                                   \
+               "bcr    14,0\n"                         \
+               op_string "     %0,%2,%1\n"             \
+               : "=d" (old_val), "+Q" (*ptr)           \
+               : "d" (op_val)                          \
+               : "cc", "memory");                      \
+       old_val;                                        \
+})
+
+extern void _raw_read_lock_wait(arch_rwlock_t *lp);
+extern void _raw_write_lock_wait(arch_rwlock_t *lp, unsigned int prev);
+
 static inline void arch_read_lock(arch_rwlock_t *rw)
 {
-       if (!arch_read_trylock_once(rw))
+       unsigned int old;
+
+       old = __RAW_LOCK(&rw->lock, 1, __RAW_OP_ADD);
+       if ((int) old < 0)
                _raw_read_lock_wait(rw);
 }
 
-static inline void arch_read_lock_flags(arch_rwlock_t *rw, unsigned long flags)
+static inline void arch_read_unlock(arch_rwlock_t *rw)
+{
+       __RAW_UNLOCK(&rw->lock, -1, __RAW_OP_ADD);
+}
+
+static inline void arch_write_lock(arch_rwlock_t *rw)
+{
+       unsigned int old;
+
+       old = __RAW_LOCK(&rw->lock, 0x80000000, __RAW_OP_OR);
+       if (old != 0)
+               _raw_write_lock_wait(rw, old);
+       rw->owner = SPINLOCK_LOCKVAL;
+}
+
+static inline void arch_write_unlock(arch_rwlock_t *rw)
+{
+       rw->owner = 0;
+       __RAW_UNLOCK(&rw->lock, 0x7fffffff, __RAW_OP_AND);
+}
+
+#else /* CONFIG_HAVE_MARCH_Z196_FEATURES */
+
+extern void _raw_read_lock_wait(arch_rwlock_t *lp);
+extern void _raw_write_lock_wait(arch_rwlock_t *lp);
+
+static inline void arch_read_lock(arch_rwlock_t *rw)
 {
        if (!arch_read_trylock_once(rw))
-               _raw_read_lock_wait_flags(rw, flags);
+               _raw_read_lock_wait(rw);
 }
 
 static inline void arch_read_unlock(arch_rwlock_t *rw)
@@ -169,19 +241,24 @@ static inline void arch_write_lock(arch_rwlock_t *rw)
 {
        if (!arch_write_trylock_once(rw))
                _raw_write_lock_wait(rw);
-}
-
-static inline void arch_write_lock_flags(arch_rwlock_t *rw, unsigned long flags)
-{
-       if (!arch_write_trylock_once(rw))
-               _raw_write_lock_wait_flags(rw, flags);
+       rw->owner = SPINLOCK_LOCKVAL;
 }
 
 static inline void arch_write_unlock(arch_rwlock_t *rw)
 {
-       _raw_compare_and_swap(&rw->lock, 0x80000000, 0);
+       typecheck(unsigned int, rw->lock);
+
+       rw->owner = 0;
+       asm volatile(
+               __ASM_BARRIER
+               "st     %1,%0\n"
+               : "+Q" (rw->lock)
+               : "d" (0)
+               : "cc", "memory");
 }
 
+#endif /* CONFIG_HAVE_MARCH_Z196_FEATURES */
+
 static inline int arch_read_trylock(arch_rwlock_t *rw)
 {
        if (!arch_read_trylock_once(rw))
@@ -191,12 +268,20 @@ static inline int arch_read_trylock(arch_rwlock_t *rw)
 
 static inline int arch_write_trylock(arch_rwlock_t *rw)
 {
-       if (!arch_write_trylock_once(rw))
-               return _raw_write_trylock_retry(rw);
+       if (!arch_write_trylock_once(rw) && !_raw_write_trylock_retry(rw))
+               return 0;
+       rw->owner = SPINLOCK_LOCKVAL;
        return 1;
 }
 
-#define arch_read_relax(lock)  cpu_relax()
-#define arch_write_relax(lock) cpu_relax()
+static inline void arch_read_relax(arch_rwlock_t *rw)
+{
+       arch_lock_relax(rw->owner);
+}
+
+static inline void arch_write_relax(arch_rwlock_t *rw)
+{
+       arch_lock_relax(rw->owner);
+}
 
 #endif /* __ASM_SPINLOCK_H */
index b2cd6ff7c2c5bcdad941bb91297fa64fb8908616..d84b6939237c1cc2c4f671edabbe9d062acd7d27 100644 (file)
@@ -13,6 +13,7 @@ typedef struct {
 
 typedef struct {
        unsigned int lock;
+       unsigned int owner;
 } arch_rwlock_t;
 
 #define __ARCH_RW_LOCK_UNLOCKED                { 0 }
index 18ea9e3f8142954926b8fea3afe79ce90193a4b3..2542a7e4c8b4577fa8c1081a0d372ba70e618d38 100644 (file)
@@ -103,6 +103,61 @@ static inline void restore_fp_regs(freg_t *fprs)
        asm volatile("ld 15,%0" : : "Q" (fprs[15]));
 }
 
+static inline void save_vx_regs(__vector128 *vxrs)
+{
+       typedef struct { __vector128 _[__NUM_VXRS]; } addrtype;
+
+       asm volatile(
+               "       la      1,%0\n"
+               "       .word   0xe70f,0x1000,0x003e\n" /* vstm 0,15,0(1) */
+               "       .word   0xe70f,0x1100,0x0c3e\n" /* vstm 16,31,256(1) */
+               : "=Q" (*(addrtype *) vxrs) : : "1");
+}
+
+static inline void save_vx_regs_safe(__vector128 *vxrs)
+{
+       unsigned long cr0, flags;
+
+       flags = arch_local_irq_save();
+       __ctl_store(cr0, 0, 0);
+       __ctl_set_bit(0, 17);
+       __ctl_set_bit(0, 18);
+       save_vx_regs(vxrs);
+       __ctl_load(cr0, 0, 0);
+       arch_local_irq_restore(flags);
+}
+
+static inline void restore_vx_regs(__vector128 *vxrs)
+{
+       typedef struct { __vector128 _[__NUM_VXRS]; } addrtype;
+
+       asm volatile(
+               "       la      1,%0\n"
+               "       .word   0xe70f,0x1000,0x0036\n" /* vlm 0,15,0(1) */
+               "       .word   0xe70f,0x1100,0x0c36\n" /* vlm 16,31,256(1) */
+               : : "Q" (*(addrtype *) vxrs) : "1");
+}
+
+static inline void save_fp_vx_regs(struct task_struct *task)
+{
+#ifdef CONFIG_64BIT
+       if (task->thread.vxrs)
+               save_vx_regs(task->thread.vxrs);
+       else
+#endif
+       save_fp_regs(task->thread.fp_regs.fprs);
+}
+
+static inline void restore_fp_vx_regs(struct task_struct *task)
+{
+#ifdef CONFIG_64BIT
+       if (task->thread.vxrs)
+               restore_vx_regs(task->thread.vxrs);
+       else
+#endif
+       restore_fp_regs(task->thread.fp_regs.fprs);
+}
+
 static inline void save_access_regs(unsigned int *acrs)
 {
        typedef struct { int _[NUM_ACRS]; } acrstype;
@@ -120,16 +175,16 @@ static inline void restore_access_regs(unsigned int *acrs)
 #define switch_to(prev,next,last) do {                                 \
        if (prev->mm) {                                                 \
                save_fp_ctl(&prev->thread.fp_regs.fpc);                 \
-               save_fp_regs(prev->thread.fp_regs.fprs);                \
+               save_fp_vx_regs(prev);                                  \
                save_access_regs(&prev->thread.acrs[0]);                \
                save_ri_cb(prev->thread.ri_cb);                         \
        }                                                               \
        if (next->mm) {                                                 \
+               update_cr_regs(next);                                   \
                restore_fp_ctl(&next->thread.fp_regs.fpc);              \
-               restore_fp_regs(next->thread.fp_regs.fprs);             \
+               restore_fp_vx_regs(next);                               \
                restore_access_regs(&next->thread.acrs[0]);             \
                restore_ri_cb(next->thread.ri_cb, prev->thread.ri_cb);  \
-               update_cr_regs(next);                                   \
        }                                                               \
        prev = __switch_to(prev,next);                                  \
 } while (0)
index b833e9c0bfbf2feb6e4f9dc2559e22385115e9b2..4d62fd5b56e5d13a264a1f3b691f90d282c355ac 100644 (file)
@@ -84,11 +84,13 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_SYSCALL_AUDIT      4       /* syscall auditing active */
 #define TIF_SECCOMP            5       /* secure computing */
 #define TIF_SYSCALL_TRACEPOINT 6       /* syscall tracepoint instrumentation */
+#define TIF_UPROBE             7       /* breakpointed or single-stepping */
 #define TIF_31BIT              16      /* 32bit process */
 #define TIF_MEMDIE             17      /* is terminating due to OOM killer */
 #define TIF_RESTORE_SIGMASK    18      /* restore signal mask in do_signal() */
 #define TIF_SINGLE_STEP                19      /* This task is single stepped */
 #define TIF_BLOCK_STEP         20      /* This task is block stepped */
+#define TIF_UPROBE_SINGLESTEP  21      /* This task is uprobe single stepped */
 
 #define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
@@ -97,6 +99,7 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_SYSCALL_AUDIT     (1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP           (1<<TIF_SECCOMP)
 #define _TIF_SYSCALL_TRACEPOINT        (1<<TIF_SYSCALL_TRACEPOINT)
+#define _TIF_UPROBE            (1<<TIF_UPROBE)
 #define _TIF_31BIT             (1<<TIF_31BIT)
 #define _TIF_SINGLE_STEP       (1<<TIF_SINGLE_STEP)
 
diff --git a/arch/s390/include/asm/uprobes.h b/arch/s390/include/asm/uprobes.h
new file mode 100644 (file)
index 0000000..1411dff
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ *    User-space Probes (UProbes) for s390
+ *
+ *    Copyright IBM Corp. 2014
+ *    Author(s): Jan Willeke,
+ */
+
+#ifndef _ASM_UPROBES_H
+#define _ASM_UPROBES_H
+
+#include <linux/notifier.h>
+
+typedef u16 uprobe_opcode_t;
+
+#define UPROBE_XOL_SLOT_BYTES  256 /* cache aligned */
+
+#define UPROBE_SWBP_INSN       0x0002
+#define UPROBE_SWBP_INSN_SIZE  2
+
+struct arch_uprobe {
+       union{
+               uprobe_opcode_t insn[3];
+               uprobe_opcode_t ixol[3];
+       };
+       unsigned int saved_per : 1;
+       unsigned int saved_int_code;
+};
+
+struct arch_uprobe_task {
+};
+
+int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm,
+                            unsigned long addr);
+int arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs);
+int arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs);
+bool arch_uprobe_xol_was_trapped(struct task_struct *tsk);
+int arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val,
+                                void *data);
+void arch_uprobe_abort_xol(struct arch_uprobe *ap, struct pt_regs *regs);
+unsigned long arch_uretprobe_hijack_return_addr(unsigned long trampoline,
+                                               struct pt_regs *regs);
+#endif /* _ASM_UPROBES_H */
index bc9746a7d47c53edf219c4b4b1f500bc0728a284..a62526d09201667f5d485192d9c6d081b7559060 100644 (file)
@@ -22,13 +22,17 @@ struct vdso_data {
        __u64 xtime_tod_stamp;          /* TOD clock for xtime          0x08 */
        __u64 xtime_clock_sec;          /* Kernel time                  0x10 */
        __u64 xtime_clock_nsec;         /*                              0x18 */
-       __u64 wtom_clock_sec;           /* Wall to monotonic clock      0x20 */
-       __u64 wtom_clock_nsec;          /*                              0x28 */
-       __u32 tz_minuteswest;           /* Minutes west of Greenwich    0x30 */
-       __u32 tz_dsttime;               /* Type of dst correction       0x34 */
-       __u32 ectg_available;           /* ECTG instruction present     0x38 */
-       __u32 tk_mult;                  /* Mult. used for xtime_nsec    0x3c */
-       __u32 tk_shift;                 /* Shift used for xtime_nsec    0x40 */
+       __u64 xtime_coarse_sec;         /* Coarse kernel time           0x20 */
+       __u64 xtime_coarse_nsec;        /*                              0x28 */
+       __u64 wtom_clock_sec;           /* Wall to monotonic clock      0x30 */
+       __u64 wtom_clock_nsec;          /*                              0x38 */
+       __u64 wtom_coarse_sec;          /* Coarse wall to monotonic     0x40 */
+       __u64 wtom_coarse_nsec;         /*                              0x48 */
+       __u32 tz_minuteswest;           /* Minutes west of Greenwich    0x50 */
+       __u32 tz_dsttime;               /* Type of dst correction       0x54 */
+       __u32 ectg_available;           /* ECTG instruction present     0x58 */
+       __u32 tk_mult;                  /* Mult. used for xtime_nsec    0x5c */
+       __u32 tk_shift;                 /* Shift used for xtime_nsec    0x60 */
 };
 
 struct vdso_per_cpu_data {
index bfe25d513ad26462f22fce6e66dd3f688e25c352..10a179af62d8c3f512a253752494b61c1801310f 100644 (file)
@@ -28,6 +28,4 @@ extern int del_virt_timer(struct vtimer_list *timer);
 extern void init_cpu_vtimer(void);
 extern void vtime_init(void);
 
-extern void vtime_stop_cpu(void);
-
 #endif /* _ASM_S390_TIMER_H */
index b30de9c01bbedad00c5e15ff52ffa8d19b06c824..5f0b8d7ddb0bce1ad36dd45f70ab757e5a33e99f 100644 (file)
@@ -7,10 +7,14 @@
 #define _ASM_S390_SIGCONTEXT_H
 
 #include <linux/compiler.h>
+#include <linux/types.h>
 
-#define __NUM_GPRS 16
-#define __NUM_FPRS 16
-#define __NUM_ACRS 16
+#define __NUM_GPRS             16
+#define __NUM_FPRS             16
+#define __NUM_ACRS             16
+#define __NUM_VXRS             32
+#define __NUM_VXRS_LOW         16
+#define __NUM_VXRS_HIGH                16
 
 #ifndef __s390x__
 
@@ -59,6 +63,16 @@ typedef struct
        _s390_fp_regs     fpregs;
 } _sigregs;
 
+typedef struct
+{
+#ifndef __s390x__
+       unsigned long gprs_high[__NUM_GPRS];
+#endif
+       unsigned long long vxrs_low[__NUM_VXRS_LOW];
+       __vector128 vxrs_high[__NUM_VXRS_HIGH];
+       unsigned char __reserved[128];
+} _sigregs_ext;
+
 struct sigcontext
 {
        unsigned long   oldmask[_SIGCONTEXT_NSIG_WORDS];
index 038f2b9178a4a2f159d9e289327a074e3ad0704c..3c3951e3415be0efd38b348bda8bea922b17d10a 100644 (file)
 typedef unsigned long addr_t; 
 typedef __signed__ long saddr_t;
 
+typedef struct {
+       __u32 u[4];
+} __vector128;
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _UAPI_S390_TYPES_H */
index 3e077b2a470579af0cb0827c5ba3050fa373450c..64a69aa5dde041cc733265b90aca197044d1fedb 100644 (file)
@@ -7,10 +7,15 @@
 #ifndef _ASM_S390_UCONTEXT_H
 #define _ASM_S390_UCONTEXT_H
 
-#define UC_EXTENDED    0x00000001
-
-#ifndef __s390x__
+#define UC_GPRS_HIGH   1       /* uc_mcontext_ext has valid high gprs */
+#define UC_VXRS                2       /* uc_mcontext_ext has valid vector regs */
 
+/*
+ * The struct ucontext_extended describes how the registers are stored
+ * on a rt signal frame. Please note that the structure is not fixed,
+ * if new CPU registers are added to the user state the size of the
+ * struct ucontext_extended will increase.
+ */
 struct ucontext_extended {
        unsigned long     uc_flags;
        struct ucontext  *uc_link;
@@ -19,11 +24,9 @@ struct ucontext_extended {
        sigset_t          uc_sigmask;
        /* Allow for uc_sigmask growth.  Glibc uses a 1024-bit sigset_t.  */
        unsigned char     __unused[128 - sizeof(sigset_t)];
-       unsigned long     uc_gprs_high[16];
+       _sigregs_ext      uc_mcontext_ext;
 };
 
-#endif
-
 struct ucontext {
        unsigned long     uc_flags;
        struct ucontext  *uc_link;
index a95c4ca99617e43360fb3b867ac3aefb92b374d6..204c43a4c245dd1835915adbbae39da494c2d947 100644 (file)
@@ -28,7 +28,7 @@ CFLAGS_ptrace.o               += -DUTS_MACHINE='"$(UTS_MACHINE)"'
 
 CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w
 
-obj-y  := traps.o time.o process.o base.o early.o setup.o vtime.o
+obj-y  := traps.o time.o process.o base.o early.o setup.o idle.o vtime.o
 obj-y  += processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o
 obj-y  += debug.o irq.o ipl.o dis.o diag.o sclp.o vdso.o
 obj-y  += sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o pgm_check.o
@@ -52,11 +52,9 @@ obj-$(CONFIG_COMPAT)         += compat_wrapper.o $(compat-obj-y)
 
 obj-$(CONFIG_STACKTRACE)       += stacktrace.o
 obj-$(CONFIG_KPROBES)          += kprobes.o
-obj-$(CONFIG_FUNCTION_TRACER)  += $(if $(CONFIG_64BIT),mcount64.o,mcount.o)
-obj-$(CONFIG_DYNAMIC_FTRACE)   += ftrace.o
-obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
-obj-$(CONFIG_FTRACE_SYSCALLS)  += ftrace.o
+obj-$(CONFIG_FUNCTION_TRACER)  += mcount.o ftrace.o
 obj-$(CONFIG_CRASH_DUMP)       += crash_dump.o
+obj-$(CONFIG_UPROBES)          += uprobes.o
 
 ifdef CONFIG_64BIT
 obj-$(CONFIG_PERF_EVENTS)      += perf_event.o perf_cpum_cf.o perf_cpum_sf.o \
index afe1715a4eb765cb06d1ab3277bce0b4ce8fc3c2..ef279a1368012e67fbbbbb3092783b461e1b98c0 100644 (file)
@@ -9,7 +9,7 @@
 #include <linux/kbuild.h>
 #include <linux/kvm_host.h>
 #include <linux/sched.h>
-#include <asm/cputime.h>
+#include <asm/idle.h>
 #include <asm/vdso.h>
 #include <asm/pgtable.h>
 
@@ -62,8 +62,12 @@ int main(void)
        DEFINE(__VDSO_XTIME_STAMP, offsetof(struct vdso_data, xtime_tod_stamp));
        DEFINE(__VDSO_XTIME_SEC, offsetof(struct vdso_data, xtime_clock_sec));
        DEFINE(__VDSO_XTIME_NSEC, offsetof(struct vdso_data, xtime_clock_nsec));
+       DEFINE(__VDSO_XTIME_CRS_SEC, offsetof(struct vdso_data, xtime_coarse_sec));
+       DEFINE(__VDSO_XTIME_CRS_NSEC, offsetof(struct vdso_data, xtime_coarse_nsec));
        DEFINE(__VDSO_WTOM_SEC, offsetof(struct vdso_data, wtom_clock_sec));
        DEFINE(__VDSO_WTOM_NSEC, offsetof(struct vdso_data, wtom_clock_nsec));
+       DEFINE(__VDSO_WTOM_CRS_SEC, offsetof(struct vdso_data, wtom_coarse_sec));
+       DEFINE(__VDSO_WTOM_CRS_NSEC, offsetof(struct vdso_data, wtom_coarse_nsec));
        DEFINE(__VDSO_TIMEZONE, offsetof(struct vdso_data, tz_minuteswest));
        DEFINE(__VDSO_ECTG_OK, offsetof(struct vdso_data, ectg_available));
        DEFINE(__VDSO_TK_MULT, offsetof(struct vdso_data, tk_mult));
@@ -73,8 +77,11 @@ int main(void)
        /* constants used by the vdso */
        DEFINE(__CLOCK_REALTIME, CLOCK_REALTIME);
        DEFINE(__CLOCK_MONOTONIC, CLOCK_MONOTONIC);
+       DEFINE(__CLOCK_REALTIME_COARSE, CLOCK_REALTIME_COARSE);
+       DEFINE(__CLOCK_MONOTONIC_COARSE, CLOCK_MONOTONIC_COARSE);
        DEFINE(__CLOCK_THREAD_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID);
        DEFINE(__CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC);
+       DEFINE(__CLOCK_COARSE_RES, LOW_RES_NSEC);
        BLANK();
        /* idle data offsets */
        DEFINE(__CLOCK_IDLE_ENTER, offsetof(struct s390_idle_data, clock_idle_enter));
index 70d4b7c4beaa92d1b85ec7b38373830b38aab3ee..a0a886c0497759e0338acd45157f267d57a724fb 100644 (file)
@@ -50,6 +50,14 @@ typedef struct
        _s390_fp_regs32     fpregs;
 } _sigregs32;
 
+typedef struct
+{
+       __u32 gprs_high[__NUM_GPRS];
+       __u64 vxrs_low[__NUM_VXRS_LOW];
+       __vector128 vxrs_high[__NUM_VXRS_HIGH];
+       __u8 __reserved[128];
+} _sigregs_ext32;
+
 #define _SIGCONTEXT_NSIG32     64
 #define _SIGCONTEXT_NSIG_BPW32 32
 #define __SIGNAL_FRAMESIZE32   96
@@ -72,6 +80,7 @@ struct ucontext32 {
        compat_sigset_t         uc_sigmask;
        /* Allow for uc_sigmask growth.  Glibc uses a 1024-bit sigset_t.  */
        unsigned char           __unused[128 - sizeof(compat_sigset_t)];
+       _sigregs_ext32          uc_mcontext_ext;
 };
 
 struct stat64_emu31;
index 598b0b42668bfc81eb6e2c5293a337e838717bbc..009f5eb111254028125104ccbf25566d2d72c5fa 100644 (file)
@@ -36,17 +36,16 @@ typedef struct
        struct sigcontext32 sc;
        _sigregs32 sregs;
        int signo;
-       __u32 gprs_high[NUM_GPRS];
-       __u8 retcode[S390_SYSCALL_SIZE];
+       _sigregs_ext32 sregs_ext;
+       __u16 svc_insn;         /* Offset of svc_insn is NOT fixed! */
 } sigframe32;
 
 typedef struct 
 {
        __u8 callee_used_stack[__SIGNAL_FRAMESIZE32];
-       __u8 retcode[S390_SYSCALL_SIZE];
+       __u16 svc_insn;
        compat_siginfo_t info;
        struct ucontext32 uc;
-       __u32 gprs_high[NUM_GPRS];
 } rt_sigframe32;
 
 int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
@@ -151,6 +150,38 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
        return err ? -EFAULT : 0;
 }
 
+/* Store registers needed to create the signal frame */
+static void store_sigregs(void)
+{
+       int i;
+
+       save_access_regs(current->thread.acrs);
+       save_fp_ctl(&current->thread.fp_regs.fpc);
+       if (current->thread.vxrs) {
+               save_vx_regs(current->thread.vxrs);
+               for (i = 0; i < __NUM_FPRS; i++)
+                       current->thread.fp_regs.fprs[i] =
+                               *(freg_t *)(current->thread.vxrs + i);
+       } else
+               save_fp_regs(current->thread.fp_regs.fprs);
+}
+
+/* Load registers after signal return */
+static void load_sigregs(void)
+{
+       int i;
+
+       restore_access_regs(current->thread.acrs);
+       /* restore_fp_ctl is done in restore_sigregs */
+       if (current->thread.vxrs) {
+               for (i = 0; i < __NUM_FPRS; i++)
+                       *(freg_t *)(current->thread.vxrs + i) =
+                               current->thread.fp_regs.fprs[i];
+               restore_vx_regs(current->thread.vxrs);
+       } else
+               restore_fp_regs(current->thread.fp_regs.fprs);
+}
+
 static int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs)
 {
        _sigregs32 user_sregs;
@@ -163,11 +194,8 @@ static int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs)
                (__u32)(regs->psw.mask & PSW_MASK_BA);
        for (i = 0; i < NUM_GPRS; i++)
                user_sregs.regs.gprs[i] = (__u32) regs->gprs[i];
-       save_access_regs(current->thread.acrs);
        memcpy(&user_sregs.regs.acrs, current->thread.acrs,
               sizeof(user_sregs.regs.acrs));
-       save_fp_ctl(&current->thread.fp_regs.fpc);
-       save_fp_regs(current->thread.fp_regs.fprs);
        memcpy(&user_sregs.fpregs, &current->thread.fp_regs,
               sizeof(user_sregs.fpregs));
        if (__copy_to_user(sregs, &user_sregs, sizeof(_sigregs32)))
@@ -207,37 +235,67 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
                regs->gprs[i] = (__u64) user_sregs.regs.gprs[i];
        memcpy(&current->thread.acrs, &user_sregs.regs.acrs,
               sizeof(current->thread.acrs));
-       restore_access_regs(current->thread.acrs);
 
        memcpy(&current->thread.fp_regs, &user_sregs.fpregs,
               sizeof(current->thread.fp_regs));
 
-       restore_fp_regs(current->thread.fp_regs.fprs);
        clear_pt_regs_flag(regs, PIF_SYSCALL); /* No longer in a system call */
        return 0;
 }
 
-static int save_sigregs_gprs_high(struct pt_regs *regs, __u32 __user *uregs)
+static int save_sigregs_ext32(struct pt_regs *regs,
+                             _sigregs_ext32 __user *sregs_ext)
 {
        __u32 gprs_high[NUM_GPRS];
+       __u64 vxrs[__NUM_VXRS_LOW];
        int i;
 
+       /* Save high gprs to signal stack */
        for (i = 0; i < NUM_GPRS; i++)
                gprs_high[i] = regs->gprs[i] >> 32;
-       if (__copy_to_user(uregs, &gprs_high, sizeof(gprs_high)))
+       if (__copy_to_user(&sregs_ext->gprs_high, &gprs_high,
+                          sizeof(sregs_ext->gprs_high)))
                return -EFAULT;
+
+       /* Save vector registers to signal stack */
+       if (current->thread.vxrs) {
+               for (i = 0; i < __NUM_VXRS_LOW; i++)
+                       vxrs[i] = *((__u64 *)(current->thread.vxrs + i) + 1);
+               if (__copy_to_user(&sregs_ext->vxrs_low, vxrs,
+                                  sizeof(sregs_ext->vxrs_low)) ||
+                   __copy_to_user(&sregs_ext->vxrs_high,
+                                  current->thread.vxrs + __NUM_VXRS_LOW,
+                                  sizeof(sregs_ext->vxrs_high)))
+                       return -EFAULT;
+       }
        return 0;
 }
 
-static int restore_sigregs_gprs_high(struct pt_regs *regs, __u32 __user *uregs)
+static int restore_sigregs_ext32(struct pt_regs *regs,
+                                _sigregs_ext32 __user *sregs_ext)
 {
        __u32 gprs_high[NUM_GPRS];
+       __u64 vxrs[__NUM_VXRS_LOW];
        int i;
 
-       if (__copy_from_user(&gprs_high, uregs, sizeof(gprs_high)))
+       /* Restore high gprs from signal stack */
+       if (__copy_from_user(&gprs_high, &sregs_ext->gprs_high,
+                            sizeof(&sregs_ext->gprs_high)))
                return -EFAULT;
        for (i = 0; i < NUM_GPRS; i++)
                *(__u32 *)&regs->gprs[i] = gprs_high[i];
+
+       /* Restore vector registers from signal stack */
+       if (current->thread.vxrs) {
+               if (__copy_from_user(vxrs, &sregs_ext->vxrs_low,
+                                    sizeof(sregs_ext->vxrs_low)) ||
+                   __copy_from_user(current->thread.vxrs + __NUM_VXRS_LOW,
+                                    &sregs_ext->vxrs_high,
+                                    sizeof(sregs_ext->vxrs_high)))
+                       return -EFAULT;
+               for (i = 0; i < __NUM_VXRS_LOW; i++)
+                       *((__u64 *)(current->thread.vxrs + i) + 1) = vxrs[i];
+       }
        return 0;
 }
 
@@ -252,8 +310,9 @@ COMPAT_SYSCALL_DEFINE0(sigreturn)
        set_current_blocked(&set);
        if (restore_sigregs32(regs, &frame->sregs))
                goto badframe;
-       if (restore_sigregs_gprs_high(regs, frame->gprs_high))
+       if (restore_sigregs_ext32(regs, &frame->sregs_ext))
                goto badframe;
+       load_sigregs();
        return regs->gprs[2];
 badframe:
        force_sig(SIGSEGV, current);
@@ -269,12 +328,13 @@ COMPAT_SYSCALL_DEFINE0(rt_sigreturn)
        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
                goto badframe;
        set_current_blocked(&set);
+       if (compat_restore_altstack(&frame->uc.uc_stack))
+               goto badframe;
        if (restore_sigregs32(regs, &frame->uc.uc_mcontext))
                goto badframe;
-       if (restore_sigregs_gprs_high(regs, frame->gprs_high))
+       if (restore_sigregs_ext32(regs, &frame->uc.uc_mcontext_ext))
                goto badframe;
-       if (compat_restore_altstack(&frame->uc.uc_stack))
-               goto badframe; 
+       load_sigregs();
        return regs->gprs[2];
 badframe:
        force_sig(SIGSEGV, current);
@@ -324,37 +384,64 @@ static int setup_frame32(struct ksignal *ksig, sigset_t *set,
                         struct pt_regs *regs)
 {
        int sig = ksig->sig;
-       sigframe32 __user *frame = get_sigframe(&ksig->ka, regs, sizeof(sigframe32));
-
+       sigframe32 __user *frame;
+       struct sigcontext32 sc;
+       unsigned long restorer;
+       size_t frame_size;
+
+       /*
+        * gprs_high are always present for 31-bit compat tasks.
+        * The space for vector registers is only allocated if
+        * the machine supports it
+        */
+       frame_size = sizeof(*frame) - sizeof(frame->sregs_ext.__reserved);
+       if (!MACHINE_HAS_VX)
+               frame_size -= sizeof(frame->sregs_ext.vxrs_low) +
+                             sizeof(frame->sregs_ext.vxrs_high);
+       frame = get_sigframe(&ksig->ka, regs, frame_size);
        if (frame == (void __user *) -1UL)
                return -EFAULT;
 
-       if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE32))
+       /* Set up backchain. */
+       if (__put_user(regs->gprs[15], (unsigned int __user *) frame))
+               return -EFAULT;
+
+       /* Create struct sigcontext32 on the signal stack */
+       memcpy(&sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE32);
+       sc.sregs = (__u32)(unsigned long __force) &frame->sregs;
+       if (__copy_to_user(&frame->sc, &sc, sizeof(frame->sc)))
                return -EFAULT;
 
+       /* Store registers needed to create the signal frame */
+       store_sigregs();
+
+       /* Create _sigregs32 on the signal stack */
        if (save_sigregs32(regs, &frame->sregs))
                return -EFAULT;
-       if (save_sigregs_gprs_high(regs, frame->gprs_high))
+
+       /* Place signal number on stack to allow backtrace from handler.  */
+       if (__put_user(regs->gprs[2], (int __force __user *) &frame->signo))
                return -EFAULT;
-       if (__put_user((unsigned long) &frame->sregs, &frame->sc.sregs))
+
+       /* Create _sigregs_ext32 on the signal stack */
+       if (save_sigregs_ext32(regs, &frame->sregs_ext))
                return -EFAULT;
 
        /* Set up to return from userspace.  If provided, use a stub
           already in userspace.  */
        if (ksig->ka.sa.sa_flags & SA_RESTORER) {
-               regs->gprs[14] = (__u64 __force) ksig->ka.sa.sa_restorer | PSW32_ADDR_AMODE;
+               restorer = (unsigned long __force)
+                       ksig->ka.sa.sa_restorer | PSW32_ADDR_AMODE;
        } else {
-               regs->gprs[14] = (__u64 __force) frame->retcode | PSW32_ADDR_AMODE;
-               if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn,
-                              (u16 __force __user *)(frame->retcode)))
+               /* Signal frames without vectors registers are short ! */
+               __u16 __user *svc = (void *) frame + frame_size - 2;
+               if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn, svc))
                        return -EFAULT;
+               restorer = (unsigned long __force) svc | PSW32_ADDR_AMODE;
         }
 
-       /* Set up backchain. */
-       if (__put_user(regs->gprs[15], (unsigned int __user *) frame))
-               return -EFAULT;
-
        /* Set up registers for signal handler */
+       regs->gprs[14] = restorer;
        regs->gprs[15] = (__force __u64) frame;
        /* Force 31 bit amode and default user address space control. */
        regs->psw.mask = PSW_MASK_BA |
@@ -375,50 +462,69 @@ static int setup_frame32(struct ksignal *ksig, sigset_t *set,
                regs->gprs[6] = task_thread_info(current)->last_break;
        }
 
-       /* Place signal number on stack to allow backtrace from handler.  */
-       if (__put_user(regs->gprs[2], (int __force __user *) &frame->signo))
-               return -EFAULT;
        return 0;
 }
 
 static int setup_rt_frame32(struct ksignal *ksig, sigset_t *set,
                            struct pt_regs *regs)
 {
-       int err = 0;
-       rt_sigframe32 __user *frame = get_sigframe(&ksig->ka, regs, sizeof(rt_sigframe32));
-
+       rt_sigframe32 __user *frame;
+       unsigned long restorer;
+       size_t frame_size;
+       u32 uc_flags;
+
+       frame_size = sizeof(*frame) -
+                    sizeof(frame->uc.uc_mcontext_ext.__reserved);
+       /*
+        * gprs_high are always present for 31-bit compat tasks.
+        * The space for vector registers is only allocated if
+        * the machine supports it
+        */
+       uc_flags = UC_GPRS_HIGH;
+       if (MACHINE_HAS_VX) {
+               if (current->thread.vxrs)
+                       uc_flags |= UC_VXRS;
+       } else
+               frame_size -= sizeof(frame->uc.uc_mcontext_ext.vxrs_low) +
+                             sizeof(frame->uc.uc_mcontext_ext.vxrs_high);
+       frame = get_sigframe(&ksig->ka, regs, frame_size);
        if (frame == (void __user *) -1UL)
                return -EFAULT;
 
-       if (copy_siginfo_to_user32(&frame->info, &ksig->info))
-               return -EFAULT;
-
-       /* Create the ucontext.  */
-       err |= __put_user(UC_EXTENDED, &frame->uc.uc_flags);
-       err |= __put_user(0, &frame->uc.uc_link);
-       err |= __compat_save_altstack(&frame->uc.uc_stack, regs->gprs[15]);
-       err |= save_sigregs32(regs, &frame->uc.uc_mcontext);
-       err |= save_sigregs_gprs_high(regs, frame->gprs_high);
-       err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
-       if (err)
+       /* Set up backchain. */
+       if (__put_user(regs->gprs[15], (unsigned int __force __user *) frame))
                return -EFAULT;
 
        /* Set up to return from userspace.  If provided, use a stub
           already in userspace.  */
        if (ksig->ka.sa.sa_flags & SA_RESTORER) {
-               regs->gprs[14] = (__u64 __force) ksig->ka.sa.sa_restorer | PSW32_ADDR_AMODE;
+               restorer = (unsigned long __force)
+                       ksig->ka.sa.sa_restorer | PSW32_ADDR_AMODE;
        } else {
-               regs->gprs[14] = (__u64 __force) frame->retcode | PSW32_ADDR_AMODE;
-               if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
-                              (u16 __force __user *)(frame->retcode)))
+               __u16 __user *svc = &frame->svc_insn;
+               if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn, svc))
                        return -EFAULT;
+               restorer = (unsigned long __force) svc | PSW32_ADDR_AMODE;
        }
 
-       /* Set up backchain. */
-       if (__put_user(regs->gprs[15], (unsigned int __force __user *) frame))
+       /* Create siginfo on the signal stack */
+       if (copy_siginfo_to_user32(&frame->info, &ksig->info))
+               return -EFAULT;
+
+       /* Store registers needed to create the signal frame */
+       store_sigregs();
+
+       /* Create ucontext on the signal stack. */
+       if (__put_user(uc_flags, &frame->uc.uc_flags) ||
+           __put_user(0, &frame->uc.uc_link) ||
+           __compat_save_altstack(&frame->uc.uc_stack, regs->gprs[15]) ||
+           save_sigregs32(regs, &frame->uc.uc_mcontext) ||
+           __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)) ||
+           save_sigregs_ext32(regs, &frame->uc.uc_mcontext_ext))
                return -EFAULT;
 
        /* Set up registers for signal handler */
+       regs->gprs[14] = restorer;
        regs->gprs[15] = (__force __u64) frame;
        /* Force 31 bit amode and default user address space control. */
        regs->psw.mask = PSW_MASK_BA |
index a3b9150e6802973b3b82a6db379c7959dfb48e9d..9f73c805902291c1619335cb38c4fe0f8492b29a 100644 (file)
@@ -46,9 +46,9 @@ struct dump_save_areas dump_save_areas;
 /*
  * Allocate and add a save area for a CPU
  */
-struct save_area *dump_save_area_create(int cpu)
+struct save_area_ext *dump_save_area_create(int cpu)
 {
-       struct save_area **save_areas, *save_area;
+       struct save_area_ext **save_areas, *save_area;
 
        save_area = kmalloc(sizeof(*save_area), GFP_KERNEL);
        if (!save_area)
@@ -385,10 +385,46 @@ static void *nt_s390_prefix(void *ptr, struct save_area *sa)
                         sizeof(sa->pref_reg), KEXEC_CORE_NOTE_NAME);
 }
 
+/*
+ * Initialize vxrs high note (full 128 bit VX registers 16-31)
+ */
+static void *nt_s390_vx_high(void *ptr, __vector128 *vx_regs)
+{
+       return nt_init(ptr, NT_S390_VXRS_HIGH, &vx_regs[16],
+                      16 * sizeof(__vector128), KEXEC_CORE_NOTE_NAME);
+}
+
+/*
+ * Initialize vxrs low note (lower halves of VX registers 0-15)
+ */
+static void *nt_s390_vx_low(void *ptr, __vector128 *vx_regs)
+{
+       Elf64_Nhdr *note;
+       u64 len;
+       int i;
+
+       note = (Elf64_Nhdr *)ptr;
+       note->n_namesz = strlen(KEXEC_CORE_NOTE_NAME) + 1;
+       note->n_descsz = 16 * 8;
+       note->n_type = NT_S390_VXRS_LOW;
+       len = sizeof(Elf64_Nhdr);
+
+       memcpy(ptr + len, KEXEC_CORE_NOTE_NAME, note->n_namesz);
+       len = roundup(len + note->n_namesz, 4);
+
+       ptr += len;
+       /* Copy lower halves of SIMD registers 0-15 */
+       for (i = 0; i < 16; i++) {
+               memcpy(ptr, &vx_regs[i], 8);
+               ptr += 8;
+       }
+       return ptr;
+}
+
 /*
  * Fill ELF notes for one CPU with save area registers
  */
-void *fill_cpu_elf_notes(void *ptr, struct save_area *sa)
+void *fill_cpu_elf_notes(void *ptr, struct save_area *sa, __vector128 *vx_regs)
 {
        ptr = nt_prstatus(ptr, sa);
        ptr = nt_fpregset(ptr, sa);
@@ -397,6 +433,10 @@ void *fill_cpu_elf_notes(void *ptr, struct save_area *sa)
        ptr = nt_s390_tod_preg(ptr, sa);
        ptr = nt_s390_ctrs(ptr, sa);
        ptr = nt_s390_prefix(ptr, sa);
+       if (MACHINE_HAS_VX && vx_regs) {
+               ptr = nt_s390_vx_low(ptr, vx_regs);
+               ptr = nt_s390_vx_high(ptr, vx_regs);
+       }
        return ptr;
 }
 
@@ -484,7 +524,7 @@ static int get_cpu_cnt(void)
        int i, cpus = 0;
 
        for (i = 0; i < dump_save_areas.count; i++) {
-               if (dump_save_areas.areas[i]->pref_reg == 0)
+               if (dump_save_areas.areas[i]->sa.pref_reg == 0)
                        continue;
                cpus++;
        }
@@ -530,17 +570,17 @@ static void loads_init(Elf64_Phdr *phdr, u64 loads_offset)
  */
 static void *notes_init(Elf64_Phdr *phdr, void *ptr, u64 notes_offset)
 {
-       struct save_area *sa;
+       struct save_area_ext *sa_ext;
        void *ptr_start = ptr;
        int i;
 
        ptr = nt_prpsinfo(ptr);
 
        for (i = 0; i < dump_save_areas.count; i++) {
-               sa = dump_save_areas.areas[i];
-               if (sa->pref_reg == 0)
+               sa_ext = dump_save_areas.areas[i];
+               if (sa_ext->sa.pref_reg == 0)
                        continue;
-               ptr = fill_cpu_elf_notes(ptr, sa);
+               ptr = fill_cpu_elf_notes(ptr, &sa_ext->sa, sa_ext->vx_regs);
        }
        ptr = nt_vmcoreinfo(ptr);
        memset(phdr, 0, sizeof(*phdr));
@@ -581,7 +621,7 @@ int elfcorehdr_alloc(unsigned long long *addr, unsigned long long *size)
 
        mem_chunk_cnt = get_mem_chunk_cnt();
 
-       alloc_size = 0x1000 + get_cpu_cnt() * 0x300 +
+       alloc_size = 0x1000 + get_cpu_cnt() * 0x4a0 +
                mem_chunk_cnt * sizeof(Elf64_Phdr);
        hdr = kzalloc_panic(alloc_size);
        /* Init elf header */
index 993efe6a887c2c31d4bcd90b02bccbb3c0234ae9..f3762937dd82ee8afcc2c0fddae6397e2be863fa 100644 (file)
@@ -60,6 +60,11 @@ enum {
        A_28,   /* Access reg. starting at position 28 */
        C_8,    /* Control reg. starting at position 8 */
        C_12,   /* Control reg. starting at position 12 */
+       V_8,    /* Vector reg. starting at position 8, extension bit at 36 */
+       V_12,   /* Vector reg. starting at position 12, extension bit at 37 */
+       V_16,   /* Vector reg. starting at position 16, extension bit at 38 */
+       V_32,   /* Vector reg. starting at position 32, extension bit at 39 */
+       W_12,   /* Vector reg. at bit 12, extension at bit 37, used as index */
        B_16,   /* Base register starting at position 16 */
        B_32,   /* Base register starting at position 32 */
        X_12,   /* Index register starting at position 12 */
@@ -82,6 +87,8 @@ enum {
        U8_24,  /* 8 bit unsigned value starting at 24 */
        U8_32,  /* 8 bit unsigned value starting at 32 */
        I8_8,   /* 8 bit signed value starting at 8 */
+       I8_16,  /* 8 bit signed value starting at 16 */
+       I8_24,  /* 8 bit signed value starting at 24 */
        I8_32,  /* 8 bit signed value starting at 32 */
        J12_12, /* PC relative offset at 12 */
        I16_16, /* 16 bit signed value starting at 16 */
@@ -96,6 +103,9 @@ enum {
        U32_16, /* 32 bit unsigned value starting at 16 */
        M_16,   /* 4 bit optional mask starting at 16 */
        M_20,   /* 4 bit optional mask starting at 20 */
+       M_24,   /* 4 bit optional mask starting at 24 */
+       M_28,   /* 4 bit optional mask starting at 28 */
+       M_32,   /* 4 bit optional mask starting at 32 */
        RO_28,  /* optional GPR starting at position 28 */
 };
 
@@ -130,7 +140,7 @@ enum {
        INSTR_RSY_RDRM,
        INSTR_RS_AARD, INSTR_RS_CCRD, INSTR_RS_R0RD, INSTR_RS_RRRD,
        INSTR_RS_RURD,
-       INSTR_RXE_FRRD, INSTR_RXE_RRRD,
+       INSTR_RXE_FRRD, INSTR_RXE_RRRD, INSTR_RXE_RRRDM,
        INSTR_RXF_FRRDF,
        INSTR_RXY_FRRD, INSTR_RXY_RRRD, INSTR_RXY_URRD,
        INSTR_RX_FRRD, INSTR_RX_RRRD, INSTR_RX_URRD,
@@ -143,6 +153,17 @@ enum {
        INSTR_SS_L0RDRD, INSTR_SS_LIRDRD, INSTR_SS_LLRDRD, INSTR_SS_RRRDRD,
        INSTR_SS_RRRDRD2, INSTR_SS_RRRDRD3,
        INSTR_S_00, INSTR_S_RD,
+       INSTR_VRI_V0IM, INSTR_VRI_V0I0, INSTR_VRI_V0IIM, INSTR_VRI_VVIM,
+       INSTR_VRI_VVV0IM, INSTR_VRI_VVV0I0, INSTR_VRI_VVIMM,
+       INSTR_VRR_VV00MMM, INSTR_VRR_VV000MM, INSTR_VRR_VV0000M,
+       INSTR_VRR_VV00000, INSTR_VRR_VVV0M0M, INSTR_VRR_VV00M0M,
+       INSTR_VRR_VVV000M, INSTR_VRR_VVV000V, INSTR_VRR_VVV0000,
+       INSTR_VRR_VVV0MMM, INSTR_VRR_VVV00MM, INSTR_VRR_VVVMM0V,
+       INSTR_VRR_VVVM0MV, INSTR_VRR_VVVM00V, INSTR_VRR_VRR0000,
+       INSTR_VRS_VVRDM, INSTR_VRS_VVRD0, INSTR_VRS_VRRDM, INSTR_VRS_VRRD0,
+       INSTR_VRS_RVRDM,
+       INSTR_VRV_VVRDM, INSTR_VRV_VWRDM,
+       INSTR_VRX_VRRDM, INSTR_VRX_VRRD0,
 };
 
 static const struct s390_operand operands[] =
@@ -168,6 +189,11 @@ static const struct s390_operand operands[] =
        [A_28]   = {  4, 28, OPERAND_AR },
        [C_8]    = {  4,  8, OPERAND_CR },
        [C_12]   = {  4, 12, OPERAND_CR },
+       [V_8]    = {  4,  8, OPERAND_VR },
+       [V_12]   = {  4, 12, OPERAND_VR },
+       [V_16]   = {  4, 16, OPERAND_VR },
+       [V_32]   = {  4, 32, OPERAND_VR },
+       [W_12]   = {  4, 12, OPERAND_INDEX | OPERAND_VR },
        [B_16]   = {  4, 16, OPERAND_BASE | OPERAND_GPR },
        [B_32]   = {  4, 32, OPERAND_BASE | OPERAND_GPR },
        [X_12]   = {  4, 12, OPERAND_INDEX | OPERAND_GPR },
@@ -190,6 +216,11 @@ static const struct s390_operand operands[] =
        [U8_24]  = {  8, 24, 0 },
        [U8_32]  = {  8, 32, 0 },
        [J12_12] = { 12, 12, OPERAND_PCREL },
+       [I8_8]   = {  8,  8, OPERAND_SIGNED },
+       [I8_16]  = {  8, 16, OPERAND_SIGNED },
+       [I8_24]  = {  8, 24, OPERAND_SIGNED },
+       [I8_32]  = {  8, 32, OPERAND_SIGNED },
+       [I16_32] = { 16, 32, OPERAND_SIGNED },
        [I16_16] = { 16, 16, OPERAND_SIGNED },
        [U16_16] = { 16, 16, 0 },
        [U16_32] = { 16, 32, 0 },
@@ -202,6 +233,9 @@ static const struct s390_operand operands[] =
        [U32_16] = { 32, 16, 0 },
        [M_16]   = {  4, 16, 0 },
        [M_20]   = {  4, 20, 0 },
+       [M_24]   = {  4, 24, 0 },
+       [M_28]   = {  4, 28, 0 },
+       [M_32]   = {  4, 32, 0 },
        [RO_28]  = {  4, 28, OPERAND_GPR }
 };
 
@@ -283,6 +317,7 @@ static const unsigned char formats[][7] = {
        [INSTR_RS_RURD]   = { 0xff, R_8,U4_12,D_20,B_16,0,0 },
        [INSTR_RXE_FRRD]  = { 0xff, F_8,D_20,X_12,B_16,0,0 },
        [INSTR_RXE_RRRD]  = { 0xff, R_8,D_20,X_12,B_16,0,0 },
+       [INSTR_RXE_RRRDM] = { 0xff, R_8,D_20,X_12,B_16,M_32,0 },
        [INSTR_RXF_FRRDF] = { 0xff, F_32,F_8,D_20,X_12,B_16,0 },
        [INSTR_RXY_FRRD]  = { 0xff, F_8,D20_20,X_12,B_16,0,0 },
        [INSTR_RXY_RRRD]  = { 0xff, R_8,D20_20,X_12,B_16,0,0 },
@@ -307,6 +342,37 @@ static const unsigned char formats[][7] = {
        [INSTR_SS_RRRDRD] = { 0xff, D_20,R_8,B_16,D_36,B_32,R_12 },
        [INSTR_S_00]      = { 0xff, 0,0,0,0,0,0 },
        [INSTR_S_RD]      = { 0xff, D_20,B_16,0,0,0,0 },
+       [INSTR_VRI_V0IM]  = { 0xff, V_8,I16_16,M_32,0,0,0 },
+       [INSTR_VRI_V0I0]  = { 0xff, V_8,I16_16,0,0,0,0 },
+       [INSTR_VRI_V0IIM] = { 0xff, V_8,I8_16,I8_24,M_32,0,0 },
+       [INSTR_VRI_VVIM]  = { 0xff, V_8,I16_16,V_12,M_32,0,0 },
+       [INSTR_VRI_VVV0IM]= { 0xff, V_8,V_12,V_16,I8_24,M_32,0 },
+       [INSTR_VRI_VVV0I0]= { 0xff, V_8,V_12,V_16,I8_24,0,0 },
+       [INSTR_VRI_VVIMM] = { 0xff, V_8,V_12,I16_16,M_32,M_28,0 },
+       [INSTR_VRR_VV00MMM]={ 0xff, V_8,V_12,M_32,M_28,M_24,0 },
+       [INSTR_VRR_VV000MM]={ 0xff, V_8,V_12,M_32,M_28,0,0 },
+       [INSTR_VRR_VV0000M]={ 0xff, V_8,V_12,M_32,0,0,0 },
+       [INSTR_VRR_VV00000]={ 0xff, V_8,V_12,0,0,0,0 },
+       [INSTR_VRR_VVV0M0M]={ 0xff, V_8,V_12,V_16,M_32,M_24,0 },
+       [INSTR_VRR_VV00M0M]={ 0xff, V_8,V_12,M_32,M_24,0,0 },
+       [INSTR_VRR_VVV000M]={ 0xff, V_8,V_12,V_16,M_32,0,0 },
+       [INSTR_VRR_VVV000V]={ 0xff, V_8,V_12,V_16,V_32,0,0 },
+       [INSTR_VRR_VVV0000]={ 0xff, V_8,V_12,V_16,0,0,0 },
+       [INSTR_VRR_VVV0MMM]={ 0xff, V_8,V_12,V_16,M_32,M_28,M_24 },
+       [INSTR_VRR_VVV00MM]={ 0xff, V_8,V_12,V_16,M_32,M_28,0 },
+       [INSTR_VRR_VVVMM0V]={ 0xff, V_8,V_12,V_16,V_32,M_20,M_24 },
+       [INSTR_VRR_VVVM0MV]={ 0xff, V_8,V_12,V_16,V_32,M_28,M_20 },
+       [INSTR_VRR_VVVM00V]={ 0xff, V_8,V_12,V_16,V_32,M_20,0 },
+       [INSTR_VRR_VRR0000]={ 0xff, V_8,R_12,R_16,0,0,0 },
+       [INSTR_VRS_VVRDM] = { 0xff, V_8,V_12,D_20,B_16,M_32,0 },
+       [INSTR_VRS_VVRD0] = { 0xff, V_8,V_12,D_20,B_16,0,0 },
+       [INSTR_VRS_VRRDM] = { 0xff, V_8,R_12,D_20,B_16,M_32,0 },
+       [INSTR_VRS_VRRD0] = { 0xff, V_8,R_12,D_20,B_16,0,0 },
+       [INSTR_VRS_RVRDM] = { 0xff, R_8,V_12,D_20,B_16,M_32,0 },
+       [INSTR_VRV_VVRDM] = { 0xff, V_8,V_12,D_20,B_16,M_32,0 },
+       [INSTR_VRV_VWRDM] = { 0xff, V_8,D_20,W_12,B_16,M_32,0 },
+       [INSTR_VRX_VRRDM] = { 0xff, V_8,D_20,X_12,B_16,M_32,0 },
+       [INSTR_VRX_VRRD0] = { 0xff, V_8,D_20,X_12,B_16,0,0 },
 };
 
 enum {
@@ -381,6 +447,11 @@ enum {
        LONG_INSN_MPCIFC,
        LONG_INSN_STPCIFC,
        LONG_INSN_PCISTB,
+       LONG_INSN_VPOPCT,
+       LONG_INSN_VERLLV,
+       LONG_INSN_VESRAV,
+       LONG_INSN_VESRLV,
+       LONG_INSN_VSBCBI
 };
 
 static char *long_insn_name[] = {
@@ -455,6 +526,11 @@ static char *long_insn_name[] = {
        [LONG_INSN_MPCIFC] = "mpcifc",
        [LONG_INSN_STPCIFC] = "stpcifc",
        [LONG_INSN_PCISTB] = "pcistb",
+       [LONG_INSN_VPOPCT] = "vpopct",
+       [LONG_INSN_VERLLV] = "verllv",
+       [LONG_INSN_VESRAV] = "vesrav",
+       [LONG_INSN_VESRLV] = "vesrlv",
+       [LONG_INSN_VSBCBI] = "vsbcbi",
 };
 
 static struct s390_insn opcode[] = {
@@ -1369,6 +1445,150 @@ static struct s390_insn opcode_e5[] = {
        { "", 0, INSTR_INVALID }
 };
 
+static struct s390_insn opcode_e7[] = {
+#ifdef CONFIG_64BIT
+       { "lcbb", 0x27, INSTR_RXE_RRRDM },
+       { "vgef", 0x13, INSTR_VRV_VVRDM },
+       { "vgeg", 0x12, INSTR_VRV_VVRDM },
+       { "vgbm", 0x44, INSTR_VRI_V0I0 },
+       { "vgm", 0x46, INSTR_VRI_V0IIM },
+       { "vl", 0x06, INSTR_VRX_VRRD0 },
+       { "vlr", 0x56, INSTR_VRR_VV00000 },
+       { "vlrp", 0x05, INSTR_VRX_VRRDM },
+       { "vleb", 0x00, INSTR_VRX_VRRDM },
+       { "vleh", 0x01, INSTR_VRX_VRRDM },
+       { "vlef", 0x03, INSTR_VRX_VRRDM },
+       { "vleg", 0x02, INSTR_VRX_VRRDM },
+       { "vleib", 0x40, INSTR_VRI_V0IM },
+       { "vleih", 0x41, INSTR_VRI_V0IM },
+       { "vleif", 0x43, INSTR_VRI_V0IM },
+       { "vleig", 0x42, INSTR_VRI_V0IM },
+       { "vlgv", 0x21, INSTR_VRS_RVRDM },
+       { "vllez", 0x04, INSTR_VRX_VRRDM },
+       { "vlm", 0x36, INSTR_VRS_VVRD0 },
+       { "vlbb", 0x07, INSTR_VRX_VRRDM },
+       { "vlvg", 0x22, INSTR_VRS_VRRDM },
+       { "vlvgp", 0x62, INSTR_VRR_VRR0000 },
+       { "vll", 0x37, INSTR_VRS_VRRD0 },
+       { "vmrh", 0x61, INSTR_VRR_VVV000M },
+       { "vmrl", 0x60, INSTR_VRR_VVV000M },
+       { "vpk", 0x94, INSTR_VRR_VVV000M },
+       { "vpks", 0x97, INSTR_VRR_VVV0M0M },
+       { "vpkls", 0x95, INSTR_VRR_VVV0M0M },
+       { "vperm", 0x8c, INSTR_VRR_VVV000V },
+       { "vpdi", 0x84, INSTR_VRR_VVV000M },
+       { "vrep", 0x4d, INSTR_VRI_VVIM },
+       { "vrepi", 0x45, INSTR_VRI_V0IM },
+       { "vscef", 0x1b, INSTR_VRV_VWRDM },
+       { "vsceg", 0x1a, INSTR_VRV_VWRDM },
+       { "vsel", 0x8d, INSTR_VRR_VVV000V },
+       { "vseg", 0x5f, INSTR_VRR_VV0000M },
+       { "vst", 0x0e, INSTR_VRX_VRRD0 },
+       { "vsteb", 0x08, INSTR_VRX_VRRDM },
+       { "vsteh", 0x09, INSTR_VRX_VRRDM },
+       { "vstef", 0x0b, INSTR_VRX_VRRDM },
+       { "vsteg", 0x0a, INSTR_VRX_VRRDM },
+       { "vstm", 0x3e, INSTR_VRS_VVRD0 },
+       { "vstl", 0x3f, INSTR_VRS_VRRD0 },
+       { "vuph", 0xd7, INSTR_VRR_VV0000M },
+       { "vuplh", 0xd5, INSTR_VRR_VV0000M },
+       { "vupl", 0xd6, INSTR_VRR_VV0000M },
+       { "vupll", 0xd4, INSTR_VRR_VV0000M },
+       { "va", 0xf3, INSTR_VRR_VVV000M },
+       { "vacc", 0xf1, INSTR_VRR_VVV000M },
+       { "vac", 0xbb, INSTR_VRR_VVVM00V },
+       { "vaccc", 0xb9, INSTR_VRR_VVVM00V },
+       { "vn", 0x68, INSTR_VRR_VVV0000 },
+       { "vnc", 0x69, INSTR_VRR_VVV0000 },
+       { "vavg", 0xf2, INSTR_VRR_VVV000M },
+       { "vavgl", 0xf0, INSTR_VRR_VVV000M },
+       { "vcksm", 0x66, INSTR_VRR_VVV0000 },
+       { "vec", 0xdb, INSTR_VRR_VV0000M },
+       { "vecl", 0xd9, INSTR_VRR_VV0000M },
+       { "vceq", 0xf8, INSTR_VRR_VVV0M0M },
+       { "vch", 0xfb, INSTR_VRR_VVV0M0M },
+       { "vchl", 0xf9, INSTR_VRR_VVV0M0M },
+       { "vclz", 0x53, INSTR_VRR_VV0000M },
+       { "vctz", 0x52, INSTR_VRR_VV0000M },
+       { "vx", 0x6d, INSTR_VRR_VVV0000 },
+       { "vgfm", 0xb4, INSTR_VRR_VVV000M },
+       { "vgfma", 0xbc, INSTR_VRR_VVVM00V },
+       { "vlc", 0xde, INSTR_VRR_VV0000M },
+       { "vlp", 0xdf, INSTR_VRR_VV0000M },
+       { "vmx", 0xff, INSTR_VRR_VVV000M },
+       { "vmxl", 0xfd, INSTR_VRR_VVV000M },
+       { "vmn", 0xfe, INSTR_VRR_VVV000M },
+       { "vmnl", 0xfc, INSTR_VRR_VVV000M },
+       { "vmal", 0xaa, INSTR_VRR_VVVM00V },
+       { "vmae", 0xae, INSTR_VRR_VVVM00V },
+       { "vmale", 0xac, INSTR_VRR_VVVM00V },
+       { "vmah", 0xab, INSTR_VRR_VVVM00V },
+       { "vmalh", 0xa9, INSTR_VRR_VVVM00V },
+       { "vmao", 0xaf, INSTR_VRR_VVVM00V },
+       { "vmalo", 0xad, INSTR_VRR_VVVM00V },
+       { "vmh", 0xa3, INSTR_VRR_VVV000M },
+       { "vmlh", 0xa1, INSTR_VRR_VVV000M },
+       { "vml", 0xa2, INSTR_VRR_VVV000M },
+       { "vme", 0xa6, INSTR_VRR_VVV000M },
+       { "vmle", 0xa4, INSTR_VRR_VVV000M },
+       { "vmo", 0xa7, INSTR_VRR_VVV000M },
+       { "vmlo", 0xa5, INSTR_VRR_VVV000M },
+       { "vno", 0x6b, INSTR_VRR_VVV0000 },
+       { "vo", 0x6a, INSTR_VRR_VVV0000 },
+       { { 0, LONG_INSN_VPOPCT }, 0x50, INSTR_VRR_VV0000M },
+       { { 0, LONG_INSN_VERLLV }, 0x73, INSTR_VRR_VVV000M },
+       { "verll", 0x33, INSTR_VRS_VVRDM },
+       { "verim", 0x72, INSTR_VRI_VVV0IM },
+       { "veslv", 0x70, INSTR_VRR_VVV000M },
+       { "vesl", 0x30, INSTR_VRS_VVRDM },
+       { { 0, LONG_INSN_VESRAV }, 0x7a, INSTR_VRR_VVV000M },
+       { "vesra", 0x3a, INSTR_VRS_VVRDM },
+       { { 0, LONG_INSN_VESRLV }, 0x78, INSTR_VRR_VVV000M },
+       { "vesrl", 0x38, INSTR_VRS_VVRDM },
+       { "vsl", 0x74, INSTR_VRR_VVV0000 },
+       { "vslb", 0x75, INSTR_VRR_VVV0000 },
+       { "vsldb", 0x77, INSTR_VRI_VVV0I0 },
+       { "vsra", 0x7e, INSTR_VRR_VVV0000 },
+       { "vsrab", 0x7f, INSTR_VRR_VVV0000 },
+       { "vsrl", 0x7c, INSTR_VRR_VVV0000 },
+       { "vsrlb", 0x7d, INSTR_VRR_VVV0000 },
+       { "vs", 0xf7, INSTR_VRR_VVV000M },
+       { "vscb", 0xf5, INSTR_VRR_VVV000M },
+       { "vsb", 0xbf, INSTR_VRR_VVVM00V },
+       { { 0, LONG_INSN_VSBCBI }, 0xbd, INSTR_VRR_VVVM00V },
+       { "vsumg", 0x65, INSTR_VRR_VVV000M },
+       { "vsumq", 0x67, INSTR_VRR_VVV000M },
+       { "vsum", 0x64, INSTR_VRR_VVV000M },
+       { "vtm", 0xd8, INSTR_VRR_VV00000 },
+       { "vfae", 0x82, INSTR_VRR_VVV0M0M },
+       { "vfee", 0x80, INSTR_VRR_VVV0M0M },
+       { "vfene", 0x81, INSTR_VRR_VVV0M0M },
+       { "vistr", 0x5c, INSTR_VRR_VV00M0M },
+       { "vstrc", 0x8a, INSTR_VRR_VVVMM0V },
+       { "vfa", 0xe3, INSTR_VRR_VVV00MM },
+       { "wfc", 0xcb, INSTR_VRR_VV000MM },
+       { "wfk", 0xca, INSTR_VRR_VV000MM },
+       { "vfce", 0xe8, INSTR_VRR_VVV0MMM },
+       { "vfch", 0xeb, INSTR_VRR_VVV0MMM },
+       { "vfche", 0xea, INSTR_VRR_VVV0MMM },
+       { "vcdg", 0xc3, INSTR_VRR_VV00MMM },
+       { "vcdlg", 0xc1, INSTR_VRR_VV00MMM },
+       { "vcgd", 0xc2, INSTR_VRR_VV00MMM },
+       { "vclgd", 0xc0, INSTR_VRR_VV00MMM },
+       { "vfd", 0xe5, INSTR_VRR_VVV00MM },
+       { "vfi", 0xc7, INSTR_VRR_VV00MMM },
+       { "vlde", 0xc4, INSTR_VRR_VV000MM },
+       { "vled", 0xc5, INSTR_VRR_VV00MMM },
+       { "vfm", 0xe7, INSTR_VRR_VVV00MM },
+       { "vfma", 0x8f, INSTR_VRR_VVVM0MV },
+       { "vfms", 0x8e, INSTR_VRR_VVVM0MV },
+       { "vfpso", 0xcc, INSTR_VRR_VV00MMM },
+       { "vfsq", 0xce, INSTR_VRR_VV000MM },
+       { "vfs", 0xe2, INSTR_VRR_VVV00MM },
+       { "vftci", 0x4a, INSTR_VRI_VVIMM },
+#endif
+};
+
 static struct s390_insn opcode_eb[] = {
 #ifdef CONFIG_64BIT
        { "lmg", 0x04, INSTR_RSY_RRRD },
@@ -1552,16 +1772,17 @@ static struct s390_insn opcode_ed[] = {
 static unsigned int extract_operand(unsigned char *code,
                                    const struct s390_operand *operand)
 {
+       unsigned char *cp;
        unsigned int val;
        int bits;
 
        /* Extract fragments of the operand byte for byte.  */
-       code += operand->shift / 8;
+       cp = code + operand->shift / 8;
        bits = (operand->shift & 7) + operand->bits;
        val = 0;
        do {
                val <<= 8;
-               val |= (unsigned int) *code++;
+               val |= (unsigned int) *cp++;
                bits -= 8;
        } while (bits > 0);
        val >>= -bits;
@@ -1571,6 +1792,18 @@ static unsigned int extract_operand(unsigned char *code,
        if (operand->bits == 20 && operand->shift == 20)
                val = (val & 0xff) << 12 | (val & 0xfff00) >> 8;
 
+       /* Check for register extensions bits for vector registers. */
+       if (operand->flags & OPERAND_VR) {
+               if (operand->shift == 8)
+                       val |= (code[4] & 8) << 1;
+               else if (operand->shift == 12)
+                       val |= (code[4] & 4) << 2;
+               else if (operand->shift == 16)
+                       val |= (code[4] & 2) << 3;
+               else if (operand->shift == 32)
+                       val |= (code[4] & 1) << 4;
+       }
+
        /* Sign extend value if the operand is signed or pc relative.  */
        if ((operand->flags & (OPERAND_SIGNED | OPERAND_PCREL)) &&
            (val & (1U << (operand->bits - 1))))
@@ -1639,6 +1872,10 @@ struct s390_insn *find_insn(unsigned char *code)
        case 0xe5:
                table = opcode_e5;
                break;
+       case 0xe7:
+               table = opcode_e7;
+               opfrag = code[5];
+               break;
        case 0xeb:
                table = opcode_eb;
                opfrag = code[5];
@@ -1734,6 +1971,8 @@ static int print_insn(char *buffer, unsigned char *code, unsigned long addr)
                                ptr += sprintf(ptr, "%%a%i", value);
                        else if (operand->flags & OPERAND_CR)
                                ptr += sprintf(ptr, "%%c%i", value);
+                       else if (operand->flags & OPERAND_VR)
+                               ptr += sprintf(ptr, "%%v%i", value);
                        else if (operand->flags & OPERAND_PCREL)
                                ptr += sprintf(ptr, "%lx", (signed int) value
                                                                      + addr);
index 0dff972a169c16dd533c8256de9771e96f459e01..cef2879edff321e151972f059973cd7e9babca68 100644 (file)
@@ -390,10 +390,10 @@ static __init void detect_machine_facilities(void)
                S390_lowcore.machine_flags |= MACHINE_FLAG_LPP;
        if (test_facility(50) && test_facility(73))
                S390_lowcore.machine_flags |= MACHINE_FLAG_TE;
-       if (test_facility(66))
-               S390_lowcore.machine_flags |= MACHINE_FLAG_RRBM;
        if (test_facility(51))
                S390_lowcore.machine_flags |= MACHINE_FLAG_TLB_LC;
+       if (test_facility(129))
+               S390_lowcore.machine_flags |= MACHINE_FLAG_VX;
 #endif
 }
 
index 1aad48398d06124541ef7936aacdb8d08f26c038..0554b9771c9f29eb727d40f0552258403e3201e3 100644 (file)
@@ -4,7 +4,7 @@
 #include <linux/types.h>
 #include <linux/signal.h>
 #include <asm/ptrace.h>
-#include <asm/cputime.h>
+#include <asm/idle.h>
 
 extern void *restart_stack;
 extern unsigned long suspend_zero_pages;
@@ -21,6 +21,8 @@ void psw_idle(struct s390_idle_data *, unsigned long);
 asmlinkage long do_syscall_trace_enter(struct pt_regs *regs);
 asmlinkage void do_syscall_trace_exit(struct pt_regs *regs);
 
+int alloc_vector_registers(struct task_struct *tsk);
+
 void do_protection_exception(struct pt_regs *regs);
 void do_dat_exception(struct pt_regs *regs);
 
@@ -43,8 +45,10 @@ void special_op_exception(struct pt_regs *regs);
 void specification_exception(struct pt_regs *regs);
 void transaction_exception(struct pt_regs *regs);
 void translation_exception(struct pt_regs *regs);
+void vector_exception(struct pt_regs *regs);
 
 void do_per_trap(struct pt_regs *regs);
+void do_report_trap(struct pt_regs *regs, int si_signo, int si_code, char *str);
 void syscall_trace(struct pt_regs *regs, int entryexit);
 void kernel_stack_overflow(struct pt_regs * regs);
 void do_signal(struct pt_regs *regs);
index f2e674c702e1f904de800b94c33bedfd5fd30b91..7b2e03afd0177cda23a6d8424f0fe8934f705648 100644 (file)
@@ -42,7 +42,8 @@ STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
 STACK_SIZE  = 1 << STACK_SHIFT
 STACK_INIT = STACK_SIZE - STACK_FRAME_OVERHEAD - __PT_SIZE
 
-_TIF_WORK      = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED)
+_TIF_WORK      = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
+                  _TIF_UPROBE)
 _TIF_TRACE     = (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \
                   _TIF_SYSCALL_TRACEPOINT)
 _CIF_WORK      = (_CIF_MCCK_PENDING | _CIF_ASCE)
@@ -265,6 +266,10 @@ sysc_work:
        jo      sysc_mcck_pending
        tm      __TI_flags+7(%r12),_TIF_NEED_RESCHED
        jo      sysc_reschedule
+#ifdef CONFIG_UPROBES
+       tm      __TI_flags+7(%r12),_TIF_UPROBE
+       jo      sysc_uprobe_notify
+#endif
        tm      __PT_FLAGS+7(%r11),_PIF_PER_TRAP
        jo      sysc_singlestep
        tm      __TI_flags+7(%r12),_TIF_SIGPENDING
@@ -322,6 +327,16 @@ sysc_notify_resume:
        larl    %r14,sysc_return
        jg      do_notify_resume
 
+#
+# _TIF_UPROBE is set, call uprobe_notify_resume
+#
+#ifdef CONFIG_UPROBES
+sysc_uprobe_notify:
+       lgr     %r2,%r11                # pass pointer to pt_regs
+       larl    %r14,sysc_return
+       jg      uprobe_notify_resume
+#endif
+
 #
 # _PIF_PER_TRAP is set, call do_per_trap
 #
index 54d6493c4a561b050ad5e47bb21b6a041b6d496f..51d14fe5eb9a318349876eb376b359695770a0a2 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Dynamic function tracer architecture backend.
  *
- * Copyright IBM Corp. 2009
+ * Copyright IBM Corp. 2009,2014
  *
  *   Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>,
  *             Martin Schwidefsky <schwidefsky@de.ibm.com>
 #include <asm/asm-offsets.h>
 #include "entry.h"
 
-#ifdef CONFIG_DYNAMIC_FTRACE
-
+void mcount_replace_code(void);
 void ftrace_disable_code(void);
 void ftrace_enable_insn(void);
 
-#ifdef CONFIG_64BIT
 /*
- * The 64-bit mcount code looks like this:
+ * The mcount code looks like this:
  *     stg     %r14,8(%r15)            # offset 0
- * >   larl    %r1,<&counter>          # offset 6
- * >   brasl   %r14,_mcount            # offset 12
+ *     larl    %r1,<&counter>          # offset 6
+ *     brasl   %r14,_mcount            # offset 12
  *     lg      %r14,8(%r15)            # offset 18
- * Total length is 24 bytes. The middle two instructions of the mcount
- * block get overwritten by ftrace_make_nop / ftrace_make_call.
- * The 64-bit enabled ftrace code block looks like this:
- *     stg     %r14,8(%r15)            # offset 0
+ * Total length is 24 bytes. The complete mcount block initially gets replaced
+ * by ftrace_make_nop. Subsequent calls to ftrace_make_call / ftrace_make_nop
+ * only patch the jg/lg instruction within the block.
+ * Note: we do not patch the first instruction to an unconditional branch,
+ * since that would break kprobes/jprobes. It is easier to leave the larl
+ * instruction in and only modify the second instruction.
+ * The enabled ftrace code block looks like this:
+ *     larl    %r0,.+24                # offset 0
  * >   lg      %r1,__LC_FTRACE_FUNC    # offset 6
- * >   lgr     %r0,%r0                 # offset 12
- * >   basr    %r14,%r1                # offset 16
- *     lg      %r14,8(%15)             # offset 18
- * The return points of the mcount/ftrace function have the same offset 18.
- * The 64-bit disable ftrace code block looks like this:
- *     stg     %r14,8(%r15)            # offset 0
+ *     br      %r1                     # offset 12
+ *     brcl    0,0                     # offset 14
+ *     brc     0,0                     # offset 20
+ * The ftrace function gets called with a non-standard C function call ABI
+ * where r0 contains the return address. It is also expected that the called
+ * function only clobbers r0 and r1, but restores r2-r15.
+ * The return point of the ftrace function has offset 24, so execution
+ * continues behind the mcount block.
+ *     larl    %r0,.+24                # offset 0
  * >   jg      .+18                    # offset 6
- * >   lgr     %r0,%r0                 # offset 12
- * >   basr    %r14,%r1                # offset 16
- *     lg      %r14,8(%15)             # offset 18
+ *     br      %r1                     # offset 12
+ *     brcl    0,0                     # offset 14
+ *     brc     0,0                     # offset 20
  * The jg instruction branches to offset 24 to skip as many instructions
  * as possible.
  */
 asm(
        "       .align  4\n"
+       "mcount_replace_code:\n"
+       "       larl    %r0,0f\n"
        "ftrace_disable_code:\n"
        "       jg      0f\n"
-       "       lgr     %r0,%r0\n"
-       "       basr    %r14,%r1\n"
+       "       br      %r1\n"
+       "       brcl    0,0\n"
+       "       brc     0,0\n"
        "0:\n"
        "       .align  4\n"
        "ftrace_enable_insn:\n"
        "       lg      %r1,"__stringify(__LC_FTRACE_FUNC)"\n");
 
+#define MCOUNT_BLOCK_SIZE      24
+#define MCOUNT_INSN_OFFSET     6
 #define FTRACE_INSN_SIZE       6
 
-#else /* CONFIG_64BIT */
-/*
- * The 31-bit mcount code looks like this:
- *     st      %r14,4(%r15)            # offset 0
- * >   bras    %r1,0f                  # offset 4
- * >   .long   _mcount                 # offset 8
- * >   .long   <&counter>              # offset 12
- * > 0:        l       %r14,0(%r1)             # offset 16
- * >   l       %r1,4(%r1)              # offset 20
- *     basr    %r14,%r14               # offset 24
- *     l       %r14,4(%r15)            # offset 26
- * Total length is 30 bytes. The twenty bytes starting from offset 4
- * to offset 24 get overwritten by ftrace_make_nop / ftrace_make_call.
- * The 31-bit enabled ftrace code block looks like this:
- *     st      %r14,4(%r15)            # offset 0
- * >   l       %r14,__LC_FTRACE_FUNC   # offset 4
- * >   j       0f                      # offset 8
- * >   .fill   12,1,0x07               # offset 12
- *   0:        basr    %r14,%r14               # offset 24
- *     l       %r14,4(%r14)            # offset 26
- * The return points of the mcount/ftrace function have the same offset 26.
- * The 31-bit disabled ftrace code block looks like this:
- *     st      %r14,4(%r15)            # offset 0
- * >   j       .+26                    # offset 4
- * >   j       0f                      # offset 8
- * >   .fill   12,1,0x07               # offset 12
- *   0:        basr    %r14,%r14               # offset 24
- *     l       %r14,4(%r14)            # offset 26
- * The j instruction branches to offset 30 to skip as many instructions
- * as possible.
- */
-asm(
-       "       .align  4\n"
-       "ftrace_disable_code:\n"
-       "       j       1f\n"
-       "       j       0f\n"
-       "       .fill   12,1,0x07\n"
-       "0:     basr    %r14,%r14\n"
-       "1:\n"
-       "       .align  4\n"
-       "ftrace_enable_insn:\n"
-       "       l       %r14,"__stringify(__LC_FTRACE_FUNC)"\n");
-
-#define FTRACE_INSN_SIZE       4
-
-#endif /* CONFIG_64BIT */
-
+int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
+                      unsigned long addr)
+{
+       return 0;
+}
 
 int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
                    unsigned long addr)
 {
+       /* Initial replacement of the whole mcount block */
+       if (addr == MCOUNT_ADDR) {
+               if (probe_kernel_write((void *) rec->ip - MCOUNT_INSN_OFFSET,
+                                      mcount_replace_code,
+                                      MCOUNT_BLOCK_SIZE))
+                       return -EPERM;
+               return 0;
+       }
        if (probe_kernel_write((void *) rec->ip, ftrace_disable_code,
                               MCOUNT_INSN_SIZE))
                return -EPERM;
@@ -135,8 +111,6 @@ int __init ftrace_dyn_arch_init(void)
        return 0;
 }
 
-#endif /* CONFIG_DYNAMIC_FTRACE */
-
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 /*
  * Hook the return address and push it in the stack of return addresses
@@ -162,31 +136,26 @@ out:
        return parent;
 }
 
-#ifdef CONFIG_DYNAMIC_FTRACE
 /*
  * Patch the kernel code at ftrace_graph_caller location. The instruction
- * there is branch relative and save to prepare_ftrace_return. To disable
- * the call to prepare_ftrace_return we patch the bras offset to point
- * directly after the instructions. To enable the call we calculate
- * the original offset to prepare_ftrace_return and put it back.
+ * there is branch relative on condition. To enable the ftrace graph code
+ * block, we simply patch the mask field of the instruction to zero and
+ * turn the instruction into a nop.
+ * To disable the ftrace graph code the mask field will be patched to
+ * all ones, which turns the instruction into an unconditional branch.
  */
 int ftrace_enable_ftrace_graph_caller(void)
 {
-       unsigned short offset;
+       u8 op = 0x04; /* set mask field to zero */
 
-       offset = ((void *) prepare_ftrace_return -
-                 (void *) ftrace_graph_caller) / 2;
-       return probe_kernel_write((void *) ftrace_graph_caller + 2,
-                                 &offset, sizeof(offset));
+       return probe_kernel_write(__va(ftrace_graph_caller)+1, &op, sizeof(op));
 }
 
 int ftrace_disable_ftrace_graph_caller(void)
 {
-       static unsigned short offset = 0x0002;
+       u8 op = 0xf4; /* set mask field to all ones */
 
-       return probe_kernel_write((void *) ftrace_graph_caller + 2,
-                                 &offset, sizeof(offset));
+       return probe_kernel_write(__va(ftrace_graph_caller)+1, &op, sizeof(op));
 }
 
-#endif /* CONFIG_DYNAMIC_FTRACE */
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
index e88d35d749501e43b296e8794351f691368dcf5e..d62eee11f0b54240339d898fbf95d4299c011545 100644 (file)
@@ -398,7 +398,7 @@ ENTRY(startup_kdump)
        xc      __LC_STFL_FAC_LIST(8),__LC_STFL_FAC_LIST
 #ifndef CONFIG_MARCH_G5
        # check capabilities against MARCH_{G5,Z900,Z990,Z9_109,Z10}
-       .insn   s,0xb2b10000,__LC_STFL_FAC_LIST # store facility list
+       .insn   s,0xb2b10000,0          # store facilities @ __LC_STFL_FAC_LIST
        tm      __LC_STFL_FAC_LIST,0x01 # stfle available ?
        jz      0f
        la      %r0,1
diff --git a/arch/s390/kernel/idle.c b/arch/s390/kernel/idle.c
new file mode 100644 (file)
index 0000000..c846aee
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Idle functions for s390.
+ *
+ * Copyright IBM Corp. 2014
+ *
+ * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/kernel_stat.h>
+#include <linux/kprobes.h>
+#include <linux/notifier.h>
+#include <linux/init.h>
+#include <linux/cpu.h>
+#include <asm/cputime.h>
+#include <asm/nmi.h>
+#include <asm/smp.h>
+#include "entry.h"
+
+static DEFINE_PER_CPU(struct s390_idle_data, s390_idle);
+
+void __kprobes enabled_wait(void)
+{
+       struct s390_idle_data *idle = &__get_cpu_var(s390_idle);
+       unsigned long long idle_time;
+       unsigned long psw_mask;
+
+       trace_hardirqs_on();
+
+       /* Wait for external, I/O or machine check interrupt. */
+       psw_mask = PSW_KERNEL_BITS | PSW_MASK_WAIT | PSW_MASK_DAT |
+               PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
+       clear_cpu_flag(CIF_NOHZ_DELAY);
+
+       /* Call the assembler magic in entry.S */
+       psw_idle(idle, psw_mask);
+
+       /* Account time spent with enabled wait psw loaded as idle time. */
+       idle->sequence++;
+       smp_wmb();
+       idle_time = idle->clock_idle_exit - idle->clock_idle_enter;
+       idle->clock_idle_enter = idle->clock_idle_exit = 0ULL;
+       idle->idle_time += idle_time;
+       idle->idle_count++;
+       account_idle_time(idle_time);
+       smp_wmb();
+       idle->sequence++;
+}
+
+static ssize_t show_idle_count(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct s390_idle_data *idle = &per_cpu(s390_idle, dev->id);
+       unsigned long long idle_count;
+       unsigned int sequence;
+
+       do {
+               sequence = ACCESS_ONCE(idle->sequence);
+               idle_count = ACCESS_ONCE(idle->idle_count);
+               if (ACCESS_ONCE(idle->clock_idle_enter))
+                       idle_count++;
+       } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence));
+       return sprintf(buf, "%llu\n", idle_count);
+}
+DEVICE_ATTR(idle_count, 0444, show_idle_count, NULL);
+
+static ssize_t show_idle_time(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct s390_idle_data *idle = &per_cpu(s390_idle, dev->id);
+       unsigned long long now, idle_time, idle_enter, idle_exit;
+       unsigned int sequence;
+
+       do {
+               now = get_tod_clock();
+               sequence = ACCESS_ONCE(idle->sequence);
+               idle_time = ACCESS_ONCE(idle->idle_time);
+               idle_enter = ACCESS_ONCE(idle->clock_idle_enter);
+               idle_exit = ACCESS_ONCE(idle->clock_idle_exit);
+       } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence));
+       idle_time += idle_enter ? ((idle_exit ? : now) - idle_enter) : 0;
+       return sprintf(buf, "%llu\n", idle_time >> 12);
+}
+DEVICE_ATTR(idle_time_us, 0444, show_idle_time, NULL);
+
+cputime64_t arch_cpu_idle_time(int cpu)
+{
+       struct s390_idle_data *idle = &per_cpu(s390_idle, cpu);
+       unsigned long long now, idle_enter, idle_exit;
+       unsigned int sequence;
+
+       do {
+               now = get_tod_clock();
+               sequence = ACCESS_ONCE(idle->sequence);
+               idle_enter = ACCESS_ONCE(idle->clock_idle_enter);
+               idle_exit = ACCESS_ONCE(idle->clock_idle_exit);
+       } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence));
+       return idle_enter ? ((idle_exit ?: now) - idle_enter) : 0;
+}
+
+void arch_cpu_idle_enter(void)
+{
+       local_mcck_disable();
+}
+
+void arch_cpu_idle(void)
+{
+       if (!test_cpu_flag(CIF_MCCK_PENDING))
+               /* Halt the cpu and keep track of cpu time accounting. */
+               enabled_wait();
+       local_irq_enable();
+}
+
+void arch_cpu_idle_exit(void)
+{
+       local_mcck_enable();
+       if (test_cpu_flag(CIF_MCCK_PENDING))
+               s390_handle_mcck();
+}
+
+void arch_cpu_idle_dead(void)
+{
+       cpu_die();
+}
index 8eb82443cfbdc812ebb56d67112e6c4b50ef2a2b..1b8a38ab7861c685af7d9b1b7f593a9733135909 100644 (file)
@@ -70,6 +70,7 @@ static const struct irq_class irqclass_sub_desc[NR_ARCH_IRQS] = {
        {.irq = IRQEXT_CMS, .name = "CMS", .desc = "[EXT] CPU-Measurement: Sampling"},
        {.irq = IRQEXT_CMC, .name = "CMC", .desc = "[EXT] CPU-Measurement: Counter"},
        {.irq = IRQEXT_CMR, .name = "CMR", .desc = "[EXT] CPU-Measurement: RI"},
+       {.irq = IRQEXT_FTP, .name = "FTP", .desc = "[EXT] HMC FTP Service"},
        {.irq = IRQIO_CIO,  .name = "CIO", .desc = "[I/O] Common I/O Layer Interrupt"},
        {.irq = IRQIO_QAI,  .name = "QAI", .desc = "[I/O] QDIO Adapter Interrupt"},
        {.irq = IRQIO_DAS,  .name = "DAS", .desc = "[I/O] DASD"},
@@ -258,7 +259,7 @@ static irqreturn_t do_ext_interrupt(int irq, void *dummy)
 
        ext_code = *(struct ext_code *) &regs->int_code;
        if (ext_code.code != EXT_IRQ_CLK_COMP)
-               __get_cpu_var(s390_idle).nohz_delay = 1;
+               set_cpu_flag(CIF_NOHZ_DELAY);
 
        index = ext_hash(ext_code.code);
        rcu_read_lock();
index bc71a7b95af546b94d6ac6ba74c6484bbb261069..27ae5433fe4d40dde353983e5a7fed711b3d7db4 100644 (file)
@@ -58,161 +58,13 @@ struct kprobe_insn_cache kprobe_dmainsn_slots = {
        .insn_size = MAX_INSN_SIZE,
 };
 
-static int __kprobes is_prohibited_opcode(kprobe_opcode_t *insn)
-{
-       if (!is_known_insn((unsigned char *)insn))
-               return -EINVAL;
-       switch (insn[0] >> 8) {
-       case 0x0c:      /* bassm */
-       case 0x0b:      /* bsm   */
-       case 0x83:      /* diag  */
-       case 0x44:      /* ex    */
-       case 0xac:      /* stnsm */
-       case 0xad:      /* stosm */
-               return -EINVAL;
-       case 0xc6:
-               switch (insn[0] & 0x0f) {
-               case 0x00: /* exrl   */
-                       return -EINVAL;
-               }
-       }
-       switch (insn[0]) {
-       case 0x0101:    /* pr    */
-       case 0xb25a:    /* bsa   */
-       case 0xb240:    /* bakr  */
-       case 0xb258:    /* bsg   */
-       case 0xb218:    /* pc    */
-       case 0xb228:    /* pt    */
-       case 0xb98d:    /* epsw  */
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int __kprobes get_fixup_type(kprobe_opcode_t *insn)
-{
-       /* default fixup method */
-       int fixup = FIXUP_PSW_NORMAL;
-
-       switch (insn[0] >> 8) {
-       case 0x05:      /* balr */
-       case 0x0d:      /* basr */
-               fixup = FIXUP_RETURN_REGISTER;
-               /* if r2 = 0, no branch will be taken */
-               if ((insn[0] & 0x0f) == 0)
-                       fixup |= FIXUP_BRANCH_NOT_TAKEN;
-               break;
-       case 0x06:      /* bctr */
-       case 0x07:      /* bcr  */
-               fixup = FIXUP_BRANCH_NOT_TAKEN;
-               break;
-       case 0x45:      /* bal  */
-       case 0x4d:      /* bas  */
-               fixup = FIXUP_RETURN_REGISTER;
-               break;
-       case 0x47:      /* bc   */
-       case 0x46:      /* bct  */
-       case 0x86:      /* bxh  */
-       case 0x87:      /* bxle */
-               fixup = FIXUP_BRANCH_NOT_TAKEN;
-               break;
-       case 0x82:      /* lpsw */
-               fixup = FIXUP_NOT_REQUIRED;
-               break;
-       case 0xb2:      /* lpswe */
-               if ((insn[0] & 0xff) == 0xb2)
-                       fixup = FIXUP_NOT_REQUIRED;
-               break;
-       case 0xa7:      /* bras */
-               if ((insn[0] & 0x0f) == 0x05)
-                       fixup |= FIXUP_RETURN_REGISTER;
-               break;
-       case 0xc0:
-               if ((insn[0] & 0x0f) == 0x05)   /* brasl */
-                       fixup |= FIXUP_RETURN_REGISTER;
-               break;
-       case 0xeb:
-               switch (insn[2] & 0xff) {
-               case 0x44: /* bxhg  */
-               case 0x45: /* bxleg */
-                       fixup = FIXUP_BRANCH_NOT_TAKEN;
-                       break;
-               }
-               break;
-       case 0xe3:      /* bctg */
-               if ((insn[2] & 0xff) == 0x46)
-                       fixup = FIXUP_BRANCH_NOT_TAKEN;
-               break;
-       case 0xec:
-               switch (insn[2] & 0xff) {
-               case 0xe5: /* clgrb */
-               case 0xe6: /* cgrb  */
-               case 0xf6: /* crb   */
-               case 0xf7: /* clrb  */
-               case 0xfc: /* cgib  */
-               case 0xfd: /* cglib */
-               case 0xfe: /* cib   */
-               case 0xff: /* clib  */
-                       fixup = FIXUP_BRANCH_NOT_TAKEN;
-                       break;
-               }
-               break;
-       }
-       return fixup;
-}
-
-static int __kprobes is_insn_relative_long(kprobe_opcode_t *insn)
-{
-       /* Check if we have a RIL-b or RIL-c format instruction which
-        * we need to modify in order to avoid instruction emulation. */
-       switch (insn[0] >> 8) {
-       case 0xc0:
-               if ((insn[0] & 0x0f) == 0x00) /* larl */
-                       return true;
-               break;
-       case 0xc4:
-               switch (insn[0] & 0x0f) {
-               case 0x02: /* llhrl  */
-               case 0x04: /* lghrl  */
-               case 0x05: /* lhrl   */
-               case 0x06: /* llghrl */
-               case 0x07: /* sthrl  */
-               case 0x08: /* lgrl   */
-               case 0x0b: /* stgrl  */
-               case 0x0c: /* lgfrl  */
-               case 0x0d: /* lrl    */
-               case 0x0e: /* llgfrl */
-               case 0x0f: /* strl   */
-                       return true;
-               }
-               break;
-       case 0xc6:
-               switch (insn[0] & 0x0f) {
-               case 0x02: /* pfdrl  */
-               case 0x04: /* cghrl  */
-               case 0x05: /* chrl   */
-               case 0x06: /* clghrl */
-               case 0x07: /* clhrl  */
-               case 0x08: /* cgrl   */
-               case 0x0a: /* clgrl  */
-               case 0x0c: /* cgfrl  */
-               case 0x0d: /* crl    */
-               case 0x0e: /* clgfrl */
-               case 0x0f: /* clrl   */
-                       return true;
-               }
-               break;
-       }
-       return false;
-}
-
 static void __kprobes copy_instruction(struct kprobe *p)
 {
        s64 disp, new_disp;
        u64 addr, new_addr;
 
        memcpy(p->ainsn.insn, p->addr, insn_length(p->opcode >> 8));
-       if (!is_insn_relative_long(p->ainsn.insn))
+       if (!probe_is_insn_relative_long(p->ainsn.insn))
                return;
        /*
         * For pc-relative instructions in RIL-b or RIL-c format patch the
@@ -276,7 +128,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
        if ((unsigned long) p->addr & 0x01)
                return -EINVAL;
        /* Make sure the probe isn't going on a difficult instruction */
-       if (is_prohibited_opcode(p->addr))
+       if (probe_is_prohibited_opcode(p->addr))
                return -EINVAL;
        if (s390_get_insn_slot(p))
                return -ENOMEM;
@@ -605,7 +457,7 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
 {
        struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
        unsigned long ip = regs->psw.addr & PSW_ADDR_INSN;
-       int fixup = get_fixup_type(p->ainsn.insn);
+       int fixup = probe_get_fixup_type(p->ainsn.insn);
 
        if (fixup & FIXUP_PSW_NORMAL)
                ip += (unsigned long) p->addr - (unsigned long) p->ainsn.insn;
@@ -789,11 +641,6 @@ void __kprobes jprobe_return(void)
        asm volatile(".word 0x0002");
 }
 
-static void __used __kprobes jprobe_return_end(void)
-{
-       asm volatile("bcr 0,0");
-}
-
 int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
 {
        struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
index 719e27b2cf2264b4000d65635ad26b6e06284043..4685337fa7c6bf9464630f5ec648ca65e53cea0c 100644 (file)
@@ -25,6 +25,7 @@
 #include <asm/elf.h>
 #include <asm/asm-offsets.h>
 #include <asm/os_info.h>
+#include <asm/switch_to.h>
 
 typedef void (*relocate_kernel_t)(kimage_entry_t *, unsigned long);
 
@@ -43,7 +44,7 @@ static void add_elf_notes(int cpu)
 
        memcpy((void *) (4608UL + sa->pref_reg), sa, sizeof(*sa));
        ptr = (u64 *) per_cpu_ptr(crash_notes, cpu);
-       ptr = fill_cpu_elf_notes(ptr, sa);
+       ptr = fill_cpu_elf_notes(ptr, sa, NULL);
        memset(ptr, 0, sizeof(struct elf_note));
 }
 
@@ -53,8 +54,11 @@ static void add_elf_notes(int cpu)
 static void setup_regs(void)
 {
        unsigned long sa = S390_lowcore.prefixreg_save_area + SAVE_AREA_BASE;
+       struct _lowcore *lc;
        int cpu, this_cpu;
 
+       /* Get lowcore pointer from store status of this CPU (absolute zero) */
+       lc = (struct _lowcore *)(unsigned long)S390_lowcore.prefixreg_save_area;
        this_cpu = smp_find_processor_id(stap());
        add_elf_notes(this_cpu);
        for_each_online_cpu(cpu) {
@@ -64,6 +68,8 @@ static void setup_regs(void)
                        continue;
                add_elf_notes(cpu);
        }
+       if (MACHINE_HAS_VX)
+               save_vx_regs_safe((void *) lc->vector_save_area_addr);
        /* Copy dump CPU store status info to absolute zero */
        memcpy((void *) SAVE_AREA_BASE, (void *) sa, sizeof(struct save_area));
 }
index 433c6dbfa442439b1b7cd5ce8c8b5a9e5566b44d..4300ea3748263d582d3baee7f1cdf8a7e2499dd6 100644 (file)
@@ -8,62 +8,72 @@
 #include <linux/linkage.h>
 #include <asm/asm-offsets.h>
 #include <asm/ftrace.h>
+#include <asm/ptrace.h>
 
        .section .kprobes.text, "ax"
 
 ENTRY(ftrace_stub)
        br      %r14
 
+#define STACK_FRAME_SIZE  (STACK_FRAME_OVERHEAD + __PT_SIZE)
+#define STACK_PTREGS     (STACK_FRAME_OVERHEAD)
+#define STACK_PTREGS_GPRS (STACK_PTREGS + __PT_GPRS)
+#define STACK_PTREGS_PSW  (STACK_PTREGS + __PT_PSW)
+
 ENTRY(_mcount)
-#ifdef CONFIG_DYNAMIC_FTRACE
        br      %r14
 
 ENTRY(ftrace_caller)
+       .globl  ftrace_regs_caller
+       .set    ftrace_regs_caller,ftrace_caller
+       lgr     %r1,%r15
+       aghi    %r15,-STACK_FRAME_SIZE
+       stg     %r1,__SF_BACKCHAIN(%r15)
+       stg     %r1,(STACK_PTREGS_GPRS+15*8)(%r15)
+       stg     %r0,(STACK_PTREGS_PSW+8)(%r15)
+       stmg    %r2,%r14,(STACK_PTREGS_GPRS+2*8)(%r15)
+#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES
+       aghik   %r2,%r0,-MCOUNT_INSN_SIZE
+       lgrl    %r4,function_trace_op
+       lgrl    %r1,ftrace_trace_function
+#else
+       lgr     %r2,%r0
+       aghi    %r2,-MCOUNT_INSN_SIZE
+       larl    %r4,function_trace_op
+       lg      %r4,0(%r4)
+       larl    %r1,ftrace_trace_function
+       lg      %r1,0(%r1)
 #endif
-       stm     %r2,%r5,16(%r15)
-       bras    %r1,1f
-0:     .long   ftrace_trace_function
-1:     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)
-       ahi     %r2,-MCOUNT_INSN_SIZE
-       l       %r14,0b-0b(%r1)
-       l       %r14,0(%r14)
-       basr    %r14,%r14
+       lgr     %r3,%r14
+       la      %r5,STACK_PTREGS(%r15)
+       basr    %r14,%r1
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
-       l       %r2,100(%r15)
-       l       %r3,152(%r15)
+# The j instruction gets runtime patched to a nop instruction.
+# See ftrace_enable_ftrace_graph_caller.
 ENTRY(ftrace_graph_caller)
-# The bras instruction gets runtime patched to call prepare_ftrace_return.
-# See ftrace_enable_ftrace_graph_caller. The patched instruction is:
-#      bras    %r14,prepare_ftrace_return
-       bras    %r14,0f
-0:     st      %r2,100(%r15)
+       j       ftrace_graph_caller_end
+       lg      %r2,(STACK_PTREGS_GPRS+14*8)(%r15)
+       lg      %r3,(STACK_PTREGS_PSW+8)(%r15)
+       brasl   %r14,prepare_ftrace_return
+       stg     %r2,(STACK_PTREGS_GPRS+14*8)(%r15)
+ftrace_graph_caller_end:
+       .globl  ftrace_graph_caller_end
 #endif
-       ahi     %r15,96
-       l       %r14,56(%r15)
-       lm      %r2,%r5,16(%r15)
-       br      %r14
+       lg      %r1,(STACK_PTREGS_PSW+8)(%r15)
+       lmg     %r2,%r15,(STACK_PTREGS_GPRS+2*8)(%r15)
+       br      %r1
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 
 ENTRY(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)
+       stmg    %r2,%r5,32(%r15)
+       lgr     %r1,%r15
+       aghi    %r15,-STACK_FRAME_OVERHEAD
+       stg     %r1,__SF_BACKCHAIN(%r15)
+       brasl   %r14,ftrace_return_to_handler
+       aghi    %r15,STACK_FRAME_OVERHEAD
+       lgr     %r14,%r2
+       lmg     %r2,%r5,32(%r15)
        br      %r14
 
 #endif
diff --git a/arch/s390/kernel/mcount64.S b/arch/s390/kernel/mcount64.S
deleted file mode 100644 (file)
index c67a8bf..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright IBM Corp. 2008, 2009
- *
- *   Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>,
- *
- */
-
-#include <linux/linkage.h>
-#include <asm/asm-offsets.h>
-#include <asm/ftrace.h>
-
-       .section .kprobes.text, "ax"
-
-ENTRY(ftrace_stub)
-       br      %r14
-
-ENTRY(_mcount)
-#ifdef CONFIG_DYNAMIC_FTRACE
-       br      %r14
-
-ENTRY(ftrace_caller)
-#endif
-       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)
-       aghi    %r2,-MCOUNT_INSN_SIZE
-       larl    %r14,ftrace_trace_function
-       lg      %r14,0(%r14)
-       basr    %r14,%r14
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
-       lg      %r2,168(%r15)
-       lg      %r3,272(%r15)
-ENTRY(ftrace_graph_caller)
-# The bras instruction gets runtime patched to call prepare_ftrace_return.
-# See ftrace_enable_ftrace_graph_caller. The patched instruction is:
-#      bras    %r14,prepare_ftrace_return
-       bras    %r14,0f
-0:     stg     %r2,168(%r15)
-#endif
-       aghi    %r15,160
-       lmg     %r2,%r5,32(%r15)
-       lg      %r14,112(%r15)
-       br      %r14
-
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
-
-ENTRY(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
index 210e1285f75a44e4fb931e527bdf786eeba6c5ee..db96b418160a0260e305e54d73190097e3dce4f0 100644 (file)
@@ -20,6 +20,7 @@
 #include <asm/cputime.h>
 #include <asm/nmi.h>
 #include <asm/crw.h>
+#include <asm/switch_to.h>
 
 struct mcck_struct {
        int kill_task;
@@ -163,6 +164,21 @@ static int notrace s390_revalidate_registers(struct mci *mci)
                        "       ld      15,120(%0)\n"
                        : : "a" (fpt_save_area));
        }
+
+#ifdef CONFIG_64BIT
+       /* Revalidate vector registers */
+       if (MACHINE_HAS_VX && current->thread.vxrs) {
+               if (!mci->vr) {
+                       /*
+                        * Vector registers can't be restored and therefore
+                        * the process needs to be terminated.
+                        */
+                       kill_task = 1;
+               }
+               restore_vx_regs((__vector128 *)
+                               S390_lowcore.vector_save_area_addr);
+       }
+#endif
        /* Revalidate access registers */
        asm volatile(
                "       lam     0,15,0(%0)"
index 813ec7260878662d097ba90ef04d90b6f183367d..f6f8886399f64e1ebcf7a6a2662451286ecc1ec1 100644 (file)
@@ -49,7 +49,7 @@ PGM_CHECK_DEFAULT                     /* 17 */
 PGM_CHECK_64BIT(transaction_exception) /* 18 */
 PGM_CHECK_DEFAULT                      /* 19 */
 PGM_CHECK_DEFAULT                      /* 1a */
-PGM_CHECK_DEFAULT                      /* 1b */
+PGM_CHECK_64BIT(vector_exception)      /* 1b */
 PGM_CHECK(space_switch_exception)      /* 1c */
 PGM_CHECK(hfp_sqrt_exception)          /* 1d */
 PGM_CHECK_DEFAULT                      /* 1e */
index 93b9ca42e5c0ace2ac209789befa3242850b0043..ed84cc224899ff76ca30e5755d7cf7f2a734d981 100644 (file)
@@ -61,30 +61,6 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
        return sf->gprs[8];
 }
 
-void arch_cpu_idle(void)
-{
-       local_mcck_disable();
-       if (test_cpu_flag(CIF_MCCK_PENDING)) {
-               local_mcck_enable();
-               local_irq_enable();
-               return;
-       }
-       /* Halt the cpu and keep track of cpu time accounting. */
-       vtime_stop_cpu();
-       local_irq_enable();
-}
-
-void arch_cpu_idle_exit(void)
-{
-       if (test_cpu_flag(CIF_MCCK_PENDING))
-               s390_handle_mcck();
-}
-
-void arch_cpu_idle_dead(void)
-{
-       cpu_die();
-}
-
 extern void __kprobes kernel_thread_starter(void);
 
 /*
index 24612029f4502064b64c53ba52426c52a9337adc..edefead3b43a55dee5e197fae4a68011a1c3c41c 100644 (file)
@@ -23,7 +23,6 @@ static DEFINE_PER_CPU(struct cpuid, cpu_id);
  */
 void cpu_init(void)
 {
-       struct s390_idle_data *idle = &__get_cpu_var(s390_idle);
        struct cpuid *id = &__get_cpu_var(cpu_id);
 
        get_cpu_id(id);
@@ -31,7 +30,6 @@ void cpu_init(void)
        current->active_mm = &init_mm;
        BUG_ON(current->mm);
        enter_lazy_tlb(&init_mm, current);
-       memset(idle, 0, sizeof(*idle));
 }
 
 /*
@@ -41,7 +39,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 {
        static const char *hwcap_str[] = {
                "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp",
-               "edat", "etf3eh", "highgprs", "te"
+               "edat", "etf3eh", "highgprs", "te", "vx"
        };
        unsigned long n = (unsigned long) v - 1;
        int i;
index 5dc7ad9e2fbf2d1b035194b30db18a82957c1358..f537e937a9882f74f61a4830651bbd1abd4ddc66 100644 (file)
 #define CREATE_TRACE_POINTS
 #include <trace/events/syscalls.h>
 
-enum s390_regset {
-       REGSET_GENERAL,
-       REGSET_FP,
-       REGSET_LAST_BREAK,
-       REGSET_TDB,
-       REGSET_SYSTEM_CALL,
-       REGSET_GENERAL_EXTENDED,
-};
-
 void update_cr_regs(struct task_struct *task)
 {
        struct pt_regs *regs = task_pt_regs(task);
@@ -55,27 +46,39 @@ void update_cr_regs(struct task_struct *task)
 
 #ifdef CONFIG_64BIT
        /* Take care of the enable/disable of transactional execution. */
-       if (MACHINE_HAS_TE) {
+       if (MACHINE_HAS_TE || MACHINE_HAS_VX) {
                unsigned long cr, cr_new;
 
                __ctl_store(cr, 0, 0);
-               /* Set or clear transaction execution TXC bit 8. */
-               cr_new = cr | (1UL << 55);
-               if (task->thread.per_flags & PER_FLAG_NO_TE)
-                       cr_new &= ~(1UL << 55);
+               cr_new = cr;
+               if (MACHINE_HAS_TE) {
+                       /* Set or clear transaction execution TXC bit 8. */
+                       cr_new |= (1UL << 55);
+                       if (task->thread.per_flags & PER_FLAG_NO_TE)
+                               cr_new &= ~(1UL << 55);
+               }
+               if (MACHINE_HAS_VX) {
+                       /* Enable/disable of vector extension */
+                       cr_new &= ~(1UL << 17);
+                       if (task->thread.vxrs)
+                               cr_new |= (1UL << 17);
+               }
                if (cr_new != cr)
                        __ctl_load(cr_new, 0, 0);
-               /* Set or clear transaction execution TDC bits 62 and 63. */
-               __ctl_store(cr, 2, 2);
-               cr_new = cr & ~3UL;
-               if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND) {
-                       if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND_TEND)
-                               cr_new |= 1UL;
-                       else
-                               cr_new |= 2UL;
+               if (MACHINE_HAS_TE) {
+                       /* Set/clear transaction execution TDC bits 62/63. */
+                       __ctl_store(cr, 2, 2);
+                       cr_new = cr & ~3UL;
+                       if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND) {
+                               if (task->thread.per_flags &
+                                   PER_FLAG_TE_ABORT_RAND_TEND)
+                                       cr_new |= 1UL;
+                               else
+                                       cr_new |= 2UL;
+                       }
+                       if (cr_new != cr)
+                               __ctl_load(cr_new, 2, 2);
                }
-               if (cr_new != cr)
-                       __ctl_load(cr_new, 2, 2);
        }
 #endif
        /* Copy user specified PER registers */
@@ -84,7 +87,8 @@ void update_cr_regs(struct task_struct *task)
        new.end = thread->per_user.end;
 
        /* merge TIF_SINGLE_STEP into user specified PER registers. */
-       if (test_tsk_thread_flag(task, TIF_SINGLE_STEP)) {
+       if (test_tsk_thread_flag(task, TIF_SINGLE_STEP) ||
+           test_tsk_thread_flag(task, TIF_UPROBE_SINGLESTEP)) {
                if (test_tsk_thread_flag(task, TIF_BLOCK_STEP))
                        new.control |= PER_EVENT_BRANCH;
                else
@@ -93,6 +97,8 @@ void update_cr_regs(struct task_struct *task)
                new.control |= PER_CONTROL_SUSPENSION;
                new.control |= PER_EVENT_TRANSACTION_END;
 #endif
+               if (test_tsk_thread_flag(task, TIF_UPROBE_SINGLESTEP))
+                       new.control |= PER_EVENT_IFETCH;
                new.start = 0;
                new.end = PSW_ADDR_INSN;
        }
@@ -803,7 +809,7 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
        long ret = 0;
 
        /* Do the secure computing check first. */
-       if (secure_computing(regs->gprs[2])) {
+       if (secure_computing()) {
                /* seccomp failures shouldn't expose any additional code. */
                ret = -1;
                goto out;
@@ -923,7 +929,15 @@ static int s390_fpregs_get(struct task_struct *target,
                save_fp_ctl(&target->thread.fp_regs.fpc);
                save_fp_regs(target->thread.fp_regs.fprs);
        }
+#ifdef CONFIG_64BIT
+       else if (target->thread.vxrs) {
+               int i;
 
+               for (i = 0; i < __NUM_VXRS_LOW; i++)
+                       target->thread.fp_regs.fprs[i] =
+                               *(freg_t *)(target->thread.vxrs + i);
+       }
+#endif
        return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
                                   &target->thread.fp_regs, 0, -1);
 }
@@ -957,9 +971,20 @@ static int s390_fpregs_set(struct task_struct *target,
                                        target->thread.fp_regs.fprs,
                                        offsetof(s390_fp_regs, fprs), -1);
 
-       if (rc == 0 && target == current) {
-               restore_fp_ctl(&target->thread.fp_regs.fpc);
-               restore_fp_regs(target->thread.fp_regs.fprs);
+       if (rc == 0) {
+               if (target == current) {
+                       restore_fp_ctl(&target->thread.fp_regs.fpc);
+                       restore_fp_regs(target->thread.fp_regs.fprs);
+               }
+#ifdef CONFIG_64BIT
+               else if (target->thread.vxrs) {
+                       int i;
+
+                       for (i = 0; i < __NUM_VXRS_LOW; i++)
+                               *(freg_t *)(target->thread.vxrs + i) =
+                                       target->thread.fp_regs.fprs[i];
+               }
+#endif
        }
 
        return rc;
@@ -1015,6 +1040,95 @@ static int s390_tdb_set(struct task_struct *target,
        return 0;
 }
 
+static int s390_vxrs_active(struct task_struct *target,
+                             const struct user_regset *regset)
+{
+       return !!target->thread.vxrs;
+}
+
+static int s390_vxrs_low_get(struct task_struct *target,
+                            const struct user_regset *regset,
+                            unsigned int pos, unsigned int count,
+                            void *kbuf, void __user *ubuf)
+{
+       __u64 vxrs[__NUM_VXRS_LOW];
+       int i;
+
+       if (target->thread.vxrs) {
+               if (target == current)
+                       save_vx_regs(target->thread.vxrs);
+               for (i = 0; i < __NUM_VXRS_LOW; i++)
+                       vxrs[i] = *((__u64 *)(target->thread.vxrs + i) + 1);
+       } else
+               memset(vxrs, 0, sizeof(vxrs));
+       return user_regset_copyout(&pos, &count, &kbuf, &ubuf, vxrs, 0, -1);
+}
+
+static int s390_vxrs_low_set(struct task_struct *target,
+                            const struct user_regset *regset,
+                            unsigned int pos, unsigned int count,
+                            const void *kbuf, const void __user *ubuf)
+{
+       __u64 vxrs[__NUM_VXRS_LOW];
+       int i, rc;
+
+       if (!target->thread.vxrs) {
+               rc = alloc_vector_registers(target);
+               if (rc)
+                       return rc;
+       } else if (target == current)
+               save_vx_regs(target->thread.vxrs);
+
+       rc = user_regset_copyin(&pos, &count, &kbuf, &ubuf, vxrs, 0, -1);
+       if (rc == 0) {
+               for (i = 0; i < __NUM_VXRS_LOW; i++)
+                       *((__u64 *)(target->thread.vxrs + i) + 1) = vxrs[i];
+               if (target == current)
+                       restore_vx_regs(target->thread.vxrs);
+       }
+
+       return rc;
+}
+
+static int s390_vxrs_high_get(struct task_struct *target,
+                             const struct user_regset *regset,
+                             unsigned int pos, unsigned int count,
+                             void *kbuf, void __user *ubuf)
+{
+       __vector128 vxrs[__NUM_VXRS_HIGH];
+
+       if (target->thread.vxrs) {
+               if (target == current)
+                       save_vx_regs(target->thread.vxrs);
+               memcpy(vxrs, target->thread.vxrs + __NUM_VXRS_LOW,
+                      sizeof(vxrs));
+       } else
+               memset(vxrs, 0, sizeof(vxrs));
+       return user_regset_copyout(&pos, &count, &kbuf, &ubuf, vxrs, 0, -1);
+}
+
+static int s390_vxrs_high_set(struct task_struct *target,
+                             const struct user_regset *regset,
+                             unsigned int pos, unsigned int count,
+                             const void *kbuf, const void __user *ubuf)
+{
+       int rc;
+
+       if (!target->thread.vxrs) {
+               rc = alloc_vector_registers(target);
+               if (rc)
+                       return rc;
+       } else if (target == current)
+               save_vx_regs(target->thread.vxrs);
+
+       rc = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+                               target->thread.vxrs + __NUM_VXRS_LOW, 0, -1);
+       if (rc == 0 && target == current)
+               restore_vx_regs(target->thread.vxrs);
+
+       return rc;
+}
+
 #endif
 
 static int s390_system_call_get(struct task_struct *target,
@@ -1038,7 +1152,7 @@ static int s390_system_call_set(struct task_struct *target,
 }
 
 static const struct user_regset s390_regsets[] = {
-       [REGSET_GENERAL] = {
+       {
                .core_note_type = NT_PRSTATUS,
                .n = sizeof(s390_regs) / sizeof(long),
                .size = sizeof(long),
@@ -1046,7 +1160,7 @@ static const struct user_regset s390_regsets[] = {
                .get = s390_regs_get,
                .set = s390_regs_set,
        },
-       [REGSET_FP] = {
+       {
                .core_note_type = NT_PRFPREG,
                .n = sizeof(s390_fp_regs) / sizeof(long),
                .size = sizeof(long),
@@ -1054,8 +1168,16 @@ static const struct user_regset s390_regsets[] = {
                .get = s390_fpregs_get,
                .set = s390_fpregs_set,
        },
+       {
+               .core_note_type = NT_S390_SYSTEM_CALL,
+               .n = 1,
+               .size = sizeof(unsigned int),
+               .align = sizeof(unsigned int),
+               .get = s390_system_call_get,
+               .set = s390_system_call_set,
+       },
 #ifdef CONFIG_64BIT
-       [REGSET_LAST_BREAK] = {
+       {
                .core_note_type = NT_S390_LAST_BREAK,
                .n = 1,
                .size = sizeof(long),
@@ -1063,7 +1185,7 @@ static const struct user_regset s390_regsets[] = {
                .get = s390_last_break_get,
                .set = s390_last_break_set,
        },
-       [REGSET_TDB] = {
+       {
                .core_note_type = NT_S390_TDB,
                .n = 1,
                .size = 256,
@@ -1071,15 +1193,25 @@ static const struct user_regset s390_regsets[] = {
                .get = s390_tdb_get,
                .set = s390_tdb_set,
        },
-#endif
-       [REGSET_SYSTEM_CALL] = {
-               .core_note_type = NT_S390_SYSTEM_CALL,
-               .n = 1,
-               .size = sizeof(unsigned int),
-               .align = sizeof(unsigned int),
-               .get = s390_system_call_get,
-               .set = s390_system_call_set,
+       {
+               .core_note_type = NT_S390_VXRS_LOW,
+               .n = __NUM_VXRS_LOW,
+               .size = sizeof(__u64),
+               .align = sizeof(__u64),
+               .active = s390_vxrs_active,
+               .get = s390_vxrs_low_get,
+               .set = s390_vxrs_low_set,
        },
+       {
+               .core_note_type = NT_S390_VXRS_HIGH,
+               .n = __NUM_VXRS_HIGH,
+               .size = sizeof(__vector128),
+               .align = sizeof(__vector128),
+               .active = s390_vxrs_active,
+               .get = s390_vxrs_high_get,
+               .set = s390_vxrs_high_set,
+       },
+#endif
 };
 
 static const struct user_regset_view user_s390_view = {
@@ -1244,7 +1376,7 @@ static int s390_compat_last_break_set(struct task_struct *target,
 }
 
 static const struct user_regset s390_compat_regsets[] = {
-       [REGSET_GENERAL] = {
+       {
                .core_note_type = NT_PRSTATUS,
                .n = sizeof(s390_compat_regs) / sizeof(compat_long_t),
                .size = sizeof(compat_long_t),
@@ -1252,7 +1384,7 @@ static const struct user_regset s390_compat_regsets[] = {
                .get = s390_compat_regs_get,
                .set = s390_compat_regs_set,
        },
-       [REGSET_FP] = {
+       {
                .core_note_type = NT_PRFPREG,
                .n = sizeof(s390_fp_regs) / sizeof(compat_long_t),
                .size = sizeof(compat_long_t),
@@ -1260,7 +1392,15 @@ static const struct user_regset s390_compat_regsets[] = {
                .get = s390_fpregs_get,
                .set = s390_fpregs_set,
        },
-       [REGSET_LAST_BREAK] = {
+       {
+               .core_note_type = NT_S390_SYSTEM_CALL,
+               .n = 1,
+               .size = sizeof(compat_uint_t),
+               .align = sizeof(compat_uint_t),
+               .get = s390_system_call_get,
+               .set = s390_system_call_set,
+       },
+       {
                .core_note_type = NT_S390_LAST_BREAK,
                .n = 1,
                .size = sizeof(long),
@@ -1268,7 +1408,7 @@ static const struct user_regset s390_compat_regsets[] = {
                .get = s390_compat_last_break_get,
                .set = s390_compat_last_break_set,
        },
-       [REGSET_TDB] = {
+       {
                .core_note_type = NT_S390_TDB,
                .n = 1,
                .size = 256,
@@ -1276,15 +1416,25 @@ static const struct user_regset s390_compat_regsets[] = {
                .get = s390_tdb_get,
                .set = s390_tdb_set,
        },
-       [REGSET_SYSTEM_CALL] = {
-               .core_note_type = NT_S390_SYSTEM_CALL,
-               .n = 1,
-               .size = sizeof(compat_uint_t),
-               .align = sizeof(compat_uint_t),
-               .get = s390_system_call_get,
-               .set = s390_system_call_set,
+       {
+               .core_note_type = NT_S390_VXRS_LOW,
+               .n = __NUM_VXRS_LOW,
+               .size = sizeof(__u64),
+               .align = sizeof(__u64),
+               .active = s390_vxrs_active,
+               .get = s390_vxrs_low_get,
+               .set = s390_vxrs_low_set,
+       },
+       {
+               .core_note_type = NT_S390_VXRS_HIGH,
+               .n = __NUM_VXRS_HIGH,
+               .size = sizeof(__vector128),
+               .align = sizeof(__vector128),
+               .active = s390_vxrs_active,
+               .get = s390_vxrs_high_get,
+               .set = s390_vxrs_high_set,
        },
-       [REGSET_GENERAL_EXTENDED] = {
+       {
                .core_note_type = NT_S390_HIGH_GPRS,
                .n = sizeof(s390_compat_regs_high) / sizeof(compat_long_t),
                .size = sizeof(compat_long_t),
index 82bc113e8c1dd3718cf663a88d7bc9a2c9c97fb4..e80d9ff9a56d41b15055e3270234c4683f7f7d91 100644 (file)
@@ -343,6 +343,9 @@ static void __init setup_lowcore(void)
                __ctl_set_bit(14, 29);
        }
 #else
+       if (MACHINE_HAS_VX)
+               lc->vector_save_area_addr =
+                       (unsigned long) &lc->vector_save_area;
        lc->vdso_per_cpu_data = (unsigned long) &lc->paste[0];
 #endif
        lc->sync_enter_timer = S390_lowcore.sync_enter_timer;
@@ -452,8 +455,8 @@ static void __init setup_memory_end(void)
 #ifdef CONFIG_64BIT
        vmalloc_size = VMALLOC_END ?: (128UL << 30) - MODULES_LEN;
        tmp = (memory_end ?: max_physmem_end) / PAGE_SIZE;
-       tmp = tmp * (sizeof(struct page) + PAGE_SIZE) + vmalloc_size;
-       if (tmp <= (1UL << 42))
+       tmp = tmp * (sizeof(struct page) + PAGE_SIZE);
+       if (tmp + vmalloc_size + MODULES_LEN <= (1UL << 42))
                vmax = 1UL << 42;       /* 3-level kernel page table */
        else
                vmax = 1UL << 53;       /* 4-level kernel page table */
@@ -765,6 +768,12 @@ static void __init setup_hwcaps(void)
         */
        if (test_facility(50) && test_facility(73))
                elf_hwcap |= HWCAP_S390_TE;
+
+       /*
+        * Vector extension HWCAP_S390_VXRS is bit 11.
+        */
+       if (test_facility(129))
+               elf_hwcap |= HWCAP_S390_VXRS;
 #endif
 
        get_cpu_id(&cpu_id);
index 469c4c6d91822f32c2512551d6c8c29026ff8462..0c1a0ff0a558bda9a389091f86628fb8b0f825bc 100644 (file)
 #include <asm/switch_to.h>
 #include "entry.h"
 
-typedef struct 
+/*
+ * Layout of an old-style signal-frame:
+ *     -----------------------------------------
+ *     | save area (_SIGNAL_FRAMESIZE)         |
+ *     -----------------------------------------
+ *     | struct sigcontext                     |
+ *     |       oldmask                         |
+ *     |       _sigregs *                      |
+ *     -----------------------------------------
+ *     | _sigregs with                         |
+ *     |       _s390_regs_common               |
+ *     |       _s390_fp_regs                   |
+ *     -----------------------------------------
+ *     | int signo                             |
+ *     -----------------------------------------
+ *     | _sigregs_ext with                     |
+ *     |       gprs_high 64 byte (opt)         |
+ *     |       vxrs_low 128 byte (opt)         |
+ *     |       vxrs_high 256 byte (opt)        |
+ *     |       reserved 128 byte (opt)         |
+ *     -----------------------------------------
+ *     | __u16 svc_insn                        |
+ *     -----------------------------------------
+ * The svc_insn entry with the sigreturn system call opcode does not
+ * have a fixed position and moves if gprs_high or vxrs exist.
+ * Future extensions will be added to _sigregs_ext.
+ */
+struct sigframe
 {
        __u8 callee_used_stack[__SIGNAL_FRAMESIZE];
        struct sigcontext sc;
        _sigregs sregs;
        int signo;
-       __u8 retcode[S390_SYSCALL_SIZE];
-} sigframe;
+       _sigregs_ext sregs_ext;
+       __u16 svc_insn;         /* Offset of svc_insn is NOT fixed! */
+};
 
-typedef struct 
+/*
+ * Layout of an rt signal-frame:
+ *     -----------------------------------------
+ *     | save area (_SIGNAL_FRAMESIZE)         |
+ *     -----------------------------------------
+ *     | svc __NR_rt_sigreturn 2 byte          |
+ *     -----------------------------------------
+ *     | struct siginfo                        |
+ *     -----------------------------------------
+ *     | struct ucontext_extended with         |
+ *     |       unsigned long uc_flags          |
+ *     |       struct ucontext *uc_link        |
+ *     |       stack_t uc_stack                |
+ *     |       _sigregs uc_mcontext with       |
+ *     |               _s390_regs_common       |
+ *     |               _s390_fp_regs           |
+ *     |       sigset_t uc_sigmask             |
+ *     |       _sigregs_ext uc_mcontext_ext    |
+ *     |               gprs_high 64 byte (opt) |
+ *     |               vxrs_low 128 byte (opt) |
+ *     |               vxrs_high 256 byte (opt)|
+ *     |               reserved 128 byte (opt) |
+ *     -----------------------------------------
+ * Future extensions will be added to _sigregs_ext.
+ */
+struct rt_sigframe
 {
        __u8 callee_used_stack[__SIGNAL_FRAMESIZE];
-       __u8 retcode[S390_SYSCALL_SIZE];
+       __u16 svc_insn;
        struct siginfo info;
-       struct ucontext uc;
-} rt_sigframe;
+       struct ucontext_extended uc;
+};
+
+/* Store registers needed to create the signal frame */
+static void store_sigregs(void)
+{
+       save_access_regs(current->thread.acrs);
+       save_fp_ctl(&current->thread.fp_regs.fpc);
+#ifdef CONFIG_64BIT
+       if (current->thread.vxrs) {
+               int i;
+
+               save_vx_regs(current->thread.vxrs);
+               for (i = 0; i < __NUM_FPRS; i++)
+                       current->thread.fp_regs.fprs[i] =
+                               *(freg_t *)(current->thread.vxrs + i);
+       } else
+#endif
+               save_fp_regs(current->thread.fp_regs.fprs);
+}
+
+/* Load registers after signal return */
+static void load_sigregs(void)
+{
+       restore_access_regs(current->thread.acrs);
+       /* restore_fp_ctl is done in restore_sigregs */
+#ifdef CONFIG_64BIT
+       if (current->thread.vxrs) {
+               int i;
+
+               for (i = 0; i < __NUM_FPRS; i++)
+                       *(freg_t *)(current->thread.vxrs + i) =
+                               current->thread.fp_regs.fprs[i];
+               restore_vx_regs(current->thread.vxrs);
+       } else
+#endif
+               restore_fp_regs(current->thread.fp_regs.fprs);
+}
 
 /* Returns non-zero on fault. */
 static int save_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
 {
        _sigregs user_sregs;
 
-       save_access_regs(current->thread.acrs);
-
        /* Copy a 'clean' PSW mask to the user to avoid leaking
           information about whether PER is currently on.  */
        user_sregs.regs.psw.mask = PSW_USER_BITS |
@@ -63,12 +150,6 @@ static int save_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
        memcpy(&user_sregs.regs.gprs, &regs->gprs, sizeof(sregs->regs.gprs));
        memcpy(&user_sregs.regs.acrs, current->thread.acrs,
               sizeof(user_sregs.regs.acrs));
-       /* 
-        * We have to store the fp registers to current->thread.fp_regs
-        * to merge them with the emulated registers.
-        */
-       save_fp_ctl(&current->thread.fp_regs.fpc);
-       save_fp_regs(current->thread.fp_regs.fprs);
        memcpy(&user_sregs.fpregs, &current->thread.fp_regs,
               sizeof(user_sregs.fpregs));
        if (__copy_to_user(sregs, &user_sregs, sizeof(_sigregs)))
@@ -107,20 +188,64 @@ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
        memcpy(&regs->gprs, &user_sregs.regs.gprs, sizeof(sregs->regs.gprs));
        memcpy(&current->thread.acrs, &user_sregs.regs.acrs,
               sizeof(current->thread.acrs));
-       restore_access_regs(current->thread.acrs);
 
        memcpy(&current->thread.fp_regs, &user_sregs.fpregs,
               sizeof(current->thread.fp_regs));
 
-       restore_fp_regs(current->thread.fp_regs.fprs);
        clear_pt_regs_flag(regs, PIF_SYSCALL); /* No longer in a system call */
        return 0;
 }
 
+/* Returns non-zero on fault. */
+static int save_sigregs_ext(struct pt_regs *regs,
+                           _sigregs_ext __user *sregs_ext)
+{
+#ifdef CONFIG_64BIT
+       __u64 vxrs[__NUM_VXRS_LOW];
+       int i;
+
+       /* Save vector registers to signal stack */
+       if (current->thread.vxrs) {
+               for (i = 0; i < __NUM_VXRS_LOW; i++)
+                       vxrs[i] = *((__u64 *)(current->thread.vxrs + i) + 1);
+               if (__copy_to_user(&sregs_ext->vxrs_low, vxrs,
+                                  sizeof(sregs_ext->vxrs_low)) ||
+                   __copy_to_user(&sregs_ext->vxrs_high,
+                                  current->thread.vxrs + __NUM_VXRS_LOW,
+                                  sizeof(sregs_ext->vxrs_high)))
+                       return -EFAULT;
+       }
+#endif
+       return 0;
+}
+
+static int restore_sigregs_ext(struct pt_regs *regs,
+                              _sigregs_ext __user *sregs_ext)
+{
+#ifdef CONFIG_64BIT
+       __u64 vxrs[__NUM_VXRS_LOW];
+       int i;
+
+       /* Restore vector registers from signal stack */
+       if (current->thread.vxrs) {
+               if (__copy_from_user(vxrs, &sregs_ext->vxrs_low,
+                                    sizeof(sregs_ext->vxrs_low)) ||
+                   __copy_from_user(current->thread.vxrs + __NUM_VXRS_LOW,
+                                    &sregs_ext->vxrs_high,
+                                    sizeof(sregs_ext->vxrs_high)))
+                       return -EFAULT;
+               for (i = 0; i < __NUM_VXRS_LOW; i++)
+                       *((__u64 *)(current->thread.vxrs + i) + 1) = vxrs[i];
+       }
+#endif
+       return 0;
+}
+
 SYSCALL_DEFINE0(sigreturn)
 {
        struct pt_regs *regs = task_pt_regs(current);
-       sigframe __user *frame = (sigframe __user *)regs->gprs[15];
+       struct sigframe __user *frame =
+               (struct sigframe __user *) regs->gprs[15];
        sigset_t set;
 
        if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE))
@@ -128,6 +253,9 @@ SYSCALL_DEFINE0(sigreturn)
        set_current_blocked(&set);
        if (restore_sigregs(regs, &frame->sregs))
                goto badframe;
+       if (restore_sigregs_ext(regs, &frame->sregs_ext))
+               goto badframe;
+       load_sigregs();
        return regs->gprs[2];
 badframe:
        force_sig(SIGSEGV, current);
@@ -137,27 +265,26 @@ badframe:
 SYSCALL_DEFINE0(rt_sigreturn)
 {
        struct pt_regs *regs = task_pt_regs(current);
-       rt_sigframe __user *frame = (rt_sigframe __user *)regs->gprs[15];
+       struct rt_sigframe __user *frame =
+               (struct rt_sigframe __user *)regs->gprs[15];
        sigset_t set;
 
        if (__copy_from_user(&set.sig, &frame->uc.uc_sigmask, sizeof(set)))
                goto badframe;
        set_current_blocked(&set);
+       if (restore_altstack(&frame->uc.uc_stack))
+               goto badframe;
        if (restore_sigregs(regs, &frame->uc.uc_mcontext))
                goto badframe;
-       if (restore_altstack(&frame->uc.uc_stack))
+       if (restore_sigregs_ext(regs, &frame->uc.uc_mcontext_ext))
                goto badframe;
+       load_sigregs();
        return regs->gprs[2];
 badframe:
        force_sig(SIGSEGV, current);
        return 0;
 }
 
-/*
- * Set up a signal frame.
- */
-
-
 /*
  * Determine which stack to use..
  */
@@ -195,39 +322,63 @@ static inline int map_signal(int sig)
 static int setup_frame(int sig, struct k_sigaction *ka,
                       sigset_t *set, struct pt_regs * regs)
 {
-       sigframe __user *frame;
-
-       frame = get_sigframe(ka, regs, sizeof(sigframe));
+       struct sigframe __user *frame;
+       struct sigcontext sc;
+       unsigned long restorer;
+       size_t frame_size;
 
+       /*
+        * gprs_high are only present for a 31-bit task running on
+        * a 64-bit kernel (see compat_signal.c) but the space for
+        * gprs_high need to be allocated if vector registers are
+        * included in the signal frame on a 31-bit system.
+        */
+       frame_size = sizeof(*frame) - sizeof(frame->sregs_ext);
+       if (MACHINE_HAS_VX)
+               frame_size += sizeof(frame->sregs_ext);
+       frame = get_sigframe(ka, regs, frame_size);
        if (frame == (void __user *) -1UL)
                return -EFAULT;
 
-       if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE))
+       /* Set up backchain. */
+       if (__put_user(regs->gprs[15], (addr_t __user *) frame))
                return -EFAULT;
 
+       /* Create struct sigcontext on the signal stack */
+       memcpy(&sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE);
+       sc.sregs = (_sigregs __user __force *) &frame->sregs;
+       if (__copy_to_user(&frame->sc, &sc, sizeof(frame->sc)))
+               return -EFAULT;
+
+       /* Store registers needed to create the signal frame */
+       store_sigregs();
+
+       /* Create _sigregs on the signal stack */
        if (save_sigregs(regs, &frame->sregs))
                return -EFAULT;
-       if (__put_user(&frame->sregs, &frame->sc.sregs))
+
+       /* Place signal number on stack to allow backtrace from handler.  */
+       if (__put_user(regs->gprs[2], (int __user *) &frame->signo))
+               return -EFAULT;
+
+       /* Create _sigregs_ext on the signal stack */
+       if (save_sigregs_ext(regs, &frame->sregs_ext))
                return -EFAULT;
 
        /* Set up to return from userspace.  If provided, use a stub
           already in userspace.  */
        if (ka->sa.sa_flags & SA_RESTORER) {
-                regs->gprs[14] = (unsigned long)
-                       ka->sa.sa_restorer | PSW_ADDR_AMODE;
+               restorer = (unsigned long) ka->sa.sa_restorer | PSW_ADDR_AMODE;
        } else {
-                regs->gprs[14] = (unsigned long)
-                       frame->retcode | PSW_ADDR_AMODE;
-               if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn,
-                              (u16 __user *)(frame->retcode)))
+               /* Signal frame without vector registers are short ! */
+               __u16 __user *svc = (void *) frame + frame_size - 2;
+               if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn, svc))
                        return -EFAULT;
+               restorer = (unsigned long) svc | PSW_ADDR_AMODE;
        }
 
-       /* Set up backchain. */
-       if (__put_user(regs->gprs[15], (addr_t __user *) frame))
-               return -EFAULT;
-
        /* Set up registers for signal handler */
+       regs->gprs[14] = restorer;
        regs->gprs[15] = (unsigned long) frame;
        /* Force default amode and default user address space control. */
        regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA |
@@ -247,54 +398,69 @@ static int setup_frame(int sig, struct k_sigaction *ka,
                regs->gprs[5] = regs->int_parm_long;
                regs->gprs[6] = task_thread_info(current)->last_break;
        }
-
-       /* Place signal number on stack to allow backtrace from handler.  */
-       if (__put_user(regs->gprs[2], (int __user *) &frame->signo))
-               return -EFAULT;
        return 0;
 }
 
 static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
                          struct pt_regs *regs)
 {
-       int err = 0;
-       rt_sigframe __user *frame;
-
-       frame = get_sigframe(&ksig->ka, regs, sizeof(rt_sigframe));
+       struct rt_sigframe __user *frame;
+       unsigned long uc_flags, restorer;
+       size_t frame_size;
 
+       frame_size = sizeof(struct rt_sigframe) - sizeof(_sigregs_ext);
+       /*
+        * gprs_high are only present for a 31-bit task running on
+        * a 64-bit kernel (see compat_signal.c) but the space for
+        * gprs_high need to be allocated if vector registers are
+        * included in the signal frame on a 31-bit system.
+        */
+       uc_flags = 0;
+#ifdef CONFIG_64BIT
+       if (MACHINE_HAS_VX) {
+               frame_size += sizeof(_sigregs_ext);
+               if (current->thread.vxrs)
+                       uc_flags |= UC_VXRS;
+       }
+#endif
+       frame = get_sigframe(&ksig->ka, regs, frame_size);
        if (frame == (void __user *) -1UL)
                return -EFAULT;
 
-       if (copy_siginfo_to_user(&frame->info, &ksig->info))
-               return -EFAULT;
-
-       /* Create the ucontext.  */
-       err |= __put_user(0, &frame->uc.uc_flags);
-       err |= __put_user(NULL, &frame->uc.uc_link);
-       err |= __save_altstack(&frame->uc.uc_stack, regs->gprs[15]);
-       err |= save_sigregs(regs, &frame->uc.uc_mcontext);
-       err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
-       if (err)
+       /* Set up backchain. */
+       if (__put_user(regs->gprs[15], (addr_t __user *) frame))
                return -EFAULT;
 
        /* Set up to return from userspace.  If provided, use a stub
           already in userspace.  */
        if (ksig->ka.sa.sa_flags & SA_RESTORER) {
-                regs->gprs[14] = (unsigned long)
+               restorer = (unsigned long)
                        ksig->ka.sa.sa_restorer | PSW_ADDR_AMODE;
        } else {
-                regs->gprs[14] = (unsigned long)
-                       frame->retcode | PSW_ADDR_AMODE;
-               if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
-                              (u16 __user *)(frame->retcode)))
+               __u16 __user *svc = &frame->svc_insn;
+               if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn, svc))
                        return -EFAULT;
+               restorer = (unsigned long) svc | PSW_ADDR_AMODE;
        }
 
-       /* Set up backchain. */
-       if (__put_user(regs->gprs[15], (addr_t __user *) frame))
+       /* Create siginfo on the signal stack */
+       if (copy_siginfo_to_user(&frame->info, &ksig->info))
+               return -EFAULT;
+
+       /* Store registers needed to create the signal frame */
+       store_sigregs();
+
+       /* Create ucontext on the signal stack. */
+       if (__put_user(uc_flags, &frame->uc.uc_flags) ||
+           __put_user(NULL, &frame->uc.uc_link) ||
+           __save_altstack(&frame->uc.uc_stack, regs->gprs[15]) ||
+           save_sigregs(regs, &frame->uc.uc_mcontext) ||
+           __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)) ||
+           save_sigregs_ext(regs, &frame->uc.uc_mcontext_ext))
                return -EFAULT;
 
        /* Set up registers for signal handler */
+       regs->gprs[14] = restorer;
        regs->gprs[15] = (unsigned long) frame;
        /* Force default amode and default user address space control. */
        regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA |
index 243c7e51260055c3de2a57e2852ed82de075f18f..6fd9e60101f1733cc3c84f010657561d4c895985 100644 (file)
@@ -45,6 +45,7 @@
 #include <asm/debug.h>
 #include <asm/os_info.h>
 #include <asm/sigp.h>
+#include <asm/idle.h>
 #include "entry.h"
 
 enum {
@@ -82,7 +83,8 @@ DEFINE_MUTEX(smp_cpu_state_mutex);
 /*
  * Signal processor helper functions.
  */
-static inline int __pcpu_sigp_relax(u16 addr, u8 order, u32 parm, u32 *status)
+static inline int __pcpu_sigp_relax(u16 addr, u8 order, unsigned long parm,
+                                   u32 *status)
 {
        int cc;
 
@@ -178,6 +180,9 @@ static int pcpu_alloc_lowcore(struct pcpu *pcpu, int cpu)
                        goto out;
        }
 #else
+       if (MACHINE_HAS_VX)
+               lc->vector_save_area_addr =
+                       (unsigned long) &lc->vector_save_area;
        if (vdso_alloc_per_cpu(lc))
                goto out;
 #endif
@@ -333,12 +338,6 @@ int smp_vcpu_scheduled(int cpu)
        return pcpu_running(pcpu_devices + cpu);
 }
 
-void smp_yield(void)
-{
-       if (MACHINE_HAS_DIAG44)
-               asm volatile("diag 0,0,0x44");
-}
-
 void smp_yield_cpu(int cpu)
 {
        if (MACHINE_HAS_DIAG9C)
@@ -517,35 +516,53 @@ EXPORT_SYMBOL(smp_ctl_clear_bit);
 static void __init smp_get_save_area(int cpu, u16 address)
 {
        void *lc = pcpu_devices[0].lowcore;
-       struct save_area *save_area;
+       struct save_area_ext *sa_ext;
+       unsigned long vx_sa;
 
        if (is_kdump_kernel())
                return;
        if (!OLDMEM_BASE && (address == boot_cpu_address ||
                             ipl_info.type != IPL_TYPE_FCP_DUMP))
                return;
-       save_area = dump_save_area_create(cpu);
-       if (!save_area)
+       sa_ext = dump_save_area_create(cpu);
+       if (!sa_ext)
                panic("could not allocate memory for save area\n");
        if (address == boot_cpu_address) {
                /* Copy the registers of the boot cpu. */
-               copy_oldmem_page(1, (void *) save_area, sizeof(*save_area),
+               copy_oldmem_page(1, (void *) &sa_ext->sa, sizeof(sa_ext->sa),
                                 SAVE_AREA_BASE - PAGE_SIZE, 0);
+               if (MACHINE_HAS_VX)
+                       save_vx_regs_safe(sa_ext->vx_regs);
                return;
        }
        /* Get the registers of a non-boot cpu. */
        __pcpu_sigp_relax(address, SIGP_STOP_AND_STORE_STATUS, 0, NULL);
-       memcpy_real(save_area, lc + SAVE_AREA_BASE, sizeof(*save_area));
+       memcpy_real(&sa_ext->sa, lc + SAVE_AREA_BASE, sizeof(sa_ext->sa));
+       if (!MACHINE_HAS_VX)
+               return;
+       /* Get the VX registers */
+       vx_sa = __get_free_page(GFP_KERNEL);
+       if (!vx_sa)
+               panic("could not allocate memory for VX save area\n");
+       __pcpu_sigp_relax(address, SIGP_STORE_ADDITIONAL_STATUS, vx_sa, NULL);
+       memcpy(sa_ext->vx_regs, (void *) vx_sa, sizeof(sa_ext->vx_regs));
+       free_page(vx_sa);
 }
 
 int smp_store_status(int cpu)
 {
+       unsigned long vx_sa;
        struct pcpu *pcpu;
 
        pcpu = pcpu_devices + cpu;
        if (__pcpu_sigp_relax(pcpu->address, SIGP_STOP_AND_STORE_STATUS,
                              0, NULL) != SIGP_CC_ORDER_CODE_ACCEPTED)
                return -EIO;
+       if (!MACHINE_HAS_VX)
+               return 0;
+       vx_sa = __pa(pcpu->lowcore->vector_save_area_addr);
+       __pcpu_sigp_relax(pcpu->address, SIGP_STORE_ADDITIONAL_STATUS,
+                         vx_sa, NULL);
        return 0;
 }
 
@@ -667,7 +684,7 @@ static void smp_start_secondary(void *cpuvoid)
        cpu_init();
        preempt_disable();
        init_cpu_timer();
-       init_cpu_vtimer();
+       vtime_init();
        pfault_init();
        notify_cpu_starting(smp_processor_id());
        set_cpu_online(smp_processor_id(), true);
@@ -726,6 +743,7 @@ int __cpu_disable(void)
        cregs[6]  &= ~0xff000000UL;     /* disable all I/O interrupts */
        cregs[14] &= ~0x1f000000UL;     /* disable most machine checks */
        __ctl_load(cregs, 0, 15);
+       clear_cpu_flag(CIF_NOHZ_DELAY);
        return 0;
 }
 
@@ -898,42 +916,6 @@ static struct attribute_group cpu_common_attr_group = {
        .attrs = cpu_common_attrs,
 };
 
-static ssize_t show_idle_count(struct device *dev,
-                               struct device_attribute *attr, char *buf)
-{
-       struct s390_idle_data *idle = &per_cpu(s390_idle, dev->id);
-       unsigned long long idle_count;
-       unsigned int sequence;
-
-       do {
-               sequence = ACCESS_ONCE(idle->sequence);
-               idle_count = ACCESS_ONCE(idle->idle_count);
-               if (ACCESS_ONCE(idle->clock_idle_enter))
-                       idle_count++;
-       } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence));
-       return sprintf(buf, "%llu\n", idle_count);
-}
-static DEVICE_ATTR(idle_count, 0444, show_idle_count, NULL);
-
-static ssize_t show_idle_time(struct device *dev,
-                               struct device_attribute *attr, char *buf)
-{
-       struct s390_idle_data *idle = &per_cpu(s390_idle, dev->id);
-       unsigned long long now, idle_time, idle_enter, idle_exit;
-       unsigned int sequence;
-
-       do {
-               now = get_tod_clock();
-               sequence = ACCESS_ONCE(idle->sequence);
-               idle_time = ACCESS_ONCE(idle->idle_time);
-               idle_enter = ACCESS_ONCE(idle->clock_idle_enter);
-               idle_exit = ACCESS_ONCE(idle->clock_idle_exit);
-       } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence));
-       idle_time += idle_enter ? ((idle_exit ? : now) - idle_enter) : 0;
-       return sprintf(buf, "%llu\n", idle_time >> 12);
-}
-static DEVICE_ATTR(idle_time_us, 0444, show_idle_time, NULL);
-
 static struct attribute *cpu_online_attrs[] = {
        &dev_attr_idle_count.attr,
        &dev_attr_idle_time_us.attr,
index 4cef607f371122fc2fcc7959bd6f12cff3d3d896..69e980de0f6282310e7978ee398a2a5a0d7184c6 100644 (file)
@@ -232,6 +232,19 @@ void update_vsyscall(struct timekeeper *tk)
                vdso_data->wtom_clock_nsec -= nsecps;
                vdso_data->wtom_clock_sec++;
        }
+
+       vdso_data->xtime_coarse_sec = tk->xtime_sec;
+       vdso_data->xtime_coarse_nsec =
+               (long)(tk->tkr.xtime_nsec >> tk->tkr.shift);
+       vdso_data->wtom_coarse_sec =
+               vdso_data->xtime_coarse_sec + tk->wall_to_monotonic.tv_sec;
+       vdso_data->wtom_coarse_nsec =
+               vdso_data->xtime_coarse_nsec + tk->wall_to_monotonic.tv_nsec;
+       while (vdso_data->wtom_coarse_nsec >= NSEC_PER_SEC) {
+               vdso_data->wtom_coarse_nsec -= NSEC_PER_SEC;
+               vdso_data->wtom_coarse_sec++;
+       }
+
        vdso_data->tk_mult = tk->tkr.mult;
        vdso_data->tk_shift = tk->tkr.shift;
        smp_wmb();
index 355a16c557026a21f50fbb39b51a5f1320b0773a..b93bed76ea94026d45c782eebe75c08dfb1a323d 100644 (file)
@@ -464,15 +464,17 @@ static struct sched_domain_topology_level s390_topology[] = {
 
 static int __init topology_init(void)
 {
-       if (!MACHINE_HAS_TOPOLOGY) {
+       if (MACHINE_HAS_TOPOLOGY)
+               set_topology_timer();
+       else
                topology_update_polarization_simple();
-               goto out;
-       }
-       set_topology_timer();
-out:
-
-       set_sched_topology(s390_topology);
-
        return device_create_file(cpu_subsys.dev_root, &dev_attr_dispatching);
 }
 device_initcall(topology_init);
+
+static int __init early_topology_init(void)
+{
+       set_sched_topology(s390_topology);
+       return 0;
+}
+early_initcall(early_topology_init);
index c5762324d9ee435367314d8fa2f03e32e2365f0e..9ff5ecba26aba803f3d8ad24196f61409bc99e2a 100644 (file)
@@ -18,6 +18,8 @@
 #include <linux/ptrace.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
+#include <linux/slab.h>
+#include <asm/switch_to.h>
 #include "entry.h"
 
 int show_unhandled_signals = 1;
@@ -58,15 +60,10 @@ int is_valid_bugaddr(unsigned long addr)
        return 1;
 }
 
-static void __kprobes do_trap(struct pt_regs *regs,
-                             int si_signo, int si_code, char *str)
+void do_report_trap(struct pt_regs *regs, int si_signo, int si_code, char *str)
 {
        siginfo_t info;
 
-       if (notify_die(DIE_TRAP, str, regs, 0,
-                      regs->int_code, si_signo) == NOTIFY_STOP)
-               return;
-
        if (user_mode(regs)) {
                info.si_signo = si_signo;
                info.si_errno = 0;
@@ -90,6 +87,15 @@ static void __kprobes do_trap(struct pt_regs *regs,
         }
 }
 
+static void __kprobes do_trap(struct pt_regs *regs, int si_signo, int si_code,
+                             char *str)
+{
+       if (notify_die(DIE_TRAP, str, regs, 0,
+                      regs->int_code, si_signo) == NOTIFY_STOP)
+               return;
+       do_report_trap(regs, si_signo, si_code, str);
+}
+
 void __kprobes do_per_trap(struct pt_regs *regs)
 {
        siginfo_t info;
@@ -178,6 +184,7 @@ void __kprobes illegal_op(struct pt_regs *regs)
        siginfo_t info;
         __u8 opcode[6];
        __u16 __user *location;
+       int is_uprobe_insn = 0;
        int signal = 0;
 
        location = get_trap_ip(regs);
@@ -194,6 +201,10 @@ void __kprobes illegal_op(struct pt_regs *regs)
                                force_sig_info(SIGTRAP, &info, current);
                        } else
                                signal = SIGILL;
+#ifdef CONFIG_UPROBES
+               } else if (*((__u16 *) opcode) == UPROBE_SWBP_INSN) {
+                       is_uprobe_insn = 1;
+#endif
 #ifdef CONFIG_MATHEMU
                } else if (opcode[0] == 0xb3) {
                        if (get_user(*((__u16 *) (opcode+2)), location+1))
@@ -219,11 +230,13 @@ void __kprobes illegal_op(struct pt_regs *regs)
 #endif
                } else
                        signal = SIGILL;
-       } else {
-               /*
-                * If we get an illegal op in kernel mode, send it through the
-                * kprobes notifier. If kprobes doesn't pick it up, SIGILL
-                */
+       }
+       /*
+        * We got either an illegal op in kernel mode, or user space trapped
+        * on a uprobes illegal instruction. See if kprobes or uprobes picks
+        * it up. If not, SIGILL.
+        */
+       if (is_uprobe_insn || !user_mode(regs)) {
                if (notify_die(DIE_BPT, "bpt", regs, 0,
                               3, SIGTRAP) != NOTIFY_STOP)
                        signal = SIGILL;
@@ -292,6 +305,74 @@ DO_ERROR_INFO(specification_exception, SIGILL, ILL_ILLOPN,
              "specification exception");
 #endif
 
+#ifdef CONFIG_64BIT
+int alloc_vector_registers(struct task_struct *tsk)
+{
+       __vector128 *vxrs;
+       int i;
+
+       /* Allocate vector register save area. */
+       vxrs = kzalloc(sizeof(__vector128) * __NUM_VXRS,
+                      GFP_KERNEL|__GFP_REPEAT);
+       if (!vxrs)
+               return -ENOMEM;
+       preempt_disable();
+       if (tsk == current)
+               save_fp_regs(tsk->thread.fp_regs.fprs);
+       /* Copy the 16 floating point registers */
+       for (i = 0; i < 16; i++)
+               *(freg_t *) &vxrs[i] = tsk->thread.fp_regs.fprs[i];
+       tsk->thread.vxrs = vxrs;
+       if (tsk == current) {
+               __ctl_set_bit(0, 17);
+               restore_vx_regs(vxrs);
+       }
+       preempt_enable();
+       return 0;
+}
+
+void vector_exception(struct pt_regs *regs)
+{
+       int si_code, vic;
+
+       if (!MACHINE_HAS_VX) {
+               do_trap(regs, SIGILL, ILL_ILLOPN, "illegal operation");
+               return;
+       }
+
+       /* get vector interrupt code from fpc */
+       asm volatile("stfpc %0" : "=m" (current->thread.fp_regs.fpc));
+       vic = (current->thread.fp_regs.fpc & 0xf00) >> 8;
+       switch (vic) {
+       case 1: /* invalid vector operation */
+               si_code = FPE_FLTINV;
+               break;
+       case 2: /* division by zero */
+               si_code = FPE_FLTDIV;
+               break;
+       case 3: /* overflow */
+               si_code = FPE_FLTOVF;
+               break;
+       case 4: /* underflow */
+               si_code = FPE_FLTUND;
+               break;
+       case 5: /* inexact */
+               si_code = FPE_FLTRES;
+               break;
+       default: /* unknown cause */
+               si_code = 0;
+       }
+       do_trap(regs, SIGFPE, si_code, "vector exception");
+}
+
+static int __init disable_vector_extension(char *str)
+{
+       S390_lowcore.machine_flags &= ~MACHINE_FLAG_VX;
+       return 1;
+}
+__setup("novx", disable_vector_extension);
+#endif
+
 void data_exception(struct pt_regs *regs)
 {
        __u16 __user *location;
@@ -357,6 +438,18 @@ void data_exception(struct pt_regs *regs)
                 }
         }
 #endif 
+#ifdef CONFIG_64BIT
+       /* Check for vector register enablement */
+       if (MACHINE_HAS_VX && !current->thread.vxrs &&
+           (current->thread.fp_regs.fpc & FPC_DXC_MASK) == 0xfe00) {
+               alloc_vector_registers(current);
+               /* Vector data exception is suppressing, rewind psw. */
+               regs->psw.addr = __rewind_psw(regs->psw, regs->int_code >> 16);
+               clear_pt_regs_flag(regs, PIF_PER_TRAP);
+               return;
+       }
+#endif
+
        if (current->thread.fp_regs.fpc & FPC_DXC_MASK)
                signal = SIGFPE;
        else
diff --git a/arch/s390/kernel/uprobes.c b/arch/s390/kernel/uprobes.c
new file mode 100644 (file)
index 0000000..956f4f7
--- /dev/null
@@ -0,0 +1,332 @@
+/*
+ *  User-space Probes (UProbes) for s390
+ *
+ *    Copyright IBM Corp. 2014
+ *    Author(s): Jan Willeke,
+ */
+
+#include <linux/kprobes.h>
+#include <linux/uaccess.h>
+#include <linux/uprobes.h>
+#include <linux/compat.h>
+#include <linux/kdebug.h>
+#include <asm/switch_to.h>
+#include <asm/facility.h>
+#include <asm/dis.h>
+#include "entry.h"
+
+#define        UPROBE_TRAP_NR  UINT_MAX
+
+int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm,
+                            unsigned long addr)
+{
+       return probe_is_prohibited_opcode(auprobe->insn);
+}
+
+int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+       if (psw_bits(regs->psw).eaba == PSW_AMODE_24BIT)
+               return -EINVAL;
+       if (!is_compat_task() && psw_bits(regs->psw).eaba == PSW_AMODE_31BIT)
+               return -EINVAL;
+       clear_pt_regs_flag(regs, PIF_PER_TRAP);
+       auprobe->saved_per = psw_bits(regs->psw).r;
+       auprobe->saved_int_code = regs->int_code;
+       regs->int_code = UPROBE_TRAP_NR;
+       regs->psw.addr = current->utask->xol_vaddr;
+       set_tsk_thread_flag(current, TIF_UPROBE_SINGLESTEP);
+       update_cr_regs(current);
+       return 0;
+}
+
+bool arch_uprobe_xol_was_trapped(struct task_struct *tsk)
+{
+       struct pt_regs *regs = task_pt_regs(tsk);
+
+       if (regs->int_code != UPROBE_TRAP_NR)
+               return true;
+       return false;
+}
+
+int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+       int fixup = probe_get_fixup_type(auprobe->insn);
+       struct uprobe_task *utask = current->utask;
+
+       clear_tsk_thread_flag(current, TIF_UPROBE_SINGLESTEP);
+       update_cr_regs(current);
+       psw_bits(regs->psw).r = auprobe->saved_per;
+       regs->int_code = auprobe->saved_int_code;
+
+       if (fixup & FIXUP_PSW_NORMAL)
+               regs->psw.addr += utask->vaddr - utask->xol_vaddr;
+       if (fixup & FIXUP_RETURN_REGISTER) {
+               int reg = (auprobe->insn[0] & 0xf0) >> 4;
+
+               regs->gprs[reg] += utask->vaddr - utask->xol_vaddr;
+       }
+       if (fixup & FIXUP_BRANCH_NOT_TAKEN) {
+               int ilen = insn_length(auprobe->insn[0] >> 8);
+
+               if (regs->psw.addr - utask->xol_vaddr == ilen)
+                       regs->psw.addr = utask->vaddr + ilen;
+       }
+       /* If per tracing was active generate trap */
+       if (regs->psw.mask & PSW_MASK_PER)
+               do_per_trap(regs);
+       return 0;
+}
+
+int arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val,
+                                void *data)
+{
+       struct die_args *args = data;
+       struct pt_regs *regs = args->regs;
+
+       if (!user_mode(regs))
+               return NOTIFY_DONE;
+       if (regs->int_code & 0x200) /* Trap during transaction */
+               return NOTIFY_DONE;
+       switch (val) {
+       case DIE_BPT:
+               if (uprobe_pre_sstep_notifier(regs))
+                       return NOTIFY_STOP;
+               break;
+       case DIE_SSTEP:
+               if (uprobe_post_sstep_notifier(regs))
+                       return NOTIFY_STOP;
+       default:
+               break;
+       }
+       return NOTIFY_DONE;
+}
+
+void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+       clear_thread_flag(TIF_UPROBE_SINGLESTEP);
+       regs->int_code = auprobe->saved_int_code;
+       regs->psw.addr = current->utask->vaddr;
+}
+
+unsigned long arch_uretprobe_hijack_return_addr(unsigned long trampoline,
+                                               struct pt_regs *regs)
+{
+       unsigned long orig;
+
+       orig = regs->gprs[14];
+       regs->gprs[14] = trampoline;
+       return orig;
+}
+
+/* Instruction Emulation */
+
+static void adjust_psw_addr(psw_t *psw, unsigned long len)
+{
+       psw->addr = __rewind_psw(*psw, -len);
+}
+
+#define EMU_ILLEGAL_OP         1
+#define EMU_SPECIFICATION      2
+#define EMU_ADDRESSING         3
+
+#define emu_load_ril(ptr, output)                      \
+({                                                     \
+       unsigned int mask = sizeof(*(ptr)) - 1;         \
+       __typeof__(*(ptr)) input;                       \
+       int __rc = 0;                                   \
+                                                       \
+       if (!test_facility(34))                         \
+               __rc = EMU_ILLEGAL_OP;                  \
+       else if ((u64 __force)ptr & mask)               \
+               __rc = EMU_SPECIFICATION;               \
+       else if (get_user(input, ptr))                  \
+               __rc = EMU_ADDRESSING;                  \
+       else                                            \
+               *(output) = input;                      \
+       __rc;                                           \
+})
+
+#define emu_store_ril(ptr, input)                      \
+({                                                     \
+       unsigned int mask = sizeof(*(ptr)) - 1;         \
+       int __rc = 0;                                   \
+                                                       \
+       if (!test_facility(34))                         \
+               __rc = EMU_ILLEGAL_OP;                  \
+       else if ((u64 __force)ptr & mask)               \
+               __rc = EMU_SPECIFICATION;               \
+       else if (put_user(*(input), ptr))               \
+               __rc = EMU_ADDRESSING;                  \
+       __rc;                                           \
+})
+
+#define emu_cmp_ril(regs, ptr, cmp)                    \
+({                                                     \
+       unsigned int mask = sizeof(*(ptr)) - 1;         \
+       __typeof__(*(ptr)) input;                       \
+       int __rc = 0;                                   \
+                                                       \
+       if (!test_facility(34))                         \
+               __rc = EMU_ILLEGAL_OP;                  \
+       else if ((u64 __force)ptr & mask)               \
+               __rc = EMU_SPECIFICATION;               \
+       else if (get_user(input, ptr))                  \
+               __rc = EMU_ADDRESSING;                  \
+       else if (input > *(cmp))                        \
+               psw_bits((regs)->psw).cc = 1;           \
+       else if (input < *(cmp))                        \
+               psw_bits((regs)->psw).cc = 2;           \
+       else                                            \
+               psw_bits((regs)->psw).cc = 0;           \
+       __rc;                                           \
+})
+
+struct insn_ril {
+       u8 opc0;
+       u8 reg  : 4;
+       u8 opc1 : 4;
+       s32 disp;
+} __packed;
+
+union split_register {
+       u64 u64;
+       u32 u32[2];
+       u16 u16[4];
+       s64 s64;
+       s32 s32[2];
+       s16 s16[4];
+};
+
+/*
+ * pc relative instructions are emulated, since parameters may not be
+ * accessible from the xol area due to range limitations.
+ */
+static void handle_insn_ril(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+       union split_register *rx;
+       struct insn_ril *insn;
+       unsigned int ilen;
+       void *uptr;
+       int rc = 0;
+
+       insn = (struct insn_ril *) &auprobe->insn;
+       rx = (union split_register *) &regs->gprs[insn->reg];
+       uptr = (void *)(regs->psw.addr + (insn->disp * 2));
+       ilen = insn_length(insn->opc0);
+
+       switch (insn->opc0) {
+       case 0xc0:
+               switch (insn->opc1) {
+               case 0x00: /* larl */
+                       rx->u64 = (unsigned long)uptr;
+                       break;
+               }
+               break;
+       case 0xc4:
+               switch (insn->opc1) {
+               case 0x02: /* llhrl */
+                       rc = emu_load_ril((u16 __user *)uptr, &rx->u32[1]);
+                       break;
+               case 0x04: /* lghrl */
+                       rc = emu_load_ril((s16 __user *)uptr, &rx->u64);
+                       break;
+               case 0x05: /* lhrl */
+                       rc = emu_load_ril((s16 __user *)uptr, &rx->u32[1]);
+                       break;
+               case 0x06: /* llghrl */
+                       rc = emu_load_ril((u16 __user *)uptr, &rx->u64);
+                       break;
+               case 0x08: /* lgrl */
+                       rc = emu_load_ril((u64 __user *)uptr, &rx->u64);
+                       break;
+               case 0x0c: /* lgfrl */
+                       rc = emu_load_ril((s32 __user *)uptr, &rx->u64);
+                       break;
+               case 0x0d: /* lrl */
+                       rc = emu_load_ril((u32 __user *)uptr, &rx->u32[1]);
+                       break;
+               case 0x0e: /* llgfrl */
+                       rc = emu_load_ril((u32 __user *)uptr, &rx->u64);
+                       break;
+               case 0x07: /* sthrl */
+                       rc = emu_store_ril((u16 __user *)uptr, &rx->u16[3]);
+                       break;
+               case 0x0b: /* stgrl */
+                       rc = emu_store_ril((u64 __user *)uptr, &rx->u64);
+                       break;
+               case 0x0f: /* strl */
+                       rc = emu_store_ril((u32 __user *)uptr, &rx->u32[1]);
+                       break;
+               }
+               break;
+       case 0xc6:
+               switch (insn->opc1) {
+               case 0x02: /* pfdrl */
+                       if (!test_facility(34))
+                               rc = EMU_ILLEGAL_OP;
+                       break;
+               case 0x04: /* cghrl */
+                       rc = emu_cmp_ril(regs, (s16 __user *)uptr, &rx->s64);
+                       break;
+               case 0x05: /* chrl */
+                       rc = emu_cmp_ril(regs, (s16 __user *)uptr, &rx->s32[1]);
+                       break;
+               case 0x06: /* clghrl */
+                       rc = emu_cmp_ril(regs, (u16 __user *)uptr, &rx->u64);
+                       break;
+               case 0x07: /* clhrl */
+                       rc = emu_cmp_ril(regs, (u16 __user *)uptr, &rx->u32[1]);
+                       break;
+               case 0x08: /* cgrl */
+                       rc = emu_cmp_ril(regs, (s64 __user *)uptr, &rx->s64);
+                       break;
+               case 0x0a: /* clgrl */
+                       rc = emu_cmp_ril(regs, (u64 __user *)uptr, &rx->u64);
+                       break;
+               case 0x0c: /* cgfrl */
+                       rc = emu_cmp_ril(regs, (s32 __user *)uptr, &rx->s64);
+                       break;
+               case 0x0d: /* crl */
+                       rc = emu_cmp_ril(regs, (s32 __user *)uptr, &rx->s32[1]);
+                       break;
+               case 0x0e: /* clgfrl */
+                       rc = emu_cmp_ril(regs, (u32 __user *)uptr, &rx->u64);
+                       break;
+               case 0x0f: /* clrl */
+                       rc = emu_cmp_ril(regs, (u32 __user *)uptr, &rx->u32[1]);
+                       break;
+               }
+               break;
+       }
+       adjust_psw_addr(&regs->psw, ilen);
+       switch (rc) {
+       case EMU_ILLEGAL_OP:
+               regs->int_code = ilen << 16 | 0x0001;
+               do_report_trap(regs, SIGILL, ILL_ILLOPC, NULL);
+               break;
+       case EMU_SPECIFICATION:
+               regs->int_code = ilen << 16 | 0x0006;
+               do_report_trap(regs, SIGILL, ILL_ILLOPC , NULL);
+               break;
+       case EMU_ADDRESSING:
+               regs->int_code = ilen << 16 | 0x0005;
+               do_report_trap(regs, SIGSEGV, SEGV_MAPERR, NULL);
+               break;
+       }
+}
+
+bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+       if ((psw_bits(regs->psw).eaba == PSW_AMODE_24BIT) ||
+           ((psw_bits(regs->psw).eaba == PSW_AMODE_31BIT) &&
+            !is_compat_task())) {
+               regs->psw.addr = __rewind_psw(regs->psw, UPROBE_SWBP_INSN_SIZE);
+               do_report_trap(regs, SIGILL, ILL_ILLADR, NULL);
+               return true;
+       }
+       if (probe_is_insn_relative_long(auprobe->insn)) {
+               handle_insn_ril(auprobe, regs);
+               return true;
+       }
+       return false;
+}
index 36aaa25d05daa4e1d785103d85a2bb5a078fc2cc..eca3f001f081309c88372de459a6dfcccd754e7d 100644 (file)
        .type  __kernel_clock_getres,@function
 __kernel_clock_getres:
        .cfi_startproc
+       basr    %r1,0
+       la      %r1,4f-.(%r1)
        chi     %r2,__CLOCK_REALTIME
        je      0f
        chi     %r2,__CLOCK_MONOTONIC
+       je      0f
+       la      %r1,5f-4f(%r1)
+       chi     %r2,__CLOCK_REALTIME_COARSE
+       je      0f
+       chi     %r2,__CLOCK_MONOTONIC_COARSE
        jne     3f
 0:     ltr     %r3,%r3
        jz      2f                              /* res == NULL */
-       basr    %r1,0
-1:     l       %r0,4f-1b(%r1)
+1:     l       %r0,0(%r1)
        xc      0(4,%r3),0(%r3)                 /* set tp->tv_sec to zero */
        st      %r0,4(%r3)                      /* store tp->tv_usec */
 2:     lhi     %r2,0
@@ -35,5 +41,6 @@ __kernel_clock_getres:
        svc     0
        br      %r14
 4:     .long   __CLOCK_REALTIME_RES
+5:     .long   __CLOCK_COARSE_RES
        .cfi_endproc
        .size   __kernel_clock_getres,.-__kernel_clock_getres
index 7cf18f8d4cb4fc9d281169ed8dee675f4c68b6be..48c2206a39561ea9373bb3fb8ec48297b3509867 100644 (file)
@@ -21,8 +21,12 @@ __kernel_clock_gettime:
        .cfi_startproc
        basr    %r5,0
 0:     al      %r5,21f-0b(%r5)                 /* get &_vdso_data */
+       chi     %r2,__CLOCK_REALTIME_COARSE
+       je      10f
        chi     %r2,__CLOCK_REALTIME
        je      11f
+       chi     %r2,__CLOCK_MONOTONIC_COARSE
+       je      9f
        chi     %r2,__CLOCK_MONOTONIC
        jne     19f
 
@@ -30,8 +34,8 @@ __kernel_clock_gettime:
 1:     l       %r4,__VDSO_UPD_COUNT+4(%r5)     /* load update counter */
        tml     %r4,0x0001                      /* pending update ? loop */
        jnz     1b
-       stck    24(%r15)                        /* Store TOD clock */
-       lm      %r0,%r1,24(%r15)
+       stcke   24(%r15)                        /* Store TOD clock */
+       lm      %r0,%r1,25(%r15)
        s       %r0,__VDSO_XTIME_STAMP(%r5)     /* TOD - cycle_last */
        sl      %r1,__VDSO_XTIME_STAMP+4(%r5)
        brc     3,2f
@@ -68,12 +72,32 @@ __kernel_clock_gettime:
        lhi     %r2,0
        br      %r14
 
+       /* CLOCK_MONOTONIC_COARSE */
+9:     l       %r4,__VDSO_UPD_COUNT+4(%r5)     /* load update counter */
+       tml     %r4,0x0001                      /* pending update ? loop */
+       jnz     9b
+       l       %r2,__VDSO_WTOM_CRS_SEC+4(%r5)
+       l       %r1,__VDSO_WTOM_CRS_NSEC+4(%r5)
+       cl      %r4,__VDSO_UPD_COUNT+4(%r5)     /* check update counter */
+       jne     9b
+       j       8b
+
+       /* CLOCK_REALTIME_COARSE */
+10:    l       %r4,__VDSO_UPD_COUNT+4(%r5)     /* load update counter */
+       tml     %r4,0x0001                      /* pending update ? loop */
+       jnz     10b
+       l       %r2,__VDSO_XTIME_CRS_SEC+4(%r5)
+       l       %r1,__VDSO_XTIME_CRS_NSEC+4(%r5)
+       cl      %r4,__VDSO_UPD_COUNT+4(%r5)     /* check update counter */
+       jne     10b
+       j       17f
+
        /* CLOCK_REALTIME */
 11:    l       %r4,__VDSO_UPD_COUNT+4(%r5)     /* load update counter */
        tml     %r4,0x0001                      /* pending update ? loop */
        jnz     11b
-       stck    24(%r15)                        /* Store TOD clock */
-       lm      %r0,%r1,24(%r15)
+       stcke   24(%r15)                        /* Store TOD clock */
+       lm      %r0,%r1,25(%r15)
        s       %r0,__VDSO_XTIME_STAMP(%r5)     /* TOD - cycle_last */
        sl      %r1,__VDSO_XTIME_STAMP+4(%r5)
        brc     3,12f
index fd621a950f7c70e917ea6ca44bb4a5fd5b9869ab..60def5f562db532e4c014687e38dcefdf1344383 100644 (file)
@@ -29,8 +29,8 @@ __kernel_gettimeofday:
        l       %r4,__VDSO_UPD_COUNT+4(%r5)     /* load update counter */
        tml     %r4,0x0001                      /* pending update ? loop */
        jnz     1b
-       stck    24(%r15)                        /* Store TOD clock */
-       lm      %r0,%r1,24(%r15)
+       stcke   24(%r15)                        /* Store TOD clock */
+       lm      %r0,%r1,25(%r15)
        s       %r0,__VDSO_XTIME_STAMP(%r5)     /* TOD - cycle_last */
        sl      %r1,__VDSO_XTIME_STAMP+4(%r5)
        brc     3,3f
index 34deba7c7ed1d8b18036b0b07f9b7cd9d41e9259..c8513deb8c663f51fa4f4bc2b2299ea24f1aaefd 100644 (file)
        .type  __kernel_clock_getres,@function
 __kernel_clock_getres:
        .cfi_startproc
+       larl    %r1,4f
+       cghi    %r2,__CLOCK_REALTIME_COARSE
+       je      0f
+       cghi    %r2,__CLOCK_MONOTONIC_COARSE
+       je      0f
+       larl    %r1,3f
        cghi    %r2,__CLOCK_REALTIME
        je      0f
        cghi    %r2,__CLOCK_MONOTONIC
@@ -32,7 +38,6 @@ __kernel_clock_getres:
        jz      2f
 0:     ltgr    %r3,%r3
        jz      1f                              /* res == NULL */
-       larl    %r1,3f
        lg      %r0,0(%r1)
        xc      0(8,%r3),0(%r3)                 /* set tp->tv_sec to zero */
        stg     %r0,8(%r3)                      /* store tp->tv_usec */
@@ -42,5 +47,6 @@ __kernel_clock_getres:
        svc     0
        br      %r14
 3:     .quad   __CLOCK_REALTIME_RE