summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-03-26 16:04:22 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2009-03-26 16:04:22 -0700
commit21cdbc1378e8aa96e1ed4a606dce1a8e7daf7fdf (patch)
tree55b6c294b912ccdc3eede15960b0ece53a69d902 /arch
parent86d9c070175de65890794fa227b68297da6206d8 (diff)
parentef3500b2b2955af4fa6b0564b51c0c604e38c571 (diff)
Merge branch 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6
* 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6: (81 commits) [S390] remove duplicated #includes [S390] cpumask: use mm_cpumask() wrapper [S390] cpumask: Use accessors code. [S390] cpumask: prepare for iterators to only go to nr_cpu_ids/nr_cpumask_bits. [S390] cpumask: remove cpu_coregroup_map [S390] fix clock comparator save area usage [S390] Add hwcap flag for the etf3 enhancement facility [S390] Ensure that ipl panic notifier is called late. [S390] fix dfp elf hwcap/facility bit detection [S390] smp: perform initial cpu reset before starting a cpu [S390] smp: fix memory leak on __cpu_up [S390] ipl: Improve checking logic and remove switch defaults. [S390] s390dbf: Remove needless check for NULL pointer. [S390] s390dbf: Remove redundant initilizations. [S390] use kzfree() [S390] BUG to BUG_ON changes [S390] zfcpdump: Prevent zcore from beeing built as a kernel module. [S390] Use csum_partial in checksum.h [S390] cleanup lowcore.h [S390] eliminate ipl_device from lowcore ...
Diffstat (limited to 'arch')
-rw-r--r--arch/s390/Kconfig11
-rw-r--r--arch/s390/crypto/prng.c3
-rw-r--r--arch/s390/include/asm/bitops.h14
-rw-r--r--arch/s390/include/asm/crw.h68
-rw-r--r--arch/s390/include/asm/dasd.h10
-rw-r--r--arch/s390/include/asm/idals.h17
-rw-r--r--arch/s390/include/asm/lowcore.h653
-rw-r--r--arch/s390/include/asm/mmu_context.h2
-rw-r--r--arch/s390/include/asm/nmi.h66
-rw-r--r--arch/s390/include/asm/processor.h16
-rw-r--r--arch/s390/include/asm/ptrace.h4
-rw-r--r--arch/s390/include/asm/qdio.h1
-rw-r--r--arch/s390/include/asm/smp.h7
-rw-r--r--arch/s390/include/asm/string.h16
-rw-r--r--arch/s390/include/asm/sysinfo.h1
-rw-r--r--arch/s390/include/asm/tlbflush.h4
-rw-r--r--arch/s390/include/asm/topology.h1
-rw-r--r--arch/s390/include/asm/vtoc.h16
-rw-r--r--arch/s390/kernel/Makefile4
-rw-r--r--arch/s390/kernel/bitmap.S56
-rw-r--r--arch/s390/kernel/bitmap.c54
-rw-r--r--arch/s390/kernel/compat_ptrace.h3
-rw-r--r--arch/s390/kernel/debug.c9
-rw-r--r--arch/s390/kernel/early.c23
-rw-r--r--arch/s390/kernel/head.S2
-rw-r--r--arch/s390/kernel/head31.S1
-rw-r--r--arch/s390/kernel/head64.S1
-rw-r--r--arch/s390/kernel/ipl.c74
-rw-r--r--arch/s390/kernel/module.c19
-rw-r--r--arch/s390/kernel/nmi.c376
-rw-r--r--arch/s390/kernel/process.c73
-rw-r--r--arch/s390/kernel/processor.c73
-rw-r--r--arch/s390/kernel/reipl64.S11
-rw-r--r--arch/s390/kernel/s390_ksyms.c44
-rw-r--r--arch/s390/kernel/setup.c52
-rw-r--r--arch/s390/kernel/smp.c68
-rw-r--r--arch/s390/kernel/sysinfo.c428
-rw-r--r--arch/s390/kernel/time.c71
-rw-r--r--arch/s390/kernel/topology.c2
-rw-r--r--arch/s390/kernel/traps.c4
-rw-r--r--arch/s390/kernel/vdso.c2
-rw-r--r--arch/s390/kernel/vmlinux.lds.S2
-rw-r--r--arch/s390/kvm/kvm-s390.c6
-rw-r--r--arch/s390/lib/delay.c2
-rw-r--r--arch/s390/lib/string.c8
-rw-r--r--arch/s390/mm/fault.c28
-rw-r--r--arch/s390/mm/init.c2
-rw-r--r--arch/s390/mm/pgtable.c6
48 files changed, 1688 insertions, 726 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 6b0a3538dc63..2a8af5e16345 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -343,13 +343,6 @@ source "mm/Kconfig"
comment "I/O subsystem configuration"
-config MACHCHK_WARNING
- bool "Process warning machine checks"
- help
- Select this option if you want the machine check handler on IBM S/390 or
- zSeries to process warning machine checks (e.g. on power failures).
- If unsure, say "Y".
-
config QDIO
tristate "QDIO support"
---help---
@@ -521,7 +514,7 @@ config APPLDATA_OS
config APPLDATA_NET_SUM
tristate "Monitor overall network statistics"
- depends on APPLDATA_BASE
+ depends on APPLDATA_BASE && NET
help
This provides network related data to the Linux - VM Monitor Stream,
currently there is only a total sum of network I/O statistics, no
@@ -552,7 +545,7 @@ config KEXEC
but is independent of hardware/microcode support.
config ZFCPDUMP
- tristate "zfcpdump support"
+ bool "zfcpdump support"
select SMP
default n
help
diff --git a/arch/s390/crypto/prng.c b/arch/s390/crypto/prng.c
index eca724d229ec..b49c00ce65e9 100644
--- a/arch/s390/crypto/prng.c
+++ b/arch/s390/crypto/prng.c
@@ -201,8 +201,7 @@ out_free:
static void __exit prng_exit(void)
{
/* wipe me */
- memset(p->buf, 0, prng_chunk_size);
- kfree(p->buf);
+ kzfree(p->buf);
kfree(p);
misc_deregister(&prng_dev);
diff --git a/arch/s390/include/asm/bitops.h b/arch/s390/include/asm/bitops.h
index 8e9243ae0c19..b30606f6d523 100644
--- a/arch/s390/include/asm/bitops.h
+++ b/arch/s390/include/asm/bitops.h
@@ -57,7 +57,7 @@
* with operation of the form "set_bit(bitnr, flags)".
*/
-/* bitmap tables from arch/S390/kernel/bitmap.S */
+/* bitmap tables from arch/s390/kernel/bitmap.c */
extern const char _oi_bitmap[];
extern const char _ni_bitmap[];
extern const char _zb_findmap[];
@@ -525,16 +525,16 @@ static inline unsigned long __ffs_word_loop(const unsigned long *addr,
static inline unsigned long __ffz_word(unsigned long nr, unsigned long word)
{
#ifdef __s390x__
- if (likely((word & 0xffffffff) == 0xffffffff)) {
+ if ((word & 0xffffffff) == 0xffffffff) {
word >>= 32;
nr += 32;
}
#endif
- if (likely((word & 0xffff) == 0xffff)) {
+ if ((word & 0xffff) == 0xffff) {
word >>= 16;
nr += 16;
}
- if (likely((word & 0xff) == 0xff)) {
+ if ((word & 0xff) == 0xff) {
word >>= 8;
nr += 8;
}
@@ -549,16 +549,16 @@ static inline unsigned long __ffz_word(unsigned long nr, unsigned long word)
static inline unsigned long __ffs_word(unsigned long nr, unsigned long word)
{
#ifdef __s390x__
- if (likely((word & 0xffffffff) == 0)) {
+ if ((word & 0xffffffff) == 0) {
word >>= 32;
nr += 32;
}
#endif
- if (likely((word & 0xffff) == 0)) {
+ if ((word & 0xffff) == 0) {
word >>= 16;
nr += 16;
}
- if (likely((word & 0xff) == 0)) {
+ if ((word & 0xff) == 0) {
word >>= 8;
nr += 8;
}
diff --git a/arch/s390/include/asm/crw.h b/arch/s390/include/asm/crw.h
new file mode 100644
index 000000000000..2185a6d619d3
--- /dev/null
+++ b/arch/s390/include/asm/crw.h
@@ -0,0 +1,68 @@
+/*
+ * Data definitions for channel report processing
+ * Copyright IBM Corp. 2000,2009
+ * Author(s): Ingo Adlung <adlung@de.ibm.com>,
+ * Martin Schwidefsky <schwidefsky@de.ibm.com>,
+ * Cornelia Huck <cornelia.huck@de.ibm.com>,
+ * Heiko Carstens <heiko.carstens@de.ibm.com>,
+ */
+
+#ifndef _ASM_S390_CRW_H
+#define _ASM_S390_CRW_H
+
+#include <linux/types.h>
+
+/*
+ * Channel Report Word
+ */
+struct crw {
+ __u32 res1 : 1; /* reserved zero */
+ __u32 slct : 1; /* solicited */
+ __u32 oflw : 1; /* overflow */
+ __u32 chn : 1; /* chained */
+ __u32 rsc : 4; /* reporting source code */
+ __u32 anc : 1; /* ancillary report */
+ __u32 res2 : 1; /* reserved zero */
+ __u32 erc : 6; /* error-recovery code */
+ __u32 rsid : 16; /* reporting-source ID */
+} __attribute__ ((packed));
+
+typedef void (*crw_handler_t)(struct crw *, struct crw *, int);
+
+extern int crw_register_handler(int rsc, crw_handler_t handler);
+extern void crw_unregister_handler(int rsc);
+extern void crw_handle_channel_report(void);
+
+#define NR_RSCS 16
+
+#define CRW_RSC_MONITOR 0x2 /* monitoring facility */
+#define CRW_RSC_SCH 0x3 /* subchannel */
+#define CRW_RSC_CPATH 0x4 /* channel path */
+#define CRW_RSC_CONFIG 0x9 /* configuration-alert facility */
+#define CRW_RSC_CSS 0xB /* channel subsystem */
+
+#define CRW_ERC_EVENT 0x00 /* event information pending */
+#define CRW_ERC_AVAIL 0x01 /* available */
+#define CRW_ERC_INIT 0x02 /* initialized */
+#define CRW_ERC_TERROR 0x03 /* temporary error */
+#define CRW_ERC_IPARM 0x04 /* installed parm initialized */
+#define CRW_ERC_TERM 0x05 /* terminal */
+#define CRW_ERC_PERRN 0x06 /* perm. error, fac. not init */
+#define CRW_ERC_PERRI 0x07 /* perm. error, facility init */
+#define CRW_ERC_PMOD 0x08 /* installed parameters modified */
+
+static inline int stcrw(struct crw *pcrw)
+{
+ int ccode;
+
+ asm volatile(
+ " stcrw 0(%2)\n"
+ " ipm %0\n"
+ " srl %0,28\n"
+ : "=d" (ccode), "=m" (*pcrw)
+ : "a" (pcrw)
+ : "cc" );
+ return ccode;
+}
+
+#endif /* _ASM_S390_CRW_H */
diff --git a/arch/s390/include/asm/dasd.h b/arch/s390/include/asm/dasd.h
index e2db6f16d9c8..218bce81ec70 100644
--- a/arch/s390/include/asm/dasd.h
+++ b/arch/s390/include/asm/dasd.h
@@ -162,15 +162,15 @@ typedef struct dasd_profile_info_t {
unsigned int dasd_io_nr_req[32]; /* histogram of # of requests in chanq */
} dasd_profile_info_t;
-/*
+/*
* struct format_data_t
* represents all data necessary to format a dasd
*/
typedef struct format_data_t {
- int start_unit; /* from track */
- int stop_unit; /* to track */
- int blksize; /* sectorsize */
- int intensity;
+ unsigned int start_unit; /* from track */
+ unsigned int stop_unit; /* to track */
+ unsigned int blksize; /* sectorsize */
+ unsigned int intensity;
} format_data_t;
/*
diff --git a/arch/s390/include/asm/idals.h b/arch/s390/include/asm/idals.h
index e82c10efe65a..aae276d00383 100644
--- a/arch/s390/include/asm/idals.h
+++ b/arch/s390/include/asm/idals.h
@@ -44,24 +44,18 @@ idal_is_needed(void *vaddr, unsigned int length)
/*
* Return the number of idal words needed for an address/length pair.
*/
-static inline unsigned int
-idal_nr_words(void *vaddr, unsigned int length)
+static inline unsigned int idal_nr_words(void *vaddr, unsigned int length)
{
-#ifdef __s390x__
- if (idal_is_needed(vaddr, length))
- return ((__pa(vaddr) & (IDA_BLOCK_SIZE-1)) + length +
- (IDA_BLOCK_SIZE-1)) >> IDA_SIZE_LOG;
-#endif
- return 0;
+ return ((__pa(vaddr) & (IDA_BLOCK_SIZE-1)) + length +
+ (IDA_BLOCK_SIZE-1)) >> IDA_SIZE_LOG;
}
/*
* Create the list of idal words for an address/length pair.
*/
-static inline unsigned long *
-idal_create_words(unsigned long *idaws, void *vaddr, unsigned int length)
+static inline unsigned long *idal_create_words(unsigned long *idaws,
+ void *vaddr, unsigned int length)
{
-#ifdef __s390x__
unsigned long paddr;
unsigned int cidaw;
@@ -74,7 +68,6 @@ idal_create_words(unsigned long *idaws, void *vaddr, unsigned int length)
paddr += IDA_BLOCK_SIZE;
*idaws++ = paddr;
}
-#endif
return idaws;
}
diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h
index f3720defdd16..b349f1c7fdfa 100644
--- a/arch/s390/include/asm/lowcore.h
+++ b/arch/s390/include/asm/lowcore.h
@@ -11,129 +11,118 @@
#ifndef _ASM_S390_LOWCORE_H
#define _ASM_S390_LOWCORE_H
-#ifndef __s390x__
-#define __LC_EXT_OLD_PSW 0x018
-#define __LC_SVC_OLD_PSW 0x020
-#define __LC_PGM_OLD_PSW 0x028
-#define __LC_MCK_OLD_PSW 0x030
-#define __LC_IO_OLD_PSW 0x038
-#define __LC_EXT_NEW_PSW 0x058
-#define __LC_SVC_NEW_PSW 0x060
-#define __LC_PGM_NEW_PSW 0x068
-#define __LC_MCK_NEW_PSW 0x070
-#define __LC_IO_NEW_PSW 0x078
-#else /* !__s390x__ */
-#define __LC_EXT_OLD_PSW 0x0130
-#define __LC_SVC_OLD_PSW 0x0140
-#define __LC_PGM_OLD_PSW 0x0150
-#define __LC_MCK_OLD_PSW 0x0160
-#define __LC_IO_OLD_PSW 0x0170
-#define __LC_EXT_NEW_PSW 0x01b0
-#define __LC_SVC_NEW_PSW 0x01c0
-#define __LC_PGM_NEW_PSW 0x01d0
-#define __LC_MCK_NEW_PSW 0x01e0
-#define __LC_IO_NEW_PSW 0x01f0
-#endif /* !__s390x__ */
-
-#define __LC_IPL_PARMBLOCK_PTR 0x014
-#define __LC_EXT_PARAMS 0x080
-#define __LC_CPU_ADDRESS 0x084
-#define __LC_EXT_INT_CODE 0x086
-
-#define __LC_SVC_ILC 0x088
-#define __LC_SVC_INT_CODE 0x08A
-#define __LC_PGM_ILC 0x08C
-#define __LC_PGM_INT_CODE 0x08E
+#define __LC_IPL_PARMBLOCK_PTR 0x0014
+#define __LC_EXT_PARAMS 0x0080
+#define __LC_CPU_ADDRESS 0x0084
+#define __LC_EXT_INT_CODE 0x0086
-#define __LC_PER_ATMID 0x096
-#define __LC_PER_ADDRESS 0x098
-#define __LC_PER_ACCESS_ID 0x0A1
-#define __LC_AR_MODE_ID 0x0A3
+#define __LC_SVC_ILC 0x0088
+#define __LC_SVC_INT_CODE 0x008a
+#define __LC_PGM_ILC 0x008c
+#define __LC_PGM_INT_CODE 0x008e
-#define __LC_SUBCHANNEL_ID 0x0B8
-#define __LC_SUBCHANNEL_NR 0x0BA
-#define __LC_IO_INT_PARM 0x0BC
-#define __LC_IO_INT_WORD 0x0C0
-#define __LC_MCCK_CODE 0x0E8
+#define __LC_PER_ATMID 0x0096
+#define __LC_PER_ADDRESS 0x0098
+#define __LC_PER_ACCESS_ID 0x00a1
+#define __LC_AR_MODE_ID 0x00a3
-#define __LC_LAST_BREAK 0x110
-
-#define __LC_RETURN_PSW 0x200
-
-#define __LC_SAVE_AREA 0xC00
-
-#ifndef __s390x__
-#define __LC_IRB 0x208
-#define __LC_SYNC_ENTER_TIMER 0x248
-#define __LC_ASYNC_ENTER_TIMER 0x250
-#define __LC_EXIT_TIMER 0x258
-#define __LC_USER_TIMER 0x260
-#define __LC_SYSTEM_TIMER 0x268
-#define __LC_STEAL_TIMER 0x270
-#define __LC_LAST_UPDATE_TIMER 0x278
-#define __LC_LAST_UPDATE_CLOCK 0x280
-#define __LC_RETURN_MCCK_PSW 0x288
-#define __LC_KERNEL_STACK 0xC40
-#define __LC_THREAD_INFO 0xC44
-#define __LC_ASYNC_STACK 0xC48
-#define __LC_KERNEL_ASCE 0xC4C
-#define __LC_USER_ASCE 0xC50
-#define __LC_PANIC_STACK 0xC54
-#define __LC_CPUID 0xC60
-#define __LC_CPUADDR 0xC68
-#define __LC_IPLDEV 0xC7C
-#define __LC_CURRENT 0xC90
-#define __LC_INT_CLOCK 0xC98
-#else /* __s390x__ */
-#define __LC_IRB 0x210
-#define __LC_SYNC_ENTER_TIMER 0x250
-#define __LC_ASYNC_ENTER_TIMER 0x258
-#define __LC_EXIT_TIMER 0x260
-#define __LC_USER_TIMER 0x268
-#define __LC_SYSTEM_TIMER 0x270
-#define __LC_STEAL_TIMER 0x278
-#define __LC_LAST_UPDATE_TIMER 0x280
-#define __LC_LAST_UPDATE_CLOCK 0x288
-#define __LC_RETURN_MCCK_PSW 0x290
-#define __LC_KERNEL_STACK 0xD40
-#define __LC_THREAD_INFO 0xD48
-#define __LC_ASYNC_STACK 0xD50
-#define __LC_KERNEL_ASCE 0xD58
-#define __LC_USER_ASCE 0xD60
-#define __LC_PANIC_STACK 0xD68
-#define __LC_CPUID 0xD80
-#define __LC_CPUADDR 0xD88
-#define __LC_IPLDEV 0xDB8
-#define __LC_CURRENT 0xDD8
-#define __LC_INT_CLOCK 0xDE8
-#define __LC_VDSO_PER_CPU 0xE38
-#endif /* __s390x__ */
+#define __LC_SUBCHANNEL_ID 0x00b8
+#define __LC_SUBCHANNEL_NR 0x00ba
+#define __LC_IO_INT_PARM 0x00bc
+#define __LC_IO_INT_WORD 0x00c0
+#define __LC_MCCK_CODE 0x00e8
-#define __LC_PASTE 0xE40
+#define __LC_DUMP_REIPL 0x0e00
-#define __LC_PANIC_MAGIC 0xE00
#ifndef __s390x__
-#define __LC_PFAULT_INTPARM 0x080
-#define __LC_CPU_TIMER_SAVE_AREA 0x0D8
-#define __LC_CLOCK_COMP_SAVE_AREA 0x0E0
-#define __LC_PSW_SAVE_AREA 0x100
-#define __LC_PREFIX_SAVE_AREA 0x108
-#define __LC_AREGS_SAVE_AREA 0x120
-#define __LC_FPREGS_SAVE_AREA 0x160
-#define __LC_GPREGS_SAVE_AREA 0x180
-#define __LC_CREGS_SAVE_AREA 0x1C0
+#define __LC_EXT_OLD_PSW 0x0018
+#define __LC_SVC_OLD_PSW 0x0020
+#define __LC_PGM_OLD_PSW 0x0028
+#define __LC_MCK_OLD_PSW 0x0030
+#define __LC_IO_OLD_PSW 0x0038
+#define __LC_EXT_NEW_PSW 0x0058
+#define __LC_SVC_NEW_PSW 0x0060
+#define __LC_PGM_NEW_PSW 0x0068
+#define __LC_MCK_NEW_PSW 0x0070
+#define __LC_IO_NEW_PSW 0x0078
+#define __LC_SAVE_AREA 0x0200
+#define __LC_RETURN_PSW 0x0240
+#define __LC_RETURN_MCCK_PSW 0x0248
+#define __LC_SYNC_ENTER_TIMER 0x0250
+#define __LC_ASYNC_ENTER_TIMER 0x0258
+#define __LC_EXIT_TIMER 0x0260
+#define __LC_USER_TIMER 0x0268
+#define __LC_SYSTEM_TIMER 0x0270
+#define __LC_STEAL_TIMER 0x0278
+#define __LC_LAST_UPDATE_TIMER 0x0280
+#define __LC_LAST_UPDATE_CLOCK 0x0288
+#define __LC_CURRENT 0x0290
+#define __LC_THREAD_INFO 0x0294
+#define __LC_KERNEL_STACK 0x0298
+#define __LC_ASYNC_STACK 0x029c
+#define __LC_PANIC_STACK 0x02a0
+#define __LC_KERNEL_ASCE 0x02a4
+#define __LC_USER_ASCE 0x02a8
+#define __LC_USER_EXEC_ASCE 0x02ac
+#define __LC_CPUID 0x02b0
+#define __LC_INT_CLOCK 0x02c8
+#define __LC_IRB 0x0300
+#define __LC_PFAULT_INTPARM 0x0080
+#define __LC_CPU_TIMER_SAVE_AREA 0x00d8
+#define __LC_CLOCK_COMP_SAVE_AREA 0x00e0
+#define __LC_PSW_SAVE_AREA 0x0100
+#define __LC_PREFIX_SAVE_AREA 0x0108
+#define __LC_AREGS_SAVE_AREA 0x0120
+#define __LC_FPREGS_SAVE_AREA 0x0160
+#define __LC_GPREGS_SAVE_AREA 0x0180
+#define __LC_CREGS_SAVE_AREA 0x01c0
#else /* __s390x__ */
-#define __LC_PFAULT_INTPARM 0x11B8
+#define __LC_LAST_BREAK 0x0110
+#define __LC_EXT_OLD_PSW 0x0130
+#define __LC_SVC_OLD_PSW 0x0140
+#define __LC_PGM_OLD_PSW 0x0150
+#define __LC_MCK_OLD_PSW 0x0160
+#define __LC_IO_OLD_PSW 0x0170
+#define __LC_EXT_NEW_PSW 0x01b0
+#define __LC_SVC_NEW_PSW 0x01c0
+#define __LC_PGM_NEW_PSW 0x01d0
+#define __LC_MCK_NEW_PSW 0x01e0
+#define __LC_IO_NEW_PSW 0x01f0
+#define __LC_SAVE_AREA 0x0200
+#define __LC_RETURN_PSW 0x0280
+#define __LC_RETURN_MCCK_PSW 0x0290
+#define __LC_SYNC_ENTER_TIMER 0x02a0
+#define __LC_ASYNC_ENTER_TIMER 0x02a8
+#define __LC_EXIT_TIMER 0x02b0
+#define __LC_USER_TIMER 0x02b8
+#define __LC_SYSTEM_TIMER 0x02c0
+#define __LC_STEAL_TIMER 0x02c8
+#define __LC_LAST_UPDATE_TIMER 0x02d0
+#define __LC_LAST_UPDATE_CLOCK 0x02d8
+#define __LC_CURRENT 0x02e0
+#define __LC_THREAD_INFO 0x02e8
+#define __LC_KERNEL_STACK 0x02f0
+#define __LC_ASYNC_STACK 0x02f8
+#define __LC_PANIC_STACK 0x0300
+#define __LC_KERNEL_ASCE 0x0308
+#define __LC_USER_ASCE 0x0310
+#define __LC_USER_EXEC_ASCE 0x0318
+#define __LC_CPUID 0x0320
+#define __LC_INT_CLOCK 0x0340
+#define __LC_VDSO_PER_CPU 0x0350
+#define __LC_IRB 0x0380
+#define __LC_PASTE 0x03c0
+#define __LC_PFAULT_INTPARM 0x11b8
#define __LC_FPREGS_SAVE_AREA 0x1200
-#define __LC_GPREGS_SAVE_AREA 0x1280
+#define __LC_GPREGS_SAVE_AREA 0x1280
#define __LC_PSW_SAVE_AREA 0x1300
#define __LC_PREFIX_SAVE_AREA 0x1318
-#define __LC_FP_CREG_SAVE_AREA 0x131C
+#define __LC_FP_CREG_SAVE_AREA 0x131c
#define __LC_TODREG_SAVE_AREA 0x1324
-#define __LC_CPU_TIMER_SAVE_AREA 0x1328
+#define __LC_CPU_TIMER_SAVE_AREA 0x1328
#define __LC_CLOCK_COMP_SAVE_AREA 0x1331
-#define __LC_AREGS_SAVE_AREA 0x1340
-#define __LC_CREGS_SAVE_AREA 0x1380
+#define __LC_AREGS_SAVE_AREA 0x1340
+#define __LC_CREGS_SAVE_AREA 0x1380
#endif /* __s390x__ */
#ifndef __ASSEMBLY__
@@ -198,222 +187,240 @@ union save_area {
struct _lowcore
{
#ifndef __s390x__
- /* prefix area: defined by architecture */
- psw_t restart_psw; /* 0x000 */
- __u32 ccw2[4]; /* 0x008 */
- psw_t external_old_psw; /* 0x018 */
- psw_t svc_old_psw; /* 0x020 */
- psw_t program_old_psw; /* 0x028 */
- psw_t mcck_old_psw; /* 0x030 */
- psw_t io_old_psw; /* 0x038 */
- __u8 pad1[0x58-0x40]; /* 0x040 */
- psw_t external_new_psw; /* 0x058 */
- psw_t svc_new_psw; /* 0x060 */
- psw_t program_new_psw; /* 0x068 */
- psw_t mcck_new_psw; /* 0x070 */
- psw_t io_new_psw; /* 0x078 */
- __u32 ext_params; /* 0x080 */
- __u16 cpu_addr; /* 0x084 */
- __u16 ext_int_code; /* 0x086 */
- __u16 svc_ilc; /* 0x088 */
- __u16 svc_code; /* 0x08a */
- __u16 pgm_ilc; /* 0x08c */
- __u16 pgm_code; /* 0x08e */
- __u32 trans_exc_code; /* 0x090 */
- __u16 mon_class_num; /* 0x094 */
- __u16 per_perc_atmid; /* 0x096 */
- __u32 per_address; /* 0x098 */
- __u32 monitor_code; /* 0x09c */
- __u8 exc_access_id; /* 0x0a0 */
- __u8 per_access_id; /* 0x0a1 */
- __u8 pad2[0xB8-0xA2]; /* 0x0a2 */
- __u16 subchannel_id; /* 0x0b8 */
- __u16 subchannel_nr; /* 0x0ba */
- __u32 io_int_parm; /* 0x0bc */
- __u32 io_int_word; /* 0x0c0 */
- __u8 pad3[0xc8-0xc4]; /* 0x0c4 */
- __u32 stfl_fac_list; /* 0x0c8 */
- __u8 pad4[0xd4-0xcc]; /* 0x0cc */
- __u32 extended_save_area_addr; /* 0x0d4 */
- __u32 cpu_timer_save_area[2]; /* 0x0d8 */
- __u32 clock_comp_save_area[2]; /* 0x0e0 */
- __u32 mcck_interruption_code[2]; /* 0x0e8 */
- __u8 pad5[0xf4-0xf0]; /* 0x0f0 */
- __u32 external_damage_code; /* 0x0f4 */
- __u32 failing_storage_address; /* 0x0f8 */
- __u8 pad6[0x100-0xfc]; /* 0x0fc */
- __u32 st_status_fixed_logout[4];/* 0x100 */
- __u8 pad7[0x120-0x110]; /* 0x110 */
- __u32 access_regs_save_area[16];/* 0x120 */
- __u32 floating_pt_save_area[8]; /* 0x160 */
- __u32 gpregs_save_area[16]; /* 0x180 */
- __u32 cregs_save_area[16]; /* 0x1c0 */
-
- psw_t return_psw; /* 0x200 */
- __u8 irb[64]; /* 0x208 */
- __u64 sync_enter_timer; /* 0x248 */
- __u64 async_enter_timer; /* 0x250 */
- __u64 exit_timer; /* 0x258 */
- __u64 user_timer; /* 0x260 */
- __u64 system_timer; /* 0x268 */
- __u64 steal_timer; /* 0x270 */
- __u64 last_update_timer; /* 0x278 */
- __u64 last_update_clock; /* 0x280 */
- psw_t return_mcck_psw; /* 0x288 */
- __u8 pad8[0xc00-0x290]; /* 0x290 */
-
- /* System info area */
- __u32 save_area[16]; /* 0xc00 */
- __u32 kernel_stack; /* 0xc40 */
- __u32 thread_info; /* 0xc44 */
- __u32 async_stack; /* 0xc48 */
- __u32 kernel_asce; /* 0xc4c */
- __u32 user_asce; /* 0xc50 */
- __u32 panic_stack; /* 0xc54 */
- __u32 user_exec_asce; /* 0xc58 */
- __u8 pad10[0xc60-0xc5c]; /* 0xc5c */
- /* entry.S sensitive area start */
- struct cpuinfo_S390 cpu_data; /* 0xc60 */
- __u32 ipl_device; /* 0xc7c */
- /* entry.S sensitive area end */
-
- /* SMP info area: defined by DJB */
- __u64 clock_comparator; /* 0xc80 */
- __u32 ext_call_fast; /* 0xc88 */
- __u32 percpu_offset; /* 0xc8c */
- __u32 current_task; /* 0xc90 */
- __u32 softirq_pending; /* 0xc94 */
- __u64 int_clock; /* 0xc98 */
- __u8 pad11[0xe00-0xca0]; /* 0xca0 */
-
- /* 0xe00 is used as indicator for dump tools */
- /* whether the kernel died with panic() or not */
- __u32 panic_magic; /* 0xe00 */
-
- /* Align to the top 1k of prefix area */
- __u8 pad12[0x1000-0xe04]; /* 0xe04 */
+ /* 0x0000 - 0x01ff: defined by architecture */
+ psw_t restart_psw; /* 0x0000 */
+ __u32 ccw2[4]; /* 0x0008 */
+ psw_t external_old_psw; /* 0x0018 */
+ psw_t svc_old_psw; /* 0x0020 */
+ psw_t program_old_psw; /* 0x0028 */
+ psw_t mcck_old_psw; /* 0x0030 */
+ psw_t io_old_psw; /* 0x0038 */
+ __u8 pad_0x0040[0x0058-0x0040]; /* 0x0040 */
+ psw_t external_new_psw; /* 0x0058 */
+ psw_t svc_new_psw; /* 0x0060 */
+ psw_t program_new_psw; /* 0x0068 */
+ psw_t mcck_new_psw; /* 0x0070 */
+ psw_t io_new_psw; /* 0x0078 */
+ __u32 ext_params; /* 0x0080 */
+ __u16 cpu_addr; /* 0x0084 */
+ __u16 ext_int_code; /* 0x0086 */
+ __u16 svc_ilc; /* 0x0088 */
+ __u16 svc_code; /* 0x008a */
+ __u16 pgm_ilc; /* 0x008c */
+ __u16 pgm_code; /* 0x008e */
+ __u32 trans_exc_code; /* 0x0090 */
+ __u16 mon_class_num; /* 0x0094 */
+ __u16 per_perc_atmid; /* 0x0096 */
+ __u32 per_address; /* 0x0098 */
+ __u32 monitor_code; /* 0x009c */
+ __u8 exc_access_id; /* 0x00a0 */
+ __u8 per_access_id; /* 0x00a1 */
+ __u8 pad_0x00a2[0x00b8-0x00a2]; /* 0x00a2 */
+ __u16 subchannel_id; /* 0x00b8 */
+ __u16 subchannel_nr; /* 0x00ba */
+ __u32 io_int_parm; /* 0x00bc */
+ __u32 io_int_word; /* 0x00c0 */
+ __u8 pad_0x00c4[0x00c8-0x00c4]; /* 0x00c4 */
+ __u32 stfl_fac_list; /* 0x00c8 */
+ __u8 pad_0x00cc[0x00d4-0x00cc]; /* 0x00cc */
+ __u32 extended_save_area_addr; /* 0x00d4 */
+ __u32 cpu_timer_save_area[2]; /* 0x00d8 */
+ __u32 clock_comp_save_area[2]; /* 0x00e0 */
+ __u32 mcck_interruption_code[2]; /* 0x00e8 */
+ __u8 pad_0x00f0[0x00f4-0x00f0]; /* 0x00f0 */
+ __u32 external_damage_code; /* 0x00f4 */
+ __u32 failing_storage_address; /* 0x00f8 */
+ __u8 pad_0x00fc[0x0100-0x00fc]; /* 0x00fc */
+ __u32 st_status_fixed_logout[4]; /* 0x0100 */
+ __u8 pad_0x0110[0x0120-0x0110]; /* 0x0110 */
+
+ /* CPU register save area: defined by architecture */
+ __u32 access_regs_save_area[16]; /* 0x0120 */
+ __u32 floating_pt_save_area[8]; /* 0x0160 */
+ __u32 gpregs_save_area[16]; /* 0x0180 */
+ __u32 cregs_save_area[16]; /* 0x01c0 */
+
+ /* Return psws. */
+ __u32 save_area[16]; /* 0x0200 */
+ psw_t return_psw; /* 0x0240 */
+ psw_t return_mcck_psw; /* 0x0248 */
+
+ /* CPU time accounting values */
+ __u64 sync_enter_timer; /* 0x0250 */
+ __u64 async_enter_timer; /* 0x0258 */
+ __u64 exit_timer; /* 0x0260 */
+ __u64 user_timer; /* 0x0268 */
+ __u64 system_timer; /* 0x0270 */
+ __u64 steal_timer; /* 0x0278 */
+ __u64 last_update_timer; /* 0x0280 */
+ __u64 last_update_clock; /* 0x0288 */
+
+ /* Current process. */
+ __u32 current_task; /* 0x0290 */
+ __u32 thread_info; /* 0x0294 */
+ __u32 kernel_stack; /* 0x0298 */
+
+ /* Interrupt and panic stack. */
+ __u32 async_stack; /* 0x029c */
+ __u32 panic_stack; /* 0x02a0 */
+
+ /* Address space pointer. */
+ __u32 kernel_asce; /* 0x02a4 */
+ __u32 user_asce; /* 0x02a8 */
+ __u32 user_exec_asce; /* 0x02ac */
+
+ /* SMP info area */
+ cpuid_t cpu_id; /* 0x02b0 */
+ __u32 cpu_nr; /* 0x02b8 */
+ __u32 softirq_pending; /* 0x02bc */
+ __u32 percpu_offset; /* 0x02c0 */
+ __u32 ext_call_fast; /* 0x02c4 */
+ __u64 int_clock; /* 0x02c8 */
+ __u64 clock_comparator; /* 0x02d0 */
+ __u8 pad_0x02d8[0x0300-0x02d8]; /* 0x02d8 */
+
+ /* Interrupt response block */
+ __u8 irb[64]; /* 0x0300 */
+
+ __u8 pad_0x0400[0x0e00-0x0400]; /* 0x0400 */
+
+ /*
+ * 0xe00 contains the address of the IPL Parameter Information
+ * block. Dump tools need IPIB for IPL after dump.
+ * Note: do not change the position of any fields in 0x0e00-0x0f00
+ */
+ __u32 ipib; /* 0x0e00 */
+ __u32 ipib_checksum; /* 0x0e04 */
+
+ /* Align to the top 1k of prefix area */
+ __u8 pad_0x0e08[0x1000-0x0e08]; /* 0x0e08 */
#else /* !__s390x__ */
- /* prefix area: defined by architecture */
- __u32 ccw1[2]; /* 0x000 */
- __u32 ccw2[4]; /* 0x008 */
- __u8 pad1[0x80-0x18]; /* 0x018 */
- __u32 ext_params; /* 0x080 */
- __u16 cpu_addr; /* 0x084 */
- __u16 ext_int_code; /* 0x086 */
- __u16 svc_ilc; /* 0x088 */
- __u16 svc_code; /* 0x08a */
- __u16 pgm_ilc; /* 0x08c */
- __u16 pgm_code; /* 0x08e */
- __u32 data_exc_code; /* 0x090 */
- __u16 mon_class_num; /* 0x094 */
- __u16 per_perc_atmid; /* 0x096 */
- addr_t per_address; /* 0x098 */
- __u8 exc_access_id; /* 0x0a0 */
- __u8 per_access_id; /* 0x0a1 */
- __u8 op_access_id; /* 0x0a2 */
- __u8 ar_access_id; /* 0x0a3 */
- __u8 pad2[0xA8-0xA4]; /* 0x0a4 */
- addr_t trans_exc_code; /* 0x0A0 */
- addr_t monitor_code; /* 0x09c */
- __u16 subchannel_id; /* 0x0b8 */
- __u16 subchannel_nr; /* 0x0ba */
- __u32 io_int_parm; /* 0x0bc */
- __u32 io_int_word; /* 0x0c0 */
- __u8 pad3[0xc8-0xc4]; /* 0x0c4 */
- __u32 stfl_fac_list; /* 0x0c8 */
- __u8 pad4[0xe8-0xcc]; /* 0x0cc */
- __u32 mcck_interruption_code[2]; /* 0x0e8 */
- __u8 pad5[0xf4-0xf0]; /* 0x0f0 */
- __u32 external_damage_code; /* 0x0f4 */
- addr_t failing_storage_address; /* 0x0f8 */
- __u8 pad6[0x120-0x100]; /* 0x100 */
- psw_t restart_old_psw; /* 0x120 */
- psw_t external_old_psw; /* 0x130 */
- psw_t svc_old_psw; /* 0x140 */
- psw_t program_old_psw; /* 0x150 */
- psw_t mcck_old_psw; /* 0x160 */
- psw_t io_old_psw; /* 0x170 */
- __u8 pad7[0x1a0-0x180]; /* 0x180 */
- psw_t restart_psw; /* 0x1a0 */
- psw_t external_new_psw; /* 0x1b0 */
- psw_t svc_new_psw; /* 0x1c0 */
- psw_t program_new_psw; /* 0x1d0 */
- psw_t mcck_new_psw; /* 0x1e0 */
- psw_t io_new_psw; /* 0x1f0 */
- psw_t return_psw; /* 0x200 */
- __u8 irb[64]; /* 0x210 */
- __u64 sync_enter_timer; /* 0x250 */
- __u64 async_enter_timer; /* 0x258 */
- __u64 exit_timer; /* 0x260 */
- __u64 user_timer; /* 0x268 */
- __u64 system_timer; /* 0x270 */
- __u64 steal_timer; /* 0x278 */
- __u64 last_update_timer; /* 0x280 */
- __u64 last_update_clock; /* 0x288 */
- psw_t return_mcck_psw; /* 0x290 */
- __u8 pad8[0xc00-0x2a0]; /* 0x2a0 */
- /* System info area */
- __u64 save_area[16]; /* 0xc00 */
- __u8 pad9[0xd40-0xc80]; /* 0xc80 */
- __u64 kernel_stack; /* 0xd40 */
- __u64 thread_info; /* 0xd48 */
- __u64 async_stack; /* 0xd50 */
- __u64 kernel_asce; /* 0xd58 */
- __u64 user_asce; /* 0xd60 */
- __u64 panic_stack; /* 0xd68 */
- __u64 user_exec_asce; /* 0xd70 */
- __u8 pad10[0xd80-0xd78]; /* 0xd78 */
- /* entry.S sensitive area start */
- struct cpuinfo_S390 cpu_data; /* 0xd80 */
- __u32 ipl_device; /* 0xdb8 */
- __u32 pad11; /* 0xdbc */
- /* entry.S sensitive area end */
-
- /* SMP info area: defined by DJB */
- __u64 clock_comparator; /* 0xdc0 */
- __u64 ext_call_fast; /* 0xdc8 */
- __u64 percpu_offset; /* 0xdd0 */
- __u64 current_task; /* 0xdd8 */
- __u32 softirq_pending; /* 0xde0 */
- __u32 pad_0x0de4; /* 0xde4 */
- __u64 int_clock; /* 0xde8 */
- __u8 pad12[0xe00-0xdf0]; /* 0xdf0 */
-
- /* 0xe00 is used as indicator for dump tools */
- /* whether the kernel died with panic() or not */
- __u32 panic_magic; /* 0xe00 */
+ /* 0x0000 - 0x01ff: defined by architecture */
+ __u32 ccw1[2]; /* 0x0000 */
+ __u32 ccw2[4]; /* 0x0008 */
+ __u8 pad_0x0018[0x0080-0x0018]; /* 0x0018 */
+ __u32 ext_params; /* 0x0080 */
+ __u16 cpu_addr; /* 0x0084 */
+ __u16 ext_int_code; /* 0x0086 */
+ __u16 svc_ilc; /* 0x0088 */
+ __u16 svc_code; /* 0x008a */
+ __u16 pgm_ilc; /* 0x008c */
+ __u16 pgm_code; /* 0x008e */
+ __u32 data_exc_code; /* 0x0090 */
+ __u16 mon_class_num; /* 0x0094 */
+ __u16 per_perc_atmid; /* 0x0096 */
+ addr_t per_address; /* 0x0098 */
+ __u8 exc_access_id; /* 0x00a0 */
+ __u8 per_access_id; /* 0x00a1 */
+ __u8 op_access_id; /* 0x00a2 */
+ __u8 ar_access_id; /* 0x00a3 */
+ __u8 pad_0x00a4[0x00a8-0x00a4]; /* 0x00a4 */
+ addr_t trans_exc_code; /* 0x00a8 */
+ addr_t monitor_code; /* 0x00b0 */
+ __u16 subchannel_id; /* 0x00b8 */
+ __u16 subchannel_nr; /* 0x00ba */
+ __u32 io_int_parm; /* 0x00bc */
+ __u32 io_int_word; /* 0x00c0 */
+ __u8 pad_0x00c4[0x00c8-0x00c4]; /* 0x00c4 */
+ __u32 stfl_fac_list; /* 0x00c8 */
+ __u8 pad_0x00cc[0x00e8-0x00cc]; /* 0x00cc */
+ __u32 mcck_interruption_code[2]; /* 0x00e8 */
+ __u8 pad_0x00f0[0x00f4-0x00f0]; /* 0x00f0 */
+ __u32 external_damage_code; /* 0x00f4 */
+ addr_t failing_storage_address; /* 0x00f8 */
+ __u8 pad_0x0100[0x0120-0x0100]; /* 0x0100 */
+ psw_t restart_old_psw; /* 0x0120 */
+ psw_t external_old_psw; /* 0x0130 */
+ psw_t svc_old_psw; /* 0x0140 */
+ psw_t program_old_psw; /* 0x0150 */
+ psw_t mcck_old_psw; /* 0x0160 */
+ psw_t io_old_psw; /* 0x0170 */
+ __u8 pad_0x0180[0x01a0-0x0180]; /* 0x0180 */
+ psw_t restart_psw; /* 0x01a0 */
+ psw_t external_new_psw; /* 0x01b0 */
+ psw_t svc_new_psw; /* 0x01c0 */
+ psw_t program_new_psw; /* 0x01d0 */
+ psw_t mcck_new_psw; /* 0x01e0 */
+ psw_t io_new_psw; /* 0x01f0 */
+
+ /* Entry/exit save area & return psws. */
+ __u64 save_area[16]; /* 0x0200 */
+ psw_t return_psw; /* 0x0280 */
+ psw_t return_mcck_psw; /* 0x0290 */
+
+ /* CPU accounting and timing values. */
+ __u64 sync_enter_timer; /* 0x02a0 */
+ __u64 async_enter_timer; /* 0x02a8 */
+ __u64 exit_timer; /* 0x02b0 */
+ __u64 user_timer; /* 0x02b8 */
+ __u64 system_timer; /* 0x02c0 */
+ __u64 steal_timer; /* 0x02c8 */
+ __u64 last_update_timer; /* 0x02d0 */
+ __u64 last_update_clock; /* 0x02d8 */
+
+ /* Current process. */
+ __u64 current_task; /* 0x02e0 */
+ __u64 thread_info; /* 0x02e8 */
+ __u64 kernel_stack; /* 0x02f0 */
+
+ /* Interrupt and panic stack. */
+ __u64 async_stack; /* 0x02f8 */
+ __u64 panic_stack; /* 0x0300 */
+
+ /* Address space pointer. */
+ __u64 kernel_asce; /* 0x0308 */
+ __u64 user_asce; /* 0x0310 */
+ __u64 user_exec_asce; /* 0x0318 */
+
+ /* SMP info area */
+ cpuid_t cpu_id; /* 0x0320 */
+ __u32 cpu_nr; /* 0x0328 */
+ __u32 softirq_pending; /* 0x032c */
+ __u64 percpu_offset; /* 0x0330 */
+ __u64 ext_call_fast; /* 0x0338 */
+ __u64 int_clock; /* 0x0340 */
+ __u64 clock_comparator; /* 0x0348 */
+ __u64 vdso_per_cpu_data; /* 0x0350 */
+ __u8 pad_0x0358[0x0380-0x0358]; /* 0x0358 */
+
+ /* Interrupt response block. */
+ __u8 irb[64]; /* 0x0380 */
/* Per cpu primary space access list */
- __u8 pad_0xe04[0xe38-0xe04]; /* 0xe04 */
- __u64 vdso_per_cpu_data; /* 0xe38 */
- __u32 paste[16]; /* 0xe40 */
-
- __u8 pad13[0x11b8-0xe80]; /* 0xe80 */
-
- /* 64 bit extparam used for pfault, diag 250 etc */
- __u64 ext_params2; /* 0x11B8 */
-
- __u8 pad14[0x1200-0x11C0]; /* 0x11C0 */
-
- /* System info area */
-
- __u64 floating_pt_save_area[16]; /* 0x1200 */
- __u64 gpregs_save_area[16]; /* 0x1280 */
- __u32 st_status_fixed_logout[4]; /* 0x1300 */
- __u8 pad15[0x1318-0x1310]; /* 0x1310 */
- __u32 prefixreg_save_area; /* 0x1318 */
- __u32 fpt_creg_save_area; /* 0x131c */
- __u8 pad16[0x1324-0x1320]; /* 0x1320 */
- __u32 tod_progreg_save_area; /* 0x1324 */
- __u32 cpu_timer_save_area[2]; /* 0x1328 */
- __u32 clock_comp_save_area[2]; /* 0x1330 */
- __u8 pad17[0x1340-0x1338]; /* 0x1338 */
- __u32 access_regs_save_area[16]; /* 0x1340 */
- __u64 cregs_save_area[16]; /* 0x1380 */
+ __u32 paste[16]; /* 0x03c0 */
+
+ __u8 pad_0x0400[0x0e00-0x0400]; /* 0x0400 */
+
+ /*
+ * 0xe00 contains the address of the IPL Parameter Information
+ * block. Dump tools need IPIB for IPL after dump.
+ * Note: do not change the position of any fields in 0x0e00-0x0f00
+ */
+ __u64 ipib; /* 0x0e00 */
+ __u32 ipib_checksum; /* 0x0e08 */
+ __u8 pad_0x0e0c[0x11b8-0x0e0c]; /* 0x0e0c */
+
+ /* 64 bit extparam used for pfault/diag 250: defined by architecture */
+ __u64 ext_params2; /* 0x11B8 */
+ __u8 pad_0x11c0[0x1200-0x11C0]; /* 0x11C0 */
+
+ /* CPU register save area: defined by architecture */
+ __u64 floating_pt_save_area[16]; /* 0x1200 */
+ __u64 gpregs_save_area[16]; /* 0x1280 */
+ __u32 st_status_fixed_logout[4]; /* 0x1300 */
+ __u8 pad_0x1310[0x1318-0x1310]; /* 0x1310 */
+ __u32 prefixreg_save_area; /* 0x1318 */
+ __u32 fpt_creg_save_area; /* 0x131c */
+ __u8 pad_0x1320[0x1324-0x1320]; /* 0x1320 */
+ __u32 tod_progreg_save_area; /* 0x1324 */
+ __u32 cpu_timer_save_area[2]; /* 0x1328 */
+ __u32 clock_comp_save_area[2]; /* 0x1330 */
+ __u8 pad_0x1338[0x1340-0x1338]; /* 0x1338 */
+ __u32 access_regs_save_area[16]; /* 0x1340 */
+ __u64 cregs_save_area[16]; /* 0x1380 */
/* align to the top of the prefix area */
-
- __u8 pad18[0x2000-0x1400]; /* 0x1400 */
+ __u8 pad_0x1400[0x2000-0x1400]; /* 0x1400 */
#endif /* !__s390x__ */
} __attribute__((packed)); /* End structure*/
@@ -433,8 +440,6 @@ static inline __u32 store_prefix(void)
return address;
}
-#define __PANIC_MAGIC 0xDEADC0DE
-
#endif
#endif
diff --git a/arch/s390/include/asm/mmu_context.h b/arch/s390/include/asm/mmu_context.h
index 28ec870655af..fc7edd6f41b6 100644
--- a/arch/s390/include/asm/mmu_context.h
+++ b/arch/s390/include/asm/mmu_context.h
@@ -74,7 +74,7 @@ static inline void update_mm(struct mm_struct *mm, struct task_struct *tsk)
static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
struct task_struct *tsk)
{
- cpu_set(smp_processor_id(), next->cpu_vm_mask);
+ cpumask_set_cpu(smp_processor_id(), mm_cpumask(next));
update_mm(next, tsk);
}
diff --git a/arch/s390/include/asm/nmi.h b/arch/s390/include/asm/nmi.h
new file mode 100644
index 000000000000..f4b60441adca
--- /dev/null
+++ b/arch/s390/include/asm/nmi.h
@@ -0,0 +1,66 @@
+/*
+ * Machine check handler definitions
+ *
+ * Copyright IBM Corp. 2000,2009
+ * Author(s): Ingo Adlung <adlung@de.ibm.com>,
+ * Martin Schwidefsky <schwidefsky@de.ibm.com>,
+ * Cornelia Huck <cornelia.huck@de.ibm.com>,
+ * Heiko Carstens <heiko.carstens@de.ibm.com>,
+ */
+
+#ifndef _ASM_S390_NMI_H
+#define _ASM_S390_NMI_H
+
+#include <linux/types.h>
+
+struct mci {
+ __u32 sd : 1; /* 00 system damage */
+ __u32 pd : 1; /* 01 instruction-processing damage */
+ __u32 sr : 1; /* 02 system recovery */
+ __u32 : 1; /* 03 */
+ __u32 cd : 1; /* 04 timing-facility damage */
+ __u32 ed : 1; /* 05 external damage */
+ __u32 : 1; /* 06 */
+ __u32 dg : 1; /* 07 degradation */
+ __u32 w : 1; /* 08 warning pending */
+ __u32 cp : 1; /* 09 channel-report pending */
+ __u32 sp : 1; /* 10 service-processor damage */
+ __u32 ck : 1; /* 11 channel-subsystem damage */
+ __u32 : 2; /* 12-13 */
+ __u32 b : 1; /* 14 backed up */
+ __u32 : 1; /* 15 */
+ __u32 se : 1; /* 16 storage error uncorrected */
+ __u32 sc : 1; /* 17 storage error corrected */
+ __u32 ke : 1; /* 18 storage-key error uncorrected */
+ __u32 ds : 1; /* 19 storage degradation */
+ __u32 wp : 1; /* 20 psw mwp validity */
+ __u32 ms : 1; /* 21 psw mask and key validity */
+ __u32 pm : 1; /* 22 psw program mask and cc validity */
+ __u32 ia : 1; /* 23 psw instruction address validity */
+ __u32 fa : 1; /* 24 failing storage address validity */
+ __u32 : 1; /* 25 */
+ __u32 ec : 1; /* 26 external damage code validity */
+ __u32 fp : 1; /* 27 floating point register validity */
+ __u32 gr : 1; /* 28 general register validity */
+ __u32 cr : 1; /* 29 control register validity */
+ __u32 : 1; /* 30 */
+ __u32 st : 1; /* 31 storage logical validity */
+ __u32 ie : 1; /* 32 indirect storage error */
+ __u32 ar : 1; /* 33 access register validity */
+ __u32 da : 1; /* 34 delayed access exception */
+ __u32 : 7; /* 35-41 */
+ __u32 pr : 1; /* 42 tod programmable register validity */
+ __u32 fc : 1; /* 43 fp control register validity */
+ __u32 ap : 1; /* 44 ancillary report */
+ __u32 : 1; /* 45 */
+ __u32 ct : 1; /* 46 cpu timer validity */
+ __u32 cc : 1; /* 47 clock comparator validity */
+ __u32 : 16; /* 47-63 */
+};
+
+struct pt_regs;
+
+extern void s390_handle_mcck(void);
+extern void s390_do_machine_check(struct pt_regs *regs);
+
+#endif /* _ASM_S390_NMI_H */
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index db4523fe38ac..61862b3ac794 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -42,22 +42,8 @@ static inline void get_cpu_id(cpuid_t *ptr)
asm volatile("stidp 0(%1)" : "=m" (*ptr) : "a" (ptr));
}
-struct cpuinfo_S390
-{
- cpuid_t cpu_id;
- __u16 cpu_addr;
- __u16 cpu_nr;
- unsigned long loops_per_jiffy;
- unsigned long *pgd_quick;
-#ifdef __s390x__
- unsigned long *pmd_quick;
-#endif /* __s390x__ */
- unsigned long *pte_quick;
- unsigned long pgtable_cache_sz;
-};
-
extern void s390_adjust_jiffies(void);
-extern void print_cpu_info(struct cpuinfo_S390 *);
+extern void print_cpu_info(void);
extern int get_cpu_capability(unsigned int *);
/*
diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h
index 8920025c3c02..f1b051630c50 100644
--- a/arch/s390/include/asm/ptrace.h
+++ b/arch/s390/include/asm/ptrace.h
@@ -172,6 +172,8 @@
#define NUM_CRS 16
#define NUM_ACRS 16
+#define NUM_CR_WORDS 3
+
#define FPR_SIZE 8
#define FPC_SIZE 4
#define FPC_PAD_SIZE 4 /* gcc insists on aligning the fpregs */
@@ -334,7 +336,7 @@ struct pt_regs
*/
typedef struct
{
- unsigned long cr[3];
+ unsigned long cr[NUM_CR_WORDS];
} per_cr_words;
#define PER_EM_MASK 0xE8000000UL
diff --git a/arch/s390/include/asm/qdio.h b/arch/s390/include/asm/qdio.h
index 27fc1746de15..402d6dcf0d26 100644
--- a/arch/s390/include/asm/qdio.h
+++ b/arch/s390/include/asm/qdio.h
@@ -314,6 +314,7 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int,
int, int, unsigned long);
/* qdio errors reported to the upper-layer program */
+#define QDIO_ERROR_SIGA_TARGET 0x02
#define QDIO_ERROR_SIGA_ACCESS_EXCEPTION 0x10
#define QDIO_ERROR_SIGA_BUSY 0x20
#define QDIO_ERROR_ACTIVATE_CHECK_CONDITION 0x40
diff --git a/arch/s390/include/asm/smp.h b/arch/s390/include/asm/smp.h
index 024b91e06239..2009158a4502 100644
--- a/arch/s390/include/asm/smp.h
+++ b/arch/s390/include/asm/smp.h
@@ -50,12 +50,7 @@ extern void machine_power_off_smp(void);
#define PROC_CHANGE_PENALTY 20 /* Schedule penalty */
-#define raw_smp_processor_id() (S390_lowcore.cpu_data.cpu_nr)
-
-static inline __u16 hard_smp_processor_id(void)
-{
- return stap();
-}
+#define raw_smp_processor_id() (S390_lowcore.cpu_nr)
/*
* returns 1 if cpu is in stopped/check stopped state or not operational
diff --git a/arch/s390/include/asm/string.h b/arch/s390/include/asm/string.h
index d074673a6d9b..cd0241db5a46 100644
--- a/arch/s390/include/asm/string.h
+++ b/arch/s390/include/asm/string.h
@@ -100,6 +100,7 @@ static inline char *strcat(char *dst, const char *src)
static inline char *strcpy(char *dst, const char *src)
{
+#if __GNUC__ < 4
register int r0 asm("0") = 0;
char *ret = dst;
@@ -109,10 +110,14 @@ static inline char *strcpy(char *dst, const char *src)
: "+&a" (dst), "+&a" (src) : "d" (r0)
: "cc", "memory");
return ret;
+#else
+ return __builtin_strcpy(dst, src);
+#endif
}
static inline size_t strlen(const char *s)
{
+#if __GNUC__ < 4
register unsigned long r0 asm("0") = 0;
const char *tmp = s;
@@ -121,6 +126,9 @@ static inline size_t strlen(const char *s)
" jo 0b"
: "+d" (r0), "+a" (tmp) : : "cc");
return r0 - (unsigned long) s;
+#else
+ return __builtin_strlen(s);
+#endif
}
static inline size_t strnlen(const char * s, size_t n)
@@ -135,7 +143,13 @@ static inline size_t strnlen(const char * s, size_t n)
: "+a" (end), "+a" (tmp) : "d" (r0) : "cc");
return end - s;
}
-
+#else /* IN_ARCH_STRING_C */
+void *memchr(const void * s, int c, size_t n);
+void *memscan(void *s, int c, size_t n);
+char *strcat(char *dst, const char *src);
+char *strcpy(char *dst, const char *src);
+size_t strlen(const char *s);
+size_t strnlen(const char * s, size_t n);
#endif /* !IN_ARCH_STRING_C */
#endif /* __KERNEL__ */
diff --git a/arch/s390/include/asm/sysinfo.h b/arch/s390/include/asm/sysinfo.h
index ad93212d9e16..9d70057d828c 100644
--- a/arch/s390/include/asm/sysinfo.h
+++ b/arch/s390/include/asm/sysinfo.h
@@ -100,6 +100,7 @@ struct sysinfo_3_2_2 {
char reserved_1[24];
} vm[8];
+ char reserved_544[3552];
};
static inline int stsi(void *sysinfo, int fc, int sel1, int sel2)
diff --git a/arch/s390/include/asm/tlbflush.h b/arch/s390/include/asm/tlbflush.h
index d60394b9745e..304cffa623e1 100644
--- a/arch/s390/include/asm/tlbflush.h
+++ b/arch/s390/include/asm/tlbflush.h
@@ -51,7 +51,7 @@ static inline void __tlb_flush_full(struct mm_struct *mm)
* If the process only ran on the local cpu, do a local flush.
*/
local_cpumask = cpumask_of_cpu(smp_processor_id());
- if (cpus_equal(mm->cpu_vm_mask, local_cpumask))
+ if (cpumask_equal(mm_cpumask(mm), &local_cpumask))
__tlb_flush_local();
else
__tlb_flush_global();
@@ -73,7 +73,7 @@ static inline void __tlb_flush_idte(unsigned long asce)
static inline void __tlb_flush_mm(struct mm_struct * mm)
{
- if (unlikely(cpus_empty(mm->cpu_vm_mask)))
+ if (unlikely(cpumask_empty(mm_cpumask(mm))))
return;
/*
* If the machine has IDTE we prefer to do a per mm flush
diff --git a/arch/s390/include/asm/topology.h b/arch/s390/include/asm/topology.h
index c979c3b56ab0..5e0ad618dc45 100644
--- a/arch/s390/include/asm/topology.h
+++ b/arch/s390/include/asm/topology.h
@@ -5,7 +5,6 @@
#define mc_capable() (1)
-cpumask_t cpu_coregroup_map(unsigned int cpu);
const struct cpumask *cpu_coregroup_mask(unsigned int cpu);
extern cpumask_t cpu_core_map[NR_CPUS];
diff --git a/arch/s390/include/asm/vtoc.h b/arch/s390/include/asm/vtoc.h
index 3a5267d90d29..8406a2b3157a 100644
--- a/arch/s390/include/asm/vtoc.h
+++ b/arch/s390/include/asm/vtoc.h
@@ -39,7 +39,7 @@ struct vtoc_labeldate
__u16 day;
} __attribute__ ((packed));
-struct vtoc_volume_label
+struct vtoc_volume_label_cdl
{
char volkey[4]; /* volume key = volume label */
char vollbl[4]; /* volume label */
@@ -56,6 +56,14 @@ struct vtoc_volume_label
char res3[29]; /* reserved */
} __attribute__ ((packed));
+struct vtoc_volume_label_ldl {
+ char vollbl[4]; /* volume label */
+ char volid[6]; /* volume identifier */
+ char res3[69]; /* reserved */
+ char ldl_version; /* version number, valid for ldl format */
+ __u64 formatted_blocks; /* valid when ldl_version >= f2 */
+} __attribute__ ((packed));
+
struct vtoc_extent
{
__u8 typeind; /* extent type indicator */
@@ -140,7 +148,11 @@ struct vtoc_format4_label
char res2[10]; /* reserved */
__u8 DS4EFLVL; /* extended free-space management level */
struct vtoc_cchhb DS4EFPTR; /* pointer to extended free-space info */
- char res3[9]; /* reserved */
+ char res3; /* reserved */
+ __u32 DS4DCYL; /* number of logical cyls */
+ char res4[2]; /* reserved */
+ __u8 DS4DEVF2; /* device flags */
+ char res5; /* reserved */
} __attribute__ ((packed));
struct vtoc_ds5ext
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 3edc6c6f258b..228e3105ded7 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -17,10 +17,12 @@ CFLAGS_smp.o := -Wno-nonnull
#
CFLAGS_ptrace.o += -DUTS_MACHINE='"$(UTS_MACHINE)"'
+CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w
+
obj-y := bitmap.o traps.o time.o process.o base.o early.o setup.o \
processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
s390_ext.o debug.o irq.o ipl.o dis.o diag.o mem_detect.o \
- vdso.o vtime.o
+ vdso.o vtime.o sysinfo.o nmi.o
obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o)
obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
diff --git a/arch/s390/kernel/bitmap.S b/arch/s390/kernel/bitmap.S
deleted file mode 100644
index dfb41f946e23..000000000000
--- a/arch/s390/kernel/bitmap.S
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * arch/s390/kernel/bitmap.S
- * Bitmaps for set_bit, clear_bit, test_and_set_bit, ...
- * See include/asm-s390/{bitops.h|posix_types.h} for details
- *
- * S390 version
- * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
- */
-
- .globl _oi_bitmap
-_oi_bitmap:
- .byte 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
-
- .globl _ni_bitmap
-_ni_bitmap:
- .byte 0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F
-
- .globl _zb_findmap
-_zb_findmap:
- .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4
- .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5
- .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4
- .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6
- .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4
- .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5
- .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4
- .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7
- .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4
- .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5
- .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4
- .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6
- .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4
- .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5
- .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4
- .byte 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,8
-
- .globl _sb_findmap
-_sb_findmap:
- .byte 8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
- .byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
- .byte 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
- .byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
- .byte 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
- .byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
- .byte 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
- .byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
- .byte 7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
- .byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
- .byte 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
- .byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
- .byte 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
- .byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
- .byte 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
- .byte 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
-
diff --git a/arch/s390/kernel/bitmap.c b/arch/s390/kernel/bitmap.c
new file mode 100644
index 000000000000..3ae4757b006a
--- /dev/null
+++ b/arch/s390/kernel/bitmap.c
@@ -0,0 +1,54 @@
+/*
+ * Bitmaps for set_bit, clear_bit, test_and_set_bit, ...
+ * See include/asm/{bitops.h|posix_types.h} for details
+ *
+ * Copyright IBM Corp. 1999,2009
+ * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>,
+ */
+
+#include <linux/bitops.h>
+#include <linux/module.h>
+
+const char _oi_bitmap[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
+EXPORT_SYMBOL(_oi_bitmap);
+
+const char _ni_bitmap[] = { 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f };
+EXPORT_SYMBOL(_ni_bitmap);
+
+const char _zb_findmap[] = {
+ 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
+ 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
+ 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
+ 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,
+ 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
+ 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
+ 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
+ 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,
+ 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
+ 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
+ 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
+ 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,
+ 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
+ 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
+ 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
+ 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,8 };
+EXPORT_SYMBOL(_zb_findmap);
+
+const char _sb_findmap[] = {
+ 8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+ 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 };
+EXPORT_SYMBOL(_sb_findmap);
diff --git a/arch/s390/kernel/compat_ptrace.h b/arch/s390/kernel/compat_ptrace.h
index a2be3a978d5c..123dd660d7fb 100644
--- a/arch/s390/kernel/compat_ptrace.h
+++ b/arch/s390/kernel/compat_ptrace.h
@@ -1,10 +1,11 @@
#ifndef _PTRACE32_H
#define _PTRACE32_H
+#include <asm/ptrace.h> /* needed for NUM_CR_WORDS */
#include "compat_linux.h" /* needed for psw_compat_t */
typedef struct {
- __u32 cr[3];
+ __u32 cr[NUM_CR_WORDS];
} per_cr_words32;
typedef struct {
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index ba03fc0a3a56..be8bceaf37d9 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -603,7 +603,7 @@ debug_input(struct file *file, const char __user *user_buf, size_t length,
static int
debug_open(struct inode *inode, struct file *file)
{
- int i = 0, rc = 0;
+ int i, rc = 0;
file_private_info_t *p_info;
debug_info_t *debug_info, *debug_info_snapshot;
@@ -642,8 +642,7 @@ found:
p_info = kmalloc(sizeof(file_private_info_t),
GFP_KERNEL);
if(!p_info){
- if(debug_info_snapshot)
- debug_info_free(debug_info_snapshot);
+ debug_info_free(debug_info_snapshot);
rc = -ENOMEM;
goto out;
}
@@ -698,8 +697,7 @@ debug_info_t *debug_register_mode(const char *name, int pages_per_area,
if ((uid != 0) || (gid != 0))
pr_warning("Root becomes the owner of all s390dbf files "
"in sysfs\n");
- if (!initialized)
- BUG();
+ BUG_ON(!initialized);
mutex_lock(&debug_mutex);
/* create new debug_info */
@@ -1156,7 +1154,6 @@ debug_unregister_view(debug_info_t * id, struct debug_view *view)
else {
debugfs_remove(id->debugfs_entries[i]);
id->views[i] = NULL;
- rc = 0;
}
spin_unlock_irqrestore(&id->lock, flags);
out:
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index 2a2ca268b1dd..4d221c81c849 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -6,6 +6,7 @@
* Heiko Carstens <heiko.carstens@de.ibm.com>
*/
+#include <linux/compiler.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/string.h>
@@ -20,6 +21,7 @@
#include <asm/processor.h>
#include <asm/sections.h>
#include <asm/setup.h>
+#include <asm/sysinfo.h>
#include <asm/cpcmd.h>
#include <asm/sclp.h>
#include "entry.h"
@@ -173,19 +175,21 @@ static noinline __init void init_kernel_storage_key(void)
page_set_storage_key(init_pfn << PAGE_SHIFT, PAGE_DEFAULT_KEY);
}
+static __initdata struct sysinfo_3_2_2 vmms __aligned(PAGE_SIZE);
+
static noinline __init void detect_machine_type(void)
{
- struct cpuinfo_S390 *cpuinfo = &S390_lowcore.cpu_data;
-
- get_cpu_id(&S390_lowcore.cpu_data.cpu_id);
-
- /* Running under z/VM ? */
- if (cpuinfo->cpu_id.version == 0xff)
- machine_flags |= MACHINE_FLAG_VM;
+ /* No VM information? Looks like LPAR */
+ if (stsi(&vmms, 3, 2, 2) == -ENOSYS)
+ return;
+ if (!vmms.count)
+ return;
- /* Running under KVM ? */
- if (cpuinfo->cpu_id.version == 0xfe)
+ /* Running under KVM? If not we assume z/VM */
+ if (!memcmp(vmms.vm[0].cpi, "\xd2\xe5\xd4", 3))
machine_flags |= MACHINE_FLAG_KVM;
+ else
+ machine_flags |= MACHINE_FLAG_VM;
}
static __init void early_pgm_check_handler(void)
@@ -348,7 +352,6 @@ static void __init setup_boot_command_line(void)
/* copy arch command line */
strlcpy(boot_command_line, COMMAND_LINE, ARCH_COMMAND_LINE_SIZE);
- boot_command_line[ARCH_COMMAND_LINE_SIZE - 1] = 0;
/* append IPL PARM data to the boot command line */
if (MACHINE_IS_VM) {
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S
index ec7e35f6055b..1046c2c9f8d1 100644
--- a/arch/s390/kernel/head.S
+++ b/arch/s390/kernel/head.S
@@ -469,6 +469,8 @@ start:
.org 0x10000
startup:basr %r13,0 # get base
.LPG0:
+ xc 0x200(256),0x200 # partially clear lowcore
+ xc 0x300(256),0x300
#ifndef CONFIG_MARCH_G5
# check processor version against MARCH_{G5,Z900,Z990,Z9_109,Z10}
diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S
index db476d114caa..2ced846065b7 100644
--- a/arch/s390/kernel/head31.S
+++ b/arch/s390/kernel/head31.S
@@ -20,7 +20,6 @@ startup_continue:
lctl %c0,%c15,.Lctl-.LPG1(%r13) # load control registers
l %r12,.Lparmaddr-.LPG1(%r13) # pointer to parameter area
# move IPL device to lowcore
- mvc __LC_IPLDEV(4),IPL_DEVICE-PARMAREA(%r12)
#
# Setup stack
#
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
index f9f70aa15244..65667b2e65ce 100644
--- a/arch/s390/kernel/head64.S
+++ b/arch/s390/kernel/head64.S
@@ -86,7 +86,6 @@ startup_continue:
lctlg %c0,%c15,.Lctl-.LPG1(%r13) # load control registers
lg %r12,.Lparmaddr-.LPG1(%r13) # pointer to parameter area
# move IPL device to lowcore
- mvc __LC_IPLDEV(4),IPL_DEVICE+4-PARMAREA(%r12)
lghi %r0,__LC_PASTE
stg %r0,__LC_VDSO_PER_CPU
#
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 2dcf590faba6..6f3711a0eaaa 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -23,7 +23,7 @@
#include <asm/ebcdic.h>
#include <asm/reset.h>
#include <asm/sclp.h>
-#include <asm/setup.h>
+#include <asm/checksum.h>
#define IPL_PARM_BLOCK_VERSION 0
@@ -56,13 +56,14 @@ struct shutdown_trigger {
};
/*
- * Five shutdown action types are supported:
+ * The following shutdown action types are supported:
*/
#define SHUTDOWN_ACTION_IPL_STR "ipl"
#define SHUTDOWN_ACTION_REIPL_STR "reipl"
#define SHUTDOWN_ACTION_DUMP_STR "dump"
#define SHUTDOWN_ACTION_VMCMD_STR "vmcmd"
#define SHUTDOWN_ACTION_STOP_STR "stop"
+#define SHUTDOWN_ACTION_DUMP_REIPL_STR "dump_reipl"
struct shutdown_action {
char *name;
@@ -146,6 +147,7 @@ static enum ipl_method reipl_method = REIPL_METHOD_DEFAULT;
static struct ipl_parameter_block *reipl_block_fcp;
static struct ipl_parameter_block *reipl_block_ccw;
static struct ipl_parameter_block *reipl_block_nss;
+static struct ipl_parameter_block *reipl_block_actual;
static int dump_capabilities = DUMP_TYPE_NONE;
static enum dump_type dump_type = DUMP_TYPE_NONE;
@@ -835,6 +837,7 @@ static int reipl_set_type(enum ipl_type type)
reipl_method = REIPL_METHOD_CCW_VM;
else
reipl_method = REIPL_METHOD_CCW_CIO;
+ reipl_block_actual = reipl_block_ccw;
break;
case IPL_TYPE_FCP:
if (diag308_set_works)
@@ -843,6 +846,7 @@ static int reipl_set_type(enum ipl_type type)
reipl_method = REIPL_METHOD_FCP_RO_VM;
else
reipl_method = REIPL_METHOD_FCP_RO_DIAG;
+ reipl_block_actual = reipl_block_fcp;
break;
case IPL_TYPE_FCP_DUMP:
reipl_method = REIPL_METHOD_FCP_DUMP;
@@ -852,6 +856,7 @@ static int reipl_set_type(enum ipl_type type)
reipl_method = REIPL_METHOD_NSS_DIAG;
else
reipl_method = REIPL_METHOD_NSS;
+ reipl_block_actual = reipl_block_nss;
break;
case IPL_TYPE_UNKNOWN:
reipl_method = REIPL_METHOD_DEFAULT;
@@ -960,7 +965,6 @@ static void reipl_run(struct shutdown_trigger *trigger)
diag308(DIAG308_IPL, NULL);
break;
case REIPL_METHOD_FCP_DUMP:
- default:
break;
}
disabled_wait((unsigned long) __builtin_return_address(0));
@@ -1069,10 +1073,12 @@ static int __init reipl_fcp_init(void)
{
int rc;
- if ((!diag308_set_works) && (ipl_info.type != IPL_TYPE_FCP))
- return 0;
- if ((!diag308_set_works) && (ipl_info.type == IPL_TYPE_FCP))
- make_attrs_ro(reipl_fcp_attrs);
+ if (!diag308_set_works) {
+ if (ipl_info.type == IPL_TYPE_FCP)
+ make_attrs_ro(reipl_fcp_attrs);
+ else
+ return 0;
+ }
reipl_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);
if (!reipl_block_fcp)
@@ -1253,7 +1259,6 @@ static void dump_run(struct shutdown_trigger *trigger)
diag308(DIAG308_DUMP, NULL);
break;
case DUMP_METHOD_NONE:
- default:
return;
}
printk(KERN_EMERG "Dump failed!\n");
@@ -1332,6 +1337,49 @@ static struct shutdown_action __refdata dump_action = {
.init = dump_init,
};
+static void dump_reipl_run(struct shutdown_trigger *trigger)
+{
+ preempt_disable();
+ /*
+ * Bypass dynamic address translation (DAT) when storing IPL parameter
+ * information block address and checksum into the prefix area
+ * (corresponding to absolute addresses 0-8191).
+ * When enhanced DAT applies and the STE format control in one,
+ * the absolute address is formed without prefixing. In this case a
+ * normal store (stg/st) into the prefix area would no more match to
+ * absolute addresses 0-8191.
+ */
+#ifdef CONFIG_64BIT
+ asm volatile("sturg %0,%1"
+ :: "a" ((unsigned long) reipl_block_actual),
+ "a" (&lowcore_ptr[smp_processor_id()]->ipib));
+#else
+ asm volatile("stura %0,%1"
+ :: "a" ((unsigned long) reipl_block_actual),
+ "a" (&lowcore_ptr[smp_processor_id()]->ipib));
+#endif
+ asm volatile("stura %0,%1"
+ :: "a" (csum_partial(reipl_block_actual,
+ reipl_block_actual->hdr.len, 0)),
+ "a" (&lowcore_ptr[smp_processor_id()]->ipib_checksum));
+ preempt_enable();
+ dump_run(trigger);
+}
+
+static int __init dump_reipl_init(void)
+{
+ if (!diag308_set_works)
+ return -EOPNOTSUPP;
+ else
+ return 0;
+}
+
+static struct shutdown_action __refdata dump_reipl_action = {
+ .name = SHUTDOWN_ACTION_DUMP_REIPL_STR,
+ .fn = dump_reipl_run,
+ .init = dump_reipl_init,
+};
+
/*
* vmcmd shutdown action: Trigger vm command on shutdown.
*/
@@ -1421,7 +1469,8 @@ static struct shutdown_action stop_action = {SHUTDOWN_ACTION_STOP_STR,
/* action list */
static struct shutdown_action *shutdown_actions_list[] = {
- &ipl_action, &reipl_action, &dump_action, &vmcmd_action, &stop_action};
+ &ipl_action, &reipl_action, &dump_reipl_action, &dump_action,
+ &vmcmd_action, &stop_action};
#define SHUTDOWN_ACTIONS_COUNT (sizeof(shutdown_actions_list) / sizeof(void *))
/*
@@ -1434,11 +1483,11 @@ static int set_trigger(const char *buf, struct shutdown_trigger *trigger,
size_t len)
{
int i;
+
for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) {
if (!shutdown_actions_list[i])
continue;
- if (strncmp(buf, shutdown_actions_list[i]->name,
- strlen(shutdown_actions_list[i]->name)) == 0) {
+ if (sysfs_streq(buf, shutdown_actions_list[i]->name)) {
trigger->action = shutdown_actions_list[i];
return len;
}
@@ -1672,7 +1721,7 @@ static int on_panic_notify(struct notifier_block *self,
static struct notifier_block on_panic_nb = {
.notifier_call = on_panic_notify,
- .priority = 0,
+ .priority = INT_MIN,
};
void __init setup_ipl(void)
@@ -1696,7 +1745,6 @@ void __init setup_ipl(void)
sizeof(ipl_info.data.nss.name));
break;
case IPL_TYPE_UNKNOWN:
- default:
/* We have no info to copy */
break;
}
diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c
index 59b4e796680a..eed4a00cb676 100644
--- a/arch/s390/kernel/module.c
+++ b/arch/s390/kernel/module.c
@@ -310,15 +310,20 @@ apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab,
info->plt_initialized = 1;
}
if (r_type == R_390_PLTOFF16 ||
- r_type == R_390_PLTOFF32
- || r_type == R_390_PLTOFF64
- )
+ r_type == R_390_PLTOFF32 ||
+ r_type == R_390_PLTOFF64)
val = me->arch.plt_offset - me->arch.got_offset +
info->plt_offset + rela->r_addend;
- else
- val = (Elf_Addr) me->module_core +
- me->arch.plt_offset + info->plt_offset +
- rela->r_addend - loc;
+ else {
+ if (!((r_type == R_390_PLT16DBL &&
+ val - loc + 0xffffUL < 0x1ffffeUL) ||
+ (r_type == R_390_PLT32DBL &&
+ val - loc + 0xffffffffULL < 0x1fffffffeULL)))
+ val = (Elf_Addr) me->module_core +
+ me->arch.plt_offset +
+ info->plt_offset;
+ val += rela->r_addend - loc;
+ }
if (r_type == R_390_PLT16DBL)
*(unsigned short *) loc = val >> 1;
else if (r_type == R_390_PLTOFF16)
diff --git a/arch/s390/kernel/nmi.c b/arch/s390/kernel/nmi.c
new file mode 100644
index 000000000000..4bfdc421d7e9
--- /dev/null
+++ b/arch/s390/kernel/nmi.c
@@ -0,0 +1,376 @@
+/*
+ * Machine check handler
+ *
+ * Copyright IBM Corp. 2000,2009
+ * Author(s): Ingo Adlung <adlung@de.ibm.com>,
+ * Martin Schwidefsky <schwidefsky@de.ibm.com>,
+ * Cornelia Huck <cornelia.huck@de.ibm.com>,
+ * Heiko Carstens <heiko.carstens@de.ibm.com>,
+ */
+
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/time.h>
+#include <linux/module.h>
+#include <asm/lowcore.h>
+#include <asm/smp.h>
+#include <asm/etr.h>
+#include <asm/cpu.h>
+#include <asm/nmi.h>
+#include <asm/crw.h>
+
+struct mcck_struct {
+ int kill_task;
+ int channel_report;
+ int warning;
+ unsigned long long mcck_code;
+};
+
+static DEFINE_PER_CPU(struct mcck_struct, cpu_mcck);
+
+static NORET_TYPE void s390_handle_damage(char *msg)
+{
+ smp_send_stop();
+ disabled_wait((unsigned long) __builtin_return_address(0));
+ while (1);
+}
+
+/*
+ * Main machine check handler function. Will be called with interrupts enabled
+ * or disabled and machine checks enabled or disabled.
+ */
+void s390_handle_mcck(void)
+{
+ unsigned long flags;
+ struct mcck_struct mcck;
+
+ /*
+ * Disable machine checks and get the current state of accumulated
+ * machine checks. Afterwards delete the old state and enable machine
+ * checks again.
+ */
+ local_irq_save(flags);
+ local_mcck_disable();
+ mcck = __get_cpu_var(cpu_mcck);
+ memset(&__get_cpu_var(cpu_mcck), 0, sizeof(struct mcck_struct));
+ clear_thread_flag(TIF_MCCK_PENDING);
+ local_mcck_enable();
+ local_irq_restore(flags);
+
+ if (mcck.channel_report)
+ crw_handle_channel_report();
+ /*
+ * A warning may remain for a prolonged period on the bare iron.
+ * (actually until the machine is powered off, or the problem is gone)
+ * So we just stop listening for the WARNING MCH and avoid continuously
+ * being interrupted. One caveat is however, that we must do this per
+ * processor and cannot use the smp version of ctl_clear_bit().
+ * On VM we only get one interrupt per virtally presented machinecheck.
+ * Though one suffices, we may get one interrupt per (virtual) cpu.
+ */
+ if (mcck.warning) { /* WARNING pending ? */
+ static int mchchk_wng_posted = 0;
+
+ /* Use single cpu clear, as we cannot handle smp here. */
+ __ctl_clear_bit(14, 24); /* Disable WARNING MCH */
+ if (xchg(&mchchk_wng_posted, 1) == 0)
+ kill_cad_pid(SIGPWR, 1);
+ }
+ if (mcck.kill_task) {
+ local_irq_enable();
+ printk(KERN_EMERG "mcck: Terminating task because of machine "
+ "malfunction (code 0x%016llx).\n", mcck.mcck_code);
+ printk(KERN_EMERG "mcck: task: %s, pid: %d.\n",
+ current->comm, current->pid);
+ do_exit(SIGSEGV);
+ }
+}
+EXPORT_SYMBOL_GPL(s390_handle_mcck);
+
+/*
+ * returns 0 if all registers could be validated
+ * returns 1 otherwise
+ */
+static int notrace s390_revalidate_registers(struct mci *mci)
+{
+ int kill_task;
+ u64 tmpclock;
+ u64 zero;
+ void *fpt_save_area, *fpt_creg_save_area;
+
+ kill_task = 0;
+ zero = 0;
+
+ if (!mci->gr) {
+ /*
+ * General purpose registers couldn't be restored and have
+ * unknown contents. Process needs to be terminated.
+ */
+ kill_task = 1;
+ }
+ if (!mci->fp) {
+ /*
+ * Floating point registers can't be restored and
+ * therefore the process needs to be terminated.
+ */
+ kill_task = 1;
+ }
+#ifndef CONFIG_64BIT
+ asm volatile(
+ " ld 0,0(%0)\n"
+ " ld 2,8(%0)\n"
+ " ld 4,16(%0)\n"
+ " ld 6,24(%0)"
+ : : "a" (&S390_lowcore.floating_pt_save_area));
+#endif
+
+ if (MACHINE_HAS_IEEE) {
+#ifdef CONFIG_64BIT
+ fpt_save_area = &S390_lowcore.floating_pt_save_area;
+ fpt_creg_save_area = &S390_lowcore.fpt_creg_save_area;
+#else
+ fpt_save_area = (void *) S390_lowcore.extended_save_area_addr;
+ fpt_creg_save_area = fpt_save_area + 128;
+#endif
+ if (!mci->fc) {
+ /*
+ * Floating point control register can't be restored.
+ * Task will be terminated.
+ */
+ asm volatile("lfpc 0(%0)" : : "a" (&zero), "m" (zero));
+ kill_task = 1;
+
+ } else
+ asm volatile("lfpc 0(%0)" : : "a" (fpt_creg_save_area));
+
+ asm volatile(
+ " ld 0,0(%0)\n"
+ " ld 1,8(%0)\n"
+ " ld 2,16(%0)\n"
+ " ld 3,24(%0)\n"
+ " ld 4,32(%0)\n"
+ " ld 5,40(%0)\n"
+ " ld 6,48(%0)\n"
+ " ld 7,56(%0)\n"
+ " ld 8,64(%0)\n"
+ " ld 9,72(%0)\n"
+ " ld 10,80(%0)\n"
+ " ld 11,88(%0)\n"
+ " ld 12,96(%0)\n"
+ " ld 13,104(%0)\n"
+ " ld 14,112(%0)\n"
+ " ld 15,120(%0)\n"
+ : : "a" (fpt_save_area));
+ }
+ /* Revalidate access registers */
+ asm volatile(
+ " lam 0,15,0(%0)"
+ : : "a" (&S390_lowcore.access_regs_save_area));
+ if (!mci->ar) {
+ /*
+ * Access registers have unknown contents.
+ * Terminating task.
+ */
+ kill_task = 1;
+ }
+ /* Revalidate control registers */
+ if (!mci->cr) {
+ /*
+ * Control registers have unknown contents.
+ * Can't recover and therefore stopping machine.
+ */
+ s390_handle_damage("invalid control registers.");
+ } else {
+#ifdef CONFIG_64BIT
+ asm volatile(
+ " lctlg 0,15,0(%0)"
+ : : "a" (&S390_lowcore.cregs_save_area));
+#else
+ asm volatile(
+ " lctl 0,15,0(%0)"
+ : : "a" (&S390_lowcore.cregs_save_area));
+#endif
+ }
+ /*
+ * We don't even try to revalidate the TOD register, since we simply
+ * can't write something sensible into that register.
+ */
+#ifdef CONFIG_64BIT
+ /*
+ * See if we can revalidate the TOD programmable register with its
+ * old contents (should be zero) otherwise set it to zero.
+ */
+ if (!mci->pr)
+ asm volatile(
+ " sr 0,0\n"
+ " sckpf"
+ : : : "0", "cc");
+ else
+ asm volatile(
+ " l 0,0(%0)\n"
+ " sckpf"
+ : : "a" (&S390_lowcore.tod_progreg_save_area)
+ : "0", "cc");
+#endif
+ /* Revalidate clock comparator register */
+ asm volatile(
+ " stck 0(%1)\n"
+ " sckc 0(%1)"
+ : "=m" (tmpclock) : "a" (&(tmpclock)) : "cc", "memory");
+
+ /* Check if old PSW is valid */
+ if (!mci->wp)
+ /*
+ * Can't tell if we come from user or kernel mode
+ * -> stopping machine.
+ */
+ s390_handle_damage("old psw invalid.");
+
+ if (!mci->ms || !mci->pm || !mci->ia)
+ kill_task = 1;
+
+ return kill_task;
+}
+
+#define MAX_IPD_COUNT 29
+#define MAX_IPD_TIME (5 * 60 * USEC_PER_SEC) /* 5 minutes */
+
+#define ED_STP_ISLAND 6 /* External damage STP island check */
+#define ED_STP_SYNC 7 /* External damage STP sync check */
+#define ED_ETR_SYNC 12 /* External damage ETR sync check */
+#define ED_ETR_SWITCH 13 /* External damage ETR switch to local */
+
+/*
+ * machine check handler.
+ */
+void notrace s390_do_machine_check(struct pt_regs *regs)
+{
+ static int ipd_count;
+ static DEFINE_SPINLOCK(ipd_lock);
+ static unsigned long long last_ipd;
+ struct mcck_struct *mcck;
+ unsigned long long tmp;
+ struct mci *mci;
+ int umode;
+
+ lockdep_off();
+ s390_idle_check();
+
+ mci = (struct mci *) &S390_lowcore.mcck_interruption_code;
+ mcck = &__get_cpu_var(cpu_mcck);
+ umode = user_mode(regs);
+
+ if (mci->sd) {
+ /* System damage -> stopping machine */
+ s390_handle_damage("received system damage machine check.");
+ }
+ if (mci->pd) {
+ if (mci->b) {
+ /* Processing backup -> verify if we can survive this */
+ u64 z_mcic, o_mcic, t_mcic;
+#ifdef CONFIG_64BIT
+ z_mcic = (1ULL<<63 | 1ULL<<59 | 1ULL<<29);
+ o_mcic = (1ULL<<43 | 1ULL<<42 | 1ULL<<41 | 1ULL<<40 |
+ 1ULL<<36 | 1ULL<<35 | 1ULL<<34 | 1ULL<<32 |
+ 1ULL<<30 | 1ULL<<21 | 1ULL<<20 | 1ULL<<17 |
+ 1ULL<<16);
+#else
+ z_mcic = (1ULL<<63 | 1ULL<<59 | 1ULL<<57 | 1ULL<<50 |
+ 1ULL<<29);
+ o_mcic = (1ULL<<43 | 1ULL<<42 | 1ULL<<41 | 1ULL<<40 |
+ 1ULL<<36 | 1ULL<<35 | 1ULL<<34 | 1ULL<<32 |
+ 1ULL<<30 | 1ULL<<20 | 1ULL<<17 | 1ULL<<16);
+#endif
+ t_mcic = *(u64 *)mci;
+
+ if (((t_mcic & z_mcic) != 0) ||
+ ((t_mcic & o_mcic) != o_mcic)) {
+ s390_handle_damage("processing backup machine "
+ "check with damage.");
+ }
+
+ /*
+ * Nullifying exigent condition, therefore we might
+ * retry this instruction.
+ */
+ spin_lock(&ipd_lock);
+ tmp = get_clock();
+ if (((tmp - last_ipd) >> 12) < MAX_IPD_TIME)
+ ipd_count++;
+ else
+ ipd_count = 1;
+ last_ipd = tmp;
+ if (ipd_count == MAX_IPD_COUNT)
+ s390_handle_damage("too many ipd retries.");
+ spin_unlock(&ipd_lock);
+ } else {
+ /* Processing damage -> stopping machine */
+ s390_handle_damage("received instruction processing "
+ "damage machine check.");
+ }
+ }
+ if (s390_revalidate_registers(mci)) {
+ if (umode) {
+ /*
+ * Couldn't restore all register contents while in
+ * user mode -> mark task for termination.
+ */
+ mcck->kill_task = 1;
+ mcck->mcck_code = *(unsigned long long *) mci;
+ set_thread_flag(TIF_MCCK_PENDING);
+ } else {
+ /*
+ * Couldn't restore all register contents while in
+ * kernel mode -> stopping machine.
+ */
+ s390_handle_damage("unable to revalidate registers.");
+ }
+ }
+ if (mci->cd) {
+ /* Timing facility damage */
+ s390_handle_damage("TOD clock damaged");
+ }
+ if (mci->ed && mci->ec) {
+ /* External damage */
+ if (S390_lowcore.external_damage_code & (1U << ED_ETR_SYNC))
+ etr_sync_check();
+ if (S390_lowcore.external_damage_code & (1U << ED_ETR_SWITCH))
+ etr_switch_to_local();
+ if (S390_lowcore.external_damage_code & (1U << ED_STP_SYNC))
+ stp_sync_check();
+ if (S390_lowcore.external_damage_code & (1U << ED_STP_ISLAND))
+ stp_island_check();
+ }
+ if (mci->se)
+ /* Storage error uncorrected */
+ s390_handle_damage("received storage error uncorrected "
+ "machine check.");
+ if (mci->ke)
+ /* Storage key-error uncorrected */
+ s390_handle_damage("received storage key-error uncorrected "
+ "machine check.");
+ if (mci->ds && mci->fa)
+ /* Storage degradation */
+ s390_handle_damage("received storage degradation machine "
+ "check.");
+ if (mci->cp) {
+ /* Channel report word pending */
+ mcck->channel_report = 1;
+ set_thread_flag(TIF_MCCK_PENDING);
+ }
+ if (mci->w) {
+ /* Warning pending */
+ mcck->warning = 1;
+ set_thread_flag(TIF_MCCK_PENDING);
+ }
+ lockdep_on();
+}
+
+static int __init machine_check_init(void)
+{
+ ctl_set_bit(14, 25); /* enable external damage MCH */
+ ctl_set_bit(14, 27); /* enable system recovery MCH */
+ ctl_set_bit(14, 24); /* enable warning MCH */
+ return 0;
+}
+arch_initcall(machine_check_init);
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index 5cd38a90e64d..b48e961a38f6 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -1,18 +1,10 @@
/*
- * arch/s390/kernel/process.c
+ * This file handles the architecture dependent parts of process handling.
*
- * S390 version
- * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
- * Hartmut Penner (hp@de.ibm.com),
- * Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
- *
- * Derived from "arch/i386/kernel/process.c"
- * Copyright (C) 1995, Linus Torvalds
- */
-
-/*
- * This file handles the architecture-dependent parts of process handling..
+ * Copyright IBM Corp. 1999,2009
+ * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>,
+ * Hartmut Penner <hp@de.ibm.com>,
+ * Denis Joseph Barrow,
*/
#include <linux/compiler.h>
@@ -47,6 +39,7 @@
#include <asm/processor.h>
#include <asm/irq.h>
#include <asm/timer.h>
+#include <asm/nmi.h>
#include "entry.h"
asmlinkage void ret_from_fork(void) asm ("ret_from_fork");
@@ -76,7 +69,6 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
return sf->gprs[8];
}
-extern void s390_handle_mcck(void);
/*
* The idle loop on a S390...
*/
@@ -149,6 +141,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
return do_fork(flags | CLONE_VM | CLONE_UNTRACED,
0, &regs, 0, NULL, NULL);
}
+EXPORT_SYMBOL(kernel_thread);
/*
* Free current thread data structures etc..
@@ -168,34 +161,35 @@ void release_thread(struct task_struct *dead_task)
}
int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp,
- unsigned long unused,
- struct task_struct * p, struct pt_regs * regs)
+ unsigned long unused,
+ struct task_struct *p, struct pt_regs *regs)
{
- struct fake_frame
- {
- struct stack_frame sf;
- struct pt_regs childregs;
- } *frame;
-
- frame = container_of(task_pt_regs(p), struct fake_frame, childregs);
- p->thread.ksp = (unsigned long) frame;
+ struct thread_info *ti;
+ struct fake_frame
+ {
+ struct stack_frame sf;
+ struct pt_regs childregs;
+ } *frame;
+
+ frame = container_of(task_pt_regs(p), struct fake_frame, childregs);
+ p->thread.ksp = (unsigned long) frame;
/* Store access registers to kernel stack of new process. */
- frame->childregs = *regs;
+ frame->childregs = *regs;
frame->childregs.gprs[2] = 0; /* child returns 0 on fork. */
- frame->childregs.gprs[15] = new_stackp;
- frame->sf.back_chain = 0;
+ frame->childregs.gprs[15] = new_stackp;
+ frame->sf.back_chain = 0;
- /* new return point is ret_from_fork */
- frame->sf.gprs[8] = (unsigned long) ret_from_fork;
+ /* new return point is ret_from_fork */
+ frame->sf.gprs[8] = (unsigned long) ret_from_fork;
- /* fake return stack for resume(), don't go back to schedule */
- frame->sf.gprs[9] = (unsigned long) frame;
+ /* fake return stack for resume(), don't go back to schedule */
+ frame->sf.gprs[9] = (unsigned long) frame;
/* Save access registers to new thread structure. */
save_access_regs(&p->thread.acrs[0]);
#ifndef CONFIG_64BIT
- /*
+ /*
* save fprs to current->thread.fp_regs to merge them with
* the emulated registers and then copy the result to the child.
*/
@@ -220,10 +214,13 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp,
#endif /* CONFIG_64BIT */
/* start new process with ar4 pointing to the correct address space */
p->thread.mm_segment = get_fs();
- /* Don't copy debug registers */
- memset(&p->thread.per_info,0,sizeof(p->thread.per_info));
-
- return 0;
+ /* Don't copy debug registers */
+ memset(&p->thread.per_info, 0, sizeof(p->thread.per_info));
+ /* Initialize per thread user and system timer values */
+ ti = task_thread_info(p);
+ ti->user_timer = 0;
+ ti->system_timer = 0;
+ return 0;
}
SYSCALL_DEFINE0(fork)
@@ -311,7 +308,7 @@ out:
int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs)
{
#ifndef CONFIG_64BIT
- /*
+ /*
* save fprs to current->thread.fp_regs to merge them with
* the emulated registers and then copy the result to the dump.
*/
@@ -322,6 +319,7 @@ int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs)
#endif /* CONFIG_64BIT */
return 1;
}
+EXPORT_SYMBOL(dump_fpu);
unsigned long get_wchan(struct task_struct *p)
{
@@ -346,4 +344,3 @@ unsigned long get_wchan(struct task_struct *p)
}
return 0;
}
-
diff --git a/arch/s390/kernel/processor.c b/arch/s390/kernel/processor.c
index 82c1872cfe80..802c8ab247f3 100644
--- a/arch/s390/kernel/processor.c
+++ b/arch/s390/kernel/processor.c
@@ -18,10 +18,11 @@
#include <asm/lowcore.h>
#include <asm/param.h>
-void __cpuinit print_cpu_info(struct cpuinfo_S390 *cpuinfo)
+void __cpuinit print_cpu_info(void)
{
pr_info("Processor %d started, address %d, identification %06X\n",
- cpuinfo->cpu_nr, cpuinfo->cpu_addr, cpuinfo->cpu_id.ident);
+ S390_lowcore.cpu_nr, S390_lowcore.cpu_addr,
+ S390_lowcore.cpu_id.ident);
}
/*
@@ -30,48 +31,46 @@ void __cpuinit print_cpu_info(struct cpuinfo_S390 *cpuinfo)
static int show_cpuinfo(struct seq_file *m, void *v)
{
- static const char *hwcap_str[8] = {
+ static const char *hwcap_str[9] = {
"esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp",
- "edat"
+ "edat", "etf3eh"
};
- struct cpuinfo_S390 *cpuinfo;
- unsigned long n = (unsigned long) v - 1;
- int i;
+ struct _lowcore *lc;
+ unsigned long n = (unsigned long) v - 1;
+ int i;
- s390_adjust_jiffies();
- preempt_disable();
- if (!n) {
- seq_printf(m, "vendor_id : IBM/S390\n"
- "# processors : %i\n"
- "bogomips per cpu: %lu.%02lu\n",
- num_online_cpus(), loops_per_jiffy/(500000/HZ),
- (loops_per_jiffy/(5000/HZ))%100);
- seq_puts(m, "features\t: ");
- for (i = 0; i < 8; i++)
- if (hwcap_str[i] && (elf_hwcap & (1UL << i)))
- seq_printf(m, "%s ", hwcap_str[i]);
- seq_puts(m, "\n");
- }
+ s390_adjust_jiffies();
+ preempt_disable();
+ if (!n) {
+ seq_printf(m, "vendor_id : IBM/S390\n"
+ "# processors : %i\n"
+ "bogomips per cpu: %lu.%02lu\n",
+ num_online_cpus(), loops_per_jiffy/(500000/HZ),
+ (loops_per_jiffy/(5000/HZ))%100);
+ seq_puts(m, "features\t: ");
+ for (i = 0; i < 9; i++)
+ if (hwcap_str[i] && (elf_hwcap & (1UL << i)))
+ seq_printf(m, "%s ", hwcap_str[i]);
+ seq_puts(m, "\n");
+ }
- if (cpu_online(n)) {
+ if (cpu_online(n)) {
#ifdef CONFIG_SMP
- if (smp_processor_id() == n)
- cpuinfo = &S390_lowcore.cpu_data;
- else
- cpuinfo = &lowcore_ptr[n]->cpu_data;
+ lc = (smp_processor_id() == n) ?
+ &S390_lowcore : lowcore_ptr[n];
#else
- cpuinfo = &S390_lowcore.cpu_data;
+ lc = &S390_lowcore;
#endif
- seq_printf(m, "processor %li: "
- "version = %02X, "
- "identification = %06X, "
- "machine = %04X\n",
- n, cpuinfo->cpu_id.version,
- cpuinfo->cpu_id.ident,
- cpuinfo->cpu_id.machine);
- }
- preempt_enable();
- return 0;
+ seq_printf(m, "processor %li: "
+ "version = %02X, "
+ "identification = %06X, "
+ "machine = %04X\n",
+ n, lc->cpu_id.version,
+ lc->cpu_id.ident,
+ lc->cpu_id.machine);
+ }
+ preempt_enable();
+ return 0;
}
static void *c_start(struct seq_file *m, loff_t *pos)
diff --git a/arch/s390/kernel/reipl64.S b/arch/s390/kernel/reipl64.S
index c41930499a5f..774147824c3d 100644
--- a/arch/s390/kernel/reipl64.S
+++ b/arch/s390/kernel/reipl64.S
@@ -1,10 +1,7 @@
/*
- * arch/s390/kernel/reipl.S
- *
- * S390 version
- * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Holger Smolinski (Holger.Smolinski@de.ibm.com)
- Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+ * Copyright IBM Corp 2000,2009
+ * Author(s): Holger Smolinski <Holger.Smolinski@de.ibm.com>,
+ * Denis Joseph Barrow,
*/
#include <asm/lowcore.h>
@@ -30,7 +27,7 @@ do_reipl_asm: basr %r13,0
mvc __LC_PREFIX_SAVE_AREA-0x1000(4,%r1),0(%r10)
stfpc __LC_FP_CREG_SAVE_AREA-0x1000(%r1)
stckc .Lclkcmp-.Lpg0(%r13)
- mvc __LC_CLOCK_COMP_SAVE_AREA-0x1000(8,%r1),.Lclkcmp-.Lpg0(%r13)
+ mvc __LC_CLOCK_COMP_SAVE_AREA-0x1000(7,%r1),.Lclkcmp-.Lpg0(%r13)
stpt __LC_CPU_TIMER_SAVE_AREA-0x1000(%r1)
stg %r13, __LC_PSW_SAVE_AREA-0x1000+8(%r1)
diff --git a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c
index 46b90cb03707..656fcbb9bd83 100644
--- a/arch/s390/kernel/s390_ksyms.c
+++ b/arch/s390/kernel/s390_ksyms.c
@@ -1,49 +1,5 @@
-/*
- * arch/s390/kernel/s390_ksyms.c
- *
- * S390 version
- */
-#include <linux/highuid.h>
#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/syscalls.h>
-#include <linux/interrupt.h>
-#include <asm/checksum.h>
-#include <asm/cpcmd.h>
-#include <asm/delay.h>
-#include <asm/pgalloc.h>
-#include <asm/setup.h>
#include <asm/ftrace.h>
-#ifdef CONFIG_IP_MULTICAST
-#include <net/arp.h>
-#endif
-
-/*
- * memory management
- */
-EXPORT_SYMBOL(_oi_bitmap);
-EXPORT_SYMBOL(_ni_bitmap);
-EXPORT_SYMBOL(_zb_findmap);
-EXPORT_SYMBOL(_sb_findmap);
-
-/*
- * binfmt_elf loader
- */
-extern int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs);
-EXPORT_SYMBOL(dump_fpu);
-EXPORT_SYMBOL(empty_zero_page);
-
-/*
- * misc.
- */
-EXPORT_SYMBOL(machine_flags);
-EXPORT_SYMBOL(__udelay);
-EXPORT_SYMBOL(kernel_thread);
-EXPORT_SYMBOL(csum_fold);
-EXPORT_SYMBOL(console_mode);
-EXPORT_SYMBOL(console_devno);
-EXPORT_SYMBOL(console_irq);
#ifdef CONFIG_FUNCTION_TRACER
EXPORT_SYMBOL(_mcount);
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index c5cfb6185eac..06201b93cbbf 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -74,9 +74,17 @@ EXPORT_SYMBOL(uaccess);
* Machine setup..
*/
unsigned int console_mode = 0;
+EXPORT_SYMBOL(console_mode);
+
unsigned int console_devno = -1;
+EXPORT_SYMBOL(console_devno);
+
unsigned int console_irq = -1;
+EXPORT_SYMBOL(console_irq);
+
unsigned long machine_flags;
+EXPORT_SYMBOL(machine_flags);
+
unsigned long elf_hwcap = 0;
char elf_platform[ELF_PLATFORM_SIZE];
@@ -86,6 +94,10 @@ volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */
int __initdata memory_end_set;
unsigned long __initdata memory_end;
+/* An array with a pointer to the lowcore of every CPU. */
+struct _lowcore *lowcore_ptr[NR_CPUS];
+EXPORT_SYMBOL(lowcore_ptr);
+
/*
* This is set up by the setup-routine at boot-time
* for S390 need to find out, what we have to setup
@@ -109,13 +121,10 @@ static struct resource data_resource = {
*/
void __cpuinit cpu_init(void)
{
- int addr = hard_smp_processor_id();
-
/*
* Store processor id in lowcore (used e.g. in timer_interrupt)
*/
- get_cpu_id(&S390_lowcore.cpu_data.cpu_id);
- S390_lowcore.cpu_data.cpu_addr = addr;
+ get_cpu_id(&S390_lowcore.cpu_id);
/*
* Force FPU initialization:
@@ -125,8 +134,7 @@ void __cpuinit cpu_init(void)
atomic_inc(&init_mm.mm_count);
current->active_mm = &init_mm;
- if (current->mm)
- BUG();
+ BUG_ON(current->mm);
enter_lazy_tlb(&init_mm, current);
}
@@ -217,7 +225,7 @@ static void __init conmode_default(void)
}
}
-#if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE)
+#ifdef CONFIG_ZFCPDUMP
static void __init setup_zfcpdump(unsigned int console_devno)
{
static char str[41];
@@ -289,11 +297,7 @@ static int __init early_parse_mem(char *p)
early_param("mem", early_parse_mem);
#ifdef CONFIG_S390_SWITCH_AMODE
-#ifdef CONFIG_PGSTE
-unsigned int switch_amode = 1;
-#else
unsigned int switch_amode = 0;
-#endif
EXPORT_SYMBOL_GPL(switch_amode);
static int set_amode_and_uaccess(unsigned long user_amode,
@@ -414,7 +418,6 @@ setup_lowcore(void)
PSW_ADDR_AMODE | (unsigned long) mcck_int_handler;
lc->io_new_psw.mask = psw_kernel_bits;
lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler;
- lc->ipl_device = S390_lowcore.ipl_device;
lc->clock_comparator = -1ULL;
lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE;
lc->async_stack = (unsigned long)
@@ -434,6 +437,7 @@ setup_lowcore(void)
lc->vdso_per_cpu_data = (unsigned long) &lc->paste[0];
#endif
set_prefix((u32)(unsigned long) lc);
+ lowcore_ptr[0] = lc;
}
static void __init
@@ -510,7 +514,7 @@ static void __init setup_memory_end(void)
unsigned long max_mem;
int i;
-#if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE)
+#ifdef CONFIG_ZFCPDUMP
if (ipl_info.type == IPL_TYPE_FCP_DUMP) {
memory_end = ZFCPDUMP_HSA_SIZE;
memory_end_set = 1;
@@ -677,7 +681,6 @@ setup_memory(void)
static void __init setup_hwcaps(void)
{
static const int stfl_bits[6] = { 0, 2, 7, 17, 19, 21 };
- struct cpuinfo_S390 *cpuinfo = &S390_lowcore.cpu_data;
unsigned long long facility_list_extended;
unsigned int facility_list;
int i;
@@ -693,15 +696,22 @@ static void __init setup_hwcaps(void)
* Bit 17: the message-security assist is installed
* Bit 19: the long-displacement facility is installed
* Bit 21: the extended-immediate facility is installed
+ * Bit 22: extended-translation facility 3 is installed
+ * Bit 30: extended-translation facility 3 enhancement facility
* These get translated to:
* HWCAP_S390_ESAN3 bit 0, HWCAP_S390_ZARCH bit 1,
* HWCAP_S390_STFLE bit 2, HWCAP_S390_MSA bit 3,
- * HWCAP_S390_LDISP bit 4, and HWCAP_S390_EIMM bit 5.
+ * HWCAP_S390_LDISP bit 4, HWCAP_S390_EIMM bit 5 and
+ * HWCAP_S390_ETF3EH bit 8 (22 && 30).
*/
for (i = 0; i < 6; i++)
if (facility_list & (1UL << (31 - stfl_bits[i])))
elf_hwcap |= 1UL << i;
+ if ((facility_list & (1UL << (31 - 22)))
+ && (facility_list & (1UL << (31 - 30))))
+ elf_hwcap |= 1UL << 8;
+
/*
* Check for additional facilities with store-facility-list-extended.
* stfle stores doublewords (8 byte) with bit 1ULL<<63 as bit 0
@@ -710,20 +720,22 @@ static void __init setup_hwcaps(void)
* How many facility words are stored depends on the number of
* doublewords passed to the instruction. The additional facilites
* are:
- * Bit 43: decimal floating point facility is installed
+ * Bit 42: decimal floating point facility is installed
+ * Bit 44: perform floating point operation facility is installed
* translated to:
- * HWCAP_S390_DFP bit 6.
+ * HWCAP_S390_DFP bit 6 (42 && 44).
*/
if ((elf_hwcap & (1UL << 2)) &&
__stfle(&facility_list_extended, 1) > 0) {
- if (facility_list_extended & (1ULL << (64 - 43)))
+ if ((facility_list_extended & (1ULL << (63 - 42)))
+ && (facility_list_extended & (1ULL << (63 - 44))))
elf_hwcap |= 1UL << 6;
}
if (MACHINE_HAS_HPAGE)
elf_hwcap |= 1UL << 7;
- switch (cpuinfo->cpu_id.machine) {
+ switch (S390_lowcore.cpu_id.machine) {
case 0x9672:
#if !defined(CONFIG_64BIT)
default: /* Use "g5" as default for 31 bit kernels. */
@@ -816,7 +828,7 @@ setup_arch(char **cmdline_p)
setup_lowcore();
cpu_init();
- __cpu_logical_map[0] = S390_lowcore.cpu_data.cpu_addr;
+ __cpu_logical_map[0] = stap();
s390_init_cpu_topology();
/*
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 2d337cbb9329..006ed5016eb4 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -32,6 +32,7 @@
#include <linux/delay.h>
#include <linux/cache.h>
#include <linux/interrupt.h>
+#include <linux/irqflags.h>
#include <linux/cpu.h>
#include <linux/timex.h>
#include <linux/bootmem.h>
@@ -50,12 +51,6 @@
#include <asm/vdso.h>
#include "entry.h"
-/*
- * An array with a pointer the lowcore of every CPU.
- */
-struct _lowcore *lowcore_ptr[NR_CPUS];
-EXPORT_SYMBOL(lowcore_ptr);
-
static struct task_struct *current_set[NR_CPUS];
static u8 smp_cpu_type;
@@ -81,9 +76,7 @@ void smp_send_stop(void)
/* Disable all interrupts/machine checks */
__load_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK);
-
- /* write magic number to zero page (absolute 0) */
- lowcore_ptr[smp_processor_id()]->panic_magic = __PANIC_MAGIC;
+ trace_hardirqs_off();
/* stop all processors */
for_each_online_cpu(cpu) {
@@ -233,7 +226,7 @@ EXPORT_SYMBOL(smp_ctl_clear_bit);
*/
#define CPU_INIT_NO 1
-#if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE)
+#ifdef CONFIG_ZFCPDUMP
/*
* zfcpdump_prefix_array holds prefix registers for the following scenario:
@@ -274,7 +267,7 @@ EXPORT_SYMBOL_GPL(zfcpdump_save_areas);
static inline void smp_get_save_area(unsigned int cpu, unsigned int phy_cpu) { }
-#endif /* CONFIG_ZFCPDUMP || CONFIG_ZFCPDUMP_MODULE */
+#endif /* CONFIG_ZFCPDUMP */
static int cpu_stopped(int cpu)
{
@@ -304,8 +297,8 @@ static int smp_rescan_cpus_sigp(cpumask_t avail)
{
int cpu_id, logical_cpu;
- logical_cpu = first_cpu(avail);
- if (logical_cpu == NR_CPUS)
+ logical_cpu = cpumask_first(&avail);
+ if (logical_cpu >= nr_cpu_ids)
return 0;
for (cpu_id = 0; cpu_id <= 65535; cpu_id++) {
if (cpu_known(cpu_id))
@@ -316,8 +309,8 @@ static int smp_rescan_cpus_sigp(cpumask_t avail)
continue;
cpu_set(logical_cpu, cpu_present_map);
smp_cpu_state[logical_cpu] = CPU_STATE_CONFIGURED;
- logical_cpu = next_cpu(logical_cpu, avail);
- if (logical_cpu == NR_CPUS)
+ logical_cpu = cpumask_next(logical_cpu, &avail);
+ if (logical_cpu >= nr_cpu_ids)
break;
}
return 0;
@@ -329,8 +322,8 @@ static int smp_rescan_cpus_sclp(cpumask_t avail)
int cpu_id, logical_cpu, cpu;
int rc;
- logical_cpu = first_cpu(avail);
- if (logical_cpu == NR_CPUS)
+ logical_cpu = cpumask_first(&avail);
+ if (logical_cpu >= nr_cpu_ids)
return 0;
info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info)
@@ -351,8 +344,8 @@ static int smp_rescan_cpus_sclp(cpumask_t avail)
smp_cpu_state[logical_cpu] = CPU_STATE_STANDBY;
else
smp_cpu_state[logical_cpu] = CPU_STATE_CONFIGURED;
- logical_cpu = next_cpu(logical_cpu, avail);
- if (logical_cpu == NR_CPUS)
+ logical_cpu = cpumask_next(logical_cpu, &avail);
+ if (logical_cpu >= nr_cpu_ids)
break;
}
out:
@@ -379,7 +372,7 @@ static void __init smp_detect_cpus(void)
c_cpus = 1;
s_cpus = 0;
- boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr;
+ boot_cpu_addr = __cpu_logical_map[0];
info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info)
panic("smp_detect_cpus failed to allocate memory\n");
@@ -453,7 +446,7 @@ int __cpuinit start_secondary(void *cpuvoid)
/* Switch on interrupts */
local_irq_enable();
/* Print info about this processor */
- print_cpu_info(&S390_lowcore.cpu_data);
+ print_cpu_info();
/* cpu_idle will call schedule for us */
cpu_idle();
return 0;
@@ -515,7 +508,6 @@ out:
return -ENOMEM;
}
-#ifdef CONFIG_HOTPLUG_CPU
static void smp_free_lowcore(int cpu)
{
struct _lowcore *lowcore;
@@ -534,7 +526,6 @@ static void smp_free_lowcore(int cpu)
free_pages((unsigned long) lowcore, lc_order);
lowcore_ptr[cpu] = NULL;
}
-#endif /* CONFIG_HOTPLUG_CPU */
/* Upping and downing of CPUs */
int __cpuinit __cpu_up(unsigned int cpu)
@@ -543,16 +534,23 @@ int __cpuinit __cpu_up(unsigned int cpu)
struct _lowcore *cpu_lowcore;
struct stack_frame *sf;
sigp_ccode ccode;
+ u32 lowcore;
if (smp_cpu_state[cpu] != CPU_STATE_CONFIGURED)
return -EIO;
if (smp_alloc_lowcore(cpu))
return -ENOMEM;
-
- ccode = signal_processor_p((__u32)(unsigned long)(lowcore_ptr[cpu]),
- cpu, sigp_set_prefix);
- if (ccode)
- return -EIO;
+ do {
+ ccode = signal_processor(cpu, sigp_initial_cpu_reset);
+ if (ccode == sigp_busy)
+ udelay(10);
+ if (ccode == sigp_not_operational)
+ goto err_out;
+ } while (ccode == sigp_busy);
+
+ lowcore = (u32)(unsigned long)lowcore_ptr[cpu];
+ while (signal_processor_p(lowcore, cpu, sigp_set_prefix) == sigp_busy)
+ udelay(10);
idle = current_set[cpu];
cpu_lowcore = lowcore_ptr[cpu];
@@ -571,9 +569,8 @@ int __cpuinit __cpu_up(unsigned int cpu)
: : "a" (&cpu_lowcore->access_regs_save_area) : "memory");
cpu_lowcore->percpu_offset = __per_cpu_offset[cpu];
cpu_lowcore->current_task = (unsigned long) idle;
- cpu_lowcore->cpu_data.cpu_nr = cpu;
+ cpu_lowcore->cpu_nr = cpu;
cpu_lowcore->kernel_asce = S390_lowcore.kernel_asce;
- cpu_lowcore->ipl_device = S390_lowcore.ipl_device;
eieio();
while (signal_processor(cpu, sigp_restart) == sigp_busy)
@@ -582,6 +579,10 @@ int __cpuinit __cpu_up(unsigned int cpu)
while (!cpu_online(cpu))
cpu_relax();
return 0;
+
+err_out:
+ smp_free_lowcore(cpu);
+ return -EIO;
}
static int __init setup_possible_cpus(char *s)
@@ -589,9 +590,8 @@ static int __init setup_possible_cpus(char *s)
int pcpus, cpu;
pcpus = simple_strtoul(s, NULL, 0);
- cpu_possible_map = cpumask_of_cpu(0);
- for (cpu = 1; cpu < pcpus && cpu < NR_CPUS; cpu++)
- cpu_set(cpu, cpu_possible_map);
+ for (cpu = 0; cpu < pcpus && cpu < nr_cpu_ids; cpu++)
+ set_cpu_possible(cpu, true);
return 0;
}
early_param("possible_cpus", setup_possible_cpus);
@@ -663,7 +663,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
/* request the 0x1201 emergency signal external interrupt */
if (register_external_interrupt(0x1201, do_ext_call_interrupt) != 0)
panic("Couldn't request external interrupt 0x1201");
- print_cpu_info(&S390_lowcore.cpu_data);
+ print_cpu_info();
/* Reallocate current lowcore, but keep its contents. */
lc_order = sizeof(long) == 8 ? 1 : 0;
diff --git a/arch/s390/kernel/sysinfo.c b/arch/s390/kernel/sysinfo.c
new file mode 100644
index 000000000000..b5e75e1061c8
--- /dev/null
+++ b/arch/s390/kernel/sysinfo.c
@@ -0,0 +1,428 @@
+/*
+ * Copyright IBM Corp. 2001, 2009
+ * Author(s): Ulrich Weigand <Ulrich.Weigand@de.ibm.com>,
+ * Martin Schwidefsky <schwidefsky@de.ibm.com>,
+ */
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <asm/ebcdic.h>
+#include <asm/sysinfo.h>
+#include <asm/cpcmd.h>
+
+/* Sigh, math-emu. Don't ask. */
+#include <asm/sfp-util.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/single.h>
+
+static inline int stsi_0(void)
+{
+ int rc = stsi(NULL, 0, 0, 0);
+ return rc == -ENOSYS ? rc : (((unsigned int) rc) >> 28);
+}
+
+static int stsi_1_1_1(struct sysinfo_1_1_1 *info, char *page, int len)
+{
+ if (stsi(info, 1, 1, 1) == -ENOSYS)
+ return len;
+
+ EBCASC(info->manufacturer, sizeof(info->manufacturer));
+ EBCASC(info->type, sizeof(info->type));
+ EBCASC(info->model, sizeof(info->model));
+ EBCASC(info->sequence, sizeof(info->sequence));
+ EBCASC(info->plant, sizeof(info->plant));
+ EBCASC(info->model_capacity, sizeof(info->model_capacity));
+ EBCASC(info->model_perm_cap, sizeof(info->model_perm_cap));
+ EBCASC(info->model_temp_cap, sizeof(info->model_temp_cap));
+ len += sprintf(page + len, "Manufacturer: %-16.16s\n",
+ info->manufacturer);
+ len += sprintf(page + len, "Type: %-4.4s\n",
+ info->type);
+ if (info->model[0] != '\0')
+ /*
+ * Sigh: the model field has been renamed with System z9
+ * to model_capacity and a new model field has been added
+ * after the plant field. To avoid confusing older programs
+ * the "Model:" prints "model_capacity model" or just
+ * "model_capacity" if the model string is empty .
+ */
+ len += sprintf(page + len,
+ "Model: %-16.16s %-16.16s\n",
+ info->model_capacity, info->model);
+ else
+ len += sprintf(page + len, "Model: %-16.16s\n",
+ info->model_capacity);
+ len += sprintf(page + len, "Sequence Code: %-16.16s\n",
+ info->sequence);
+ len += sprintf(page + len, "Plant: %-4.4s\n",
+ info->plant);
+ len += sprintf(page + len, "Model Capacity: %-16.16s %08u\n",
+ info->model_capacity, *(u32 *) info->model_cap_rating);
+ if (info->model_perm_cap[0] != '\0')
+ len += sprintf(page + len,
+ "Model Perm. Capacity: %-16.16s %08u\n",
+ info->model_perm_cap,
+ *(u32 *) info->model_perm_cap_rating);
+ if (info->model_temp_cap[0] != '\0')
+ len += sprintf(page + len,
+ "Model Temp. Capacity: %-16.16s %08u\n",
+ info->model_temp_cap,
+ *(u32 *) info->model_temp_cap_rating);
+ return len;
+}
+
+static int stsi_1_2_2(struct sysinfo_1_2_2 *info, char *page, int len)
+{
+ struct sysinfo_1_2_2_extension *ext;
+ int i;
+
+ if (stsi(info, 1, 2, 2) == -ENOSYS)
+ return len;
+ ext = (struct sysinfo_1_2_2_extension *)
+ ((unsigned long) info + info->acc_offset);
+
+ len += sprintf(page + len, "\n");
+ len += sprintf(page + len, "CPUs Total: %d\n",
+ info->cpus_total);
+ len += sprintf(page + len, "CPUs Configured: %d\n",
+ info->cpus_configured);
+ len += sprintf(page + len, "CPUs Standby: %d\n",
+ info->cpus_standby);
+ len += sprintf(page + len, "CPUs Reserved: %d\n",
+ info->cpus_reserved);
+
+ if (info->format == 1) {
+ /*
+ * Sigh 2. According to the specification the alternate
+ * capability field is a 32 bit floating point number
+ * if the higher order 8 bits are not zero. Printing
+ * a floating point number in the kernel is a no-no,
+ * always print the number as 32 bit unsigned integer.
+ * The user-space needs to know about the strange
+ * encoding of the alternate cpu capability.
+ */
+ len += sprintf(page + len, "Capability: %u %u\n",
+ info->capability, ext->alt_capability);
+ for (i = 2; i <= info->cpus_total; i++)
+ len += sprintf(page + len,
+ "Adjustment %02d-way: %u %u\n",
+ i, info->adjustment[i-2],
+ ext->alt_adjustment[i-2]);
+
+ } else {
+ len += sprintf(page + len, "Capability: %u\n",
+ info->capability);
+ for (i = 2; i <= info->cpus_total; i++)
+ len += sprintf(page + len,
+ "Adjustment %02d-way: %u\n",
+ i, info->adjustment[i-2]);
+ }
+
+ if (info->secondary_capability != 0)
+ len += sprintf(page + len, "Secondary Capability: %d\n",
+ info->secondary_capability);
+ return len;
+}
+
+static int stsi_2_2_2(struct sysinfo_2_2_2 *info, char *page, int len)
+{
+ if (stsi(info, 2, 2, 2) == -ENOSYS)
+ return len;
+
+ EBCASC(info->name, sizeof(info->name));
+
+ len += sprintf(page + len, "\n");
+ len += sprintf(page + len, "LPAR Number: %d\n",
+ info->lpar_number);
+
+ len += sprintf(page + len, "LPAR Characteristics: ");
+ if (info->characteristics & LPAR_CHAR_DEDICATED)
+ len += sprintf(page + len, "Dedicated ");
+ if (info->characteristics & LPAR_CHAR_SHARED)
+ len += sprintf(page + len, "Shared ");
+ if (info->characteristics & LPAR_CHAR_LIMITED)
+ len += sprintf(page + len, "Limited ");
+ len += sprintf(page + len, "\n");
+
+ len += sprintf(page + len, "LPAR Name: %-8.8s\n",
+ info->name);
+
+ len += sprintf(page + len, "LPAR Adjustment: %d\n",
+ info->caf);
+
+ len += sprintf(page + len, "LPAR CPUs Total: %d\n",
+ info->cpus_total);
+ len += sprintf(page + len, "LPAR CPUs Configured: %d\n",
+ info->cpus_configured);
+ len += sprintf(page + len, "LPAR CPUs Standby: %d\n",
+ info->cpus_standby);
+ len += sprintf(page + len, "LPAR CPUs Reserved: %d\n",
+ info->cpus_reserved);
+ len += sprintf(page + len, "LPAR CPUs Dedicated: %d\n",
+ info->cpus_dedicated);
+ len += sprintf(page + len, "LPAR CPUs Shared: %d\n",
+ info->cpus_shared);
+ return len;
+}
+
+static int stsi_3_2_2(struct sysinfo_3_2_2 *info, char *page, int len)
+{
+ int i;
+
+ if (stsi(info, 3, 2, 2) == -ENOSYS)
+ return len;
+ for (i = 0; i < info->count; i++) {
+ EBCASC(info->vm[i].name, sizeof(info->vm[i].name));
+ EBCASC(info->vm[i].cpi, sizeof(info->vm[i].cpi));
+ len += sprintf(page + len, "\n");
+ len += sprintf(page + len, "VM%02d Name: %-8.8s\n",
+ i, info->vm[i].name);
+ len += sprintf(page + len, "VM%02d Control Program: %-16.16s\n",
+ i, info->vm[i].cpi);
+
+ len += sprintf(page + len, "VM%02d Adjustment: %d\n",
+ i, info->vm[i].caf);
+
+ len += sprintf(page + len, "VM%02d CPUs Total: %d\n",
+ i, info->vm[i].cpus_total);
+ len += sprintf(page + len, "VM%02d CPUs Configured: %d\n",
+ i, info->vm[i].cpus_configured);
+ len += sprintf(page + len, "VM%02d CPUs Standby: %d\n",
+ i, info->vm[i].cpus_standby);
+ len += sprintf(page + len, "VM%02d CPUs Reserved: %d\n",
+ i, info->vm[i].cpus_reserved);
+ }
+ return len;
+}
+
+static int proc_read_sysinfo(char *page, char **start,
+ off_t off, int count,
+ int *eof, void *data)
+{
+ unsigned long info = get_zeroed_page(GFP_KERNEL);
+ int level, len;
+
+ if (!info)
+ return 0;
+
+ len = 0;
+ level = stsi_0();
+ if (level >= 1)
+ len = stsi_1_1_1((struct sysinfo_1_1_1 *) info, page, len);
+
+ if (level >= 1)
+ len = stsi_1_2_2((struct sysinfo_1_2_2 *) info, page, len);
+
+ if (level >= 2)
+ len = stsi_2_2_2((struct sysinfo_2_2_2 *) info, page, len);
+
+ if (level >= 3)
+ len = stsi_3_2_2((struct sysinfo_3_2_2 *) info, page, len);
+
+ free_page(info);
+ return len;
+}
+
+static __init int create_proc_sysinfo(void)
+{
+ create_proc_read_entry("sysinfo", 0444, NULL,
+ proc_read_sysinfo, NULL);
+ return 0;
+}
+device_initcall(create_proc_sysinfo);
+
+/*
+ * Service levels interface.
+ */
+
+static DECLARE_RWSEM(service_level_sem);
+static LIST_HEAD(service_level_list);
+
+int register_service_level(struct service_level *slr)
+{
+ struct service_level *ptr;
+
+ down_write(&service_level_sem);
+ list_for_each_entry(ptr, &service_level_list, list)
+ if (ptr == slr) {
+ up_write(&service_level_sem);
+ return -EEXIST;
+ }
+ list_add_tail(&slr->list, &service_level_list);
+ up_write(&service_level_sem);
+ return 0;
+}
+EXPORT_SYMBOL(register_service_level);
+
+int unregister_service_level(struct service_level *slr)
+{
+ struct service_level *ptr, *next;
+ int rc = -ENOENT;
+
+ down_write(&service_level_sem);
+ list_for_each_entry_safe(ptr, next, &service_level_list, list) {
+ if (ptr != slr)
+ continue;
+ list_del(&ptr->list);
+ rc = 0;
+ break;
+ }
+ up_write(&service_level_sem);
+ return rc;
+}
+EXPORT_SYMBOL(unregister_service_level);
+
+static void *service_level_start(struct seq_file *m, loff_t *pos)
+{
+ down_read(&service_level_sem);
+ return seq_list_start(&service_level_list, *pos);
+}
+
+static void *service_level_next(struct seq_file *m, void *p, loff_t *pos)
+{
+ return seq_list_next(p, &service_level_list, pos);
+}
+
+static void service_level_stop(struct seq_file *m, void *p)
+{
+ up_read(&service_level_sem);
+}
+
+static int service_level_show(struct seq_file *m, void *p)
+{
+ struct service_level *slr;
+
+ slr = list_entry(p, struct service_level, list);
+ slr->seq_print(m, slr);
+ return 0;
+}
+
+static const struct seq_operations service_level_seq_ops = {
+ .start = service_level_start,
+ .next = service_level_next,
+ .stop = service_level_stop,
+ .show = service_level_show
+};
+
+static int service_level_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &service_level_seq_ops);
+}
+
+static const struct file_operations service_level_ops = {
+ .open = service_level_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release
+};
+
+static void service_level_vm_print(struct seq_file *m,
+ struct service_level *slr)
+{
+ char *query_buffer, *str;
+
+ query_buffer = kmalloc(1024, GFP_KERNEL | GFP_DMA);
+ if (!query_buffer)
+ return;
+ cpcmd("QUERY CPLEVEL", query_buffer, 1024, NULL);
+ str = strchr(query_buffer, '\n');
+ if (str)
+ *str = 0;
+ seq_printf(m, "VM: %s\n", query_buffer);
+ kfree(query_buffer);
+}
+
+static struct service_level service_level_vm = {
+ .seq_print = service_level_vm_print
+};
+
+static __init int create_proc_service_level(void)
+{
+ proc_create("service_levels", 0, NULL, &service_level_ops);
+ if (MACHINE_IS_VM)
+ register_service_level(&service_level_vm);
+ return 0;
+}
+subsys_initcall(create_proc_service_level);
+
+/*
+ * Bogomips calculation based on cpu capability.
+ */
+int get_cpu_capability(unsigned int *capability)
+{
+ struct sysinfo_1_2_2 *info;
+ int rc;
+
+ info = (void *) get_zeroed_page(GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+ rc = stsi(info, 1, 2, 2);
+ if (rc == -ENOSYS)
+ goto out;
+ rc = 0;
+ *capability = info->capability;
+out:
+ free_page((unsigned long) info);
+ return rc;
+}
+
+/*
+ * CPU capability might have changed. Therefore recalculate loops_per_jiffy.
+ */
+void s390_adjust_jiffies(void)
+{
+ struct sysinfo_1_2_2 *info;
+ const unsigned int fmil = 0x4b189680; /* 1e7 as 32-bit float. */
+ FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR);
+ FP_DECL_EX;
+ unsigned int capability;
+
+ info = (void *) get_zeroed_page(GFP_KERNEL);
+ if (!info)
+ return;
+
+ if (stsi(info, 1, 2, 2) != -ENOSYS) {
+ /*
+ * Major sigh. The cpu capability encoding is "special".
+ * If the first 9 bits of info->capability are 0 then it
+ * is a 32 bit unsigned integer in the range 0 .. 2^23.
+ * If the first 9 bits are != 0 then it is a 32 bit float.
+ * In addition a lower value indicates a proportionally
+ * higher cpu capacity. Bogomips are the other way round.
+ * To get to a halfway suitable number we divide 1e7
+ * by the cpu capability number. Yes, that means a floating
+ * point division .. math-emu here we come :-)
+ */
+ FP_UNPACK_SP(SA, &fmil);
+ if ((info->capability >> 23) == 0)
+ FP_FROM_INT_S(SB, info->capability, 32, int);
+ else
+ FP_UNPACK_SP(SB, &info->capability);
+ FP_DIV_S(SR, SA, SB);
+ FP_TO_INT_S(capability, SR, 32, 0);
+ } else
+ /*
+ * Really old machine without stsi block for basic
+ * cpu information. Report 42.0 bogomips.
+ */
+ capability = 42;
+ loops_per_jiffy = capability * (500000/HZ);
+ free_page((unsigned long) info);
+}
+
+/*
+ * calibrate the delay loop
+ */
+void __cpuinit calibrate_delay(void)
+{
+ s390_adjust_jiffies();
+ /* Print the good old Bogomips line .. */
+ printk(KERN_DEBUG "Calibrating delay loop (skipped)... "
+ "%lu.%02lu BogoMIPS preset\n", loops_per_jiffy/(500000/HZ),
+ (loops_per_jiffy/(5000/HZ)) % 100);
+}
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index fc468cae4460..f72d41068dc2 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -331,6 +331,7 @@ static unsigned long long adjust_time(unsigned long long old,
}
static DEFINE_PER_CPU(atomic_t, clock_sync_word);
+static DEFINE_MUTEX(clock_sync_mutex);
static unsigned long clock_sync_flags;
#define CLOCK_SYNC_HAS_ETR 0
@@ -394,6 +395,20 @@ static void enable_sync_clock(void)
atomic_set_mask(0x80000000, sw_ptr);
}
+/*
+ * Function to check if the clock is in sync.
+ */
+static inline int check_sync_clock(void)
+{
+ atomic_t *sw_ptr;
+ int rc;
+
+ sw_ptr = &get_cpu_var(clock_sync_word);
+ rc = (atomic_read(sw_ptr) & 0x80000000U) != 0;
+ put_cpu_var(clock_sync_sync);
+ return rc;
+}
+
/* Single threaded workqueue used for etr and stp sync events */
static struct workqueue_struct *time_sync_wq;
@@ -485,6 +500,8 @@ static void etr_reset(void)
if (etr_setr(&etr_eacr) == 0) {
etr_tolec = get_clock();
set_bit(CLOCK_SYNC_HAS_ETR, &clock_sync_flags);
+ if (etr_port0_online && etr_port1_online)
+ set_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
} else if (etr_port0_online || etr_port1_online) {
pr_warning("The real or virtual hardware system does "
"not provide an ETR interface\n");
@@ -533,8 +550,7 @@ void etr_switch_to_local(void)
{
if (!etr_eacr.sl)
return;
- if (test_bit(CLOCK_SYNC_ETR, &clock_sync_flags))
- disable_sync_clock(NULL);
+ disable_sync_clock(NULL);
set_bit(ETR_EVENT_SWITCH_LOCAL, &etr_events);
queue_work(time_sync_wq, &etr_work);
}
@@ -549,8 +565,7 @@ void etr_sync_check(void)
{
if (!etr_eacr.es)
return;
- if (test_bit(CLOCK_SYNC_ETR, &clock_sync_flags))
- disable_sync_clock(NULL);
+ disable_sync_clock(NULL);
set_bit(ETR_EVENT_SYNC_CHECK, &etr_events);
queue_work(time_sync_wq, &etr_work);
}
@@ -914,7 +929,7 @@ static struct etr_eacr etr_handle_update(struct etr_aib *aib,
* Do not try to get the alternate port aib if the clock
* is not in sync yet.
*/
- if (!test_bit(CLOCK_SYNC_STP, &clock_sync_flags) && !eacr.es)
+ if (!check_sync_clock())
return eacr;
/*
@@ -997,7 +1012,6 @@ static void etr_work_fn(struct work_struct *work)
on_each_cpu(disable_sync_clock, NULL, 1);
del_timer_sync(&etr_timer);
etr_update_eacr(eacr);
- clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
goto out_unlock;
}
@@ -1071,18 +1085,13 @@ static void etr_work_fn(struct work_struct *work)
/* Both ports not usable. */
eacr.es = eacr.sl = 0;
sync_port = -1;
- clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
}
- if (!test_bit(CLOCK_SYNC_ETR, &clock_sync_flags))
- eacr.es = 0;
-
/*
* If the clock is in sync just update the eacr and return.
* If there is no valid sync port wait for a port update.
*/
- if (test_bit(CLOCK_SYNC_STP, &clock_sync_flags) ||
- eacr.es || sync_port < 0) {
+ if (check_sync_clock() || sync_port < 0) {
etr_update_eacr(eacr);
etr_set_tolec_timeout(now);
goto out_unlock;
@@ -1103,13 +1112,11 @@ static void etr_work_fn(struct work_struct *work)
* and set up a timer to try again after 0.5 seconds
*/
etr_update_eacr(eacr);
- set_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
if (now < etr_tolec + (1600000 << 12) ||
etr_sync_clock_stop(&aib, sync_port) != 0) {
/* Sync failed. Try again in 1/2 second. */
eacr.es = 0;
etr_update_eacr(eacr);
- clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
etr_set_sync_timeout();
} else
etr_set_tolec_timeout(now);
@@ -1191,19 +1198,30 @@ static ssize_t etr_online_store(struct sys_device *dev,
return -EINVAL;
if (!test_bit(CLOCK_SYNC_HAS_ETR, &clock_sync_flags))
return -EOPNOTSUPP;
+ mutex_lock(&clock_sync_mutex);
if (dev == &etr_port0_dev) {
if (etr_port0_online == value)
- return count; /* Nothing to do. */
+ goto out; /* Nothing to do. */
etr_port0_online = value;
+ if (etr_port0_online && etr_port1_online)
+ set_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
+ else
+ clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
set_bit(ETR_EVENT_PORT0_CHANGE, &etr_events);
queue_work(time_sync_wq, &etr_work);
} else {
if (etr_port1_online == value)
- return count; /* Nothing to do. */
+ goto out; /* Nothing to do. */
etr_port1_online = value;
+ if (etr_port0_online && etr_port1_online)
+ set_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
+ else
+ clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
set_bit(ETR_EVENT_PORT1_CHANGE, &etr_events);
queue_work(time_sync_wq, &etr_work);
}
+out:
+ mutex_unlock(&clock_sync_mutex);
return count;
}
@@ -1471,8 +1489,6 @@ static void stp_timing_alert(struct stp_irq_parm *intparm)
*/
void stp_sync_check(void)
{
- if (!test_bit(CLOCK_SYNC_STP, &clock_sync_flags))
- return;
disable_sync_clock(NULL);
queue_work(time_sync_wq, &stp_work);
}
@@ -1485,8 +1501,6 @@ void stp_sync_check(void)
*/
void stp_island_check(void)
{
- if (!test_bit(CLOCK_SYNC_STP, &clock_sync_flags))
- return;
disable_sync_clock(NULL);
queue_work(time_sync_wq, &stp_work);
}
@@ -1513,10 +1527,6 @@ static int stp_sync_clock(void *data)
enable_sync_clock();
- set_bit(CLOCK_SYNC_STP, &clock_sync_flags);
- if (test_and_clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags))
- queue_work(time_sync_wq, &etr_work);
-
rc = 0;
if (stp_info.todoff[0] || stp_info.todoff[1] ||
stp_info.todoff[2] || stp_info.todoff[3] ||
@@ -1535,9 +1545,6 @@ static int stp_sync_clock(void *data)
if (rc) {
disable_sync_clock(NULL);
stp_sync->in_sync = -EAGAIN;
- clear_bit(CLOCK_SYNC_STP, &clock_sync_flags);
- if (etr_port0_online || etr_port1_online)
- queue_work(time_sync_wq, &etr_work);
} else
stp_sync->in_sync = 1;
xchg(&first, 0);
@@ -1569,6 +1576,10 @@ static void stp_work_fn(struct work_struct *work)
if (rc || stp_info.c == 0)
goto out_unlock;
+ /* Skip synchronization if the clock is already in sync. */
+ if (check_sync_clock())
+ goto out_unlock;
+
memset(&stp_sync, 0, sizeof(stp_sync));
get_online_cpus();
atomic_set(&stp_sync.cpus, num_online_cpus() - 1);
@@ -1684,8 +1695,14 @@ static ssize_t stp_online_store(struct sysdev_class *class,
return -EINVAL;
if (!test_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags))
return -EOPNOTSUPP;
+ mutex_lock(&clock_sync_mutex);
stp_online = value;
+ if (stp_online)
+ set_bit(CLOCK_SYNC_STP, &clock_sync_flags);
+ else
+ clear_bit(CLOCK_SYNC_STP, &clock_sync_flags);
queue_work(time_sync_wq, &stp_work);
+ mutex_unlock(&clock_sync_mutex);
return count;
}
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c
index cc362c9ea8f1..3c72c9cf22b6 100644
--- a/arch/s390/kernel/topology.c
+++ b/arch/s390/kernel/topology.c
@@ -74,7 +74,7 @@ static DEFINE_SPINLOCK(topology_lock);
cpumask_t cpu_core_map[NR_CPUS];
-cpumask_t cpu_coregroup_map(unsigned int cpu)
+static cpumask_t cpu_coregroup_map(unsigned int cpu)
{
struct core_info *core = &core_info;
unsigned long flags;
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index 4584d81984c0..c2e42cc65ce7 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -61,9 +61,11 @@ extern pgm_check_handler_t do_asce_exception;
#define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; })
#ifndef CONFIG_64BIT
+#define LONG "%08lx "
#define FOURLONG "%08lx %08lx %08lx %08lx\n"
static int kstack_depth_to_print = 12;
#else /* CONFIG_64BIT */
+#define LONG "%016lx "
#define FOURLONG "%016lx %016lx %016lx %016lx\n"
static int kstack_depth_to_print = 20;
#endif /* CONFIG_64BIT */
@@ -155,7 +157,7 @@ void show_stack(struct task_struct *task, unsigned long *sp)
break;
if (i && ((i * sizeof (long) % 32) == 0))
printk("\n ");
- printk("%p ", (void *)*stack++);
+ printk(LONG, *stack++);
}
printk("\n");
show_trace(task, sp);
diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c
index 690e17819686..89b2e7f1b7a9 100644
--- a/arch/s390/kernel/vdso.c
+++ b/arch/s390/kernel/vdso.c
@@ -144,7 +144,6 @@ out:
return -ENOMEM;
}
-#ifdef CONFIG_HOTPLUG_CPU
void vdso_free_per_cpu(int cpu, struct _lowcore *lowcore)
{
unsigned long segment_table, page_table, page_frame;
@@ -163,7 +162,6 @@ void vdso_free_per_cpu(int cpu, struct _lowcore *lowcore)
free_page(page_table);
free_pages(segment_table, SEGMENT_ORDER);
}
-#endif /* CONFIG_HOTPLUG_CPU */
static void __vdso_init_cr5(void *dummy)
{
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index d796d05c9c01..7a2063eb88f0 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -108,6 +108,8 @@ SECTIONS
EXIT_TEXT
}
+ /* early.c uses stsi, which requires page aligned data. */
+ . = ALIGN(PAGE_SIZE);
.init.data : {
INIT_DATA
}
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index cbfe91e10120..f4d56e9939c9 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -23,7 +23,7 @@
#include <linux/timer.h>
#include <asm/lowcore.h>
#include <asm/pgtable.h>
-
+#include <asm/nmi.h>
#include "kvm-s390.h"
#include "gaccess.h"
@@ -286,7 +286,7 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
setup_timer(&vcpu->arch.ckc_timer, kvm_s390_idle_wakeup,
(unsigned long) vcpu);
get_cpu_id(&vcpu->arch.cpu_id);
- vcpu->arch.cpu_id.version = 0xfe;
+ vcpu->arch.cpu_id.version = 0xff;
return 0;
}
@@ -440,8 +440,6 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
return -EINVAL; /* not implemented yet */
}
-extern void s390_handle_mcck(void);
-
static void __vcpu_run(struct kvm_vcpu *vcpu)
{
memcpy(&vcpu->arch.sie_block->gg14, &vcpu->arch.guest_gprs[14], 16);
diff --git a/arch/s390/lib/delay.c b/arch/s390/lib/delay.c
index 6ccb9fab055a..3f5f680726ed 100644
--- a/arch/s390/lib/delay.c
+++ b/arch/s390/lib/delay.c
@@ -9,6 +9,7 @@
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/timex.h>
+#include <linux/module.h>
#include <linux/irqflags.h>
#include <linux/interrupt.h>
@@ -92,6 +93,7 @@ out:
local_irq_restore(flags);
preempt_enable();
}
+EXPORT_SYMBOL(__udelay);
/*
* Simple udelay variant. To be used on startup and reboot
diff --git a/arch/s390/lib/string.c b/arch/s390/lib/string.c
index ae5cf5d03d41..4143b7c19096 100644
--- a/arch/s390/lib/string.c
+++ b/arch/s390/lib/string.c
@@ -44,7 +44,11 @@ static inline char *__strnend(const char *s, size_t n)
*/
size_t strlen(const char *s)
{
+#if __GNUC__ < 4
return __strend(s) - s;
+#else
+ return __builtin_strlen(s);
+#endif
}
EXPORT_SYMBOL(strlen);
@@ -70,6 +74,7 @@ EXPORT_SYMBOL(strnlen);
*/
char *strcpy(char *dest, const char *src)
{
+#if __GNUC__ < 4
register int r0 asm("0") = 0;
char *ret = dest;
@@ -78,6 +83,9 @@ char *strcpy(char *dest, const char *src)
: "+&a" (dest), "+&a" (src) : "d" (r0)
: "cc", "memory" );
return ret;
+#else
+ return __builtin_strcpy(dest, src);
+#endif
}
EXPORT_SYMBOL(strcpy);
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 4d537205e83c..833e8366c351 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -200,29 +200,6 @@ static void do_low_address(struct pt_regs *regs, unsigned long error_code)
do_no_context(regs, error_code, 0);
}
-/*
- * We ran out of memory, or some other thing happened to us that made
- * us unable to handle the page fault gracefully.
- */
-static int do_out_of_memory(struct pt_regs *regs, unsigned long error_code,
- unsigned long address)
-{
- struct task_struct *tsk = current;
- struct mm_struct *mm = tsk->mm;
-
- up_read(&mm->mmap_sem);
- if (is_global_init(tsk)) {
- yield();
- down_read(&mm->mmap_sem);
- return 1;
- }
- printk("VM: killing process %s\n", tsk->comm);
- if (regs->psw.mask & PSW_MASK_PSTATE)
- do_group_exit(SIGKILL);
- do_no_context(regs, error_code, address);
- return 0;
-}
-
static void do_sigbus(struct pt_regs *regs, unsigned long error_code,
unsigned long address)
{
@@ -367,7 +344,6 @@ good_area:
goto bad_area;
}
-survive:
if (is_vm_hugetlb_page(vma))
address &= HPAGE_MASK;
/*
@@ -378,8 +354,8 @@ survive:
fault = handle_mm_fault(mm, vma, address, write);
if (unlikely(fault & VM_FAULT_ERROR)) {
if (fault & VM_FAULT_OOM) {
- if (do_out_of_memory(regs, error_code, address))
- goto survive;
+ up_read(&mm->mmap_sem);
+ pagefault_out_of_memory();
return;
} else if (fault & VM_FAULT_SIGBUS) {
do_sigbus(regs, error_code, address);
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index f0258ca3b17e..c634dfbe92e9 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -40,7 +40,9 @@
DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE)));
+
char empty_zero_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
+EXPORT_SYMBOL(empty_zero_page);
/*
* paging_init() sets up the page tables
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index 6b6ddc4ea02b..be6c1cf4ad5a 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -258,6 +258,10 @@ int s390_enable_sie(void)
struct task_struct *tsk = current;
struct mm_struct *mm, *old_mm;
+ /* Do we have switched amode? If no, we cannot do sie */
+ if (!switch_amode)
+ return -EINVAL;
+
/* Do we have pgstes? if yes, we are done */
if (tsk->mm->context.has_pgste)
return 0;
@@ -292,7 +296,7 @@ int s390_enable_sie(void)
tsk->mm = tsk->active_mm = mm;
preempt_disable();
update_mm(mm, tsk);
- cpu_set(smp_processor_id(), mm->cpu_vm_mask);
+ cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm));
preempt_enable();
task_unlock(tsk);
mmput(old_mm);