summaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2006-10-01 18:55:53 +0200
committerDavid Woodhouse <dwmw2@infradead.org>2006-10-01 18:55:53 +0200
commit8a84fc15ae5cafcc366dd85cf8e1ab2040679abc (patch)
tree5d8dce194c9667fa92e9ec9f545cec867a9a1e0d /arch/s390
parent[MTD ONENAND] Check OneNAND lock scheme & all block unlock command support (diff)
parentMerge master.kernel.org:/pub/scm/linux/kernel/git/davej/agpgart (diff)
downloadlinux-8a84fc15ae5cafcc366dd85cf8e1ab2040679abc.tar.xz
linux-8a84fc15ae5cafcc366dd85cf8e1ab2040679abc.zip
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Manually resolve conflict in include/mtd/Kbuild Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/Kconfig29
-rw-r--r--arch/s390/Makefile1
-rw-r--r--arch/s390/appldata/appldata.h16
-rw-r--r--arch/s390/appldata/appldata_base.c85
-rw-r--r--arch/s390/appldata/appldata_mem.c3
-rw-r--r--arch/s390/appldata/appldata_os.c1
-rw-r--r--arch/s390/crypto/aes_s390.c285
-rw-r--r--arch/s390/crypto/crypt_s390.h207
-rw-r--r--arch/s390/crypto/des_s390.c559
-rw-r--r--arch/s390/crypto/sha1_s390.c2
-rw-r--r--arch/s390/crypto/sha256_s390.c2
-rw-r--r--arch/s390/defconfig1
-rw-r--r--arch/s390/hypfs/hypfs.h2
-rw-r--r--arch/s390/hypfs/hypfs_diag.c42
-rw-r--r--arch/s390/hypfs/hypfs_diag.h2
-rw-r--r--arch/s390/hypfs/inode.c36
-rw-r--r--arch/s390/kernel/Makefile3
-rw-r--r--arch/s390/kernel/compat_linux.c7
-rw-r--r--arch/s390/kernel/compat_wrapper.S442
-rw-r--r--arch/s390/kernel/cpcmd.c83
-rw-r--r--arch/s390/kernel/debug.c2
-rw-r--r--arch/s390/kernel/entry.S481
-rw-r--r--arch/s390/kernel/entry64.S459
-rw-r--r--arch/s390/kernel/head.S691
-rw-r--r--arch/s390/kernel/head31.S59
-rw-r--r--arch/s390/kernel/head64.S472
-rw-r--r--arch/s390/kernel/ipl.c933
-rw-r--r--arch/s390/kernel/kprobes.c657
-rw-r--r--arch/s390/kernel/process.c5
-rw-r--r--arch/s390/kernel/reipl.S108
-rw-r--r--arch/s390/kernel/reipl64.S127
-rw-r--r--arch/s390/kernel/reipl_diag.c39
-rw-r--r--arch/s390/kernel/relocate_kernel.S74
-rw-r--r--arch/s390/kernel/relocate_kernel64.S82
-rw-r--r--arch/s390/kernel/s390_ksyms.c6
-rw-r--r--arch/s390/kernel/semaphore.c22
-rw-r--r--arch/s390/kernel/setup.c274
-rw-r--r--arch/s390/kernel/signal.c40
-rw-r--r--arch/s390/kernel/smp.c83
-rw-r--r--arch/s390/kernel/stacktrace.c17
-rw-r--r--arch/s390/kernel/time.c26
-rw-r--r--arch/s390/kernel/traps.c34
-rw-r--r--arch/s390/kernel/vmlinux.lds.S3
-rw-r--r--arch/s390/lib/Makefile5
-rw-r--r--arch/s390/lib/delay.c11
-rw-r--r--arch/s390/lib/div64.c151
-rw-r--r--arch/s390/lib/spinlock.c62
-rw-r--r--arch/s390/lib/uaccess.S211
-rw-r--r--arch/s390/lib/uaccess64.S207
-rw-r--r--arch/s390/lib/uaccess_mvcos.c166
-rw-r--r--arch/s390/lib/uaccess_std.c356
-rw-r--r--arch/s390/math-emu/math.c126
-rw-r--r--arch/s390/math-emu/sfp-util.h73
-rw-r--r--arch/s390/mm/cmm.c225
-rw-r--r--arch/s390/mm/extmem.c16
-rw-r--r--arch/s390/mm/fault.c77
-rw-r--r--arch/s390/mm/init.c77
57 files changed, 5073 insertions, 3192 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 2f4f70c4dbb2..f900a516f099 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -51,6 +51,10 @@ config 64BIT
Select this option if you have a 64 bit IBM zSeries machine
and want to use the 64 bit addressing mode.
+config 32BIT
+ bool
+ default y if !64BIT
+
config SMP
bool "Symmetric multi-processing support"
---help---
@@ -149,6 +153,14 @@ config MARCH_Z990
This will be slightly faster but does not work on
older machines such as the z900.
+config MARCH_Z9_109
+ bool "IBM System z9"
+ help
+ Select this to enable optimizations for IBM System z9-109, IBM
+ System z9 Enterprise Class (z9 EC), and IBM System z9 Business
+ Class (z9 BC). The kernel will be slightly faster but will not
+ work on older machines such as the z990, z890, z900, and z800.
+
endchoice
config PACK_STACK
@@ -460,8 +472,7 @@ config S390_HYPFS_FS
information in an s390 hypervisor environment.
config KEXEC
- bool "kexec system call (EXPERIMENTAL)"
- depends on EXPERIMENTAL
+ bool "kexec system call"
help
kexec is a system call that implements the ability to shutdown your
current kernel, and to start another kernel. It is like a reboot
@@ -487,8 +498,22 @@ source "drivers/net/Kconfig"
source "fs/Kconfig"
+menu "Instrumentation Support"
+
source "arch/s390/oprofile/Kconfig"
+config KPROBES
+ bool "Kprobes (EXPERIMENTAL)"
+ depends on EXPERIMENTAL && MODULES
+ help
+ Kprobes allows you to trap at almost any kernel address and
+ execute a callback function. register_kprobe() establishes
+ a probepoint and specifies the callback. Kprobes is useful
+ for kernel debugging, non-intrusive instrumentation and testing.
+ If in doubt, say "N".
+
+endmenu
+
source "arch/s390/Kconfig.debug"
source "security/Kconfig"
diff --git a/arch/s390/Makefile b/arch/s390/Makefile
index 74ef57dcfa60..5deb9f7544a1 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
@@ -33,6 +33,7 @@ endif
cflags-$(CONFIG_MARCH_G5) += $(call cc-option,-march=g5)
cflags-$(CONFIG_MARCH_Z900) += $(call cc-option,-march=z900)
cflags-$(CONFIG_MARCH_Z990) += $(call cc-option,-march=z990)
+cflags-$(CONFIG_MARCH_Z9_109) += $(call cc-option,-march=z9-109)
#
# Prevent tail-call optimizations, to get clearer backtraces:
diff --git a/arch/s390/appldata/appldata.h b/arch/s390/appldata/appldata.h
index 71d65eb30650..0429481dea63 100644
--- a/arch/s390/appldata/appldata.h
+++ b/arch/s390/appldata/appldata.h
@@ -29,22 +29,6 @@
#define CTL_APPLDATA_NET_SUM 2125
#define CTL_APPLDATA_PROC 2126
-#ifndef CONFIG_64BIT
-
-#define APPLDATA_START_INTERVAL_REC 0x00 /* Function codes for */
-#define APPLDATA_STOP_REC 0x01 /* DIAG 0xDC */
-#define APPLDATA_GEN_EVENT_RECORD 0x02
-#define APPLDATA_START_CONFIG_REC 0x03
-
-#else
-
-#define APPLDATA_START_INTERVAL_REC 0x80
-#define APPLDATA_STOP_REC 0x81
-#define APPLDATA_GEN_EVENT_RECORD 0x82
-#define APPLDATA_START_CONFIG_REC 0x83
-
-#endif /* CONFIG_64BIT */
-
#define P_INFO(x...) printk(KERN_INFO MY_PRINT_NAME " info: " x)
#define P_ERROR(x...) printk(KERN_ERR MY_PRINT_NAME " error: " x)
#define P_WARNING(x...) printk(KERN_WARNING MY_PRINT_NAME " status: " x)
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c
index a0a94e0ef8d1..2b1e6c9a6e0e 100644
--- a/arch/s390/appldata/appldata_base.c
+++ b/arch/s390/appldata/appldata_base.c
@@ -14,20 +14,20 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/errno.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/smp.h>
#include <linux/interrupt.h>
#include <linux/proc_fs.h>
-#include <linux/page-flags.h>
+#include <linux/mm.h>
#include <linux/swap.h>
#include <linux/pagemap.h>
#include <linux/sysctl.h>
-#include <asm/timer.h>
-//#include <linux/kernel_stat.h>
#include <linux/notifier.h>
#include <linux/cpu.h>
#include <linux/workqueue.h>
+#include <asm/appldata.h>
+#include <asm/timer.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/smp.h>
#include "appldata.h"
@@ -39,34 +39,6 @@
#define TOD_MICRO 0x01000 /* nr. of TOD clock units
for 1 microsecond */
-
-/*
- * Parameter list for DIAGNOSE X'DC'
- */
-#ifndef CONFIG_64BIT
-struct appldata_parameter_list {
- u16 diag; /* The DIAGNOSE code X'00DC' */
- u8 function; /* The function code for the DIAGNOSE */
- u8 parlist_length; /* Length of the parameter list */
- u32 product_id_addr; /* Address of the 16-byte product ID */
- u16 reserved;
- u16 buffer_length; /* Length of the application data buffer */
- u32 buffer_addr; /* Address of the application data buffer */
-};
-#else
-struct appldata_parameter_list {
- u16 diag;
- u8 function;
- u8 parlist_length;
- u32 unused01;
- u16 reserved;
- u16 buffer_length;
- u32 unused02;
- u64 product_id_addr;
- u64 buffer_addr;
-};
-#endif /* CONFIG_64BIT */
-
/*
* /proc entries (sysctl)
*/
@@ -181,46 +153,17 @@ static void appldata_work_fn(void *data)
int appldata_diag(char record_nr, u16 function, unsigned long buffer,
u16 length, char *mod_lvl)
{
- unsigned long ry;
- struct appldata_product_id {
- char prod_nr[7]; /* product nr. */
- char prod_fn[2]; /* product function */
- char record_nr; /* record nr. */
- char version_nr[2]; /* version */
- char release_nr[2]; /* release */
- char mod_lvl[2]; /* modification lvl. */
- } appldata_product_id = {
- /* all strings are EBCDIC, record_nr is byte */
+ struct appldata_product_id id = {
.prod_nr = {0xD3, 0xC9, 0xD5, 0xE4,
- 0xE7, 0xD2, 0xD9}, /* "LINUXKR" */
- .prod_fn = {0xD5, 0xD3}, /* "NL" */
- .record_nr = record_nr,
- .version_nr = {0xF2, 0xF6}, /* "26" */
- .release_nr = {0xF0, 0xF1}, /* "01" */
- .mod_lvl = {mod_lvl[0], mod_lvl[1]},
- };
- struct appldata_parameter_list appldata_parameter_list = {
- .diag = 0xDC,
- .function = function,
- .parlist_length =
- sizeof(appldata_parameter_list),
- .buffer_length = length,
- .product_id_addr =
- (unsigned long) &appldata_product_id,
- .buffer_addr = virt_to_phys((void *) buffer)
+ 0xE7, 0xD2, 0xD9}, /* "LINUXKR" */
+ .prod_fn = 0xD5D3, /* "NL" */
+ .version_nr = 0xF2F6, /* "26" */
+ .release_nr = 0xF0F1, /* "01" */
};
- if (!MACHINE_IS_VM)
- return -ENOSYS;
- ry = -1;
- asm volatile(
- "diag %1,%0,0xDC\n\t"
- : "=d" (ry)
- : "d" (&appldata_parameter_list),
- "m" (appldata_parameter_list),
- "m" (appldata_product_id)
- : "cc");
- return (int) ry;
+ id.record_nr = record_nr;
+ id.mod_lvl = (mod_lvl[0]) << 8 | mod_lvl[1];
+ return appldata_asm(&id, function, (void *) buffer, length);
}
/************************ timer, work, DIAG <END> ****************************/
diff --git a/arch/s390/appldata/appldata_mem.c b/arch/s390/appldata/appldata_mem.c
index ab3b0765a64e..8aea3698a77b 100644
--- a/arch/s390/appldata/appldata_mem.c
+++ b/arch/s390/appldata/appldata_mem.c
@@ -117,8 +117,7 @@ static void appldata_get_mem_data(void *data)
mem_data->pgpgout = ev[PGPGOUT] >> 1;
mem_data->pswpin = ev[PSWPIN];
mem_data->pswpout = ev[PSWPOUT];
- mem_data->pgalloc = ev[PGALLOC_HIGH] + ev[PGALLOC_NORMAL] +
- ev[PGALLOC_DMA];
+ mem_data->pgalloc = ev[PGALLOC_NORMAL] + ev[PGALLOC_DMA];
mem_data->pgfault = ev[PGFAULT];
mem_data->pgmajfault = ev[PGMAJFAULT];
diff --git a/arch/s390/appldata/appldata_os.c b/arch/s390/appldata/appldata_os.c
index 161acc5c8a1b..76a15523ae9e 100644
--- a/arch/s390/appldata/appldata_os.c
+++ b/arch/s390/appldata/appldata_os.c
@@ -16,6 +16,7 @@
#include <linux/kernel_stat.h>
#include <linux/netdevice.h>
#include <linux/sched.h>
+#include <asm/appldata.h>
#include <asm/smp.h>
#include "appldata.h"
diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c
index 5713c7e5bd16..15c9eec02928 100644
--- a/arch/s390/crypto/aes_s390.c
+++ b/arch/s390/crypto/aes_s390.c
@@ -16,9 +16,9 @@
*
*/
+#include <crypto/algapi.h>
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/crypto.h>
#include "crypt_s390.h"
#define AES_MIN_KEY_SIZE 16
@@ -34,13 +34,16 @@ int has_aes_256 = 0;
struct s390_aes_ctx {
u8 iv[AES_BLOCK_SIZE];
u8 key[AES_MAX_KEY_SIZE];
+ long enc;
+ long dec;
int key_len;
};
static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
- unsigned int key_len, u32 *flags)
+ unsigned int key_len)
{
struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
+ u32 *flags = &tfm->crt_flags;
switch (key_len) {
case 16:
@@ -110,133 +113,206 @@ static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
}
}
-static unsigned int aes_encrypt_ecb(const struct cipher_desc *desc, u8 *out,
- const u8 *in, unsigned int nbytes)
-{
- struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm);
- int ret;
- /* only use complete blocks */
- nbytes &= ~(AES_BLOCK_SIZE - 1);
+static struct crypto_alg aes_alg = {
+ .cra_name = "aes",
+ .cra_driver_name = "aes-s390",
+ .cra_priority = CRYPT_S390_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct s390_aes_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(aes_alg.cra_list),
+ .cra_u = {
+ .cipher = {
+ .cia_min_keysize = AES_MIN_KEY_SIZE,
+ .cia_max_keysize = AES_MAX_KEY_SIZE,
+ .cia_setkey = aes_set_key,
+ .cia_encrypt = aes_encrypt,
+ .cia_decrypt = aes_decrypt,
+ }
+ }
+};
+
+static int ecb_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+ unsigned int key_len)
+{
+ struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
- switch (sctx->key_len) {
+ switch (key_len) {
case 16:
- ret = crypt_s390_km(KM_AES_128_ENCRYPT, &sctx->key, out, in, nbytes);
- BUG_ON((ret < 0) || (ret != nbytes));
+ sctx->enc = KM_AES_128_ENCRYPT;
+ sctx->dec = KM_AES_128_DECRYPT;
break;
case 24:
- ret = crypt_s390_km(KM_AES_192_ENCRYPT, &sctx->key, out, in, nbytes);
- BUG_ON((ret < 0) || (ret != nbytes));
+ sctx->enc = KM_AES_192_ENCRYPT;
+ sctx->dec = KM_AES_192_DECRYPT;
break;
case 32:
- ret = crypt_s390_km(KM_AES_256_ENCRYPT, &sctx->key, out, in, nbytes);
- BUG_ON((ret < 0) || (ret != nbytes));
+ sctx->enc = KM_AES_256_ENCRYPT;
+ sctx->dec = KM_AES_256_DECRYPT;
break;
}
- return nbytes;
+
+ return aes_set_key(tfm, in_key, key_len);
}
-static unsigned int aes_decrypt_ecb(const struct cipher_desc *desc, u8 *out,
- const u8 *in, unsigned int nbytes)
+static int ecb_aes_crypt(struct blkcipher_desc *desc, long func, void *param,
+ struct blkcipher_walk *walk)
{
- struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm);
- int ret;
+ int ret = blkcipher_walk_virt(desc, walk);
+ unsigned int nbytes;
- /* only use complete blocks */
- nbytes &= ~(AES_BLOCK_SIZE - 1);
+ while ((nbytes = walk->nbytes)) {
+ /* only use complete blocks */
+ unsigned int n = nbytes & ~(AES_BLOCK_SIZE - 1);
+ u8 *out = walk->dst.virt.addr;
+ u8 *in = walk->src.virt.addr;
- switch (sctx->key_len) {
- case 16:
- ret = crypt_s390_km(KM_AES_128_DECRYPT, &sctx->key, out, in, nbytes);
- BUG_ON((ret < 0) || (ret != nbytes));
- break;
- case 24:
- ret = crypt_s390_km(KM_AES_192_DECRYPT, &sctx->key, out, in, nbytes);
- BUG_ON((ret < 0) || (ret != nbytes));
- break;
- case 32:
- ret = crypt_s390_km(KM_AES_256_DECRYPT, &sctx->key, out, in, nbytes);
- BUG_ON((ret < 0) || (ret != nbytes));
- break;
+ ret = crypt_s390_km(func, param, out, in, n);
+ BUG_ON((ret < 0) || (ret != n));
+
+ nbytes &= AES_BLOCK_SIZE - 1;
+ ret = blkcipher_walk_done(desc, walk, nbytes);
}
- return nbytes;
+
+ return ret;
}
-static unsigned int aes_encrypt_cbc(const struct cipher_desc *desc, u8 *out,
- const u8 *in, unsigned int nbytes)
+static int ecb_aes_encrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
{
- struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm);
- int ret;
+ struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
- /* only use complete blocks */
- nbytes &= ~(AES_BLOCK_SIZE - 1);
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ return ecb_aes_crypt(desc, sctx->enc, sctx->key, &walk);
+}
- memcpy(&sctx->iv, desc->info, AES_BLOCK_SIZE);
- switch (sctx->key_len) {
+static int ecb_aes_decrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ return ecb_aes_crypt(desc, sctx->dec, sctx->key, &walk);
+}
+
+static struct crypto_alg ecb_aes_alg = {
+ .cra_name = "ecb(aes)",
+ .cra_driver_name = "ecb-aes-s390",
+ .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct s390_aes_ctx),
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(ecb_aes_alg.cra_list),
+ .cra_u = {
+ .blkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .setkey = ecb_aes_set_key,
+ .encrypt = ecb_aes_encrypt,
+ .decrypt = ecb_aes_decrypt,
+ }
+ }
+};
+
+static int cbc_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+ unsigned int key_len)
+{
+ struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
+
+ switch (key_len) {
case 16:
- ret = crypt_s390_kmc(KMC_AES_128_ENCRYPT, &sctx->iv, out, in, nbytes);
- BUG_ON((ret < 0) || (ret != nbytes));
+ sctx->enc = KMC_AES_128_ENCRYPT;
+ sctx->dec = KMC_AES_128_DECRYPT;
break;
case 24:
- ret = crypt_s390_kmc(KMC_AES_192_ENCRYPT, &sctx->iv, out, in, nbytes);
- BUG_ON((ret < 0) || (ret != nbytes));
+ sctx->enc = KMC_AES_192_ENCRYPT;
+ sctx->dec = KMC_AES_192_DECRYPT;
break;
case 32:
- ret = crypt_s390_kmc(KMC_AES_256_ENCRYPT, &sctx->iv, out, in, nbytes);
- BUG_ON((ret < 0) || (ret != nbytes));
+ sctx->enc = KMC_AES_256_ENCRYPT;
+ sctx->dec = KMC_AES_256_DECRYPT;
break;
}
- memcpy(desc->info, &sctx->iv, AES_BLOCK_SIZE);
- return nbytes;
+ return aes_set_key(tfm, in_key, key_len);
}
-static unsigned int aes_decrypt_cbc(const struct cipher_desc *desc, u8 *out,
- const u8 *in, unsigned int nbytes)
+static int cbc_aes_crypt(struct blkcipher_desc *desc, long func, void *param,
+ struct blkcipher_walk *walk)
{
- struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm);
- int ret;
+ int ret = blkcipher_walk_virt(desc, walk);
+ unsigned int nbytes = walk->nbytes;
- /* only use complete blocks */
- nbytes &= ~(AES_BLOCK_SIZE - 1);
+ if (!nbytes)
+ goto out;
- memcpy(&sctx->iv, desc->info, AES_BLOCK_SIZE);
- switch (sctx->key_len) {
- case 16:
- ret = crypt_s390_kmc(KMC_AES_128_DECRYPT, &sctx->iv, out, in, nbytes);
- BUG_ON((ret < 0) || (ret != nbytes));
- break;
- case 24:
- ret = crypt_s390_kmc(KMC_AES_192_DECRYPT, &sctx->iv, out, in, nbytes);
- BUG_ON((ret < 0) || (ret != nbytes));
- break;
- case 32:
- ret = crypt_s390_kmc(KMC_AES_256_DECRYPT, &sctx->iv, out, in, nbytes);
- BUG_ON((ret < 0) || (ret != nbytes));
- break;
- }
- return nbytes;
+ memcpy(param, walk->iv, AES_BLOCK_SIZE);
+ do {
+ /* only use complete blocks */
+ unsigned int n = nbytes & ~(AES_BLOCK_SIZE - 1);
+ u8 *out = walk->dst.virt.addr;
+ u8 *in = walk->src.virt.addr;
+
+ ret = crypt_s390_kmc(func, param, out, in, n);
+ BUG_ON((ret < 0) || (ret != n));
+
+ nbytes &= AES_BLOCK_SIZE - 1;
+ ret = blkcipher_walk_done(desc, walk, nbytes);
+ } while ((nbytes = walk->nbytes));
+ memcpy(walk->iv, param, AES_BLOCK_SIZE);
+
+out:
+ return ret;
}
+static int cbc_aes_encrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
-static struct crypto_alg aes_alg = {
- .cra_name = "aes",
- .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ return cbc_aes_crypt(desc, sctx->enc, sctx->iv, &walk);
+}
+
+static int cbc_aes_decrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ return cbc_aes_crypt(desc, sctx->dec, sctx->iv, &walk);
+}
+
+static struct crypto_alg cbc_aes_alg = {
+ .cra_name = "cbc(aes)",
+ .cra_driver_name = "cbc-aes-s390",
+ .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
.cra_blocksize = AES_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct s390_aes_ctx),
+ .cra_type = &crypto_blkcipher_type,
.cra_module = THIS_MODULE,
- .cra_list = LIST_HEAD_INIT(aes_alg.cra_list),
+ .cra_list = LIST_HEAD_INIT(cbc_aes_alg.cra_list),
.cra_u = {
- .cipher = {
- .cia_min_keysize = AES_MIN_KEY_SIZE,
- .cia_max_keysize = AES_MAX_KEY_SIZE,
- .cia_setkey = aes_set_key,
- .cia_encrypt = aes_encrypt,
- .cia_decrypt = aes_decrypt,
- .cia_encrypt_ecb = aes_encrypt_ecb,
- .cia_decrypt_ecb = aes_decrypt_ecb,
- .cia_encrypt_cbc = aes_encrypt_cbc,
- .cia_decrypt_cbc = aes_decrypt_cbc,
+ .blkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ .setkey = cbc_aes_set_key,
+ .encrypt = cbc_aes_encrypt,
+ .decrypt = cbc_aes_decrypt,
}
}
};
@@ -256,13 +332,40 @@ static int __init aes_init(void)
return -ENOSYS;
ret = crypto_register_alg(&aes_alg);
- if (ret != 0)
- printk(KERN_INFO "crypt_s390: aes_s390 couldn't be loaded.\n");
+ if (ret != 0) {
+ printk(KERN_INFO "crypt_s390: aes-s390 couldn't be loaded.\n");
+ goto aes_err;
+ }
+
+ ret = crypto_register_alg(&ecb_aes_alg);
+ if (ret != 0) {
+ printk(KERN_INFO
+ "crypt_s390: ecb-aes-s390 couldn't be loaded.\n");
+ goto ecb_aes_err;
+ }
+
+ ret = crypto_register_alg(&cbc_aes_alg);
+ if (ret != 0) {
+ printk(KERN_INFO
+ "crypt_s390: cbc-aes-s390 couldn't be loaded.\n");
+ goto cbc_aes_err;
+ }
+
+out:
return ret;
+
+cbc_aes_err:
+ crypto_unregister_alg(&ecb_aes_alg);
+ecb_aes_err:
+ crypto_unregister_alg(&aes_alg);
+aes_err:
+ goto out;
}
static void __exit aes_fini(void)
{
+ crypto_unregister_alg(&cbc_aes_alg);
+ crypto_unregister_alg(&ecb_aes_alg);
crypto_unregister_alg(&aes_alg);
}
diff --git a/arch/s390/crypto/crypt_s390.h b/arch/s390/crypto/crypt_s390.h
index d1c259a7fe33..2b137089f625 100644
--- a/arch/s390/crypto/crypt_s390.h
+++ b/arch/s390/crypto/crypt_s390.h
@@ -20,6 +20,9 @@
#define CRYPT_S390_OP_MASK 0xFF00
#define CRYPT_S390_FUNC_MASK 0x00FF
+#define CRYPT_S390_PRIORITY 300
+#define CRYPT_S390_COMPOSITE_PRIORITY 400
+
/* s930 cryptographic operations */
enum crypt_s390_operations {
CRYPT_S390_KM = 0x0100,
@@ -102,63 +105,6 @@ struct crypt_s390_query_status {
};
/*
- * Standard fixup and ex_table sections for crypt_s390 inline functions.
- * label 0: the s390 crypto operation
- * label 1: just after 1 to catch illegal operation exception
- * (unsupported model)
- * label 6: the return point after fixup
- * label 7: set error value if exception _in_ crypto operation
- * label 8: set error value if illegal operation exception
- * [ret] is the variable to receive the error code
- * [ERR] is the error code value
- */
-#ifndef CONFIG_64BIT
-#define __crypt_s390_fixup \
- ".section .fixup,\"ax\" \n" \
- "7: lhi %0,%h[e1] \n" \
- " bras 1,9f \n" \
- " .long 6b \n" \
- "8: lhi %0,%h[e2] \n" \
- " bras 1,9f \n" \
- " .long 6b \n" \
- "9: l 1,0(1) \n" \
- " br 1 \n" \
- ".previous \n" \
- ".section __ex_table,\"a\" \n" \
- " .align 4 \n" \
- " .long 0b,7b \n" \
- " .long 1b,8b \n" \
- ".previous"
-#else /* CONFIG_64BIT */
-#define __crypt_s390_fixup \
- ".section .fixup,\"ax\" \n" \
- "7: lhi %0,%h[e1] \n" \
- " jg 6b \n" \
- "8: lhi %0,%h[e2] \n" \
- " jg 6b \n" \
- ".previous\n" \
- ".section __ex_table,\"a\" \n" \
- " .align 8 \n" \
- " .quad 0b,7b \n" \
- " .quad 1b,8b \n" \
- ".previous"
-#endif /* CONFIG_64BIT */
-
-/*
- * Standard code for setting the result of s390 crypto instructions.
- * %0: the register which will receive the result
- * [result]: the register containing the result (e.g. second operand length
- * to compute number of processed bytes].
- */
-#ifndef CONFIG_64BIT
-#define __crypt_s390_set_result \
- " lr %0,%[result] \n"
-#else /* CONFIG_64BIT */
-#define __crypt_s390_set_result \
- " lgr %0,%[result] \n"
-#endif
-
-/*
* Executes the KM (CIPHER MESSAGE) operation of the CPU.
* @param func: the function code passed to KM; see crypt_s390_km_func
* @param param: address of parameter block; see POP for details on each func
@@ -173,28 +119,24 @@ crypt_s390_km(long func, void* param, u8* dest, const u8* src, long src_len)
{
register long __func asm("0") = func & CRYPT_S390_FUNC_MASK;
register void* __param asm("1") = param;
- register u8* __dest asm("4") = dest;
register const u8* __src asm("2") = src;
register long __src_len asm("3") = src_len;
+ register u8* __dest asm("4") = dest;
int ret;
- ret = 0;
- __asm__ __volatile__ (
- "0: .insn rre,0xB92E0000,%1,%2 \n" /* KM opcode */
+ asm volatile(
+ "0: .insn rre,0xb92e0000,%3,%1 \n" /* KM opcode */
"1: brc 1,0b \n" /* handle partial completion */
- __crypt_s390_set_result
- "6: \n"
- __crypt_s390_fixup
- : "+d" (ret), "+a" (__dest), "+a" (__src),
- [result] "+d" (__src_len)
- : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func),
- "a" (__param)
- : "cc", "memory"
- );
- if (ret >= 0 && func & CRYPT_S390_FUNC_MASK){
- ret = src_len - ret;
- }
- return ret;
+ " ahi %0,%h7\n"
+ "2: ahi %0,%h8\n"
+ "3:\n"
+ EX_TABLE(0b,3b) EX_TABLE(1b,2b)
+ : "=d" (ret), "+a" (__src), "+d" (__src_len), "+a" (__dest)
+ : "d" (__func), "a" (__param), "0" (-EFAULT),
+ "K" (ENOSYS), "K" (-ENOSYS + EFAULT) : "cc", "memory");
+ if (ret < 0)
+ return ret;
+ return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
}
/*
@@ -212,28 +154,24 @@ crypt_s390_kmc(long func, void* param, u8* dest, const u8* src, long src_len)
{
register long __func asm("0") = func & CRYPT_S390_FUNC_MASK;
register void* __param asm("1") = param;
- register u8* __dest asm("4") = dest;
register const u8* __src asm("2") = src;
register long __src_len asm("3") = src_len;
+ register u8* __dest asm("4") = dest;
int ret;
- ret = 0;
- __asm__ __volatile__ (
- "0: .insn rre,0xB92F0000,%1,%2 \n" /* KMC opcode */
+ asm volatile(
+ "0: .insn rre,0xb92f0000,%3,%1 \n" /* KMC opcode */
"1: brc 1,0b \n" /* handle partial completion */
- __crypt_s390_set_result
- "6: \n"
- __crypt_s390_fixup
- : "+d" (ret), "+a" (__dest), "+a" (__src),
- [result] "+d" (__src_len)
- : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func),
- "a" (__param)
- : "cc", "memory"
- );
- if (ret >= 0 && func & CRYPT_S390_FUNC_MASK){
- ret = src_len - ret;
- }
- return ret;
+ " ahi %0,%h7\n"
+ "2: ahi %0,%h8\n"
+ "3:\n"
+ EX_TABLE(0b,3b) EX_TABLE(1b,2b)
+ : "=d" (ret), "+a" (__src), "+d" (__src_len), "+a" (__dest)
+ : "d" (__func), "a" (__param), "0" (-EFAULT),
+ "K" (ENOSYS), "K" (-ENOSYS + EFAULT) : "cc", "memory");
+ if (ret < 0)
+ return ret;
+ return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
}
/*
@@ -255,22 +193,19 @@ crypt_s390_kimd(long func, void* param, const u8* src, long src_len)
register long __src_len asm("3") = src_len;
int ret;
- ret = 0;
- __asm__ __volatile__ (
- "0: .insn rre,0xB93E0000,%1,%1 \n" /* KIMD opcode */
- "1: brc 1,0b \n" /* handle partical completion */
- __crypt_s390_set_result
- "6: \n"
- __crypt_s390_fixup
- : "+d" (ret), "+a" (__src), [result] "+d" (__src_len)
- : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func),
- "a" (__param)
- : "cc", "memory"
- );
- if (ret >= 0 && (func & CRYPT_S390_FUNC_MASK)){
- ret = src_len - ret;
- }
- return ret;
+ asm volatile(
+ "0: .insn rre,0xb93e0000,%1,%1 \n" /* KIMD opcode */
+ "1: brc 1,0b \n" /* handle partial completion */
+ " ahi %0,%h6\n"
+ "2: ahi %0,%h7\n"
+ "3:\n"
+ EX_TABLE(0b,3b) EX_TABLE(1b,2b)
+ : "=d" (ret), "+a" (__src), "+d" (__src_len)
+ : "d" (__func), "a" (__param), "0" (-EFAULT),
+ "K" (ENOSYS), "K" (-ENOSYS + EFAULT) : "cc", "memory");
+ if (ret < 0)
+ return ret;
+ return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
}
/*
@@ -291,22 +226,19 @@ crypt_s390_klmd(long func, void* param, const u8* src, long src_len)
register long __src_len asm("3") = src_len;
int ret;
- ret = 0;
- __asm__ __volatile__ (
- "0: .insn rre,0xB93F0000,%1,%1 \n" /* KLMD opcode */
- "1: brc 1,0b \n" /* handle partical completion */
- __crypt_s390_set_result
- "6: \n"
- __crypt_s390_fixup
- : "+d" (ret), "+a" (__src), [result] "+d" (__src_len)
- : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func),
- "a" (__param)
- : "cc", "memory"
- );
- if (ret >= 0 && func & CRYPT_S390_FUNC_MASK){
- ret = src_len - ret;
- }
- return ret;
+ asm volatile(
+ "0: .insn rre,0xb93f0000,%1,%1 \n" /* KLMD opcode */
+ "1: brc 1,0b \n" /* handle partial completion */
+ " ahi %0,%h6\n"
+ "2: ahi %0,%h7\n"
+ "3:\n"
+ EX_TABLE(0b,3b) EX_TABLE(1b,2b)
+ : "=d" (ret), "+a" (__src), "+d" (__src_len)
+ : "d" (__func), "a" (__param), "0" (-EFAULT),
+ "K" (ENOSYS), "K" (-ENOSYS + EFAULT) : "cc", "memory");
+ if (ret < 0)
+ return ret;
+ return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
}
/*
@@ -328,22 +260,19 @@ crypt_s390_kmac(long func, void* param, const u8* src, long src_len)
register long __src_len asm("3") = src_len;
int ret;
- ret = 0;
- __asm__ __volatile__ (
- "0: .insn rre,0xB91E0000,%5,%5 \n" /* KMAC opcode */
- "1: brc 1,0b \n" /* handle partical completion */
- __crypt_s390_set_result
- "6: \n"
- __crypt_s390_fixup
- : "+d" (ret), "+a" (__src), [result] "+d" (__src_len)
- : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func),
- "a" (__param)
- : "cc", "memory"
- );
- if (ret >= 0 && func & CRYPT_S390_FUNC_MASK){
- ret = src_len - ret;
- }
- return ret;
+ asm volatile(
+ "0: .insn rre,0xb91e0000,%1,%1 \n" /* KLAC opcode */
+ "1: brc 1,0b \n" /* handle partial completion */
+ " ahi %0,%h6\n"
+ "2: ahi %0,%h7\n"
+ "3:\n"
+ EX_TABLE(0b,3b) EX_TABLE(1b,2b)
+ : "=d" (ret), "+a" (__src), "+d" (__src_len)
+ : "d" (__func), "a" (__param), "0" (-EFAULT),
+ "K" (ENOSYS), "K" (-ENOSYS + EFAULT) : "cc", "memory");
+ if (ret < 0)
+ return ret;
+ return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
}
/**
diff --git a/arch/s390/crypto/des_s390.c b/arch/s390/crypto/des_s390.c
index b3f7496a79b4..2aba04852fe3 100644
--- a/arch/s390/crypto/des_s390.c
+++ b/arch/s390/crypto/des_s390.c
@@ -13,9 +13,10 @@
* (at your option) any later version.
*
*/
+
+#include <crypto/algapi.h>
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/crypto.h>
#include "crypt_s390.h"
#include "crypto_des.h"
@@ -45,9 +46,10 @@ struct crypt_s390_des3_192_ctx {
};
static int des_setkey(struct crypto_tfm *tfm, const u8 *key,
- unsigned int keylen, u32 *flags)
+ unsigned int keylen)
{
struct crypt_s390_des_ctx *dctx = crypto_tfm_ctx(tfm);
+ u32 *flags = &tfm->crt_flags;
int ret;
/* test if key is valid (not a weak key) */
@@ -71,85 +73,159 @@ static void des_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
crypt_s390_km(KM_DEA_DECRYPT, dctx->key, out, in, DES_BLOCK_SIZE);
}
-static unsigned int des_encrypt_ecb(const struct cipher_desc *desc, u8 *out,
- const u8 *in, unsigned int nbytes)
+static struct crypto_alg des_alg = {
+ .cra_name = "des",
+ .cra_driver_name = "des-s390",
+ .cra_priority = CRYPT_S390_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+ .cra_blocksize = DES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct crypt_s390_des_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(des_alg.cra_list),
+ .cra_u = {
+ .cipher = {
+ .cia_min_keysize = DES_KEY_SIZE,
+ .cia_max_keysize = DES_KEY_SIZE,
+ .cia_setkey = des_setkey,
+ .cia_encrypt = des_encrypt,
+ .cia_decrypt = des_decrypt,
+ }
+ }
+};
+
+static int ecb_desall_crypt(struct blkcipher_desc *desc, long func,
+ void *param, struct blkcipher_walk *walk)
{
- struct crypt_s390_des_ctx *sctx = crypto_tfm_ctx(desc->tfm);
- int ret;
+ int ret = blkcipher_walk_virt(desc, walk);
+ unsigned int nbytes;
+
+ while ((nbytes = walk->nbytes)) {
+ /* only use complete blocks */
+ unsigned int n = nbytes & ~(DES_BLOCK_SIZE - 1);
+ u8 *out = walk->dst.virt.addr;
+ u8 *in = walk->src.virt.addr;
- /* only use complete blocks */
- nbytes &= ~(DES_BLOCK_SIZE - 1);
- ret = crypt_s390_km(KM_DEA_ENCRYPT, sctx->key, out, in, nbytes);
- BUG_ON((ret < 0) || (ret != nbytes));
+ ret = crypt_s390_km(func, param, out, in, n);
+ BUG_ON((ret < 0) || (ret != n));
- return nbytes;
+ nbytes &= DES_BLOCK_SIZE - 1;
+ ret = blkcipher_walk_done(desc, walk, nbytes);
+ }
+
+ return ret;
}
-static unsigned int des_decrypt_ecb(const struct cipher_desc *desc, u8 *out,
- const u8 *in, unsigned int nbytes)
+static int cbc_desall_crypt(struct blkcipher_desc *desc, long func,
+ void *param, struct blkcipher_walk *walk)
{
- struct crypt_s390_des_ctx *sctx = crypto_tfm_ctx(desc->tfm);
- int ret;
+ int ret = blkcipher_walk_virt(desc, walk);
+ unsigned int nbytes = walk->nbytes;
+
+ if (!nbytes)
+ goto out;
+
+ memcpy(param, walk->iv, DES_BLOCK_SIZE);
+ do {
+ /* only use complete blocks */
+ unsigned int n = nbytes & ~(DES_BLOCK_SIZE - 1);
+ u8 *out = walk->dst.virt.addr;
+ u8 *in = walk->src.virt.addr;
- /* only use complete blocks */
- nbytes &= ~(DES_BLOCK_SIZE - 1);
- ret = crypt_s390_km(KM_DEA_DECRYPT, sctx->key, out, in, nbytes);
- BUG_ON((ret < 0) || (ret != nbytes));
+ ret = crypt_s390_kmc(func, param, out, in, n);
+ BUG_ON((ret < 0) || (ret != n));
- return nbytes;
+ nbytes &= DES_BLOCK_SIZE - 1;
+ ret = blkcipher_walk_done(desc, walk, nbytes);
+ } while ((nbytes = walk->nbytes));
+ memcpy(walk->iv, param, DES_BLOCK_SIZE);
+
+out:
+ return ret;
}
-static unsigned int des_encrypt_cbc(const struct cipher_desc *desc, u8 *out,
- const u8 *in, unsigned int nbytes)
+static int ecb_des_encrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
{
- struct crypt_s390_des_ctx *sctx = crypto_tfm_ctx(desc->tfm);
- int ret;
+ struct crypt_s390_des_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
- /* only use complete blocks */
- nbytes &= ~(DES_BLOCK_SIZE - 1);
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ return ecb_desall_crypt(desc, KM_DEA_ENCRYPT, sctx->key, &walk);
+}
- memcpy(sctx->iv, desc->info, DES_BLOCK_SIZE);
- ret = crypt_s390_kmc(KMC_DEA_ENCRYPT, &sctx->iv, out, in, nbytes);
- BUG_ON((ret < 0) || (ret != nbytes));
+static int ecb_des_decrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ struct crypt_s390_des_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
- memcpy(desc->info, sctx->iv, DES_BLOCK_SIZE);
- return nbytes;
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ return ecb_desall_crypt(desc, KM_DEA_DECRYPT, sctx->key, &walk);
}
-static unsigned int des_decrypt_cbc(const struct cipher_desc *desc, u8 *out,
- const u8 *in, unsigned int nbytes)
+static struct crypto_alg ecb_des_alg = {
+ .cra_name = "ecb(des)",
+ .cra_driver_name = "ecb-des-s390",
+ .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_blocksize = DES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct crypt_s390_des_ctx),
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(ecb_des_alg.cra_list),
+ .cra_u = {
+ .blkcipher = {
+ .min_keysize = DES_KEY_SIZE,
+ .max_keysize = DES_KEY_SIZE,
+ .setkey = des_setkey,
+ .encrypt = ecb_des_encrypt,
+ .decrypt = ecb_des_decrypt,
+ }
+ }
+};
+
+static int cbc_des_encrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
{
- struct crypt_s390_des_ctx *sctx = crypto_tfm_ctx(desc->tfm);
- int ret;
+ struct crypt_s390_des_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
- /* only use complete blocks */
- nbytes &= ~(DES_BLOCK_SIZE - 1);
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ return cbc_desall_crypt(desc, KMC_DEA_ENCRYPT, sctx->iv, &walk);
+}
- memcpy(&sctx->iv, desc->info, DES_BLOCK_SIZE);
- ret = crypt_s390_kmc(KMC_DEA_DECRYPT, &sctx->iv, out, in, nbytes);
- BUG_ON((ret < 0) || (ret != nbytes));
+static int cbc_des_decrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ struct crypt_s390_des_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
- return nbytes;
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ return cbc_desall_crypt(desc, KMC_DEA_DECRYPT, sctx->iv, &walk);
}
-static struct crypto_alg des_alg = {
- .cra_name = "des",
- .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+static struct crypto_alg cbc_des_alg = {
+ .cra_name = "cbc(des)",
+ .cra_driver_name = "cbc-des-s390",
+ .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
.cra_blocksize = DES_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct crypt_s390_des_ctx),
+ .cra_type = &crypto_blkcipher_type,
.cra_module = THIS_MODULE,
- .cra_list = LIST_HEAD_INIT(des_alg.cra_list),
+ .cra_list = LIST_HEAD_INIT(cbc_des_alg.cra_list),
.cra_u = {
- .cipher = {
- .cia_min_keysize = DES_KEY_SIZE,
- .cia_max_keysize = DES_KEY_SIZE,
- .cia_setkey = des_setkey,
- .cia_encrypt = des_encrypt,
- .cia_decrypt = des_decrypt,
- .cia_encrypt_ecb = des_encrypt_ecb,
- .cia_decrypt_ecb = des_decrypt_ecb,
- .cia_encrypt_cbc = des_encrypt_cbc,
- .cia_decrypt_cbc = des_decrypt_cbc,
+ .blkcipher = {
+ .min_keysize = DES_KEY_SIZE,
+ .max_keysize = DES_KEY_SIZE,
+ .ivsize = DES_BLOCK_SIZE,
+ .setkey = des_setkey,
+ .encrypt = cbc_des_encrypt,
+ .decrypt = cbc_des_decrypt,
}
}
};
@@ -167,11 +243,12 @@ static struct crypto_alg des_alg = {
*
*/
static int des3_128_setkey(struct crypto_tfm *tfm, const u8 *key,
- unsigned int keylen, u32 *flags)
+ unsigned int keylen)
{
int i, ret;
struct crypt_s390_des3_128_ctx *dctx = crypto_tfm_ctx(tfm);
- const u8* temp_key = key;
+ const u8 *temp_key = key;
+ u32 *flags = &tfm->crt_flags;
if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE))) {
*flags |= CRYPTO_TFM_RES_BAD_KEY_SCHED;
@@ -202,89 +279,111 @@ static void des3_128_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
DES3_128_BLOCK_SIZE);
}
-static unsigned int des3_128_encrypt_ecb(const struct cipher_desc *desc,
- u8 *out, const u8 *in,
- unsigned int nbytes)
-{
- struct crypt_s390_des3_128_ctx *sctx = crypto_tfm_ctx(desc->tfm);
- int ret;
+static struct crypto_alg des3_128_alg = {
+ .cra_name = "des3_ede128",
+ .cra_driver_name = "des3_ede128-s390",
+ .cra_priority = CRYPT_S390_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+ .cra_blocksize = DES3_128_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct crypt_s390_des3_128_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(des3_128_alg.cra_list),
+ .cra_u = {
+ .cipher = {
+ .cia_min_keysize = DES3_128_KEY_SIZE,
+ .cia_max_keysize = DES3_128_KEY_SIZE,
+ .cia_setkey = des3_128_setkey,
+ .cia_encrypt = des3_128_encrypt,
+ .cia_decrypt = des3_128_decrypt,
+ }
+ }
+};
- /* only use complete blocks */
- nbytes &= ~(DES3_128_BLOCK_SIZE - 1);
- ret = crypt_s390_km(KM_TDEA_128_ENCRYPT, sctx->key, out, in, nbytes);
- BUG_ON((ret < 0) || (ret != nbytes));
+static int ecb_des3_128_encrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst,
+ struct scatterlist *src, unsigned int nbytes)
+{
+ struct crypt_s390_des3_128_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
- return nbytes;
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ return ecb_desall_crypt(desc, KM_TDEA_128_ENCRYPT, sctx->key, &walk);
}
-static unsigned int des3_128_decrypt_ecb(const struct cipher_desc *desc,
- u8 *out, const u8 *in,
- unsigned int nbytes)
+static int ecb_des3_128_decrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst,
+ struct scatterlist *src, unsigned int nbytes)
{
- struct crypt_s390_des3_128_ctx *sctx = crypto_tfm_ctx(desc->tfm);
- int ret;
+ struct crypt_s390_des3_128_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
- /* only use complete blocks */
- nbytes &= ~(DES3_128_BLOCK_SIZE - 1);
- ret = crypt_s390_km(KM_TDEA_128_DECRYPT, sctx->key, out, in, nbytes);
- BUG_ON((ret < 0) || (ret != nbytes));
-
- return nbytes;
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ return ecb_desall_crypt(desc, KM_TDEA_128_DECRYPT, sctx->key, &walk);
}
-static unsigned int des3_128_encrypt_cbc(const struct cipher_desc *desc,
- u8 *out, const u8 *in,
- unsigned int nbytes)
-{
- struct crypt_s390_des3_128_ctx *sctx = crypto_tfm_ctx(desc->tfm);
- int ret;
-
- /* only use complete blocks */
- nbytes &= ~(DES3_128_BLOCK_SIZE - 1);
+static struct crypto_alg ecb_des3_128_alg = {
+ .cra_name = "ecb(des3_ede128)",
+ .cra_driver_name = "ecb-des3_ede128-s390",
+ .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_blocksize = DES3_128_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct crypt_s390_des3_128_ctx),
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(
+ ecb_des3_128_alg.cra_list),
+ .cra_u = {
+ .blkcipher = {
+ .min_keysize = DES3_128_KEY_SIZE,
+ .max_keysize = DES3_128_KEY_SIZE,
+ .setkey = des3_128_setkey,
+ .encrypt = ecb_des3_128_encrypt,
+ .decrypt = ecb_des3_128_decrypt,
+ }
+ }
+};
- memcpy(sctx->iv, desc->info, DES3_128_BLOCK_SIZE);
- ret = crypt_s390_kmc(KMC_TDEA_128_ENCRYPT, &sctx->iv, out, in, nbytes);
- BUG_ON((ret < 0) || (ret != nbytes));
+static int cbc_des3_128_encrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst,
+ struct scatterlist *src, unsigned int nbytes)
+{
+ struct crypt_s390_des3_128_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
- memcpy(desc->info, sctx->iv, DES3_128_BLOCK_SIZE);
- return nbytes;
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ return cbc_desall_crypt(desc, KMC_TDEA_128_ENCRYPT, sctx->iv, &walk);
}
-static unsigned int des3_128_decrypt_cbc(const struct cipher_desc *desc,
- u8 *out, const u8 *in,
- unsigned int nbytes)
+static int cbc_des3_128_decrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst,
+ struct scatterlist *src, unsigned int nbytes)
{
- struct crypt_s390_des3_128_ctx *sctx = crypto_tfm_ctx(desc->tfm);
- int ret;
-
- /* only use complete blocks */
- nbytes &= ~(DES3_128_BLOCK_SIZE - 1);
-
- memcpy(&sctx->iv, desc->info, DES3_128_BLOCK_SIZE);
- ret = crypt_s390_kmc(KMC_TDEA_128_DECRYPT, &sctx->iv, out, in, nbytes);
- BUG_ON((ret < 0) || (ret != nbytes));
+ struct crypt_s390_des3_128_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
- return nbytes;
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ return cbc_desall_crypt(desc, KMC_TDEA_128_DECRYPT, sctx->iv, &walk);
}
-static struct crypto_alg des3_128_alg = {
- .cra_name = "des3_ede128",
- .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+static struct crypto_alg cbc_des3_128_alg = {
+ .cra_name = "cbc(des3_ede128)",
+ .cra_driver_name = "cbc-des3_ede128-s390",
+ .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
.cra_blocksize = DES3_128_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct crypt_s390_des3_128_ctx),
+ .cra_type = &crypto_blkcipher_type,
.cra_module = THIS_MODULE,
- .cra_list = LIST_HEAD_INIT(des3_128_alg.cra_list),
+ .cra_list = LIST_HEAD_INIT(
+ cbc_des3_128_alg.cra_list),
.cra_u = {
- .cipher = {
- .cia_min_keysize = DES3_128_KEY_SIZE,
- .cia_max_keysize = DES3_128_KEY_SIZE,
- .cia_setkey = des3_128_setkey,
- .cia_encrypt = des3_128_encrypt,
- .cia_decrypt = des3_128_decrypt,
- .cia_encrypt_ecb = des3_128_encrypt_ecb,
- .cia_decrypt_ecb = des3_128_decrypt_ecb,
- .cia_encrypt_cbc = des3_128_encrypt_cbc,
- .cia_decrypt_cbc = des3_128_decrypt_cbc,
+ .blkcipher = {
+ .min_keysize = DES3_128_KEY_SIZE,
+ .max_keysize = DES3_128_KEY_SIZE,
+ .ivsize = DES3_128_BLOCK_SIZE,
+ .setkey = des3_128_setkey,
+ .encrypt = cbc_des3_128_encrypt,
+ .decrypt = cbc_des3_128_decrypt,
}
}
};
@@ -303,11 +402,12 @@ static struct crypto_alg des3_128_alg = {
*
*/
static int des3_192_setkey(struct crypto_tfm *tfm, const u8 *key,
- unsigned int keylen, u32 *flags)
+ unsigned int keylen)
{
int i, ret;
struct crypt_s390_des3_192_ctx *dctx = crypto_tfm_ctx(tfm);
- const u8* temp_key = key;
+ const u8 *temp_key = key;
+ u32 *flags = &tfm->crt_flags;
if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE) &&
memcmp(&key[DES_KEY_SIZE], &key[DES_KEY_SIZE * 2],
@@ -341,89 +441,111 @@ static void des3_192_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
DES3_192_BLOCK_SIZE);
}
-static unsigned int des3_192_encrypt_ecb(const struct cipher_desc *desc,
- u8 *out, const u8 *in,
- unsigned int nbytes)
-{
- struct crypt_s390_des3_192_ctx *sctx = crypto_tfm_ctx(desc->tfm);
- int ret;
+static struct crypto_alg des3_192_alg = {
+ .cra_name = "des3_ede",
+ .cra_driver_name = "des3_ede-s390",
+ .cra_priority = CRYPT_S390_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+ .cra_blocksize = DES3_192_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct crypt_s390_des3_192_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(des3_192_alg.cra_list),
+ .cra_u = {
+ .cipher = {
+ .cia_min_keysize = DES3_192_KEY_SIZE,
+ .cia_max_keysize = DES3_192_KEY_SIZE,
+ .cia_setkey = des3_192_setkey,
+ .cia_encrypt = des3_192_encrypt,
+ .cia_decrypt = des3_192_decrypt,
+ }
+ }
+};
- /* only use complete blocks */
- nbytes &= ~(DES3_192_BLOCK_SIZE - 1);
- ret = crypt_s390_km(KM_TDEA_192_ENCRYPT, sctx->key, out, in, nbytes);
- BUG_ON((ret < 0) || (ret != nbytes));
+static int ecb_des3_192_encrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst,
+ struct scatterlist *src, unsigned int nbytes)
+{
+ struct crypt_s390_des3_192_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
- return nbytes;
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ return ecb_desall_crypt(desc, KM_TDEA_192_ENCRYPT, sctx->key, &walk);
}
-static unsigned int des3_192_decrypt_ecb(const struct cipher_desc *desc,
- u8 *out, const u8 *in,
- unsigned int nbytes)
+static int ecb_des3_192_decrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst,
+ struct scatterlist *src, unsigned int nbytes)
{
- struct crypt_s390_des3_192_ctx *sctx = crypto_tfm_ctx(desc->tfm);
- int ret;
-
- /* only use complete blocks */
- nbytes &= ~(DES3_192_BLOCK_SIZE - 1);
- ret = crypt_s390_km(KM_TDEA_192_DECRYPT, sctx->key, out, in, nbytes);
- BUG_ON((ret < 0) || (ret != nbytes));
+ struct crypt_s390_des3_192_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
- return nbytes;
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ return ecb_desall_crypt(desc, KM_TDEA_192_DECRYPT, sctx->key, &walk);
}
-static unsigned int des3_192_encrypt_cbc(const struct cipher_desc *desc,
- u8 *out, const u8 *in,
- unsigned int nbytes)
-{
- struct crypt_s390_des3_192_ctx *sctx = crypto_tfm_ctx(desc->tfm);
- int ret;
-
- /* only use complete blocks */
- nbytes &= ~(DES3_192_BLOCK_SIZE - 1);
+static struct crypto_alg ecb_des3_192_alg = {
+ .cra_name = "ecb(des3_ede)",
+ .cra_driver_name = "ecb-des3_ede-s390",
+ .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_blocksize = DES3_192_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct crypt_s390_des3_192_ctx),
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(
+ ecb_des3_192_alg.cra_list),
+ .cra_u = {
+ .blkcipher = {
+ .min_keysize = DES3_192_KEY_SIZE,
+ .max_keysize = DES3_192_KEY_SIZE,
+ .setkey = des3_192_setkey,
+ .encrypt = ecb_des3_192_encrypt,
+ .decrypt = ecb_des3_192_decrypt,
+ }
+ }
+};
- memcpy(sctx->iv, desc->info, DES3_192_BLOCK_SIZE);
- ret = crypt_s390_kmc(KMC_TDEA_192_ENCRYPT, &sctx->iv, out, in, nbytes);
- BUG_ON((ret < 0) || (ret != nbytes));
+static int cbc_des3_192_encrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst,
+ struct scatterlist *src, unsigned int nbytes)
+{
+ struct crypt_s390_des3_192_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
- memcpy(desc->info, sctx->iv, DES3_192_BLOCK_SIZE);
- return nbytes;
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ return cbc_desall_crypt(desc, KMC_TDEA_192_ENCRYPT, sctx->iv, &walk);
}
-static unsigned int des3_192_decrypt_cbc(const struct cipher_desc *desc,
- u8 *out, const u8 *in,
- unsigned int nbytes)
+static int cbc_des3_192_decrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst,
+ struct scatterlist *src, unsigned int nbytes)
{
- struct crypt_s390_des3_192_ctx *sctx = crypto_tfm_ctx(desc->tfm);
- int ret;
+ struct crypt_s390_des3_192_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
- /* only use complete blocks */
- nbytes &= ~(DES3_192_BLOCK_SIZE - 1);
-
- memcpy(&sctx->iv, desc->info, DES3_192_BLOCK_SIZE);
- ret = crypt_s390_kmc(KMC_TDEA_192_DECRYPT, &sctx->iv, out, in, nbytes);
- BUG_ON((ret < 0) || (ret != nbytes));
-
- return nbytes;
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ return cbc_desall_crypt(desc, KMC_TDEA_192_DECRYPT, sctx->iv, &walk);
}
-static struct crypto_alg des3_192_alg = {
- .cra_name = "des3_ede",
- .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+static struct crypto_alg cbc_des3_192_alg = {
+ .cra_name = "cbc(des3_ede)",
+ .cra_driver_name = "cbc-des3_ede-s390",
+ .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
.cra_blocksize = DES3_192_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct crypt_s390_des3_192_ctx),
+ .cra_type = &crypto_blkcipher_type,
.cra_module = THIS_MODULE,
- .cra_list = LIST_HEAD_INIT(des3_192_alg.cra_list),
+ .cra_list = LIST_HEAD_INIT(
+ cbc_des3_192_alg.cra_list),
.cra_u = {
- .cipher = {
- .cia_min_keysize = DES3_192_KEY_SIZE,
- .cia_max_keysize = DES3_192_KEY_SIZE,
- .cia_setkey = des3_192_setkey,
- .cia_encrypt = des3_192_encrypt,
- .cia_decrypt = des3_192_decrypt,
- .cia_encrypt_ecb = des3_192_encrypt_ecb,
- .cia_decrypt_ecb = des3_192_decrypt_ecb,
- .cia_encrypt_cbc = des3_192_encrypt_cbc,
- .cia_decrypt_cbc = des3_192_decrypt_cbc,
+ .blkcipher = {
+ .min_keysize = DES3_192_KEY_SIZE,
+ .max_keysize = DES3_192_KEY_SIZE,
+ .ivsize = DES3_192_BLOCK_SIZE,
+ .setkey = des3_192_setkey,
+ .encrypt = cbc_des3_192_encrypt,
+ .decrypt = cbc_des3_192_decrypt,
}
}
};
@@ -437,22 +559,69 @@ static int init(void)
!crypt_s390_func_available(KM_TDEA_192_ENCRYPT))
return -ENOSYS;
- ret |= (crypto_register_alg(&des_alg) == 0) ? 0:1;
- ret |= (crypto_register_alg(&des3_128_alg) == 0) ? 0:2;
- ret |= (crypto_register_alg(&des3_192_alg) == 0) ? 0:4;
- if (ret) {
- crypto_unregister_alg(&des3_192_alg);
- crypto_unregister_alg(&des3_128_alg);
- crypto_unregister_alg(&des_alg);
- return -EEXIST;
- }
- return 0;
+ ret = crypto_register_alg(&des_alg);
+ if (ret)
+ goto des_err;
+ ret = crypto_register_alg(&ecb_des_alg);
+ if (ret)
+ goto ecb_des_err;
+ ret = crypto_register_alg(&cbc_des_alg);
+ if (ret)
+ goto cbc_des_err;
+
+ ret = crypto_register_alg(&des3_128_alg);
+ if (ret)
+ goto des3_128_err;
+ ret = crypto_register_alg(&ecb_des3_128_alg);
+ if (ret)
+ goto ecb_des3_128_err;
+ ret = crypto_register_alg(&cbc_des3_128_alg);
+ if (ret)
+ goto cbc_des3_128_err;
+
+ ret = crypto_register_alg(&des3_192_alg);
+ if (ret)
+ goto des3_192_err;
+ ret = crypto_register_alg(&ecb_des3_192_alg);
+ if (ret)
+ goto ecb_des3_192_err;
+ ret = crypto_register_alg(&cbc_des3_192_alg);
+ if (ret)
+ goto cbc_des3_192_err;
+
+out:
+ return ret;
+
+cbc_des3_192_err:
+ crypto_unregister_alg(&ecb_des3_192_alg);
+ecb_des3_192_err:
+ crypto_unregister_alg(&des3_192_alg);
+des3_192_err:
+ crypto_unregister_alg(&cbc_des3_128_alg);
+cbc_des3_128_err:
+ crypto_unregister_alg(&ecb_des3_128_alg);
+ecb_des3_128_err:
+ crypto_unregister_alg(&des3_128_alg);
+des3_128_err:
+ crypto_unregister_alg(&cbc_des_alg);
+cbc_des_err:
+ crypto_unregister_alg(&ecb_des_alg);
+ecb_des_err:
+ crypto_unregister_alg(&des_alg);
+des_err:
+ goto out;
}
static void __exit fini(void)
{
+ crypto_unregister_alg(&cbc_des3_192_alg);
+ crypto_unregister_alg(&ecb_des3_192_alg);
crypto_unregister_alg(&des3_192_alg);
+ crypto_unregister_alg(&cbc_des3_128_alg);
+ crypto_unregister_alg(&ecb_des3_128_alg);
crypto_unregister_alg(&des3_128_alg);
+ crypto_unregister_alg(&cbc_des_alg);
+ crypto_unregister_alg(&ecb_des_alg);
crypto_unregister_alg(&des_alg);
}
diff --git a/arch/s390/crypto/sha1_s390.c b/arch/s390/crypto/sha1_s390.c
index 9d34a35b1aa5..49ca8690ee39 100644
--- a/arch/s390/crypto/sha1_s390.c
+++ b/arch/s390/crypto/sha1_s390.c
@@ -126,6 +126,8 @@ static void sha1_final(struct crypto_tfm *tfm, u8 *out)
static struct crypto_alg alg = {
.cra_name = "sha1",
+ .cra_driver_name = "sha1-s390",
+ .cra_priority = CRYPT_S390_PRIORITY,
.cra_flags = CRYPTO_ALG_TYPE_DIGEST,
.cra_blocksize = SHA1_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct crypt_s390_sha1_ctx),
diff --git a/arch/s390/crypto/sha256_s390.c b/arch/s390/crypto/sha256_s390.c
index f573df30f31d..8e4e67503fe7 100644
--- a/arch/s390/crypto/sha256_s390.c
+++ b/arch/s390/crypto/sha256_s390.c
@@ -127,6 +127,8 @@ static void sha256_final(struct crypto_tfm *tfm, u8 *out)
static struct crypto_alg alg = {
.cra_name = "sha256",
+ .cra_driver_name = "sha256-s390",
+ .cra_priority = CRYPT_S390_PRIORITY,
.cra_flags = CRYPTO_ALG_TYPE_DIGEST,
.cra_blocksize = SHA256_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct s390_sha256_ctx),
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index f1d4591eddbb..35da53986b1b 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -428,6 +428,7 @@ CONFIG_S390_TAPE_34XX=m
# CONFIG_VMLOGRDR is not set
# CONFIG_VMCP is not set
# CONFIG_MONREADER is not set
+CONFIG_MONWRITER=m
#
# Cryptographic devices
diff --git a/arch/s390/hypfs/hypfs.h b/arch/s390/hypfs/hypfs.h
index ea5567be00fc..f3dbd91965c6 100644
--- a/arch/s390/hypfs/hypfs.h
+++ b/arch/s390/hypfs/hypfs.h
@@ -1,5 +1,5 @@
/*
- * fs/hypfs/hypfs.h
+ * arch/s390/hypfs/hypfs.h
* Hypervisor filesystem for Linux on s390.
*
* Copyright (C) IBM Corp. 2006
diff --git a/arch/s390/hypfs/hypfs_diag.c b/arch/s390/hypfs/hypfs_diag.c
index 1785bce2b919..443fa377d9ff 100644
--- a/arch/s390/hypfs/hypfs_diag.c
+++ b/arch/s390/hypfs/hypfs_diag.c
@@ -1,5 +1,5 @@
/*
- * fs/hypfs/hypfs_diag.c
+ * arch/s390/hypfs/hypfs_diag.c
* Hypervisor filesystem for Linux on s390. Diag 204 and 224
* implementation.
*
@@ -333,22 +333,14 @@ static int diag204(unsigned long subcode, unsigned long size, void *addr)
register unsigned long _subcode asm("0") = subcode;
register unsigned long _size asm("1") = size;
- asm volatile (" diag %2,%0,0x204\n"
- "0: \n" ".section __ex_table,\"a\"\n"
-#ifndef __s390x__
- " .align 4\n"
- " .long 0b,0b\n"
-#else
- " .align 8\n"
- " .quad 0b,0b\n"
-#endif
- ".previous":"+d" (_subcode), "+d"(_size)
- :"d"(addr)
- :"memory");
+ asm volatile(
+ " diag %2,%0,0x204\n"
+ "0:\n"
+ EX_TABLE(0b,0b)
+ : "+d" (_subcode), "+d" (_size) : "d" (addr) : "memory");
if (_subcode)
return -1;
- else
- return _size;
+ return _size;
}
/*
@@ -403,7 +395,8 @@ static void *diag204_get_buffer(enum diag204_format fmt, int *pages)
*pages = 1;
return diag204_alloc_rbuf();
} else {/* INFO_EXT */
- *pages = diag204(SUBC_RSI | INFO_EXT, 0, NULL);
+ *pages = diag204((unsigned long)SUBC_RSI |
+ (unsigned long)INFO_EXT, 0, NULL);
if (*pages <= 0)
return ERR_PTR(-ENOSYS);
else
@@ -432,12 +425,14 @@ static int diag204_probe(void)
buf = diag204_get_buffer(INFO_EXT, &pages);
if (!IS_ERR(buf)) {
- if (diag204(SUBC_STIB7 | INFO_EXT, pages, buf) >= 0) {
+ if (diag204((unsigned long)SUBC_STIB7 |
+ (unsigned long)INFO_EXT, pages, buf) >= 0) {
diag204_store_sc = SUBC_STIB7;
diag204_info_type = INFO_EXT;
goto out;
}
- if (diag204(SUBC_STIB6 | INFO_EXT, pages, buf) >= 0) {
+ if (diag204((unsigned long)SUBC_STIB6 |
+ (unsigned long)INFO_EXT, pages, buf) >= 0) {
diag204_store_sc = SUBC_STIB7;
diag204_info_type = INFO_EXT;
goto out;
@@ -452,7 +447,8 @@ static int diag204_probe(void)
rc = PTR_ERR(buf);
goto fail_alloc;
}
- if (diag204(SUBC_STIB4 | INFO_SIMPLE, pages, buf) >= 0) {
+ if (diag204((unsigned long)SUBC_STIB4 |
+ (unsigned long)INFO_SIMPLE, pages, buf) >= 0) {
diag204_store_sc = SUBC_STIB4;
diag204_info_type = INFO_SIMPLE;
goto out;
@@ -476,7 +472,8 @@ static void *diag204_store(void)
buf = diag204_get_buffer(diag204_info_type, &pages);
if (IS_ERR(buf))
goto out;
- if (diag204(diag204_store_sc | diag204_info_type, pages, buf) < 0)
+ if (diag204((unsigned long)diag204_store_sc |
+ (unsigned long)diag204_info_type, pages, buf) < 0)
return ERR_PTR(-ENOSYS);
out:
return buf;
@@ -486,8 +483,7 @@ out:
static void diag224(void *ptr)
{
- asm volatile(" diag %0,%1,0x224\n"
- : :"d" (0), "d"(ptr) : "memory");
+ asm volatile("diag %0,%1,0x224" : :"d" (0), "d"(ptr) : "memory");
}
static int diag224_get_name_table(void)
@@ -531,7 +527,7 @@ __init int hypfs_diag_init(void)
return rc;
}
-__exit void hypfs_diag_exit(void)
+void hypfs_diag_exit(void)
{
diag224_delete_name_table();
diag204_free_buffer();
diff --git a/arch/s390/hypfs/hypfs_diag.h b/arch/s390/hypfs/hypfs_diag.h
index 793dea6b9bb6..256b384aebe1 100644
--- a/arch/s390/hypfs/hypfs_diag.h
+++ b/arch/s390/hypfs/hypfs_diag.h
@@ -1,5 +1,5 @@
/*
- * fs/hypfs/hypfs_diag.h
+ * arch/s390/hypfs_diag.h
* Hypervisor filesystem for Linux on s390.
*
* Copyright (C) IBM Corp. 2006
diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c
index 18c091925ea5..cd702ae45d6d 100644
--- a/arch/s390/hypfs/inode.c
+++ b/arch/s390/hypfs/inode.c
@@ -1,5 +1,5 @@
/*
- * fs/hypfs/inode.c
+ * arch/s390/hypfs/inode.c
* Hypervisor filesystem for Linux on s390.
*
* Copyright (C) IBM Corp. 2006
@@ -91,7 +91,6 @@ static struct inode *hypfs_make_inode(struct super_block *sb, int mode)
ret->i_mode = mode;
ret->i_uid = hypfs_info->uid;
ret->i_gid = hypfs_info->gid;
- ret->i_blksize = PAGE_CACHE_SIZE;
ret->i_blocks = 0;
ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
if (mode & S_IFDIR)
@@ -104,13 +103,13 @@ static struct inode *hypfs_make_inode(struct super_block *sb, int mode)
static void hypfs_drop_inode(struct inode *inode)
{
- kfree(inode->u.generic_ip);
+ kfree(inode->i_private);
generic_delete_inode(inode);
}
static int hypfs_open(struct inode *inode, struct file *filp)
{
- char *data = filp->f_dentry->d_inode->u.generic_ip;
+ char *data = filp->f_dentry->d_inode->i_private;
struct hypfs_sb_info *fs_info;
if (filp->f_mode & FMODE_WRITE) {
@@ -135,12 +134,20 @@ static int hypfs_open(struct inode *inode, struct file *filp)
return 0;
}
-static ssize_t hypfs_aio_read(struct kiocb *iocb, __user char *buf,
- size_t count, loff_t offset)
+static ssize_t hypfs_aio_read(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t offset)
{
char *data;
size_t len;
struct file *filp = iocb->ki_filp;
+ /* XXX: temporary */
+ char __user *buf = iov[0].iov_base;
+ size_t count = iov[0].iov_len;
+
+ if (nr_segs != 1) {
+ count = -EINVAL;
+ goto out;
+ }
data = filp->private_data;
len = strlen(data);
@@ -159,12 +166,13 @@ static ssize_t hypfs_aio_read(struct kiocb *iocb, __user char *buf,
out:
return count;
}
-static ssize_t hypfs_aio_write(struct kiocb *iocb, const char __user *buf,
- size_t count, loff_t pos)
+static ssize_t hypfs_aio_write(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t offset)
{
int rc;
struct super_block *sb;
struct hypfs_sb_info *fs_info;
+ size_t count = iov_length(iov, nr_segs);
sb = iocb->ki_filp->f_dentry->d_inode->i_sb;
fs_info = sb->s_fs_info;
@@ -312,10 +320,12 @@ static void hypfs_kill_super(struct super_block *sb)
{
struct hypfs_sb_info *sb_info = sb->s_fs_info;
- hypfs_delete_tree(sb->s_root);
- hypfs_remove(sb_info->update_file);
- kfree(sb->s_fs_info);
- sb->s_fs_info = NULL;
+ if (sb->s_root) {
+ hypfs_delete_tree(sb->s_root);
+ hypfs_remove(sb_info->update_file);
+ kfree(sb->s_fs_info);
+ sb->s_fs_info = NULL;
+ }
kill_litter_super(sb);
}
@@ -350,7 +360,7 @@ static struct dentry *hypfs_create_file(struct super_block *sb,
parent->d_inode->i_nlink++;
} else
BUG();
- inode->u.generic_ip = data;
+ inode->i_private = data;
d_instantiate(dentry, inode);
dget(dentry);
return dentry;
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 9a33ed6ca696..aa978978d3d1 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -6,7 +6,7 @@ EXTRA_AFLAGS := -traditional
obj-y := bitmap.o traps.o time.o process.o \
setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
- semaphore.o s390_ext.o debug.o profile.o irq.o reipl_diag.o
+ semaphore.o s390_ext.o debug.o profile.o irq.o ipl.o
obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o)
obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
@@ -24,6 +24,7 @@ obj-$(CONFIG_COMPAT) += compat_linux.o compat_signal.o \
obj-$(CONFIG_VIRT_TIMER) += vtime.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o
+obj-$(CONFIG_KPROBES) += kprobes.o
# Kexec part
S390_KEXEC_OBJS := machine_kexec.o crash.o
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index 785c9f70ac98..c46e3d48e410 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -544,10 +544,7 @@ sys32_execve(struct pt_regs regs)
current->ptrace &= ~PT_DTRACE;
task_unlock(current);
current->thread.fp_regs.fpc=0;
- __asm__ __volatile__
- ("sr 0,0\n\t"
- "sfpc 0,0\n\t"
- : : :"0");
+ asm volatile("sfpc %0,0" : : "d" (0));
}
putname(filename);
out:
@@ -708,7 +705,7 @@ asmlinkage long sys32_sendfile64(int out_fd, int in_fd,
return ret;
}
-#ifdef CONFIG_SYSCTL
+#ifdef CONFIG_SYSCTL_SYSCALL
struct __sysctl_args32 {
u32 name;
int nlen;
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index 4d53b2739357..4aabeeaa7cf7 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -4,97 +4,97 @@
*
* Copyright (C) IBM Corp. 2000,2006
* Author(s): Gerhard Tonn (ton@de.ibm.com),
-* Thomas Spatzier (tspat@de.ibm.com)
-*/
+* Thomas Spatzier (tspat@de.ibm.com)
+*/
- .globl sys32_exit_wrapper
+ .globl sys32_exit_wrapper
sys32_exit_wrapper:
lgfr %r2,%r2 # int
jg sys_exit # branch to sys_exit
-
- .globl sys32_read_wrapper
+
+ .globl sys32_read_wrapper
sys32_read_wrapper:
llgfr %r2,%r2 # unsigned int
llgtr %r3,%r3 # char *
llgfr %r4,%r4 # size_t
jg sys32_read # branch to sys_read
- .globl sys32_write_wrapper
+ .globl sys32_write_wrapper
sys32_write_wrapper:
llgfr %r2,%r2 # unsigned int
llgtr %r3,%r3 # const char *
llgfr %r4,%r4 # size_t
jg sys32_write # branch to system call
- .globl sys32_open_wrapper
+ .globl sys32_open_wrapper
sys32_open_wrapper:
llgtr %r2,%r2 # const char *
lgfr %r3,%r3 # int
lgfr %r4,%r4 # int
jg sys_open # branch to system call
- .globl sys32_close_wrapper
+ .globl sys32_close_wrapper
sys32_close_wrapper:
llgfr %r2,%r2 # unsigned int
jg sys_close # branch to system call
- .globl sys32_creat_wrapper
+ .globl sys32_creat_wrapper
sys32_creat_wrapper:
llgtr %r2,%r2 # const char *
lgfr %r3,%r3 # int
jg sys_creat # branch to system call
- .globl sys32_link_wrapper
+ .globl sys32_link_wrapper
sys32_link_wrapper:
llgtr %r2,%r2 # const char *
llgtr %r3,%r3 # const char *
jg sys_link # branch to system call
- .globl sys32_unlink_wrapper
+ .globl sys32_unlink_wrapper
sys32_unlink_wrapper:
llgtr %r2,%r2 # const char *
jg sys_unlink # branch to system call
- .globl sys32_chdir_wrapper
+ .globl sys32_chdir_wrapper
sys32_chdir_wrapper:
llgtr %r2,%r2 # const char *
jg sys_chdir # branch to system call
- .globl sys32_time_wrapper
+ .globl sys32_time_wrapper
sys32_time_wrapper:
llgtr %r2,%r2 # int *
jg compat_sys_time # branch to system call
- .globl sys32_mknod_wrapper
+ .globl sys32_mknod_wrapper
sys32_mknod_wrapper:
llgtr %r2,%r2 # const char *
- lgfr %r3,%r3 # int
+ lgfr %r3,%r3 # int
llgfr %r4,%r4 # dev
jg sys_mknod # branch to system call
- .globl sys32_chmod_wrapper
+ .globl sys32_chmod_wrapper
sys32_chmod_wrapper:
llgtr %r2,%r2 # const char *
llgfr %r3,%r3 # mode_t
jg sys_chmod # branch to system call
- .globl sys32_lchown16_wrapper
+ .globl sys32_lchown16_wrapper
sys32_lchown16_wrapper:
llgtr %r2,%r2 # const char *
- llgfr %r3,%r3 # __kernel_old_uid_emu31_t
- llgfr %r4,%r4 # __kernel_old_uid_emu31_t
+ llgfr %r3,%r3 # __kernel_old_uid_emu31_t
+ llgfr %r4,%r4 # __kernel_old_uid_emu31_t
jg sys32_lchown16 # branch to system call
- .globl sys32_lseek_wrapper
+ .globl sys32_lseek_wrapper
sys32_lseek_wrapper:
llgfr %r2,%r2 # unsigned int
lgfr %r3,%r3 # off_t
llgfr %r4,%r4 # unsigned int
jg sys_lseek # branch to system call
-#sys32_getpid_wrapper # void
+#sys32_getpid_wrapper # void
- .globl sys32_mount_wrapper
+ .globl sys32_mount_wrapper
sys32_mount_wrapper:
llgtr %r2,%r2 # char *
llgtr %r3,%r3 # char *
@@ -103,19 +103,19 @@ sys32_mount_wrapper:
llgtr %r6,%r6 # void *
jg compat_sys_mount # branch to system call
- .globl sys32_oldumount_wrapper
+ .globl sys32_oldumount_wrapper
sys32_oldumount_wrapper:
llgtr %r2,%r2 # char *
jg sys_oldumount # branch to system call
- .globl sys32_setuid16_wrapper
+ .globl sys32_setuid16_wrapper
sys32_setuid16_wrapper:
- llgfr %r2,%r2 # __kernel_old_uid_emu31_t
+ llgfr %r2,%r2 # __kernel_old_uid_emu31_t
jg sys32_setuid16 # branch to system call
-#sys32_getuid16_wrapper # void
+#sys32_getuid16_wrapper # void
- .globl sys32_ptrace_wrapper
+ .globl sys32_ptrace_wrapper
sys32_ptrace_wrapper:
lgfr %r2,%r2 # long
lgfr %r3,%r3 # long
@@ -123,168 +123,168 @@ sys32_ptrace_wrapper:
llgfr %r5,%r5 # long
jg sys_ptrace # branch to system call
- .globl sys32_alarm_wrapper
+ .globl sys32_alarm_wrapper
sys32_alarm_wrapper:
llgfr %r2,%r2 # unsigned int
jg sys_alarm # branch to system call
-#sys32_pause_wrapper # void
+#sys32_pause_wrapper # void
- .globl compat_sys_utime_wrapper
+ .globl compat_sys_utime_wrapper
compat_sys_utime_wrapper:
llgtr %r2,%r2 # char *
llgtr %r3,%r3 # struct compat_utimbuf *
jg compat_sys_utime # branch to system call
- .globl sys32_access_wrapper
+ .globl sys32_access_wrapper
sys32_access_wrapper:
llgtr %r2,%r2 # const char *
lgfr %r3,%r3 # int
jg sys_access # branch to system call
- .globl sys32_nice_wrapper
+ .globl sys32_nice_wrapper
sys32_nice_wrapper:
lgfr %r2,%r2 # int
jg sys_nice # branch to system call
-#sys32_sync_wrapper # void
+#sys32_sync_wrapper # void
- .globl sys32_kill_wrapper
+ .globl sys32_kill_wrapper
sys32_kill_wrapper:
lgfr %r2,%r2 # int
lgfr %r3,%r3 # int
jg sys_kill # branch to system call
- .globl sys32_rename_wrapper
+ .globl sys32_rename_wrapper
sys32_rename_wrapper:
llgtr %r2,%r2 # const char *
llgtr %r3,%r3 # const char *
jg sys_rename # branch to system call
- .globl sys32_mkdir_wrapper
+ .globl sys32_mkdir_wrapper
sys32_mkdir_wrapper:
llgtr %r2,%r2 # const char *
lgfr %r3,%r3 # int
jg sys_mkdir # branch to system call
- .globl sys32_rmdir_wrapper
+ .globl sys32_rmdir_wrapper
sys32_rmdir_wrapper:
llgtr %r2,%r2 # const char *
jg sys_rmdir # branch to system call
- .globl sys32_dup_wrapper
+ .globl sys32_dup_wrapper
sys32_dup_wrapper:
llgfr %r2,%r2 # unsigned int
jg sys_dup # branch to system call
- .globl sys32_pipe_wrapper
+ .globl sys32_pipe_wrapper
sys32_pipe_wrapper:
llgtr %r2,%r2 # u32 *
jg sys_pipe # branch to system call
- .globl compat_sys_times_wrapper
+ .globl compat_sys_times_wrapper
compat_sys_times_wrapper:
llgtr %r2,%r2 # struct compat_tms *
jg compat_sys_times # branch to system call
- .globl sys32_brk_wrapper
+ .globl sys32_brk_wrapper
sys32_brk_wrapper:
llgtr %r2,%r2 # unsigned long
jg sys_brk # branch to system call
- .globl sys32_setgid16_wrapper
+ .globl sys32_setgid16_wrapper
sys32_setgid16_wrapper:
- llgfr %r2,%r2 # __kernel_old_gid_emu31_t
+ llgfr %r2,%r2 # __kernel_old_gid_emu31_t
jg sys32_setgid16 # branch to system call
-#sys32_getgid16_wrapper # void
+#sys32_getgid16_wrapper # void
.globl sys32_signal_wrapper
sys32_signal_wrapper:
- lgfr %r2,%r2 # int
+ lgfr %r2,%r2 # int
llgtr %r3,%r3 # __sighandler_t
jg sys_signal
-#sys32_geteuid16_wrapper # void
+#sys32_geteuid16_wrapper # void
-#sys32_getegid16_wrapper # void
+#sys32_getegid16_wrapper # void
- .globl sys32_acct_wrapper
+ .globl sys32_acct_wrapper
sys32_acct_wrapper:
llgtr %r2,%r2 # char *
jg sys_acct # branch to system call
- .globl sys32_umount_wrapper
+ .globl sys32_umount_wrapper
sys32_umount_wrapper:
llgtr %r2,%r2 # char *
lgfr %r3,%r3 # int
jg sys_umount # branch to system call
- .globl compat_sys_ioctl_wrapper
+ .globl compat_sys_ioctl_wrapper
compat_sys_ioctl_wrapper:
llgfr %r2,%r2 # unsigned int
llgfr %r3,%r3 # unsigned int
llgfr %r4,%r4 # unsigned int
jg compat_sys_ioctl # branch to system call
- .globl compat_sys_fcntl_wrapper
+ .globl compat_sys_fcntl_wrapper
compat_sys_fcntl_wrapper:
llgfr %r2,%r2 # unsigned int
- llgfr %r3,%r3 # unsigned int
+ llgfr %r3,%r3 # unsigned int
llgfr %r4,%r4 # unsigned long
jg compat_sys_fcntl # branch to system call
- .globl sys32_setpgid_wrapper
+ .globl sys32_setpgid_wrapper
sys32_setpgid_wrapper:
lgfr %r2,%r2 # pid_t
lgfr %r3,%r3 # pid_t
jg sys_setpgid # branch to system call
- .globl sys32_umask_wrapper
+ .globl sys32_umask_wrapper
sys32_umask_wrapper:
lgfr %r2,%r2 # int
jg sys_umask # branch to system call
- .globl sys32_chroot_wrapper
+ .globl sys32_chroot_wrapper
sys32_chroot_wrapper:
llgtr %r2,%r2 # char *
jg sys_chroot # branch to system call
.globl sys32_ustat_wrapper
sys32_ustat_wrapper:
- llgfr %r2,%r2 # dev_t
+ llgfr %r2,%r2 # dev_t
llgtr %r3,%r3 # struct ustat *
jg sys_ustat
- .globl sys32_dup2_wrapper
+ .globl sys32_dup2_wrapper
sys32_dup2_wrapper:
llgfr %r2,%r2 # unsigned int
llgfr %r3,%r3 # unsigned int
jg sys_dup2 # branch to system call
-#sys32_getppid_wrapper # void
+#sys32_getppid_wrapper # void
-#sys32_getpgrp_wrapper # void
+#sys32_getpgrp_wrapper # void
-#sys32_setsid_wrapper # void
+#sys32_setsid_wrapper # void
- .globl sys32_sigaction_wrapper
+ .globl sys32_sigaction_wrapper
sys32_sigaction_wrapper:
- lgfr %r2,%r2 # int
+ lgfr %r2,%r2 # int
llgtr %r3,%r3 # const struct old_sigaction *
llgtr %r4,%r4 # struct old_sigaction32 *
jg sys32_sigaction # branch to system call
- .globl sys32_setreuid16_wrapper
+ .globl sys32_setreuid16_wrapper
sys32_setreuid16_wrapper:
- llgfr %r2,%r2 # __kernel_old_uid_emu31_t
- llgfr %r3,%r3 # __kernel_old_uid_emu31_t
+ llgfr %r2,%r2 # __kernel_old_uid_emu31_t
+ llgfr %r3,%r3 # __kernel_old_uid_emu31_t
jg sys32_setreuid16 # branch to system call
- .globl sys32_setregid16_wrapper
+ .globl sys32_setregid16_wrapper
sys32_setregid16_wrapper:
- llgfr %r2,%r2 # __kernel_old_gid_emu31_t
- llgfr %r3,%r3 # __kernel_old_gid_emu31_t
+ llgfr %r2,%r2 # __kernel_old_gid_emu31_t
+ llgfr %r3,%r3 # __kernel_old_gid_emu31_t
jg sys32_setregid16 # branch to system call
.globl sys_sigsuspend_wrapper
@@ -294,95 +294,95 @@ sys_sigsuspend_wrapper:
llgfr %r4,%r4 # old_sigset_t
jg sys_sigsuspend
- .globl compat_sys_sigpending_wrapper
+ .globl compat_sys_sigpending_wrapper
compat_sys_sigpending_wrapper:
llgtr %r2,%r2 # compat_old_sigset_t *
jg compat_sys_sigpending # branch to system call
- .globl sys32_sethostname_wrapper
+ .globl sys32_sethostname_wrapper
sys32_sethostname_wrapper:
llgtr %r2,%r2 # char *
lgfr %r3,%r3 # int
jg sys_sethostname # branch to system call
- .globl compat_sys_setrlimit_wrapper
+ .globl compat_sys_setrlimit_wrapper
compat_sys_setrlimit_wrapper:
llgfr %r2,%r2 # unsigned int
llgtr %r3,%r3 # struct rlimit_emu31 *
jg compat_sys_setrlimit # branch to system call
- .globl compat_sys_old_getrlimit_wrapper
+ .globl compat_sys_old_getrlimit_wrapper
compat_sys_old_getrlimit_wrapper:
llgfr %r2,%r2 # unsigned int
llgtr %r3,%r3 # struct rlimit_emu31 *
jg compat_sys_old_getrlimit # branch to system call
- .globl compat_sys_getrlimit_wrapper
+ .globl compat_sys_getrlimit_wrapper
compat_sys_getrlimit_wrapper:
llgfr %r2,%r2 # unsigned int
llgtr %r3,%r3 # struct rlimit_emu31 *
jg compat_sys_getrlimit # branch to system call
- .globl sys32_mmap2_wrapper
+ .globl sys32_mmap2_wrapper
sys32_mmap2_wrapper:
llgtr %r2,%r2 # struct mmap_arg_struct_emu31 *
jg sys32_mmap2 # branch to system call
- .globl compat_sys_getrusage_wrapper
+ .globl compat_sys_getrusage_wrapper
compat_sys_getrusage_wrapper:
lgfr %r2,%r2 # int
llgtr %r3,%r3 # struct rusage_emu31 *
jg compat_sys_getrusage # branch to system call
- .globl sys32_gettimeofday_wrapper
+ .globl sys32_gettimeofday_wrapper
sys32_gettimeofday_wrapper:
llgtr %r2,%r2 # struct timeval_emu31 *
llgtr %r3,%r3 # struct timezone *
jg sys32_gettimeofday # branch to system call
- .globl sys32_settimeofday_wrapper
+ .globl sys32_settimeofday_wrapper
sys32_settimeofday_wrapper:
llgtr %r2,%r2 # struct timeval_emu31 *
llgtr %r3,%r3 # struct timezone *
jg sys32_settimeofday # branch to system call
- .globl sys32_getgroups16_wrapper
+ .globl sys32_getgroups16_wrapper
sys32_getgroups16_wrapper:
lgfr %r2,%r2 # int
llgtr %r3,%r3 # __kernel_old_gid_emu31_t *
jg sys32_getgroups16 # branch to system call
- .globl sys32_setgroups16_wrapper
+ .globl sys32_setgroups16_wrapper
sys32_setgroups16_wrapper:
lgfr %r2,%r2 # int
llgtr %r3,%r3 # __kernel_old_gid_emu31_t *
jg sys32_setgroups16 # branch to system call
- .globl sys32_symlink_wrapper
+ .globl sys32_symlink_wrapper
sys32_symlink_wrapper:
llgtr %r2,%r2 # const char *
llgtr %r3,%r3 # const char *
jg sys_symlink # branch to system call
- .globl sys32_readlink_wrapper
+ .globl sys32_readlink_wrapper
sys32_readlink_wrapper:
llgtr %r2,%r2 # const char *
llgtr %r3,%r3 # char *
lgfr %r4,%r4 # int
jg sys_readlink # branch to system call
- .globl sys32_uselib_wrapper
+ .globl sys32_uselib_wrapper
sys32_uselib_wrapper:
llgtr %r2,%r2 # const char *
jg sys_uselib # branch to system call
- .globl sys32_swapon_wrapper
+ .globl sys32_swapon_wrapper
sys32_swapon_wrapper:
llgtr %r2,%r2 # const char *
lgfr %r3,%r3 # int
jg sys_swapon # branch to system call
- .globl sys32_reboot_wrapper
+ .globl sys32_reboot_wrapper
sys32_reboot_wrapper:
lgfr %r2,%r2 # int
lgfr %r3,%r3 # int
@@ -390,121 +390,121 @@ sys32_reboot_wrapper:
llgtr %r5,%r5 # void *
jg sys_reboot # branch to system call
- .globl old32_readdir_wrapper
+ .globl old32_readdir_wrapper
old32_readdir_wrapper:
llgfr %r2,%r2 # unsigned int
llgtr %r3,%r3 # void *
llgfr %r4,%r4 # unsigned int
jg compat_sys_old_readdir # branch to system call
- .globl old32_mmap_wrapper
+ .globl old32_mmap_wrapper
old32_mmap_wrapper:
llgtr %r2,%r2 # struct mmap_arg_struct_emu31 *
jg old32_mmap # branch to system call
- .globl sys32_munmap_wrapper
+ .globl sys32_munmap_wrapper
sys32_munmap_wrapper:
llgfr %r2,%r2 # unsigned long
- llgfr %r3,%r3 # size_t
+ llgfr %r3,%r3 # size_t
jg sys_munmap # branch to system call
- .globl sys32_truncate_wrapper
+ .globl sys32_truncate_wrapper
sys32_truncate_wrapper:
llgtr %r2,%r2 # const char *
llgfr %r3,%r3 # unsigned long
jg sys_truncate # branch to system call
- .globl sys32_ftruncate_wrapper
+ .globl sys32_ftruncate_wrapper
sys32_ftruncate_wrapper:
llgfr %r2,%r2 # unsigned int
llgfr %r3,%r3 # unsigned long
jg sys_ftruncate # branch to system call
- .globl sys32_fchmod_wrapper
+ .globl sys32_fchmod_wrapper
sys32_fchmod_wrapper:
llgfr %r2,%r2 # unsigned int
llgfr %r3,%r3 # mode_t
jg sys_fchmod # branch to system call
- .globl sys32_fchown16_wrapper
+ .globl sys32_fchown16_wrapper
sys32_fchown16_wrapper:
llgfr %r2,%r2 # unsigned int
llgfr %r3,%r3 # compat_uid_t
llgfr %r4,%r4 # compat_uid_t
jg sys32_fchown16 # branch to system call
- .globl sys32_getpriority_wrapper
+ .globl sys32_getpriority_wrapper
sys32_getpriority_wrapper:
lgfr %r2,%r2 # int
lgfr %r3,%r3 # int
jg sys_getpriority # branch to system call
- .globl sys32_setpriority_wrapper
+ .globl sys32_setpriority_wrapper
sys32_setpriority_wrapper:
lgfr %r2,%r2 # int
lgfr %r3,%r3 # int
lgfr %r4,%r4 # int
jg sys_setpriority # branch to system call
- .globl compat_sys_statfs_wrapper
+ .globl compat_sys_statfs_wrapper
compat_sys_statfs_wrapper:
llgtr %r2,%r2 # char *
llgtr %r3,%r3 # struct compat_statfs *
jg compat_sys_statfs # branch to system call
- .globl compat_sys_fstatfs_wrapper
+ .globl compat_sys_fstatfs_wrapper
compat_sys_fstatfs_wrapper:
llgfr %r2,%r2 # unsigned int
llgtr %r3,%r3 # struct compat_statfs *
jg compat_sys_fstatfs # branch to system call
- .globl compat_sys_socketcall_wrapper
+ .globl compat_sys_socketcall_wrapper
compat_sys_socketcall_wrapper:
lgfr %r2,%r2 # int
llgtr %r3,%r3 # u32 *
jg compat_sys_socketcall # branch to system call
- .globl sys32_syslog_wrapper
+ .globl sys32_syslog_wrapper
sys32_syslog_wrapper:
lgfr %r2,%r2 # int
llgtr %r3,%r3 # char *
lgfr %r4,%r4 # int
jg sys_syslog # branch to system call
- .globl compat_sys_setitimer_wrapper
+ .globl compat_sys_setitimer_wrapper
compat_sys_setitimer_wrapper:
lgfr %r2,%r2 # int
llgtr %r3,%r3 # struct itimerval_emu31 *
llgtr %r4,%r4 # struct itimerval_emu31 *
jg compat_sys_setitimer # branch to system call
- .globl compat_sys_getitimer_wrapper
+ .globl compat_sys_getitimer_wrapper
compat_sys_getitimer_wrapper:
lgfr %r2,%r2 # int
llgtr %r3,%r3 # struct itimerval_emu31 *
jg compat_sys_getitimer # branch to system call
- .globl compat_sys_newstat_wrapper
+ .globl compat_sys_newstat_wrapper
compat_sys_newstat_wrapper:
llgtr %r2,%r2 # char *
llgtr %r3,%r3 # struct stat_emu31 *
jg compat_sys_newstat # branch to system call
- .globl compat_sys_newlstat_wrapper
+ .globl compat_sys_newlstat_wrapper
compat_sys_newlstat_wrapper:
llgtr %r2,%r2 # char *
llgtr %r3,%r3 # struct stat_emu31 *
jg compat_sys_newlstat # branch to system call
- .globl compat_sys_newfstat_wrapper
+ .globl compat_sys_newfstat_wrapper
compat_sys_newfstat_wrapper:
llgfr %r2,%r2 # unsigned int
llgtr %r3,%r3 # struct stat_emu31 *
jg compat_sys_newfstat # branch to system call
-#sys32_vhangup_wrapper # void
+#sys32_vhangup_wrapper # void
- .globl compat_sys_wait4_wrapper
+ .globl compat_sys_wait4_wrapper
compat_sys_wait4_wrapper:
lgfr %r2,%r2 # pid_t
llgtr %r3,%r3 # unsigned int *
@@ -512,17 +512,17 @@ compat_sys_wait4_wrapper:
llgtr %r5,%r5 # struct rusage *
jg compat_sys_wait4 # branch to system call
- .globl sys32_swapoff_wrapper
+ .globl sys32_swapoff_wrapper
sys32_swapoff_wrapper:
llgtr %r2,%r2 # const char *
jg sys_swapoff # branch to system call
- .globl sys32_sysinfo_wrapper
+ .globl sys32_sysinfo_wrapper
sys32_sysinfo_wrapper:
llgtr %r2,%r2 # struct sysinfo_emu31 *
jg sys32_sysinfo # branch to system call
- .globl sys32_ipc_wrapper
+ .globl sys32_ipc_wrapper
sys32_ipc_wrapper:
llgfr %r2,%r2 # uint
lgfr %r3,%r3 # int
@@ -531,59 +531,59 @@ sys32_ipc_wrapper:
llgfr %r6,%r6 # u32
jg sys32_ipc # branch to system call
- .globl sys32_fsync_wrapper
+ .globl sys32_fsync_wrapper
sys32_fsync_wrapper:
llgfr %r2,%r2 # unsigned int
jg sys_fsync # branch to system call
-#sys32_sigreturn_wrapper # done in sigreturn_glue
+#sys32_sigreturn_wrapper # done in sigreturn_glue
-#sys32_clone_wrapper # done in clone_glue
+#sys32_clone_wrapper # done in clone_glue
- .globl sys32_setdomainname_wrapper
+ .globl sys32_setdomainname_wrapper
sys32_setdomainname_wrapper:
llgtr %r2,%r2 # char *
lgfr %r3,%r3 # int
jg sys_setdomainname # branch to system call
- .globl sys32_newuname_wrapper
+ .globl sys32_newuname_wrapper
sys32_newuname_wrapper:
llgtr %r2,%r2 # struct new_utsname *
jg s390x_newuname # branch to system call
- .globl compat_sys_adjtimex_wrapper
+ .globl compat_sys_adjtimex_wrapper
compat_sys_adjtimex_wrapper:
llgtr %r2,%r2 # struct compat_timex *
jg compat_sys_adjtimex # branch to system call
- .globl sys32_mprotect_wrapper
+ .globl sys32_mprotect_wrapper
sys32_mprotect_wrapper:
llgtr %r2,%r2 # unsigned long (actually pointer
llgfr %r3,%r3 # size_t
llgfr %r4,%r4 # unsigned long
jg sys_mprotect # branch to system call
- .globl compat_sys_sigprocmask_wrapper
+ .globl compat_sys_sigprocmask_wrapper
compat_sys_sigprocmask_wrapper:
lgfr %r2,%r2 # int
llgtr %r3,%r3 # compat_old_sigset_t *
llgtr %r4,%r4 # compat_old_sigset_t *
jg compat_sys_sigprocmask # branch to system call
- .globl sys32_init_module_wrapper
+ .globl sys32_init_module_wrapper
sys32_init_module_wrapper:
llgtr %r2,%r2 # void *
llgfr %r3,%r3 # unsigned long
llgtr %r4,%r4 # char *
jg sys32_init_module # branch to system call
- .globl sys32_delete_module_wrapper
+ .globl sys32_delete_module_wrapper
sys32_delete_module_wrapper:
llgtr %r2,%r2 # const char *
llgfr %r3,%r3 # unsigned int
jg sys32_delete_module # branch to system call
- .globl sys32_quotactl_wrapper
+ .globl sys32_quotactl_wrapper
sys32_quotactl_wrapper:
llgfr %r2,%r2 # unsigned int
llgtr %r3,%r3 # const char *
@@ -591,45 +591,45 @@ sys32_quotactl_wrapper:
llgtr %r5,%r5 # caddr_t
jg sys_quotactl # branch to system call
- .globl sys32_getpgid_wrapper
+ .globl sys32_getpgid_wrapper
sys32_getpgid_wrapper:
lgfr %r2,%r2 # pid_t
jg sys_getpgid # branch to system call
- .globl sys32_fchdir_wrapper
+ .globl sys32_fchdir_wrapper
sys32_fchdir_wrapper:
llgfr %r2,%r2 # unsigned int
jg sys_fchdir # branch to system call
- .globl sys32_bdflush_wrapper
+ .globl sys32_bdflush_wrapper
sys32_bdflush_wrapper:
lgfr %r2,%r2 # int
lgfr %r3,%r3 # long
jg sys_bdflush # branch to system call
- .globl sys32_sysfs_wrapper
+ .globl sys32_sysfs_wrapper
sys32_sysfs_wrapper:
lgfr %r2,%r2 # int
llgfr %r3,%r3 # unsigned long
llgfr %r4,%r4 # unsigned long
jg sys_sysfs # branch to system call
- .globl sys32_personality_wrapper
+ .globl sys32_personality_wrapper
sys32_personality_wrapper:
llgfr %r2,%r2 # unsigned long
jg s390x_personality # branch to system call
- .globl sys32_setfsuid16_wrapper
+ .globl sys32_setfsuid16_wrapper
sys32_setfsuid16_wrapper:
- llgfr %r2,%r2 # __kernel_old_uid_emu31_t
+ llgfr %r2,%r2 # __kernel_old_uid_emu31_t
jg sys32_setfsuid16 # branch to system call
- .globl sys32_setfsgid16_wrapper
+ .globl sys32_setfsgid16_wrapper
sys32_setfsgid16_wrapper:
- llgfr %r2,%r2 # __kernel_old_gid_emu31_t
+ llgfr %r2,%r2 # __kernel_old_gid_emu31_t
jg sys32_setfsgid16 # branch to system call
- .globl sys32_llseek_wrapper
+ .globl sys32_llseek_wrapper
sys32_llseek_wrapper:
llgfr %r2,%r2 # unsigned int
llgfr %r3,%r3 # unsigned long
@@ -638,14 +638,14 @@ sys32_llseek_wrapper:
llgfr %r6,%r6 # unsigned int
jg sys_llseek # branch to system call
- .globl sys32_getdents_wrapper
+ .globl sys32_getdents_wrapper
sys32_getdents_wrapper:
llgfr %r2,%r2 # unsigned int
llgtr %r3,%r3 # void *
llgfr %r4,%r4 # unsigned int
jg compat_sys_getdents # branch to system call
- .globl compat_sys_select_wrapper
+ .globl compat_sys_select_wrapper
compat_sys_select_wrapper:
lgfr %r2,%r2 # int
llgtr %r3,%r3 # compat_fd_set *
@@ -654,113 +654,113 @@ compat_sys_select_wrapper:
llgtr %r6,%r6 # struct compat_timeval *
jg compat_sys_select # branch to system call
- .globl sys32_flock_wrapper
+ .globl sys32_flock_wrapper
sys32_flock_wrapper:
llgfr %r2,%r2 # unsigned int
llgfr %r3,%r3 # unsigned int
jg sys_flock # branch to system call
- .globl sys32_msync_wrapper
+ .globl sys32_msync_wrapper
sys32_msync_wrapper:
llgfr %r2,%r2 # unsigned long
llgfr %r3,%r3 # size_t
lgfr %r4,%r4 # int
jg sys_msync # branch to system call
- .globl compat_sys_readv_wrapper
+ .globl compat_sys_readv_wrapper
compat_sys_readv_wrapper:
lgfr %r2,%r2 # int
llgtr %r3,%r3 # const struct compat_iovec *
llgfr %r4,%r4 # unsigned long
jg compat_sys_readv # branch to system call
- .globl compat_sys_writev_wrapper
+ .globl compat_sys_writev_wrapper
compat_sys_writev_wrapper:
lgfr %r2,%r2 # int
llgtr %r3,%r3 # const struct compat_iovec *
llgfr %r4,%r4 # unsigned long
jg compat_sys_writev # branch to system call
- .globl sys32_getsid_wrapper
+ .globl sys32_getsid_wrapper
sys32_getsid_wrapper:
lgfr %r2,%r2 # pid_t
jg sys_getsid # branch to system call
- .globl sys32_fdatasync_wrapper
+ .globl sys32_fdatasync_wrapper
sys32_fdatasync_wrapper:
llgfr %r2,%r2 # unsigned int
jg sys_fdatasync # branch to system call
-#sys32_sysctl_wrapper # tbd
+#sys32_sysctl_wrapper # tbd
- .globl sys32_mlock_wrapper
+ .globl sys32_mlock_wrapper
sys32_mlock_wrapper:
llgfr %r2,%r2 # unsigned long
llgfr %r3,%r3 # size_t
jg sys_mlock # branch to system call
- .globl sys32_munlock_wrapper
+ .globl sys32_munlock_wrapper
sys32_munlock_wrapper:
llgfr %r2,%r2 # unsigned long
llgfr %r3,%r3 # size_t
jg sys_munlock # branch to system call
- .globl sys32_mlockall_wrapper
+ .globl sys32_mlockall_wrapper
sys32_mlockall_wrapper:
lgfr %r2,%r2 # int
jg sys_mlockall # branch to system call
-#sys32_munlockall_wrapper # void
+#sys32_munlockall_wrapper # void
- .globl sys32_sched_setparam_wrapper
+ .globl sys32_sched_setparam_wrapper
sys32_sched_setparam_wrapper:
lgfr %r2,%r2 # pid_t
llgtr %r3,%r3 # struct sched_param *
jg sys_sched_setparam # branch to system call
- .globl sys32_sched_getparam_wrapper
+ .globl sys32_sched_getparam_wrapper
sys32_sched_getparam_wrapper:
lgfr %r2,%r2 # pid_t
llgtr %r3,%r3 # struct sched_param *
jg sys_sched_getparam # branch to system call
- .globl sys32_sched_setscheduler_wrapper
+ .globl sys32_sched_setscheduler_wrapper
sys32_sched_setscheduler_wrapper:
lgfr %r2,%r2 # pid_t
lgfr %r3,%r3 # int
llgtr %r4,%r4 # struct sched_param *
jg sys_sched_setscheduler # branch to system call
- .globl sys32_sched_getscheduler_wrapper
+ .globl sys32_sched_getscheduler_wrapper
sys32_sched_getscheduler_wrapper:
lgfr %r2,%r2 # pid_t
jg sys_sched_getscheduler # branch to system call
-#sys32_sched_yield_wrapper # void
+#sys32_sched_yield_wrapper # void
- .globl sys32_sched_get_priority_max_wrapper
+ .globl sys32_sched_get_priority_max_wrapper
sys32_sched_get_priority_max_wrapper:
lgfr %r2,%r2 # int
jg sys_sched_get_priority_max # branch to system call
- .globl sys32_sched_get_priority_min_wrapper
+ .globl sys32_sched_get_priority_min_wrapper
sys32_sched_get_priority_min_wrapper:
lgfr %r2,%r2 # int
jg sys_sched_get_priority_min # branch to system call
- .globl sys32_sched_rr_get_interval_wrapper
+ .globl sys32_sched_rr_get_interval_wrapper
sys32_sched_rr_get_interval_wrapper:
lgfr %r2,%r2 # pid_t
llgtr %r3,%r3 # struct compat_timespec *
jg sys32_sched_rr_get_interval # branch to system call
- .globl compat_sys_nanosleep_wrapper
+ .globl compat_sys_nanosleep_wrapper
compat_sys_nanosleep_wrapper:
llgtr %r2,%r2 # struct compat_timespec *
llgtr %r3,%r3 # struct compat_timespec *
jg compat_sys_nanosleep # branch to system call
- .globl sys32_mremap_wrapper
+ .globl sys32_mremap_wrapper
sys32_mremap_wrapper:
llgfr %r2,%r2 # unsigned long
llgfr %r3,%r3 # unsigned long
@@ -769,49 +769,49 @@ sys32_mremap_wrapper:
llgfr %r6,%r6 # unsigned long
jg sys_mremap # branch to system call
- .globl sys32_setresuid16_wrapper
+ .globl sys32_setresuid16_wrapper
sys32_setresuid16_wrapper:
- llgfr %r2,%r2 # __kernel_old_uid_emu31_t
- llgfr %r3,%r3 # __kernel_old_uid_emu31_t
- llgfr %r4,%r4 # __kernel_old_uid_emu31_t
+ llgfr %r2,%r2 # __kernel_old_uid_emu31_t
+ llgfr %r3,%r3 # __kernel_old_uid_emu31_t
+ llgfr %r4,%r4 # __kernel_old_uid_emu31_t
jg sys32_setresuid16 # branch to system call
- .globl sys32_getresuid16_wrapper
+ .globl sys32_getresuid16_wrapper
sys32_getresuid16_wrapper:
llgtr %r2,%r2 # __kernel_old_uid_emu31_t *
llgtr %r3,%r3 # __kernel_old_uid_emu31_t *
llgtr %r4,%r4 # __kernel_old_uid_emu31_t *
jg sys32_getresuid16 # branch to system call
- .globl sys32_poll_wrapper
+ .globl sys32_poll_wrapper
sys32_poll_wrapper:
- llgtr %r2,%r2 # struct pollfd *
- llgfr %r3,%r3 # unsigned int
- lgfr %r4,%r4 # long
+ llgtr %r2,%r2 # struct pollfd *
+ llgfr %r3,%r3 # unsigned int
+ lgfr %r4,%r4 # long
jg sys_poll # branch to system call
- .globl compat_sys_nfsservctl_wrapper
+ .globl compat_sys_nfsservctl_wrapper
compat_sys_nfsservctl_wrapper:
- lgfr %r2,%r2 # int
+ lgfr %r2,%r2 # int
llgtr %r3,%r3 # struct compat_nfsctl_arg*
llgtr %r4,%r4 # union compat_nfsctl_res*
jg compat_sys_nfsservctl # branch to system call
- .globl sys32_setresgid16_wrapper
+ .globl sys32_setresgid16_wrapper
sys32_setresgid16_wrapper:
- llgfr %r2,%r2 # __kernel_old_gid_emu31_t
- llgfr %r3,%r3 # __kernel_old_gid_emu31_t
- llgfr %r4,%r4 # __kernel_old_gid_emu31_t
+ llgfr %r2,%r2 # __kernel_old_gid_emu31_t
+ llgfr %r3,%r3 # __kernel_old_gid_emu31_t
+ llgfr %r4,%r4 # __kernel_old_gid_emu31_t
jg sys32_setresgid16 # branch to system call
- .globl sys32_getresgid16_wrapper
+ .globl sys32_getresgid16_wrapper
sys32_getresgid16_wrapper:
llgtr %r2,%r2 # __kernel_old_gid_emu31_t *
llgtr %r3,%r3 # __kernel_old_gid_emu31_t *
llgtr %r4,%r4 # __kernel_old_gid_emu31_t *
jg sys32_getresgid16 # branch to system call
- .globl sys32_prctl_wrapper
+ .globl sys32_prctl_wrapper
sys32_prctl_wrapper:
lgfr %r2,%r2 # int
llgfr %r3,%r3 # unsigned long
@@ -820,9 +820,9 @@ sys32_prctl_wrapper:
llgfr %r6,%r6 # unsigned long
jg sys_prctl # branch to system call
-#sys32_rt_sigreturn_wrapper # done in rt_sigreturn_glue
+#sys32_rt_sigreturn_wrapper # done in rt_sigreturn_glue
- .globl sys32_rt_sigaction_wrapper
+ .globl sys32_rt_sigaction_wrapper
sys32_rt_sigaction_wrapper:
lgfr %r2,%r2 # int
llgtr %r3,%r3 # const struct sigaction_emu31 *
@@ -830,7 +830,7 @@ sys32_rt_sigaction_wrapper:
llgfr %r5,%r5 # size_t
jg sys32_rt_sigaction # branch to system call
- .globl sys32_rt_sigprocmask_wrapper
+ .globl sys32_rt_sigprocmask_wrapper
sys32_rt_sigprocmask_wrapper:
lgfr %r2,%r2 # int
llgtr %r3,%r3 # old_sigset_emu31 *
@@ -838,13 +838,13 @@ sys32_rt_sigprocmask_wrapper:
llgfr %r5,%r5 # size_t
jg sys32_rt_sigprocmask # branch to system call
- .globl sys32_rt_sigpending_wrapper
+ .globl sys32_rt_sigpending_wrapper
sys32_rt_sigpending_wrapper:
llgtr %r2,%r2 # sigset_emu31 *
llgfr %r3,%r3 # size_t
jg sys32_rt_sigpending # branch to system call
- .globl compat_sys_rt_sigtimedwait_wrapper
+ .globl compat_sys_rt_sigtimedwait_wrapper
compat_sys_rt_sigtimedwait_wrapper:
llgtr %r2,%r2 # const sigset_emu31_t *
llgtr %r3,%r3 # siginfo_emu31_t *
@@ -852,7 +852,7 @@ compat_sys_rt_sigtimedwait_wrapper:
llgfr %r5,%r5 # size_t
jg compat_sys_rt_sigtimedwait # branch to system call
- .globl sys32_rt_sigqueueinfo_wrapper
+ .globl sys32_rt_sigqueueinfo_wrapper
sys32_rt_sigqueueinfo_wrapper:
lgfr %r2,%r2 # int
lgfr %r3,%r3 # int
@@ -865,7 +865,7 @@ compat_sys_rt_sigsuspend_wrapper:
llgfr %r3,%r3 # compat_size_t
jg compat_sys_rt_sigsuspend
- .globl sys32_pread64_wrapper
+ .globl sys32_pread64_wrapper
sys32_pread64_wrapper:
llgfr %r2,%r2 # unsigned int
llgtr %r3,%r3 # char *
@@ -874,7 +874,7 @@ sys32_pread64_wrapper:
llgfr %r6,%r6 # u32
jg sys32_pread64 # branch to system call
- .globl sys32_pwrite64_wrapper
+ .globl sys32_pwrite64_wrapper
sys32_pwrite64_wrapper:
llgfr %r2,%r2 # unsigned int
llgtr %r3,%r3 # const char *
@@ -883,26 +883,26 @@ sys32_pwrite64_wrapper:
llgfr %r6,%r6 # u32
jg sys32_pwrite64 # branch to system call
- .globl sys32_chown16_wrapper
+ .globl sys32_chown16_wrapper
sys32_chown16_wrapper:
llgtr %r2,%r2 # const char *
- llgfr %r3,%r3 # __kernel_old_uid_emu31_t
- llgfr %r4,%r4 # __kernel_old_gid_emu31_t
+ llgfr %r3,%r3 # __kernel_old_uid_emu31_t
+ llgfr %r4,%r4 # __kernel_old_gid_emu31_t
jg sys32_chown16 # branch to system call
- .globl sys32_getcwd_wrapper
+ .globl sys32_getcwd_wrapper
sys32_getcwd_wrapper:
llgtr %r2,%r2 # char *
llgfr %r3,%r3 # unsigned long
jg sys_getcwd # branch to system call
- .globl sys32_capget_wrapper
+ .globl sys32_capget_wrapper
sys32_capget_wrapper:
llgtr %r2,%r2 # cap_user_header_t
llgtr %r3,%r3 # cap_user_data_t
jg sys_capget # branch to system call
- .globl sys32_capset_wrapper
+ .globl sys32_capset_wrapper
sys32_capset_wrapper:
llgtr %r2,%r2 # cap_user_header_t
llgtr %r3,%r3 # const cap_user_data_t
@@ -910,11 +910,11 @@ sys32_capset_wrapper:
.globl sys32_sigaltstack_wrapper
sys32_sigaltstack_wrapper:
- llgtr %r2,%r2 # const stack_emu31_t *
- llgtr %r3,%r3 # stack_emu31_t *
+ llgtr %r2,%r2 # const stack_emu31_t *
+ llgtr %r3,%r3 # stack_emu31_t *
jg sys32_sigaltstack
- .globl sys32_sendfile_wrapper
+ .globl sys32_sendfile_wrapper
sys32_sendfile_wrapper:
lgfr %r2,%r2 # int
lgfr %r3,%r3 # int
@@ -922,33 +922,33 @@ sys32_sendfile_wrapper:
llgfr %r5,%r5 # size_t
jg sys32_sendfile # branch to system call
-#sys32_vfork_wrapper # done in vfork_glue
+#sys32_vfork_wrapper # done in vfork_glue
- .globl sys32_truncate64_wrapper
+ .globl sys32_truncate64_wrapper
sys32_truncate64_wrapper:
llgtr %r2,%r2 # const char *
llgfr %r3,%r3 # unsigned long
llgfr %r4,%r4 # unsigned long
jg sys32_truncate64 # branch to system call
- .globl sys32_ftruncate64_wrapper
+ .globl sys32_ftruncate64_wrapper
sys32_ftruncate64_wrapper:
llgfr %r2,%r2 # unsigned int
llgfr %r3,%r3 # unsigned long
llgfr %r4,%r4 # unsigned long
jg sys32_ftruncate64 # branch to system call
- .globl sys32_lchown_wrapper
+ .globl sys32_lchown_wrapper
sys32_lchown_wrapper:
llgtr %r2,%r2 # const char *
llgfr %r3,%r3 # uid_t
llgfr %r4,%r4 # gid_t
jg sys_lchown # branch to system call
-#sys32_getuid_wrapper # void
-#sys32_getgid_wrapper # void
-#sys32_geteuid_wrapper # void
-#sys32_getegid_wrapper # void
+#sys32_getuid_wrapper # void
+#sys32_getgid_wrapper # void
+#sys32_geteuid_wrapper # void
+#sys32_getegid_wrapper # void
.globl sys32_setreuid_wrapper
sys32_setreuid_wrapper:
@@ -962,111 +962,111 @@ sys32_setregid_wrapper:
llgfr %r3,%r3 # gid_t
jg sys_setregid # branch to system call
- .globl sys32_getgroups_wrapper
+ .globl sys32_getgroups_wrapper
sys32_getgroups_wrapper:
lgfr %r2,%r2 # int
llgtr %r3,%r3 # gid_t *
jg sys_getgroups # branch to system call
- .globl sys32_setgroups_wrapper
+ .globl sys32_setgroups_wrapper
sys32_setgroups_wrapper:
lgfr %r2,%r2 # int
llgtr %r3,%r3 # gid_t *
jg sys_setgroups # branch to system call
- .globl sys32_fchown_wrapper
+ .globl sys32_fchown_wrapper
sys32_fchown_wrapper:
llgfr %r2,%r2 # unsigned int
llgfr %r3,%r3 # uid_t
llgfr %r4,%r4 # gid_t
jg sys_fchown # branch to system call
- .globl sys32_setresuid_wrapper
+ .globl sys32_setresuid_wrapper
sys32_setresuid_wrapper:
llgfr %r2,%r2 # uid_t
llgfr %r3,%r3 # uid_t
llgfr %r4,%r4 # uid_t
jg sys_setresuid # branch to system call
- .globl sys32_getresuid_wrapper
+ .globl sys32_getresuid_wrapper
sys32_getresuid_wrapper:
llgtr %r2,%r2 # uid_t *
llgtr %r3,%r3 # uid_t *
llgtr %r4,%r4 # uid_t *
jg sys_getresuid # branch to system call
- .globl sys32_setresgid_wrapper
+ .globl sys32_setresgid_wrapper
sys32_setresgid_wrapper:
llgfr %r2,%r2 # gid_t
llgfr %r3,%r3 # gid_t
llgfr %r4,%r4 # gid_t
jg sys_setresgid # branch to system call
- .globl sys32_getresgid_wrapper
+ .globl sys32_getresgid_wrapper
sys32_getresgid_wrapper:
llgtr %r2,%r2 # gid_t *
llgtr %r3,%r3 # gid_t *
llgtr %r4,%r4 # gid_t *
jg sys_getresgid # branch to system call
- .globl sys32_chown_wrapper
+ .globl sys32_chown_wrapper
sys32_chown_wrapper:
llgtr %r2,%r2 # const char *
llgfr %r3,%r3 # uid_t
llgfr %r4,%r4 # gid_t
jg sys_chown # branch to system call
- .globl sys32_setuid_wrapper
+ .globl sys32_setuid_wrapper
sys32_setuid_wrapper:
llgfr %r2,%r2 # uid_t
jg sys_setuid # branch to system call
- .globl sys32_setgid_wrapper
+ .globl sys32_setgid_wrapper
sys32_setgid_wrapper:
llgfr %r2,%r2 # gid_t
jg sys_setgid # branch to system call
- .globl sys32_setfsuid_wrapper
+ .globl sys32_setfsuid_wrapper
sys32_setfsuid_wrapper:
llgfr %r2,%r2 # uid_t
jg sys_setfsuid # branch to system call
- .globl sys32_setfsgid_wrapper
+ .globl sys32_setfsgid_wrapper
sys32_setfsgid_wrapper:
llgfr %r2,%r2 # gid_t
jg sys_setfsgid # branch to system call
- .globl sys32_pivot_root_wrapper
+ .globl sys32_pivot_root_wrapper
sys32_pivot_root_wrapper:
llgtr %r2,%r2 # const char *
llgtr %r3,%r3 # const char *
jg sys_pivot_root # branch to system call
- .globl sys32_mincore_wrapper
+ .globl sys32_mincore_wrapper
sys32_mincore_wrapper:
llgfr %r2,%r2 # unsigned long
llgfr %r3,%r3 # size_t
llgtr %r4,%r4 # unsigned char *
jg sys_mincore # branch to system call
- .globl sys32_madvise_wrapper
+ .globl sys32_madvise_wrapper
sys32_madvise_wrapper:
llgfr %r2,%r2 # unsigned long
llgfr %r3,%r3 # size_t
lgfr %r4,%r4 # int
jg sys_madvise # branch to system call
- .globl sys32_getdents64_wrapper
+ .globl sys32_getdents64_wrapper
sys32_getdents64_wrapper:
llgfr %r2,%r2 # unsigned int
llgtr %r3,%r3 # void *
llgfr %r4,%r4 # unsigned int
jg sys_getdents64 # branch to system call
- .globl compat_sys_fcntl64_wrapper
+ .globl compat_sys_fcntl64_wrapper
compat_sys_fcntl64_wrapper:
llgfr %r2,%r2 # unsigned int
- llgfr %r3,%r3 # unsigned int
+ llgfr %r3,%r3 # unsigned int
llgfr %r4,%r4 # unsigned long
jg compat_sys_fcntl64 # branch to system call
@@ -1087,10 +1087,10 @@ sys32_stime_wrapper:
llgtr %r2,%r2 # long *
jg compat_sys_stime # branch to system call
- .globl sys32_sysctl_wrapper
+ .globl sys32_sysctl_wrapper
sys32_sysctl_wrapper:
- llgtr %r2,%r2 # struct __sysctl_args32 *
- jg sys32_sysctl
+ llgtr %r2,%r2 # struct __sysctl_args32 *
+ jg sys32_sysctl
.globl sys32_fstat64_wrapper
sys32_fstat64_wrapper:
@@ -1098,7 +1098,7 @@ sys32_fstat64_wrapper:
llgtr %r3,%r3 # struct stat64 *
jg sys32_fstat64 # branch to system call
- .globl compat_sys_futex_wrapper
+ .globl compat_sys_futex_wrapper
compat_sys_futex_wrapper:
llgtr %r2,%r2 # u32 *
lgfr %r3,%r3 # int
@@ -1213,22 +1213,22 @@ sys32_sched_getaffinity_wrapper:
llgtr %r4,%r4 # unsigned long *
jg compat_sys_sched_getaffinity
- .globl sys32_exit_group_wrapper
+ .globl sys32_exit_group_wrapper
sys32_exit_group_wrapper:
lgfr %r2,%r2 # int
jg sys_exit_group # branch to system call
- .globl sys32_set_tid_address_wrapper
+ .globl sys32_set_tid_address_wrapper
sys32_set_tid_address_wrapper:
llgtr %r2,%r2 # int *
jg sys_set_tid_address # branch to system call
- .globl sys_epoll_create_wrapper
+ .globl sys_epoll_create_wrapper
sys_epoll_create_wrapper:
lgfr %r2,%r2 # int
jg sys_epoll_create # branch to system call
- .globl sys_epoll_ctl_wrapper
+ .globl sys_epoll_ctl_wrapper
sys_epoll_ctl_wrapper:
lgfr %r2,%r2 # int
lgfr %r3,%r3 # int
@@ -1236,7 +1236,7 @@ sys_epoll_ctl_wrapper:
llgtr %r5,%r5 # struct epoll_event *
jg sys_epoll_ctl # branch to system call
- .globl sys_epoll_wait_wrapper
+ .globl sys_epoll_wait_wrapper
sys_epoll_wait_wrapper:
lgfr %r2,%r2 # int
llgtr %r3,%r3 # struct epoll_event *
diff --git a/arch/s390/kernel/cpcmd.c b/arch/s390/kernel/cpcmd.c
index 4ef44e536b2c..1eae74e72f95 100644
--- a/arch/s390/kernel/cpcmd.c
+++ b/arch/s390/kernel/cpcmd.c
@@ -25,11 +25,8 @@ static char cpcmd_buf[241];
*/
int __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
{
- const int mask = 0x40000000L;
- unsigned long flags;
- int return_code;
- int return_len;
- int cmdlen;
+ unsigned long flags, cmdlen;
+ int return_code, return_len;
spin_lock_irqsave(&cpcmd_lock, flags);
cmdlen = strlen(cmd);
@@ -38,64 +35,44 @@ int __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
ASCEBC(cpcmd_buf, cmdlen);
if (response != NULL && rlen > 0) {
+ register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf;
+ register unsigned long reg3 asm ("3") = (addr_t) response;
+ register unsigned long reg4 asm ("4") = cmdlen | 0x40000000L;
+ register unsigned long reg5 asm ("5") = rlen;
+
memset(response, 0, rlen);
+ asm volatile(
#ifndef CONFIG_64BIT
- asm volatile ( "lra 2,0(%2)\n"
- "lr 4,%3\n"
- "o 4,%6\n"
- "lra 3,0(%4)\n"
- "lr 5,%5\n"
- "diag 2,4,0x8\n"
- "brc 8, 1f\n"
- "ar 5, %5\n"
- "1: \n"
- "lr %0,4\n"
- "lr %1,5\n"
- : "=d" (return_code), "=d" (return_len)
- : "a" (cpcmd_buf), "d" (cmdlen),
- "a" (response), "d" (rlen), "m" (mask)
- : "cc", "2", "3", "4", "5" );
+ " diag %2,%0,0x8\n"
+ " brc 8,1f\n"
+ " ar %1,%4\n"
#else /* CONFIG_64BIT */
- asm volatile ( "lrag 2,0(%2)\n"
- "lgr 4,%3\n"
- "o 4,%6\n"
- "lrag 3,0(%4)\n"
- "lgr 5,%5\n"
- "sam31\n"
- "diag 2,4,0x8\n"
- "sam64\n"
- "brc 8, 1f\n"
- "agr 5, %5\n"
- "1: \n"
- "lgr %0,4\n"
- "lgr %1,5\n"
- : "=d" (return_code), "=d" (return_len)
- : "a" (cpcmd_buf), "d" (cmdlen),
- "a" (response), "d" (rlen), "m" (mask)
- : "cc", "2", "3", "4", "5" );
+ " sam31\n"
+ " diag %2,%0,0x8\n"
+ " sam64\n"
+ " brc 8,1f\n"
+ " agr %1,%4\n"
#endif /* CONFIG_64BIT */
+ "1:\n"
+ : "+d" (reg4), "+d" (reg5)
+ : "d" (reg2), "d" (reg3), "d" (rlen) : "cc");
+ return_code = (int) reg4;
+ return_len = (int) reg5;
EBCASC(response, rlen);
} else {
+ register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf;
+ register unsigned long reg3 asm ("3") = cmdlen;
return_len = 0;
+ asm volatile(
#ifndef CONFIG_64BIT
- asm volatile ( "lra 2,0(%1)\n"
- "lr 3,%2\n"
- "diag 2,3,0x8\n"
- "lr %0,3\n"
- : "=d" (return_code)
- : "a" (cpcmd_buf), "d" (cmdlen)
- : "2", "3" );
+ " diag %1,%0,0x8\n"
#else /* CONFIG_64BIT */
- asm volatile ( "lrag 2,0(%1)\n"
- "lgr 3,%2\n"
- "sam31\n"
- "diag 2,3,0x8\n"
- "sam64\n"
- "lgr %0,3\n"
- : "=d" (return_code)
- : "a" (cpcmd_buf), "d" (cmdlen)
- : "2", "3" );
+ " sam31\n"
+ " diag %1,%0,0x8\n"
+ " sam64\n"
#endif /* CONFIG_64BIT */
+ : "+d" (reg3) : "d" (reg2) : "cc");
+ return_code = (int) reg3;
}
spin_unlock_irqrestore(&cpcmd_lock, flags);
if (response_code != NULL)
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index 7ba20922a535..43f3d0c7e132 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -603,7 +603,7 @@ debug_open(struct inode *inode, struct file *file)
debug_info_t *debug_info, *debug_info_snapshot;
down(&debug_lock);
- debug_info = (struct debug_info*)file->f_dentry->d_inode->u.generic_ip;
+ debug_info = file->f_dentry->d_inode->i_private;
/* find debug view */
for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
if (!debug_info->views[i])
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 5b5799ac8f83..dddc3de30401 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -4,8 +4,8 @@
*
* Copyright (C) IBM Corp. 1999,2006
* 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),
+ * Hartmut Penner (hp@de.ibm.com),
+ * Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
* Heiko Carstens <heiko.carstens@de.ibm.com>
*/
@@ -24,29 +24,29 @@
* Stack layout for the system_call stack entry.
* The first few entries are identical to the user_regs_struct.
*/
-SP_PTREGS = STACK_FRAME_OVERHEAD
-SP_ARGS = STACK_FRAME_OVERHEAD + __PT_ARGS
-SP_PSW = STACK_FRAME_OVERHEAD + __PT_PSW
-SP_R0 = STACK_FRAME_OVERHEAD + __PT_GPRS
-SP_R1 = STACK_FRAME_OVERHEAD + __PT_GPRS + 4
-SP_R2 = STACK_FRAME_OVERHEAD + __PT_GPRS + 8
-SP_R3 = STACK_FRAME_OVERHEAD + __PT_GPRS + 12
-SP_R4 = STACK_FRAME_OVERHEAD + __PT_GPRS + 16
-SP_R5 = STACK_FRAME_OVERHEAD + __PT_GPRS + 20
-SP_R6 = STACK_FRAME_OVERHEAD + __PT_GPRS + 24
-SP_R7 = STACK_FRAME_OVERHEAD + __PT_GPRS + 28
-SP_R8 = STACK_FRAME_OVERHEAD + __PT_GPRS + 32
-SP_R9 = STACK_FRAME_OVERHEAD + __PT_GPRS + 36
-SP_R10 = STACK_FRAME_OVERHEAD + __PT_GPRS + 40
-SP_R11 = STACK_FRAME_OVERHEAD + __PT_GPRS + 44
-SP_R12 = STACK_FRAME_OVERHEAD + __PT_GPRS + 48
-SP_R13 = STACK_FRAME_OVERHEAD + __PT_GPRS + 52
-SP_R14 = STACK_FRAME_OVERHEAD + __PT_GPRS + 56
-SP_R15 = STACK_FRAME_OVERHEAD + __PT_GPRS + 60
-SP_ORIG_R2 = STACK_FRAME_OVERHEAD + __PT_ORIG_GPR2
-SP_ILC = STACK_FRAME_OVERHEAD + __PT_ILC
-SP_TRAP = STACK_FRAME_OVERHEAD + __PT_TRAP
-SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE
+SP_PTREGS = STACK_FRAME_OVERHEAD
+SP_ARGS = STACK_FRAME_OVERHEAD + __PT_ARGS
+SP_PSW = STACK_FRAME_OVERHEAD + __PT_PSW
+SP_R0 = STACK_FRAME_OVERHEAD + __PT_GPRS
+SP_R1 = STACK_FRAME_OVERHEAD + __PT_GPRS + 4
+SP_R2 = STACK_FRAME_OVERHEAD + __PT_GPRS + 8
+SP_R3 = STACK_FRAME_OVERHEAD + __PT_GPRS + 12
+SP_R4 = STACK_FRAME_OVERHEAD + __PT_GPRS + 16
+SP_R5 = STACK_FRAME_OVERHEAD + __PT_GPRS + 20
+SP_R6 = STACK_FRAME_OVERHEAD + __PT_GPRS + 24
+SP_R7 = STACK_FRAME_OVERHEAD + __PT_GPRS + 28
+SP_R8 = STACK_FRAME_OVERHEAD + __PT_GPRS + 32
+SP_R9 = STACK_FRAME_OVERHEAD + __PT_GPRS + 36
+SP_R10 = STACK_FRAME_OVERHEAD + __PT_GPRS + 40
+SP_R11 = STACK_FRAME_OVERHEAD + __PT_GPRS + 44
+SP_R12 = STACK_FRAME_OVERHEAD + __PT_GPRS + 48
+SP_R13 = STACK_FRAME_OVERHEAD + __PT_GPRS + 52
+SP_R14 = STACK_FRAME_OVERHEAD + __PT_GPRS + 56
+SP_R15 = STACK_FRAME_OVERHEAD + __PT_GPRS + 60
+SP_ORIG_R2 = STACK_FRAME_OVERHEAD + __PT_ORIG_GPR2
+SP_ILC = STACK_FRAME_OVERHEAD + __PT_ILC
+SP_TRAP = STACK_FRAME_OVERHEAD + __PT_TRAP
+SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE
_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
_TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
@@ -81,14 +81,14 @@ STACK_SIZE = 1 << STACK_SHIFT
* R15 - kernel stack pointer
*/
- .macro STORE_TIMER lc_offset
+ .macro STORE_TIMER lc_offset
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
stpt \lc_offset
#endif
.endm
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
- .macro UPDATE_VTIME lc_from,lc_to,lc_sum
+ .macro UPDATE_VTIME lc_from,lc_to,lc_sum
lm %r10,%r11,\lc_from
sl %r10,\lc_to
sl %r11,\lc_to+4
@@ -147,7 +147,7 @@ STACK_SIZE = 1 << STACK_SHIFT
2:
.endm
- .macro CREATE_STACK_FRAME psworg,savearea
+ .macro CREATE_STACK_FRAME psworg,savearea
s %r15,BASED(.Lc_spsize) # make room for registers & psw
mvc SP_PSW(8,%r15),0(%r12) # move user PSW to stack
la %r12,\psworg
@@ -160,7 +160,7 @@ STACK_SIZE = 1 << STACK_SHIFT
st %r12,__SF_BACKCHAIN(%r15) # clear back chain
.endm
- .macro RESTORE_ALL psworg,sync
+ .macro RESTORE_ALL psworg,sync
mvc \psworg(8),SP_PSW(%r15) # move user PSW to lowcore
.if !\sync
ni \psworg+1,0xfd # clear wait state bit
@@ -177,16 +177,16 @@ STACK_SIZE = 1 << STACK_SHIFT
* Returns:
* gpr2 = prev
*/
- .globl __switch_to
+ .globl __switch_to
__switch_to:
- basr %r1,0
+ basr %r1,0
__switch_to_base:
tm __THREAD_per(%r3),0xe8 # new process is using per ?
bz __switch_to_noper-__switch_to_base(%r1) # if not we're fine
- stctl %c9,%c11,__SF_EMPTY(%r15) # We are using per stuff
- clc __THREAD_per(12,%r3),__SF_EMPTY(%r15)
- be __switch_to_noper-__switch_to_base(%r1) # we got away w/o bashing TLB's
- lctl %c9,%c11,__THREAD_per(%r3) # Nope we didn't
+ stctl %c9,%c11,__SF_EMPTY(%r15) # We are using per stuff
+ clc __THREAD_per(12,%r3),__SF_EMPTY(%r15)
+ be __switch_to_noper-__switch_to_base(%r1) # we got away w/o bashing TLB's
+ lctl %c9,%c11,__THREAD_per(%r3) # Nope we didn't
__switch_to_noper:
l %r4,__THREAD_info(%r2) # get thread_info of prev
tm __TI_flags+3(%r4),_TIF_MCCK_PENDING # machine check pending?
@@ -195,13 +195,13 @@ __switch_to_noper:
l %r4,__THREAD_info(%r3) # get thread_info of next
oi __TI_flags+3(%r4),_TIF_MCCK_PENDING # set it in next
__switch_to_no_mcck:
- stm %r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task
+ stm %r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task
st %r15,__THREAD_ksp(%r2) # store kernel stack to prev->tss.ksp
l %r15,__THREAD_ksp(%r3) # load kernel stack from next->tss.ksp
lm %r6,%r15,__SF_GPRS(%r15)# load __switch_to registers of next task
st %r3,__LC_CURRENT # __LC_CURRENT = current task struct
lctl %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4
- l %r3,__THREAD_info(%r3) # load thread_info from task struct
+ l %r3,__THREAD_info(%r3) # load thread_info from task struct
st %r3,__LC_THREAD_INFO
ahi %r3,STACK_SIZE
st %r3,__LC_KERNEL_STACK # __LC_KERNEL_STACK = new kernel stack
@@ -213,7 +213,7 @@ __critical_start:
* are executed with interrupts enabled.
*/
- .globl system_call
+ .globl system_call
system_call:
STORE_TIMER __LC_SYNC_ENTER_TIMER
sysc_saveall:
@@ -233,24 +233,24 @@ sysc_update:
#endif
sysc_do_svc:
l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
- sla %r7,2 # *4 and test for svc 0
- bnz BASED(sysc_nr_ok) # svc number > 0
+ sla %r7,2 # *4 and test for svc 0
+ bnz BASED(sysc_nr_ok) # svc number > 0
# svc 0: system call number in %r1
cl %r1,BASED(.Lnr_syscalls)
bnl BASED(sysc_nr_ok)
- lr %r7,%r1 # copy svc number to %r7
- sla %r7,2 # *4
+ lr %r7,%r1 # copy svc number to %r7
+ sla %r7,2 # *4
sysc_nr_ok:
mvc SP_ARGS(4,%r15),SP_R7(%r15)
sysc_do_restart:
l %r8,BASED(.Lsysc_table)
tm __TI_flags+3(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
l %r8,0(%r7,%r8) # get system call addr.
- bnz BASED(sysc_tracesys)
- basr %r14,%r8 # call sys_xxxx
- st %r2,SP_R2(%r15) # store return value (change R2 on stack)
- # ATTENTION: check sys_execve_glue before
- # changing anything here !!
+ bnz BASED(sysc_tracesys)
+ basr %r14,%r8 # call sys_xxxx
+ st %r2,SP_R2(%r15) # store return value (change R2 on stack)
+ # ATTENTION: check sys_execve_glue before
+ # changing anything here !!
sysc_return:
tm SP_PSW+1(%r15),0x01 # returning to user ?
@@ -258,14 +258,14 @@ sysc_return:
tm __TI_flags+3(%r9),_TIF_WORK_SVC
bnz BASED(sysc_work) # there is work to do (signals etc.)
sysc_leave:
- RESTORE_ALL __LC_RETURN_PSW,1
+ RESTORE_ALL __LC_RETURN_PSW,1
#
# recheck if there is more work to do
#
sysc_work_loop:
tm __TI_flags+3(%r9),_TIF_WORK_SVC
- bz BASED(sysc_leave) # there is no work to do
+ bz BASED(sysc_leave) # there is no work to do
#
# One of the work bits is on. Find out which one.
#
@@ -284,11 +284,11 @@ sysc_work:
#
# _TIF_NEED_RESCHED is set, call schedule
-#
-sysc_reschedule:
- l %r1,BASED(.Lschedule)
- la %r14,BASED(sysc_work_loop)
- br %r1 # call scheduler
+#
+sysc_reschedule:
+ l %r1,BASED(.Lschedule)
+ la %r14,BASED(sysc_work_loop)
+ br %r1 # call scheduler
#
# _TIF_MCCK_PENDING is set, call handler
@@ -301,11 +301,11 @@ sysc_mcck_pending:
#
# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
#
-sysc_sigpending:
+sysc_sigpending:
ni __TI_flags+3(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
- la %r2,SP_PTREGS(%r15) # load pt_regs
- l %r1,BASED(.Ldo_signal)
- basr %r14,%r1 # call do_signal
+ la %r2,SP_PTREGS(%r15) # load pt_regs
+ l %r1,BASED(.Ldo_signal)
+ basr %r14,%r1 # call do_signal
tm __TI_flags+3(%r9),_TIF_RESTART_SVC
bo BASED(sysc_restart)
tm __TI_flags+3(%r9),_TIF_SINGLE_STEP
@@ -317,11 +317,11 @@ sysc_sigpending:
#
sysc_restart:
ni __TI_flags+3(%r9),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC
- l %r7,SP_R2(%r15) # load new svc number
+ l %r7,SP_R2(%r15) # load new svc number
sla %r7,2
mvc SP_R2(4,%r15),SP_ORIG_R2(%r15) # restore first argument
- lm %r2,%r6,SP_R2(%r15) # load svc arguments
- b BASED(sysc_do_restart) # restart svc
+ lm %r2,%r6,SP_R2(%r15) # load svc arguments
+ b BASED(sysc_do_restart) # restart svc
#
# _TIF_SINGLE_STEP is set, call do_single_step
@@ -338,8 +338,8 @@ sysc_singlestep:
# call trace before and after sys_call
#
sysc_tracesys:
- l %r1,BASED(.Ltrace)
- la %r2,SP_PTREGS(%r15) # load pt_regs
+ l %r1,BASED(.Ltrace)
+ la %r2,SP_PTREGS(%r15) # load pt_regs
la %r3,0
srl %r7,2
st %r7,SP_R2(%r15)
@@ -347,19 +347,19 @@ sysc_tracesys:
clc SP_R2(4,%r15),BASED(.Lnr_syscalls)
bnl BASED(sysc_tracenogo)
l %r8,BASED(.Lsysc_table)
- l %r7,SP_R2(%r15) # strace might have changed the
- sll %r7,2 # system call
+ l %r7,SP_R2(%r15) # strace might have changed the
+ sll %r7,2 # system call
l %r8,0(%r7,%r8)
sysc_tracego:
lm %r3,%r6,SP_R3(%r15)
l %r2,SP_ORIG_R2(%r15)
- basr %r14,%r8 # call sys_xxx
- st %r2,SP_R2(%r15) # store return value
+ basr %r14,%r8 # call sys_xxx
+ st %r2,SP_R2(%r15) # store return value
sysc_tracenogo:
tm __TI_flags+3(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
- bz BASED(sysc_return)
+ bz BASED(sysc_return)
l %r1,BASED(.Ltrace)
- la %r2,SP_PTREGS(%r15) # load pt_regs
+ la %r2,SP_PTREGS(%r15) # load pt_regs
la %r3,1
la %r14,BASED(sysc_return)
br %r1
@@ -367,17 +367,17 @@ sysc_tracenogo:
#
# a new process exits the kernel with ret_from_fork
#
- .globl ret_from_fork
+ .globl ret_from_fork
ret_from_fork:
l %r13,__LC_SVC_NEW_PSW+4
l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
tm SP_PSW+1(%r15),0x01 # forking a kernel thread ?
bo BASED(0f)
st %r15,SP_R15(%r15) # store stack pointer for new kthread
-0: l %r1,BASED(.Lschedtail)
- basr %r14,%r1
+0: l %r1,BASED(.Lschedtail)
+ basr %r14,%r1
TRACE_IRQS_ON
- stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
+ stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
b BASED(sysc_return)
#
@@ -386,52 +386,51 @@ ret_from_fork:
# but are called with different parameter.
# return-address is set up above
#
-sys_clone_glue:
- la %r2,SP_PTREGS(%r15) # load pt_regs
- l %r1,BASED(.Lclone)
- br %r1 # branch to sys_clone
-
-sys_fork_glue:
- la %r2,SP_PTREGS(%r15) # load pt_regs
- l %r1,BASED(.Lfork)
- br %r1 # branch to sys_fork
-
-sys_vfork_glue:
- la %r2,SP_PTREGS(%r15) # load pt_regs
- l %r1,BASED(.Lvfork)
- br %r1 # branch to sys_vfork
-
-sys_execve_glue:
- la %r2,SP_PTREGS(%r15) # load pt_regs
- l %r1,BASED(.Lexecve)
- lr %r12,%r14 # save return address
- basr %r14,%r1 # call sys_execve
- ltr %r2,%r2 # check if execve failed
- bnz 0(%r12) # it did fail -> store result in gpr2
- b 4(%r12) # SKIP ST 2,SP_R2(15) after BASR 14,8
- # in system_call/sysc_tracesys
-
-sys_sigreturn_glue:
- la %r2,SP_PTREGS(%r15) # load pt_regs as parameter
- l %r1,BASED(.Lsigreturn)
- br %r1 # branch to sys_sigreturn
-
-sys_rt_sigreturn_glue:
- la %r2,SP_PTREGS(%r15) # load pt_regs as parameter
- l %r1,BASED(.Lrt_sigreturn)
- br %r1 # branch to sys_sigreturn
+sys_clone_glue:
+ la %r2,SP_PTREGS(%r15) # load pt_regs
+ l %r1,BASED(.Lclone)
+ br %r1 # branch to sys_clone
-sys_sigaltstack_glue:
- la %r4,SP_PTREGS(%r15) # load pt_regs as parameter
- l %r1,BASED(.Lsigaltstack)
- br %r1 # branch to sys_sigreturn
+sys_fork_glue:
+ la %r2,SP_PTREGS(%r15) # load pt_regs
+ l %r1,BASED(.Lfork)
+ br %r1 # branch to sys_fork
+sys_vfork_glue:
+ la %r2,SP_PTREGS(%r15) # load pt_regs
+ l %r1,BASED(.Lvfork)
+ br %r1 # branch to sys_vfork
+
+sys_execve_glue:
+ la %r2,SP_PTREGS(%r15) # load pt_regs
+ l %r1,BASED(.Lexecve)
+ lr %r12,%r14 # save return address
+ basr %r14,%r1 # call sys_execve
+ ltr %r2,%r2 # check if execve failed
+ bnz 0(%r12) # it did fail -> store result in gpr2
+ b 4(%r12) # SKIP ST 2,SP_R2(15) after BASR 14,8
+ # in system_call/sysc_tracesys
+
+sys_sigreturn_glue:
+ la %r2,SP_PTREGS(%r15) # load pt_regs as parameter
+ l %r1,BASED(.Lsigreturn)
+ br %r1 # branch to sys_sigreturn
+
+sys_rt_sigreturn_glue:
+ la %r2,SP_PTREGS(%r15) # load pt_regs as parameter
+ l %r1,BASED(.Lrt_sigreturn)
+ br %r1 # branch to sys_sigreturn
+
+sys_sigaltstack_glue:
+ la %r4,SP_PTREGS(%r15) # load pt_regs as parameter
+ l %r1,BASED(.Lsigaltstack)
+ br %r1 # branch to sys_sigreturn
/*
* Program check handler routine
*/
- .globl pgm_check_handler
+ .globl pgm_check_handler
pgm_check_handler:
/*
* First we need to check for a special case:
@@ -448,8 +447,8 @@ pgm_check_handler:
*/
STORE_TIMER __LC_SYNC_ENTER_TIMER
SAVE_ALL_BASE __LC_SAVE_AREA
- tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
- bnz BASED(pgm_per) # got per exception -> special case
+ tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
+ bnz BASED(pgm_per) # got per exception -> special case
SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA
CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
@@ -461,29 +460,29 @@ pgm_check_handler:
pgm_no_vtime:
#endif
l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
- l %r3,__LC_PGM_ILC # load program interruption code
+ l %r3,__LC_PGM_ILC # load program interruption code
la %r8,0x7f
nr %r8,%r3
pgm_do_call:
- l %r7,BASED(.Ljump_table)
- sll %r8,2
- l %r7,0(%r8,%r7) # load address of handler routine
- la %r2,SP_PTREGS(%r15) # address of register-save area
- la %r14,BASED(sysc_return)
- br %r7 # branch to interrupt-handler
+ l %r7,BASED(.Ljump_table)
+ sll %r8,2
+ l %r7,0(%r8,%r7) # load address of handler routine
+ la %r2,SP_PTREGS(%r15) # address of register-save area
+ la %r14,BASED(sysc_return)
+ br %r7 # branch to interrupt-handler
#
# handle per exception
#
pgm_per:
- tm __LC_PGM_OLD_PSW,0x40 # test if per event recording is on
- bnz BASED(pgm_per_std) # ok, normal per event from user space
+ tm __LC_PGM_OLD_PSW,0x40 # test if per event recording is on
+ bnz BASED(pgm_per_std) # ok, normal per event from user space
# ok its one of the special cases, now we need to find out which one
- clc __LC_PGM_OLD_PSW(8),__LC_SVC_NEW_PSW
- be BASED(pgm_svcper)
+ clc __LC_PGM_OLD_PSW(8),__LC_SVC_NEW_PSW
+ be BASED(pgm_svcper)
# no interesting special case, ignore PER event
- lm %r12,%r15,__LC_SAVE_AREA
- lpsw 0x28
+ lm %r12,%r15,__LC_SAVE_AREA
+ lpsw 0x28
#
# Normal per exception
@@ -505,10 +504,12 @@ pgm_no_vtime2:
mvc __THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS
mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID
oi __TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
- l %r3,__LC_PGM_ILC # load program interruption code
+ tm SP_PSW+1(%r15),0x01 # kernel per event ?
+ bz BASED(kernel_per)
+ l %r3,__LC_PGM_ILC # load program interruption code
la %r8,0x7f
- nr %r8,%r3 # clear per-event-bit and ilc
- be BASED(sysc_return) # only per or per+check ?
+ nr %r8,%r3 # clear per-event-bit and ilc
+ be BASED(sysc_return) # only per or per+check ?
b BASED(pgm_do_call)
#
@@ -536,11 +537,21 @@ pgm_no_vtime3:
stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
b BASED(sysc_do_svc)
+#
+# per was called from kernel, must be kprobes
+#
+kernel_per:
+ mvi SP_TRAP+1(%r15),0x28 # set trap indication to pgm check
+ la %r2,SP_PTREGS(%r15) # address of register-save area
+ l %r1,BASED(.Lhandle_per) # load adr. of per handler
+ la %r14,BASED(sysc_leave) # load adr. of system return
+ br %r1 # branch to do_single_step
+
/*
* IO interrupt handler routine
*/
- .globl io_int_handler
+ .globl io_int_handler
io_int_handler:
STORE_TIMER __LC_ASYNC_ENTER_TIMER
stck __LC_INT_CLOCK
@@ -557,42 +568,42 @@ io_no_vtime:
#endif
l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
TRACE_IRQS_OFF
- l %r1,BASED(.Ldo_IRQ) # load address of do_IRQ
- la %r2,SP_PTREGS(%r15) # address of register-save area
- basr %r14,%r1 # branch to standard irq handler
+ l %r1,BASED(.Ldo_IRQ) # load address of do_IRQ
+ la %r2,SP_PTREGS(%r15) # address of register-save area
+ basr %r14,%r1 # branch to standard irq handler
TRACE_IRQS_ON
io_return:
- tm SP_PSW+1(%r15),0x01 # returning to user ?
+ tm SP_PSW+1(%r15),0x01 # returning to user ?
#ifdef CONFIG_PREEMPT
- bno BASED(io_preempt) # no -> check for preemptive scheduling
+ bno BASED(io_preempt) # no -> check for preemptive scheduling
#else
- bno BASED(io_leave) # no-> skip resched & signal
+ bno BASED(io_leave) # no-> skip resched & signal
#endif
tm __TI_flags+3(%r9),_TIF_WORK_INT
- bnz BASED(io_work) # there is work to do (signals etc.)
+ bnz BASED(io_work) # there is work to do (signals etc.)
io_leave:
- RESTORE_ALL __LC_RETURN_PSW,0
+ RESTORE_ALL __LC_RETURN_PSW,0
io_done:
#ifdef CONFIG_PREEMPT
io_preempt:
icm %r0,15,__TI_precount(%r9)
- bnz BASED(io_leave)
+ bnz BASED(io_leave)
l %r1,SP_R15(%r15)
s %r1,BASED(.Lc_spsize)
mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
- xc __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
+ xc __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
lr %r15,%r1
io_resume_loop:
tm __TI_flags+3(%r9),_TIF_NEED_RESCHED
bno BASED(io_leave)
- mvc __TI_precount(4,%r9),BASED(.Lc_pactive)
- stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
- l %r1,BASED(.Lschedule)
+ mvc __TI_precount(4,%r9),BASED(.Lc_pactive)
+ stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
+ l %r1,BASED(.Lschedule)
basr %r14,%r1 # call schedule
- stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
- xc __TI_precount(4,%r9),__TI_precount(%r9)
+ stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
+ xc __TI_precount(4,%r9),__TI_precount(%r9)
b BASED(io_resume_loop)
#endif
@@ -603,16 +614,16 @@ io_work:
l %r1,__LC_KERNEL_STACK
s %r1,BASED(.Lc_spsize)
mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
- xc __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
+ xc __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
lr %r15,%r1
#
# One of the work bits is on. Find out which one.
# Checked are: _TIF_SIGPENDING, _TIF_RESTORE_SIGMASK, _TIF_NEED_RESCHED
-# and _TIF_MCCK_PENDING
+# and _TIF_MCCK_PENDING
#
io_work_loop:
tm __TI_flags+3(%r9),_TIF_MCCK_PENDING
- bo BASED(io_mcck_pending)
+ bo BASED(io_mcck_pending)
tm __TI_flags+3(%r9),_TIF_NEED_RESCHED
bo BASED(io_reschedule)
tm __TI_flags+3(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)
@@ -625,36 +636,36 @@ io_work_loop:
io_mcck_pending:
l %r1,BASED(.Ls390_handle_mcck)
la %r14,BASED(io_work_loop)
- br %r1 # TIF bit will be cleared by handler
+ br %r1 # TIF bit will be cleared by handler
#
# _TIF_NEED_RESCHED is set, call schedule
-#
-io_reschedule:
- l %r1,BASED(.Lschedule)
- stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
- basr %r14,%r1 # call scheduler
- stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
+#
+io_reschedule:
+ l %r1,BASED(.Lschedule)
+ stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
+ basr %r14,%r1 # call scheduler
+ stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
tm __TI_flags+3(%r9),_TIF_WORK_INT
- bz BASED(io_leave) # there is no work to do
+ bz BASED(io_leave) # there is no work to do
b BASED(io_work_loop)
#
# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
#
-io_sigpending:
- stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
- la %r2,SP_PTREGS(%r15) # load pt_regs
- l %r1,BASED(.Ldo_signal)
- basr %r14,%r1 # call do_signal
- stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
+io_sigpending:
+ stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
+ la %r2,SP_PTREGS(%r15) # load pt_regs
+ l %r1,BASED(.Ldo_signal)
+ basr %r14,%r1 # call do_signal
+ stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
b BASED(io_work_loop)
/*
* External interrupt handler routine
*/
- .globl ext_int_handler
+ .globl ext_int_handler
ext_int_handler:
STORE_TIMER __LC_ASYNC_ENTER_TIMER
stck __LC_INT_CLOCK
@@ -671,8 +682,8 @@ ext_no_vtime:
#endif
l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
TRACE_IRQS_OFF
- la %r2,SP_PTREGS(%r15) # address of register-save area
- lh %r3,__LC_EXT_INT_CODE # get interruption code
+ la %r2,SP_PTREGS(%r15) # address of register-save area
+ lh %r3,__LC_EXT_INT_CODE # get interruption code
l %r1,BASED(.Ldo_extint)
basr %r14,%r1
TRACE_IRQS_ON
@@ -684,13 +695,13 @@ __critical_end:
* Machine check handler routines
*/
- .globl mcck_int_handler
+ .globl mcck_int_handler
mcck_int_handler:
spt __LC_CPU_TIMER_SAVE_AREA # revalidate cpu timer
lm %r0,%r15,__LC_GPREGS_SAVE_AREA # revalidate gprs
SAVE_ALL_BASE __LC_SAVE_AREA+32
la %r12,__LC_MCK_OLD_PSW
- tm __LC_MCCK_CODE,0x80 # system damage?
+ tm __LC_MCCK_CODE,0x80 # system damage?
bo BASED(mcck_int_main) # yes -> rest of mcck code invalid
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
mvc __LC_SAVE_AREA+52(8),__LC_ASYNC_ENTER_TIMER
@@ -729,7 +740,7 @@ mcck_int_main:
l %r15,__LC_PANIC_STACK # load panic stack
0: CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+32
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
- tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid?
+ tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid?
bno BASED(mcck_no_vtime) # no -> skip cleanup critical
tm SP_PSW+1(%r15),0x01 # interrupting from user ?
bz BASED(mcck_no_vtime)
@@ -740,14 +751,14 @@ mcck_no_vtime:
#endif
l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
la %r2,SP_PTREGS(%r15) # load pt_regs
- l %r1,BASED(.Ls390_mcck)
- basr %r14,%r1 # call machine check handler
- tm SP_PSW+1(%r15),0x01 # returning to user ?
+ l %r1,BASED(.Ls390_mcck)
+ basr %r14,%r1 # call machine check handler
+ tm SP_PSW+1(%r15),0x01 # returning to user ?
bno BASED(mcck_return)
- l %r1,__LC_KERNEL_STACK # switch to kernel stack
+ l %r1,__LC_KERNEL_STACK # switch to kernel stack
s %r1,BASED(.Lc_spsize)
mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
- xc __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
+ xc __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
lr %r15,%r1
stosm __SF_EMPTY(%r15),0x04 # turn dat on
tm __TI_flags+3(%r9),_TIF_MCCK_PENDING
@@ -771,36 +782,36 @@ mcck_return:
lm %r0,%r15,SP_R0(%r15) # load gprs 0-15
lpsw __LC_RETURN_MCCK_PSW # back to caller
- RESTORE_ALL __LC_RETURN_MCCK_PSW,0
+ RESTORE_ALL __LC_RETURN_MCCK_PSW,0
#ifdef CONFIG_SMP
/*
* Restart interruption handler, kick starter for additional CPUs
*/
- .globl restart_int_handler
+ .globl restart_int_handler
restart_int_handler:
- l %r15,__LC_SAVE_AREA+60 # load ksp
- lctl %c0,%c15,__LC_CREGS_SAVE_AREA # get new ctl regs
- lam %a0,%a15,__LC_AREGS_SAVE_AREA
- lm %r6,%r15,__SF_GPRS(%r15) # load registers from clone
- stosm __SF_EMPTY(%r15),0x04 # now we can turn dat on
- basr %r14,0
- l %r14,restart_addr-.(%r14)
- br %r14 # branch to start_secondary
+ l %r15,__LC_SAVE_AREA+60 # load ksp
+ lctl %c0,%c15,__LC_CREGS_SAVE_AREA # get new ctl regs
+ lam %a0,%a15,__LC_AREGS_SAVE_AREA
+ lm %r6,%r15,__SF_GPRS(%r15) # load registers from clone
+ stosm __SF_EMPTY(%r15),0x04 # now we can turn dat on
+ basr %r14,0
+ l %r14,restart_addr-.(%r14)
+ br %r14 # branch to start_secondary
restart_addr:
- .long start_secondary
+ .long start_secondary
#else
/*
* If we do not run with SMP enabled, let the new CPU crash ...
*/
- .globl restart_int_handler
+ .globl restart_int_handler
restart_int_handler:
- basr %r1,0
+ basr %r1,0
restart_base:
- lpsw restart_crash-restart_base(%r1)
- .align 8
+ lpsw restart_crash-restart_base(%r1)
+ .align 8
restart_crash:
- .long 0x000a0000,0x00000000
+ .long 0x000a0000,0x00000000
restart_go:
#endif
@@ -822,11 +833,11 @@ stack_overflow:
be BASED(0f)
la %r1,__LC_SAVE_AREA+16
0: mvc SP_R12(16,%r15),0(%r1) # move %r12-%r15 to stack
- xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear back chain
+ xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear back chain
l %r1,BASED(1f) # branch to kernel_stack_overflow
- la %r2,SP_PTREGS(%r15) # load pt_regs
+ la %r2,SP_PTREGS(%r15) # load pt_regs
br %r1
-1: .long kernel_stack_overflow
+1: .long kernel_stack_overflow
#endif
cleanup_table_system_call:
@@ -928,10 +939,10 @@ cleanup_novtime:
cleanup_system_call_insn:
.long sysc_saveall + 0x80000000
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
- .long system_call + 0x80000000
- .long sysc_vtime + 0x80000000
- .long sysc_stime + 0x80000000
- .long sysc_update + 0x80000000
+ .long system_call + 0x80000000
+ .long sysc_vtime + 0x80000000
+ .long sysc_stime + 0x80000000
+ .long sysc_update + 0x80000000
#endif
cleanup_sysc_return:
@@ -997,57 +1008,57 @@ cleanup_io_leave_insn:
/*
* Integer constants
*/
- .align 4
-.Lc_spsize: .long SP_SIZE
-.Lc_overhead: .long STACK_FRAME_OVERHEAD
-.Lc_pactive: .long PREEMPT_ACTIVE
-.Lnr_syscalls: .long NR_syscalls
-.L0x018: .short 0x018
-.L0x020: .short 0x020
-.L0x028: .short 0x028
-.L0x030: .short 0x030
-.L0x038: .short 0x038
-.Lc_1: .long 1
+ .align 4
+.Lc_spsize: .long SP_SIZE
+.Lc_overhead: .long STACK_FRAME_OVERHEAD
+.Lc_pactive: .long PREEMPT_ACTIVE
+.Lnr_syscalls: .long NR_syscalls
+.L0x018: .short 0x018
+.L0x020: .short 0x020
+.L0x028: .short 0x028
+.L0x030: .short 0x030
+.L0x038: .short 0x038
+.Lc_1: .long 1
/*
* Symbol constants
*/
-.Ls390_mcck: .long s390_do_machine_check
+.Ls390_mcck: .long s390_do_machine_check
.Ls390_handle_mcck:
- .long s390_handle_mcck
-.Lmck_old_psw: .long __LC_MCK_OLD_PSW
-.Ldo_IRQ: .long do_IRQ
-.Ldo_extint: .long do_extint
-.Ldo_signal: .long do_signal
-.Lhandle_per: .long do_single_step
-.Ljump_table: .long pgm_check_table
-.Lschedule: .long schedule
-.Lclone: .long sys_clone
-.Lexecve: .long sys_execve
-.Lfork: .long sys_fork
-.Lrt_sigreturn:.long sys_rt_sigreturn
+ .long s390_handle_mcck
+.Lmck_old_psw: .long __LC_MCK_OLD_PSW
+.Ldo_IRQ: .long do_IRQ
+.Ldo_extint: .long do_extint
+.Ldo_signal: .long do_signal
+.Lhandle_per: .long do_single_step
+.Ljump_table: .long pgm_check_table
+.Lschedule: .long schedule
+.Lclone: .long sys_clone
+.Lexecve: .long sys_execve
+.Lfork: .long sys_fork
+.Lrt_sigreturn: .long sys_rt_sigreturn
.Lrt_sigsuspend:
- .long sys_rt_sigsuspend
-.Lsigreturn: .long sys_sigreturn
-.Lsigsuspend: .long sys_sigsuspend
-.Lsigaltstack: .long sys_sigaltstack
-.Ltrace: .long syscall_trace
-.Lvfork: .long sys_vfork
-.Lschedtail: .long schedule_tail
-.Lsysc_table: .long sys_call_table
+ .long sys_rt_sigsuspend
+.Lsigreturn: .long sys_sigreturn
+.Lsigsuspend: .long sys_sigsuspend
+.Lsigaltstack: .long sys_sigaltstack
+.Ltrace: .long syscall_trace
+.Lvfork: .long sys_vfork
+.Lschedtail: .long schedule_tail
+.Lsysc_table: .long sys_call_table
#ifdef CONFIG_TRACE_IRQFLAGS
-.Ltrace_irq_on:.long trace_hardirqs_on
+.Ltrace_irq_on: .long trace_hardirqs_on
.Ltrace_irq_off:
- .long trace_hardirqs_off
+ .long trace_hardirqs_off
#endif
.Lcritical_start:
- .long __critical_start + 0x80000000
+ .long __critical_start + 0x80000000
.Lcritical_end:
- .long __critical_end + 0x80000000
+ .long __critical_end + 0x80000000
.Lcleanup_critical:
- .long cleanup_critical
+ .long cleanup_critical
- .section .rodata, "a"
+ .section .rodata, "a"
#define SYSCALL(esa,esame,emu) .long esa
sys_call_table:
#include "syscalls.S"
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 56f5f613b868..0f758c329a5d 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -4,8 +4,8 @@
*
* Copyright (C) IBM Corp. 1999,2006
* 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),
+ * Hartmut Penner (hp@de.ibm.com),
+ * Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
* Heiko Carstens <heiko.carstens@de.ibm.com>
*/
@@ -24,29 +24,29 @@
* Stack layout for the system_call stack entry.
* The first few entries are identical to the user_regs_struct.
*/
-SP_PTREGS = STACK_FRAME_OVERHEAD
-SP_ARGS = STACK_FRAME_OVERHEAD + __PT_ARGS
-SP_PSW = STACK_FRAME_OVERHEAD + __PT_PSW
-SP_R0 = STACK_FRAME_OVERHEAD + __PT_GPRS
-SP_R1 = STACK_FRAME_OVERHEAD + __PT_GPRS + 8
-SP_R2 = STACK_FRAME_OVERHEAD + __PT_GPRS + 16
-SP_R3 = STACK_FRAME_OVERHEAD + __PT_GPRS + 24
-SP_R4 = STACK_FRAME_OVERHEAD + __PT_GPRS + 32
-SP_R5 = STACK_FRAME_OVERHEAD + __PT_GPRS + 40
-SP_R6 = STACK_FRAME_OVERHEAD + __PT_GPRS + 48
-SP_R7 = STACK_FRAME_OVERHEAD + __PT_GPRS + 56
-SP_R8 = STACK_FRAME_OVERHEAD + __PT_GPRS + 64
-SP_R9 = STACK_FRAME_OVERHEAD + __PT_GPRS + 72
-SP_R10 = STACK_FRAME_OVERHEAD + __PT_GPRS + 80
-SP_R11 = STACK_FRAME_OVERHEAD + __PT_GPRS + 88
-SP_R12 = STACK_FRAME_OVERHEAD + __PT_GPRS + 96
-SP_R13 = STACK_FRAME_OVERHEAD + __PT_GPRS + 104
-SP_R14 = STACK_FRAME_OVERHEAD + __PT_GPRS + 112
-SP_R15 = STACK_FRAME_OVERHEAD + __PT_GPRS + 120
-SP_ORIG_R2 = STACK_FRAME_OVERHEAD + __PT_ORIG_GPR2
-SP_ILC = STACK_FRAME_OVERHEAD + __PT_ILC
-SP_TRAP = STACK_FRAME_OVERHEAD + __PT_TRAP
-SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE
+SP_PTREGS = STACK_FRAME_OVERHEAD
+SP_ARGS = STACK_FRAME_OVERHEAD + __PT_ARGS
+SP_PSW = STACK_FRAME_OVERHEAD + __PT_PSW
+SP_R0 = STACK_FRAME_OVERHEAD + __PT_GPRS
+SP_R1 = STACK_FRAME_OVERHEAD + __PT_GPRS + 8
+SP_R2 = STACK_FRAME_OVERHEAD + __PT_GPRS + 16
+SP_R3 = STACK_FRAME_OVERHEAD + __PT_GPRS + 24
+SP_R4 = STACK_FRAME_OVERHEAD + __PT_GPRS + 32
+SP_R5 = STACK_FRAME_OVERHEAD + __PT_GPRS + 40
+SP_R6 = STACK_FRAME_OVERHEAD + __PT_GPRS + 48
+SP_R7 = STACK_FRAME_OVERHEAD + __PT_GPRS + 56
+SP_R8 = STACK_FRAME_OVERHEAD + __PT_GPRS + 64
+SP_R9 = STACK_FRAME_OVERHEAD + __PT_GPRS + 72
+SP_R10 = STACK_FRAME_OVERHEAD + __PT_GPRS + 80
+SP_R11 = STACK_FRAME_OVERHEAD + __PT_GPRS + 88
+SP_R12 = STACK_FRAME_OVERHEAD + __PT_GPRS + 96
+SP_R13 = STACK_FRAME_OVERHEAD + __PT_GPRS + 104
+SP_R14 = STACK_FRAME_OVERHEAD + __PT_GPRS + 112
+SP_R15 = STACK_FRAME_OVERHEAD + __PT_GPRS + 120
+SP_ORIG_R2 = STACK_FRAME_OVERHEAD + __PT_ORIG_GPR2
+SP_ILC = STACK_FRAME_OVERHEAD + __PT_ILC
+SP_TRAP = STACK_FRAME_OVERHEAD + __PT_TRAP
+SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE
STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
STACK_SIZE = 1 << STACK_SHIFT
@@ -71,14 +71,14 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
#define TRACE_IRQS_OFF
#endif
- .macro STORE_TIMER lc_offset
+ .macro STORE_TIMER lc_offset
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
stpt \lc_offset
#endif
.endm
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
- .macro UPDATE_VTIME lc_from,lc_to,lc_sum
+ .macro UPDATE_VTIME lc_from,lc_to,lc_sum
lg %r10,\lc_from
slg %r10,\lc_to
alg %r10,\lc_sum
@@ -94,7 +94,7 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
* R15 - kernel stack pointer
*/
- .macro SAVE_ALL_BASE savearea
+ .macro SAVE_ALL_BASE savearea
stmg %r12,%r15,\savearea
larl %r13,system_call
.endm
@@ -139,8 +139,8 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
.endm
.macro CREATE_STACK_FRAME psworg,savearea
- aghi %r15,-SP_SIZE # make room for registers & psw
- mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack
+ aghi %r15,-SP_SIZE # make room for registers & psw
+ mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack
la %r12,\psworg
stg %r2,SP_ORIG_R2(%r15) # store original content of gpr 2
icm %r12,12,__LC_SVC_ILC
@@ -149,7 +149,7 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
mvc SP_R12(32,%r15),\savearea # move %r12-%r15 to stack
la %r12,0
stg %r12,__SF_BACKCHAIN(%r15)
- .endm
+ .endm
.macro RESTORE_ALL psworg,sync
mvc \psworg(16),SP_PSW(%r15) # move user PSW to lowcore
@@ -168,29 +168,29 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
* Returns:
* gpr2 = prev
*/
- .globl __switch_to
+ .globl __switch_to
__switch_to:
tm __THREAD_per+4(%r3),0xe8 # is the new process using per ?
jz __switch_to_noper # if not we're fine
- stctg %c9,%c11,__SF_EMPTY(%r15)# We are using per stuff
- clc __THREAD_per(24,%r3),__SF_EMPTY(%r15)
- je __switch_to_noper # we got away without bashing TLB's
- lctlg %c9,%c11,__THREAD_per(%r3) # Nope we didn't
+ stctg %c9,%c11,__SF_EMPTY(%r15)# We are using per stuff
+ clc __THREAD_per(24,%r3),__SF_EMPTY(%r15)
+ je __switch_to_noper # we got away without bashing TLB's
+ lctlg %c9,%c11,__THREAD_per(%r3) # Nope we didn't
__switch_to_noper:
- lg %r4,__THREAD_info(%r2) # get thread_info of prev
+ lg %r4,__THREAD_info(%r2) # get thread_info of prev
tm __TI_flags+7(%r4),_TIF_MCCK_PENDING # machine check pending?
jz __switch_to_no_mcck
ni __TI_flags+7(%r4),255-_TIF_MCCK_PENDING # clear flag in prev
lg %r4,__THREAD_info(%r3) # get thread_info of next
oi __TI_flags+7(%r4),_TIF_MCCK_PENDING # set it in next
__switch_to_no_mcck:
- stmg %r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task
+ stmg %r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task
stg %r15,__THREAD_ksp(%r2) # store kernel stack to prev->tss.ksp
lg %r15,__THREAD_ksp(%r3) # load kernel stack from next->tss.ksp
- lmg %r6,%r15,__SF_GPRS(%r15)# load __switch_to registers of next task
+ lmg %r6,%r15,__SF_GPRS(%r15)# load __switch_to registers of next task
stg %r3,__LC_CURRENT # __LC_CURRENT = current task struct
lctl %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4
- lg %r3,__THREAD_info(%r3) # load thread_info from task struct
+ lg %r3,__THREAD_info(%r3) # load thread_info from task struct
stg %r3,__LC_THREAD_INFO
aghi %r3,STACK_SIZE
stg %r3,__LC_KERNEL_STACK # __LC_KERNEL_STACK = new kernel stack
@@ -202,14 +202,14 @@ __critical_start:
* are executed with interrupts enabled.
*/
- .globl system_call
+ .globl system_call
system_call:
STORE_TIMER __LC_SYNC_ENTER_TIMER
sysc_saveall:
SAVE_ALL_BASE __LC_SAVE_AREA
SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
- CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
- llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore
+ CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
+ llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
sysc_vtime:
tm SP_PSW+1(%r15),0x01 # interrupting from user ?
@@ -222,45 +222,45 @@ sysc_update:
#endif
sysc_do_svc:
lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct
- slag %r7,%r7,2 # *4 and test for svc 0
+ slag %r7,%r7,2 # *4 and test for svc 0
jnz sysc_nr_ok
# svc 0: system call number in %r1
cl %r1,BASED(.Lnr_syscalls)
jnl sysc_nr_ok
- lgfr %r7,%r1 # clear high word in r1
- slag %r7,%r7,2 # svc 0: system call number in %r1
+ lgfr %r7,%r1 # clear high word in r1
+ slag %r7,%r7,2 # svc 0: system call number in %r1
sysc_nr_ok:
mvc SP_ARGS(8,%r15),SP_R7(%r15)
sysc_do_restart:
- larl %r10,sys_call_table
+ larl %r10,sys_call_table
#ifdef CONFIG_COMPAT
tm __TI_flags+5(%r9),(_TIF_31BIT>>16) # running in 31 bit mode ?
jno sysc_noemu
- larl %r10,sys_call_table_emu # use 31 bit emulation system calls
+ larl %r10,sys_call_table_emu # use 31 bit emulation system calls
sysc_noemu:
#endif
tm __TI_flags+7(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
- lgf %r8,0(%r7,%r10) # load address of system call routine
- jnz sysc_tracesys
- basr %r14,%r8 # call sys_xxxx
- stg %r2,SP_R2(%r15) # store return value (change R2 on stack)
- # ATTENTION: check sys_execve_glue before
- # changing anything here !!
+ lgf %r8,0(%r7,%r10) # load address of system call routine
+ jnz sysc_tracesys
+ basr %r14,%r8 # call sys_xxxx
+ stg %r2,SP_R2(%r15) # store return value (change R2 on stack)
+ # ATTENTION: check sys_execve_glue before
+ # changing anything here !!
sysc_return:
- tm SP_PSW+1(%r15),0x01 # returning to user ?
- jno sysc_leave
+ tm SP_PSW+1(%r15),0x01 # returning to user ?
+ jno sysc_leave
tm __TI_flags+7(%r9),_TIF_WORK_SVC
- jnz sysc_work # there is work to do (signals etc.)
+ jnz sysc_work # there is work to do (signals etc.)
sysc_leave:
- RESTORE_ALL __LC_RETURN_PSW,1
+ RESTORE_ALL __LC_RETURN_PSW,1
#
# recheck if there is more work to do
#
sysc_work_loop:
tm __TI_flags+7(%r9),_TIF_WORK_SVC
- jz sysc_leave # there is no work to do
+ jz sysc_leave # there is no work to do
#
# One of the work bits is on. Find out which one.
#
@@ -279,25 +279,25 @@ sysc_work:
#
# _TIF_NEED_RESCHED is set, call schedule
-#
-sysc_reschedule:
- larl %r14,sysc_work_loop
- jg schedule # return point is sysc_return
+#
+sysc_reschedule:
+ larl %r14,sysc_work_loop
+ jg schedule # return point is sysc_return
#
# _TIF_MCCK_PENDING is set, call handler
#
sysc_mcck_pending:
larl %r14,sysc_work_loop
- jg s390_handle_mcck # TIF bit will be cleared by handler
+ jg s390_handle_mcck # TIF bit will be cleared by handler
#
# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
#
-sysc_sigpending:
+sysc_sigpending:
ni __TI_flags+7(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
- la %r2,SP_PTREGS(%r15) # load pt_regs
- brasl %r14,do_signal # call do_signal
+ la %r2,SP_PTREGS(%r15) # load pt_regs
+ brasl %r14,do_signal # call do_signal
tm __TI_flags+7(%r9),_TIF_RESTART_SVC
jo sysc_restart
tm __TI_flags+7(%r9),_TIF_SINGLE_STEP
@@ -309,11 +309,11 @@ sysc_sigpending:
#
sysc_restart:
ni __TI_flags+7(%r9),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC
- lg %r7,SP_R2(%r15) # load new svc number
- slag %r7,%r7,2 # *4
+ lg %r7,SP_R2(%r15) # load new svc number
+ slag %r7,%r7,2 # *4
mvc SP_R2(8,%r15),SP_ORIG_R2(%r15) # restore first argument
- lmg %r2,%r6,SP_R2(%r15) # load svc arguments
- j sysc_do_restart # restart svc
+ lmg %r2,%r6,SP_R2(%r15) # load svc arguments
+ j sysc_do_restart # restart svc
#
# _TIF_SINGLE_STEP is set, call do_single_step
@@ -326,49 +326,48 @@ sysc_singlestep:
larl %r14,sysc_return # load adr. of system return
jg do_single_step # branch to do_sigtrap
-
#
# call syscall_trace before and after system call
# special linkage: %r12 contains the return address for trace_svc
#
sysc_tracesys:
- la %r2,SP_PTREGS(%r15) # load pt_regs
+ la %r2,SP_PTREGS(%r15) # load pt_regs
la %r3,0
srl %r7,2
- stg %r7,SP_R2(%r15)
- brasl %r14,syscall_trace
+ stg %r7,SP_R2(%r15)
+ brasl %r14,syscall_trace
lghi %r0,NR_syscalls
clg %r0,SP_R2(%r15)
jnh sysc_tracenogo
- lg %r7,SP_R2(%r15) # strace might have changed the
- sll %r7,2 # system call
+ lg %r7,SP_R2(%r15) # strace might have changed the
+ sll %r7,2 # system call
lgf %r8,0(%r7,%r10)
sysc_tracego:
- lmg %r3,%r6,SP_R3(%r15)
- lg %r2,SP_ORIG_R2(%r15)
- basr %r14,%r8 # call sys_xxx
- stg %r2,SP_R2(%r15) # store return value
+ lmg %r3,%r6,SP_R3(%r15)
+ lg %r2,SP_ORIG_R2(%r15)
+ basr %r14,%r8 # call sys_xxx
+ stg %r2,SP_R2(%r15) # store return value
sysc_tracenogo:
tm __TI_flags+7(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
- jz sysc_return
- la %r2,SP_PTREGS(%r15) # load pt_regs
+ jz sysc_return
+ la %r2,SP_PTREGS(%r15) # load pt_regs
la %r3,1
- larl %r14,sysc_return # return point is sysc_return
+ larl %r14,sysc_return # return point is sysc_return
jg syscall_trace
#
# a new process exits the kernel with ret_from_fork
#
- .globl ret_from_fork
+ .globl ret_from_fork
ret_from_fork:
lg %r13,__LC_SVC_NEW_PSW+8
lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct
tm SP_PSW+1(%r15),0x01 # forking a kernel thread ?
jo 0f
stg %r15,SP_R15(%r15) # store stack pointer for new kthread
-0: brasl %r14,schedule_tail
+0: brasl %r14,schedule_tail
TRACE_IRQS_ON
- stosm 24(%r15),0x03 # reenable interrupts
+ stosm 24(%r15),0x03 # reenable interrupts
j sysc_return
#
@@ -377,78 +376,78 @@ ret_from_fork:
# but are called with different parameter.
# return-address is set up above
#
-sys_clone_glue:
- la %r2,SP_PTREGS(%r15) # load pt_regs
- jg sys_clone # branch to sys_clone
+sys_clone_glue:
+ la %r2,SP_PTREGS(%r15) # load pt_regs
+ jg sys_clone # branch to sys_clone
#ifdef CONFIG_COMPAT
-sys32_clone_glue:
- la %r2,SP_PTREGS(%r15) # load pt_regs
- jg sys32_clone # branch to sys32_clone
+sys32_clone_glue:
+ la %r2,SP_PTREGS(%r15) # load pt_regs
+ jg sys32_clone # branch to sys32_clone
#endif
-sys_fork_glue:
- la %r2,SP_PTREGS(%r15) # load pt_regs
- jg sys_fork # branch to sys_fork
-
-sys_vfork_glue:
- la %r2,SP_PTREGS(%r15) # load pt_regs
- jg sys_vfork # branch to sys_vfork
-
-sys_execve_glue:
- la %r2,SP_PTREGS(%r15) # load pt_regs
- lgr %r12,%r14 # save return address
- brasl %r14,sys_execve # call sys_execve
- ltgr %r2,%r2 # check if execve failed
- bnz 0(%r12) # it did fail -> store result in gpr2
- b 6(%r12) # SKIP STG 2,SP_R2(15) in
- # system_call/sysc_tracesys
+sys_fork_glue:
+ la %r2,SP_PTREGS(%r15) # load pt_regs
+ jg sys_fork # branch to sys_fork
+
+sys_vfork_glue:
+ la %r2,SP_PTREGS(%r15) # load pt_regs
+ jg sys_vfork # branch to sys_vfork
+
+sys_execve_glue:
+ la %r2,SP_PTREGS(%r15) # load pt_regs
+ lgr %r12,%r14 # save return address
+ brasl %r14,sys_execve # call sys_execve
+ ltgr %r2,%r2 # check if execve failed
+ bnz 0(%r12) # it did fail -> store result in gpr2
+ b 6(%r12) # SKIP STG 2,SP_R2(15) in
+ # system_call/sysc_tracesys
#ifdef CONFIG_COMPAT
-sys32_execve_glue:
- la %r2,SP_PTREGS(%r15) # load pt_regs
- lgr %r12,%r14 # save return address
- brasl %r14,sys32_execve # call sys32_execve
- ltgr %r2,%r2 # check if execve failed
- bnz 0(%r12) # it did fail -> store result in gpr2
- b 6(%r12) # SKIP STG 2,SP_R2(15) in
- # system_call/sysc_tracesys
+sys32_execve_glue:
+ la %r2,SP_PTREGS(%r15) # load pt_regs
+ lgr %r12,%r14 # save return address
+ brasl %r14,sys32_execve # call sys32_execve
+ ltgr %r2,%r2 # check if execve failed
+ bnz 0(%r12) # it did fail -> store result in gpr2
+ b 6(%r12) # SKIP STG 2,SP_R2(15) in
+ # system_call/sysc_tracesys
#endif
-sys_sigreturn_glue:
- la %r2,SP_PTREGS(%r15) # load pt_regs as parameter
- jg sys_sigreturn # branch to sys_sigreturn
+sys_sigreturn_glue:
+ la %r2,SP_PTREGS(%r15) # load pt_regs as parameter
+ jg sys_sigreturn # branch to sys_sigreturn
#ifdef CONFIG_COMPAT
-sys32_sigreturn_glue:
- la %r2,SP_PTREGS(%r15) # load pt_regs as parameter
- jg sys32_sigreturn # branch to sys32_sigreturn
+sys32_sigreturn_glue:
+ la %r2,SP_PTREGS(%r15) # load pt_regs as parameter
+ jg sys32_sigreturn # branch to sys32_sigreturn
#endif
-sys_rt_sigreturn_glue:
- la %r2,SP_PTREGS(%r15) # load pt_regs as parameter
- jg sys_rt_sigreturn # branch to sys_sigreturn
+sys_rt_sigreturn_glue:
+ la %r2,SP_PTREGS(%r15) # load pt_regs as parameter
+ jg sys_rt_sigreturn # branch to sys_sigreturn
#ifdef CONFIG_COMPAT
-sys32_rt_sigreturn_glue:
- la %r2,SP_PTREGS(%r15) # load pt_regs as parameter
- jg sys32_rt_sigreturn # branch to sys32_sigreturn
+sys32_rt_sigreturn_glue:
+ la %r2,SP_PTREGS(%r15) # load pt_regs as parameter
+ jg sys32_rt_sigreturn # branch to sys32_sigreturn
#endif
sys_sigaltstack_glue:
- la %r4,SP_PTREGS(%r15) # load pt_regs as parameter
- jg sys_sigaltstack # branch to sys_sigreturn
+ la %r4,SP_PTREGS(%r15) # load pt_regs as parameter
+ jg sys_sigaltstack # branch to sys_sigreturn
#ifdef CONFIG_COMPAT
sys32_sigaltstack_glue:
- la %r4,SP_PTREGS(%r15) # load pt_regs as parameter
- jg sys32_sigaltstack_wrapper # branch to sys_sigreturn
+ la %r4,SP_PTREGS(%r15) # load pt_regs as parameter
+ jg sys32_sigaltstack_wrapper # branch to sys_sigreturn
#endif
/*
* Program check handler routine
*/
- .globl pgm_check_handler
+ .globl pgm_check_handler
pgm_check_handler:
/*
* First we need to check for a special case:
@@ -465,8 +464,8 @@ pgm_check_handler:
*/
STORE_TIMER __LC_SYNC_ENTER_TIMER
SAVE_ALL_BASE __LC_SAVE_AREA
- tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
- jnz pgm_per # got per exception -> special case
+ tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
+ jnz pgm_per # got per exception -> special case
SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA
CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
@@ -478,29 +477,29 @@ pgm_check_handler:
pgm_no_vtime:
#endif
lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct
- lgf %r3,__LC_PGM_ILC # load program interruption code
+ lgf %r3,__LC_PGM_ILC # load program interruption code
lghi %r8,0x7f
ngr %r8,%r3
pgm_do_call:
- sll %r8,3
- larl %r1,pgm_check_table
- lg %r1,0(%r8,%r1) # load address of handler routine
- la %r2,SP_PTREGS(%r15) # address of register-save area
+ sll %r8,3
+ larl %r1,pgm_check_table
+ lg %r1,0(%r8,%r1) # load address of handler routine
+ la %r2,SP_PTREGS(%r15) # address of register-save area
larl %r14,sysc_return
- br %r1 # branch to interrupt-handler
+ br %r1 # branch to interrupt-handler
#
# handle per exception
#
pgm_per:
- tm __LC_PGM_OLD_PSW,0x40 # test if per event recording is on
- jnz pgm_per_std # ok, normal per event from user space
+ tm __LC_PGM_OLD_PSW,0x40 # test if per event recording is on
+ jnz pgm_per_std # ok, normal per event from user space
# ok its one of the special cases, now we need to find out which one
- clc __LC_PGM_OLD_PSW(16),__LC_SVC_NEW_PSW
- je pgm_svcper
+ clc __LC_PGM_OLD_PSW(16),__LC_SVC_NEW_PSW
+ je pgm_svcper
# no interesting special case, ignore PER event
lmg %r12,%r15,__LC_SAVE_AREA
- lpswe __LC_PGM_OLD_PSW
+ lpswe __LC_PGM_OLD_PSW
#
# Normal per exception
@@ -518,13 +517,15 @@ pgm_no_vtime2:
#endif
lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct
lg %r1,__TI_task(%r9)
+ tm SP_PSW+1(%r15),0x01 # kernel per event ?
+ jz kernel_per
mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID
mvc __THREAD_per+__PER_address(8,%r1),__LC_PER_ADDRESS
mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID
oi __TI_flags+7(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
- lgf %r3,__LC_PGM_ILC # load program interruption code
+ lgf %r3,__LC_PGM_ILC # load program interruption code
lghi %r8,0x7f
- ngr %r8,%r3 # clear per-event-bit and ilc
+ ngr %r8,%r3 # clear per-event-bit and ilc
je sysc_return
j pgm_do_call
@@ -542,7 +543,7 @@ pgm_svcper:
mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
pgm_no_vtime3:
#endif
- llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore
+ llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore
lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct
lg %r1,__TI_task(%r9)
mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID
@@ -553,10 +554,20 @@ pgm_no_vtime3:
stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
j sysc_do_svc
+#
+# per was called from kernel, must be kprobes
+#
+kernel_per:
+ lhi %r0,__LC_PGM_OLD_PSW
+ sth %r0,SP_TRAP(%r15) # set trap indication to pgm check
+ la %r2,SP_PTREGS(%r15) # address of register-save area
+ larl %r14,sysc_leave # load adr. of system ret, no work
+ jg do_single_step # branch to do_single_step
+
/*
* IO interrupt handler routine
*/
- .globl io_int_handler
+ .globl io_int_handler
io_int_handler:
STORE_TIMER __LC_ASYNC_ENTER_TIMER
stck __LC_INT_CLOCK
@@ -573,42 +584,42 @@ io_no_vtime:
#endif
lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct
TRACE_IRQS_OFF
- la %r2,SP_PTREGS(%r15) # address of register-save area
- brasl %r14,do_IRQ # call standard irq handler
+ la %r2,SP_PTREGS(%r15) # address of register-save area
+ brasl %r14,do_IRQ # call standard irq handler
TRACE_IRQS_ON
io_return:
- tm SP_PSW+1(%r15),0x01 # returning to user ?
+ tm SP_PSW+1(%r15),0x01 # returning to user ?
#ifdef CONFIG_PREEMPT
- jno io_preempt # no -> check for preemptive scheduling
+ jno io_preempt # no -> check for preemptive scheduling
#else
- jno io_leave # no-> skip resched & signal
+ jno io_leave # no-> skip resched & signal
#endif
tm __TI_flags+7(%r9),_TIF_WORK_INT
- jnz io_work # there is work to do (signals etc.)
+ jnz io_work # there is work to do (signals etc.)
io_leave:
- RESTORE_ALL __LC_RETURN_PSW,0
+ RESTORE_ALL __LC_RETURN_PSW,0
io_done:
#ifdef CONFIG_PREEMPT
io_preempt:
- icm %r0,15,__TI_precount(%r9)
- jnz io_leave
+ icm %r0,15,__TI_precount(%r9)
+ jnz io_leave
# switch to kernel stack
lg %r1,SP_R15(%r15)
aghi %r1,-SP_SIZE
mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
- xc __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain
+ xc __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain
lgr %r15,%r1
io_resume_loop:
tm __TI_flags+7(%r9),_TIF_NEED_RESCHED
jno io_leave
- larl %r1,.Lc_pactive
- mvc __TI_precount(4,%r9),0(%r1)
- stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
- brasl %r14,schedule # call schedule
- stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
- xc __TI_precount(4,%r9),__TI_precount(%r9)
+ larl %r1,.Lc_pactive
+ mvc __TI_precount(4,%r9),0(%r1)
+ stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
+ brasl %r14,schedule # call schedule
+ stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
+ xc __TI_precount(4,%r9),__TI_precount(%r9)
j io_resume_loop
#endif
@@ -619,7 +630,7 @@ io_work:
lg %r1,__LC_KERNEL_STACK
aghi %r1,-SP_SIZE
mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
- xc __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain
+ xc __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain
lgr %r15,%r1
#
# One of the work bits is on. Find out which one.
@@ -644,11 +655,11 @@ io_mcck_pending:
#
# _TIF_NEED_RESCHED is set, call schedule
-#
-io_reschedule:
- stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
- brasl %r14,schedule # call scheduler
- stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
+#
+io_reschedule:
+ stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
+ brasl %r14,schedule # call scheduler
+ stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
tm __TI_flags+7(%r9),_TIF_WORK_INT
jz io_leave # there is no work to do
j io_work_loop
@@ -656,17 +667,17 @@ io_reschedule:
#
# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
#
-io_sigpending:
- stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
- la %r2,SP_PTREGS(%r15) # load pt_regs
+io_sigpending:
+ stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
+ la %r2,SP_PTREGS(%r15) # load pt_regs
brasl %r14,do_signal # call do_signal
- stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
+ stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
j io_work_loop
/*
* External interrupt handler routine
*/
- .globl ext_int_handler
+ .globl ext_int_handler
ext_int_handler:
STORE_TIMER __LC_ASYNC_ENTER_TIMER
stck __LC_INT_CLOCK
@@ -683,9 +694,9 @@ ext_no_vtime:
#endif
lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct
TRACE_IRQS_OFF
- la %r2,SP_PTREGS(%r15) # address of register-save area
- llgh %r3,__LC_EXT_INT_CODE # get interruption code
- brasl %r14,do_extint
+ la %r2,SP_PTREGS(%r15) # address of register-save area
+ llgh %r3,__LC_EXT_INT_CODE # get interruption code
+ brasl %r14,do_extint
TRACE_IRQS_ON
j io_return
@@ -694,14 +705,14 @@ __critical_end:
/*
* Machine check handler routines
*/
- .globl mcck_int_handler
+ .globl mcck_int_handler
mcck_int_handler:
la %r1,4095 # revalidate r1
spt __LC_CPU_TIMER_SAVE_AREA-4095(%r1) # revalidate cpu timer
- lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs
+ lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs
SAVE_ALL_BASE __LC_SAVE_AREA+64
la %r12,__LC_MCK_OLD_PSW
- tm __LC_MCCK_CODE,0x80 # system damage?
+ tm __LC_MCCK_CODE,0x80 # system damage?
jo mcck_int_main # yes -> rest of mcck code invalid
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
la %r14,4095
@@ -725,19 +736,19 @@ mcck_int_handler:
#endif
tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid?
jno mcck_int_main # no -> skip cleanup critical
- tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit
+ tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit
jnz mcck_int_main # from user -> load kernel stack
clc __LC_MCK_OLD_PSW+8(8),BASED(.Lcritical_end)
jhe mcck_int_main
- clc __LC_MCK_OLD_PSW+8(8),BASED(.Lcritical_start)
+ clc __LC_MCK_OLD_PSW+8(8),BASED(.Lcritical_start)
jl mcck_int_main
- brasl %r14,cleanup_critical
+ brasl %r14,cleanup_critical
mcck_int_main:
- lg %r14,__LC_PANIC_STACK # are we already on the panic stack?
+ lg %r14,__LC_PANIC_STACK # are we already on the panic stack?
slgr %r14,%r15
srag %r14,%r14,PAGE_SHIFT
jz 0f
- lg %r15,__LC_PANIC_STACK # load panic stack
+ lg %r15,__LC_PANIC_STACK # load panic stack
0: CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+64
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid?
@@ -752,7 +763,7 @@ mcck_no_vtime:
lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct
la %r2,SP_PTREGS(%r15) # load pt_regs
brasl %r14,s390_do_machine_check
- tm SP_PSW+1(%r15),0x01 # returning to user ?
+ tm SP_PSW+1(%r15),0x01 # returning to user ?
jno mcck_return
lg %r1,__LC_KERNEL_STACK # switch to kernel stack
aghi %r1,-SP_SIZE
@@ -782,28 +793,28 @@ mcck_return:
/*
* Restart interruption handler, kick starter for additional CPUs
*/
- .globl restart_int_handler
+ .globl restart_int_handler
restart_int_handler:
- lg %r15,__LC_SAVE_AREA+120 # load ksp
- lghi %r10,__LC_CREGS_SAVE_AREA
- lctlg %c0,%c15,0(%r10) # get new ctl regs
- lghi %r10,__LC_AREGS_SAVE_AREA
- lam %a0,%a15,0(%r10)
- lmg %r6,%r15,__SF_GPRS(%r15) # load registers from clone
- stosm __SF_EMPTY(%r15),0x04 # now we can turn dat on
- jg start_secondary
+ lg %r15,__LC_SAVE_AREA+120 # load ksp
+ lghi %r10,__LC_CREGS_SAVE_AREA
+ lctlg %c0,%c15,0(%r10) # get new ctl regs
+ lghi %r10,__LC_AREGS_SAVE_AREA
+ lam %a0,%a15,0(%r10)
+ lmg %r6,%r15,__SF_GPRS(%r15) # load registers from clone
+ stosm __SF_EMPTY(%r15),0x04 # now we can turn dat on
+ jg start_secondary
#else
/*
* If we do not run with SMP enabled, let the new CPU crash ...
*/
- .globl restart_int_handler
+ .globl restart_int_handler
restart_int_handler:
- basr %r1,0
+ basr %r1,0
restart_base:
- lpswe restart_crash-restart_base(%r1)
- .align 8
+ lpswe restart_crash-restart_base(%r1)
+ .align 8
restart_crash:
- .long 0x000a0000,0x00000000,0x00000000,0x00000000
+ .long 0x000a0000,0x00000000,0x00000000,0x00000000
restart_go:
#endif
@@ -815,7 +826,7 @@ restart_go:
*/
stack_overflow:
lg %r15,__LC_PANIC_STACK # change to panic stack
- aghi %r1,-SP_SIZE
+ aghi %r15,-SP_SIZE
mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack
stmg %r0,%r11,SP_R0(%r15) # store gprs %r0-%r11 to kernel stack
la %r1,__LC_SAVE_AREA
@@ -823,10 +834,10 @@ stack_overflow:
je 0f
chi %r12,__LC_PGM_OLD_PSW
je 0f
- la %r1,__LC_SAVE_AREA+16
-0: mvc SP_R12(32,%r15),0(%r1) # move %r12-%r15 to stack
- xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) # clear back chain
- la %r2,SP_PTREGS(%r15) # load pt_regs
+ la %r1,__LC_SAVE_AREA+32
+0: mvc SP_R12(32,%r15),0(%r1) # move %r12-%r15 to stack
+ xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) # clear back chain
+ la %r2,SP_PTREGS(%r15) # load pt_regs
jg kernel_stack_overflow
#endif
@@ -929,10 +940,10 @@ cleanup_novtime:
cleanup_system_call_insn:
.quad sysc_saveall
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
- .quad system_call
- .quad sysc_vtime
- .quad sysc_stime
- .quad sysc_update
+ .quad system_call
+ .quad sysc_vtime
+ .quad sysc_stime
+ .quad sysc_update
#endif
cleanup_sysc_return:
@@ -998,21 +1009,21 @@ cleanup_io_leave_insn:
/*
* Integer constants
*/
- .align 4
+ .align 4
.Lconst:
-.Lc_pactive: .long PREEMPT_ACTIVE
-.Lnr_syscalls: .long NR_syscalls
-.L0x0130: .short 0x130
-.L0x0140: .short 0x140
-.L0x0150: .short 0x150
-.L0x0160: .short 0x160
-.L0x0170: .short 0x170
+.Lc_pactive: .long PREEMPT_ACTIVE
+.Lnr_syscalls: .long NR_syscalls
+.L0x0130: .short 0x130
+.L0x0140: .short 0x140
+.L0x0150: .short 0x150
+.L0x0160: .short 0x160
+.L0x0170: .short 0x170
.Lcritical_start:
- .quad __critical_start
+ .quad __critical_start
.Lcritical_end:
- .quad __critical_end
+ .quad __critical_end
- .section .rodata, "a"
+ .section .rodata, "a"
#define SYSCALL(esa,esame,emu) .long esame
sys_call_table:
#include "syscalls.S"
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S
index adad8863ee2f..0cf59bb7a857 100644
--- a/arch/s390/kernel/head.S
+++ b/arch/s390/kernel/head.S
@@ -36,508 +36,451 @@
#endif
#ifndef CONFIG_IPL
- .org 0
- .long 0x00080000,0x80000000+startup # Just a restart PSW
+ .org 0
+ .long 0x00080000,0x80000000+startup # Just a restart PSW
#else
#ifdef CONFIG_IPL_TAPE
#define IPL_BS 1024
- .org 0
- .long 0x00080000,0x80000000+iplstart # The first 24 bytes are loaded
- .long 0x27000000,0x60000001 # by ipl to addresses 0-23.
- .long 0x02000000,0x20000000+IPL_BS # (a PSW and two CCWs).
- .long 0x00000000,0x00000000 # external old psw
- .long 0x00000000,0x00000000 # svc old psw
- .long 0x00000000,0x00000000 # program check old psw
- .long 0x00000000,0x00000000 # machine check old psw
- .long 0x00000000,0x00000000 # io old psw
- .long 0x00000000,0x00000000
- .long 0x00000000,0x00000000
- .long 0x00000000,0x00000000
- .long 0x000a0000,0x00000058 # external new psw
- .long 0x000a0000,0x00000060 # svc new psw
- .long 0x000a0000,0x00000068 # program check new psw
- .long 0x000a0000,0x00000070 # machine check new psw
- .long 0x00080000,0x80000000+.Lioint # io new psw
-
- .org 0x100
+ .org 0
+ .long 0x00080000,0x80000000+iplstart # The first 24 bytes are loaded
+ .long 0x27000000,0x60000001 # by ipl to addresses 0-23.
+ .long 0x02000000,0x20000000+IPL_BS # (a PSW and two CCWs).
+ .long 0x00000000,0x00000000 # external old psw
+ .long 0x00000000,0x00000000 # svc old psw
+ .long 0x00000000,0x00000000 # program check old psw
+ .long 0x00000000,0x00000000 # machine check old psw
+ .long 0x00000000,0x00000000 # io old psw
+ .long 0x00000000,0x00000000
+ .long 0x00000000,0x00000000
+ .long 0x00000000,0x00000000
+ .long 0x000a0000,0x00000058 # external new psw
+ .long 0x000a0000,0x00000060 # svc new psw
+ .long 0x000a0000,0x00000068 # program check new psw
+ .long 0x000a0000,0x00000070 # machine check new psw
+ .long 0x00080000,0x80000000+.Lioint # io new psw
+
+ .org 0x100
#
# subroutine for loading from tape
-# Paramters:
+# Paramters:
# R1 = device number
# R2 = load address
-.Lloader:
- st %r14,.Lldret
- la %r3,.Lorbread # r3 = address of orb
- la %r5,.Lirb # r5 = address of irb
- st %r2,.Lccwread+4 # initialize CCW data addresses
- lctl %c6,%c6,.Lcr6
- slr %r2,%r2
+.Lloader:
+ st %r14,.Lldret
+ la %r3,.Lorbread # r3 = address of orb
+ la %r5,.Lirb # r5 = address of irb
+ st %r2,.Lccwread+4 # initialize CCW data addresses
+ lctl %c6,%c6,.Lcr6
+ slr %r2,%r2
.Lldlp:
- la %r6,3 # 3 retries
+ la %r6,3 # 3 retries
.Lssch:
- ssch 0(%r3) # load chunk of IPL_BS bytes
- bnz .Llderr
+ ssch 0(%r3) # load chunk of IPL_BS bytes
+ bnz .Llderr
.Lw4end:
- bas %r14,.Lwait4io
- tm 8(%r5),0x82 # do we have a problem ?
- bnz .Lrecov
- slr %r7,%r7
- icm %r7,3,10(%r5) # get residual count
- lcr %r7,%r7
- la %r7,IPL_BS(%r7) # IPL_BS-residual=#bytes read
- ar %r2,%r7 # add to total size
- tm 8(%r5),0x01 # found a tape mark ?
- bnz .Ldone
- l %r0,.Lccwread+4 # update CCW data addresses
- ar %r0,%r7
- st %r0,.Lccwread+4
- b .Lldlp
+ bas %r14,.Lwait4io
+ tm 8(%r5),0x82 # do we have a problem ?
+ bnz .Lrecov
+ slr %r7,%r7
+ icm %r7,3,10(%r5) # get residual count
+ lcr %r7,%r7
+ la %r7,IPL_BS(%r7) # IPL_BS-residual=#bytes read
+ ar %r2,%r7 # add to total size
+ tm 8(%r5),0x01 # found a tape mark ?
+ bnz .Ldone
+ l %r0,.Lccwread+4 # update CCW data addresses
+ ar %r0,%r7
+ st %r0,.Lccwread+4
+ b .Lldlp
.Ldone:
- l %r14,.Lldret
- br %r14 # r2 contains the total size
+ l %r14,.Lldret
+ br %r14 # r2 contains the total size
.Lrecov:
- bas %r14,.Lsense # do the sensing
- bct %r6,.Lssch # dec. retry count & branch
- b .Llderr
+ bas %r14,.Lsense # do the sensing
+ bct %r6,.Lssch # dec. retry count & branch
+ b .Llderr
#
# Sense subroutine
#
.Lsense:
- st %r14,.Lsnsret
- la %r7,.Lorbsense
- ssch 0(%r7) # start sense command
- bnz .Llderr
- bas %r14,.Lwait4io
- l %r14,.Lsnsret
- tm 8(%r5),0x82 # do we have a problem ?
- bnz .Llderr
- br %r14
+ st %r14,.Lsnsret
+ la %r7,.Lorbsense
+ ssch 0(%r7) # start sense command
+ bnz .Llderr
+ bas %r14,.Lwait4io
+ l %r14,.Lsnsret
+ tm 8(%r5),0x82 # do we have a problem ?
+ bnz .Llderr
+ br %r14
#
# Wait for interrupt subroutine
#
.Lwait4io:
- lpsw .Lwaitpsw
+ lpsw .Lwaitpsw
.Lioint:
- c %r1,0xb8 # compare subchannel number
- bne .Lwait4io
- tsch 0(%r5)
- slr %r0,%r0
- tm 8(%r5),0x82 # do we have a problem ?
- bnz .Lwtexit
- tm 8(%r5),0x04 # got device end ?
- bz .Lwait4io
+ c %r1,0xb8 # compare subchannel number
+ bne .Lwait4io
+ tsch 0(%r5)
+ slr %r0,%r0
+ tm 8(%r5),0x82 # do we have a problem ?
+ bnz .Lwtexit
+ tm 8(%r5),0x04 # got device end ?
+ bz .Lwait4io
.Lwtexit:
- br %r14
+ br %r14
.Llderr:
- lpsw .Lcrash
+ lpsw .Lcrash
- .align 8
+ .align 8
.Lorbread:
- .long 0x00000000,0x0080ff00,.Lccwread
- .align 8
+ .long 0x00000000,0x0080ff00,.Lccwread
+ .align 8
.Lorbsense:
- .long 0x00000000,0x0080ff00,.Lccwsense
- .align 8
+ .long 0x00000000,0x0080ff00,.Lccwsense
+ .align 8
.Lccwread:
- .long 0x02200000+IPL_BS,0x00000000
+ .long 0x02200000+IPL_BS,0x00000000
.Lccwsense:
- .long 0x04200001,0x00000000
+ .long 0x04200001,0x00000000
.Lwaitpsw:
- .long 0x020a0000,0x80000000+.Lioint
+ .long 0x020a0000,0x80000000+.Lioint
-.Lirb: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-.Lcr6: .long 0xff000000
- .align 8
-.Lcrash:.long 0x000a0000,0x00000000
-.Lldret:.long 0
+.Lirb: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+.Lcr6: .long 0xff000000
+ .align 8
+.Lcrash:.long 0x000a0000,0x00000000
+.Lldret:.long 0
.Lsnsret: .long 0
-#endif /* CONFIG_IPL_TAPE */
+#endif /* CONFIG_IPL_TAPE */
#ifdef CONFIG_IPL_VM
-#define IPL_BS 0x730
- .org 0
- .long 0x00080000,0x80000000+iplstart # The first 24 bytes are loaded
- .long 0x02000018,0x60000050 # by ipl to addresses 0-23.
- .long 0x02000068,0x60000050 # (a PSW and two CCWs).
- .fill 80-24,1,0x40 # bytes 24-79 are discarded !!
- .long 0x020000f0,0x60000050 # The next 160 byte are loaded
- .long 0x02000140,0x60000050 # to addresses 0x18-0xb7
- .long 0x02000190,0x60000050 # They form the continuation
- .long 0x020001e0,0x60000050 # of the CCW program started
- .long 0x02000230,0x60000050 # by ipl and load the range
- .long 0x02000280,0x60000050 # 0x0f0-0x730 from the image
- .long 0x020002d0,0x60000050 # to the range 0x0f0-0x730
- .long 0x02000320,0x60000050 # in memory. At the end of
- .long 0x02000370,0x60000050 # the channel program the PSW
- .long 0x020003c0,0x60000050 # at location 0 is loaded.
- .long 0x02000410,0x60000050 # Initial processing starts
- .long 0x02000460,0x60000050 # at 0xf0 = iplstart.
- .long 0x020004b0,0x60000050
- .long 0x02000500,0x60000050
- .long 0x02000550,0x60000050
- .long 0x020005a0,0x60000050
- .long 0x020005f0,0x60000050
- .long 0x02000640,0x60000050
- .long 0x02000690,0x60000050
- .long 0x020006e0,0x20000050
-
- .org 0xf0
+#define IPL_BS 0x730
+ .org 0
+ .long 0x00080000,0x80000000+iplstart # The first 24 bytes are loaded
+ .long 0x02000018,0x60000050 # by ipl to addresses 0-23.
+ .long 0x02000068,0x60000050 # (a PSW and two CCWs).
+ .fill 80-24,1,0x40 # bytes 24-79 are discarded !!
+ .long 0x020000f0,0x60000050 # The next 160 byte are loaded
+ .long 0x02000140,0x60000050 # to addresses 0x18-0xb7
+ .long 0x02000190,0x60000050 # They form the continuation
+ .long 0x020001e0,0x60000050 # of the CCW program started
+ .long 0x02000230,0x60000050 # by ipl and load the range
+ .long 0x02000280,0x60000050 # 0x0f0-0x730 from the image
+ .long 0x020002d0,0x60000050 # to the range 0x0f0-0x730
+ .long 0x02000320,0x60000050 # in memory. At the end of
+ .long 0x02000370,0x60000050 # the channel program the PSW
+ .long 0x020003c0,0x60000050 # at location 0 is loaded.
+ .long 0x02000410,0x60000050 # Initial processing starts
+ .long 0x02000460,0x60000050 # at 0xf0 = iplstart.
+ .long 0x020004b0,0x60000050
+ .long 0x02000500,0x60000050
+ .long 0x02000550,0x60000050
+ .long 0x020005a0,0x60000050
+ .long 0x020005f0,0x60000050
+ .long 0x02000640,0x60000050
+ .long 0x02000690,0x60000050
+ .long 0x020006e0,0x20000050
+
+ .org 0xf0
#
# subroutine for loading cards from the reader
#
-.Lloader:
- la %r3,.Lorb # r2 = address of orb into r2
- la %r5,.Lirb # r4 = address of irb
- la %r6,.Lccws
- la %r7,20
+.Lloader:
+ la %r3,.Lorb # r2 = address of orb into r2
+ la %r5,.Lirb # r4 = address of irb
+ la %r6,.Lccws
+ la %r7,20
.Linit:
- st %r2,4(%r6) # initialize CCW data addresses
- la %r2,0x50(%r2)
- la %r6,8(%r6)
- bct 7,.Linit
+ st %r2,4(%r6) # initialize CCW data addresses
+ la %r2,0x50(%r2)
+ la %r6,8(%r6)
+ bct 7,.Linit
- lctl %c6,%c6,.Lcr6 # set IO subclass mask
- slr %r2,%r2
+ lctl %c6,%c6,.Lcr6 # set IO subclass mask
+ slr %r2,%r2
.Lldlp:
- ssch 0(%r3) # load chunk of 1600 bytes
- bnz .Llderr
+ ssch 0(%r3) # load chunk of 1600 bytes
+ bnz .Llderr
.Lwait4irq:
- mvc 0x78(8),.Lnewpsw # set up IO interrupt psw
- lpsw .Lwaitpsw
+ mvc 0x78(8),.Lnewpsw # set up IO interrupt psw
+ lpsw .Lwaitpsw
.Lioint:
- c %r1,0xb8 # compare subchannel number
- bne .Lwait4irq
- tsch 0(%r5)
-
- slr %r0,%r0
- ic %r0,8(%r5) # get device status
- chi %r0,8 # channel end ?
- be .Lcont
- chi %r0,12 # channel end + device end ?
- be .Lcont
-
- l %r0,4(%r5)
- s %r0,8(%r3) # r0/8 = number of ccws executed
- mhi %r0,10 # *10 = number of bytes in ccws
- lh %r3,10(%r5) # get residual count
- sr %r0,%r3 # #ccws*80-residual=#bytes read
- ar %r2,%r0
-
- br %r14 # r2 contains the total size
+ c %r1,0xb8 # compare subchannel number
+ bne .Lwait4irq
+ tsch 0(%r5)
+
+ slr %r0,%r0
+ ic %r0,8(%r5) # get device status
+ chi %r0,8 # channel end ?
+ be .Lcont
+ chi %r0,12 # channel end + device end ?
+ be .Lcont
+
+ l %r0,4(%r5)
+ s %r0,8(%r3) # r0/8 = number of ccws executed
+ mhi %r0,10 # *10 = number of bytes in ccws
+ lh %r3,10(%r5) # get residual count
+ sr %r0,%r3 # #ccws*80-residual=#bytes read
+ ar %r2,%r0
+
+ br %r14 # r2 contains the total size
.Lcont:
- ahi %r2,0x640 # add 0x640 to total size
- la %r6,.Lccws
- la %r7,20
+ ahi %r2,0x640 # add 0x640 to total size
+ la %r6,.Lccws
+ la %r7,20
.Lincr:
- l %r0,4(%r6) # update CCW data addresses
- ahi %r0,0x640
- st %r0,4(%r6)
- ahi %r6,8
- bct 7,.Lincr
+ l %r0,4(%r6) # update CCW data addresses
+ ahi %r0,0x640
+ st %r0,4(%r6)
+ ahi %r6,8
+ bct 7,.Lincr
- b .Lldlp
+ b .Lldlp
.Llderr:
- lpsw .Lcrash
-
- .align 8
-.Lorb: .long 0x00000000,0x0080ff00,.Lccws
-.Lirb: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-.Lcr6: .long 0xff000000
-.Lloadp:.long 0,0
- .align 8
-.Lcrash:.long 0x000a0000,0x00000000
+ lpsw .Lcrash
+
+ .align 8
+.Lorb: .long 0x00000000,0x0080ff00,.Lccws
+.Lirb: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+.Lcr6: .long 0xff000000
+.Lloadp:.long 0,0
+ .align 8
+.Lcrash:.long 0x000a0000,0x00000000
.Lnewpsw:
- .long 0x00080000,0x80000000+.Lioint
+ .long 0x00080000,0x80000000+.Lioint
.Lwaitpsw:
- .long 0x020a0000,0x80000000+.Lioint
+ .long 0x020a0000,0x80000000+.Lioint
- .align 8
-.Lccws: .rept 19
- .long 0x02600050,0x00000000
- .endr
- .long 0x02200050,0x00000000
-#endif /* CONFIG_IPL_VM */
+ .align 8
+.Lccws: .rept 19
+ .long 0x02600050,0x00000000
+ .endr
+ .long 0x02200050,0x00000000
+#endif /* CONFIG_IPL_VM */
iplstart:
- lh %r1,0xb8 # test if subchannel number
- bct %r1,.Lnoload # is valid
- l %r1,0xb8 # load ipl subchannel number
- la %r2,IPL_BS # load start address
- bas %r14,.Lloader # load rest of ipl image
- l %r12,.Lparm # pointer to parameter area
- st %r1,IPL_DEVICE+ARCH_OFFSET-PARMAREA(%r12) # save ipl device number
+ lh %r1,0xb8 # test if subchannel number
+ bct %r1,.Lnoload # is valid
+ l %r1,0xb8 # load ipl subchannel number
+ la %r2,IPL_BS # load start address
+ bas %r14,.Lloader # load rest of ipl image
+ l %r12,.Lparm # pointer to parameter area
+ st %r1,IPL_DEVICE+ARCH_OFFSET-PARMAREA(%r12) # save ipl device number
#
# load parameter file from ipl device
#
.Lagain1:
- l %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) # ramdisk loc. is temp
- bas %r14,.Lloader # load parameter file
- ltr %r2,%r2 # got anything ?
- bz .Lnopf
- chi %r2,895
- bnh .Lnotrunc
- la %r2,895
+ l %r2,.Linitrd # ramdisk loc. is temp
+ bas %r14,.Lloader # load parameter file
+ ltr %r2,%r2 # got anything ?
+ bz .Lnopf
+ chi %r2,895
+ bnh .Lnotrunc
+ la %r2,895
.Lnotrunc:
- l %r4,INITRD_START+ARCH_OFFSET-PARMAREA(%r12)
- clc 0(3,%r4),.L_hdr # if it is HDRx
- bz .Lagain1 # skip dataset header
- clc 0(3,%r4),.L_eof # if it is EOFx
- bz .Lagain1 # skip dateset trailer
- la %r5,0(%r4,%r2)
- lr %r3,%r2
+ l %r4,.Linitrd
+ clc 0(3,%r4),.L_hdr # if it is HDRx
+ bz .Lagain1 # skip dataset header
+ clc 0(3,%r4),.L_eof # if it is EOFx
+ bz .Lagain1 # skip dateset trailer
+ la %r5,0(%r4,%r2)
+ lr %r3,%r2
.Lidebc:
- tm 0(%r5),0x80 # high order bit set ?
- bo .Ldocv # yes -> convert from EBCDIC
- ahi %r5,-1
- bct %r3,.Lidebc
- b .Lnocv
+ tm 0(%r5),0x80 # high order bit set ?
+ bo .Ldocv # yes -> convert from EBCDIC
+ ahi %r5,-1
+ bct %r3,.Lidebc
+ b .Lnocv
.Ldocv:
- l %r3,.Lcvtab
- tr 0(256,%r4),0(%r3) # convert parameters to ascii
- tr 256(256,%r4),0(%r3)
- tr 512(256,%r4),0(%r3)
- tr 768(122,%r4),0(%r3)
-.Lnocv: la %r3,COMMAND_LINE-PARMAREA(%r12) # load adr. of command line
- mvc 0(256,%r3),0(%r4)
- mvc 256(256,%r3),256(%r4)
- mvc 512(256,%r3),512(%r4)
- mvc 768(122,%r3),768(%r4)
- slr %r0,%r0
- b .Lcntlp
+ l %r3,.Lcvtab
+ tr 0(256,%r4),0(%r3) # convert parameters to ascii
+ tr 256(256,%r4),0(%r3)
+ tr 512(256,%r4),0(%r3)
+ tr 768(122,%r4),0(%r3)
+.Lnocv: la %r3,COMMAND_LINE-PARMAREA(%r12) # load adr. of command line
+ mvc 0(256,%r3),0(%r4)
+ mvc 256(256,%r3),256(%r4)
+ mvc 512(256,%r3),512(%r4)
+ mvc 768(122,%r3),768(%r4)
+ slr %r0,%r0
+ b .Lcntlp
.Ldelspc:
- ic %r0,0(%r2,%r3)
- chi %r0,0x20 # is it a space ?
- be .Lcntlp
- ahi %r2,1
- b .Leolp
+ ic %r0,0(%r2,%r3)
+ chi %r0,0x20 # is it a space ?
+ be .Lcntlp
+ ahi %r2,1
+ b .Leolp
.Lcntlp:
- brct %r2,.Ldelspc
+ brct %r2,.Ldelspc
.Leolp:
- slr %r0,%r0
- stc %r0,0(%r2,%r3) # terminate buffer
+ slr %r0,%r0
+ stc %r0,0(%r2,%r3) # terminate buffer
.Lnopf:
#
# load ramdisk from ipl device
-#
+#
.Lagain2:
- l %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) # addr of ramdisk
- bas %r14,.Lloader # load ramdisk
- st %r2,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r12) # store size of ramdisk
- ltr %r2,%r2
- bnz .Lrdcont
- st %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) # no ramdisk found
+ l %r2,.Linitrd # addr of ramdisk
+ st %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12)
+ bas %r14,.Lloader # load ramdisk
+ st %r2,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r12) # store size of rd
+ ltr %r2,%r2
+ bnz .Lrdcont
+ st %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) # no ramdisk found
.Lrdcont:
- l %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12)
+ l %r2,.Linitrd
- clc 0(3,%r2),.L_hdr # skip HDRx and EOFx
- bz .Lagain2
- clc 0(3,%r2),.L_eof
- bz .Lagain2
+ clc 0(3,%r2),.L_hdr # skip HDRx and EOFx
+ bz .Lagain2
+ clc 0(3,%r2),.L_eof
+ bz .Lagain2
#ifdef CONFIG_IPL_VM
#
# reset files in VM reader
#
- stidp __LC_CPUID # store cpuid
- tm __LC_CPUID,0xff # running VM ?
- bno .Lnoreset
- la %r2,.Lreset
- lhi %r3,26
- diag %r2,%r3,8
- la %r5,.Lirb
- stsch 0(%r5) # check if irq is pending
- tm 30(%r5),0x0f # by verifying if any of the
- bnz .Lwaitforirq # activity or status control
- tm 31(%r5),0xff # bits is set in the schib
- bz .Lnoreset
+ stidp __LC_CPUID # store cpuid
+ tm __LC_CPUID,0xff # running VM ?
+ bno .Lnoreset
+ la %r2,.Lreset
+ lhi %r3,26
+ diag %r2,%r3,8
+ la %r5,.Lirb
+ stsch 0(%r5) # check if irq is pending
+ tm 30(%r5),0x0f # by verifying if any of the
+ bnz .Lwaitforirq # activity or status control
+ tm 31(%r5),0xff # bits is set in the schib
+ bz .Lnoreset
.Lwaitforirq:
- mvc 0x78(8),.Lrdrnewpsw # set up IO interrupt psw
+ mvc 0x78(8),.Lrdrnewpsw # set up IO interrupt psw
.Lwaitrdrirq:
- lpsw .Lrdrwaitpsw
+ lpsw .Lrdrwaitpsw
.Lrdrint:
- c %r1,0xb8 # compare subchannel number
- bne .Lwaitrdrirq
- la %r5,.Lirb
- tsch 0(%r5)
+ c %r1,0xb8 # compare subchannel number
+ bne .Lwaitrdrirq
+ la %r5,.Lirb
+ tsch 0(%r5)
.Lnoreset:
- b .Lnoload
+ b .Lnoload
- .align 8
+ .align 8
.Lrdrnewpsw:
- .long 0x00080000,0x80000000+.Lrdrint
+ .long 0x00080000,0x80000000+.Lrdrint
.Lrdrwaitpsw:
- .long 0x020a0000,0x80000000+.Lrdrint
+ .long 0x020a0000,0x80000000+.Lrdrint
#endif
#
# everything loaded, go for it
#
.Lnoload:
- l %r1,.Lstartup
- br %r1
+ l %r1,.Lstartup
+ br %r1
+.Linitrd:.long _end + 0x400000 # default address of initrd
.Lparm: .long PARMAREA
.Lstartup: .long startup
-.Lcvtab:.long _ebcasc # ebcdic to ascii table
-.Lreset:.byte 0xc3,0xc8,0xc1,0xd5,0xc7,0xc5,0x40,0xd9,0xc4,0xd9,0x40
- .byte 0xc1,0xd3,0xd3,0x40,0xd2,0xc5,0xc5,0xd7,0x40,0xd5,0xd6
- .byte 0xc8,0xd6,0xd3,0xc4 # "change rdr all keep nohold"
-.L_eof: .long 0xc5d6c600 /* C'EOF' */
-.L_hdr: .long 0xc8c4d900 /* C'HDR' */
+.Lcvtab:.long _ebcasc # ebcdic to ascii table
+.Lreset:.byte 0xc3,0xc8,0xc1,0xd5,0xc7,0xc5,0x40,0xd9,0xc4,0xd9,0x40
+ .byte 0xc1,0xd3,0xd3,0x40,0xd2,0xc5,0xc5,0xd7,0x40,0xd5,0xd6
+ .byte 0xc8,0xd6,0xd3,0xc4 # "change rdr all keep nohold"
+.L_eof: .long 0xc5d6c600 /* C'EOF' */
+.L_hdr: .long 0xc8c4d900 /* C'HDR' */
-#endif /* CONFIG_IPL */
+#endif /* CONFIG_IPL */
#
# SALIPL loader support. Based on a patch by Rob van der Heij.
# This entry point is called directly from the SALIPL loader and
# doesn't need a builtin ipl record.
#
- .org 0x800
- .globl start
+ .org 0x800
+ .globl start
start:
- stm %r0,%r15,0x07b0 # store registers
- basr %r12,%r0
+ stm %r0,%r15,0x07b0 # store registers
+ basr %r12,%r0
.base:
- l %r11,.parm
- l %r8,.cmd # pointer to command buffer
+ l %r11,.parm
+ l %r8,.cmd # pointer to command buffer
- ltr %r9,%r9 # do we have SALIPL parameters?
- bp .sk8x8
+ ltr %r9,%r9 # do we have SALIPL parameters?
+ bp .sk8x8
- mvc 0(64,%r8),0x00b0 # copy saved registers
- xc 64(240-64,%r8),0(%r8) # remainder of buffer
- tr 0(64,%r8),.lowcase
- b .gotr
+ mvc 0(64,%r8),0x00b0 # copy saved registers
+ xc 64(240-64,%r8),0(%r8) # remainder of buffer
+ tr 0(64,%r8),.lowcase
+ b .gotr
.sk8x8:
- mvc 0(240,%r8),0(%r9) # copy iplparms into buffer
+ mvc 0(240,%r8),0(%r9) # copy iplparms into buffer
.gotr:
- l %r10,.tbl # EBCDIC to ASCII table
- tr 0(240,%r8),0(%r10)
- stidp __LC_CPUID # Are we running on VM maybe
- cli __LC_CPUID,0xff
- bnz .test
- .long 0x83300060 # diag 3,0,x'0060' - storage size
- b .done
+ l %r10,.tbl # EBCDIC to ASCII table
+ tr 0(240,%r8),0(%r10)
+ stidp __LC_CPUID # Are we running on VM maybe
+ cli __LC_CPUID,0xff
+ bnz .test
+ .long 0x83300060 # diag 3,0,x'0060' - storage size
+ b .done
.test:
- mvc 0x68(8),.pgmnw # set up pgm check handler
- l %r2,.fourmeg
- lr %r3,%r2
- bctr %r3,%r0 # 4M-1
-.loop: iske %r0,%r3
- ar %r3,%r2
+ mvc 0x68(8),.pgmnw # set up pgm check handler
+ l %r2,.fourmeg
+ lr %r3,%r2
+ bctr %r3,%r0 # 4M-1
+.loop: iske %r0,%r3
+ ar %r3,%r2
.pgmx:
- sr %r3,%r2
- la %r3,1(%r3)
+ sr %r3,%r2
+ la %r3,1(%r3)
.done:
- l %r1,.memsize
- st %r3,ARCH_OFFSET(%r1)
- slr %r0,%r0
- st %r0,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r11)
- st %r0,INITRD_START+ARCH_OFFSET-PARMAREA(%r11)
- j startup # continue with startup
-.tbl: .long _ebcasc # translate table
-.cmd: .long COMMAND_LINE # address of command line buffer
-.parm: .long PARMAREA
+ l %r1,.memsize
+ st %r3,ARCH_OFFSET(%r1)
+ slr %r0,%r0
+ st %r0,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r11)
+ st %r0,INITRD_START+ARCH_OFFSET-PARMAREA(%r11)
+ j startup # continue with startup
+.tbl: .long _ebcasc # translate table
+.cmd: .long COMMAND_LINE # address of command line buffer
+.parm: .long PARMAREA
.memsize: .long memory_size
.fourmeg: .long 0x00400000 # 4M
-.pgmnw: .long 0x00080000,.pgmx
+.pgmnw: .long 0x00080000,.pgmx
.lowcase:
- .byte 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07
+ .byte 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07
.byte 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f
- .byte 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17
+ .byte 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17
.byte 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f
- .byte 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27
+ .byte 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27
.byte 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f
- .byte 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37
+ .byte 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37
.byte 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f
- .byte 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47
+ .byte 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47
.byte 0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f
- .byte 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57
+ .byte 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57
.byte 0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f
- .byte 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67
+ .byte 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67
.byte 0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f
- .byte 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77
+ .byte 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77
.byte 0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f
- .byte 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87
+ .byte 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87
.byte 0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f
- .byte 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97
+ .byte 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97
.byte 0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f
- .byte 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7
+ .byte 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7
.byte 0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf
- .byte 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7
+ .byte 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7
.byte 0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf
- .byte 0xc0,0x81,0x82,0x83,0x84,0x85,0x86,0x87 # .abcdefg
+ .byte 0xc0,0x81,0x82,0x83,0x84,0x85,0x86,0x87 # .abcdefg
.byte 0x88,0x89,0xca,0xcb,0xcc,0xcd,0xce,0xcf # hi
- .byte 0xd0,0x91,0x92,0x93,0x94,0x95,0x96,0x97 # .jklmnop
+ .byte 0xd0,0x91,0x92,0x93,0x94,0x95,0x96,0x97 # .jklmnop
.byte 0x98,0x99,0xda,0xdb,0xdc,0xdd,0xde,0xdf # qr
.byte 0xe0,0xe1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7 # ..stuvwx
.byte 0xa8,0xa9,0xea,0xeb,0xec,0xed,0xee,0xef # yz
- .byte 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7
+ .byte 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7
.byte 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
-.macro GET_IPL_DEVICE
-.Lget_ipl_device:
- l %r1,0xb8 # get sid
- sll %r1,15 # test if subchannel is enabled
- srl %r1,31
- ltr %r1,%r1
- bz 2f-.LPG1(%r13) # subchannel disabled
- l %r1,0xb8
- la %r5,.Lipl_schib-.LPG1(%r13)
- stsch 0(%r5) # get schib of subchannel
- bnz 2f-.LPG1(%r13) # schib not available
- tm 5(%r5),0x01 # devno valid?
- bno 2f-.LPG1(%r13)
- la %r6,ipl_parameter_flags-.LPG1(%r13)
- oi 3(%r6),0x01 # set flag
- la %r2,ipl_devno-.LPG1(%r13)
- mvc 0(2,%r2),6(%r5) # store devno
- tm 4(%r5),0x80 # qdio capable device?
- bno 2f-.LPG1(%r13)
- oi 3(%r6),0x02 # set flag
-
- # copy ipl parameters
-
- lhi %r0,4096
- l %r2,20(%r0) # get address of parameter list
- lhi %r3,IPL_PARMBLOCK_ORIGIN
- st %r3,20(%r0)
- lhi %r4,1
- cr %r2,%r3 # start parameters < destination ?
- jl 0f
- lhi %r1,1 # copy direction is upwards
- j 1f
-0: lhi %r1,-1 # copy direction is downwards
- ar %r2,%r0
- ar %r3,%r0
- ar %r2,%r1
- ar %r3,%r1
-1: mvc 0(1,%r3),0(%r2) # finally copy ipl parameters
- ar %r3,%r1
- ar %r2,%r1
- sr %r0,%r4
- jne 1b
- b 2f-.LPG1(%r13)
-
- .align 4
-.Lipl_schib:
- .rept 13
- .long 0
- .endr
-
- .globl ipl_parameter_flags
-ipl_parameter_flags:
- .long 0
- .globl ipl_devno
-ipl_devno:
- .word 0
-2:
-.endm
-
#ifdef CONFIG_64BIT
#include "head64.S"
#else
diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S
index a4dc61f3285e..1b952a3664e2 100644
--- a/arch/s390/kernel/head31.S
+++ b/arch/s390/kernel/head31.S
@@ -26,8 +26,8 @@ startup:basr %r13,0 # get base
#
.org PARMAREA
.long 0,0 # IPL_DEVICE
- .long 0,RAMDISK_ORIGIN # INITRD_START
- .long 0,RAMDISK_SIZE # INITRD_SIZE
+ .long 0,0 # INITRD_START
+ .long 0,0 # INITRD_SIZE
.org COMMAND_LINE
.byte "root=/dev/ram0 ro"
@@ -37,12 +37,23 @@ startup:basr %r13,0 # get base
startup_continue:
basr %r13,0 # get base
-.LPG1: GET_IPL_DEVICE
+.LPG1: mvi __LC_AR_MODE_ID,0 # set ESA flag (mode 0)
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
+#
+ l %r15,.Linittu-.LPG1(%r13)
+ mvc __LC_CURRENT(4),__TI_task(%r15)
+ ahi %r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union+THREAD_SIZE
+ st %r15,__LC_KERNEL_STACK # set end of kernel stack
+ ahi %r15,-96
+ xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain
+ l %r14,.Lipl_save_parameters-.LPG1(%r13)
+ basr %r14,%r14
#
# clear bss memory
#
@@ -114,6 +125,10 @@ startup_continue:
b .Lfchunk-.LPG1(%r13)
.align 4
+.Lipl_save_parameters:
+ .long ipl_save_parameters
+.Linittu:
+ .long init_thread_union
.Lpmask:
.byte 0
.align 8
@@ -239,6 +254,16 @@ startup_continue:
oi 3(%r12),0x80 # set IDTE flag
.Lchkidte:
+#
+# find out if the diag 0x9c is available
+#
+ mvc __LC_PGM_NEW_PSW(8),.Lpcdiag9c-.LPG1(%r13)
+ stap __LC_CPUID+4 # store cpu address
+ lh %r1,__LC_CPUID+4
+ diag %r1,0,0x9c # test diag 0x9c
+ oi 2(%r12),1 # set diag9c flag
+.Lchkdiag9c:
+
lpsw .Lentry-.LPG1(13) # jump to _stext in primary-space,
# virtual and never return ...
.align 8
@@ -266,6 +291,7 @@ startup_continue:
.Lpccsp:.long 0x00080000,0x80000000 + .Lchkcsp
.Lpcmvpg:.long 0x00080000,0x80000000 + .Lchkmvpg
.Lpcidte:.long 0x00080000,0x80000000 + .Lchkidte
+.Lpcdiag9c:.long 0x00080000,0x80000000 + .Lchkdiag9c
.Lmemsize:.long memory_size
.Lmchunk:.long memory_chunk
.Lmflags:.long machine_flags
@@ -273,7 +299,23 @@ startup_continue:
.Lbss_end: .long _end
.Lparmaddr: .long PARMAREA
.Lsccbaddr: .long .Lsccb
+
+ .globl ipl_schib
+ipl_schib:
+ .rept 13
+ .long 0
+ .endr
+
+ .globl ipl_flags
+ipl_flags:
+ .long 0
+ .globl ipl_devno
+ipl_devno:
+ .word 0
+
.org 0x12000
+.globl s390_readinfo_sccb
+s390_readinfo_sccb:
.Lsccb:
.hword 0x1000 # length, one page
.byte 0x00,0x00,0x00
@@ -302,16 +344,6 @@ startup_continue:
.globl _stext
_stext: basr %r13,0 # get base
.LPG3:
-#
-# Setup stack
-#
- l %r15,.Linittu-.LPG3(%r13)
- mvc __LC_CURRENT(4),__TI_task(%r15)
- ahi %r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union+THREAD_SIZE
- st %r15,__LC_KERNEL_STACK # set end of kernel stack
- ahi %r15,-96
- xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain
-
# check control registers
stctl %c0,%c15,0(%r15)
oi 2(%r15),0x40 # enable sigp emergency signal
@@ -330,6 +362,5 @@ _stext: basr %r13,0 # get base
#
.align 8
.Ldw: .long 0x000a0000,0x00000000
-.Linittu:.long init_thread_union
.Lstart:.long start_kernel
.Laregs:.long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
index 9d80c5b1ef95..b30e5897cdf7 100644
--- a/arch/s390/kernel/head64.S
+++ b/arch/s390/kernel/head64.S
@@ -15,221 +15,232 @@
# this is called either by the ipl loader or directly by PSW restart
# or linload or SALIPL
#
- .org 0x10000
-startup:basr %r13,0 # get base
-.LPG0: l %r13,0f-.LPG0(%r13)
- b 0(%r13)
-0: .long startup_continue
+ .org 0x10000
+startup:basr %r13,0 # get base
+.LPG0: l %r13,0f-.LPG0(%r13)
+ b 0(%r13)
+0: .long startup_continue
#
# params at 10400 (setup.h)
#
- .org PARMAREA
- .quad 0 # IPL_DEVICE
- .quad RAMDISK_ORIGIN # INITRD_START
- .quad RAMDISK_SIZE # INITRD_SIZE
+ .org PARMAREA
+ .quad 0 # IPL_DEVICE
+ .quad 0 # INITRD_START
+ .quad 0 # INITRD_SIZE
- .org COMMAND_LINE
- .byte "root=/dev/ram0 ro"
- .byte 0
+ .org COMMAND_LINE
+ .byte "root=/dev/ram0 ro"
+ .byte 0
- .org 0x11000
+ .org 0x11000
startup_continue:
- basr %r13,0 # get base
-.LPG1: sll %r13,1 # remove high order bit
- srl %r13,1
- GET_IPL_DEVICE
- lhi %r1,1 # mode 1 = esame
- slr %r0,%r0 # set cpuid to zero
- sigp %r1,%r0,0x12 # switch to esame mode
- sam64 # switch to 64 bit mode
- 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)
+ basr %r13,0 # get base
+.LPG1: sll %r13,1 # remove high order bit
+ srl %r13,1
+ lhi %r1,1 # mode 1 = esame
+ mvi __LC_AR_MODE_ID,1 # set esame flag
+ slr %r0,%r0 # set cpuid to zero
+ sigp %r1,%r0,0x12 # switch to esame mode
+ sam64 # switch to 64 bit mode
+ 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)
+#
+# Setup stack
+#
+ larl %r15,init_thread_union
+ lg %r14,__TI_task(%r15) # cache current in lowcore
+ stg %r14,__LC_CURRENT
+ aghi %r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union + THREAD_SIZE
+ stg %r15,__LC_KERNEL_STACK # set end of kernel stack
+ aghi %r15,-160
+ xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain
+ brasl %r14,ipl_save_parameters
#
# clear bss memory
#
- larl %r2,__bss_start # start of bss segment
- larl %r3,_end # end of bss segment
- sgr %r3,%r2 # length of bss
- sgr %r4,%r4 #
- sgr %r5,%r5 # set src,length and pad to zero
- mvcle %r2,%r4,0 # clear mem
- jo .-4 # branch back, if not finish
+ larl %r2,__bss_start # start of bss segment
+ larl %r3,_end # end of bss segment
+ sgr %r3,%r2 # length of bss
+ sgr %r4,%r4 #
+ sgr %r5,%r5 # set src,length and pad to zero
+ mvcle %r2,%r4,0 # clear mem
+ jo .-4 # branch back, if not finish
- l %r2,.Lrcp-.LPG1(%r13) # Read SCP forced command word
+ l %r2,.Lrcp-.LPG1(%r13) # Read SCP forced command word
.Lservicecall:
- stosm .Lpmask-.LPG1(%r13),0x01 # authorize ext interrupts
+ stosm .Lpmask-.LPG1(%r13),0x01 # authorize ext interrupts
- stctg %r0,%r0,.Lcr-.LPG1(%r13) # get cr0
- la %r1,0x200 # set bit 22
- og %r1,.Lcr-.LPG1(%r13) # or old cr0 with r1
- stg %r1,.Lcr-.LPG1(%r13)
- lctlg %r0,%r0,.Lcr-.LPG1(%r13) # load modified cr0
+ stctg %r0,%r0,.Lcr-.LPG1(%r13) # get cr0
+ la %r1,0x200 # set bit 22
+ og %r1,.Lcr-.LPG1(%r13) # or old cr0 with r1
+ stg %r1,.Lcr-.LPG1(%r13)
+ lctlg %r0,%r0,.Lcr-.LPG1(%r13) # load modified cr0
- mvc __LC_EXT_NEW_PSW(8),.Lpcmsk-.LPG1(%r13) # set postcall psw
- larl %r1,.Lsclph
- stg %r1,__LC_EXT_NEW_PSW+8 # set handler
+ mvc __LC_EXT_NEW_PSW(8),.Lpcmsk-.LPG1(%r13) # set postcall psw
+ larl %r1,.Lsclph
+ stg %r1,__LC_EXT_NEW_PSW+8 # set handler
- larl %r4,.Lsccb # %r4 is our index for sccb stuff
- lgr %r1,%r4 # our sccb
- .insn rre,0xb2200000,%r2,%r1 # service call
- ipm %r1
- srl %r1,28 # get cc code
- xr %r3,%r3
- chi %r1,3
- be .Lfchunk-.LPG1(%r13) # leave
- chi %r1,2
- be .Lservicecall-.LPG1(%r13)
- lpswe .Lwaitsclp-.LPG1(%r13)
+ larl %r4,.Lsccb # %r4 is our index for sccb stuff
+ lgr %r1,%r4 # our sccb
+ .insn rre,0xb2200000,%r2,%r1 # service call
+ ipm %r1
+ srl %r1,28 # get cc code
+ xr %r3,%r3
+ chi %r1,3
+ be .Lfchunk-.LPG1(%r13) # leave
+ chi %r1,2
+ be .Lservicecall-.LPG1(%r13)
+ lpswe .Lwaitsclp-.LPG1(%r13)
.Lsclph:
- lh %r1,.Lsccbr-.Lsccb(%r4)
- chi %r1,0x10 # 0x0010 is the sucess code
- je .Lprocsccb # let's process the sccb
- chi %r1,0x1f0
- bne .Lfchunk-.LPG1(%r13) # unhandled error code
- c %r2,.Lrcp-.LPG1(%r13) # Did we try Read SCP forced
- bne .Lfchunk-.LPG1(%r13) # if no, give up
- l %r2,.Lrcp2-.LPG1(%r13) # try with Read SCP
- b .Lservicecall-.LPG1(%r13)
+ lh %r1,.Lsccbr-.Lsccb(%r4)
+ chi %r1,0x10 # 0x0010 is the sucess code
+ je .Lprocsccb # let's process the sccb
+ chi %r1,0x1f0
+ bne .Lfchunk-.LPG1(%r13) # unhandled error code
+ c %r2,.Lrcp-.LPG1(%r13) # Did we try Read SCP forced
+ bne .Lfchunk-.LPG1(%r13) # if no, give up
+ l %r2,.Lrcp2-.LPG1(%r13) # try with Read SCP
+ b .Lservicecall-.LPG1(%r13)
.Lprocsccb:
- lghi %r1,0
- icm %r1,3,.Lscpincr1-.Lsccb(%r4) # use this one if != 0
- jnz .Lscnd
- lg %r1,.Lscpincr2-.Lsccb(%r4) # otherwise use this one
+ lghi %r1,0
+ icm %r1,3,.Lscpincr1-.Lsccb(%r4) # use this one if != 0
+ jnz .Lscnd
+ lg %r1,.Lscpincr2-.Lsccb(%r4) # otherwise use this one
.Lscnd:
- xr %r3,%r3 # same logic
- ic %r3,.Lscpa1-.Lsccb(%r4)
- chi %r3,0x00
- jne .Lcompmem
- l %r3,.Lscpa2-.Lsccb(%r4)
+ xr %r3,%r3 # same logic
+ ic %r3,.Lscpa1-.Lsccb(%r4)
+ chi %r3,0x00
+ jne .Lcompmem
+ l %r3,.Lscpa2-.Lsccb(%r4)
.Lcompmem:
- mlgr %r2,%r1 # mem in MB on 128-bit
- l %r1,.Lonemb-.LPG1(%r13)
- mlgr %r2,%r1 # mem size in bytes in %r3
- b .Lfchunk-.LPG1(%r13)
+ mlgr %r2,%r1 # mem in MB on 128-bit
+ l %r1,.Lonemb-.LPG1(%r13)
+ mlgr %r2,%r1 # mem size in bytes in %r3
+ b .Lfchunk-.LPG1(%r13)
- .align 4
+ .align 4
.Lpmask:
- .byte 0
- .align 8
+ .byte 0
+ .align 8
.Lcr:
- .quad 0x00 # place holder for cr0
+ .quad 0x00 # place holder for cr0
.Lwaitsclp:
- .quad 0x0102000180000000,.Lsclph
+ .quad 0x0102000180000000,.Lsclph
.Lrcp:
- .int 0x00120001 # Read SCP forced code
+ .int 0x00120001 # Read SCP forced code
.Lrcp2:
- .int 0x00020001 # Read SCP code
+ .int 0x00020001 # Read SCP code
.Lonemb:
- .int 0x100000
+ .int 0x100000
.Lfchunk:
- # set program check new psw mask
- mvc __LC_PGM_NEW_PSW(8),.Lpcmsk-.LPG1(%r13)
+ # set program check new psw mask
+ mvc __LC_PGM_NEW_PSW(8),.Lpcmsk-.LPG1(%r13)
#
# find memory chunks.
#
- lgr %r9,%r3 # end of mem
- larl %r1,.Lchkmem # set program check address
- stg %r1,__LC_PGM_NEW_PSW+8
- la %r1,1 # test in increments of 128KB
- sllg %r1,%r1,17
- larl %r3,memory_chunk
- slgr %r4,%r4 # set start of chunk to zero
- slgr %r5,%r5 # set end of chunk to zero
- slr %r6,%r6 # set access code to zero
- la %r10,MEMORY_CHUNKS # number of chunks
+ lgr %r9,%r3 # end of mem
+ larl %r1,.Lchkmem # set program check address
+ stg %r1,__LC_PGM_NEW_PSW+8
+ la %r1,1 # test in increments of 128KB
+ sllg %r1,%r1,17
+ larl %r3,memory_chunk
+ slgr %r4,%r4 # set start of chunk to zero
+ slgr %r5,%r5 # set end of chunk to zero
+ slr %r6,%r6 # set access code to zero
+ la %r10,MEMORY_CHUNKS # number of chunks
.Lloop:
- tprot 0(%r5),0 # test protection of first byte
- ipm %r7
- srl %r7,28
- clr %r6,%r7 # compare cc with last access code
- je .Lsame
- j .Lchkmem
+ tprot 0(%r5),0 # test protection of first byte
+ ipm %r7
+ srl %r7,28
+ clr %r6,%r7 # compare cc with last access code
+ je .Lsame
+ j .Lchkmem
.Lsame:
- algr %r5,%r1 # add 128KB to end of chunk
- # no need to check here,
- brc 12,.Lloop # this is the same chunk
-.Lchkmem: # > 16EB or tprot got a program check
- clgr %r4,%r5 # chunk size > 0?
- je .Lchkloop
- stg %r4,0(%r3) # store start address of chunk
- lgr %r0,%r5
- slgr %r0,%r4
- stg %r0,8(%r3) # store size of chunk
- st %r6,20(%r3) # store type of chunk
- la %r3,24(%r3)
- larl %r8,memory_size
- stg %r5,0(%r8) # store memory size
- ahi %r10,-1 # update chunk number
+ algr %r5,%r1 # add 128KB to end of chunk
+ # no need to check here,
+ brc 12,.Lloop # this is the same chunk
+.Lchkmem: # > 16EB or tprot got a program check
+ clgr %r4,%r5 # chunk size > 0?
+ je .Lchkloop
+ stg %r4,0(%r3) # store start address of chunk
+ lgr %r0,%r5
+ slgr %r0,%r4
+ stg %r0,8(%r3) # store size of chunk
+ st %r6,20(%r3) # store type of chunk
+ la %r3,24(%r3)
+ larl %r8,memory_size
+ stg %r5,0(%r8) # store memory size
+ ahi %r10,-1 # update chunk number
.Lchkloop:
- lr %r6,%r7 # set access code to last cc
+ lr %r6,%r7 # set access code to last cc
# we got an exception or we're starting a new
# chunk , we must check if we should
# still try to find valid memory (if we detected
# the amount of available storage), and if we
# have chunks left
- lghi %r4,1
- sllg %r4,%r4,31
- clgr %r5,%r4
- je .Lhsaskip
- xr %r0, %r0
- clgr %r0, %r9 # did we detect memory?
- je .Ldonemem # if not, leave
- chi %r10, 0 # do we have chunks left?
- je .Ldonemem
+ lghi %r4,1
+ sllg %r4,%r4,31
+ clgr %r5,%r4
+ je .Lhsaskip
+ xr %r0, %r0
+ clgr %r0, %r9 # did we detect memory?
+ je .Ldonemem # if not, leave
+ chi %r10, 0 # do we have chunks left?
+ je .Ldonemem
.Lhsaskip:
- algr %r5,%r1 # add 128KB to end of chunk
- lgr %r4,%r5 # potential new chunk
- clgr %r5,%r9 # should we go on?
- jl .Lloop
-.Ldonemem:
+ algr %r5,%r1 # add 128KB to end of chunk
+ lgr %r4,%r5 # potential new chunk
+ clgr %r5,%r9 # should we go on?
+ jl .Lloop
+.Ldonemem:
- larl %r12,machine_flags
+ larl %r12,machine_flags
#
# find out if we are running under VM
#
- stidp __LC_CPUID # store cpuid
- tm __LC_CPUID,0xff # running under VM ?
- bno 0f-.LPG1(%r13)
- oi 7(%r12),1 # set VM flag
-0: lh %r0,__LC_CPUID+4 # get cpu version
- chi %r0,0x7490 # running on a P/390 ?
- bne 1f-.LPG1(%r13)
- oi 7(%r12),4 # set P/390 flag
+ stidp __LC_CPUID # store cpuid
+ tm __LC_CPUID,0xff # running under VM ?
+ bno 0f-.LPG1(%r13)
+ oi 7(%r12),1 # set VM flag
+0: lh %r0,__LC_CPUID+4 # get cpu version
+ chi %r0,0x7490 # running on a P/390 ?
+ bne 1f-.LPG1(%r13)
+ oi 7(%r12),4 # set P/390 flag
1:
#
# find out if we have the MVPG instruction
#
- la %r1,0f-.LPG1(%r13) # set program check address
- stg %r1,__LC_PGM_NEW_PSW+8
- sgr %r0,%r0
- lghi %r1,0
- lghi %r2,0
- mvpg %r1,%r2 # test MVPG instruction
- oi 7(%r12),16 # set MVPG flag
+ la %r1,0f-.LPG1(%r13) # set program check address
+ stg %r1,__LC_PGM_NEW_PSW+8
+ sgr %r0,%r0
+ lghi %r1,0
+ lghi %r2,0
+ mvpg %r1,%r2 # test MVPG instruction
+ oi 7(%r12),16 # set MVPG flag
0:
#
# find out if the diag 0x44 works in 64 bit mode
#
- la %r1,0f-.LPG1(%r13) # set program check address
- stg %r1,__LC_PGM_NEW_PSW+8
- diag 0,0,0x44 # test diag 0x44
- oi 7(%r12),32 # set diag44 flag
-0:
+ la %r1,0f-.LPG1(%r13) # set program check address
+ stg %r1,__LC_PGM_NEW_PSW+8
+ diag 0,0,0x44 # test diag 0x44
+ oi 7(%r12),32 # set diag44 flag
+0:
#
# find out if we have the IDTE instruction
#
- la %r1,0f-.LPG1(%r13) # set program check address
- stg %r1,__LC_PGM_NEW_PSW+8
+ la %r1,0f-.LPG1(%r13) # set program check address
+ stg %r1,__LC_PGM_NEW_PSW+8
.long 0xb2b10000 # store facility list
tm 0xc8,0x08 # check bit for clearing-by-ASCE
bno 0f-.LPG1(%r13)
@@ -239,90 +250,117 @@ startup_continue:
oi 7(%r12),0x80 # set IDTE flag
0:
- lpswe .Lentry-.LPG1(13) # jump to _stext in primary-space,
- # virtual and never return ...
- .align 16
-.Lentry:.quad 0x0000000180000000,_stext
-.Lctl: .quad 0x04b50002 # cr0: various things
- .quad 0 # cr1: primary space segment table
- .quad .Lduct # cr2: dispatchable unit control table
- .quad 0 # cr3: instruction authorization
- .quad 0 # cr4: instruction authorization
- .quad 0xffffffffffffffff # cr5: primary-aste origin
- .quad 0 # cr6: I/O interrupts
- .quad 0 # cr7: secondary space segment table
- .quad 0 # cr8: access registers translation
- .quad 0 # cr9: tracing off
- .quad 0 # cr10: tracing off
- .quad 0 # cr11: tracing off
- .quad 0 # cr12: tracing off
- .quad 0 # cr13: home space segment table
- .quad 0xc0000000 # cr14: machine check handling off
- .quad 0 # cr15: linkage stack operations
-.Lduct: .long 0,0,0,0,0,0,0,0
- .long 0,0,0,0,0,0,0,0
-.Lpcmsk:.quad 0x0000000180000000
+#
+# find out if the diag 0x9c is available
+#
+ la %r1,0f-.LPG1(%r13) # set program check address
+ stg %r1,__LC_PGM_NEW_PSW+8
+ stap __LC_CPUID+4 # store cpu address
+ lh %r1,__LC_CPUID+4
+ diag %r1,0,0x9c # test diag 0x9c
+ oi 6(%r12),1 # set diag9c flag
+0:
+
+#
+# find out if we have the MVCOS instruction
+#
+ la %r1,0f-.LPG1(%r13) # set program check address
+ stg %r1,__LC_PGM_NEW_PSW+8
+ .short 0xc800 # mvcos 0(%r0),0(%r0),%r0
+ .short 0x0000
+ .short 0x0000
+0: tm 0x8f,0x13 # special-operation exception?
+ bno 1f-.LPG1(%r13) # if yes, MVCOS is present
+ oi 6(%r12),2 # set MVCOS flag
+1:
+
+ lpswe .Lentry-.LPG1(13) # jump to _stext in primary-space,
+ # virtual and never return ...
+ .align 16
+.Lentry:.quad 0x0000000180000000,_stext
+.Lctl: .quad 0x04b50002 # cr0: various things
+ .quad 0 # cr1: primary space segment table
+ .quad .Lduct # cr2: dispatchable unit control table
+ .quad 0 # cr3: instruction authorization
+ .quad 0 # cr4: instruction authorization
+ .quad 0xffffffffffffffff # cr5: primary-aste origin
+ .quad 0 # cr6: I/O interrupts
+ .quad 0 # cr7: secondary space segment table
+ .quad 0 # cr8: access registers translation
+ .quad 0 # cr9: tracing off
+ .quad 0 # cr10: tracing off
+ .quad 0 # cr11: tracing off
+ .quad 0 # cr12: tracing off
+ .quad 0 # cr13: home space segment table
+ .quad 0xc0000000 # cr14: machine check handling off
+ .quad 0 # cr15: linkage stack operations
+.Lduct: .long 0,0,0,0,0,0,0,0
+ .long 0,0,0,0,0,0,0,0
+.Lpcmsk:.quad 0x0000000180000000
.L4malign:.quad 0xffffffffffc00000
-.Lscan2g:.quad 0x80000000 + 0x20000 - 8 # 2GB + 128K - 8
-.Lnop: .long 0x07000700
+.Lscan2g:.quad 0x80000000 + 0x20000 - 8 # 2GB + 128K - 8
+.Lnop: .long 0x07000700
.Lparmaddr:
.quad PARMAREA
+ .globl ipl_schib
+ipl_schib:
+ .rept 13
+ .long 0
+ .endr
+
+ .globl ipl_flags
+ipl_flags:
+ .long 0
+ .globl ipl_devno
+ipl_devno:
+ .word 0
+
.org 0x12000
+.globl s390_readinfo_sccb
+s390_readinfo_sccb:
.Lsccb:
- .hword 0x1000 # length, one page
- .byte 0x00,0x00,0x00
- .byte 0x80 # variable response bit set
+ .hword 0x1000 # length, one page
+ .byte 0x00,0x00,0x00
+ .byte 0x80 # variable response bit set
.Lsccbr:
- .hword 0x00 # response code
+ .hword 0x00 # response code
.Lscpincr1:
- .hword 0x00
+ .hword 0x00
.Lscpa1:
- .byte 0x00
- .fill 89,1,0
+ .byte 0x00
+ .fill 89,1,0
.Lscpa2:
- .int 0x00
+ .int 0x00
.Lscpincr2:
- .quad 0x00
- .fill 3984,1,0
+ .quad 0x00
+ .fill 3984,1,0
.org 0x13000
#ifdef CONFIG_SHARED_KERNEL
- .org 0x100000
+ .org 0x100000
#endif
-
+
#
# startup-code, running in absolute addressing mode
#
- .globl _stext
-_stext: basr %r13,0 # get base
+ .globl _stext
+_stext: basr %r13,0 # get base
.LPG3:
-#
-# Setup stack
-#
- larl %r15,init_thread_union
- lg %r14,__TI_task(%r15) # cache current in lowcore
- stg %r14,__LC_CURRENT
- aghi %r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union + THREAD_SIZE
- stg %r15,__LC_KERNEL_STACK # set end of kernel stack
- aghi %r15,-160
- xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain
-
# check control registers
- stctg %c0,%c15,0(%r15)
- oi 6(%r15),0x40 # enable sigp emergency signal
- oi 4(%r15),0x10 # switch on low address proctection
- lctlg %c0,%c15,0(%r15)
+ stctg %c0,%c15,0(%r15)
+ oi 6(%r15),0x40 # enable sigp emergency signal
+ oi 4(%r15),0x10 # switch on low address proctection
+ lctlg %c0,%c15,0(%r15)
-#
- lam 0,15,.Laregs-.LPG3(%r13) # load access regs needed by uaccess
- brasl %r14,start_kernel # go to C code
+ lam 0,15,.Laregs-.LPG3(%r13) # load acrs needed by uaccess
+ brasl %r14,start_kernel # go to C code
#
# We returned from start_kernel ?!? PANIK
#
- basr %r13,0
- lpswe .Ldw-.(%r13) # load disabled wait psw
-#
- .align 8
-.Ldw: .quad 0x0002000180000000,0x0000000000000000
-.Laregs: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+ basr %r13,0
+ lpswe .Ldw-.(%r13) # load disabled wait psw
+
+ .align 8
+.Ldw: .quad 0x0002000180000000,0x0000000000000000
+.Laregs:.long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
new file mode 100644
index 000000000000..1f5e782b3d05
--- /dev/null
+++ b/arch/s390/kernel/ipl.c
@@ -0,0 +1,933 @@
+/*
+ * arch/s390/kernel/ipl.c
+ * ipl/reipl/dump support for Linux on s390.
+ *
+ * Copyright (C) IBM Corp. 2005,2006
+ * Author(s): Michael Holzheu <holzheu@de.ibm.com>
+ * Heiko Carstens <heiko.carstens@de.ibm.com>
+ * Volker Sameske <sameske@de.ibm.com>
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/reboot.h>
+#include <asm/smp.h>
+#include <asm/setup.h>
+#include <asm/cpcmd.h>
+#include <asm/cio.h>
+
+#define IPL_PARM_BLOCK_VERSION 0
+
+enum ipl_type {
+ IPL_TYPE_NONE = 1,
+ IPL_TYPE_UNKNOWN = 2,
+ IPL_TYPE_CCW = 4,
+ IPL_TYPE_FCP = 8,
+};
+
+#define IPL_NONE_STR "none"
+#define IPL_UNKNOWN_STR "unknown"
+#define IPL_CCW_STR "ccw"
+#define IPL_FCP_STR "fcp"
+
+static char *ipl_type_str(enum ipl_type type)
+{
+ switch (type) {
+ case IPL_TYPE_NONE:
+ return IPL_NONE_STR;
+ case IPL_TYPE_CCW:
+ return IPL_CCW_STR;
+ case IPL_TYPE_FCP:
+ return IPL_FCP_STR;
+ case IPL_TYPE_UNKNOWN:
+ default:
+ return IPL_UNKNOWN_STR;
+ }
+}
+
+enum ipl_method {
+ IPL_METHOD_NONE,
+ IPL_METHOD_CCW_CIO,
+ IPL_METHOD_CCW_DIAG,
+ IPL_METHOD_CCW_VM,
+ IPL_METHOD_FCP_RO_DIAG,
+ IPL_METHOD_FCP_RW_DIAG,
+ IPL_METHOD_FCP_RO_VM,
+};
+
+enum shutdown_action {
+ SHUTDOWN_REIPL,
+ SHUTDOWN_DUMP,
+ SHUTDOWN_STOP,
+};
+
+#define SHUTDOWN_REIPL_STR "reipl"
+#define SHUTDOWN_DUMP_STR "dump"
+#define SHUTDOWN_STOP_STR "stop"
+
+static char *shutdown_action_str(enum shutdown_action action)
+{
+ switch (action) {
+ case SHUTDOWN_REIPL:
+ return SHUTDOWN_REIPL_STR;
+ case SHUTDOWN_DUMP:
+ return SHUTDOWN_DUMP_STR;
+ case SHUTDOWN_STOP:
+ return SHUTDOWN_STOP_STR;
+ default:
+ BUG();
+ }
+}
+
+enum diag308_subcode {
+ DIAG308_IPL = 3,
+ DIAG308_DUMP = 4,
+ DIAG308_SET = 5,
+ DIAG308_STORE = 6,
+};
+
+enum diag308_ipl_type {
+ DIAG308_IPL_TYPE_FCP = 0,
+ DIAG308_IPL_TYPE_CCW = 2,
+};
+
+enum diag308_opt {
+ DIAG308_IPL_OPT_IPL = 0x10,
+ DIAG308_IPL_OPT_DUMP = 0x20,
+};
+
+enum diag308_rc {
+ DIAG308_RC_OK = 1,
+};
+
+static int diag308_set_works = 0;
+
+static int reipl_capabilities = IPL_TYPE_UNKNOWN;
+static enum ipl_type reipl_type = IPL_TYPE_UNKNOWN;
+static enum ipl_method reipl_method = IPL_METHOD_NONE;
+static struct ipl_parameter_block *reipl_block_fcp;
+static struct ipl_parameter_block *reipl_block_ccw;
+
+static int dump_capabilities = IPL_TYPE_NONE;
+static enum ipl_type dump_type = IPL_TYPE_NONE;
+static enum ipl_method dump_method = IPL_METHOD_NONE;
+static struct ipl_parameter_block *dump_block_fcp;
+static struct ipl_parameter_block *dump_block_ccw;
+
+static enum shutdown_action on_panic_action = SHUTDOWN_STOP;
+
+static int diag308(unsigned long subcode, void *addr)
+{
+ register unsigned long _addr asm("0") = (unsigned long) addr;
+ register unsigned long _rc asm("1") = 0;
+
+ asm volatile(
+ " diag %0,%2,0x308\n"
+ "0:\n"
+ EX_TABLE(0b,0b)
+ : "+d" (_addr), "+d" (_rc)
+ : "d" (subcode) : "cc", "memory");
+ return _rc;
+}
+
+/* SYSFS */
+
+#define DEFINE_IPL_ATTR_RO(_prefix, _name, _format, _value) \
+static ssize_t sys_##_prefix##_##_name##_show(struct subsystem *subsys, \
+ char *page) \
+{ \
+ return sprintf(page, _format, _value); \
+} \
+static struct subsys_attribute sys_##_prefix##_##_name##_attr = \
+ __ATTR(_name, S_IRUGO, sys_##_prefix##_##_name##_show, NULL);
+
+#define DEFINE_IPL_ATTR_RW(_prefix, _name, _fmt_out, _fmt_in, _value) \
+static ssize_t sys_##_prefix##_##_name##_show(struct subsystem *subsys, \
+ char *page) \
+{ \
+ return sprintf(page, _fmt_out, \
+ (unsigned long long) _value); \
+} \
+static ssize_t sys_##_prefix##_##_name##_store(struct subsystem *subsys,\
+ const char *buf, size_t len) \
+{ \
+ unsigned long long value; \
+ if (sscanf(buf, _fmt_in, &value) != 1) \
+ return -EINVAL; \
+ _value = value; \
+ return len; \
+} \
+static struct subsys_attribute sys_##_prefix##_##_name##_attr = \
+ __ATTR(_name,(S_IRUGO | S_IWUSR), \
+ sys_##_prefix##_##_name##_show, \
+ sys_##_prefix##_##_name##_store);
+
+static void make_attrs_ro(struct attribute **attrs)
+{
+ while (*attrs) {
+ (*attrs)->mode = S_IRUGO;
+ attrs++;
+ }
+}
+
+/*
+ * ipl section
+ */
+
+static enum ipl_type ipl_get_type(void)
+{
+ struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
+
+ if (!(ipl_flags & IPL_DEVNO_VALID))
+ return IPL_TYPE_UNKNOWN;
+ if (!(ipl_flags & IPL_PARMBLOCK_VALID))
+ return IPL_TYPE_CCW;
+ if (ipl->hdr.version > IPL_MAX_SUPPORTED_VERSION)
+ return IPL_TYPE_UNKNOWN;
+ if (ipl->hdr.pbt != DIAG308_IPL_TYPE_FCP)
+ return IPL_TYPE_UNKNOWN;
+ return IPL_TYPE_FCP;
+}
+
+static ssize_t ipl_type_show(struct subsystem *subsys, char *page)
+{
+ return sprintf(page, "%s\n", ipl_type_str(ipl_get_type()));
+}
+
+static struct subsys_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type);
+
+static ssize_t sys_ipl_device_show(struct subsystem *subsys, char *page)
+{
+ struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
+
+ switch (ipl_get_type()) {
+ case IPL_TYPE_CCW:
+ return sprintf(page, "0.0.%04x\n", ipl_devno);
+ case IPL_TYPE_FCP:
+ return sprintf(page, "0.0.%04x\n", ipl->ipl_info.fcp.devno);
+ default:
+ return 0;
+ }
+}
+
+static struct subsys_attribute sys_ipl_device_attr =
+ __ATTR(device, S_IRUGO, sys_ipl_device_show, NULL);
+
+static ssize_t ipl_parameter_read(struct kobject *kobj, char *buf, loff_t off,
+ size_t count)
+{
+ unsigned int size = IPL_PARMBLOCK_SIZE;
+
+ if (off > size)
+ return 0;
+ if (off + count > size)
+ count = size - off;
+ memcpy(buf, (void *)IPL_PARMBLOCK_START + off, count);
+ return count;
+}
+
+static struct bin_attribute ipl_parameter_attr = {
+ .attr = {
+ .name = "binary_parameter",
+ .mode = S_IRUGO,
+ .owner = THIS_MODULE,
+ },
+ .size = PAGE_SIZE,
+ .read = &ipl_parameter_read,
+};
+
+static ssize_t ipl_scp_data_read(struct kobject *kobj, char *buf, loff_t off,
+ size_t count)
+{
+ unsigned int size = IPL_PARMBLOCK_START->ipl_info.fcp.scp_data_len;
+ void *scp_data = &IPL_PARMBLOCK_START->ipl_info.fcp.scp_data;
+
+ if (off > size)
+ return 0;
+ if (off + count > size)
+ count = size - off;
+ memcpy(buf, scp_data + off, count);
+ return count;
+}
+
+static struct bin_attribute ipl_scp_data_attr = {
+ .attr = {
+ .name = "scp_data",
+ .mode = S_IRUGO,
+ .owner = THIS_MODULE,
+ },
+ .size = PAGE_SIZE,
+ .read = &ipl_scp_data_read,
+};
+
+/* FCP ipl device attributes */
+
+DEFINE_IPL_ATTR_RO(ipl_fcp, wwpn, "0x%016llx\n", (unsigned long long)
+ IPL_PARMBLOCK_START->ipl_info.fcp.wwpn);
+DEFINE_IPL_ATTR_RO(ipl_fcp, lun, "0x%016llx\n", (unsigned long long)
+ IPL_PARMBLOCK_START->ipl_info.fcp.lun);
+DEFINE_IPL_ATTR_RO(ipl_fcp, bootprog, "%lld\n", (unsigned long long)
+ IPL_PARMBLOCK_START->ipl_info.fcp.bootprog);
+DEFINE_IPL_ATTR_RO(ipl_fcp, br_lba, "%lld\n", (unsigned long long)
+ IPL_PARMBLOCK_START->ipl_info.fcp.br_lba);
+
+static struct attribute *ipl_fcp_attrs[] = {
+ &sys_ipl_type_attr.attr,
+ &sys_ipl_device_attr.attr,
+ &sys_ipl_fcp_wwpn_attr.attr,
+ &sys_ipl_fcp_lun_attr.attr,
+ &sys_ipl_fcp_bootprog_attr.attr,
+ &sys_ipl_fcp_br_lba_attr.attr,
+ NULL,
+};
+
+static struct attribute_group ipl_fcp_attr_group = {
+ .attrs = ipl_fcp_attrs,
+};
+
+/* CCW ipl device attributes */
+
+static struct attribute *ipl_ccw_attrs[] = {
+ &sys_ipl_type_attr.attr,
+ &sys_ipl_device_attr.attr,
+ NULL,
+};
+
+static struct attribute_group ipl_ccw_attr_group = {
+ .attrs = ipl_ccw_attrs,
+};
+
+/* UNKNOWN ipl device attributes */
+
+static struct attribute *ipl_unknown_attrs[] = {
+ &sys_ipl_type_attr.attr,
+ NULL,
+};
+
+static struct attribute_group ipl_unknown_attr_group = {
+ .attrs = ipl_unknown_attrs,
+};
+
+static decl_subsys(ipl, NULL, NULL);
+
+/*
+ * reipl section
+ */
+
+/* FCP reipl device attributes */
+
+DEFINE_IPL_ATTR_RW(reipl_fcp, wwpn, "0x%016llx\n", "%016llx\n",
+ reipl_block_fcp->ipl_info.fcp.wwpn);
+DEFINE_IPL_ATTR_RW(reipl_fcp, lun, "0x%016llx\n", "%016llx\n",
+ reipl_block_fcp->ipl_info.fcp.lun);
+DEFINE_IPL_ATTR_RW(reipl_fcp, bootprog, "%lld\n", "%lld\n",
+ reipl_block_fcp->ipl_info.fcp.bootprog);
+DEFINE_IPL_ATTR_RW(reipl_fcp, br_lba, "%lld\n", "%lld\n",
+ reipl_block_fcp->ipl_info.fcp.br_lba);
+DEFINE_IPL_ATTR_RW(reipl_fcp, device, "0.0.%04llx\n", "0.0.%llx\n",
+ reipl_block_fcp->ipl_info.fcp.devno);
+
+static struct attribute *reipl_fcp_attrs[] = {
+ &sys_reipl_fcp_device_attr.attr,
+ &sys_reipl_fcp_wwpn_attr.attr,
+ &sys_reipl_fcp_lun_attr.attr,
+ &sys_reipl_fcp_bootprog_attr.attr,
+ &sys_reipl_fcp_br_lba_attr.attr,
+ NULL,
+};
+
+static struct attribute_group reipl_fcp_attr_group = {
+ .name = IPL_FCP_STR,
+ .attrs = reipl_fcp_attrs,
+};
+
+/* CCW reipl device attributes */
+
+DEFINE_IPL_ATTR_RW(reipl_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
+ reipl_block_ccw->ipl_info.ccw.devno);
+
+static struct attribute *reipl_ccw_attrs[] = {
+ &sys_reipl_ccw_device_attr.attr,
+ NULL,
+};
+
+static struct attribute_group reipl_ccw_attr_group = {
+ .name = IPL_CCW_STR,
+ .attrs = reipl_ccw_attrs,
+};
+
+/* reipl type */
+
+static int reipl_set_type(enum ipl_type type)
+{
+ if (!(reipl_capabilities & type))
+ return -EINVAL;
+
+ switch(type) {
+ case IPL_TYPE_CCW:
+ if (MACHINE_IS_VM)
+ reipl_method = IPL_METHOD_CCW_VM;
+ else
+ reipl_method = IPL_METHOD_CCW_CIO;
+ break;
+ case IPL_TYPE_FCP:
+ if (diag308_set_works)
+ reipl_method = IPL_METHOD_FCP_RW_DIAG;
+ else if (MACHINE_IS_VM)
+ reipl_method = IPL_METHOD_FCP_RO_VM;
+ else
+ reipl_method = IPL_METHOD_FCP_RO_DIAG;
+ break;
+ default:
+ reipl_method = IPL_METHOD_NONE;
+ }
+ reipl_type = type;
+ return 0;
+}
+
+static ssize_t reipl_type_show(struct subsystem *subsys, char *page)
+{
+ return sprintf(page, "%s\n", ipl_type_str(reipl_type));
+}
+
+static ssize_t reipl_type_store(struct subsystem *subsys, const char *buf,
+ size_t len)
+{
+ int rc = -EINVAL;
+
+ if (strncmp(buf, IPL_CCW_STR, strlen(IPL_CCW_STR)) == 0)
+ rc = reipl_set_type(IPL_TYPE_CCW);
+ else if (strncmp(buf, IPL_FCP_STR, strlen(IPL_FCP_STR)) == 0)
+ rc = reipl_set_type(IPL_TYPE_FCP);
+ return (rc != 0) ? rc : len;
+}
+
+static struct subsys_attribute reipl_type_attr =
+ __ATTR(reipl_type, 0644, reipl_type_show, reipl_type_store);
+
+static decl_subsys(reipl, NULL, NULL);
+
+/*
+ * dump section
+ */
+
+/* FCP dump device attributes */
+
+DEFINE_IPL_ATTR_RW(dump_fcp, wwpn, "0x%016llx\n", "%016llx\n",
+ dump_block_fcp->ipl_info.fcp.wwpn);
+DEFINE_IPL_ATTR_RW(dump_fcp, lun, "0x%016llx\n", "%016llx\n",
+ dump_block_fcp->ipl_info.fcp.lun);
+DEFINE_IPL_ATTR_RW(dump_fcp, bootprog, "%lld\n", "%lld\n",
+ dump_block_fcp->ipl_info.fcp.bootprog);
+DEFINE_IPL_ATTR_RW(dump_fcp, br_lba, "%lld\n", "%lld\n",
+ dump_block_fcp->ipl_info.fcp.br_lba);
+DEFINE_IPL_ATTR_RW(dump_fcp, device, "0.0.%04llx\n", "0.0.%llx\n",
+ dump_block_fcp->ipl_info.fcp.devno);
+
+static struct attribute *dump_fcp_attrs[] = {
+ &sys_dump_fcp_device_attr.attr,
+ &sys_dump_fcp_wwpn_attr.attr,
+ &sys_dump_fcp_lun_attr.attr,
+ &sys_dump_fcp_bootprog_attr.attr,
+ &sys_dump_fcp_br_lba_attr.attr,
+ NULL,
+};
+
+static struct attribute_group dump_fcp_attr_group = {
+ .name = IPL_FCP_STR,
+ .attrs = dump_fcp_attrs,
+};
+
+/* CCW dump device attributes */
+
+DEFINE_IPL_ATTR_RW(dump_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
+ dump_block_ccw->ipl_info.ccw.devno);
+
+static struct attribute *dump_ccw_attrs[] = {
+ &sys_dump_ccw_device_attr.attr,
+ NULL,
+};
+
+static struct attribute_group dump_ccw_attr_group = {
+ .name = IPL_CCW_STR,
+ .attrs = dump_ccw_attrs,
+};
+
+/* dump type */
+
+static int dump_set_type(enum ipl_type type)
+{
+ if (!(dump_capabilities & type))
+ return -EINVAL;
+ switch(type) {
+ case IPL_TYPE_CCW:
+ if (MACHINE_IS_VM)
+ dump_method = IPL_METHOD_CCW_VM;
+ else
+ dump_method = IPL_METHOD_CCW_CIO;
+ break;
+ case IPL_TYPE_FCP:
+ dump_method = IPL_METHOD_FCP_RW_DIAG;
+ break;
+ default:
+ dump_method = IPL_METHOD_NONE;
+ }
+ dump_type = type;
+ return 0;
+}
+
+static ssize_t dump_type_show(struct subsystem *subsys, char *page)
+{
+ return sprintf(page, "%s\n", ipl_type_str(dump_type));
+}
+
+static ssize_t dump_type_store(struct subsystem *subsys, const char *buf,
+ size_t len)
+{
+ int rc = -EINVAL;
+
+ if (strncmp(buf, IPL_NONE_STR, strlen(IPL_NONE_STR)) == 0)
+ rc = dump_set_type(IPL_TYPE_NONE);
+ else if (strncmp(buf, IPL_CCW_STR, strlen(IPL_CCW_STR)) == 0)
+ rc = dump_set_type(IPL_TYPE_CCW);
+ else if (strncmp(buf, IPL_FCP_STR, strlen(IPL_FCP_STR)) == 0)
+ rc = dump_set_type(IPL_TYPE_FCP);
+ return (rc != 0) ? rc : len;
+}
+
+static struct subsys_attribute dump_type_attr =
+ __ATTR(dump_type, 0644, dump_type_show, dump_type_store);
+
+static decl_subsys(dump, NULL, NULL);
+
+#ifdef CONFIG_SMP
+static void dump_smp_stop_all(void)
+{
+ int cpu;
+ preempt_disable();
+ for_each_online_cpu(cpu) {
+ if (cpu == smp_processor_id())
+ continue;
+ while (signal_processor(cpu, sigp_stop) == sigp_busy)
+ udelay(10);
+ }
+ preempt_enable();
+}
+#else
+#define dump_smp_stop_all() do { } while (0)
+#endif
+
+/*
+ * Shutdown actions section
+ */
+
+static decl_subsys(shutdown_actions, NULL, NULL);
+
+/* on panic */
+
+static ssize_t on_panic_show(struct subsystem *subsys, char *page)
+{
+ return sprintf(page, "%s\n", shutdown_action_str(on_panic_action));
+}
+
+static ssize_t on_panic_store(struct subsystem *subsys, const char *buf,
+ size_t len)
+{
+ if (strncmp(buf, SHUTDOWN_REIPL_STR, strlen(SHUTDOWN_REIPL_STR)) == 0)
+ on_panic_action = SHUTDOWN_REIPL;
+ else if (strncmp(buf, SHUTDOWN_DUMP_STR,
+ strlen(SHUTDOWN_DUMP_STR)) == 0)
+ on_panic_action = SHUTDOWN_DUMP;
+ else if (strncmp(buf, SHUTDOWN_STOP_STR,
+ strlen(SHUTDOWN_STOP_STR)) == 0)
+ on_panic_action = SHUTDOWN_STOP;
+ else
+ return -EINVAL;
+
+ return len;
+}
+
+static struct subsys_attribute on_panic_attr =
+ __ATTR(on_panic, 0644, on_panic_show, on_panic_store);
+
+static void print_fcp_block(struct ipl_parameter_block *fcp_block)
+{
+ printk(KERN_EMERG "wwpn: %016llx\n",
+ (unsigned long long)fcp_block->ipl_info.fcp.wwpn);
+ printk(KERN_EMERG "lun: %016llx\n",
+ (unsigned long long)fcp_block->ipl_info.fcp.lun);
+ printk(KERN_EMERG "bootprog: %lld\n",
+ (unsigned long long)fcp_block->ipl_info.fcp.bootprog);
+ printk(KERN_EMERG "br_lba: %lld\n",
+ (unsigned long long)fcp_block->ipl_info.fcp.br_lba);
+ printk(KERN_EMERG "device: %llx\n",
+ (unsigned long long)fcp_block->ipl_info.fcp.devno);
+ printk(KERN_EMERG "opt: %x\n", fcp_block->ipl_info.fcp.opt);
+}
+
+void do_reipl(void)
+{
+ struct ccw_dev_id devid;
+ static char buf[100];
+
+ switch (reipl_type) {
+ case IPL_TYPE_CCW:
+ printk(KERN_EMERG "reboot on ccw device: 0.0.%04x\n",
+ reipl_block_ccw->ipl_info.ccw.devno);
+ break;
+ case IPL_TYPE_FCP:
+ printk(KERN_EMERG "reboot on fcp device:\n");
+ print_fcp_block(reipl_block_fcp);
+ break;
+ default:
+ break;
+ }
+
+ switch (reipl_method) {
+ case IPL_METHOD_CCW_CIO:
+ devid.devno = reipl_block_ccw->ipl_info.ccw.devno;
+ devid.ssid = 0;
+ reipl_ccw_dev(&devid);
+ break;
+ case IPL_METHOD_CCW_VM:
+ sprintf(buf, "IPL %X", reipl_block_ccw->ipl_info.ccw.devno);
+ cpcmd(buf, NULL, 0, NULL);
+ break;
+ case IPL_METHOD_CCW_DIAG:
+ diag308(DIAG308_SET, reipl_block_ccw);
+ diag308(DIAG308_IPL, NULL);
+ break;
+ case IPL_METHOD_FCP_RW_DIAG:
+ diag308(DIAG308_SET, reipl_block_fcp);
+ diag308(DIAG308_IPL, NULL);
+ break;
+ case IPL_METHOD_FCP_RO_DIAG:
+ diag308(DIAG308_IPL, NULL);
+ break;
+ case IPL_METHOD_FCP_RO_VM:
+ cpcmd("IPL", NULL, 0, NULL);
+ break;
+ case IPL_METHOD_NONE:
+ default:
+ if (MACHINE_IS_VM)
+ cpcmd("IPL", NULL, 0, NULL);
+ diag308(DIAG308_IPL, NULL);
+ break;
+ }
+ panic("reipl failed!\n");
+}
+
+static void do_dump(void)
+{
+ struct ccw_dev_id devid;
+ static char buf[100];
+
+ switch (dump_type) {
+ case IPL_TYPE_CCW:
+ printk(KERN_EMERG "Automatic dump on ccw device: 0.0.%04x\n",
+ dump_block_ccw->ipl_info.ccw.devno);
+ break;
+ case IPL_TYPE_FCP:
+ printk(KERN_EMERG "Automatic dump on fcp device:\n");
+ print_fcp_block(dump_block_fcp);
+ break;
+ default:
+ return;
+ }
+
+ switch (dump_method) {
+ case IPL_METHOD_CCW_CIO:
+ dump_smp_stop_all();
+ devid.devno = dump_block_ccw->ipl_info.ccw.devno;
+ devid.ssid = 0;
+ reipl_ccw_dev(&devid);
+ break;
+ case IPL_METHOD_CCW_VM:
+ dump_smp_stop_all();
+ sprintf(buf, "STORE STATUS");
+ cpcmd(buf, NULL, 0, NULL);
+ sprintf(buf, "IPL %X", dump_block_ccw->ipl_info.ccw.devno);
+ cpcmd(buf, NULL, 0, NULL);
+ break;
+ case IPL_METHOD_CCW_DIAG:
+ diag308(DIAG308_SET, dump_block_ccw);
+ diag308(DIAG308_DUMP, NULL);
+ break;
+ case IPL_METHOD_FCP_RW_DIAG:
+ diag308(DIAG308_SET, dump_block_fcp);
+ diag308(DIAG308_DUMP, NULL);
+ break;
+ case IPL_METHOD_NONE:
+ default:
+ return;
+ }
+ printk(KERN_EMERG "Dump failed!\n");
+}
+
+/* init functions */
+
+static int __init ipl_register_fcp_files(void)
+{
+ int rc;
+
+ rc = sysfs_create_group(&ipl_subsys.kset.kobj,
+ &ipl_fcp_attr_group);
+ if (rc)
+ goto out;
+ rc = sysfs_create_bin_file(&ipl_subsys.kset.kobj,
+ &ipl_parameter_attr);
+ if (rc)
+ goto out_ipl_parm;
+ rc = sysfs_create_bin_file(&ipl_subsys.kset.kobj,
+ &ipl_scp_data_attr);
+ if (!rc)
+ goto out;
+
+ sysfs_remove_bin_file(&ipl_subsys.kset.kobj, &ipl_parameter_attr);
+
+out_ipl_parm:
+ sysfs_remove_group(&ipl_subsys.kset.kobj, &ipl_fcp_attr_group);
+out:
+ return rc;
+}
+
+static int __init ipl_init(void)
+{
+ int rc;
+
+ rc = firmware_register(&ipl_subsys);
+ if (rc)
+ return rc;
+ switch (ipl_get_type()) {
+ case IPL_TYPE_CCW:
+ rc = sysfs_create_group(&ipl_subsys.kset.kobj,
+ &ipl_ccw_attr_group);
+ break;
+ case IPL_TYPE_FCP:
+ rc = ipl_register_fcp_files();
+ break;
+ default:
+ rc = sysfs_create_group(&ipl_subsys.kset.kobj,
+ &ipl_unknown_attr_group);
+ break;
+ }
+ if (rc)
+ firmware_unregister(&ipl_subsys);
+ return rc;
+}
+
+static void __init reipl_probe(void)
+{
+ void *buffer;
+
+ buffer = (void *) get_zeroed_page(GFP_KERNEL);
+ if (!buffer)
+ return;
+ if (diag308(DIAG308_STORE, buffer) == DIAG308_RC_OK)
+ diag308_set_works = 1;
+ free_page((unsigned long)buffer);
+}
+
+static int __init reipl_ccw_init(void)
+{
+ int rc;
+
+ reipl_block_ccw = (void *) get_zeroed_page(GFP_KERNEL);
+ if (!reipl_block_ccw)
+ return -ENOMEM;
+ rc = sysfs_create_group(&reipl_subsys.kset.kobj, &reipl_ccw_attr_group);
+ if (rc) {
+ free_page((unsigned long)reipl_block_ccw);
+ return rc;
+ }
+ reipl_block_ccw->hdr.len = IPL_PARM_BLK_CCW_LEN;
+ reipl_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION;
+ reipl_block_ccw->hdr.blk0_len = sizeof(reipl_block_ccw->ipl_info.ccw);
+ reipl_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW;
+ if (ipl_get_type() == IPL_TYPE_CCW)
+ reipl_block_ccw->ipl_info.ccw.devno = ipl_devno;
+ reipl_capabilities |= IPL_TYPE_CCW;
+ return 0;
+}
+
+static int __init reipl_fcp_init(void)
+{
+ int rc;
+
+ if ((!diag308_set_works) && (ipl_get_type() != IPL_TYPE_FCP))
+ return 0;
+ if ((!diag308_set_works) && (ipl_get_type() == IPL_TYPE_FCP))
+ make_attrs_ro(reipl_fcp_attrs);
+
+ reipl_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);
+ if (!reipl_block_fcp)
+ return -ENOMEM;
+ rc = sysfs_create_group(&reipl_subsys.kset.kobj, &reipl_fcp_attr_group);
+ if (rc) {
+ free_page((unsigned long)reipl_block_fcp);
+ return rc;
+ }
+ if (ipl_get_type() == IPL_TYPE_FCP) {
+ memcpy(reipl_block_fcp, IPL_PARMBLOCK_START, PAGE_SIZE);
+ } else {
+ reipl_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN;
+ reipl_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION;
+ reipl_block_fcp->hdr.blk0_len =
+ sizeof(reipl_block_fcp->ipl_info.fcp);
+ reipl_block_fcp->hdr.pbt = DIAG308_IPL_TYPE_FCP;
+ reipl_block_fcp->ipl_info.fcp.opt = DIAG308_IPL_OPT_IPL;
+ }
+ reipl_capabilities |= IPL_TYPE_FCP;
+ return 0;
+}
+
+static int __init reipl_init(void)
+{
+ int rc;
+
+ rc = firmware_register(&reipl_subsys);
+ if (rc)
+ return rc;
+ rc = subsys_create_file(&reipl_subsys, &reipl_type_attr);
+ if (rc) {
+ firmware_unregister(&reipl_subsys);
+ return rc;
+ }
+ rc = reipl_ccw_init();
+ if (rc)
+ return rc;
+ rc = reipl_fcp_init();
+ if (rc)
+ return rc;
+ rc = reipl_set_type(ipl_get_type());
+ if (rc)
+ return rc;
+ return 0;
+}
+
+static int __init dump_ccw_init(void)
+{
+ int rc;
+
+ dump_block_ccw = (void *) get_zeroed_page(GFP_KERNEL);
+ if (!dump_block_ccw)
+ return -ENOMEM;
+ rc = sysfs_create_group(&dump_subsys.kset.kobj, &dump_ccw_attr_group);
+ if (rc) {
+ free_page((unsigned long)dump_block_ccw);
+ return rc;
+ }
+ dump_block_ccw->hdr.len = IPL_PARM_BLK_CCW_LEN;
+ dump_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION;
+ dump_block_ccw->hdr.blk0_len = sizeof(reipl_block_ccw->ipl_info.ccw);
+ dump_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW;
+ dump_capabilities |= IPL_TYPE_CCW;
+ return 0;
+}
+
+extern char s390_readinfo_sccb[];
+
+static int __init dump_fcp_init(void)
+{
+ int rc;
+
+ if(!(s390_readinfo_sccb[91] & 0x2))
+ return 0; /* LDIPL DUMP is not installed */
+ if (!diag308_set_works)
+ return 0;
+ dump_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);
+ if (!dump_block_fcp)
+ return -ENOMEM;
+ rc = sysfs_create_group(&dump_subsys.kset.kobj, &dump_fcp_attr_group);
+ if (rc) {
+ free_page((unsigned long)dump_block_fcp);
+ return rc;
+ }
+ dump_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN;
+ dump_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION;
+ dump_block_fcp->hdr.blk0_len = sizeof(dump_block_fcp->ipl_info.fcp);
+ dump_block_fcp->hdr.pbt = DIAG308_IPL_TYPE_FCP;
+ dump_block_fcp->ipl_info.fcp.opt = DIAG308_IPL_OPT_DUMP;
+ dump_capabilities |= IPL_TYPE_FCP;
+ return 0;
+}
+
+#define SHUTDOWN_ON_PANIC_PRIO 0
+
+static int shutdown_on_panic_notify(struct notifier_block *self,
+ unsigned long event, void *data)
+{
+ if (on_panic_action == SHUTDOWN_DUMP)
+ do_dump();
+ else if (on_panic_action == SHUTDOWN_REIPL)
+ do_reipl();
+ return NOTIFY_OK;
+}
+
+static struct notifier_block shutdown_on_panic_nb = {
+ .notifier_call = shutdown_on_panic_notify,
+ .priority = SHUTDOWN_ON_PANIC_PRIO
+};
+
+static int __init dump_init(void)
+{
+ int rc;
+
+ rc = firmware_register(&dump_subsys);
+ if (rc)
+ return rc;
+ rc = subsys_create_file(&dump_subsys, &dump_type_attr);
+ if (rc) {
+ firmware_unregister(&dump_subsys);
+ return rc;
+ }
+ rc = dump_ccw_init();
+ if (rc)
+ return rc;
+ rc = dump_fcp_init();
+ if (rc)
+ return rc;
+ dump_set_type(IPL_TYPE_NONE);
+ return 0;
+}
+
+static int __init shutdown_actions_init(void)
+{
+ int rc;
+
+ rc = firmware_register(&shutdown_actions_subsys);
+ if (rc)
+ return rc;
+ rc = subsys_create_file(&shutdown_actions_subsys, &on_panic_attr);
+ if (rc) {
+ firmware_unregister(&shutdown_actions_subsys);
+ return rc;
+ }
+ atomic_notifier_chain_register(&panic_notifier_list,
+ &shutdown_on_panic_nb);
+ return 0;
+}
+
+static int __init s390_ipl_init(void)
+{
+ int rc;
+
+ reipl_probe();
+ rc = ipl_init();
+ if (rc)
+ return rc;
+ rc = reipl_init();
+ if (rc)
+ return rc;
+ rc = dump_init();
+ if (rc)
+ return rc;
+ rc = shutdown_actions_init();
+ if (rc)
+ return rc;
+ return 0;
+}
+
+__initcall(s390_ipl_init);
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
new file mode 100644
index 000000000000..ca28fb0b3790
--- /dev/null
+++ b/arch/s390/kernel/kprobes.c
@@ -0,0 +1,657 @@
+/*
+ * Kernel Probes (KProbes)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2002, 2006
+ *
+ * s390 port, used ppc64 as template. Mike Grundy <grundym@us.ibm.com>
+ */
+
+#include <linux/config.h>
+#include <linux/kprobes.h>
+#include <linux/ptrace.h>
+#include <linux/preempt.h>
+#include <linux/stop_machine.h>
+#include <asm/cacheflush.h>
+#include <asm/kdebug.h>
+#include <asm/sections.h>
+#include <asm/uaccess.h>
+#include <linux/module.h>
+
+DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
+DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
+
+int __kprobes arch_prepare_kprobe(struct kprobe *p)
+{
+ /* Make sure the probe isn't going on a difficult instruction */
+ if (is_prohibited_opcode((kprobe_opcode_t *) p->addr))
+ return -EINVAL;
+
+ if ((unsigned long)p->addr & 0x01) {
+ printk("Attempt to register kprobe at an unaligned address\n");
+ return -EINVAL;
+ }
+
+ /* Use the get_insn_slot() facility for correctness */
+ if (!(p->ainsn.insn = get_insn_slot()))
+ return -ENOMEM;
+
+ memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
+
+ get_instruction_type(&p->ainsn);
+ p->opcode = *p->addr;
+ return 0;
+}
+
+int __kprobes is_prohibited_opcode(kprobe_opcode_t *instruction)
+{
+ switch (*(__u8 *) instruction) {
+ case 0x0c: /* bassm */
+ case 0x0b: /* bsm */
+ case 0x83: /* diag */
+ case 0x44: /* ex */
+ return -EINVAL;
+ }
+ switch (*(__u16 *) instruction) {
+ case 0x0101: /* pr */
+ case 0xb25a: /* bsa */
+ case 0xb240: /* bakr */
+ case 0xb258: /* bsg */
+ case 0xb218: /* pc */
+ case 0xb228: /* pt */
+ return -EINVAL;
+ }
+ return 0;
+}
+
+void __kprobes get_instruction_type(struct arch_specific_insn *ainsn)
+{
+ /* default fixup method */
+ ainsn->fixup = FIXUP_PSW_NORMAL;
+
+ /* save r1 operand */
+ ainsn->reg = (*ainsn->insn & 0xf0) >> 4;
+
+ /* save the instruction length (pop 5-5) in bytes */
+ switch (*(__u8 *) (ainsn->insn) >> 4) {
+ case 0:
+ ainsn->ilen = 2;
+ break;
+ case 1:
+ case 2:
+ ainsn->ilen = 4;
+ break;
+ case 3:
+ ainsn->ilen = 6;
+ break;
+ }
+
+ switch (*(__u8 *) ainsn->insn) {
+ case 0x05: /* balr */
+ case 0x0d: /* basr */
+ ainsn->fixup = FIXUP_RETURN_REGISTER;
+ /* if r2 = 0, no branch will be taken */
+ if ((*ainsn->insn & 0x0f) == 0)
+ ainsn->fixup |= FIXUP_BRANCH_NOT_TAKEN;
+ break;
+ case 0x06: /* bctr */
+ case 0x07: /* bcr */
+ ainsn->fixup = FIXUP_BRANCH_NOT_TAKEN;
+ break;
+ case 0x45: /* bal */
+ case 0x4d: /* bas */
+ ainsn->fixup = FIXUP_RETURN_REGISTER;
+ break;
+ case 0x47: /* bc */
+ case 0x46: /* bct */
+ case 0x86: /* bxh */
+ case 0x87: /* bxle */
+ ainsn->fixup = FIXUP_BRANCH_NOT_TAKEN;
+ break;
+ case 0x82: /* lpsw */
+ ainsn->fixup = FIXUP_NOT_REQUIRED;
+ break;
+ case 0xb2: /* lpswe */
+ if (*(((__u8 *) ainsn->insn) + 1) == 0xb2) {
+ ainsn->fixup = FIXUP_NOT_REQUIRED;
+ }
+ break;
+ case 0xa7: /* bras */
+ if ((*ainsn->insn & 0x0f) == 0x05) {
+ ainsn->fixup |= FIXUP_RETURN_REGISTER;
+ }
+ break;
+ case 0xc0:
+ if ((*ainsn->insn & 0x0f) == 0x00 /* larl */
+ || (*ainsn->insn & 0x0f) == 0x05) /* brasl */
+ ainsn->fixup |= FIXUP_RETURN_REGISTER;
+ break;
+ case 0xeb:
+ if (*(((__u8 *) ainsn->insn) + 5 ) == 0x44 || /* bxhg */
+ *(((__u8 *) ainsn->insn) + 5) == 0x45) {/* bxleg */
+ ainsn->fixup = FIXUP_BRANCH_NOT_TAKEN;
+ }
+ break;
+ case 0xe3: /* bctg */
+ if (*(((__u8 *) ainsn->insn) + 5) == 0x46) {
+ ainsn->fixup = FIXUP_BRANCH_NOT_TAKEN;
+ }
+ break;
+ }
+}
+
+static int __kprobes swap_instruction(void *aref)
+{
+ struct ins_replace_args *args = aref;
+ int err = -EFAULT;
+
+ asm volatile(
+ "0: mvc 0(2,%2),0(%3)\n"
+ "1: la %0,0\n"
+ "2:\n"
+ EX_TABLE(0b,2b)
+ : "+d" (err), "=m" (*args->ptr)
+ : "a" (args->ptr), "a" (&args->new), "m" (args->new));
+ return err;
+}
+
+void __kprobes arch_arm_kprobe(struct kprobe *p)
+{
+ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+ unsigned long status = kcb->kprobe_status;
+ struct ins_replace_args args;
+
+ args.ptr = p->addr;
+ args.old = p->opcode;
+ args.new = BREAKPOINT_INSTRUCTION;
+
+ kcb->kprobe_status = KPROBE_SWAP_INST;
+ stop_machine_run(swap_instruction, &args, NR_CPUS);
+ kcb->kprobe_status = status;
+}
+
+void __kprobes arch_disarm_kprobe(struct kprobe *p)
+{
+ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+ unsigned long status = kcb->kprobe_status;
+ struct ins_replace_args args;
+
+ args.ptr = p->addr;
+ args.old = BREAKPOINT_INSTRUCTION;
+ args.new = p->opcode;
+
+ kcb->kprobe_status = KPROBE_SWAP_INST;
+ stop_machine_run(swap_instruction, &args, NR_CPUS);
+ kcb->kprobe_status = status;
+}
+
+void __kprobes arch_remove_kprobe(struct kprobe *p)
+{
+ mutex_lock(&kprobe_mutex);
+ free_insn_slot(p->ainsn.insn);
+ mutex_unlock(&kprobe_mutex);
+}
+
+static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
+{
+ per_cr_bits kprobe_per_regs[1];
+
+ memset(kprobe_per_regs, 0, sizeof(per_cr_bits));
+ regs->psw.addr = (unsigned long)p->ainsn.insn | PSW_ADDR_AMODE;
+
+ /* Set up the per control reg info, will pass to lctl */
+ kprobe_per_regs[0].em_instruction_fetch = 1;
+ kprobe_per_regs[0].starting_addr = (unsigned long)p->ainsn.insn;
+ kprobe_per_regs[0].ending_addr = (unsigned long)p->ainsn.insn + 1;
+
+ /* Set the PER control regs, turns on single step for this address */
+ __ctl_load(kprobe_per_regs, 9, 11);
+ regs->psw.mask |= PSW_MASK_PER;
+ regs->psw.mask &= ~(PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK);
+}
+
+static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
+{
+ kcb->prev_kprobe.kp = kprobe_running();
+ kcb->prev_kprobe.status = kcb->kprobe_status;
+ kcb->prev_kprobe.kprobe_saved_imask = kcb->kprobe_saved_imask;
+ memcpy(kcb->prev_kprobe.kprobe_saved_ctl, kcb->kprobe_saved_ctl,
+ sizeof(kcb->kprobe_saved_ctl));
+}
+
+static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+{
+ __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
+ kcb->kprobe_status = kcb->prev_kprobe.status;
+ kcb->kprobe_saved_imask = kcb->prev_kprobe.kprobe_saved_imask;
+ memcpy(kcb->kprobe_saved_ctl, kcb->prev_kprobe.kprobe_saved_ctl,
+ sizeof(kcb->kprobe_saved_ctl));
+}
+
+static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+ struct kprobe_ctlblk *kcb)
+{
+ __get_cpu_var(current_kprobe) = p;
+ /* Save the interrupt and per flags */
+ kcb->kprobe_saved_imask = regs->psw.mask &
+ (PSW_MASK_PER | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK);
+ /* Save the control regs that govern PER */
+ __ctl_store(kcb->kprobe_saved_ctl, 9, 11);
+}
+
+/* Called with kretprobe_lock held */
+void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
+ struct pt_regs *regs)
+{
+ struct kretprobe_instance *ri;
+
+ if ((ri = get_free_rp_inst(rp)) != NULL) {
+ ri->rp = rp;
+ ri->task = current;
+ ri->ret_addr = (kprobe_opcode_t *) regs->gprs[14];
+
+ /* Replace the return addr with trampoline addr */
+ regs->gprs[14] = (unsigned long)&kretprobe_trampoline;
+
+ add_rp_inst(ri);
+ } else {
+ rp->nmissed++;
+ }
+}
+
+static int __kprobes kprobe_handler(struct pt_regs *regs)
+{
+ struct kprobe *p;
+ int ret = 0;
+ unsigned long *addr = (unsigned long *)
+ ((regs->psw.addr & PSW_ADDR_INSN) - 2);
+ struct kprobe_ctlblk *kcb;
+
+ /*
+ * We don't want to be preempted for the entire
+ * duration of kprobe processing
+ */
+ preempt_disable();
+ kcb = get_kprobe_ctlblk();
+
+ /* Check we're not actually recursing */
+ if (kprobe_running()) {
+ p = get_kprobe(addr);
+ if (p) {
+ if (kcb->kprobe_status == KPROBE_HIT_SS &&
+ *p->ainsn.insn == BREAKPOINT_INSTRUCTION) {
+ regs->psw.mask &= ~PSW_MASK_PER;
+ regs->psw.mask |= kcb->kprobe_saved_imask;
+ goto no_kprobe;
+ }
+ /* We have reentered the kprobe_handler(), since
+ * another probe was hit while within the handler.
+ * We here save the original kprobes variables and
+ * just single step on the instruction of the new probe
+ * without calling any user handlers.
+ */
+ save_previous_kprobe(kcb);
+ set_current_kprobe(p, regs, kcb);
+ kprobes_inc_nmissed_count(p);
+ prepare_singlestep(p, regs);
+ kcb->kprobe_status = KPROBE_REENTER;
+ return 1;
+ } else {
+ p = __get_cpu_var(current_kprobe);
+ if (p->break_handler && p->break_handler(p, regs)) {
+ goto ss_probe;
+ }
+ }
+ goto no_kprobe;
+ }
+
+ p = get_kprobe(addr);
+ if (!p) {
+ if (*addr != BREAKPOINT_INSTRUCTION) {
+ /*
+ * The breakpoint instruction was removed right
+ * after we hit it. Another cpu has removed
+ * either a probepoint or a debugger breakpoint
+ * at this address. In either case, no further
+ * handling of this interrupt is appropriate.
+ *
+ */
+ ret = 1;
+ }
+ /* Not one of ours: let kernel handle it */
+ goto no_kprobe;
+ }
+
+ kcb->kprobe_status = KPROBE_HIT_ACTIVE;
+ set_current_kprobe(p, regs, kcb);
+ if (p->pre_handler && p->pre_handler(p, regs))
+ /* handler has already set things up, so skip ss setup */
+ return 1;
+
+ss_probe:
+ prepare_singlestep(p, regs);
+ kcb->kprobe_status = KPROBE_HIT_SS;
+ return 1;
+
+no_kprobe:
+ preempt_enable_no_resched();
+ return ret;
+}
+
+/*
+ * Function return probe trampoline:
+ * - init_kprobes() establishes a probepoint here
+ * - When the probed function returns, this probe
+ * causes the handlers to fire
+ */
+void __kprobes kretprobe_trampoline_holder(void)
+{
+ asm volatile(".global kretprobe_trampoline\n"
+ "kretprobe_trampoline: bcr 0,0\n");
+}
+
+/*
+ * Called when the probe at kretprobe trampoline is hit
+ */
+int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
+{
+ struct kretprobe_instance *ri = NULL;
+ struct hlist_head *head;
+ struct hlist_node *node, *tmp;
+ unsigned long flags, orig_ret_address = 0;
+ unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline;
+
+ spin_lock_irqsave(&kretprobe_lock, flags);
+ head = kretprobe_inst_table_head(current);
+
+ /*
+ * It is possible to have multiple instances associated with a given
+ * task either because an multiple functions in the call path
+ * have a return probe installed on them, and/or more then one return
+ * return probe was registered for a target function.
+ *
+ * We can handle this because:
+ * - instances are always inserted at the head of the list
+ * - when multiple return probes are registered for the same
+ * function, the first instance's ret_addr will point to the
+ * real return address, and all the rest will point to
+ * kretprobe_trampoline
+ */
+ hlist_for_each_entry_safe(ri, node, tmp, head, hlist) {
+ if (ri->task != current)
+ /* another task is sharing our hash bucket */
+ continue;
+
+ if (ri->rp && ri->rp->handler)
+ ri->rp->handler(ri, regs);
+
+ orig_ret_address = (unsigned long)ri->ret_addr;
+ recycle_rp_inst(ri);
+
+ if (orig_ret_address != trampoline_address) {
+ /*
+ * This is the real return address. Any other
+ * instances associated with this task are for
+ * other calls deeper on the call stack
+ */
+ break;
+ }
+ }
+ BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address));
+ regs->psw.addr = orig_ret_address | PSW_ADDR_AMODE;
+
+ reset_current_kprobe();
+ spin_unlock_irqrestore(&kretprobe_lock, flags);
+ preempt_enable_no_resched();
+
+ /*
+ * By returning a non-zero value, we are telling
+ * kprobe_handler() that we don't want the post_handler
+ * to run (and have re-enabled preemption)
+ */
+ return 1;
+}
+
+/*
+ * Called after single-stepping. p->addr is the address of the
+ * instruction whose first byte has been replaced by the "breakpoint"
+ * instruction. To avoid the SMP problems that can occur when we
+ * temporarily put back the original opcode to single-step, we
+ * single-stepped a copy of the instruction. The address of this
+ * copy is p->ainsn.insn.
+ */
+static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
+{
+ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+ regs->psw.addr &= PSW_ADDR_INSN;
+
+ if (p->ainsn.fixup & FIXUP_PSW_NORMAL)
+ regs->psw.addr = (unsigned long)p->addr +
+ ((unsigned long)regs->psw.addr -
+ (unsigned long)p->ainsn.insn);
+
+ if (p->ainsn.fixup & FIXUP_BRANCH_NOT_TAKEN)
+ if ((unsigned long)regs->psw.addr -
+ (unsigned long)p->ainsn.insn == p->ainsn.ilen)
+ regs->psw.addr = (unsigned long)p->addr + p->ainsn.ilen;
+
+ if (p->ainsn.fixup & FIXUP_RETURN_REGISTER)
+ regs->gprs[p->ainsn.reg] = ((unsigned long)p->addr +
+ (regs->gprs[p->ainsn.reg] -
+ (unsigned long)p->ainsn.insn))
+ | PSW_ADDR_AMODE;
+
+ regs->psw.addr |= PSW_ADDR_AMODE;
+ /* turn off PER mode */
+ regs->psw.mask &= ~PSW_MASK_PER;
+ /* Restore the original per control regs */
+ __ctl_load(kcb->kprobe_saved_ctl, 9, 11);
+ regs->psw.mask |= kcb->kprobe_saved_imask;
+}
+
+static int __kprobes post_kprobe_handler(struct pt_regs *regs)
+{
+ struct kprobe *cur = kprobe_running();
+ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+ if (!cur)
+ return 0;
+
+ if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) {
+ kcb->kprobe_status = KPROBE_HIT_SSDONE;
+ cur->post_handler(cur, regs, 0);
+ }
+
+ resume_execution(cur, regs);
+
+ /*Restore back the original saved kprobes variables and continue. */
+ if (kcb->kprobe_status == KPROBE_REENTER) {
+ restore_previous_kprobe(kcb);
+ goto out;
+ }
+ reset_current_kprobe();
+out:
+ preempt_enable_no_resched();
+
+ /*
+ * if somebody else is singlestepping across a probe point, psw mask
+ * will have PER set, in which case, continue the remaining processing
+ * of do_single_step, as if this is not a probe hit.
+ */
+ if (regs->psw.mask & PSW_MASK_PER) {
+ return 0;
+ }
+
+ return 1;
+}
+
+static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+{
+ struct kprobe *cur = kprobe_running();
+ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+ const struct exception_table_entry *entry;
+
+ switch(kcb->kprobe_status) {
+ case KPROBE_SWAP_INST:
+ /* We are here because the instruction replacement failed */
+ return 0;
+ case KPROBE_HIT_SS:
+ case KPROBE_REENTER:
+ /*
+ * We are here because the instruction being single
+ * stepped caused a page fault. We reset the current
+ * kprobe and the nip points back to the probe address
+ * and allow the page fault handler to continue as a
+ * normal page fault.
+ */
+ regs->psw.addr = (unsigned long)cur->addr | PSW_ADDR_AMODE;
+ regs->psw.mask &= ~PSW_MASK_PER;
+ regs->psw.mask |= kcb->kprobe_saved_imask;
+ if (kcb->kprobe_status == KPROBE_REENTER)
+ restore_previous_kprobe(kcb);
+ else
+ reset_current_kprobe();
+ preempt_enable_no_resched();
+ break;
+ case KPROBE_HIT_ACTIVE:
+ case KPROBE_HIT_SSDONE:
+ /*
+ * We increment the nmissed count for accounting,
+ * we can also use npre/npostfault count for accouting
+ * these specific fault cases.
+ */
+ kprobes_inc_nmissed_count(cur);
+
+ /*
+ * We come here because instructions in the pre/post
+ * handler caused the page_fault, this could happen
+ * if handler tries to access user space by
+ * copy_from_user(), get_user() etc. Let the
+ * user-specified handler try to fix it first.
+ */
+ if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
+ return 1;
+
+ /*
+ * In case the user-specified fault handler returned
+ * zero, try to fix up.
+ */
+ entry = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN);
+ if (entry) {
+ regs->psw.addr = entry->fixup | PSW_ADDR_AMODE;
+ return 1;
+ }
+
+ /*
+ * fixup_exception() could not handle it,
+ * Let do_page_fault() fix it.
+ */
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+/*
+ * Wrapper routine to for handling exceptions.
+ */
+int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
+ unsigned long val, void *data)
+{
+ struct die_args *args = (struct die_args *)data;
+ int ret = NOTIFY_DONE;
+
+ switch (val) {
+ case DIE_BPT:
+ if (kprobe_handler(args->regs))
+ ret = NOTIFY_STOP;
+ break;
+ case DIE_SSTEP:
+ if (post_kprobe_handler(args->regs))
+ ret = NOTIFY_STOP;
+ break;
+ case DIE_TRAP:
+ case DIE_PAGE_FAULT:
+ /* kprobe_running() needs smp_processor_id() */
+ preempt_disable();
+ if (kprobe_running() &&
+ kprobe_fault_handler(args->regs, args->trapnr))
+ ret = NOTIFY_STOP;
+ preempt_enable();
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+ struct jprobe *jp = container_of(p, struct jprobe, kp);
+ unsigned long addr;
+ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+ memcpy(&kcb->jprobe_saved_regs, regs, sizeof(struct pt_regs));
+
+ /* setup return addr to the jprobe handler routine */
+ regs->psw.addr = (unsigned long)(jp->entry) | PSW_ADDR_AMODE;
+
+ /* r14 is the function return address */
+ kcb->jprobe_saved_r14 = (unsigned long)regs->gprs[14];
+ /* r15 is the stack pointer */
+ kcb->jprobe_saved_r15 = (unsigned long)regs->gprs[15];
+ addr = (unsigned long)kcb->jprobe_saved_r15;
+
+ memcpy(kcb->jprobes_stack, (kprobe_opcode_t *) addr,
+ MIN_STACK_SIZE(addr));
+ return 1;
+}
+
+void __kprobes jprobe_return(void)
+{
+ asm volatile(".word 0x0002");
+}
+
+void __kprobes jprobe_return_end(void)
+{
+ asm volatile("bcr 0,0");
+}
+
+int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
+{
+ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+ unsigned long stack_addr = (unsigned long)(kcb->jprobe_saved_r15);
+
+ /* Put the regs back */
+ memcpy(regs, &kcb->jprobe_saved_regs, sizeof(struct pt_regs));
+ /* put the stack back */
+ memcpy((kprobe_opcode_t *) stack_addr, kcb->jprobes_stack,
+ MIN_STACK_SIZE(stack_addr));
+ preempt_enable_no_resched();
+ return 1;
+}
+
+static struct kprobe trampoline_p = {
+ .addr = (kprobe_opcode_t *) & kretprobe_trampoline,
+ .pre_handler = trampoline_probe_handler
+};
+
+int __init arch_init_kprobes(void)
+{
+ return register_kprobe(&trampoline_p);
+}
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index d3cbfa3005ec..6603fbb41d07 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -45,7 +45,7 @@
#include <asm/irq.h>
#include <asm/timer.h>
-asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
+asmlinkage void ret_from_fork(void) asm ("ret_from_fork");
/*
* Return saved PC of a blocked thread. used in kernel/sched.
@@ -177,7 +177,8 @@ void show_regs(struct pt_regs *regs)
extern void kernel_thread_starter(void);
-__asm__(".align 4\n"
+asm(
+ ".align 4\n"
"kernel_thread_starter:\n"
" la 2,0(10)\n"
" basr 14,9\n"
diff --git a/arch/s390/kernel/reipl.S b/arch/s390/kernel/reipl.S
index 658e5ac484f9..0340477f3b08 100644
--- a/arch/s390/kernel/reipl.S
+++ b/arch/s390/kernel/reipl.S
@@ -8,63 +8,82 @@
#include <asm/lowcore.h>
- .globl do_reipl
-do_reipl: basr %r13,0
+ .globl do_reipl_asm
+do_reipl_asm: basr %r13,0
.Lpg0: lpsw .Lnewpsw-.Lpg0(%r13)
-.Lpg1: lctl %c6,%c6,.Lall-.Lpg0(%r13)
- stctl %c0,%c0,.Lctlsave-.Lpg0(%r13)
- ni .Lctlsave-.Lpg0(%r13),0xef
- lctl %c0,%c0,.Lctlsave-.Lpg0(%r13)
- lr %r1,%r2
- mvc __LC_PGM_NEW_PSW(8),.Lpcnew-.Lpg0(%r13)
- stsch .Lschib-.Lpg0(%r13)
- oi .Lschib+5-.Lpg0(%r13),0x84
-.Lecs: xi .Lschib+27-.Lpg0(%r13),0x01
- msch .Lschib-.Lpg0(%r13)
- lhi %r0,5
-.Lssch: ssch .Liplorb-.Lpg0(%r13)
+
+ # switch off lowcore protection
+
+.Lpg1: stctl %c0,%c0,.Lctlsave1-.Lpg0(%r13)
+ stctl %c0,%c0,.Lctlsave2-.Lpg0(%r13)
+ ni .Lctlsave1-.Lpg0(%r13),0xef
+ lctl %c0,%c0,.Lctlsave1-.Lpg0(%r13)
+
+ # do store status of all registers
+
+ stm %r0,%r15,__LC_GPREGS_SAVE_AREA
+ stctl %c0,%c15,__LC_CREGS_SAVE_AREA
+ mvc __LC_CREGS_SAVE_AREA(4),.Lctlsave2-.Lpg0(%r13)
+ stam %a0,%a15,__LC_AREGS_SAVE_AREA
+ stpx __LC_PREFIX_SAVE_AREA
+ stckc .Lclkcmp-.Lpg0(%r13)
+ mvc __LC_CLOCK_COMP_SAVE_AREA(8),.Lclkcmp-.Lpg0(%r13)
+ stpt __LC_CPU_TIMER_SAVE_AREA
+ st %r13, __LC_PSW_SAVE_AREA+4
+
+ lctl %c6,%c6,.Lall-.Lpg0(%r13)
+ lr %r1,%r2
+ mvc __LC_PGM_NEW_PSW(8),.Lpcnew-.Lpg0(%r13)
+ stsch .Lschib-.Lpg0(%r13)
+ oi .Lschib+5-.Lpg0(%r13),0x84
+.Lecs: xi .Lschib+27-.Lpg0(%r13),0x01
+ msch .Lschib-.Lpg0(%r13)
+ lhi %r0,5
+.Lssch: ssch .Liplorb-.Lpg0(%r13)
jz .L001
- brct %r0,.Lssch
+ brct %r0,.Lssch
bas %r14,.Ldisab-.Lpg0(%r13)
-.L001: mvc __LC_IO_NEW_PSW(8),.Lionew-.Lpg0(%r13)
-.Ltpi: lpsw .Lwaitpsw-.Lpg0(%r13)
+.L001: mvc __LC_IO_NEW_PSW(8),.Lionew-.Lpg0(%r13)
+.Ltpi: lpsw .Lwaitpsw-.Lpg0(%r13)
.Lcont: c %r1,__LC_SUBCHANNEL_ID
jnz .Ltpi
clc __LC_IO_INT_PARM(4),.Liplorb-.Lpg0(%r13)
jnz .Ltpi
- tsch .Liplirb-.Lpg0(%r13)
+ tsch .Liplirb-.Lpg0(%r13)
tm .Liplirb+9-.Lpg0(%r13),0xbf
- jz .L002
- bas %r14,.Ldisab-.Lpg0(%r13)
-.L002: tm .Liplirb+8-.Lpg0(%r13),0xf3
- jz .L003
- bas %r14,.Ldisab-.Lpg0(%r13)
+ jz .L002
+ bas %r14,.Ldisab-.Lpg0(%r13)
+.L002: tm .Liplirb+8-.Lpg0(%r13),0xf3
+ jz .L003
+ bas %r14,.Ldisab-.Lpg0(%r13)
.L003: spx .Lnull-.Lpg0(%r13)
- st %r1,__LC_SUBCHANNEL_ID
- lpsw 0
- sigp 0,0,0(6)
-.Ldisab: st %r14,.Ldispsw+4-.Lpg0(%r13)
+ st %r1,__LC_SUBCHANNEL_ID
+ lpsw 0
+ sigp 0,0,0(6)
+.Ldisab: st %r14,.Ldispsw+4-.Lpg0(%r13)
lpsw .Ldispsw-.Lpg0(%r13)
- .align 8
+ .align 8
+.Lclkcmp: .quad 0x0000000000000000
.Lall: .long 0xff000000
-.Lnull: .long 0x00000000
-.Lctlsave: .long 0x00000000
- .align 8
-.Lnewpsw: .long 0x00080000,0x80000000+.Lpg1
-.Lpcnew: .long 0x00080000,0x80000000+.Lecs
-.Lionew: .long 0x00080000,0x80000000+.Lcont
+.Lnull: .long 0x00000000
+.Lctlsave1: .long 0x00000000
+.Lctlsave2: .long 0x00000000
+ .align 8
+.Lnewpsw: .long 0x00080000,0x80000000+.Lpg1
+.Lpcnew: .long 0x00080000,0x80000000+.Lecs
+.Lionew: .long 0x00080000,0x80000000+.Lcont
.Lwaitpsw: .long 0x020a0000,0x00000000+.Ltpi
-.Ldispsw: .long 0x000a0000,0x00000000
-.Liplccws: .long 0x02000000,0x60000018
- .long 0x08000008,0x20000001
+.Ldispsw: .long 0x000a0000,0x00000000
+.Liplccws: .long 0x02000000,0x60000018
+ .long 0x08000008,0x20000001
.Liplorb: .long 0x0049504c,0x0040ff80
.long 0x00000000+.Liplccws
-.Lschib: .long 0x00000000,0x00000000
- .long 0x00000000,0x00000000
- .long 0x00000000,0x00000000
- .long 0x00000000,0x00000000
- .long 0x00000000,0x00000000
- .long 0x00000000,0x00000000
+.Lschib: .long 0x00000000,0x00000000
+ .long 0x00000000,0x00000000
+ .long 0x00000000,0x00000000
+ .long 0x00000000,0x00000000
+ .long 0x00000000,0x00000000
+ .long 0x00000000,0x00000000
.Liplirb: .long 0x00000000,0x00000000
.long 0x00000000,0x00000000
.long 0x00000000,0x00000000
@@ -73,6 +92,3 @@ do_reipl: basr %r13,0
.long 0x00000000,0x00000000
.long 0x00000000,0x00000000
.long 0x00000000,0x00000000
-
-
-
diff --git a/arch/s390/kernel/reipl64.S b/arch/s390/kernel/reipl64.S
index 4d090d60f3ef..de7435054f7c 100644
--- a/arch/s390/kernel/reipl64.S
+++ b/arch/s390/kernel/reipl64.S
@@ -4,56 +4,74 @@
* 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)
+ Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
*/
#include <asm/lowcore.h>
- .globl do_reipl
-do_reipl: basr %r13,0
-.Lpg0: lpswe .Lnewpsw-.Lpg0(%r13)
+ .globl do_reipl_asm
+do_reipl_asm: basr %r13,0
+
+ # do store status of all registers
+
+.Lpg0: stg %r1,.Lregsave-.Lpg0(%r13)
+ lghi %r1,0x1000
+ stmg %r0,%r15,__LC_GPREGS_SAVE_AREA-0x1000(%r1)
+ lg %r0,.Lregsave-.Lpg0(%r13)
+ stg %r0,__LC_GPREGS_SAVE_AREA-0x1000+8(%r1)
+ stctg %c0,%c15,__LC_CREGS_SAVE_AREA-0x1000(%r1)
+ stam %a0,%a15,__LC_AREGS_SAVE_AREA-0x1000(%r1)
+ stpx __LC_PREFIX_SAVE_AREA-0x1000(%r1)
+ stfpc __LC_FP_CREG_SAVE_AREA-0x1000(%r1)
+ stckc .Lclkcmp-.Lpg0(%r13)
+ mvc __LC_CLOCK_COMP_SAVE_AREA-0x1000(8,%r1),.Lclkcmp-.Lpg0(%r13)
+ stpt __LC_CPU_TIMER_SAVE_AREA-0x1000(%r1)
+ stg %r13, __LC_PSW_SAVE_AREA-0x1000+8(%r1)
+
+ lpswe .Lnewpsw-.Lpg0(%r13)
.Lpg1: lctlg %c6,%c6,.Lall-.Lpg0(%r13)
- stctg %c0,%c0,.Lctlsave-.Lpg0(%r13)
- ni .Lctlsave+4-.Lpg0(%r13),0xef
- lctlg %c0,%c0,.Lctlsave-.Lpg0(%r13)
- lgr %r1,%r2
- mvc __LC_PGM_NEW_PSW(16),.Lpcnew-.Lpg0(%r13)
- stsch .Lschib-.Lpg0(%r13)
- oi .Lschib+5-.Lpg0(%r13),0x84
-.Lecs: xi .Lschib+27-.Lpg0(%r13),0x01
- msch .Lschib-.Lpg0(%r13)
- lghi %r0,5
-.Lssch: ssch .Liplorb-.Lpg0(%r13)
+ stctg %c0,%c0,.Lregsave-.Lpg0(%r13)
+ ni .Lregsave+4-.Lpg0(%r13),0xef
+ lctlg %c0,%c0,.Lregsave-.Lpg0(%r13)
+ lgr %r1,%r2
+ mvc __LC_PGM_NEW_PSW(16),.Lpcnew-.Lpg0(%r13)
+ stsch .Lschib-.Lpg0(%r13)
+ oi .Lschib+5-.Lpg0(%r13),0x84
+.Lecs: xi .Lschib+27-.Lpg0(%r13),0x01
+ msch .Lschib-.Lpg0(%r13)
+ lghi %r0,5
+.Lssch: ssch .Liplorb-.Lpg0(%r13)
jz .L001
- brct %r0,.Lssch
+ brct %r0,.Lssch
bas %r14,.Ldisab-.Lpg0(%r13)
-.L001: mvc __LC_IO_NEW_PSW(16),.Lionew-.Lpg0(%r13)
-.Ltpi: lpswe .Lwaitpsw-.Lpg0(%r13)
+.L001: mvc __LC_IO_NEW_PSW(16),.Lionew-.Lpg0(%r13)
+.Ltpi: lpswe .Lwaitpsw-.Lpg0(%r13)
.Lcont: c %r1,__LC_SUBCHANNEL_ID
jnz .Ltpi
clc __LC_IO_INT_PARM(4),.Liplorb-.Lpg0(%r13)
jnz .Ltpi
- tsch .Liplirb-.Lpg0(%r13)
+ tsch .Liplirb-.Lpg0(%r13)
tm .Liplirb+9-.Lpg0(%r13),0xbf
- jz .L002
- bas %r14,.Ldisab-.Lpg0(%r13)
-.L002: tm .Liplirb+8-.Lpg0(%r13),0xf3
- jz .L003
- bas %r14,.Ldisab-.Lpg0(%r13)
+ jz .L002
+ bas %r14,.Ldisab-.Lpg0(%r13)
+.L002: tm .Liplirb+8-.Lpg0(%r13),0xf3
+ jz .L003
+ bas %r14,.Ldisab-.Lpg0(%r13)
.L003: spx .Lnull-.Lpg0(%r13)
- st %r1,__LC_SUBCHANNEL_ID
- lhi %r1,0 # mode 0 = esa
- slr %r0,%r0 # set cpuid to zero
- sigp %r1,%r0,0x12 # switch to esa mode
- lpsw 0
-.Ldisab: sll %r14,1
- srl %r14,1 # need to kill hi bit to avoid specification exceptions.
- st %r14,.Ldispsw+12-.Lpg0(%r13)
+ st %r1,__LC_SUBCHANNEL_ID
+ lhi %r1,0 # mode 0 = esa
+ slr %r0,%r0 # set cpuid to zero
+ sigp %r1,%r0,0x12 # switch to esa mode
+ lpsw 0
+.Ldisab: sll %r14,1
+ srl %r14,1 # need to kill hi bit to avoid specification exceptions.
+ st %r14,.Ldispsw+12-.Lpg0(%r13)
lpswe .Ldispsw-.Lpg0(%r13)
- .align 8
+ .align 8
+.Lclkcmp: .quad 0x0000000000000000
.Lall: .quad 0x00000000ff000000
-.Lctlsave: .quad 0x0000000000000000
-.Lnull: .long 0x0000000000000000
- .align 16
+.Lregsave: .quad 0x0000000000000000
+.Lnull: .long 0x0000000000000000
+ .align 16
/*
* These addresses have to be 31 bit otherwise
* the sigp will throw a specifcation exception
@@ -63,26 +81,26 @@ do_reipl: basr %r13,0
* 31bit lpswe instruction a fact they appear to have
* ommited from the pop.
*/
-.Lnewpsw: .quad 0x0000000080000000
- .quad .Lpg1
-.Lpcnew: .quad 0x0000000080000000
- .quad .Lecs
-.Lionew: .quad 0x0000000080000000
- .quad .Lcont
+.Lnewpsw: .quad 0x0000000080000000
+ .quad .Lpg1
+.Lpcnew: .quad 0x0000000080000000
+ .quad .Lecs
+.Lionew: .quad 0x0000000080000000
+ .quad .Lcont
.Lwaitpsw: .quad 0x0202000080000000
- .quad .Ltpi
-.Ldispsw: .quad 0x0002000080000000
- .quad 0x0000000000000000
-.Liplccws: .long 0x02000000,0x60000018
- .long 0x08000008,0x20000001
+ .quad .Ltpi
+.Ldispsw: .quad 0x0002000080000000
+ .quad 0x0000000000000000
+.Liplccws: .long 0x02000000,0x60000018
+ .long 0x08000008,0x20000001
.Liplorb: .long 0x0049504c,0x0040ff80
.long 0x00000000+.Liplccws
-.Lschib: .long 0x00000000,0x00000000
- .long 0x00000000,0x00000000
- .long 0x00000000,0x00000000
- .long 0x00000000,0x00000000
- .long 0x00000000,0x00000000
- .long 0x00000000,0x00000000
+.Lschib: .long 0x00000000,0x00000000
+ .long 0x00000000,0x00000000
+ .long 0x00000000,0x00000000
+ .long 0x00000000,0x00000000
+ .long 0x00000000,0x00000000
+ .long 0x00000000,0x00000000
.Liplirb: .long 0x00000000,0x00000000
.long 0x00000000,0x00000000
.long 0x00000000,0x00000000
@@ -91,6 +109,3 @@ do_reipl: basr %r13,0
.long 0x00000000,0x00000000
.long 0x00000000,0x00000000
.long 0x00000000,0x00000000
-
-
-
diff --git a/arch/s390/kernel/reipl_diag.c b/arch/s390/kernel/reipl_diag.c
deleted file mode 100644
index 1f33951ba439..000000000000
--- a/arch/s390/kernel/reipl_diag.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * This file contains the implementation of the
- * Linux re-IPL support
- *
- * (C) Copyright IBM Corp. 2005
- *
- * Author(s): Volker Sameske (sameske@de.ibm.com)
- *
- */
-
-#include <linux/kernel.h>
-
-static unsigned int reipl_diag_rc1;
-static unsigned int reipl_diag_rc2;
-
-/*
- * re-IPL the system using the last used IPL parameters
- */
-void reipl_diag(void)
-{
- asm volatile (
- " la %%r4,0\n"
- " la %%r5,0\n"
- " diag %%r4,%2,0x308\n"
- "0:\n"
- " st %%r4,%0\n"
- " st %%r5,%1\n"
- ".section __ex_table,\"a\"\n"
-#ifdef CONFIG_64BIT
- " .align 8\n"
- " .quad 0b, 0b\n"
-#else
- " .align 4\n"
- " .long 0b, 0b\n"
-#endif
- ".previous\n"
- : "=m" (reipl_diag_rc1), "=m" (reipl_diag_rc2)
- : "d" (3) : "cc", "4", "5" );
-}
diff --git a/arch/s390/kernel/relocate_kernel.S b/arch/s390/kernel/relocate_kernel.S
index 2a25ec7147ff..f9899ff2e5b0 100644
--- a/arch/s390/kernel/relocate_kernel.S
+++ b/arch/s390/kernel/relocate_kernel.S
@@ -3,7 +3,7 @@
*
* (C) Copyright IBM Corp. 2005
*
- * Author(s): Rolf Adelsberger <adelsberger@de.ibm.com>
+ * Author(s): Rolf Adelsberger,
* Heiko Carstens <heiko.carstens@de.ibm.com>
*
*/
@@ -24,14 +24,14 @@
.text
.globl relocate_kernel
relocate_kernel:
- basr %r13,0 #base address
+ basr %r13,0 # base address
.base:
- stnsm sys_msk-.base(%r13),0xf8 #disable DAT and IRQ (external)
- spx zero64-.base(%r13) #absolute addressing mode
+ stnsm sys_msk-.base(%r13),0xf8 # disable DAT and IRQ (external)
+ spx zero64-.base(%r13) # absolute addressing mode
stctl %c0,%c15,ctlregs-.base(%r13)
stm %r0,%r15,gprregs-.base(%r13)
la %r1,load_psw-.base(%r13)
- mvc 0(8,%r0),0(%r1)
+ mvc 0(8,%r0),0(%r1)
la %r0,.back-.base(%r13)
st %r0,4(%r0)
oi 4(%r0),0x80
@@ -51,50 +51,50 @@
.back_pgm:
lm %r0,%r15,gprregs-.base(%r13)
.start_reloc:
- lhi %r10,-1 #preparing the mask
- sll %r10,12 #shift it such that it becomes 0xf000
+ lhi %r10,-1 # preparing the mask
+ sll %r10,12 # shift it such that it becomes 0xf000
.top:
- lhi %r7,4096 #load PAGE_SIZE in r7
- lhi %r9,4096 #load PAGE_SIZE in r9
- l %r5,0(%r2) #read another word for indirection page
- ahi %r2,4 #increment pointer
- tml %r5,0x1 #is it a destination page?
- je .indir_check #NO, goto "indir_check"
- lr %r6,%r5 #r6 = r5
- nr %r6,%r10 #mask it out and...
- j .top #...next iteration
+ lhi %r7,4096 # load PAGE_SIZE in r7
+ lhi %r9,4096 # load PAGE_SIZE in r9
+ l %r5,0(%r2) # read another word for indirection page
+ ahi %r2,4 # increment pointer
+ tml %r5,0x1 # is it a destination page?
+ je .indir_check # NO, goto "indir_check"
+ lr %r6,%r5 # r6 = r5
+ nr %r6,%r10 # mask it out and...
+ j .top # ...next iteration
.indir_check:
- tml %r5,0x2 #is it a indirection page?
- je .done_test #NO, goto "done_test"
- nr %r5,%r10 #YES, mask out,
- lr %r2,%r5 #move it into the right register,
- j .top #and read next...
+ tml %r5,0x2 # is it a indirection page?
+ je .done_test # NO, goto "done_test"
+ nr %r5,%r10 # YES, mask out,
+ lr %r2,%r5 # move it into the right register,
+ j .top # and read next...
.done_test:
- tml %r5,0x4 #is it the done indicator?
- je .source_test #NO! Well, then it should be the source indicator...
- j .done #ok, lets finish it here...
+ tml %r5,0x4 # is it the done indicator?
+ je .source_test # NO! Well, then it should be the source indicator...
+ j .done # ok, lets finish it here...
.source_test:
- tml %r5,0x8 #it should be a source indicator...
- je .top #NO, ignore it...
- lr %r8,%r5 #r8 = r5
- nr %r8,%r10 #masking
- 0: mvcle %r6,%r8,0x0 #copy PAGE_SIZE bytes from r8 to r6 - pad with 0
+ tml %r5,0x8 # it should be a source indicator...
+ je .top # NO, ignore it...
+ lr %r8,%r5 # r8 = r5
+ nr %r8,%r10 # masking
+ 0: mvcle %r6,%r8,0x0 # copy PAGE_SIZE bytes from r8 to r6 - pad with 0
jo 0b
j .top
.done:
- sr %r0,%r0 #clear register r0
- la %r4,load_psw-.base(%r13) #load psw-address into the register
- o %r3,4(%r4) #or load address into psw
+ sr %r0,%r0 # clear register r0
+ la %r4,load_psw-.base(%r13) # load psw-address into the register
+ o %r3,4(%r4) # or load address into psw
st %r3,4(%r4)
- mvc 0(8,%r0),0(%r4) #copy psw to absolute address 0
+ mvc 0(8,%r0),0(%r4) # copy psw to absolute address 0
tm have_diag308-.base(%r13),0x01
jno .no_diag308
diag %r0,%r0,0x308
.no_diag308:
- sr %r1,%r1 #clear %r1
- sr %r2,%r2 #clear %r2
- sigp %r1,%r2,0x12 #set cpuid to zero
- lpsw 0 #hopefully start new kernel...
+ sr %r1,%r1 # clear %r1
+ sr %r2,%r2 # clear %r2
+ sigp %r1,%r2,0x12 # set cpuid to zero
+ lpsw 0 # hopefully start new kernel...
.align 8
zero64:
diff --git a/arch/s390/kernel/relocate_kernel64.S b/arch/s390/kernel/relocate_kernel64.S
index 8cdb86e8911f..4fb443042d9c 100644
--- a/arch/s390/kernel/relocate_kernel64.S
+++ b/arch/s390/kernel/relocate_kernel64.S
@@ -3,7 +3,7 @@
*
* (C) Copyright IBM Corp. 2005
*
- * Author(s): Rolf Adelsberger <adelsberger@de.ibm.com>
+ * Author(s): Rolf Adelsberger,
* Heiko Carstens <heiko.carstens@de.ibm.com>
*
*/
@@ -25,10 +25,10 @@
.text
.globl relocate_kernel
relocate_kernel:
- basr %r13,0 #base address
+ basr %r13,0 # base address
.base:
- stnsm sys_msk-.base(%r13),0xf8 #disable DAT and IRQs
- spx zero64-.base(%r13) #absolute addressing mode
+ stnsm sys_msk-.base(%r13),0xf8 # disable DAT and IRQs
+ spx zero64-.base(%r13) # absolute addressing mode
stctg %c0,%c15,ctlregs-.base(%r13)
stmg %r0,%r15,gprregs-.base(%r13)
lghi %r0,3
@@ -37,16 +37,16 @@
la %r0,.back_pgm-.base(%r13)
stg %r0,0x1d8(%r0)
la %r1,load_psw-.base(%r13)
- mvc 0(8,%r0),0(%r1)
+ mvc 0(8,%r0),0(%r1)
la %r0,.back-.base(%r13)
st %r0,4(%r0)
oi 4(%r0),0x80
lghi %r0,0
diag %r0,%r0,0x308
.back:
- lhi %r1,1 #mode 1 = esame
- sigp %r1,%r0,0x12 #switch to esame mode
- sam64 #switch to 64 bit addressing mode
+ lhi %r1,1 # mode 1 = esame
+ sigp %r1,%r0,0x12 # switch to esame mode
+ sam64 # switch to 64 bit addressing mode
basr %r13,0
.back_base:
oi have_diag308-.back_base(%r13),0x01
@@ -56,50 +56,50 @@
.back_pgm:
lmg %r0,%r15,gprregs-.base(%r13)
.top:
- lghi %r7,4096 #load PAGE_SIZE in r7
- lghi %r9,4096 #load PAGE_SIZE in r9
- lg %r5,0(%r2) #read another word for indirection page
- aghi %r2,8 #increment pointer
- tml %r5,0x1 #is it a destination page?
- je .indir_check #NO, goto "indir_check"
- lgr %r6,%r5 #r6 = r5
- nill %r6,0xf000 #mask it out and...
- j .top #...next iteration
+ lghi %r7,4096 # load PAGE_SIZE in r7
+ lghi %r9,4096 # load PAGE_SIZE in r9
+ lg %r5,0(%r2) # read another word for indirection page
+ aghi %r2,8 # increment pointer
+ tml %r5,0x1 # is it a destination page?
+ je .indir_check # NO, goto "indir_check"
+ lgr %r6,%r5 # r6 = r5
+ nill %r6,0xf000 # mask it out and...
+ j .top # ...next iteration
.indir_check:
- tml %r5,0x2 #is it a indirection page?
- je .done_test #NO, goto "done_test"
- nill %r5,0xf000 #YES, mask out,
- lgr %r2,%r5 #move it into the right register,
- j .top #and read next...
+ tml %r5,0x2 # is it a indirection page?
+ je .done_test # NO, goto "done_test"
+ nill %r5,0xf000 # YES, mask out,
+ lgr %r2,%r5 # move it into the right register,
+ j .top # and read next...
.done_test:
- tml %r5,0x4 #is it the done indicator?
- je .source_test #NO! Well, then it should be the source indicator...
- j .done #ok, lets finish it here...
+ tml %r5,0x4 # is it the done indicator?
+ je .source_test # NO! Well, then it should be the source indicator...
+ j .done # ok, lets finish it here...
.source_test:
- tml %r5,0x8 #it should be a source indicator...
- je .top #NO, ignore it...
- lgr %r8,%r5 #r8 = r5
- nill %r8,0xf000 #masking
- 0: mvcle %r6,%r8,0x0 #copy PAGE_SIZE bytes from r8 to r6 - pad with 0
+ tml %r5,0x8 # it should be a source indicator...
+ je .top # NO, ignore it...
+ lgr %r8,%r5 # r8 = r5
+ nill %r8,0xf000 # masking
+ 0: mvcle %r6,%r8,0x0 # copy PAGE_SIZE bytes from r8 to r6 - pad with 0
jo 0b
- j .top
+ j .top
.done:
- sgr %r0,%r0 #clear register r0
- la %r4,load_psw-.base(%r13) #load psw-address into the register
- o %r3,4(%r4) #or load address into psw
+ sgr %r0,%r0 # clear register r0
+ la %r4,load_psw-.base(%r13) # load psw-address into the register
+ o %r3,4(%r4) # or load address into psw
st %r3,4(%r4)
- mvc 0(8,%r0),0(%r4) #copy psw to absolute address 0
+ mvc 0(8,%r0),0(%r4) # copy psw to absolute address 0
tm have_diag308-.base(%r13),0x01
jno .no_diag308
diag %r0,%r0,0x308
.no_diag308:
- sam31 #31 bit mode
- sr %r1,%r1 #erase register r1
- sr %r2,%r2 #erase register r2
- sigp %r1,%r2,0x12 #set cpuid to zero
- lpsw 0 #hopefully start new kernel...
+ sam31 # 31 bit mode
+ sr %r1,%r1 # erase register r1
+ sr %r2,%r2 # erase register r2
+ sigp %r1,%r2,0x12 # set cpuid to zero
+ lpsw 0 # hopefully start new kernel...
- .align 8
+ .align 8
zero64:
.quad 0
load_psw:
diff --git a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c
index c73a45467fa4..9f19e833a562 100644
--- a/arch/s390/kernel/s390_ksyms.c
+++ b/arch/s390/kernel/s390_ksyms.c
@@ -25,12 +25,6 @@ EXPORT_SYMBOL(_oi_bitmap);
EXPORT_SYMBOL(_ni_bitmap);
EXPORT_SYMBOL(_zb_findmap);
EXPORT_SYMBOL(_sb_findmap);
-EXPORT_SYMBOL(__copy_from_user_asm);
-EXPORT_SYMBOL(__copy_to_user_asm);
-EXPORT_SYMBOL(__copy_in_user_asm);
-EXPORT_SYMBOL(__clear_user_asm);
-EXPORT_SYMBOL(__strncpy_from_user_asm);
-EXPORT_SYMBOL(__strnlen_user_asm);
EXPORT_SYMBOL(diag10);
/*
diff --git a/arch/s390/kernel/semaphore.c b/arch/s390/kernel/semaphore.c
index 8dfb690c159f..191303f6c1d8 100644
--- a/arch/s390/kernel/semaphore.c
+++ b/arch/s390/kernel/semaphore.c
@@ -26,17 +26,17 @@ static inline int __sem_update_count(struct semaphore *sem, int incr)
{
int old_val, new_val;
- __asm__ __volatile__(" l %0,0(%3)\n"
- "0: ltr %1,%0\n"
- " jhe 1f\n"
- " lhi %1,0\n"
- "1: ar %1,%4\n"
- " cs %0,%1,0(%3)\n"
- " jl 0b\n"
- : "=&d" (old_val), "=&d" (new_val),
- "=m" (sem->count)
- : "a" (&sem->count), "d" (incr), "m" (sem->count)
- : "cc" );
+ asm volatile(
+ " l %0,0(%3)\n"
+ "0: ltr %1,%0\n"
+ " jhe 1f\n"
+ " lhi %1,0\n"
+ "1: ar %1,%4\n"
+ " cs %0,%1,0(%3)\n"
+ " jl 0b\n"
+ : "=&d" (old_val), "=&d" (new_val), "=m" (sem->count)
+ : "a" (&sem->count), "d" (incr), "m" (sem->count)
+ : "cc");
return old_val;
}
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index c902f059c7aa..a21cfbb9d97e 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -37,6 +37,7 @@
#include <linux/kernel_stat.h>
#include <linux/device.h>
#include <linux/notifier.h>
+#include <linux/pfn.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -50,6 +51,12 @@
#include <asm/sections.h>
/*
+ * User copy operations.
+ */
+struct uaccess_ops uaccess;
+EXPORT_SYMBOL_GPL(uaccess);
+
+/*
* Machine setup..
*/
unsigned int console_mode = 0;
@@ -94,7 +101,7 @@ void __devinit cpu_init (void)
/*
* Store processor id in lowcore (used e.g. in timer_interrupt)
*/
- asm volatile ("stidp %0": "=m" (S390_lowcore.cpu_data.cpu_id));
+ asm volatile("stidp %0": "=m" (S390_lowcore.cpu_data.cpu_id));
S390_lowcore.cpu_data.cpu_addr = addr;
/*
@@ -284,16 +291,9 @@ void (*_machine_power_off)(void) = machine_power_off_smp;
/*
* Reboot, halt and power_off routines for non SMP.
*/
-extern void reipl(unsigned long devno);
-extern void reipl_diag(void);
static void do_machine_restart_nonsmp(char * __unused)
{
- reipl_diag();
-
- if (MACHINE_IS_VM)
- cpcmd ("IPL", NULL, 0, NULL);
- else
- reipl (0x10000 | S390_lowcore.ipl_device);
+ do_reipl();
}
static void do_machine_halt_nonsmp(void)
@@ -501,13 +501,47 @@ setup_memory(void)
* partially used pages are not usable - thus
* we are rounding upwards:
*/
- start_pfn = (__pa(&_end) + PAGE_SIZE - 1) >> PAGE_SHIFT;
- end_pfn = max_pfn = memory_end >> PAGE_SHIFT;
+ start_pfn = PFN_UP(__pa(&_end));
+ end_pfn = max_pfn = PFN_DOWN(memory_end);
/* Initialize storage key for kernel pages */
for (init_pfn = 0 ; init_pfn < start_pfn; init_pfn++)
page_set_storage_key(init_pfn << PAGE_SHIFT, PAGE_DEFAULT_KEY);
+#ifdef CONFIG_BLK_DEV_INITRD
+ /*
+ * Move the initrd in case the bitmap of the bootmem allocater
+ * would overwrite it.
+ */
+
+ if (INITRD_START && INITRD_SIZE) {
+ unsigned long bmap_size;
+ unsigned long start;
+
+ bmap_size = bootmem_bootmap_pages(end_pfn - start_pfn + 1);
+ bmap_size = PFN_PHYS(bmap_size);
+
+ if (PFN_PHYS(start_pfn) + bmap_size > INITRD_START) {
+ start = PFN_PHYS(start_pfn) + bmap_size + PAGE_SIZE;
+
+ if (start + INITRD_SIZE > memory_end) {
+ printk("initrd extends beyond end of memory "
+ "(0x%08lx > 0x%08lx)\n"
+ "disabling initrd\n",
+ start + INITRD_SIZE, memory_end);
+ INITRD_START = INITRD_SIZE = 0;
+ } else {
+ printk("Moving initrd (0x%08lx -> 0x%08lx, "
+ "size: %ld)\n",
+ INITRD_START, start, INITRD_SIZE);
+ memmove((void *) start, (void *) INITRD_START,
+ INITRD_SIZE);
+ INITRD_START = start;
+ }
+ }
+ }
+#endif
+
/*
* Initialize the boot-time allocator (with low memory only):
*/
@@ -559,7 +593,7 @@ setup_memory(void)
reserve_bootmem(start_pfn << PAGE_SHIFT, bootmap_size);
#ifdef CONFIG_BLK_DEV_INITRD
- if (INITRD_START) {
+ if (INITRD_START && INITRD_SIZE) {
if (INITRD_START + INITRD_SIZE <= memory_end) {
reserve_bootmem(INITRD_START, INITRD_SIZE);
initrd_start = INITRD_START;
@@ -613,6 +647,11 @@ setup_arch(char **cmdline_p)
memory_end = memory_size;
+ if (MACHINE_HAS_MVCOS)
+ memcpy(&uaccess, &uaccess_mvcos, sizeof(uaccess));
+ else
+ memcpy(&uaccess, &uaccess_std, sizeof(uaccess));
+
parse_early_param();
#ifndef CONFIG_64BIT
@@ -720,214 +759,3 @@ struct seq_operations cpuinfo_op = {
.show = show_cpuinfo,
};
-#define DEFINE_IPL_ATTR(_name, _format, _value) \
-static ssize_t ipl_##_name##_show(struct subsystem *subsys, \
- char *page) \
-{ \
- return sprintf(page, _format, _value); \
-} \
-static struct subsys_attribute ipl_##_name##_attr = \
- __ATTR(_name, S_IRUGO, ipl_##_name##_show, NULL);
-
-DEFINE_IPL_ATTR(wwpn, "0x%016llx\n", (unsigned long long)
- IPL_PARMBLOCK_START->fcp.wwpn);
-DEFINE_IPL_ATTR(lun, "0x%016llx\n", (unsigned long long)
- IPL_PARMBLOCK_START->fcp.lun);
-DEFINE_IPL_ATTR(bootprog, "%lld\n", (unsigned long long)
- IPL_PARMBLOCK_START->fcp.bootprog);
-DEFINE_IPL_ATTR(br_lba, "%lld\n", (unsigned long long)
- IPL_PARMBLOCK_START->fcp.br_lba);
-
-enum ipl_type_type {
- ipl_type_unknown,
- ipl_type_ccw,
- ipl_type_fcp,
-};
-
-static enum ipl_type_type
-get_ipl_type(void)
-{
- struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
-
- if (!IPL_DEVNO_VALID)
- return ipl_type_unknown;
- if (!IPL_PARMBLOCK_VALID)
- return ipl_type_ccw;
- if (ipl->hdr.header.version > IPL_MAX_SUPPORTED_VERSION)
- return ipl_type_unknown;
- if (ipl->fcp.pbt != IPL_TYPE_FCP)
- return ipl_type_unknown;
- return ipl_type_fcp;
-}
-
-static ssize_t
-ipl_type_show(struct subsystem *subsys, char *page)
-{
- switch (get_ipl_type()) {
- case ipl_type_ccw:
- return sprintf(page, "ccw\n");
- case ipl_type_fcp:
- return sprintf(page, "fcp\n");
- default:
- return sprintf(page, "unknown\n");
- }
-}
-
-static struct subsys_attribute ipl_type_attr = __ATTR_RO(ipl_type);
-
-static ssize_t
-ipl_device_show(struct subsystem *subsys, char *page)
-{
- struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
-
- switch (get_ipl_type()) {
- case ipl_type_ccw:
- return sprintf(page, "0.0.%04x\n", ipl_devno);
- case ipl_type_fcp:
- return sprintf(page, "0.0.%04x\n", ipl->fcp.devno);
- default:
- return 0;
- }
-}
-
-static struct subsys_attribute ipl_device_attr =
- __ATTR(device, S_IRUGO, ipl_device_show, NULL);
-
-static struct attribute *ipl_fcp_attrs[] = {
- &ipl_type_attr.attr,
- &ipl_device_attr.attr,
- &ipl_wwpn_attr.attr,
- &ipl_lun_attr.attr,
- &ipl_bootprog_attr.attr,
- &ipl_br_lba_attr.attr,
- NULL,
-};
-
-static struct attribute_group ipl_fcp_attr_group = {
- .attrs = ipl_fcp_attrs,
-};
-
-static struct attribute *ipl_ccw_attrs[] = {
- &ipl_type_attr.attr,
- &ipl_device_attr.attr,
- NULL,
-};
-
-static struct attribute_group ipl_ccw_attr_group = {
- .attrs = ipl_ccw_attrs,
-};
-
-static struct attribute *ipl_unknown_attrs[] = {
- &ipl_type_attr.attr,
- NULL,
-};
-
-static struct attribute_group ipl_unknown_attr_group = {
- .attrs = ipl_unknown_attrs,
-};
-
-static ssize_t
-ipl_parameter_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
-{
- unsigned int size = IPL_PARMBLOCK_SIZE;
-
- if (off > size)
- return 0;
- if (off + count > size)
- count = size - off;
-
- memcpy(buf, (void *) IPL_PARMBLOCK_START + off, count);
- return count;
-}
-
-static struct bin_attribute ipl_parameter_attr = {
- .attr = {
- .name = "binary_parameter",
- .mode = S_IRUGO,
- .owner = THIS_MODULE,
- },
- .size = PAGE_SIZE,
- .read = &ipl_parameter_read,
-};
-
-static ssize_t
-ipl_scp_data_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
-{
- unsigned int size = IPL_PARMBLOCK_START->fcp.scp_data_len;
- void *scp_data = &IPL_PARMBLOCK_START->fcp.scp_data;
-
- if (off > size)
- return 0;
- if (off + count > size)
- count = size - off;
-
- memcpy(buf, scp_data + off, count);
- return count;
-}
-
-static struct bin_attribute ipl_scp_data_attr = {
- .attr = {
- .name = "scp_data",
- .mode = S_IRUGO,
- .owner = THIS_MODULE,
- },
- .size = PAGE_SIZE,
- .read = &ipl_scp_data_read,
-};
-
-static decl_subsys(ipl, NULL, NULL);
-
-static int ipl_register_fcp_files(void)
-{
- int rc;
-
- rc = sysfs_create_group(&ipl_subsys.kset.kobj,
- &ipl_fcp_attr_group);
- if (rc)
- goto out;
- rc = sysfs_create_bin_file(&ipl_subsys.kset.kobj,
- &ipl_parameter_attr);
- if (rc)
- goto out_ipl_parm;
- rc = sysfs_create_bin_file(&ipl_subsys.kset.kobj,
- &ipl_scp_data_attr);
- if (!rc)
- goto out;
-
- sysfs_remove_bin_file(&ipl_subsys.kset.kobj, &ipl_parameter_attr);
-
-out_ipl_parm:
- sysfs_remove_group(&ipl_subsys.kset.kobj, &ipl_fcp_attr_group);
-out:
- return rc;
-}
-
-static int __init
-ipl_device_sysfs_register(void) {
- int rc;
-
- rc = firmware_register(&ipl_subsys);
- if (rc)
- goto out;
-
- switch (get_ipl_type()) {
- case ipl_type_ccw:
- rc = sysfs_create_group(&ipl_subsys.kset.kobj,
- &ipl_ccw_attr_group);
- break;
- case ipl_type_fcp:
- rc = ipl_register_fcp_files();
- break;
- default:
- rc = sysfs_create_group(&ipl_subsys.kset.kobj,
- &ipl_unknown_attr_group);
- break;
- }
-
- if (rc)
- firmware_unregister(&ipl_subsys);
-out:
- return rc;
-}
-
-__initcall(ipl_device_sysfs_register);
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index a887b686f279..642095ec7c07 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -114,29 +114,26 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
static int save_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
{
unsigned long old_mask = regs->psw.mask;
- int err;
-
+ _sigregs user_sregs;
+
save_access_regs(current->thread.acrs);
/* Copy a 'clean' PSW mask to the user to avoid leaking
information about whether PER is currently on. */
regs->psw.mask = PSW_MASK_MERGE(PSW_USER_BITS, regs->psw.mask);
- err = __copy_to_user(&sregs->regs.psw, &regs->psw,
- sizeof(sregs->regs.psw)+sizeof(sregs->regs.gprs));
+ memcpy(&user_sregs.regs.psw, &regs->psw, sizeof(sregs->regs.psw) +
+ sizeof(sregs->regs.gprs));
regs->psw.mask = old_mask;
- if (err != 0)
- return err;
- err = __copy_to_user(&sregs->regs.acrs, current->thread.acrs,
- sizeof(sregs->regs.acrs));
- if (err != 0)
- return err;
+ memcpy(&user_sregs.regs.acrs, current->thread.acrs,
+ sizeof(sregs->regs.acrs));
/*
* We have to store the fp registers to current->thread.fp_regs
* to merge them with the emulated registers.
*/
save_fp_regs(&current->thread.fp_regs);
- return __copy_to_user(&sregs->fpregs, &current->thread.fp_regs,
- sizeof(s390_fp_regs));
+ memcpy(&user_sregs.fpregs, &current->thread.fp_regs,
+ sizeof(s390_fp_regs));
+ return __copy_to_user(sregs, &user_sregs, sizeof(_sigregs));
}
/* Returns positive number on error */
@@ -144,27 +141,25 @@ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
{
unsigned long old_mask = regs->psw.mask;
int err;
+ _sigregs user_sregs;
/* Alwys make any pending restarted system call return -EINTR */
current_thread_info()->restart_block.fn = do_no_restart_syscall;
- err = __copy_from_user(&regs->psw, &sregs->regs.psw,
- sizeof(sregs->regs.psw)+sizeof(sregs->regs.gprs));
+ err = __copy_from_user(&user_sregs, sregs, sizeof(_sigregs));
regs->psw.mask = PSW_MASK_MERGE(old_mask, regs->psw.mask);
regs->psw.addr |= PSW_ADDR_AMODE;
if (err)
return err;
- err = __copy_from_user(&current->thread.acrs, &sregs->regs.acrs,
- sizeof(sregs->regs.acrs));
- if (err)
- return err;
+ memcpy(&regs->psw, &user_sregs.regs.psw, sizeof(sregs->regs.psw) +
+ sizeof(sregs->regs.gprs));
+ memcpy(&current->thread.acrs, &user_sregs.regs.acrs,
+ sizeof(sregs->regs.acrs));
restore_access_regs(current->thread.acrs);
- err = __copy_from_user(&current->thread.fp_regs, &sregs->fpregs,
- sizeof(s390_fp_regs));
+ memcpy(&current->thread.fp_regs, &user_sregs.fpregs,
+ sizeof(s390_fp_regs));
current->thread.fp_regs.fpc &= FPC_VALID_MASK;
- if (err)
- return err;
restore_fp_regs(&current->thread.fp_regs);
regs->trap = -1; /* disable syscall checks */
@@ -457,6 +452,7 @@ void do_signal(struct pt_regs *regs)
case -ERESTART_RESTARTBLOCK:
regs->gprs[2] = -EINTR;
}
+ regs->trap = -1; /* Don't deal with this again. */
}
/* Get signal to deliver. When running under ptrace, at this point
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 8e03219eea76..a8e6199755d4 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -59,14 +59,11 @@ static struct task_struct *current_set[NR_CPUS];
extern char vmhalt_cmd[];
extern char vmpoff_cmd[];
-extern void reipl(unsigned long devno);
-extern void reipl_diag(void);
-
static void smp_ext_bitcall(int, ec_bit_sig);
static void smp_ext_bitcall_others(ec_bit_sig);
/*
- * Structure and data for smp_call_function(). This is designed to minimise
+5B * Structure and data for smp_call_function(). This is designed to minimise
* static memory requirements. It also looks cleaner.
*/
static DEFINE_SPINLOCK(call_lock);
@@ -279,12 +276,7 @@ static void do_machine_restart(void * __unused)
* interrupted by an external interrupt and s390irq
* locks are always held disabled).
*/
- reipl_diag();
-
- if (MACHINE_IS_VM)
- cpcmd ("IPL", NULL, 0, NULL);
- else
- reipl (0x10000 | S390_lowcore.ipl_device);
+ do_reipl();
}
void machine_restart_smp(char * __unused)
@@ -426,59 +418,49 @@ void smp_send_reschedule(int cpu)
/*
* parameter area for the set/clear control bit callbacks
*/
-typedef struct
-{
- __u16 start_ctl;
- __u16 end_ctl;
+struct ec_creg_mask_parms {
unsigned long orvals[16];
unsigned long andvals[16];
-} ec_creg_mask_parms;
+};
/*
* callback for setting/clearing control bits
*/
void smp_ctl_bit_callback(void *info) {
- ec_creg_mask_parms *pp;
+ struct ec_creg_mask_parms *pp = info;
unsigned long cregs[16];
int i;
- pp = (ec_creg_mask_parms *) info;
- __ctl_store(cregs[pp->start_ctl], pp->start_ctl, pp->end_ctl);
- for (i = pp->start_ctl; i <= pp->end_ctl; i++)
+ __ctl_store(cregs, 0, 15);
+ for (i = 0; i <= 15; i++)
cregs[i] = (cregs[i] & pp->andvals[i]) | pp->orvals[i];
- __ctl_load(cregs[pp->start_ctl], pp->start_ctl, pp->end_ctl);
+ __ctl_load(cregs, 0, 15);
}
/*
* Set a bit in a control register of all cpus
*/
-void smp_ctl_set_bit(int cr, int bit) {
- ec_creg_mask_parms parms;
+void smp_ctl_set_bit(int cr, int bit)
+{
+ struct ec_creg_mask_parms parms;
- parms.start_ctl = cr;
- parms.end_ctl = cr;
+ memset(&parms.orvals, 0, sizeof(parms.orvals));
+ memset(&parms.andvals, 0xff, sizeof(parms.andvals));
parms.orvals[cr] = 1 << bit;
- parms.andvals[cr] = -1L;
- preempt_disable();
- smp_call_function(smp_ctl_bit_callback, &parms, 0, 1);
- __ctl_set_bit(cr, bit);
- preempt_enable();
+ on_each_cpu(smp_ctl_bit_callback, &parms, 0, 1);
}
/*
* Clear a bit in a control register of all cpus
*/
-void smp_ctl_clear_bit(int cr, int bit) {
- ec_creg_mask_parms parms;
+void smp_ctl_clear_bit(int cr, int bit)
+{
+ struct ec_creg_mask_parms parms;
- parms.start_ctl = cr;
- parms.end_ctl = cr;
- parms.orvals[cr] = 0;
+ memset(&parms.orvals, 0, sizeof(parms.orvals));
+ memset(&parms.andvals, 0xff, sizeof(parms.andvals));
parms.andvals[cr] = ~(1L << bit);
- preempt_disable();
- smp_call_function(smp_ctl_bit_callback, &parms, 0, 1);
- __ctl_clear_bit(cr, bit);
- preempt_enable();
+ on_each_cpu(smp_ctl_bit_callback, &parms, 0, 1);
}
/*
@@ -658,9 +640,9 @@ __cpu_up(unsigned int cpu)
sf->gprs[9] = (unsigned long) sf;
cpu_lowcore->save_area[15] = (unsigned long) sf;
__ctl_store(cpu_lowcore->cregs_save_area[0], 0, 15);
- __asm__ __volatile__("stam 0,15,0(%0)"
- : : "a" (&cpu_lowcore->access_regs_save_area)
- : "memory");
+ asm volatile(
+ " stam 0,15,0(%0)"
+ : : "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;
@@ -716,7 +698,7 @@ int
__cpu_disable(void)
{
unsigned long flags;
- ec_creg_mask_parms cr_parms;
+ struct ec_creg_mask_parms cr_parms;
int cpu = smp_processor_id();
spin_lock_irqsave(&smp_reserve_lock, flags);
@@ -732,30 +714,21 @@ __cpu_disable(void)
pfault_fini();
#endif
- /* disable all external interrupts */
+ memset(&cr_parms.orvals, 0, sizeof(cr_parms.orvals));
+ memset(&cr_parms.andvals, 0xff, sizeof(cr_parms.andvals));
- cr_parms.start_ctl = 0;
- cr_parms.end_ctl = 0;
+ /* disable all external interrupts */
cr_parms.orvals[0] = 0;
cr_parms.andvals[0] = ~(1<<15 | 1<<14 | 1<<13 | 1<<12 |
1<<11 | 1<<10 | 1<< 6 | 1<< 4);
- smp_ctl_bit_callback(&cr_parms);
-
/* disable all I/O interrupts */
-
- cr_parms.start_ctl = 6;
- cr_parms.end_ctl = 6;
cr_parms.orvals[6] = 0;
cr_parms.andvals[6] = ~(1<<31 | 1<<30 | 1<<29 | 1<<28 |
1<<27 | 1<<26 | 1<<25 | 1<<24);
- smp_ctl_bit_callback(&cr_parms);
-
/* disable most machine checks */
-
- cr_parms.start_ctl = 14;
- cr_parms.end_ctl = 14;
cr_parms.orvals[14] = 0;
cr_parms.andvals[14] = ~(1<<28 | 1<<27 | 1<<26 | 1<<25 | 1<<24);
+
smp_ctl_bit_callback(&cr_parms);
spin_unlock_irqrestore(&smp_reserve_lock, flags);
diff --git a/arch/s390/kernel/stacktrace.c b/arch/s390/kernel/stacktrace.c
index de83f38288d0..d9428a0fc8fb 100644
--- a/arch/s390/kernel/stacktrace.c
+++ b/arch/s390/kernel/stacktrace.c
@@ -59,9 +59,7 @@ static inline unsigned long save_context_stack(struct stack_trace *trace,
}
}
-void save_stack_trace(struct stack_trace *trace,
- struct task_struct *task, int all_contexts,
- unsigned int skip)
+void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
{
register unsigned long sp asm ("15");
unsigned long orig_sp;
@@ -69,22 +67,23 @@ void save_stack_trace(struct stack_trace *trace,
sp &= PSW_ADDR_INSN;
orig_sp = sp;
- sp = save_context_stack(trace, &skip, sp,
+ sp = save_context_stack(trace, &trace->skip, sp,
S390_lowcore.panic_stack - PAGE_SIZE,
S390_lowcore.panic_stack);
- if ((sp != orig_sp) && !all_contexts)
+ if ((sp != orig_sp) && !trace->all_contexts)
return;
- sp = save_context_stack(trace, &skip, sp,
+ sp = save_context_stack(trace, &trace->skip, sp,
S390_lowcore.async_stack - ASYNC_SIZE,
S390_lowcore.async_stack);
- if ((sp != orig_sp) && !all_contexts)
+ if ((sp != orig_sp) && !trace->all_contexts)
return;
if (task)
- save_context_stack(trace, &skip, sp,
+ save_context_stack(trace, &trace->skip, sp,
(unsigned long) task_stack_page(task),
(unsigned long) task_stack_page(task) + THREAD_SIZE);
else
- save_context_stack(trace, &skip, sp, S390_lowcore.thread_info,
+ save_context_stack(trace, &trace->skip, sp,
+ S390_lowcore.thread_info,
S390_lowcore.thread_info + THREAD_SIZE);
return;
}
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 74e6178fbaf2..4bf66cc4a267 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -53,8 +53,6 @@ static u64 init_timer_cc;
static u64 jiffies_timer_cc;
static u64 xtime_cc;
-extern unsigned long wall_jiffies;
-
/*
* Scheduler clock - returns current time in nanosec units.
*/
@@ -87,9 +85,8 @@ static inline unsigned long do_gettimeoffset(void)
{
__u64 now;
- now = (get_clock() - jiffies_timer_cc) >> 12;
- /* We require the offset from the latest update of xtime */
- now -= (__u64) wall_jiffies*USECS_PER_JIFFY;
+ now = (get_clock() - jiffies_timer_cc) >> 12;
+ now -= (__u64) jiffies * USECS_PER_JIFFY;
return (unsigned long) now;
}
@@ -166,7 +163,7 @@ EXPORT_SYMBOL(do_settimeofday);
void account_ticks(struct pt_regs *regs)
{
__u64 tmp;
- __u32 ticks, xticks;
+ __u32 ticks;
/* Calculate how many ticks have passed. */
if (S390_lowcore.int_clock < S390_lowcore.jiffy_timer) {
@@ -204,6 +201,7 @@ void account_ticks(struct pt_regs *regs)
*/
write_seqlock(&xtime_lock);
if (S390_lowcore.jiffy_timer > xtime_cc) {
+ __u32 xticks;
tmp = S390_lowcore.jiffy_timer - xtime_cc;
if (tmp >= 2*CLK_TICKS_PER_JIFFY) {
xticks = __div(tmp, CLK_TICKS_PER_JIFFY);
@@ -212,13 +210,11 @@ void account_ticks(struct pt_regs *regs)
xticks = 1;
xtime_cc += CLK_TICKS_PER_JIFFY;
}
- while (xticks--)
- do_timer(regs);
+ do_timer(xticks);
}
write_sequnlock(&xtime_lock);
#else
- for (xticks = ticks; xticks > 0; xticks--)
- do_timer(regs);
+ do_timer(ticks);
#endif
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
@@ -351,10 +347,12 @@ void __init time_init(void)
int cc;
/* kick the TOD clock */
- asm volatile ("STCK 0(%1)\n\t"
- "IPM %0\n\t"
- "SRL %0,28" : "=r" (cc) : "a" (&init_timer_cc)
- : "memory", "cc");
+ asm volatile(
+ " stck 0(%2)\n"
+ " ipm %0\n"
+ " srl %0,28"
+ : "=d" (cc), "=m" (init_timer_cc)
+ : "a" (&init_timer_cc) : "cc");
switch (cc) {
case 0: /* clock in set state: all is fine */
break;
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index bde1d1d59858..3eb4fab048b8 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -29,6 +29,7 @@
#include <linux/module.h>
#include <linux/kallsyms.h>
#include <linux/reboot.h>
+#include <linux/kprobes.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -39,6 +40,7 @@
#include <asm/s390_ext.h>
#include <asm/lowcore.h>
#include <asm/debug.h>
+#include <asm/kdebug.h>
/* Called from entry.S only */
extern void handle_per_exception(struct pt_regs *regs);
@@ -74,6 +76,20 @@ static int kstack_depth_to_print = 12;
static int kstack_depth_to_print = 20;
#endif /* CONFIG_64BIT */
+ATOMIC_NOTIFIER_HEAD(s390die_chain);
+
+int register_die_notifier(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_register(&s390die_chain, nb);
+}
+EXPORT_SYMBOL(register_die_notifier);
+
+int unregister_die_notifier(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_unregister(&s390die_chain, nb);
+}
+EXPORT_SYMBOL(unregister_die_notifier);
+
/*
* For show_trace we have tree different stack to consider:
* - the panic stack which is used if the kernel stack has overflown
@@ -305,8 +321,9 @@ report_user_fault(long interruption_code, struct pt_regs *regs)
#endif
}
-static void inline do_trap(long interruption_code, int signr, char *str,
- struct pt_regs *regs, siginfo_t *info)
+static void __kprobes inline do_trap(long interruption_code, int signr,
+ char *str, struct pt_regs *regs,
+ siginfo_t *info)
{
/*
* We got all needed information from the lowcore and can
@@ -315,6 +332,10 @@ static void inline do_trap(long interruption_code, int signr, char *str,
if (regs->psw.mask & PSW_MASK_PSTATE)
local_irq_enable();
+ if (notify_die(DIE_TRAP, str, regs, interruption_code,
+ interruption_code, signr) == NOTIFY_STOP)
+ return;
+
if (regs->psw.mask & PSW_MASK_PSTATE) {
struct task_struct *tsk = current;
@@ -336,8 +357,12 @@ static inline void __user *get_check_address(struct pt_regs *regs)
return (void __user *)((regs->psw.addr-S390_lowcore.pgm_ilc) & PSW_ADDR_INSN);
}
-void do_single_step(struct pt_regs *regs)
+void __kprobes do_single_step(struct pt_regs *regs)
{
+ if (notify_die(DIE_SSTEP, "sstep", regs, 0, 0,
+ SIGTRAP) == NOTIFY_STOP){
+ return;
+ }
if ((current->ptrace & PT_PTRACED) != 0)
force_sig(SIGTRAP, current);
}
@@ -572,8 +597,7 @@ asmlinkage void data_exception(struct pt_regs * regs, long interruption_code)
local_irq_enable();
if (MACHINE_HAS_IEEE)
- __asm__ volatile ("stfpc %0\n\t"
- : "=m" (current->thread.fp_regs.fpc));
+ asm volatile("stfpc %0" : "=m" (current->thread.fp_regs.fpc));
#ifdef CONFIG_MATHEMU
else if (regs->psw.mask & PSW_MASK_PSTATE) {
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index ff5f7bb34f75..af9e69a03011 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -24,6 +24,7 @@ SECTIONS
*(.text)
SCHED_TEXT
LOCK_TEXT
+ KPROBES_TEXT
*(.fixup)
*(.gnu.warning)
} = 0x0700
@@ -117,7 +118,7 @@ SECTIONS
/* Sections to be discarded */
/DISCARD/ : {
- *(.exitcall.exit)
+ *(.exit.text) *(.exit.data) *(.exitcall.exit)
}
/* Stabs debugging sections. */
diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile
index e05d087a6eae..b0cfa6c4883d 100644
--- a/arch/s390/lib/Makefile
+++ b/arch/s390/lib/Makefile
@@ -4,6 +4,7 @@
EXTRA_AFLAGS := -traditional
-lib-y += delay.o string.o
-lib-y += $(if $(CONFIG_64BIT),uaccess64.o,uaccess.o)
+lib-y += delay.o string.o uaccess_std.o
+lib-$(CONFIG_32BIT) += div64.o
+lib-$(CONFIG_64BIT) += uaccess_mvcos.o
lib-$(CONFIG_SMP) += spinlock.o
diff --git a/arch/s390/lib/delay.c b/arch/s390/lib/delay.c
index 468f4ea33f99..027c4742a001 100644
--- a/arch/s390/lib/delay.c
+++ b/arch/s390/lib/delay.c
@@ -27,9 +27,7 @@ void __delay(unsigned long loops)
* yield the megahertz number of the cpu. The important function
* is udelay and that is done using the tod clock. -- martin.
*/
- __asm__ __volatile__(
- "0: brct %0,0b"
- : /* no outputs */ : "r" ((loops/2) + 1));
+ asm volatile("0: brct %0,0b" : : "d" ((loops/2) + 1));
}
/*
@@ -38,13 +36,12 @@ void __delay(unsigned long loops)
*/
void __udelay(unsigned long usecs)
{
- uint64_t start_cc, end_cc;
+ uint64_t start_cc;
if (usecs == 0)
return;
- asm volatile ("STCK %0" : "=m" (start_cc));
+ start_cc = get_clock();
do {
cpu_relax();
- asm volatile ("STCK %0" : "=m" (end_cc));
- } while (((end_cc - start_cc)/4096) < usecs);
+ } while (((get_clock() - start_cc)/4096) < usecs);
}
diff --git a/arch/s390/lib/div64.c b/arch/s390/lib/div64.c
new file mode 100644
index 000000000000..0481f3424a13
--- /dev/null
+++ b/arch/s390/lib/div64.c
@@ -0,0 +1,151 @@
+/*
+ * arch/s390/lib/div64.c
+ *
+ * __div64_32 implementation for 31 bit.
+ *
+ * Copyright (C) IBM Corp. 2006
+ * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+
+#ifdef CONFIG_MARCH_G5
+
+/*
+ * Function to divide an unsigned 64 bit integer by an unsigned
+ * 31 bit integer using signed 64/32 bit division.
+ */
+static uint32_t __div64_31(uint64_t *n, uint32_t base)
+{
+ register uint32_t reg2 asm("2");
+ register uint32_t reg3 asm("3");
+ uint32_t *words = (uint32_t *) n;
+ uint32_t tmp;
+
+ /* Special case base==1, remainder = 0, quotient = n */
+ if (base == 1)
+ return 0;
+ /*
+ * Special case base==0 will cause a fixed point divide exception
+ * on the dr instruction and may not happen anyway. For the
+ * following calculation we can assume base > 1. The first
+ * signed 64 / 32 bit division with an upper half of 0 will
+ * give the correct upper half of the 64 bit quotient.
+ */
+ reg2 = 0UL;
+ reg3 = words[0];
+ asm volatile(
+ " dr %0,%2\n"
+ : "+d" (reg2), "+d" (reg3) : "d" (base) : "cc" );
+ words[0] = reg3;
+ reg3 = words[1];
+ /*
+ * To get the lower half of the 64 bit quotient and the 32 bit
+ * remainder we have to use a little trick. Since we only have
+ * a signed division the quotient can get too big. To avoid this
+ * the 64 bit dividend is halved, then the signed division will
+ * work. Afterwards the quotient and the remainder are doubled.
+ * If the last bit of the dividend has been one the remainder
+ * is increased by one then checked against the base. If the
+ * remainder has overflown subtract base and increase the
+ * quotient. Simple, no ?
+ */
+ asm volatile(
+ " nr %2,%1\n"
+ " srdl %0,1\n"
+ " dr %0,%3\n"
+ " alr %0,%0\n"
+ " alr %1,%1\n"
+ " alr %0,%2\n"
+ " clr %0,%3\n"
+ " jl 0f\n"
+ " slr %0,%3\n"
+ " alr %1,%2\n"
+ "0:\n"
+ : "+d" (reg2), "+d" (reg3), "=d" (tmp)
+ : "d" (base), "2" (1UL) : "cc" );
+ words[1] = reg3;
+ return reg2;
+}
+
+/*
+ * Function to divide an unsigned 64 bit integer by an unsigned
+ * 32 bit integer using the unsigned 64/31 bit division.
+ */
+uint32_t __div64_32(uint64_t *n, uint32_t base)
+{
+ uint32_t r;
+
+ /*
+ * If the most significant bit of base is set, divide n by
+ * (base/2). That allows to use 64/31 bit division and gives a
+ * good approximation of the result: n = (base/2)*q + r. The
+ * result needs to be corrected with two simple transformations.
+ * If base is already < 2^31-1 __div64_31 can be used directly.
+ */
+ r = __div64_31(n, ((signed) base < 0) ? (base/2) : base);
+ if ((signed) base < 0) {
+ uint64_t q = *n;
+ /*
+ * First transformation:
+ * n = (base/2)*q + r
+ * = ((base/2)*2)*(q/2) + ((q&1) ? (base/2) : 0) + r
+ * Since r < (base/2), r + (base/2) < base.
+ * With q1 = (q/2) and r1 = r + ((q&1) ? (base/2) : 0)
+ * n = ((base/2)*2)*q1 + r1 with r1 < base.
+ */
+ if (q & 1)
+ r += base/2;
+ q >>= 1;
+ /*
+ * Second transformation. ((base/2)*2) could have lost the
+ * last bit.
+ * n = ((base/2)*2)*q1 + r1
+ * = base*q1 - ((base&1) ? q1 : 0) + r1
+ */
+ if (base & 1) {
+ int64_t rx = r - q;
+ /*
+ * base is >= 2^31. The worst case for the while
+ * loop is n=2^64-1 base=2^31+1. That gives a
+ * maximum for q=(2^64-1)/2^31 = 0x1ffffffff. Since
+ * base >= 2^31 the loop is finished after a maximum
+ * of three iterations.
+ */
+ while (rx < 0) {
+ rx += base;
+ q--;
+ }
+ r = rx;
+ }
+ *n = q;
+ }
+ return r;
+}
+
+#else /* MARCH_G5 */
+
+uint32_t __div64_32(uint64_t *n, uint32_t base)
+{
+ register uint32_t reg2 asm("2");
+ register uint32_t reg3 asm("3");
+ uint32_t *words = (uint32_t *) n;
+
+ reg2 = 0UL;
+ reg3 = words[0];
+ asm volatile(
+ " dlr %0,%2\n"
+ : "+d" (reg2), "+d" (reg3) : "d" (base) : "cc" );
+ words[0] = reg3;
+ reg3 = words[1];
+ asm volatile(
+ " dlr %0,%2\n"
+ : "+d" (reg2), "+d" (reg3) : "d" (base) : "cc" );
+ words[1] = reg3;
+ return reg2;
+}
+
+#endif /* MARCH_G5 */
+
+EXPORT_SYMBOL(__div64_32);
diff --git a/arch/s390/lib/spinlock.c b/arch/s390/lib/spinlock.c
index b9b7958a226a..8d76403fcf89 100644
--- a/arch/s390/lib/spinlock.c
+++ b/arch/s390/lib/spinlock.c
@@ -24,57 +24,76 @@ static int __init spin_retry_setup(char *str)
}
__setup("spin_retry=", spin_retry_setup);
-static inline void
-_diag44(void)
+static inline void _raw_yield(void)
{
-#ifdef CONFIG_64BIT
if (MACHINE_HAS_DIAG44)
-#endif
asm volatile("diag 0,0,0x44");
}
-void
-_raw_spin_lock_wait(raw_spinlock_t *lp, unsigned int pc)
+static inline void _raw_yield_cpu(int cpu)
+{
+ if (MACHINE_HAS_DIAG9C)
+ asm volatile("diag %0,0,0x9c"
+ : : "d" (__cpu_logical_map[cpu]));
+ else
+ _raw_yield();
+}
+
+void _raw_spin_lock_wait(raw_spinlock_t *lp, unsigned int pc)
{
int count = spin_retry;
+ unsigned int cpu = ~smp_processor_id();
while (1) {
if (count-- <= 0) {
- _diag44();
+ unsigned int owner = lp->owner_cpu;
+ if (owner != 0)
+ _raw_yield_cpu(~owner);
count = spin_retry;
}
if (__raw_spin_is_locked(lp))
continue;
- if (_raw_compare_and_swap(&lp->lock, 0, pc) == 0)
+ if (_raw_compare_and_swap(&lp->owner_cpu, 0, cpu) == 0) {
+ lp->owner_pc = pc;
return;
+ }
}
}
EXPORT_SYMBOL(_raw_spin_lock_wait);
-int
-_raw_spin_trylock_retry(raw_spinlock_t *lp, unsigned int pc)
+int _raw_spin_trylock_retry(raw_spinlock_t *lp, unsigned int pc)
{
- int count = spin_retry;
+ unsigned int cpu = ~smp_processor_id();
+ int count;
- while (count-- > 0) {
+ for (count = spin_retry; count > 0; count--) {
if (__raw_spin_is_locked(lp))
continue;
- if (_raw_compare_and_swap(&lp->lock, 0, pc) == 0)
+ if (_raw_compare_and_swap(&lp->owner_cpu, 0, cpu) == 0) {
+ lp->owner_pc = pc;
return 1;
+ }
}
return 0;
}
EXPORT_SYMBOL(_raw_spin_trylock_retry);
-void
-_raw_read_lock_wait(raw_rwlock_t *rw)
+void _raw_spin_relax(raw_spinlock_t *lock)
+{
+ unsigned int cpu = lock->owner_cpu;
+ if (cpu != 0)
+ _raw_yield_cpu(~cpu);
+}
+EXPORT_SYMBOL(_raw_spin_relax);
+
+void _raw_read_lock_wait(raw_rwlock_t *rw)
{
unsigned int old;
int count = spin_retry;
while (1) {
if (count-- <= 0) {
- _diag44();
+ _raw_yield();
count = spin_retry;
}
if (!__raw_read_can_lock(rw))
@@ -86,8 +105,7 @@ _raw_read_lock_wait(raw_rwlock_t *rw)
}
EXPORT_SYMBOL(_raw_read_lock_wait);
-int
-_raw_read_trylock_retry(raw_rwlock_t *rw)
+int _raw_read_trylock_retry(raw_rwlock_t *rw)
{
unsigned int old;
int count = spin_retry;
@@ -103,14 +121,13 @@ _raw_read_trylock_retry(raw_rwlock_t *rw)
}
EXPORT_SYMBOL(_raw_read_trylock_retry);
-void
-_raw_write_lock_wait(raw_rwlock_t *rw)
+void _raw_write_lock_wait(raw_rwlock_t *rw)
{
int count = spin_retry;
while (1) {
if (count-- <= 0) {
- _diag44();
+ _raw_yield();
count = spin_retry;
}
if (!__raw_write_can_lock(rw))
@@ -121,8 +138,7 @@ _raw_write_lock_wait(raw_rwlock_t *rw)
}
EXPORT_SYMBOL(_raw_write_lock_wait);
-int
-_raw_write_trylock_retry(raw_rwlock_t *rw)
+int _raw_write_trylock_retry(raw_rwlock_t *rw)
{
int count = spin_retry;
diff --git a/arch/s390/lib/uaccess.S b/arch/s390/lib/uaccess.S
deleted file mode 100644
index 837275284d9f..000000000000
--- a/arch/s390/lib/uaccess.S
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * arch/s390/lib/uaccess.S
- * __copy_{from|to}_user functions.
- *
- * s390
- * Copyright (C) 2000,2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Authors(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
- *
- * These functions have standard call interface
- */
-
-#include <linux/errno.h>
-#include <asm/lowcore.h>
-#include <asm/asm-offsets.h>
-
- .text
- .align 4
- .globl __copy_from_user_asm
- # %r2 = to, %r3 = n, %r4 = from
-__copy_from_user_asm:
- slr %r0,%r0
-0: mvcp 0(%r3,%r2),0(%r4),%r0
- jnz 1f
- slr %r2,%r2
- br %r14
-1: la %r2,256(%r2)
- la %r4,256(%r4)
- ahi %r3,-256
-2: mvcp 0(%r3,%r2),0(%r4),%r0
- jnz 1b
-3: slr %r2,%r2
- br %r14
-4: lhi %r0,-4096
- lr %r5,%r4
- slr %r5,%r0
- nr %r5,%r0 # %r5 = (%r4 + 4096) & -4096
- slr %r5,%r4 # %r5 = #bytes to next user page boundary
- clr %r3,%r5 # copy crosses next page boundary ?
- jnh 6f # no, the current page faulted
- # move with the reduced length which is < 256
-5: mvcp 0(%r5,%r2),0(%r4),%r0
- slr %r3,%r5
-6: lr %r2,%r3
- br %r14
- .section __ex_table,"a"
- .long 0b,4b
- .long 2b,4b
- .long 5b,6b
- .previous
-
- .align 4
- .text
- .globl __copy_to_user_asm
- # %r2 = from, %r3 = n, %r4 = to
-__copy_to_user_asm:
- slr %r0,%r0
-0: mvcs 0(%r3,%r4),0(%r2),%r0
- jnz 1f
- slr %r2,%r2
- br %r14
-1: la %r2,256(%r2)
- la %r4,256(%r4)
- ahi %r3,-256
-2: mvcs 0(%r3,%r4),0(%r2),%r0
- jnz 1b
-3: slr %r2,%r2
- br %r14
-4: lhi %r0,-4096
- lr %r5,%r4
- slr %r5,%r0
- nr %r5,%r0 # %r5 = (%r4 + 4096) & -4096
- slr %r5,%r4 # %r5 = #bytes to next user page boundary
- clr %r3,%r5 # copy crosses next page boundary ?
- jnh 6f # no, the current page faulted
- # move with the reduced length which is < 256
-5: mvcs 0(%r5,%r4),0(%r2),%r0
- slr %r3,%r5
-6: lr %r2,%r3
- br %r14
- .section __ex_table,"a"
- .long 0b,4b
- .long 2b,4b
- .long 5b,6b
- .previous
-
- .align 4
- .text
- .globl __copy_in_user_asm
- # %r2 = from, %r3 = n, %r4 = to
-__copy_in_user_asm:
- ahi %r3,-1
- jo 6f
- sacf 256
- bras %r1,4f
-0: ahi %r3,257
-1: mvc 0(1,%r4),0(%r2)
- la %r2,1(%r2)
- la %r4,1(%r4)
- ahi %r3,-1
- jnz 1b
-2: lr %r2,%r3
- br %r14
-3: mvc 0(256,%r4),0(%r2)
- la %r2,256(%r2)
- la %r4,256(%r4)
-4: ahi %r3,-256
- jnm 3b
-5: ex %r3,4(%r1)
- sacf 0
-6: slr %r2,%r2
- br %r14
- .section __ex_table,"a"
- .long 1b,2b
- .long 3b,0b
- .long 5b,0b
- .previous
-
- .align 4
- .text
- .globl __clear_user_asm
- # %r2 = to, %r3 = n
-__clear_user_asm:
- bras %r5,0f
- .long empty_zero_page
-0: l %r5,0(%r5)
- slr %r0,%r0
-1: mvcs 0(%r3,%r2),0(%r5),%r0
- jnz 2f
- slr %r2,%r2
- br %r14
-2: la %r2,256(%r2)
- ahi %r3,-256
-3: mvcs 0(%r3,%r2),0(%r5),%r0
- jnz 2b
-4: slr %r2,%r2
- br %r14
-5: lhi %r0,-4096
- lr %r4,%r2
- slr %r4,%r0
- nr %r4,%r0 # %r4 = (%r2 + 4096) & -4096
- slr %r4,%r2 # %r4 = #bytes to next user page boundary
- clr %r3,%r4 # clear crosses next page boundary ?
- jnh 7f # no, the current page faulted
- # clear with the reduced length which is < 256
-6: mvcs 0(%r4,%r2),0(%r5),%r0
- slr %r3,%r4
-7: lr %r2,%r3
- br %r14
- .section __ex_table,"a"
- .long 1b,5b
- .long 3b,5b
- .long 6b,7b
- .previous
-
- .align 4
- .text
- .globl __strncpy_from_user_asm
- # %r2 = count, %r3 = dst, %r4 = src
-__strncpy_from_user_asm:
- lhi %r0,0
- lr %r1,%r4
- la %r4,0(%r4) # clear high order bit from %r4
- la %r2,0(%r2,%r4) # %r2 points to first byte after string
- sacf 256
-0: srst %r2,%r1
- jo 0b
- sacf 0
- lr %r1,%r2
- jh 1f # \0 found in string ?
- ahi %r1,1 # include \0 in copy
-1: slr %r1,%r4 # %r1 = copy length (without \0)
- slr %r2,%r4 # %r2 = return length (including \0)
-2: mvcp 0(%r1,%r3),0(%r4),%r0
- jnz 3f
- br %r14
-3: la %r3,256(%r3)
- la %r4,256(%r4)
- ahi %r1,-256
- mvcp 0(%r1,%r3),0(%r4),%r0
- jnz 3b
- br %r14
-4: sacf 0
- lhi %r2,-EFAULT
- br %r14
- .section __ex_table,"a"
- .long 0b,4b
- .previous
-
- .align 4
- .text
- .globl __strnlen_user_asm
- # %r2 = count, %r3 = src
-__strnlen_user_asm:
- lhi %r0,0
- lr %r1,%r3
- la %r3,0(%r3) # clear high order bit from %r4
- la %r2,0(%r2,%r3) # %r2 points to first byte after string
- sacf 256
-0: srst %r2,%r1
- jo 0b
- sacf 0
- ahi %r2,1 # strnlen_user result includes the \0
- # or return count+1 if \0 not found
- slr %r2,%r3
- br %r14
-2: sacf 0
- slr %r2,%r2 # return 0 on exception
- br %r14
- .section __ex_table,"a"
- .long 0b,2b
- .previous
diff --git a/arch/s390/lib/uaccess64.S b/arch/s390/lib/uaccess64.S
deleted file mode 100644
index 1f755be22f92..000000000000
--- a/arch/s390/lib/uaccess64.S
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * arch/s390x/lib/uaccess.S
- * __copy_{from|to}_user functions.
- *
- * s390
- * Copyright (C) 2000,2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Authors(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
- *
- * These functions have standard call interface
- */
-
-#include <linux/errno.h>
-#include <asm/lowcore.h>
-#include <asm/asm-offsets.h>
-
- .text
- .align 4
- .globl __copy_from_user_asm
- # %r2 = to, %r3 = n, %r4 = from
-__copy_from_user_asm:
- slgr %r0,%r0
-0: mvcp 0(%r3,%r2),0(%r4),%r0
- jnz 1f
- slgr %r2,%r2
- br %r14
-1: la %r2,256(%r2)
- la %r4,256(%r4)
- aghi %r3,-256
-2: mvcp 0(%r3,%r2),0(%r4),%r0
- jnz 1b
-3: slgr %r2,%r2
- br %r14
-4: lghi %r0,-4096
- lgr %r5,%r4
- slgr %r5,%r0
- ngr %r5,%r0 # %r5 = (%r4 + 4096) & -4096
- slgr %r5,%r4 # %r5 = #bytes to next user page boundary
- clgr %r3,%r5 # copy crosses next page boundary ?
- jnh 6f # no, the current page faulted
- # move with the reduced length which is < 256
-5: mvcp 0(%r5,%r2),0(%r4),%r0
- slgr %r3,%r5
-6: lgr %r2,%r3
- br %r14
- .section __ex_table,"a"
- .quad 0b,4b
- .quad 2b,4b
- .quad 5b,6b
- .previous
-
- .align 4
- .text
- .globl __copy_to_user_asm
- # %r2 = from, %r3 = n, %r4 = to
-__copy_to_user_asm:
- slgr %r0,%r0
-0: mvcs 0(%r3,%r4),0(%r2),%r0
- jnz 1f
- slgr %r2,%r2
- br %r14
-1: la %r2,256(%r2)
- la %r4,256(%r4)
- aghi %r3,-256
-2: mvcs 0(%r3,%r4),0(%r2),%r0
- jnz 1b
-3: slgr %r2,%r2
- br %r14
-4: lghi %r0,-4096
- lgr %r5,%r4
- slgr %r5,%r0
- ngr %r5,%r0 # %r5 = (%r4 + 4096) & -4096
- slgr %r5,%r4 # %r5 = #bytes to next user page boundary
- clgr %r3,%r5 # copy crosses next page boundary ?
- jnh 6f # no, the current page faulted
- # move with the reduced length which is < 256
-5: mvcs 0(%r5,%r4),0(%r2),%r0
- slgr %r3,%r5
-6: lgr %r2,%r3
- br %r14
- .section __ex_table,"a"
- .quad 0b,4b
- .quad 2b,4b
- .quad 5b,6b
- .previous
-
- .align 4
- .text
- .globl __copy_in_user_asm
- # %r2 = from, %r3 = n, %r4 = to
-__copy_in_user_asm:
- aghi %r3,-1
- jo 6f
- sacf 256
- bras %r1,4f
-0: aghi %r3,257
-1: mvc 0(1,%r4),0(%r2)
- la %r2,1(%r2)
- la %r4,1(%r4)
- aghi %r3,-1
- jnz 1b
-2: lgr %r2,%r3
- br %r14
-3: mvc 0(256,%r4),0(%r2)
- la %r2,256(%r2)
- la %r4,256(%r4)
-4: aghi %r3,-256
- jnm 3b
-5: ex %r3,4(%r1)
- sacf 0
-6: slgr %r2,%r2
- br 14
- .section __ex_table,"a"
- .quad 1b,2b
- .quad 3b,0b
- .quad 5b,0b
- .previous
-
- .align 4
- .text
- .globl __clear_user_asm
- # %r2 = to, %r3 = n
-__clear_user_asm:
- slgr %r0,%r0
- larl %r5,empty_zero_page
-1: mvcs 0(%r3,%r2),0(%r5),%r0
- jnz 2f
- slgr %r2,%r2
- br %r14
-2: la %r2,256(%r2)
- aghi %r3,-256
-3: mvcs 0(%r3,%r2),0(%r5),%r0
- jnz 2b
-4: slgr %r2,%r2
- br %r14
-5: lghi %r0,-4096
- lgr %r4,%r2
- slgr %r4,%r0
- ngr %r4,%r0 # %r4 = (%r2 + 4096) & -4096
- slgr %r4,%r2 # %r4 = #bytes to next user page boundary
- clgr %r3,%r4 # clear crosses next page boundary ?
- jnh 7f # no, the current page faulted
- # clear with the reduced length which is < 256
-6: mvcs 0(%r4,%r2),0(%r5),%r0
- slgr %r3,%r4
-7: lgr %r2,%r3
- br %r14
- .section __ex_table,"a"
- .quad 1b,5b
- .quad 3b,5b
- .quad 6b,7b
- .previous
-
- .align 4
- .text
- .globl __strncpy_from_user_asm
- # %r2 = count, %r3 = dst, %r4 = src
-__strncpy_from_user_asm:
- lghi %r0,0
- lgr %r1,%r4
- la %r2,0(%r2,%r4) # %r2 points to first byte after string
- sacf 256
-0: srst %r2,%r1
- jo 0b
- sacf 0
- lgr %r1,%r2
- jh 1f # \0 found in string ?
- aghi %r1,1 # include \0 in copy
-1: slgr %r1,%r4 # %r1 = copy length (without \0)
- slgr %r2,%r4 # %r2 = return length (including \0)
-2: mvcp 0(%r1,%r3),0(%r4),%r0
- jnz 3f
- br %r14
-3: la %r3,256(%r3)
- la %r4,256(%r4)
- aghi %r1,-256
- mvcp 0(%r1,%r3),0(%r4),%r0
- jnz 3b
- br %r14
-4: sacf 0
- lghi %r2,-EFAULT
- br %r14
- .section __ex_table,"a"
- .quad 0b,4b
- .previous
-
- .align 4
- .text
- .globl __strnlen_user_asm
- # %r2 = count, %r3 = src
-__strnlen_user_asm:
- lghi %r0,0
- lgr %r1,%r3
- la %r2,0(%r2,%r3) # %r2 points to first byte after string
- sacf 256
-0: srst %r2,%r1
- jo 0b
- sacf 0
- aghi %r2,1 # strnlen_user result includes the \0
- # or return count+1 if \0 not found
- slgr %r2,%r3
- br %r14
-2: sacf 0
- slgr %r2,%r2 # return 0 on exception
- br %r14
- .section __ex_table,"a"
- .quad 0b,2b
- .previous
diff --git a/arch/s390/lib/uaccess_mvcos.c b/arch/s390/lib/uaccess_mvcos.c
new file mode 100644
index 000000000000..121b2935a422
--- /dev/null
+++ b/arch/s390/lib/uaccess_mvcos.c
@@ -0,0 +1,166 @@
+/*
+ * arch/s390/lib/uaccess_mvcos.c
+ *
+ * Optimized user space space access functions based on mvcos.
+ *
+ * Copyright (C) IBM Corp. 2006
+ * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ * Gerald Schaefer (gerald.schaefer@de.ibm.com)
+ */
+
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <asm/uaccess.h>
+#include <asm/futex.h>
+
+#ifndef __s390x__
+#define AHI "ahi"
+#define ALR "alr"
+#define CLR "clr"
+#define LHI "lhi"
+#define SLR "slr"
+#else
+#define AHI "aghi"
+#define ALR "algr"
+#define CLR "clgr"
+#define LHI "lghi"
+#define SLR "slgr"
+#endif
+
+size_t copy_from_user_mvcos(size_t size, const void __user *ptr, void *x)
+{
+ register unsigned long reg0 asm("0") = 0x81UL;
+ unsigned long tmp1, tmp2;
+
+ tmp1 = -4096UL;
+ asm volatile(
+ "0: .insn ss,0xc80000000000,0(%0,%2),0(%1),0\n"
+ " jz 7f\n"
+ "1:"ALR" %0,%3\n"
+ " "SLR" %1,%3\n"
+ " "SLR" %2,%3\n"
+ " j 0b\n"
+ "2: la %4,4095(%1)\n"/* %4 = ptr + 4095 */
+ " nr %4,%3\n" /* %4 = (ptr + 4095) & -4096 */
+ " "SLR" %4,%1\n"
+ " "CLR" %0,%4\n" /* copy crosses next page boundary? */
+ " jnh 4f\n"
+ "3: .insn ss,0xc80000000000,0(%4,%2),0(%1),0\n"
+ " "SLR" %0,%4\n"
+ " "ALR" %2,%4\n"
+ "4:"LHI" %4,-1\n"
+ " "ALR" %4,%0\n" /* copy remaining size, subtract 1 */
+ " bras %3,6f\n" /* memset loop */
+ " xc 0(1,%2),0(%2)\n"
+ "5: xc 0(256,%2),0(%2)\n"
+ " la %2,256(%2)\n"
+ "6:"AHI" %4,-256\n"
+ " jnm 5b\n"
+ " ex %4,0(%3)\n"
+ " j 8f\n"
+ "7:"SLR" %0,%0\n"
+ "8: \n"
+ EX_TABLE(0b,2b) EX_TABLE(3b,4b)
+ : "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
+ : "d" (reg0) : "cc", "memory");
+ return size;
+}
+
+size_t copy_to_user_mvcos(size_t size, void __user *ptr, const void *x)
+{
+ register unsigned long reg0 asm("0") = 0x810000UL;
+ unsigned long tmp1, tmp2;
+
+ tmp1 = -4096UL;
+ asm volatile(
+ "0: .insn ss,0xc80000000000,0(%0,%1),0(%2),0\n"
+ " jz 4f\n"
+ "1:"ALR" %0,%3\n"
+ " "SLR" %1,%3\n"
+ " "SLR" %2,%3\n"
+ " j 0b\n"
+ "2: la %4,4095(%1)\n"/* %4 = ptr + 4095 */
+ " nr %4,%3\n" /* %4 = (ptr + 4095) & -4096 */
+ " "SLR" %4,%1\n"
+ " "CLR" %0,%4\n" /* copy crosses next page boundary? */
+ " jnh 5f\n"
+ "3: .insn ss,0xc80000000000,0(%4,%1),0(%2),0\n"
+ " "SLR" %0,%4\n"
+ " j 5f\n"
+ "4:"SLR" %0,%0\n"
+ "5: \n"
+ EX_TABLE(0b,2b) EX_TABLE(3b,5b)
+ : "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
+ : "d" (reg0) : "cc", "memory");
+ return size;
+}
+
+size_t copy_in_user_mvcos(size_t size, void __user *to, const void __user *from)
+{
+ register unsigned long reg0 asm("0") = 0x810081UL;
+ unsigned long tmp1, tmp2;
+
+ tmp1 = -4096UL;
+ /* FIXME: copy with reduced length. */
+ asm volatile(
+ "0: .insn ss,0xc80000000000,0(%0,%1),0(%2),0\n"
+ " jz 2f\n"
+ "1:"ALR" %0,%3\n"
+ " "SLR" %1,%3\n"
+ " "SLR" %2,%3\n"
+ " j 0b\n"
+ "2:"SLR" %0,%0\n"
+ "3: \n"
+ EX_TABLE(0b,3b)
+ : "+a" (size), "+a" (to), "+a" (from), "+a" (tmp1), "=a" (tmp2)
+ : "d" (reg0) : "cc", "memory");
+ return size;
+}
+
+size_t clear_user_mvcos(size_t size, void __user *to)
+{
+ register unsigned long reg0 asm("0") = 0x810000UL;
+ unsigned long tmp1, tmp2;
+
+ tmp1 = -4096UL;
+ asm volatile(
+ "0: .insn ss,0xc80000000000,0(%0,%1),0(%4),0\n"
+ " jz 4f\n"
+ "1:"ALR" %0,%2\n"
+ " "SLR" %1,%2\n"
+ " j 0b\n"
+ "2: la %3,4095(%1)\n"/* %4 = to + 4095 */
+ " nr %3,%2\n" /* %4 = (to + 4095) & -4096 */
+ " "SLR" %3,%1\n"
+ " "CLR" %0,%3\n" /* copy crosses next page boundary? */
+ " jnh 5f\n"
+ "3: .insn ss,0xc80000000000,0(%3,%1),0(%4),0\n"
+ " "SLR" %0,%3\n"
+ " j 5f\n"
+ "4:"SLR" %0,%0\n"
+ "5: \n"
+ EX_TABLE(0b,2b) EX_TABLE(3b,5b)
+ : "+a" (size), "+a" (to), "+a" (tmp1), "=a" (tmp2)
+ : "a" (empty_zero_page), "d" (reg0) : "cc", "memory");
+ return size;
+}
+
+extern size_t copy_from_user_std_small(size_t, const void __user *, void *);
+extern size_t copy_to_user_std_small(size_t, void __user *, const void *);
+extern size_t strnlen_user_std(size_t, const char __user *);
+extern size_t strncpy_from_user_std(size_t, const char __user *, char *);
+extern int futex_atomic_op(int, int __user *, int, int *);
+extern int futex_atomic_cmpxchg(int __user *, int, int);
+
+struct uaccess_ops uaccess_mvcos = {
+ .copy_from_user = copy_from_user_mvcos,
+ .copy_from_user_small = copy_from_user_std_small,
+ .copy_to_user = copy_to_user_mvcos,
+ .copy_to_user_small = copy_to_user_std_small,
+ .copy_in_user = copy_in_user_mvcos,
+ .clear_user = clear_user_mvcos,
+ .strnlen_user = strnlen_user_std,
+ .strncpy_from_user = strncpy_from_user_std,
+ .futex_atomic_op = futex_atomic_op,
+ .futex_atomic_cmpxchg = futex_atomic_cmpxchg,
+};
diff --git a/arch/s390/lib/uaccess_std.c b/arch/s390/lib/uaccess_std.c
new file mode 100644
index 000000000000..f44f0078b354
--- /dev/null
+++ b/arch/s390/lib/uaccess_std.c
@@ -0,0 +1,356 @@
+/*
+ * arch/s390/lib/uaccess_std.c
+ *
+ * Standard user space access functions based on mvcp/mvcs and doing
+ * interesting things in the secondary space mode.
+ *
+ * Copyright (C) IBM Corp. 2006
+ * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ * Gerald Schaefer (gerald.schaefer@de.ibm.com)
+ */
+
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <asm/uaccess.h>
+#include <asm/futex.h>
+
+#ifndef __s390x__
+#define AHI "ahi"
+#define ALR "alr"
+#define CLR "clr"
+#define LHI "lhi"
+#define SLR "slr"
+#else
+#define AHI "aghi"
+#define ALR "algr"
+#define CLR "clgr"
+#define LHI "lghi"
+#define SLR "slgr"
+#endif
+
+size_t copy_from_user_std(size_t size, const void __user *ptr, void *x)
+{
+ unsigned long tmp1, tmp2;
+
+ tmp1 = -256UL;
+ asm volatile(
+ "0: mvcp 0(%0,%2),0(%1),%3\n"
+ " jz 8f\n"
+ "1:"ALR" %0,%3\n"
+ " la %1,256(%1)\n"
+ " la %2,256(%2)\n"
+ "2: mvcp 0(%0,%2),0(%1),%3\n"
+ " jnz 1b\n"
+ " j 8f\n"
+ "3: la %4,255(%1)\n" /* %4 = ptr + 255 */
+ " "LHI" %3,-4096\n"
+ " nr %4,%3\n" /* %4 = (ptr + 255) & -4096 */
+ " "SLR" %4,%1\n"
+ " "CLR" %0,%4\n" /* copy crosses next page boundary? */
+ " jnh 5f\n"
+ "4: mvcp 0(%4,%2),0(%1),%3\n"
+ " "SLR" %0,%4\n"
+ " "ALR" %2,%4\n"
+ "5:"LHI" %4,-1\n"
+ " "ALR" %4,%0\n" /* copy remaining size, subtract 1 */
+ " bras %3,7f\n" /* memset loop */
+ " xc 0(1,%2),0(%2)\n"
+ "6: xc 0(256,%2),0(%2)\n"
+ " la %2,256(%2)\n"
+ "7:"AHI" %4,-256\n"
+ " jnm 6b\n"
+ " ex %4,0(%3)\n"
+ " j 9f\n"
+ "8:"SLR" %0,%0\n"
+ "9: \n"
+ EX_TABLE(0b,3b) EX_TABLE(2b,3b) EX_TABLE(4b,5b)
+ : "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
+ : : "cc", "memory");
+ return size;
+}
+
+size_t copy_from_user_std_small(size_t size, const void __user *ptr, void *x)
+{
+ unsigned long tmp1, tmp2;
+
+ tmp1 = 0UL;
+ asm volatile(
+ "0: mvcp 0(%0,%2),0(%1),%3\n"
+ " "SLR" %0,%0\n"
+ " j 5f\n"
+ "1: la %4,255(%1)\n" /* %4 = ptr + 255 */
+ " "LHI" %3,-4096\n"
+ " nr %4,%3\n" /* %4 = (ptr + 255) & -4096 */
+ " "SLR" %4,%1\n"
+ " "CLR" %0,%4\n" /* copy crosses next page boundary? */
+ " jnh 5f\n"
+ "2: mvcp 0(%4,%2),0(%1),%3\n"
+ " "SLR" %0,%4\n"
+ " "ALR" %2,%4\n"
+ "3:"LHI" %4,-1\n"
+ " "ALR" %4,%0\n" /* copy remaining size, subtract 1 */
+ " bras %3,4f\n"
+ " xc 0(1,%2),0(%2)\n"
+ "4: ex %4,0(%3)\n"
+ "5:\n"
+ EX_TABLE(0b,1b) EX_TABLE(2b,3b)
+ : "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
+ : : "cc", "memory");
+ return size;
+}
+
+size_t copy_to_user_std(size_t size, void __user *ptr, const void *x)
+{
+ unsigned long tmp1, tmp2;
+
+ tmp1 = -256UL;
+ asm volatile(
+ "0: mvcs 0(%0,%1),0(%2),%3\n"
+ " jz 5f\n"
+ "1:"ALR" %0,%3\n"
+ " la %1,256(%1)\n"
+ " la %2,256(%2)\n"
+ "2: mvcs 0(%0,%1),0(%2),%3\n"
+ " jnz 1b\n"
+ " j 5f\n"
+ "3: la %4,255(%1)\n" /* %4 = ptr + 255 */
+ " "LHI" %3,-4096\n"
+ " nr %4,%3\n" /* %4 = (ptr + 255) & -4096 */
+ " "SLR" %4,%1\n"
+ " "CLR" %0,%4\n" /* copy crosses next page boundary? */
+ " jnh 6f\n"
+ "4: mvcs 0(%4,%1),0(%2),%3\n"
+ " "SLR" %0,%4\n"
+ " j 6f\n"
+ "5:"SLR" %0,%0\n"
+ "6: \n"
+ EX_TABLE(0b,3b) EX_TABLE(2b,3b) EX_TABLE(4b,6b)
+ : "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
+ : : "cc", "memory");
+ return size;
+}
+
+size_t copy_to_user_std_small(size_t size, void __user *ptr, const void *x)
+{
+ unsigned long tmp1, tmp2;
+
+ tmp1 = 0UL;
+ asm volatile(
+ "0: mvcs 0(%0,%1),0(%2),%3\n"
+ " "SLR" %0,%0\n"
+ " j 3f\n"
+ "1: la %4,255(%1)\n" /* ptr + 255 */
+ " "LHI" %3,-4096\n"
+ " nr %4,%3\n" /* (ptr + 255) & -4096UL */
+ " "SLR" %4,%1\n"
+ " "CLR" %0,%4\n" /* copy crosses next page boundary? */
+ " jnh 3f\n"
+ "2: mvcs 0(%4,%1),0(%2),%3\n"
+ " "SLR" %0,%4\n"
+ "3:\n"
+ EX_TABLE(0b,1b) EX_TABLE(2b,3b)
+ : "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
+ : : "cc", "memory");
+ return size;
+}
+
+size_t copy_in_user_std(size_t size, void __user *to, const void __user *from)
+{
+ unsigned long tmp1;
+
+ asm volatile(
+ " "AHI" %0,-1\n"
+ " jo 5f\n"
+ " sacf 256\n"
+ " bras %3,3f\n"
+ "0:"AHI" %0,257\n"
+ "1: mvc 0(1,%1),0(%2)\n"
+ " la %1,1(%1)\n"
+ " la %2,1(%2)\n"
+ " "AHI" %0,-1\n"
+ " jnz 1b\n"
+ " j 5f\n"
+ "2: mvc 0(256,%1),0(%2)\n"
+ " la %1,256(%1)\n"
+ " la %2,256(%2)\n"
+ "3:"AHI" %0,-256\n"
+ " jnm 2b\n"
+ "4: ex %0,1b-0b(%3)\n"
+ " sacf 0\n"
+ "5: "SLR" %0,%0\n"
+ "6:\n"
+ EX_TABLE(1b,6b) EX_TABLE(2b,0b) EX_TABLE(4b,0b)
+ : "+a" (size), "+a" (to), "+a" (from), "=a" (tmp1)
+ : : "cc", "memory");
+ return size;
+}
+
+size_t clear_user_std(size_t size, void __user *to)
+{
+ unsigned long tmp1, tmp2;
+
+ asm volatile(
+ " "AHI" %0,-1\n"
+ " jo 5f\n"
+ " sacf 256\n"
+ " bras %3,3f\n"
+ " xc 0(1,%1),0(%1)\n"
+ "0:"AHI" %0,257\n"
+ " la %2,255(%1)\n" /* %2 = ptr + 255 */
+ " srl %2,12\n"
+ " sll %2,12\n" /* %2 = (ptr + 255) & -4096 */
+ " "SLR" %2,%1\n"
+ " "CLR" %0,%2\n" /* clear crosses next page boundary? */
+ " jnh 5f\n"
+ " "AHI" %2,-1\n"
+ "1: ex %2,0(%3)\n"
+ " "AHI" %2,1\n"
+ " "SLR" %0,%2\n"
+ " j 5f\n"
+ "2: xc 0(256,%1),0(%1)\n"
+ " la %1,256(%1)\n"
+ "3:"AHI" %0,-256\n"
+ " jnm 2b\n"
+ "4: ex %0,0(%3)\n"
+ " sacf 0\n"
+ "5: "SLR" %0,%0\n"
+ "6:\n"
+ EX_TABLE(1b,6b) EX_TABLE(2b,0b) EX_TABLE(4b,0b)
+ : "+a" (size), "+a" (to), "=a" (tmp1), "=a" (tmp2)
+ : : "cc", "memory");
+ return size;
+}
+
+size_t strnlen_user_std(size_t size, const char __user *src)
+{
+ register unsigned long reg0 asm("0") = 0UL;
+ unsigned long tmp1, tmp2;
+
+ asm volatile(
+ " la %2,0(%1)\n"
+ " la %3,0(%0,%1)\n"
+ " "SLR" %0,%0\n"
+ " sacf 256\n"
+ "0: srst %3,%2\n"
+ " jo 0b\n"
+ " la %0,1(%3)\n" /* strnlen_user results includes \0 */
+ " "SLR" %0,%1\n"
+ "1: sacf 0\n"
+ EX_TABLE(0b,1b)
+ : "+a" (size), "+a" (src), "=a" (tmp1), "=a" (tmp2)
+ : "d" (reg0) : "cc", "memory");
+ return size;
+}
+
+size_t strncpy_from_user_std(size_t size, const char __user *src, char *dst)
+{
+ register unsigned long reg0 asm("0") = 0UL;
+ unsigned long tmp1, tmp2;
+
+ asm volatile(
+ " la %3,0(%1)\n"
+ " la %4,0(%0,%1)\n"
+ " sacf 256\n"
+ "0: srst %4,%3\n"
+ " jo 0b\n"
+ " sacf 0\n"
+ " la %0,0(%4)\n"
+ " jh 1f\n" /* found \0 in string ? */
+ " "AHI" %4,1\n" /* include \0 in copy */
+ "1:"SLR" %0,%1\n" /* %0 = return length (without \0) */
+ " "SLR" %4,%1\n" /* %4 = copy length (including \0) */
+ "2: mvcp 0(%4,%2),0(%1),%5\n"
+ " jz 9f\n"
+ "3:"AHI" %4,-256\n"
+ " la %1,256(%1)\n"
+ " la %2,256(%2)\n"
+ "4: mvcp 0(%4,%2),0(%1),%5\n"
+ " jnz 3b\n"
+ " j 9f\n"
+ "7: sacf 0\n"
+ "8:"LHI" %0,%6\n"
+ "9:\n"
+ EX_TABLE(0b,7b) EX_TABLE(2b,8b) EX_TABLE(4b,8b)
+ : "+a" (size), "+a" (src), "+d" (dst), "=a" (tmp1), "=a" (tmp2)
+ : "d" (reg0), "K" (-EFAULT) : "cc", "memory");
+ return size;
+}
+
+#define __futex_atomic_op(insn, ret, oldval, newval, uaddr, oparg) \
+ asm volatile( \
+ " sacf 256\n" \
+ "0: l %1,0(%6)\n" \
+ "1:"insn \
+ "2: cs %1,%2,0(%6)\n" \
+ "3: jl 1b\n" \
+ " lhi %0,0\n" \
+ "4: sacf 0\n" \
+ EX_TABLE(0b,4b) EX_TABLE(2b,4b) EX_TABLE(3b,4b) \
+ : "=d" (ret), "=&d" (oldval), "=&d" (newval), \
+ "=m" (*uaddr) \
+ : "0" (-EFAULT), "d" (oparg), "a" (uaddr), \
+ "m" (*uaddr) : "cc");
+
+int futex_atomic_op(int op, int __user *uaddr, int oparg, int *old)
+{
+ int oldval = 0, newval, ret;
+
+ inc_preempt_count();
+
+ switch (op) {
+ case FUTEX_OP_SET:
+ __futex_atomic_op("lr %2,%5\n",
+ ret, oldval, newval, uaddr, oparg);
+ break;
+ case FUTEX_OP_ADD:
+ __futex_atomic_op("lr %2,%1\nar %2,%5\n",
+ ret, oldval, newval, uaddr, oparg);
+ break;
+ case FUTEX_OP_OR:
+ __futex_atomic_op("lr %2,%1\nor %2,%5\n",
+ ret, oldval, newval, uaddr, oparg);
+ break;
+ case FUTEX_OP_ANDN:
+ __futex_atomic_op("lr %2,%1\nnr %2,%5\n",
+ ret, oldval, newval, uaddr, oparg);
+ break;
+ case FUTEX_OP_XOR:
+ __futex_atomic_op("lr %2,%1\nxr %2,%5\n",
+ ret, oldval, newval, uaddr, oparg);
+ break;
+ default:
+ ret = -ENOSYS;
+ }
+ dec_preempt_count();
+ *old = oldval;
+ return ret;
+}
+
+int futex_atomic_cmpxchg(int __user *uaddr, int oldval, int newval)
+{
+ int ret;
+
+ asm volatile(
+ " sacf 256\n"
+ " cs %1,%4,0(%5)\n"
+ "0: lr %0,%1\n"
+ "1: sacf 0\n"
+ EX_TABLE(0b,1b)
+ : "=d" (ret), "+d" (oldval), "=m" (*uaddr)
+ : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr)
+ : "cc", "memory" );
+ return ret;
+}
+
+struct uaccess_ops uaccess_std = {
+ .copy_from_user = copy_from_user_std,
+ .copy_from_user_small = copy_from_user_std_small,
+ .copy_to_user = copy_to_user_std,
+ .copy_to_user_small = copy_to_user_std_small,
+ .copy_in_user = copy_in_user_std,
+ .clear_user = clear_user_std,
+ .strnlen_user = strnlen_user_std,
+ .strncpy_from_user = strncpy_from_user_std,
+ .futex_atomic_op = futex_atomic_op,
+ .futex_atomic_cmpxchg = futex_atomic_cmpxchg,
+};
diff --git a/arch/s390/math-emu/math.c b/arch/s390/math-emu/math.c
index b4957c84e4d6..6b9aec5a2c18 100644
--- a/arch/s390/math-emu/math.c
+++ b/arch/s390/math-emu/math.c
@@ -1564,52 +1564,52 @@ static int emu_tceb (struct pt_regs *regs, int rx, long val) {
}
static inline void emu_load_regd(int reg) {
- if ((reg&9) != 0) /* test if reg in {0,2,4,6} */
+ if ((reg&9) != 0) /* test if reg in {0,2,4,6} */
return;
- asm volatile ( /* load reg from fp_regs.fprs[reg] */
- " bras 1,0f\n"
- " ld 0,0(%1)\n"
- "0: ex %0,0(1)"
- : /* no output */
- : "a" (reg<<4),"a" (&current->thread.fp_regs.fprs[reg].d)
- : "1" );
+ asm volatile( /* load reg from fp_regs.fprs[reg] */
+ " bras 1,0f\n"
+ " ld 0,0(%1)\n"
+ "0: ex %0,0(1)"
+ : /* no output */
+ : "a" (reg<<4),"a" (&current->thread.fp_regs.fprs[reg].d)
+ : "1");
}
static inline void emu_load_rege(int reg) {
- if ((reg&9) != 0) /* test if reg in {0,2,4,6} */
+ if ((reg&9) != 0) /* test if reg in {0,2,4,6} */
return;
- asm volatile ( /* load reg from fp_regs.fprs[reg] */
- " bras 1,0f\n"
- " le 0,0(%1)\n"
- "0: ex %0,0(1)"
- : /* no output */
- : "a" (reg<<4), "a" (&current->thread.fp_regs.fprs[reg].f)
- : "1" );
+ asm volatile( /* load reg from fp_regs.fprs[reg] */
+ " bras 1,0f\n"
+ " le 0,0(%1)\n"
+ "0: ex %0,0(1)"
+ : /* no output */
+ : "a" (reg<<4), "a" (&current->thread.fp_regs.fprs[reg].f)
+ : "1");
}
static inline void emu_store_regd(int reg) {
- if ((reg&9) != 0) /* test if reg in {0,2,4,6} */
+ if ((reg&9) != 0) /* test if reg in {0,2,4,6} */
return;
- asm volatile ( /* store reg to fp_regs.fprs[reg] */
- " bras 1,0f\n"
- " std 0,0(%1)\n"
- "0: ex %0,0(1)"
- : /* no output */
- : "a" (reg<<4), "a" (&current->thread.fp_regs.fprs[reg].d)
- : "1" );
+ asm volatile( /* store reg to fp_regs.fprs[reg] */
+ " bras 1,0f\n"
+ " std 0,0(%1)\n"
+ "0: ex %0,0(1)"
+ : /* no output */
+ : "a" (reg<<4), "a" (&current->thread.fp_regs.fprs[reg].d)
+ : "1");
}
static inline void emu_store_rege(int reg) {
- if ((reg&9) != 0) /* test if reg in {0,2,4,6} */
+ if ((reg&9) != 0) /* test if reg in {0,2,4,6} */
return;
- asm volatile ( /* store reg to fp_regs.fprs[reg] */
- " bras 1,0f\n"
- " ste 0,0(%1)\n"
- "0: ex %0,0(1)"
- : /* no output */
- : "a" (reg<<4), "a" (&current->thread.fp_regs.fprs[reg].f)
- : "1" );
+ asm volatile( /* store reg to fp_regs.fprs[reg] */
+ " bras 1,0f\n"
+ " ste 0,0(%1)\n"
+ "0: ex %0,0(1)"
+ : /* no output */
+ : "a" (reg<<4), "a" (&current->thread.fp_regs.fprs[reg].f)
+ : "1");
}
int math_emu_b3(__u8 *opcode, struct pt_regs * regs) {
@@ -2089,23 +2089,22 @@ int math_emu_ldr(__u8 *opcode) {
if ((opc & 0x90) == 0) { /* test if rx in {0,2,4,6} */
/* we got an exception therfore ry can't be in {0,2,4,6} */
- __asm__ __volatile ( /* load rx from fp_regs.fprs[ry] */
- " bras 1,0f\n"
- " ld 0,0(%1)\n"
- "0: ex %0,0(1)"
- : /* no output */
- : "a" (opc & 0xf0),
- "a" (&fp_regs->fprs[opc & 0xf].d)
- : "1" );
+ asm volatile( /* load rx from fp_regs.fprs[ry] */
+ " bras 1,0f\n"
+ " ld 0,0(%1)\n"
+ "0: ex %0,0(1)"
+ : /* no output */
+ : "a" (opc & 0xf0), "a" (&fp_regs->fprs[opc & 0xf].d)
+ : "1");
} else if ((opc & 0x9) == 0) { /* test if ry in {0,2,4,6} */
- __asm__ __volatile ( /* store ry to fp_regs.fprs[rx] */
- " bras 1,0f\n"
- " std 0,0(%1)\n"
- "0: ex %0,0(1)"
- : /* no output */
- : "a" ((opc & 0xf) << 4),
- "a" (&fp_regs->fprs[(opc & 0xf0)>>4].d)
- : "1" );
+ asm volatile ( /* store ry to fp_regs.fprs[rx] */
+ " bras 1,0f\n"
+ " std 0,0(%1)\n"
+ "0: ex %0,0(1)"
+ : /* no output */
+ : "a" ((opc & 0xf) << 4),
+ "a" (&fp_regs->fprs[(opc & 0xf0)>>4].d)
+ : "1");
} else /* move fp_regs.fprs[ry] to fp_regs.fprs[rx] */
fp_regs->fprs[(opc & 0xf0) >> 4] = fp_regs->fprs[opc & 0xf];
return 0;
@@ -2120,23 +2119,22 @@ int math_emu_ler(__u8 *opcode) {
if ((opc & 0x90) == 0) { /* test if rx in {0,2,4,6} */
/* we got an exception therfore ry can't be in {0,2,4,6} */
- __asm__ __volatile ( /* load rx from fp_regs.fprs[ry] */
- " bras 1,0f\n"
- " le 0,0(%1)\n"
- "0: ex %0,0(1)"
- : /* no output */
- : "a" (opc & 0xf0),
- "a" (&fp_regs->fprs[opc & 0xf].f)
- : "1" );
+ asm volatile( /* load rx from fp_regs.fprs[ry] */
+ " bras 1,0f\n"
+ " le 0,0(%1)\n"
+ "0: ex %0,0(1)"
+ : /* no output */
+ : "a" (opc & 0xf0), "a" (&fp_regs->fprs[opc & 0xf].f)
+ : "1");
} else if ((opc & 0x9) == 0) { /* test if ry in {0,2,4,6} */
- __asm__ __volatile ( /* store ry to fp_regs.fprs[rx] */
- " bras 1,0f\n"
- " ste 0,0(%1)\n"
- "0: ex %0,0(1)"
- : /* no output */
- : "a" ((opc & 0xf) << 4),
- "a" (&fp_regs->fprs[(opc & 0xf0) >> 4].f)
- : "1" );
+ asm volatile( /* store ry to fp_regs.fprs[rx] */
+ " bras 1,0f\n"
+ " ste 0,0(%1)\n"
+ "0: ex %0,0(1)"
+ : /* no output */
+ : "a" ((opc & 0xf) << 4),
+ "a" (&fp_regs->fprs[(opc & 0xf0) >> 4].f)
+ : "1");
} else /* move fp_regs.fprs[ry] to fp_regs.fprs[rx] */
fp_regs->fprs[(opc & 0xf0) >> 4] = fp_regs->fprs[opc & 0xf];
return 0;
diff --git a/arch/s390/math-emu/sfp-util.h b/arch/s390/math-emu/sfp-util.h
index ab556b600f73..5b6ca4570ea4 100644
--- a/arch/s390/math-emu/sfp-util.h
+++ b/arch/s390/math-emu/sfp-util.h
@@ -4,48 +4,51 @@
#include <asm/byteorder.h>
#define add_ssaaaa(sh, sl, ah, al, bh, bl) ({ \
- unsigned int __sh = (ah); \
- unsigned int __sl = (al); \
- __asm__ (" alr %1,%3\n" \
- " brc 12,0f\n" \
- " ahi %0,1\n" \
- "0: alr %0,%2" \
- : "+&d" (__sh), "+d" (__sl) \
- : "d" (bh), "d" (bl) : "cc" ); \
- (sh) = __sh; \
- (sl) = __sl; \
+ unsigned int __sh = (ah); \
+ unsigned int __sl = (al); \
+ asm volatile( \
+ " alr %1,%3\n" \
+ " brc 12,0f\n" \
+ " ahi %0,1\n" \
+ "0: alr %0,%2" \
+ : "+&d" (__sh), "+d" (__sl) \
+ : "d" (bh), "d" (bl) : "cc"); \
+ (sh) = __sh; \
+ (sl) = __sl; \
})
#define sub_ddmmss(sh, sl, ah, al, bh, bl) ({ \
- unsigned int __sh = (ah); \
- unsigned int __sl = (al); \
- __asm__ (" slr %1,%3\n" \
- " brc 3,0f\n" \
- " ahi %0,-1\n" \
- "0: slr %0,%2" \
- : "+&d" (__sh), "+d" (__sl) \
- : "d" (bh), "d" (bl) : "cc" ); \
- (sh) = __sh; \
- (sl) = __sl; \
+ unsigned int __sh = (ah); \
+ unsigned int __sl = (al); \
+ asm volatile( \
+ " slr %1,%3\n" \
+ " brc 3,0f\n" \
+ " ahi %0,-1\n" \
+ "0: slr %0,%2" \
+ : "+&d" (__sh), "+d" (__sl) \
+ : "d" (bh), "d" (bl) : "cc"); \
+ (sh) = __sh; \
+ (sl) = __sl; \
})
/* a umul b = a mul b + (a>=2<<31) ? b<<32:0 + (b>=2<<31) ? a<<32:0 */
#define umul_ppmm(wh, wl, u, v) ({ \
- unsigned int __wh = u; \
- unsigned int __wl = v; \
- __asm__ (" ltr 1,%0\n" \
- " mr 0,%1\n" \
- " jnm 0f\n" \
- " alr 0,%1\n" \
- "0: ltr %1,%1\n" \
- " jnm 1f\n" \
- " alr 0,%0\n" \
- "1: lr %0,0\n" \
- " lr %1,1\n" \
- : "+d" (__wh), "+d" (__wl) \
- : : "0", "1", "cc" ); \
- wh = __wh; \
- wl = __wl; \
+ unsigned int __wh = u; \
+ unsigned int __wl = v; \
+ asm volatile( \
+ " ltr 1,%0\n" \
+ " mr 0,%1\n" \
+ " jnm 0f\n" \
+ " alr 0,%1\n" \
+ "0: ltr %1,%1\n" \
+ " jnm 1f\n" \
+ " alr 0,%0\n" \
+ "1: lr %0,0\n" \
+ " lr %1,1\n" \
+ : "+d" (__wh), "+d" (__wl) \
+ : : "0", "1", "cc"); \
+ wh = __wh; \
+ wl = __wl; \
})
#define udiv_qrnnd(q, r, n1, n0, d) \
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c
index ceea51cff03b..607f50ead1fd 100644
--- a/arch/s390/mm/cmm.c
+++ b/arch/s390/mm/cmm.c
@@ -15,6 +15,8 @@
#include <linux/sched.h>
#include <linux/sysctl.h>
#include <linux/ctype.h>
+#include <linux/swap.h>
+#include <linux/kthread.h>
#include <asm/pgalloc.h>
#include <asm/uaccess.h>
@@ -34,18 +36,18 @@ struct cmm_page_array {
unsigned long pages[CMM_NR_PAGES];
};
-static long cmm_pages = 0;
-static long cmm_timed_pages = 0;
-static volatile long cmm_pages_target = 0;
-static volatile long cmm_timed_pages_target = 0;
-static long cmm_timeout_pages = 0;
-static long cmm_timeout_seconds = 0;
+static long cmm_pages;
+static long cmm_timed_pages;
+static volatile long cmm_pages_target;
+static volatile long cmm_timed_pages_target;
+static long cmm_timeout_pages;
+static long cmm_timeout_seconds;
-static struct cmm_page_array *cmm_page_list = NULL;
-static struct cmm_page_array *cmm_timed_page_list = NULL;
+static struct cmm_page_array *cmm_page_list;
+static struct cmm_page_array *cmm_timed_page_list;
+static DEFINE_SPINLOCK(cmm_lock);
-static unsigned long cmm_thread_active = 0;
-static struct work_struct cmm_thread_starter;
+static struct task_struct *cmm_thread_ptr;
static wait_queue_head_t cmm_thread_wait;
static struct timer_list cmm_timer;
@@ -53,87 +55,100 @@ static void cmm_timer_fn(unsigned long);
static void cmm_set_timer(void);
static long
-cmm_strtoul(const char *cp, char **endp)
+cmm_alloc_pages(long nr, long *counter, struct cmm_page_array **list)
{
- unsigned int base = 10;
-
- if (*cp == '0') {
- base = 8;
- cp++;
- if ((*cp == 'x' || *cp == 'X') && isxdigit(cp[1])) {
- base = 16;
- cp++;
- }
- }
- return simple_strtoul(cp, endp, base);
-}
-
-static long
-cmm_alloc_pages(long pages, long *counter, struct cmm_page_array **list)
-{
- struct cmm_page_array *pa;
- unsigned long page;
+ struct cmm_page_array *pa, *npa;
+ unsigned long addr;
- pa = *list;
- while (pages) {
- page = __get_free_page(GFP_NOIO);
- if (!page)
+ while (nr) {
+ addr = __get_free_page(GFP_NOIO);
+ if (!addr)
break;
+ spin_lock(&cmm_lock);
+ pa = *list;
if (!pa || pa->index >= CMM_NR_PAGES) {
/* Need a new page for the page list. */
- pa = (struct cmm_page_array *)
+ spin_unlock(&cmm_lock);
+ npa = (struct cmm_page_array *)
__get_free_page(GFP_NOIO);
- if (!pa) {
- free_page(page);
+ if (!npa) {
+ free_page(addr);
break;
}
- pa->next = *list;
- pa->index = 0;
- *list = pa;
+ spin_lock(&cmm_lock);
+ pa = *list;
+ if (!pa || pa->index >= CMM_NR_PAGES) {
+ npa->next = pa;
+ npa->index = 0;
+ pa = npa;
+ *list = pa;
+ } else
+ free_page((unsigned long) npa);
}
- diag10(page);
- pa->pages[pa->index++] = page;
+ diag10(addr);
+ pa->pages[pa->index++] = addr;
(*counter)++;
- pages--;
+ spin_unlock(&cmm_lock);
+ nr--;
}
- return pages;
+ return nr;
}
-static void
-cmm_free_pages(long pages, long *counter, struct cmm_page_array **list)
+static long
+cmm_free_pages(long nr, long *counter, struct cmm_page_array **list)
{
struct cmm_page_array *pa;
- unsigned long page;
+ unsigned long addr;
+ spin_lock(&cmm_lock);
pa = *list;
- while (pages) {
+ while (nr) {
if (!pa || pa->index <= 0)
break;
- page = pa->pages[--pa->index];
+ addr = pa->pages[--pa->index];
if (pa->index == 0) {
pa = pa->next;
free_page((unsigned long) *list);
*list = pa;
}
- free_page(page);
+ free_page(addr);
(*counter)--;
- pages--;
+ nr--;
}
+ spin_unlock(&cmm_lock);
+ return nr;
+}
+
+static int cmm_oom_notify(struct notifier_block *self,
+ unsigned long dummy, void *parm)
+{
+ unsigned long *freed = parm;
+ long nr = 256;
+
+ nr = cmm_free_pages(nr, &cmm_timed_pages, &cmm_timed_page_list);
+ if (nr > 0)
+ nr = cmm_free_pages(nr, &cmm_pages, &cmm_page_list);
+ cmm_pages_target = cmm_pages;
+ cmm_timed_pages_target = cmm_timed_pages;
+ *freed += 256 - nr;
+ return NOTIFY_OK;
}
+static struct notifier_block cmm_oom_nb = {
+ .notifier_call = cmm_oom_notify
+};
+
static int
cmm_thread(void *dummy)
{
int rc;
- daemonize("cmmthread");
while (1) {
rc = wait_event_interruptible(cmm_thread_wait,
(cmm_pages != cmm_pages_target ||
- cmm_timed_pages != cmm_timed_pages_target));
- if (rc == -ERESTARTSYS) {
- /* Got kill signal. End thread. */
- clear_bit(0, &cmm_thread_active);
+ cmm_timed_pages != cmm_timed_pages_target ||
+ kthread_should_stop()));
+ if (kthread_should_stop() || rc == -ERESTARTSYS) {
cmm_pages_target = cmm_pages;
cmm_timed_pages_target = cmm_timed_pages;
break;
@@ -159,16 +174,8 @@ cmm_thread(void *dummy)
}
static void
-cmm_start_thread(void)
-{
- kernel_thread(cmm_thread, NULL, 0);
-}
-
-static void
cmm_kick_thread(void)
{
- if (!test_and_set_bit(0, &cmm_thread_active))
- schedule_work(&cmm_thread_starter);
wake_up(&cmm_thread_wait);
}
@@ -193,21 +200,21 @@ cmm_set_timer(void)
static void
cmm_timer_fn(unsigned long ignored)
{
- long pages;
+ long nr;
- pages = cmm_timed_pages_target - cmm_timeout_pages;
- if (pages < 0)
+ nr = cmm_timed_pages_target - cmm_timeout_pages;
+ if (nr < 0)
cmm_timed_pages_target = 0;
else
- cmm_timed_pages_target = pages;
+ cmm_timed_pages_target = nr;
cmm_kick_thread();
cmm_set_timer();
}
void
-cmm_set_pages(long pages)
+cmm_set_pages(long nr)
{
- cmm_pages_target = pages;
+ cmm_pages_target = nr;
cmm_kick_thread();
}
@@ -218,9 +225,9 @@ cmm_get_pages(void)
}
void
-cmm_add_timed_pages(long pages)
+cmm_add_timed_pages(long nr)
{
- cmm_timed_pages_target += pages;
+ cmm_timed_pages_target += nr;
cmm_kick_thread();
}
@@ -231,9 +238,9 @@ cmm_get_timed_pages(void)
}
void
-cmm_set_timeout(long pages, long seconds)
+cmm_set_timeout(long nr, long seconds)
{
- cmm_timeout_pages = pages;
+ cmm_timeout_pages = nr;
cmm_timeout_seconds = seconds;
cmm_set_timer();
}
@@ -261,7 +268,7 @@ cmm_pages_handler(ctl_table *ctl, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
char buf[16], *p;
- long pages;
+ long nr;
int len;
if (!*lenp || (*ppos && !write)) {
@@ -276,17 +283,17 @@ cmm_pages_handler(ctl_table *ctl, int write, struct file *filp,
return -EFAULT;
buf[sizeof(buf) - 1] = '\0';
cmm_skip_blanks(buf, &p);
- pages = cmm_strtoul(p, &p);
+ nr = simple_strtoul(p, &p, 0);
if (ctl == &cmm_table[0])
- cmm_set_pages(pages);
+ cmm_set_pages(nr);
else
- cmm_add_timed_pages(pages);
+ cmm_add_timed_pages(nr);
} else {
if (ctl == &cmm_table[0])
- pages = cmm_get_pages();
+ nr = cmm_get_pages();
else
- pages = cmm_get_timed_pages();
- len = sprintf(buf, "%ld\n", pages);
+ nr = cmm_get_timed_pages();
+ len = sprintf(buf, "%ld\n", nr);
if (len > *lenp)
len = *lenp;
if (copy_to_user(buffer, buf, len))
@@ -302,7 +309,7 @@ cmm_timeout_handler(ctl_table *ctl, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
char buf[64], *p;
- long pages, seconds;
+ long nr, seconds;
int len;
if (!*lenp || (*ppos && !write)) {
@@ -317,10 +324,10 @@ cmm_timeout_handler(ctl_table *ctl, int write, struct file *filp,
return -EFAULT;
buf[sizeof(buf) - 1] = '\0';
cmm_skip_blanks(buf, &p);
- pages = cmm_strtoul(p, &p);
+ nr = simple_strtoul(p, &p, 0);
cmm_skip_blanks(p, &p);
- seconds = cmm_strtoul(p, &p);
- cmm_set_timeout(pages, seconds);
+ seconds = simple_strtoul(p, &p, 0);
+ cmm_set_timeout(nr, seconds);
} else {
len = sprintf(buf, "%ld %ld\n",
cmm_timeout_pages, cmm_timeout_seconds);
@@ -373,7 +380,7 @@ static struct ctl_table cmm_dir_table[] = {
static void
cmm_smsg_target(char *from, char *msg)
{
- long pages, seconds;
+ long nr, seconds;
if (strlen(sender) > 0 && strcmp(from, sender) != 0)
return;
@@ -382,27 +389,27 @@ cmm_smsg_target(char *from, char *msg)
if (strncmp(msg, "SHRINK", 6) == 0) {
if (!cmm_skip_blanks(msg + 6, &msg))
return;
- pages = cmm_strtoul(msg, &msg);
+ nr = simple_strtoul(msg, &msg, 0);
cmm_skip_blanks(msg, &msg);
if (*msg == '\0')
- cmm_set_pages(pages);
+ cmm_set_pages(nr);
} else if (strncmp(msg, "RELEASE", 7) == 0) {
if (!cmm_skip_blanks(msg + 7, &msg))
return;
- pages = cmm_strtoul(msg, &msg);
+ nr = simple_strtoul(msg, &msg, 0);
cmm_skip_blanks(msg, &msg);
if (*msg == '\0')
- cmm_add_timed_pages(pages);
+ cmm_add_timed_pages(nr);
} else if (strncmp(msg, "REUSE", 5) == 0) {
if (!cmm_skip_blanks(msg + 5, &msg))
return;
- pages = cmm_strtoul(msg, &msg);
+ nr = simple_strtoul(msg, &msg, 0);
if (!cmm_skip_blanks(msg, &msg))
return;
- seconds = cmm_strtoul(msg, &msg);
+ seconds = simple_strtoul(msg, &msg, 0);
cmm_skip_blanks(msg, &msg);
if (*msg == '\0')
- cmm_set_timeout(pages, seconds);
+ cmm_set_timeout(nr, seconds);
}
}
#endif
@@ -412,21 +419,49 @@ struct ctl_table_header *cmm_sysctl_header;
static int
cmm_init (void)
{
+ int rc = -ENOMEM;
+
#ifdef CONFIG_CMM_PROC
cmm_sysctl_header = register_sysctl_table(cmm_dir_table, 1);
+ if (!cmm_sysctl_header)
+ goto out;
#endif
#ifdef CONFIG_CMM_IUCV
- smsg_register_callback(SMSG_PREFIX, cmm_smsg_target);
+ rc = smsg_register_callback(SMSG_PREFIX, cmm_smsg_target);
+ if (rc < 0)
+ goto out_smsg;
#endif
- INIT_WORK(&cmm_thread_starter, (void *) cmm_start_thread, NULL);
+ rc = register_oom_notifier(&cmm_oom_nb);
+ if (rc < 0)
+ goto out_oom_notify;
init_waitqueue_head(&cmm_thread_wait);
init_timer(&cmm_timer);
- return 0;
+ cmm_thread_ptr = kthread_run(cmm_thread, NULL, "cmmthread");
+ rc = IS_ERR(cmm_thread_ptr) ? PTR_ERR(cmm_thread_ptr) : 0;
+ if (!rc)
+ goto out;
+ /*
+ * kthread_create failed. undo all the stuff from above again.
+ */
+ unregister_oom_notifier(&cmm_oom_nb);
+
+out_oom_notify:
+#ifdef CONFIG_CMM_IUCV
+ smsg_unregister_callback(SMSG_PREFIX, cmm_smsg_target);
+out_smsg:
+#endif
+#ifdef CONFIG_CMM_PROC
+ unregister_sysctl_table(cmm_sysctl_header);
+#endif
+out:
+ return rc;
}
static void
cmm_exit(void)
{
+ kthread_stop(cmm_thread_ptr);
+ unregister_oom_notifier(&cmm_oom_nb);
cmm_free_pages(cmm_pages, &cmm_pages, &cmm_page_list);
cmm_free_pages(cmm_timed_pages, &cmm_timed_pages, &cmm_timed_page_list);
#ifdef CONFIG_CMM_PROC
diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c
index 9b11e3e20903..226275d5c4f6 100644
--- a/arch/s390/mm/extmem.c
+++ b/arch/s390/mm/extmem.c
@@ -142,17 +142,17 @@ dcss_diag (__u8 func, void *parameter,
rx = (unsigned long) parameter;
ry = (unsigned long) func;
- __asm__ __volatile__(
+ asm volatile(
#ifdef CONFIG_64BIT
- " sam31\n" // switch to 31 bit
- " diag %0,%1,0x64\n"
- " sam64\n" // switch back to 64 bit
+ " sam31\n"
+ " diag %0,%1,0x64\n"
+ " sam64\n"
#else
- " diag %0,%1,0x64\n"
+ " diag %0,%1,0x64\n"
#endif
- " ipm %2\n"
- " srl %2,28\n"
- : "+d" (rx), "+d" (ry), "=d" (rc) : : "cc" );
+ " ipm %2\n"
+ " srl %2,28\n"
+ : "+d" (rx), "+d" (ry), "=d" (rc) : : "cc");
*ret1 = rx;
*ret2 = ry;
return rc;
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 7cd82575813d..9c3c19fe62fc 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -25,10 +25,12 @@
#include <linux/console.h>
#include <linux/module.h>
#include <linux/hardirq.h>
+#include <linux/kprobes.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
+#include <asm/kdebug.h>
#ifndef CONFIG_64BIT
#define __FAIL_ADDR_MASK 0x7ffff000
@@ -48,6 +50,38 @@ extern int sysctl_userprocess_debug;
extern void die(const char *,struct pt_regs *,long);
+#ifdef CONFIG_KPROBES
+ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
+int register_page_fault_notifier(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
+}
+
+int unregister_page_fault_notifier(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb);
+}
+
+static inline int notify_page_fault(enum die_val val, const char *str,
+ struct pt_regs *regs, long err, int trap, int sig)
+{
+ struct die_args args = {
+ .regs = regs,
+ .str = str,
+ .err = err,
+ .trapnr = trap,
+ .signr = sig
+ };
+ return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
+}
+#else
+static inline int notify_page_fault(enum die_val val, const char *str,
+ struct pt_regs *regs, long err, int trap, int sig)
+{
+ return NOTIFY_DONE;
+}
+#endif
+
extern spinlock_t timerlist_lock;
/*
@@ -159,7 +193,7 @@ static void do_sigsegv(struct pt_regs *regs, unsigned long error_code,
* 11 Page translation -> Not present (nullification)
* 3b Region third trans. -> Not present (nullification)
*/
-static inline void
+static inline void __kprobes
do_exception(struct pt_regs *regs, unsigned long error_code, int is_protection)
{
struct task_struct *tsk;
@@ -173,6 +207,10 @@ do_exception(struct pt_regs *regs, unsigned long error_code, int is_protection)
tsk = current;
mm = tsk->mm;
+ if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
+ SIGSEGV) == NOTIFY_STOP)
+ return;
+
/*
* Check for low-address protection. This needs to be treated
* as a special case because the translation exception code
@@ -315,8 +353,9 @@ no_context:
*/
out_of_memory:
up_read(&mm->mmap_sem);
- if (tsk->pid == 1) {
+ if (is_init(tsk)) {
yield();
+ down_read(&mm->mmap_sem);
goto survive;
}
printk("VM: killing process %s\n", tsk->comm);
@@ -385,20 +424,13 @@ int pfault_init(void)
if (pfault_disable)
return -1;
- __asm__ __volatile__(
- " diag %1,%0,0x258\n"
- "0: j 2f\n"
- "1: la %0,8\n"
+ asm volatile(
+ " diag %1,%0,0x258\n"
+ "0: j 2f\n"
+ "1: la %0,8\n"
"2:\n"
- ".section __ex_table,\"a\"\n"
- " .align 4\n"
-#ifndef CONFIG_64BIT
- " .long 0b,1b\n"
-#else /* CONFIG_64BIT */
- " .quad 0b,1b\n"
-#endif /* CONFIG_64BIT */
- ".previous"
- : "=d" (rc) : "a" (&refbk), "m" (refbk) : "cc" );
+ EX_TABLE(0b,1b)
+ : "=d" (rc) : "a" (&refbk), "m" (refbk) : "cc");
__ctl_set_bit(0, 9);
return rc;
}
@@ -411,18 +443,11 @@ void pfault_fini(void)
if (pfault_disable)
return;
__ctl_clear_bit(0,9);
- __asm__ __volatile__(
- " diag %0,0,0x258\n"
+ asm volatile(
+ " diag %0,0,0x258\n"
"0:\n"
- ".section __ex_table,\"a\"\n"
- " .align 4\n"
-#ifndef CONFIG_64BIT
- " .long 0b,0b\n"
-#else /* CONFIG_64BIT */
- " .quad 0b,0b\n"
-#endif /* CONFIG_64BIT */
- ".previous"
- : : "a" (&refbk), "m" (refbk) : "cc" );
+ EX_TABLE(0b,0b)
+ : : "a" (&refbk), "m" (refbk) : "cc");
}
asmlinkage void
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index 6e6b6de77770..127044e1707c 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -45,26 +45,17 @@ void diag10(unsigned long addr)
{
if (addr >= 0x7ff00000)
return;
+ asm volatile(
#ifdef CONFIG_64BIT
- asm volatile (
- " sam31\n"
- " diag %0,%0,0x10\n"
- "0: sam64\n"
- ".section __ex_table,\"a\"\n"
- " .align 8\n"
- " .quad 0b, 0b\n"
- ".previous\n"
- : : "a" (addr));
+ " sam31\n"
+ " diag %0,%0,0x10\n"
+ "0: sam64\n"
#else
- asm volatile (
- " diag %0,%0,0x10\n"
+ " diag %0,%0,0x10\n"
"0:\n"
- ".section __ex_table,\"a\"\n"
- " .align 4\n"
- " .long 0b, 0b\n"
- ".previous\n"
- : : "a" (addr));
#endif
+ EX_TABLE(0b,0b)
+ : : "a" (addr));
}
void show_mem(void)
@@ -108,16 +99,23 @@ void __init paging_init(void)
unsigned long pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | _KERNSEG_TABLE;
static const int ssm_mask = 0x04000000L;
unsigned long ro_start_pfn, ro_end_pfn;
+ unsigned long zones_size[MAX_NR_ZONES];
ro_start_pfn = PFN_DOWN((unsigned long)&__start_rodata);
ro_end_pfn = PFN_UP((unsigned long)&__end_rodata);
+ memset(zones_size, 0, sizeof(zones_size));
+ zones_size[ZONE_DMA] = max_low_pfn;
+ free_area_init_node(0, &contig_page_data, zones_size,
+ __pa(PAGE_OFFSET) >> PAGE_SHIFT,
+ zholes_size);
+
/* unmap whole virtual address space */
pg_dir = swapper_pg_dir;
- for (i=0;i<KERNEL_PGD_PTRS;i++)
- pmd_clear((pmd_t*)pg_dir++);
+ for (i = 0; i < PTRS_PER_PGD; i++)
+ pmd_clear((pmd_t *) pg_dir++);
/*
* map whole physical memory to virtual memory (identity mapping)
@@ -131,10 +129,7 @@ void __init paging_init(void)
*/
pg_table = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
- pg_dir->pgd0 = (_PAGE_TABLE | __pa(pg_table));
- pg_dir->pgd1 = (_PAGE_TABLE | (__pa(pg_table)+1024));
- pg_dir->pgd2 = (_PAGE_TABLE | (__pa(pg_table)+2048));
- pg_dir->pgd3 = (_PAGE_TABLE | (__pa(pg_table)+3072));
+ pmd_populate_kernel(&init_mm, (pmd_t *) pg_dir, pg_table);
pg_dir++;
for (tmp = 0 ; tmp < PTRS_PER_PTE ; tmp++,pg_table++) {
@@ -143,8 +138,8 @@ void __init paging_init(void)
else
pte = pfn_pte(pfn, PAGE_KERNEL);
if (pfn >= max_low_pfn)
- pte_clear(&init_mm, 0, &pte);
- set_pte(pg_table, pte);
+ pte_val(pte) = _PAGE_TYPE_EMPTY;
+ set_pte(pg_table, pte);
pfn++;
}
}
@@ -152,23 +147,12 @@ void __init paging_init(void)
S390_lowcore.kernel_asce = pgdir_k;
/* enable virtual mapping in kernel mode */
- __asm__ __volatile__(" LCTL 1,1,%0\n"
- " LCTL 7,7,%0\n"
- " LCTL 13,13,%0\n"
- " SSM %1"
- : : "m" (pgdir_k), "m" (ssm_mask));
+ __ctl_load(pgdir_k, 1, 1);
+ __ctl_load(pgdir_k, 7, 7);
+ __ctl_load(pgdir_k, 13, 13);
+ __raw_local_irq_ssm(ssm_mask);
local_flush_tlb();
-
- {
- unsigned long zones_size[MAX_NR_ZONES];
-
- memset(zones_size, 0, sizeof(zones_size));
- zones_size[ZONE_DMA] = max_low_pfn;
- free_area_init_node(0, &contig_page_data, zones_size,
- __pa(PAGE_OFFSET) >> PAGE_SHIFT,
- zholes_size);
- }
return;
}
@@ -236,10 +220,8 @@ void __init paging_init(void)
pte = pfn_pte(pfn, __pgprot(_PAGE_RO));
else
pte = pfn_pte(pfn, PAGE_KERNEL);
- if (pfn >= max_low_pfn) {
- pte_clear(&init_mm, 0, &pte);
- continue;
- }
+ if (pfn >= max_low_pfn)
+ pte_val(pte) = _PAGE_TYPE_EMPTY;
set_pte(pt_dir, pte);
pfn++;
}
@@ -249,11 +231,10 @@ void __init paging_init(void)
S390_lowcore.kernel_asce = pgdir_k;
/* enable virtual mapping in kernel mode */
- __asm__ __volatile__("lctlg 1,1,%0\n\t"
- "lctlg 7,7,%0\n\t"
- "lctlg 13,13,%0\n\t"
- "ssm %1"
- : :"m" (pgdir_k), "m" (ssm_mask));
+ __ctl_load(pgdir_k, 1, 1);
+ __ctl_load(pgdir_k, 7, 7);
+ __ctl_load(pgdir_k, 13, 13);
+ __raw_local_irq_ssm(ssm_mask);
local_flush_tlb();