summaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/Kconfig43
-rw-r--r--arch/s390/appldata/appldata_base.c6
-rw-r--r--arch/s390/appldata/appldata_net_sum.c8
-rw-r--r--arch/s390/crypto/aes_s390.c2
-rw-r--r--arch/s390/crypto/prng.c2
-rw-r--r--arch/s390/defconfig87
-rw-r--r--arch/s390/hypfs/hypfs_diag.c6
-rw-r--r--arch/s390/hypfs/hypfs_vm.c2
-rw-r--r--arch/s390/include/asm/asm-offsets.h1
-rw-r--r--arch/s390/include/asm/atomic.h8
-rw-r--r--arch/s390/include/asm/bug.h2
-rw-r--r--arch/s390/include/asm/cacheflush.h1
-rw-r--r--arch/s390/include/asm/ccwdev.h4
-rw-r--r--arch/s390/include/asm/cputime.h14
-rw-r--r--arch/s390/include/asm/delay.h7
-rw-r--r--arch/s390/include/asm/elf.h13
-rw-r--r--arch/s390/include/asm/kvm.h3
-rw-r--r--arch/s390/include/asm/mmu_context.h4
-rw-r--r--arch/s390/include/asm/param.h28
-rw-r--r--arch/s390/include/asm/pgalloc.h3
-rw-r--r--arch/s390/include/asm/pgtable.h4
-rw-r--r--arch/s390/include/asm/ptrace.h4
-rw-r--r--arch/s390/include/asm/setup.h17
-rw-r--r--arch/s390/include/asm/smp.h54
-rw-r--r--arch/s390/include/asm/socket.h2
-rw-r--r--arch/s390/include/asm/sockios.h21
-rw-r--r--arch/s390/include/asm/spinlock.h95
-rw-r--r--arch/s390/include/asm/spinlock_types.h8
-rw-r--r--arch/s390/include/asm/termbits.h206
-rw-r--r--arch/s390/include/asm/todclk.h23
-rw-r--r--arch/s390/include/asm/uaccess.h2
-rw-r--r--arch/s390/include/asm/ucontext.h15
-rw-r--r--arch/s390/include/asm/unistd.h3
-rw-r--r--arch/s390/kernel/Makefile1
-rw-r--r--arch/s390/kernel/compat_linux.c96
-rw-r--r--arch/s390/kernel/compat_linux.h6
-rw-r--r--arch/s390/kernel/compat_signal.c35
-rw-r--r--arch/s390/kernel/compat_wrapper.S17
-rw-r--r--arch/s390/kernel/debug.c16
-rw-r--r--arch/s390/kernel/early.c9
-rw-r--r--arch/s390/kernel/entry.S8
-rw-r--r--arch/s390/kernel/entry64.S8
-rw-r--r--arch/s390/kernel/ftrace.c70
-rw-r--r--arch/s390/kernel/head64.S3
-rw-r--r--arch/s390/kernel/ipl.c13
-rw-r--r--arch/s390/kernel/module.c3
-rw-r--r--arch/s390/kernel/processor.c6
-rw-r--r--arch/s390/kernel/ptrace.c70
-rw-r--r--arch/s390/kernel/s390_ext.c2
-rw-r--r--arch/s390/kernel/setup.c51
-rw-r--r--arch/s390/kernel/smp.c7
-rw-r--r--arch/s390/kernel/swsusp_asm64.S28
-rw-r--r--arch/s390/kernel/sys_s390.c30
-rw-r--r--arch/s390/kernel/syscalls.S1
-rw-r--r--arch/s390/kernel/time.c7
-rw-r--r--arch/s390/kernel/traps.c6
-rw-r--r--arch/s390/kernel/vdso.c25
-rw-r--r--arch/s390/kernel/vmlinux.lds.S1
-rw-r--r--arch/s390/kernel/vtime.c2
-rw-r--r--arch/s390/kvm/Kconfig1
-rw-r--r--arch/s390/kvm/kvm-s390.c30
-rw-r--r--arch/s390/kvm/kvm-s390.h2
-rw-r--r--arch/s390/kvm/sigp.c6
-rw-r--r--arch/s390/lib/delay.c27
-rw-r--r--arch/s390/lib/spinlock.c46
-rw-r--r--arch/s390/lib/uaccess_mvcos.c16
-rw-r--r--arch/s390/lib/uaccess_pt.c147
-rw-r--r--arch/s390/lib/uaccess_std.c14
-rw-r--r--arch/s390/math-emu/math.c4
-rw-r--r--arch/s390/mm/cmm.c72
-rw-r--r--arch/s390/mm/fault.c378
-rw-r--r--arch/s390/mm/pgtable.c12
-rw-r--r--arch/s390/mm/vmem.c11
73 files changed, 887 insertions, 1098 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 43c0aca..c802352 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -95,6 +95,34 @@ config S390
select HAVE_ARCH_TRACEHOOK
select INIT_ALL_POSSIBLE
select HAVE_PERF_EVENTS
+ select ARCH_INLINE_SPIN_TRYLOCK
+ select ARCH_INLINE_SPIN_TRYLOCK_BH
+ select ARCH_INLINE_SPIN_LOCK
+ select ARCH_INLINE_SPIN_LOCK_BH
+ select ARCH_INLINE_SPIN_LOCK_IRQ
+ select ARCH_INLINE_SPIN_LOCK_IRQSAVE
+ select ARCH_INLINE_SPIN_UNLOCK
+ select ARCH_INLINE_SPIN_UNLOCK_BH
+ select ARCH_INLINE_SPIN_UNLOCK_IRQ
+ select ARCH_INLINE_SPIN_UNLOCK_IRQRESTORE
+ select ARCH_INLINE_READ_TRYLOCK
+ select ARCH_INLINE_READ_LOCK
+ select ARCH_INLINE_READ_LOCK_BH
+ select ARCH_INLINE_READ_LOCK_IRQ
+ select ARCH_INLINE_READ_LOCK_IRQSAVE
+ select ARCH_INLINE_READ_UNLOCK
+ select ARCH_INLINE_READ_UNLOCK_BH
+ select ARCH_INLINE_READ_UNLOCK_IRQ
+ select ARCH_INLINE_READ_UNLOCK_IRQRESTORE
+ select ARCH_INLINE_WRITE_TRYLOCK
+ select ARCH_INLINE_WRITE_LOCK
+ select ARCH_INLINE_WRITE_LOCK_BH
+ select ARCH_INLINE_WRITE_LOCK_IRQ
+ select ARCH_INLINE_WRITE_LOCK_IRQSAVE
+ select ARCH_INLINE_WRITE_UNLOCK
+ select ARCH_INLINE_WRITE_UNLOCK_BH
+ select ARCH_INLINE_WRITE_UNLOCK_IRQ
+ select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE
config SCHED_OMIT_FRAME_POINTER
bool
@@ -192,23 +220,8 @@ config AUDIT_ARCH
bool
default y
-config S390_SWITCH_AMODE
- bool "Switch kernel/user addressing modes"
- help
- This option allows to switch the addressing modes of kernel and user
- space. The kernel parameter switch_amode=on will enable this feature,
- default is disabled. Enabling this (via kernel parameter) on machines
- earlier than IBM System z9-109 EC/BC will reduce system performance.
-
- Note that this option will also be selected by selecting the execute
- protection option below. Enabling the execute protection via the
- noexec kernel parameter will also switch the addressing modes,
- independent of the switch_amode kernel parameter.
-
-
config S390_EXEC_PROTECT
bool "Data execute protection"
- select S390_SWITCH_AMODE
help
This option allows to enable a buffer overflow protection for user
space programs and it also selects the addressing mode option above.
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c
index b55fd7e..5c91995 100644
--- a/arch/s390/appldata/appldata_base.c
+++ b/arch/s390/appldata/appldata_base.c
@@ -61,12 +61,12 @@ static struct ctl_table appldata_table[] = {
{
.procname = "timer",
.mode = S_IRUGO | S_IWUSR,
- .proc_handler = &appldata_timer_handler,
+ .proc_handler = appldata_timer_handler,
},
{
.procname = "interval",
.mode = S_IRUGO | S_IWUSR,
- .proc_handler = &appldata_interval_handler,
+ .proc_handler = appldata_interval_handler,
},
{ },
};
@@ -551,7 +551,7 @@ static int appldata_thaw(struct device *dev)
return appldata_restore(dev);
}
-static struct dev_pm_ops appldata_pm_ops = {
+static const struct dev_pm_ops appldata_pm_ops = {
.freeze = appldata_freeze,
.thaw = appldata_thaw,
.restore = appldata_restore,
diff --git a/arch/s390/appldata/appldata_net_sum.c b/arch/s390/appldata/appldata_net_sum.c
index fa741f8..4ce7fa9 100644
--- a/arch/s390/appldata/appldata_net_sum.c
+++ b/arch/s390/appldata/appldata_net_sum.c
@@ -83,8 +83,9 @@ static void appldata_get_net_sum_data(void *data)
rx_dropped = 0;
tx_dropped = 0;
collisions = 0;
- read_lock(&dev_base_lock);
- for_each_netdev(&init_net, dev) {
+
+ rcu_read_lock();
+ for_each_netdev_rcu(&init_net, dev) {
const struct net_device_stats *stats = dev_get_stats(dev);
rx_packets += stats->rx_packets;
@@ -98,7 +99,8 @@ static void appldata_get_net_sum_data(void *data)
collisions += stats->collisions;
i++;
}
- read_unlock(&dev_base_lock);
+ rcu_read_unlock();
+
net_data->nr_interfaces = i;
net_data->rx_packets = rx_packets;
net_data->tx_packets = tx_packets;
diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c
index 6118890..6be4503 100644
--- a/arch/s390/crypto/aes_s390.c
+++ b/arch/s390/crypto/aes_s390.c
@@ -174,7 +174,7 @@ static int fallback_init_cip(struct crypto_tfm *tfm)
if (IS_ERR(sctx->fallback.cip)) {
pr_err("Allocating AES fallback algorithm %s failed\n",
name);
- return PTR_ERR(sctx->fallback.blk);
+ return PTR_ERR(sctx->fallback.cip);
}
return 0;
diff --git a/arch/s390/crypto/prng.c b/arch/s390/crypto/prng.c
index b49c00c..a320990 100644
--- a/arch/s390/crypto/prng.c
+++ b/arch/s390/crypto/prng.c
@@ -6,7 +6,6 @@
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/kernel.h>
-#include <linux/smp_lock.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
@@ -49,7 +48,6 @@ static unsigned char parm_block[32] = {
static int prng_open(struct inode *inode, struct file *file)
{
- cycle_kernel_lock();
return nonseekable_open(inode, file);
}
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index ab44644..b416aa1 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.31
-# Tue Sep 22 17:43:13 2009
+# Linux kernel version: 2.6.33-rc2
+# Mon Jan 4 09:03:07 2010
#
CONFIG_SCHED_MC=y
CONFIG_MMU=y
@@ -51,6 +51,7 @@ CONFIG_AUDIT=y
#
CONFIG_TREE_RCU=y
# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_TINY_RCU is not set
# CONFIG_RCU_TRACE is not set
CONFIG_RCU_FANOUT=64
# CONFIG_RCU_FANOUT_EXACT is not set
@@ -113,7 +114,6 @@ CONFIG_HAVE_PERF_EVENTS=y
# CONFIG_PERF_EVENTS is not set
# CONFIG_PERF_COUNTERS is not set
CONFIG_VM_EVENT_COUNTERS=y
-# CONFIG_STRIP_ASM_SYMS is not set
# CONFIG_COMPAT_BRK is not set
CONFIG_SLAB=y
# CONFIG_SLUB is not set
@@ -149,21 +149,78 @@ CONFIG_STOP_MACHINE=y
CONFIG_BLOCK=y
CONFIG_BLK_DEV_BSG=y
# CONFIG_BLK_DEV_INTEGRITY is not set
+# CONFIG_BLK_CGROUP is not set
CONFIG_BLOCK_COMPAT=y
#
# IO Schedulers
#
CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
-# CONFIG_DEFAULT_AS is not set
+# CONFIG_CFQ_GROUP_IOSCHED is not set
CONFIG_DEFAULT_DEADLINE=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="deadline"
CONFIG_PREEMPT_NOTIFIERS=y
+CONFIG_ARCH_INLINE_SPIN_TRYLOCK=y
+CONFIG_ARCH_INLINE_SPIN_TRYLOCK_BH=y
+CONFIG_ARCH_INLINE_SPIN_LOCK=y
+CONFIG_ARCH_INLINE_SPIN_LOCK_BH=y
+CONFIG_ARCH_INLINE_SPIN_LOCK_IRQ=y
+CONFIG_ARCH_INLINE_SPIN_LOCK_IRQSAVE=y
+CONFIG_ARCH_INLINE_SPIN_UNLOCK=y
+CONFIG_ARCH_INLINE_SPIN_UNLOCK_BH=y
+CONFIG_ARCH_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_ARCH_INLINE_SPIN_UNLOCK_IRQRESTORE=y
+CONFIG_ARCH_INLINE_READ_TRYLOCK=y
+CONFIG_ARCH_INLINE_READ_LOCK=y
+CONFIG_ARCH_INLINE_READ_LOCK_BH=y
+CONFIG_ARCH_INLINE_READ_LOCK_IRQ=y
+CONFIG_ARCH_INLINE_READ_LOCK_IRQSAVE=y
+CONFIG_ARCH_INLINE_READ_UNLOCK=y
+CONFIG_ARCH_INLINE_READ_UNLOCK_BH=y
+CONFIG_ARCH_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_ARCH_INLINE_READ_UNLOCK_IRQRESTORE=y
+CONFIG_ARCH_INLINE_WRITE_TRYLOCK=y
+CONFIG_ARCH_INLINE_WRITE_LOCK=y
+CONFIG_ARCH_INLINE_WRITE_LOCK_BH=y
+CONFIG_ARCH_INLINE_WRITE_LOCK_IRQ=y
+CONFIG_ARCH_INLINE_WRITE_LOCK_IRQSAVE=y
+CONFIG_ARCH_INLINE_WRITE_UNLOCK=y
+CONFIG_ARCH_INLINE_WRITE_UNLOCK_BH=y
+CONFIG_ARCH_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE=y
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_SPIN_UNLOCK is not set
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_READ_UNLOCK is not set
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQ is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_WRITE_UNLOCK is not set
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
CONFIG_FREEZER=y
#
@@ -185,7 +242,6 @@ CONFIG_HOTPLUG_CPU=y
CONFIG_COMPAT=y
CONFIG_SYSVIPC_COMPAT=y
CONFIG_AUDIT_ARCH=y
-CONFIG_S390_SWITCH_AMODE=y
CONFIG_S390_EXEC_PROTECT=y
#
@@ -228,14 +284,13 @@ CONFIG_MEMORY_HOTPLUG=y
CONFIG_MEMORY_HOTPLUG_SPARSE=y
CONFIG_MEMORY_HOTREMOVE=y
CONFIG_PAGEFLAGS_EXTENDED=y
-CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_SPLIT_PTLOCK_CPUS=999999
CONFIG_MIGRATION=y
CONFIG_PHYS_ADDR_T_64BIT=y
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
-CONFIG_HAVE_MLOCK=y
-CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+# CONFIG_KSM is not set
CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
#
@@ -340,6 +395,7 @@ CONFIG_INET6_XFRM_MODE_TUNNEL=y
CONFIG_INET6_XFRM_MODE_BEET=y
# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
CONFIG_IPV6_SIT=y
+# CONFIG_IPV6_SIT_6RD is not set
CONFIG_IPV6_NDISC_NODETYPE=y
# CONFIG_IPV6_TUNNEL is not set
# CONFIG_IPV6_MULTIPLE_TABLES is not set
@@ -505,6 +561,10 @@ CONFIG_BLK_DEV=y
# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=m
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+
+#
+# DRBD disabled because PROC_FS, INET or CONNECTOR not selected
+#
CONFIG_BLK_DEV_NBD=m
# CONFIG_BLK_DEV_OSD is not set
CONFIG_BLK_DEV_RAM=y
@@ -711,7 +771,6 @@ CONFIG_S390_VMUR=m
# CONFIG_PPS is not set
# CONFIG_POWER_SUPPLY is not set
# CONFIG_THERMAL is not set
-# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
# CONFIG_REGULATOR is not set
# CONFIG_MEMSTICK is not set
@@ -865,6 +924,7 @@ CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
CONFIG_FRAME_WARN=2048
CONFIG_MAGIC_SYSRQ=y
+# CONFIG_STRIP_ASM_SYMS is not set
# CONFIG_UNUSED_SYMBOLS is not set
CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
@@ -932,7 +992,6 @@ CONFIG_BRANCH_PROFILE_NONE=y
CONFIG_SAMPLES=y
# CONFIG_SAMPLE_KOBJECT is not set
# CONFIG_SAMPLE_KPROBES is not set
-# CONFIG_KMEMCHECK is not set
#
# Security options
@@ -940,7 +999,11 @@ CONFIG_SAMPLES=y
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
# CONFIG_SECURITYFS is not set
-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_DEFAULT_SECURITY_SELINUX is not set
+# CONFIG_DEFAULT_SECURITY_SMACK is not set
+# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
CONFIG_CRYPTO=y
#
diff --git a/arch/s390/hypfs/hypfs_diag.c b/arch/s390/hypfs/hypfs_diag.c
index 704dd39..2b92d50 100644
--- a/arch/s390/hypfs/hypfs_diag.c
+++ b/arch/s390/hypfs/hypfs_diag.c
@@ -164,7 +164,7 @@ static inline void part_hdr__part_name(enum diag204_format type, void *hdr,
LPAR_NAME_LEN);
EBCASC(name, LPAR_NAME_LEN);
name[LPAR_NAME_LEN] = 0;
- strstrip(name);
+ strim(name);
}
struct cpu_info {
@@ -438,7 +438,7 @@ static int diag204_probe(void)
}
if (diag204((unsigned long)SUBC_STIB6 |
(unsigned long)INFO_EXT, pages, buf) >= 0) {
- diag204_store_sc = SUBC_STIB7;
+ diag204_store_sc = SUBC_STIB6;
diag204_info_type = INFO_EXT;
goto out;
}
@@ -523,7 +523,7 @@ static int diag224_idx2name(int index, char *name)
memcpy(name, diag224_cpu_names + ((index + 1) * CPU_NAME_LEN),
CPU_NAME_LEN);
name[CPU_NAME_LEN] = 0;
- strstrip(name);
+ strim(name);
return 0;
}
diff --git a/arch/s390/hypfs/hypfs_vm.c b/arch/s390/hypfs/hypfs_vm.c
index d01fc8f7..f0b0d31 100644
--- a/arch/s390/hypfs/hypfs_vm.c
+++ b/arch/s390/hypfs/hypfs_vm.c
@@ -124,7 +124,7 @@ static int hpyfs_vm_create_guest(struct super_block *sb,
/* guest dir */
memcpy(guest_name, data->guest_name, NAME_LEN);
EBCASC(guest_name, NAME_LEN);
- strstrip(guest_name);
+ strim(guest_name);
guest_dir = hypfs_mkdir(sb, systems_dir, guest_name);
if (IS_ERR(guest_dir))
return PTR_ERR(guest_dir);
diff --git a/arch/s390/include/asm/asm-offsets.h b/arch/s390/include/asm/asm-offsets.h
new file mode 100644
index 0000000..d370ee3
--- /dev/null
+++ b/arch/s390/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/s390/include/asm/atomic.h b/arch/s390/include/asm/atomic.h
index ae7c8f9..2a113d6 100644
--- a/arch/s390/include/asm/atomic.h
+++ b/arch/s390/include/asm/atomic.h
@@ -21,7 +21,7 @@
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
#define __CS_LOOP(ptr, op_val, op_string) ({ \
- typeof(ptr->counter) old_val, new_val; \
+ int old_val, new_val; \
asm volatile( \
" l %0,%2\n" \
"0: lr %1,%0\n" \
@@ -38,7 +38,7 @@
#else /* __GNUC__ */
#define __CS_LOOP(ptr, op_val, op_string) ({ \
- typeof(ptr->counter) old_val, new_val; \
+ int old_val, new_val; \
asm volatile( \
" l %0,0(%3)\n" \
"0: lr %1,%0\n" \
@@ -143,7 +143,7 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
#define __CSG_LOOP(ptr, op_val, op_string) ({ \
- typeof(ptr->counter) old_val, new_val; \
+ long long old_val, new_val; \
asm volatile( \
" lg %0,%2\n" \
"0: lgr %1,%0\n" \
@@ -160,7 +160,7 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
#else /* __GNUC__ */
#define __CSG_LOOP(ptr, op_val, op_string) ({ \
- typeof(ptr->counter) old_val, new_val; \
+ long long old_val, new_val; \
asm volatile( \
" lg %0,0(%3)\n" \
"0: lgr %1,%0\n" \
diff --git a/arch/s390/include/asm/bug.h b/arch/s390/include/asm/bug.h
index 7efd0ab..efb74fd 100644
--- a/arch/s390/include/asm/bug.h
+++ b/arch/s390/include/asm/bug.h
@@ -49,7 +49,7 @@
#define BUG() do { \
__EMIT_BUG(0); \
- for (;;); \
+ unreachable(); \
} while (0)
#define WARN_ON(x) ({ \
diff --git a/arch/s390/include/asm/cacheflush.h b/arch/s390/include/asm/cacheflush.h
index 49d5af9..405cc97 100644
--- a/arch/s390/include/asm/cacheflush.h
+++ b/arch/s390/include/asm/cacheflush.h
@@ -10,6 +10,7 @@
#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
+#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0
#define flush_dcache_page(page) do { } while (0)
#define flush_dcache_mmap_lock(mapping) do { } while (0)
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
diff --git a/arch/s390/include/asm/ccwdev.h b/arch/s390/include/asm/ccwdev.h
index 2a54195..f4bd346 100644
--- a/arch/s390/include/asm/ccwdev.h
+++ b/arch/s390/include/asm/ccwdev.h
@@ -142,6 +142,8 @@ struct ccw1;
extern int ccw_device_set_options_mask(struct ccw_device *, unsigned long);
extern int ccw_device_set_options(struct ccw_device *, unsigned long);
extern void ccw_device_clear_options(struct ccw_device *, unsigned long);
+int ccw_device_is_pathgroup(struct ccw_device *cdev);
+int ccw_device_is_multipath(struct ccw_device *cdev);
/* Allow for i/o completion notification after primary interrupt status. */
#define CCWDEV_EARLY_NOTIFICATION 0x0001
@@ -151,6 +153,8 @@ extern void ccw_device_clear_options(struct ccw_device *, unsigned long);
#define CCWDEV_DO_PATHGROUP 0x0004
/* Allow forced onlining of boxed devices. */
#define CCWDEV_ALLOW_FORCE 0x0008
+/* Try to use multipath mode. */
+#define CCWDEV_DO_MULTIPATH 0x0010
extern int ccw_device_start(struct ccw_device *, struct ccw1 *,
unsigned long, __u8, unsigned long);
diff --git a/arch/s390/include/asm/cputime.h b/arch/s390/include/asm/cputime.h
index 24b1244..258ba88 100644
--- a/arch/s390/include/asm/cputime.h
+++ b/arch/s390/include/asm/cputime.h
@@ -78,7 +78,7 @@ cputime64_to_jiffies64(cputime64_t cputime)
static inline unsigned int
cputime_to_msecs(const cputime_t cputime)
{
- return __div(cputime, 4096000);
+ return cputime_div(cputime, 4096000);
}
static inline cputime_t
@@ -160,7 +160,7 @@ cputime_to_timeval(const cputime_t cputime, struct timeval *value)
static inline clock_t
cputime_to_clock_t(cputime_t cputime)
{
- return __div(cputime, 4096000000ULL / USER_HZ);
+ return cputime_div(cputime, 4096000000ULL / USER_HZ);
}
static inline cputime_t
@@ -175,7 +175,7 @@ clock_t_to_cputime(unsigned long x)
static inline clock_t
cputime64_to_clock_t(cputime64_t cputime)
{
- return __div(cputime, 4096000000ULL / USER_HZ);
+ return cputime_div(cputime, 4096000000ULL / USER_HZ);
}
struct s390_idle_data {
@@ -183,6 +183,7 @@ struct s390_idle_data {
unsigned long long idle_count;
unsigned long long idle_enter;
unsigned long long idle_time;
+ int nohz_delay;
};
DECLARE_PER_CPU(struct s390_idle_data, s390_idle);
@@ -198,4 +199,11 @@ static inline void s390_idle_check(void)
vtime_start_cpu();
}
+static inline int s390_nohz_delay(int cpu)
+{
+ return per_cpu(s390_idle, cpu).nohz_delay != 0;
+}
+
+#define arch_needs_cpu(cpu) s390_nohz_delay(cpu)
+
#endif /* _S390_CPUTIME_H */
diff --git a/arch/s390/include/asm/delay.h b/arch/s390/include/asm/delay.h
index a356c95..8a096b8 100644
--- a/arch/s390/include/asm/delay.h
+++ b/arch/s390/include/asm/delay.h
@@ -14,10 +14,11 @@
#ifndef _S390_DELAY_H
#define _S390_DELAY_H
-extern void __udelay(unsigned long usecs);
-extern void udelay_simple(unsigned long usecs);
+extern void __udelay(unsigned long long usecs);
+extern void udelay_simple(unsigned long long usecs);
extern void __delay(unsigned long loops);
-#define udelay(n) __udelay(n)
+#define udelay(n) __udelay((unsigned long long) (n))
+#define mdelay(n) __udelay((unsigned long long) (n) * 1000)
#endif /* defined(_S390_DELAY_H) */
diff --git a/arch/s390/include/asm/elf.h b/arch/s390/include/asm/elf.h
index 74d0bbb..354d426 100644
--- a/arch/s390/include/asm/elf.h
+++ b/arch/s390/include/asm/elf.h
@@ -92,6 +92,18 @@
/* Keep this the last entry. */
#define R_390_NUM 61
+/* Bits present in AT_HWCAP. */
+#define HWCAP_S390_ESAN3 1
+#define HWCAP_S390_ZARCH 2
+#define HWCAP_S390_STFLE 4
+#define HWCAP_S390_MSA 8
+#define HWCAP_S390_LDISP 16
+#define HWCAP_S390_EIMM 32
+#define HWCAP_S390_DFP 64
+#define HWCAP_S390_HPAGE 128
+#define HWCAP_S390_ETF3EH 256
+#define HWCAP_S390_HIGH_GPRS 512
+
/*
* These are used to set parameters in the core dumps.
*/
@@ -143,7 +155,6 @@ extern unsigned int vdso_enabled;
} while (0)
#define CORE_DUMP_USE_REGSET
-#define USE_ELF_CORE_DUMP
#define ELF_EXEC_PAGESIZE 4096
/* This is the location that an ET_DYN program is loaded if exec'ed. Typical
diff --git a/arch/s390/include/asm/kvm.h b/arch/s390/include/asm/kvm.h
index 3dfcaeb..82b32a1 100644
--- a/arch/s390/include/asm/kvm.h
+++ b/arch/s390/include/asm/kvm.h
@@ -1,6 +1,5 @@
#ifndef __LINUX_KVM_S390_H
#define __LINUX_KVM_S390_H
-
/*
* asm-s390/kvm.h - KVM s390 specific structures and definitions
*
@@ -15,6 +14,8 @@
*/
#include <linux/types.h>
+#define __KVM_S390
+
/* for KVM_GET_REGS and KVM_SET_REGS */
struct kvm_regs {
/* general purpose regs for s390 */
diff --git a/arch/s390/include/asm/mmu_context.h b/arch/s390/include/asm/mmu_context.h
index fc7edd6..976e273 100644
--- a/arch/s390/include/asm/mmu_context.h
+++ b/arch/s390/include/asm/mmu_context.h
@@ -36,7 +36,7 @@ static inline int init_new_context(struct task_struct *tsk,
mm->context.has_pgste = 1;
mm->context.alloc_pgste = 1;
} else {
- mm->context.noexec = s390_noexec;
+ mm->context.noexec = (user_mode == SECONDARY_SPACE_MODE);
mm->context.has_pgste = 0;
mm->context.alloc_pgste = 0;
}
@@ -58,7 +58,7 @@ static inline void update_mm(struct mm_struct *mm, struct task_struct *tsk)
pgd_t *pgd = mm->pgd;
S390_lowcore.user_asce = mm->context.asce_bits | __pa(pgd);
- if (switch_amode) {
+ if (user_mode != HOME_SPACE_MODE) {
/* Load primary space page table origin. */
pgd = mm->context.noexec ? get_shadow_table(pgd) : pgd;
S390_lowcore.user_exec_asce = mm->context.asce_bits | __pa(pgd);
diff --git a/arch/s390/include/asm/param.h b/arch/s390/include/asm/param.h
index 34aaa46..c616821 100644
--- a/arch/s390/include/asm/param.h
+++ b/arch/s390/include/asm/param.h
@@ -1,30 +1,6 @@
-/*
- * include/asm-s390/param.h
- *
- * S390 version
- *
- * Derived from "include/asm-i386/param.h"
- */
-
#ifndef _ASMS390_PARAM_H
#define _ASMS390_PARAM_H
-#ifdef __KERNEL__
-# define HZ CONFIG_HZ /* Internal kernel timer frequency */
-# define USER_HZ 100 /* .. some user interfaces are in "ticks" */
-# define CLOCKS_PER_SEC (USER_HZ) /* like times() */
-#endif
-
-#ifndef HZ
-#define HZ 100
-#endif
-
-#define EXEC_PAGESIZE 4096
-
-#ifndef NOGROUP
-#define NOGROUP (-1)
-#endif
-
-#define MAXHOSTNAMELEN 64 /* max length of hostname */
+#include <asm-generic/param.h>
-#endif
+#endif /* _ASMS390_PARAM_H */
diff --git a/arch/s390/include/asm/pgalloc.h b/arch/s390/include/asm/pgalloc.h
index ddad590..68940d0 100644
--- a/arch/s390/include/asm/pgalloc.h
+++ b/arch/s390/include/asm/pgalloc.h
@@ -143,7 +143,8 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
spin_lock_init(&mm->context.list_lock);
INIT_LIST_HEAD(&mm->context.crst_list);
INIT_LIST_HEAD(&mm->context.pgtable_list);
- return (pgd_t *) crst_table_alloc(mm, s390_noexec);
+ return (pgd_t *)
+ crst_table_alloc(mm, user_mode == SECONDARY_SPACE_MODE);
}
#define pgd_free(mm, pgd) crst_table_free(mm, (unsigned long *) pgd)
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
index 60a7b1a..e2fa79c 100644
--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -169,12 +169,13 @@ extern unsigned long VMALLOC_START;
* STL Segment-Table-Length: Segment-table length (STL+1*16 entries -> up to 2048)
*
* A 64 bit pagetable entry of S390 has following format:
- * | PFRA |0IP0| OS |
+ * | PFRA |0IPC| OS |
* 0000000000111111111122222222223333333333444444444455555555556666
* 0123456789012345678901234567890123456789012345678901234567890123
*
* I Page-Invalid Bit: Page is not available for address-translation
* P Page-Protection Bit: Store access not possible for page
+ * C Change-bit override: HW is not required to set change bit
*
* A 64 bit segmenttable entry of S390 has following format:
* | P-table origin | TT
@@ -218,6 +219,7 @@ extern unsigned long VMALLOC_START;
*/
/* Hardware bits in the page table entry */
+#define _PAGE_CO 0x100 /* HW Change-bit override */
#define _PAGE_RO 0x200 /* HW read-only bit */
#define _PAGE_INVALID 0x400 /* HW invalid bit */
diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h
index 539263f..95dcf18 100644
--- a/arch/s390/include/asm/ptrace.h
+++ b/arch/s390/include/asm/ptrace.h
@@ -311,6 +311,10 @@ typedef struct
__u32 orig_gpr2;
} s390_compat_regs;
+typedef struct
+{
+ __u32 gprs_high[NUM_GPRS];
+} s390_compat_regs_high;
#ifdef __KERNEL__
diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h
index e37478e..52a779c 100644
--- a/arch/s390/include/asm/setup.h
+++ b/arch/s390/include/asm/setup.h
@@ -49,17 +49,12 @@ extern unsigned long memory_end;
void detect_memory_layout(struct mem_chunk chunk[]);
-#ifdef CONFIG_S390_SWITCH_AMODE
-extern unsigned int switch_amode;
-#else
-#define switch_amode (0)
-#endif
-
-#ifdef CONFIG_S390_EXEC_PROTECT
-extern unsigned int s390_noexec;
-#else
-#define s390_noexec (0)
-#endif
+#define PRIMARY_SPACE_MODE 0
+#define ACCESS_REGISTER_MODE 1
+#define SECONDARY_SPACE_MODE 2
+#define HOME_SPACE_MODE 3
+
+extern unsigned int user_mode;
/*
* Machine features detected in head.S
diff --git a/arch/s390/include/asm/smp.h b/arch/s390/include/asm/smp.h
index a868b27..2ab1141 100644
--- a/arch/s390/include/asm/smp.h
+++ b/arch/s390/include/asm/smp.h
@@ -1,57 +1,22 @@
/*
- * include/asm-s390/smp.h
- *
- * S390 version
- * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
- * Martin Schwidefsky (schwidefsky@de.ibm.com)
- * Heiko Carstens (heiko.carstens@de.ibm.com)
+ * Copyright IBM Corp. 1999,2009
+ * Author(s): Denis Joseph Barrow,
+ * Martin Schwidefsky <schwidefsky@de.ibm.com>,
+ * Heiko Carstens <heiko.carstens@de.ibm.com>,
*/
#ifndef __ASM_SMP_H
#define __ASM_SMP_H
-#include <linux/threads.h>
-#include <linux/cpumask.h>
-#include <linux/bitops.h>
+#ifdef CONFIG_SMP
-#if defined(__KERNEL__) && defined(CONFIG_SMP) && !defined(__ASSEMBLY__)
-
-#include <asm/lowcore.h>
-#include <asm/sigp.h>
-#include <asm/ptrace.h>
#include <asm/system.h>
-
-/*
- s390 specific smp.c headers
- */
-typedef struct
-{
- int intresting;
- sigp_ccode ccode;
- __u32 status;
- __u16 cpu;
-} sigp_info;
+#include <asm/sigp.h>
extern void machine_restart_smp(char *);
extern void machine_halt_smp(void);
extern void machine_power_off_smp(void);
-#define NO_PROC_ID 0xFF /* No processor magic marker */
-
-/*
- * This magic constant controls our willingness to transfer
- * a process across CPUs. Such a transfer incurs misses on the L1
- * cache, and on a P6 or P5 with multiple L2 caches L2 hits. My
- * gut feeling is this will vary by board in value. For a board
- * with separate L2 cache it probably depends also on the RSS, and
- * for a board with shared L2 cache it ought to decay fast as other
- * processes are run.
- */
-
-#define PROC_CHANGE_PENALTY 20 /* Schedule penalty */
-
#define raw_smp_processor_id() (S390_lowcore.cpu_nr)
-#define cpu_logical_map(cpu) (cpu)
extern int __cpu_disable (void);
extern void __cpu_die (unsigned int cpu);
@@ -64,7 +29,9 @@ extern int smp_cpu_polarization[];
extern void arch_send_call_function_single_ipi(int cpu);
extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
-#endif
+extern union save_area *zfcpdump_save_areas[NR_CPUS + 1];
+
+#endif /* CONFIG_SMP */
#ifdef CONFIG_HOTPLUG_CPU
extern int smp_rescan_cpus(void);
@@ -72,5 +39,4 @@ extern int smp_rescan_cpus(void);
static inline int smp_rescan_cpus(void) { return 0; }
#endif
-extern union save_area *zfcpdump_save_areas[NR_CPUS + 1];
-#endif
+#endif /* __ASM_SMP_H */
diff --git a/arch/s390/include/asm/socket.h b/arch/s390/include/asm/socket.h
index e42df89..fdff1e9 100644
--- a/arch/s390/include/asm/socket.h
+++ b/arch/s390/include/asm/socket.h
@@ -68,4 +68,6 @@
#define SO_PROTOCOL 38
#define SO_DOMAIN 39
+#define SO_RXQ_OVFL 40
+
#endif /* _ASM_SOCKET_H */
diff --git a/arch/s390/include/asm/sockios.h b/arch/s390/include/asm/sockios.h
index f4fc16c..6f60eee 100644
--- a/arch/s390/include/asm/sockios.h
+++ b/arch/s390/include/asm/sockios.h
@@ -1,21 +1,6 @@
-/*
- * include/asm-s390/sockios.h
- *
- * S390 version
- *
- * Derived from "include/asm-i386/sockios.h"
- */
+#ifndef _ASM_S390_SOCKIOS_H
+#define _ASM_S390_SOCKIOS_H
-#ifndef __ARCH_S390_SOCKIOS__
-#define __ARCH_S390_SOCKIOS__
-
-/* Socket-level I/O control calls. */
-#define FIOSETOWN 0x8901
-#define SIOCSPGRP 0x8902
-#define FIOGETOWN 0x8903
-#define SIOCGPGRP 0x8904
-#define SIOCATMARK 0x8905
-#define SIOCGSTAMP 0x8906 /* Get stamp (timeval) */
-#define SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */
+#include <asm-generic/sockios.h>
#endif
diff --git a/arch/s390/include/asm/spinlock.h b/arch/s390/include/asm/spinlock.h
index 41ce686..a587907 100644
--- a/arch/s390/include/asm/spinlock.h
+++ b/arch/s390/include/asm/spinlock.h
@@ -52,27 +52,27 @@ _raw_compare_and_swap(volatile unsigned int *lock,
* (the type definitions are in asm/spinlock_types.h)
*/
-#define __raw_spin_is_locked(x) ((x)->owner_cpu != 0)
-#define __raw_spin_unlock_wait(lock) \
- do { while (__raw_spin_is_locked(lock)) \
- _raw_spin_relax(lock); } while (0)
+#define arch_spin_is_locked(x) ((x)->owner_cpu != 0)
+#define arch_spin_unlock_wait(lock) \
+ do { while (arch_spin_is_locked(lock)) \
+ arch_spin_relax(lock); } while (0)
-extern void _raw_spin_lock_wait(raw_spinlock_t *);
-extern void _raw_spin_lock_wait_flags(raw_spinlock_t *, unsigned long flags);
-extern int _raw_spin_trylock_retry(raw_spinlock_t *);
-extern void _raw_spin_relax(raw_spinlock_t *lock);
+extern void arch_spin_lock_wait(arch_spinlock_t *);
+extern void arch_spin_lock_wait_flags(arch_spinlock_t *, unsigned long flags);
+extern int arch_spin_trylock_retry(arch_spinlock_t *);
+extern void arch_spin_relax(arch_spinlock_t *lock);
-static inline void __raw_spin_lock(raw_spinlock_t *lp)
+static inline void arch_spin_lock(arch_spinlock_t *lp)
{
int old;
old = _raw_compare_and_swap(&lp->owner_cpu, 0, ~smp_processor_id());
if (likely(old == 0))
return;
- _raw_spin_lock_wait(lp);
+ arch_spin_lock_wait(lp);
}
-static inline void __raw_spin_lock_flags(raw_spinlock_t *lp,
+static inline void arch_spin_lock_flags(arch_spinlock_t *lp,
unsigned long flags)
{
int old;
@@ -80,20 +80,20 @@ static inline void __raw_spin_lock_flags(raw_spinlock_t *lp,
old = _raw_compare_and_swap(&lp->owner_cpu, 0, ~smp_processor_id());
if (likely(old == 0))
return;
- _raw_spin_lock_wait_flags(lp, flags);
+ arch_spin_lock_wait_flags(lp, flags);
}
-static inline int __raw_spin_trylock(raw_spinlock_t *lp)
+static inline int arch_spin_trylock(arch_spinlock_t *lp)
{
int old;
old = _raw_compare_and_swap(&lp->owner_cpu, 0, ~smp_processor_id());
if (likely(old == 0))
return 1;
- return _raw_spin_trylock_retry(lp);
+ return arch_spin_trylock_retry(lp);
}
-static inline void __raw_spin_unlock(raw_spinlock_t *lp)
+static inline void arch_spin_unlock(arch_spinlock_t *lp)
{
_raw_compare_and_swap(&lp->owner_cpu, lp->owner_cpu, 0);
}
@@ -113,22 +113,22 @@ static inline void __raw_spin_unlock(raw_spinlock_t *lp)
* read_can_lock - would read_trylock() succeed?
* @lock: the rwlock in question.
*/
-#define __raw_read_can_lock(x) ((int)(x)->lock >= 0)
+#define arch_read_can_lock(x) ((int)(x)->lock >= 0)
/**
* write_can_lock - would write_trylock() succeed?
* @lock: the rwlock in question.
*/
-#define __raw_write_can_lock(x) ((x)->lock == 0)
+#define arch_write_can_lock(x) ((x)->lock == 0)
-extern void _raw_read_lock_wait(raw_rwlock_t *lp);
-extern void _raw_read_lock_wait_flags(raw_rwlock_t *lp, unsigned long flags);
-extern int _raw_read_trylock_retry(raw_rwlock_t *lp);
-extern void _raw_write_lock_wait(raw_rwlock_t *lp);
-extern void _raw_write_lock_wait_flags(raw_rwlock_t *lp, unsigned long flags);
-extern int _raw_write_trylock_retry(raw_rwlock_t *lp);
+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);
-static inline void __raw_read_lock(raw_rwlock_t *rw)
+static inline void arch_read_lock(arch_rwlock_t *rw)
{
unsigned int old;
old = rw->lock & 0x7fffffffU;
@@ -136,7 +136,7 @@ static inline void __raw_read_lock(raw_rwlock_t *rw)
_raw_read_lock_wait(rw);
}
-static inline void __raw_read_lock_flags(raw_rwlock_t *rw, unsigned long flags)
+static inline void arch_read_lock_flags(arch_rwlock_t *rw, unsigned long flags)
{
unsigned int old;
old = rw->lock & 0x7fffffffU;
@@ -144,7 +144,7 @@ static inline void __raw_read_lock_flags(raw_rwlock_t *rw, unsigned long flags)
_raw_read_lock_wait_flags(rw, flags);
}
-static inline void __raw_read_unlock(raw_rwlock_t *rw)
+static inline void arch_read_unlock(arch_rwlock_t *rw)
{
unsigned int old, cmp;
@@ -155,24 +155,24 @@ static inline void __raw_read_unlock(raw_rwlock_t *rw)
} while (cmp != old);
}
-static inline void __raw_write_lock(raw_rwlock_t *rw)
+static inline void arch_write_lock(arch_rwlock_t *rw)
{
if (unlikely(_raw_compare_and_swap(&rw->lock, 0, 0x80000000) != 0))
_raw_write_lock_wait(rw);
}
-static inline void __raw_write_lock_flags(raw_rwlock_t *rw, unsigned long flags)
+static inline void arch_write_lock_flags(arch_rwlock_t *rw, unsigned long flags)
{
if (unlikely(_raw_compare_and_swap(&rw->lock, 0, 0x80000000) != 0))
_raw_write_lock_wait_flags(rw, flags);
}
-static inline void __raw_write_unlock(raw_rwlock_t *rw)
+static inline void arch_write_unlock(arch_rwlock_t *rw)
{
_raw_compare_and_swap(&rw->lock, 0x80000000, 0);
}
-static inline int __raw_read_trylock(raw_rwlock_t *rw)
+static inline int arch_read_trylock(arch_rwlock_t *rw)
{
unsigned int old;
old = rw->lock & 0x7fffffffU;
@@ -181,43 +181,14 @@ static inline int __raw_read_trylock(raw_rwlock_t *rw)
return _raw_read_trylock_retry(rw);
}
-static inline int __raw_write_trylock(raw_rwlock_t *rw)
+static inline int arch_write_trylock(arch_rwlock_t *rw)
{
if (likely(_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0))
return 1;
return _raw_write_trylock_retry(rw);
}
-#define _raw_read_relax(lock) cpu_relax()
-#define _raw_write_relax(lock) cpu_relax()
-
-#define __always_inline__spin_lock
-#define __always_inline__read_lock
-#define __always_inline__write_lock
-#define __always_inline__spin_lock_bh
-#define __always_inline__read_lock_bh
-#define __always_inline__write_lock_bh
-#define __always_inline__spin_lock_irq
-#define __always_inline__read_lock_irq
-#define __always_inline__write_lock_irq
-#define __always_inline__spin_lock_irqsave
-#define __always_inline__read_lock_irqsave
-#define __always_inline__write_lock_irqsave
-#define __always_inline__spin_trylock
-#define __always_inline__read_trylock
-#define __always_inline__write_trylock
-#define __always_inline__spin_trylock_bh
-#define __always_inline__spin_unlock
-#define __always_inline__read_unlock
-#define __always_inline__write_unlock
-#define __always_inline__spin_unlock_bh
-#define __always_inline__read_unlock_bh
-#define __always_inline__write_unlock_bh
-#define __always_inline__spin_unlock_irq
-#define __always_inline__read_unlock_irq
-#define __always_inline__write_unlock_irq
-#define __always_inline__spin_unlock_irqrestore
-#define __always_inline__read_unlock_irqrestore
-#define __always_inline__write_unlock_irqrestore
+#define arch_read_relax(lock) cpu_relax()
+#define arch_write_relax(lock) cpu_relax()
#endif /* __ASM_SPINLOCK_H */
diff --git a/arch/s390/include/asm/spinlock_types.h b/arch/s390/include/asm/spinlock_types.h
index 654abc4..9c76656 100644
--- a/arch/s390/include/asm/spinlock_types.h
+++ b/arch/s390/include/asm/spinlock_types.h
@@ -7,14 +7,14 @@
typedef struct {
volatile unsigned int owner_cpu;
-} __attribute__ ((aligned (4))) raw_spinlock_t;
+} __attribute__ ((aligned (4))) arch_spinlock_t;
-#define __RAW_SPIN_LOCK_UNLOCKED { 0 }
+#define __ARCH_SPIN_LOCK_UNLOCKED { 0 }
typedef struct {
volatile unsigned int lock;
-} raw_rwlock_t;
+} arch_rwlock_t;
-#define __RAW_RW_LOCK_UNLOCKED { 0 }
+#define __ARCH_RW_LOCK_UNLOCKED { 0 }
#endif
diff --git a/arch/s390/include/asm/termbits.h b/arch/s390/include/asm/termbits.h
index 58731853..71bf6ac 100644
--- a/arch/s390/include/asm/termbits.h
+++ b/arch/s390/include/asm/termbits.h
@@ -1,206 +1,6 @@
-/*
- * include/asm-s390/termbits.h
- *
- * S390 version
- *
- * Derived from "include/asm-i386/termbits.h"
- */
+#ifndef _ASM_S390_TERMBITS_H
+#define _ASM_S390_TERMBITS_H
-#ifndef __ARCH_S390_TERMBITS_H__
-#define __ARCH_S390_TERMBITS_H__
-
-#include <linux/posix_types.h>
-
-typedef unsigned char cc_t;
-typedef unsigned int speed_t;
-typedef unsigned int tcflag_t;
-
-#define NCCS 19
-struct termios {
- tcflag_t c_iflag; /* input mode flags */
- tcflag_t c_oflag; /* output mode flags */
- tcflag_t c_cflag; /* control mode flags */
- tcflag_t c_lflag; /* local mode flags */
- cc_t c_line; /* line discipline */
- cc_t c_cc[NCCS]; /* control characters */
-};
-
-struct termios2 {
- tcflag_t c_iflag; /* input mode flags */
- tcflag_t c_oflag; /* output mode flags */
- tcflag_t c_cflag; /* control mode flags */
- tcflag_t c_lflag; /* local mode flags */
- cc_t c_line; /* line discipline */
- cc_t c_cc[NCCS]; /* control characters */
- speed_t c_ispeed; /* input speed */
- speed_t c_ospeed; /* output speed */
-};
-
-struct ktermios {
- tcflag_t c_iflag; /* input mode flags */
- tcflag_t c_oflag; /* output mode flags */
- tcflag_t c_cflag; /* control mode flags */
- tcflag_t c_lflag; /* local mode flags */
- cc_t c_line; /* line discipline */
- cc_t c_cc[NCCS]; /* control characters */
- speed_t c_ispeed; /* input speed */
- speed_t c_ospeed; /* output speed */
-};
-
-/* c_cc characters */
-#define VINTR 0
-#define VQUIT 1
-#define VERASE 2
-#define VKILL 3
-#define VEOF 4
-#define VTIME 5
-#define VMIN 6
-#define VSWTC 7
-#define VSTART 8
-#define VSTOP 9
-#define VSUSP 10
-#define VEOL 11
-#define VREPRINT 12
-#define VDISCARD 13
-#define VWERASE 14
-#define VLNEXT 15
-#define VEOL2 16
-
-/* c_iflag bits */
-#define IGNBRK 0000001
-#define BRKINT 0000002
-#define IGNPAR 0000004
-#define PARMRK 0000010
-#define INPCK 0000020
-#define ISTRIP 0000040
-#define INLCR 0000100
-#define IGNCR 0000200
-#define ICRNL 0000400
-#define IUCLC 0001000
-#define IXON 0002000
-#define IXANY 0004000
-#define IXOFF 0010000
-#define IMAXBEL 0020000
-#define IUTF8 0040000
-
-/* c_oflag bits */
-#define OPOST 0000001
-#define OLCUC 0000002
-#define ONLCR 0000004
-#define OCRNL 0000010
-#define ONOCR 0000020
-#define ONLRET 0000040
-#define OFILL 0000100
-#define OFDEL 0000200
-#define NLDLY 0000400
-#define NL0 0000000
-#define NL1 0000400
-#define CRDLY 0003000
-#define CR0 0000000
-#define CR1 0001000
-#define CR2 0002000
-#define CR3 0003000
-#define TABDLY 0014000
-#define TAB0 0000000
-#define TAB1 0004000
-#define TAB2 0010000
-#define TAB3 0014000
-#define XTABS 0014000
-#define BSDLY 0020000
-#define BS0 0000000
-#define BS1 0020000
-#define VTDLY 0040000
-#define VT0 0000000
-#define VT1 0040000
-#define FFDLY 0100000
-#define FF0 0000000
-#define FF1 0100000
-
-/* c_cflag bit meaning */
-#define CBAUD 0010017
-#define B0 0000000 /* hang up */
-#define B50 0000001
-#define B75 0000002
-#define B110 0000003
-#define B134 0000004
-#define B150 0000005
-#define B200 0000006
-#define B300 0000007
-#define B600 0000010
-#define B1200 0000011
-#define B1800 0000012
-#define B2400 0000013
-#define B4800 0000014
-#define B9600 0000015
-#define B19200 0000016
-#define B38400 0000017
-#define EXTA B19200
-#define EXTB B38400
-#define CSIZE 0000060
-#define CS5 0000000
-#define CS6 0000020
-#define CS7 0000040
-#define CS8 0000060
-#define CSTOPB 0000100
-#define CREAD 0000200
-#define PARENB 0000400
-#define PARODD 0001000
-#define HUPCL 0002000
-#define CLOCAL 0004000
-#define CBAUDEX 0010000
-#define BOTHER 0010000
-#define B57600 0010001
-#define B115200 0010002
-#define B230400 0010003
-#define B460800 0010004
-#define B500000 0010005
-#define B576000 0010006
-#define B921600 0010007
-#define B1000000 0010010
-#define B1152000 0010011
-#define B1500000 0010012
-#define B2000000 0010013
-#define B2500000 0010014
-#define B3000000 0010015
-#define B3500000 0010016
-#define B4000000 0010017
-#define CIBAUD 002003600000 /* input baud rate */
-#define CMSPAR 010000000000 /* mark or space (stick) parity */
-#define CRTSCTS 020000000000 /* flow control */
-
-#define IBSHIFT 16 /* Shift from CBAUD to CIBAUD */
-
-/* c_lflag bits */
-#define ISIG 0000001
-#define ICANON 0000002
-#define XCASE 0000004
-#define ECHO 0000010
-#define ECHOE 0000020
-#define ECHOK 0000040
-#define ECHONL 0000100
-#define NOFLSH 0000200
-#define TOSTOP 0000400
-#define ECHOCTL 0001000
-#define ECHOPRT 0002000
-#define ECHOKE 0004000
-#define FLUSHO 0010000
-#define PENDIN 0040000
-#define IEXTEN 0100000
-
-/* tcflow() and TCXONC use these */
-#define TCOOFF 0
-#define TCOON 1
-#define TCIOFF 2
-#define TCION 3
-
-/* tcflush() and TCFLSH use these */
-#define TCIFLUSH 0
-#define TCOFLUSH 1
-#define TCIOFLUSH 2
-
-/* tcsetattr uses these */
-#define TCSANOW 0
-#define TCSADRAIN 1
-#define TCSAFLUSH 2
+#include <asm-generic/termbits.h>
#endif
diff --git a/arch/s390/include/asm/todclk.h b/arch/s390/include/asm/todclk.h
deleted file mode 100644
index c7f6205..0000000
--- a/arch/s390/include/asm/todclk.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * File...........: linux/include/asm/todclk.h
- * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
- * Bugreports.to..: <Linux390@de.ibm.com>
- * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
- *
- * History of changes (starts July 2000)
- */
-
-#ifndef __ASM_TODCLK_H
-#define __ASM_TODCLK_H
-
-#ifdef __KERNEL__
-
-#define TOD_uSEC (0x1000ULL)
-#define TOD_mSEC (1000 * TOD_uSEC)
-#define TOD_SEC (1000 * TOD_mSEC)
-#define TOD_MIN (60 * TOD_SEC)
-#define TOD_HOUR (60 * TOD_MIN)
-
-#endif
-
-#endif
diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h
index 8377e91..cbf0a87 100644
--- a/arch/s390/include/asm/uaccess.h
+++ b/arch/s390/include/asm/uaccess.h
@@ -93,6 +93,8 @@ extern struct uaccess_ops uaccess_mvcos;
extern struct uaccess_ops uaccess_mvcos_switch;
extern struct uaccess_ops uaccess_pt;
+extern int __handle_fault(unsigned long, unsigned long, int);
+
static inline int __put_user_fn(size_t size, void __user *ptr, void *x)
{
size = uaccess.copy_to_user_small(size, ptr, x);
diff --git a/arch/s390/include/asm/ucontext.h b/arch/s390/include/asm/ucontext.h
index d69bec0..cfb874e 100644
--- a/arch/s390/include/asm/ucontext.h
+++ b/arch/s390/include/asm/ucontext.h
@@ -9,6 +9,21 @@
#ifndef _ASM_S390_UCONTEXT_H
#define _ASM_S390_UCONTEXT_H
+#define UC_EXTENDED 0x00000001
+
+#ifndef __s390x__
+
+struct ucontext_extended {
+ unsigned long uc_flags;
+ struct ucontext *uc_link;
+ stack_t uc_stack;
+ _sigregs uc_mcontext;
+ unsigned long uc_sigmask[2];
+ unsigned long uc_gprs_high[16];
+};
+
+#endif
+
struct ucontext {
unsigned long uc_flags;
struct ucontext *uc_link;
diff --git a/arch/s390/include/asm/unistd.h b/arch/s390/include/asm/unistd.h
index cb5232d..192a720 100644
--- a/arch/s390/include/asm/unistd.h
+++ b/arch/s390/include/asm/unistd.h
@@ -269,7 +269,8 @@
#define __NR_pwritev 329
#define __NR_rt_tgsigqueueinfo 330
#define __NR_perf_event_open 331
-#define NR_syscalls 332
+#define __NR_recvmmsg 332
+#define NR_syscalls 333
/*
* There are some system calls that are not present on 64 bit, some
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index c7be8e1..683f638 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -44,6 +44,7 @@ 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
# Kexec part
S390_KEXEC_OBJS := machine_kexec.o crash.o
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index 0debcec..22c9e55 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -31,14 +31,8 @@
#include <linux/shm.h>
#include <linux/slab.h>
#include <linux/uio.h>
-#include <linux/nfs_fs.h>
#include <linux/quota.h>
#include <linux/module.h>
-#include <linux/sunrpc/svc.h>
-#include <linux/nfsd/nfsd.h>
-#include <linux/nfsd/cache.h>
-#include <linux/nfsd/xdr.h>
-#include <linux/nfsd/syscall.h>
#include <linux/poll.h>
#include <linux/personality.h>
#include <linux/stat.h>
@@ -527,59 +521,6 @@ asmlinkage long sys32_sendfile64(int out_fd, int in_fd,
return ret;
}
-#ifdef CONFIG_SYSCTL_SYSCALL
-struct __sysctl_args32 {
- u32 name;
- int nlen;
- u32 oldval;
- u32 oldlenp;
- u32 newval;
- u32 newlen;
- u32 __unused[4];
-};
-
-asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
-{
- struct __sysctl_args32 tmp;
- int error;
- size_t oldlen;
- size_t __user *oldlenp = NULL;
- unsigned long addr = (((unsigned long)&args->__unused[0]) + 7) & ~7;
-
- if (copy_from_user(&tmp, args, sizeof(tmp)))
- return -EFAULT;
-
- if (tmp.oldval && tmp.oldlenp) {
- /* Duh, this is ugly and might not work if sysctl_args
- is in read-only memory, but do_sysctl does indirectly
- a lot of uaccess in both directions and we'd have to
- basically copy the whole sysctl.c here, and
- glibc's __sysctl uses rw memory for the structure
- anyway. */
- if (get_user(oldlen, (u32 __user *)compat_ptr(tmp.oldlenp)) ||
- put_user(oldlen, (size_t __user *)addr))
- return -EFAULT;
- oldlenp = (size_t __user *)addr;
- }
-
- lock_kernel();
- error = do_sysctl(compat_ptr(tmp.name), tmp.nlen, compat_ptr(tmp.oldval),
- oldlenp, compat_ptr(tmp.newval), tmp.newlen);
- unlock_kernel();
- if (oldlenp) {
- if (!error) {
- if (get_user(oldlen, (size_t __user *)addr) ||
- put_user(oldlen, (u32 __user *)compat_ptr(tmp.oldlenp)))
- error = -EFAULT;
- }
- if (copy_to_user(args->__unused, tmp.__unused,
- sizeof(tmp.__unused)))
- error = -EFAULT;
- }
- return error;
-}
-#endif
-
struct stat64_emu31 {
unsigned long long st_dev;
unsigned int __pad1;
@@ -683,38 +624,6 @@ struct mmap_arg_struct_emu31 {
u32 offset;
};
-/* common code for old and new mmaps */
-static inline long do_mmap2(
- unsigned long addr, unsigned long len,
- unsigned long prot, unsigned long flags,
- unsigned long fd, unsigned long pgoff)
-{
- struct file * file = NULL;
- unsigned long error = -EBADF;
-
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
- if (!(flags & MAP_ANONYMOUS)) {
- file = fget(fd);
- if (!file)
- goto out;
- }
-
- down_write(&current->mm->mmap_sem);
- error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
- if (!IS_ERR((void *) error) && error + len >= 0x80000000ULL) {
- /* Result is out of bounds. */
- do_munmap(current->mm, addr, len);
- error = -ENOMEM;
- }
- up_write(&current->mm->mmap_sem);
-
- if (file)
- fput(file);
-out:
- return error;
-}
-
-
asmlinkage unsigned long
old32_mmap(struct mmap_arg_struct_emu31 __user *arg)
{
@@ -728,7 +637,8 @@ old32_mmap(struct mmap_arg_struct_emu31 __user *arg)
if (a.offset & ~PAGE_MASK)
goto out;
- error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
+ error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd,
+ a.offset >> PAGE_SHIFT);
out:
return error;
}
@@ -741,7 +651,7 @@ sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg)
if (copy_from_user(&a, arg, sizeof(a)))
goto out;
- error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
+ error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
out:
return error;
}
diff --git a/arch/s390/kernel/compat_linux.h b/arch/s390/kernel/compat_linux.h
index c07f9ca..cb97afc 100644
--- a/arch/s390/kernel/compat_linux.h
+++ b/arch/s390/kernel/compat_linux.h
@@ -4,10 +4,6 @@
#include <linux/compat.h>
#include <linux/socket.h>
#include <linux/syscalls.h>
-#include <linux/nfs_fs.h>
-#include <linux/sunrpc/svc.h>
-#include <linux/nfsd/nfsd.h>
-#include <linux/nfsd/export.h>
/* Macro that masks the high order bit of an 32 bit pointer and converts it*/
/* to a 64 bit pointer */
@@ -162,7 +158,6 @@ struct ucontext32 {
compat_sigset_t uc_sigmask; /* mask last for extensibility */
};
-struct __sysctl_args32;
struct stat64_emu31;
struct mmap_arg_struct_emu31;
struct fadvise64_64_args;
@@ -212,7 +207,6 @@ long sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset,
size_t count);
long sys32_sendfile64(int out_fd, int in_fd, compat_loff_t __user *offset,
s32 count);
-long sys32_sysctl(struct __sysctl_args32 __user *args);
long sys32_stat64(char __user * filename, struct stat64_emu31 __user * statbuf);
long sys32_lstat64(char __user * filename,
struct stat64_emu31 __user * statbuf);
diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c
index b537cb0..eee9998 100644
--- a/arch/s390/kernel/compat_signal.c
+++ b/arch/s390/kernel/compat_signal.c
@@ -39,6 +39,7 @@ typedef struct
struct sigcontext32 sc;
_sigregs32 sregs;
int signo;
+ __u32 gprs_high[NUM_GPRS];
__u8 retcode[S390_SYSCALL_SIZE];
} sigframe32;
@@ -48,6 +49,7 @@ typedef struct
__u8 retcode[S390_SYSCALL_SIZE];
compat_siginfo_t info;
struct ucontext32 uc;
+ __u32 gprs_high[NUM_GPRS];
} rt_sigframe32;
int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
@@ -344,6 +346,30 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
return 0;
}
+static int save_sigregs_gprs_high(struct pt_regs *regs, __u32 __user *uregs)
+{
+ __u32 gprs_high[NUM_GPRS];
+ int i;
+
+ for (i = 0; i < NUM_GPRS; i++)
+ gprs_high[i] = regs->gprs[i] >> 32;
+
+ return __copy_to_user(uregs, &gprs_high, sizeof(gprs_high));
+}
+
+static int restore_sigregs_gprs_high(struct pt_regs *regs, __u32 __user *uregs)
+{
+ __u32 gprs_high[NUM_GPRS];
+ int err, i;
+
+ err = __copy_from_user(&gprs_high, uregs, sizeof(gprs_high));
+ if (err)
+ return err;
+ for (i = 0; i < NUM_GPRS; i++)
+ *(__u32 *)&regs->gprs[i] = gprs_high[i];
+ return 0;
+}
+
asmlinkage long sys32_sigreturn(void)
{
struct pt_regs *regs = task_pt_regs(current);
@@ -363,6 +389,8 @@ asmlinkage long sys32_sigreturn(void)
if (restore_sigregs32(regs, &frame->sregs))
goto badframe;
+ if (restore_sigregs_gprs_high(regs, frame->gprs_high))
+ goto badframe;
return regs->gprs[2];
@@ -394,6 +422,8 @@ asmlinkage long sys32_rt_sigreturn(void)
if (restore_sigregs32(regs, &frame->uc.uc_mcontext))
goto badframe;
+ if (restore_sigregs_gprs_high(regs, frame->gprs_high))
+ goto badframe;
err = __get_user(ss_sp, &frame->uc.uc_stack.ss_sp);
st.ss_sp = compat_ptr(ss_sp);
@@ -474,6 +504,8 @@ static int setup_frame32(int sig, struct k_sigaction *ka,
if (save_sigregs32(regs, &frame->sregs))
goto give_sigsegv;
+ if (save_sigregs_gprs_high(regs, frame->gprs_high))
+ goto give_sigsegv;
if (__put_user((unsigned long) &frame->sregs, &frame->sc.sregs))
goto give_sigsegv;
@@ -529,13 +561,14 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
goto give_sigsegv;
/* Create the ucontext. */
- err |= __put_user(0, &frame->uc.uc_flags);
+ err |= __put_user(UC_EXTENDED, &frame->uc.uc_flags);
err |= __put_user(0, &frame->uc.uc_link);
err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
err |= __put_user(sas_ss_flags(regs->gprs[15]),
&frame->uc.uc_stack.ss_flags);
err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
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)
goto give_sigsegv;
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index 682fb69..faeaccc 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -409,7 +409,7 @@ sys32_munmap_wrapper:
.globl sys32_truncate_wrapper
sys32_truncate_wrapper:
llgtr %r2,%r2 # const char *
- llgfr %r3,%r3 # unsigned long
+ lgfr %r3,%r3 # long
jg sys_truncate # branch to system call
.globl sys32_ftruncate_wrapper
@@ -689,8 +689,6 @@ sys32_fdatasync_wrapper:
llgfr %r2,%r2 # unsigned int
jg sys_fdatasync # branch to system call
-#sys32_sysctl_wrapper # tbd
-
.globl sys32_mlock_wrapper
sys32_mlock_wrapper:
llgfr %r2,%r2 # unsigned long
@@ -1087,8 +1085,8 @@ sys32_stime_wrapper:
.globl sys32_sysctl_wrapper
sys32_sysctl_wrapper:
- llgtr %r2,%r2 # struct __sysctl_args32 *
- jg sys32_sysctl
+ llgtr %r2,%r2 # struct compat_sysctl_args *
+ jg compat_sys_sysctl
.globl sys32_fstat64_wrapper
sys32_fstat64_wrapper:
@@ -1855,3 +1853,12 @@ sys32_execve_wrapper:
llgtr %r3,%r3 # compat_uptr_t *
llgtr %r4,%r4 # compat_uptr_t *
jg sys32_execve # branch to system call
+
+ .globl compat_sys_recvmmsg_wrapper
+compat_sys_recvmmsg_wrapper:
+ lgfr %r2,%r2 # int
+ llgtr %r3,%r3 # struct compat_mmsghdr *
+ llgfr %r4,%r4 # unsigned int
+ llgfr %r5,%r5 # unsigned int
+ llgtr %r6,%r6 # struct compat_timespec *
+ jg compat_sys_recvmmsg
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index 20f282c..0168472 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -18,6 +18,7 @@
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/ctype.h>
+#include <linux/string.h>
#include <linux/sysctl.h>
#include <asm/uaccess.h>
#include <linux/module.h>
@@ -893,35 +894,30 @@ s390dbf_procactive(ctl_table *table, int write,
static struct ctl_table s390dbf_table[] = {
{
- .ctl_name = CTL_S390DBF_STOPPABLE,
.procname = "debug_stoppable",
.data = &debug_stoppable,
.maxlen = sizeof(int),
.mode = S_IRUGO | S_IWUSR,
- .proc_handler = &proc_dointvec,
- .strategy = &sysctl_intvec,
+ .proc_handler = proc_dointvec,
},
{
- .ctl_name = CTL_S390DBF_ACTIVE,
.procname = "debug_active",
.data = &debug_active,
.maxlen = sizeof(int),
.mode = S_IRUGO | S_IWUSR,
- .proc_handler = &s390dbf_procactive,
- .strategy = &sysctl_intvec,
+ .proc_handler = s390dbf_procactive,
},
- { .ctl_name = 0 }
+ { }
};
static struct ctl_table s390dbf_dir_table[] = {
{
- .ctl_name = CTL_S390DBF,
.procname = "s390dbf",
.maxlen = 0,
.mode = S_IRUGO | S_IXUGO,
.child = s390dbf_table,
},
- { .ctl_name = 0 }
+ { }
};
static struct ctl_table_header *s390dbf_sysctl_header;
@@ -1183,7 +1179,7 @@ debug_get_uint(char *buf)
{
int rc;
- for(; isspace(*buf); buf++);
+ buf = skip_spaces(buf);
rc = simple_strtoul(buf, &buf, 10);
if(*buf){
rc = -EINVAL;
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index bf8b4ae..e49e9e0 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -55,6 +55,7 @@ static void __init reset_tod_clock(void)
disabled_wait(0);
sched_clock_base_cc = TOD_UNIX_EPOCH;
+ S390_lowcore.last_update_clock = sched_clock_base_cc;
}
#ifdef CONFIG_SHARED_KERNEL
@@ -167,6 +168,14 @@ static noinline __init void create_kernel_nss(void)
return;
}
+ /* re-initialize cputime accounting. */
+ sched_clock_base_cc = get_clock();
+ S390_lowcore.last_update_clock = sched_clock_base_cc;
+ S390_lowcore.last_update_timer = 0x7fffffffffffffffULL;
+ S390_lowcore.user_timer = 0;
+ S390_lowcore.system_timer = 0;
+ asm volatile("SPT 0(%0)" : : "a" (&S390_lowcore.last_update_timer));
+
/* re-setup boot command line with new ipl vm parms */
ipl_update_parameters();
setup_boot_command_line();
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index f43d2ee..48215d1 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -565,10 +565,10 @@ pgm_svcper:
lh %r7,0x8a # get svc number from lowcore
l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
TRACE_IRQS_OFF
- l %r1,__TI_task(%r9)
- mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID
- mvc __THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS
- mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID
+ l %r8,__TI_task(%r9)
+ mvc __THREAD_per+__PER_atmid(2,%r8),__LC_PER_ATMID
+ mvc __THREAD_per+__PER_address(4,%r8),__LC_PER_ADDRESS
+ mvc __THREAD_per+__PER_access_id(1,%r8),__LC_PER_ACCESS_ID
oi __TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
TRACE_IRQS_ON
stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index a6f7b20..9aff1d4 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -543,10 +543,10 @@ pgm_svcper:
mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore
lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct
- lg %r1,__TI_task(%r9)
- mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID
- mvc __THREAD_per+__PER_address(8,%r1),__LC_PER_ADDRESS
- mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID
+ lg %r8,__TI_task(%r9)
+ mvc __THREAD_per+__PER_atmid(2,%r8),__LC_PER_ATMID
+ mvc __THREAD_per+__PER_address(8,%r8),__LC_PER_ADDRESS
+ mvc __THREAD_per+__PER_access_id(1,%r8),__LC_PER_ACCESS_ID
oi __TI_flags+7(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
TRACE_IRQS_ON
stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
diff --git a/arch/s390/kernel/ftrace.c b/arch/s390/kernel/ftrace.c
index 57bdcb1..5a82bc6 100644
--- a/arch/s390/kernel/ftrace.c
+++ b/arch/s390/kernel/ftrace.c
@@ -185,9 +185,6 @@ unsigned long prepare_ftrace_return(unsigned long ip, unsigned long parent)
{
struct ftrace_graph_ent trace;
- /* Nmi's are currently unsupported. */
- if (unlikely(in_nmi()))
- goto out;
if (unlikely(atomic_read(&current->tracing_graph_pause)))
goto out;
if (ftrace_push_return_trace(parent, ip, &trace.depth, 0) == -EBUSY)
@@ -206,73 +203,10 @@ out:
#ifdef CONFIG_FTRACE_SYSCALLS
-extern unsigned long __start_syscalls_metadata[];
-extern unsigned long __stop_syscalls_metadata[];
extern unsigned int sys_call_table[];
-static struct syscall_metadata **syscalls_metadata;
-
-struct syscall_metadata *syscall_nr_to_meta(int nr)
-{
- if (!syscalls_metadata || nr >= NR_syscalls || nr < 0)
- return NULL;
-
- return syscalls_metadata[nr];
-}
-
-int syscall_name_to_nr(char *name)
-{
- int i;
-
- if (!syscalls_metadata)
- return -1;
- for (i = 0; i < NR_syscalls; i++)
- if (syscalls_metadata[i])
- if (!strcmp(syscalls_metadata[i]->name, name))
- return i;
- return -1;
-}
-
-void set_syscall_enter_id(int num, int id)
-{
- syscalls_metadata[num]->enter_id = id;
-}
-
-void set_syscall_exit_id(int num, int id)
+unsigned long __init arch_syscall_addr(int nr)
{
- syscalls_metadata[num]->exit_id = id;
-}
-
-static struct syscall_metadata *find_syscall_meta(unsigned long syscall)
-{
- struct syscall_metadata *start;
- struct syscall_metadata *stop;
- char str[KSYM_SYMBOL_LEN];
-
- start = (struct syscall_metadata *)__start_syscalls_metadata;
- stop = (struct syscall_metadata *)__stop_syscalls_metadata;
- kallsyms_lookup(syscall, NULL, NULL, NULL, str);
-
- for ( ; start < stop; start++) {
- if (start->name && !strcmp(start->name + 3, str + 3))
- return start;
- }
- return NULL;
-}
-
-static int __init arch_init_ftrace_syscalls(void)
-{
- struct syscall_metadata *meta;
- int i;
- syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) * NR_syscalls,
- GFP_KERNEL);
- if (!syscalls_metadata)
- return -ENOMEM;
- for (i = 0; i < NR_syscalls; i++) {
- meta = find_syscall_meta((unsigned long)sys_call_table[i]);
- syscalls_metadata[i] = meta;
- }
- return 0;
+ return (unsigned long)sys_call_table[nr];
}
-arch_initcall(arch_init_ftrace_syscalls);
#endif
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
index 6a25080..d984a2a 100644
--- a/arch/s390/kernel/head64.S
+++ b/arch/s390/kernel/head64.S
@@ -83,6 +83,8 @@ startup_continue:
slr %r0,%r0 # set cpuid to zero
sigp %r1,%r0,0x12 # switch to esame mode
sam64 # switch to 64 bit mode
+ llgfr %r13,%r13 # clear high-order half of base reg
+ lmh %r0,%r15,.Lzero64-.LPG1(%r13) # clear high-order half
lctlg %c0,%c15,.Lctl-.LPG1(%r13) # load control registers
lg %r12,.Lparmaddr-.LPG1(%r13) # pointer to parameter area
# move IPL device to lowcore
@@ -127,6 +129,7 @@ startup_continue:
.L4malign:.quad 0xffffffffffc00000
.Lscan2g:.quad 0x80000000 + 0x20000 - 8 # 2GB + 128K - 8
.Lnop: .long 0x07000700
+.Lzero64:.fill 16,4,0x0
#ifdef CONFIG_ZFCPDUMP
.Lcurrent_cpu:
.long 0x0
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index ee57a42..4d73296 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -221,7 +221,7 @@ static ssize_t sys_##_prefix##_##_name##_store(struct kobject *kobj, \
const char *buf, size_t len) \
{ \
strncpy(_value, buf, sizeof(_value) - 1); \
- strstrip(_value); \
+ strim(_value); \
return len; \
} \
static struct kobj_attribute sys_##_prefix##_##_name##_attr = \
@@ -472,7 +472,7 @@ static ssize_t ipl_ccw_loadparm_show(struct kobject *kobj,
return sprintf(page, "#unknown#\n");
memcpy(loadparm, &sclp_ipl_info.loadparm, LOADPARM_LEN);
EBCASC(loadparm, LOADPARM_LEN);
- strstrip(loadparm);
+ strim(loadparm);
return sprintf(page, "%s\n", loadparm);
}
@@ -776,7 +776,7 @@ static void reipl_get_ascii_loadparm(char *loadparm,
memcpy(loadparm, ibp->ipl_info.ccw.load_parm, LOADPARM_LEN);
EBCASC(loadparm, LOADPARM_LEN);
loadparm[LOADPARM_LEN] = 0;
- strstrip(loadparm);
+ strim(loadparm);
}
static ssize_t reipl_generic_loadparm_show(struct ipl_parameter_block *ipb,
@@ -1595,10 +1595,9 @@ static void stop_run(struct shutdown_trigger *trigger)
{
if (strcmp(trigger->name, ON_PANIC_STR) == 0)
disabled_wait((unsigned long) __builtin_return_address(0));
- else {
- signal_processor(smp_processor_id(), sigp_stop);
- for (;;);
- }
+ while (signal_processor(smp_processor_id(), sigp_stop) == sigp_busy)
+ cpu_relax();
+ for (;;);
}
static struct shutdown_action stop_action = {SHUTDOWN_ACTION_STOP_STR,
diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c
index ab2e3ed..639380a 100644
--- a/arch/s390/kernel/module.c
+++ b/arch/s390/kernel/module.c
@@ -55,6 +55,8 @@ void *module_alloc(unsigned long size)
/* Free memory returned from module_alloc */
void module_free(struct module *mod, void *module_region)
{
+ vfree(mod->arch.syminfo);
+ mod->arch.syminfo = NULL;
vfree(module_region);
}
@@ -402,6 +404,7 @@ int module_finalize(const Elf_Ehdr *hdr,
struct module *me)
{
vfree(me->arch.syminfo);
+ me->arch.syminfo = NULL;
return module_bug_finalize(hdr, sechdrs, me);
}
diff --git a/arch/s390/kernel/processor.c b/arch/s390/kernel/processor.c
index 802c8ab..0729f36 100644
--- a/arch/s390/kernel/processor.c
+++ b/arch/s390/kernel/processor.c
@@ -31,9 +31,9 @@ void __cpuinit print_cpu_info(void)
static int show_cpuinfo(struct seq_file *m, void *v)
{
- static const char *hwcap_str[9] = {
+ static const char *hwcap_str[10] = {
"esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp",
- "edat", "etf3eh"
+ "edat", "etf3eh", "highgprs"
};
struct _lowcore *lc;
unsigned long n = (unsigned long) v - 1;
@@ -48,7 +48,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
num_online_cpus(), loops_per_jiffy/(500000/HZ),
(loops_per_jiffy/(5000/HZ))%100);
seq_puts(m, "features\t: ");
- for (i = 0; i < 9; i++)
+ for (i = 0; i < 10; i++)
if (hwcap_str[i] && (elf_hwcap & (1UL << i)))
seq_printf(m, "%s ", hwcap_str[i]);
seq_puts(m, "\n");
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index a873867..13815d3 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -57,6 +57,7 @@
enum s390_regset {
REGSET_GENERAL,
REGSET_FP,
+ REGSET_GENERAL_EXTENDED,
};
static void
@@ -879,6 +880,67 @@ static int s390_compat_regs_set(struct task_struct *target,
return rc;
}
+static int s390_compat_regs_high_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+{
+ compat_ulong_t *gprs_high;
+
+ gprs_high = (compat_ulong_t *)
+ &task_pt_regs(target)->gprs[pos / sizeof(compat_ulong_t)];
+ if (kbuf) {
+ compat_ulong_t *k = kbuf;
+ while (count > 0) {
+ *k++ = *gprs_high;
+ gprs_high += 2;
+ count -= sizeof(*k);
+ }
+ } else {
+ compat_ulong_t __user *u = ubuf;
+ while (count > 0) {
+ if (__put_user(*gprs_high, u++))
+ return -EFAULT;
+ gprs_high += 2;
+ count -= sizeof(*u);
+ }
+ }
+ return 0;
+}
+
+static int s390_compat_regs_high_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ compat_ulong_t *gprs_high;
+ int rc = 0;
+
+ gprs_high = (compat_ulong_t *)
+ &task_pt_regs(target)->gprs[pos / sizeof(compat_ulong_t)];
+ if (kbuf) {
+ const compat_ulong_t *k = kbuf;
+ while (count > 0) {
+ *gprs_high = *k++;
+ *gprs_high += 2;
+ count -= sizeof(*k);
+ }
+ } else {
+ const compat_ulong_t __user *u = ubuf;
+ while (count > 0 && !rc) {
+ unsigned long word;
+ rc = __get_user(word, u++);
+ if (rc)
+ break;
+ *gprs_high = word;
+ *gprs_high += 2;
+ count -= sizeof(*u);
+ }
+ }
+
+ return rc;
+}
+
static const struct user_regset s390_compat_regsets[] = {
[REGSET_GENERAL] = {
.core_note_type = NT_PRSTATUS,
@@ -896,6 +958,14 @@ static const struct user_regset s390_compat_regsets[] = {
.get = s390_fpregs_get,
.set = s390_fpregs_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),
+ .align = sizeof(compat_long_t),
+ .get = s390_compat_regs_high_get,
+ .set = s390_compat_regs_high_set,
+ },
};
static const struct user_regset_view user_s390_compat_view = {
diff --git a/arch/s390/kernel/s390_ext.c b/arch/s390/kernel/s390_ext.c
index 0de305b..59618bc 100644
--- a/arch/s390/kernel/s390_ext.c
+++ b/arch/s390/kernel/s390_ext.c
@@ -126,6 +126,8 @@ void __irq_entry do_extint(struct pt_regs *regs, unsigned short code)
/* Serve timer interrupts first. */
clock_comparator_work();
kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++;
+ if (code != 0x1004)
+ __get_cpu_var(s390_idle).nohz_delay = 1;
index = ext_hash(code);
for (p = ext_int_hash[index]; p; p = p->next) {
if (likely(p->code == code))
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 9ed13a1..0663287 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -305,9 +305,8 @@ static int __init early_parse_mem(char *p)
}
early_param("mem", early_parse_mem);
-#ifdef CONFIG_S390_SWITCH_AMODE
-unsigned int switch_amode = 0;
-EXPORT_SYMBOL_GPL(switch_amode);
+unsigned int user_mode = HOME_SPACE_MODE;
+EXPORT_SYMBOL_GPL(user_mode);
static int set_amode_and_uaccess(unsigned long user_amode,
unsigned long user32_amode)
@@ -340,23 +339,29 @@ static int set_amode_and_uaccess(unsigned long user_amode,
*/
static int __init early_parse_switch_amode(char *p)
{
- switch_amode = 1;
+ if (user_mode != SECONDARY_SPACE_MODE)
+ user_mode = PRIMARY_SPACE_MODE;
return 0;
}
early_param("switch_amode", early_parse_switch_amode);
-#else /* CONFIG_S390_SWITCH_AMODE */
-static inline int set_amode_and_uaccess(unsigned long user_amode,
- unsigned long user32_amode)
+static int __init early_parse_user_mode(char *p)
{
+ if (p && strcmp(p, "primary") == 0)
+ user_mode = PRIMARY_SPACE_MODE;
+#ifdef CONFIG_S390_EXEC_PROTECT
+ else if (p && strcmp(p, "secondary") == 0)
+ user_mode = SECONDARY_SPACE_MODE;
+#endif
+ else if (!p || strcmp(p, "home") == 0)
+ user_mode = HOME_SPACE_MODE;
+ else
+ return 1;
return 0;
}
-#endif /* CONFIG_S390_SWITCH_AMODE */
+early_param("user_mode", early_parse_user_mode);
#ifdef CONFIG_S390_EXEC_PROTECT
-unsigned int s390_noexec = 0;
-EXPORT_SYMBOL_GPL(s390_noexec);
-
/*
* Enable execute protection?
*/
@@ -364,8 +369,7 @@ static int __init early_parse_noexec(char *p)
{
if (!strncmp(p, "off", 3))
return 0;
- switch_amode = 1;
- s390_noexec = 1;
+ user_mode = SECONDARY_SPACE_MODE;
return 0;
}
early_param("noexec", early_parse_noexec);
@@ -373,7 +377,7 @@ early_param("noexec", early_parse_noexec);
static void setup_addressing_mode(void)
{
- if (s390_noexec) {
+ if (user_mode == SECONDARY_SPACE_MODE) {
if (set_amode_and_uaccess(PSW_ASC_SECONDARY,
PSW32_ASC_SECONDARY))
pr_info("Execute protection active, "
@@ -381,7 +385,7 @@ static void setup_addressing_mode(void)
else
pr_info("Execute protection active, "
"mvcos not available\n");
- } else if (switch_amode) {
+ } else if (user_mode == PRIMARY_SPACE_MODE) {
if (set_amode_and_uaccess(PSW_ASC_PRIMARY, PSW32_ASC_PRIMARY))
pr_info("Address spaces switched, "
"mvcos available\n");
@@ -411,7 +415,7 @@ setup_lowcore(void)
lc->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
lc->restart_psw.addr =
PSW_ADDR_AMODE | (unsigned long) restart_int_handler;
- if (switch_amode)
+ if (user_mode != HOME_SPACE_MODE)
lc->restart_psw.mask |= PSW_ASC_HOME;
lc->external_new_psw.mask = psw_kernel_bits;
lc->external_new_psw.addr =
@@ -729,7 +733,7 @@ static void __init setup_hwcaps(void)
if ((facility_list & (1UL << (31 - 22)))
&& (facility_list & (1UL << (31 - 30))))
- elf_hwcap |= 1UL << 8;
+ elf_hwcap |= HWCAP_S390_ETF3EH;
/*
* Check for additional facilities with store-facility-list-extended.
@@ -748,11 +752,20 @@ static void __init setup_hwcaps(void)
__stfle(&facility_list_extended, 1) > 0) {
if ((facility_list_extended & (1ULL << (63 - 42)))
&& (facility_list_extended & (1ULL << (63 - 44))))
- elf_hwcap |= 1UL << 6;
+ elf_hwcap |= HWCAP_S390_DFP;
}
+ /*
+ * Huge page support HWCAP_S390_HPAGE is bit 7.
+ */
if (MACHINE_HAS_HPAGE)
- elf_hwcap |= 1UL << 7;
+ elf_hwcap |= HWCAP_S390_HPAGE;
+
+ /*
+ * 64-bit register support for 31-bit processes
+ * HWCAP_S390_HIGH_GPRS is bit 9.
+ */
+ elf_hwcap |= HWCAP_S390_HIGH_GPRS;
switch (S390_lowcore.cpu_id.machine) {
case 0x9672:
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index c932caa..93e5203 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -76,7 +76,6 @@ static int cpu_stopped(int cpu)
__u32 status;
switch (signal_processor_ps(&status, 0, cpu, sigp_sense)) {
- case sigp_order_code_accepted:
case sigp_status_stored:
/* Check for stopped and check stop state */
if (status & 0x50)
@@ -638,6 +637,8 @@ void __cpu_die(unsigned int cpu)
/* Wait until target cpu is down */
while (!cpu_stopped(cpu))
cpu_relax();
+ while (signal_processor_p(0, cpu, sigp_set_prefix) == sigp_busy)
+ udelay(10);
smp_free_lowcore(cpu);
pr_info("Processor %d stopped\n", cpu);
}
@@ -645,8 +646,8 @@ void __cpu_die(unsigned int cpu)
void cpu_die(void)
{
idle_task_exit();
- signal_processor(smp_processor_id(), sigp_stop);
- BUG();
+ while (signal_processor(smp_processor_id(), sigp_stop) == sigp_busy)
+ cpu_relax();
for (;;);
}
diff --git a/arch/s390/kernel/swsusp_asm64.S b/arch/s390/kernel/swsusp_asm64.S
index fe927d0..0c26cc1 100644
--- a/arch/s390/kernel/swsusp_asm64.S
+++ b/arch/s390/kernel/swsusp_asm64.S
@@ -43,7 +43,7 @@ swsusp_arch_suspend:
lghi %r1,0x1000
/* Save CPU address */
- stap __LC_CPU_ADDRESS(%r1)
+ stap __LC_CPU_ADDRESS(%r0)
/* Store registers */
mvc 0x318(4,%r1),__SF_EMPTY(%r15) /* move prefix to lowcore */
@@ -69,8 +69,21 @@ swsusp_arch_suspend:
stmg %r0,%r15,0x280(%r1) /* store general registers */
stpt 0x328(%r1) /* store timer */
+ stck __SF_EMPTY(%r15) /* store clock */
stckc 0x330(%r1) /* store clock comparator */
+ /* Update cputime accounting before going to sleep */
+ lg %r0,__LC_LAST_UPDATE_TIMER
+ slg %r0,0x328(%r1)
+ alg %r0,__LC_SYSTEM_TIMER
+ stg %r0,__LC_SYSTEM_TIMER
+ mvc __LC_LAST_UPDATE_TIMER(8),0x328(%r1)
+ lg %r0,__LC_LAST_UPDATE_CLOCK
+ slg %r0,__SF_EMPTY(%r15)
+ alg %r0,__LC_STEAL_TIMER
+ stg %r0,__LC_STEAL_TIMER
+ mvc __LC_LAST_UPDATE_CLOCK(8),__SF_EMPTY(%r15)
+
/* Activate DAT */
stosm __SF_EMPTY(%r15),0x04
@@ -159,8 +172,7 @@ pgm_check_entry:
larl %r1,.Lresume_cpu /* Resume CPU address: r2 */
stap 0(%r1)
llgh %r2,0(%r1)
- lghi %r3,0x1000
- llgh %r1,__LC_CPU_ADDRESS(%r3) /* Suspend CPU address: r1 */
+ llgh %r1,__LC_CPU_ADDRESS(%r0) /* Suspend CPU address: r1 */
cgr %r1,%r2
je restore_registers /* r1 = r2 -> nothing to do */
larl %r4,.Lrestart_suspend_psw /* Set new restart PSW */
@@ -187,6 +199,7 @@ pgm_check_entry:
brc 2,4b /* busy, try again */
5:
sigp %r9,%r2,__SIGP_STOP /* stop resume (current) CPU */
+ brc 2,5b /* busy, try again */
6: j 6b
restart_suspend:
@@ -194,14 +207,18 @@ restart_suspend:
llgh %r2,0(%r1)
7:
sigp %r9,%r2,__SIGP_SENSE /* Wait for resume CPU */
+ brc 8,7b /* accepted, status 0, still running */
brc 2,7b /* busy, try again */
tmll %r9,0x40 /* Test if resume CPU is stopped */
jz 7b
restore_registers:
/* Restore registers */
- lghi %r13,0x1000 /* %r1 = pointer to save arae */
+ lghi %r13,0x1000 /* %r1 = pointer to save area */
+ /* Ignore time spent in suspended state. */
+ llgf %r1,0x318(%r13)
+ stck __LC_LAST_UPDATE_CLOCK(%r1)
spt 0x328(%r13) /* reprogram timer */
//sckc 0x330(%r13) /* set clock comparator */
@@ -229,9 +246,6 @@ restore_registers:
/* Load old stack */
lg %r15,0x2f8(%r13)
- /* Pointer to save area */
- lghi %r13,0x1000
-
/* Restore prefix register */
spx 0x318(%r13)
diff --git a/arch/s390/kernel/sys_s390.c b/arch/s390/kernel/sys_s390.c
index e9d94f6..86a74c9 100644
--- a/arch/s390/kernel/sys_s390.c
+++ b/arch/s390/kernel/sys_s390.c
@@ -32,32 +32,6 @@
#include <asm/uaccess.h>
#include "entry.h"
-/* common code for old and new mmaps */
-static inline long do_mmap2(
- unsigned long addr, unsigned long len,
- unsigned long prot, unsigned long flags,
- unsigned long fd, unsigned long pgoff)
-{
- long error = -EBADF;
- struct file * file = NULL;
-
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
- if (!(flags & MAP_ANONYMOUS)) {
- file = fget(fd);
- if (!file)
- goto out;
- }
-
- down_write(&current->mm->mmap_sem);
- error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
- up_write(&current->mm->mmap_sem);
-
- if (file)
- fput(file);
-out:
- return error;
-}
-
/*
* Perform the select(nd, in, out, ex, tv) and mmap() system
* calls. Linux for S/390 isn't able to handle more than 5
@@ -81,7 +55,7 @@ SYSCALL_DEFINE1(mmap2, struct mmap_arg_struct __user *, arg)
if (copy_from_user(&a, arg, sizeof(a)))
goto out;
- error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
+ error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
out:
return error;
}
@@ -98,7 +72,7 @@ SYSCALL_DEFINE1(s390_old_mmap, struct mmap_arg_struct __user *, arg)
if (a.offset & ~PAGE_MASK)
goto out;
- error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
+ error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
out:
return error;
}
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index 30eca07..4f292c9 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -340,3 +340,4 @@ SYSCALL(sys_preadv,sys_preadv,compat_sys_preadv_wrapper)
SYSCALL(sys_pwritev,sys_pwritev,compat_sys_pwritev_wrapper)
SYSCALL(sys_rt_tgsigqueueinfo,sys_rt_tgsigqueueinfo,compat_sys_rt_tgsigqueueinfo_wrapper) /* 330 */
SYSCALL(sys_perf_event_open,sys_perf_event_open,sys_perf_event_open_wrapper)
+SYSCALL(sys_recvmmsg,sys_recvmmsg,compat_sys_recvmmsg_wrapper)
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 34162a0..65065ac 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -214,7 +214,8 @@ struct clocksource * __init clocksource_default_clock(void)
return &clocksource_tod;
}
-void update_vsyscall(struct timespec *wall_time, struct clocksource *clock)
+void update_vsyscall(struct timespec *wall_time, struct clocksource *clock,
+ u32 mult)
{
if (clock != &clocksource_tod)
return;
@@ -334,7 +335,7 @@ int get_sync_clock(unsigned long long *clock)
sw0 = atomic_read(sw_ptr);
*clock = get_clock();
sw1 = atomic_read(sw_ptr);
- put_cpu_var(clock_sync_sync);
+ put_cpu_var(clock_sync_word);
if (sw0 == sw1 && (sw0 & 0x80000000U))
/* Success: time is in sync. */
return 0;
@@ -384,7 +385,7 @@ static inline int check_sync_clock(void)
sw_ptr = &get_cpu_var(clock_sync_word);
rc = (atomic_read(sw_ptr) & 0x80000000U) != 0;
- put_cpu_var(clock_sync_sync);
+ put_cpu_var(clock_sync_word);
return rc;
}
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index c2e42cc..6e7ad63 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -18,7 +18,7 @@
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/errno.h>
-#include <linux/ptrace.h>
+#include <linux/tracehook.h>
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/smp.h>
@@ -382,7 +382,7 @@ void __kprobes do_single_step(struct pt_regs *regs)
SIGTRAP) == NOTIFY_STOP){
return;
}
- if ((current->ptrace & PT_PTRACED) != 0)
+ if (tracehook_consider_fatal_signal(current, SIGTRAP))
force_sig(SIGTRAP, current);
}
@@ -483,7 +483,7 @@ static void illegal_op(struct pt_regs * regs, long interruption_code)
if (get_user(*((__u16 *) opcode), (__u16 __user *) location))
return;
if (*((__u16 *) opcode) == S390_BREAKPOINT_U16) {
- if (current->ptrace & PT_PTRACED)
+ if (tracehook_consider_fatal_signal(current, SIGTRAP))
force_sig(SIGTRAP, current);
else
signal = SIGILL;
diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c
index 45a3e9a..5f99e66 100644
--- a/arch/s390/kernel/vdso.c
+++ b/arch/s390/kernel/vdso.c
@@ -86,7 +86,8 @@ static void vdso_init_data(struct vdso_data *vd)
unsigned int facility_list;
facility_list = stfl();
- vd->ectg_available = switch_amode && (facility_list & 1);
+ vd->ectg_available =
+ user_mode != HOME_SPACE_MODE && (facility_list & 1);
}
#ifdef CONFIG_64BIT
@@ -114,7 +115,7 @@ int vdso_alloc_per_cpu(int cpu, struct _lowcore *lowcore)
lowcore->vdso_per_cpu_data = __LC_PASTE;
- if (!switch_amode || !vdso_enabled)
+ if (user_mode == HOME_SPACE_MODE || !vdso_enabled)
return 0;
segment_table = __get_free_pages(GFP_KERNEL, SEGMENT_ORDER);
@@ -160,7 +161,7 @@ void vdso_free_per_cpu(int cpu, struct _lowcore *lowcore)
unsigned long segment_table, page_table, page_frame;
u32 *psal, *aste;
- if (!switch_amode || !vdso_enabled)
+ if (user_mode == HOME_SPACE_MODE || !vdso_enabled)
return;
psal = (u32 *)(addr_t) lowcore->paste[4];
@@ -184,7 +185,7 @@ static void __vdso_init_cr5(void *dummy)
static void vdso_init_cr5(void)
{
- if (switch_amode && vdso_enabled)
+ if (user_mode != HOME_SPACE_MODE && vdso_enabled)
on_each_cpu(__vdso_init_cr5, NULL, 1);
}
#endif /* CONFIG_64BIT */
@@ -247,6 +248,13 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
}
/*
+ * Put vDSO base into mm struct. We need to do this before calling
+ * install_special_mapping or the perf counter mmap tracking code
+ * will fail to recognise it as a vDSO (since arch_vma_name fails).
+ */
+ current->mm->context.vdso_base = vdso_base;
+
+ /*
* our vma flags don't have VM_WRITE so by default, the process
* isn't allowed to write those pages.
* gdb can break that with ptrace interface, and thus trigger COW
@@ -267,14 +275,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
VM_ALWAYSDUMP,
vdso_pagelist);
if (rc)
- goto out_up;
-
- /* Put vDSO base into mm struct */
- current->mm->context.vdso_base = vdso_base;
-
- up_write(&mm->mmap_sem);
- return 0;
-
+ current->mm->context.vdso_base = 0;
out_up:
up_write(&mm->mmap_sem);
return rc;
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index bc15ef9..a68ac10 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -51,6 +51,7 @@ SECTIONS
. = ALIGN(PAGE_SIZE);
_eshared = .; /* End of shareable data */
+ _sdata = .; /* Start of data section */
EXCEPTION_TABLE(16) :data
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
index c41bb0d..b59a812 100644
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -167,6 +167,8 @@ void vtime_stop_cpu(void)
/* Wait for external, I/O or machine check interrupt. */
psw.mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_IO | PSW_MASK_EXT;
+ idle->nohz_delay = 0;
+
/* Check if the CPU timer needs to be reprogrammed. */
if (vq->do_spt) {
__u64 vmax = VTIMER_MAX_SLICE;
diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig
index bf164fc..6ee55ae 100644
--- a/arch/s390/kvm/Kconfig
+++ b/arch/s390/kvm/Kconfig
@@ -20,7 +20,6 @@ config KVM
depends on HAVE_KVM && EXPERIMENTAL
select PREEMPT_NOTIFIERS
select ANON_INODES
- select S390_SWITCH_AMODE
---help---
Support hosting paravirtualized guest machines using the SIE
virtualization capability on the mainframe. This should work
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 07ced89..f8bcaef 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -74,9 +74,10 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
static unsigned long long *facilities;
/* Section: not file related */
-void kvm_arch_hardware_enable(void *garbage)
+int kvm_arch_hardware_enable(void *garbage)
{
/* every s390 is virtualization enabled ;-) */
+ return 0;
}
void kvm_arch_hardware_disable(void *garbage)
@@ -116,10 +117,16 @@ long kvm_arch_dev_ioctl(struct file *filp,
int kvm_dev_ioctl_check_extension(long ext)
{
+ int r;
+
switch (ext) {
+ case KVM_CAP_S390_PSW:
+ r = 1;
+ break;
default:
- return 0;
+ r = 0;
}
+ return r;
}
/* Section: vm related */
@@ -150,7 +157,7 @@ long kvm_arch_vm_ioctl(struct file *filp,
break;
}
default:
- r = -EINVAL;
+ r = -ENOTTY;
}
return r;
@@ -419,8 +426,10 @@ static int kvm_arch_vcpu_ioctl_set_initial_psw(struct kvm_vcpu *vcpu, psw_t psw)
vcpu_load(vcpu);
if (atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_RUNNING)
rc = -EBUSY;
- else
- vcpu->arch.sie_block->gpsw = psw;
+ else {
+ vcpu->run->psw_mask = psw.mask;
+ vcpu->run->psw_addr = psw.addr;
+ }
vcpu_put(vcpu);
return rc;
}
@@ -508,9 +517,6 @@ rerun_vcpu:
switch (kvm_run->exit_reason) {
case KVM_EXIT_S390_SIEIC:
- vcpu->arch.sie_block->gpsw.mask = kvm_run->s390_sieic.mask;
- vcpu->arch.sie_block->gpsw.addr = kvm_run->s390_sieic.addr;
- break;
case KVM_EXIT_UNKNOWN:
case KVM_EXIT_INTR:
case KVM_EXIT_S390_RESET:
@@ -519,6 +525,9 @@ rerun_vcpu:
BUG();
}
+ vcpu->arch.sie_block->gpsw.mask = kvm_run->psw_mask;
+ vcpu->arch.sie_block->gpsw.addr = kvm_run->psw_addr;
+
might_fault();
do {
@@ -538,8 +547,6 @@ rerun_vcpu:
/* intercept cannot be handled in-kernel, prepare kvm-run */
kvm_run->exit_reason = KVM_EXIT_S390_SIEIC;
kvm_run->s390_sieic.icptcode = vcpu->arch.sie_block->icptcode;
- kvm_run->s390_sieic.mask = vcpu->arch.sie_block->gpsw.mask;
- kvm_run->s390_sieic.addr = vcpu->arch.sie_block->gpsw.addr;
kvm_run->s390_sieic.ipa = vcpu->arch.sie_block->ipa;
kvm_run->s390_sieic.ipb = vcpu->arch.sie_block->ipb;
rc = 0;
@@ -551,6 +558,9 @@ rerun_vcpu:
rc = 0;
}
+ kvm_run->psw_mask = vcpu->arch.sie_block->gpsw.mask;
+ kvm_run->psw_addr = vcpu->arch.sie_block->gpsw.addr;
+
if (vcpu->sigset_active)
sigprocmask(SIG_SETMASK, &sigsaved, NULL);
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
index ec5eee7..06cce82 100644
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -58,7 +58,7 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code);
int kvm_s390_inject_sigp_stop(struct kvm_vcpu *vcpu, int action);
-static inline int kvm_s390_vcpu_get_memsize(struct kvm_vcpu *vcpu)
+static inline long kvm_s390_vcpu_get_memsize(struct kvm_vcpu *vcpu)
{
return vcpu->arch.sie_block->gmslm
- vcpu->arch.sie_block->gmsor
diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c
index 40c8c67..15ee111 100644
--- a/arch/s390/kvm/sigp.c
+++ b/arch/s390/kvm/sigp.c
@@ -188,9 +188,9 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address,
/* make sure that the new value is valid memory */
address = address & 0x7fffe000u;
- if ((copy_from_guest(vcpu, &tmp,
- (u64) (address + vcpu->arch.sie_block->gmsor) , 1)) ||
- (copy_from_guest(vcpu, &tmp, (u64) (address +
+ if ((copy_from_user(&tmp, (void __user *)
+ (address + vcpu->arch.sie_block->gmsor) , 1)) ||
+ (copy_from_user(&tmp, (void __user *)(address +
vcpu->arch.sie_block->gmsor + PAGE_SIZE), 1))) {
*reg |= SIGP_STAT_INVALID_PARAMETER;
return 1; /* invalid parameter */
diff --git a/arch/s390/lib/delay.c b/arch/s390/lib/delay.c
index 97c1eca8..752b362 100644
--- a/arch/s390/lib/delay.c
+++ b/arch/s390/lib/delay.c
@@ -25,13 +25,13 @@ void __delay(unsigned long loops)
asm volatile("0: brct %0,0b" : : "d" ((loops/2) + 1));
}
-static void __udelay_disabled(unsigned long usecs)
+static void __udelay_disabled(unsigned long long usecs)
{
unsigned long mask, cr0, cr0_saved;
u64 clock_saved;
clock_saved = local_tick_disable();
- set_clock_comparator(get_clock() + ((u64) usecs << 12));
+ set_clock_comparator(get_clock() + (usecs << 12));
__ctl_store(cr0_saved, 0, 0);
cr0 = (cr0_saved & 0xffff00e0) | 0x00000800;
__ctl_load(cr0 , 0, 0);
@@ -46,20 +46,25 @@ static void __udelay_disabled(unsigned long usecs)
set_clock_comparator(S390_lowcore.clock_comparator);
}
-static void __udelay_enabled(unsigned long usecs)
+static void __udelay_enabled(unsigned long long usecs)
{
unsigned long mask;
- u64 end, time;
+ u64 clock_saved;
+ u64 end;
mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT | PSW_MASK_IO;
- end = get_clock() + ((u64) usecs << 12);
+ end = get_clock() + (usecs << 12);
do {
- time = end < S390_lowcore.clock_comparator ?
- end : S390_lowcore.clock_comparator;
- set_clock_comparator(time);
+ clock_saved = 0;
+ if (end < S390_lowcore.clock_comparator) {
+ clock_saved = local_tick_disable();
+ set_clock_comparator(end);
+ }
trace_hardirqs_on();
__load_psw_mask(mask);
local_irq_disable();
+ if (clock_saved)
+ local_tick_enable(clock_saved);
} while (get_clock() < end);
set_clock_comparator(S390_lowcore.clock_comparator);
}
@@ -67,7 +72,7 @@ static void __udelay_enabled(unsigned long usecs)
/*
* Waits for 'usecs' microseconds using the TOD clock comparator.
*/
-void __udelay(unsigned long usecs)
+void __udelay(unsigned long long usecs)
{
unsigned long flags;
@@ -101,11 +106,11 @@ EXPORT_SYMBOL(__udelay);
* Simple udelay variant. To be used on startup and reboot
* when the interrupt handler isn't working.
*/
-void udelay_simple(unsigned long usecs)
+void udelay_simple(unsigned long long usecs)
{
u64 end;
- end = get_clock() + ((u64) usecs << 12);
+ end = get_clock() + (usecs << 12);
while (get_clock() < end)
cpu_relax();
}
diff --git a/arch/s390/lib/spinlock.c b/arch/s390/lib/spinlock.c
index f7e0d30..10754a3 100644
--- a/arch/s390/lib/spinlock.c
+++ b/arch/s390/lib/spinlock.c
@@ -39,7 +39,7 @@ static inline void _raw_yield_cpu(int cpu)
_raw_yield();
}
-void _raw_spin_lock_wait(raw_spinlock_t *lp)
+void arch_spin_lock_wait(arch_spinlock_t *lp)
{
int count = spin_retry;
unsigned int cpu = ~smp_processor_id();
@@ -51,15 +51,15 @@ void _raw_spin_lock_wait(raw_spinlock_t *lp)
_raw_yield_cpu(~owner);
count = spin_retry;
}
- if (__raw_spin_is_locked(lp))
+ if (arch_spin_is_locked(lp))
continue;
if (_raw_compare_and_swap(&lp->owner_cpu, 0, cpu) == 0)
return;
}
}
-EXPORT_SYMBOL(_raw_spin_lock_wait);
+EXPORT_SYMBOL(arch_spin_lock_wait);
-void _raw_spin_lock_wait_flags(raw_spinlock_t *lp, unsigned long flags)
+void arch_spin_lock_wait_flags(arch_spinlock_t *lp, unsigned long flags)
{
int count = spin_retry;
unsigned int cpu = ~smp_processor_id();
@@ -72,7 +72,7 @@ void _raw_spin_lock_wait_flags(raw_spinlock_t *lp, unsigned long flags)
_raw_yield_cpu(~owner);
count = spin_retry;
}
- if (__raw_spin_is_locked(lp))
+ if (arch_spin_is_locked(lp))
continue;
local_irq_disable();
if (_raw_compare_and_swap(&lp->owner_cpu, 0, cpu) == 0)
@@ -80,32 +80,32 @@ void _raw_spin_lock_wait_flags(raw_spinlock_t *lp, unsigned long flags)
local_irq_restore(flags);
}
}
-EXPORT_SYMBOL(_raw_spin_lock_wait_flags);
+EXPORT_SYMBOL(arch_spin_lock_wait_flags);
-int _raw_spin_trylock_retry(raw_spinlock_t *lp)
+int arch_spin_trylock_retry(arch_spinlock_t *lp)
{
unsigned int cpu = ~smp_processor_id();
int count;
for (count = spin_retry; count > 0; count--) {
- if (__raw_spin_is_locked(lp))
+ if (arch_spin_is_locked(lp))
continue;
if (_raw_compare_and_swap(&lp->owner_cpu, 0, cpu) == 0)
return 1;
}
return 0;
}
-EXPORT_SYMBOL(_raw_spin_trylock_retry);
+EXPORT_SYMBOL(arch_spin_trylock_retry);
-void _raw_spin_relax(raw_spinlock_t *lock)
+void arch_spin_relax(arch_spinlock_t *lock)
{
unsigned int cpu = lock->owner_cpu;
if (cpu != 0)
_raw_yield_cpu(~cpu);
}
-EXPORT_SYMBOL(_raw_spin_relax);
+EXPORT_SYMBOL(arch_spin_relax);
-void _raw_read_lock_wait(raw_rwlock_t *rw)
+void _raw_read_lock_wait(arch_rwlock_t *rw)
{
unsigned int old;
int count = spin_retry;
@@ -115,7 +115,7 @@ void _raw_read_lock_wait(raw_rwlock_t *rw)
_raw_yield();
count = spin_retry;
}
- if (!__raw_read_can_lock(rw))
+ if (!arch_read_can_lock(rw))
continue;
old = rw->lock & 0x7fffffffU;
if (_raw_compare_and_swap(&rw->lock, old, old + 1) == old)
@@ -124,7 +124,7 @@ void _raw_read_lock_wait(raw_rwlock_t *rw)
}
EXPORT_SYMBOL(_raw_read_lock_wait);
-void _raw_read_lock_wait_flags(raw_rwlock_t *rw, unsigned long flags)
+void _raw_read_lock_wait_flags(arch_rwlock_t *rw, unsigned long flags)
{
unsigned int old;
int count = spin_retry;
@@ -135,7 +135,7 @@ void _raw_read_lock_wait_flags(raw_rwlock_t *rw, unsigned long flags)
_raw_yield();
count = spin_retry;
}
- if (!__raw_read_can_lock(rw))
+ if (!arch_read_can_lock(rw))
continue;
old = rw->lock & 0x7fffffffU;
local_irq_disable();
@@ -145,13 +145,13 @@ void _raw_read_lock_wait_flags(raw_rwlock_t *rw, unsigned long flags)
}
EXPORT_SYMBOL(_raw_read_lock_wait_flags);
-int _raw_read_trylock_retry(raw_rwlock_t *rw)
+int _raw_read_trylock_retry(arch_rwlock_t *rw)
{
unsigned int old;
int count = spin_retry;
while (count-- > 0) {
- if (!__raw_read_can_lock(rw))
+ if (!arch_read_can_lock(rw))
continue;
old = rw->lock & 0x7fffffffU;
if (_raw_compare_and_swap(&rw->lock, old, old + 1) == old)
@@ -161,7 +161,7 @@ int _raw_read_trylock_retry(raw_rwlock_t *rw)
}
EXPORT_SYMBOL(_raw_read_trylock_retry);
-void _raw_write_lock_wait(raw_rwlock_t *rw)
+void _raw_write_lock_wait(arch_rwlock_t *rw)
{
int count = spin_retry;
@@ -170,7 +170,7 @@ void _raw_write_lock_wait(raw_rwlock_t *rw)
_raw_yield();
count = spin_retry;
}
- if (!__raw_write_can_lock(rw))
+ if (!arch_write_can_lock(rw))
continue;
if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0)
return;
@@ -178,7 +178,7 @@ void _raw_write_lock_wait(raw_rwlock_t *rw)
}
EXPORT_SYMBOL(_raw_write_lock_wait);
-void _raw_write_lock_wait_flags(raw_rwlock_t *rw, unsigned long flags)
+void _raw_write_lock_wait_flags(arch_rwlock_t *rw, unsigned long flags)
{
int count = spin_retry;
@@ -188,7 +188,7 @@ void _raw_write_lock_wait_flags(raw_rwlock_t *rw, unsigned long flags)
_raw_yield();
count = spin_retry;
}
- if (!__raw_write_can_lock(rw))
+ if (!arch_write_can_lock(rw))
continue;
local_irq_disable();
if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0)
@@ -197,12 +197,12 @@ void _raw_write_lock_wait_flags(raw_rwlock_t *rw, unsigned long flags)
}
EXPORT_SYMBOL(_raw_write_lock_wait_flags);
-int _raw_write_trylock_retry(raw_rwlock_t *rw)
+int _raw_write_trylock_retry(arch_rwlock_t *rw)
{
int count = spin_retry;
while (count-- > 0) {
- if (!__raw_write_can_lock(rw))
+ if (!arch_write_can_lock(rw))
continue;
if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0)
return 1;
diff --git a/arch/s390/lib/uaccess_mvcos.c b/arch/s390/lib/uaccess_mvcos.c
index 3f15aaf..60455f1 100644
--- a/arch/s390/lib/uaccess_mvcos.c
+++ b/arch/s390/lib/uaccess_mvcos.c
@@ -36,7 +36,7 @@ static size_t copy_from_user_mvcos(size_t size, const void __user *ptr, void *x)
tmp1 = -4096UL;
asm volatile(
"0: .insn ss,0xc80000000000,0(%0,%2),0(%1),0\n"
- " jz 7f\n"
+ "9: jz 7f\n"
"1:"ALR" %0,%3\n"
" "SLR" %1,%3\n"
" "SLR" %2,%3\n"
@@ -47,7 +47,7 @@ static size_t copy_from_user_mvcos(size_t size, const void __user *ptr, void *x)
" "CLR" %0,%4\n" /* copy crosses next page boundary? */
" jnh 4f\n"
"3: .insn ss,0xc80000000000,0(%4,%2),0(%1),0\n"
- " "SLR" %0,%4\n"
+ "10:"SLR" %0,%4\n"
" "ALR" %2,%4\n"
"4:"LHI" %4,-1\n"
" "ALR" %4,%0\n" /* copy remaining size, subtract 1 */
@@ -61,7 +61,7 @@ static size_t copy_from_user_mvcos(size_t size, const void __user *ptr, void *x)
" j 8f\n"
"7:"SLR" %0,%0\n"
"8: \n"
- EX_TABLE(0b,2b) EX_TABLE(3b,4b)
+ EX_TABLE(0b,2b) EX_TABLE(3b,4b) EX_TABLE(9b,2b) EX_TABLE(10b,4b)
: "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
: "d" (reg0) : "cc", "memory");
return size;
@@ -82,7 +82,7 @@ static size_t copy_to_user_mvcos(size_t size, void __user *ptr, const void *x)
tmp1 = -4096UL;
asm volatile(
"0: .insn ss,0xc80000000000,0(%0,%1),0(%2),0\n"
- " jz 4f\n"
+ "6: jz 4f\n"
"1:"ALR" %0,%3\n"
" "SLR" %1,%3\n"
" "SLR" %2,%3\n"
@@ -93,11 +93,11 @@ static size_t copy_to_user_mvcos(size_t size, void __user *ptr, const void *x)
" "CLR" %0,%4\n" /* copy crosses next page boundary? */
" jnh 5f\n"
"3: .insn ss,0xc80000000000,0(%4,%1),0(%2),0\n"
- " "SLR" %0,%4\n"
+ "7:"SLR" %0,%4\n"
" j 5f\n"
"4:"SLR" %0,%0\n"
"5: \n"
- EX_TABLE(0b,2b) EX_TABLE(3b,5b)
+ EX_TABLE(0b,2b) EX_TABLE(3b,5b) EX_TABLE(6b,2b) EX_TABLE(7b,5b)
: "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
: "d" (reg0) : "cc", "memory");
return size;
@@ -162,7 +162,6 @@ static size_t clear_user_mvcos(size_t size, void __user *to)
return size;
}
-#ifdef CONFIG_S390_SWITCH_AMODE
static size_t strnlen_user_mvcos(size_t count, const char __user *src)
{
char buf[256];
@@ -200,7 +199,6 @@ static size_t strncpy_from_user_mvcos(size_t count, const char __user *src,
} while ((len_str == len) && (done < count));
return done;
}
-#endif /* CONFIG_S390_SWITCH_AMODE */
struct uaccess_ops uaccess_mvcos = {
.copy_from_user = copy_from_user_mvcos_check,
@@ -215,7 +213,6 @@ struct uaccess_ops uaccess_mvcos = {
.futex_atomic_cmpxchg = futex_atomic_cmpxchg_std,
};
-#ifdef CONFIG_S390_SWITCH_AMODE
struct uaccess_ops uaccess_mvcos_switch = {
.copy_from_user = copy_from_user_mvcos,
.copy_from_user_small = copy_from_user_mvcos,
@@ -228,4 +225,3 @@ struct uaccess_ops uaccess_mvcos_switch = {
.futex_atomic_op = futex_atomic_op_pt,
.futex_atomic_cmpxchg = futex_atomic_cmpxchg_pt,
};
-#endif
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c
index cb5d59e..404f2de 100644
--- a/arch/s390/lib/uaccess_pt.c
+++ b/arch/s390/lib/uaccess_pt.c
@@ -23,86 +23,21 @@ static inline pte_t *follow_table(struct mm_struct *mm, unsigned long addr)
pgd = pgd_offset(mm, addr);
if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
- return NULL;
+ return (pte_t *) 0x3a;
pud = pud_offset(pgd, addr);
if (pud_none(*pud) || unlikely(pud_bad(*pud)))
- return NULL;
+ return (pte_t *) 0x3b;
pmd = pmd_offset(pud, addr);
if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
- return NULL;
+ return (pte_t *) 0x10;
return pte_offset_map(pmd, addr);
}
-static int __handle_fault(struct mm_struct *mm, unsigned long address,
- int write_access)
-{
- struct vm_area_struct *vma;
- int ret = -EFAULT;
- int fault;
-
- if (in_atomic())
- return ret;
- down_read(&mm->mmap_sem);
- vma = find_vma(mm, address);
- if (unlikely(!vma))
- goto out;
- if (unlikely(vma->vm_start > address)) {
- if (!(vma->vm_flags & VM_GROWSDOWN))
- goto out;
- if (expand_stack(vma, address))
- goto out;
- }
-
- if (!write_access) {
- /* page not present, check vm flags */
- if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
- goto out;
- } else {
- if (!(vma->vm_flags & VM_WRITE))
- goto out;
- }
-
-survive:
- fault = handle_mm_fault(mm, vma, address, write_access ? FAULT_FLAG_WRITE : 0);
- if (unlikely(fault & VM_FAULT_ERROR)) {
- if (fault & VM_FAULT_OOM)
- goto out_of_memory;
- else if (fault & VM_FAULT_SIGBUS)
- goto out_sigbus;
- BUG();
- }
- if (fault & VM_FAULT_MAJOR)
- current->maj_flt++;
- else
- current->min_flt++;
- ret = 0;
-out:
- up_read(&mm->mmap_sem);
- return ret;
-
-out_of_memory:
- up_read(&mm->mmap_sem);
- if (is_global_init(current)) {
- yield();
- down_read(&mm->mmap_sem);
- goto survive;
- }
- printk("VM: killing process %s\n", current->comm);
- return ret;
-
-out_sigbus:
- up_read(&mm->mmap_sem);
- current->thread.prot_addr = address;
- current->thread.trap_no = 0x11;
- force_sig(SIGBUS, current);
- return ret;
-}
-
-static size_t __user_copy_pt(unsigned long uaddr, void *kptr,
- size_t n, int write_user)
+static __always_inline size_t __user_copy_pt(unsigned long uaddr, void *kptr,
+ size_t n, int write_user)
{
struct mm_struct *mm = current->mm;
unsigned long offset, pfn, done, size;
@@ -114,12 +49,17 @@ retry:
spin_lock(&mm->page_table_lock);
do {
pte = follow_table(mm, uaddr);
- if (!pte || !pte_present(*pte) ||
- (write_user && !pte_write(*pte)))
+ if ((unsigned long) pte < 0x1000)
goto fault;
+ if (!pte_present(*pte)) {
+ pte = (pte_t *) 0x11;
+ goto fault;
+ } else if (write_user && !pte_write(*pte)) {
+ pte = (pte_t *) 0x04;
+ goto fault;
+ }
pfn = pte_pfn(*pte);
-
offset = uaddr & (PAGE_SIZE - 1);
size = min(n - done, PAGE_SIZE - offset);
if (write_user) {
@@ -137,7 +77,7 @@ retry:
return n - done;
fault:
spin_unlock(&mm->page_table_lock);
- if (__handle_fault(mm, uaddr, write_user))
+ if (__handle_fault(uaddr, (unsigned long) pte, write_user))
return n - done;
goto retry;
}
@@ -146,30 +86,31 @@ fault:
* Do DAT for user address by page table walk, return kernel address.
* This function needs to be called with current->mm->page_table_lock held.
*/
-static unsigned long __dat_user_addr(unsigned long uaddr)
+static __always_inline unsigned long __dat_user_addr(unsigned long uaddr)
{
struct mm_struct *mm = current->mm;
- unsigned long pfn, ret;
+ unsigned long pfn;
pte_t *pte;
int rc;
- ret = 0;
retry:
pte = follow_table(mm, uaddr);
- if (!pte || !pte_present(*pte))
+ if ((unsigned long) pte < 0x1000)
goto fault;
+ if (!pte_present(*pte)) {
+ pte = (pte_t *) 0x11;
+ goto fault;
+ }
pfn = pte_pfn(*pte);
- ret = (pfn << PAGE_SHIFT) + (uaddr & (PAGE_SIZE - 1));
-out:
- return ret;
+ return (pfn << PAGE_SHIFT) + (uaddr & (PAGE_SIZE - 1));
fault:
spin_unlock(&mm->page_table_lock);
- rc = __handle_fault(mm, uaddr, 0);
+ rc = __handle_fault(uaddr, (unsigned long) pte, 0);
spin_lock(&mm->page_table_lock);
- if (rc)
- goto out;
- goto retry;
+ if (!rc)
+ goto retry;
+ return 0;
}
size_t copy_from_user_pt(size_t n, const void __user *from, void *to)
@@ -234,8 +175,12 @@ retry:
spin_lock(&mm->page_table_lock);
do {
pte = follow_table(mm, uaddr);
- if (!pte || !pte_present(*pte))
+ if ((unsigned long) pte < 0x1000)
+ goto fault;
+ if (!pte_present(*pte)) {
+ pte = (pte_t *) 0x11;
goto fault;
+ }
pfn = pte_pfn(*pte);
offset = uaddr & (PAGE_SIZE-1);
@@ -249,9 +194,8 @@ retry:
return done + 1;
fault:
spin_unlock(&mm->page_table_lock);
- if (__handle_fault(mm, uaddr, 0)) {
+ if (__handle_fault(uaddr, (unsigned long) pte, 0))
return 0;
- }
goto retry;
}
@@ -284,7 +228,7 @@ static size_t copy_in_user_pt(size_t n, void __user *to,
{
struct mm_struct *mm = current->mm;
unsigned long offset_from, offset_to, offset_max, pfn_from, pfn_to,
- uaddr, done, size;
+ uaddr, done, size, error_code;
unsigned long uaddr_from = (unsigned long) from;
unsigned long uaddr_to = (unsigned long) to;
pte_t *pte_from, *pte_to;
@@ -298,17 +242,28 @@ static size_t copy_in_user_pt(size_t n, void __user *to,
retry:
spin_lock(&mm->page_table_lock);
do {
+ write_user = 0;
+ uaddr = uaddr_from;
pte_from = follow_table(mm, uaddr_from);
- if (!pte_from || !pte_present(*pte_from)) {
- uaddr = uaddr_from;
- write_user = 0;
+ error_code = (unsigned long) pte_from;
+ if (error_code < 0x1000)
+ goto fault;
+ if (!pte_present(*pte_from)) {
+ error_code = 0x11;
goto fault;
}
+ write_user = 1;
+ uaddr = uaddr_to;
pte_to = follow_table(mm, uaddr_to);
- if (!pte_to || !pte_present(*pte_to) || !pte_write(*pte_to)) {
- uaddr = uaddr_to;
- write_user = 1;
+ error_code = (unsigned long) pte_to;
+ if (error_code < 0x1000)
+ goto fault;
+ if (!pte_present(*pte_to)) {
+ error_code = 0x11;
+ goto fault;
+ } else if (!pte_write(*pte_to)) {
+ error_code = 0x04;
goto fault;
}
@@ -329,7 +284,7 @@ retry:
return n - done;
fault:
spin_unlock(&mm->page_table_lock);
- if (__handle_fault(mm, uaddr, write_user))
+ if (__handle_fault(uaddr, error_code, write_user))
return n - done;
goto retry;
}
diff --git a/arch/s390/lib/uaccess_std.c b/arch/s390/lib/uaccess_std.c
index d2ffbad..07deaee 100644
--- a/arch/s390/lib/uaccess_std.c
+++ b/arch/s390/lib/uaccess_std.c
@@ -36,12 +36,12 @@ size_t copy_from_user_std(size_t size, const void __user *ptr, void *x)
tmp1 = -256UL;
asm volatile(
"0: mvcp 0(%0,%2),0(%1),%3\n"
- " jz 8f\n"
+ "10:jz 8f\n"
"1:"ALR" %0,%3\n"
" la %1,256(%1)\n"
" la %2,256(%2)\n"
"2: mvcp 0(%0,%2),0(%1),%3\n"
- " jnz 1b\n"
+ "11:jnz 1b\n"
" j 8f\n"
"3: la %4,255(%1)\n" /* %4 = ptr + 255 */
" "LHI" %3,-4096\n"
@@ -50,7 +50,7 @@ size_t copy_from_user_std(size_t size, const void __user *ptr, void *x)
" "CLR" %0,%4\n" /* copy crosses next page boundary? */
" jnh 5f\n"
"4: mvcp 0(%4,%2),0(%1),%3\n"
- " "SLR" %0,%4\n"
+ "12:"SLR" %0,%4\n"
" "ALR" %2,%4\n"
"5:"LHI" %4,-1\n"
" "ALR" %4,%0\n" /* copy remaining size, subtract 1 */
@@ -65,6 +65,7 @@ size_t copy_from_user_std(size_t size, const void __user *ptr, void *x)
"8:"SLR" %0,%0\n"
"9: \n"
EX_TABLE(0b,3b) EX_TABLE(2b,3b) EX_TABLE(4b,5b)
+ EX_TABLE(10b,3b) EX_TABLE(11b,3b) EX_TABLE(12b,5b)
: "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
: : "cc", "memory");
return size;
@@ -85,12 +86,12 @@ size_t copy_to_user_std(size_t size, void __user *ptr, const void *x)
tmp1 = -256UL;
asm volatile(
"0: mvcs 0(%0,%1),0(%2),%3\n"
- " jz 5f\n"
+ "7: jz 5f\n"
"1:"ALR" %0,%3\n"
" la %1,256(%1)\n"
" la %2,256(%2)\n"
"2: mvcs 0(%0,%1),0(%2),%3\n"
- " jnz 1b\n"
+ "8: jnz 1b\n"
" j 5f\n"
"3: la %4,255(%1)\n" /* %4 = ptr + 255 */
" "LHI" %3,-4096\n"
@@ -99,11 +100,12 @@ size_t copy_to_user_std(size_t size, void __user *ptr, const void *x)
" "CLR" %0,%4\n" /* copy crosses next page boundary? */
" jnh 6f\n"
"4: mvcs 0(%4,%1),0(%2),%3\n"
- " "SLR" %0,%4\n"
+ "9:"SLR" %0,%4\n"
" j 6f\n"
"5:"SLR" %0,%0\n"
"6: \n"
EX_TABLE(0b,3b) EX_TABLE(2b,3b) EX_TABLE(4b,6b)
+ EX_TABLE(7b,3b) EX_TABLE(8b,3b) EX_TABLE(9b,6b)
: "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
: : "cc", "memory");
return size;
diff --git a/arch/s390/math-emu/math.c b/arch/s390/math-emu/math.c
index 3ee78cc..cd4e9c1 100644
--- a/arch/s390/math-emu/math.c
+++ b/arch/s390/math-emu/math.c
@@ -2088,7 +2088,7 @@ int math_emu_ldr(__u8 *opcode) {
__u16 opc = *((__u16 *) opcode);
if ((opc & 0x90) == 0) { /* test if rx in {0,2,4,6} */
- /* we got an exception therfore ry can't be in {0,2,4,6} */
+ /* we got an exception therefore ry can't be in {0,2,4,6} */
asm volatile( /* load rx from fp_regs.fprs[ry] */
" bras 1,0f\n"
" ld 0,0(%1)\n"
@@ -2118,7 +2118,7 @@ int math_emu_ler(__u8 *opcode) {
__u16 opc = *((__u16 *) opcode);
if ((opc & 0x90) == 0) { /* test if rx in {0,2,4,6} */
- /* we got an exception therfore ry can't be in {0,2,4,6} */
+ /* we got an exception therefore ry can't be in {0,2,4,6} */
asm volatile( /* load rx from fp_regs.fprs[ry] */
" bras 1,0f\n"
" le 0,0(%1)\n"
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c
index b201135..76a3637 100644
--- a/arch/s390/mm/cmm.c
+++ b/arch/s390/mm/cmm.c
@@ -18,6 +18,7 @@
#include <linux/swap.h>
#include <linux/kthread.h>
#include <linux/oom.h>
+#include <linux/suspend.h>
#include <asm/pgalloc.h>
#include <asm/uaccess.h>
@@ -44,6 +45,7 @@ static volatile long cmm_pages_target;
static volatile long cmm_timed_pages_target;
static long cmm_timeout_pages;
static long cmm_timeout_seconds;
+static int cmm_suspended;
static struct cmm_page_array *cmm_page_list;
static struct cmm_page_array *cmm_timed_page_list;
@@ -147,9 +149,9 @@ cmm_thread(void *dummy)
while (1) {
rc = wait_event_interruptible(cmm_thread_wait,
- (cmm_pages != cmm_pages_target ||
- cmm_timed_pages != cmm_timed_pages_target ||
- kthread_should_stop()));
+ (!cmm_suspended && (cmm_pages != cmm_pages_target ||
+ cmm_timed_pages != cmm_timed_pages_target)) ||
+ kthread_should_stop());
if (kthread_should_stop() || rc == -ERESTARTSYS) {
cmm_pages_target = cmm_pages;
cmm_timed_pages_target = cmm_timed_pages;
@@ -343,30 +345,29 @@ static struct ctl_table cmm_table[] = {
{
.procname = "cmm_pages",
.mode = 0644,
- .proc_handler = &cmm_pages_handler,
+ .proc_handler = cmm_pages_handler,
},
{
.procname = "cmm_timed_pages",
.mode = 0644,
- .proc_handler = &cmm_pages_handler,
+ .proc_handler = cmm_pages_handler,
},
{
.procname = "cmm_timeout",
.mode = 0644,
- .proc_handler = &cmm_timeout_handler,
+ .proc_handler = cmm_timeout_handler,
},
- { .ctl_name = 0 }
+ { }
};
static struct ctl_table cmm_dir_table[] = {
{
- .ctl_name = CTL_VM,
.procname = "vm",
.maxlen = 0,
.mode = 0555,
.child = cmm_table,
},
- { .ctl_name = 0 }
+ { }
};
#endif
@@ -411,6 +412,38 @@ cmm_smsg_target(char *from, char *msg)
static struct ctl_table_header *cmm_sysctl_header;
+static int cmm_suspend(void)
+{
+ cmm_suspended = 1;
+ cmm_free_pages(cmm_pages, &cmm_pages, &cmm_page_list);
+ cmm_free_pages(cmm_timed_pages, &cmm_timed_pages, &cmm_timed_page_list);
+ return 0;
+}
+
+static int cmm_resume(void)
+{
+ cmm_suspended = 0;
+ cmm_kick_thread();
+ return 0;
+}
+
+static int cmm_power_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ switch (event) {
+ case PM_POST_HIBERNATION:
+ return cmm_resume();
+ case PM_HIBERNATION_PREPARE:
+ return cmm_suspend();
+ default:
+ return NOTIFY_DONE;
+ }
+}
+
+static struct notifier_block cmm_power_notifier = {
+ .notifier_call = cmm_power_event,
+};
+
static int
cmm_init (void)
{
@@ -419,7 +452,7 @@ cmm_init (void)
#ifdef CONFIG_CMM_PROC
cmm_sysctl_header = register_sysctl_table(cmm_dir_table);
if (!cmm_sysctl_header)
- goto out;
+ goto out_sysctl;
#endif
#ifdef CONFIG_CMM_IUCV
rc = smsg_register_callback(SMSG_PREFIX, cmm_smsg_target);
@@ -429,17 +462,21 @@ cmm_init (void)
rc = register_oom_notifier(&cmm_oom_nb);
if (rc < 0)
goto out_oom_notify;
+ rc = register_pm_notifier(&cmm_power_notifier);
+ if (rc)
+ goto out_pm;
init_waitqueue_head(&cmm_thread_wait);
init_timer(&cmm_timer);
cmm_thread_ptr = kthread_run(cmm_thread, NULL, "cmmthread");
rc = IS_ERR(cmm_thread_ptr) ? PTR_ERR(cmm_thread_ptr) : 0;
- if (!rc)
- goto out;
- /*
- * kthread_create failed. undo all the stuff from above again.
- */
- unregister_oom_notifier(&cmm_oom_nb);
+ if (rc)
+ goto out_kthread;
+ return 0;
+out_kthread:
+ unregister_pm_notifier(&cmm_power_notifier);
+out_pm:
+ unregister_oom_notifier(&cmm_oom_nb);
out_oom_notify:
#ifdef CONFIG_CMM_IUCV
smsg_unregister_callback(SMSG_PREFIX, cmm_smsg_target);
@@ -447,8 +484,8 @@ out_smsg:
#endif
#ifdef CONFIG_CMM_PROC
unregister_sysctl_table(cmm_sysctl_header);
+out_sysctl:
#endif
-out:
return rc;
}
@@ -456,6 +493,7 @@ static void
cmm_exit(void)
{
kthread_stop(cmm_thread_ptr);
+ unregister_pm_notifier(&cmm_power_notifier);
unregister_oom_notifier(&cmm_oom_nb);
cmm_free_pages(cmm_pages, &cmm_pages, &cmm_page_list);
cmm_free_pages(cmm_timed_pages, &cmm_timed_pages, &cmm_timed_page_list);
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 6d50746..fc102e7 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -34,16 +34,15 @@
#include <asm/pgtable.h>
#include <asm/s390_ext.h>
#include <asm/mmu_context.h>
+#include <asm/compat.h>
#include "../kernel/entry.h"
#ifndef CONFIG_64BIT
#define __FAIL_ADDR_MASK 0x7ffff000
-#define __FIXUP_MASK 0x7fffffff
#define __SUBCODE_MASK 0x0200
#define __PF_RES_FIELD 0ULL
#else /* CONFIG_64BIT */
#define __FAIL_ADDR_MASK -4096L
-#define __FIXUP_MASK ~0L
#define __SUBCODE_MASK 0x0600
#define __PF_RES_FIELD 0x8000000000000000ULL
#endif /* CONFIG_64BIT */
@@ -52,11 +51,15 @@
extern int sysctl_userprocess_debug;
#endif
-#ifdef CONFIG_KPROBES
-static inline int notify_page_fault(struct pt_regs *regs, long err)
+#define VM_FAULT_BADCONTEXT 0x010000
+#define VM_FAULT_BADMAP 0x020000
+#define VM_FAULT_BADACCESS 0x040000
+
+static inline int notify_page_fault(struct pt_regs *regs)
{
int ret = 0;
+#ifdef CONFIG_KPROBES
/* kprobe_running() needs smp_processor_id() */
if (!user_mode(regs)) {
preempt_disable();
@@ -64,15 +67,9 @@ static inline int notify_page_fault(struct pt_regs *regs, long err)
ret = 1;
preempt_enable();
}
-
+#endif
return ret;
}
-#else
-static inline int notify_page_fault(struct pt_regs *regs, long err)
-{
- return 0;
-}
-#endif
/*
@@ -100,57 +97,50 @@ void bust_spinlocks(int yes)
/*
* Returns the address space associated with the fault.
- * Returns 0 for kernel space, 1 for user space and
- * 2 for code execution in user space with noexec=on.
+ * Returns 0 for kernel space and 1 for user space.
*/
-static inline int check_space(struct task_struct *tsk)
+static inline int user_space_fault(unsigned long trans_exc_code)
{
/*
- * The lowest two bits of S390_lowcore.trans_exc_code
- * indicate which paging table was used.
+ * The lowest two bits of the translation exception
+ * identification indicate which paging table was used.
*/
- int desc = S390_lowcore.trans_exc_code & 3;
-
- if (desc == 3) /* Home Segment Table Descriptor */
- return switch_amode == 0;
- if (desc == 2) /* Secondary Segment Table Descriptor */
- return tsk->thread.mm_segment.ar4;
-#ifdef CONFIG_S390_SWITCH_AMODE
- if (unlikely(desc == 1)) { /* STD determined via access register */
- /* %a0 always indicates primary space. */
- if (S390_lowcore.exc_access_id != 0) {
- save_access_regs(tsk->thread.acrs);
- /*
- * An alet of 0 indicates primary space.
- * An alet of 1 indicates secondary space.
- * Any other alet values generate an
- * alen-translation exception.
- */
- if (tsk->thread.acrs[S390_lowcore.exc_access_id])
- return tsk->thread.mm_segment.ar4;
- }
- }
-#endif
- /* Primary Segment Table Descriptor */
- return switch_amode << s390_noexec;
+ trans_exc_code &= 3;
+ if (trans_exc_code == 2)
+ /* Access via secondary space, set_fs setting decides */
+ return current->thread.mm_segment.ar4;
+ if (user_mode == HOME_SPACE_MODE)
+ /* User space if the access has been done via home space. */
+ return trans_exc_code == 3;
+ /*
+ * If the user space is not the home space the kernel runs in home
+ * space. Access via secondary space has already been covered,
+ * access via primary space or access register is from user space
+ * and access via home space is from the kernel.
+ */
+ return trans_exc_code != 3;
}
/*
* Send SIGSEGV to task. This is an external routine
* to keep the stack usage of do_page_fault small.
*/
-static void do_sigsegv(struct pt_regs *regs, unsigned long error_code,
- int si_code, unsigned long address)
+static noinline void do_sigsegv(struct pt_regs *regs, long int_code,
+ int si_code, unsigned long trans_exc_code)
{
struct siginfo si;
+ unsigned long address;
+ address = trans_exc_code & __FAIL_ADDR_MASK;
+ current->thread.prot_addr = address;
+ current->thread.trap_no = int_code;
#if defined(CONFIG_SYSCTL) || defined(CONFIG_PROCESS_DEBUG)
#if defined(CONFIG_SYSCTL)
if (sysctl_userprocess_debug)
#endif
{
printk("User process fault: interruption code 0x%lX\n",
- error_code);
+ int_code);
printk("failing address: %lX\n", address);
show_regs(regs);
}
@@ -161,13 +151,14 @@ static void do_sigsegv(struct pt_regs *regs, unsigned long error_code,
force_sig_info(SIGSEGV, &si, current);
}
-static void do_no_context(struct pt_regs *regs, unsigned long error_code,
- unsigned long address)
+static noinline void do_no_context(struct pt_regs *regs, long int_code,
+ unsigned long trans_exc_code)
{
const struct exception_table_entry *fixup;
+ unsigned long address;
/* Are we prepared to handle this kernel fault? */
- fixup = search_exception_tables(regs->psw.addr & __FIXUP_MASK);
+ fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN);
if (fixup) {
regs->psw.addr = fixup->fixup | PSW_ADDR_AMODE;
return;
@@ -177,129 +168,149 @@ static void do_no_context(struct pt_regs *regs, unsigned long error_code,
* Oops. The kernel tried to access some bad page. We'll have to
* terminate things with extreme prejudice.
*/
- if (check_space(current) == 0)
+ address = trans_exc_code & __FAIL_ADDR_MASK;
+ if (!user_space_fault(trans_exc_code))
printk(KERN_ALERT "Unable to handle kernel pointer dereference"
" at virtual kernel address %p\n", (void *)address);
else
printk(KERN_ALERT "Unable to handle kernel paging request"
" at virtual user address %p\n", (void *)address);
- die("Oops", regs, error_code);
+ die("Oops", regs, int_code);
do_exit(SIGKILL);
}
-static void do_low_address(struct pt_regs *regs, unsigned long error_code)
+static noinline void do_low_address(struct pt_regs *regs, long int_code,
+ unsigned long trans_exc_code)
{
/* Low-address protection hit in kernel mode means
NULL pointer write access in kernel mode. */
if (regs->psw.mask & PSW_MASK_PSTATE) {
/* Low-address protection hit in user mode 'cannot happen'. */
- die ("Low-address protection", regs, error_code);
+ die ("Low-address protection", regs, int_code);
do_exit(SIGKILL);
}
- do_no_context(regs, error_code, 0);
+ do_no_context(regs, int_code, trans_exc_code);
}
-static void do_sigbus(struct pt_regs *regs, unsigned long error_code,
- unsigned long address)
+static noinline void do_sigbus(struct pt_regs *regs, long int_code,
+ unsigned long trans_exc_code)
{
struct task_struct *tsk = current;
- struct mm_struct *mm = tsk->mm;
- up_read(&mm->mmap_sem);
/*
* Send a sigbus, regardless of whether we were in kernel
* or user mode.
*/
- tsk->thread.prot_addr = address;
- tsk->thread.trap_no = error_code;
+ tsk->thread.prot_addr = trans_exc_code & __FAIL_ADDR_MASK;
+ tsk->thread.trap_no = int_code;
force_sig(SIGBUS, tsk);
-
- /* Kernel mode? Handle exceptions or die */
- if (!(regs->psw.mask & PSW_MASK_PSTATE))
- do_no_context(regs, error_code, address);
}
#ifdef CONFIG_S390_EXEC_PROTECT
-static int signal_return(struct mm_struct *mm, struct pt_regs *regs,
- unsigned long address, unsigned long error_code)
+static noinline int signal_return(struct pt_regs *regs, long int_code,
+ unsigned long trans_exc_code)
{
u16 instruction;
int rc;
-#ifdef CONFIG_COMPAT
- int compat;
-#endif
- pagefault_disable();
rc = __get_user(instruction, (u16 __user *) regs->psw.addr);
- pagefault_enable();
- if (rc)
- return -EFAULT;
- up_read(&mm->mmap_sem);
- clear_tsk_thread_flag(current, TIF_SINGLE_STEP);
-#ifdef CONFIG_COMPAT
- compat = is_compat_task();
- if (compat && instruction == 0x0a77)
- sys32_sigreturn();
- else if (compat && instruction == 0x0aad)
- sys32_rt_sigreturn();
- else
-#endif
- if (instruction == 0x0a77)
- sys_sigreturn();
- else if (instruction == 0x0aad)
- sys_rt_sigreturn();
- else {
- current->thread.prot_addr = address;
- current->thread.trap_no = error_code;
- do_sigsegv(regs, error_code, SEGV_MAPERR, address);
- }
+ if (!rc && instruction == 0x0a77) {
+ clear_tsk_thread_flag(current, TIF_SINGLE_STEP);
+ if (is_compat_task())
+ sys32_sigreturn();
+ else
+ sys_sigreturn();
+ } else if (!rc && instruction == 0x0aad) {
+ clear_tsk_thread_flag(current, TIF_SINGLE_STEP);
+ if (is_compat_task())
+ sys32_rt_sigreturn();
+ else
+ sys_rt_sigreturn();
+ } else
+ do_sigsegv(regs, int_code, SEGV_MAPERR, trans_exc_code);
return 0;
}
#endif /* CONFIG_S390_EXEC_PROTECT */
+static noinline void do_fault_error(struct pt_regs *regs, long int_code,
+ unsigned long trans_exc_code, int fault)
+{
+ int si_code;
+
+ switch (fault) {
+ case VM_FAULT_BADACCESS:
+#ifdef CONFIG_S390_EXEC_PROTECT
+ if ((regs->psw.mask & PSW_MASK_ASC) == PSW_ASC_SECONDARY &&
+ (trans_exc_code & 3) == 0) {
+ signal_return(regs, int_code, trans_exc_code);
+ break;
+ }
+#endif /* CONFIG_S390_EXEC_PROTECT */
+ case VM_FAULT_BADMAP:
+ /* Bad memory access. Check if it is kernel or user space. */
+ if (regs->psw.mask & PSW_MASK_PSTATE) {
+ /* User mode accesses just cause a SIGSEGV */
+ si_code = (fault == VM_FAULT_BADMAP) ?
+ SEGV_MAPERR : SEGV_ACCERR;
+ do_sigsegv(regs, int_code, si_code, trans_exc_code);
+ return;
+ }
+ case VM_FAULT_BADCONTEXT:
+ do_no_context(regs, int_code, trans_exc_code);
+ break;
+ default: /* fault & VM_FAULT_ERROR */
+ if (fault & VM_FAULT_OOM)
+ pagefault_out_of_memory();
+ else if (fault & VM_FAULT_SIGBUS) {
+ do_sigbus(regs, int_code, trans_exc_code);
+ /* Kernel mode? Handle exceptions or die */
+ if (!(regs->psw.mask & PSW_MASK_PSTATE))
+ do_no_context(regs, int_code, trans_exc_code);
+ } else
+ BUG();
+ break;
+ }
+}
+
/*
* This routine handles page faults. It determines the address,
* and the problem, and then passes it off to one of the appropriate
* routines.
*
- * error_code:
+ * interruption code (int_code):
* 04 Protection -> Write-Protection (suprression)
* 10 Segment translation -> Not present (nullification)
* 11 Page translation -> Not present (nullification)
* 3b Region third trans. -> Not present (nullification)
*/
-static inline void
-do_exception(struct pt_regs *regs, unsigned long error_code, int write)
+static inline int do_exception(struct pt_regs *regs, int access,
+ unsigned long trans_exc_code)
{
struct task_struct *tsk;
struct mm_struct *mm;
struct vm_area_struct *vma;
unsigned long address;
- int space;
- int si_code;
int fault;
- if (notify_page_fault(regs, error_code))
- return;
+ if (notify_page_fault(regs))
+ return 0;
tsk = current;
mm = tsk->mm;
- /* get the failing address and the affected space */
- address = S390_lowcore.trans_exc_code & __FAIL_ADDR_MASK;
- space = check_space(tsk);
-
/*
* Verify that the fault happened in user space, that
* we are not in an interrupt and that there is a
* user context.
*/
- if (unlikely(space == 0 || in_atomic() || !mm))
- goto no_context;
+ fault = VM_FAULT_BADCONTEXT;
+ if (unlikely(!user_space_fault(trans_exc_code) || in_atomic() || !mm))
+ goto out;
+ address = trans_exc_code & __FAIL_ADDR_MASK;
/*
* When we get here, the fault happened in the current
* task's user address space, so we can switch on the
@@ -309,42 +320,26 @@ do_exception(struct pt_regs *regs, unsigned long error_code, int write)
perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
down_read(&mm->mmap_sem);
- si_code = SEGV_MAPERR;
+ fault = VM_FAULT_BADMAP;
vma = find_vma(mm, address);
if (!vma)
- goto bad_area;
-
-#ifdef CONFIG_S390_EXEC_PROTECT
- if (unlikely((space == 2) && !(vma->vm_flags & VM_EXEC)))
- if (!signal_return(mm, regs, address, error_code))
- /*
- * signal_return() has done an up_read(&mm->mmap_sem)
- * if it returns 0.
- */
- return;
-#endif
+ goto out_up;
- if (vma->vm_start <= address)
- goto good_area;
- if (!(vma->vm_flags & VM_GROWSDOWN))
- goto bad_area;
- if (expand_stack(vma, address))
- goto bad_area;
-/*
- * Ok, we have a good vm_area for this memory access, so
- * we can handle it..
- */
-good_area:
- si_code = SEGV_ACCERR;
- if (!write) {
- /* page not present, check vm flags */
- if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
- goto bad_area;
- } else {
- if (!(vma->vm_flags & VM_WRITE))
- goto bad_area;
+ if (unlikely(vma->vm_start > address)) {
+ if (!(vma->vm_flags & VM_GROWSDOWN))
+ goto out_up;
+ if (expand_stack(vma, address))
+ goto out_up;
}
+ /*
+ * Ok, we have a good vm_area for this memory access, so
+ * we can handle it..
+ */
+ fault = VM_FAULT_BADACCESS;
+ if (unlikely(!(vma->vm_flags & access)))
+ goto out_up;
+
if (is_vm_hugetlb_page(vma))
address &= HPAGE_MASK;
/*
@@ -352,18 +347,11 @@ good_area:
* make sure we exit gracefully rather than endlessly redo
* the fault.
*/
- fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0);
- if (unlikely(fault & VM_FAULT_ERROR)) {
- if (fault & VM_FAULT_OOM) {
- up_read(&mm->mmap_sem);
- pagefault_out_of_memory();
- return;
- } else if (fault & VM_FAULT_SIGBUS) {
- do_sigbus(regs, error_code, address);
- return;
- }
- BUG();
- }
+ fault = handle_mm_fault(mm, vma, address,
+ (access == VM_WRITE) ? FAULT_FLAG_WRITE : 0);
+ if (unlikely(fault & VM_FAULT_ERROR))
+ goto out_up;
+
if (fault & VM_FAULT_MAJOR) {
tsk->maj_flt++;
perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0,
@@ -373,74 +361,69 @@ good_area:
perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0,
regs, address);
}
- up_read(&mm->mmap_sem);
/*
* The instruction that caused the program check will
* be repeated. Don't signal single step via SIGTRAP.
*/
clear_tsk_thread_flag(tsk, TIF_SINGLE_STEP);
- return;
-
-/*
- * Something tried to access memory that isn't in our memory map..
- * Fix it, but check if it's kernel or user first..
- */
-bad_area:
+ fault = 0;
+out_up:
up_read(&mm->mmap_sem);
-
- /* User mode accesses just cause a SIGSEGV */
- if (regs->psw.mask & PSW_MASK_PSTATE) {
- tsk->thread.prot_addr = address;
- tsk->thread.trap_no = error_code;
- do_sigsegv(regs, error_code, si_code, address);
- return;
- }
-
-no_context:
- do_no_context(regs, error_code, address);
+out:
+ return fault;
}
-void __kprobes do_protection_exception(struct pt_regs *regs,
- long error_code)
+void __kprobes do_protection_exception(struct pt_regs *regs, long int_code)
{
+ unsigned long trans_exc_code = S390_lowcore.trans_exc_code;
+ int fault;
+
/* Protection exception is supressing, decrement psw address. */
- regs->psw.addr -= (error_code >> 16);
+ regs->psw.addr -= (int_code >> 16);
/*
* Check for low-address protection. This needs to be treated
* as a special case because the translation exception code
* field is not guaranteed to contain valid data in this case.
*/
- if (unlikely(!(S390_lowcore.trans_exc_code & 4))) {
- do_low_address(regs, error_code);
+ if (unlikely(!(trans_exc_code & 4))) {
+ do_low_address(regs, int_code, trans_exc_code);
return;
}
- do_exception(regs, 4, 1);
+ fault = do_exception(regs, VM_WRITE, trans_exc_code);
+ if (unlikely(fault))
+ do_fault_error(regs, 4, trans_exc_code, fault);
}
-void __kprobes do_dat_exception(struct pt_regs *regs, long error_code)
+void __kprobes do_dat_exception(struct pt_regs *regs, long int_code)
{
- do_exception(regs, error_code & 0xff, 0);
+ unsigned long trans_exc_code = S390_lowcore.trans_exc_code;
+ int access, fault;
+
+ access = VM_READ | VM_EXEC | VM_WRITE;
+#ifdef CONFIG_S390_EXEC_PROTECT
+ if ((regs->psw.mask & PSW_MASK_ASC) == PSW_ASC_SECONDARY &&
+ (trans_exc_code & 3) == 0)
+ access = VM_EXEC;
+#endif
+ fault = do_exception(regs, access, trans_exc_code);
+ if (unlikely(fault))
+ do_fault_error(regs, int_code & 255, trans_exc_code, fault);
}
#ifdef CONFIG_64BIT
-void __kprobes do_asce_exception(struct pt_regs *regs, unsigned long error_code)
+void __kprobes do_asce_exception(struct pt_regs *regs, long int_code)
{
- struct mm_struct *mm;
+ unsigned long trans_exc_code = S390_lowcore.trans_exc_code;
+ struct mm_struct *mm = current->mm;
struct vm_area_struct *vma;
- unsigned long address;
- int space;
-
- mm = current->mm;
- address = S390_lowcore.trans_exc_code & __FAIL_ADDR_MASK;
- space = check_space(current);
- if (unlikely(space == 0 || in_atomic() || !mm))
+ if (unlikely(!user_space_fault(trans_exc_code) || in_atomic() || !mm))
goto no_context;
local_irq_enable();
down_read(&mm->mmap_sem);
- vma = find_vma(mm, address);
+ vma = find_vma(mm, trans_exc_code & __FAIL_ADDR_MASK);
up_read(&mm->mmap_sem);
if (vma) {
@@ -450,17 +433,38 @@ void __kprobes do_asce_exception(struct pt_regs *regs, unsigned long error_code)
/* User mode accesses just cause a SIGSEGV */
if (regs->psw.mask & PSW_MASK_PSTATE) {
- current->thread.prot_addr = address;
- current->thread.trap_no = error_code;
- do_sigsegv(regs, error_code, SEGV_MAPERR, address);
+ do_sigsegv(regs, int_code, SEGV_MAPERR, trans_exc_code);
return;
}
no_context:
- do_no_context(regs, error_code, address);
+ do_no_context(regs, int_code, trans_exc_code);
}
#endif
+int __handle_fault(unsigned long uaddr, unsigned long int_code, int write_user)
+{
+ struct pt_regs regs;
+ int access, fault;
+
+ regs.psw.mask = psw_kernel_bits;
+ if (!irqs_disabled())
+ regs.psw.mask |= PSW_MASK_IO | PSW_MASK_EXT;
+ regs.psw.addr = (unsigned long) __builtin_return_address(0);
+ regs.psw.addr |= PSW_ADDR_AMODE;
+ uaddr &= PAGE_MASK;
+ access = write_user ? VM_WRITE : VM_READ;
+ fault = do_exception(&regs, access, uaddr | 2);
+ if (unlikely(fault)) {
+ if (fault & VM_FAULT_OOM) {
+ pagefault_out_of_memory();
+ fault = 0;
+ } else if (fault & VM_FAULT_SIGBUS)
+ do_sigbus(&regs, int_code, uaddr);
+ }
+ return fault ? -EFAULT : 0;
+}
+
#ifdef CONFIG_PFAULT
/*
* 'pfault' pseudo page faults routines.
@@ -522,7 +526,7 @@ void pfault_fini(void)
: : "a" (&refbk), "m" (refbk) : "cc");
}
-static void pfault_interrupt(__u16 error_code)
+static void pfault_interrupt(__u16 int_code)
{
struct task_struct *tsk;
__u16 subcode;
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index c60bfb3..ad621e0 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -269,7 +269,7 @@ int s390_enable_sie(void)
struct mm_struct *mm, *old_mm;
/* Do we have switched amode? If no, we cannot do sie */
- if (!switch_amode)
+ if (user_mode == HOME_SPACE_MODE)
return -EINVAL;
/* Do we have pgstes? if yes, we are done */
@@ -279,7 +279,10 @@ int s390_enable_sie(void)
/* lets check if we are allowed to replace the mm */
task_lock(tsk);
if (!tsk->mm || atomic_read(&tsk->mm->mm_users) > 1 ||
- tsk->mm != tsk->active_mm || !hlist_empty(&tsk->mm->ioctx_list)) {
+#ifdef CONFIG_AIO
+ !hlist_empty(&tsk->mm->ioctx_list) ||
+#endif
+ tsk->mm != tsk->active_mm) {
task_unlock(tsk);
return -EINVAL;
}
@@ -295,7 +298,10 @@ int s390_enable_sie(void)
/* Now lets check again if something happened */
task_lock(tsk);
if (!tsk->mm || atomic_read(&tsk->mm->mm_users) > 1 ||
- tsk->mm != tsk->active_mm || !hlist_empty(&tsk->mm->ioctx_list)) {
+#ifdef CONFIG_AIO
+ !hlist_empty(&tsk->mm->ioctx_list) ||
+#endif
+ tsk->mm != tsk->active_mm) {
mmput(mm);
task_unlock(tsk);
return -EINVAL;
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
index 5f91a38..300ab01 100644
--- a/arch/s390/mm/vmem.c
+++ b/arch/s390/mm/vmem.c
@@ -70,8 +70,12 @@ static pte_t __ref *vmem_pte_alloc(void)
pte = alloc_bootmem(PTRS_PER_PTE * sizeof(pte_t));
if (!pte)
return NULL;
- clear_table((unsigned long *) pte, _PAGE_TYPE_EMPTY,
- PTRS_PER_PTE * sizeof(pte_t));
+ if (MACHINE_HAS_HPAGE)
+ clear_table((unsigned long *) pte, _PAGE_TYPE_EMPTY | _PAGE_CO,
+ PTRS_PER_PTE * sizeof(pte_t));
+ else
+ clear_table((unsigned long *) pte, _PAGE_TYPE_EMPTY,
+ PTRS_PER_PTE * sizeof(pte_t));
return pte;
}
@@ -112,7 +116,8 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
if (MACHINE_HAS_HPAGE && !(address & ~HPAGE_MASK) &&
(address + HPAGE_SIZE <= start + size) &&
(address >= HPAGE_SIZE)) {
- pte_val(pte) |= _SEGMENT_ENTRY_LARGE;
+ pte_val(pte) |= _SEGMENT_ENTRY_LARGE |
+ _SEGMENT_ENTRY_CO;
pmd_val(*pm_dir) = pte_val(pte);
address += HPAGE_SIZE - PAGE_SIZE;
continue;
OpenPOWER on IntegriCloud