aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-22 22:23:34 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-22 22:23:34 -0400
commit56d61a0e26c5a61c66d1ac259a59960295939da9 (patch)
treea23a30a966fe4220060682179294087cba1f9c57
parent5f48b338cd28f4095697a174d7e3e72084aca893 (diff)
parent190a1d722a59725706daf832bc8a511ed62f249d (diff)
Merge branch 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6
* 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6: [S390] 4level-fixup cleanup [S390] Cleanup page table definitions. [S390] Introduce follow_table in uaccess_pt.c [S390] Remove unused user_seg from thread structure. [S390] tlb flush fix. [S390] kernel: Fix dump on panic for DASDs under LPAR. [S390] struct class_device -> struct device conversion. [S390] cio: Fix incomplete commit for uevent suppression. [S390] cio: Use to_channelpath() for device to channel path conversion. [S390] Add per-cpu idle time / idle count sysfs attributes. [S390] Update default configuration.
-rw-r--r--arch/s390/defconfig131
-rw-r--r--arch/s390/kernel/ipl.c2
-rw-r--r--arch/s390/kernel/process.c18
-rw-r--r--arch/s390/kernel/smp.c65
-rw-r--r--arch/s390/lib/uaccess_pt.c90
-rw-r--r--arch/s390/mm/Makefile2
-rw-r--r--arch/s390/mm/init.c32
-rw-r--r--arch/s390/mm/pgtable.c94
-rw-r--r--arch/s390/mm/vmem.c53
-rw-r--r--drivers/s390/char/raw3270.c26
-rw-r--r--drivers/s390/char/tape_class.c19
-rw-r--r--drivers/s390/char/tape_class.h4
-rw-r--r--drivers/s390/char/vmlogrdr.c15
-rw-r--r--drivers/s390/cio/chp.c12
-rw-r--r--drivers/s390/cio/css.c9
-rw-r--r--include/asm-s390/cpu.h25
-rw-r--r--include/asm-s390/mmu_context.h50
-rw-r--r--include/asm-s390/page.h4
-rw-r--r--include/asm-s390/pgalloc.h250
-rw-r--r--include/asm-s390/pgtable.h429
-rw-r--r--include/asm-s390/processor.h20
-rw-r--r--include/asm-s390/tlb.h129
-rw-r--r--include/asm-s390/tlbflush.h152
23 files changed, 918 insertions, 713 deletions
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index 2aae23dba4bb..ece7b99da895 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -1,7 +1,7 @@
1# 1#
2# Automatically generated make config: don't edit 2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.22 3# Linux kernel version: 2.6.23
4# Tue Jul 17 12:50:23 2007 4# Mon Oct 22 12:10:44 2007
5# 5#
6CONFIG_MMU=y 6CONFIG_MMU=y
7CONFIG_ZONE_DMA=y 7CONFIG_ZONE_DMA=y
@@ -19,15 +19,11 @@ CONFIG_S390=y
19CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" 19CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
20 20
21# 21#
22# Code maturity level options 22# General setup
23# 23#
24CONFIG_EXPERIMENTAL=y 24CONFIG_EXPERIMENTAL=y
25CONFIG_LOCK_KERNEL=y 25CONFIG_LOCK_KERNEL=y
26CONFIG_INIT_ENV_ARG_LIMIT=32 26CONFIG_INIT_ENV_ARG_LIMIT=32
27
28#
29# General setup
30#
31CONFIG_LOCALVERSION="" 27CONFIG_LOCALVERSION=""
32CONFIG_LOCALVERSION_AUTO=y 28CONFIG_LOCALVERSION_AUTO=y
33CONFIG_SWAP=y 29CONFIG_SWAP=y
@@ -42,7 +38,14 @@ CONFIG_AUDIT=y
42CONFIG_IKCONFIG=y 38CONFIG_IKCONFIG=y
43CONFIG_IKCONFIG_PROC=y 39CONFIG_IKCONFIG_PROC=y
44CONFIG_LOG_BUF_SHIFT=17 40CONFIG_LOG_BUF_SHIFT=17
41CONFIG_CGROUPS=y
42# CONFIG_CGROUP_DEBUG is not set
43CONFIG_CGROUP_NS=y
44CONFIG_CGROUP_CPUACCT=y
45# CONFIG_CPUSETS is not set 45# CONFIG_CPUSETS is not set
46CONFIG_FAIR_GROUP_SCHED=y
47CONFIG_FAIR_USER_SCHED=y
48# CONFIG_FAIR_CGROUP_SCHED is not set
46CONFIG_SYSFS_DEPRECATED=y 49CONFIG_SYSFS_DEPRECATED=y
47# CONFIG_RELAY is not set 50# CONFIG_RELAY is not set
48CONFIG_BLK_DEV_INITRD=y 51CONFIG_BLK_DEV_INITRD=y
@@ -63,7 +66,6 @@ CONFIG_FUTEX=y
63CONFIG_ANON_INODES=y 66CONFIG_ANON_INODES=y
64CONFIG_EPOLL=y 67CONFIG_EPOLL=y
65CONFIG_SIGNALFD=y 68CONFIG_SIGNALFD=y
66CONFIG_TIMERFD=y
67CONFIG_EVENTFD=y 69CONFIG_EVENTFD=y
68CONFIG_SHMEM=y 70CONFIG_SHMEM=y
69CONFIG_VM_EVENT_COUNTERS=y 71CONFIG_VM_EVENT_COUNTERS=y
@@ -83,6 +85,7 @@ CONFIG_STOP_MACHINE=y
83CONFIG_BLOCK=y 85CONFIG_BLOCK=y
84# CONFIG_BLK_DEV_IO_TRACE is not set 86# CONFIG_BLK_DEV_IO_TRACE is not set
85CONFIG_BLK_DEV_BSG=y 87CONFIG_BLK_DEV_BSG=y
88CONFIG_BLOCK_COMPAT=y
86 89
87# 90#
88# IO Schedulers 91# IO Schedulers
@@ -108,7 +111,6 @@ CONFIG_64BIT=y
108CONFIG_SMP=y 111CONFIG_SMP=y
109CONFIG_NR_CPUS=32 112CONFIG_NR_CPUS=32
110CONFIG_HOTPLUG_CPU=y 113CONFIG_HOTPLUG_CPU=y
111CONFIG_DEFAULT_MIGRATION_COST=1000000
112CONFIG_COMPAT=y 114CONFIG_COMPAT=y
113CONFIG_SYSVIPC_COMPAT=y 115CONFIG_SYSVIPC_COMPAT=y
114CONFIG_AUDIT_ARCH=y 116CONFIG_AUDIT_ARCH=y
@@ -143,9 +145,11 @@ CONFIG_FLATMEM_MANUAL=y
143CONFIG_FLATMEM=y 145CONFIG_FLATMEM=y
144CONFIG_FLAT_NODE_MEM_MAP=y 146CONFIG_FLAT_NODE_MEM_MAP=y
145# CONFIG_SPARSEMEM_STATIC is not set 147# CONFIG_SPARSEMEM_STATIC is not set
148# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
146CONFIG_SPLIT_PTLOCK_CPUS=4 149CONFIG_SPLIT_PTLOCK_CPUS=4
147CONFIG_RESOURCES_64BIT=y 150CONFIG_RESOURCES_64BIT=y
148CONFIG_ZONE_DMA_FLAG=1 151CONFIG_ZONE_DMA_FLAG=1
152CONFIG_BOUNCE=y
149CONFIG_VIRT_TO_BUS=y 153CONFIG_VIRT_TO_BUS=y
150CONFIG_HOLES_IN_ZONE=y 154CONFIG_HOLES_IN_ZONE=y
151 155
@@ -219,12 +223,14 @@ CONFIG_INET_TUNNEL=y
219CONFIG_INET_XFRM_MODE_TRANSPORT=y 223CONFIG_INET_XFRM_MODE_TRANSPORT=y
220CONFIG_INET_XFRM_MODE_TUNNEL=y 224CONFIG_INET_XFRM_MODE_TUNNEL=y
221CONFIG_INET_XFRM_MODE_BEET=y 225CONFIG_INET_XFRM_MODE_BEET=y
226CONFIG_INET_LRO=y
222CONFIG_INET_DIAG=y 227CONFIG_INET_DIAG=y
223CONFIG_INET_TCP_DIAG=y 228CONFIG_INET_TCP_DIAG=y
224# CONFIG_TCP_CONG_ADVANCED is not set 229# CONFIG_TCP_CONG_ADVANCED is not set
225CONFIG_TCP_CONG_CUBIC=y 230CONFIG_TCP_CONG_CUBIC=y
226CONFIG_DEFAULT_TCP_CONG="cubic" 231CONFIG_DEFAULT_TCP_CONG="cubic"
227# CONFIG_TCP_MD5SIG is not set 232# CONFIG_TCP_MD5SIG is not set
233# CONFIG_IP_VS is not set
228CONFIG_IPV6=y 234CONFIG_IPV6=y
229# CONFIG_IPV6_PRIVACY is not set 235# CONFIG_IPV6_PRIVACY is not set
230# CONFIG_IPV6_ROUTER_PREF is not set 236# CONFIG_IPV6_ROUTER_PREF is not set
@@ -243,7 +249,48 @@ CONFIG_IPV6_SIT=y
243# CONFIG_IPV6_TUNNEL is not set 249# CONFIG_IPV6_TUNNEL is not set
244# CONFIG_IPV6_MULTIPLE_TABLES is not set 250# CONFIG_IPV6_MULTIPLE_TABLES is not set
245# CONFIG_NETWORK_SECMARK is not set 251# CONFIG_NETWORK_SECMARK is not set
246# CONFIG_NETFILTER is not set 252CONFIG_NETFILTER=y
253# CONFIG_NETFILTER_DEBUG is not set
254
255#
256# Core Netfilter Configuration
257#
258CONFIG_NETFILTER_NETLINK=m
259CONFIG_NETFILTER_NETLINK_QUEUE=m
260CONFIG_NETFILTER_NETLINK_LOG=m
261CONFIG_NF_CONNTRACK_ENABLED=m
262CONFIG_NF_CONNTRACK=m
263# CONFIG_NF_CT_ACCT is not set
264# CONFIG_NF_CONNTRACK_MARK is not set
265# CONFIG_NF_CONNTRACK_EVENTS is not set
266# CONFIG_NF_CT_PROTO_SCTP is not set
267# CONFIG_NF_CT_PROTO_UDPLITE is not set
268# CONFIG_NF_CONNTRACK_AMANDA is not set
269# CONFIG_NF_CONNTRACK_FTP is not set
270# CONFIG_NF_CONNTRACK_H323 is not set
271# CONFIG_NF_CONNTRACK_IRC is not set
272# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
273# CONFIG_NF_CONNTRACK_PPTP is not set
274# CONFIG_NF_CONNTRACK_SANE is not set
275# CONFIG_NF_CONNTRACK_SIP is not set
276# CONFIG_NF_CONNTRACK_TFTP is not set
277# CONFIG_NF_CT_NETLINK is not set
278# CONFIG_NETFILTER_XTABLES is not set
279
280#
281# IP: Netfilter Configuration
282#
283# CONFIG_NF_CONNTRACK_IPV4 is not set
284# CONFIG_IP_NF_QUEUE is not set
285# CONFIG_IP_NF_IPTABLES is not set
286# CONFIG_IP_NF_ARPTABLES is not set
287
288#
289# IPv6: Netfilter Configuration (EXPERIMENTAL)
290#
291# CONFIG_NF_CONNTRACK_IPV6 is not set
292# CONFIG_IP6_NF_QUEUE is not set
293# CONFIG_IP6_NF_IPTABLES is not set
247# CONFIG_IP_DCCP is not set 294# CONFIG_IP_DCCP is not set
248CONFIG_IP_SCTP=m 295CONFIG_IP_SCTP=m
249# CONFIG_SCTP_DBG_MSG is not set 296# CONFIG_SCTP_DBG_MSG is not set
@@ -263,12 +310,7 @@ CONFIG_SCTP_HMAC_MD5=y
263# CONFIG_LAPB is not set 310# CONFIG_LAPB is not set
264# CONFIG_ECONET is not set 311# CONFIG_ECONET is not set
265# CONFIG_WAN_ROUTER is not set 312# CONFIG_WAN_ROUTER is not set
266
267#
268# QoS and/or fair queueing
269#
270CONFIG_NET_SCHED=y 313CONFIG_NET_SCHED=y
271CONFIG_NET_SCH_FIFO=y
272 314
273# 315#
274# Queueing/Scheduling 316# Queueing/Scheduling
@@ -306,10 +348,12 @@ CONFIG_NET_CLS_ACT=y
306CONFIG_NET_ACT_POLICE=y 348CONFIG_NET_ACT_POLICE=y
307# CONFIG_NET_ACT_GACT is not set 349# CONFIG_NET_ACT_GACT is not set
308# CONFIG_NET_ACT_MIRRED is not set 350# CONFIG_NET_ACT_MIRRED is not set
351CONFIG_NET_ACT_NAT=m
309# CONFIG_NET_ACT_PEDIT is not set 352# CONFIG_NET_ACT_PEDIT is not set
310# CONFIG_NET_ACT_SIMP is not set 353# CONFIG_NET_ACT_SIMP is not set
311CONFIG_NET_CLS_POLICE=y 354CONFIG_NET_CLS_POLICE=y
312# CONFIG_NET_CLS_IND is not set 355# CONFIG_NET_CLS_IND is not set
356CONFIG_NET_SCH_FIFO=y
313 357
314# 358#
315# Network testing 359# Network testing
@@ -329,6 +373,7 @@ CONFIG_CCW=y
329# 373#
330# Generic Driver Options 374# Generic Driver Options
331# 375#
376CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
332CONFIG_STANDALONE=y 377CONFIG_STANDALONE=y
333CONFIG_PREVENT_FIRMWARE_BUILD=y 378CONFIG_PREVENT_FIRMWARE_BUILD=y
334# CONFIG_FW_LOADER is not set 379# CONFIG_FW_LOADER is not set
@@ -400,17 +445,11 @@ CONFIG_SCSI_FC_ATTRS=y
400# CONFIG_SCSI_ISCSI_ATTRS is not set 445# CONFIG_SCSI_ISCSI_ATTRS is not set
401# CONFIG_SCSI_SAS_ATTRS is not set 446# CONFIG_SCSI_SAS_ATTRS is not set
402# CONFIG_SCSI_SAS_LIBSAS is not set 447# CONFIG_SCSI_SAS_LIBSAS is not set
403 448# CONFIG_SCSI_SRP_ATTRS is not set
404# 449CONFIG_SCSI_LOWLEVEL=y
405# SCSI low-level drivers
406#
407# CONFIG_ISCSI_TCP is not set 450# CONFIG_ISCSI_TCP is not set
408# CONFIG_SCSI_DEBUG is not set 451# CONFIG_SCSI_DEBUG is not set
409CONFIG_ZFCP=y 452CONFIG_ZFCP=y
410
411#
412# Multi-device support (RAID and LVM)
413#
414CONFIG_MD=y 453CONFIG_MD=y
415CONFIG_BLK_DEV_MD=y 454CONFIG_BLK_DEV_MD=y
416CONFIG_MD_LINEAR=m 455CONFIG_MD_LINEAR=m
@@ -429,7 +468,9 @@ CONFIG_DM_ZERO=y
429CONFIG_DM_MULTIPATH=y 468CONFIG_DM_MULTIPATH=y
430# CONFIG_DM_MULTIPATH_EMC is not set 469# CONFIG_DM_MULTIPATH_EMC is not set
431# CONFIG_DM_MULTIPATH_RDAC is not set 470# CONFIG_DM_MULTIPATH_RDAC is not set
471# CONFIG_DM_MULTIPATH_HP is not set
432# CONFIG_DM_DELAY is not set 472# CONFIG_DM_DELAY is not set
473# CONFIG_DM_UEVENT is not set
433CONFIG_NETDEVICES=y 474CONFIG_NETDEVICES=y
434# CONFIG_NETDEVICES_MULTIQUEUE is not set 475# CONFIG_NETDEVICES_MULTIQUEUE is not set
435# CONFIG_IFB is not set 476# CONFIG_IFB is not set
@@ -438,8 +479,13 @@ CONFIG_BONDING=m
438# CONFIG_MACVLAN is not set 479# CONFIG_MACVLAN is not set
439CONFIG_EQUALIZER=m 480CONFIG_EQUALIZER=m
440CONFIG_TUN=m 481CONFIG_TUN=m
482CONFIG_VETH=m
441CONFIG_NET_ETHERNET=y 483CONFIG_NET_ETHERNET=y
442# CONFIG_MII is not set 484# CONFIG_MII is not set
485# CONFIG_IBM_NEW_EMAC_ZMII is not set
486# CONFIG_IBM_NEW_EMAC_RGMII is not set
487# CONFIG_IBM_NEW_EMAC_TAH is not set
488# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
443CONFIG_NETDEV_1000=y 489CONFIG_NETDEV_1000=y
444CONFIG_NETDEV_10000=y 490CONFIG_NETDEV_10000=y
445# CONFIG_TR is not set 491# CONFIG_TR is not set
@@ -473,7 +519,6 @@ CONFIG_CCWGROUP=y
473CONFIG_UNIX98_PTYS=y 519CONFIG_UNIX98_PTYS=y
474CONFIG_LEGACY_PTYS=y 520CONFIG_LEGACY_PTYS=y
475CONFIG_LEGACY_PTY_COUNT=256 521CONFIG_LEGACY_PTY_COUNT=256
476# CONFIG_WATCHDOG is not set
477CONFIG_HW_RANDOM=m 522CONFIG_HW_RANDOM=m
478# CONFIG_R3964 is not set 523# CONFIG_R3964 is not set
479CONFIG_RAW_DRIVER=m 524CONFIG_RAW_DRIVER=m
@@ -490,7 +535,6 @@ CONFIG_TN3270_CONSOLE=y
490CONFIG_TN3215=y 535CONFIG_TN3215=y
491CONFIG_TN3215_CONSOLE=y 536CONFIG_TN3215_CONSOLE=y
492CONFIG_CCW_CONSOLE=y 537CONFIG_CCW_CONSOLE=y
493CONFIG_SCLP=y
494CONFIG_SCLP_TTY=y 538CONFIG_SCLP_TTY=y
495CONFIG_SCLP_CONSOLE=y 539CONFIG_SCLP_CONSOLE=y
496CONFIG_SCLP_VT220_TTY=y 540CONFIG_SCLP_VT220_TTY=y
@@ -514,6 +558,11 @@ CONFIG_S390_TAPE_34XX=m
514CONFIG_MONWRITER=m 558CONFIG_MONWRITER=m
515CONFIG_S390_VMUR=m 559CONFIG_S390_VMUR=m
516# CONFIG_POWER_SUPPLY is not set 560# CONFIG_POWER_SUPPLY is not set
561# CONFIG_WATCHDOG is not set
562
563#
564# Sonics Silicon Backplane
565#
517 566
518# 567#
519# File systems 568# File systems
@@ -569,7 +618,6 @@ CONFIG_SYSFS=y
569CONFIG_TMPFS=y 618CONFIG_TMPFS=y
570CONFIG_TMPFS_POSIX_ACL=y 619CONFIG_TMPFS_POSIX_ACL=y
571# CONFIG_HUGETLB_PAGE is not set 620# CONFIG_HUGETLB_PAGE is not set
572CONFIG_RAMFS=y
573CONFIG_CONFIGFS_FS=m 621CONFIG_CONFIGFS_FS=m
574 622
575# 623#
@@ -588,10 +636,7 @@ CONFIG_CONFIGFS_FS=m
588# CONFIG_QNX4FS_FS is not set 636# CONFIG_QNX4FS_FS is not set
589# CONFIG_SYSV_FS is not set 637# CONFIG_SYSV_FS is not set
590# CONFIG_UFS_FS is not set 638# CONFIG_UFS_FS is not set
591 639CONFIG_NETWORK_FILESYSTEMS=y
592#
593# Network File Systems
594#
595CONFIG_NFS_FS=y 640CONFIG_NFS_FS=y
596CONFIG_NFS_V3=y 641CONFIG_NFS_V3=y
597# CONFIG_NFS_V3_ACL is not set 642# CONFIG_NFS_V3_ACL is not set
@@ -638,27 +683,13 @@ CONFIG_MSDOS_PARTITION=y
638# CONFIG_KARMA_PARTITION is not set 683# CONFIG_KARMA_PARTITION is not set
639# CONFIG_EFI_PARTITION is not set 684# CONFIG_EFI_PARTITION is not set
640# CONFIG_SYSV68_PARTITION is not set 685# CONFIG_SYSV68_PARTITION is not set
641
642#
643# Native Language Support
644#
645# CONFIG_NLS is not set 686# CONFIG_NLS is not set
646
647#
648# Distributed Lock Manager
649#
650CONFIG_DLM=m 687CONFIG_DLM=m
651# CONFIG_DLM_DEBUG is not set 688# CONFIG_DLM_DEBUG is not set
652 689CONFIG_INSTRUMENTATION=y
653#
654# Instrumentation Support
655#
656
657#
658# Profiling support
659#
660# CONFIG_PROFILING is not set 690# CONFIG_PROFILING is not set
661CONFIG_KPROBES=y 691CONFIG_KPROBES=y
692# CONFIG_MARKERS is not set
662 693
663# 694#
664# Kernel hacking 695# Kernel hacking
@@ -682,6 +713,7 @@ CONFIG_DEBUG_SPINLOCK=y
682CONFIG_DEBUG_MUTEXES=y 713CONFIG_DEBUG_MUTEXES=y
683# CONFIG_DEBUG_LOCK_ALLOC is not set 714# CONFIG_DEBUG_LOCK_ALLOC is not set
684# CONFIG_PROVE_LOCKING is not set 715# CONFIG_PROVE_LOCKING is not set
716# CONFIG_LOCK_STAT is not set
685CONFIG_DEBUG_SPINLOCK_SLEEP=y 717CONFIG_DEBUG_SPINLOCK_SLEEP=y
686# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set 718# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
687# CONFIG_DEBUG_KOBJECT is not set 719# CONFIG_DEBUG_KOBJECT is not set
@@ -694,14 +726,17 @@ CONFIG_FORCED_INLINING=y
694# CONFIG_RCU_TORTURE_TEST is not set 726# CONFIG_RCU_TORTURE_TEST is not set
695# CONFIG_LKDTM is not set 727# CONFIG_LKDTM is not set
696# CONFIG_FAULT_INJECTION is not set 728# CONFIG_FAULT_INJECTION is not set
729CONFIG_SAMPLES=y
697 730
698# 731#
699# Security options 732# Security options
700# 733#
701# CONFIG_KEYS is not set 734# CONFIG_KEYS is not set
702# CONFIG_SECURITY is not set 735# CONFIG_SECURITY is not set
736# CONFIG_SECURITY_FILE_CAPABILITIES is not set
703CONFIG_CRYPTO=y 737CONFIG_CRYPTO=y
704CONFIG_CRYPTO_ALGAPI=y 738CONFIG_CRYPTO_ALGAPI=y
739CONFIG_CRYPTO_AEAD=m
705CONFIG_CRYPTO_BLKCIPHER=y 740CONFIG_CRYPTO_BLKCIPHER=y
706CONFIG_CRYPTO_HASH=m 741CONFIG_CRYPTO_HASH=m
707CONFIG_CRYPTO_MANAGER=y 742CONFIG_CRYPTO_MANAGER=y
@@ -720,6 +755,7 @@ CONFIG_CRYPTO_ECB=m
720CONFIG_CRYPTO_CBC=y 755CONFIG_CRYPTO_CBC=y
721CONFIG_CRYPTO_PCBC=m 756CONFIG_CRYPTO_PCBC=m
722# CONFIG_CRYPTO_LRW is not set 757# CONFIG_CRYPTO_LRW is not set
758# CONFIG_CRYPTO_XTS is not set
723# CONFIG_CRYPTO_CRYPTD is not set 759# CONFIG_CRYPTO_CRYPTD is not set
724# CONFIG_CRYPTO_DES is not set 760# CONFIG_CRYPTO_DES is not set
725CONFIG_CRYPTO_FCRYPT=m 761CONFIG_CRYPTO_FCRYPT=m
@@ -733,11 +769,13 @@ CONFIG_CRYPTO_FCRYPT=m
733# CONFIG_CRYPTO_ARC4 is not set 769# CONFIG_CRYPTO_ARC4 is not set
734# CONFIG_CRYPTO_KHAZAD is not set 770# CONFIG_CRYPTO_KHAZAD is not set
735# CONFIG_CRYPTO_ANUBIS is not set 771# CONFIG_CRYPTO_ANUBIS is not set
772CONFIG_CRYPTO_SEED=m
736# CONFIG_CRYPTO_DEFLATE is not set 773# CONFIG_CRYPTO_DEFLATE is not set
737# CONFIG_CRYPTO_MICHAEL_MIC is not set 774# CONFIG_CRYPTO_MICHAEL_MIC is not set
738# CONFIG_CRYPTO_CRC32C is not set 775# CONFIG_CRYPTO_CRC32C is not set
739CONFIG_CRYPTO_CAMELLIA=m 776CONFIG_CRYPTO_CAMELLIA=m
740# CONFIG_CRYPTO_TEST is not set 777# CONFIG_CRYPTO_TEST is not set
778CONFIG_CRYPTO_AUTHENC=m
741CONFIG_CRYPTO_HW=y 779CONFIG_CRYPTO_HW=y
742# CONFIG_CRYPTO_SHA1_S390 is not set 780# CONFIG_CRYPTO_SHA1_S390 is not set
743# CONFIG_CRYPTO_SHA256_S390 is not set 781# CONFIG_CRYPTO_SHA256_S390 is not set
@@ -755,5 +793,6 @@ CONFIG_BITREVERSE=m
755# CONFIG_CRC16 is not set 793# CONFIG_CRC16 is not set
756# CONFIG_CRC_ITU_T is not set 794# CONFIG_CRC_ITU_T is not set
757CONFIG_CRC32=m 795CONFIG_CRC32=m
796CONFIG_CRC7=m
758# CONFIG_LIBCRC32C is not set 797# CONFIG_LIBCRC32C is not set
759CONFIG_PLIST=y 798CONFIG_PLIST=y
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 66b51901c87d..ce0856d32500 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -648,6 +648,8 @@ static int dump_set_type(enum dump_type type)
648 case DUMP_TYPE_CCW: 648 case DUMP_TYPE_CCW:
649 if (MACHINE_IS_VM) 649 if (MACHINE_IS_VM)
650 dump_method = DUMP_METHOD_CCW_VM; 650 dump_method = DUMP_METHOD_CCW_VM;
651 else if (diag308_set_works)
652 dump_method = DUMP_METHOD_CCW_DIAG;
651 else 653 else
652 dump_method = DUMP_METHOD_CCW_CIO; 654 dump_method = DUMP_METHOD_CCW_CIO;
653 break; 655 break;
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index 70c57378f426..96492cf2d491 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -44,6 +44,7 @@
44#include <asm/processor.h> 44#include <asm/processor.h>
45#include <asm/irq.h> 45#include <asm/irq.h>
46#include <asm/timer.h> 46#include <asm/timer.h>
47#include <asm/cpu.h>
47 48
48asmlinkage void ret_from_fork(void) asm ("ret_from_fork"); 49asmlinkage void ret_from_fork(void) asm ("ret_from_fork");
49 50
@@ -91,6 +92,14 @@ EXPORT_SYMBOL(unregister_idle_notifier);
91 92
92void do_monitor_call(struct pt_regs *regs, long interruption_code) 93void do_monitor_call(struct pt_regs *regs, long interruption_code)
93{ 94{
95 struct s390_idle_data *idle;
96
97 idle = &__get_cpu_var(s390_idle);
98 spin_lock(&idle->lock);
99 idle->idle_time += get_clock() - idle->idle_enter;
100 idle->in_idle = 0;
101 spin_unlock(&idle->lock);
102
94 /* disable monitor call class 0 */ 103 /* disable monitor call class 0 */
95 __ctl_clear_bit(8, 15); 104 __ctl_clear_bit(8, 15);
96 105
@@ -105,6 +114,7 @@ extern void s390_handle_mcck(void);
105static void default_idle(void) 114static void default_idle(void)
106{ 115{
107 int cpu, rc; 116 int cpu, rc;
117 struct s390_idle_data *idle;
108 118
109 /* CPU is going idle. */ 119 /* CPU is going idle. */
110 cpu = smp_processor_id(); 120 cpu = smp_processor_id();
@@ -142,6 +152,12 @@ static void default_idle(void)
142 return; 152 return;
143 } 153 }
144 154
155 idle = &__get_cpu_var(s390_idle);
156 spin_lock(&idle->lock);
157 idle->idle_count++;
158 idle->in_idle = 1;
159 idle->idle_enter = get_clock();
160 spin_unlock(&idle->lock);
145 trace_hardirqs_on(); 161 trace_hardirqs_on();
146 /* Wait for external, I/O or machine check interrupt. */ 162 /* Wait for external, I/O or machine check interrupt. */
147 __load_psw_mask(psw_kernel_bits | PSW_MASK_WAIT | 163 __load_psw_mask(psw_kernel_bits | PSW_MASK_WAIT |
@@ -254,14 +270,12 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp,
254 save_fp_regs(&current->thread.fp_regs); 270 save_fp_regs(&current->thread.fp_regs);
255 memcpy(&p->thread.fp_regs, &current->thread.fp_regs, 271 memcpy(&p->thread.fp_regs, &current->thread.fp_regs,
256 sizeof(s390_fp_regs)); 272 sizeof(s390_fp_regs));
257 p->thread.user_seg = __pa((unsigned long) p->mm->pgd) | _SEGMENT_TABLE;
258 /* Set a new TLS ? */ 273 /* Set a new TLS ? */
259 if (clone_flags & CLONE_SETTLS) 274 if (clone_flags & CLONE_SETTLS)
260 p->thread.acrs[0] = regs->gprs[6]; 275 p->thread.acrs[0] = regs->gprs[6];
261#else /* CONFIG_64BIT */ 276#else /* CONFIG_64BIT */
262 /* Save the fpu registers to new thread structure. */ 277 /* Save the fpu registers to new thread structure. */
263 save_fp_regs(&p->thread.fp_regs); 278 save_fp_regs(&p->thread.fp_regs);
264 p->thread.user_seg = __pa((unsigned long) p->mm->pgd) | _REGION_TABLE;
265 /* Set a new TLS ? */ 279 /* Set a new TLS ? */
266 if (clone_flags & CLONE_SETTLS) { 280 if (clone_flags & CLONE_SETTLS) {
267 if (test_thread_flag(TIF_31BIT)) { 281 if (test_thread_flag(TIF_31BIT)) {
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 35edbef1d222..1d97fe1c0e53 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -42,6 +42,7 @@
42#include <asm/tlbflush.h> 42#include <asm/tlbflush.h>
43#include <asm/timer.h> 43#include <asm/timer.h>
44#include <asm/lowcore.h> 44#include <asm/lowcore.h>
45#include <asm/cpu.h>
45 46
46/* 47/*
47 * An array with a pointer the lowcore of every CPU. 48 * An array with a pointer the lowcore of every CPU.
@@ -325,7 +326,7 @@ static void smp_ext_bitcall(int cpu, ec_bit_sig sig)
325 */ 326 */
326void smp_ptlb_callback(void *info) 327void smp_ptlb_callback(void *info)
327{ 328{
328 local_flush_tlb(); 329 __tlb_flush_local();
329} 330}
330 331
331void smp_ptlb_all(void) 332void smp_ptlb_all(void)
@@ -494,6 +495,8 @@ int __cpuinit start_secondary(void *cpuvoid)
494 return 0; 495 return 0;
495} 496}
496 497
498DEFINE_PER_CPU(struct s390_idle_data, s390_idle);
499
497static void __init smp_create_idle(unsigned int cpu) 500static void __init smp_create_idle(unsigned int cpu)
498{ 501{
499 struct task_struct *p; 502 struct task_struct *p;
@@ -506,6 +509,7 @@ static void __init smp_create_idle(unsigned int cpu)
506 if (IS_ERR(p)) 509 if (IS_ERR(p))
507 panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p)); 510 panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p));
508 current_set[cpu] = p; 511 current_set[cpu] = p;
512 spin_lock_init(&(&per_cpu(s390_idle, cpu))->lock);
509} 513}
510 514
511static int cpu_stopped(int cpu) 515static int cpu_stopped(int cpu)
@@ -724,6 +728,7 @@ void __init smp_prepare_boot_cpu(void)
724 cpu_set(0, cpu_online_map); 728 cpu_set(0, cpu_online_map);
725 S390_lowcore.percpu_offset = __per_cpu_offset[0]; 729 S390_lowcore.percpu_offset = __per_cpu_offset[0];
726 current_set[0] = current; 730 current_set[0] = current;
731 spin_lock_init(&(&__get_cpu_var(s390_idle))->lock);
727} 732}
728 733
729void __init smp_cpus_done(unsigned int max_cpus) 734void __init smp_cpus_done(unsigned int max_cpus)
@@ -756,22 +761,71 @@ static ssize_t show_capability(struct sys_device *dev, char *buf)
756} 761}
757static SYSDEV_ATTR(capability, 0444, show_capability, NULL); 762static SYSDEV_ATTR(capability, 0444, show_capability, NULL);
758 763
764static ssize_t show_idle_count(struct sys_device *dev, char *buf)
765{
766 struct s390_idle_data *idle;
767 unsigned long long idle_count;
768
769 idle = &per_cpu(s390_idle, dev->id);
770 spin_lock_irq(&idle->lock);
771 idle_count = idle->idle_count;
772 spin_unlock_irq(&idle->lock);
773 return sprintf(buf, "%llu\n", idle_count);
774}
775static SYSDEV_ATTR(idle_count, 0444, show_idle_count, NULL);
776
777static ssize_t show_idle_time(struct sys_device *dev, char *buf)
778{
779 struct s390_idle_data *idle;
780 unsigned long long new_time;
781
782 idle = &per_cpu(s390_idle, dev->id);
783 spin_lock_irq(&idle->lock);
784 if (idle->in_idle) {
785 new_time = get_clock();
786 idle->idle_time += new_time - idle->idle_enter;
787 idle->idle_enter = new_time;
788 }
789 new_time = idle->idle_time;
790 spin_unlock_irq(&idle->lock);
791 return sprintf(buf, "%llu us\n", new_time >> 12);
792}
793static SYSDEV_ATTR(idle_time, 0444, show_idle_time, NULL);
794
795static struct attribute *cpu_attrs[] = {
796 &attr_capability.attr,
797 &attr_idle_count.attr,
798 &attr_idle_time.attr,
799 NULL,
800};
801
802static struct attribute_group cpu_attr_group = {
803 .attrs = cpu_attrs,
804};
805
759static int __cpuinit smp_cpu_notify(struct notifier_block *self, 806static int __cpuinit smp_cpu_notify(struct notifier_block *self,
760 unsigned long action, void *hcpu) 807 unsigned long action, void *hcpu)
761{ 808{
762 unsigned int cpu = (unsigned int)(long)hcpu; 809 unsigned int cpu = (unsigned int)(long)hcpu;
763 struct cpu *c = &per_cpu(cpu_devices, cpu); 810 struct cpu *c = &per_cpu(cpu_devices, cpu);
764 struct sys_device *s = &c->sysdev; 811 struct sys_device *s = &c->sysdev;
812 struct s390_idle_data *idle;
765 813
766 switch (action) { 814 switch (action) {
767 case CPU_ONLINE: 815 case CPU_ONLINE:
768 case CPU_ONLINE_FROZEN: 816 case CPU_ONLINE_FROZEN:
769 if (sysdev_create_file(s, &attr_capability)) 817 idle = &per_cpu(s390_idle, cpu);
818 spin_lock_irq(&idle->lock);
819 idle->idle_enter = 0;
820 idle->idle_time = 0;
821 idle->idle_count = 0;
822 spin_unlock_irq(&idle->lock);
823 if (sysfs_create_group(&s->kobj, &cpu_attr_group))
770 return NOTIFY_BAD; 824 return NOTIFY_BAD;
771 break; 825 break;
772 case CPU_DEAD: 826 case CPU_DEAD:
773 case CPU_DEAD_FROZEN: 827 case CPU_DEAD_FROZEN:
774 sysdev_remove_file(s, &attr_capability); 828 sysfs_remove_group(&s->kobj, &cpu_attr_group);
775 break; 829 break;
776 } 830 }
777 return NOTIFY_OK; 831 return NOTIFY_OK;
@@ -784,6 +838,7 @@ static struct notifier_block __cpuinitdata smp_cpu_nb = {
784static int __init topology_init(void) 838static int __init topology_init(void)
785{ 839{
786 int cpu; 840 int cpu;
841 int rc;
787 842
788 register_cpu_notifier(&smp_cpu_nb); 843 register_cpu_notifier(&smp_cpu_nb);
789 844
@@ -796,7 +851,9 @@ static int __init topology_init(void)
796 if (!cpu_online(cpu)) 851 if (!cpu_online(cpu))
797 continue; 852 continue;
798 s = &c->sysdev; 853 s = &c->sysdev;
799 sysdev_create_file(s, &attr_capability); 854 rc = sysfs_create_group(&s->kobj, &cpu_attr_group);
855 if (rc)
856 return rc;
800 } 857 }
801 return 0; 858 return 0;
802} 859}
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c
index b159a9d65680..7e8efaade2ea 100644
--- a/arch/s390/lib/uaccess_pt.c
+++ b/arch/s390/lib/uaccess_pt.c
@@ -15,6 +15,27 @@
15#include <asm/futex.h> 15#include <asm/futex.h>
16#include "uaccess.h" 16#include "uaccess.h"
17 17
18static inline pte_t *follow_table(struct mm_struct *mm, unsigned long addr)
19{
20 pgd_t *pgd;
21 pud_t *pud;
22 pmd_t *pmd;
23
24 pgd = pgd_offset(mm, addr);
25 if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
26 return NULL;
27
28 pud = pud_offset(pgd, addr);
29 if (pud_none(*pud) || unlikely(pud_bad(*pud)))
30 return NULL;
31
32 pmd = pmd_offset(pud, addr);
33 if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
34 return NULL;
35
36 return pte_offset_map(pmd, addr);
37}
38
18static int __handle_fault(struct mm_struct *mm, unsigned long address, 39static int __handle_fault(struct mm_struct *mm, unsigned long address,
19 int write_access) 40 int write_access)
20{ 41{
@@ -85,8 +106,6 @@ static size_t __user_copy_pt(unsigned long uaddr, void *kptr,
85{ 106{
86 struct mm_struct *mm = current->mm; 107 struct mm_struct *mm = current->mm;
87 unsigned long offset, pfn, done, size; 108 unsigned long offset, pfn, done, size;
88 pgd_t *pgd;
89 pmd_t *pmd;
90 pte_t *pte; 109 pte_t *pte;
91 void *from, *to; 110 void *from, *to;
92 111
@@ -94,15 +113,7 @@ static size_t __user_copy_pt(unsigned long uaddr, void *kptr,
94retry: 113retry:
95 spin_lock(&mm->page_table_lock); 114 spin_lock(&mm->page_table_lock);
96 do { 115 do {
97 pgd = pgd_offset(mm, uaddr); 116 pte = follow_table(mm, uaddr);
98 if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
99 goto fault;
100
101 pmd = pmd_offset(pgd, uaddr);
102 if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
103 goto fault;
104
105 pte = pte_offset_map(pmd, uaddr);
106 if (!pte || !pte_present(*pte) || 117 if (!pte || !pte_present(*pte) ||
107 (write_user && !pte_write(*pte))) 118 (write_user && !pte_write(*pte)))
108 goto fault; 119 goto fault;
@@ -142,22 +153,12 @@ static unsigned long __dat_user_addr(unsigned long uaddr)
142{ 153{
143 struct mm_struct *mm = current->mm; 154 struct mm_struct *mm = current->mm;
144 unsigned long pfn, ret; 155 unsigned long pfn, ret;
145 pgd_t *pgd;
146 pmd_t *pmd;
147 pte_t *pte; 156 pte_t *pte;
148 int rc; 157 int rc;
149 158
150 ret = 0; 159 ret = 0;
151retry: 160retry:
152 pgd = pgd_offset(mm, uaddr); 161 pte = follow_table(mm, uaddr);
153 if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
154 goto fault;
155
156 pmd = pmd_offset(pgd, uaddr);
157 if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
158 goto fault;
159
160 pte = pte_offset_map(pmd, uaddr);
161 if (!pte || !pte_present(*pte)) 162 if (!pte || !pte_present(*pte))
162 goto fault; 163 goto fault;
163 164
@@ -229,8 +230,6 @@ static size_t strnlen_user_pt(size_t count, const char __user *src)
229 unsigned long uaddr = (unsigned long) src; 230 unsigned long uaddr = (unsigned long) src;
230 struct mm_struct *mm = current->mm; 231 struct mm_struct *mm = current->mm;
231 unsigned long offset, pfn, done, len; 232 unsigned long offset, pfn, done, len;
232 pgd_t *pgd;
233 pmd_t *pmd;
234 pte_t *pte; 233 pte_t *pte;
235 size_t len_str; 234 size_t len_str;
236 235
@@ -240,15 +239,7 @@ static size_t strnlen_user_pt(size_t count, const char __user *src)
240retry: 239retry:
241 spin_lock(&mm->page_table_lock); 240 spin_lock(&mm->page_table_lock);
242 do { 241 do {
243 pgd = pgd_offset(mm, uaddr); 242 pte = follow_table(mm, uaddr);
244 if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
245 goto fault;
246
247 pmd = pmd_offset(pgd, uaddr);
248 if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
249 goto fault;
250
251 pte = pte_offset_map(pmd, uaddr);
252 if (!pte || !pte_present(*pte)) 243 if (!pte || !pte_present(*pte))
253 goto fault; 244 goto fault;
254 245
@@ -308,8 +299,6 @@ static size_t copy_in_user_pt(size_t n, void __user *to,
308 uaddr, done, size; 299 uaddr, done, size;
309 unsigned long uaddr_from = (unsigned long) from; 300 unsigned long uaddr_from = (unsigned long) from;
310 unsigned long uaddr_to = (unsigned long) to; 301 unsigned long uaddr_to = (unsigned long) to;
311 pgd_t *pgd_from, *pgd_to;
312 pmd_t *pmd_from, *pmd_to;
313 pte_t *pte_from, *pte_to; 302 pte_t *pte_from, *pte_to;
314 int write_user; 303 int write_user;
315 304
@@ -317,39 +306,14 @@ static size_t copy_in_user_pt(size_t n, void __user *to,
317retry: 306retry:
318 spin_lock(&mm->page_table_lock); 307 spin_lock(&mm->page_table_lock);
319 do { 308 do {
320 pgd_from = pgd_offset(mm, uaddr_from); 309 pte_from = follow_table(mm, uaddr_from);
321 if (pgd_none(*pgd_from) || unlikely(pgd_bad(*pgd_from))) {
322 uaddr = uaddr_from;
323 write_user = 0;
324 goto fault;
325 }
326 pgd_to = pgd_offset(mm, uaddr_to);
327 if (pgd_none(*pgd_to) || unlikely(pgd_bad(*pgd_to))) {
328 uaddr = uaddr_to;
329 write_user = 1;
330 goto fault;
331 }
332
333 pmd_from = pmd_offset(pgd_from, uaddr_from);
334 if (pmd_none(*pmd_from) || unlikely(pmd_bad(*pmd_from))) {
335 uaddr = uaddr_from;
336 write_user = 0;
337 goto fault;
338 }
339 pmd_to = pmd_offset(pgd_to, uaddr_to);
340 if (pmd_none(*pmd_to) || unlikely(pmd_bad(*pmd_to))) {
341 uaddr = uaddr_to;
342 write_user = 1;
343 goto fault;
344 }
345
346 pte_from = pte_offset_map(pmd_from, uaddr_from);
347 if (!pte_from || !pte_present(*pte_from)) { 310 if (!pte_from || !pte_present(*pte_from)) {
348 uaddr = uaddr_from; 311 uaddr = uaddr_from;
349 write_user = 0; 312 write_user = 0;
350 goto fault; 313 goto fault;
351 } 314 }
352 pte_to = pte_offset_map(pmd_to, uaddr_to); 315
316 pte_to = follow_table(mm, uaddr_to);
353 if (!pte_to || !pte_present(*pte_to) || !pte_write(*pte_to)) { 317 if (!pte_to || !pte_present(*pte_to) || !pte_write(*pte_to)) {
354 uaddr = uaddr_to; 318 uaddr = uaddr_to;
355 write_user = 1; 319 write_user = 1;
diff --git a/arch/s390/mm/Makefile b/arch/s390/mm/Makefile
index f95449b29fa5..66401930f83e 100644
--- a/arch/s390/mm/Makefile
+++ b/arch/s390/mm/Makefile
@@ -2,6 +2,6 @@
2# Makefile for the linux s390-specific parts of the memory manager. 2# Makefile for the linux s390-specific parts of the memory manager.
3# 3#
4 4
5obj-y := init.o fault.o extmem.o mmap.o vmem.o 5obj-y := init.o fault.o extmem.o mmap.o vmem.o pgtable.o
6obj-$(CONFIG_CMM) += cmm.o 6obj-$(CONFIG_CMM) += cmm.o
7 7
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index 3a25bbf2eb0a..b234bb4a6da7 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -81,6 +81,7 @@ void show_mem(void)
81static void __init setup_ro_region(void) 81static void __init setup_ro_region(void)
82{ 82{
83 pgd_t *pgd; 83 pgd_t *pgd;
84 pud_t *pud;
84 pmd_t *pmd; 85 pmd_t *pmd;
85 pte_t *pte; 86 pte_t *pte;
86 pte_t new_pte; 87 pte_t new_pte;
@@ -91,7 +92,8 @@ static void __init setup_ro_region(void)
91 92
92 for (; address < end; address += PAGE_SIZE) { 93 for (; address < end; address += PAGE_SIZE) {
93 pgd = pgd_offset_k(address); 94 pgd = pgd_offset_k(address);
94 pmd = pmd_offset(pgd, address); 95 pud = pud_offset(pgd, address);
96 pmd = pmd_offset(pud, address);
95 pte = pte_offset_kernel(pmd, address); 97 pte = pte_offset_kernel(pmd, address);
96 new_pte = mk_pte_phys(address, __pgprot(_PAGE_RO)); 98 new_pte = mk_pte_phys(address, __pgprot(_PAGE_RO));
97 *pte = new_pte; 99 *pte = new_pte;
@@ -103,32 +105,28 @@ static void __init setup_ro_region(void)
103 */ 105 */
104void __init paging_init(void) 106void __init paging_init(void)
105{ 107{
106 pgd_t *pg_dir;
107 int i;
108 unsigned long pgdir_k;
109 static const int ssm_mask = 0x04000000L; 108 static const int ssm_mask = 0x04000000L;
110 unsigned long max_zone_pfns[MAX_NR_ZONES]; 109 unsigned long max_zone_pfns[MAX_NR_ZONES];
110 unsigned long pgd_type;
111 111
112 pg_dir = swapper_pg_dir; 112 init_mm.pgd = swapper_pg_dir;
113 113 S390_lowcore.kernel_asce = __pa(init_mm.pgd) & PAGE_MASK;
114#ifdef CONFIG_64BIT 114#ifdef CONFIG_64BIT
115 pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | _KERN_REGION_TABLE; 115 S390_lowcore.kernel_asce |= _ASCE_TYPE_REGION3 | _ASCE_TABLE_LENGTH;
116 for (i = 0; i < PTRS_PER_PGD; i++) 116 pgd_type = _REGION3_ENTRY_EMPTY;
117 pgd_clear_kernel(pg_dir + i);
118#else 117#else
119 pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | _KERNSEG_TABLE; 118 S390_lowcore.kernel_asce |= _ASCE_TABLE_LENGTH;
120 for (i = 0; i < PTRS_PER_PGD; i++) 119 pgd_type = _SEGMENT_ENTRY_EMPTY;
121 pmd_clear_kernel((pmd_t *)(pg_dir + i));
122#endif 120#endif
121 clear_table((unsigned long *) init_mm.pgd, pgd_type,
122 sizeof(unsigned long)*2048);
123 vmem_map_init(); 123 vmem_map_init();
124 setup_ro_region(); 124 setup_ro_region();
125 125
126 S390_lowcore.kernel_asce = pgdir_k;
127
128 /* enable virtual mapping in kernel mode */ 126 /* enable virtual mapping in kernel mode */
129 __ctl_load(pgdir_k, 1, 1); 127 __ctl_load(S390_lowcore.kernel_asce, 1, 1);
130 __ctl_load(pgdir_k, 7, 7); 128 __ctl_load(S390_lowcore.kernel_asce, 7, 7);
131 __ctl_load(pgdir_k, 13, 13); 129 __ctl_load(S390_lowcore.kernel_asce, 13, 13);
132 __raw_local_irq_ssm(ssm_mask); 130 __raw_local_irq_ssm(ssm_mask);
133 131
134 memset(max_zone_pfns, 0, sizeof(max_zone_pfns)); 132 memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
new file mode 100644
index 000000000000..e60e0ae13402
--- /dev/null
+++ b/arch/s390/mm/pgtable.c
@@ -0,0 +1,94 @@
1/*
2 * arch/s390/mm/pgtable.c
3 *
4 * Copyright IBM Corp. 2007
5 * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
6 */
7
8#include <linux/sched.h>
9#include <linux/kernel.h>
10#include <linux/errno.h>
11#include <linux/mm.h>
12#include <linux/swap.h>
13#include <linux/smp.h>
14#include <linux/highmem.h>
15#include <linux/slab.h>
16#include <linux/pagemap.h>
17#include <linux/spinlock.h>
18#include <linux/module.h>
19#include <linux/quicklist.h>
20
21#include <asm/system.h>
22#include <asm/pgtable.h>
23#include <asm/pgalloc.h>
24#include <asm/tlb.h>
25#include <asm/tlbflush.h>
26
27#ifndef CONFIG_64BIT
28#define ALLOC_ORDER 1
29#else
30#define ALLOC_ORDER 2
31#endif
32
33unsigned long *crst_table_alloc(struct mm_struct *mm, int noexec)
34{
35 struct page *page = alloc_pages(GFP_KERNEL, ALLOC_ORDER);
36
37 if (!page)
38 return NULL;
39 page->index = 0;
40 if (noexec) {
41 struct page *shadow = alloc_pages(GFP_KERNEL, ALLOC_ORDER);
42 if (!shadow) {
43 __free_pages(page, ALLOC_ORDER);
44 return NULL;
45 }
46 page->index = page_to_phys(shadow);
47 }
48 return (unsigned long *) page_to_phys(page);
49}
50
51void crst_table_free(unsigned long *table)
52{
53 unsigned long *shadow = get_shadow_table(table);
54
55 if (shadow)
56 free_pages((unsigned long) shadow, ALLOC_ORDER);
57 free_pages((unsigned long) table, ALLOC_ORDER);
58}
59
60/*
61 * page table entry allocation/free routines.
62 */
63unsigned long *page_table_alloc(int noexec)
64{
65 struct page *page = alloc_page(GFP_KERNEL);
66 unsigned long *table;
67
68 if (!page)
69 return NULL;
70 page->index = 0;
71 if (noexec) {
72 struct page *shadow = alloc_page(GFP_KERNEL);
73 if (!shadow) {
74 __free_page(page);
75 return NULL;
76 }
77 table = (unsigned long *) page_to_phys(shadow);
78 clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE);
79 page->index = (addr_t) table;
80 }
81 table = (unsigned long *) page_to_phys(page);
82 clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE);
83 return table;
84}
85
86void page_table_free(unsigned long *table)
87{
88 unsigned long *shadow = get_shadow_pte(table);
89
90 if (shadow)
91 free_page((unsigned long) shadow);
92 free_page((unsigned long) table);
93
94}
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
index fd594d5fe142..fb9c5a85aa56 100644
--- a/arch/s390/mm/vmem.c
+++ b/arch/s390/mm/vmem.c
@@ -73,31 +73,28 @@ static void __init_refok *vmem_alloc_pages(unsigned int order)
73 return alloc_bootmem_pages((1 << order) * PAGE_SIZE); 73 return alloc_bootmem_pages((1 << order) * PAGE_SIZE);
74} 74}
75 75
76#define vmem_pud_alloc() ({ BUG(); ((pud_t *) NULL); })
77
76static inline pmd_t *vmem_pmd_alloc(void) 78static inline pmd_t *vmem_pmd_alloc(void)
77{ 79{
78 pmd_t *pmd; 80 pmd_t *pmd = NULL;
79 int i;
80 81
81 pmd = vmem_alloc_pages(PMD_ALLOC_ORDER); 82#ifdef CONFIG_64BIT
83 pmd = vmem_alloc_pages(2);
82 if (!pmd) 84 if (!pmd)
83 return NULL; 85 return NULL;
84 for (i = 0; i < PTRS_PER_PMD; i++) 86 clear_table((unsigned long *) pmd, _SEGMENT_ENTRY_EMPTY, PAGE_SIZE*4);
85 pmd_clear_kernel(pmd + i); 87#endif
86 return pmd; 88 return pmd;
87} 89}
88 90
89static inline pte_t *vmem_pte_alloc(void) 91static inline pte_t *vmem_pte_alloc(void)
90{ 92{
91 pte_t *pte; 93 pte_t *pte = vmem_alloc_pages(0);
92 pte_t empty_pte;
93 int i;
94 94
95 pte = vmem_alloc_pages(PTE_ALLOC_ORDER);
96 if (!pte) 95 if (!pte)
97 return NULL; 96 return NULL;
98 pte_val(empty_pte) = _PAGE_TYPE_EMPTY; 97 clear_table((unsigned long *) pte, _PAGE_TYPE_EMPTY, PAGE_SIZE);
99 for (i = 0; i < PTRS_PER_PTE; i++)
100 pte[i] = empty_pte;
101 return pte; 98 return pte;
102} 99}
103 100
@@ -108,6 +105,7 @@ static int vmem_add_range(unsigned long start, unsigned long size)
108{ 105{
109 unsigned long address; 106 unsigned long address;
110 pgd_t *pg_dir; 107 pgd_t *pg_dir;
108 pud_t *pu_dir;
111 pmd_t *pm_dir; 109 pmd_t *pm_dir;
112 pte_t *pt_dir; 110 pte_t *pt_dir;
113 pte_t pte; 111 pte_t pte;
@@ -116,13 +114,21 @@ static int vmem_add_range(unsigned long start, unsigned long size)
116 for (address = start; address < start + size; address += PAGE_SIZE) { 114 for (address = start; address < start + size; address += PAGE_SIZE) {
117 pg_dir = pgd_offset_k(address); 115 pg_dir = pgd_offset_k(address);
118 if (pgd_none(*pg_dir)) { 116 if (pgd_none(*pg_dir)) {
117 pu_dir = vmem_pud_alloc();
118 if (!pu_dir)
119 goto out;
120 pgd_populate_kernel(&init_mm, pg_dir, pu_dir);
121 }
122
123 pu_dir = pud_offset(pg_dir, address);
124 if (pud_none(*pu_dir)) {
119 pm_dir = vmem_pmd_alloc(); 125 pm_dir = vmem_pmd_alloc();
120 if (!pm_dir) 126 if (!pm_dir)
121 goto out; 127 goto out;
122 pgd_populate_kernel(&init_mm, pg_dir, pm_dir); 128 pud_populate_kernel(&init_mm, pu_dir, pm_dir);
123 } 129 }
124 130
125 pm_dir = pmd_offset(pg_dir, address); 131 pm_dir = pmd_offset(pu_dir, address);
126 if (pmd_none(*pm_dir)) { 132 if (pmd_none(*pm_dir)) {
127 pt_dir = vmem_pte_alloc(); 133 pt_dir = vmem_pte_alloc();
128 if (!pt_dir) 134 if (!pt_dir)
@@ -148,6 +154,7 @@ static void vmem_remove_range(unsigned long start, unsigned long size)
148{ 154{
149 unsigned long address; 155 unsigned long address;
150 pgd_t *pg_dir; 156 pgd_t *pg_dir;
157 pud_t *pu_dir;
151 pmd_t *pm_dir; 158 pmd_t *pm_dir;
152 pte_t *pt_dir; 159 pte_t *pt_dir;
153 pte_t pte; 160 pte_t pte;
@@ -155,9 +162,10 @@ static void vmem_remove_range(unsigned long start, unsigned long size)
155 pte_val(pte) = _PAGE_TYPE_EMPTY; 162 pte_val(pte) = _PAGE_TYPE_EMPTY;
156 for (address = start; address < start + size; address += PAGE_SIZE) { 163 for (address = start; address < start + size; address += PAGE_SIZE) {
157 pg_dir = pgd_offset_k(address); 164 pg_dir = pgd_offset_k(address);
158 if (pgd_none(*pg_dir)) 165 pu_dir = pud_offset(pg_dir, address);
166 if (pud_none(*pu_dir))
159 continue; 167 continue;
160 pm_dir = pmd_offset(pg_dir, address); 168 pm_dir = pmd_offset(pu_dir, address);
161 if (pmd_none(*pm_dir)) 169 if (pmd_none(*pm_dir))
162 continue; 170 continue;
163 pt_dir = pte_offset_kernel(pm_dir, address); 171 pt_dir = pte_offset_kernel(pm_dir, address);
@@ -174,6 +182,7 @@ static int vmem_add_mem_map(unsigned long start, unsigned long size)
174 unsigned long address, start_addr, end_addr; 182 unsigned long address, start_addr, end_addr;
175 struct page *map_start, *map_end; 183 struct page *map_start, *map_end;
176 pgd_t *pg_dir; 184 pgd_t *pg_dir;
185 pud_t *pu_dir;
177 pmd_t *pm_dir; 186 pmd_t *pm_dir;
178 pte_t *pt_dir; 187 pte_t *pt_dir;
179 pte_t pte; 188 pte_t pte;
@@ -188,13 +197,21 @@ static int vmem_add_mem_map(unsigned long start, unsigned long size)
188 for (address = start_addr; address < end_addr; address += PAGE_SIZE) { 197 for (address = start_addr; address < end_addr; address += PAGE_SIZE) {
189 pg_dir = pgd_offset_k(address); 198 pg_dir = pgd_offset_k(address);
190 if (pgd_none(*pg_dir)) { 199 if (pgd_none(*pg_dir)) {
200 pu_dir = vmem_pud_alloc();
201 if (!pu_dir)
202 goto out;
203 pgd_populate_kernel(&init_mm, pg_dir, pu_dir);
204 }
205
206 pu_dir = pud_offset(pg_dir, address);
207 if (pud_none(*pu_dir)) {
191 pm_dir = vmem_pmd_alloc(); 208 pm_dir = vmem_pmd_alloc();
192 if (!pm_dir) 209 if (!pm_dir)
193 goto out; 210 goto out;
194 pgd_populate_kernel(&init_mm, pg_dir, pm_dir); 211 pud_populate_kernel(&init_mm, pu_dir, pm_dir);
195 } 212 }
196 213
197 pm_dir = pmd_offset(pg_dir, address); 214 pm_dir = pmd_offset(pu_dir, address);
198 if (pmd_none(*pm_dir)) { 215 if (pmd_none(*pm_dir)) {
199 pt_dir = vmem_pte_alloc(); 216 pt_dir = vmem_pte_alloc();
200 if (!pt_dir) 217 if (!pt_dir)
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index 2edd5fb6d3dc..8d1c64a24dec 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -48,8 +48,8 @@ struct raw3270 {
48 struct timer_list timer; /* Device timer. */ 48 struct timer_list timer; /* Device timer. */
49 49
50 unsigned char *ascebc; /* ascii -> ebcdic table */ 50 unsigned char *ascebc; /* ascii -> ebcdic table */
51 struct class_device *clttydev; /* 3270-class tty device ptr */ 51 struct device *clttydev; /* 3270-class tty device ptr */
52 struct class_device *cltubdev; /* 3270-class tub device ptr */ 52 struct device *cltubdev; /* 3270-class tub device ptr */
53 53
54 struct raw3270_request init_request; 54 struct raw3270_request init_request;
55 unsigned char init_data[256]; 55 unsigned char init_data[256];
@@ -1107,11 +1107,9 @@ raw3270_delete_device(struct raw3270 *rp)
1107 /* Remove from device chain. */ 1107 /* Remove from device chain. */
1108 mutex_lock(&raw3270_mutex); 1108 mutex_lock(&raw3270_mutex);
1109 if (rp->clttydev && !IS_ERR(rp->clttydev)) 1109 if (rp->clttydev && !IS_ERR(rp->clttydev))
1110 class_device_destroy(class3270, 1110 device_destroy(class3270, MKDEV(IBM_TTY3270_MAJOR, rp->minor));
1111 MKDEV(IBM_TTY3270_MAJOR, rp->minor));
1112 if (rp->cltubdev && !IS_ERR(rp->cltubdev)) 1111 if (rp->cltubdev && !IS_ERR(rp->cltubdev))
1113 class_device_destroy(class3270, 1112 device_destroy(class3270, MKDEV(IBM_FS3270_MAJOR, rp->minor));
1114 MKDEV(IBM_FS3270_MAJOR, rp->minor));
1115 list_del_init(&rp->list); 1113 list_del_init(&rp->list);
1116 mutex_unlock(&raw3270_mutex); 1114 mutex_unlock(&raw3270_mutex);
1117 1115
@@ -1181,24 +1179,22 @@ static int raw3270_create_attributes(struct raw3270 *rp)
1181 if (rc) 1179 if (rc)
1182 goto out; 1180 goto out;
1183 1181
1184 rp->clttydev = class_device_create(class3270, NULL, 1182 rp->clttydev = device_create(class3270, &rp->cdev->dev,
1185 MKDEV(IBM_TTY3270_MAJOR, rp->minor), 1183 MKDEV(IBM_TTY3270_MAJOR, rp->minor),
1186 &rp->cdev->dev, "tty%s", 1184 "tty%s", rp->cdev->dev.bus_id);
1187 rp->cdev->dev.bus_id);
1188 if (IS_ERR(rp->clttydev)) { 1185 if (IS_ERR(rp->clttydev)) {
1189 rc = PTR_ERR(rp->clttydev); 1186 rc = PTR_ERR(rp->clttydev);
1190 goto out_ttydev; 1187 goto out_ttydev;
1191 } 1188 }
1192 1189
1193 rp->cltubdev = class_device_create(class3270, NULL, 1190 rp->cltubdev = device_create(class3270, &rp->cdev->dev,
1194 MKDEV(IBM_FS3270_MAJOR, rp->minor), 1191 MKDEV(IBM_FS3270_MAJOR, rp->minor),
1195 &rp->cdev->dev, "tub%s", 1192 "tub%s", rp->cdev->dev.bus_id);
1196 rp->cdev->dev.bus_id);
1197 if (!IS_ERR(rp->cltubdev)) 1193 if (!IS_ERR(rp->cltubdev))
1198 goto out; 1194 goto out;
1199 1195
1200 rc = PTR_ERR(rp->cltubdev); 1196 rc = PTR_ERR(rp->cltubdev);
1201 class_device_destroy(class3270, MKDEV(IBM_TTY3270_MAJOR, rp->minor)); 1197 device_destroy(class3270, MKDEV(IBM_TTY3270_MAJOR, rp->minor));
1202 1198
1203out_ttydev: 1199out_ttydev:
1204 sysfs_remove_group(&rp->cdev->dev.kobj, &raw3270_attr_group); 1200 sysfs_remove_group(&rp->cdev->dev.kobj, &raw3270_attr_group);
diff --git a/drivers/s390/char/tape_class.c b/drivers/s390/char/tape_class.c
index 2e0d29730b67..aa7f166f4034 100644
--- a/drivers/s390/char/tape_class.c
+++ b/drivers/s390/char/tape_class.c
@@ -69,12 +69,9 @@ struct tape_class_device *register_tape_dev(
69 if (rc) 69 if (rc)
70 goto fail_with_cdev; 70 goto fail_with_cdev;
71 71
72 tcd->class_device = class_device_create( 72 tcd->class_device = device_create(tape_class, device,
73 tape_class, 73 tcd->char_device->dev,
74 NULL, 74 "%s", tcd->device_name
75 tcd->char_device->dev,
76 device,
77 "%s", tcd->device_name
78 ); 75 );
79 rc = IS_ERR(tcd->class_device) ? PTR_ERR(tcd->class_device) : 0; 76 rc = IS_ERR(tcd->class_device) ? PTR_ERR(tcd->class_device) : 0;
80 if (rc) 77 if (rc)
@@ -90,7 +87,7 @@ struct tape_class_device *register_tape_dev(
90 return tcd; 87 return tcd;
91 88
92fail_with_class_device: 89fail_with_class_device:
93 class_device_destroy(tape_class, tcd->char_device->dev); 90 device_destroy(tape_class, tcd->char_device->dev);
94 91
95fail_with_cdev: 92fail_with_cdev:
96 cdev_del(tcd->char_device); 93 cdev_del(tcd->char_device);
@@ -105,11 +102,9 @@ EXPORT_SYMBOL(register_tape_dev);
105void unregister_tape_dev(struct tape_class_device *tcd) 102void unregister_tape_dev(struct tape_class_device *tcd)
106{ 103{
107 if (tcd != NULL && !IS_ERR(tcd)) { 104 if (tcd != NULL && !IS_ERR(tcd)) {
108 sysfs_remove_link( 105 sysfs_remove_link(&tcd->class_device->kobj,
109 &tcd->class_device->dev->kobj, 106 tcd->mode_name);
110 tcd->mode_name 107 device_destroy(tape_class, tcd->char_device->dev);
111 );
112 class_device_destroy(tape_class, tcd->char_device->dev);
113 cdev_del(tcd->char_device); 108 cdev_del(tcd->char_device);
114 kfree(tcd); 109 kfree(tcd);
115 } 110 }
diff --git a/drivers/s390/char/tape_class.h b/drivers/s390/char/tape_class.h
index a8bd9b47fad6..e2b5ac918acf 100644
--- a/drivers/s390/char/tape_class.h
+++ b/drivers/s390/char/tape_class.h
@@ -24,8 +24,8 @@
24#define TAPECLASS_NAME_LEN 32 24#define TAPECLASS_NAME_LEN 32
25 25
26struct tape_class_device { 26struct tape_class_device {
27 struct cdev * char_device; 27 struct cdev *char_device;
28 struct class_device * class_device; 28 struct device *class_device;
29 char device_name[TAPECLASS_NAME_LEN]; 29 char device_name[TAPECLASS_NAME_LEN];
30 char mode_name[TAPECLASS_NAME_LEN]; 30 char mode_name[TAPECLASS_NAME_LEN];
31}; 31};
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index 12f7a4ce82c1..e0c4c508e121 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -74,7 +74,7 @@ struct vmlogrdr_priv_t {
74 int dev_in_use; /* 1: already opened, 0: not opened*/ 74 int dev_in_use; /* 1: already opened, 0: not opened*/
75 spinlock_t priv_lock; 75 spinlock_t priv_lock;
76 struct device *device; 76 struct device *device;
77 struct class_device *class_device; 77 struct device *class_device;
78 int autorecording; 78 int autorecording;
79 int autopurge; 79 int autopurge;
80}; 80};
@@ -762,12 +762,10 @@ static int vmlogrdr_register_device(struct vmlogrdr_priv_t *priv)
762 device_unregister(dev); 762 device_unregister(dev);
763 return ret; 763 return ret;
764 } 764 }
765 priv->class_device = class_device_create( 765 priv->class_device = device_create(vmlogrdr_class, dev,
766 vmlogrdr_class, 766 MKDEV(vmlogrdr_major,
767 NULL, 767 priv->minor_num),
768 MKDEV(vmlogrdr_major, priv->minor_num), 768 "%s", dev->bus_id);
769 dev,
770 "%s", dev->bus_id );
771 if (IS_ERR(priv->class_device)) { 769 if (IS_ERR(priv->class_device)) {
772 ret = PTR_ERR(priv->class_device); 770 ret = PTR_ERR(priv->class_device);
773 priv->class_device=NULL; 771 priv->class_device=NULL;
@@ -783,8 +781,7 @@ static int vmlogrdr_register_device(struct vmlogrdr_priv_t *priv)
783 781
784static int vmlogrdr_unregister_device(struct vmlogrdr_priv_t *priv) 782static int vmlogrdr_unregister_device(struct vmlogrdr_priv_t *priv)
785{ 783{
786 class_device_destroy(vmlogrdr_class, 784 device_destroy(vmlogrdr_class, MKDEV(vmlogrdr_major, priv->minor_num));
787 MKDEV(vmlogrdr_major, priv->minor_num));
788 if (priv->device != NULL) { 785 if (priv->device != NULL) {
789 sysfs_remove_group(&priv->device->kobj, &vmlogrdr_attr_group); 786 sysfs_remove_group(&priv->device->kobj, &vmlogrdr_attr_group);
790 device_unregister(priv->device); 787 device_unregister(priv->device);
diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c
index 42c1f4659adb..297cdceb0ca4 100644
--- a/drivers/s390/cio/chp.c
+++ b/drivers/s390/cio/chp.c
@@ -246,7 +246,7 @@ int chp_add_cmg_attr(struct channel_path *chp)
246static ssize_t chp_status_show(struct device *dev, 246static ssize_t chp_status_show(struct device *dev,
247 struct device_attribute *attr, char *buf) 247 struct device_attribute *attr, char *buf)
248{ 248{
249 struct channel_path *chp = container_of(dev, struct channel_path, dev); 249 struct channel_path *chp = to_channelpath(dev);
250 250
251 if (!chp) 251 if (!chp)
252 return 0; 252 return 0;
@@ -258,7 +258,7 @@ static ssize_t chp_status_write(struct device *dev,
258 struct device_attribute *attr, 258 struct device_attribute *attr,
259 const char *buf, size_t count) 259 const char *buf, size_t count)
260{ 260{
261 struct channel_path *cp = container_of(dev, struct channel_path, dev); 261 struct channel_path *cp = to_channelpath(dev);
262 char cmd[10]; 262 char cmd[10];
263 int num_args; 263 int num_args;
264 int error; 264 int error;
@@ -286,7 +286,7 @@ static ssize_t chp_configure_show(struct device *dev,
286 struct channel_path *cp; 286 struct channel_path *cp;
287 int status; 287 int status;
288 288
289 cp = container_of(dev, struct channel_path, dev); 289 cp = to_channelpath(dev);
290 status = chp_info_get_status(cp->chpid); 290 status = chp_info_get_status(cp->chpid);
291 if (status < 0) 291 if (status < 0)
292 return status; 292 return status;
@@ -308,7 +308,7 @@ static ssize_t chp_configure_write(struct device *dev,
308 return -EINVAL; 308 return -EINVAL;
309 if (val != 0 && val != 1) 309 if (val != 0 && val != 1)
310 return -EINVAL; 310 return -EINVAL;
311 cp = container_of(dev, struct channel_path, dev); 311 cp = to_channelpath(dev);
312 chp_cfg_schedule(cp->chpid, val); 312 chp_cfg_schedule(cp->chpid, val);
313 cfg_wait_idle(); 313 cfg_wait_idle();
314 314
@@ -320,7 +320,7 @@ static DEVICE_ATTR(configure, 0644, chp_configure_show, chp_configure_write);
320static ssize_t chp_type_show(struct device *dev, struct device_attribute *attr, 320static ssize_t chp_type_show(struct device *dev, struct device_attribute *attr,
321 char *buf) 321 char *buf)
322{ 322{
323 struct channel_path *chp = container_of(dev, struct channel_path, dev); 323 struct channel_path *chp = to_channelpath(dev);
324 324
325 if (!chp) 325 if (!chp)
326 return 0; 326 return 0;
@@ -374,7 +374,7 @@ static void chp_release(struct device *dev)
374{ 374{
375 struct channel_path *cp; 375 struct channel_path *cp;
376 376
377 cp = container_of(dev, struct channel_path, dev); 377 cp = to_channelpath(dev);
378 kfree(cp); 378 kfree(cp);
379} 379}
380 380
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 5d83dd471461..838f7ac0dc32 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -182,6 +182,15 @@ static int css_register_subchannel(struct subchannel *sch)
182 sch->dev.bus = &css_bus_type; 182 sch->dev.bus = &css_bus_type;
183 sch->dev.release = &css_subchannel_release; 183 sch->dev.release = &css_subchannel_release;
184 sch->dev.groups = subch_attr_groups; 184 sch->dev.groups = subch_attr_groups;
185 /*
186 * We don't want to generate uevents for I/O subchannels that don't
187 * have a working ccw device behind them since they will be
188 * unregistered before they can be used anyway, so we delay the add
189 * uevent until after device recognition was successful.
190 */
191 if (!cio_is_console(sch->schid))
192 /* Console is special, no need to suppress. */
193 sch->dev.uevent_suppress = 1;
185 css_update_ssd_info(sch); 194 css_update_ssd_info(sch);
186 /* make it known to the system */ 195 /* make it known to the system */
187 ret = css_sch_device_register(sch); 196 ret = css_sch_device_register(sch);
diff --git a/include/asm-s390/cpu.h b/include/asm-s390/cpu.h
new file mode 100644
index 000000000000..352dde194f3c
--- /dev/null
+++ b/include/asm-s390/cpu.h
@@ -0,0 +1,25 @@
1/*
2 * include/asm-s390/cpu.h
3 *
4 * Copyright IBM Corp. 2007
5 * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
6 */
7
8#ifndef _ASM_S390_CPU_H_
9#define _ASM_S390_CPU_H_
10
11#include <linux/types.h>
12#include <linux/percpu.h>
13#include <linux/spinlock.h>
14
15struct s390_idle_data {
16 spinlock_t lock;
17 unsigned int in_idle;
18 unsigned long long idle_count;
19 unsigned long long idle_enter;
20 unsigned long long idle_time;
21};
22
23DECLARE_PER_CPU(struct s390_idle_data, s390_idle);
24
25#endif /* _ASM_S390_CPU_H_ */
diff --git a/include/asm-s390/mmu_context.h b/include/asm-s390/mmu_context.h
index 501cb9b06314..05b842126b99 100644
--- a/include/asm-s390/mmu_context.h
+++ b/include/asm-s390/mmu_context.h
@@ -21,45 +21,43 @@
21 21
22#ifndef __s390x__ 22#ifndef __s390x__
23#define LCTL_OPCODE "lctl" 23#define LCTL_OPCODE "lctl"
24#define PGTABLE_BITS (_SEGMENT_TABLE|USER_STD_MASK)
25#else 24#else
26#define LCTL_OPCODE "lctlg" 25#define LCTL_OPCODE "lctlg"
27#define PGTABLE_BITS (_REGION_TABLE|USER_STD_MASK)
28#endif 26#endif
29 27
30static inline void enter_lazy_tlb(struct mm_struct *mm, 28static inline void update_mm(struct mm_struct *mm, struct task_struct *tsk)
31 struct task_struct *tsk)
32{ 29{
30 pgd_t *pgd = mm->pgd;
31 unsigned long asce_bits;
32
33 /* Calculate asce bits from the first pgd table entry. */
34 asce_bits = _ASCE_TABLE_LENGTH | _ASCE_USER_BITS;
35#ifdef CONFIG_64BIT
36 asce_bits |= _ASCE_TYPE_REGION3;
37#endif
38 S390_lowcore.user_asce = asce_bits | __pa(pgd);
39 if (switch_amode) {
40 /* Load primary space page table origin. */
41 pgd_t *shadow_pgd = get_shadow_table(pgd) ? : pgd;
42 S390_lowcore.user_exec_asce = asce_bits | __pa(shadow_pgd);
43 asm volatile(LCTL_OPCODE" 1,1,%0\n"
44 : : "m" (S390_lowcore.user_exec_asce) );
45 } else
46 /* Load home space page table origin. */
47 asm volatile(LCTL_OPCODE" 13,13,%0"
48 : : "m" (S390_lowcore.user_asce) );
33} 49}
34 50
35static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, 51static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
36 struct task_struct *tsk) 52 struct task_struct *tsk)
37{ 53{
38 pgd_t *shadow_pgd = get_shadow_pgd(next->pgd); 54 if (unlikely(prev == next))
39 55 return;
40 if (prev != next) {
41 S390_lowcore.user_asce = (__pa(next->pgd) & PAGE_MASK) |
42 PGTABLE_BITS;
43 if (shadow_pgd) {
44 /* Load primary/secondary space page table origin. */
45 S390_lowcore.user_exec_asce =
46 (__pa(shadow_pgd) & PAGE_MASK) | PGTABLE_BITS;
47 asm volatile(LCTL_OPCODE" 1,1,%0\n"
48 LCTL_OPCODE" 7,7,%1"
49 : : "m" (S390_lowcore.user_exec_asce),
50 "m" (S390_lowcore.user_asce) );
51 } else if (switch_amode) {
52 /* Load primary space page table origin. */
53 asm volatile(LCTL_OPCODE" 1,1,%0"
54 : : "m" (S390_lowcore.user_asce) );
55 } else
56 /* Load home space page table origin. */
57 asm volatile(LCTL_OPCODE" 13,13,%0"
58 : : "m" (S390_lowcore.user_asce) );
59 }
60 cpu_set(smp_processor_id(), next->cpu_vm_mask); 56 cpu_set(smp_processor_id(), next->cpu_vm_mask);
57 update_mm(next, tsk);
61} 58}
62 59
60#define enter_lazy_tlb(mm,tsk) do { } while (0)
63#define deactivate_mm(tsk,mm) do { } while (0) 61#define deactivate_mm(tsk,mm) do { } while (0)
64 62
65static inline void activate_mm(struct mm_struct *prev, 63static inline void activate_mm(struct mm_struct *prev,
diff --git a/include/asm-s390/page.h b/include/asm-s390/page.h
index ceec3826a67c..584d0ee3c7f6 100644
--- a/include/asm-s390/page.h
+++ b/include/asm-s390/page.h
@@ -82,6 +82,7 @@ typedef struct { unsigned long pte; } pte_t;
82#ifndef __s390x__ 82#ifndef __s390x__
83 83
84typedef struct { unsigned long pmd; } pmd_t; 84typedef struct { unsigned long pmd; } pmd_t;
85typedef struct { unsigned long pud; } pud_t;
85typedef struct { 86typedef struct {
86 unsigned long pgd0; 87 unsigned long pgd0;
87 unsigned long pgd1; 88 unsigned long pgd1;
@@ -90,6 +91,7 @@ typedef struct {
90 } pgd_t; 91 } pgd_t;
91 92
92#define pmd_val(x) ((x).pmd) 93#define pmd_val(x) ((x).pmd)
94#define pud_val(x) ((x).pud)
93#define pgd_val(x) ((x).pgd0) 95#define pgd_val(x) ((x).pgd0)
94 96
95#else /* __s390x__ */ 97#else /* __s390x__ */
@@ -98,10 +100,12 @@ typedef struct {
98 unsigned long pmd0; 100 unsigned long pmd0;
99 unsigned long pmd1; 101 unsigned long pmd1;
100 } pmd_t; 102 } pmd_t;
103typedef struct { unsigned long pud; } pud_t;
101typedef struct { unsigned long pgd; } pgd_t; 104typedef struct { unsigned long pgd; } pgd_t;
102 105
103#define pmd_val(x) ((x).pmd0) 106#define pmd_val(x) ((x).pmd0)
104#define pmd_val1(x) ((x).pmd1) 107#define pmd_val1(x) ((x).pmd1)
108#define pud_val(x) ((x).pud)
105#define pgd_val(x) ((x).pgd) 109#define pgd_val(x) ((x).pgd)
106 110
107#endif /* __s390x__ */ 111#endif /* __s390x__ */
diff --git a/include/asm-s390/pgalloc.h b/include/asm-s390/pgalloc.h
index e45d3c9a4b7e..709dd1740956 100644
--- a/include/asm-s390/pgalloc.h
+++ b/include/asm-s390/pgalloc.h
@@ -19,140 +19,115 @@
19 19
20#define check_pgt_cache() do {} while (0) 20#define check_pgt_cache() do {} while (0)
21 21
22/* 22unsigned long *crst_table_alloc(struct mm_struct *, int);
23 * Page allocation orders. 23void crst_table_free(unsigned long *);
24 */
25#ifndef __s390x__
26# define PTE_ALLOC_ORDER 0
27# define PMD_ALLOC_ORDER 0
28# define PGD_ALLOC_ORDER 1
29#else /* __s390x__ */
30# define PTE_ALLOC_ORDER 0
31# define PMD_ALLOC_ORDER 2
32# define PGD_ALLOC_ORDER 2
33#endif /* __s390x__ */
34 24
35/* 25unsigned long *page_table_alloc(int);
36 * Allocate and free page tables. The xxx_kernel() versions are 26void page_table_free(unsigned long *);
37 * used to allocate a kernel page table - this turns on ASN bits
38 * if any.
39 */
40 27
41static inline pgd_t *pgd_alloc(struct mm_struct *mm) 28static inline void clear_table(unsigned long *s, unsigned long val, size_t n)
42{ 29{
43 pgd_t *pgd = (pgd_t *) __get_free_pages(GFP_KERNEL, PGD_ALLOC_ORDER); 30 *s = val;
44 int i; 31 n = (n / 256) - 1;
45 32 asm volatile(
46 if (!pgd) 33#ifdef CONFIG_64BIT
47 return NULL; 34 " mvc 8(248,%0),0(%0)\n"
48 if (s390_noexec) {
49 pgd_t *shadow_pgd = (pgd_t *)
50 __get_free_pages(GFP_KERNEL, PGD_ALLOC_ORDER);
51 struct page *page = virt_to_page(pgd);
52
53 if (!shadow_pgd) {
54 free_pages((unsigned long) pgd, PGD_ALLOC_ORDER);
55 return NULL;
56 }
57 page->lru.next = (void *) shadow_pgd;
58 }
59 for (i = 0; i < PTRS_PER_PGD; i++)
60#ifndef __s390x__
61 pmd_clear(pmd_offset(pgd + i, i*PGDIR_SIZE));
62#else 35#else
63 pgd_clear(pgd + i); 36 " mvc 4(252,%0),0(%0)\n"
64#endif 37#endif
65 return pgd; 38 "0: mvc 256(256,%0),0(%0)\n"
39 " la %0,256(%0)\n"
40 " brct %1,0b\n"
41 : "+a" (s), "+d" (n));
66} 42}
67 43
68static inline void pgd_free(pgd_t *pgd) 44static inline void crst_table_init(unsigned long *crst, unsigned long entry)
69{ 45{
70 pgd_t *shadow_pgd = get_shadow_pgd(pgd); 46 clear_table(crst, entry, sizeof(unsigned long)*2048);
71 47 crst = get_shadow_table(crst);
72 if (shadow_pgd) 48 if (crst)
73 free_pages((unsigned long) shadow_pgd, PGD_ALLOC_ORDER); 49 clear_table(crst, entry, sizeof(unsigned long)*2048);
74 free_pages((unsigned long) pgd, PGD_ALLOC_ORDER);
75} 50}
76 51
77#ifndef __s390x__ 52#ifndef __s390x__
78/* 53
79 * page middle directory allocation/free routines. 54static inline unsigned long pgd_entry_type(struct mm_struct *mm)
80 * We use pmd cache only on s390x, so these are dummy routines. This
81 * code never triggers because the pgd will always be present.
82 */
83#define pmd_alloc_one(mm,address) ({ BUG(); ((pmd_t *)2); })
84#define pmd_free(x) do { } while (0)
85#define __pmd_free_tlb(tlb,x) do { } while (0)
86#define pgd_populate(mm, pmd, pte) BUG()
87#define pgd_populate_kernel(mm, pmd, pte) BUG()
88#else /* __s390x__ */
89static inline pmd_t * pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr)
90{ 55{
91 pmd_t *pmd = (pmd_t *) __get_free_pages(GFP_KERNEL, PMD_ALLOC_ORDER); 56 return _SEGMENT_ENTRY_EMPTY;
92 int i;
93
94 if (!pmd)
95 return NULL;
96 if (s390_noexec) {
97 pmd_t *shadow_pmd = (pmd_t *)
98 __get_free_pages(GFP_KERNEL, PMD_ALLOC_ORDER);
99 struct page *page = virt_to_page(pmd);
100
101 if (!shadow_pmd) {
102 free_pages((unsigned long) pmd, PMD_ALLOC_ORDER);
103 return NULL;
104 }
105 page->lru.next = (void *) shadow_pmd;
106 }
107 for (i=0; i < PTRS_PER_PMD; i++)
108 pmd_clear(pmd + i);
109 return pmd;
110} 57}
111 58
112static inline void pmd_free (pmd_t *pmd) 59#define pud_alloc_one(mm,address) ({ BUG(); ((pud_t *)2); })
60#define pud_free(x) do { } while (0)
61
62#define pmd_alloc_one(mm,address) ({ BUG(); ((pmd_t *)2); })
63#define pmd_free(x) do { } while (0)
64
65#define pgd_populate(mm, pgd, pud) BUG()
66#define pgd_populate_kernel(mm, pgd, pud) BUG()
67
68#define pud_populate(mm, pud, pmd) BUG()
69#define pud_populate_kernel(mm, pud, pmd) BUG()
70
71#else /* __s390x__ */
72
73static inline unsigned long pgd_entry_type(struct mm_struct *mm)
113{ 74{
114 pmd_t *shadow_pmd = get_shadow_pmd(pmd); 75 return _REGION3_ENTRY_EMPTY;
76}
77
78#define pud_alloc_one(mm,address) ({ BUG(); ((pud_t *)2); })
79#define pud_free(x) do { } while (0)
115 80
116 if (shadow_pmd) 81static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr)
117 free_pages((unsigned long) shadow_pmd, PMD_ALLOC_ORDER); 82{
118 free_pages((unsigned long) pmd, PMD_ALLOC_ORDER); 83 unsigned long *crst = crst_table_alloc(mm, s390_noexec);
84 if (crst)
85 crst_table_init(crst, _SEGMENT_ENTRY_EMPTY);
86 return (pmd_t *) crst;
119} 87}
88#define pmd_free(pmd) crst_table_free((unsigned long *) pmd)
120 89
121#define __pmd_free_tlb(tlb,pmd) \ 90#define pgd_populate(mm, pgd, pud) BUG()
122 do { \ 91#define pgd_populate_kernel(mm, pgd, pud) BUG()
123 tlb_flush_mmu(tlb, 0, 0); \
124 pmd_free(pmd); \
125 } while (0)
126 92
127static inline void 93static inline void pud_populate_kernel(struct mm_struct *mm,
128pgd_populate_kernel(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmd) 94 pud_t *pud, pmd_t *pmd)
129{ 95{
130 pgd_val(*pgd) = _PGD_ENTRY | __pa(pmd); 96 pud_val(*pud) = _REGION3_ENTRY | __pa(pmd);
131} 97}
132 98
133static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmd) 99static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
134{ 100{
135 pgd_t *shadow_pgd = get_shadow_pgd(pgd); 101 pud_t *shadow_pud = get_shadow_table(pud);
136 pmd_t *shadow_pmd = get_shadow_pmd(pmd); 102 pmd_t *shadow_pmd = get_shadow_table(pmd);
137 103
138 if (shadow_pgd && shadow_pmd) 104 if (shadow_pud && shadow_pmd)
139 pgd_populate_kernel(mm, shadow_pgd, shadow_pmd); 105 pud_populate_kernel(mm, shadow_pud, shadow_pmd);
140 pgd_populate_kernel(mm, pgd, pmd); 106 pud_populate_kernel(mm, pud, pmd);
141} 107}
142 108
143#endif /* __s390x__ */ 109#endif /* __s390x__ */
144 110
111static inline pgd_t *pgd_alloc(struct mm_struct *mm)
112{
113 unsigned long *crst = crst_table_alloc(mm, s390_noexec);
114 if (crst)
115 crst_table_init(crst, pgd_entry_type(mm));
116 return (pgd_t *) crst;
117}
118#define pgd_free(pgd) crst_table_free((unsigned long *) pgd)
119
145static inline void 120static inline void
146pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, pte_t *pte) 121pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, pte_t *pte)
147{ 122{
148#ifndef __s390x__ 123#ifndef __s390x__
149 pmd_val(pmd[0]) = _PAGE_TABLE + __pa(pte); 124 pmd_val(pmd[0]) = _SEGMENT_ENTRY + __pa(pte);
150 pmd_val(pmd[1]) = _PAGE_TABLE + __pa(pte+256); 125 pmd_val(pmd[1]) = _SEGMENT_ENTRY + __pa(pte+256);
151 pmd_val(pmd[2]) = _PAGE_TABLE + __pa(pte+512); 126 pmd_val(pmd[2]) = _SEGMENT_ENTRY + __pa(pte+512);
152 pmd_val(pmd[3]) = _PAGE_TABLE + __pa(pte+768); 127 pmd_val(pmd[3]) = _SEGMENT_ENTRY + __pa(pte+768);
153#else /* __s390x__ */ 128#else /* __s390x__ */
154 pmd_val(*pmd) = _PMD_ENTRY + __pa(pte); 129 pmd_val(*pmd) = _SEGMENT_ENTRY + __pa(pte);
155 pmd_val1(*pmd) = _PMD_ENTRY + __pa(pte+256); 130 pmd_val1(*pmd) = _SEGMENT_ENTRY + __pa(pte+256);
156#endif /* __s390x__ */ 131#endif /* __s390x__ */
157} 132}
158 133
@@ -160,7 +135,7 @@ static inline void
160pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *page) 135pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *page)
161{ 136{
162 pte_t *pte = (pte_t *)page_to_phys(page); 137 pte_t *pte = (pte_t *)page_to_phys(page);
163 pmd_t *shadow_pmd = get_shadow_pmd(pmd); 138 pmd_t *shadow_pmd = get_shadow_table(pmd);
164 pte_t *shadow_pte = get_shadow_pte(pte); 139 pte_t *shadow_pte = get_shadow_pte(pte);
165 140
166 pmd_populate_kernel(mm, pmd, pte); 141 pmd_populate_kernel(mm, pmd, pte);
@@ -171,67 +146,14 @@ pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *page)
171/* 146/*
172 * page table entry allocation/free routines. 147 * page table entry allocation/free routines.
173 */ 148 */
174static inline pte_t * 149#define pte_alloc_one_kernel(mm, vmaddr) \
175pte_alloc_one_kernel(struct mm_struct *mm, unsigned long vmaddr) 150 ((pte_t *) page_table_alloc(s390_noexec))
176{ 151#define pte_alloc_one(mm, vmaddr) \
177 pte_t *pte = (pte_t *) __get_free_page(GFP_KERNEL|__GFP_REPEAT); 152 virt_to_page(page_table_alloc(s390_noexec))
178 int i; 153
179 154#define pte_free_kernel(pte) \
180 if (!pte) 155 page_table_free((unsigned long *) pte)
181 return NULL; 156#define pte_free(pte) \
182 if (s390_noexec) { 157 page_table_free((unsigned long *) page_to_phys((struct page *) pte))
183 pte_t *shadow_pte = (pte_t *)
184 __get_free_page(GFP_KERNEL|__GFP_REPEAT);
185 struct page *page = virt_to_page(pte);
186
187 if (!shadow_pte) {
188 free_page((unsigned long) pte);
189 return NULL;
190 }
191 page->lru.next = (void *) shadow_pte;
192 }
193 for (i=0; i < PTRS_PER_PTE; i++) {
194 pte_clear(mm, vmaddr, pte + i);
195 vmaddr += PAGE_SIZE;
196 }
197 return pte;
198}
199
200static inline struct page *
201pte_alloc_one(struct mm_struct *mm, unsigned long vmaddr)
202{
203 pte_t *pte = pte_alloc_one_kernel(mm, vmaddr);
204 if (pte)
205 return virt_to_page(pte);
206 return NULL;
207}
208
209static inline void pte_free_kernel(pte_t *pte)
210{
211 pte_t *shadow_pte = get_shadow_pte(pte);
212
213 if (shadow_pte)
214 free_page((unsigned long) shadow_pte);
215 free_page((unsigned long) pte);
216}
217
218static inline void pte_free(struct page *pte)
219{
220 struct page *shadow_page = get_shadow_page(pte);
221
222 if (shadow_page)
223 __free_page(shadow_page);
224 __free_page(pte);
225}
226
227#define __pte_free_tlb(tlb, pte) \
228({ \
229 struct mmu_gather *__tlb = (tlb); \
230 struct page *__pte = (pte); \
231 struct page *shadow_page = get_shadow_page(__pte); \
232 if (shadow_page) \
233 tlb_remove_page(__tlb, shadow_page); \
234 tlb_remove_page(__tlb, __pte); \
235})
236 158
237#endif /* _S390_PGALLOC_H */ 159#endif /* _S390_PGALLOC_H */
diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h
index 39bb5192dc31..f2cc25b74adf 100644
--- a/include/asm-s390/pgtable.h
+++ b/include/asm-s390/pgtable.h
@@ -13,8 +13,6 @@
13#ifndef _ASM_S390_PGTABLE_H 13#ifndef _ASM_S390_PGTABLE_H
14#define _ASM_S390_PGTABLE_H 14#define _ASM_S390_PGTABLE_H
15 15
16#include <asm-generic/4level-fixup.h>
17
18/* 16/*
19 * The Linux memory management assumes a three-level page table setup. For 17 * The Linux memory management assumes a three-level page table setup. For
20 * s390 31 bit we "fold" the mid level into the top-level page table, so 18 * s390 31 bit we "fold" the mid level into the top-level page table, so
@@ -35,9 +33,6 @@
35#include <asm/bug.h> 33#include <asm/bug.h>
36#include <asm/processor.h> 34#include <asm/processor.h>
37 35
38struct vm_area_struct; /* forward declaration (include/linux/mm.h) */
39struct mm_struct;
40
41extern pgd_t swapper_pg_dir[] __attribute__ ((aligned (4096))); 36extern pgd_t swapper_pg_dir[] __attribute__ ((aligned (4096)));
42extern void paging_init(void); 37extern void paging_init(void);
43extern void vmem_map_init(void); 38extern void vmem_map_init(void);
@@ -63,14 +58,18 @@ extern char empty_zero_page[PAGE_SIZE];
63 */ 58 */
64#ifndef __s390x__ 59#ifndef __s390x__
65# define PMD_SHIFT 22 60# define PMD_SHIFT 22
61# define PUD_SHIFT 22
66# define PGDIR_SHIFT 22 62# define PGDIR_SHIFT 22
67#else /* __s390x__ */ 63#else /* __s390x__ */
68# define PMD_SHIFT 21 64# define PMD_SHIFT 21
65# define PUD_SHIFT 31
69# define PGDIR_SHIFT 31 66# define PGDIR_SHIFT 31
70#endif /* __s390x__ */ 67#endif /* __s390x__ */
71 68
72#define PMD_SIZE (1UL << PMD_SHIFT) 69#define PMD_SIZE (1UL << PMD_SHIFT)
73#define PMD_MASK (~(PMD_SIZE-1)) 70#define PMD_MASK (~(PMD_SIZE-1))
71#define PUD_SIZE (1UL << PUD_SHIFT)
72#define PUD_MASK (~(PUD_SIZE-1))
74#define PGDIR_SIZE (1UL << PGDIR_SHIFT) 73#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
75#define PGDIR_MASK (~(PGDIR_SIZE-1)) 74#define PGDIR_MASK (~(PGDIR_SIZE-1))
76 75
@@ -83,10 +82,12 @@ extern char empty_zero_page[PAGE_SIZE];
83#ifndef __s390x__ 82#ifndef __s390x__
84# define PTRS_PER_PTE 1024 83# define PTRS_PER_PTE 1024
85# define PTRS_PER_PMD 1 84# define PTRS_PER_PMD 1
85# define PTRS_PER_PUD 1
86# define PTRS_PER_PGD 512 86# define PTRS_PER_PGD 512
87#else /* __s390x__ */ 87#else /* __s390x__ */
88# define PTRS_PER_PTE 512 88# define PTRS_PER_PTE 512
89# define PTRS_PER_PMD 1024 89# define PTRS_PER_PMD 1024
90# define PTRS_PER_PUD 1
90# define PTRS_PER_PGD 2048 91# define PTRS_PER_PGD 2048
91#endif /* __s390x__ */ 92#endif /* __s390x__ */
92 93
@@ -96,6 +97,8 @@ extern char empty_zero_page[PAGE_SIZE];
96 printk("%s:%d: bad pte %p.\n", __FILE__, __LINE__, (void *) pte_val(e)) 97 printk("%s:%d: bad pte %p.\n", __FILE__, __LINE__, (void *) pte_val(e))
97#define pmd_ERROR(e) \ 98#define pmd_ERROR(e) \
98 printk("%s:%d: bad pmd %p.\n", __FILE__, __LINE__, (void *) pmd_val(e)) 99 printk("%s:%d: bad pmd %p.\n", __FILE__, __LINE__, (void *) pmd_val(e))
100#define pud_ERROR(e) \
101 printk("%s:%d: bad pud %p.\n", __FILE__, __LINE__, (void *) pud_val(e))
99#define pgd_ERROR(e) \ 102#define pgd_ERROR(e) \
100 printk("%s:%d: bad pgd %p.\n", __FILE__, __LINE__, (void *) pgd_val(e)) 103 printk("%s:%d: bad pgd %p.\n", __FILE__, __LINE__, (void *) pgd_val(e))
101 104
@@ -195,7 +198,7 @@ extern unsigned long vmalloc_end;
195 * I Segment-Invalid Bit: Segment is not available for address-translation 198 * I Segment-Invalid Bit: Segment is not available for address-translation
196 * TT Type 01 199 * TT Type 01
197 * TF 200 * TF
198 * TL Table lenght 201 * TL Table length
199 * 202 *
200 * The 64 bit regiontable origin of S390 has following format: 203 * The 64 bit regiontable origin of S390 has following format:
201 * | region table origon | DTTL 204 * | region table origon | DTTL
@@ -221,6 +224,8 @@ extern unsigned long vmalloc_end;
221/* Hardware bits in the page table entry */ 224/* Hardware bits in the page table entry */
222#define _PAGE_RO 0x200 /* HW read-only bit */ 225#define _PAGE_RO 0x200 /* HW read-only bit */
223#define _PAGE_INVALID 0x400 /* HW invalid bit */ 226#define _PAGE_INVALID 0x400 /* HW invalid bit */
227
228/* Software bits in the page table entry */
224#define _PAGE_SWT 0x001 /* SW pte type bit t */ 229#define _PAGE_SWT 0x001 /* SW pte type bit t */
225#define _PAGE_SWX 0x002 /* SW pte type bit x */ 230#define _PAGE_SWX 0x002 /* SW pte type bit x */
226 231
@@ -264,60 +269,75 @@ extern unsigned long vmalloc_end;
264 269
265#ifndef __s390x__ 270#ifndef __s390x__
266 271
267/* Bits in the segment table entry */ 272/* Bits in the segment table address-space-control-element */
268#define _PAGE_TABLE_LEN 0xf /* only full page-tables */ 273#define _ASCE_SPACE_SWITCH 0x80000000UL /* space switch event */
269#define _PAGE_TABLE_COM 0x10 /* common page-table */ 274#define _ASCE_ORIGIN_MASK 0x7ffff000UL /* segment table origin */
270#define _PAGE_TABLE_INV 0x20 /* invalid page-table */ 275#define _ASCE_PRIVATE_SPACE 0x100 /* private space control */
271#define _SEG_PRESENT 0x001 /* Software (overlap with PTL) */ 276#define _ASCE_ALT_EVENT 0x80 /* storage alteration event control */
272 277#define _ASCE_TABLE_LENGTH 0x7f /* 128 x 64 entries = 8k */
273/* Bits int the storage key */
274#define _PAGE_CHANGED 0x02 /* HW changed bit */
275#define _PAGE_REFERENCED 0x04 /* HW referenced bit */
276
277#define _USER_SEG_TABLE_LEN 0x7f /* user-segment-table up to 2 GB */
278#define _KERNEL_SEG_TABLE_LEN 0x7f /* kernel-segment-table up to 2 GB */
279
280/*
281 * User and Kernel pagetables are identical
282 */
283#define _PAGE_TABLE _PAGE_TABLE_LEN
284#define _KERNPG_TABLE _PAGE_TABLE_LEN
285
286/*
287 * The Kernel segment-tables includes the User segment-table
288 */
289 278
290#define _SEGMENT_TABLE (_USER_SEG_TABLE_LEN|0x80000000|0x100) 279/* Bits in the segment table entry */
291#define _KERNSEG_TABLE _KERNEL_SEG_TABLE_LEN 280#define _SEGMENT_ENTRY_ORIGIN 0x7fffffc0UL /* page table origin */
281#define _SEGMENT_ENTRY_INV 0x20 /* invalid segment table entry */
282#define _SEGMENT_ENTRY_COMMON 0x10 /* common segment bit */
283#define _SEGMENT_ENTRY_PTL 0x0f /* page table length */
292 284
293#define USER_STD_MASK 0x00000080UL 285#define _SEGMENT_ENTRY (_SEGMENT_ENTRY_PTL)
286#define _SEGMENT_ENTRY_EMPTY (_SEGMENT_ENTRY_INV)
294 287
295#else /* __s390x__ */ 288#else /* __s390x__ */
296 289
290/* Bits in the segment/region table address-space-control-element */
291#define _ASCE_ORIGIN ~0xfffUL/* segment table origin */
292#define _ASCE_PRIVATE_SPACE 0x100 /* private space control */
293#define _ASCE_ALT_EVENT 0x80 /* storage alteration event control */
294#define _ASCE_SPACE_SWITCH 0x40 /* space switch event */
295#define _ASCE_REAL_SPACE 0x20 /* real space control */
296#define _ASCE_TYPE_MASK 0x0c /* asce table type mask */
297#define _ASCE_TYPE_REGION1 0x0c /* region first table type */
298#define _ASCE_TYPE_REGION2 0x08 /* region second table type */
299#define _ASCE_TYPE_REGION3 0x04 /* region third table type */
300#define _ASCE_TYPE_SEGMENT 0x00 /* segment table type */
301#define _ASCE_TABLE_LENGTH 0x03 /* region table length */
302
303/* Bits in the region table entry */
304#define _REGION_ENTRY_ORIGIN ~0xfffUL/* region/segment table origin */
305#define _REGION_ENTRY_INV 0x20 /* invalid region table entry */
306#define _REGION_ENTRY_TYPE_MASK 0x0c /* region/segment table type mask */
307#define _REGION_ENTRY_TYPE_R1 0x0c /* region first table type */
308#define _REGION_ENTRY_TYPE_R2 0x08 /* region second table type */
309#define _REGION_ENTRY_TYPE_R3 0x04 /* region third table type */
310#define _REGION_ENTRY_LENGTH 0x03 /* region third length */
311
312#define _REGION1_ENTRY (_REGION_ENTRY_TYPE_R1 | _REGION_ENTRY_LENGTH)
313#define _REGION1_ENTRY_EMPTY (_REGION_ENTRY_TYPE_R1 | _REGION_ENTRY_INV)
314#define _REGION2_ENTRY (_REGION_ENTRY_TYPE_R2 | _REGION_ENTRY_LENGTH)
315#define _REGION2_ENTRY_EMPTY (_REGION_ENTRY_TYPE_R2 | _REGION_ENTRY_INV)
316#define _REGION3_ENTRY (_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_LENGTH)
317#define _REGION3_ENTRY_EMPTY (_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_INV)
318
297/* Bits in the segment table entry */ 319/* Bits in the segment table entry */
298#define _PMD_ENTRY_INV 0x20 /* invalid segment table entry */ 320#define _SEGMENT_ENTRY_ORIGIN ~0x7ffUL/* segment table origin */
299#define _PMD_ENTRY 0x00 321#define _SEGMENT_ENTRY_RO 0x200 /* page protection bit */
322#define _SEGMENT_ENTRY_INV 0x20 /* invalid segment table entry */
323
324#define _SEGMENT_ENTRY (0)
325#define _SEGMENT_ENTRY_EMPTY (_SEGMENT_ENTRY_INV)
300 326
301/* Bits in the region third table entry */ 327#endif /* __s390x__ */
302#define _PGD_ENTRY_INV 0x20 /* invalid region table entry */
303#define _PGD_ENTRY 0x07
304 328
305/* 329/*
306 * User and kernel page directory 330 * A user page table pointer has the space-switch-event bit, the
331 * private-space-control bit and the storage-alteration-event-control
332 * bit set. A kernel page table pointer doesn't need them.
307 */ 333 */
308#define _REGION_THIRD 0x4 334#define _ASCE_USER_BITS (_ASCE_SPACE_SWITCH | _ASCE_PRIVATE_SPACE | \
309#define _REGION_THIRD_LEN 0x3 335 _ASCE_ALT_EVENT)
310#define _REGION_TABLE (_REGION_THIRD|_REGION_THIRD_LEN|0x40|0x100)
311#define _KERN_REGION_TABLE (_REGION_THIRD|_REGION_THIRD_LEN)
312
313#define USER_STD_MASK 0x0000000000000080UL
314 336
315/* Bits in the storage key */ 337/* Bits int the storage key */
316#define _PAGE_CHANGED 0x02 /* HW changed bit */ 338#define _PAGE_CHANGED 0x02 /* HW changed bit */
317#define _PAGE_REFERENCED 0x04 /* HW referenced bit */ 339#define _PAGE_REFERENCED 0x04 /* HW referenced bit */
318 340
319#endif /* __s390x__ */
320
321/* 341/*
322 * Page protection definitions. 342 * Page protection definitions.
323 */ 343 */
@@ -358,65 +378,38 @@ extern unsigned long vmalloc_end;
358#define __S111 PAGE_EX_RW 378#define __S111 PAGE_EX_RW
359 379
360#ifndef __s390x__ 380#ifndef __s390x__
361# define PMD_SHADOW_SHIFT 1 381# define PxD_SHADOW_SHIFT 1
362# define PGD_SHADOW_SHIFT 1
363#else /* __s390x__ */ 382#else /* __s390x__ */
364# define PMD_SHADOW_SHIFT 2 383# define PxD_SHADOW_SHIFT 2
365# define PGD_SHADOW_SHIFT 2
366#endif /* __s390x__ */ 384#endif /* __s390x__ */
367 385
368static inline struct page *get_shadow_page(struct page *page) 386static inline struct page *get_shadow_page(struct page *page)
369{ 387{
370 if (s390_noexec && !list_empty(&page->lru)) 388 if (s390_noexec && page->index)
371 return virt_to_page(page->lru.next); 389 return virt_to_page((void *)(addr_t) page->index);
372 return NULL;
373}
374
375static inline pte_t *get_shadow_pte(pte_t *ptep)
376{
377 unsigned long pteptr = (unsigned long) (ptep);
378
379 if (s390_noexec) {
380 unsigned long offset = pteptr & (PAGE_SIZE - 1);
381 void *addr = (void *) (pteptr ^ offset);
382 struct page *page = virt_to_page(addr);
383 if (!list_empty(&page->lru))
384 return (pte_t *) ((unsigned long) page->lru.next |
385 offset);
386 }
387 return NULL; 390 return NULL;
388} 391}
389 392
390static inline pmd_t *get_shadow_pmd(pmd_t *pmdp) 393static inline void *get_shadow_pte(void *table)
391{ 394{
392 unsigned long pmdptr = (unsigned long) (pmdp); 395 unsigned long addr, offset;
396 struct page *page;
393 397
394 if (s390_noexec) { 398 addr = (unsigned long) table;
395 unsigned long offset = pmdptr & 399 offset = addr & (PAGE_SIZE - 1);
396 ((PAGE_SIZE << PMD_SHADOW_SHIFT) - 1); 400 page = virt_to_page((void *)(addr ^ offset));
397 void *addr = (void *) (pmdptr ^ offset); 401 return (void *)(addr_t)(page->index ? (page->index | offset) : 0UL);
398 struct page *page = virt_to_page(addr);
399 if (!list_empty(&page->lru))
400 return (pmd_t *) ((unsigned long) page->lru.next |
401 offset);
402 }
403 return NULL;
404} 402}
405 403
406static inline pgd_t *get_shadow_pgd(pgd_t *pgdp) 404static inline void *get_shadow_table(void *table)
407{ 405{
408 unsigned long pgdptr = (unsigned long) (pgdp); 406 unsigned long addr, offset;
407 struct page *page;
409 408
410 if (s390_noexec) { 409 addr = (unsigned long) table;
411 unsigned long offset = pgdptr & 410 offset = addr & ((PAGE_SIZE << PxD_SHADOW_SHIFT) - 1);
412 ((PAGE_SIZE << PGD_SHADOW_SHIFT) - 1); 411 page = virt_to_page((void *)(addr ^ offset));
413 void *addr = (void *) (pgdptr ^ offset); 412 return (void *)(addr_t)(page->index ? (page->index | offset) : 0UL);
414 struct page *page = virt_to_page(addr);
415 if (!list_empty(&page->lru))
416 return (pgd_t *) ((unsigned long) page->lru.next |
417 offset);
418 }
419 return NULL;
420} 413}
421 414
422/* 415/*
@@ -424,7 +417,8 @@ static inline pgd_t *get_shadow_pgd(pgd_t *pgdp)
424 * within a page table are directly modified. Thus, the following 417 * within a page table are directly modified. Thus, the following
425 * hook is made available. 418 * hook is made available.
426 */ 419 */
427static inline void set_pte(pte_t *pteptr, pte_t pteval) 420static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
421 pte_t *pteptr, pte_t pteval)
428{ 422{
429 pte_t *shadow_pte = get_shadow_pte(pteptr); 423 pte_t *shadow_pte = get_shadow_pte(pteptr);
430 424
@@ -437,7 +431,6 @@ static inline void set_pte(pte_t *pteptr, pte_t pteval)
437 pte_val(*shadow_pte) = _PAGE_TYPE_EMPTY; 431 pte_val(*shadow_pte) = _PAGE_TYPE_EMPTY;
438 } 432 }
439} 433}
440#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
441 434
442/* 435/*
443 * pgd/pmd/pte query functions 436 * pgd/pmd/pte query functions
@@ -448,47 +441,50 @@ static inline int pgd_present(pgd_t pgd) { return 1; }
448static inline int pgd_none(pgd_t pgd) { return 0; } 441static inline int pgd_none(pgd_t pgd) { return 0; }
449static inline int pgd_bad(pgd_t pgd) { return 0; } 442static inline int pgd_bad(pgd_t pgd) { return 0; }
450 443
451static inline int pmd_present(pmd_t pmd) { return pmd_val(pmd) & _SEG_PRESENT; } 444static inline int pud_present(pud_t pud) { return 1; }
452static inline int pmd_none(pmd_t pmd) { return pmd_val(pmd) & _PAGE_TABLE_INV; } 445static inline int pud_none(pud_t pud) { return 0; }
453static inline int pmd_bad(pmd_t pmd) 446static inline int pud_bad(pud_t pud) { return 0; }
454{
455 return (pmd_val(pmd) & (~PAGE_MASK & ~_PAGE_TABLE_INV)) != _PAGE_TABLE;
456}
457 447
458#else /* __s390x__ */ 448#else /* __s390x__ */
459 449
460static inline int pgd_present(pgd_t pgd) 450static inline int pgd_present(pgd_t pgd) { return 1; }
451static inline int pgd_none(pgd_t pgd) { return 0; }
452static inline int pgd_bad(pgd_t pgd) { return 0; }
453
454static inline int pud_present(pud_t pud)
461{ 455{
462 return (pgd_val(pgd) & ~PAGE_MASK) == _PGD_ENTRY; 456 return pud_val(pud) & _REGION_ENTRY_ORIGIN;
463} 457}
464 458
465static inline int pgd_none(pgd_t pgd) 459static inline int pud_none(pud_t pud)
466{ 460{
467 return pgd_val(pgd) & _PGD_ENTRY_INV; 461 return pud_val(pud) & _REGION_ENTRY_INV;
468} 462}
469 463
470static inline int pgd_bad(pgd_t pgd) 464static inline int pud_bad(pud_t pud)
471{ 465{
472 return (pgd_val(pgd) & (~PAGE_MASK & ~_PGD_ENTRY_INV)) != _PGD_ENTRY; 466 unsigned long mask = ~_REGION_ENTRY_ORIGIN & ~_REGION_ENTRY_INV;
467 return (pud_val(pud) & mask) != _REGION3_ENTRY;
473} 468}
474 469
470#endif /* __s390x__ */
471
475static inline int pmd_present(pmd_t pmd) 472static inline int pmd_present(pmd_t pmd)
476{ 473{
477 return (pmd_val(pmd) & ~PAGE_MASK) == _PMD_ENTRY; 474 return pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN;
478} 475}
479 476
480static inline int pmd_none(pmd_t pmd) 477static inline int pmd_none(pmd_t pmd)
481{ 478{
482 return pmd_val(pmd) & _PMD_ENTRY_INV; 479 return pmd_val(pmd) & _SEGMENT_ENTRY_INV;
483} 480}
484 481
485static inline int pmd_bad(pmd_t pmd) 482static inline int pmd_bad(pmd_t pmd)
486{ 483{
487 return (pmd_val(pmd) & (~PAGE_MASK & ~_PMD_ENTRY_INV)) != _PMD_ENTRY; 484 unsigned long mask = ~_SEGMENT_ENTRY_ORIGIN & ~_SEGMENT_ENTRY_INV;
485 return (pmd_val(pmd) & mask) != _SEGMENT_ENTRY;
488} 486}
489 487
490#endif /* __s390x__ */
491
492static inline int pte_none(pte_t pte) 488static inline int pte_none(pte_t pte)
493{ 489{
494 return (pte_val(pte) & _PAGE_INVALID) && !(pte_val(pte) & _PAGE_SWT); 490 return (pte_val(pte) & _PAGE_INVALID) && !(pte_val(pte) & _PAGE_SWT);
@@ -508,7 +504,8 @@ static inline int pte_file(pte_t pte)
508 return (pte_val(pte) & mask) == _PAGE_TYPE_FILE; 504 return (pte_val(pte) & mask) == _PAGE_TYPE_FILE;
509} 505}
510 506
511#define pte_same(a,b) (pte_val(a) == pte_val(b)) 507#define __HAVE_ARCH_PTE_SAME
508#define pte_same(a,b) (pte_val(a) == pte_val(b))
512 509
513/* 510/*
514 * query functions pte_write/pte_dirty/pte_young only work if 511 * query functions pte_write/pte_dirty/pte_young only work if
@@ -543,58 +540,52 @@ static inline int pte_young(pte_t pte)
543 540
544#ifndef __s390x__ 541#ifndef __s390x__
545 542
546static inline void pgd_clear(pgd_t * pgdp) { } 543#define pgd_clear(pgd) do { } while (0)
544#define pud_clear(pud) do { } while (0)
547 545
548static inline void pmd_clear_kernel(pmd_t * pmdp) 546static inline void pmd_clear_kernel(pmd_t * pmdp)
549{ 547{
550 pmd_val(pmdp[0]) = _PAGE_TABLE_INV; 548 pmd_val(pmdp[0]) = _SEGMENT_ENTRY_EMPTY;
551 pmd_val(pmdp[1]) = _PAGE_TABLE_INV; 549 pmd_val(pmdp[1]) = _SEGMENT_ENTRY_EMPTY;
552 pmd_val(pmdp[2]) = _PAGE_TABLE_INV; 550 pmd_val(pmdp[2]) = _SEGMENT_ENTRY_EMPTY;
553 pmd_val(pmdp[3]) = _PAGE_TABLE_INV; 551 pmd_val(pmdp[3]) = _SEGMENT_ENTRY_EMPTY;
554}
555
556static inline void pmd_clear(pmd_t * pmdp)
557{
558 pmd_t *shadow_pmd = get_shadow_pmd(pmdp);
559
560 pmd_clear_kernel(pmdp);
561 if (shadow_pmd)
562 pmd_clear_kernel(shadow_pmd);
563} 552}
564 553
565#else /* __s390x__ */ 554#else /* __s390x__ */
566 555
567static inline void pgd_clear_kernel(pgd_t * pgdp) 556#define pgd_clear(pgd) do { } while (0)
557
558static inline void pud_clear_kernel(pud_t *pud)
568{ 559{
569 pgd_val(*pgdp) = _PGD_ENTRY_INV | _PGD_ENTRY; 560 pud_val(*pud) = _REGION3_ENTRY_EMPTY;
570} 561}
571 562
572static inline void pgd_clear(pgd_t * pgdp) 563static inline void pud_clear(pud_t * pud)
573{ 564{
574 pgd_t *shadow_pgd = get_shadow_pgd(pgdp); 565 pud_t *shadow = get_shadow_table(pud);
575 566
576 pgd_clear_kernel(pgdp); 567 pud_clear_kernel(pud);
577 if (shadow_pgd) 568 if (shadow)
578 pgd_clear_kernel(shadow_pgd); 569 pud_clear_kernel(shadow);
579} 570}
580 571
581static inline void pmd_clear_kernel(pmd_t * pmdp) 572static inline void pmd_clear_kernel(pmd_t * pmdp)
582{ 573{
583 pmd_val(*pmdp) = _PMD_ENTRY_INV | _PMD_ENTRY; 574 pmd_val(*pmdp) = _SEGMENT_ENTRY_EMPTY;
584 pmd_val1(*pmdp) = _PMD_ENTRY_INV | _PMD_ENTRY; 575 pmd_val1(*pmdp) = _SEGMENT_ENTRY_EMPTY;
585} 576}
586 577
578#endif /* __s390x__ */
579
587static inline void pmd_clear(pmd_t * pmdp) 580static inline void pmd_clear(pmd_t * pmdp)
588{ 581{
589 pmd_t *shadow_pmd = get_shadow_pmd(pmdp); 582 pmd_t *shadow_pmd = get_shadow_table(pmdp);
590 583
591 pmd_clear_kernel(pmdp); 584 pmd_clear_kernel(pmdp);
592 if (shadow_pmd) 585 if (shadow_pmd)
593 pmd_clear_kernel(shadow_pmd); 586 pmd_clear_kernel(shadow_pmd);
594} 587}
595 588
596#endif /* __s390x__ */
597
598static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) 589static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
599{ 590{
600 pte_t *shadow_pte = get_shadow_pte(ptep); 591 pte_t *shadow_pte = get_shadow_pte(ptep);
@@ -663,24 +654,19 @@ static inline pte_t pte_mkyoung(pte_t pte)
663 return pte; 654 return pte;
664} 655}
665 656
666static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep) 657#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
658static inline int ptep_test_and_clear_young(struct vm_area_struct *vma,
659 unsigned long addr, pte_t *ptep)
667{ 660{
668 return 0; 661 return 0;
669} 662}
670 663
671static inline int 664#define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
672ptep_clear_flush_young(struct vm_area_struct *vma, 665static inline int ptep_clear_flush_young(struct vm_area_struct *vma,
673 unsigned long address, pte_t *ptep) 666 unsigned long address, pte_t *ptep)
674{ 667{
675 /* No need to flush TLB; bits are in storage key */ 668 /* No need to flush TLB; bits are in storage key */
676 return ptep_test_and_clear_young(vma, address, ptep); 669 return 0;
677}
678
679static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
680{
681 pte_t pte = *ptep;
682 pte_clear(mm, addr, ptep);
683 return pte;
684} 670}
685 671
686static inline void __ptep_ipte(unsigned long address, pte_t *ptep) 672static inline void __ptep_ipte(unsigned long address, pte_t *ptep)
@@ -709,6 +695,32 @@ static inline void ptep_invalidate(unsigned long address, pte_t *ptep)
709 __ptep_ipte(address, ptep); 695 __ptep_ipte(address, ptep);
710} 696}
711 697
698/*
699 * This is hard to understand. ptep_get_and_clear and ptep_clear_flush
700 * both clear the TLB for the unmapped pte. The reason is that
701 * ptep_get_and_clear is used in common code (e.g. change_pte_range)
702 * to modify an active pte. The sequence is
703 * 1) ptep_get_and_clear
704 * 2) set_pte_at
705 * 3) flush_tlb_range
706 * On s390 the tlb needs to get flushed with the modification of the pte
707 * if the pte is active. The only way how this can be implemented is to
708 * have ptep_get_and_clear do the tlb flush. In exchange flush_tlb_range
709 * is a nop.
710 */
711#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
712#define ptep_get_and_clear(__mm, __address, __ptep) \
713({ \
714 pte_t __pte = *(__ptep); \
715 if (atomic_read(&(__mm)->mm_users) > 1 || \
716 (__mm) != current->active_mm) \
717 ptep_invalidate(__address, __ptep); \
718 else \
719 pte_clear((__mm), (__address), (__ptep)); \
720 __pte; \
721})
722
723#define __HAVE_ARCH_PTEP_CLEAR_FLUSH
712static inline pte_t ptep_clear_flush(struct vm_area_struct *vma, 724static inline pte_t ptep_clear_flush(struct vm_area_struct *vma,
713 unsigned long address, pte_t *ptep) 725 unsigned long address, pte_t *ptep)
714{ 726{
@@ -717,12 +729,40 @@ static inline pte_t ptep_clear_flush(struct vm_area_struct *vma,
717 return pte; 729 return pte;
718} 730}
719 731
720static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) 732/*
733 * The batched pte unmap code uses ptep_get_and_clear_full to clear the
734 * ptes. Here an optimization is possible. tlb_gather_mmu flushes all
735 * tlbs of an mm if it can guarantee that the ptes of the mm_struct
736 * cannot be accessed while the batched unmap is running. In this case
737 * full==1 and a simple pte_clear is enough. See tlb.h.
738 */
739#define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL
740static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm,
741 unsigned long addr,
742 pte_t *ptep, int full)
721{ 743{
722 pte_t old_pte = *ptep; 744 pte_t pte = *ptep;
723 set_pte_at(mm, addr, ptep, pte_wrprotect(old_pte)); 745
746 if (full)
747 pte_clear(mm, addr, ptep);
748 else
749 ptep_invalidate(addr, ptep);
750 return pte;
724} 751}
725 752
753#define __HAVE_ARCH_PTEP_SET_WRPROTECT
754#define ptep_set_wrprotect(__mm, __addr, __ptep) \
755({ \
756 pte_t __pte = *(__ptep); \
757 if (pte_write(__pte)) { \
758 if (atomic_read(&(__mm)->mm_users) > 1 || \
759 (__mm) != current->active_mm) \
760 ptep_invalidate(__addr, __ptep); \
761 set_pte_at(__mm, __addr, __ptep, pte_wrprotect(__pte)); \
762 } \
763})
764
765#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
726#define ptep_set_access_flags(__vma, __addr, __ptep, __entry, __dirty) \ 766#define ptep_set_access_flags(__vma, __addr, __ptep, __entry, __dirty) \
727({ \ 767({ \
728 int __changed = !pte_same(*(__ptep), __entry); \ 768 int __changed = !pte_same(*(__ptep), __entry); \
@@ -740,11 +780,13 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
740 * should therefore only be called if it is not mapped in any 780 * should therefore only be called if it is not mapped in any
741 * address space. 781 * address space.
742 */ 782 */
783#define __HAVE_ARCH_PAGE_TEST_DIRTY
743static inline int page_test_dirty(struct page *page) 784static inline int page_test_dirty(struct page *page)
744{ 785{
745 return (page_get_storage_key(page_to_phys(page)) & _PAGE_CHANGED) != 0; 786 return (page_get_storage_key(page_to_phys(page)) & _PAGE_CHANGED) != 0;
746} 787}
747 788
789#define __HAVE_ARCH_PAGE_CLEAR_DIRTY
748static inline void page_clear_dirty(struct page *page) 790static inline void page_clear_dirty(struct page *page)
749{ 791{
750 page_set_storage_key(page_to_phys(page), PAGE_DEFAULT_KEY); 792 page_set_storage_key(page_to_phys(page), PAGE_DEFAULT_KEY);
@@ -753,6 +795,7 @@ static inline void page_clear_dirty(struct page *page)
753/* 795/*
754 * Test and clear referenced bit in storage key. 796 * Test and clear referenced bit in storage key.
755 */ 797 */
798#define __HAVE_ARCH_PAGE_TEST_AND_CLEAR_YOUNG
756static inline int page_test_and_clear_young(struct page *page) 799static inline int page_test_and_clear_young(struct page *page)
757{ 800{
758 unsigned long physpage = page_to_phys(page); 801 unsigned long physpage = page_to_phys(page);
@@ -784,63 +827,48 @@ static inline pte_t mk_pte(struct page *page, pgprot_t pgprot)
784 return mk_pte_phys(physpage, pgprot); 827 return mk_pte_phys(physpage, pgprot);
785} 828}
786 829
787static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot) 830#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
788{ 831#define pud_index(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1))
789 unsigned long physpage = __pa((pfn) << PAGE_SHIFT); 832#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
790 833#define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE-1))
791 return mk_pte_phys(physpage, pgprot);
792}
793
794#ifdef __s390x__
795
796static inline pmd_t pfn_pmd(unsigned long pfn, pgprot_t pgprot)
797{
798 unsigned long physpage = __pa((pfn) << PAGE_SHIFT);
799
800 return __pmd(physpage + pgprot_val(pgprot));
801}
802
803#endif /* __s390x__ */
804
805#define pte_pfn(x) (pte_val(x) >> PAGE_SHIFT)
806#define pte_page(x) pfn_to_page(pte_pfn(x))
807 834
808#define pmd_page_vaddr(pmd) (pmd_val(pmd) & PAGE_MASK) 835#define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address))
836#define pgd_offset_k(address) pgd_offset(&init_mm, address)
809 837
810#define pmd_page(pmd) pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT) 838#ifndef __s390x__
811 839
812#define pgd_page_vaddr(pgd) (pgd_val(pgd) & PAGE_MASK) 840#define pmd_deref(pmd) (pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN)
841#define pud_deref(pmd) ({ BUG(); 0UL; })
842#define pgd_deref(pmd) ({ BUG(); 0UL; })
813 843
814#define pgd_page(pgd) pfn_to_page(pgd_val(pgd) >> PAGE_SHIFT) 844#define pud_offset(pgd, address) ((pud_t *) pgd)
845#define pmd_offset(pud, address) ((pmd_t *) pud + pmd_index(address))
815 846
816/* to find an entry in a page-table-directory */ 847#else /* __s390x__ */
817#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
818#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))
819 848
820/* to find an entry in a kernel page-table-directory */ 849#define pmd_deref(pmd) (pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN)
821#define pgd_offset_k(address) pgd_offset(&init_mm, address) 850#define pud_deref(pud) (pud_val(pud) & _REGION_ENTRY_ORIGIN)
851#define pgd_deref(pgd) ({ BUG(); 0UL; })
822 852
823#ifndef __s390x__ 853#define pud_offset(pgd, address) ((pud_t *) pgd)
824 854
825/* Find an entry in the second-level page table.. */ 855static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address)
826static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
827{ 856{
828 return (pmd_t *) dir; 857 pmd_t *pmd = (pmd_t *) pud_deref(*pud);
858 return pmd + pmd_index(address);
829} 859}
830 860
831#else /* __s390x__ */ 861#endif /* __s390x__ */
832 862
833/* Find an entry in the second-level page table.. */ 863#define pfn_pte(pfn,pgprot) mk_pte_phys(__pa((pfn) << PAGE_SHIFT),(pgprot))
834#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1)) 864#define pte_pfn(x) (pte_val(x) >> PAGE_SHIFT)
835#define pmd_offset(dir,addr) \ 865#define pte_page(x) pfn_to_page(pte_pfn(x))
836 ((pmd_t *) pgd_page_vaddr(*(dir)) + pmd_index(addr))
837 866
838#endif /* __s390x__ */ 867#define pmd_page(pmd) pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT)
839 868
840/* Find an entry in the third-level page table.. */ 869/* Find an entry in the lowest level page table.. */
841#define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE-1)) 870#define pte_offset(pmd, addr) ((pte_t *) pmd_deref(*(pmd)) + pte_index(addr))
842#define pte_offset_kernel(pmd, address) \ 871#define pte_offset_kernel(pmd, address) pte_offset(pmd,address)
843 ((pte_t *) pmd_page_vaddr(*(pmd)) + pte_index(address))
844#define pte_offset_map(pmd, address) pte_offset_kernel(pmd, address) 872#define pte_offset_map(pmd, address) pte_offset_kernel(pmd, address)
845#define pte_offset_map_nested(pmd, address) pte_offset_kernel(pmd, address) 873#define pte_offset_map_nested(pmd, address) pte_offset_kernel(pmd, address)
846#define pte_unmap(pte) do { } while (0) 874#define pte_unmap(pte) do { } while (0)
@@ -930,17 +958,6 @@ extern int remove_shared_memory(unsigned long start, unsigned long size);
930#define __HAVE_ARCH_MEMMAP_INIT 958#define __HAVE_ARCH_MEMMAP_INIT
931extern void memmap_init(unsigned long, int, unsigned long, unsigned long); 959extern void memmap_init(unsigned long, int, unsigned long, unsigned long);
932 960
933#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
934#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
935#define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
936#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
937#define __HAVE_ARCH_PTEP_CLEAR_FLUSH
938#define __HAVE_ARCH_PTEP_SET_WRPROTECT
939#define __HAVE_ARCH_PTE_SAME
940#define __HAVE_ARCH_PAGE_TEST_DIRTY
941#define __HAVE_ARCH_PAGE_CLEAR_DIRTY
942#define __HAVE_ARCH_PAGE_TEST_AND_CLEAR_YOUNG
943#include <asm-generic/pgtable.h> 961#include <asm-generic/pgtable.h>
944 962
945#endif /* _S390_PAGE_H */ 963#endif /* _S390_PAGE_H */
946
diff --git a/include/asm-s390/processor.h b/include/asm-s390/processor.h
index 3b972d4c6b29..21d40a19355e 100644
--- a/include/asm-s390/processor.h
+++ b/include/asm-s390/processor.h
@@ -93,7 +93,6 @@ struct thread_struct {
93 s390_fp_regs fp_regs; 93 s390_fp_regs fp_regs;
94 unsigned int acrs[NUM_ACRS]; 94 unsigned int acrs[NUM_ACRS];
95 unsigned long ksp; /* kernel stack pointer */ 95 unsigned long ksp; /* kernel stack pointer */
96 unsigned long user_seg; /* HSTD */
97 mm_segment_t mm_segment; 96 mm_segment_t mm_segment;
98 unsigned long prot_addr; /* address of protection-excep. */ 97 unsigned long prot_addr; /* address of protection-excep. */
99 unsigned int error_code; /* error-code of last prog-excep. */ 98 unsigned int error_code; /* error-code of last prog-excep. */
@@ -128,22 +127,9 @@ struct stack_frame {
128 127
129#define ARCH_MIN_TASKALIGN 8 128#define ARCH_MIN_TASKALIGN 8
130 129
131#ifndef __s390x__ 130#define INIT_THREAD { \
132# define __SWAPPER_PG_DIR __pa(&swapper_pg_dir[0]) + _SEGMENT_TABLE 131 .ksp = sizeof(init_stack) + (unsigned long) &init_stack, \
133#else /* __s390x__ */ 132}
134# define __SWAPPER_PG_DIR __pa(&swapper_pg_dir[0]) + _REGION_TABLE
135#endif /* __s390x__ */
136
137#define INIT_THREAD {{0,{{0},{0},{0},{0},{0},{0},{0},{0},{0},{0}, \
138 {0},{0},{0},{0},{0},{0}}}, \
139 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
140 sizeof(init_stack) + (unsigned long) &init_stack, \
141 __SWAPPER_PG_DIR, \
142 {0}, \
143 0,0,0, \
144 (per_struct) {{{{0,}}},0,0,0,0,{{0,}}}, \
145 0, 0 \
146}
147 133
148/* 134/*
149 * Do necessary setup to start up a new thread. 135 * Do necessary setup to start up a new thread.
diff --git a/include/asm-s390/tlb.h b/include/asm-s390/tlb.h
index 51bd957b85bd..618693cfc10f 100644
--- a/include/asm-s390/tlb.h
+++ b/include/asm-s390/tlb.h
@@ -2,19 +2,130 @@
2#define _S390_TLB_H 2#define _S390_TLB_H
3 3
4/* 4/*
5 * s390 doesn't need any special per-pte or 5 * TLB flushing on s390 is complicated. The following requirement
6 * per-vma handling.. 6 * from the principles of operation is the most arduous:
7 *
8 * "A valid table entry must not be changed while it is attached
9 * to any CPU and may be used for translation by that CPU except to
10 * (1) invalidate the entry by using INVALIDATE PAGE TABLE ENTRY,
11 * or INVALIDATE DAT TABLE ENTRY, (2) alter bits 56-63 of a page
12 * table entry, or (3) make a change by means of a COMPARE AND SWAP
13 * AND PURGE instruction that purges the TLB."
14 *
15 * The modification of a pte of an active mm struct therefore is
16 * a two step process: i) invalidate the pte, ii) store the new pte.
17 * This is true for the page protection bit as well.
18 * The only possible optimization is to flush at the beginning of
19 * a tlb_gather_mmu cycle if the mm_struct is currently not in use.
20 *
21 * Pages used for the page tables is a different story. FIXME: more
7 */ 22 */
8#define tlb_start_vma(tlb, vma) do { } while (0) 23
9#define tlb_end_vma(tlb, vma) do { } while (0) 24#include <linux/mm.h>
10#define __tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0) 25#include <linux/swap.h>
26#include <asm/processor.h>
27#include <asm/pgalloc.h>
28#include <asm/smp.h>
29#include <asm/tlbflush.h>
30
31#ifndef CONFIG_SMP
32#define TLB_NR_PTRS 1
33#else
34#define TLB_NR_PTRS 508
35#endif
36
37struct mmu_gather {
38 struct mm_struct *mm;
39 unsigned int fullmm;
40 unsigned int nr_ptes;
41 unsigned int nr_pmds;
42 void *array[TLB_NR_PTRS];
43};
44
45DECLARE_PER_CPU(struct mmu_gather, mmu_gathers);
46
47static inline struct mmu_gather *tlb_gather_mmu(struct mm_struct *mm,
48 unsigned int full_mm_flush)
49{
50 struct mmu_gather *tlb = &get_cpu_var(mmu_gathers);
51
52 tlb->mm = mm;
53 tlb->fullmm = full_mm_flush || (num_online_cpus() == 1) ||
54 (atomic_read(&mm->mm_users) <= 1 && mm == current->active_mm);
55 tlb->nr_ptes = 0;
56 tlb->nr_pmds = TLB_NR_PTRS;
57 if (tlb->fullmm)
58 __tlb_flush_mm(mm);
59 return tlb;
60}
61
62static inline void tlb_flush_mmu(struct mmu_gather *tlb,
63 unsigned long start, unsigned long end)
64{
65 if (!tlb->fullmm && (tlb->nr_ptes > 0 || tlb->nr_pmds < TLB_NR_PTRS))
66 __tlb_flush_mm(tlb->mm);
67 while (tlb->nr_ptes > 0)
68 pte_free(tlb->array[--tlb->nr_ptes]);
69 while (tlb->nr_pmds < TLB_NR_PTRS)
70 pmd_free((pmd_t *) tlb->array[tlb->nr_pmds++]);
71}
72
73static inline void tlb_finish_mmu(struct mmu_gather *tlb,
74 unsigned long start, unsigned long end)
75{
76 tlb_flush_mmu(tlb, start, end);
77
78 /* keep the page table cache within bounds */
79 check_pgt_cache();
80
81 put_cpu_var(mmu_gathers);
82}
11 83
12/* 84/*
13 * .. because we flush the whole mm when it 85 * Release the page cache reference for a pte removed by
14 * fills up. 86 * tlb_ptep_clear_flush. In both flush modes the tlb fo a page cache page
87 * has already been freed, so just do free_page_and_swap_cache.
15 */ 88 */
16#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm) 89static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)
90{
91 free_page_and_swap_cache(page);
92}
17 93
18#include <asm-generic/tlb.h> 94/*
95 * pte_free_tlb frees a pte table and clears the CRSTE for the
96 * page table from the tlb.
97 */
98static inline void pte_free_tlb(struct mmu_gather *tlb, struct page *page)
99{
100 if (!tlb->fullmm) {
101 tlb->array[tlb->nr_ptes++] = page;
102 if (tlb->nr_ptes >= tlb->nr_pmds)
103 tlb_flush_mmu(tlb, 0, 0);
104 } else
105 pte_free(page);
106}
19 107
108/*
109 * pmd_free_tlb frees a pmd table and clears the CRSTE for the
110 * segment table entry from the tlb.
111 */
112static inline void pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
113{
114#ifdef __s390x__
115 if (!tlb->fullmm) {
116 tlb->array[--tlb->nr_pmds] = (struct page *) pmd;
117 if (tlb->nr_ptes >= tlb->nr_pmds)
118 tlb_flush_mmu(tlb, 0, 0);
119 } else
120 pmd_free(pmd);
20#endif 121#endif
122}
123
124#define pud_free_tlb(tlb, pud) do { } while (0)
125
126#define tlb_start_vma(tlb, vma) do { } while (0)
127#define tlb_end_vma(tlb, vma) do { } while (0)
128#define tlb_remove_tlb_entry(tlb, ptep, addr) do { } while (0)
129#define tlb_migrate_finish(mm) do { } while (0)
130
131#endif /* _S390_TLB_H */
diff --git a/include/asm-s390/tlbflush.h b/include/asm-s390/tlbflush.h
index 6de2632a3e4f..a69bd2490d52 100644
--- a/include/asm-s390/tlbflush.h
+++ b/include/asm-s390/tlbflush.h
@@ -6,68 +6,19 @@
6#include <asm/pgalloc.h> 6#include <asm/pgalloc.h>
7 7
8/* 8/*
9 * TLB flushing: 9 * Flush all tlb entries on the local cpu.
10 *
11 * - flush_tlb() flushes the current mm struct TLBs
12 * - flush_tlb_all() flushes all processes TLBs
13 * - flush_tlb_mm(mm) flushes the specified mm context TLB's
14 * - flush_tlb_page(vma, vmaddr) flushes one page
15 * - flush_tlb_range(vma, start, end) flushes a range of pages
16 * - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
17 */
18
19/*
20 * S/390 has three ways of flushing TLBs
21 * 'ptlb' does a flush of the local processor
22 * 'csp' flushes the TLBs on all PUs of a SMP
23 * 'ipte' invalidates a pte in a page table and flushes that out of
24 * the TLBs of all PUs of a SMP
25 */
26
27#define local_flush_tlb() \
28do { asm volatile("ptlb": : :"memory"); } while (0)
29
30#ifndef CONFIG_SMP
31
32/*
33 * We always need to flush, since s390 does not flush tlb
34 * on each context switch
35 */ 10 */
36 11static inline void __tlb_flush_local(void)
37static inline void flush_tlb(void)
38{ 12{
39 local_flush_tlb(); 13 asm volatile("ptlb" : : : "memory");
40} 14}
41static inline void flush_tlb_all(void)
42{
43 local_flush_tlb();
44}
45static inline void flush_tlb_mm(struct mm_struct *mm)
46{
47 local_flush_tlb();
48}
49static inline void flush_tlb_page(struct vm_area_struct *vma,
50 unsigned long addr)
51{
52 local_flush_tlb();
53}
54static inline void flush_tlb_range(struct vm_area_struct *vma,
55 unsigned long start, unsigned long end)
56{
57 local_flush_tlb();
58}
59
60#define flush_tlb_kernel_range(start, end) \
61 local_flush_tlb();
62
63#else
64 15
65#include <asm/smp.h> 16/*
66 17 * Flush all tlb entries on all cpus.
67extern void smp_ptlb_all(void); 18 */
68 19static inline void __tlb_flush_global(void)
69static inline void global_flush_tlb(void)
70{ 20{
21 extern void smp_ptlb_all(void);
71 register unsigned long reg2 asm("2"); 22 register unsigned long reg2 asm("2");
72 register unsigned long reg3 asm("3"); 23 register unsigned long reg3 asm("3");
73 register unsigned long reg4 asm("4"); 24 register unsigned long reg4 asm("4");
@@ -89,66 +40,75 @@ static inline void global_flush_tlb(void)
89} 40}
90 41
91/* 42/*
92 * We only have to do global flush of tlb if process run since last 43 * Flush all tlb entries of a page table on all cpus.
93 * flush on any other pu than current.
94 * If we have threads (mm->count > 1) we always do a global flush,
95 * since the process runs on more than one processor at the same time.
96 */ 44 */
45static inline void __tlb_flush_idte(pgd_t *pgd)
46{
47 asm volatile(
48 " .insn rrf,0xb98e0000,0,%0,%1,0"
49 : : "a" (2048), "a" (__pa(pgd) & PAGE_MASK) : "cc" );
50}
97 51
98static inline void __flush_tlb_mm(struct mm_struct * mm) 52static inline void __tlb_flush_mm(struct mm_struct * mm)
99{ 53{
100 cpumask_t local_cpumask; 54 cpumask_t local_cpumask;
101 55
102 if (unlikely(cpus_empty(mm->cpu_vm_mask))) 56 if (unlikely(cpus_empty(mm->cpu_vm_mask)))
103 return; 57 return;
58 /*
59 * If the machine has IDTE we prefer to do a per mm flush
60 * on all cpus instead of doing a local flush if the mm
61 * only ran on the local cpu.
62 */
104 if (MACHINE_HAS_IDTE) { 63 if (MACHINE_HAS_IDTE) {
105 pgd_t *shadow_pgd = get_shadow_pgd(mm->pgd); 64 pgd_t *shadow_pgd = get_shadow_table(mm->pgd);
106 65
107 if (shadow_pgd) { 66 if (shadow_pgd)
108 asm volatile( 67 __tlb_flush_idte(shadow_pgd);
109 " .insn rrf,0xb98e0000,0,%0,%1,0" 68 __tlb_flush_idte(mm->pgd);
110 : : "a" (2048),
111 "a" (__pa(shadow_pgd) & PAGE_MASK) : "cc" );
112 }
113 asm volatile(
114 " .insn rrf,0xb98e0000,0,%0,%1,0"
115 : : "a" (2048), "a" (__pa(mm->pgd)&PAGE_MASK) : "cc");
116 return; 69 return;
117 } 70 }
118 preempt_disable(); 71 preempt_disable();
72 /*
73 * If the process only ran on the local cpu, do a local flush.
74 */
119 local_cpumask = cpumask_of_cpu(smp_processor_id()); 75 local_cpumask = cpumask_of_cpu(smp_processor_id());
120 if (cpus_equal(mm->cpu_vm_mask, local_cpumask)) 76 if (cpus_equal(mm->cpu_vm_mask, local_cpumask))
121 local_flush_tlb(); 77 __tlb_flush_local();
122 else 78 else
123 global_flush_tlb(); 79 __tlb_flush_global();
124 preempt_enable(); 80 preempt_enable();
125} 81}
126 82
127static inline void flush_tlb(void) 83static inline void __tlb_flush_mm_cond(struct mm_struct * mm)
128{
129 __flush_tlb_mm(current->mm);
130}
131static inline void flush_tlb_all(void)
132{
133 global_flush_tlb();
134}
135static inline void flush_tlb_mm(struct mm_struct *mm)
136{
137 __flush_tlb_mm(mm);
138}
139static inline void flush_tlb_page(struct vm_area_struct *vma,
140 unsigned long addr)
141{
142 __flush_tlb_mm(vma->vm_mm);
143}
144static inline void flush_tlb_range(struct vm_area_struct *vma,
145 unsigned long start, unsigned long end)
146{ 84{
147 __flush_tlb_mm(vma->vm_mm); 85 if (atomic_read(&mm->mm_users) <= 1 && mm == current->active_mm)
86 __tlb_flush_mm(mm);
148} 87}
149 88
150#define flush_tlb_kernel_range(start, end) global_flush_tlb() 89/*
90 * TLB flushing:
91 * flush_tlb() - flushes the current mm struct TLBs
92 * flush_tlb_all() - flushes all processes TLBs
93 * flush_tlb_mm(mm) - flushes the specified mm context TLB's
94 * flush_tlb_page(vma, vmaddr) - flushes one page
95 * flush_tlb_range(vma, start, end) - flushes a range of pages
96 * flush_tlb_kernel_range(start, end) - flushes a range of kernel pages
97 */
151 98
152#endif 99/*
100 * flush_tlb_mm goes together with ptep_set_wrprotect for the
101 * copy_page_range operation and flush_tlb_range is related to
102 * ptep_get_and_clear for change_protection. ptep_set_wrprotect and
103 * ptep_get_and_clear do not flush the TLBs directly if the mm has
104 * only one user. At the end of the update the flush_tlb_mm and
105 * flush_tlb_range functions need to do the flush.
106 */
107#define flush_tlb() do { } while (0)
108#define flush_tlb_all() do { } while (0)
109#define flush_tlb_mm(mm) __tlb_flush_mm_cond(mm)
110#define flush_tlb_page(vma, addr) do { } while (0)
111#define flush_tlb_range(vma, start, end) __tlb_flush_mm_cond(mm)
112#define flush_tlb_kernel_range(start, end) __tlb_flush_mm(&init_mm)
153 113
154#endif /* _S390_TLBFLUSH_H */ 114#endif /* _S390_TLBFLUSH_H */